blob: bf7063db03dec003553ee3eb0438b336384d8586 [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
nethercote820bd8c2004-09-07 23:04:49 +0000111// Note that VG_(valgrind_last) names the last byte of the section, whereas
112// the VG_(*_end) vars name the byte one past the end of the section.
113Addr VG_(valgrind_last);
fitzhardinge98abfc72003-12-16 02:05:15 +0000114
fitzhardingeb50068f2004-02-24 23:42:55 +0000115vki_rlimit VG_(client_rlimit_data);
thughesc37184f2004-09-11 14:16:57 +0000116vki_rlimit VG_(client_rlimit_stack);
fitzhardingeb50068f2004-02-24 23:42:55 +0000117
nethercote71980f02004-01-24 18:18:54 +0000118/* This is set early to indicate whether this CPU has the
119 SSE/fxsave/fxrestor features. */
120Bool VG_(have_ssestate);
121
fitzhardinge98abfc72003-12-16 02:05:15 +0000122/* stage1 (main) executable */
nethercotef6a1d502004-08-09 12:21:57 +0000123static Int vgexecfd = -1;
fitzhardingea49f9b52003-12-16 22:26:45 +0000124
125/* client executable */
126Int VG_(clexecfd) = -1;
fitzhardinge98abfc72003-12-16 02:05:15 +0000127
128/* Path to library directory */
129const Char *VG_(libdir) = VG_LIBDIR;
130
131/* our argc/argv */
nethercotef6a1d502004-08-09 12:21:57 +0000132static Int vg_argc;
133static Char **vg_argv;
fitzhardinge98abfc72003-12-16 02:05:15 +0000134
jsgf855d93d2003-10-13 22:26:55 +0000135/* PID of the main thread */
136Int VG_(main_pid);
137
138/* PGRP of process */
139Int VG_(main_pgrp);
njn25e49d8e72002-09-23 09:36:25 +0000140
thughesad1c9562004-06-26 11:27:52 +0000141/* Application-visible file descriptor limits */
142Int VG_(fd_soft_limit) = -1;
143Int VG_(fd_hard_limit) = -1;
fitzhardingef0046f22003-12-18 02:39:22 +0000144
nethercote71980f02004-01-24 18:18:54 +0000145/* As deduced from esp_at_startup, the client's argc, argv[] and
146 envp[] as extracted from the client's stack at startup-time. */
147Int VG_(client_argc);
148Char** VG_(client_argv);
149Char** VG_(client_envp);
sewardjde4a1d02002-03-22 01:27:54 +0000150
151/* ---------------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +0000152 Running stuff
sewardjde4a1d02002-03-22 01:27:54 +0000153 ------------------------------------------------------------------ */
sewardjde4a1d02002-03-22 01:27:54 +0000154
nethercote71980f02004-01-24 18:18:54 +0000155/* Counts downwards in VG_(run_innerloop). */
156UInt VG_(dispatch_ctr);
sewardjde4a1d02002-03-22 01:27:54 +0000157
158/* 64-bit counter for the number of basic blocks done. */
159ULong VG_(bbs_done);
sewardjde4a1d02002-03-22 01:27:54 +0000160
nethercote71980f02004-01-24 18:18:54 +0000161/* Tell the logging mechanism whether we are logging to a file
162 descriptor or a socket descriptor. */
163Bool VG_(logging_to_filedes) = True;
164
sewardj73cf3bc2002-11-03 03:20:15 +0000165
nethercote71980f02004-01-24 18:18:54 +0000166/*====================================================================*/
167/*=== Counters, for profiling purposes only ===*/
168/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +0000169
nethercote92e7b7f2004-08-07 17:52:25 +0000170// These ones maintained by vg_dispatch.S
171UInt VG_(bb_enchain_count) = 0; // Number of chain operations done
172UInt VG_(bb_dechain_count) = 0; // Number of unchain operations done
173UInt VG_(unchained_jumps_done) = 0; // Number of unchained jumps done
sewardjde4a1d02002-03-22 01:27:54 +0000174
sewardjde4a1d02002-03-22 01:27:54 +0000175/* Counts pertaining to internal sanity checking. */
nethercote297effd2004-08-02 15:07:57 +0000176static UInt sanity_fast_count = 0;
177static UInt sanity_slow_count = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000178
nethercote3a42fb82004-08-03 18:08:50 +0000179static void print_all_stats ( void )
nethercote71980f02004-01-24 18:18:54 +0000180{
nethercote3a42fb82004-08-03 18:08:50 +0000181 // Translation stats
nethercote92e7b7f2004-08-07 17:52:25 +0000182 VG_(print_tt_tc_stats)();
nethercote71980f02004-01-24 18:18:54 +0000183 VG_(message)(Vg_DebugMsg,
nethercote92e7b7f2004-08-07 17:52:25 +0000184 "chainings: %d chainings, %d unchainings.",
nethercote71980f02004-01-24 18:18:54 +0000185 VG_(bb_enchain_count), VG_(bb_dechain_count) );
186 VG_(message)(Vg_DebugMsg,
nethercote3a42fb82004-08-03 18:08:50 +0000187 " dispatch: %llu jumps (bb entries); of them %u (%lu%%) unchained.",
nethercote71980f02004-01-24 18:18:54 +0000188 VG_(bbs_done),
189 VG_(unchained_jumps_done),
190 ((ULong)(100) * (ULong)(VG_(unchained_jumps_done)))
191 / ( VG_(bbs_done)==0 ? 1 : VG_(bbs_done) )
192 );
193
nethercote3a42fb82004-08-03 18:08:50 +0000194 // Scheduler stats
nethercote844e7122004-08-02 15:27:22 +0000195 VG_(print_scheduler_stats)();
nethercote71980f02004-01-24 18:18:54 +0000196
nethercote3a42fb82004-08-03 18:08:50 +0000197 // Reg-alloc stats
nethercotebee3fd92004-08-02 15:17:43 +0000198 VG_(print_reg_alloc_stats)();
nethercote71980f02004-01-24 18:18:54 +0000199 VG_(message)(Vg_DebugMsg,
200 " sanity: %d cheap, %d expensive checks.",
nethercote297effd2004-08-02 15:07:57 +0000201 sanity_fast_count, sanity_slow_count );
nethercote3a42fb82004-08-03 18:08:50 +0000202
203 // C call stats
nethercote71980f02004-01-24 18:18:54 +0000204 VG_(print_ccall_stats)();
nethercote3a42fb82004-08-03 18:08:50 +0000205
206 // UInstr histogram
207 if (VG_(clo_verbosity) > 3)
208 VG_(print_UInstr_histogram)();
209
210 // Memory stats
nethercote885dd912004-08-03 23:14:00 +0000211 if (VG_(clo_verbosity) > 2) {
nethercote3a42fb82004-08-03 18:08:50 +0000212 VG_(message)(Vg_DebugMsg, "");
213 VG_(message)(Vg_DebugMsg,
214 "------ Valgrind's internal memory use stats follow ------" );
nethercote885dd912004-08-03 23:14:00 +0000215 VG_(sanity_check_malloc_all)();
nethercote3a42fb82004-08-03 18:08:50 +0000216 VG_(print_all_arena_stats)();
nethercote885dd912004-08-03 23:14:00 +0000217 VG_(message)(Vg_DebugMsg, "");
nethercote3a42fb82004-08-03 18:08:50 +0000218 VG_(message)(Vg_DebugMsg,
219 "------ Valgrind's ExeContext management stats follow ------" );
220 VG_(print_ExeContext_stats)();
221 }
nethercote71980f02004-01-24 18:18:54 +0000222}
223
224
225/*====================================================================*/
226/*=== Miscellaneous global functions ===*/
227/*====================================================================*/
228
nethercotecf97ffb2004-09-09 13:40:31 +0000229static Int ptrace_setregs(Int pid, ThreadId tid)
230{
231 if (VG_(is_running_thread)( tid ))
232 return VGA_(ptrace_setregs_from_BB)(pid);
233 else
234 return VGA_(ptrace_setregs_from_tst)(pid, &VG_(threads)[tid].arch);
235}
236
nethercote04d0fbc2004-01-26 16:48:06 +0000237/* Start debugger and get it to attach to this process. Called if the
238 user requests this service after an error has been shown, so she can
nethercote71980f02004-01-24 18:18:54 +0000239 poke around and look at parameters, memory, etc. You can't
nethercote04d0fbc2004-01-26 16:48:06 +0000240 meaningfully get the debugger to continue the program, though; to
241 continue, quit the debugger. */
242void VG_(start_debugger) ( Int tid )
nethercote71980f02004-01-24 18:18:54 +0000243{
244 Int pid;
245
246 if ((pid = fork()) == 0) {
247 ptrace(PTRACE_TRACEME, 0, NULL, NULL);
248 VG_(kkill)(VG_(getpid)(), VKI_SIGSTOP);
249
250 } else if (pid > 0) {
nethercote71980f02004-01-24 18:18:54 +0000251 Int status;
252 Int res;
253
nethercote71980f02004-01-24 18:18:54 +0000254 if ((res = VG_(waitpid)(pid, &status, 0)) == pid &&
255 WIFSTOPPED(status) && WSTOPSIG(status) == SIGSTOP &&
nethercotecf97ffb2004-09-09 13:40:31 +0000256 ptrace_setregs(pid, tid) == 0 &&
thughes1d160052004-04-21 15:39:57 +0000257 kill(pid, SIGSTOP) == 0 &&
258 ptrace(PTRACE_DETACH, pid, NULL, 0) == 0) {
nethercote04d0fbc2004-01-26 16:48:06 +0000259 Char pidbuf[15];
260 Char file[30];
261 Char buf[100];
262 Char *bufptr;
263 Char *cmdptr;
264
265 VG_(sprintf)(pidbuf, "%d", pid);
266 VG_(sprintf)(file, "/proc/%d/fd/%d", pid, VG_(clexecfd));
267
268 bufptr = buf;
269 cmdptr = VG_(clo_db_command);
270
271 while (*cmdptr) {
272 switch (*cmdptr) {
273 case '%':
274 switch (*++cmdptr) {
275 case 'f':
276 VG_(memcpy)(bufptr, file, VG_(strlen)(file));
277 bufptr += VG_(strlen)(file);
278 cmdptr++;
279 break;
280 case 'p':
281 VG_(memcpy)(bufptr, pidbuf, VG_(strlen)(pidbuf));
282 bufptr += VG_(strlen)(pidbuf);
283 cmdptr++;
284 break;
285 default:
286 *bufptr++ = *cmdptr++;
287 break;
288 }
289 break;
290 default:
291 *bufptr++ = *cmdptr++;
292 break;
293 }
294 }
295
296 *bufptr++ = '\0';
297
298 VG_(message)(Vg_UserMsg, "starting debugger with cmd: %s", buf);
nethercote71980f02004-01-24 18:18:54 +0000299 res = VG_(system)(buf);
300 if (res == 0) {
301 VG_(message)(Vg_UserMsg, "");
302 VG_(message)(Vg_UserMsg,
nethercote04d0fbc2004-01-26 16:48:06 +0000303 "Debugger has detached. Valgrind regains control. We continue.");
nethercote71980f02004-01-24 18:18:54 +0000304 } else {
305 VG_(message)(Vg_UserMsg, "Apparently failed!");
306 VG_(message)(Vg_UserMsg, "");
307 }
308 }
309
310 VG_(kkill)(pid, VKI_SIGKILL);
311 VG_(waitpid)(pid, &status, 0);
312 }
313}
314
315
316/* Print some helpful-ish text about unimplemented things, and give
317 up. */
318void VG_(unimplemented) ( Char* msg )
319{
320 VG_(message)(Vg_UserMsg, "");
321 VG_(message)(Vg_UserMsg,
322 "Valgrind detected that your program requires");
323 VG_(message)(Vg_UserMsg,
324 "the following unimplemented functionality:");
325 VG_(message)(Vg_UserMsg, " %s", msg);
326 VG_(message)(Vg_UserMsg,
327 "This may be because the functionality is hard to implement,");
328 VG_(message)(Vg_UserMsg,
329 "or because no reasonable program would behave this way,");
330 VG_(message)(Vg_UserMsg,
331 "or because nobody has yet needed it. In any case, let us know at");
332 VG_(message)(Vg_UserMsg,
333 "%s and/or try to work around the problem, if you can.", VG_BUGS_TO);
334 VG_(message)(Vg_UserMsg,
335 "");
336 VG_(message)(Vg_UserMsg,
337 "Valgrind has to exit now. Sorry. Bye!");
338 VG_(message)(Vg_UserMsg,
339 "");
340 VG_(pp_sched_status)();
341 VG_(exit)(1);
342}
343
344Addr VG_(get_stack_pointer) ( void )
345{
346 return VG_(baseBlock)[VGOFF_(m_esp)];
347}
348
349/* Debugging thing .. can be called from assembly with OYNK macro. */
350void VG_(oynk) ( Int n )
351{
352 OINK(n);
353}
354
355/* Initialize the PID and PGRP of scheduler LWP; this is also called
356 in any new children after fork. */
357static void newpid(ThreadId unused)
358{
359 /* PID of scheduler LWP */
360 VG_(main_pid) = VG_(getpid)();
361 VG_(main_pgrp) = VG_(getpgrp)();
362}
363
364/*====================================================================*/
365/*=== Check we were launched by stage 1 ===*/
366/*====================================================================*/
367
368/* Look for our AUXV table */
nethercote31779c72004-07-30 21:50:15 +0000369int scan_auxv(void)
nethercote71980f02004-01-24 18:18:54 +0000370{
371 const struct ume_auxv *auxv = find_auxv((int *)ume_exec_esp);
nethercote31779c72004-07-30 21:50:15 +0000372 int padfile = -1, found = 0;
nethercote71980f02004-01-24 18:18:54 +0000373
374 for (; auxv->a_type != AT_NULL; auxv++)
375 switch(auxv->a_type) {
376 case AT_UME_PADFD:
nethercote31779c72004-07-30 21:50:15 +0000377 padfile = auxv->u.a_val;
nethercote71980f02004-01-24 18:18:54 +0000378 found |= 1;
379 break;
380
381 case AT_UME_EXECFD:
nethercotef6a1d502004-08-09 12:21:57 +0000382 vgexecfd = auxv->u.a_val;
nethercote71980f02004-01-24 18:18:54 +0000383 found |= 2;
384 break;
385 }
386
nethercote361a14e2004-07-26 11:11:56 +0000387 if ( found != (1|2) ) {
388 fprintf(stderr, "valgrind: stage2 must be launched by stage1\n");
nethercote71980f02004-01-24 18:18:54 +0000389 exit(127);
390 }
nethercote31779c72004-07-30 21:50:15 +0000391 vg_assert(padfile >= 0);
392 return padfile;
nethercote71980f02004-01-24 18:18:54 +0000393}
394
395
396/*====================================================================*/
397/*=== Address space determination ===*/
398/*====================================================================*/
399
nethercote31779c72004-07-30 21:50:15 +0000400static void layout_remaining_space(Addr argc_addr, float ratio)
nethercote71980f02004-01-24 18:18:54 +0000401{
nethercote31779c72004-07-30 21:50:15 +0000402 Int ires;
403 void* vres;
404 addr_t client_size, shadow_size;
nethercote71980f02004-01-24 18:18:54 +0000405
nethercote31779c72004-07-30 21:50:15 +0000406 VG_(valgrind_base) = (addr_t)&kickstart_base;
nethercote820bd8c2004-09-07 23:04:49 +0000407 VG_(valgrind_last) = ROUNDUP(argc_addr, 0x10000) - 1; // stack
nethercote71980f02004-01-24 18:18:54 +0000408
nethercote31779c72004-07-30 21:50:15 +0000409 // This gives the client the largest possible address space while
410 // taking into account the tool's shadow needs.
411 client_size = ROUNDDN((VG_(valgrind_base)-REDZONE_SIZE) / (1.+ratio),
nethercote71980f02004-01-24 18:18:54 +0000412 CLIENT_SIZE_MULTIPLE);
nethercote31779c72004-07-30 21:50:15 +0000413 VG_(client_base) = CLIENT_BASE;
nethercote71980f02004-01-24 18:18:54 +0000414 VG_(client_end) = VG_(client_base) + client_size;
nethercotee2097312004-06-27 12:29:56 +0000415 /* where !FIXED mmap goes */
nethercotebc7b4f42004-07-26 12:44:35 +0000416 VG_(client_mapbase) = VG_(client_base) +
417 PGROUNDDN((addr_t)(client_size * CLIENT_HEAP_PROPORTION));
nethercote71980f02004-01-24 18:18:54 +0000418
nethercote31779c72004-07-30 21:50:15 +0000419 VG_(shadow_base) = VG_(client_end) + REDZONE_SIZE;
nethercote410bfe62004-09-04 15:53:35 +0000420 VG_(shadow_end) = VG_(valgrind_base);
421 shadow_size = VG_(shadow_end) - VG_(shadow_base);
nethercote71980f02004-01-24 18:18:54 +0000422
nethercotee2097312004-06-27 12:29:56 +0000423#define SEGSIZE(a,b) ((VG_(b) - VG_(a))/(1024*1024))
424
nethercote71980f02004-01-24 18:18:54 +0000425 if (0)
nethercotee2097312004-06-27 12:29:56 +0000426 VG_(printf)(
427 "client_base %8x (%dMB)\n"
428 "client_mapbase %8x (%dMB)\n"
429 "client_end %8x (%dMB)\n"
430 "shadow_base %8x (%dMB)\n"
nethercote410bfe62004-09-04 15:53:35 +0000431 "shadow_end %8x\n"
nethercotee2097312004-06-27 12:29:56 +0000432 "valgrind_base %8x (%dMB)\n"
nethercote820bd8c2004-09-07 23:04:49 +0000433 "valgrind_last %8x\n",
nethercotee2097312004-06-27 12:29:56 +0000434 VG_(client_base), SEGSIZE(client_base, client_mapbase),
435 VG_(client_mapbase), SEGSIZE(client_mapbase, client_end),
436 VG_(client_end), SEGSIZE(client_end, shadow_base),
437 VG_(shadow_base), SEGSIZE(shadow_base, shadow_end),
nethercote410bfe62004-09-04 15:53:35 +0000438 VG_(shadow_end),
nethercote820bd8c2004-09-07 23:04:49 +0000439 VG_(valgrind_base), SEGSIZE(valgrind_base, valgrind_last),
440 VG_(valgrind_last)
nethercotee2097312004-06-27 12:29:56 +0000441 );
442
443#undef SEGSIZE
nethercote71980f02004-01-24 18:18:54 +0000444
445 // Ban redzone
nethercotee567e702004-07-10 17:49:17 +0000446 vres = mmap((void *)VG_(client_end), REDZONE_SIZE, PROT_NONE,
fitzhardinge72ddff62004-09-08 20:03:51 +0000447 MAP_FIXED|MAP_ANON|MAP_PRIVATE|MAP_NORESERVE, -1, 0);
nethercotee567e702004-07-10 17:49:17 +0000448 vg_assert((void*)-1 != vres);
nethercote71980f02004-01-24 18:18:54 +0000449
450 // Make client hole
nethercotee567e702004-07-10 17:49:17 +0000451 ires = munmap((void*)VG_(client_base), client_size);
452 vg_assert(0 == ires);
nethercote71980f02004-01-24 18:18:54 +0000453
454 // Map shadow memory.
455 // Initially all inaccessible, incrementally initialized as it is used
nethercotee567e702004-07-10 17:49:17 +0000456 if (shadow_size != 0) {
457 vres = mmap((char *)VG_(shadow_base), shadow_size, PROT_NONE,
fitzhardinge72ddff62004-09-08 20:03:51 +0000458 MAP_PRIVATE|MAP_ANON|MAP_FIXED|MAP_NORESERVE, -1, 0);
nethercoted4722622004-08-30 19:36:42 +0000459 if ((void*)-1 == vres) {
460 fprintf(stderr,
nethercote8c1ce432004-10-08 14:01:14 +0000461 "valgrind: Could not allocate address space (%p bytes)\n"
462 "valgrind: for shadow memory\n"
463 "valgrind: Possible causes:\n"
464 "valgrind: - For some systems (especially under RedHat 8), Valgrind\n"
465 "valgrind: needs at least 1.5GB swap space.\n"
466 "valgrind: - Or, your virtual memory size may be limited (check\n"
467 "valgrind: with 'ulimit -v').\n"
468 "valgrind: - Or, your system may use a kernel that provides only a\n"
469 "valgrind: too-small (eg. 2GB) user address space.\n"
470 , (void*)shadow_size
471 );
nethercoted4722622004-08-30 19:36:42 +0000472 exit(1);
473 }
nethercotee567e702004-07-10 17:49:17 +0000474 }
nethercote71980f02004-01-24 18:18:54 +0000475}
476
477/*====================================================================*/
478/*=== Command line setup ===*/
479/*====================================================================*/
480
481/* Nb: malloc'd memory never freed -- kept throughout like argv, envp */
482static char* get_file_clo(char* dir)
483{
484# define FLEN 512
485 Int fd, n;
486 struct stat s1;
487 char* f_clo = NULL;
488 char filename[FLEN];
489
490 snprintf(filename, FLEN, "%s/.valgrindrc", ( NULL == dir ? "" : dir ) );
491 fd = VG_(open)(filename, 0, VKI_S_IRUSR);
492 if ( fd > 0 ) {
493 if ( 0 == fstat(fd, &s1) ) {
494 f_clo = malloc(s1.st_size+1);
495 vg_assert(f_clo);
496 n = read(fd, f_clo, s1.st_size);
497 if (n == -1) n = 0;
498 f_clo[n] = '\0';
499 }
500 close(fd);
501 }
502 return f_clo;
503# undef FLEN
504}
505
nethercotee2097312004-06-27 12:29:56 +0000506#define ISSPACE(cc) ((cc) == ' ' || (cc) == '\t' || (cc) == '\n')
507
nethercote71980f02004-01-24 18:18:54 +0000508static Int count_args(char* s)
509{
510 Int n = 0;
511 if (s) {
512 char* cp = s;
513 while (True) {
514 // We have alternating sequences: blanks, non-blanks, blanks...
515 // count the non-blanks sequences.
516 while ( ISSPACE(*cp) ) cp++;
517 if ( !*cp ) break;
518 n++;
519 while ( !ISSPACE(*cp) && *cp ) cp++;
520 }
521 }
522 return n;
523}
524
525/* add args out of environment, skipping multiple spaces and -- args */
526static char** copy_args( char* s, char** to )
527{
528 if (s) {
529 char* cp = s;
530 while (True) {
531 // We have alternating sequences: blanks, non-blanks, blanks...
532 // copy the non-blanks sequences, and add terminating '\0'
533 while ( ISSPACE(*cp) ) cp++;
534 if ( !*cp ) break;
535 *to++ = cp;
536 while ( !ISSPACE(*cp) && *cp ) cp++;
537 if ( *cp ) *cp++ = '\0'; // terminate if necessary
538 if (VG_STREQ(to[-1], "--")) to--; // undo any '--' arg
539 }
540 }
541 return to;
542}
543
nethercotee2097312004-06-27 12:29:56 +0000544#undef ISSPACE
545
nethercote71980f02004-01-24 18:18:54 +0000546// Augment command line with arguments from environment and .valgrindrc
547// files.
548static void augment_command_line(Int* vg_argc_inout, char*** vg_argv_inout)
549{
nethercotef6a1d502004-08-09 12:21:57 +0000550 int vg_argc0 = *vg_argc_inout;
551 char** vg_argv0 = *vg_argv_inout;
nethercote71980f02004-01-24 18:18:54 +0000552
553 char* env_clo = getenv(VALGRINDOPTS);
554 char* f1_clo = get_file_clo( getenv("HOME") );
555 char* f2_clo = get_file_clo(".");
556
557 /* copy any extra args from file or environment, if present */
558 if ( (env_clo && *env_clo) || (f1_clo && *f1_clo) || (f2_clo && *f2_clo) ) {
559 /* ' ' separated extra options */
560 char **from;
561 char **to;
thughescaca0022004-09-13 10:20:34 +0000562 int orig_arg_count, env_arg_count, f1_arg_count, f2_arg_count;
563
564 for ( orig_arg_count = 0; vg_argv0[orig_arg_count]; orig_arg_count++ );
565
nethercote71980f02004-01-24 18:18:54 +0000566 env_arg_count = count_args(env_clo);
567 f1_arg_count = count_args(f1_clo);
568 f2_arg_count = count_args(f2_clo);
569
570 if (0)
571 printf("extra-argc=%d %d %d\n",
572 env_arg_count, f1_arg_count, f2_arg_count);
573
574 /* +2: +1 for null-termination, +1 for added '--' */
nethercotef6a1d502004-08-09 12:21:57 +0000575 from = vg_argv0;
thughescaca0022004-09-13 10:20:34 +0000576 vg_argv0 = malloc( (orig_arg_count + env_arg_count + f1_arg_count
nethercote71980f02004-01-24 18:18:54 +0000577 + f2_arg_count + 2) * sizeof(char **));
nethercotef6a1d502004-08-09 12:21:57 +0000578 vg_assert(vg_argv0);
579 to = vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000580
581 /* copy argv[0] */
582 *to++ = *from++;
583
584 /* Copy extra args from env var and file, in the order: ~/.valgrindrc,
585 * $VALGRIND_OPTS, ./.valgrindrc -- more local options are put later
586 * to override less local ones. */
587 to = copy_args(f1_clo, to);
588 to = copy_args(env_clo, to);
589 to = copy_args(f2_clo, to);
590
591 /* copy original arguments, stopping at command or -- */
592 while (*from) {
593 if (**from != '-')
594 break;
595 if (VG_STREQ(*from, "--")) {
596 from++; /* skip -- */
597 break;
598 }
599 *to++ = *from++;
600 }
601
602 /* add -- */
603 *to++ = "--";
604
nethercotef6a1d502004-08-09 12:21:57 +0000605 vg_argc0 = to - vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000606
607 /* copy rest of original command line, then NULL */
608 while (*from) *to++ = *from++;
609 *to = NULL;
610 }
611
nethercotef6a1d502004-08-09 12:21:57 +0000612 *vg_argc_inout = vg_argc0;
613 *vg_argv_inout = vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000614}
615
nethercotef6a1d502004-08-09 12:21:57 +0000616#define VG_CLO_SEP '\01'
617
nethercote71980f02004-01-24 18:18:54 +0000618static void get_command_line( int argc, char** argv,
619 Int* vg_argc_out, Char*** vg_argv_out,
620 char*** cl_argv_out )
621{
nethercotef6a1d502004-08-09 12:21:57 +0000622 int vg_argc0;
623 char** vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000624 char** cl_argv;
625 char* env_clo = getenv(VALGRINDCLO);
626
627 if (env_clo != NULL && *env_clo != '\0') {
628 char *cp;
629 char **cpp;
630
nethercotef6a1d502004-08-09 12:21:57 +0000631 /* OK, VALGRINDCLO is set, which means we must be a child of another
632 Valgrind process using --trace-children, so we're getting all our
633 arguments from VALGRINDCLO, and the entire command line belongs to
634 the client (including argv[0]) */
635 vg_argc0 = 1; /* argv[0] */
nethercote71980f02004-01-24 18:18:54 +0000636 for (cp = env_clo; *cp; cp++)
nethercotef6a1d502004-08-09 12:21:57 +0000637 if (*cp == VG_CLO_SEP)
638 vg_argc0++;
nethercote71980f02004-01-24 18:18:54 +0000639
nethercotef6a1d502004-08-09 12:21:57 +0000640 vg_argv0 = malloc(sizeof(char **) * (vg_argc0 + 1));
641 vg_assert(vg_argv0);
nethercote71980f02004-01-24 18:18:54 +0000642
nethercotef6a1d502004-08-09 12:21:57 +0000643 cpp = vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000644
645 *cpp++ = "valgrind"; /* nominal argv[0] */
646 *cpp++ = env_clo;
647
nethercotef6a1d502004-08-09 12:21:57 +0000648 // Replace the VG_CLO_SEP args separator with '\0'
nethercote71980f02004-01-24 18:18:54 +0000649 for (cp = env_clo; *cp; cp++) {
nethercotef6a1d502004-08-09 12:21:57 +0000650 if (*cp == VG_CLO_SEP) {
nethercote71980f02004-01-24 18:18:54 +0000651 *cp++ = '\0'; /* chop it up in place */
652 *cpp++ = cp;
653 }
654 }
655 *cpp = NULL;
656 cl_argv = argv;
657
658 } else {
659 /* Count the arguments on the command line. */
nethercotef6a1d502004-08-09 12:21:57 +0000660 vg_argv0 = argv;
nethercote71980f02004-01-24 18:18:54 +0000661
nethercotef6a1d502004-08-09 12:21:57 +0000662 for (vg_argc0 = 1; vg_argc0 < argc; vg_argc0++) {
663 if (argv[vg_argc0][0] != '-') /* exe name */
nethercote71980f02004-01-24 18:18:54 +0000664 break;
nethercotef6a1d502004-08-09 12:21:57 +0000665 if (VG_STREQ(argv[vg_argc0], "--")) { /* dummy arg */
666 vg_argc0++;
nethercote71980f02004-01-24 18:18:54 +0000667 break;
668 }
669 }
nethercotef6a1d502004-08-09 12:21:57 +0000670 cl_argv = &argv[vg_argc0];
nethercote71980f02004-01-24 18:18:54 +0000671
672 /* Get extra args from VALGRIND_OPTS and .valgrindrc files.
nethercotef6a1d502004-08-09 12:21:57 +0000673 Note we don't do this if getting args from VALGRINDCLO, as
674 those extra args will already be present in VALGRINDCLO. */
675 augment_command_line(&vg_argc0, &vg_argv0);
nethercote71980f02004-01-24 18:18:54 +0000676 }
677
678 if (0) {
679 Int i;
nethercotef6a1d502004-08-09 12:21:57 +0000680 for (i = 0; i < vg_argc0; i++)
681 printf("vg_argv0[%d]=\"%s\"\n", i, vg_argv0[i]);
nethercote71980f02004-01-24 18:18:54 +0000682 }
683
nethercotef6a1d502004-08-09 12:21:57 +0000684 *vg_argc_out = vg_argc0;
685 *vg_argv_out = (Char**)vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000686 *cl_argv_out = cl_argv;
687}
688
689
690/*====================================================================*/
691/*=== Environment and stack setup ===*/
692/*====================================================================*/
693
694/* Scan a colon-separated list, and call a function on each element.
695 The string must be mutable, because we insert a temporary '\0', but
thughes4ad52d02004-06-27 17:37:21 +0000696 the string will end up unmodified. (*func) should return True if it
nethercote71980f02004-01-24 18:18:54 +0000697 doesn't need to see any more.
thughes4ad52d02004-06-27 17:37:21 +0000698
699 This routine will return True if (*func) returns True and False if
700 it reaches the end of the list without that happening.
nethercote71980f02004-01-24 18:18:54 +0000701*/
thughes4ad52d02004-06-27 17:37:21 +0000702static Bool scan_colsep(char *colsep, Bool (*func)(const char *))
nethercote71980f02004-01-24 18:18:54 +0000703{
704 char *cp, *entry;
705 int end;
706
707 if (colsep == NULL ||
708 *colsep == '\0')
thughes4ad52d02004-06-27 17:37:21 +0000709 return False;
nethercote71980f02004-01-24 18:18:54 +0000710
711 entry = cp = colsep;
712
713 do {
714 end = (*cp == '\0');
715
716 if (*cp == ':' || *cp == '\0') {
717 char save = *cp;
718
719 *cp = '\0';
thughes21942d92004-07-12 09:35:37 +0000720 if ((*func)(entry)) {
721 *cp = save;
thughes4ad52d02004-06-27 17:37:21 +0000722 return True;
thughes21942d92004-07-12 09:35:37 +0000723 }
nethercote71980f02004-01-24 18:18:54 +0000724 *cp = save;
725 entry = cp+1;
726 }
727 cp++;
728 } while(!end);
thughes4ad52d02004-06-27 17:37:21 +0000729
730 return False;
731}
732
733static Bool contains(const char *p) {
734 if (VG_STREQ(p, VG_(libdir))) {
735 return True;
736 }
737 return False;
nethercote71980f02004-01-24 18:18:54 +0000738}
739
740/* Prepare the client's environment. This is basically a copy of our
741 environment, except:
742 1. LD_LIBRARY_PATH=$VALGRINDLIB:$LD_LIBRARY_PATH
743 2. LD_PRELOAD=$VALGRINDLIB/vg_inject.so:($VALGRINDLIB/vgpreload_TOOL.so:)?$LD_PRELOAD
744
745 If any of these is missing, then it is added.
746
747 Yummy. String hacking in C.
748
749 If this needs to handle any more variables it should be hacked
750 into something table driven.
751 */
752static char **fix_environment(char **origenv, const char *preload)
753{
754 static const char inject_so[] = "vg_inject.so";
755 static const char ld_library_path[] = "LD_LIBRARY_PATH=";
756 static const char ld_preload[] = "LD_PRELOAD=";
757 static const char valgrind_clo[] = VALGRINDCLO "=";
758 static const int ld_library_path_len = sizeof(ld_library_path)-1;
759 static const int ld_preload_len = sizeof(ld_preload)-1;
760 static const int valgrind_clo_len = sizeof(valgrind_clo)-1;
761 int ld_preload_done = 0;
762 int ld_library_path_done = 0;
763 char *inject_path;
764 int inject_path_len;
765 int vgliblen = strlen(VG_(libdir));
766 char **cpp;
767 char **ret;
768 int envc;
769 const int preloadlen = (preload == NULL) ? 0 : strlen(preload);
770
771 /* Find the vg_inject.so; also make room for the tool preload
772 library */
773 inject_path_len = sizeof(inject_so) + vgliblen + preloadlen + 16;
774 inject_path = malloc(inject_path_len);
nethercote7c018f42004-07-17 16:40:50 +0000775 vg_assert(inject_path);
nethercote71980f02004-01-24 18:18:54 +0000776
777 if (preload)
778 snprintf(inject_path, inject_path_len, "%s/%s:%s",
779 VG_(libdir), inject_so, preload);
780 else
781 snprintf(inject_path, inject_path_len, "%s/%s",
782 VG_(libdir), inject_so);
783
784 /* Count the original size of the env */
785 envc = 0; /* trailing NULL */
786 for (cpp = origenv; cpp && *cpp; cpp++)
787 envc++;
788
789 /* Allocate a new space */
790 ret = malloc(sizeof(char *) * (envc+3+1)); /* 3 new entries + NULL */
nethercote7c018f42004-07-17 16:40:50 +0000791 vg_assert(ret);
nethercote71980f02004-01-24 18:18:54 +0000792
793 /* copy it over */
794 for (cpp = ret; *origenv; )
795 *cpp++ = *origenv++;
796 *cpp = NULL;
797
798 vg_assert(envc == (cpp - ret));
799
800 /* Walk over the new environment, mashing as we go */
801 for (cpp = ret; cpp && *cpp; cpp++) {
802 if (memcmp(*cpp, ld_library_path, ld_library_path_len) == 0) {
nethercote71980f02004-01-24 18:18:54 +0000803 /* If the LD_LIBRARY_PATH already contains libdir, then don't
804 bother adding it again, even if it isn't the first (it
805 seems that the Java runtime will keep reexecing itself
806 unless its paths are at the front of LD_LIBRARY_PATH) */
thughes4ad52d02004-06-27 17:37:21 +0000807 if (!scan_colsep(*cpp + ld_library_path_len, contains)) {
nethercote71980f02004-01-24 18:18:54 +0000808 int len = strlen(*cpp) + vgliblen*2 + 16;
809 char *cp = malloc(len);
nethercote7c018f42004-07-17 16:40:50 +0000810 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000811
812 snprintf(cp, len, "%s%s:%s",
813 ld_library_path, VG_(libdir),
814 (*cpp)+ld_library_path_len);
815
816 *cpp = cp;
817 }
818
819 ld_library_path_done = 1;
820 } else if (memcmp(*cpp, ld_preload, ld_preload_len) == 0) {
821 int len = strlen(*cpp) + inject_path_len;
822 char *cp = malloc(len);
nethercote7c018f42004-07-17 16:40:50 +0000823 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000824
825 snprintf(cp, len, "%s%s:%s",
826 ld_preload, inject_path, (*cpp)+ld_preload_len);
827
828 *cpp = cp;
829
830 ld_preload_done = 1;
831 } else if (memcmp(*cpp, valgrind_clo, valgrind_clo_len) == 0) {
832 *cpp = "";
833 }
834 }
835
836 /* Add the missing bits */
837
838 if (!ld_library_path_done) {
839 int len = ld_library_path_len + vgliblen*2 + 16;
840 char *cp = malloc(len);
nethercote7c018f42004-07-17 16:40:50 +0000841 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000842
843 snprintf(cp, len, "%s%s", ld_library_path, VG_(libdir));
844
845 ret[envc++] = cp;
846 }
847
848 if (!ld_preload_done) {
849 int len = ld_preload_len + inject_path_len;
850 char *cp = malloc(len);
nethercote7c018f42004-07-17 16:40:50 +0000851 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000852
853 snprintf(cp, len, "%s%s",
854 ld_preload, inject_path);
855
856 ret[envc++] = cp;
857 }
858
859 ret[envc] = NULL;
860
861 return ret;
862}
863
864extern char **environ; /* our environment */
865//#include <error.h>
866
867/* Add a string onto the string table, and return its address */
868static char *copy_str(char **tab, const char *str)
869{
870 char *cp = *tab;
871 char *orig = cp;
872
873 while(*str)
874 *cp++ = *str++;
875 *cp++ = '\0';
876
877 if (0)
nethercotef84f6952004-07-15 14:58:33 +0000878 printf("copied %p \"%s\" len %d\n", orig, orig, cp-orig);
nethercote71980f02004-01-24 18:18:54 +0000879
880 *tab = cp;
881
882 return orig;
883}
884
885/*
886 This sets up the client's initial stack, containing the args,
887 environment and aux vector.
888
889 The format of the stack is:
890
891 higher address +-----------------+
892 | Trampoline code |
893 +-----------------+
894 | |
895 : string table :
896 | |
897 +-----------------+
898 | AT_NULL |
899 - -
900 | auxv |
901 +-----------------+
902 | NULL |
903 - -
904 | envp |
905 +-----------------+
906 | NULL |
907 - -
908 | argv |
909 +-----------------+
910 | argc |
911 lower address +-----------------+ <- esp
912 | undefined |
913 : :
914 */
915static Addr setup_client_stack(char **orig_argv, char **orig_envp,
916 const struct exeinfo *info,
917 UInt** client_auxv)
918{
nethercotee567e702004-07-10 17:49:17 +0000919 void* res;
nethercote71980f02004-01-24 18:18:54 +0000920 char **cpp;
921 char *strtab; /* string table */
922 char *stringbase;
923 addr_t *ptr;
924 struct ume_auxv *auxv;
925 const struct ume_auxv *orig_auxv;
926 const struct ume_auxv *cauxv;
927 unsigned stringsize; /* total size of strings in bytes */
928 unsigned auxsize; /* total size of auxv in bytes */
929 int argc; /* total argc */
930 int envc; /* total number of env vars */
931 unsigned stacksize; /* total client stack size */
932 addr_t cl_esp; /* client stack base (initial esp) */
933
934 /* use our own auxv as a prototype */
935 orig_auxv = find_auxv(ume_exec_esp);
936
937 /* ==================== compute sizes ==================== */
938
939 /* first of all, work out how big the client stack will be */
940 stringsize = 0;
941
942 /* paste on the extra args if the loader needs them (ie, the #!
943 interpreter and its argument) */
944 argc = 0;
nethercoted6a56872004-07-26 15:32:47 +0000945 if (info->interp_name != NULL) {
nethercote71980f02004-01-24 18:18:54 +0000946 argc++;
nethercoted6a56872004-07-26 15:32:47 +0000947 stringsize += strlen(info->interp_name) + 1;
nethercote71980f02004-01-24 18:18:54 +0000948 }
nethercoted6a56872004-07-26 15:32:47 +0000949 if (info->interp_args != NULL) {
nethercote71980f02004-01-24 18:18:54 +0000950 argc++;
nethercoted6a56872004-07-26 15:32:47 +0000951 stringsize += strlen(info->interp_args) + 1;
nethercote71980f02004-01-24 18:18:54 +0000952 }
953
954 /* now scan the args we're given... */
955 for (cpp = orig_argv; *cpp; cpp++) {
956 argc++;
957 stringsize += strlen(*cpp) + 1;
958 }
959
960 /* ...and the environment */
961 envc = 0;
962 for (cpp = orig_envp; cpp && *cpp; cpp++) {
963 envc++;
964 stringsize += strlen(*cpp) + 1;
965 }
966
967 /* now, how big is the auxv? */
968 auxsize = sizeof(*auxv); /* there's always at least one entry: AT_NULL */
969 for (cauxv = orig_auxv; cauxv->a_type != AT_NULL; cauxv++) {
970 if (cauxv->a_type == AT_PLATFORM)
971 stringsize += strlen(cauxv->u.a_ptr) + 1;
972 auxsize += sizeof(*cauxv);
973 }
974
975 /* OK, now we know how big the client stack is */
976 stacksize =
977 sizeof(int) + /* argc */
978 sizeof(char **)*argc + /* argv */
979 sizeof(char **) + /* terminal NULL */
980 sizeof(char **)*envc + /* envp */
981 sizeof(char **) + /* terminal NULL */
982 auxsize + /* auxv */
983 ROUNDUP(stringsize, sizeof(int)) +/* strings (aligned) */
984 VKI_BYTES_PER_PAGE; /* page for trampoline code */
985
nethercotef84f6952004-07-15 14:58:33 +0000986 // decide where stack goes!
987 VG_(clstk_end) = VG_(client_end);
988
989 VG_(client_trampoline_code) = VG_(clstk_end) - VKI_BYTES_PER_PAGE;
990
nethercote71980f02004-01-24 18:18:54 +0000991 /* cl_esp is the client's stack pointer */
nethercotef84f6952004-07-15 14:58:33 +0000992 cl_esp = VG_(clstk_end) - stacksize;
nethercote71980f02004-01-24 18:18:54 +0000993 cl_esp = ROUNDDN(cl_esp, 16); /* make stack 16 byte aligned */
994
nethercote71980f02004-01-24 18:18:54 +0000995 /* base of the string table (aligned) */
996 stringbase = strtab = (char *)(VG_(client_trampoline_code) - ROUNDUP(stringsize, sizeof(int)));
997
998 VG_(clstk_base) = PGROUNDDN(cl_esp);
nethercote71980f02004-01-24 18:18:54 +0000999
nethercote5ee67ca2004-06-22 14:00:09 +00001000 if (0)
1001 printf("stringsize=%d auxsize=%d stacksize=%d\n"
nethercote6a27d832004-09-07 10:17:02 +00001002 "clstk_base %p\n"
1003 "clstk_end %p\n",
1004 stringsize, auxsize, stacksize,
1005 (void*)VG_(clstk_base), (void*)VG_(clstk_end));
nethercote5ee67ca2004-06-22 14:00:09 +00001006
1007
nethercote71980f02004-01-24 18:18:54 +00001008 /* ==================== allocate space ==================== */
1009
1010 /* allocate a stack - mmap enough space for the stack */
nethercotef84f6952004-07-15 14:58:33 +00001011 res = mmap((void *)PGROUNDDN(cl_esp), VG_(clstk_end) - PGROUNDDN(cl_esp),
nethercotee567e702004-07-10 17:49:17 +00001012 PROT_READ | PROT_WRITE | PROT_EXEC,
1013 MAP_PRIVATE | MAP_ANON | MAP_FIXED, -1, 0);
1014 vg_assert((void*)-1 != res);
nethercote71980f02004-01-24 18:18:54 +00001015
1016 /* ==================== copy client stack ==================== */
1017
1018 ptr = (addr_t *)cl_esp;
1019
1020 /* --- argc --- */
1021 *ptr++ = argc; /* client argc */
1022
1023 /* --- argv --- */
nethercoted6a56872004-07-26 15:32:47 +00001024 if (info->interp_name) {
1025 *ptr++ = (addr_t)copy_str(&strtab, info->interp_name);
1026 free(info->interp_name);
nethercote71980f02004-01-24 18:18:54 +00001027 }
nethercoted6a56872004-07-26 15:32:47 +00001028 if (info->interp_args) {
1029 *ptr++ = (addr_t)copy_str(&strtab, info->interp_args);
1030 free(info->interp_args);
nethercote71980f02004-01-24 18:18:54 +00001031 }
1032 for (cpp = orig_argv; *cpp; ptr++, cpp++) {
1033 *ptr = (addr_t)copy_str(&strtab, *cpp);
1034 }
1035 *ptr++ = 0;
1036
1037 /* --- envp --- */
1038 VG_(client_envp) = (Char **)ptr;
1039 for (cpp = orig_envp; cpp && *cpp; ptr++, cpp++)
1040 *ptr = (addr_t)copy_str(&strtab, *cpp);
1041 *ptr++ = 0;
1042
1043 /* --- auxv --- */
1044 auxv = (struct ume_auxv *)ptr;
1045 *client_auxv = (UInt *)auxv;
1046
1047 for (; orig_auxv->a_type != AT_NULL; auxv++, orig_auxv++) {
1048 /* copy the entry... */
1049 *auxv = *orig_auxv;
1050
1051 /* ...and fix up the copy */
1052 switch(auxv->a_type) {
1053 case AT_PHDR:
1054 if (info->phdr == 0)
1055 auxv->a_type = AT_IGNORE;
1056 else
1057 auxv->u.a_val = info->phdr;
1058 break;
1059
1060 case AT_PHNUM:
1061 if (info->phdr == 0)
1062 auxv->a_type = AT_IGNORE;
1063 else
1064 auxv->u.a_val = info->phnum;
1065 break;
1066
1067 case AT_BASE:
1068 if (info->interp_base == 0)
1069 auxv->a_type = AT_IGNORE;
1070 else
1071 auxv->u.a_val = info->interp_base;
1072 break;
1073
1074 case AT_PLATFORM: /* points to a platform description string */
1075 auxv->u.a_ptr = copy_str(&strtab, orig_auxv->u.a_ptr);
1076 break;
1077
1078 case AT_ENTRY:
1079 auxv->u.a_val = info->entry;
1080 break;
1081
1082 case AT_IGNORE:
1083 case AT_EXECFD:
1084 case AT_PHENT:
1085 case AT_PAGESZ:
1086 case AT_FLAGS:
1087 case AT_NOTELF:
1088 case AT_UID:
1089 case AT_EUID:
1090 case AT_GID:
1091 case AT_EGID:
1092 case AT_CLKTCK:
1093 case AT_HWCAP:
1094 case AT_FPUCW:
1095 case AT_DCACHEBSIZE:
1096 case AT_ICACHEBSIZE:
1097 case AT_UCACHEBSIZE:
1098 /* All these are pointerless, so we don't need to do anything
1099 about them. */
1100 break;
1101
1102 case AT_SECURE:
1103 /* If this is 1, then it means that this program is running
1104 suid, and therefore the dynamic linker should be careful
1105 about LD_PRELOAD, etc. However, since stage1 (the thing
1106 the kernel actually execve's) should never be SUID, and we
1107 need LD_PRELOAD/LD_LIBRARY_PATH to work for the client, we
1108 set AT_SECURE to 0. */
1109 auxv->u.a_val = 0;
1110 break;
1111
1112 case AT_SYSINFO:
1113 /* Leave this unmolested for now, but we'll update it later
1114 when we set up the client trampoline code page */
1115 break;
1116
1117 case AT_SYSINFO_EHDR:
1118 /* Trash this, because we don't reproduce it */
1119 auxv->a_type = AT_IGNORE;
1120 break;
1121
1122 default:
1123 /* stomp out anything we don't know about */
1124 if (0)
1125 printf("stomping auxv entry %d\n", auxv->a_type);
1126 auxv->a_type = AT_IGNORE;
1127 break;
1128
1129 }
1130 }
1131 *auxv = *orig_auxv;
1132 vg_assert(auxv->a_type == AT_NULL);
1133
nethercotef84f6952004-07-15 14:58:33 +00001134 /* --- trampoline page --- */
1135 VG_(memcpy)( (void *)VG_(client_trampoline_code),
1136 &VG_(trampoline_code_start), VG_(trampoline_code_length) );
1137
nethercote71980f02004-01-24 18:18:54 +00001138 vg_assert((strtab-stringbase) == stringsize);
1139
nethercote5ee67ca2004-06-22 14:00:09 +00001140 /* We know the initial ESP is pointing at argc/argv */
1141 VG_(client_argc) = *(Int*)cl_esp;
1142 VG_(client_argv) = (Char**)(cl_esp + sizeof(Int));
1143
nethercote71980f02004-01-24 18:18:54 +00001144 return cl_esp;
1145}
1146
1147/*====================================================================*/
1148/*=== Find executable ===*/
1149/*====================================================================*/
1150
thughes4ad52d02004-06-27 17:37:21 +00001151static const char* executable_name;
1152
1153static Bool match_executable(const char *entry) {
1154 char buf[strlen(entry) + strlen(executable_name) + 2];
1155
1156 /* empty PATH element means . */
1157 if (*entry == '\0')
1158 entry = ".";
1159
1160 snprintf(buf, sizeof(buf), "%s/%s", entry, executable_name);
1161
1162 if (access(buf, R_OK|X_OK) == 0) {
1163 executable_name = strdup(buf);
1164 vg_assert(NULL != executable_name);
1165 return True;
1166 }
1167 return False;
1168}
1169
nethercote71980f02004-01-24 18:18:54 +00001170static const char* find_executable(const char* exec)
1171{
1172 vg_assert(NULL != exec);
thughes4ad52d02004-06-27 17:37:21 +00001173 executable_name = exec;
1174 if (strchr(executable_name, '/') == NULL) {
nethercote71980f02004-01-24 18:18:54 +00001175 /* no '/' - we need to search the path */
1176 char *path = getenv("PATH");
thughes4ad52d02004-06-27 17:37:21 +00001177 scan_colsep(path, match_executable);
nethercote71980f02004-01-24 18:18:54 +00001178 }
thughes4ad52d02004-06-27 17:37:21 +00001179 return executable_name;
nethercote71980f02004-01-24 18:18:54 +00001180}
1181
1182
1183/*====================================================================*/
1184/*=== Loading tools ===*/
1185/*====================================================================*/
1186
1187static void list_tools(void)
1188{
1189 DIR *dir = opendir(VG_(libdir));
1190 struct dirent *de;
1191 int first = 1;
1192
1193 if (dir == NULL) {
1194 fprintf(stderr, "Can't open %s: %s (installation problem?)\n",
nethercotef4928da2004-06-15 10:54:40 +00001195 VG_(libdir), strerror(errno));
nethercote71980f02004-01-24 18:18:54 +00001196 return;
1197 }
1198
nethercotef4928da2004-06-15 10:54:40 +00001199 while ((de = readdir(dir)) != NULL) {
nethercote71980f02004-01-24 18:18:54 +00001200 int len = strlen(de->d_name);
1201
1202 /* look for vgskin_TOOL.so names */
1203 if (len > (7+1+3) && /* "vgskin_" + at least 1-char toolname + ".so" */
nethercotef4928da2004-06-15 10:54:40 +00001204 strncmp(de->d_name, "vgskin_", 7) == 0 &&
1205 VG_STREQ(de->d_name + len - 3, ".so")) {
1206 if (first) {
1207 fprintf(stderr, "Available tools:\n");
1208 first = 0;
1209 }
1210 de->d_name[len-3] = '\0';
1211 fprintf(stderr, "\t%s\n", de->d_name+7);
nethercote71980f02004-01-24 18:18:54 +00001212 }
1213 }
1214
1215 closedir(dir);
1216
1217 if (first)
nethercotef4928da2004-06-15 10:54:40 +00001218 fprintf(stderr, "No tools available in \"%s\" (installation problem?)\n",
1219 VG_(libdir));
nethercote71980f02004-01-24 18:18:54 +00001220}
1221
1222
1223/* Find and load a tool, and check it looks ok. Also looks to see if there's
1224 * a matching vgpreload_*.so file, and returns its name in *preloadpath. */
1225static void load_tool( const char *toolname, void** handle_out,
1226 ToolInfo** toolinfo_out, char **preloadpath_out )
1227{
1228 Bool ok;
1229 int len = strlen(VG_(libdir)) + strlen(toolname)*2 + 16;
1230 char buf[len];
1231 void* handle;
1232 ToolInfo* toolinfo;
1233 char* preloadpath = NULL;
1234 Int* vg_malloc_redzonep;
1235
1236 // XXX: allowing full paths for --tool option -- does it make sense?
1237 // Doesn't allow for vgpreload_<tool>.so.
1238
1239 if (strchr(toolname, '/') != 0) {
1240 /* toolname contains '/', and so must be a pathname */
1241 handle = dlopen(toolname, RTLD_NOW);
1242 } else {
1243 /* just try in the libdir */
1244 snprintf(buf, len, "%s/vgskin_%s.so", VG_(libdir), toolname);
1245 handle = dlopen(buf, RTLD_NOW);
1246
1247 if (handle != NULL) {
1248 snprintf(buf, len, "%s/vgpreload_%s.so", VG_(libdir), toolname);
1249 if (access(buf, R_OK) == 0) {
1250 preloadpath = strdup(buf);
1251 vg_assert(NULL != preloadpath);
1252 }
1253 }
1254 }
1255
1256 ok = (NULL != handle);
1257 if (!ok) {
1258 fprintf(stderr, "Can't open tool \"%s\": %s\n", toolname, dlerror());
1259 goto bad_load;
1260 }
1261
1262 toolinfo = dlsym(handle, "vgSkin_tool_info");
1263 ok = (NULL != toolinfo);
1264 if (!ok) {
1265 fprintf(stderr, "Tool \"%s\" doesn't define SK_(tool_info) - "
1266 "add VG_DETERMINE_INTERFACE_VERSION?\n", toolname);
1267 goto bad_load;
1268 }
1269
1270 ok = (toolinfo->sizeof_ToolInfo == sizeof(*toolinfo) &&
1271 toolinfo->interface_major_version == VG_CORE_INTERFACE_MAJOR_VERSION &&
1272 toolinfo->sk_pre_clo_init != NULL);
1273 if (!ok) {
1274 fprintf(stderr, "Error:\n"
1275 " Tool and core interface versions do not match.\n"
1276 " Interface version used by core is: %d.%d (size %d)\n"
1277 " Interface version used by tool is: %d.%d (size %d)\n"
1278 " The major version numbers must match.\n",
1279 VG_CORE_INTERFACE_MAJOR_VERSION,
1280 VG_CORE_INTERFACE_MINOR_VERSION,
1281 sizeof(*toolinfo),
1282 toolinfo->interface_major_version,
1283 toolinfo->interface_minor_version,
1284 toolinfo->sizeof_ToolInfo);
1285 fprintf(stderr, " You need to at least recompile, and possibly update,\n");
1286 if (VG_CORE_INTERFACE_MAJOR_VERSION > toolinfo->interface_major_version)
nethercote996901a2004-08-03 13:29:09 +00001287 fprintf(stderr, " your tool to work with this version of Valgrind.\n");
nethercote71980f02004-01-24 18:18:54 +00001288 else
nethercote996901a2004-08-03 13:29:09 +00001289 fprintf(stderr, " your version of Valgrind to work with this tool.\n");
nethercote71980f02004-01-24 18:18:54 +00001290 goto bad_load;
1291 }
1292
1293 // Set redzone size for V's allocator
1294 vg_malloc_redzonep = dlsym(handle, STR(VG_(vg_malloc_redzone_szB)));
1295 if ( NULL != vg_malloc_redzonep ) {
1296 VG_(vg_malloc_redzone_szB) = *vg_malloc_redzonep;
1297 }
1298
1299 vg_assert(NULL != handle && NULL != toolinfo);
1300 *handle_out = handle;
1301 *toolinfo_out = toolinfo;
1302 *preloadpath_out = preloadpath;
1303 return;
1304
1305
1306 bad_load:
1307 if (handle != NULL)
1308 dlclose(handle);
1309
nethercotef4928da2004-06-15 10:54:40 +00001310 fprintf(stderr, "valgrind: couldn't load tool\n");
nethercote71980f02004-01-24 18:18:54 +00001311 list_tools();
1312 exit(127);
1313}
1314
nethercotef4928da2004-06-15 10:54:40 +00001315
1316/*====================================================================*/
1317/*=== Command line errors ===*/
1318/*====================================================================*/
1319
1320static void abort_msg ( void )
1321{
nethercotef8548672004-06-21 12:42:35 +00001322 VG_(clo_log_to) = VgLogTo_Fd;
1323 VG_(clo_log_fd) = 2; /* stderr */
nethercotef4928da2004-06-15 10:54:40 +00001324}
1325
1326void VG_(bad_option) ( Char* opt )
1327{
1328 abort_msg();
1329 VG_(printf)("valgrind: Bad option `%s'; aborting.\n", opt);
1330 VG_(printf)("valgrind: Use --help for more information.\n");
1331 VG_(exit)(1);
1332}
1333
1334static void missing_tool_option ( void )
1335{
1336 abort_msg();
1337 VG_(printf)("valgrind: Missing --tool option\n");
1338 list_tools();
1339 VG_(printf)("valgrind: Use --help for more information.\n");
1340 VG_(exit)(1);
1341}
1342
1343static void missing_prog ( void )
1344{
1345 abort_msg();
1346 VG_(printf)("valgrind: no program specified\n");
1347 VG_(printf)("valgrind: Use --help for more information.\n");
1348 VG_(exit)(1);
1349}
1350
1351static void config_error ( Char* msg )
1352{
1353 abort_msg();
1354 VG_(printf)("valgrind: Startup or configuration error:\n %s\n", msg);
1355 VG_(printf)("valgrind: Unable to start up properly. Giving up.\n");
1356 VG_(exit)(1);
1357}
1358
1359
nethercote71980f02004-01-24 18:18:54 +00001360/*====================================================================*/
1361/*=== Loading the client ===*/
1362/*====================================================================*/
1363
nethercotef4928da2004-06-15 10:54:40 +00001364static void load_client(char* cl_argv[], const char* exec, Int need_help,
nethercote71980f02004-01-24 18:18:54 +00001365 /*out*/struct exeinfo* info, /*out*/Addr* client_eip)
1366{
1367 // If they didn't specify an executable with --exec, and didn't specify
1368 // --help, then use client argv[0] (searching $PATH if necessary).
nethercotef4928da2004-06-15 10:54:40 +00001369 if (NULL == exec && !need_help) {
nethercote71980f02004-01-24 18:18:54 +00001370 if (cl_argv[0] == NULL ||
1371 ( NULL == (exec = find_executable(cl_argv[0])) ) )
1372 {
nethercotef4928da2004-06-15 10:54:40 +00001373 missing_prog();
nethercote71980f02004-01-24 18:18:54 +00001374 }
1375 }
1376
1377 info->map_base = VG_(client_mapbase);
nethercote71980f02004-01-24 18:18:54 +00001378 info->exe_base = VG_(client_base);
1379 info->exe_end = VG_(client_end);
1380 info->argv = cl_argv;
1381
nethercotef4928da2004-06-15 10:54:40 +00001382 if (need_help) {
nethercote71980f02004-01-24 18:18:54 +00001383 VG_(clexecfd) = -1;
nethercoteea147e72004-07-26 15:43:57 +00001384 // Set the minimal number of entries in 'info' to continue.
nethercoted6a56872004-07-26 15:32:47 +00001385 info->interp_name = NULL;
1386 info->interp_args = NULL;
nethercote71980f02004-01-24 18:18:54 +00001387 } else {
1388 Int ret;
1389 VG_(clexecfd) = VG_(open)(exec, O_RDONLY, VKI_S_IRUSR);
1390 ret = do_exec(exec, info);
1391 if (ret != 0) {
nethercoteea147e72004-07-26 15:43:57 +00001392 fprintf(stderr, "valgrind: do_exec(%s) failed: %s\n",
1393 exec, strerror(ret));
nethercote71980f02004-01-24 18:18:54 +00001394 exit(127);
1395 }
1396 }
1397
1398 /* Copy necessary bits of 'info' that were filled in */
1399 *client_eip = info->init_eip;
1400 VG_(brk_base) = VG_(brk_limit) = info->brkbase;
1401}
1402
nethercote969ecf12004-10-13 17:29:01 +00001403/*====================================================================*/
1404/*=== Address space unpadding ===*/
1405/*====================================================================*/
1406
1407typedef struct {
1408 char* killpad_start;
1409 char* killpad_end;
1410 struct stat* killpad_padstat;
1411} killpad_extra;
1412
1413static int killpad(char *segstart, char *segend, const char *perm, off_t off,
1414 int maj, int min, int ino, void* ex)
1415{
1416 killpad_extra* extra = ex;
1417 void *b, *e;
1418 int res;
1419
1420 vg_assert(NULL != extra->killpad_padstat);
1421
1422 if (extra->killpad_padstat->st_dev != makedev(maj, min) ||
1423 extra->killpad_padstat->st_ino != ino)
1424 return 1;
1425
1426 if (segend <= extra->killpad_start || segstart >= extra->killpad_end)
1427 return 1;
1428
1429 if (segstart <= extra->killpad_start)
1430 b = extra->killpad_start;
1431 else
1432 b = segstart;
1433
1434 if (segend >= extra->killpad_end)
1435 e = extra->killpad_end;
1436 else
1437 e = segend;
1438
1439 res = munmap(b, (char *)e-(char *)b);
1440 vg_assert(0 == res);
1441
1442 return 1;
1443}
1444
1445// Remove padding of 'padfile' from a range of address space.
1446void as_unpad(void *start, void *end, int padfile)
1447{
1448 static struct stat padstat;
1449 killpad_extra extra;
1450 int res;
1451
1452 vg_assert(padfile > 0);
1453
1454 res = fstat(padfile, &padstat);
1455 vg_assert(0 == res);
1456 extra.killpad_padstat = &padstat;
1457 extra.killpad_start = start;
1458 extra.killpad_end = end;
1459 foreach_map(killpad, &extra);
1460}
1461
1462void as_closepadfile(int padfile)
1463{
1464 int res = close(padfile);
1465 vg_assert(0 == res);
1466}
1467
nethercote71980f02004-01-24 18:18:54 +00001468
1469/*====================================================================*/
nethercotef6a1d502004-08-09 12:21:57 +00001470/*=== Command-line: variables, processing, etc ===*/
nethercote71980f02004-01-24 18:18:54 +00001471/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +00001472
njn25e49d8e72002-09-23 09:36:25 +00001473/* Define, and set defaults. */
1474Bool VG_(clo_error_limit) = True;
nethercote04d0fbc2004-01-26 16:48:06 +00001475Bool VG_(clo_db_attach) = False;
1476Char* VG_(clo_db_command) = VG_CLO_DEFAULT_DBCOMMAND;
njn43c799e2003-04-08 00:08:52 +00001477Bool VG_(clo_gen_suppressions) = False;
nethercote27fec902004-06-16 21:26:32 +00001478Int VG_(clo_sanity_level) = 1;
njn25e49d8e72002-09-23 09:36:25 +00001479Int VG_(clo_verbosity) = 1;
1480Bool VG_(clo_demangle) = True;
njn25e49d8e72002-09-23 09:36:25 +00001481Bool VG_(clo_trace_children) = False;
sewardj4cf05692002-10-27 20:28:29 +00001482
nethercotef1e5e152004-09-01 23:58:16 +00001483/* See big comment in core.h for meaning of these three.
nethercotee1730692003-11-20 10:38:07 +00001484 fd is initially stdout, for --help, but gets moved to stderr by default
1485 immediately afterwards. */
sewardj4cf05692002-10-27 20:28:29 +00001486VgLogTo VG_(clo_log_to) = VgLogTo_Fd;
nethercotef8548672004-06-21 12:42:35 +00001487Int VG_(clo_log_fd) = 1;
1488Char* VG_(clo_log_name) = NULL;
sewardj4cf05692002-10-27 20:28:29 +00001489
thughes6233a382004-08-21 11:10:44 +00001490Bool VG_(clo_time_stamp) = False;
1491
sewardj6024b212003-07-13 10:54:33 +00001492Int VG_(clo_input_fd) = 0; /* stdin */
njn25e49d8e72002-09-23 09:36:25 +00001493Int VG_(clo_n_suppressions) = 0;
sewardjde4a1d02002-03-22 01:27:54 +00001494Char* VG_(clo_suppressions)[VG_CLO_MAX_SFILES];
njn25e49d8e72002-09-23 09:36:25 +00001495Bool VG_(clo_profile) = False;
1496Bool VG_(clo_single_step) = False;
1497Bool VG_(clo_optimise) = True;
1498UChar VG_(clo_trace_codegen) = 0; // 00000000b
1499Bool VG_(clo_trace_syscalls) = False;
1500Bool VG_(clo_trace_signals) = False;
1501Bool VG_(clo_trace_symtab) = False;
njn25e49d8e72002-09-23 09:36:25 +00001502Bool VG_(clo_trace_sched) = False;
1503Int VG_(clo_trace_pthread_level) = 0;
njn25e49d8e72002-09-23 09:36:25 +00001504Int VG_(clo_dump_error) = 0;
1505Int VG_(clo_backtrace_size) = 4;
1506Char* VG_(clo_weird_hacks) = NULL;
sewardj858964b2002-10-05 14:15:43 +00001507Bool VG_(clo_run_libc_freeres) = True;
rjwalshf5f536f2003-11-17 17:45:00 +00001508Bool VG_(clo_track_fds) = False;
sewardj22854b92002-11-30 14:00:47 +00001509Bool VG_(clo_chain_bb) = True;
nethercote77eba602003-11-13 17:35:04 +00001510Bool VG_(clo_show_below_main) = False;
fitzhardinge98abfc72003-12-16 02:05:15 +00001511Bool VG_(clo_pointercheck) = True;
fitzhardinge462f4f92003-12-18 02:10:54 +00001512Bool VG_(clo_branchpred) = False;
sewardj2370f3b2002-11-30 15:01:01 +00001513
jsgf855d93d2003-10-13 22:26:55 +00001514static Bool VG_(clo_wait_for_gdb) = False;
1515
1516/* If we're doing signal routing, poll for signals every 50mS by
1517 default. */
1518Int VG_(clo_signal_polltime) = 50;
1519
1520/* These flags reduce thread wakeup latency on syscall completion and
1521 signal delivery, respectively. The downside is possible unfairness. */
1522Bool VG_(clo_lowlat_syscalls) = False; /* low-latency syscalls */
1523Bool VG_(clo_lowlat_signals) = False; /* low-latency signals */
1524
sewardjde4a1d02002-03-22 01:27:54 +00001525
nethercote6c999f22004-01-31 22:55:15 +00001526void usage ( Bool debug_help )
njn7cf0bd32002-06-08 13:36:03 +00001527{
njn25e49d8e72002-09-23 09:36:25 +00001528 Char* usage1 =
nethercote71980f02004-01-24 18:18:54 +00001529"usage: valgrind --tool=<toolname> [options] prog-and-args\n"
njn25e49d8e72002-09-23 09:36:25 +00001530"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001531" common user options for all Valgrind tools, with defaults in [ ]:\n"
nethercote0d588502004-06-21 13:27:11 +00001532" --tool=<name> use the Valgrind tool named <name>\n"
nethercotea76368b2004-06-16 11:56:29 +00001533" -h --help show this message\n"
nethercote6c999f22004-01-31 22:55:15 +00001534" --help-debug show this message, plus debugging options\n"
njn25e49d8e72002-09-23 09:36:25 +00001535" --version show version\n"
njn25e49d8e72002-09-23 09:36:25 +00001536" -q --quiet run silently; only print error msgs\n"
1537" -v --verbose be more verbose, incl counts of errors\n"
nethercote77eba602003-11-13 17:35:04 +00001538" --trace-children=no|yes Valgrind-ise child processes? [no]\n"
nethercote0d588502004-06-21 13:27:11 +00001539" --track-fds=no|yes track open file descriptors? [no]\n"
thughes6233a382004-08-21 11:10:44 +00001540" --time-stamp=no|yes add timestamps to log messages? [no]\n"
nethercote2b0793f2003-12-02 10:41:18 +00001541"\n"
1542" uncommon user options for all Valgrind tools:\n"
nethercote0d588502004-06-21 13:27:11 +00001543" --run-libc-freeres=no|yes free up glibc memory at exit? [yes]\n"
1544" --weird-hacks=hack1,hack2,... recognised hacks: lax-ioctls [none]\n"
1545" --signal-polltime=<time> signal poll period (mS) for older kernels [50]\n"
1546" --lowlat-signals=no|yes improve thread signal wake-up latency [no]\n"
1547" --lowlat-syscalls=no|yes improve thread syscall wake-up latency [no]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001548" --pointercheck=no|yes enforce client address space limits [yes]\n"
njn25e49d8e72002-09-23 09:36:25 +00001549"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001550" user options for Valgrind tools that report errors:\n"
nethercotef8548672004-06-21 12:42:35 +00001551" --log-fd=<number> log messages to file descriptor [2=stderr]\n"
1552" --log-file=<file> log messages to <file>.pid<pid>\n"
1553" --log-socket=ipaddr:port log messages to socket ipaddr:port\n"
nethercote2b0793f2003-12-02 10:41:18 +00001554" --demangle=no|yes automatically demangle C++ names? [yes]\n"
1555" --num-callers=<number> show <num> callers in stack traces [4]\n"
1556" --error-limit=no|yes stop showing new errors if too many? [yes]\n"
1557" --show-below-main=no|yes continue stack traces below main() [no]\n"
1558" --suppressions=<filename> suppress errors described in <filename>\n"
1559" --gen-suppressions=no|yes print suppressions for errors detected [no]\n"
nethercote04d0fbc2004-01-26 16:48:06 +00001560" --db-attach=no|yes start debugger when errors detected? [no]\n"
1561" --db-command=<command> command to start debugger [gdb -nw %%f %%p]\n"
1562" --input-fd=<number> file descriptor for input [0=stdin]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001563"\n";
njn7cf0bd32002-06-08 13:36:03 +00001564
njn25e49d8e72002-09-23 09:36:25 +00001565 Char* usage2 =
1566"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001567" debugging options for all Valgrind tools:\n"
njn25e49d8e72002-09-23 09:36:25 +00001568" --sanity-level=<number> level of sanity checking to do [1]\n"
1569" --single-step=no|yes translate each instr separately? [no]\n"
1570" --optimise=no|yes improve intermediate code? [yes]\n"
nethercote137bc552003-11-14 17:47:54 +00001571" --profile=no|yes profile? (tool must be built for it) [no]\n"
sewardj22854b92002-11-30 14:00:47 +00001572" --chain-bb=no|yes do basic-block chaining? [yes]\n"
fitzhardinge462f4f92003-12-18 02:10:54 +00001573" --branchpred=yes|no generate branch prediction hints [no]\n"
njn25e49d8e72002-09-23 09:36:25 +00001574" --trace-codegen=<XXXXX> show generated code? (X = 0|1) [00000]\n"
1575" --trace-syscalls=no|yes show all system calls? [no]\n"
1576" --trace-signals=no|yes show signal handling details? [no]\n"
1577" --trace-symtab=no|yes show symbol table details? [no]\n"
njn25e49d8e72002-09-23 09:36:25 +00001578" --trace-sched=no|yes show thread scheduler details? [no]\n"
njn3e884182003-04-15 13:03:23 +00001579" --trace-pthread=none|some|all show pthread event details? [none]\n"
jsgf855d93d2003-10-13 22:26:55 +00001580" --wait-for-gdb=yes|no pause on startup to wait for gdb attach\n"
njn25e49d8e72002-09-23 09:36:25 +00001581"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001582" debugging options for Valgrind tools that report errors\n"
1583" --dump-error=<number> show translation for basic block associated\n"
1584" with <number>'th error context [0=show none]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001585"\n";
njn3e884182003-04-15 13:03:23 +00001586
1587 Char* usage3 =
1588"\n"
nethercote71980f02004-01-24 18:18:54 +00001589" Extra options read from ~/.valgrindrc, $VALGRIND_OPTS, ./.valgrindrc\n"
njn25e49d8e72002-09-23 09:36:25 +00001590"\n"
nethercote08fa9a72004-07-16 17:44:00 +00001591" Valgrind is Copyright (C) 2000-2004 Julian Seward et al.\n"
njn25e49d8e72002-09-23 09:36:25 +00001592" and licensed under the GNU General Public License, version 2.\n"
1593" Bug reports, feedback, admiration, abuse, etc, to: %s.\n"
njnd04b7c62002-10-03 14:05:52 +00001594"\n"
nethercote137bc552003-11-14 17:47:54 +00001595" Tools are copyright and licensed by their authors. See each\n"
1596" tool's start-up message for more information.\n"
njn25e49d8e72002-09-23 09:36:25 +00001597"\n";
njn7cf0bd32002-06-08 13:36:03 +00001598
fitzhardinge98abfc72003-12-16 02:05:15 +00001599 VG_(printf)(usage1);
1600 if (VG_(details).name) {
1601 VG_(printf)(" user options for %s:\n", VG_(details).name);
fitzhardinge98abfc72003-12-16 02:05:15 +00001602 if (VG_(needs).command_line_options)
1603 SK_(print_usage)();
1604 else
1605 VG_(printf)(" (none)\n");
1606 }
nethercote6c999f22004-01-31 22:55:15 +00001607 if (debug_help) {
1608 VG_(printf)(usage2);
fitzhardinge98abfc72003-12-16 02:05:15 +00001609
nethercote6c999f22004-01-31 22:55:15 +00001610 if (VG_(details).name) {
1611 VG_(printf)(" debugging options for %s:\n", VG_(details).name);
1612
1613 if (VG_(needs).command_line_options)
1614 SK_(print_debug_usage)();
1615 else
1616 VG_(printf)(" (none)\n");
1617 }
fitzhardinge98abfc72003-12-16 02:05:15 +00001618 }
nethercote421281e2003-11-20 16:20:55 +00001619 VG_(printf)(usage3, VG_BUGS_TO);
nethercotef4928da2004-06-15 10:54:40 +00001620 VG_(exit)(0);
njn7cf0bd32002-06-08 13:36:03 +00001621}
sewardjde4a1d02002-03-22 01:27:54 +00001622
nethercote71980f02004-01-24 18:18:54 +00001623static void pre_process_cmd_line_options
nethercote6c999f22004-01-31 22:55:15 +00001624 ( Int* need_help, const char** tool, const char** exec )
sewardj1c1b1162003-02-23 01:25:51 +00001625{
nethercote71980f02004-01-24 18:18:54 +00001626 UInt i;
sewardjde4a1d02002-03-22 01:27:54 +00001627
nethercote71980f02004-01-24 18:18:54 +00001628 /* parse the options we have (only the options we care about now) */
nethercotef6a1d502004-08-09 12:21:57 +00001629 for (i = 1; i < vg_argc; i++) {
nethercote71980f02004-01-24 18:18:54 +00001630
nethercotef6a1d502004-08-09 12:21:57 +00001631 if (strcmp(vg_argv[i], "--version") == 0) {
nethercote71980f02004-01-24 18:18:54 +00001632 printf("valgrind-" VERSION "\n");
nethercotef4928da2004-06-15 10:54:40 +00001633 exit(0);
nethercote71980f02004-01-24 18:18:54 +00001634
nethercotef6a1d502004-08-09 12:21:57 +00001635 } else if (VG_CLO_STREQ(vg_argv[i], "--help") ||
1636 VG_CLO_STREQ(vg_argv[i], "-h")) {
nethercote6c999f22004-01-31 22:55:15 +00001637 *need_help = 1;
1638
nethercotef6a1d502004-08-09 12:21:57 +00001639 } else if (VG_CLO_STREQ(vg_argv[i], "--help-debug")) {
nethercote6c999f22004-01-31 22:55:15 +00001640 *need_help = 2;
nethercote71980f02004-01-24 18:18:54 +00001641
nethercotef6a1d502004-08-09 12:21:57 +00001642 } else if (VG_CLO_STREQN(7, vg_argv[i], "--tool=") ||
1643 VG_CLO_STREQN(7, vg_argv[i], "--skin=")) {
1644 *tool = &vg_argv[i][7];
nethercote71980f02004-01-24 18:18:54 +00001645
nethercotef6a1d502004-08-09 12:21:57 +00001646 } else if (VG_CLO_STREQN(7, vg_argv[i], "--exec=")) {
1647 *exec = &vg_argv[i][7];
nethercote71980f02004-01-24 18:18:54 +00001648 }
1649 }
1650
nethercotef4928da2004-06-15 10:54:40 +00001651 /* If no tool specified, can act appropriately without loading tool */
nethercote71980f02004-01-24 18:18:54 +00001652 if (*tool == NULL) {
nethercotef4928da2004-06-15 10:54:40 +00001653 if (0 == *need_help) {
1654 // neither --tool nor --help/--help-debug specified
1655 missing_tool_option();
1656 } else {
1657 // Give help message, without any tool-specific help
1658 usage(/*help-debug?*/2 == *need_help);
1659 }
nethercote71980f02004-01-24 18:18:54 +00001660 }
1661}
1662
nethercote5ee67ca2004-06-22 14:00:09 +00001663static void process_cmd_line_options( UInt* client_auxv, const char* toolname )
nethercote71980f02004-01-24 18:18:54 +00001664{
nethercotef8548672004-06-21 12:42:35 +00001665 Int i, eventually_log_fd;
nethercote71980f02004-01-24 18:18:54 +00001666 Int *auxp;
1667 Int toolname_len = VG_(strlen)(toolname);
sewardjde4a1d02002-03-22 01:27:54 +00001668
nethercotee1730692003-11-20 10:38:07 +00001669 /* log to stderr by default, but usage message goes to stdout */
nethercotef8548672004-06-21 12:42:35 +00001670 eventually_log_fd = 2;
sewardjde4a1d02002-03-22 01:27:54 +00001671
sewardj19d81412002-06-03 01:10:40 +00001672 /* Check for sane path in ./configure --prefix=... */
fitzhardinge98abfc72003-12-16 02:05:15 +00001673 if (VG_LIBDIR[0] != '/')
sewardj19d81412002-06-03 01:10:40 +00001674 config_error("Please use absolute paths in "
1675 "./configure --prefix=... or --libdir=...");
sewardj38170912002-05-10 21:07:22 +00001676
nethercote71980f02004-01-24 18:18:54 +00001677 for (auxp = client_auxv; auxp[0] != VKI_AT_NULL; auxp += 2) {
fitzhardinge98abfc72003-12-16 02:05:15 +00001678 switch(auxp[0]) {
1679 case VKI_AT_SYSINFO:
fitzhardinge92360792003-12-24 10:11:11 +00001680 auxp[1] = (Int)(VG_(client_trampoline_code) + VG_(tramp_syscall_offset));
fitzhardinge98abfc72003-12-16 02:05:15 +00001681 break;
sewardjde4a1d02002-03-22 01:27:54 +00001682 }
fitzhardinge98abfc72003-12-16 02:05:15 +00001683 }
sewardjde4a1d02002-03-22 01:27:54 +00001684
nethercotef6a1d502004-08-09 12:21:57 +00001685 for (i = 1; i < vg_argc; i++) {
nethercote71980f02004-01-24 18:18:54 +00001686
nethercotef6a1d502004-08-09 12:21:57 +00001687 Char* arg = vg_argv[i];
thughes3bfd5a02004-07-18 08:05:44 +00001688 Char* colon = arg;
nethercote71980f02004-01-24 18:18:54 +00001689
thughes3bfd5a02004-07-18 08:05:44 +00001690 /* Look for a colon in the switch name */
1691 while (*colon && *colon != ':' && *colon != '=')
1692 colon++;
nethercote71980f02004-01-24 18:18:54 +00001693
1694 /* Look for matching "--toolname:foo" */
thughes3bfd5a02004-07-18 08:05:44 +00001695 if (*colon == ':') {
nethercote71980f02004-01-24 18:18:54 +00001696 if (VG_CLO_STREQN(2, arg, "--") &&
1697 VG_CLO_STREQN(toolname_len, arg+2, toolname) &&
1698 VG_CLO_STREQN(1, arg+2+toolname_len, ":"))
1699 {
1700 // prefix matches, convert "--toolname:foo" to "--foo"
1701 if (0)
1702 VG_(printf)("tool-specific arg: %s\n", arg);
1703 arg += toolname_len + 1;
1704 arg[0] = '-';
1705 arg[1] = '-';
1706
1707 } else {
1708 // prefix doesn't match, skip to next arg
1709 continue;
1710 }
1711 }
1712
fitzhardinge98abfc72003-12-16 02:05:15 +00001713 /* Ignore these options - they've already been handled */
nethercote71980f02004-01-24 18:18:54 +00001714 if (VG_CLO_STREQN(7, arg, "--tool=") ||
1715 VG_CLO_STREQN(7, arg, "--skin="))
fitzhardinge98abfc72003-12-16 02:05:15 +00001716 continue;
nethercote71980f02004-01-24 18:18:54 +00001717 if (VG_CLO_STREQN(7, arg, "--exec="))
fitzhardinge98abfc72003-12-16 02:05:15 +00001718 continue;
1719
nethercote71980f02004-01-24 18:18:54 +00001720 if ( VG_CLO_STREQ(arg, "--"))
fitzhardinge98abfc72003-12-16 02:05:15 +00001721 continue;
nethercote27fec902004-06-16 21:26:32 +00001722
nethercote71980f02004-01-24 18:18:54 +00001723 else if (VG_CLO_STREQ(arg, "-v") ||
1724 VG_CLO_STREQ(arg, "--verbose"))
sewardjde4a1d02002-03-22 01:27:54 +00001725 VG_(clo_verbosity)++;
nethercote27fec902004-06-16 21:26:32 +00001726
nethercote71980f02004-01-24 18:18:54 +00001727 else if (VG_CLO_STREQ(arg, "-q") ||
1728 VG_CLO_STREQ(arg, "--quiet"))
sewardjde4a1d02002-03-22 01:27:54 +00001729 VG_(clo_verbosity)--;
1730
nethercote27fec902004-06-16 21:26:32 +00001731 else VG_BOOL_CLO("--branchpred", VG_(clo_branchpred))
1732 else VG_BOOL_CLO("--chain-bb", VG_(clo_chain_bb))
1733 else VG_BOOL_CLO("--db-attach", VG_(clo_db_attach))
1734 else VG_BOOL_CLO("--demangle", VG_(clo_demangle))
1735 else VG_BOOL_CLO("--error-limit", VG_(clo_error_limit))
1736 else VG_BOOL_CLO("--gen-suppressions", VG_(clo_gen_suppressions))
1737 else VG_BOOL_CLO("--lowlat-signals", VG_(clo_lowlat_signals))
1738 else VG_BOOL_CLO("--lowlat-syscalls", VG_(clo_lowlat_syscalls))
1739 else VG_BOOL_CLO("--optimise", VG_(clo_optimise))
1740 else VG_BOOL_CLO("--pointercheck", VG_(clo_pointercheck))
1741 else VG_BOOL_CLO("--profile", VG_(clo_profile))
1742 else VG_BOOL_CLO("--run-libc-freeres", VG_(clo_run_libc_freeres))
1743 else VG_BOOL_CLO("--show-below-main", VG_(clo_show_below_main))
1744 else VG_BOOL_CLO("--single-step", VG_(clo_single_step))
thughes6233a382004-08-21 11:10:44 +00001745 else VG_BOOL_CLO("--time-stamp", VG_(clo_time_stamp))
nethercote27fec902004-06-16 21:26:32 +00001746 else VG_BOOL_CLO("--track-fds", VG_(clo_track_fds))
1747 else VG_BOOL_CLO("--trace-children", VG_(clo_trace_children))
1748 else VG_BOOL_CLO("--trace-sched", VG_(clo_trace_sched))
1749 else VG_BOOL_CLO("--trace-signals", VG_(clo_trace_signals))
1750 else VG_BOOL_CLO("--trace-symtab", VG_(clo_trace_symtab))
1751 else VG_BOOL_CLO("--trace-syscalls", VG_(clo_trace_syscalls))
1752 else VG_BOOL_CLO("--wait-for-gdb", VG_(clo_wait_for_gdb))
sewardj72f98ff2002-06-13 17:23:38 +00001753
nethercote27fec902004-06-16 21:26:32 +00001754 else VG_STR_CLO ("--db-command", VG_(clo_db_command))
1755 else VG_STR_CLO ("--weird-hacks", VG_(clo_weird_hacks))
sewardjde4a1d02002-03-22 01:27:54 +00001756
nethercote27fec902004-06-16 21:26:32 +00001757 else VG_NUM_CLO ("--dump-error", VG_(clo_dump_error))
1758 else VG_NUM_CLO ("--input-fd", VG_(clo_input_fd))
1759 else VG_NUM_CLO ("--sanity-level", VG_(clo_sanity_level))
1760 else VG_NUM_CLO ("--signal­polltime", VG_(clo_signal_polltime))
1761 else VG_BNUM_CLO("--num-callers", VG_(clo_backtrace_size), 1,
1762 VG_DEEPEST_BACKTRACE)
sewardjde4a1d02002-03-22 01:27:54 +00001763
nethercotef8548672004-06-21 12:42:35 +00001764 // for backwards compatibility, replaced by --log-fd
nethercote71980f02004-01-24 18:18:54 +00001765 else if (VG_CLO_STREQN(13, arg, "--logfile-fd=")) {
nethercotef8548672004-06-21 12:42:35 +00001766 VG_(clo_log_to) = VgLogTo_Fd;
1767 VG_(clo_log_name) = NULL;
1768 eventually_log_fd = (Int)VG_(atoll)(&arg[13]);
1769 }
1770 else if (VG_CLO_STREQN(9, arg, "--log-fd=")) {
1771 VG_(clo_log_to) = VgLogTo_Fd;
1772 VG_(clo_log_name) = NULL;
1773 eventually_log_fd = (Int)VG_(atoll)(&arg[9]);
sewardj4cf05692002-10-27 20:28:29 +00001774 }
1775
nethercotef8548672004-06-21 12:42:35 +00001776 // for backwards compatibility, replaced by --log-file
nethercote71980f02004-01-24 18:18:54 +00001777 else if (VG_CLO_STREQN(10, arg, "--logfile=")) {
nethercotef8548672004-06-21 12:42:35 +00001778 VG_(clo_log_to) = VgLogTo_File;
1779 VG_(clo_log_name) = &arg[10];
1780 }
1781 else if (VG_CLO_STREQN(11, arg, "--log-file=")) {
1782 VG_(clo_log_to) = VgLogTo_File;
1783 VG_(clo_log_name) = &arg[11];
sewardj4cf05692002-10-27 20:28:29 +00001784 }
sewardjde4a1d02002-03-22 01:27:54 +00001785
nethercotef8548672004-06-21 12:42:35 +00001786 // for backwards compatibility, replaced by --log-socket
nethercote71980f02004-01-24 18:18:54 +00001787 else if (VG_CLO_STREQN(12, arg, "--logsocket=")) {
nethercotef8548672004-06-21 12:42:35 +00001788 VG_(clo_log_to) = VgLogTo_Socket;
1789 VG_(clo_log_name) = &arg[12];
1790 }
1791 else if (VG_CLO_STREQN(13, arg, "--log-socket=")) {
1792 VG_(clo_log_to) = VgLogTo_Socket;
1793 VG_(clo_log_name) = &arg[13];
sewardj73cf3bc2002-11-03 03:20:15 +00001794 }
1795
nethercote71980f02004-01-24 18:18:54 +00001796 else if (VG_CLO_STREQN(15, arg, "--suppressions=")) {
sewardjde4a1d02002-03-22 01:27:54 +00001797 if (VG_(clo_n_suppressions) >= VG_CLO_MAX_SFILES) {
njn25e49d8e72002-09-23 09:36:25 +00001798 VG_(message)(Vg_UserMsg, "Too many suppression files specified.");
sewardjde4a1d02002-03-22 01:27:54 +00001799 VG_(message)(Vg_UserMsg,
1800 "Increase VG_CLO_MAX_SFILES and recompile.");
nethercote71980f02004-01-24 18:18:54 +00001801 VG_(bad_option)(arg);
sewardjde4a1d02002-03-22 01:27:54 +00001802 }
nethercote71980f02004-01-24 18:18:54 +00001803 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = &arg[15];
sewardjde4a1d02002-03-22 01:27:54 +00001804 VG_(clo_n_suppressions)++;
1805 }
sewardjde4a1d02002-03-22 01:27:54 +00001806
njn25e49d8e72002-09-23 09:36:25 +00001807 /* "vwxyz" --> 000zyxwv (binary) */
nethercote71980f02004-01-24 18:18:54 +00001808 else if (VG_CLO_STREQN(16, arg, "--trace-codegen=")) {
njn25e49d8e72002-09-23 09:36:25 +00001809 Int j;
nethercote71980f02004-01-24 18:18:54 +00001810 char* opt = & arg[16];
njn25e49d8e72002-09-23 09:36:25 +00001811
1812 if (5 != VG_(strlen)(opt)) {
1813 VG_(message)(Vg_UserMsg,
1814 "--trace-codegen argument must have 5 digits");
nethercote71980f02004-01-24 18:18:54 +00001815 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001816 }
1817 for (j = 0; j < 5; j++) {
1818 if ('0' == opt[j]) { /* do nothing */ }
1819 else if ('1' == opt[j]) VG_(clo_trace_codegen) |= (1 << j);
1820 else {
1821 VG_(message)(Vg_UserMsg, "--trace-codegen argument can only "
1822 "contain 0s and 1s");
nethercote71980f02004-01-24 18:18:54 +00001823 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001824 }
1825 }
1826 }
sewardjde4a1d02002-03-22 01:27:54 +00001827
nethercote71980f02004-01-24 18:18:54 +00001828 else if (VG_CLO_STREQ(arg, "--trace-pthread=none"))
sewardj45b4b372002-04-16 22:50:32 +00001829 VG_(clo_trace_pthread_level) = 0;
nethercote71980f02004-01-24 18:18:54 +00001830 else if (VG_CLO_STREQ(arg, "--trace-pthread=some"))
sewardj45b4b372002-04-16 22:50:32 +00001831 VG_(clo_trace_pthread_level) = 1;
nethercote71980f02004-01-24 18:18:54 +00001832 else if (VG_CLO_STREQ(arg, "--trace-pthread=all"))
sewardj45b4b372002-04-16 22:50:32 +00001833 VG_(clo_trace_pthread_level) = 2;
sewardj8937c812002-04-12 20:12:20 +00001834
nethercote71980f02004-01-24 18:18:54 +00001835 else if ( ! VG_(needs).command_line_options
1836 || ! SK_(process_cmd_line_option)(arg) ) {
nethercotef4928da2004-06-15 10:54:40 +00001837 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001838 }
sewardjde4a1d02002-03-22 01:27:54 +00001839 }
1840
nethercote27fec902004-06-16 21:26:32 +00001841 // Check various option values
1842
njnf9ebf672003-05-12 21:41:30 +00001843 if (VG_(clo_verbosity) < 0)
sewardjde4a1d02002-03-22 01:27:54 +00001844 VG_(clo_verbosity) = 0;
1845
nethercote04d0fbc2004-01-26 16:48:06 +00001846 if (VG_(clo_db_attach) && VG_(clo_trace_children)) {
sewardjde4a1d02002-03-22 01:27:54 +00001847 VG_(message)(Vg_UserMsg, "");
1848 VG_(message)(Vg_UserMsg,
nethercote04d0fbc2004-01-26 16:48:06 +00001849 "--db-attach=yes conflicts with --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001850 VG_(message)(Vg_UserMsg,
1851 "Please choose one or the other, but not both.");
nethercote04d0fbc2004-01-26 16:48:06 +00001852 VG_(bad_option)("--db-attach=yes and --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001853 }
1854
nethercotef8548672004-06-21 12:42:35 +00001855 /* Set up logging now. After this is done, VG_(clo_log_fd)
sewardj4cf05692002-10-27 20:28:29 +00001856 should be connected to whatever sink has been selected, and we
1857 indiscriminately chuck stuff into it without worrying what the
1858 nature of it is. Oh the wonder of Unix streams. */
1859
nethercotee1730692003-11-20 10:38:07 +00001860 /* So far we should be still attached to stdout, so we can show on
sewardj4cf05692002-10-27 20:28:29 +00001861 the terminal any problems to do with processing command line
1862 opts. */
nethercotef8548672004-06-21 12:42:35 +00001863 vg_assert(VG_(clo_log_fd) == 1 /* stdout */);
sewardj73cf3bc2002-11-03 03:20:15 +00001864 vg_assert(VG_(logging_to_filedes) == True);
sewardj4cf05692002-10-27 20:28:29 +00001865
1866 switch (VG_(clo_log_to)) {
sewardj73cf3bc2002-11-03 03:20:15 +00001867
sewardj4cf05692002-10-27 20:28:29 +00001868 case VgLogTo_Fd:
nethercotef8548672004-06-21 12:42:35 +00001869 vg_assert(VG_(clo_log_name) == NULL);
1870 VG_(clo_log_fd) = eventually_log_fd;
sewardj4cf05692002-10-27 20:28:29 +00001871 break;
sewardj73cf3bc2002-11-03 03:20:15 +00001872
sewardj4cf05692002-10-27 20:28:29 +00001873 case VgLogTo_File: {
1874 Char logfilename[1000];
jsgff3c3f1a2003-10-14 22:13:28 +00001875 Int seq = 0;
1876 Int pid = VG_(getpid)();
1877
nethercotef8548672004-06-21 12:42:35 +00001878 vg_assert(VG_(clo_log_name) != NULL);
1879 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
jsgff3c3f1a2003-10-14 22:13:28 +00001880
nethercote71980f02004-01-24 18:18:54 +00001881 for (;;) {
jsgff3c3f1a2003-10-14 22:13:28 +00001882 if (seq == 0)
1883 VG_(sprintf)(logfilename, "%s.pid%d",
nethercotef8548672004-06-21 12:42:35 +00001884 VG_(clo_log_name), pid );
jsgff3c3f1a2003-10-14 22:13:28 +00001885 else
1886 VG_(sprintf)(logfilename, "%s.pid%d.%d",
nethercotef8548672004-06-21 12:42:35 +00001887 VG_(clo_log_name), pid, seq );
jsgff3c3f1a2003-10-14 22:13:28 +00001888 seq++;
1889
nethercotef8548672004-06-21 12:42:35 +00001890 eventually_log_fd
jsgff3c3f1a2003-10-14 22:13:28 +00001891 = VG_(open)(logfilename,
1892 VKI_O_CREAT|VKI_O_WRONLY|VKI_O_EXCL|VKI_O_TRUNC,
1893 VKI_S_IRUSR|VKI_S_IWUSR);
nethercotef8548672004-06-21 12:42:35 +00001894 if (eventually_log_fd >= 0) {
1895 VG_(clo_log_fd) = VG_(safe_fd)(eventually_log_fd);
jsgff3c3f1a2003-10-14 22:13:28 +00001896 break;
1897 } else {
nethercotef8548672004-06-21 12:42:35 +00001898 if (eventually_log_fd != -VKI_EEXIST) {
jsgff3c3f1a2003-10-14 22:13:28 +00001899 VG_(message)(Vg_UserMsg,
1900 "Can't create/open log file `%s.pid%d'; giving up!",
nethercotef8548672004-06-21 12:42:35 +00001901 VG_(clo_log_name), pid);
jsgff3c3f1a2003-10-14 22:13:28 +00001902 VG_(bad_option)(
nethercotef8548672004-06-21 12:42:35 +00001903 "--log-file=<file> didn't work out for some reason.");
jsgff3c3f1a2003-10-14 22:13:28 +00001904 break;
1905 }
1906 }
1907 }
sewardj4cf05692002-10-27 20:28:29 +00001908 break;
sewardj73cf3bc2002-11-03 03:20:15 +00001909 }
1910
1911 case VgLogTo_Socket: {
nethercotef8548672004-06-21 12:42:35 +00001912 vg_assert(VG_(clo_log_name) != NULL);
1913 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
1914 eventually_log_fd = VG_(connect_via_socket)( VG_(clo_log_name) );
1915 if (eventually_log_fd == -1) {
sewardj73cf3bc2002-11-03 03:20:15 +00001916 VG_(message)(Vg_UserMsg,
nethercotef8548672004-06-21 12:42:35 +00001917 "Invalid --log-socket=ipaddr or --log-socket=ipaddr:port spec");
sewardj73cf3bc2002-11-03 03:20:15 +00001918 VG_(message)(Vg_UserMsg,
nethercotef8548672004-06-21 12:42:35 +00001919 "of `%s'; giving up!", VG_(clo_log_name) );
sewardj73cf3bc2002-11-03 03:20:15 +00001920 VG_(bad_option)(
nethercotef8548672004-06-21 12:42:35 +00001921 "--log-socket=");
sewardj4cf05692002-10-27 20:28:29 +00001922 }
nethercotef8548672004-06-21 12:42:35 +00001923 if (eventually_log_fd == -2) {
sewardj73cf3bc2002-11-03 03:20:15 +00001924 VG_(message)(Vg_UserMsg,
sewardj570f8902002-11-03 11:44:36 +00001925 "valgrind: failed to connect to logging server `%s'.",
nethercotef8548672004-06-21 12:42:35 +00001926 VG_(clo_log_name) );
sewardj570f8902002-11-03 11:44:36 +00001927 VG_(message)(Vg_UserMsg,
1928 "Log messages will sent to stderr instead." );
1929 VG_(message)(Vg_UserMsg,
1930 "" );
1931 /* We don't change anything here. */
1932 } else {
nethercotef8548672004-06-21 12:42:35 +00001933 vg_assert(eventually_log_fd > 0);
1934 VG_(clo_log_fd) = eventually_log_fd;
sewardj570f8902002-11-03 11:44:36 +00001935 VG_(logging_to_filedes) = False;
1936 }
sewardj73cf3bc2002-11-03 03:20:15 +00001937 break;
1938 }
1939
sewardj4cf05692002-10-27 20:28:29 +00001940 }
1941
nethercotef8548672004-06-21 12:42:35 +00001942 /* Move log_fd into the safe range, so it doesn't conflict with any app fds */
thughesad1c9562004-06-26 11:27:52 +00001943 eventually_log_fd = VG_(fcntl)(VG_(clo_log_fd), VKI_F_DUPFD, VG_(fd_hard_limit));
nethercotef8548672004-06-21 12:42:35 +00001944 if (eventually_log_fd < 0)
jsgf855d93d2003-10-13 22:26:55 +00001945 VG_(message)(Vg_UserMsg, "valgrind: failed to move logfile fd into safe range");
1946 else {
nethercotef8548672004-06-21 12:42:35 +00001947 VG_(clo_log_fd) = eventually_log_fd;
1948 VG_(fcntl)(VG_(clo_log_fd), VKI_F_SETFD, VKI_FD_CLOEXEC);
jsgf855d93d2003-10-13 22:26:55 +00001949 }
1950
sewardj4cf05692002-10-27 20:28:29 +00001951 /* Ok, the logging sink is running now. Print a suitable preamble.
1952 If logging to file or a socket, write details of parent PID and
1953 command line args, to help people trying to interpret the
1954 results of a run which encompasses multiple processes. */
sewardjde4a1d02002-03-22 01:27:54 +00001955
sewardj83adf412002-05-01 01:25:45 +00001956 if (VG_(clo_verbosity > 0)) {
nethercote996901a2004-08-03 13:29:09 +00001957 /* Tool details */
nethercotea131bb82004-09-06 15:34:37 +00001958 VG_(message)(Vg_UserMsg, "%s%s%s, %s for %s.",
njnd04b7c62002-10-03 14:05:52 +00001959 VG_(details).name,
1960 NULL == VG_(details).version ? "" : "-",
1961 NULL == VG_(details).version
1962 ? (Char*)"" : VG_(details).version,
nethercotea131bb82004-09-06 15:34:37 +00001963 VG_(details).description,
1964 VG_PLATFORM);
njnd04b7c62002-10-03 14:05:52 +00001965 VG_(message)(Vg_UserMsg, "%s", VG_(details).copyright_author);
sewardj3b2736a2002-03-24 12:18:35 +00001966
njnd04b7c62002-10-03 14:05:52 +00001967 /* Core details */
1968 VG_(message)(Vg_UserMsg,
nethercotea131bb82004-09-06 15:34:37 +00001969 "Using valgrind-%s, a program supervision framework for %s.",
1970 VERSION, VG_PLATFORM);
sewardjde4a1d02002-03-22 01:27:54 +00001971 VG_(message)(Vg_UserMsg,
nethercote08fa9a72004-07-16 17:44:00 +00001972 "Copyright (C) 2000-2004, and GNU GPL'd, by Julian Seward et al.");
njnd04b7c62002-10-03 14:05:52 +00001973 }
1974
nethercotec1e395d2003-11-10 13:26:49 +00001975 if (VG_(clo_verbosity) > 0 && VG_(clo_log_to) != VgLogTo_Fd) {
sewardj4cf05692002-10-27 20:28:29 +00001976 VG_(message)(Vg_UserMsg, "");
1977 VG_(message)(Vg_UserMsg,
1978 "My PID = %d, parent PID = %d. Prog and args are:",
1979 VG_(getpid)(), VG_(getppid)() );
1980 for (i = 0; i < VG_(client_argc); i++)
1981 VG_(message)(Vg_UserMsg, " %s", VG_(client_argv)[i]);
1982 }
1983
sewardjde4a1d02002-03-22 01:27:54 +00001984 if (VG_(clo_verbosity) > 1) {
nethercotea70f7352004-04-18 12:08:46 +00001985 Int fd;
sewardj4cf05692002-10-27 20:28:29 +00001986 if (VG_(clo_log_to) != VgLogTo_Fd)
1987 VG_(message)(Vg_UserMsg, "");
fitzhardinge98abfc72003-12-16 02:05:15 +00001988 VG_(message)(Vg_UserMsg, "Valgrind library directory: %s", VG_(libdir));
njn86dc2bc2003-09-09 07:26:21 +00001989 VG_(message)(Vg_UserMsg, "Command line");
1990 for (i = 0; i < VG_(client_argc); i++)
1991 VG_(message)(Vg_UserMsg, " %s", VG_(client_argv)[i]);
1992
sewardjde4a1d02002-03-22 01:27:54 +00001993 VG_(message)(Vg_UserMsg, "Startup, with flags:");
nethercotef6a1d502004-08-09 12:21:57 +00001994 for (i = 1; i < vg_argc; i++) {
1995 VG_(message)(Vg_UserMsg, " %s", vg_argv[i]);
sewardjde4a1d02002-03-22 01:27:54 +00001996 }
nethercotea70f7352004-04-18 12:08:46 +00001997
1998 VG_(message)(Vg_UserMsg, "Contents of /proc/version:");
1999 fd = VG_(open) ( "/proc/version", VKI_O_RDONLY, 0 );
2000 if (fd < 0) {
2001 VG_(message)(Vg_UserMsg, " can't open /proc/version");
2002 } else {
2003 #define BUF_LEN 256
2004 Char version_buf[BUF_LEN];
2005 Int n = VG_(read) ( fd, version_buf, BUF_LEN );
2006 vg_assert(n <= 256);
2007 if (n > 0) {
2008 version_buf[n-1] = '\0';
2009 VG_(message)(Vg_UserMsg, " %s", version_buf);
2010 } else {
2011 VG_(message)(Vg_UserMsg, " (empty?)");
2012 }
2013 VG_(close)(fd);
2014 #undef BUF_LEN
2015 }
sewardjde4a1d02002-03-22 01:27:54 +00002016 }
2017
fitzhardinge98abfc72003-12-16 02:05:15 +00002018 if (VG_(clo_n_suppressions) < VG_CLO_MAX_SFILES-1 &&
njn25e49d8e72002-09-23 09:36:25 +00002019 (VG_(needs).core_errors || VG_(needs).skin_errors)) {
nethercote996901a2004-08-03 13:29:09 +00002020 /* If there are no suppression files specified and the tool
fitzhardinge98abfc72003-12-16 02:05:15 +00002021 needs one, load the default */
2022 static const Char default_supp[] = "default.supp";
2023 Int len = VG_(strlen)(VG_(libdir)) + 1 + sizeof(default_supp);
2024 Char *buf = VG_(arena_malloc)(VG_AR_CORE, len);
2025 VG_(sprintf)(buf, "%s/%s", VG_(libdir), default_supp);
2026 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = buf;
2027 VG_(clo_n_suppressions)++;
sewardjde4a1d02002-03-22 01:27:54 +00002028 }
sewardj4cf05692002-10-27 20:28:29 +00002029
njn6a230532003-07-21 10:38:23 +00002030 if (VG_(clo_gen_suppressions) &&
2031 !VG_(needs).core_errors && !VG_(needs).skin_errors) {
nethercotef4928da2004-06-15 10:54:40 +00002032 VG_(message)(Vg_UserMsg,
2033 "Can't use --gen-suppressions=yes with this tool,");
2034 VG_(message)(Vg_UserMsg,
2035 "as it doesn't generate errors.");
2036 VG_(bad_option)("--gen-suppressions=yes");
njn6a230532003-07-21 10:38:23 +00002037 }
sewardjde4a1d02002-03-22 01:27:54 +00002038}
2039
nethercotef6a1d502004-08-09 12:21:57 +00002040// Build the string for VALGRINDCLO.
2041Char* VG_(build_child_VALGRINDCLO)( Char* exename )
2042{
2043 /* If we're tracing the children, then we need to start it
2044 with our starter+arguments, which are copied into VALGRINDCLO,
2045 except the --exec= option is changed if present.
2046 */
2047 Int i;
2048 Char *exec;
2049 Char *cp;
2050 Char *optvar;
2051 Int optlen, execlen;
2052
2053 // All these allocated blocks are not free - because we're either
2054 // going to exec, or panic when we fail.
2055
2056 // Create --exec= option: "--exec=<exename>"
2057 exec = VG_(arena_malloc)(VG_AR_CORE,
2058 VG_(strlen)( exename ) + 7/*--exec=*/ + 1/*\0*/);
2059 vg_assert(NULL != exec);
2060 VG_(sprintf)(exec, "--exec=%s", exename);
2061
2062 // Allocate space for optvar (may overestimate by counting --exec twice,
2063 // no matter)
2064 optlen = 1;
2065 for (i = 0; i < vg_argc; i++)
2066 optlen += VG_(strlen)(vg_argv[i]) + 1;
2067 optlen += VG_(strlen)(exec)+1;
2068 optvar = VG_(arena_malloc)(VG_AR_CORE, optlen);
2069
2070 // Copy all valgrind args except the old --exec (if present)
2071 // VG_CLO_SEP is the separator.
2072 cp = optvar;
2073 for (i = 1; i < vg_argc; i++) {
2074 Char *arg = vg_argv[i];
2075
2076 if (VG_(memcmp)(arg, "--exec=", 7) == 0) {
2077 // don't copy existing --exec= arg
2078 } else if (VG_(strcmp)(arg, "--") == 0) {
2079 // stop at "--"
2080 break;
2081 } else {
2082 // copy non "--exec" arg
2083 Int len = VG_(strlen)(arg);
2084 VG_(memcpy)(cp, arg, len);
2085 cp += len;
2086 *cp++ = VG_CLO_SEP;
2087 }
2088 }
2089 // Add the new --exec= option
2090 execlen = VG_(strlen)(exec);
2091 VG_(memcpy)(cp, exec, execlen);
2092 cp += execlen;
2093 *cp++ = VG_CLO_SEP;
2094
2095 *cp = '\0';
2096
2097 return optvar;
2098}
2099
2100// Build "/proc/self/fd/<execfd>".
2101Char* VG_(build_child_exename)( void )
2102{
2103 Char* exename = VG_(arena_malloc)(VG_AR_CORE, 64);
2104 vg_assert(NULL != exename);
2105 VG_(sprintf)(exename, "/proc/self/fd/%d", vgexecfd);
2106 return exename;
2107}
2108
sewardjde4a1d02002-03-22 01:27:54 +00002109
nethercote71980f02004-01-24 18:18:54 +00002110/*====================================================================*/
2111/*=== File descriptor setup ===*/
2112/*====================================================================*/
2113
2114static void setup_file_descriptors(void)
2115{
2116 struct vki_rlimit rl;
2117
2118 /* Get the current file descriptor limits. */
2119 if (VG_(getrlimit)(VKI_RLIMIT_NOFILE, &rl) < 0) {
2120 rl.rlim_cur = 1024;
2121 rl.rlim_max = 1024;
2122 }
2123
2124 /* Work out where to move the soft limit to. */
2125 if (rl.rlim_cur + VG_N_RESERVED_FDS <= rl.rlim_max) {
2126 rl.rlim_cur = rl.rlim_cur + VG_N_RESERVED_FDS;
2127 } else {
2128 rl.rlim_cur = rl.rlim_max;
2129 }
2130
2131 /* Reserve some file descriptors for our use. */
thughesad1c9562004-06-26 11:27:52 +00002132 VG_(fd_soft_limit) = rl.rlim_cur - VG_N_RESERVED_FDS;
2133 VG_(fd_hard_limit) = rl.rlim_cur - VG_N_RESERVED_FDS;
nethercote71980f02004-01-24 18:18:54 +00002134
2135 /* Update the soft limit. */
2136 VG_(setrlimit)(VKI_RLIMIT_NOFILE, &rl);
2137
nethercotef6a1d502004-08-09 12:21:57 +00002138 if (vgexecfd != -1)
2139 vgexecfd = VG_(safe_fd)( vgexecfd );
nethercote71980f02004-01-24 18:18:54 +00002140 if (VG_(clexecfd) != -1)
2141 VG_(clexecfd) = VG_(safe_fd)( VG_(clexecfd) );
2142}
2143
2144
2145/*====================================================================*/
nethercote1d447092004-02-01 17:29:59 +00002146/*=== baseBlock: definition + setup ===*/
nethercote71980f02004-01-24 18:18:54 +00002147/*====================================================================*/
2148
nethercote71980f02004-01-24 18:18:54 +00002149Int VGOFF_(helper_undefined_instruction) = INVALID_OFFSET;
2150
2151/* MAX_NONCOMPACT_HELPERS can be increased easily. If MAX_COMPACT_HELPERS is
2152 * increased too much, they won't really be compact any more... */
2153#define MAX_COMPACT_HELPERS 8
2154#define MAX_NONCOMPACT_HELPERS 50
2155
nethercote81f9a6f2004-08-03 15:45:46 +00002156/* For storing tool-specific helpers, determined at runtime. The addr
2157 * and offset arrays together form a (addr, offset) map that allows a
2158 * helper's baseBlock offset to be computed from its address. It's done
2159 * like this so CCALLs can use the function address rather than having to
2160 * muck around with offsets. */
2161static UInt VG_(n_compact_helpers) = 0;
2162static UInt VG_(n_noncompact_helpers) = 0;
2163static Addr VG_(compact_helper_addrs) [MAX_COMPACT_HELPERS];
2164static Int VG_(compact_helper_offsets)[MAX_COMPACT_HELPERS];
2165static Addr VG_(noncompact_helper_addrs) [MAX_NONCOMPACT_HELPERS];
2166static Int VG_(noncompact_helper_offsets)[MAX_NONCOMPACT_HELPERS];
nethercote71980f02004-01-24 18:18:54 +00002167
2168/* This is the actual defn of baseblock. */
2169UInt VG_(baseBlock)[VG_BASEBLOCK_WORDS];
2170
nethercote71980f02004-01-24 18:18:54 +00002171/* Words. */
2172static Int baB_off = 0;
2173
2174
nethercote71980f02004-01-24 18:18:54 +00002175/* Returns the offset, in words. */
nethercote2e05c332004-09-06 16:43:37 +00002176Int VG_(alloc_BaB) ( Int words )
sewardjde4a1d02002-03-22 01:27:54 +00002177{
nethercote71980f02004-01-24 18:18:54 +00002178 Int off = baB_off;
2179 baB_off += words;
2180 if (baB_off >= VG_BASEBLOCK_WORDS)
nethercote2e05c332004-09-06 16:43:37 +00002181 VG_(core_panic)( "VG_(alloc_BaB): baseBlock is too small");
sewardjde4a1d02002-03-22 01:27:54 +00002182
nethercote71980f02004-01-24 18:18:54 +00002183 return off;
sewardjde4a1d02002-03-22 01:27:54 +00002184}
2185
nethercote71980f02004-01-24 18:18:54 +00002186/* Align offset, in *bytes* */
nethercote2e05c332004-09-06 16:43:37 +00002187void VG_(align_BaB) ( UInt align )
njn25e49d8e72002-09-23 09:36:25 +00002188{
nethercote71980f02004-01-24 18:18:54 +00002189 vg_assert(2 == align || 4 == align || 8 == align || 16 == align);
2190 baB_off += (align-1);
2191 baB_off &= ~(align-1);
njn25e49d8e72002-09-23 09:36:25 +00002192}
2193
nethercote71980f02004-01-24 18:18:54 +00002194/* Allocate 1 word in baseBlock and set it to the given value. */
nethercote2e05c332004-09-06 16:43:37 +00002195Int VG_(alloc_BaB_1_set) ( Addr a )
njn25e49d8e72002-09-23 09:36:25 +00002196{
nethercote2e05c332004-09-06 16:43:37 +00002197 Int off = VG_(alloc_BaB)(1);
nethercote71980f02004-01-24 18:18:54 +00002198 VG_(baseBlock)[off] = (UInt)a;
2199 return off;
njn25e49d8e72002-09-23 09:36:25 +00002200}
2201
nethercote71980f02004-01-24 18:18:54 +00002202/* Registers a function in compact_helper_addrs; compact_helper_offsets is
2203 filled in later. */
2204void VG_(register_compact_helper)(Addr a)
sewardjde4a1d02002-03-22 01:27:54 +00002205{
nethercote71980f02004-01-24 18:18:54 +00002206 if (MAX_COMPACT_HELPERS <= VG_(n_compact_helpers)) {
2207 VG_(printf)("Can only register %d compact helpers\n",
2208 MAX_COMPACT_HELPERS);
2209 VG_(core_panic)("Too many compact helpers registered");
2210 }
2211 VG_(compact_helper_addrs)[VG_(n_compact_helpers)] = a;
2212 VG_(n_compact_helpers)++;
2213}
2214
2215/* Registers a function in noncompact_helper_addrs; noncompact_helper_offsets
2216 * is filled in later.
2217 */
2218void VG_(register_noncompact_helper)(Addr a)
2219{
2220 if (MAX_NONCOMPACT_HELPERS <= VG_(n_noncompact_helpers)) {
2221 VG_(printf)("Can only register %d non-compact helpers\n",
2222 MAX_NONCOMPACT_HELPERS);
2223 VG_(printf)("Try increasing MAX_NON_COMPACT_HELPERS\n");
2224 VG_(core_panic)("Too many non-compact helpers registered");
2225 }
2226 VG_(noncompact_helper_addrs)[VG_(n_noncompact_helpers)] = a;
2227 VG_(n_noncompact_helpers)++;
2228}
2229
nethercote996901a2004-08-03 13:29:09 +00002230/* Allocate offsets in baseBlock for the tool helpers */
nethercote71980f02004-01-24 18:18:54 +00002231static
2232void assign_helpers_in_baseBlock(UInt n, Int offsets[], Addr addrs[])
2233{
2234 UInt i;
2235 for (i = 0; i < n; i++)
nethercote2e05c332004-09-06 16:43:37 +00002236 offsets[i] = VG_(alloc_BaB_1_set)( addrs[i] );
nethercote71980f02004-01-24 18:18:54 +00002237}
2238
2239Bool VG_(need_to_handle_esp_assignment)(void)
2240{
2241 return ( VG_(defined_new_mem_stack_4)() ||
2242 VG_(defined_die_mem_stack_4)() ||
2243 VG_(defined_new_mem_stack_8)() ||
2244 VG_(defined_die_mem_stack_8)() ||
2245 VG_(defined_new_mem_stack_12)() ||
2246 VG_(defined_die_mem_stack_12)() ||
2247 VG_(defined_new_mem_stack_16)() ||
2248 VG_(defined_die_mem_stack_16)() ||
2249 VG_(defined_new_mem_stack_32)() ||
2250 VG_(defined_die_mem_stack_32)() ||
2251 VG_(defined_new_mem_stack)() ||
2252 VG_(defined_die_mem_stack)()
2253 );
2254}
2255
nethercote2e05c332004-09-06 16:43:37 +00002256// The low/high split is for x86, so that the more common helpers can be
2257// in the first 128 bytes of the start, which allows the use of a more
2258// compact addressing mode.
nethercote71980f02004-01-24 18:18:54 +00002259static void init_baseBlock ( Addr client_eip, Addr esp_at_startup )
2260{
nethercote2e05c332004-09-06 16:43:37 +00002261 VGA_(init_low_baseBlock)(client_eip, esp_at_startup);
nethercote71980f02004-01-24 18:18:54 +00002262
nethercote71980f02004-01-24 18:18:54 +00002263 /* Allocate slots for compact helpers */
2264 assign_helpers_in_baseBlock(VG_(n_compact_helpers),
2265 VG_(compact_helper_offsets),
2266 VG_(compact_helper_addrs));
2267
nethercote2e05c332004-09-06 16:43:37 +00002268 VGA_(init_high_baseBlock)(client_eip, esp_at_startup);
fitzhardingef0046f22003-12-18 02:39:22 +00002269
nethercote71980f02004-01-24 18:18:54 +00002270#define REG(kind, size) \
2271 if (VG_(defined_##kind##_mem_stack##size)()) \
2272 VG_(register_noncompact_helper)( \
2273 (Addr) VG_(tool_interface).track_##kind##_mem_stack##size );
2274 REG(new, _8);
2275 REG(new, _12);
2276 REG(new, _16);
2277 REG(new, _32);
2278 REG(new, );
2279 REG(die, _8);
2280 REG(die, _12);
2281 REG(die, _16);
2282 REG(die, _32);
2283 REG(die, );
2284#undef REG
fitzhardingef0046f22003-12-18 02:39:22 +00002285
nethercote71980f02004-01-24 18:18:54 +00002286 if (VG_(need_to_handle_esp_assignment)())
2287 VG_(register_noncompact_helper)((Addr) VG_(unknown_esp_update));
fitzhardingeb791a192003-12-18 07:22:44 +00002288
nethercote2e05c332004-09-06 16:43:37 +00002289 VGOFF_(helper_undefined_instruction)
2290 = VG_(alloc_BaB_1_set)( (Addr) & VG_(helper_undefined_instruction));
sewardjde4a1d02002-03-22 01:27:54 +00002291
nethercote71980f02004-01-24 18:18:54 +00002292 /* Allocate slots for noncompact helpers */
2293 assign_helpers_in_baseBlock(VG_(n_noncompact_helpers),
2294 VG_(noncompact_helper_offsets),
2295 VG_(noncompact_helper_addrs));
2296}
sewardjde4a1d02002-03-22 01:27:54 +00002297
nethercote81f9a6f2004-08-03 15:45:46 +00002298// Finds the baseBlock offset of a tool-specified helper.
2299// Searches through compacts first, then non-compacts.
2300Int VG_(helper_offset)(Addr a)
2301{
2302 UInt i;
2303 Char buf[100];
2304
2305 for (i = 0; i < VG_(n_compact_helpers); i++)
2306 if (VG_(compact_helper_addrs)[i] == a)
2307 return VG_(compact_helper_offsets)[i];
2308 for (i = 0; i < VG_(n_noncompact_helpers); i++)
2309 if (VG_(noncompact_helper_addrs)[i] == a)
2310 return VG_(noncompact_helper_offsets)[i];
2311
2312 /* Shouldn't get here */
2313 VG_(get_fnname) ( a, buf, 100 );
2314
2315 VG_(printf)(
2316 "\nCouldn't find offset of helper from its address (%p: %s).\n"
2317 "A helper function probably used hasn't been registered?\n\n", a, buf);
2318
2319 VG_(printf)(" compact helpers: ");
2320 for (i = 0; i < VG_(n_compact_helpers); i++)
2321 VG_(printf)("%p ", VG_(compact_helper_addrs)[i]);
2322
2323 VG_(printf)("\n non-compact helpers: ");
2324 for (i = 0; i < VG_(n_noncompact_helpers); i++)
2325 VG_(printf)("%p ", VG_(noncompact_helper_addrs)[i]);
2326
2327 VG_(printf)("\n");
2328 VG_(skin_panic)("Unfound helper");
2329}
2330
sewardj5f07b662002-04-23 16:52:51 +00002331
nethercote71980f02004-01-24 18:18:54 +00002332/*====================================================================*/
nethercote71980f02004-01-24 18:18:54 +00002333/*=== Initialise program data/text, etc. ===*/
2334/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +00002335
nethercote71980f02004-01-24 18:18:54 +00002336static void build_valgrind_map_callback
2337 ( Addr start, UInt size, Char rr, Char ww, Char xx,
2338 UInt dev, UInt ino, ULong foffset, const UChar* filename )
sewardjde4a1d02002-03-22 01:27:54 +00002339{
nethercote71980f02004-01-24 18:18:54 +00002340 UInt prot = 0;
2341 UInt flags = SF_MMAP|SF_NOSYMS;
2342 Bool is_stack_segment;
2343
2344 is_stack_segment =
2345 (start == VG_(clstk_base) && (start+size) == VG_(clstk_end));
2346
2347 /* Only record valgrind mappings for now, without loading any
2348 symbols. This is so we know where the free space is before we
2349 start allocating more memory (note: heap is OK, it's just mmap
2350 which is the problem here). */
nethercote820bd8c2004-09-07 23:04:49 +00002351 if (start >= VG_(valgrind_base) && (start+size-1) <= VG_(valgrind_last)) {
nethercote71980f02004-01-24 18:18:54 +00002352 flags |= SF_VALGRIND;
2353 VG_(map_file_segment)(start, size, prot, flags, dev, ino, foffset, filename);
2354 }
sewardjde4a1d02002-03-22 01:27:54 +00002355}
2356
nethercote71980f02004-01-24 18:18:54 +00002357// Global var used to pass local data to callback
2358Addr esp_at_startup___global_arg = 0;
sewardjde4a1d02002-03-22 01:27:54 +00002359
nethercote71980f02004-01-24 18:18:54 +00002360static void build_segment_map_callback
2361 ( Addr start, UInt size, Char rr, Char ww, Char xx,
2362 UInt dev, UInt ino, ULong foffset, const UChar* filename )
sewardj45b672d2003-07-25 19:58:11 +00002363{
nethercote71980f02004-01-24 18:18:54 +00002364 UInt prot = 0;
2365 UInt flags;
2366 Bool is_stack_segment;
2367 Addr r_esp;
sewardj45b672d2003-07-25 19:58:11 +00002368
nethercote71980f02004-01-24 18:18:54 +00002369 is_stack_segment
2370 = (start == VG_(clstk_base) && (start+size) == VG_(clstk_end));
fitzhardinge98abfc72003-12-16 02:05:15 +00002371
nethercote71980f02004-01-24 18:18:54 +00002372 if (rr == 'r') prot |= VKI_PROT_READ;
2373 if (ww == 'w') prot |= VKI_PROT_WRITE;
2374 if (xx == 'x') prot |= VKI_PROT_EXEC;
fitzhardinge98abfc72003-12-16 02:05:15 +00002375
nethercote71980f02004-01-24 18:18:54 +00002376 if (is_stack_segment)
2377 flags = SF_STACK | SF_GROWDOWN;
2378 else
2379 flags = SF_EXEC|SF_MMAP;
fitzhardinge98abfc72003-12-16 02:05:15 +00002380
nethercote71980f02004-01-24 18:18:54 +00002381 if (filename != NULL)
2382 flags |= SF_FILE;
fitzhardinge98abfc72003-12-16 02:05:15 +00002383
nethercote820bd8c2004-09-07 23:04:49 +00002384 if (start >= VG_(valgrind_base) && (start+size-1) <= VG_(valgrind_last))
nethercote71980f02004-01-24 18:18:54 +00002385 flags |= SF_VALGRIND;
fitzhardinge98abfc72003-12-16 02:05:15 +00002386
nethercote71980f02004-01-24 18:18:54 +00002387 VG_(map_file_segment)(start, size, prot, flags, dev, ino, foffset, filename);
fitzhardinge98abfc72003-12-16 02:05:15 +00002388
nethercote71980f02004-01-24 18:18:54 +00002389 if (VG_(is_client_addr)(start) && VG_(is_client_addr)(start+size-1))
2390 VG_TRACK( new_mem_startup, start, size, rr=='r', ww=='w', xx=='x' );
sewardj3e1eb1f2002-05-18 13:14:17 +00002391
nethercote71980f02004-01-24 18:18:54 +00002392 /* If this is the stack segment mark all below %esp as noaccess. */
2393 r_esp = esp_at_startup___global_arg;
2394 vg_assert(0 != r_esp);
2395 if (is_stack_segment) {
2396 if (0)
2397 VG_(message)(Vg_DebugMsg, "invalidating stack area: %x .. %x",
2398 start,r_esp);
2399 VG_TRACK( die_mem_stack, start, r_esp-start );
sewardjde4a1d02002-03-22 01:27:54 +00002400 }
sewardjde4a1d02002-03-22 01:27:54 +00002401}
2402
2403
nethercote71980f02004-01-24 18:18:54 +00002404/*====================================================================*/
2405/*=== Sanity check machinery (permanently engaged) ===*/
2406/*====================================================================*/
njn25e49d8e72002-09-23 09:36:25 +00002407
2408/* A fast sanity check -- suitable for calling circa once per
2409 millisecond. */
2410
nethercote885dd912004-08-03 23:14:00 +00002411void VG_(sanity_check_general) ( Bool force_expensive )
njn25e49d8e72002-09-23 09:36:25 +00002412{
njn37cea302002-09-30 11:24:00 +00002413 VGP_PUSHCC(VgpCoreCheapSanity);
2414
nethercote27fec902004-06-16 21:26:32 +00002415 if (VG_(clo_sanity_level) < 1) return;
njn25e49d8e72002-09-23 09:36:25 +00002416
2417 /* --- First do all the tests that we can do quickly. ---*/
2418
nethercote297effd2004-08-02 15:07:57 +00002419 sanity_fast_count++;
njn25e49d8e72002-09-23 09:36:25 +00002420
njn25e49d8e72002-09-23 09:36:25 +00002421 /* Check stuff pertaining to the memory check system. */
2422
2423 /* Check that nobody has spuriously claimed that the first or
2424 last 16 pages of memory have become accessible [...] */
njn37cea302002-09-30 11:24:00 +00002425 if (VG_(needs).sanity_checks) {
2426 VGP_PUSHCC(VgpSkinCheapSanity);
njn25e49d8e72002-09-23 09:36:25 +00002427 vg_assert(SK_(cheap_sanity_check)());
njn37cea302002-09-30 11:24:00 +00002428 VGP_POPCC(VgpSkinCheapSanity);
2429 }
njn25e49d8e72002-09-23 09:36:25 +00002430
2431 /* --- Now some more expensive checks. ---*/
2432
2433 /* Once every 25 times, check some more expensive stuff. */
2434 if ( force_expensive
nethercote27fec902004-06-16 21:26:32 +00002435 || VG_(clo_sanity_level) > 1
nethercote297effd2004-08-02 15:07:57 +00002436 || (VG_(clo_sanity_level) == 1 && (sanity_fast_count % 25) == 0)) {
njn25e49d8e72002-09-23 09:36:25 +00002437
njn37cea302002-09-30 11:24:00 +00002438 VGP_PUSHCC(VgpCoreExpensiveSanity);
nethercote297effd2004-08-02 15:07:57 +00002439 sanity_slow_count++;
njn25e49d8e72002-09-23 09:36:25 +00002440
nethercote885dd912004-08-03 23:14:00 +00002441 VG_(sanity_check_proxy)();
jsgf855d93d2003-10-13 22:26:55 +00002442
njn25e49d8e72002-09-23 09:36:25 +00002443# if 0
2444 { void zzzmemscan(void); zzzmemscan(); }
2445# endif
2446
nethercote297effd2004-08-02 15:07:57 +00002447 if ((sanity_fast_count % 250) == 0)
nethercote92e7b7f2004-08-07 17:52:25 +00002448 VG_(sanity_check_tt_tc)();
njn25e49d8e72002-09-23 09:36:25 +00002449
2450 if (VG_(needs).sanity_checks) {
njn37cea302002-09-30 11:24:00 +00002451 VGP_PUSHCC(VgpSkinExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002452 vg_assert(SK_(expensive_sanity_check)());
njn37cea302002-09-30 11:24:00 +00002453 VGP_POPCC(VgpSkinExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002454 }
2455 /*
nethercote297effd2004-08-02 15:07:57 +00002456 if ((sanity_fast_count % 500) == 0) VG_(mallocSanityCheckAll)();
njn25e49d8e72002-09-23 09:36:25 +00002457 */
njn37cea302002-09-30 11:24:00 +00002458 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002459 }
2460
nethercote27fec902004-06-16 21:26:32 +00002461 if (VG_(clo_sanity_level) > 1) {
njn37cea302002-09-30 11:24:00 +00002462 VGP_PUSHCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002463 /* Check sanity of the low-level memory manager. Note that bugs
2464 in the client's code can cause this to fail, so we don't do
2465 this check unless specially asked for. And because it's
2466 potentially very expensive. */
nethercote885dd912004-08-03 23:14:00 +00002467 VG_(sanity_check_malloc_all)();
njn37cea302002-09-30 11:24:00 +00002468 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002469 }
njn37cea302002-09-30 11:24:00 +00002470 VGP_POPCC(VgpCoreCheapSanity);
njn25e49d8e72002-09-23 09:36:25 +00002471}
nethercote71980f02004-01-24 18:18:54 +00002472
2473
2474/*====================================================================*/
2475/*=== main() ===*/
2476/*====================================================================*/
2477
nethercotec314eba2004-07-15 12:59:41 +00002478/*
2479 This code decides on the layout of the client and Valgrind address
nethercote996901a2004-08-03 13:29:09 +00002480 spaces, loads valgrind.so and the tool.so into the valgrind part,
nethercotec314eba2004-07-15 12:59:41 +00002481 loads the client executable (and the dynamic linker, if necessary)
2482 into the client part, and calls into Valgrind proper.
2483
2484 The code is careful not to allow spurious mappings to appear in the
2485 wrong parts of the address space. In particular, to make sure
2486 dlopen puts things in the right place, it will pad out the forbidden
2487 chunks of address space so that dlopen is forced to put things where
2488 we want them.
2489
2490 The memory map it creates is:
2491
2492 CLIENT_BASE +-------------------------+
2493 | client address space |
2494 : :
2495 : :
2496 | client stack |
2497 client_end +-------------------------+
2498 | redzone |
2499 shadow_base +-------------------------+
2500 | |
nethercote996901a2004-08-03 13:29:09 +00002501 : shadow memory for tools :
nethercotec314eba2004-07-15 12:59:41 +00002502 | (may be 0 sized) |
2503 shadow_end +-------------------------+
nethercotec314eba2004-07-15 12:59:41 +00002504 valgrind_base +-------------------------+
2505 | kickstart executable |
2506 | valgrind heap vvvvvvvvv| (barely used)
2507 - -
2508 | valgrind .so files |
2509 | and mappings |
2510 - -
2511 | valgrind stack ^^^^^^^^^|
nethercote820bd8c2004-09-07 23:04:49 +00002512 valgrind_last +-------------------------+
nethercotec314eba2004-07-15 12:59:41 +00002513 : kernel :
2514
2515 Nb: Before we can do general allocations with VG_(arena_malloc)() and
2516 VG_(mmap)(), we need to build the segment skip-list, so we know where
2517 we can put things. However, building that structure requires
2518 allocating memory. So we need to a bootstrapping process. It's done
2519 by making VG_(arena_malloc)() have a special static superblock that's
2520 used for the first 1MB's worth of allocations. This is enough to
2521 build the segment skip-list.
2522*/
2523
nethercote31779c72004-07-30 21:50:15 +00002524static int prmap(char *start, char *end, const char *perm, off_t off,
2525 int maj, int min, int ino, void* dummy) {
thughes4ad52d02004-06-27 17:37:21 +00002526 printf("mapping %10p-%10p %s %02x:%02x %d\n",
2527 start, end, perm, maj, min, ino);
2528 return True;
2529}
2530
nethercote71980f02004-01-24 18:18:54 +00002531int main(int argc, char **argv)
2532{
2533 char **cl_argv;
2534 const char *tool = NULL;
2535 const char *exec = NULL;
2536 char *preload; /* tool-specific LD_PRELOAD .so */
2537 char **env;
nethercote6c999f22004-01-31 22:55:15 +00002538 Int need_help = 0; // 0 = no, 1 = --help, 2 = --help-debug
nethercote71980f02004-01-24 18:18:54 +00002539 struct exeinfo info;
2540 ToolInfo *toolinfo = NULL;
2541 void *tool_dlhandle;
2542 Addr client_eip;
2543 Addr esp_at_startup; /* client's %esp at the point we gained control. */
2544 UInt * client_auxv;
2545 VgSchedReturnCode src;
nethercote47dd12c2004-06-22 14:18:42 +00002546 Int exitcode = 0;
nethercote238a3c32004-08-09 13:13:31 +00002547 Int fatal_sigNo = -1;
fitzhardingeb50068f2004-02-24 23:42:55 +00002548 vki_rlimit zero = { 0, 0 };
nethercote31779c72004-07-30 21:50:15 +00002549 Int padfile;
nethercote759dda32004-08-07 18:16:56 +00002550 ThreadId last_run_tid = 0; // Last thread the scheduler ran.
2551
nethercote71980f02004-01-24 18:18:54 +00002552
2553 //============================================================
2554 // Nb: startup is complex. Prerequisites are shown at every step.
2555 //
2556 // *** Be very careful when messing with the order ***
2557 //============================================================
2558
nethercotef4928da2004-06-15 10:54:40 +00002559 //============================================================
2560 // Command line argument handling order:
2561 // * If --help/--help-debug are present, show usage message
2562 // (if --tool is also present, that includes the tool-specific usage)
2563 // * Then, if --tool is missing, abort with error msg
2564 // * Then, if client is missing, abort with error msg
2565 // * Then, if any cmdline args are bad, abort with error msg
2566 //============================================================
2567
fitzhardingeb50068f2004-02-24 23:42:55 +00002568 // Get the current process datasize rlimit, and set it to zero.
2569 // This prevents any internal uses of brk() from having any effect.
2570 // We remember the old value so we can restore it on exec, so that
2571 // child processes will have a reasonable brk value.
2572 VG_(getrlimit)(VKI_RLIMIT_DATA, &VG_(client_rlimit_data));
2573 zero.rlim_max = VG_(client_rlimit_data).rlim_max;
2574 VG_(setrlimit)(VKI_RLIMIT_DATA, &zero);
thughesc37184f2004-09-11 14:16:57 +00002575
2576 // Get the current process stack rlimit.
2577 VG_(getrlimit)(VKI_RLIMIT_STACK, &VG_(client_rlimit_stack));
2578
nethercote71980f02004-01-24 18:18:54 +00002579 //--------------------------------------------------------------
2580 // Check we were launched by stage1
nethercotec314eba2004-07-15 12:59:41 +00002581 // p: n/a
nethercote71980f02004-01-24 18:18:54 +00002582 //--------------------------------------------------------------
nethercote31779c72004-07-30 21:50:15 +00002583 padfile = scan_auxv();
nethercote71980f02004-01-24 18:18:54 +00002584
2585 if (0) {
nethercote71980f02004-01-24 18:18:54 +00002586 printf("========== main() ==========\n");
nethercote31779c72004-07-30 21:50:15 +00002587 foreach_map(prmap, /*dummy*/NULL);
nethercote71980f02004-01-24 18:18:54 +00002588 }
2589
2590 //--------------------------------------------------------------
2591 // Look for alternative libdir
2592 // p: n/a
2593 //--------------------------------------------------------------
2594 { char *cp = getenv(VALGRINDLIB);
2595 if (cp != NULL)
2596 VG_(libdir) = cp;
2597 }
2598
2599 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002600 // Get valgrind args + client args (inc. from VALGRIND_OPTS/.valgrindrc).
2601 // Pre-process the command line.
2602 // p: n/a
2603 //--------------------------------------------------------------
nethercotef6a1d502004-08-09 12:21:57 +00002604 get_command_line(argc, argv, &vg_argc, &vg_argv, &cl_argv);
nethercote71980f02004-01-24 18:18:54 +00002605 pre_process_cmd_line_options(&need_help, &tool, &exec);
2606
2607 //==============================================================
2608 // Nb: once a tool is specified, the tool.so must be loaded even if
2609 // they specified --help or didn't specify a client program.
2610 //==============================================================
2611
2612 //--------------------------------------------------------------
2613 // With client padded out, map in tool
nethercote71980f02004-01-24 18:18:54 +00002614 // p: set-libdir [for VG_(libdir)]
2615 // p: pre_process_cmd_line_options() [for 'tool']
2616 //--------------------------------------------------------------
2617 load_tool(tool, &tool_dlhandle, &toolinfo, &preload);
2618
2619 //==============================================================
2620 // Can use VG_(malloc)() and VG_(arena_malloc)() only after load_tool()
nethercotec314eba2004-07-15 12:59:41 +00002621 // -- redzone size is now set. This is checked by vg_malloc2.c.
nethercote71980f02004-01-24 18:18:54 +00002622 //==============================================================
2623
2624 //--------------------------------------------------------------
2625 // Finalise address space layout
nethercote31779c72004-07-30 21:50:15 +00002626 // p: load_tool() [for 'toolinfo']
nethercote71980f02004-01-24 18:18:54 +00002627 //--------------------------------------------------------------
nethercote31779c72004-07-30 21:50:15 +00002628 layout_remaining_space( (Addr) & argc, toolinfo->shadow_ratio );
nethercote71980f02004-01-24 18:18:54 +00002629
2630 //--------------------------------------------------------------
2631 // Load client executable, finding in $PATH if necessary
nethercote71980f02004-01-24 18:18:54 +00002632 // p: pre_process_cmd_line_options() [for 'exec', 'need_help']
2633 // p: layout_remaining_space [so there's space]
2634 //--------------------------------------------------------------
nethercotef4928da2004-06-15 10:54:40 +00002635 load_client(cl_argv, exec, need_help, &info, &client_eip);
nethercote71980f02004-01-24 18:18:54 +00002636
2637 //--------------------------------------------------------------
nethercote969ecf12004-10-13 17:29:01 +00002638 // Everything in place, remove padding done by stage1
nethercote71980f02004-01-24 18:18:54 +00002639 // p: layout_remaining_space() [everything must be mapped in before now]
2640 // p: load_client() [ditto]
2641 //--------------------------------------------------------------
nethercote31779c72004-07-30 21:50:15 +00002642 as_unpad((void *)VG_(shadow_end), (void *)~0, padfile);
2643 as_closepadfile(padfile); // no more padding
nethercote71980f02004-01-24 18:18:54 +00002644
2645 //--------------------------------------------------------------
2646 // Set up client's environment
2647 // p: set-libdir [for VG_(libdir)]
2648 // p: load_tool() [for 'preload']
2649 //--------------------------------------------------------------
2650 env = fix_environment(environ, preload);
2651
2652 //--------------------------------------------------------------
nethercote5ee67ca2004-06-22 14:00:09 +00002653 // Setup client stack, eip, and VG_(client_arg[cv])
nethercote71980f02004-01-24 18:18:54 +00002654 // p: load_client() [for 'info']
2655 // p: fix_environment() [for 'env']
2656 //--------------------------------------------------------------
2657 esp_at_startup = setup_client_stack(cl_argv, env, &info, &client_auxv);
2658
2659 if (0)
nethercote6a27d832004-09-07 10:17:02 +00002660 printf("entry=%p client esp=%p vg_argc=%d brkbase=%p\n",
2661 (void*)client_eip, (void*)esp_at_startup, vg_argc,
2662 (void*)VG_(brk_base));
nethercote71980f02004-01-24 18:18:54 +00002663
2664 //==============================================================
2665 // Finished setting up operating environment. Now initialise
2666 // Valgrind. (This is where the old VG_(main)() started.)
2667 //==============================================================
2668
2669 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002670 // atfork
2671 // p: n/a
2672 //--------------------------------------------------------------
2673 VG_(atfork)(NULL, NULL, newpid);
2674 newpid(VG_INVALID_THREADID);
2675
2676 //--------------------------------------------------------------
2677 // setup file descriptors
2678 // p: n/a
2679 //--------------------------------------------------------------
2680 setup_file_descriptors();
2681
2682 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002683 // Read /proc/self/maps into a buffer
2684 // p: all memory layout, environment setup [so memory maps are right]
2685 //--------------------------------------------------------------
2686 VG_(read_procselfmaps)();
2687
2688 //--------------------------------------------------------------
2689 // Build segment map (Valgrind segments only)
2690 // p: read proc/self/maps
2691 // p: sk_pre_clo_init() [to setup new_mem_startup tracker]
2692 //--------------------------------------------------------------
2693 VG_(parse_procselfmaps) ( build_valgrind_map_callback );
2694
2695 //==============================================================
2696 // Can use VG_(arena_malloc)() with non-CORE arena after segments set up
2697 //==============================================================
2698
2699 //--------------------------------------------------------------
2700 // Init tool: pre_clo_init, process cmd line, post_clo_init
2701 // p: setup_client_stack() [for 'VG_(client_arg[cv]']
2702 // p: load_tool() [for 'tool']
2703 // p: setup_file_descriptors() [for 'VG_(fd_xxx_limit)']
2704 // p: parse_procselfmaps [so VG segments are setup so tool can
2705 // call VG_(malloc)]
nethercote71980f02004-01-24 18:18:54 +00002706 //--------------------------------------------------------------
2707 (*toolinfo->sk_pre_clo_init)();
2708 VG_(tool_init_dlsym)(tool_dlhandle);
2709 VG_(sanity_check_needs)();
2710
nethercotef4928da2004-06-15 10:54:40 +00002711 // If --tool and --help/--help-debug was given, now give the core+tool
2712 // help message
nethercotef4928da2004-06-15 10:54:40 +00002713 if (need_help) {
2714 usage(/*--help-debug?*/2 == need_help);
2715 }
nethercotec314eba2004-07-15 12:59:41 +00002716 process_cmd_line_options(client_auxv, tool);
2717
2718 SK_(post_clo_init)();
nethercotef4928da2004-06-15 10:54:40 +00002719
2720 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002721 // Build segment map (all segments)
2722 // p: setup_client_stack() [for 'esp_at_startup']
2723 // p: init tool [for 'new_mem_startup']
nethercote71980f02004-01-24 18:18:54 +00002724 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002725 esp_at_startup___global_arg = esp_at_startup;
2726 VG_(parse_procselfmaps) ( build_segment_map_callback ); /* everything */
2727 esp_at_startup___global_arg = 0;
2728
2729 //--------------------------------------------------------------
nethercotef84f6952004-07-15 14:58:33 +00002730 // Protect client trampoline page (which is also sysinfo stuff)
2731 // p: segment stuff [otherwise get seg faults...]
nethercotec314eba2004-07-15 12:59:41 +00002732 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002733 VG_(mprotect)( (void *)VG_(client_trampoline_code),
2734 VG_(trampoline_code_length), VKI_PROT_READ|VKI_PROT_EXEC );
2735
2736 //==============================================================
2737 // Can use VG_(map)() after segments set up
2738 //==============================================================
nethercote71980f02004-01-24 18:18:54 +00002739
2740 //--------------------------------------------------------------
2741 // Allow GDB attach
2742 // p: process_cmd_line_options() [for VG_(clo_wait_for_gdb)]
2743 //--------------------------------------------------------------
2744 /* Hook to delay things long enough so we can get the pid and
2745 attach GDB in another shell. */
2746 if (VG_(clo_wait_for_gdb)) {
2747 VG_(printf)("pid=%d\n", VG_(getpid)());
2748 /* do "jump *$eip" to skip this in gdb */
2749 VG_(do_syscall)(__NR_pause);
2750 }
2751
2752 //--------------------------------------------------------------
nethercote1d447092004-02-01 17:29:59 +00002753 // Set up baseBlock
nethercote71980f02004-01-24 18:18:54 +00002754 // p: {pre,post}_clo_init() [for tool helper registration]
2755 // load_client() [for 'client_eip']
2756 // setup_client_stack() [for 'esp_at_startup']
2757 //--------------------------------------------------------------
2758 init_baseBlock(client_eip, esp_at_startup);
2759
2760 //--------------------------------------------------------------
2761 // Search for file descriptors that are inherited from our parent
2762 // p: process_cmd_line_options [for VG_(clo_track_fds)]
2763 //--------------------------------------------------------------
2764 if (VG_(clo_track_fds))
2765 VG_(init_preopened_fds)();
2766
2767 //--------------------------------------------------------------
2768 // Initialise the scheduler
2769 // p: init_baseBlock() [baseBlock regs copied into VG_(threads)[1]]
2770 // p: setup_file_descriptors() [else VG_(safe_fd)() breaks]
2771 //--------------------------------------------------------------
2772 VG_(scheduler_init)();
2773
2774 //--------------------------------------------------------------
2775 // Set up the ProxyLWP machinery
2776 // p: VG_(scheduler_init)()? [XXX: subtle dependency?]
nethercote71980f02004-01-24 18:18:54 +00002777 //--------------------------------------------------------------
2778 VG_(proxy_init)();
2779
2780 //--------------------------------------------------------------
2781 // Initialise the signal handling subsystem
2782 // p: VG_(atfork)(NULL, NULL, newpid) [else problems with sigmasks]
2783 // p: VG_(proxy_init)() [else breaks...]
2784 //--------------------------------------------------------------
2785 // Nb: temporarily parks the saved blocking-mask in saved_sigmask.
2786 VG_(sigstartup_actions)();
2787
2788 //--------------------------------------------------------------
2789 // Perhaps we're profiling Valgrind?
2790 // p: process_cmd_line_options() [for VG_(clo_profile)]
2791 // p: others?
2792 //
2793 // XXX: this seems to be broken? It always says the tool wasn't built
2794 // for profiling; vg_profile.c's functions don't seem to be overriding
2795 // vg_dummy_profile.c's?
2796 //
2797 // XXX: want this as early as possible. Looking for --profile
2798 // in pre_process_cmd_line_options() could get it earlier.
2799 //--------------------------------------------------------------
2800 if (VG_(clo_profile))
2801 VGP_(init_profiling)();
2802
2803 VGP_PUSHCC(VgpStartup);
2804
2805 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002806 // Read suppression file
2807 // p: process_cmd_line_options() [for VG_(clo_suppressions)]
2808 //--------------------------------------------------------------
2809 if (VG_(needs).core_errors || VG_(needs).skin_errors)
2810 VG_(load_suppressions)();
2811
2812 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002813 // Initialise translation table and translation cache
2814 // p: read_procselfmaps [so the anonymous mmaps for the TT/TC
2815 // aren't identified as part of the client, which would waste
2816 // > 20M of virtual address space.]
2817 //--------------------------------------------------------------
2818 VG_(init_tt_tc)();
2819
2820 //--------------------------------------------------------------
2821 // Read debug info to find glibc entry points to intercept
2822 // p: parse_procselfmaps? [XXX for debug info?]
2823 // p: init_tt_tc? [XXX ???]
2824 //--------------------------------------------------------------
2825 VG_(setup_code_redirect_table)();
2826
2827 //--------------------------------------------------------------
2828 // Verbosity message
2829 // p: end_rdtsc_calibration [so startup message is printed first]
2830 //--------------------------------------------------------------
2831 if (VG_(clo_verbosity) == 1)
2832 VG_(message)(Vg_UserMsg, "For more details, rerun with: -v");
2833 if (VG_(clo_verbosity) > 0)
2834 VG_(message)(Vg_UserMsg, "");
2835
2836 //--------------------------------------------------------------
2837 // Setup pointercheck
2838 // p: process_cmd_line_options() [for VG_(clo_pointercheck)]
2839 //--------------------------------------------------------------
nethercote775508a2004-09-07 22:38:23 +00002840 if (VG_(clo_pointercheck))
2841 VG_(clo_pointercheck) = VGA_(setup_pointercheck)();
nethercote71980f02004-01-24 18:18:54 +00002842
nethercote71980f02004-01-24 18:18:54 +00002843 //--------------------------------------------------------------
2844 // Run!
2845 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002846 VGP_POPCC(VgpStartup);
2847 VGP_PUSHCC(VgpSched);
2848
nethercote238a3c32004-08-09 13:13:31 +00002849 src = VG_(scheduler)( &exitcode, &last_run_tid, &fatal_sigNo );
nethercote71980f02004-01-24 18:18:54 +00002850
nethercote238a3c32004-08-09 13:13:31 +00002851 VGP_POPCC(VgpSched);
nethercote71980f02004-01-24 18:18:54 +00002852
2853
2854 //--------------------------------------------------------------
2855 // Finalisation: cleanup, messages, etc. Order no so important, only
2856 // affects what order the messages come.
2857 //--------------------------------------------------------------
2858 if (VG_(clo_verbosity) > 0)
2859 VG_(message)(Vg_UserMsg, "");
2860
2861 if (src == VgSrc_Deadlock) {
2862 VG_(message)(Vg_UserMsg,
2863 "Warning: pthread scheduler exited due to deadlock");
2864 }
2865
2866 /* Print out file descriptor summary and stats. */
2867 if (VG_(clo_track_fds))
nethercote3a42fb82004-08-03 18:08:50 +00002868 VG_(show_open_fds)();
nethercote71980f02004-01-24 18:18:54 +00002869
2870 if (VG_(needs).core_errors || VG_(needs).skin_errors)
2871 VG_(show_all_errors)();
2872
nethercote47dd12c2004-06-22 14:18:42 +00002873 SK_(fini)( exitcode );
nethercote71980f02004-01-24 18:18:54 +00002874
nethercote885dd912004-08-03 23:14:00 +00002875 VG_(sanity_check_general)( True /*include expensive checks*/ );
nethercote71980f02004-01-24 18:18:54 +00002876
2877 if (VG_(clo_verbosity) > 1)
nethercote3a42fb82004-08-03 18:08:50 +00002878 print_all_stats();
nethercote71980f02004-01-24 18:18:54 +00002879
nethercote71980f02004-01-24 18:18:54 +00002880 if (VG_(clo_profile))
2881 VGP_(done_profiling)();
2882
nethercote71980f02004-01-24 18:18:54 +00002883 /* We're exiting, so nuke all the threads and clean up the proxy LWPs */
2884 vg_assert(src == VgSrc_FatalSig ||
nethercote759dda32004-08-07 18:16:56 +00002885 VG_(threads)[last_run_tid].status == VgTs_Runnable ||
2886 VG_(threads)[last_run_tid].status == VgTs_WaitJoiner);
nethercote71980f02004-01-24 18:18:54 +00002887 VG_(nuke_all_threads_except)(VG_INVALID_THREADID);
2888
2889 //--------------------------------------------------------------
2890 // Exit, according to the scheduler's return code
2891 //--------------------------------------------------------------
2892 switch (src) {
2893 case VgSrc_ExitSyscall: /* the normal way out */
nethercote759dda32004-08-07 18:16:56 +00002894 vg_assert(last_run_tid > 0 && last_run_tid < VG_N_THREADS);
nethercote71980f02004-01-24 18:18:54 +00002895 VG_(proxy_shutdown)();
2896
2897 /* The thread's %EBX at the time it did __NR_exit() will hold
2898 the arg to __NR_exit(), so we just do __NR_exit() with
2899 that arg. */
nethercote47dd12c2004-06-22 14:18:42 +00002900 VG_(exit)( exitcode );
nethercote71980f02004-01-24 18:18:54 +00002901 /* NOT ALIVE HERE! */
2902 VG_(core_panic)("entered the afterlife in main() -- ExitSyscall");
2903 break; /* what the hell :) */
2904
2905 case VgSrc_Deadlock:
2906 /* Just exit now. No point in continuing. */
2907 VG_(proxy_shutdown)();
2908 VG_(exit)(0);
2909 VG_(core_panic)("entered the afterlife in main() -- Deadlock");
2910 break;
2911
nethercote71980f02004-01-24 18:18:54 +00002912 case VgSrc_FatalSig:
2913 /* We were killed by a fatal signal, so replicate the effect */
nethercote238a3c32004-08-09 13:13:31 +00002914 vg_assert(fatal_sigNo != -1);
2915 VG_(kill_self)(fatal_sigNo);
nethercote71980f02004-01-24 18:18:54 +00002916 VG_(core_panic)("main(): signal was supposed to be fatal");
2917 break;
2918
2919 default:
2920 VG_(core_panic)("main(): unexpected scheduler return code");
2921 }
2922
2923 abort();
2924}
2925
2926
sewardjde4a1d02002-03-22 01:27:54 +00002927/*--------------------------------------------------------------------*/
2928/*--- end vg_main.c ---*/
2929/*--------------------------------------------------------------------*/