blob: b80e286dbb2332bc25341bd0a18b5a0ce0e66938 [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/*
njnc9539842002-10-02 13:26:35 +00007 This file is part of Valgrind, an extensible x86 protected-mode
8 emulator for monitoring program execution on x86-Unixes.
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"
35#include "ume_arch.h"
nethercote71980f02004-01-24 18:18:54 +000036
37#include <dirent.h>
38#include <dlfcn.h>
39#include <errno.h>
40#include <fcntl.h>
41#include <stdio.h>
fitzhardingeb727d042004-01-06 00:18:21 +000042#include <stdlib.h>
nethercote71980f02004-01-24 18:18:54 +000043#include <string.h>
44#include <sys/mman.h>
45#include <sys/types.h>
46#include <sys/stat.h>
fitzhardingeb727d042004-01-06 00:18:21 +000047#include <sys/ptrace.h>
48#include <sys/signal.h>
fitzhardingeb727d042004-01-06 00:18:21 +000049#include <sys/wait.h>
50#include <unistd.h>
51
thughes74b8de22004-04-22 18:12:31 +000052#ifndef AT_DCACHEBSIZE
53#define AT_DCACHEBSIZE 19
54#endif /* AT_DCACHEBSIZE */
55
56#ifndef AT_ICACHEBSIZE
57#define AT_ICACHEBSIZE 20
58#endif /* AT_ICACHEBSIZE */
59
60#ifndef AT_UCACHEBSIZE
61#define AT_UCACHEBSIZE 21
62#endif /* AT_UCACHEBSIZE */
63
nethercote71980f02004-01-24 18:18:54 +000064#ifndef AT_SYSINFO
65#define AT_SYSINFO 32
66#endif /* AT_SYSINFO */
67
68#ifndef AT_SYSINFO_EHDR
69#define AT_SYSINFO_EHDR 33
70#endif /* AT_SYSINFO_EHDR */
71
72#ifndef AT_SECURE
73#define AT_SECURE 23 /* secure mode boolean */
74#endif /* AT_SECURE */
75
nethercote71980f02004-01-24 18:18:54 +000076/* redzone gap between client address space and shadow */
77#define REDZONE_SIZE (1 * 1024*1024)
78
79/* size multiple for client address space */
nethercotee94b2de2004-06-23 16:15:06 +000080#define CLIENT_SIZE_MULTIPLE (1 * 1024*1024)
nethercote71980f02004-01-24 18:18:54 +000081
nethercotee2097312004-06-27 12:29:56 +000082/* Proportion of client space for its heap (rest is for mmaps + stack) */
83#define CLIENT_HEAP_PROPORTION 0.333
nethercote71980f02004-01-24 18:18:54 +000084
85/*====================================================================*/
86/*=== Global entities not referenced from generated code ===*/
87/*====================================================================*/
88
sewardjde4a1d02002-03-22 01:27:54 +000089/* ---------------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +000090 Startup stuff
sewardjde4a1d02002-03-22 01:27:54 +000091 ------------------------------------------------------------------ */
nethercote71980f02004-01-24 18:18:54 +000092/* linker-defined base address */
93extern char kickstart_base;
sewardjde4a1d02002-03-22 01:27:54 +000094
nethercote71980f02004-01-24 18:18:54 +000095/* Client address space, lowest to highest (see top of ume.c) */
96Addr VG_(client_base); /* client address space limits */
fitzhardinge98abfc72003-12-16 02:05:15 +000097Addr VG_(client_end);
98Addr VG_(client_mapbase);
fitzhardinge92360792003-12-24 10:11:11 +000099Addr VG_(client_trampoline_code);
fitzhardinge98abfc72003-12-16 02:05:15 +0000100Addr VG_(clstk_base);
101Addr VG_(clstk_end);
nethercote71980f02004-01-24 18:18:54 +0000102
103Addr VG_(brk_base); /* start of brk */
104Addr VG_(brk_limit); /* current brk */
105
nethercote996901a2004-08-03 13:29:09 +0000106Addr VG_(shadow_base); /* tool's shadow memory */
fitzhardinge98abfc72003-12-16 02:05:15 +0000107Addr VG_(shadow_end);
nethercote71980f02004-01-24 18:18:54 +0000108
109Addr VG_(valgrind_base); /* valgrind's address range */
rjwalsh18b66312004-08-23 18:15:12 +0000110
111// VG_(valgrind_end) has a slightly different meaning to all the other
112// VG_(*_end) vars -- ie. it names the last byte, whereas the others
113// go one byte past the end.
114
fitzhardinge98abfc72003-12-16 02:05:15 +0000115Addr VG_(valgrind_end);
116
fitzhardingeb50068f2004-02-24 23:42:55 +0000117vki_rlimit VG_(client_rlimit_data);
118
nethercote71980f02004-01-24 18:18:54 +0000119/* This is set early to indicate whether this CPU has the
120 SSE/fxsave/fxrestor features. */
121Bool VG_(have_ssestate);
122
fitzhardinge98abfc72003-12-16 02:05:15 +0000123/* stage1 (main) executable */
nethercotef6a1d502004-08-09 12:21:57 +0000124static Int vgexecfd = -1;
fitzhardingea49f9b52003-12-16 22:26:45 +0000125
126/* client executable */
127Int VG_(clexecfd) = -1;
fitzhardinge98abfc72003-12-16 02:05:15 +0000128
129/* Path to library directory */
130const Char *VG_(libdir) = VG_LIBDIR;
131
132/* our argc/argv */
nethercotef6a1d502004-08-09 12:21:57 +0000133static Int vg_argc;
134static Char **vg_argv;
fitzhardinge98abfc72003-12-16 02:05:15 +0000135
jsgf855d93d2003-10-13 22:26:55 +0000136/* PID of the main thread */
137Int VG_(main_pid);
138
139/* PGRP of process */
140Int VG_(main_pgrp);
njn25e49d8e72002-09-23 09:36:25 +0000141
thughesad1c9562004-06-26 11:27:52 +0000142/* Application-visible file descriptor limits */
143Int VG_(fd_soft_limit) = -1;
144Int VG_(fd_hard_limit) = -1;
fitzhardingef0046f22003-12-18 02:39:22 +0000145
nethercote71980f02004-01-24 18:18:54 +0000146/* As deduced from esp_at_startup, the client's argc, argv[] and
147 envp[] as extracted from the client's stack at startup-time. */
148Int VG_(client_argc);
149Char** VG_(client_argv);
150Char** VG_(client_envp);
sewardjde4a1d02002-03-22 01:27:54 +0000151
152/* ---------------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +0000153 Running stuff
sewardjde4a1d02002-03-22 01:27:54 +0000154 ------------------------------------------------------------------ */
sewardjde4a1d02002-03-22 01:27:54 +0000155
nethercote71980f02004-01-24 18:18:54 +0000156/* Counts downwards in VG_(run_innerloop). */
157UInt VG_(dispatch_ctr);
sewardjde4a1d02002-03-22 01:27:54 +0000158
159/* 64-bit counter for the number of basic blocks done. */
160ULong VG_(bbs_done);
sewardjde4a1d02002-03-22 01:27:54 +0000161
nethercote71980f02004-01-24 18:18:54 +0000162/* Tell the logging mechanism whether we are logging to a file
163 descriptor or a socket descriptor. */
164Bool VG_(logging_to_filedes) = True;
165
sewardj73cf3bc2002-11-03 03:20:15 +0000166
nethercote71980f02004-01-24 18:18:54 +0000167/*====================================================================*/
168/*=== Counters, for profiling purposes only ===*/
169/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +0000170
nethercote92e7b7f2004-08-07 17:52:25 +0000171// These ones maintained by vg_dispatch.S
172UInt VG_(bb_enchain_count) = 0; // Number of chain operations done
173UInt VG_(bb_dechain_count) = 0; // Number of unchain operations done
174UInt VG_(unchained_jumps_done) = 0; // Number of unchained jumps done
sewardjde4a1d02002-03-22 01:27:54 +0000175
sewardjde4a1d02002-03-22 01:27:54 +0000176/* Counts pertaining to internal sanity checking. */
nethercote297effd2004-08-02 15:07:57 +0000177static UInt sanity_fast_count = 0;
178static UInt sanity_slow_count = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000179
nethercote3a42fb82004-08-03 18:08:50 +0000180static void print_all_stats ( void )
nethercote71980f02004-01-24 18:18:54 +0000181{
nethercote3a42fb82004-08-03 18:08:50 +0000182 // Translation stats
nethercote92e7b7f2004-08-07 17:52:25 +0000183 VG_(print_tt_tc_stats)();
nethercote71980f02004-01-24 18:18:54 +0000184 VG_(message)(Vg_DebugMsg,
nethercote92e7b7f2004-08-07 17:52:25 +0000185 "chainings: %d chainings, %d unchainings.",
nethercote71980f02004-01-24 18:18:54 +0000186 VG_(bb_enchain_count), VG_(bb_dechain_count) );
187 VG_(message)(Vg_DebugMsg,
nethercote3a42fb82004-08-03 18:08:50 +0000188 " dispatch: %llu jumps (bb entries); of them %u (%lu%%) unchained.",
nethercote71980f02004-01-24 18:18:54 +0000189 VG_(bbs_done),
190 VG_(unchained_jumps_done),
191 ((ULong)(100) * (ULong)(VG_(unchained_jumps_done)))
192 / ( VG_(bbs_done)==0 ? 1 : VG_(bbs_done) )
193 );
194
nethercote3a42fb82004-08-03 18:08:50 +0000195 // Scheduler stats
nethercote844e7122004-08-02 15:27:22 +0000196 VG_(print_scheduler_stats)();
nethercote71980f02004-01-24 18:18:54 +0000197
nethercote3a42fb82004-08-03 18:08:50 +0000198 // Reg-alloc stats
nethercotebee3fd92004-08-02 15:17:43 +0000199 VG_(print_reg_alloc_stats)();
nethercote71980f02004-01-24 18:18:54 +0000200 VG_(message)(Vg_DebugMsg,
201 " sanity: %d cheap, %d expensive checks.",
nethercote297effd2004-08-02 15:07:57 +0000202 sanity_fast_count, sanity_slow_count );
nethercote3a42fb82004-08-03 18:08:50 +0000203
204 // C call stats
nethercote71980f02004-01-24 18:18:54 +0000205 VG_(print_ccall_stats)();
nethercote3a42fb82004-08-03 18:08:50 +0000206
207 // UInstr histogram
208 if (VG_(clo_verbosity) > 3)
209 VG_(print_UInstr_histogram)();
210
211 // Memory stats
nethercote885dd912004-08-03 23:14:00 +0000212 if (VG_(clo_verbosity) > 2) {
nethercote3a42fb82004-08-03 18:08:50 +0000213 VG_(message)(Vg_DebugMsg, "");
214 VG_(message)(Vg_DebugMsg,
215 "------ Valgrind's internal memory use stats follow ------" );
nethercote885dd912004-08-03 23:14:00 +0000216 VG_(sanity_check_malloc_all)();
nethercote3a42fb82004-08-03 18:08:50 +0000217 VG_(print_all_arena_stats)();
nethercote885dd912004-08-03 23:14:00 +0000218 VG_(message)(Vg_DebugMsg, "");
nethercote3a42fb82004-08-03 18:08:50 +0000219 VG_(message)(Vg_DebugMsg,
220 "------ Valgrind's ExeContext management stats follow ------" );
221 VG_(print_ExeContext_stats)();
222 }
nethercote71980f02004-01-24 18:18:54 +0000223}
224
225
226/*====================================================================*/
227/*=== Miscellaneous global functions ===*/
228/*====================================================================*/
229
nethercote04d0fbc2004-01-26 16:48:06 +0000230/* Start debugger and get it to attach to this process. Called if the
231 user requests this service after an error has been shown, so she can
nethercote71980f02004-01-24 18:18:54 +0000232 poke around and look at parameters, memory, etc. You can't
nethercote04d0fbc2004-01-26 16:48:06 +0000233 meaningfully get the debugger to continue the program, though; to
234 continue, quit the debugger. */
235void VG_(start_debugger) ( Int tid )
nethercote71980f02004-01-24 18:18:54 +0000236{
237 Int pid;
238
239 if ((pid = fork()) == 0) {
240 ptrace(PTRACE_TRACEME, 0, NULL, NULL);
241 VG_(kkill)(VG_(getpid)(), VKI_SIGSTOP);
242
243 } else if (pid > 0) {
244 struct user_regs_struct regs;
245 Int status;
246 Int res;
247
nethercote9380b4a2004-09-07 22:22:39 +0000248 if (VG_(is_running_thread)( tid ))
249 VGA_(regs_for_ptrace_from_BB)(&regs);
250 else
251 VGA_(regs_for_ptrace_from_tst)(&VG_(threads)[tid].arch, &regs);
nethercote71980f02004-01-24 18:18:54 +0000252
253 if ((res = VG_(waitpid)(pid, &status, 0)) == pid &&
254 WIFSTOPPED(status) && WSTOPSIG(status) == SIGSTOP &&
255 ptrace(PTRACE_SETREGS, pid, NULL, &regs) == 0 &&
thughes1d160052004-04-21 15:39:57 +0000256 kill(pid, SIGSTOP) == 0 &&
257 ptrace(PTRACE_DETACH, pid, NULL, 0) == 0) {
nethercote04d0fbc2004-01-26 16:48:06 +0000258 Char pidbuf[15];
259 Char file[30];
260 Char buf[100];
261 Char *bufptr;
262 Char *cmdptr;
263
264 VG_(sprintf)(pidbuf, "%d", pid);
265 VG_(sprintf)(file, "/proc/%d/fd/%d", pid, VG_(clexecfd));
266
267 bufptr = buf;
268 cmdptr = VG_(clo_db_command);
269
270 while (*cmdptr) {
271 switch (*cmdptr) {
272 case '%':
273 switch (*++cmdptr) {
274 case 'f':
275 VG_(memcpy)(bufptr, file, VG_(strlen)(file));
276 bufptr += VG_(strlen)(file);
277 cmdptr++;
278 break;
279 case 'p':
280 VG_(memcpy)(bufptr, pidbuf, VG_(strlen)(pidbuf));
281 bufptr += VG_(strlen)(pidbuf);
282 cmdptr++;
283 break;
284 default:
285 *bufptr++ = *cmdptr++;
286 break;
287 }
288 break;
289 default:
290 *bufptr++ = *cmdptr++;
291 break;
292 }
293 }
294
295 *bufptr++ = '\0';
296
297 VG_(message)(Vg_UserMsg, "starting debugger with cmd: %s", buf);
nethercote71980f02004-01-24 18:18:54 +0000298 res = VG_(system)(buf);
299 if (res == 0) {
300 VG_(message)(Vg_UserMsg, "");
301 VG_(message)(Vg_UserMsg,
nethercote04d0fbc2004-01-26 16:48:06 +0000302 "Debugger has detached. Valgrind regains control. We continue.");
nethercote71980f02004-01-24 18:18:54 +0000303 } else {
304 VG_(message)(Vg_UserMsg, "Apparently failed!");
305 VG_(message)(Vg_UserMsg, "");
306 }
307 }
308
309 VG_(kkill)(pid, VKI_SIGKILL);
310 VG_(waitpid)(pid, &status, 0);
311 }
312}
313
314
315/* Print some helpful-ish text about unimplemented things, and give
316 up. */
317void VG_(unimplemented) ( Char* msg )
318{
319 VG_(message)(Vg_UserMsg, "");
320 VG_(message)(Vg_UserMsg,
321 "Valgrind detected that your program requires");
322 VG_(message)(Vg_UserMsg,
323 "the following unimplemented functionality:");
324 VG_(message)(Vg_UserMsg, " %s", msg);
325 VG_(message)(Vg_UserMsg,
326 "This may be because the functionality is hard to implement,");
327 VG_(message)(Vg_UserMsg,
328 "or because no reasonable program would behave this way,");
329 VG_(message)(Vg_UserMsg,
330 "or because nobody has yet needed it. In any case, let us know at");
331 VG_(message)(Vg_UserMsg,
332 "%s and/or try to work around the problem, if you can.", VG_BUGS_TO);
333 VG_(message)(Vg_UserMsg,
334 "");
335 VG_(message)(Vg_UserMsg,
336 "Valgrind has to exit now. Sorry. Bye!");
337 VG_(message)(Vg_UserMsg,
338 "");
339 VG_(pp_sched_status)();
340 VG_(exit)(1);
341}
342
343Addr VG_(get_stack_pointer) ( void )
344{
345 return VG_(baseBlock)[VGOFF_(m_esp)];
346}
347
348/* Debugging thing .. can be called from assembly with OYNK macro. */
349void VG_(oynk) ( Int n )
350{
351 OINK(n);
352}
353
354/* Initialize the PID and PGRP of scheduler LWP; this is also called
355 in any new children after fork. */
356static void newpid(ThreadId unused)
357{
358 /* PID of scheduler LWP */
359 VG_(main_pid) = VG_(getpid)();
360 VG_(main_pgrp) = VG_(getpgrp)();
361}
362
363/*====================================================================*/
364/*=== Check we were launched by stage 1 ===*/
365/*====================================================================*/
366
367/* Look for our AUXV table */
nethercote31779c72004-07-30 21:50:15 +0000368int scan_auxv(void)
nethercote71980f02004-01-24 18:18:54 +0000369{
370 const struct ume_auxv *auxv = find_auxv((int *)ume_exec_esp);
nethercote31779c72004-07-30 21:50:15 +0000371 int padfile = -1, found = 0;
nethercote71980f02004-01-24 18:18:54 +0000372
373 for (; auxv->a_type != AT_NULL; auxv++)
374 switch(auxv->a_type) {
375 case AT_UME_PADFD:
nethercote31779c72004-07-30 21:50:15 +0000376 padfile = auxv->u.a_val;
nethercote71980f02004-01-24 18:18:54 +0000377 found |= 1;
378 break;
379
380 case AT_UME_EXECFD:
nethercotef6a1d502004-08-09 12:21:57 +0000381 vgexecfd = auxv->u.a_val;
nethercote71980f02004-01-24 18:18:54 +0000382 found |= 2;
383 break;
384 }
385
nethercote361a14e2004-07-26 11:11:56 +0000386 if ( found != (1|2) ) {
387 fprintf(stderr, "valgrind: stage2 must be launched by stage1\n");
nethercote71980f02004-01-24 18:18:54 +0000388 exit(127);
389 }
nethercote31779c72004-07-30 21:50:15 +0000390 vg_assert(padfile >= 0);
391 return padfile;
nethercote71980f02004-01-24 18:18:54 +0000392}
393
394
395/*====================================================================*/
396/*=== Address space determination ===*/
397/*====================================================================*/
398
nethercote31779c72004-07-30 21:50:15 +0000399static void layout_remaining_space(Addr argc_addr, float ratio)
nethercote71980f02004-01-24 18:18:54 +0000400{
nethercote31779c72004-07-30 21:50:15 +0000401 Int ires;
402 void* vres;
403 addr_t client_size, shadow_size;
nethercote71980f02004-01-24 18:18:54 +0000404
nethercote31779c72004-07-30 21:50:15 +0000405 VG_(valgrind_base) = (addr_t)&kickstart_base;
rjwalsh18b66312004-08-23 18:15:12 +0000406
407 // VG_(valgrind_end) has a slightly different meaning to all the other
408 // VG_(*_end) vars -- ie. it names the last byte, whereas the others
409 // go one byte past the end.
410
rjwalshebca8b42004-08-23 18:13:16 +0000411 VG_(valgrind_end) = ROUNDUP(argc_addr, 0x10000) - 1; // stack
nethercote71980f02004-01-24 18:18:54 +0000412
nethercote31779c72004-07-30 21:50:15 +0000413 // This gives the client the largest possible address space while
414 // taking into account the tool's shadow needs.
415 client_size = ROUNDDN((VG_(valgrind_base)-REDZONE_SIZE) / (1.+ratio),
nethercote71980f02004-01-24 18:18:54 +0000416 CLIENT_SIZE_MULTIPLE);
nethercote31779c72004-07-30 21:50:15 +0000417 VG_(client_base) = CLIENT_BASE;
nethercote71980f02004-01-24 18:18:54 +0000418 VG_(client_end) = VG_(client_base) + client_size;
nethercotee2097312004-06-27 12:29:56 +0000419 /* where !FIXED mmap goes */
nethercotebc7b4f42004-07-26 12:44:35 +0000420 VG_(client_mapbase) = VG_(client_base) +
421 PGROUNDDN((addr_t)(client_size * CLIENT_HEAP_PROPORTION));
nethercote71980f02004-01-24 18:18:54 +0000422
nethercote31779c72004-07-30 21:50:15 +0000423 VG_(shadow_base) = VG_(client_end) + REDZONE_SIZE;
nethercote410bfe62004-09-04 15:53:35 +0000424 VG_(shadow_end) = VG_(valgrind_base);
425 shadow_size = VG_(shadow_end) - VG_(shadow_base);
nethercote71980f02004-01-24 18:18:54 +0000426
nethercotee2097312004-06-27 12:29:56 +0000427#define SEGSIZE(a,b) ((VG_(b) - VG_(a))/(1024*1024))
428
nethercote71980f02004-01-24 18:18:54 +0000429 if (0)
nethercotee2097312004-06-27 12:29:56 +0000430 VG_(printf)(
431 "client_base %8x (%dMB)\n"
432 "client_mapbase %8x (%dMB)\n"
433 "client_end %8x (%dMB)\n"
434 "shadow_base %8x (%dMB)\n"
nethercote410bfe62004-09-04 15:53:35 +0000435 "shadow_end %8x\n"
nethercotee2097312004-06-27 12:29:56 +0000436 "valgrind_base %8x (%dMB)\n"
nethercotee2097312004-06-27 12:29:56 +0000437 "valgrind_end %8x\n",
438 VG_(client_base), SEGSIZE(client_base, client_mapbase),
439 VG_(client_mapbase), SEGSIZE(client_mapbase, client_end),
440 VG_(client_end), SEGSIZE(client_end, shadow_base),
441 VG_(shadow_base), SEGSIZE(shadow_base, shadow_end),
nethercote410bfe62004-09-04 15:53:35 +0000442 VG_(shadow_end),
nethercotec314eba2004-07-15 12:59:41 +0000443 VG_(valgrind_base), SEGSIZE(valgrind_base, valgrind_end),
nethercotee2097312004-06-27 12:29:56 +0000444 VG_(valgrind_end)
445 );
446
447#undef SEGSIZE
nethercote71980f02004-01-24 18:18:54 +0000448
449 // Ban redzone
nethercotee567e702004-07-10 17:49:17 +0000450 vres = mmap((void *)VG_(client_end), REDZONE_SIZE, PROT_NONE,
451 MAP_FIXED|MAP_ANON|MAP_PRIVATE, -1, 0);
452 vg_assert((void*)-1 != vres);
nethercote71980f02004-01-24 18:18:54 +0000453
454 // Make client hole
nethercotee567e702004-07-10 17:49:17 +0000455 ires = munmap((void*)VG_(client_base), client_size);
456 vg_assert(0 == ires);
nethercote71980f02004-01-24 18:18:54 +0000457
458 // Map shadow memory.
459 // Initially all inaccessible, incrementally initialized as it is used
nethercotee567e702004-07-10 17:49:17 +0000460 if (shadow_size != 0) {
461 vres = mmap((char *)VG_(shadow_base), shadow_size, PROT_NONE,
462 MAP_PRIVATE|MAP_ANON|MAP_FIXED, -1, 0);
nethercoted4722622004-08-30 19:36:42 +0000463 if ((void*)-1 == vres) {
464 fprintf(stderr,
465 "valgrind: Couldn't allocate address space for shadow memory\n"
466 "valgrind: Are you using a kernel with a small user address space,\n"
467 "valgrind: or do you have your virtual memory size limited?\n");
468 exit(1);
469 }
nethercotee567e702004-07-10 17:49:17 +0000470 }
nethercote71980f02004-01-24 18:18:54 +0000471}
472
473/*====================================================================*/
474/*=== Command line setup ===*/
475/*====================================================================*/
476
477/* Nb: malloc'd memory never freed -- kept throughout like argv, envp */
478static char* get_file_clo(char* dir)
479{
480# define FLEN 512
481 Int fd, n;
482 struct stat s1;
483 char* f_clo = NULL;
484 char filename[FLEN];
485
486 snprintf(filename, FLEN, "%s/.valgrindrc", ( NULL == dir ? "" : dir ) );
487 fd = VG_(open)(filename, 0, VKI_S_IRUSR);
488 if ( fd > 0 ) {
489 if ( 0 == fstat(fd, &s1) ) {
490 f_clo = malloc(s1.st_size+1);
491 vg_assert(f_clo);
492 n = read(fd, f_clo, s1.st_size);
493 if (n == -1) n = 0;
494 f_clo[n] = '\0';
495 }
496 close(fd);
497 }
498 return f_clo;
499# undef FLEN
500}
501
nethercotee2097312004-06-27 12:29:56 +0000502#define ISSPACE(cc) ((cc) == ' ' || (cc) == '\t' || (cc) == '\n')
503
nethercote71980f02004-01-24 18:18:54 +0000504static Int count_args(char* s)
505{
506 Int n = 0;
507 if (s) {
508 char* cp = s;
509 while (True) {
510 // We have alternating sequences: blanks, non-blanks, blanks...
511 // count the non-blanks sequences.
512 while ( ISSPACE(*cp) ) cp++;
513 if ( !*cp ) break;
514 n++;
515 while ( !ISSPACE(*cp) && *cp ) cp++;
516 }
517 }
518 return n;
519}
520
521/* add args out of environment, skipping multiple spaces and -- args */
522static char** copy_args( char* s, char** to )
523{
524 if (s) {
525 char* cp = s;
526 while (True) {
527 // We have alternating sequences: blanks, non-blanks, blanks...
528 // copy the non-blanks sequences, and add terminating '\0'
529 while ( ISSPACE(*cp) ) cp++;
530 if ( !*cp ) break;
531 *to++ = cp;
532 while ( !ISSPACE(*cp) && *cp ) cp++;
533 if ( *cp ) *cp++ = '\0'; // terminate if necessary
534 if (VG_STREQ(to[-1], "--")) to--; // undo any '--' arg
535 }
536 }
537 return to;
538}
539
nethercotee2097312004-06-27 12:29:56 +0000540#undef ISSPACE
541
nethercote71980f02004-01-24 18:18:54 +0000542// Augment command line with arguments from environment and .valgrindrc
543// files.
544static void augment_command_line(Int* vg_argc_inout, char*** vg_argv_inout)
545{
nethercotef6a1d502004-08-09 12:21:57 +0000546 int vg_argc0 = *vg_argc_inout;
547 char** vg_argv0 = *vg_argv_inout;
nethercote71980f02004-01-24 18:18:54 +0000548
549 char* env_clo = getenv(VALGRINDOPTS);
550 char* f1_clo = get_file_clo( getenv("HOME") );
551 char* f2_clo = get_file_clo(".");
552
553 /* copy any extra args from file or environment, if present */
554 if ( (env_clo && *env_clo) || (f1_clo && *f1_clo) || (f2_clo && *f2_clo) ) {
555 /* ' ' separated extra options */
556 char **from;
557 char **to;
558 int env_arg_count, f1_arg_count, f2_arg_count;
559
560 env_arg_count = count_args(env_clo);
561 f1_arg_count = count_args(f1_clo);
562 f2_arg_count = count_args(f2_clo);
563
564 if (0)
565 printf("extra-argc=%d %d %d\n",
566 env_arg_count, f1_arg_count, f2_arg_count);
567
568 /* +2: +1 for null-termination, +1 for added '--' */
nethercotef6a1d502004-08-09 12:21:57 +0000569 from = vg_argv0;
570 vg_argv0 = malloc( (vg_argc0 + env_arg_count + f1_arg_count
nethercote71980f02004-01-24 18:18:54 +0000571 + f2_arg_count + 2) * sizeof(char **));
nethercotef6a1d502004-08-09 12:21:57 +0000572 vg_assert(vg_argv0);
573 to = vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000574
575 /* copy argv[0] */
576 *to++ = *from++;
577
578 /* Copy extra args from env var and file, in the order: ~/.valgrindrc,
579 * $VALGRIND_OPTS, ./.valgrindrc -- more local options are put later
580 * to override less local ones. */
581 to = copy_args(f1_clo, to);
582 to = copy_args(env_clo, to);
583 to = copy_args(f2_clo, to);
584
585 /* copy original arguments, stopping at command or -- */
586 while (*from) {
587 if (**from != '-')
588 break;
589 if (VG_STREQ(*from, "--")) {
590 from++; /* skip -- */
591 break;
592 }
593 *to++ = *from++;
594 }
595
596 /* add -- */
597 *to++ = "--";
598
nethercotef6a1d502004-08-09 12:21:57 +0000599 vg_argc0 = to - vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000600
601 /* copy rest of original command line, then NULL */
602 while (*from) *to++ = *from++;
603 *to = NULL;
604 }
605
nethercotef6a1d502004-08-09 12:21:57 +0000606 *vg_argc_inout = vg_argc0;
607 *vg_argv_inout = vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000608}
609
nethercotef6a1d502004-08-09 12:21:57 +0000610#define VG_CLO_SEP '\01'
611
nethercote71980f02004-01-24 18:18:54 +0000612static void get_command_line( int argc, char** argv,
613 Int* vg_argc_out, Char*** vg_argv_out,
614 char*** cl_argv_out )
615{
nethercotef6a1d502004-08-09 12:21:57 +0000616 int vg_argc0;
617 char** vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000618 char** cl_argv;
619 char* env_clo = getenv(VALGRINDCLO);
620
621 if (env_clo != NULL && *env_clo != '\0') {
622 char *cp;
623 char **cpp;
624
nethercotef6a1d502004-08-09 12:21:57 +0000625 /* OK, VALGRINDCLO is set, which means we must be a child of another
626 Valgrind process using --trace-children, so we're getting all our
627 arguments from VALGRINDCLO, and the entire command line belongs to
628 the client (including argv[0]) */
629 vg_argc0 = 1; /* argv[0] */
nethercote71980f02004-01-24 18:18:54 +0000630 for (cp = env_clo; *cp; cp++)
nethercotef6a1d502004-08-09 12:21:57 +0000631 if (*cp == VG_CLO_SEP)
632 vg_argc0++;
nethercote71980f02004-01-24 18:18:54 +0000633
nethercotef6a1d502004-08-09 12:21:57 +0000634 vg_argv0 = malloc(sizeof(char **) * (vg_argc0 + 1));
635 vg_assert(vg_argv0);
nethercote71980f02004-01-24 18:18:54 +0000636
nethercotef6a1d502004-08-09 12:21:57 +0000637 cpp = vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000638
639 *cpp++ = "valgrind"; /* nominal argv[0] */
640 *cpp++ = env_clo;
641
nethercotef6a1d502004-08-09 12:21:57 +0000642 // Replace the VG_CLO_SEP args separator with '\0'
nethercote71980f02004-01-24 18:18:54 +0000643 for (cp = env_clo; *cp; cp++) {
nethercotef6a1d502004-08-09 12:21:57 +0000644 if (*cp == VG_CLO_SEP) {
nethercote71980f02004-01-24 18:18:54 +0000645 *cp++ = '\0'; /* chop it up in place */
646 *cpp++ = cp;
647 }
648 }
649 *cpp = NULL;
650 cl_argv = argv;
651
652 } else {
653 /* Count the arguments on the command line. */
nethercotef6a1d502004-08-09 12:21:57 +0000654 vg_argv0 = argv;
nethercote71980f02004-01-24 18:18:54 +0000655
nethercotef6a1d502004-08-09 12:21:57 +0000656 for (vg_argc0 = 1; vg_argc0 < argc; vg_argc0++) {
657 if (argv[vg_argc0][0] != '-') /* exe name */
nethercote71980f02004-01-24 18:18:54 +0000658 break;
nethercotef6a1d502004-08-09 12:21:57 +0000659 if (VG_STREQ(argv[vg_argc0], "--")) { /* dummy arg */
660 vg_argc0++;
nethercote71980f02004-01-24 18:18:54 +0000661 break;
662 }
663 }
nethercotef6a1d502004-08-09 12:21:57 +0000664 cl_argv = &argv[vg_argc0];
nethercote71980f02004-01-24 18:18:54 +0000665
666 /* Get extra args from VALGRIND_OPTS and .valgrindrc files.
nethercotef6a1d502004-08-09 12:21:57 +0000667 Note we don't do this if getting args from VALGRINDCLO, as
668 those extra args will already be present in VALGRINDCLO. */
669 augment_command_line(&vg_argc0, &vg_argv0);
nethercote71980f02004-01-24 18:18:54 +0000670 }
671
672 if (0) {
673 Int i;
nethercotef6a1d502004-08-09 12:21:57 +0000674 for (i = 0; i < vg_argc0; i++)
675 printf("vg_argv0[%d]=\"%s\"\n", i, vg_argv0[i]);
nethercote71980f02004-01-24 18:18:54 +0000676 }
677
nethercotef6a1d502004-08-09 12:21:57 +0000678 *vg_argc_out = vg_argc0;
679 *vg_argv_out = (Char**)vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000680 *cl_argv_out = cl_argv;
681}
682
683
684/*====================================================================*/
685/*=== Environment and stack setup ===*/
686/*====================================================================*/
687
688/* Scan a colon-separated list, and call a function on each element.
689 The string must be mutable, because we insert a temporary '\0', but
thughes4ad52d02004-06-27 17:37:21 +0000690 the string will end up unmodified. (*func) should return True if it
nethercote71980f02004-01-24 18:18:54 +0000691 doesn't need to see any more.
thughes4ad52d02004-06-27 17:37:21 +0000692
693 This routine will return True if (*func) returns True and False if
694 it reaches the end of the list without that happening.
nethercote71980f02004-01-24 18:18:54 +0000695*/
thughes4ad52d02004-06-27 17:37:21 +0000696static Bool scan_colsep(char *colsep, Bool (*func)(const char *))
nethercote71980f02004-01-24 18:18:54 +0000697{
698 char *cp, *entry;
699 int end;
700
701 if (colsep == NULL ||
702 *colsep == '\0')
thughes4ad52d02004-06-27 17:37:21 +0000703 return False;
nethercote71980f02004-01-24 18:18:54 +0000704
705 entry = cp = colsep;
706
707 do {
708 end = (*cp == '\0');
709
710 if (*cp == ':' || *cp == '\0') {
711 char save = *cp;
712
713 *cp = '\0';
thughes21942d92004-07-12 09:35:37 +0000714 if ((*func)(entry)) {
715 *cp = save;
thughes4ad52d02004-06-27 17:37:21 +0000716 return True;
thughes21942d92004-07-12 09:35:37 +0000717 }
nethercote71980f02004-01-24 18:18:54 +0000718 *cp = save;
719 entry = cp+1;
720 }
721 cp++;
722 } while(!end);
thughes4ad52d02004-06-27 17:37:21 +0000723
724 return False;
725}
726
727static Bool contains(const char *p) {
728 if (VG_STREQ(p, VG_(libdir))) {
729 return True;
730 }
731 return False;
nethercote71980f02004-01-24 18:18:54 +0000732}
733
734/* Prepare the client's environment. This is basically a copy of our
735 environment, except:
736 1. LD_LIBRARY_PATH=$VALGRINDLIB:$LD_LIBRARY_PATH
737 2. LD_PRELOAD=$VALGRINDLIB/vg_inject.so:($VALGRINDLIB/vgpreload_TOOL.so:)?$LD_PRELOAD
738
739 If any of these is missing, then it is added.
740
741 Yummy. String hacking in C.
742
743 If this needs to handle any more variables it should be hacked
744 into something table driven.
745 */
746static char **fix_environment(char **origenv, const char *preload)
747{
748 static const char inject_so[] = "vg_inject.so";
749 static const char ld_library_path[] = "LD_LIBRARY_PATH=";
750 static const char ld_preload[] = "LD_PRELOAD=";
751 static const char valgrind_clo[] = VALGRINDCLO "=";
752 static const int ld_library_path_len = sizeof(ld_library_path)-1;
753 static const int ld_preload_len = sizeof(ld_preload)-1;
754 static const int valgrind_clo_len = sizeof(valgrind_clo)-1;
755 int ld_preload_done = 0;
756 int ld_library_path_done = 0;
757 char *inject_path;
758 int inject_path_len;
759 int vgliblen = strlen(VG_(libdir));
760 char **cpp;
761 char **ret;
762 int envc;
763 const int preloadlen = (preload == NULL) ? 0 : strlen(preload);
764
765 /* Find the vg_inject.so; also make room for the tool preload
766 library */
767 inject_path_len = sizeof(inject_so) + vgliblen + preloadlen + 16;
768 inject_path = malloc(inject_path_len);
nethercote7c018f42004-07-17 16:40:50 +0000769 vg_assert(inject_path);
nethercote71980f02004-01-24 18:18:54 +0000770
771 if (preload)
772 snprintf(inject_path, inject_path_len, "%s/%s:%s",
773 VG_(libdir), inject_so, preload);
774 else
775 snprintf(inject_path, inject_path_len, "%s/%s",
776 VG_(libdir), inject_so);
777
778 /* Count the original size of the env */
779 envc = 0; /* trailing NULL */
780 for (cpp = origenv; cpp && *cpp; cpp++)
781 envc++;
782
783 /* Allocate a new space */
784 ret = malloc(sizeof(char *) * (envc+3+1)); /* 3 new entries + NULL */
nethercote7c018f42004-07-17 16:40:50 +0000785 vg_assert(ret);
nethercote71980f02004-01-24 18:18:54 +0000786
787 /* copy it over */
788 for (cpp = ret; *origenv; )
789 *cpp++ = *origenv++;
790 *cpp = NULL;
791
792 vg_assert(envc == (cpp - ret));
793
794 /* Walk over the new environment, mashing as we go */
795 for (cpp = ret; cpp && *cpp; cpp++) {
796 if (memcmp(*cpp, ld_library_path, ld_library_path_len) == 0) {
nethercote71980f02004-01-24 18:18:54 +0000797 /* If the LD_LIBRARY_PATH already contains libdir, then don't
798 bother adding it again, even if it isn't the first (it
799 seems that the Java runtime will keep reexecing itself
800 unless its paths are at the front of LD_LIBRARY_PATH) */
thughes4ad52d02004-06-27 17:37:21 +0000801 if (!scan_colsep(*cpp + ld_library_path_len, contains)) {
nethercote71980f02004-01-24 18:18:54 +0000802 int len = strlen(*cpp) + vgliblen*2 + 16;
803 char *cp = malloc(len);
nethercote7c018f42004-07-17 16:40:50 +0000804 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000805
806 snprintf(cp, len, "%s%s:%s",
807 ld_library_path, VG_(libdir),
808 (*cpp)+ld_library_path_len);
809
810 *cpp = cp;
811 }
812
813 ld_library_path_done = 1;
814 } else if (memcmp(*cpp, ld_preload, ld_preload_len) == 0) {
815 int len = strlen(*cpp) + inject_path_len;
816 char *cp = malloc(len);
nethercote7c018f42004-07-17 16:40:50 +0000817 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000818
819 snprintf(cp, len, "%s%s:%s",
820 ld_preload, inject_path, (*cpp)+ld_preload_len);
821
822 *cpp = cp;
823
824 ld_preload_done = 1;
825 } else if (memcmp(*cpp, valgrind_clo, valgrind_clo_len) == 0) {
826 *cpp = "";
827 }
828 }
829
830 /* Add the missing bits */
831
832 if (!ld_library_path_done) {
833 int len = ld_library_path_len + vgliblen*2 + 16;
834 char *cp = malloc(len);
nethercote7c018f42004-07-17 16:40:50 +0000835 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000836
837 snprintf(cp, len, "%s%s", ld_library_path, VG_(libdir));
838
839 ret[envc++] = cp;
840 }
841
842 if (!ld_preload_done) {
843 int len = ld_preload_len + inject_path_len;
844 char *cp = malloc(len);
nethercote7c018f42004-07-17 16:40:50 +0000845 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000846
847 snprintf(cp, len, "%s%s",
848 ld_preload, inject_path);
849
850 ret[envc++] = cp;
851 }
852
853 ret[envc] = NULL;
854
855 return ret;
856}
857
858extern char **environ; /* our environment */
859//#include <error.h>
860
861/* Add a string onto the string table, and return its address */
862static char *copy_str(char **tab, const char *str)
863{
864 char *cp = *tab;
865 char *orig = cp;
866
867 while(*str)
868 *cp++ = *str++;
869 *cp++ = '\0';
870
871 if (0)
nethercotef84f6952004-07-15 14:58:33 +0000872 printf("copied %p \"%s\" len %d\n", orig, orig, cp-orig);
nethercote71980f02004-01-24 18:18:54 +0000873
874 *tab = cp;
875
876 return orig;
877}
878
879/*
880 This sets up the client's initial stack, containing the args,
881 environment and aux vector.
882
883 The format of the stack is:
884
885 higher address +-----------------+
886 | Trampoline code |
887 +-----------------+
888 | |
889 : string table :
890 | |
891 +-----------------+
892 | AT_NULL |
893 - -
894 | auxv |
895 +-----------------+
896 | NULL |
897 - -
898 | envp |
899 +-----------------+
900 | NULL |
901 - -
902 | argv |
903 +-----------------+
904 | argc |
905 lower address +-----------------+ <- esp
906 | undefined |
907 : :
908 */
909static Addr setup_client_stack(char **orig_argv, char **orig_envp,
910 const struct exeinfo *info,
911 UInt** client_auxv)
912{
nethercotee567e702004-07-10 17:49:17 +0000913 void* res;
nethercote71980f02004-01-24 18:18:54 +0000914 char **cpp;
915 char *strtab; /* string table */
916 char *stringbase;
917 addr_t *ptr;
918 struct ume_auxv *auxv;
919 const struct ume_auxv *orig_auxv;
920 const struct ume_auxv *cauxv;
921 unsigned stringsize; /* total size of strings in bytes */
922 unsigned auxsize; /* total size of auxv in bytes */
923 int argc; /* total argc */
924 int envc; /* total number of env vars */
925 unsigned stacksize; /* total client stack size */
926 addr_t cl_esp; /* client stack base (initial esp) */
927
928 /* use our own auxv as a prototype */
929 orig_auxv = find_auxv(ume_exec_esp);
930
931 /* ==================== compute sizes ==================== */
932
933 /* first of all, work out how big the client stack will be */
934 stringsize = 0;
935
936 /* paste on the extra args if the loader needs them (ie, the #!
937 interpreter and its argument) */
938 argc = 0;
nethercoted6a56872004-07-26 15:32:47 +0000939 if (info->interp_name != NULL) {
nethercote71980f02004-01-24 18:18:54 +0000940 argc++;
nethercoted6a56872004-07-26 15:32:47 +0000941 stringsize += strlen(info->interp_name) + 1;
nethercote71980f02004-01-24 18:18:54 +0000942 }
nethercoted6a56872004-07-26 15:32:47 +0000943 if (info->interp_args != NULL) {
nethercote71980f02004-01-24 18:18:54 +0000944 argc++;
nethercoted6a56872004-07-26 15:32:47 +0000945 stringsize += strlen(info->interp_args) + 1;
nethercote71980f02004-01-24 18:18:54 +0000946 }
947
948 /* now scan the args we're given... */
949 for (cpp = orig_argv; *cpp; cpp++) {
950 argc++;
951 stringsize += strlen(*cpp) + 1;
952 }
953
954 /* ...and the environment */
955 envc = 0;
956 for (cpp = orig_envp; cpp && *cpp; cpp++) {
957 envc++;
958 stringsize += strlen(*cpp) + 1;
959 }
960
961 /* now, how big is the auxv? */
962 auxsize = sizeof(*auxv); /* there's always at least one entry: AT_NULL */
963 for (cauxv = orig_auxv; cauxv->a_type != AT_NULL; cauxv++) {
964 if (cauxv->a_type == AT_PLATFORM)
965 stringsize += strlen(cauxv->u.a_ptr) + 1;
966 auxsize += sizeof(*cauxv);
967 }
968
969 /* OK, now we know how big the client stack is */
970 stacksize =
971 sizeof(int) + /* argc */
972 sizeof(char **)*argc + /* argv */
973 sizeof(char **) + /* terminal NULL */
974 sizeof(char **)*envc + /* envp */
975 sizeof(char **) + /* terminal NULL */
976 auxsize + /* auxv */
977 ROUNDUP(stringsize, sizeof(int)) +/* strings (aligned) */
978 VKI_BYTES_PER_PAGE; /* page for trampoline code */
979
nethercotef84f6952004-07-15 14:58:33 +0000980 // decide where stack goes!
981 VG_(clstk_end) = VG_(client_end);
982
983 VG_(client_trampoline_code) = VG_(clstk_end) - VKI_BYTES_PER_PAGE;
984
nethercote71980f02004-01-24 18:18:54 +0000985 /* cl_esp is the client's stack pointer */
nethercotef84f6952004-07-15 14:58:33 +0000986 cl_esp = VG_(clstk_end) - stacksize;
nethercote71980f02004-01-24 18:18:54 +0000987 cl_esp = ROUNDDN(cl_esp, 16); /* make stack 16 byte aligned */
988
nethercote71980f02004-01-24 18:18:54 +0000989 /* base of the string table (aligned) */
990 stringbase = strtab = (char *)(VG_(client_trampoline_code) - ROUNDUP(stringsize, sizeof(int)));
991
992 VG_(clstk_base) = PGROUNDDN(cl_esp);
nethercote71980f02004-01-24 18:18:54 +0000993
nethercote5ee67ca2004-06-22 14:00:09 +0000994 if (0)
995 printf("stringsize=%d auxsize=%d stacksize=%d\n"
nethercote6a27d832004-09-07 10:17:02 +0000996 "clstk_base %p\n"
997 "clstk_end %p\n",
998 stringsize, auxsize, stacksize,
999 (void*)VG_(clstk_base), (void*)VG_(clstk_end));
nethercote5ee67ca2004-06-22 14:00:09 +00001000
1001
nethercote71980f02004-01-24 18:18:54 +00001002 /* ==================== allocate space ==================== */
1003
1004 /* allocate a stack - mmap enough space for the stack */
nethercotef84f6952004-07-15 14:58:33 +00001005 res = mmap((void *)PGROUNDDN(cl_esp), VG_(clstk_end) - PGROUNDDN(cl_esp),
nethercotee567e702004-07-10 17:49:17 +00001006 PROT_READ | PROT_WRITE | PROT_EXEC,
1007 MAP_PRIVATE | MAP_ANON | MAP_FIXED, -1, 0);
1008 vg_assert((void*)-1 != res);
nethercote71980f02004-01-24 18:18:54 +00001009
1010 /* ==================== copy client stack ==================== */
1011
1012 ptr = (addr_t *)cl_esp;
1013
1014 /* --- argc --- */
1015 *ptr++ = argc; /* client argc */
1016
1017 /* --- argv --- */
nethercoted6a56872004-07-26 15:32:47 +00001018 if (info->interp_name) {
1019 *ptr++ = (addr_t)copy_str(&strtab, info->interp_name);
1020 free(info->interp_name);
nethercote71980f02004-01-24 18:18:54 +00001021 }
nethercoted6a56872004-07-26 15:32:47 +00001022 if (info->interp_args) {
1023 *ptr++ = (addr_t)copy_str(&strtab, info->interp_args);
1024 free(info->interp_args);
nethercote71980f02004-01-24 18:18:54 +00001025 }
1026 for (cpp = orig_argv; *cpp; ptr++, cpp++) {
1027 *ptr = (addr_t)copy_str(&strtab, *cpp);
1028 }
1029 *ptr++ = 0;
1030
1031 /* --- envp --- */
1032 VG_(client_envp) = (Char **)ptr;
1033 for (cpp = orig_envp; cpp && *cpp; ptr++, cpp++)
1034 *ptr = (addr_t)copy_str(&strtab, *cpp);
1035 *ptr++ = 0;
1036
1037 /* --- auxv --- */
1038 auxv = (struct ume_auxv *)ptr;
1039 *client_auxv = (UInt *)auxv;
1040
1041 for (; orig_auxv->a_type != AT_NULL; auxv++, orig_auxv++) {
1042 /* copy the entry... */
1043 *auxv = *orig_auxv;
1044
1045 /* ...and fix up the copy */
1046 switch(auxv->a_type) {
1047 case AT_PHDR:
1048 if (info->phdr == 0)
1049 auxv->a_type = AT_IGNORE;
1050 else
1051 auxv->u.a_val = info->phdr;
1052 break;
1053
1054 case AT_PHNUM:
1055 if (info->phdr == 0)
1056 auxv->a_type = AT_IGNORE;
1057 else
1058 auxv->u.a_val = info->phnum;
1059 break;
1060
1061 case AT_BASE:
1062 if (info->interp_base == 0)
1063 auxv->a_type = AT_IGNORE;
1064 else
1065 auxv->u.a_val = info->interp_base;
1066 break;
1067
1068 case AT_PLATFORM: /* points to a platform description string */
1069 auxv->u.a_ptr = copy_str(&strtab, orig_auxv->u.a_ptr);
1070 break;
1071
1072 case AT_ENTRY:
1073 auxv->u.a_val = info->entry;
1074 break;
1075
1076 case AT_IGNORE:
1077 case AT_EXECFD:
1078 case AT_PHENT:
1079 case AT_PAGESZ:
1080 case AT_FLAGS:
1081 case AT_NOTELF:
1082 case AT_UID:
1083 case AT_EUID:
1084 case AT_GID:
1085 case AT_EGID:
1086 case AT_CLKTCK:
1087 case AT_HWCAP:
1088 case AT_FPUCW:
1089 case AT_DCACHEBSIZE:
1090 case AT_ICACHEBSIZE:
1091 case AT_UCACHEBSIZE:
1092 /* All these are pointerless, so we don't need to do anything
1093 about them. */
1094 break;
1095
1096 case AT_SECURE:
1097 /* If this is 1, then it means that this program is running
1098 suid, and therefore the dynamic linker should be careful
1099 about LD_PRELOAD, etc. However, since stage1 (the thing
1100 the kernel actually execve's) should never be SUID, and we
1101 need LD_PRELOAD/LD_LIBRARY_PATH to work for the client, we
1102 set AT_SECURE to 0. */
1103 auxv->u.a_val = 0;
1104 break;
1105
1106 case AT_SYSINFO:
1107 /* Leave this unmolested for now, but we'll update it later
1108 when we set up the client trampoline code page */
1109 break;
1110
1111 case AT_SYSINFO_EHDR:
1112 /* Trash this, because we don't reproduce it */
1113 auxv->a_type = AT_IGNORE;
1114 break;
1115
1116 default:
1117 /* stomp out anything we don't know about */
1118 if (0)
1119 printf("stomping auxv entry %d\n", auxv->a_type);
1120 auxv->a_type = AT_IGNORE;
1121 break;
1122
1123 }
1124 }
1125 *auxv = *orig_auxv;
1126 vg_assert(auxv->a_type == AT_NULL);
1127
nethercotef84f6952004-07-15 14:58:33 +00001128 /* --- trampoline page --- */
1129 VG_(memcpy)( (void *)VG_(client_trampoline_code),
1130 &VG_(trampoline_code_start), VG_(trampoline_code_length) );
1131
nethercote71980f02004-01-24 18:18:54 +00001132 vg_assert((strtab-stringbase) == stringsize);
1133
nethercote5ee67ca2004-06-22 14:00:09 +00001134 /* We know the initial ESP is pointing at argc/argv */
1135 VG_(client_argc) = *(Int*)cl_esp;
1136 VG_(client_argv) = (Char**)(cl_esp + sizeof(Int));
1137
nethercote71980f02004-01-24 18:18:54 +00001138 return cl_esp;
1139}
1140
1141/*====================================================================*/
1142/*=== Find executable ===*/
1143/*====================================================================*/
1144
thughes4ad52d02004-06-27 17:37:21 +00001145static const char* executable_name;
1146
1147static Bool match_executable(const char *entry) {
1148 char buf[strlen(entry) + strlen(executable_name) + 2];
1149
1150 /* empty PATH element means . */
1151 if (*entry == '\0')
1152 entry = ".";
1153
1154 snprintf(buf, sizeof(buf), "%s/%s", entry, executable_name);
1155
1156 if (access(buf, R_OK|X_OK) == 0) {
1157 executable_name = strdup(buf);
1158 vg_assert(NULL != executable_name);
1159 return True;
1160 }
1161 return False;
1162}
1163
nethercote71980f02004-01-24 18:18:54 +00001164static const char* find_executable(const char* exec)
1165{
1166 vg_assert(NULL != exec);
thughes4ad52d02004-06-27 17:37:21 +00001167 executable_name = exec;
1168 if (strchr(executable_name, '/') == NULL) {
nethercote71980f02004-01-24 18:18:54 +00001169 /* no '/' - we need to search the path */
1170 char *path = getenv("PATH");
thughes4ad52d02004-06-27 17:37:21 +00001171 scan_colsep(path, match_executable);
nethercote71980f02004-01-24 18:18:54 +00001172 }
thughes4ad52d02004-06-27 17:37:21 +00001173 return executable_name;
nethercote71980f02004-01-24 18:18:54 +00001174}
1175
1176
1177/*====================================================================*/
1178/*=== Loading tools ===*/
1179/*====================================================================*/
1180
1181static void list_tools(void)
1182{
1183 DIR *dir = opendir(VG_(libdir));
1184 struct dirent *de;
1185 int first = 1;
1186
1187 if (dir == NULL) {
1188 fprintf(stderr, "Can't open %s: %s (installation problem?)\n",
nethercotef4928da2004-06-15 10:54:40 +00001189 VG_(libdir), strerror(errno));
nethercote71980f02004-01-24 18:18:54 +00001190 return;
1191 }
1192
nethercotef4928da2004-06-15 10:54:40 +00001193 while ((de = readdir(dir)) != NULL) {
nethercote71980f02004-01-24 18:18:54 +00001194 int len = strlen(de->d_name);
1195
1196 /* look for vgskin_TOOL.so names */
1197 if (len > (7+1+3) && /* "vgskin_" + at least 1-char toolname + ".so" */
nethercotef4928da2004-06-15 10:54:40 +00001198 strncmp(de->d_name, "vgskin_", 7) == 0 &&
1199 VG_STREQ(de->d_name + len - 3, ".so")) {
1200 if (first) {
1201 fprintf(stderr, "Available tools:\n");
1202 first = 0;
1203 }
1204 de->d_name[len-3] = '\0';
1205 fprintf(stderr, "\t%s\n", de->d_name+7);
nethercote71980f02004-01-24 18:18:54 +00001206 }
1207 }
1208
1209 closedir(dir);
1210
1211 if (first)
nethercotef4928da2004-06-15 10:54:40 +00001212 fprintf(stderr, "No tools available in \"%s\" (installation problem?)\n",
1213 VG_(libdir));
nethercote71980f02004-01-24 18:18:54 +00001214}
1215
1216
1217/* Find and load a tool, and check it looks ok. Also looks to see if there's
1218 * a matching vgpreload_*.so file, and returns its name in *preloadpath. */
1219static void load_tool( const char *toolname, void** handle_out,
1220 ToolInfo** toolinfo_out, char **preloadpath_out )
1221{
1222 Bool ok;
1223 int len = strlen(VG_(libdir)) + strlen(toolname)*2 + 16;
1224 char buf[len];
1225 void* handle;
1226 ToolInfo* toolinfo;
1227 char* preloadpath = NULL;
1228 Int* vg_malloc_redzonep;
1229
1230 // XXX: allowing full paths for --tool option -- does it make sense?
1231 // Doesn't allow for vgpreload_<tool>.so.
1232
1233 if (strchr(toolname, '/') != 0) {
1234 /* toolname contains '/', and so must be a pathname */
1235 handle = dlopen(toolname, RTLD_NOW);
1236 } else {
1237 /* just try in the libdir */
1238 snprintf(buf, len, "%s/vgskin_%s.so", VG_(libdir), toolname);
1239 handle = dlopen(buf, RTLD_NOW);
1240
1241 if (handle != NULL) {
1242 snprintf(buf, len, "%s/vgpreload_%s.so", VG_(libdir), toolname);
1243 if (access(buf, R_OK) == 0) {
1244 preloadpath = strdup(buf);
1245 vg_assert(NULL != preloadpath);
1246 }
1247 }
1248 }
1249
1250 ok = (NULL != handle);
1251 if (!ok) {
1252 fprintf(stderr, "Can't open tool \"%s\": %s\n", toolname, dlerror());
1253 goto bad_load;
1254 }
1255
1256 toolinfo = dlsym(handle, "vgSkin_tool_info");
1257 ok = (NULL != toolinfo);
1258 if (!ok) {
1259 fprintf(stderr, "Tool \"%s\" doesn't define SK_(tool_info) - "
1260 "add VG_DETERMINE_INTERFACE_VERSION?\n", toolname);
1261 goto bad_load;
1262 }
1263
1264 ok = (toolinfo->sizeof_ToolInfo == sizeof(*toolinfo) &&
1265 toolinfo->interface_major_version == VG_CORE_INTERFACE_MAJOR_VERSION &&
1266 toolinfo->sk_pre_clo_init != NULL);
1267 if (!ok) {
1268 fprintf(stderr, "Error:\n"
1269 " Tool and core interface versions do not match.\n"
1270 " Interface version used by core is: %d.%d (size %d)\n"
1271 " Interface version used by tool is: %d.%d (size %d)\n"
1272 " The major version numbers must match.\n",
1273 VG_CORE_INTERFACE_MAJOR_VERSION,
1274 VG_CORE_INTERFACE_MINOR_VERSION,
1275 sizeof(*toolinfo),
1276 toolinfo->interface_major_version,
1277 toolinfo->interface_minor_version,
1278 toolinfo->sizeof_ToolInfo);
1279 fprintf(stderr, " You need to at least recompile, and possibly update,\n");
1280 if (VG_CORE_INTERFACE_MAJOR_VERSION > toolinfo->interface_major_version)
nethercote996901a2004-08-03 13:29:09 +00001281 fprintf(stderr, " your tool to work with this version of Valgrind.\n");
nethercote71980f02004-01-24 18:18:54 +00001282 else
nethercote996901a2004-08-03 13:29:09 +00001283 fprintf(stderr, " your version of Valgrind to work with this tool.\n");
nethercote71980f02004-01-24 18:18:54 +00001284 goto bad_load;
1285 }
1286
1287 // Set redzone size for V's allocator
1288 vg_malloc_redzonep = dlsym(handle, STR(VG_(vg_malloc_redzone_szB)));
1289 if ( NULL != vg_malloc_redzonep ) {
1290 VG_(vg_malloc_redzone_szB) = *vg_malloc_redzonep;
1291 }
1292
1293 vg_assert(NULL != handle && NULL != toolinfo);
1294 *handle_out = handle;
1295 *toolinfo_out = toolinfo;
1296 *preloadpath_out = preloadpath;
1297 return;
1298
1299
1300 bad_load:
1301 if (handle != NULL)
1302 dlclose(handle);
1303
nethercotef4928da2004-06-15 10:54:40 +00001304 fprintf(stderr, "valgrind: couldn't load tool\n");
nethercote71980f02004-01-24 18:18:54 +00001305 list_tools();
1306 exit(127);
1307}
1308
nethercotef4928da2004-06-15 10:54:40 +00001309
1310/*====================================================================*/
1311/*=== Command line errors ===*/
1312/*====================================================================*/
1313
1314static void abort_msg ( void )
1315{
nethercotef8548672004-06-21 12:42:35 +00001316 VG_(clo_log_to) = VgLogTo_Fd;
1317 VG_(clo_log_fd) = 2; /* stderr */
nethercotef4928da2004-06-15 10:54:40 +00001318}
1319
1320void VG_(bad_option) ( Char* opt )
1321{
1322 abort_msg();
1323 VG_(printf)("valgrind: Bad option `%s'; aborting.\n", opt);
1324 VG_(printf)("valgrind: Use --help for more information.\n");
1325 VG_(exit)(1);
1326}
1327
1328static void missing_tool_option ( void )
1329{
1330 abort_msg();
1331 VG_(printf)("valgrind: Missing --tool option\n");
1332 list_tools();
1333 VG_(printf)("valgrind: Use --help for more information.\n");
1334 VG_(exit)(1);
1335}
1336
1337static void missing_prog ( void )
1338{
1339 abort_msg();
1340 VG_(printf)("valgrind: no program specified\n");
1341 VG_(printf)("valgrind: Use --help for more information.\n");
1342 VG_(exit)(1);
1343}
1344
1345static void config_error ( Char* msg )
1346{
1347 abort_msg();
1348 VG_(printf)("valgrind: Startup or configuration error:\n %s\n", msg);
1349 VG_(printf)("valgrind: Unable to start up properly. Giving up.\n");
1350 VG_(exit)(1);
1351}
1352
1353
nethercote71980f02004-01-24 18:18:54 +00001354/*====================================================================*/
1355/*=== Loading the client ===*/
1356/*====================================================================*/
1357
nethercotef4928da2004-06-15 10:54:40 +00001358static void load_client(char* cl_argv[], const char* exec, Int need_help,
nethercote71980f02004-01-24 18:18:54 +00001359 /*out*/struct exeinfo* info, /*out*/Addr* client_eip)
1360{
1361 // If they didn't specify an executable with --exec, and didn't specify
1362 // --help, then use client argv[0] (searching $PATH if necessary).
nethercotef4928da2004-06-15 10:54:40 +00001363 if (NULL == exec && !need_help) {
nethercote71980f02004-01-24 18:18:54 +00001364 if (cl_argv[0] == NULL ||
1365 ( NULL == (exec = find_executable(cl_argv[0])) ) )
1366 {
nethercotef4928da2004-06-15 10:54:40 +00001367 missing_prog();
nethercote71980f02004-01-24 18:18:54 +00001368 }
1369 }
1370
1371 info->map_base = VG_(client_mapbase);
nethercote71980f02004-01-24 18:18:54 +00001372 info->exe_base = VG_(client_base);
1373 info->exe_end = VG_(client_end);
1374 info->argv = cl_argv;
1375
nethercotef4928da2004-06-15 10:54:40 +00001376 if (need_help) {
nethercote71980f02004-01-24 18:18:54 +00001377 VG_(clexecfd) = -1;
nethercoteea147e72004-07-26 15:43:57 +00001378 // Set the minimal number of entries in 'info' to continue.
nethercoted6a56872004-07-26 15:32:47 +00001379 info->interp_name = NULL;
1380 info->interp_args = NULL;
nethercote71980f02004-01-24 18:18:54 +00001381 } else {
1382 Int ret;
1383 VG_(clexecfd) = VG_(open)(exec, O_RDONLY, VKI_S_IRUSR);
1384 ret = do_exec(exec, info);
1385 if (ret != 0) {
nethercoteea147e72004-07-26 15:43:57 +00001386 fprintf(stderr, "valgrind: do_exec(%s) failed: %s\n",
1387 exec, strerror(ret));
nethercote71980f02004-01-24 18:18:54 +00001388 exit(127);
1389 }
1390 }
1391
1392 /* Copy necessary bits of 'info' that were filled in */
1393 *client_eip = info->init_eip;
1394 VG_(brk_base) = VG_(brk_limit) = info->brkbase;
1395}
1396
1397
1398/*====================================================================*/
nethercotef6a1d502004-08-09 12:21:57 +00001399/*=== Command-line: variables, processing, etc ===*/
nethercote71980f02004-01-24 18:18:54 +00001400/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +00001401
njn25e49d8e72002-09-23 09:36:25 +00001402/* Define, and set defaults. */
1403Bool VG_(clo_error_limit) = True;
nethercote04d0fbc2004-01-26 16:48:06 +00001404Bool VG_(clo_db_attach) = False;
1405Char* VG_(clo_db_command) = VG_CLO_DEFAULT_DBCOMMAND;
njn43c799e2003-04-08 00:08:52 +00001406Bool VG_(clo_gen_suppressions) = False;
nethercote27fec902004-06-16 21:26:32 +00001407Int VG_(clo_sanity_level) = 1;
njn25e49d8e72002-09-23 09:36:25 +00001408Int VG_(clo_verbosity) = 1;
1409Bool VG_(clo_demangle) = True;
njn25e49d8e72002-09-23 09:36:25 +00001410Bool VG_(clo_trace_children) = False;
sewardj4cf05692002-10-27 20:28:29 +00001411
nethercotef1e5e152004-09-01 23:58:16 +00001412/* See big comment in core.h for meaning of these three.
nethercotee1730692003-11-20 10:38:07 +00001413 fd is initially stdout, for --help, but gets moved to stderr by default
1414 immediately afterwards. */
sewardj4cf05692002-10-27 20:28:29 +00001415VgLogTo VG_(clo_log_to) = VgLogTo_Fd;
nethercotef8548672004-06-21 12:42:35 +00001416Int VG_(clo_log_fd) = 1;
1417Char* VG_(clo_log_name) = NULL;
sewardj4cf05692002-10-27 20:28:29 +00001418
thughes6233a382004-08-21 11:10:44 +00001419Bool VG_(clo_time_stamp) = False;
1420
sewardj6024b212003-07-13 10:54:33 +00001421Int VG_(clo_input_fd) = 0; /* stdin */
njn25e49d8e72002-09-23 09:36:25 +00001422Int VG_(clo_n_suppressions) = 0;
sewardjde4a1d02002-03-22 01:27:54 +00001423Char* VG_(clo_suppressions)[VG_CLO_MAX_SFILES];
njn25e49d8e72002-09-23 09:36:25 +00001424Bool VG_(clo_profile) = False;
1425Bool VG_(clo_single_step) = False;
1426Bool VG_(clo_optimise) = True;
1427UChar VG_(clo_trace_codegen) = 0; // 00000000b
1428Bool VG_(clo_trace_syscalls) = False;
1429Bool VG_(clo_trace_signals) = False;
1430Bool VG_(clo_trace_symtab) = False;
njn25e49d8e72002-09-23 09:36:25 +00001431Bool VG_(clo_trace_sched) = False;
1432Int VG_(clo_trace_pthread_level) = 0;
njn25e49d8e72002-09-23 09:36:25 +00001433Int VG_(clo_dump_error) = 0;
1434Int VG_(clo_backtrace_size) = 4;
1435Char* VG_(clo_weird_hacks) = NULL;
sewardj858964b2002-10-05 14:15:43 +00001436Bool VG_(clo_run_libc_freeres) = True;
rjwalshf5f536f2003-11-17 17:45:00 +00001437Bool VG_(clo_track_fds) = False;
sewardj22854b92002-11-30 14:00:47 +00001438Bool VG_(clo_chain_bb) = True;
nethercote77eba602003-11-13 17:35:04 +00001439Bool VG_(clo_show_below_main) = False;
fitzhardinge98abfc72003-12-16 02:05:15 +00001440Bool VG_(clo_pointercheck) = True;
fitzhardinge462f4f92003-12-18 02:10:54 +00001441Bool VG_(clo_branchpred) = False;
sewardj2370f3b2002-11-30 15:01:01 +00001442
jsgf855d93d2003-10-13 22:26:55 +00001443static Bool VG_(clo_wait_for_gdb) = False;
1444
1445/* If we're doing signal routing, poll for signals every 50mS by
1446 default. */
1447Int VG_(clo_signal_polltime) = 50;
1448
1449/* These flags reduce thread wakeup latency on syscall completion and
1450 signal delivery, respectively. The downside is possible unfairness. */
1451Bool VG_(clo_lowlat_syscalls) = False; /* low-latency syscalls */
1452Bool VG_(clo_lowlat_signals) = False; /* low-latency signals */
1453
sewardjde4a1d02002-03-22 01:27:54 +00001454
nethercote6c999f22004-01-31 22:55:15 +00001455void usage ( Bool debug_help )
njn7cf0bd32002-06-08 13:36:03 +00001456{
njn25e49d8e72002-09-23 09:36:25 +00001457 Char* usage1 =
nethercote71980f02004-01-24 18:18:54 +00001458"usage: valgrind --tool=<toolname> [options] prog-and-args\n"
njn25e49d8e72002-09-23 09:36:25 +00001459"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001460" common user options for all Valgrind tools, with defaults in [ ]:\n"
nethercote0d588502004-06-21 13:27:11 +00001461" --tool=<name> use the Valgrind tool named <name>\n"
nethercotea76368b2004-06-16 11:56:29 +00001462" -h --help show this message\n"
nethercote6c999f22004-01-31 22:55:15 +00001463" --help-debug show this message, plus debugging options\n"
njn25e49d8e72002-09-23 09:36:25 +00001464" --version show version\n"
njn25e49d8e72002-09-23 09:36:25 +00001465" -q --quiet run silently; only print error msgs\n"
1466" -v --verbose be more verbose, incl counts of errors\n"
nethercote77eba602003-11-13 17:35:04 +00001467" --trace-children=no|yes Valgrind-ise child processes? [no]\n"
nethercote0d588502004-06-21 13:27:11 +00001468" --track-fds=no|yes track open file descriptors? [no]\n"
thughes6233a382004-08-21 11:10:44 +00001469" --time-stamp=no|yes add timestamps to log messages? [no]\n"
nethercote2b0793f2003-12-02 10:41:18 +00001470"\n"
1471" uncommon user options for all Valgrind tools:\n"
nethercote0d588502004-06-21 13:27:11 +00001472" --run-libc-freeres=no|yes free up glibc memory at exit? [yes]\n"
1473" --weird-hacks=hack1,hack2,... recognised hacks: lax-ioctls [none]\n"
1474" --signal-polltime=<time> signal poll period (mS) for older kernels [50]\n"
1475" --lowlat-signals=no|yes improve thread signal wake-up latency [no]\n"
1476" --lowlat-syscalls=no|yes improve thread syscall wake-up latency [no]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001477" --pointercheck=no|yes enforce client address space limits [yes]\n"
njn25e49d8e72002-09-23 09:36:25 +00001478"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001479" user options for Valgrind tools that report errors:\n"
nethercotef8548672004-06-21 12:42:35 +00001480" --log-fd=<number> log messages to file descriptor [2=stderr]\n"
1481" --log-file=<file> log messages to <file>.pid<pid>\n"
1482" --log-socket=ipaddr:port log messages to socket ipaddr:port\n"
nethercote2b0793f2003-12-02 10:41:18 +00001483" --demangle=no|yes automatically demangle C++ names? [yes]\n"
1484" --num-callers=<number> show <num> callers in stack traces [4]\n"
1485" --error-limit=no|yes stop showing new errors if too many? [yes]\n"
1486" --show-below-main=no|yes continue stack traces below main() [no]\n"
1487" --suppressions=<filename> suppress errors described in <filename>\n"
1488" --gen-suppressions=no|yes print suppressions for errors detected [no]\n"
nethercote04d0fbc2004-01-26 16:48:06 +00001489" --db-attach=no|yes start debugger when errors detected? [no]\n"
1490" --db-command=<command> command to start debugger [gdb -nw %%f %%p]\n"
1491" --input-fd=<number> file descriptor for input [0=stdin]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001492"\n";
njn7cf0bd32002-06-08 13:36:03 +00001493
njn25e49d8e72002-09-23 09:36:25 +00001494 Char* usage2 =
1495"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001496" debugging options for all Valgrind tools:\n"
njn25e49d8e72002-09-23 09:36:25 +00001497" --sanity-level=<number> level of sanity checking to do [1]\n"
1498" --single-step=no|yes translate each instr separately? [no]\n"
1499" --optimise=no|yes improve intermediate code? [yes]\n"
nethercote137bc552003-11-14 17:47:54 +00001500" --profile=no|yes profile? (tool must be built for it) [no]\n"
sewardj22854b92002-11-30 14:00:47 +00001501" --chain-bb=no|yes do basic-block chaining? [yes]\n"
fitzhardinge462f4f92003-12-18 02:10:54 +00001502" --branchpred=yes|no generate branch prediction hints [no]\n"
njn25e49d8e72002-09-23 09:36:25 +00001503" --trace-codegen=<XXXXX> show generated code? (X = 0|1) [00000]\n"
1504" --trace-syscalls=no|yes show all system calls? [no]\n"
1505" --trace-signals=no|yes show signal handling details? [no]\n"
1506" --trace-symtab=no|yes show symbol table details? [no]\n"
njn25e49d8e72002-09-23 09:36:25 +00001507" --trace-sched=no|yes show thread scheduler details? [no]\n"
njn3e884182003-04-15 13:03:23 +00001508" --trace-pthread=none|some|all show pthread event details? [none]\n"
jsgf855d93d2003-10-13 22:26:55 +00001509" --wait-for-gdb=yes|no pause on startup to wait for gdb attach\n"
njn25e49d8e72002-09-23 09:36:25 +00001510"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001511" debugging options for Valgrind tools that report errors\n"
1512" --dump-error=<number> show translation for basic block associated\n"
1513" with <number>'th error context [0=show none]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001514"\n";
njn3e884182003-04-15 13:03:23 +00001515
1516 Char* usage3 =
1517"\n"
nethercote71980f02004-01-24 18:18:54 +00001518" Extra options read from ~/.valgrindrc, $VALGRIND_OPTS, ./.valgrindrc\n"
njn25e49d8e72002-09-23 09:36:25 +00001519"\n"
nethercote08fa9a72004-07-16 17:44:00 +00001520" Valgrind is Copyright (C) 2000-2004 Julian Seward et al.\n"
njn25e49d8e72002-09-23 09:36:25 +00001521" and licensed under the GNU General Public License, version 2.\n"
1522" Bug reports, feedback, admiration, abuse, etc, to: %s.\n"
njnd04b7c62002-10-03 14:05:52 +00001523"\n"
nethercote137bc552003-11-14 17:47:54 +00001524" Tools are copyright and licensed by their authors. See each\n"
1525" tool's start-up message for more information.\n"
njn25e49d8e72002-09-23 09:36:25 +00001526"\n";
njn7cf0bd32002-06-08 13:36:03 +00001527
fitzhardinge98abfc72003-12-16 02:05:15 +00001528 VG_(printf)(usage1);
1529 if (VG_(details).name) {
1530 VG_(printf)(" user options for %s:\n", VG_(details).name);
fitzhardinge98abfc72003-12-16 02:05:15 +00001531 if (VG_(needs).command_line_options)
1532 SK_(print_usage)();
1533 else
1534 VG_(printf)(" (none)\n");
1535 }
nethercote6c999f22004-01-31 22:55:15 +00001536 if (debug_help) {
1537 VG_(printf)(usage2);
fitzhardinge98abfc72003-12-16 02:05:15 +00001538
nethercote6c999f22004-01-31 22:55:15 +00001539 if (VG_(details).name) {
1540 VG_(printf)(" debugging options for %s:\n", VG_(details).name);
1541
1542 if (VG_(needs).command_line_options)
1543 SK_(print_debug_usage)();
1544 else
1545 VG_(printf)(" (none)\n");
1546 }
fitzhardinge98abfc72003-12-16 02:05:15 +00001547 }
nethercote421281e2003-11-20 16:20:55 +00001548 VG_(printf)(usage3, VG_BUGS_TO);
nethercotef4928da2004-06-15 10:54:40 +00001549 VG_(exit)(0);
njn7cf0bd32002-06-08 13:36:03 +00001550}
sewardjde4a1d02002-03-22 01:27:54 +00001551
nethercote71980f02004-01-24 18:18:54 +00001552static void pre_process_cmd_line_options
nethercote6c999f22004-01-31 22:55:15 +00001553 ( Int* need_help, const char** tool, const char** exec )
sewardj1c1b1162003-02-23 01:25:51 +00001554{
nethercote71980f02004-01-24 18:18:54 +00001555 UInt i;
sewardjde4a1d02002-03-22 01:27:54 +00001556
nethercote71980f02004-01-24 18:18:54 +00001557 /* parse the options we have (only the options we care about now) */
nethercotef6a1d502004-08-09 12:21:57 +00001558 for (i = 1; i < vg_argc; i++) {
nethercote71980f02004-01-24 18:18:54 +00001559
nethercotef6a1d502004-08-09 12:21:57 +00001560 if (strcmp(vg_argv[i], "--version") == 0) {
nethercote71980f02004-01-24 18:18:54 +00001561 printf("valgrind-" VERSION "\n");
nethercotef4928da2004-06-15 10:54:40 +00001562 exit(0);
nethercote71980f02004-01-24 18:18:54 +00001563
nethercotef6a1d502004-08-09 12:21:57 +00001564 } else if (VG_CLO_STREQ(vg_argv[i], "--help") ||
1565 VG_CLO_STREQ(vg_argv[i], "-h")) {
nethercote6c999f22004-01-31 22:55:15 +00001566 *need_help = 1;
1567
nethercotef6a1d502004-08-09 12:21:57 +00001568 } else if (VG_CLO_STREQ(vg_argv[i], "--help-debug")) {
nethercote6c999f22004-01-31 22:55:15 +00001569 *need_help = 2;
nethercote71980f02004-01-24 18:18:54 +00001570
nethercotef6a1d502004-08-09 12:21:57 +00001571 } else if (VG_CLO_STREQN(7, vg_argv[i], "--tool=") ||
1572 VG_CLO_STREQN(7, vg_argv[i], "--skin=")) {
1573 *tool = &vg_argv[i][7];
nethercote71980f02004-01-24 18:18:54 +00001574
nethercotef6a1d502004-08-09 12:21:57 +00001575 } else if (VG_CLO_STREQN(7, vg_argv[i], "--exec=")) {
1576 *exec = &vg_argv[i][7];
nethercote71980f02004-01-24 18:18:54 +00001577 }
1578 }
1579
nethercotef4928da2004-06-15 10:54:40 +00001580 /* If no tool specified, can act appropriately without loading tool */
nethercote71980f02004-01-24 18:18:54 +00001581 if (*tool == NULL) {
nethercotef4928da2004-06-15 10:54:40 +00001582 if (0 == *need_help) {
1583 // neither --tool nor --help/--help-debug specified
1584 missing_tool_option();
1585 } else {
1586 // Give help message, without any tool-specific help
1587 usage(/*help-debug?*/2 == *need_help);
1588 }
nethercote71980f02004-01-24 18:18:54 +00001589 }
1590}
1591
nethercote5ee67ca2004-06-22 14:00:09 +00001592static void process_cmd_line_options( UInt* client_auxv, const char* toolname )
nethercote71980f02004-01-24 18:18:54 +00001593{
nethercotef8548672004-06-21 12:42:35 +00001594 Int i, eventually_log_fd;
nethercote71980f02004-01-24 18:18:54 +00001595 Int *auxp;
1596 Int toolname_len = VG_(strlen)(toolname);
sewardjde4a1d02002-03-22 01:27:54 +00001597
nethercotee1730692003-11-20 10:38:07 +00001598 /* log to stderr by default, but usage message goes to stdout */
nethercotef8548672004-06-21 12:42:35 +00001599 eventually_log_fd = 2;
sewardjde4a1d02002-03-22 01:27:54 +00001600
sewardj19d81412002-06-03 01:10:40 +00001601 /* Check for sane path in ./configure --prefix=... */
fitzhardinge98abfc72003-12-16 02:05:15 +00001602 if (VG_LIBDIR[0] != '/')
sewardj19d81412002-06-03 01:10:40 +00001603 config_error("Please use absolute paths in "
1604 "./configure --prefix=... or --libdir=...");
sewardj38170912002-05-10 21:07:22 +00001605
nethercote71980f02004-01-24 18:18:54 +00001606 for (auxp = client_auxv; auxp[0] != VKI_AT_NULL; auxp += 2) {
fitzhardinge98abfc72003-12-16 02:05:15 +00001607 switch(auxp[0]) {
1608 case VKI_AT_SYSINFO:
fitzhardinge92360792003-12-24 10:11:11 +00001609 auxp[1] = (Int)(VG_(client_trampoline_code) + VG_(tramp_syscall_offset));
fitzhardinge98abfc72003-12-16 02:05:15 +00001610 break;
sewardjde4a1d02002-03-22 01:27:54 +00001611 }
fitzhardinge98abfc72003-12-16 02:05:15 +00001612 }
sewardjde4a1d02002-03-22 01:27:54 +00001613
nethercotef6a1d502004-08-09 12:21:57 +00001614 for (i = 1; i < vg_argc; i++) {
nethercote71980f02004-01-24 18:18:54 +00001615
nethercotef6a1d502004-08-09 12:21:57 +00001616 Char* arg = vg_argv[i];
thughes3bfd5a02004-07-18 08:05:44 +00001617 Char* colon = arg;
nethercote71980f02004-01-24 18:18:54 +00001618
thughes3bfd5a02004-07-18 08:05:44 +00001619 /* Look for a colon in the switch name */
1620 while (*colon && *colon != ':' && *colon != '=')
1621 colon++;
nethercote71980f02004-01-24 18:18:54 +00001622
1623 /* Look for matching "--toolname:foo" */
thughes3bfd5a02004-07-18 08:05:44 +00001624 if (*colon == ':') {
nethercote71980f02004-01-24 18:18:54 +00001625 if (VG_CLO_STREQN(2, arg, "--") &&
1626 VG_CLO_STREQN(toolname_len, arg+2, toolname) &&
1627 VG_CLO_STREQN(1, arg+2+toolname_len, ":"))
1628 {
1629 // prefix matches, convert "--toolname:foo" to "--foo"
1630 if (0)
1631 VG_(printf)("tool-specific arg: %s\n", arg);
1632 arg += toolname_len + 1;
1633 arg[0] = '-';
1634 arg[1] = '-';
1635
1636 } else {
1637 // prefix doesn't match, skip to next arg
1638 continue;
1639 }
1640 }
1641
fitzhardinge98abfc72003-12-16 02:05:15 +00001642 /* Ignore these options - they've already been handled */
nethercote71980f02004-01-24 18:18:54 +00001643 if (VG_CLO_STREQN(7, arg, "--tool=") ||
1644 VG_CLO_STREQN(7, arg, "--skin="))
fitzhardinge98abfc72003-12-16 02:05:15 +00001645 continue;
nethercote71980f02004-01-24 18:18:54 +00001646 if (VG_CLO_STREQN(7, arg, "--exec="))
fitzhardinge98abfc72003-12-16 02:05:15 +00001647 continue;
1648
nethercote71980f02004-01-24 18:18:54 +00001649 if ( VG_CLO_STREQ(arg, "--"))
fitzhardinge98abfc72003-12-16 02:05:15 +00001650 continue;
nethercote27fec902004-06-16 21:26:32 +00001651
nethercote71980f02004-01-24 18:18:54 +00001652 else if (VG_CLO_STREQ(arg, "-v") ||
1653 VG_CLO_STREQ(arg, "--verbose"))
sewardjde4a1d02002-03-22 01:27:54 +00001654 VG_(clo_verbosity)++;
nethercote27fec902004-06-16 21:26:32 +00001655
nethercote71980f02004-01-24 18:18:54 +00001656 else if (VG_CLO_STREQ(arg, "-q") ||
1657 VG_CLO_STREQ(arg, "--quiet"))
sewardjde4a1d02002-03-22 01:27:54 +00001658 VG_(clo_verbosity)--;
1659
nethercote27fec902004-06-16 21:26:32 +00001660 else VG_BOOL_CLO("--branchpred", VG_(clo_branchpred))
1661 else VG_BOOL_CLO("--chain-bb", VG_(clo_chain_bb))
1662 else VG_BOOL_CLO("--db-attach", VG_(clo_db_attach))
1663 else VG_BOOL_CLO("--demangle", VG_(clo_demangle))
1664 else VG_BOOL_CLO("--error-limit", VG_(clo_error_limit))
1665 else VG_BOOL_CLO("--gen-suppressions", VG_(clo_gen_suppressions))
1666 else VG_BOOL_CLO("--lowlat-signals", VG_(clo_lowlat_signals))
1667 else VG_BOOL_CLO("--lowlat-syscalls", VG_(clo_lowlat_syscalls))
1668 else VG_BOOL_CLO("--optimise", VG_(clo_optimise))
1669 else VG_BOOL_CLO("--pointercheck", VG_(clo_pointercheck))
1670 else VG_BOOL_CLO("--profile", VG_(clo_profile))
1671 else VG_BOOL_CLO("--run-libc-freeres", VG_(clo_run_libc_freeres))
1672 else VG_BOOL_CLO("--show-below-main", VG_(clo_show_below_main))
1673 else VG_BOOL_CLO("--single-step", VG_(clo_single_step))
thughes6233a382004-08-21 11:10:44 +00001674 else VG_BOOL_CLO("--time-stamp", VG_(clo_time_stamp))
nethercote27fec902004-06-16 21:26:32 +00001675 else VG_BOOL_CLO("--track-fds", VG_(clo_track_fds))
1676 else VG_BOOL_CLO("--trace-children", VG_(clo_trace_children))
1677 else VG_BOOL_CLO("--trace-sched", VG_(clo_trace_sched))
1678 else VG_BOOL_CLO("--trace-signals", VG_(clo_trace_signals))
1679 else VG_BOOL_CLO("--trace-symtab", VG_(clo_trace_symtab))
1680 else VG_BOOL_CLO("--trace-syscalls", VG_(clo_trace_syscalls))
1681 else VG_BOOL_CLO("--wait-for-gdb", VG_(clo_wait_for_gdb))
sewardj72f98ff2002-06-13 17:23:38 +00001682
nethercote27fec902004-06-16 21:26:32 +00001683 else VG_STR_CLO ("--db-command", VG_(clo_db_command))
1684 else VG_STR_CLO ("--weird-hacks", VG_(clo_weird_hacks))
sewardjde4a1d02002-03-22 01:27:54 +00001685
nethercote27fec902004-06-16 21:26:32 +00001686 else VG_NUM_CLO ("--dump-error", VG_(clo_dump_error))
1687 else VG_NUM_CLO ("--input-fd", VG_(clo_input_fd))
1688 else VG_NUM_CLO ("--sanity-level", VG_(clo_sanity_level))
1689 else VG_NUM_CLO ("--signal­polltime", VG_(clo_signal_polltime))
1690 else VG_BNUM_CLO("--num-callers", VG_(clo_backtrace_size), 1,
1691 VG_DEEPEST_BACKTRACE)
sewardjde4a1d02002-03-22 01:27:54 +00001692
nethercotef8548672004-06-21 12:42:35 +00001693 // for backwards compatibility, replaced by --log-fd
nethercote71980f02004-01-24 18:18:54 +00001694 else if (VG_CLO_STREQN(13, arg, "--logfile-fd=")) {
nethercotef8548672004-06-21 12:42:35 +00001695 VG_(clo_log_to) = VgLogTo_Fd;
1696 VG_(clo_log_name) = NULL;
1697 eventually_log_fd = (Int)VG_(atoll)(&arg[13]);
1698 }
1699 else if (VG_CLO_STREQN(9, arg, "--log-fd=")) {
1700 VG_(clo_log_to) = VgLogTo_Fd;
1701 VG_(clo_log_name) = NULL;
1702 eventually_log_fd = (Int)VG_(atoll)(&arg[9]);
sewardj4cf05692002-10-27 20:28:29 +00001703 }
1704
nethercotef8548672004-06-21 12:42:35 +00001705 // for backwards compatibility, replaced by --log-file
nethercote71980f02004-01-24 18:18:54 +00001706 else if (VG_CLO_STREQN(10, arg, "--logfile=")) {
nethercotef8548672004-06-21 12:42:35 +00001707 VG_(clo_log_to) = VgLogTo_File;
1708 VG_(clo_log_name) = &arg[10];
1709 }
1710 else if (VG_CLO_STREQN(11, arg, "--log-file=")) {
1711 VG_(clo_log_to) = VgLogTo_File;
1712 VG_(clo_log_name) = &arg[11];
sewardj4cf05692002-10-27 20:28:29 +00001713 }
sewardjde4a1d02002-03-22 01:27:54 +00001714
nethercotef8548672004-06-21 12:42:35 +00001715 // for backwards compatibility, replaced by --log-socket
nethercote71980f02004-01-24 18:18:54 +00001716 else if (VG_CLO_STREQN(12, arg, "--logsocket=")) {
nethercotef8548672004-06-21 12:42:35 +00001717 VG_(clo_log_to) = VgLogTo_Socket;
1718 VG_(clo_log_name) = &arg[12];
1719 }
1720 else if (VG_CLO_STREQN(13, arg, "--log-socket=")) {
1721 VG_(clo_log_to) = VgLogTo_Socket;
1722 VG_(clo_log_name) = &arg[13];
sewardj73cf3bc2002-11-03 03:20:15 +00001723 }
1724
nethercote71980f02004-01-24 18:18:54 +00001725 else if (VG_CLO_STREQN(15, arg, "--suppressions=")) {
sewardjde4a1d02002-03-22 01:27:54 +00001726 if (VG_(clo_n_suppressions) >= VG_CLO_MAX_SFILES) {
njn25e49d8e72002-09-23 09:36:25 +00001727 VG_(message)(Vg_UserMsg, "Too many suppression files specified.");
sewardjde4a1d02002-03-22 01:27:54 +00001728 VG_(message)(Vg_UserMsg,
1729 "Increase VG_CLO_MAX_SFILES and recompile.");
nethercote71980f02004-01-24 18:18:54 +00001730 VG_(bad_option)(arg);
sewardjde4a1d02002-03-22 01:27:54 +00001731 }
nethercote71980f02004-01-24 18:18:54 +00001732 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = &arg[15];
sewardjde4a1d02002-03-22 01:27:54 +00001733 VG_(clo_n_suppressions)++;
1734 }
sewardjde4a1d02002-03-22 01:27:54 +00001735
njn25e49d8e72002-09-23 09:36:25 +00001736 /* "vwxyz" --> 000zyxwv (binary) */
nethercote71980f02004-01-24 18:18:54 +00001737 else if (VG_CLO_STREQN(16, arg, "--trace-codegen=")) {
njn25e49d8e72002-09-23 09:36:25 +00001738 Int j;
nethercote71980f02004-01-24 18:18:54 +00001739 char* opt = & arg[16];
njn25e49d8e72002-09-23 09:36:25 +00001740
1741 if (5 != VG_(strlen)(opt)) {
1742 VG_(message)(Vg_UserMsg,
1743 "--trace-codegen argument must have 5 digits");
nethercote71980f02004-01-24 18:18:54 +00001744 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001745 }
1746 for (j = 0; j < 5; j++) {
1747 if ('0' == opt[j]) { /* do nothing */ }
1748 else if ('1' == opt[j]) VG_(clo_trace_codegen) |= (1 << j);
1749 else {
1750 VG_(message)(Vg_UserMsg, "--trace-codegen argument can only "
1751 "contain 0s and 1s");
nethercote71980f02004-01-24 18:18:54 +00001752 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001753 }
1754 }
1755 }
sewardjde4a1d02002-03-22 01:27:54 +00001756
nethercote71980f02004-01-24 18:18:54 +00001757 else if (VG_CLO_STREQ(arg, "--trace-pthread=none"))
sewardj45b4b372002-04-16 22:50:32 +00001758 VG_(clo_trace_pthread_level) = 0;
nethercote71980f02004-01-24 18:18:54 +00001759 else if (VG_CLO_STREQ(arg, "--trace-pthread=some"))
sewardj45b4b372002-04-16 22:50:32 +00001760 VG_(clo_trace_pthread_level) = 1;
nethercote71980f02004-01-24 18:18:54 +00001761 else if (VG_CLO_STREQ(arg, "--trace-pthread=all"))
sewardj45b4b372002-04-16 22:50:32 +00001762 VG_(clo_trace_pthread_level) = 2;
sewardj8937c812002-04-12 20:12:20 +00001763
nethercote71980f02004-01-24 18:18:54 +00001764 else if ( ! VG_(needs).command_line_options
1765 || ! SK_(process_cmd_line_option)(arg) ) {
nethercotef4928da2004-06-15 10:54:40 +00001766 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001767 }
sewardjde4a1d02002-03-22 01:27:54 +00001768 }
1769
nethercote27fec902004-06-16 21:26:32 +00001770 // Check various option values
1771
njnf9ebf672003-05-12 21:41:30 +00001772 if (VG_(clo_verbosity) < 0)
sewardjde4a1d02002-03-22 01:27:54 +00001773 VG_(clo_verbosity) = 0;
1774
nethercote04d0fbc2004-01-26 16:48:06 +00001775 if (VG_(clo_db_attach) && VG_(clo_trace_children)) {
sewardjde4a1d02002-03-22 01:27:54 +00001776 VG_(message)(Vg_UserMsg, "");
1777 VG_(message)(Vg_UserMsg,
nethercote04d0fbc2004-01-26 16:48:06 +00001778 "--db-attach=yes conflicts with --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001779 VG_(message)(Vg_UserMsg,
1780 "Please choose one or the other, but not both.");
nethercote04d0fbc2004-01-26 16:48:06 +00001781 VG_(bad_option)("--db-attach=yes and --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001782 }
1783
nethercotef8548672004-06-21 12:42:35 +00001784 /* Set up logging now. After this is done, VG_(clo_log_fd)
sewardj4cf05692002-10-27 20:28:29 +00001785 should be connected to whatever sink has been selected, and we
1786 indiscriminately chuck stuff into it without worrying what the
1787 nature of it is. Oh the wonder of Unix streams. */
1788
nethercotee1730692003-11-20 10:38:07 +00001789 /* So far we should be still attached to stdout, so we can show on
sewardj4cf05692002-10-27 20:28:29 +00001790 the terminal any problems to do with processing command line
1791 opts. */
nethercotef8548672004-06-21 12:42:35 +00001792 vg_assert(VG_(clo_log_fd) == 1 /* stdout */);
sewardj73cf3bc2002-11-03 03:20:15 +00001793 vg_assert(VG_(logging_to_filedes) == True);
sewardj4cf05692002-10-27 20:28:29 +00001794
1795 switch (VG_(clo_log_to)) {
sewardj73cf3bc2002-11-03 03:20:15 +00001796
sewardj4cf05692002-10-27 20:28:29 +00001797 case VgLogTo_Fd:
nethercotef8548672004-06-21 12:42:35 +00001798 vg_assert(VG_(clo_log_name) == NULL);
1799 VG_(clo_log_fd) = eventually_log_fd;
sewardj4cf05692002-10-27 20:28:29 +00001800 break;
sewardj73cf3bc2002-11-03 03:20:15 +00001801
sewardj4cf05692002-10-27 20:28:29 +00001802 case VgLogTo_File: {
1803 Char logfilename[1000];
jsgff3c3f1a2003-10-14 22:13:28 +00001804 Int seq = 0;
1805 Int pid = VG_(getpid)();
1806
nethercotef8548672004-06-21 12:42:35 +00001807 vg_assert(VG_(clo_log_name) != NULL);
1808 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
jsgff3c3f1a2003-10-14 22:13:28 +00001809
nethercote71980f02004-01-24 18:18:54 +00001810 for (;;) {
jsgff3c3f1a2003-10-14 22:13:28 +00001811 if (seq == 0)
1812 VG_(sprintf)(logfilename, "%s.pid%d",
nethercotef8548672004-06-21 12:42:35 +00001813 VG_(clo_log_name), pid );
jsgff3c3f1a2003-10-14 22:13:28 +00001814 else
1815 VG_(sprintf)(logfilename, "%s.pid%d.%d",
nethercotef8548672004-06-21 12:42:35 +00001816 VG_(clo_log_name), pid, seq );
jsgff3c3f1a2003-10-14 22:13:28 +00001817 seq++;
1818
nethercotef8548672004-06-21 12:42:35 +00001819 eventually_log_fd
jsgff3c3f1a2003-10-14 22:13:28 +00001820 = VG_(open)(logfilename,
1821 VKI_O_CREAT|VKI_O_WRONLY|VKI_O_EXCL|VKI_O_TRUNC,
1822 VKI_S_IRUSR|VKI_S_IWUSR);
nethercotef8548672004-06-21 12:42:35 +00001823 if (eventually_log_fd >= 0) {
1824 VG_(clo_log_fd) = VG_(safe_fd)(eventually_log_fd);
jsgff3c3f1a2003-10-14 22:13:28 +00001825 break;
1826 } else {
nethercotef8548672004-06-21 12:42:35 +00001827 if (eventually_log_fd != -VKI_EEXIST) {
jsgff3c3f1a2003-10-14 22:13:28 +00001828 VG_(message)(Vg_UserMsg,
1829 "Can't create/open log file `%s.pid%d'; giving up!",
nethercotef8548672004-06-21 12:42:35 +00001830 VG_(clo_log_name), pid);
jsgff3c3f1a2003-10-14 22:13:28 +00001831 VG_(bad_option)(
nethercotef8548672004-06-21 12:42:35 +00001832 "--log-file=<file> didn't work out for some reason.");
jsgff3c3f1a2003-10-14 22:13:28 +00001833 break;
1834 }
1835 }
1836 }
sewardj4cf05692002-10-27 20:28:29 +00001837 break;
sewardj73cf3bc2002-11-03 03:20:15 +00001838 }
1839
1840 case VgLogTo_Socket: {
nethercotef8548672004-06-21 12:42:35 +00001841 vg_assert(VG_(clo_log_name) != NULL);
1842 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
1843 eventually_log_fd = VG_(connect_via_socket)( VG_(clo_log_name) );
1844 if (eventually_log_fd == -1) {
sewardj73cf3bc2002-11-03 03:20:15 +00001845 VG_(message)(Vg_UserMsg,
nethercotef8548672004-06-21 12:42:35 +00001846 "Invalid --log-socket=ipaddr or --log-socket=ipaddr:port spec");
sewardj73cf3bc2002-11-03 03:20:15 +00001847 VG_(message)(Vg_UserMsg,
nethercotef8548672004-06-21 12:42:35 +00001848 "of `%s'; giving up!", VG_(clo_log_name) );
sewardj73cf3bc2002-11-03 03:20:15 +00001849 VG_(bad_option)(
nethercotef8548672004-06-21 12:42:35 +00001850 "--log-socket=");
sewardj4cf05692002-10-27 20:28:29 +00001851 }
nethercotef8548672004-06-21 12:42:35 +00001852 if (eventually_log_fd == -2) {
sewardj73cf3bc2002-11-03 03:20:15 +00001853 VG_(message)(Vg_UserMsg,
sewardj570f8902002-11-03 11:44:36 +00001854 "valgrind: failed to connect to logging server `%s'.",
nethercotef8548672004-06-21 12:42:35 +00001855 VG_(clo_log_name) );
sewardj570f8902002-11-03 11:44:36 +00001856 VG_(message)(Vg_UserMsg,
1857 "Log messages will sent to stderr instead." );
1858 VG_(message)(Vg_UserMsg,
1859 "" );
1860 /* We don't change anything here. */
1861 } else {
nethercotef8548672004-06-21 12:42:35 +00001862 vg_assert(eventually_log_fd > 0);
1863 VG_(clo_log_fd) = eventually_log_fd;
sewardj570f8902002-11-03 11:44:36 +00001864 VG_(logging_to_filedes) = False;
1865 }
sewardj73cf3bc2002-11-03 03:20:15 +00001866 break;
1867 }
1868
sewardj4cf05692002-10-27 20:28:29 +00001869 }
1870
nethercotef8548672004-06-21 12:42:35 +00001871 /* Move log_fd into the safe range, so it doesn't conflict with any app fds */
thughesad1c9562004-06-26 11:27:52 +00001872 eventually_log_fd = VG_(fcntl)(VG_(clo_log_fd), VKI_F_DUPFD, VG_(fd_hard_limit));
nethercotef8548672004-06-21 12:42:35 +00001873 if (eventually_log_fd < 0)
jsgf855d93d2003-10-13 22:26:55 +00001874 VG_(message)(Vg_UserMsg, "valgrind: failed to move logfile fd into safe range");
1875 else {
nethercotef8548672004-06-21 12:42:35 +00001876 VG_(clo_log_fd) = eventually_log_fd;
1877 VG_(fcntl)(VG_(clo_log_fd), VKI_F_SETFD, VKI_FD_CLOEXEC);
jsgf855d93d2003-10-13 22:26:55 +00001878 }
1879
sewardj4cf05692002-10-27 20:28:29 +00001880 /* Ok, the logging sink is running now. Print a suitable preamble.
1881 If logging to file or a socket, write details of parent PID and
1882 command line args, to help people trying to interpret the
1883 results of a run which encompasses multiple processes. */
sewardjde4a1d02002-03-22 01:27:54 +00001884
sewardj83adf412002-05-01 01:25:45 +00001885 if (VG_(clo_verbosity > 0)) {
nethercote996901a2004-08-03 13:29:09 +00001886 /* Tool details */
nethercotea131bb82004-09-06 15:34:37 +00001887 VG_(message)(Vg_UserMsg, "%s%s%s, %s for %s.",
njnd04b7c62002-10-03 14:05:52 +00001888 VG_(details).name,
1889 NULL == VG_(details).version ? "" : "-",
1890 NULL == VG_(details).version
1891 ? (Char*)"" : VG_(details).version,
nethercotea131bb82004-09-06 15:34:37 +00001892 VG_(details).description,
1893 VG_PLATFORM);
njnd04b7c62002-10-03 14:05:52 +00001894 VG_(message)(Vg_UserMsg, "%s", VG_(details).copyright_author);
sewardj3b2736a2002-03-24 12:18:35 +00001895
njnd04b7c62002-10-03 14:05:52 +00001896 /* Core details */
1897 VG_(message)(Vg_UserMsg,
nethercotea131bb82004-09-06 15:34:37 +00001898 "Using valgrind-%s, a program supervision framework for %s.",
1899 VERSION, VG_PLATFORM);
sewardjde4a1d02002-03-22 01:27:54 +00001900 VG_(message)(Vg_UserMsg,
nethercote08fa9a72004-07-16 17:44:00 +00001901 "Copyright (C) 2000-2004, and GNU GPL'd, by Julian Seward et al.");
njnd04b7c62002-10-03 14:05:52 +00001902 }
1903
nethercotec1e395d2003-11-10 13:26:49 +00001904 if (VG_(clo_verbosity) > 0 && VG_(clo_log_to) != VgLogTo_Fd) {
sewardj4cf05692002-10-27 20:28:29 +00001905 VG_(message)(Vg_UserMsg, "");
1906 VG_(message)(Vg_UserMsg,
1907 "My PID = %d, parent PID = %d. Prog and args are:",
1908 VG_(getpid)(), VG_(getppid)() );
1909 for (i = 0; i < VG_(client_argc); i++)
1910 VG_(message)(Vg_UserMsg, " %s", VG_(client_argv)[i]);
1911 }
1912
sewardjde4a1d02002-03-22 01:27:54 +00001913 if (VG_(clo_verbosity) > 1) {
nethercotea70f7352004-04-18 12:08:46 +00001914 Int fd;
sewardj4cf05692002-10-27 20:28:29 +00001915 if (VG_(clo_log_to) != VgLogTo_Fd)
1916 VG_(message)(Vg_UserMsg, "");
fitzhardinge98abfc72003-12-16 02:05:15 +00001917 VG_(message)(Vg_UserMsg, "Valgrind library directory: %s", VG_(libdir));
njn86dc2bc2003-09-09 07:26:21 +00001918 VG_(message)(Vg_UserMsg, "Command line");
1919 for (i = 0; i < VG_(client_argc); i++)
1920 VG_(message)(Vg_UserMsg, " %s", VG_(client_argv)[i]);
1921
sewardjde4a1d02002-03-22 01:27:54 +00001922 VG_(message)(Vg_UserMsg, "Startup, with flags:");
nethercotef6a1d502004-08-09 12:21:57 +00001923 for (i = 1; i < vg_argc; i++) {
1924 VG_(message)(Vg_UserMsg, " %s", vg_argv[i]);
sewardjde4a1d02002-03-22 01:27:54 +00001925 }
nethercotea70f7352004-04-18 12:08:46 +00001926
1927 VG_(message)(Vg_UserMsg, "Contents of /proc/version:");
1928 fd = VG_(open) ( "/proc/version", VKI_O_RDONLY, 0 );
1929 if (fd < 0) {
1930 VG_(message)(Vg_UserMsg, " can't open /proc/version");
1931 } else {
1932 #define BUF_LEN 256
1933 Char version_buf[BUF_LEN];
1934 Int n = VG_(read) ( fd, version_buf, BUF_LEN );
1935 vg_assert(n <= 256);
1936 if (n > 0) {
1937 version_buf[n-1] = '\0';
1938 VG_(message)(Vg_UserMsg, " %s", version_buf);
1939 } else {
1940 VG_(message)(Vg_UserMsg, " (empty?)");
1941 }
1942 VG_(close)(fd);
1943 #undef BUF_LEN
1944 }
sewardjde4a1d02002-03-22 01:27:54 +00001945 }
1946
fitzhardinge98abfc72003-12-16 02:05:15 +00001947 if (VG_(clo_n_suppressions) < VG_CLO_MAX_SFILES-1 &&
njn25e49d8e72002-09-23 09:36:25 +00001948 (VG_(needs).core_errors || VG_(needs).skin_errors)) {
nethercote996901a2004-08-03 13:29:09 +00001949 /* If there are no suppression files specified and the tool
fitzhardinge98abfc72003-12-16 02:05:15 +00001950 needs one, load the default */
1951 static const Char default_supp[] = "default.supp";
1952 Int len = VG_(strlen)(VG_(libdir)) + 1 + sizeof(default_supp);
1953 Char *buf = VG_(arena_malloc)(VG_AR_CORE, len);
1954 VG_(sprintf)(buf, "%s/%s", VG_(libdir), default_supp);
1955 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = buf;
1956 VG_(clo_n_suppressions)++;
sewardjde4a1d02002-03-22 01:27:54 +00001957 }
sewardj4cf05692002-10-27 20:28:29 +00001958
njn6a230532003-07-21 10:38:23 +00001959 if (VG_(clo_gen_suppressions) &&
1960 !VG_(needs).core_errors && !VG_(needs).skin_errors) {
nethercotef4928da2004-06-15 10:54:40 +00001961 VG_(message)(Vg_UserMsg,
1962 "Can't use --gen-suppressions=yes with this tool,");
1963 VG_(message)(Vg_UserMsg,
1964 "as it doesn't generate errors.");
1965 VG_(bad_option)("--gen-suppressions=yes");
njn6a230532003-07-21 10:38:23 +00001966 }
sewardjde4a1d02002-03-22 01:27:54 +00001967}
1968
nethercotef6a1d502004-08-09 12:21:57 +00001969// Build the string for VALGRINDCLO.
1970Char* VG_(build_child_VALGRINDCLO)( Char* exename )
1971{
1972 /* If we're tracing the children, then we need to start it
1973 with our starter+arguments, which are copied into VALGRINDCLO,
1974 except the --exec= option is changed if present.
1975 */
1976 Int i;
1977 Char *exec;
1978 Char *cp;
1979 Char *optvar;
1980 Int optlen, execlen;
1981
1982 // All these allocated blocks are not free - because we're either
1983 // going to exec, or panic when we fail.
1984
1985 // Create --exec= option: "--exec=<exename>"
1986 exec = VG_(arena_malloc)(VG_AR_CORE,
1987 VG_(strlen)( exename ) + 7/*--exec=*/ + 1/*\0*/);
1988 vg_assert(NULL != exec);
1989 VG_(sprintf)(exec, "--exec=%s", exename);
1990
1991 // Allocate space for optvar (may overestimate by counting --exec twice,
1992 // no matter)
1993 optlen = 1;
1994 for (i = 0; i < vg_argc; i++)
1995 optlen += VG_(strlen)(vg_argv[i]) + 1;
1996 optlen += VG_(strlen)(exec)+1;
1997 optvar = VG_(arena_malloc)(VG_AR_CORE, optlen);
1998
1999 // Copy all valgrind args except the old --exec (if present)
2000 // VG_CLO_SEP is the separator.
2001 cp = optvar;
2002 for (i = 1; i < vg_argc; i++) {
2003 Char *arg = vg_argv[i];
2004
2005 if (VG_(memcmp)(arg, "--exec=", 7) == 0) {
2006 // don't copy existing --exec= arg
2007 } else if (VG_(strcmp)(arg, "--") == 0) {
2008 // stop at "--"
2009 break;
2010 } else {
2011 // copy non "--exec" arg
2012 Int len = VG_(strlen)(arg);
2013 VG_(memcpy)(cp, arg, len);
2014 cp += len;
2015 *cp++ = VG_CLO_SEP;
2016 }
2017 }
2018 // Add the new --exec= option
2019 execlen = VG_(strlen)(exec);
2020 VG_(memcpy)(cp, exec, execlen);
2021 cp += execlen;
2022 *cp++ = VG_CLO_SEP;
2023
2024 *cp = '\0';
2025
2026 return optvar;
2027}
2028
2029// Build "/proc/self/fd/<execfd>".
2030Char* VG_(build_child_exename)( void )
2031{
2032 Char* exename = VG_(arena_malloc)(VG_AR_CORE, 64);
2033 vg_assert(NULL != exename);
2034 VG_(sprintf)(exename, "/proc/self/fd/%d", vgexecfd);
2035 return exename;
2036}
2037
sewardjde4a1d02002-03-22 01:27:54 +00002038
nethercote71980f02004-01-24 18:18:54 +00002039/*====================================================================*/
2040/*=== File descriptor setup ===*/
2041/*====================================================================*/
2042
2043static void setup_file_descriptors(void)
2044{
2045 struct vki_rlimit rl;
2046
2047 /* Get the current file descriptor limits. */
2048 if (VG_(getrlimit)(VKI_RLIMIT_NOFILE, &rl) < 0) {
2049 rl.rlim_cur = 1024;
2050 rl.rlim_max = 1024;
2051 }
2052
2053 /* Work out where to move the soft limit to. */
2054 if (rl.rlim_cur + VG_N_RESERVED_FDS <= rl.rlim_max) {
2055 rl.rlim_cur = rl.rlim_cur + VG_N_RESERVED_FDS;
2056 } else {
2057 rl.rlim_cur = rl.rlim_max;
2058 }
2059
2060 /* Reserve some file descriptors for our use. */
thughesad1c9562004-06-26 11:27:52 +00002061 VG_(fd_soft_limit) = rl.rlim_cur - VG_N_RESERVED_FDS;
2062 VG_(fd_hard_limit) = rl.rlim_cur - VG_N_RESERVED_FDS;
nethercote71980f02004-01-24 18:18:54 +00002063
2064 /* Update the soft limit. */
2065 VG_(setrlimit)(VKI_RLIMIT_NOFILE, &rl);
2066
nethercotef6a1d502004-08-09 12:21:57 +00002067 if (vgexecfd != -1)
2068 vgexecfd = VG_(safe_fd)( vgexecfd );
nethercote71980f02004-01-24 18:18:54 +00002069 if (VG_(clexecfd) != -1)
2070 VG_(clexecfd) = VG_(safe_fd)( VG_(clexecfd) );
2071}
2072
2073
2074/*====================================================================*/
nethercote1d447092004-02-01 17:29:59 +00002075/*=== baseBlock: definition + setup ===*/
nethercote71980f02004-01-24 18:18:54 +00002076/*====================================================================*/
2077
nethercote71980f02004-01-24 18:18:54 +00002078Int VGOFF_(helper_undefined_instruction) = INVALID_OFFSET;
2079
2080/* MAX_NONCOMPACT_HELPERS can be increased easily. If MAX_COMPACT_HELPERS is
2081 * increased too much, they won't really be compact any more... */
2082#define MAX_COMPACT_HELPERS 8
2083#define MAX_NONCOMPACT_HELPERS 50
2084
nethercote81f9a6f2004-08-03 15:45:46 +00002085/* For storing tool-specific helpers, determined at runtime. The addr
2086 * and offset arrays together form a (addr, offset) map that allows a
2087 * helper's baseBlock offset to be computed from its address. It's done
2088 * like this so CCALLs can use the function address rather than having to
2089 * muck around with offsets. */
2090static UInt VG_(n_compact_helpers) = 0;
2091static UInt VG_(n_noncompact_helpers) = 0;
2092static Addr VG_(compact_helper_addrs) [MAX_COMPACT_HELPERS];
2093static Int VG_(compact_helper_offsets)[MAX_COMPACT_HELPERS];
2094static Addr VG_(noncompact_helper_addrs) [MAX_NONCOMPACT_HELPERS];
2095static Int VG_(noncompact_helper_offsets)[MAX_NONCOMPACT_HELPERS];
nethercote71980f02004-01-24 18:18:54 +00002096
2097/* This is the actual defn of baseblock. */
2098UInt VG_(baseBlock)[VG_BASEBLOCK_WORDS];
2099
nethercote71980f02004-01-24 18:18:54 +00002100/* Words. */
2101static Int baB_off = 0;
2102
2103
nethercote71980f02004-01-24 18:18:54 +00002104/* Returns the offset, in words. */
nethercote2e05c332004-09-06 16:43:37 +00002105Int VG_(alloc_BaB) ( Int words )
sewardjde4a1d02002-03-22 01:27:54 +00002106{
nethercote71980f02004-01-24 18:18:54 +00002107 Int off = baB_off;
2108 baB_off += words;
2109 if (baB_off >= VG_BASEBLOCK_WORDS)
nethercote2e05c332004-09-06 16:43:37 +00002110 VG_(core_panic)( "VG_(alloc_BaB): baseBlock is too small");
sewardjde4a1d02002-03-22 01:27:54 +00002111
nethercote71980f02004-01-24 18:18:54 +00002112 return off;
sewardjde4a1d02002-03-22 01:27:54 +00002113}
2114
nethercote71980f02004-01-24 18:18:54 +00002115/* Align offset, in *bytes* */
nethercote2e05c332004-09-06 16:43:37 +00002116void VG_(align_BaB) ( UInt align )
njn25e49d8e72002-09-23 09:36:25 +00002117{
nethercote71980f02004-01-24 18:18:54 +00002118 vg_assert(2 == align || 4 == align || 8 == align || 16 == align);
2119 baB_off += (align-1);
2120 baB_off &= ~(align-1);
njn25e49d8e72002-09-23 09:36:25 +00002121}
2122
nethercote71980f02004-01-24 18:18:54 +00002123/* Allocate 1 word in baseBlock and set it to the given value. */
nethercote2e05c332004-09-06 16:43:37 +00002124Int VG_(alloc_BaB_1_set) ( Addr a )
njn25e49d8e72002-09-23 09:36:25 +00002125{
nethercote2e05c332004-09-06 16:43:37 +00002126 Int off = VG_(alloc_BaB)(1);
nethercote71980f02004-01-24 18:18:54 +00002127 VG_(baseBlock)[off] = (UInt)a;
2128 return off;
njn25e49d8e72002-09-23 09:36:25 +00002129}
2130
nethercote71980f02004-01-24 18:18:54 +00002131/* Registers a function in compact_helper_addrs; compact_helper_offsets is
2132 filled in later. */
2133void VG_(register_compact_helper)(Addr a)
sewardjde4a1d02002-03-22 01:27:54 +00002134{
nethercote71980f02004-01-24 18:18:54 +00002135 if (MAX_COMPACT_HELPERS <= VG_(n_compact_helpers)) {
2136 VG_(printf)("Can only register %d compact helpers\n",
2137 MAX_COMPACT_HELPERS);
2138 VG_(core_panic)("Too many compact helpers registered");
2139 }
2140 VG_(compact_helper_addrs)[VG_(n_compact_helpers)] = a;
2141 VG_(n_compact_helpers)++;
2142}
2143
2144/* Registers a function in noncompact_helper_addrs; noncompact_helper_offsets
2145 * is filled in later.
2146 */
2147void VG_(register_noncompact_helper)(Addr a)
2148{
2149 if (MAX_NONCOMPACT_HELPERS <= VG_(n_noncompact_helpers)) {
2150 VG_(printf)("Can only register %d non-compact helpers\n",
2151 MAX_NONCOMPACT_HELPERS);
2152 VG_(printf)("Try increasing MAX_NON_COMPACT_HELPERS\n");
2153 VG_(core_panic)("Too many non-compact helpers registered");
2154 }
2155 VG_(noncompact_helper_addrs)[VG_(n_noncompact_helpers)] = a;
2156 VG_(n_noncompact_helpers)++;
2157}
2158
nethercote996901a2004-08-03 13:29:09 +00002159/* Allocate offsets in baseBlock for the tool helpers */
nethercote71980f02004-01-24 18:18:54 +00002160static
2161void assign_helpers_in_baseBlock(UInt n, Int offsets[], Addr addrs[])
2162{
2163 UInt i;
2164 for (i = 0; i < n; i++)
nethercote2e05c332004-09-06 16:43:37 +00002165 offsets[i] = VG_(alloc_BaB_1_set)( addrs[i] );
nethercote71980f02004-01-24 18:18:54 +00002166}
2167
2168Bool VG_(need_to_handle_esp_assignment)(void)
2169{
2170 return ( VG_(defined_new_mem_stack_4)() ||
2171 VG_(defined_die_mem_stack_4)() ||
2172 VG_(defined_new_mem_stack_8)() ||
2173 VG_(defined_die_mem_stack_8)() ||
2174 VG_(defined_new_mem_stack_12)() ||
2175 VG_(defined_die_mem_stack_12)() ||
2176 VG_(defined_new_mem_stack_16)() ||
2177 VG_(defined_die_mem_stack_16)() ||
2178 VG_(defined_new_mem_stack_32)() ||
2179 VG_(defined_die_mem_stack_32)() ||
2180 VG_(defined_new_mem_stack)() ||
2181 VG_(defined_die_mem_stack)()
2182 );
2183}
2184
nethercote2e05c332004-09-06 16:43:37 +00002185// The low/high split is for x86, so that the more common helpers can be
2186// in the first 128 bytes of the start, which allows the use of a more
2187// compact addressing mode.
nethercote71980f02004-01-24 18:18:54 +00002188static void init_baseBlock ( Addr client_eip, Addr esp_at_startup )
2189{
nethercote2e05c332004-09-06 16:43:37 +00002190 VGA_(init_low_baseBlock)(client_eip, esp_at_startup);
nethercote71980f02004-01-24 18:18:54 +00002191
nethercote71980f02004-01-24 18:18:54 +00002192 /* Allocate slots for compact helpers */
2193 assign_helpers_in_baseBlock(VG_(n_compact_helpers),
2194 VG_(compact_helper_offsets),
2195 VG_(compact_helper_addrs));
2196
nethercote2e05c332004-09-06 16:43:37 +00002197 VGA_(init_high_baseBlock)(client_eip, esp_at_startup);
fitzhardingef0046f22003-12-18 02:39:22 +00002198
nethercote71980f02004-01-24 18:18:54 +00002199#define REG(kind, size) \
2200 if (VG_(defined_##kind##_mem_stack##size)()) \
2201 VG_(register_noncompact_helper)( \
2202 (Addr) VG_(tool_interface).track_##kind##_mem_stack##size );
2203 REG(new, _8);
2204 REG(new, _12);
2205 REG(new, _16);
2206 REG(new, _32);
2207 REG(new, );
2208 REG(die, _8);
2209 REG(die, _12);
2210 REG(die, _16);
2211 REG(die, _32);
2212 REG(die, );
2213#undef REG
fitzhardingef0046f22003-12-18 02:39:22 +00002214
nethercote71980f02004-01-24 18:18:54 +00002215 if (VG_(need_to_handle_esp_assignment)())
2216 VG_(register_noncompact_helper)((Addr) VG_(unknown_esp_update));
fitzhardingeb791a192003-12-18 07:22:44 +00002217
nethercote2e05c332004-09-06 16:43:37 +00002218 VGOFF_(helper_undefined_instruction)
2219 = VG_(alloc_BaB_1_set)( (Addr) & VG_(helper_undefined_instruction));
sewardjde4a1d02002-03-22 01:27:54 +00002220
nethercote71980f02004-01-24 18:18:54 +00002221 /* Allocate slots for noncompact helpers */
2222 assign_helpers_in_baseBlock(VG_(n_noncompact_helpers),
2223 VG_(noncompact_helper_offsets),
2224 VG_(noncompact_helper_addrs));
2225}
sewardjde4a1d02002-03-22 01:27:54 +00002226
nethercote81f9a6f2004-08-03 15:45:46 +00002227// Finds the baseBlock offset of a tool-specified helper.
2228// Searches through compacts first, then non-compacts.
2229Int VG_(helper_offset)(Addr a)
2230{
2231 UInt i;
2232 Char buf[100];
2233
2234 for (i = 0; i < VG_(n_compact_helpers); i++)
2235 if (VG_(compact_helper_addrs)[i] == a)
2236 return VG_(compact_helper_offsets)[i];
2237 for (i = 0; i < VG_(n_noncompact_helpers); i++)
2238 if (VG_(noncompact_helper_addrs)[i] == a)
2239 return VG_(noncompact_helper_offsets)[i];
2240
2241 /* Shouldn't get here */
2242 VG_(get_fnname) ( a, buf, 100 );
2243
2244 VG_(printf)(
2245 "\nCouldn't find offset of helper from its address (%p: %s).\n"
2246 "A helper function probably used hasn't been registered?\n\n", a, buf);
2247
2248 VG_(printf)(" compact helpers: ");
2249 for (i = 0; i < VG_(n_compact_helpers); i++)
2250 VG_(printf)("%p ", VG_(compact_helper_addrs)[i]);
2251
2252 VG_(printf)("\n non-compact helpers: ");
2253 for (i = 0; i < VG_(n_noncompact_helpers); i++)
2254 VG_(printf)("%p ", VG_(noncompact_helper_addrs)[i]);
2255
2256 VG_(printf)("\n");
2257 VG_(skin_panic)("Unfound helper");
2258}
2259
sewardj5f07b662002-04-23 16:52:51 +00002260
nethercote71980f02004-01-24 18:18:54 +00002261/*====================================================================*/
nethercote71980f02004-01-24 18:18:54 +00002262/*=== Initialise program data/text, etc. ===*/
2263/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +00002264
nethercote71980f02004-01-24 18:18:54 +00002265static void build_valgrind_map_callback
2266 ( Addr start, UInt size, Char rr, Char ww, Char xx,
2267 UInt dev, UInt ino, ULong foffset, const UChar* filename )
sewardjde4a1d02002-03-22 01:27:54 +00002268{
nethercote71980f02004-01-24 18:18:54 +00002269 UInt prot = 0;
2270 UInt flags = SF_MMAP|SF_NOSYMS;
2271 Bool is_stack_segment;
2272
2273 is_stack_segment =
2274 (start == VG_(clstk_base) && (start+size) == VG_(clstk_end));
2275
2276 /* Only record valgrind mappings for now, without loading any
2277 symbols. This is so we know where the free space is before we
2278 start allocating more memory (note: heap is OK, it's just mmap
2279 which is the problem here). */
2280 if (start >= VG_(valgrind_base) && (start+size) <= VG_(valgrind_end)) {
2281 flags |= SF_VALGRIND;
2282 VG_(map_file_segment)(start, size, prot, flags, dev, ino, foffset, filename);
2283 }
sewardjde4a1d02002-03-22 01:27:54 +00002284}
2285
nethercote71980f02004-01-24 18:18:54 +00002286// Global var used to pass local data to callback
2287Addr esp_at_startup___global_arg = 0;
sewardjde4a1d02002-03-22 01:27:54 +00002288
nethercote71980f02004-01-24 18:18:54 +00002289static void build_segment_map_callback
2290 ( Addr start, UInt size, Char rr, Char ww, Char xx,
2291 UInt dev, UInt ino, ULong foffset, const UChar* filename )
sewardj45b672d2003-07-25 19:58:11 +00002292{
nethercote71980f02004-01-24 18:18:54 +00002293 UInt prot = 0;
2294 UInt flags;
2295 Bool is_stack_segment;
2296 Addr r_esp;
sewardj45b672d2003-07-25 19:58:11 +00002297
nethercote71980f02004-01-24 18:18:54 +00002298 is_stack_segment
2299 = (start == VG_(clstk_base) && (start+size) == VG_(clstk_end));
fitzhardinge98abfc72003-12-16 02:05:15 +00002300
nethercote71980f02004-01-24 18:18:54 +00002301 if (rr == 'r') prot |= VKI_PROT_READ;
2302 if (ww == 'w') prot |= VKI_PROT_WRITE;
2303 if (xx == 'x') prot |= VKI_PROT_EXEC;
fitzhardinge98abfc72003-12-16 02:05:15 +00002304
nethercote71980f02004-01-24 18:18:54 +00002305 if (is_stack_segment)
2306 flags = SF_STACK | SF_GROWDOWN;
2307 else
2308 flags = SF_EXEC|SF_MMAP;
fitzhardinge98abfc72003-12-16 02:05:15 +00002309
nethercote71980f02004-01-24 18:18:54 +00002310 if (filename != NULL)
2311 flags |= SF_FILE;
fitzhardinge98abfc72003-12-16 02:05:15 +00002312
nethercote71980f02004-01-24 18:18:54 +00002313 if (start >= VG_(valgrind_base) && (start+size) <= VG_(valgrind_end))
2314 flags |= SF_VALGRIND;
fitzhardinge98abfc72003-12-16 02:05:15 +00002315
nethercote71980f02004-01-24 18:18:54 +00002316 VG_(map_file_segment)(start, size, prot, flags, dev, ino, foffset, filename);
fitzhardinge98abfc72003-12-16 02:05:15 +00002317
nethercote71980f02004-01-24 18:18:54 +00002318 if (VG_(is_client_addr)(start) && VG_(is_client_addr)(start+size-1))
2319 VG_TRACK( new_mem_startup, start, size, rr=='r', ww=='w', xx=='x' );
sewardj3e1eb1f2002-05-18 13:14:17 +00002320
nethercote71980f02004-01-24 18:18:54 +00002321 /* If this is the stack segment mark all below %esp as noaccess. */
2322 r_esp = esp_at_startup___global_arg;
2323 vg_assert(0 != r_esp);
2324 if (is_stack_segment) {
2325 if (0)
2326 VG_(message)(Vg_DebugMsg, "invalidating stack area: %x .. %x",
2327 start,r_esp);
2328 VG_TRACK( die_mem_stack, start, r_esp-start );
sewardjde4a1d02002-03-22 01:27:54 +00002329 }
sewardjde4a1d02002-03-22 01:27:54 +00002330}
2331
2332
nethercote71980f02004-01-24 18:18:54 +00002333/*====================================================================*/
2334/*=== Sanity check machinery (permanently engaged) ===*/
2335/*====================================================================*/
njn25e49d8e72002-09-23 09:36:25 +00002336
2337/* A fast sanity check -- suitable for calling circa once per
2338 millisecond. */
2339
nethercote885dd912004-08-03 23:14:00 +00002340void VG_(sanity_check_general) ( Bool force_expensive )
njn25e49d8e72002-09-23 09:36:25 +00002341{
njn37cea302002-09-30 11:24:00 +00002342 VGP_PUSHCC(VgpCoreCheapSanity);
2343
nethercote27fec902004-06-16 21:26:32 +00002344 if (VG_(clo_sanity_level) < 1) return;
njn25e49d8e72002-09-23 09:36:25 +00002345
2346 /* --- First do all the tests that we can do quickly. ---*/
2347
nethercote297effd2004-08-02 15:07:57 +00002348 sanity_fast_count++;
njn25e49d8e72002-09-23 09:36:25 +00002349
njn25e49d8e72002-09-23 09:36:25 +00002350 /* Check stuff pertaining to the memory check system. */
2351
2352 /* Check that nobody has spuriously claimed that the first or
2353 last 16 pages of memory have become accessible [...] */
njn37cea302002-09-30 11:24:00 +00002354 if (VG_(needs).sanity_checks) {
2355 VGP_PUSHCC(VgpSkinCheapSanity);
njn25e49d8e72002-09-23 09:36:25 +00002356 vg_assert(SK_(cheap_sanity_check)());
njn37cea302002-09-30 11:24:00 +00002357 VGP_POPCC(VgpSkinCheapSanity);
2358 }
njn25e49d8e72002-09-23 09:36:25 +00002359
2360 /* --- Now some more expensive checks. ---*/
2361
2362 /* Once every 25 times, check some more expensive stuff. */
2363 if ( force_expensive
nethercote27fec902004-06-16 21:26:32 +00002364 || VG_(clo_sanity_level) > 1
nethercote297effd2004-08-02 15:07:57 +00002365 || (VG_(clo_sanity_level) == 1 && (sanity_fast_count % 25) == 0)) {
njn25e49d8e72002-09-23 09:36:25 +00002366
njn37cea302002-09-30 11:24:00 +00002367 VGP_PUSHCC(VgpCoreExpensiveSanity);
nethercote297effd2004-08-02 15:07:57 +00002368 sanity_slow_count++;
njn25e49d8e72002-09-23 09:36:25 +00002369
nethercote885dd912004-08-03 23:14:00 +00002370 VG_(sanity_check_proxy)();
jsgf855d93d2003-10-13 22:26:55 +00002371
njn25e49d8e72002-09-23 09:36:25 +00002372# if 0
2373 { void zzzmemscan(void); zzzmemscan(); }
2374# endif
2375
nethercote297effd2004-08-02 15:07:57 +00002376 if ((sanity_fast_count % 250) == 0)
nethercote92e7b7f2004-08-07 17:52:25 +00002377 VG_(sanity_check_tt_tc)();
njn25e49d8e72002-09-23 09:36:25 +00002378
2379 if (VG_(needs).sanity_checks) {
njn37cea302002-09-30 11:24:00 +00002380 VGP_PUSHCC(VgpSkinExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002381 vg_assert(SK_(expensive_sanity_check)());
njn37cea302002-09-30 11:24:00 +00002382 VGP_POPCC(VgpSkinExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002383 }
2384 /*
nethercote297effd2004-08-02 15:07:57 +00002385 if ((sanity_fast_count % 500) == 0) VG_(mallocSanityCheckAll)();
njn25e49d8e72002-09-23 09:36:25 +00002386 */
njn37cea302002-09-30 11:24:00 +00002387 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002388 }
2389
nethercote27fec902004-06-16 21:26:32 +00002390 if (VG_(clo_sanity_level) > 1) {
njn37cea302002-09-30 11:24:00 +00002391 VGP_PUSHCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002392 /* Check sanity of the low-level memory manager. Note that bugs
2393 in the client's code can cause this to fail, so we don't do
2394 this check unless specially asked for. And because it's
2395 potentially very expensive. */
nethercote885dd912004-08-03 23:14:00 +00002396 VG_(sanity_check_malloc_all)();
njn37cea302002-09-30 11:24:00 +00002397 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002398 }
njn37cea302002-09-30 11:24:00 +00002399 VGP_POPCC(VgpCoreCheapSanity);
njn25e49d8e72002-09-23 09:36:25 +00002400}
nethercote71980f02004-01-24 18:18:54 +00002401
2402
2403/*====================================================================*/
2404/*=== main() ===*/
2405/*====================================================================*/
2406
nethercotec314eba2004-07-15 12:59:41 +00002407/*
2408 This code decides on the layout of the client and Valgrind address
nethercote996901a2004-08-03 13:29:09 +00002409 spaces, loads valgrind.so and the tool.so into the valgrind part,
nethercotec314eba2004-07-15 12:59:41 +00002410 loads the client executable (and the dynamic linker, if necessary)
2411 into the client part, and calls into Valgrind proper.
2412
2413 The code is careful not to allow spurious mappings to appear in the
2414 wrong parts of the address space. In particular, to make sure
2415 dlopen puts things in the right place, it will pad out the forbidden
2416 chunks of address space so that dlopen is forced to put things where
2417 we want them.
2418
2419 The memory map it creates is:
2420
2421 CLIENT_BASE +-------------------------+
2422 | client address space |
2423 : :
2424 : :
2425 | client stack |
2426 client_end +-------------------------+
2427 | redzone |
2428 shadow_base +-------------------------+
2429 | |
nethercote996901a2004-08-03 13:29:09 +00002430 : shadow memory for tools :
nethercotec314eba2004-07-15 12:59:41 +00002431 | (may be 0 sized) |
2432 shadow_end +-------------------------+
nethercotec314eba2004-07-15 12:59:41 +00002433 valgrind_base +-------------------------+
2434 | kickstart executable |
2435 | valgrind heap vvvvvvvvv| (barely used)
2436 - -
2437 | valgrind .so files |
2438 | and mappings |
2439 - -
2440 | valgrind stack ^^^^^^^^^|
2441 valgrind_end +-------------------------+
2442 : kernel :
2443
2444 Nb: Before we can do general allocations with VG_(arena_malloc)() and
2445 VG_(mmap)(), we need to build the segment skip-list, so we know where
2446 we can put things. However, building that structure requires
2447 allocating memory. So we need to a bootstrapping process. It's done
2448 by making VG_(arena_malloc)() have a special static superblock that's
2449 used for the first 1MB's worth of allocations. This is enough to
2450 build the segment skip-list.
2451*/
2452
nethercote31779c72004-07-30 21:50:15 +00002453static int prmap(char *start, char *end, const char *perm, off_t off,
2454 int maj, int min, int ino, void* dummy) {
thughes4ad52d02004-06-27 17:37:21 +00002455 printf("mapping %10p-%10p %s %02x:%02x %d\n",
2456 start, end, perm, maj, min, ino);
2457 return True;
2458}
2459
nethercote71980f02004-01-24 18:18:54 +00002460int main(int argc, char **argv)
2461{
2462 char **cl_argv;
2463 const char *tool = NULL;
2464 const char *exec = NULL;
2465 char *preload; /* tool-specific LD_PRELOAD .so */
2466 char **env;
nethercote6c999f22004-01-31 22:55:15 +00002467 Int need_help = 0; // 0 = no, 1 = --help, 2 = --help-debug
nethercote71980f02004-01-24 18:18:54 +00002468 struct exeinfo info;
2469 ToolInfo *toolinfo = NULL;
2470 void *tool_dlhandle;
2471 Addr client_eip;
2472 Addr esp_at_startup; /* client's %esp at the point we gained control. */
2473 UInt * client_auxv;
2474 VgSchedReturnCode src;
nethercote47dd12c2004-06-22 14:18:42 +00002475 Int exitcode = 0;
nethercote238a3c32004-08-09 13:13:31 +00002476 Int fatal_sigNo = -1;
fitzhardingeb50068f2004-02-24 23:42:55 +00002477 vki_rlimit zero = { 0, 0 };
nethercote31779c72004-07-30 21:50:15 +00002478 Int padfile;
nethercote759dda32004-08-07 18:16:56 +00002479 ThreadId last_run_tid = 0; // Last thread the scheduler ran.
2480
nethercote71980f02004-01-24 18:18:54 +00002481
2482 //============================================================
2483 // Nb: startup is complex. Prerequisites are shown at every step.
2484 //
2485 // *** Be very careful when messing with the order ***
2486 //============================================================
2487
nethercotef4928da2004-06-15 10:54:40 +00002488 //============================================================
2489 // Command line argument handling order:
2490 // * If --help/--help-debug are present, show usage message
2491 // (if --tool is also present, that includes the tool-specific usage)
2492 // * Then, if --tool is missing, abort with error msg
2493 // * Then, if client is missing, abort with error msg
2494 // * Then, if any cmdline args are bad, abort with error msg
2495 //============================================================
2496
fitzhardingeb50068f2004-02-24 23:42:55 +00002497 // Get the current process datasize rlimit, and set it to zero.
2498 // This prevents any internal uses of brk() from having any effect.
2499 // We remember the old value so we can restore it on exec, so that
2500 // child processes will have a reasonable brk value.
2501 VG_(getrlimit)(VKI_RLIMIT_DATA, &VG_(client_rlimit_data));
2502 zero.rlim_max = VG_(client_rlimit_data).rlim_max;
2503 VG_(setrlimit)(VKI_RLIMIT_DATA, &zero);
2504
nethercote71980f02004-01-24 18:18:54 +00002505 //--------------------------------------------------------------
2506 // Check we were launched by stage1
nethercotec314eba2004-07-15 12:59:41 +00002507 // p: n/a
nethercote71980f02004-01-24 18:18:54 +00002508 //--------------------------------------------------------------
nethercote31779c72004-07-30 21:50:15 +00002509 padfile = scan_auxv();
nethercote71980f02004-01-24 18:18:54 +00002510
2511 if (0) {
nethercote71980f02004-01-24 18:18:54 +00002512 printf("========== main() ==========\n");
nethercote31779c72004-07-30 21:50:15 +00002513 foreach_map(prmap, /*dummy*/NULL);
nethercote71980f02004-01-24 18:18:54 +00002514 }
2515
2516 //--------------------------------------------------------------
2517 // Look for alternative libdir
2518 // p: n/a
2519 //--------------------------------------------------------------
2520 { char *cp = getenv(VALGRINDLIB);
2521 if (cp != NULL)
2522 VG_(libdir) = cp;
2523 }
2524
2525 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002526 // Get valgrind args + client args (inc. from VALGRIND_OPTS/.valgrindrc).
2527 // Pre-process the command line.
2528 // p: n/a
2529 //--------------------------------------------------------------
nethercotef6a1d502004-08-09 12:21:57 +00002530 get_command_line(argc, argv, &vg_argc, &vg_argv, &cl_argv);
nethercote71980f02004-01-24 18:18:54 +00002531 pre_process_cmd_line_options(&need_help, &tool, &exec);
2532
2533 //==============================================================
2534 // Nb: once a tool is specified, the tool.so must be loaded even if
2535 // they specified --help or didn't specify a client program.
2536 //==============================================================
2537
2538 //--------------------------------------------------------------
2539 // With client padded out, map in tool
nethercote71980f02004-01-24 18:18:54 +00002540 // p: set-libdir [for VG_(libdir)]
2541 // p: pre_process_cmd_line_options() [for 'tool']
2542 //--------------------------------------------------------------
2543 load_tool(tool, &tool_dlhandle, &toolinfo, &preload);
2544
2545 //==============================================================
2546 // Can use VG_(malloc)() and VG_(arena_malloc)() only after load_tool()
nethercotec314eba2004-07-15 12:59:41 +00002547 // -- redzone size is now set. This is checked by vg_malloc2.c.
nethercote71980f02004-01-24 18:18:54 +00002548 //==============================================================
2549
2550 //--------------------------------------------------------------
2551 // Finalise address space layout
nethercote31779c72004-07-30 21:50:15 +00002552 // p: load_tool() [for 'toolinfo']
nethercote71980f02004-01-24 18:18:54 +00002553 //--------------------------------------------------------------
nethercote31779c72004-07-30 21:50:15 +00002554 layout_remaining_space( (Addr) & argc, toolinfo->shadow_ratio );
nethercote71980f02004-01-24 18:18:54 +00002555
2556 //--------------------------------------------------------------
2557 // Load client executable, finding in $PATH if necessary
nethercote71980f02004-01-24 18:18:54 +00002558 // p: pre_process_cmd_line_options() [for 'exec', 'need_help']
2559 // p: layout_remaining_space [so there's space]
2560 //--------------------------------------------------------------
nethercotef4928da2004-06-15 10:54:40 +00002561 load_client(cl_argv, exec, need_help, &info, &client_eip);
nethercote71980f02004-01-24 18:18:54 +00002562
2563 //--------------------------------------------------------------
2564 // Everything in place, unpad us
2565 // p: layout_remaining_space() [everything must be mapped in before now]
2566 // p: load_client() [ditto]
2567 //--------------------------------------------------------------
nethercote31779c72004-07-30 21:50:15 +00002568 as_unpad((void *)VG_(shadow_end), (void *)~0, padfile);
2569 as_closepadfile(padfile); // no more padding
nethercote71980f02004-01-24 18:18:54 +00002570
2571 //--------------------------------------------------------------
2572 // Set up client's environment
2573 // p: set-libdir [for VG_(libdir)]
2574 // p: load_tool() [for 'preload']
2575 //--------------------------------------------------------------
2576 env = fix_environment(environ, preload);
2577
2578 //--------------------------------------------------------------
nethercote5ee67ca2004-06-22 14:00:09 +00002579 // Setup client stack, eip, and VG_(client_arg[cv])
nethercote71980f02004-01-24 18:18:54 +00002580 // p: load_client() [for 'info']
2581 // p: fix_environment() [for 'env']
2582 //--------------------------------------------------------------
2583 esp_at_startup = setup_client_stack(cl_argv, env, &info, &client_auxv);
2584
2585 if (0)
nethercote6a27d832004-09-07 10:17:02 +00002586 printf("entry=%p client esp=%p vg_argc=%d brkbase=%p\n",
2587 (void*)client_eip, (void*)esp_at_startup, vg_argc,
2588 (void*)VG_(brk_base));
nethercote71980f02004-01-24 18:18:54 +00002589
2590 //==============================================================
2591 // Finished setting up operating environment. Now initialise
2592 // Valgrind. (This is where the old VG_(main)() started.)
2593 //==============================================================
2594
2595 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002596 // atfork
2597 // p: n/a
2598 //--------------------------------------------------------------
2599 VG_(atfork)(NULL, NULL, newpid);
2600 newpid(VG_INVALID_THREADID);
2601
2602 //--------------------------------------------------------------
2603 // setup file descriptors
2604 // p: n/a
2605 //--------------------------------------------------------------
2606 setup_file_descriptors();
2607
2608 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002609 // Read /proc/self/maps into a buffer
2610 // p: all memory layout, environment setup [so memory maps are right]
2611 //--------------------------------------------------------------
2612 VG_(read_procselfmaps)();
2613
2614 //--------------------------------------------------------------
2615 // Build segment map (Valgrind segments only)
2616 // p: read proc/self/maps
2617 // p: sk_pre_clo_init() [to setup new_mem_startup tracker]
2618 //--------------------------------------------------------------
2619 VG_(parse_procselfmaps) ( build_valgrind_map_callback );
2620
2621 //==============================================================
2622 // Can use VG_(arena_malloc)() with non-CORE arena after segments set up
2623 //==============================================================
2624
2625 //--------------------------------------------------------------
2626 // Init tool: pre_clo_init, process cmd line, post_clo_init
2627 // p: setup_client_stack() [for 'VG_(client_arg[cv]']
2628 // p: load_tool() [for 'tool']
2629 // p: setup_file_descriptors() [for 'VG_(fd_xxx_limit)']
2630 // p: parse_procselfmaps [so VG segments are setup so tool can
2631 // call VG_(malloc)]
nethercote71980f02004-01-24 18:18:54 +00002632 //--------------------------------------------------------------
2633 (*toolinfo->sk_pre_clo_init)();
2634 VG_(tool_init_dlsym)(tool_dlhandle);
2635 VG_(sanity_check_needs)();
2636
nethercotef4928da2004-06-15 10:54:40 +00002637 // If --tool and --help/--help-debug was given, now give the core+tool
2638 // help message
nethercotef4928da2004-06-15 10:54:40 +00002639 if (need_help) {
2640 usage(/*--help-debug?*/2 == need_help);
2641 }
nethercotec314eba2004-07-15 12:59:41 +00002642 process_cmd_line_options(client_auxv, tool);
2643
2644 SK_(post_clo_init)();
nethercotef4928da2004-06-15 10:54:40 +00002645
2646 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002647 // Build segment map (all segments)
2648 // p: setup_client_stack() [for 'esp_at_startup']
2649 // p: init tool [for 'new_mem_startup']
nethercote71980f02004-01-24 18:18:54 +00002650 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002651 esp_at_startup___global_arg = esp_at_startup;
2652 VG_(parse_procselfmaps) ( build_segment_map_callback ); /* everything */
2653 esp_at_startup___global_arg = 0;
2654
2655 //--------------------------------------------------------------
nethercotef84f6952004-07-15 14:58:33 +00002656 // Protect client trampoline page (which is also sysinfo stuff)
2657 // p: segment stuff [otherwise get seg faults...]
nethercotec314eba2004-07-15 12:59:41 +00002658 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002659 VG_(mprotect)( (void *)VG_(client_trampoline_code),
2660 VG_(trampoline_code_length), VKI_PROT_READ|VKI_PROT_EXEC );
2661
2662 //==============================================================
2663 // Can use VG_(map)() after segments set up
2664 //==============================================================
nethercote71980f02004-01-24 18:18:54 +00002665
2666 //--------------------------------------------------------------
2667 // Allow GDB attach
2668 // p: process_cmd_line_options() [for VG_(clo_wait_for_gdb)]
2669 //--------------------------------------------------------------
2670 /* Hook to delay things long enough so we can get the pid and
2671 attach GDB in another shell. */
2672 if (VG_(clo_wait_for_gdb)) {
2673 VG_(printf)("pid=%d\n", VG_(getpid)());
2674 /* do "jump *$eip" to skip this in gdb */
2675 VG_(do_syscall)(__NR_pause);
2676 }
2677
2678 //--------------------------------------------------------------
nethercote1d447092004-02-01 17:29:59 +00002679 // Set up baseBlock
nethercote71980f02004-01-24 18:18:54 +00002680 // p: {pre,post}_clo_init() [for tool helper registration]
2681 // load_client() [for 'client_eip']
2682 // setup_client_stack() [for 'esp_at_startup']
2683 //--------------------------------------------------------------
2684 init_baseBlock(client_eip, esp_at_startup);
2685
2686 //--------------------------------------------------------------
2687 // Search for file descriptors that are inherited from our parent
2688 // p: process_cmd_line_options [for VG_(clo_track_fds)]
2689 //--------------------------------------------------------------
2690 if (VG_(clo_track_fds))
2691 VG_(init_preopened_fds)();
2692
2693 //--------------------------------------------------------------
2694 // Initialise the scheduler
2695 // p: init_baseBlock() [baseBlock regs copied into VG_(threads)[1]]
2696 // p: setup_file_descriptors() [else VG_(safe_fd)() breaks]
2697 //--------------------------------------------------------------
2698 VG_(scheduler_init)();
2699
2700 //--------------------------------------------------------------
2701 // Set up the ProxyLWP machinery
2702 // p: VG_(scheduler_init)()? [XXX: subtle dependency?]
nethercote71980f02004-01-24 18:18:54 +00002703 //--------------------------------------------------------------
2704 VG_(proxy_init)();
2705
2706 //--------------------------------------------------------------
2707 // Initialise the signal handling subsystem
2708 // p: VG_(atfork)(NULL, NULL, newpid) [else problems with sigmasks]
2709 // p: VG_(proxy_init)() [else breaks...]
2710 //--------------------------------------------------------------
2711 // Nb: temporarily parks the saved blocking-mask in saved_sigmask.
2712 VG_(sigstartup_actions)();
2713
2714 //--------------------------------------------------------------
2715 // Perhaps we're profiling Valgrind?
2716 // p: process_cmd_line_options() [for VG_(clo_profile)]
2717 // p: others?
2718 //
2719 // XXX: this seems to be broken? It always says the tool wasn't built
2720 // for profiling; vg_profile.c's functions don't seem to be overriding
2721 // vg_dummy_profile.c's?
2722 //
2723 // XXX: want this as early as possible. Looking for --profile
2724 // in pre_process_cmd_line_options() could get it earlier.
2725 //--------------------------------------------------------------
2726 if (VG_(clo_profile))
2727 VGP_(init_profiling)();
2728
2729 VGP_PUSHCC(VgpStartup);
2730
2731 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002732 // Read suppression file
2733 // p: process_cmd_line_options() [for VG_(clo_suppressions)]
2734 //--------------------------------------------------------------
2735 if (VG_(needs).core_errors || VG_(needs).skin_errors)
2736 VG_(load_suppressions)();
2737
2738 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002739 // Initialise translation table and translation cache
2740 // p: read_procselfmaps [so the anonymous mmaps for the TT/TC
2741 // aren't identified as part of the client, which would waste
2742 // > 20M of virtual address space.]
2743 //--------------------------------------------------------------
2744 VG_(init_tt_tc)();
2745
2746 //--------------------------------------------------------------
2747 // Read debug info to find glibc entry points to intercept
2748 // p: parse_procselfmaps? [XXX for debug info?]
2749 // p: init_tt_tc? [XXX ???]
2750 //--------------------------------------------------------------
2751 VG_(setup_code_redirect_table)();
2752
2753 //--------------------------------------------------------------
2754 // Verbosity message
2755 // p: end_rdtsc_calibration [so startup message is printed first]
2756 //--------------------------------------------------------------
2757 if (VG_(clo_verbosity) == 1)
2758 VG_(message)(Vg_UserMsg, "For more details, rerun with: -v");
2759 if (VG_(clo_verbosity) > 0)
2760 VG_(message)(Vg_UserMsg, "");
2761
2762 //--------------------------------------------------------------
2763 // Setup pointercheck
2764 // p: process_cmd_line_options() [for VG_(clo_pointercheck)]
2765 //--------------------------------------------------------------
nethercote775508a2004-09-07 22:38:23 +00002766 if (VG_(clo_pointercheck))
2767 VG_(clo_pointercheck) = VGA_(setup_pointercheck)();
nethercote71980f02004-01-24 18:18:54 +00002768
nethercote71980f02004-01-24 18:18:54 +00002769 //--------------------------------------------------------------
2770 // Run!
2771 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002772 VGP_POPCC(VgpStartup);
2773 VGP_PUSHCC(VgpSched);
2774
nethercote238a3c32004-08-09 13:13:31 +00002775 src = VG_(scheduler)( &exitcode, &last_run_tid, &fatal_sigNo );
nethercote71980f02004-01-24 18:18:54 +00002776
nethercote238a3c32004-08-09 13:13:31 +00002777 VGP_POPCC(VgpSched);
nethercote71980f02004-01-24 18:18:54 +00002778
2779
2780 //--------------------------------------------------------------
2781 // Finalisation: cleanup, messages, etc. Order no so important, only
2782 // affects what order the messages come.
2783 //--------------------------------------------------------------
2784 if (VG_(clo_verbosity) > 0)
2785 VG_(message)(Vg_UserMsg, "");
2786
2787 if (src == VgSrc_Deadlock) {
2788 VG_(message)(Vg_UserMsg,
2789 "Warning: pthread scheduler exited due to deadlock");
2790 }
2791
2792 /* Print out file descriptor summary and stats. */
2793 if (VG_(clo_track_fds))
nethercote3a42fb82004-08-03 18:08:50 +00002794 VG_(show_open_fds)();
nethercote71980f02004-01-24 18:18:54 +00002795
2796 if (VG_(needs).core_errors || VG_(needs).skin_errors)
2797 VG_(show_all_errors)();
2798
nethercote47dd12c2004-06-22 14:18:42 +00002799 SK_(fini)( exitcode );
nethercote71980f02004-01-24 18:18:54 +00002800
nethercote885dd912004-08-03 23:14:00 +00002801 VG_(sanity_check_general)( True /*include expensive checks*/ );
nethercote71980f02004-01-24 18:18:54 +00002802
2803 if (VG_(clo_verbosity) > 1)
nethercote3a42fb82004-08-03 18:08:50 +00002804 print_all_stats();
nethercote71980f02004-01-24 18:18:54 +00002805
nethercote71980f02004-01-24 18:18:54 +00002806 if (VG_(clo_profile))
2807 VGP_(done_profiling)();
2808
nethercote71980f02004-01-24 18:18:54 +00002809 /* We're exiting, so nuke all the threads and clean up the proxy LWPs */
2810 vg_assert(src == VgSrc_FatalSig ||
nethercote759dda32004-08-07 18:16:56 +00002811 VG_(threads)[last_run_tid].status == VgTs_Runnable ||
2812 VG_(threads)[last_run_tid].status == VgTs_WaitJoiner);
nethercote71980f02004-01-24 18:18:54 +00002813 VG_(nuke_all_threads_except)(VG_INVALID_THREADID);
2814
2815 //--------------------------------------------------------------
2816 // Exit, according to the scheduler's return code
2817 //--------------------------------------------------------------
2818 switch (src) {
2819 case VgSrc_ExitSyscall: /* the normal way out */
nethercote759dda32004-08-07 18:16:56 +00002820 vg_assert(last_run_tid > 0 && last_run_tid < VG_N_THREADS);
nethercote71980f02004-01-24 18:18:54 +00002821 VG_(proxy_shutdown)();
2822
2823 /* The thread's %EBX at the time it did __NR_exit() will hold
2824 the arg to __NR_exit(), so we just do __NR_exit() with
2825 that arg. */
nethercote47dd12c2004-06-22 14:18:42 +00002826 VG_(exit)( exitcode );
nethercote71980f02004-01-24 18:18:54 +00002827 /* NOT ALIVE HERE! */
2828 VG_(core_panic)("entered the afterlife in main() -- ExitSyscall");
2829 break; /* what the hell :) */
2830
2831 case VgSrc_Deadlock:
2832 /* Just exit now. No point in continuing. */
2833 VG_(proxy_shutdown)();
2834 VG_(exit)(0);
2835 VG_(core_panic)("entered the afterlife in main() -- Deadlock");
2836 break;
2837
nethercote71980f02004-01-24 18:18:54 +00002838 case VgSrc_FatalSig:
2839 /* We were killed by a fatal signal, so replicate the effect */
nethercote238a3c32004-08-09 13:13:31 +00002840 vg_assert(fatal_sigNo != -1);
2841 VG_(kill_self)(fatal_sigNo);
nethercote71980f02004-01-24 18:18:54 +00002842 VG_(core_panic)("main(): signal was supposed to be fatal");
2843 break;
2844
2845 default:
2846 VG_(core_panic)("main(): unexpected scheduler return code");
2847 }
2848
2849 abort();
2850}
2851
2852
sewardjde4a1d02002-03-22 01:27:54 +00002853/*--------------------------------------------------------------------*/
2854/*--- end vg_main.c ---*/
2855/*--------------------------------------------------------------------*/