blob: 0bfa60b5346b80772dba047d26526de928f250e3 [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,
461 "valgrind: Couldn't allocate address space for shadow memory\n"
462 "valgrind: Are you using a kernel with a small user address space,\n"
463 "valgrind: or do you have your virtual memory size limited?\n");
464 exit(1);
465 }
nethercotee567e702004-07-10 17:49:17 +0000466 }
nethercote71980f02004-01-24 18:18:54 +0000467}
468
469/*====================================================================*/
470/*=== Command line setup ===*/
471/*====================================================================*/
472
473/* Nb: malloc'd memory never freed -- kept throughout like argv, envp */
474static char* get_file_clo(char* dir)
475{
476# define FLEN 512
477 Int fd, n;
478 struct stat s1;
479 char* f_clo = NULL;
480 char filename[FLEN];
481
482 snprintf(filename, FLEN, "%s/.valgrindrc", ( NULL == dir ? "" : dir ) );
483 fd = VG_(open)(filename, 0, VKI_S_IRUSR);
484 if ( fd > 0 ) {
485 if ( 0 == fstat(fd, &s1) ) {
486 f_clo = malloc(s1.st_size+1);
487 vg_assert(f_clo);
488 n = read(fd, f_clo, s1.st_size);
489 if (n == -1) n = 0;
490 f_clo[n] = '\0';
491 }
492 close(fd);
493 }
494 return f_clo;
495# undef FLEN
496}
497
nethercotee2097312004-06-27 12:29:56 +0000498#define ISSPACE(cc) ((cc) == ' ' || (cc) == '\t' || (cc) == '\n')
499
nethercote71980f02004-01-24 18:18:54 +0000500static Int count_args(char* s)
501{
502 Int n = 0;
503 if (s) {
504 char* cp = s;
505 while (True) {
506 // We have alternating sequences: blanks, non-blanks, blanks...
507 // count the non-blanks sequences.
508 while ( ISSPACE(*cp) ) cp++;
509 if ( !*cp ) break;
510 n++;
511 while ( !ISSPACE(*cp) && *cp ) cp++;
512 }
513 }
514 return n;
515}
516
517/* add args out of environment, skipping multiple spaces and -- args */
518static char** copy_args( char* s, char** to )
519{
520 if (s) {
521 char* cp = s;
522 while (True) {
523 // We have alternating sequences: blanks, non-blanks, blanks...
524 // copy the non-blanks sequences, and add terminating '\0'
525 while ( ISSPACE(*cp) ) cp++;
526 if ( !*cp ) break;
527 *to++ = cp;
528 while ( !ISSPACE(*cp) && *cp ) cp++;
529 if ( *cp ) *cp++ = '\0'; // terminate if necessary
530 if (VG_STREQ(to[-1], "--")) to--; // undo any '--' arg
531 }
532 }
533 return to;
534}
535
nethercotee2097312004-06-27 12:29:56 +0000536#undef ISSPACE
537
nethercote71980f02004-01-24 18:18:54 +0000538// Augment command line with arguments from environment and .valgrindrc
539// files.
540static void augment_command_line(Int* vg_argc_inout, char*** vg_argv_inout)
541{
nethercotef6a1d502004-08-09 12:21:57 +0000542 int vg_argc0 = *vg_argc_inout;
543 char** vg_argv0 = *vg_argv_inout;
nethercote71980f02004-01-24 18:18:54 +0000544
545 char* env_clo = getenv(VALGRINDOPTS);
546 char* f1_clo = get_file_clo( getenv("HOME") );
547 char* f2_clo = get_file_clo(".");
548
549 /* copy any extra args from file or environment, if present */
550 if ( (env_clo && *env_clo) || (f1_clo && *f1_clo) || (f2_clo && *f2_clo) ) {
551 /* ' ' separated extra options */
552 char **from;
553 char **to;
thughescaca0022004-09-13 10:20:34 +0000554 int orig_arg_count, env_arg_count, f1_arg_count, f2_arg_count;
555
556 for ( orig_arg_count = 0; vg_argv0[orig_arg_count]; orig_arg_count++ );
557
nethercote71980f02004-01-24 18:18:54 +0000558 env_arg_count = count_args(env_clo);
559 f1_arg_count = count_args(f1_clo);
560 f2_arg_count = count_args(f2_clo);
561
562 if (0)
563 printf("extra-argc=%d %d %d\n",
564 env_arg_count, f1_arg_count, f2_arg_count);
565
566 /* +2: +1 for null-termination, +1 for added '--' */
nethercotef6a1d502004-08-09 12:21:57 +0000567 from = vg_argv0;
thughescaca0022004-09-13 10:20:34 +0000568 vg_argv0 = malloc( (orig_arg_count + env_arg_count + f1_arg_count
nethercote71980f02004-01-24 18:18:54 +0000569 + f2_arg_count + 2) * sizeof(char **));
nethercotef6a1d502004-08-09 12:21:57 +0000570 vg_assert(vg_argv0);
571 to = vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000572
573 /* copy argv[0] */
574 *to++ = *from++;
575
576 /* Copy extra args from env var and file, in the order: ~/.valgrindrc,
577 * $VALGRIND_OPTS, ./.valgrindrc -- more local options are put later
578 * to override less local ones. */
579 to = copy_args(f1_clo, to);
580 to = copy_args(env_clo, to);
581 to = copy_args(f2_clo, to);
582
583 /* copy original arguments, stopping at command or -- */
584 while (*from) {
585 if (**from != '-')
586 break;
587 if (VG_STREQ(*from, "--")) {
588 from++; /* skip -- */
589 break;
590 }
591 *to++ = *from++;
592 }
593
594 /* add -- */
595 *to++ = "--";
596
nethercotef6a1d502004-08-09 12:21:57 +0000597 vg_argc0 = to - vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000598
599 /* copy rest of original command line, then NULL */
600 while (*from) *to++ = *from++;
601 *to = NULL;
602 }
603
nethercotef6a1d502004-08-09 12:21:57 +0000604 *vg_argc_inout = vg_argc0;
605 *vg_argv_inout = vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000606}
607
nethercotef6a1d502004-08-09 12:21:57 +0000608#define VG_CLO_SEP '\01'
609
nethercote71980f02004-01-24 18:18:54 +0000610static void get_command_line( int argc, char** argv,
611 Int* vg_argc_out, Char*** vg_argv_out,
612 char*** cl_argv_out )
613{
nethercotef6a1d502004-08-09 12:21:57 +0000614 int vg_argc0;
615 char** vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000616 char** cl_argv;
617 char* env_clo = getenv(VALGRINDCLO);
618
619 if (env_clo != NULL && *env_clo != '\0') {
620 char *cp;
621 char **cpp;
622
nethercotef6a1d502004-08-09 12:21:57 +0000623 /* OK, VALGRINDCLO is set, which means we must be a child of another
624 Valgrind process using --trace-children, so we're getting all our
625 arguments from VALGRINDCLO, and the entire command line belongs to
626 the client (including argv[0]) */
627 vg_argc0 = 1; /* argv[0] */
nethercote71980f02004-01-24 18:18:54 +0000628 for (cp = env_clo; *cp; cp++)
nethercotef6a1d502004-08-09 12:21:57 +0000629 if (*cp == VG_CLO_SEP)
630 vg_argc0++;
nethercote71980f02004-01-24 18:18:54 +0000631
nethercotef6a1d502004-08-09 12:21:57 +0000632 vg_argv0 = malloc(sizeof(char **) * (vg_argc0 + 1));
633 vg_assert(vg_argv0);
nethercote71980f02004-01-24 18:18:54 +0000634
nethercotef6a1d502004-08-09 12:21:57 +0000635 cpp = vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000636
637 *cpp++ = "valgrind"; /* nominal argv[0] */
638 *cpp++ = env_clo;
639
nethercotef6a1d502004-08-09 12:21:57 +0000640 // Replace the VG_CLO_SEP args separator with '\0'
nethercote71980f02004-01-24 18:18:54 +0000641 for (cp = env_clo; *cp; cp++) {
nethercotef6a1d502004-08-09 12:21:57 +0000642 if (*cp == VG_CLO_SEP) {
nethercote71980f02004-01-24 18:18:54 +0000643 *cp++ = '\0'; /* chop it up in place */
644 *cpp++ = cp;
645 }
646 }
647 *cpp = NULL;
648 cl_argv = argv;
649
650 } else {
651 /* Count the arguments on the command line. */
nethercotef6a1d502004-08-09 12:21:57 +0000652 vg_argv0 = argv;
nethercote71980f02004-01-24 18:18:54 +0000653
nethercotef6a1d502004-08-09 12:21:57 +0000654 for (vg_argc0 = 1; vg_argc0 < argc; vg_argc0++) {
655 if (argv[vg_argc0][0] != '-') /* exe name */
nethercote71980f02004-01-24 18:18:54 +0000656 break;
nethercotef6a1d502004-08-09 12:21:57 +0000657 if (VG_STREQ(argv[vg_argc0], "--")) { /* dummy arg */
658 vg_argc0++;
nethercote71980f02004-01-24 18:18:54 +0000659 break;
660 }
661 }
nethercotef6a1d502004-08-09 12:21:57 +0000662 cl_argv = &argv[vg_argc0];
nethercote71980f02004-01-24 18:18:54 +0000663
664 /* Get extra args from VALGRIND_OPTS and .valgrindrc files.
nethercotef6a1d502004-08-09 12:21:57 +0000665 Note we don't do this if getting args from VALGRINDCLO, as
666 those extra args will already be present in VALGRINDCLO. */
667 augment_command_line(&vg_argc0, &vg_argv0);
nethercote71980f02004-01-24 18:18:54 +0000668 }
669
670 if (0) {
671 Int i;
nethercotef6a1d502004-08-09 12:21:57 +0000672 for (i = 0; i < vg_argc0; i++)
673 printf("vg_argv0[%d]=\"%s\"\n", i, vg_argv0[i]);
nethercote71980f02004-01-24 18:18:54 +0000674 }
675
nethercotef6a1d502004-08-09 12:21:57 +0000676 *vg_argc_out = vg_argc0;
677 *vg_argv_out = (Char**)vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000678 *cl_argv_out = cl_argv;
679}
680
681
682/*====================================================================*/
683/*=== Environment and stack setup ===*/
684/*====================================================================*/
685
686/* Scan a colon-separated list, and call a function on each element.
687 The string must be mutable, because we insert a temporary '\0', but
thughes4ad52d02004-06-27 17:37:21 +0000688 the string will end up unmodified. (*func) should return True if it
nethercote71980f02004-01-24 18:18:54 +0000689 doesn't need to see any more.
thughes4ad52d02004-06-27 17:37:21 +0000690
691 This routine will return True if (*func) returns True and False if
692 it reaches the end of the list without that happening.
nethercote71980f02004-01-24 18:18:54 +0000693*/
thughes4ad52d02004-06-27 17:37:21 +0000694static Bool scan_colsep(char *colsep, Bool (*func)(const char *))
nethercote71980f02004-01-24 18:18:54 +0000695{
696 char *cp, *entry;
697 int end;
698
699 if (colsep == NULL ||
700 *colsep == '\0')
thughes4ad52d02004-06-27 17:37:21 +0000701 return False;
nethercote71980f02004-01-24 18:18:54 +0000702
703 entry = cp = colsep;
704
705 do {
706 end = (*cp == '\0');
707
708 if (*cp == ':' || *cp == '\0') {
709 char save = *cp;
710
711 *cp = '\0';
thughes21942d92004-07-12 09:35:37 +0000712 if ((*func)(entry)) {
713 *cp = save;
thughes4ad52d02004-06-27 17:37:21 +0000714 return True;
thughes21942d92004-07-12 09:35:37 +0000715 }
nethercote71980f02004-01-24 18:18:54 +0000716 *cp = save;
717 entry = cp+1;
718 }
719 cp++;
720 } while(!end);
thughes4ad52d02004-06-27 17:37:21 +0000721
722 return False;
723}
724
725static Bool contains(const char *p) {
726 if (VG_STREQ(p, VG_(libdir))) {
727 return True;
728 }
729 return False;
nethercote71980f02004-01-24 18:18:54 +0000730}
731
732/* Prepare the client's environment. This is basically a copy of our
733 environment, except:
734 1. LD_LIBRARY_PATH=$VALGRINDLIB:$LD_LIBRARY_PATH
735 2. LD_PRELOAD=$VALGRINDLIB/vg_inject.so:($VALGRINDLIB/vgpreload_TOOL.so:)?$LD_PRELOAD
736
737 If any of these is missing, then it is added.
738
739 Yummy. String hacking in C.
740
741 If this needs to handle any more variables it should be hacked
742 into something table driven.
743 */
744static char **fix_environment(char **origenv, const char *preload)
745{
746 static const char inject_so[] = "vg_inject.so";
747 static const char ld_library_path[] = "LD_LIBRARY_PATH=";
748 static const char ld_preload[] = "LD_PRELOAD=";
749 static const char valgrind_clo[] = VALGRINDCLO "=";
750 static const int ld_library_path_len = sizeof(ld_library_path)-1;
751 static const int ld_preload_len = sizeof(ld_preload)-1;
752 static const int valgrind_clo_len = sizeof(valgrind_clo)-1;
753 int ld_preload_done = 0;
754 int ld_library_path_done = 0;
755 char *inject_path;
756 int inject_path_len;
757 int vgliblen = strlen(VG_(libdir));
758 char **cpp;
759 char **ret;
760 int envc;
761 const int preloadlen = (preload == NULL) ? 0 : strlen(preload);
762
763 /* Find the vg_inject.so; also make room for the tool preload
764 library */
765 inject_path_len = sizeof(inject_so) + vgliblen + preloadlen + 16;
766 inject_path = malloc(inject_path_len);
nethercote7c018f42004-07-17 16:40:50 +0000767 vg_assert(inject_path);
nethercote71980f02004-01-24 18:18:54 +0000768
769 if (preload)
770 snprintf(inject_path, inject_path_len, "%s/%s:%s",
771 VG_(libdir), inject_so, preload);
772 else
773 snprintf(inject_path, inject_path_len, "%s/%s",
774 VG_(libdir), inject_so);
775
776 /* Count the original size of the env */
777 envc = 0; /* trailing NULL */
778 for (cpp = origenv; cpp && *cpp; cpp++)
779 envc++;
780
781 /* Allocate a new space */
782 ret = malloc(sizeof(char *) * (envc+3+1)); /* 3 new entries + NULL */
nethercote7c018f42004-07-17 16:40:50 +0000783 vg_assert(ret);
nethercote71980f02004-01-24 18:18:54 +0000784
785 /* copy it over */
786 for (cpp = ret; *origenv; )
787 *cpp++ = *origenv++;
788 *cpp = NULL;
789
790 vg_assert(envc == (cpp - ret));
791
792 /* Walk over the new environment, mashing as we go */
793 for (cpp = ret; cpp && *cpp; cpp++) {
794 if (memcmp(*cpp, ld_library_path, ld_library_path_len) == 0) {
nethercote71980f02004-01-24 18:18:54 +0000795 /* If the LD_LIBRARY_PATH already contains libdir, then don't
796 bother adding it again, even if it isn't the first (it
797 seems that the Java runtime will keep reexecing itself
798 unless its paths are at the front of LD_LIBRARY_PATH) */
thughes4ad52d02004-06-27 17:37:21 +0000799 if (!scan_colsep(*cpp + ld_library_path_len, contains)) {
nethercote71980f02004-01-24 18:18:54 +0000800 int len = strlen(*cpp) + vgliblen*2 + 16;
801 char *cp = malloc(len);
nethercote7c018f42004-07-17 16:40:50 +0000802 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000803
804 snprintf(cp, len, "%s%s:%s",
805 ld_library_path, VG_(libdir),
806 (*cpp)+ld_library_path_len);
807
808 *cpp = cp;
809 }
810
811 ld_library_path_done = 1;
812 } else if (memcmp(*cpp, ld_preload, ld_preload_len) == 0) {
813 int len = strlen(*cpp) + inject_path_len;
814 char *cp = malloc(len);
nethercote7c018f42004-07-17 16:40:50 +0000815 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000816
817 snprintf(cp, len, "%s%s:%s",
818 ld_preload, inject_path, (*cpp)+ld_preload_len);
819
820 *cpp = cp;
821
822 ld_preload_done = 1;
823 } else if (memcmp(*cpp, valgrind_clo, valgrind_clo_len) == 0) {
824 *cpp = "";
825 }
826 }
827
828 /* Add the missing bits */
829
830 if (!ld_library_path_done) {
831 int len = ld_library_path_len + vgliblen*2 + 16;
832 char *cp = malloc(len);
nethercote7c018f42004-07-17 16:40:50 +0000833 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000834
835 snprintf(cp, len, "%s%s", ld_library_path, VG_(libdir));
836
837 ret[envc++] = cp;
838 }
839
840 if (!ld_preload_done) {
841 int len = ld_preload_len + inject_path_len;
842 char *cp = malloc(len);
nethercote7c018f42004-07-17 16:40:50 +0000843 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000844
845 snprintf(cp, len, "%s%s",
846 ld_preload, inject_path);
847
848 ret[envc++] = cp;
849 }
850
851 ret[envc] = NULL;
852
853 return ret;
854}
855
856extern char **environ; /* our environment */
857//#include <error.h>
858
859/* Add a string onto the string table, and return its address */
860static char *copy_str(char **tab, const char *str)
861{
862 char *cp = *tab;
863 char *orig = cp;
864
865 while(*str)
866 *cp++ = *str++;
867 *cp++ = '\0';
868
869 if (0)
nethercotef84f6952004-07-15 14:58:33 +0000870 printf("copied %p \"%s\" len %d\n", orig, orig, cp-orig);
nethercote71980f02004-01-24 18:18:54 +0000871
872 *tab = cp;
873
874 return orig;
875}
876
877/*
878 This sets up the client's initial stack, containing the args,
879 environment and aux vector.
880
881 The format of the stack is:
882
883 higher address +-----------------+
884 | Trampoline code |
885 +-----------------+
886 | |
887 : string table :
888 | |
889 +-----------------+
890 | AT_NULL |
891 - -
892 | auxv |
893 +-----------------+
894 | NULL |
895 - -
896 | envp |
897 +-----------------+
898 | NULL |
899 - -
900 | argv |
901 +-----------------+
902 | argc |
903 lower address +-----------------+ <- esp
904 | undefined |
905 : :
906 */
907static Addr setup_client_stack(char **orig_argv, char **orig_envp,
908 const struct exeinfo *info,
909 UInt** client_auxv)
910{
nethercotee567e702004-07-10 17:49:17 +0000911 void* res;
nethercote71980f02004-01-24 18:18:54 +0000912 char **cpp;
913 char *strtab; /* string table */
914 char *stringbase;
915 addr_t *ptr;
916 struct ume_auxv *auxv;
917 const struct ume_auxv *orig_auxv;
918 const struct ume_auxv *cauxv;
919 unsigned stringsize; /* total size of strings in bytes */
920 unsigned auxsize; /* total size of auxv in bytes */
921 int argc; /* total argc */
922 int envc; /* total number of env vars */
923 unsigned stacksize; /* total client stack size */
924 addr_t cl_esp; /* client stack base (initial esp) */
925
926 /* use our own auxv as a prototype */
927 orig_auxv = find_auxv(ume_exec_esp);
928
929 /* ==================== compute sizes ==================== */
930
931 /* first of all, work out how big the client stack will be */
932 stringsize = 0;
933
934 /* paste on the extra args if the loader needs them (ie, the #!
935 interpreter and its argument) */
936 argc = 0;
nethercoted6a56872004-07-26 15:32:47 +0000937 if (info->interp_name != NULL) {
nethercote71980f02004-01-24 18:18:54 +0000938 argc++;
nethercoted6a56872004-07-26 15:32:47 +0000939 stringsize += strlen(info->interp_name) + 1;
nethercote71980f02004-01-24 18:18:54 +0000940 }
nethercoted6a56872004-07-26 15:32:47 +0000941 if (info->interp_args != NULL) {
nethercote71980f02004-01-24 18:18:54 +0000942 argc++;
nethercoted6a56872004-07-26 15:32:47 +0000943 stringsize += strlen(info->interp_args) + 1;
nethercote71980f02004-01-24 18:18:54 +0000944 }
945
946 /* now scan the args we're given... */
947 for (cpp = orig_argv; *cpp; cpp++) {
948 argc++;
949 stringsize += strlen(*cpp) + 1;
950 }
951
952 /* ...and the environment */
953 envc = 0;
954 for (cpp = orig_envp; cpp && *cpp; cpp++) {
955 envc++;
956 stringsize += strlen(*cpp) + 1;
957 }
958
959 /* now, how big is the auxv? */
960 auxsize = sizeof(*auxv); /* there's always at least one entry: AT_NULL */
961 for (cauxv = orig_auxv; cauxv->a_type != AT_NULL; cauxv++) {
962 if (cauxv->a_type == AT_PLATFORM)
963 stringsize += strlen(cauxv->u.a_ptr) + 1;
964 auxsize += sizeof(*cauxv);
965 }
966
967 /* OK, now we know how big the client stack is */
968 stacksize =
969 sizeof(int) + /* argc */
970 sizeof(char **)*argc + /* argv */
971 sizeof(char **) + /* terminal NULL */
972 sizeof(char **)*envc + /* envp */
973 sizeof(char **) + /* terminal NULL */
974 auxsize + /* auxv */
975 ROUNDUP(stringsize, sizeof(int)) +/* strings (aligned) */
976 VKI_BYTES_PER_PAGE; /* page for trampoline code */
977
nethercotef84f6952004-07-15 14:58:33 +0000978 // decide where stack goes!
979 VG_(clstk_end) = VG_(client_end);
980
981 VG_(client_trampoline_code) = VG_(clstk_end) - VKI_BYTES_PER_PAGE;
982
nethercote71980f02004-01-24 18:18:54 +0000983 /* cl_esp is the client's stack pointer */
nethercotef84f6952004-07-15 14:58:33 +0000984 cl_esp = VG_(clstk_end) - stacksize;
nethercote71980f02004-01-24 18:18:54 +0000985 cl_esp = ROUNDDN(cl_esp, 16); /* make stack 16 byte aligned */
986
nethercote71980f02004-01-24 18:18:54 +0000987 /* base of the string table (aligned) */
988 stringbase = strtab = (char *)(VG_(client_trampoline_code) - ROUNDUP(stringsize, sizeof(int)));
989
990 VG_(clstk_base) = PGROUNDDN(cl_esp);
nethercote71980f02004-01-24 18:18:54 +0000991
nethercote5ee67ca2004-06-22 14:00:09 +0000992 if (0)
993 printf("stringsize=%d auxsize=%d stacksize=%d\n"
nethercote6a27d832004-09-07 10:17:02 +0000994 "clstk_base %p\n"
995 "clstk_end %p\n",
996 stringsize, auxsize, stacksize,
997 (void*)VG_(clstk_base), (void*)VG_(clstk_end));
nethercote5ee67ca2004-06-22 14:00:09 +0000998
999
nethercote71980f02004-01-24 18:18:54 +00001000 /* ==================== allocate space ==================== */
1001
1002 /* allocate a stack - mmap enough space for the stack */
nethercotef84f6952004-07-15 14:58:33 +00001003 res = mmap((void *)PGROUNDDN(cl_esp), VG_(clstk_end) - PGROUNDDN(cl_esp),
nethercotee567e702004-07-10 17:49:17 +00001004 PROT_READ | PROT_WRITE | PROT_EXEC,
1005 MAP_PRIVATE | MAP_ANON | MAP_FIXED, -1, 0);
1006 vg_assert((void*)-1 != res);
nethercote71980f02004-01-24 18:18:54 +00001007
1008 /* ==================== copy client stack ==================== */
1009
1010 ptr = (addr_t *)cl_esp;
1011
1012 /* --- argc --- */
1013 *ptr++ = argc; /* client argc */
1014
1015 /* --- argv --- */
nethercoted6a56872004-07-26 15:32:47 +00001016 if (info->interp_name) {
1017 *ptr++ = (addr_t)copy_str(&strtab, info->interp_name);
1018 free(info->interp_name);
nethercote71980f02004-01-24 18:18:54 +00001019 }
nethercoted6a56872004-07-26 15:32:47 +00001020 if (info->interp_args) {
1021 *ptr++ = (addr_t)copy_str(&strtab, info->interp_args);
1022 free(info->interp_args);
nethercote71980f02004-01-24 18:18:54 +00001023 }
1024 for (cpp = orig_argv; *cpp; ptr++, cpp++) {
1025 *ptr = (addr_t)copy_str(&strtab, *cpp);
1026 }
1027 *ptr++ = 0;
1028
1029 /* --- envp --- */
1030 VG_(client_envp) = (Char **)ptr;
1031 for (cpp = orig_envp; cpp && *cpp; ptr++, cpp++)
1032 *ptr = (addr_t)copy_str(&strtab, *cpp);
1033 *ptr++ = 0;
1034
1035 /* --- auxv --- */
1036 auxv = (struct ume_auxv *)ptr;
1037 *client_auxv = (UInt *)auxv;
1038
1039 for (; orig_auxv->a_type != AT_NULL; auxv++, orig_auxv++) {
1040 /* copy the entry... */
1041 *auxv = *orig_auxv;
1042
1043 /* ...and fix up the copy */
1044 switch(auxv->a_type) {
1045 case AT_PHDR:
1046 if (info->phdr == 0)
1047 auxv->a_type = AT_IGNORE;
1048 else
1049 auxv->u.a_val = info->phdr;
1050 break;
1051
1052 case AT_PHNUM:
1053 if (info->phdr == 0)
1054 auxv->a_type = AT_IGNORE;
1055 else
1056 auxv->u.a_val = info->phnum;
1057 break;
1058
1059 case AT_BASE:
1060 if (info->interp_base == 0)
1061 auxv->a_type = AT_IGNORE;
1062 else
1063 auxv->u.a_val = info->interp_base;
1064 break;
1065
1066 case AT_PLATFORM: /* points to a platform description string */
1067 auxv->u.a_ptr = copy_str(&strtab, orig_auxv->u.a_ptr);
1068 break;
1069
1070 case AT_ENTRY:
1071 auxv->u.a_val = info->entry;
1072 break;
1073
1074 case AT_IGNORE:
1075 case AT_EXECFD:
1076 case AT_PHENT:
1077 case AT_PAGESZ:
1078 case AT_FLAGS:
1079 case AT_NOTELF:
1080 case AT_UID:
1081 case AT_EUID:
1082 case AT_GID:
1083 case AT_EGID:
1084 case AT_CLKTCK:
1085 case AT_HWCAP:
1086 case AT_FPUCW:
1087 case AT_DCACHEBSIZE:
1088 case AT_ICACHEBSIZE:
1089 case AT_UCACHEBSIZE:
1090 /* All these are pointerless, so we don't need to do anything
1091 about them. */
1092 break;
1093
1094 case AT_SECURE:
1095 /* If this is 1, then it means that this program is running
1096 suid, and therefore the dynamic linker should be careful
1097 about LD_PRELOAD, etc. However, since stage1 (the thing
1098 the kernel actually execve's) should never be SUID, and we
1099 need LD_PRELOAD/LD_LIBRARY_PATH to work for the client, we
1100 set AT_SECURE to 0. */
1101 auxv->u.a_val = 0;
1102 break;
1103
1104 case AT_SYSINFO:
1105 /* Leave this unmolested for now, but we'll update it later
1106 when we set up the client trampoline code page */
1107 break;
1108
1109 case AT_SYSINFO_EHDR:
1110 /* Trash this, because we don't reproduce it */
1111 auxv->a_type = AT_IGNORE;
1112 break;
1113
1114 default:
1115 /* stomp out anything we don't know about */
1116 if (0)
1117 printf("stomping auxv entry %d\n", auxv->a_type);
1118 auxv->a_type = AT_IGNORE;
1119 break;
1120
1121 }
1122 }
1123 *auxv = *orig_auxv;
1124 vg_assert(auxv->a_type == AT_NULL);
1125
nethercotef84f6952004-07-15 14:58:33 +00001126 /* --- trampoline page --- */
1127 VG_(memcpy)( (void *)VG_(client_trampoline_code),
1128 &VG_(trampoline_code_start), VG_(trampoline_code_length) );
1129
nethercote71980f02004-01-24 18:18:54 +00001130 vg_assert((strtab-stringbase) == stringsize);
1131
nethercote5ee67ca2004-06-22 14:00:09 +00001132 /* We know the initial ESP is pointing at argc/argv */
1133 VG_(client_argc) = *(Int*)cl_esp;
1134 VG_(client_argv) = (Char**)(cl_esp + sizeof(Int));
1135
nethercote71980f02004-01-24 18:18:54 +00001136 return cl_esp;
1137}
1138
1139/*====================================================================*/
1140/*=== Find executable ===*/
1141/*====================================================================*/
1142
thughes4ad52d02004-06-27 17:37:21 +00001143static const char* executable_name;
1144
1145static Bool match_executable(const char *entry) {
1146 char buf[strlen(entry) + strlen(executable_name) + 2];
1147
1148 /* empty PATH element means . */
1149 if (*entry == '\0')
1150 entry = ".";
1151
1152 snprintf(buf, sizeof(buf), "%s/%s", entry, executable_name);
1153
1154 if (access(buf, R_OK|X_OK) == 0) {
1155 executable_name = strdup(buf);
1156 vg_assert(NULL != executable_name);
1157 return True;
1158 }
1159 return False;
1160}
1161
nethercote71980f02004-01-24 18:18:54 +00001162static const char* find_executable(const char* exec)
1163{
1164 vg_assert(NULL != exec);
thughes4ad52d02004-06-27 17:37:21 +00001165 executable_name = exec;
1166 if (strchr(executable_name, '/') == NULL) {
nethercote71980f02004-01-24 18:18:54 +00001167 /* no '/' - we need to search the path */
1168 char *path = getenv("PATH");
thughes4ad52d02004-06-27 17:37:21 +00001169 scan_colsep(path, match_executable);
nethercote71980f02004-01-24 18:18:54 +00001170 }
thughes4ad52d02004-06-27 17:37:21 +00001171 return executable_name;
nethercote71980f02004-01-24 18:18:54 +00001172}
1173
1174
1175/*====================================================================*/
1176/*=== Loading tools ===*/
1177/*====================================================================*/
1178
1179static void list_tools(void)
1180{
1181 DIR *dir = opendir(VG_(libdir));
1182 struct dirent *de;
1183 int first = 1;
1184
1185 if (dir == NULL) {
1186 fprintf(stderr, "Can't open %s: %s (installation problem?)\n",
nethercotef4928da2004-06-15 10:54:40 +00001187 VG_(libdir), strerror(errno));
nethercote71980f02004-01-24 18:18:54 +00001188 return;
1189 }
1190
nethercotef4928da2004-06-15 10:54:40 +00001191 while ((de = readdir(dir)) != NULL) {
nethercote71980f02004-01-24 18:18:54 +00001192 int len = strlen(de->d_name);
1193
1194 /* look for vgskin_TOOL.so names */
1195 if (len > (7+1+3) && /* "vgskin_" + at least 1-char toolname + ".so" */
nethercotef4928da2004-06-15 10:54:40 +00001196 strncmp(de->d_name, "vgskin_", 7) == 0 &&
1197 VG_STREQ(de->d_name + len - 3, ".so")) {
1198 if (first) {
1199 fprintf(stderr, "Available tools:\n");
1200 first = 0;
1201 }
1202 de->d_name[len-3] = '\0';
1203 fprintf(stderr, "\t%s\n", de->d_name+7);
nethercote71980f02004-01-24 18:18:54 +00001204 }
1205 }
1206
1207 closedir(dir);
1208
1209 if (first)
nethercotef4928da2004-06-15 10:54:40 +00001210 fprintf(stderr, "No tools available in \"%s\" (installation problem?)\n",
1211 VG_(libdir));
nethercote71980f02004-01-24 18:18:54 +00001212}
1213
1214
1215/* Find and load a tool, and check it looks ok. Also looks to see if there's
1216 * a matching vgpreload_*.so file, and returns its name in *preloadpath. */
1217static void load_tool( const char *toolname, void** handle_out,
1218 ToolInfo** toolinfo_out, char **preloadpath_out )
1219{
1220 Bool ok;
1221 int len = strlen(VG_(libdir)) + strlen(toolname)*2 + 16;
1222 char buf[len];
1223 void* handle;
1224 ToolInfo* toolinfo;
1225 char* preloadpath = NULL;
1226 Int* vg_malloc_redzonep;
1227
1228 // XXX: allowing full paths for --tool option -- does it make sense?
1229 // Doesn't allow for vgpreload_<tool>.so.
1230
1231 if (strchr(toolname, '/') != 0) {
1232 /* toolname contains '/', and so must be a pathname */
1233 handle = dlopen(toolname, RTLD_NOW);
1234 } else {
1235 /* just try in the libdir */
1236 snprintf(buf, len, "%s/vgskin_%s.so", VG_(libdir), toolname);
1237 handle = dlopen(buf, RTLD_NOW);
1238
1239 if (handle != NULL) {
1240 snprintf(buf, len, "%s/vgpreload_%s.so", VG_(libdir), toolname);
1241 if (access(buf, R_OK) == 0) {
1242 preloadpath = strdup(buf);
1243 vg_assert(NULL != preloadpath);
1244 }
1245 }
1246 }
1247
1248 ok = (NULL != handle);
1249 if (!ok) {
1250 fprintf(stderr, "Can't open tool \"%s\": %s\n", toolname, dlerror());
1251 goto bad_load;
1252 }
1253
1254 toolinfo = dlsym(handle, "vgSkin_tool_info");
1255 ok = (NULL != toolinfo);
1256 if (!ok) {
1257 fprintf(stderr, "Tool \"%s\" doesn't define SK_(tool_info) - "
1258 "add VG_DETERMINE_INTERFACE_VERSION?\n", toolname);
1259 goto bad_load;
1260 }
1261
1262 ok = (toolinfo->sizeof_ToolInfo == sizeof(*toolinfo) &&
1263 toolinfo->interface_major_version == VG_CORE_INTERFACE_MAJOR_VERSION &&
1264 toolinfo->sk_pre_clo_init != NULL);
1265 if (!ok) {
1266 fprintf(stderr, "Error:\n"
1267 " Tool and core interface versions do not match.\n"
1268 " Interface version used by core is: %d.%d (size %d)\n"
1269 " Interface version used by tool is: %d.%d (size %d)\n"
1270 " The major version numbers must match.\n",
1271 VG_CORE_INTERFACE_MAJOR_VERSION,
1272 VG_CORE_INTERFACE_MINOR_VERSION,
1273 sizeof(*toolinfo),
1274 toolinfo->interface_major_version,
1275 toolinfo->interface_minor_version,
1276 toolinfo->sizeof_ToolInfo);
1277 fprintf(stderr, " You need to at least recompile, and possibly update,\n");
1278 if (VG_CORE_INTERFACE_MAJOR_VERSION > toolinfo->interface_major_version)
nethercote996901a2004-08-03 13:29:09 +00001279 fprintf(stderr, " your tool to work with this version of Valgrind.\n");
nethercote71980f02004-01-24 18:18:54 +00001280 else
nethercote996901a2004-08-03 13:29:09 +00001281 fprintf(stderr, " your version of Valgrind to work with this tool.\n");
nethercote71980f02004-01-24 18:18:54 +00001282 goto bad_load;
1283 }
1284
1285 // Set redzone size for V's allocator
1286 vg_malloc_redzonep = dlsym(handle, STR(VG_(vg_malloc_redzone_szB)));
1287 if ( NULL != vg_malloc_redzonep ) {
1288 VG_(vg_malloc_redzone_szB) = *vg_malloc_redzonep;
1289 }
1290
1291 vg_assert(NULL != handle && NULL != toolinfo);
1292 *handle_out = handle;
1293 *toolinfo_out = toolinfo;
1294 *preloadpath_out = preloadpath;
1295 return;
1296
1297
1298 bad_load:
1299 if (handle != NULL)
1300 dlclose(handle);
1301
nethercotef4928da2004-06-15 10:54:40 +00001302 fprintf(stderr, "valgrind: couldn't load tool\n");
nethercote71980f02004-01-24 18:18:54 +00001303 list_tools();
1304 exit(127);
1305}
1306
nethercotef4928da2004-06-15 10:54:40 +00001307
1308/*====================================================================*/
1309/*=== Command line errors ===*/
1310/*====================================================================*/
1311
1312static void abort_msg ( void )
1313{
nethercotef8548672004-06-21 12:42:35 +00001314 VG_(clo_log_to) = VgLogTo_Fd;
1315 VG_(clo_log_fd) = 2; /* stderr */
nethercotef4928da2004-06-15 10:54:40 +00001316}
1317
1318void VG_(bad_option) ( Char* opt )
1319{
1320 abort_msg();
1321 VG_(printf)("valgrind: Bad option `%s'; aborting.\n", opt);
1322 VG_(printf)("valgrind: Use --help for more information.\n");
1323 VG_(exit)(1);
1324}
1325
1326static void missing_tool_option ( void )
1327{
1328 abort_msg();
1329 VG_(printf)("valgrind: Missing --tool option\n");
1330 list_tools();
1331 VG_(printf)("valgrind: Use --help for more information.\n");
1332 VG_(exit)(1);
1333}
1334
1335static void missing_prog ( void )
1336{
1337 abort_msg();
1338 VG_(printf)("valgrind: no program specified\n");
1339 VG_(printf)("valgrind: Use --help for more information.\n");
1340 VG_(exit)(1);
1341}
1342
1343static void config_error ( Char* msg )
1344{
1345 abort_msg();
1346 VG_(printf)("valgrind: Startup or configuration error:\n %s\n", msg);
1347 VG_(printf)("valgrind: Unable to start up properly. Giving up.\n");
1348 VG_(exit)(1);
1349}
1350
1351
nethercote71980f02004-01-24 18:18:54 +00001352/*====================================================================*/
1353/*=== Loading the client ===*/
1354/*====================================================================*/
1355
nethercotef4928da2004-06-15 10:54:40 +00001356static void load_client(char* cl_argv[], const char* exec, Int need_help,
nethercote71980f02004-01-24 18:18:54 +00001357 /*out*/struct exeinfo* info, /*out*/Addr* client_eip)
1358{
1359 // If they didn't specify an executable with --exec, and didn't specify
1360 // --help, then use client argv[0] (searching $PATH if necessary).
nethercotef4928da2004-06-15 10:54:40 +00001361 if (NULL == exec && !need_help) {
nethercote71980f02004-01-24 18:18:54 +00001362 if (cl_argv[0] == NULL ||
1363 ( NULL == (exec = find_executable(cl_argv[0])) ) )
1364 {
nethercotef4928da2004-06-15 10:54:40 +00001365 missing_prog();
nethercote71980f02004-01-24 18:18:54 +00001366 }
1367 }
1368
1369 info->map_base = VG_(client_mapbase);
nethercote71980f02004-01-24 18:18:54 +00001370 info->exe_base = VG_(client_base);
1371 info->exe_end = VG_(client_end);
1372 info->argv = cl_argv;
1373
nethercotef4928da2004-06-15 10:54:40 +00001374 if (need_help) {
nethercote71980f02004-01-24 18:18:54 +00001375 VG_(clexecfd) = -1;
nethercoteea147e72004-07-26 15:43:57 +00001376 // Set the minimal number of entries in 'info' to continue.
nethercoted6a56872004-07-26 15:32:47 +00001377 info->interp_name = NULL;
1378 info->interp_args = NULL;
nethercote71980f02004-01-24 18:18:54 +00001379 } else {
1380 Int ret;
1381 VG_(clexecfd) = VG_(open)(exec, O_RDONLY, VKI_S_IRUSR);
1382 ret = do_exec(exec, info);
1383 if (ret != 0) {
nethercoteea147e72004-07-26 15:43:57 +00001384 fprintf(stderr, "valgrind: do_exec(%s) failed: %s\n",
1385 exec, strerror(ret));
nethercote71980f02004-01-24 18:18:54 +00001386 exit(127);
1387 }
1388 }
1389
1390 /* Copy necessary bits of 'info' that were filled in */
1391 *client_eip = info->init_eip;
1392 VG_(brk_base) = VG_(brk_limit) = info->brkbase;
1393}
1394
1395
1396/*====================================================================*/
nethercotef6a1d502004-08-09 12:21:57 +00001397/*=== Command-line: variables, processing, etc ===*/
nethercote71980f02004-01-24 18:18:54 +00001398/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +00001399
njn25e49d8e72002-09-23 09:36:25 +00001400/* Define, and set defaults. */
1401Bool VG_(clo_error_limit) = True;
nethercote04d0fbc2004-01-26 16:48:06 +00001402Bool VG_(clo_db_attach) = False;
1403Char* VG_(clo_db_command) = VG_CLO_DEFAULT_DBCOMMAND;
njn43c799e2003-04-08 00:08:52 +00001404Bool VG_(clo_gen_suppressions) = False;
nethercote27fec902004-06-16 21:26:32 +00001405Int VG_(clo_sanity_level) = 1;
njn25e49d8e72002-09-23 09:36:25 +00001406Int VG_(clo_verbosity) = 1;
1407Bool VG_(clo_demangle) = True;
njn25e49d8e72002-09-23 09:36:25 +00001408Bool VG_(clo_trace_children) = False;
sewardj4cf05692002-10-27 20:28:29 +00001409
nethercotef1e5e152004-09-01 23:58:16 +00001410/* See big comment in core.h for meaning of these three.
nethercotee1730692003-11-20 10:38:07 +00001411 fd is initially stdout, for --help, but gets moved to stderr by default
1412 immediately afterwards. */
sewardj4cf05692002-10-27 20:28:29 +00001413VgLogTo VG_(clo_log_to) = VgLogTo_Fd;
nethercotef8548672004-06-21 12:42:35 +00001414Int VG_(clo_log_fd) = 1;
1415Char* VG_(clo_log_name) = NULL;
sewardj4cf05692002-10-27 20:28:29 +00001416
thughes6233a382004-08-21 11:10:44 +00001417Bool VG_(clo_time_stamp) = False;
1418
sewardj6024b212003-07-13 10:54:33 +00001419Int VG_(clo_input_fd) = 0; /* stdin */
njn25e49d8e72002-09-23 09:36:25 +00001420Int VG_(clo_n_suppressions) = 0;
sewardjde4a1d02002-03-22 01:27:54 +00001421Char* VG_(clo_suppressions)[VG_CLO_MAX_SFILES];
njn25e49d8e72002-09-23 09:36:25 +00001422Bool VG_(clo_profile) = False;
1423Bool VG_(clo_single_step) = False;
1424Bool VG_(clo_optimise) = True;
1425UChar VG_(clo_trace_codegen) = 0; // 00000000b
1426Bool VG_(clo_trace_syscalls) = False;
1427Bool VG_(clo_trace_signals) = False;
1428Bool VG_(clo_trace_symtab) = False;
njn25e49d8e72002-09-23 09:36:25 +00001429Bool VG_(clo_trace_sched) = False;
1430Int VG_(clo_trace_pthread_level) = 0;
njn25e49d8e72002-09-23 09:36:25 +00001431Int VG_(clo_dump_error) = 0;
1432Int VG_(clo_backtrace_size) = 4;
1433Char* VG_(clo_weird_hacks) = NULL;
sewardj858964b2002-10-05 14:15:43 +00001434Bool VG_(clo_run_libc_freeres) = True;
rjwalshf5f536f2003-11-17 17:45:00 +00001435Bool VG_(clo_track_fds) = False;
sewardj22854b92002-11-30 14:00:47 +00001436Bool VG_(clo_chain_bb) = True;
nethercote77eba602003-11-13 17:35:04 +00001437Bool VG_(clo_show_below_main) = False;
fitzhardinge98abfc72003-12-16 02:05:15 +00001438Bool VG_(clo_pointercheck) = True;
fitzhardinge462f4f92003-12-18 02:10:54 +00001439Bool VG_(clo_branchpred) = False;
sewardj2370f3b2002-11-30 15:01:01 +00001440
jsgf855d93d2003-10-13 22:26:55 +00001441static Bool VG_(clo_wait_for_gdb) = False;
1442
1443/* If we're doing signal routing, poll for signals every 50mS by
1444 default. */
1445Int VG_(clo_signal_polltime) = 50;
1446
1447/* These flags reduce thread wakeup latency on syscall completion and
1448 signal delivery, respectively. The downside is possible unfairness. */
1449Bool VG_(clo_lowlat_syscalls) = False; /* low-latency syscalls */
1450Bool VG_(clo_lowlat_signals) = False; /* low-latency signals */
1451
sewardjde4a1d02002-03-22 01:27:54 +00001452
nethercote6c999f22004-01-31 22:55:15 +00001453void usage ( Bool debug_help )
njn7cf0bd32002-06-08 13:36:03 +00001454{
njn25e49d8e72002-09-23 09:36:25 +00001455 Char* usage1 =
nethercote71980f02004-01-24 18:18:54 +00001456"usage: valgrind --tool=<toolname> [options] prog-and-args\n"
njn25e49d8e72002-09-23 09:36:25 +00001457"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001458" common user options for all Valgrind tools, with defaults in [ ]:\n"
nethercote0d588502004-06-21 13:27:11 +00001459" --tool=<name> use the Valgrind tool named <name>\n"
nethercotea76368b2004-06-16 11:56:29 +00001460" -h --help show this message\n"
nethercote6c999f22004-01-31 22:55:15 +00001461" --help-debug show this message, plus debugging options\n"
njn25e49d8e72002-09-23 09:36:25 +00001462" --version show version\n"
njn25e49d8e72002-09-23 09:36:25 +00001463" -q --quiet run silently; only print error msgs\n"
1464" -v --verbose be more verbose, incl counts of errors\n"
nethercote77eba602003-11-13 17:35:04 +00001465" --trace-children=no|yes Valgrind-ise child processes? [no]\n"
nethercote0d588502004-06-21 13:27:11 +00001466" --track-fds=no|yes track open file descriptors? [no]\n"
thughes6233a382004-08-21 11:10:44 +00001467" --time-stamp=no|yes add timestamps to log messages? [no]\n"
nethercote2b0793f2003-12-02 10:41:18 +00001468"\n"
1469" uncommon user options for all Valgrind tools:\n"
nethercote0d588502004-06-21 13:27:11 +00001470" --run-libc-freeres=no|yes free up glibc memory at exit? [yes]\n"
1471" --weird-hacks=hack1,hack2,... recognised hacks: lax-ioctls [none]\n"
1472" --signal-polltime=<time> signal poll period (mS) for older kernels [50]\n"
1473" --lowlat-signals=no|yes improve thread signal wake-up latency [no]\n"
1474" --lowlat-syscalls=no|yes improve thread syscall wake-up latency [no]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001475" --pointercheck=no|yes enforce client address space limits [yes]\n"
njn25e49d8e72002-09-23 09:36:25 +00001476"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001477" user options for Valgrind tools that report errors:\n"
nethercotef8548672004-06-21 12:42:35 +00001478" --log-fd=<number> log messages to file descriptor [2=stderr]\n"
1479" --log-file=<file> log messages to <file>.pid<pid>\n"
1480" --log-socket=ipaddr:port log messages to socket ipaddr:port\n"
nethercote2b0793f2003-12-02 10:41:18 +00001481" --demangle=no|yes automatically demangle C++ names? [yes]\n"
1482" --num-callers=<number> show <num> callers in stack traces [4]\n"
1483" --error-limit=no|yes stop showing new errors if too many? [yes]\n"
1484" --show-below-main=no|yes continue stack traces below main() [no]\n"
1485" --suppressions=<filename> suppress errors described in <filename>\n"
1486" --gen-suppressions=no|yes print suppressions for errors detected [no]\n"
nethercote04d0fbc2004-01-26 16:48:06 +00001487" --db-attach=no|yes start debugger when errors detected? [no]\n"
1488" --db-command=<command> command to start debugger [gdb -nw %%f %%p]\n"
1489" --input-fd=<number> file descriptor for input [0=stdin]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001490"\n";
njn7cf0bd32002-06-08 13:36:03 +00001491
njn25e49d8e72002-09-23 09:36:25 +00001492 Char* usage2 =
1493"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001494" debugging options for all Valgrind tools:\n"
njn25e49d8e72002-09-23 09:36:25 +00001495" --sanity-level=<number> level of sanity checking to do [1]\n"
1496" --single-step=no|yes translate each instr separately? [no]\n"
1497" --optimise=no|yes improve intermediate code? [yes]\n"
nethercote137bc552003-11-14 17:47:54 +00001498" --profile=no|yes profile? (tool must be built for it) [no]\n"
sewardj22854b92002-11-30 14:00:47 +00001499" --chain-bb=no|yes do basic-block chaining? [yes]\n"
fitzhardinge462f4f92003-12-18 02:10:54 +00001500" --branchpred=yes|no generate branch prediction hints [no]\n"
njn25e49d8e72002-09-23 09:36:25 +00001501" --trace-codegen=<XXXXX> show generated code? (X = 0|1) [00000]\n"
1502" --trace-syscalls=no|yes show all system calls? [no]\n"
1503" --trace-signals=no|yes show signal handling details? [no]\n"
1504" --trace-symtab=no|yes show symbol table details? [no]\n"
njn25e49d8e72002-09-23 09:36:25 +00001505" --trace-sched=no|yes show thread scheduler details? [no]\n"
njn3e884182003-04-15 13:03:23 +00001506" --trace-pthread=none|some|all show pthread event details? [none]\n"
jsgf855d93d2003-10-13 22:26:55 +00001507" --wait-for-gdb=yes|no pause on startup to wait for gdb attach\n"
njn25e49d8e72002-09-23 09:36:25 +00001508"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001509" debugging options for Valgrind tools that report errors\n"
1510" --dump-error=<number> show translation for basic block associated\n"
1511" with <number>'th error context [0=show none]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001512"\n";
njn3e884182003-04-15 13:03:23 +00001513
1514 Char* usage3 =
1515"\n"
nethercote71980f02004-01-24 18:18:54 +00001516" Extra options read from ~/.valgrindrc, $VALGRIND_OPTS, ./.valgrindrc\n"
njn25e49d8e72002-09-23 09:36:25 +00001517"\n"
nethercote08fa9a72004-07-16 17:44:00 +00001518" Valgrind is Copyright (C) 2000-2004 Julian Seward et al.\n"
njn25e49d8e72002-09-23 09:36:25 +00001519" and licensed under the GNU General Public License, version 2.\n"
1520" Bug reports, feedback, admiration, abuse, etc, to: %s.\n"
njnd04b7c62002-10-03 14:05:52 +00001521"\n"
nethercote137bc552003-11-14 17:47:54 +00001522" Tools are copyright and licensed by their authors. See each\n"
1523" tool's start-up message for more information.\n"
njn25e49d8e72002-09-23 09:36:25 +00001524"\n";
njn7cf0bd32002-06-08 13:36:03 +00001525
fitzhardinge98abfc72003-12-16 02:05:15 +00001526 VG_(printf)(usage1);
1527 if (VG_(details).name) {
1528 VG_(printf)(" user options for %s:\n", VG_(details).name);
fitzhardinge98abfc72003-12-16 02:05:15 +00001529 if (VG_(needs).command_line_options)
1530 SK_(print_usage)();
1531 else
1532 VG_(printf)(" (none)\n");
1533 }
nethercote6c999f22004-01-31 22:55:15 +00001534 if (debug_help) {
1535 VG_(printf)(usage2);
fitzhardinge98abfc72003-12-16 02:05:15 +00001536
nethercote6c999f22004-01-31 22:55:15 +00001537 if (VG_(details).name) {
1538 VG_(printf)(" debugging options for %s:\n", VG_(details).name);
1539
1540 if (VG_(needs).command_line_options)
1541 SK_(print_debug_usage)();
1542 else
1543 VG_(printf)(" (none)\n");
1544 }
fitzhardinge98abfc72003-12-16 02:05:15 +00001545 }
nethercote421281e2003-11-20 16:20:55 +00001546 VG_(printf)(usage3, VG_BUGS_TO);
nethercotef4928da2004-06-15 10:54:40 +00001547 VG_(exit)(0);
njn7cf0bd32002-06-08 13:36:03 +00001548}
sewardjde4a1d02002-03-22 01:27:54 +00001549
nethercote71980f02004-01-24 18:18:54 +00001550static void pre_process_cmd_line_options
nethercote6c999f22004-01-31 22:55:15 +00001551 ( Int* need_help, const char** tool, const char** exec )
sewardj1c1b1162003-02-23 01:25:51 +00001552{
nethercote71980f02004-01-24 18:18:54 +00001553 UInt i;
sewardjde4a1d02002-03-22 01:27:54 +00001554
nethercote71980f02004-01-24 18:18:54 +00001555 /* parse the options we have (only the options we care about now) */
nethercotef6a1d502004-08-09 12:21:57 +00001556 for (i = 1; i < vg_argc; i++) {
nethercote71980f02004-01-24 18:18:54 +00001557
nethercotef6a1d502004-08-09 12:21:57 +00001558 if (strcmp(vg_argv[i], "--version") == 0) {
nethercote71980f02004-01-24 18:18:54 +00001559 printf("valgrind-" VERSION "\n");
nethercotef4928da2004-06-15 10:54:40 +00001560 exit(0);
nethercote71980f02004-01-24 18:18:54 +00001561
nethercotef6a1d502004-08-09 12:21:57 +00001562 } else if (VG_CLO_STREQ(vg_argv[i], "--help") ||
1563 VG_CLO_STREQ(vg_argv[i], "-h")) {
nethercote6c999f22004-01-31 22:55:15 +00001564 *need_help = 1;
1565
nethercotef6a1d502004-08-09 12:21:57 +00001566 } else if (VG_CLO_STREQ(vg_argv[i], "--help-debug")) {
nethercote6c999f22004-01-31 22:55:15 +00001567 *need_help = 2;
nethercote71980f02004-01-24 18:18:54 +00001568
nethercotef6a1d502004-08-09 12:21:57 +00001569 } else if (VG_CLO_STREQN(7, vg_argv[i], "--tool=") ||
1570 VG_CLO_STREQN(7, vg_argv[i], "--skin=")) {
1571 *tool = &vg_argv[i][7];
nethercote71980f02004-01-24 18:18:54 +00001572
nethercotef6a1d502004-08-09 12:21:57 +00001573 } else if (VG_CLO_STREQN(7, vg_argv[i], "--exec=")) {
1574 *exec = &vg_argv[i][7];
nethercote71980f02004-01-24 18:18:54 +00001575 }
1576 }
1577
nethercotef4928da2004-06-15 10:54:40 +00001578 /* If no tool specified, can act appropriately without loading tool */
nethercote71980f02004-01-24 18:18:54 +00001579 if (*tool == NULL) {
nethercotef4928da2004-06-15 10:54:40 +00001580 if (0 == *need_help) {
1581 // neither --tool nor --help/--help-debug specified
1582 missing_tool_option();
1583 } else {
1584 // Give help message, without any tool-specific help
1585 usage(/*help-debug?*/2 == *need_help);
1586 }
nethercote71980f02004-01-24 18:18:54 +00001587 }
1588}
1589
nethercote5ee67ca2004-06-22 14:00:09 +00001590static void process_cmd_line_options( UInt* client_auxv, const char* toolname )
nethercote71980f02004-01-24 18:18:54 +00001591{
nethercotef8548672004-06-21 12:42:35 +00001592 Int i, eventually_log_fd;
nethercote71980f02004-01-24 18:18:54 +00001593 Int *auxp;
1594 Int toolname_len = VG_(strlen)(toolname);
sewardjde4a1d02002-03-22 01:27:54 +00001595
nethercotee1730692003-11-20 10:38:07 +00001596 /* log to stderr by default, but usage message goes to stdout */
nethercotef8548672004-06-21 12:42:35 +00001597 eventually_log_fd = 2;
sewardjde4a1d02002-03-22 01:27:54 +00001598
sewardj19d81412002-06-03 01:10:40 +00001599 /* Check for sane path in ./configure --prefix=... */
fitzhardinge98abfc72003-12-16 02:05:15 +00001600 if (VG_LIBDIR[0] != '/')
sewardj19d81412002-06-03 01:10:40 +00001601 config_error("Please use absolute paths in "
1602 "./configure --prefix=... or --libdir=...");
sewardj38170912002-05-10 21:07:22 +00001603
nethercote71980f02004-01-24 18:18:54 +00001604 for (auxp = client_auxv; auxp[0] != VKI_AT_NULL; auxp += 2) {
fitzhardinge98abfc72003-12-16 02:05:15 +00001605 switch(auxp[0]) {
1606 case VKI_AT_SYSINFO:
fitzhardinge92360792003-12-24 10:11:11 +00001607 auxp[1] = (Int)(VG_(client_trampoline_code) + VG_(tramp_syscall_offset));
fitzhardinge98abfc72003-12-16 02:05:15 +00001608 break;
sewardjde4a1d02002-03-22 01:27:54 +00001609 }
fitzhardinge98abfc72003-12-16 02:05:15 +00001610 }
sewardjde4a1d02002-03-22 01:27:54 +00001611
nethercotef6a1d502004-08-09 12:21:57 +00001612 for (i = 1; i < vg_argc; i++) {
nethercote71980f02004-01-24 18:18:54 +00001613
nethercotef6a1d502004-08-09 12:21:57 +00001614 Char* arg = vg_argv[i];
thughes3bfd5a02004-07-18 08:05:44 +00001615 Char* colon = arg;
nethercote71980f02004-01-24 18:18:54 +00001616
thughes3bfd5a02004-07-18 08:05:44 +00001617 /* Look for a colon in the switch name */
1618 while (*colon && *colon != ':' && *colon != '=')
1619 colon++;
nethercote71980f02004-01-24 18:18:54 +00001620
1621 /* Look for matching "--toolname:foo" */
thughes3bfd5a02004-07-18 08:05:44 +00001622 if (*colon == ':') {
nethercote71980f02004-01-24 18:18:54 +00001623 if (VG_CLO_STREQN(2, arg, "--") &&
1624 VG_CLO_STREQN(toolname_len, arg+2, toolname) &&
1625 VG_CLO_STREQN(1, arg+2+toolname_len, ":"))
1626 {
1627 // prefix matches, convert "--toolname:foo" to "--foo"
1628 if (0)
1629 VG_(printf)("tool-specific arg: %s\n", arg);
1630 arg += toolname_len + 1;
1631 arg[0] = '-';
1632 arg[1] = '-';
1633
1634 } else {
1635 // prefix doesn't match, skip to next arg
1636 continue;
1637 }
1638 }
1639
fitzhardinge98abfc72003-12-16 02:05:15 +00001640 /* Ignore these options - they've already been handled */
nethercote71980f02004-01-24 18:18:54 +00001641 if (VG_CLO_STREQN(7, arg, "--tool=") ||
1642 VG_CLO_STREQN(7, arg, "--skin="))
fitzhardinge98abfc72003-12-16 02:05:15 +00001643 continue;
nethercote71980f02004-01-24 18:18:54 +00001644 if (VG_CLO_STREQN(7, arg, "--exec="))
fitzhardinge98abfc72003-12-16 02:05:15 +00001645 continue;
1646
nethercote71980f02004-01-24 18:18:54 +00001647 if ( VG_CLO_STREQ(arg, "--"))
fitzhardinge98abfc72003-12-16 02:05:15 +00001648 continue;
nethercote27fec902004-06-16 21:26:32 +00001649
nethercote71980f02004-01-24 18:18:54 +00001650 else if (VG_CLO_STREQ(arg, "-v") ||
1651 VG_CLO_STREQ(arg, "--verbose"))
sewardjde4a1d02002-03-22 01:27:54 +00001652 VG_(clo_verbosity)++;
nethercote27fec902004-06-16 21:26:32 +00001653
nethercote71980f02004-01-24 18:18:54 +00001654 else if (VG_CLO_STREQ(arg, "-q") ||
1655 VG_CLO_STREQ(arg, "--quiet"))
sewardjde4a1d02002-03-22 01:27:54 +00001656 VG_(clo_verbosity)--;
1657
nethercote27fec902004-06-16 21:26:32 +00001658 else VG_BOOL_CLO("--branchpred", VG_(clo_branchpred))
1659 else VG_BOOL_CLO("--chain-bb", VG_(clo_chain_bb))
1660 else VG_BOOL_CLO("--db-attach", VG_(clo_db_attach))
1661 else VG_BOOL_CLO("--demangle", VG_(clo_demangle))
1662 else VG_BOOL_CLO("--error-limit", VG_(clo_error_limit))
1663 else VG_BOOL_CLO("--gen-suppressions", VG_(clo_gen_suppressions))
1664 else VG_BOOL_CLO("--lowlat-signals", VG_(clo_lowlat_signals))
1665 else VG_BOOL_CLO("--lowlat-syscalls", VG_(clo_lowlat_syscalls))
1666 else VG_BOOL_CLO("--optimise", VG_(clo_optimise))
1667 else VG_BOOL_CLO("--pointercheck", VG_(clo_pointercheck))
1668 else VG_BOOL_CLO("--profile", VG_(clo_profile))
1669 else VG_BOOL_CLO("--run-libc-freeres", VG_(clo_run_libc_freeres))
1670 else VG_BOOL_CLO("--show-below-main", VG_(clo_show_below_main))
1671 else VG_BOOL_CLO("--single-step", VG_(clo_single_step))
thughes6233a382004-08-21 11:10:44 +00001672 else VG_BOOL_CLO("--time-stamp", VG_(clo_time_stamp))
nethercote27fec902004-06-16 21:26:32 +00001673 else VG_BOOL_CLO("--track-fds", VG_(clo_track_fds))
1674 else VG_BOOL_CLO("--trace-children", VG_(clo_trace_children))
1675 else VG_BOOL_CLO("--trace-sched", VG_(clo_trace_sched))
1676 else VG_BOOL_CLO("--trace-signals", VG_(clo_trace_signals))
1677 else VG_BOOL_CLO("--trace-symtab", VG_(clo_trace_symtab))
1678 else VG_BOOL_CLO("--trace-syscalls", VG_(clo_trace_syscalls))
1679 else VG_BOOL_CLO("--wait-for-gdb", VG_(clo_wait_for_gdb))
sewardj72f98ff2002-06-13 17:23:38 +00001680
nethercote27fec902004-06-16 21:26:32 +00001681 else VG_STR_CLO ("--db-command", VG_(clo_db_command))
1682 else VG_STR_CLO ("--weird-hacks", VG_(clo_weird_hacks))
sewardjde4a1d02002-03-22 01:27:54 +00001683
nethercote27fec902004-06-16 21:26:32 +00001684 else VG_NUM_CLO ("--dump-error", VG_(clo_dump_error))
1685 else VG_NUM_CLO ("--input-fd", VG_(clo_input_fd))
1686 else VG_NUM_CLO ("--sanity-level", VG_(clo_sanity_level))
1687 else VG_NUM_CLO ("--signal­polltime", VG_(clo_signal_polltime))
1688 else VG_BNUM_CLO("--num-callers", VG_(clo_backtrace_size), 1,
1689 VG_DEEPEST_BACKTRACE)
sewardjde4a1d02002-03-22 01:27:54 +00001690
nethercotef8548672004-06-21 12:42:35 +00001691 // for backwards compatibility, replaced by --log-fd
nethercote71980f02004-01-24 18:18:54 +00001692 else if (VG_CLO_STREQN(13, arg, "--logfile-fd=")) {
nethercotef8548672004-06-21 12:42:35 +00001693 VG_(clo_log_to) = VgLogTo_Fd;
1694 VG_(clo_log_name) = NULL;
1695 eventually_log_fd = (Int)VG_(atoll)(&arg[13]);
1696 }
1697 else if (VG_CLO_STREQN(9, arg, "--log-fd=")) {
1698 VG_(clo_log_to) = VgLogTo_Fd;
1699 VG_(clo_log_name) = NULL;
1700 eventually_log_fd = (Int)VG_(atoll)(&arg[9]);
sewardj4cf05692002-10-27 20:28:29 +00001701 }
1702
nethercotef8548672004-06-21 12:42:35 +00001703 // for backwards compatibility, replaced by --log-file
nethercote71980f02004-01-24 18:18:54 +00001704 else if (VG_CLO_STREQN(10, arg, "--logfile=")) {
nethercotef8548672004-06-21 12:42:35 +00001705 VG_(clo_log_to) = VgLogTo_File;
1706 VG_(clo_log_name) = &arg[10];
1707 }
1708 else if (VG_CLO_STREQN(11, arg, "--log-file=")) {
1709 VG_(clo_log_to) = VgLogTo_File;
1710 VG_(clo_log_name) = &arg[11];
sewardj4cf05692002-10-27 20:28:29 +00001711 }
sewardjde4a1d02002-03-22 01:27:54 +00001712
nethercotef8548672004-06-21 12:42:35 +00001713 // for backwards compatibility, replaced by --log-socket
nethercote71980f02004-01-24 18:18:54 +00001714 else if (VG_CLO_STREQN(12, arg, "--logsocket=")) {
nethercotef8548672004-06-21 12:42:35 +00001715 VG_(clo_log_to) = VgLogTo_Socket;
1716 VG_(clo_log_name) = &arg[12];
1717 }
1718 else if (VG_CLO_STREQN(13, arg, "--log-socket=")) {
1719 VG_(clo_log_to) = VgLogTo_Socket;
1720 VG_(clo_log_name) = &arg[13];
sewardj73cf3bc2002-11-03 03:20:15 +00001721 }
1722
nethercote71980f02004-01-24 18:18:54 +00001723 else if (VG_CLO_STREQN(15, arg, "--suppressions=")) {
sewardjde4a1d02002-03-22 01:27:54 +00001724 if (VG_(clo_n_suppressions) >= VG_CLO_MAX_SFILES) {
njn25e49d8e72002-09-23 09:36:25 +00001725 VG_(message)(Vg_UserMsg, "Too many suppression files specified.");
sewardjde4a1d02002-03-22 01:27:54 +00001726 VG_(message)(Vg_UserMsg,
1727 "Increase VG_CLO_MAX_SFILES and recompile.");
nethercote71980f02004-01-24 18:18:54 +00001728 VG_(bad_option)(arg);
sewardjde4a1d02002-03-22 01:27:54 +00001729 }
nethercote71980f02004-01-24 18:18:54 +00001730 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = &arg[15];
sewardjde4a1d02002-03-22 01:27:54 +00001731 VG_(clo_n_suppressions)++;
1732 }
sewardjde4a1d02002-03-22 01:27:54 +00001733
njn25e49d8e72002-09-23 09:36:25 +00001734 /* "vwxyz" --> 000zyxwv (binary) */
nethercote71980f02004-01-24 18:18:54 +00001735 else if (VG_CLO_STREQN(16, arg, "--trace-codegen=")) {
njn25e49d8e72002-09-23 09:36:25 +00001736 Int j;
nethercote71980f02004-01-24 18:18:54 +00001737 char* opt = & arg[16];
njn25e49d8e72002-09-23 09:36:25 +00001738
1739 if (5 != VG_(strlen)(opt)) {
1740 VG_(message)(Vg_UserMsg,
1741 "--trace-codegen argument must have 5 digits");
nethercote71980f02004-01-24 18:18:54 +00001742 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001743 }
1744 for (j = 0; j < 5; j++) {
1745 if ('0' == opt[j]) { /* do nothing */ }
1746 else if ('1' == opt[j]) VG_(clo_trace_codegen) |= (1 << j);
1747 else {
1748 VG_(message)(Vg_UserMsg, "--trace-codegen argument can only "
1749 "contain 0s and 1s");
nethercote71980f02004-01-24 18:18:54 +00001750 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001751 }
1752 }
1753 }
sewardjde4a1d02002-03-22 01:27:54 +00001754
nethercote71980f02004-01-24 18:18:54 +00001755 else if (VG_CLO_STREQ(arg, "--trace-pthread=none"))
sewardj45b4b372002-04-16 22:50:32 +00001756 VG_(clo_trace_pthread_level) = 0;
nethercote71980f02004-01-24 18:18:54 +00001757 else if (VG_CLO_STREQ(arg, "--trace-pthread=some"))
sewardj45b4b372002-04-16 22:50:32 +00001758 VG_(clo_trace_pthread_level) = 1;
nethercote71980f02004-01-24 18:18:54 +00001759 else if (VG_CLO_STREQ(arg, "--trace-pthread=all"))
sewardj45b4b372002-04-16 22:50:32 +00001760 VG_(clo_trace_pthread_level) = 2;
sewardj8937c812002-04-12 20:12:20 +00001761
nethercote71980f02004-01-24 18:18:54 +00001762 else if ( ! VG_(needs).command_line_options
1763 || ! SK_(process_cmd_line_option)(arg) ) {
nethercotef4928da2004-06-15 10:54:40 +00001764 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001765 }
sewardjde4a1d02002-03-22 01:27:54 +00001766 }
1767
nethercote27fec902004-06-16 21:26:32 +00001768 // Check various option values
1769
njnf9ebf672003-05-12 21:41:30 +00001770 if (VG_(clo_verbosity) < 0)
sewardjde4a1d02002-03-22 01:27:54 +00001771 VG_(clo_verbosity) = 0;
1772
nethercote04d0fbc2004-01-26 16:48:06 +00001773 if (VG_(clo_db_attach) && VG_(clo_trace_children)) {
sewardjde4a1d02002-03-22 01:27:54 +00001774 VG_(message)(Vg_UserMsg, "");
1775 VG_(message)(Vg_UserMsg,
nethercote04d0fbc2004-01-26 16:48:06 +00001776 "--db-attach=yes conflicts with --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001777 VG_(message)(Vg_UserMsg,
1778 "Please choose one or the other, but not both.");
nethercote04d0fbc2004-01-26 16:48:06 +00001779 VG_(bad_option)("--db-attach=yes and --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001780 }
1781
nethercotef8548672004-06-21 12:42:35 +00001782 /* Set up logging now. After this is done, VG_(clo_log_fd)
sewardj4cf05692002-10-27 20:28:29 +00001783 should be connected to whatever sink has been selected, and we
1784 indiscriminately chuck stuff into it without worrying what the
1785 nature of it is. Oh the wonder of Unix streams. */
1786
nethercotee1730692003-11-20 10:38:07 +00001787 /* So far we should be still attached to stdout, so we can show on
sewardj4cf05692002-10-27 20:28:29 +00001788 the terminal any problems to do with processing command line
1789 opts. */
nethercotef8548672004-06-21 12:42:35 +00001790 vg_assert(VG_(clo_log_fd) == 1 /* stdout */);
sewardj73cf3bc2002-11-03 03:20:15 +00001791 vg_assert(VG_(logging_to_filedes) == True);
sewardj4cf05692002-10-27 20:28:29 +00001792
1793 switch (VG_(clo_log_to)) {
sewardj73cf3bc2002-11-03 03:20:15 +00001794
sewardj4cf05692002-10-27 20:28:29 +00001795 case VgLogTo_Fd:
nethercotef8548672004-06-21 12:42:35 +00001796 vg_assert(VG_(clo_log_name) == NULL);
1797 VG_(clo_log_fd) = eventually_log_fd;
sewardj4cf05692002-10-27 20:28:29 +00001798 break;
sewardj73cf3bc2002-11-03 03:20:15 +00001799
sewardj4cf05692002-10-27 20:28:29 +00001800 case VgLogTo_File: {
1801 Char logfilename[1000];
jsgff3c3f1a2003-10-14 22:13:28 +00001802 Int seq = 0;
1803 Int pid = VG_(getpid)();
1804
nethercotef8548672004-06-21 12:42:35 +00001805 vg_assert(VG_(clo_log_name) != NULL);
1806 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
jsgff3c3f1a2003-10-14 22:13:28 +00001807
nethercote71980f02004-01-24 18:18:54 +00001808 for (;;) {
jsgff3c3f1a2003-10-14 22:13:28 +00001809 if (seq == 0)
1810 VG_(sprintf)(logfilename, "%s.pid%d",
nethercotef8548672004-06-21 12:42:35 +00001811 VG_(clo_log_name), pid );
jsgff3c3f1a2003-10-14 22:13:28 +00001812 else
1813 VG_(sprintf)(logfilename, "%s.pid%d.%d",
nethercotef8548672004-06-21 12:42:35 +00001814 VG_(clo_log_name), pid, seq );
jsgff3c3f1a2003-10-14 22:13:28 +00001815 seq++;
1816
nethercotef8548672004-06-21 12:42:35 +00001817 eventually_log_fd
jsgff3c3f1a2003-10-14 22:13:28 +00001818 = VG_(open)(logfilename,
1819 VKI_O_CREAT|VKI_O_WRONLY|VKI_O_EXCL|VKI_O_TRUNC,
1820 VKI_S_IRUSR|VKI_S_IWUSR);
nethercotef8548672004-06-21 12:42:35 +00001821 if (eventually_log_fd >= 0) {
1822 VG_(clo_log_fd) = VG_(safe_fd)(eventually_log_fd);
jsgff3c3f1a2003-10-14 22:13:28 +00001823 break;
1824 } else {
nethercotef8548672004-06-21 12:42:35 +00001825 if (eventually_log_fd != -VKI_EEXIST) {
jsgff3c3f1a2003-10-14 22:13:28 +00001826 VG_(message)(Vg_UserMsg,
1827 "Can't create/open log file `%s.pid%d'; giving up!",
nethercotef8548672004-06-21 12:42:35 +00001828 VG_(clo_log_name), pid);
jsgff3c3f1a2003-10-14 22:13:28 +00001829 VG_(bad_option)(
nethercotef8548672004-06-21 12:42:35 +00001830 "--log-file=<file> didn't work out for some reason.");
jsgff3c3f1a2003-10-14 22:13:28 +00001831 break;
1832 }
1833 }
1834 }
sewardj4cf05692002-10-27 20:28:29 +00001835 break;
sewardj73cf3bc2002-11-03 03:20:15 +00001836 }
1837
1838 case VgLogTo_Socket: {
nethercotef8548672004-06-21 12:42:35 +00001839 vg_assert(VG_(clo_log_name) != NULL);
1840 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
1841 eventually_log_fd = VG_(connect_via_socket)( VG_(clo_log_name) );
1842 if (eventually_log_fd == -1) {
sewardj73cf3bc2002-11-03 03:20:15 +00001843 VG_(message)(Vg_UserMsg,
nethercotef8548672004-06-21 12:42:35 +00001844 "Invalid --log-socket=ipaddr or --log-socket=ipaddr:port spec");
sewardj73cf3bc2002-11-03 03:20:15 +00001845 VG_(message)(Vg_UserMsg,
nethercotef8548672004-06-21 12:42:35 +00001846 "of `%s'; giving up!", VG_(clo_log_name) );
sewardj73cf3bc2002-11-03 03:20:15 +00001847 VG_(bad_option)(
nethercotef8548672004-06-21 12:42:35 +00001848 "--log-socket=");
sewardj4cf05692002-10-27 20:28:29 +00001849 }
nethercotef8548672004-06-21 12:42:35 +00001850 if (eventually_log_fd == -2) {
sewardj73cf3bc2002-11-03 03:20:15 +00001851 VG_(message)(Vg_UserMsg,
sewardj570f8902002-11-03 11:44:36 +00001852 "valgrind: failed to connect to logging server `%s'.",
nethercotef8548672004-06-21 12:42:35 +00001853 VG_(clo_log_name) );
sewardj570f8902002-11-03 11:44:36 +00001854 VG_(message)(Vg_UserMsg,
1855 "Log messages will sent to stderr instead." );
1856 VG_(message)(Vg_UserMsg,
1857 "" );
1858 /* We don't change anything here. */
1859 } else {
nethercotef8548672004-06-21 12:42:35 +00001860 vg_assert(eventually_log_fd > 0);
1861 VG_(clo_log_fd) = eventually_log_fd;
sewardj570f8902002-11-03 11:44:36 +00001862 VG_(logging_to_filedes) = False;
1863 }
sewardj73cf3bc2002-11-03 03:20:15 +00001864 break;
1865 }
1866
sewardj4cf05692002-10-27 20:28:29 +00001867 }
1868
nethercotef8548672004-06-21 12:42:35 +00001869 /* Move log_fd into the safe range, so it doesn't conflict with any app fds */
thughesad1c9562004-06-26 11:27:52 +00001870 eventually_log_fd = VG_(fcntl)(VG_(clo_log_fd), VKI_F_DUPFD, VG_(fd_hard_limit));
nethercotef8548672004-06-21 12:42:35 +00001871 if (eventually_log_fd < 0)
jsgf855d93d2003-10-13 22:26:55 +00001872 VG_(message)(Vg_UserMsg, "valgrind: failed to move logfile fd into safe range");
1873 else {
nethercotef8548672004-06-21 12:42:35 +00001874 VG_(clo_log_fd) = eventually_log_fd;
1875 VG_(fcntl)(VG_(clo_log_fd), VKI_F_SETFD, VKI_FD_CLOEXEC);
jsgf855d93d2003-10-13 22:26:55 +00001876 }
1877
sewardj4cf05692002-10-27 20:28:29 +00001878 /* Ok, the logging sink is running now. Print a suitable preamble.
1879 If logging to file or a socket, write details of parent PID and
1880 command line args, to help people trying to interpret the
1881 results of a run which encompasses multiple processes. */
sewardjde4a1d02002-03-22 01:27:54 +00001882
sewardj83adf412002-05-01 01:25:45 +00001883 if (VG_(clo_verbosity > 0)) {
nethercote996901a2004-08-03 13:29:09 +00001884 /* Tool details */
nethercotea131bb82004-09-06 15:34:37 +00001885 VG_(message)(Vg_UserMsg, "%s%s%s, %s for %s.",
njnd04b7c62002-10-03 14:05:52 +00001886 VG_(details).name,
1887 NULL == VG_(details).version ? "" : "-",
1888 NULL == VG_(details).version
1889 ? (Char*)"" : VG_(details).version,
nethercotea131bb82004-09-06 15:34:37 +00001890 VG_(details).description,
1891 VG_PLATFORM);
njnd04b7c62002-10-03 14:05:52 +00001892 VG_(message)(Vg_UserMsg, "%s", VG_(details).copyright_author);
sewardj3b2736a2002-03-24 12:18:35 +00001893
njnd04b7c62002-10-03 14:05:52 +00001894 /* Core details */
1895 VG_(message)(Vg_UserMsg,
nethercotea131bb82004-09-06 15:34:37 +00001896 "Using valgrind-%s, a program supervision framework for %s.",
1897 VERSION, VG_PLATFORM);
sewardjde4a1d02002-03-22 01:27:54 +00001898 VG_(message)(Vg_UserMsg,
nethercote08fa9a72004-07-16 17:44:00 +00001899 "Copyright (C) 2000-2004, and GNU GPL'd, by Julian Seward et al.");
njnd04b7c62002-10-03 14:05:52 +00001900 }
1901
nethercotec1e395d2003-11-10 13:26:49 +00001902 if (VG_(clo_verbosity) > 0 && VG_(clo_log_to) != VgLogTo_Fd) {
sewardj4cf05692002-10-27 20:28:29 +00001903 VG_(message)(Vg_UserMsg, "");
1904 VG_(message)(Vg_UserMsg,
1905 "My PID = %d, parent PID = %d. Prog and args are:",
1906 VG_(getpid)(), VG_(getppid)() );
1907 for (i = 0; i < VG_(client_argc); i++)
1908 VG_(message)(Vg_UserMsg, " %s", VG_(client_argv)[i]);
1909 }
1910
sewardjde4a1d02002-03-22 01:27:54 +00001911 if (VG_(clo_verbosity) > 1) {
nethercotea70f7352004-04-18 12:08:46 +00001912 Int fd;
sewardj4cf05692002-10-27 20:28:29 +00001913 if (VG_(clo_log_to) != VgLogTo_Fd)
1914 VG_(message)(Vg_UserMsg, "");
fitzhardinge98abfc72003-12-16 02:05:15 +00001915 VG_(message)(Vg_UserMsg, "Valgrind library directory: %s", VG_(libdir));
njn86dc2bc2003-09-09 07:26:21 +00001916 VG_(message)(Vg_UserMsg, "Command line");
1917 for (i = 0; i < VG_(client_argc); i++)
1918 VG_(message)(Vg_UserMsg, " %s", VG_(client_argv)[i]);
1919
sewardjde4a1d02002-03-22 01:27:54 +00001920 VG_(message)(Vg_UserMsg, "Startup, with flags:");
nethercotef6a1d502004-08-09 12:21:57 +00001921 for (i = 1; i < vg_argc; i++) {
1922 VG_(message)(Vg_UserMsg, " %s", vg_argv[i]);
sewardjde4a1d02002-03-22 01:27:54 +00001923 }
nethercotea70f7352004-04-18 12:08:46 +00001924
1925 VG_(message)(Vg_UserMsg, "Contents of /proc/version:");
1926 fd = VG_(open) ( "/proc/version", VKI_O_RDONLY, 0 );
1927 if (fd < 0) {
1928 VG_(message)(Vg_UserMsg, " can't open /proc/version");
1929 } else {
1930 #define BUF_LEN 256
1931 Char version_buf[BUF_LEN];
1932 Int n = VG_(read) ( fd, version_buf, BUF_LEN );
1933 vg_assert(n <= 256);
1934 if (n > 0) {
1935 version_buf[n-1] = '\0';
1936 VG_(message)(Vg_UserMsg, " %s", version_buf);
1937 } else {
1938 VG_(message)(Vg_UserMsg, " (empty?)");
1939 }
1940 VG_(close)(fd);
1941 #undef BUF_LEN
1942 }
sewardjde4a1d02002-03-22 01:27:54 +00001943 }
1944
fitzhardinge98abfc72003-12-16 02:05:15 +00001945 if (VG_(clo_n_suppressions) < VG_CLO_MAX_SFILES-1 &&
njn25e49d8e72002-09-23 09:36:25 +00001946 (VG_(needs).core_errors || VG_(needs).skin_errors)) {
nethercote996901a2004-08-03 13:29:09 +00001947 /* If there are no suppression files specified and the tool
fitzhardinge98abfc72003-12-16 02:05:15 +00001948 needs one, load the default */
1949 static const Char default_supp[] = "default.supp";
1950 Int len = VG_(strlen)(VG_(libdir)) + 1 + sizeof(default_supp);
1951 Char *buf = VG_(arena_malloc)(VG_AR_CORE, len);
1952 VG_(sprintf)(buf, "%s/%s", VG_(libdir), default_supp);
1953 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = buf;
1954 VG_(clo_n_suppressions)++;
sewardjde4a1d02002-03-22 01:27:54 +00001955 }
sewardj4cf05692002-10-27 20:28:29 +00001956
njn6a230532003-07-21 10:38:23 +00001957 if (VG_(clo_gen_suppressions) &&
1958 !VG_(needs).core_errors && !VG_(needs).skin_errors) {
nethercotef4928da2004-06-15 10:54:40 +00001959 VG_(message)(Vg_UserMsg,
1960 "Can't use --gen-suppressions=yes with this tool,");
1961 VG_(message)(Vg_UserMsg,
1962 "as it doesn't generate errors.");
1963 VG_(bad_option)("--gen-suppressions=yes");
njn6a230532003-07-21 10:38:23 +00001964 }
sewardjde4a1d02002-03-22 01:27:54 +00001965}
1966
nethercotef6a1d502004-08-09 12:21:57 +00001967// Build the string for VALGRINDCLO.
1968Char* VG_(build_child_VALGRINDCLO)( Char* exename )
1969{
1970 /* If we're tracing the children, then we need to start it
1971 with our starter+arguments, which are copied into VALGRINDCLO,
1972 except the --exec= option is changed if present.
1973 */
1974 Int i;
1975 Char *exec;
1976 Char *cp;
1977 Char *optvar;
1978 Int optlen, execlen;
1979
1980 // All these allocated blocks are not free - because we're either
1981 // going to exec, or panic when we fail.
1982
1983 // Create --exec= option: "--exec=<exename>"
1984 exec = VG_(arena_malloc)(VG_AR_CORE,
1985 VG_(strlen)( exename ) + 7/*--exec=*/ + 1/*\0*/);
1986 vg_assert(NULL != exec);
1987 VG_(sprintf)(exec, "--exec=%s", exename);
1988
1989 // Allocate space for optvar (may overestimate by counting --exec twice,
1990 // no matter)
1991 optlen = 1;
1992 for (i = 0; i < vg_argc; i++)
1993 optlen += VG_(strlen)(vg_argv[i]) + 1;
1994 optlen += VG_(strlen)(exec)+1;
1995 optvar = VG_(arena_malloc)(VG_AR_CORE, optlen);
1996
1997 // Copy all valgrind args except the old --exec (if present)
1998 // VG_CLO_SEP is the separator.
1999 cp = optvar;
2000 for (i = 1; i < vg_argc; i++) {
2001 Char *arg = vg_argv[i];
2002
2003 if (VG_(memcmp)(arg, "--exec=", 7) == 0) {
2004 // don't copy existing --exec= arg
2005 } else if (VG_(strcmp)(arg, "--") == 0) {
2006 // stop at "--"
2007 break;
2008 } else {
2009 // copy non "--exec" arg
2010 Int len = VG_(strlen)(arg);
2011 VG_(memcpy)(cp, arg, len);
2012 cp += len;
2013 *cp++ = VG_CLO_SEP;
2014 }
2015 }
2016 // Add the new --exec= option
2017 execlen = VG_(strlen)(exec);
2018 VG_(memcpy)(cp, exec, execlen);
2019 cp += execlen;
2020 *cp++ = VG_CLO_SEP;
2021
2022 *cp = '\0';
2023
2024 return optvar;
2025}
2026
2027// Build "/proc/self/fd/<execfd>".
2028Char* VG_(build_child_exename)( void )
2029{
2030 Char* exename = VG_(arena_malloc)(VG_AR_CORE, 64);
2031 vg_assert(NULL != exename);
2032 VG_(sprintf)(exename, "/proc/self/fd/%d", vgexecfd);
2033 return exename;
2034}
2035
sewardjde4a1d02002-03-22 01:27:54 +00002036
nethercote71980f02004-01-24 18:18:54 +00002037/*====================================================================*/
2038/*=== File descriptor setup ===*/
2039/*====================================================================*/
2040
2041static void setup_file_descriptors(void)
2042{
2043 struct vki_rlimit rl;
2044
2045 /* Get the current file descriptor limits. */
2046 if (VG_(getrlimit)(VKI_RLIMIT_NOFILE, &rl) < 0) {
2047 rl.rlim_cur = 1024;
2048 rl.rlim_max = 1024;
2049 }
2050
2051 /* Work out where to move the soft limit to. */
2052 if (rl.rlim_cur + VG_N_RESERVED_FDS <= rl.rlim_max) {
2053 rl.rlim_cur = rl.rlim_cur + VG_N_RESERVED_FDS;
2054 } else {
2055 rl.rlim_cur = rl.rlim_max;
2056 }
2057
2058 /* Reserve some file descriptors for our use. */
thughesad1c9562004-06-26 11:27:52 +00002059 VG_(fd_soft_limit) = rl.rlim_cur - VG_N_RESERVED_FDS;
2060 VG_(fd_hard_limit) = rl.rlim_cur - VG_N_RESERVED_FDS;
nethercote71980f02004-01-24 18:18:54 +00002061
2062 /* Update the soft limit. */
2063 VG_(setrlimit)(VKI_RLIMIT_NOFILE, &rl);
2064
nethercotef6a1d502004-08-09 12:21:57 +00002065 if (vgexecfd != -1)
2066 vgexecfd = VG_(safe_fd)( vgexecfd );
nethercote71980f02004-01-24 18:18:54 +00002067 if (VG_(clexecfd) != -1)
2068 VG_(clexecfd) = VG_(safe_fd)( VG_(clexecfd) );
2069}
2070
2071
2072/*====================================================================*/
nethercote1d447092004-02-01 17:29:59 +00002073/*=== baseBlock: definition + setup ===*/
nethercote71980f02004-01-24 18:18:54 +00002074/*====================================================================*/
2075
nethercote71980f02004-01-24 18:18:54 +00002076Int VGOFF_(helper_undefined_instruction) = INVALID_OFFSET;
2077
2078/* MAX_NONCOMPACT_HELPERS can be increased easily. If MAX_COMPACT_HELPERS is
2079 * increased too much, they won't really be compact any more... */
2080#define MAX_COMPACT_HELPERS 8
2081#define MAX_NONCOMPACT_HELPERS 50
2082
nethercote81f9a6f2004-08-03 15:45:46 +00002083/* For storing tool-specific helpers, determined at runtime. The addr
2084 * and offset arrays together form a (addr, offset) map that allows a
2085 * helper's baseBlock offset to be computed from its address. It's done
2086 * like this so CCALLs can use the function address rather than having to
2087 * muck around with offsets. */
2088static UInt VG_(n_compact_helpers) = 0;
2089static UInt VG_(n_noncompact_helpers) = 0;
2090static Addr VG_(compact_helper_addrs) [MAX_COMPACT_HELPERS];
2091static Int VG_(compact_helper_offsets)[MAX_COMPACT_HELPERS];
2092static Addr VG_(noncompact_helper_addrs) [MAX_NONCOMPACT_HELPERS];
2093static Int VG_(noncompact_helper_offsets)[MAX_NONCOMPACT_HELPERS];
nethercote71980f02004-01-24 18:18:54 +00002094
2095/* This is the actual defn of baseblock. */
2096UInt VG_(baseBlock)[VG_BASEBLOCK_WORDS];
2097
nethercote71980f02004-01-24 18:18:54 +00002098/* Words. */
2099static Int baB_off = 0;
2100
2101
nethercote71980f02004-01-24 18:18:54 +00002102/* Returns the offset, in words. */
nethercote2e05c332004-09-06 16:43:37 +00002103Int VG_(alloc_BaB) ( Int words )
sewardjde4a1d02002-03-22 01:27:54 +00002104{
nethercote71980f02004-01-24 18:18:54 +00002105 Int off = baB_off;
2106 baB_off += words;
2107 if (baB_off >= VG_BASEBLOCK_WORDS)
nethercote2e05c332004-09-06 16:43:37 +00002108 VG_(core_panic)( "VG_(alloc_BaB): baseBlock is too small");
sewardjde4a1d02002-03-22 01:27:54 +00002109
nethercote71980f02004-01-24 18:18:54 +00002110 return off;
sewardjde4a1d02002-03-22 01:27:54 +00002111}
2112
nethercote71980f02004-01-24 18:18:54 +00002113/* Align offset, in *bytes* */
nethercote2e05c332004-09-06 16:43:37 +00002114void VG_(align_BaB) ( UInt align )
njn25e49d8e72002-09-23 09:36:25 +00002115{
nethercote71980f02004-01-24 18:18:54 +00002116 vg_assert(2 == align || 4 == align || 8 == align || 16 == align);
2117 baB_off += (align-1);
2118 baB_off &= ~(align-1);
njn25e49d8e72002-09-23 09:36:25 +00002119}
2120
nethercote71980f02004-01-24 18:18:54 +00002121/* Allocate 1 word in baseBlock and set it to the given value. */
nethercote2e05c332004-09-06 16:43:37 +00002122Int VG_(alloc_BaB_1_set) ( Addr a )
njn25e49d8e72002-09-23 09:36:25 +00002123{
nethercote2e05c332004-09-06 16:43:37 +00002124 Int off = VG_(alloc_BaB)(1);
nethercote71980f02004-01-24 18:18:54 +00002125 VG_(baseBlock)[off] = (UInt)a;
2126 return off;
njn25e49d8e72002-09-23 09:36:25 +00002127}
2128
nethercote71980f02004-01-24 18:18:54 +00002129/* Registers a function in compact_helper_addrs; compact_helper_offsets is
2130 filled in later. */
2131void VG_(register_compact_helper)(Addr a)
sewardjde4a1d02002-03-22 01:27:54 +00002132{
nethercote71980f02004-01-24 18:18:54 +00002133 if (MAX_COMPACT_HELPERS <= VG_(n_compact_helpers)) {
2134 VG_(printf)("Can only register %d compact helpers\n",
2135 MAX_COMPACT_HELPERS);
2136 VG_(core_panic)("Too many compact helpers registered");
2137 }
2138 VG_(compact_helper_addrs)[VG_(n_compact_helpers)] = a;
2139 VG_(n_compact_helpers)++;
2140}
2141
2142/* Registers a function in noncompact_helper_addrs; noncompact_helper_offsets
2143 * is filled in later.
2144 */
2145void VG_(register_noncompact_helper)(Addr a)
2146{
2147 if (MAX_NONCOMPACT_HELPERS <= VG_(n_noncompact_helpers)) {
2148 VG_(printf)("Can only register %d non-compact helpers\n",
2149 MAX_NONCOMPACT_HELPERS);
2150 VG_(printf)("Try increasing MAX_NON_COMPACT_HELPERS\n");
2151 VG_(core_panic)("Too many non-compact helpers registered");
2152 }
2153 VG_(noncompact_helper_addrs)[VG_(n_noncompact_helpers)] = a;
2154 VG_(n_noncompact_helpers)++;
2155}
2156
nethercote996901a2004-08-03 13:29:09 +00002157/* Allocate offsets in baseBlock for the tool helpers */
nethercote71980f02004-01-24 18:18:54 +00002158static
2159void assign_helpers_in_baseBlock(UInt n, Int offsets[], Addr addrs[])
2160{
2161 UInt i;
2162 for (i = 0; i < n; i++)
nethercote2e05c332004-09-06 16:43:37 +00002163 offsets[i] = VG_(alloc_BaB_1_set)( addrs[i] );
nethercote71980f02004-01-24 18:18:54 +00002164}
2165
2166Bool VG_(need_to_handle_esp_assignment)(void)
2167{
2168 return ( VG_(defined_new_mem_stack_4)() ||
2169 VG_(defined_die_mem_stack_4)() ||
2170 VG_(defined_new_mem_stack_8)() ||
2171 VG_(defined_die_mem_stack_8)() ||
2172 VG_(defined_new_mem_stack_12)() ||
2173 VG_(defined_die_mem_stack_12)() ||
2174 VG_(defined_new_mem_stack_16)() ||
2175 VG_(defined_die_mem_stack_16)() ||
2176 VG_(defined_new_mem_stack_32)() ||
2177 VG_(defined_die_mem_stack_32)() ||
2178 VG_(defined_new_mem_stack)() ||
2179 VG_(defined_die_mem_stack)()
2180 );
2181}
2182
nethercote2e05c332004-09-06 16:43:37 +00002183// The low/high split is for x86, so that the more common helpers can be
2184// in the first 128 bytes of the start, which allows the use of a more
2185// compact addressing mode.
nethercote71980f02004-01-24 18:18:54 +00002186static void init_baseBlock ( Addr client_eip, Addr esp_at_startup )
2187{
nethercote2e05c332004-09-06 16:43:37 +00002188 VGA_(init_low_baseBlock)(client_eip, esp_at_startup);
nethercote71980f02004-01-24 18:18:54 +00002189
nethercote71980f02004-01-24 18:18:54 +00002190 /* Allocate slots for compact helpers */
2191 assign_helpers_in_baseBlock(VG_(n_compact_helpers),
2192 VG_(compact_helper_offsets),
2193 VG_(compact_helper_addrs));
2194
nethercote2e05c332004-09-06 16:43:37 +00002195 VGA_(init_high_baseBlock)(client_eip, esp_at_startup);
fitzhardingef0046f22003-12-18 02:39:22 +00002196
nethercote71980f02004-01-24 18:18:54 +00002197#define REG(kind, size) \
2198 if (VG_(defined_##kind##_mem_stack##size)()) \
2199 VG_(register_noncompact_helper)( \
2200 (Addr) VG_(tool_interface).track_##kind##_mem_stack##size );
2201 REG(new, _8);
2202 REG(new, _12);
2203 REG(new, _16);
2204 REG(new, _32);
2205 REG(new, );
2206 REG(die, _8);
2207 REG(die, _12);
2208 REG(die, _16);
2209 REG(die, _32);
2210 REG(die, );
2211#undef REG
fitzhardingef0046f22003-12-18 02:39:22 +00002212
nethercote71980f02004-01-24 18:18:54 +00002213 if (VG_(need_to_handle_esp_assignment)())
2214 VG_(register_noncompact_helper)((Addr) VG_(unknown_esp_update));
fitzhardingeb791a192003-12-18 07:22:44 +00002215
nethercote2e05c332004-09-06 16:43:37 +00002216 VGOFF_(helper_undefined_instruction)
2217 = VG_(alloc_BaB_1_set)( (Addr) & VG_(helper_undefined_instruction));
sewardjde4a1d02002-03-22 01:27:54 +00002218
nethercote71980f02004-01-24 18:18:54 +00002219 /* Allocate slots for noncompact helpers */
2220 assign_helpers_in_baseBlock(VG_(n_noncompact_helpers),
2221 VG_(noncompact_helper_offsets),
2222 VG_(noncompact_helper_addrs));
2223}
sewardjde4a1d02002-03-22 01:27:54 +00002224
nethercote81f9a6f2004-08-03 15:45:46 +00002225// Finds the baseBlock offset of a tool-specified helper.
2226// Searches through compacts first, then non-compacts.
2227Int VG_(helper_offset)(Addr a)
2228{
2229 UInt i;
2230 Char buf[100];
2231
2232 for (i = 0; i < VG_(n_compact_helpers); i++)
2233 if (VG_(compact_helper_addrs)[i] == a)
2234 return VG_(compact_helper_offsets)[i];
2235 for (i = 0; i < VG_(n_noncompact_helpers); i++)
2236 if (VG_(noncompact_helper_addrs)[i] == a)
2237 return VG_(noncompact_helper_offsets)[i];
2238
2239 /* Shouldn't get here */
2240 VG_(get_fnname) ( a, buf, 100 );
2241
2242 VG_(printf)(
2243 "\nCouldn't find offset of helper from its address (%p: %s).\n"
2244 "A helper function probably used hasn't been registered?\n\n", a, buf);
2245
2246 VG_(printf)(" compact helpers: ");
2247 for (i = 0; i < VG_(n_compact_helpers); i++)
2248 VG_(printf)("%p ", VG_(compact_helper_addrs)[i]);
2249
2250 VG_(printf)("\n non-compact helpers: ");
2251 for (i = 0; i < VG_(n_noncompact_helpers); i++)
2252 VG_(printf)("%p ", VG_(noncompact_helper_addrs)[i]);
2253
2254 VG_(printf)("\n");
2255 VG_(skin_panic)("Unfound helper");
2256}
2257
sewardj5f07b662002-04-23 16:52:51 +00002258
nethercote71980f02004-01-24 18:18:54 +00002259/*====================================================================*/
nethercote71980f02004-01-24 18:18:54 +00002260/*=== Initialise program data/text, etc. ===*/
2261/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +00002262
nethercote71980f02004-01-24 18:18:54 +00002263static void build_valgrind_map_callback
2264 ( Addr start, UInt size, Char rr, Char ww, Char xx,
2265 UInt dev, UInt ino, ULong foffset, const UChar* filename )
sewardjde4a1d02002-03-22 01:27:54 +00002266{
nethercote71980f02004-01-24 18:18:54 +00002267 UInt prot = 0;
2268 UInt flags = SF_MMAP|SF_NOSYMS;
2269 Bool is_stack_segment;
2270
2271 is_stack_segment =
2272 (start == VG_(clstk_base) && (start+size) == VG_(clstk_end));
2273
2274 /* Only record valgrind mappings for now, without loading any
2275 symbols. This is so we know where the free space is before we
2276 start allocating more memory (note: heap is OK, it's just mmap
2277 which is the problem here). */
nethercote820bd8c2004-09-07 23:04:49 +00002278 if (start >= VG_(valgrind_base) && (start+size-1) <= VG_(valgrind_last)) {
nethercote71980f02004-01-24 18:18:54 +00002279 flags |= SF_VALGRIND;
2280 VG_(map_file_segment)(start, size, prot, flags, dev, ino, foffset, filename);
2281 }
sewardjde4a1d02002-03-22 01:27:54 +00002282}
2283
nethercote71980f02004-01-24 18:18:54 +00002284// Global var used to pass local data to callback
2285Addr esp_at_startup___global_arg = 0;
sewardjde4a1d02002-03-22 01:27:54 +00002286
nethercote71980f02004-01-24 18:18:54 +00002287static void build_segment_map_callback
2288 ( Addr start, UInt size, Char rr, Char ww, Char xx,
2289 UInt dev, UInt ino, ULong foffset, const UChar* filename )
sewardj45b672d2003-07-25 19:58:11 +00002290{
nethercote71980f02004-01-24 18:18:54 +00002291 UInt prot = 0;
2292 UInt flags;
2293 Bool is_stack_segment;
2294 Addr r_esp;
sewardj45b672d2003-07-25 19:58:11 +00002295
nethercote71980f02004-01-24 18:18:54 +00002296 is_stack_segment
2297 = (start == VG_(clstk_base) && (start+size) == VG_(clstk_end));
fitzhardinge98abfc72003-12-16 02:05:15 +00002298
nethercote71980f02004-01-24 18:18:54 +00002299 if (rr == 'r') prot |= VKI_PROT_READ;
2300 if (ww == 'w') prot |= VKI_PROT_WRITE;
2301 if (xx == 'x') prot |= VKI_PROT_EXEC;
fitzhardinge98abfc72003-12-16 02:05:15 +00002302
nethercote71980f02004-01-24 18:18:54 +00002303 if (is_stack_segment)
2304 flags = SF_STACK | SF_GROWDOWN;
2305 else
2306 flags = SF_EXEC|SF_MMAP;
fitzhardinge98abfc72003-12-16 02:05:15 +00002307
nethercote71980f02004-01-24 18:18:54 +00002308 if (filename != NULL)
2309 flags |= SF_FILE;
fitzhardinge98abfc72003-12-16 02:05:15 +00002310
nethercote820bd8c2004-09-07 23:04:49 +00002311 if (start >= VG_(valgrind_base) && (start+size-1) <= VG_(valgrind_last))
nethercote71980f02004-01-24 18:18:54 +00002312 flags |= SF_VALGRIND;
fitzhardinge98abfc72003-12-16 02:05:15 +00002313
nethercote71980f02004-01-24 18:18:54 +00002314 VG_(map_file_segment)(start, size, prot, flags, dev, ino, foffset, filename);
fitzhardinge98abfc72003-12-16 02:05:15 +00002315
nethercote71980f02004-01-24 18:18:54 +00002316 if (VG_(is_client_addr)(start) && VG_(is_client_addr)(start+size-1))
2317 VG_TRACK( new_mem_startup, start, size, rr=='r', ww=='w', xx=='x' );
sewardj3e1eb1f2002-05-18 13:14:17 +00002318
nethercote71980f02004-01-24 18:18:54 +00002319 /* If this is the stack segment mark all below %esp as noaccess. */
2320 r_esp = esp_at_startup___global_arg;
2321 vg_assert(0 != r_esp);
2322 if (is_stack_segment) {
2323 if (0)
2324 VG_(message)(Vg_DebugMsg, "invalidating stack area: %x .. %x",
2325 start,r_esp);
2326 VG_TRACK( die_mem_stack, start, r_esp-start );
sewardjde4a1d02002-03-22 01:27:54 +00002327 }
sewardjde4a1d02002-03-22 01:27:54 +00002328}
2329
2330
nethercote71980f02004-01-24 18:18:54 +00002331/*====================================================================*/
2332/*=== Sanity check machinery (permanently engaged) ===*/
2333/*====================================================================*/
njn25e49d8e72002-09-23 09:36:25 +00002334
2335/* A fast sanity check -- suitable for calling circa once per
2336 millisecond. */
2337
nethercote885dd912004-08-03 23:14:00 +00002338void VG_(sanity_check_general) ( Bool force_expensive )
njn25e49d8e72002-09-23 09:36:25 +00002339{
njn37cea302002-09-30 11:24:00 +00002340 VGP_PUSHCC(VgpCoreCheapSanity);
2341
nethercote27fec902004-06-16 21:26:32 +00002342 if (VG_(clo_sanity_level) < 1) return;
njn25e49d8e72002-09-23 09:36:25 +00002343
2344 /* --- First do all the tests that we can do quickly. ---*/
2345
nethercote297effd2004-08-02 15:07:57 +00002346 sanity_fast_count++;
njn25e49d8e72002-09-23 09:36:25 +00002347
njn25e49d8e72002-09-23 09:36:25 +00002348 /* Check stuff pertaining to the memory check system. */
2349
2350 /* Check that nobody has spuriously claimed that the first or
2351 last 16 pages of memory have become accessible [...] */
njn37cea302002-09-30 11:24:00 +00002352 if (VG_(needs).sanity_checks) {
2353 VGP_PUSHCC(VgpSkinCheapSanity);
njn25e49d8e72002-09-23 09:36:25 +00002354 vg_assert(SK_(cheap_sanity_check)());
njn37cea302002-09-30 11:24:00 +00002355 VGP_POPCC(VgpSkinCheapSanity);
2356 }
njn25e49d8e72002-09-23 09:36:25 +00002357
2358 /* --- Now some more expensive checks. ---*/
2359
2360 /* Once every 25 times, check some more expensive stuff. */
2361 if ( force_expensive
nethercote27fec902004-06-16 21:26:32 +00002362 || VG_(clo_sanity_level) > 1
nethercote297effd2004-08-02 15:07:57 +00002363 || (VG_(clo_sanity_level) == 1 && (sanity_fast_count % 25) == 0)) {
njn25e49d8e72002-09-23 09:36:25 +00002364
njn37cea302002-09-30 11:24:00 +00002365 VGP_PUSHCC(VgpCoreExpensiveSanity);
nethercote297effd2004-08-02 15:07:57 +00002366 sanity_slow_count++;
njn25e49d8e72002-09-23 09:36:25 +00002367
nethercote885dd912004-08-03 23:14:00 +00002368 VG_(sanity_check_proxy)();
jsgf855d93d2003-10-13 22:26:55 +00002369
njn25e49d8e72002-09-23 09:36:25 +00002370# if 0
2371 { void zzzmemscan(void); zzzmemscan(); }
2372# endif
2373
nethercote297effd2004-08-02 15:07:57 +00002374 if ((sanity_fast_count % 250) == 0)
nethercote92e7b7f2004-08-07 17:52:25 +00002375 VG_(sanity_check_tt_tc)();
njn25e49d8e72002-09-23 09:36:25 +00002376
2377 if (VG_(needs).sanity_checks) {
njn37cea302002-09-30 11:24:00 +00002378 VGP_PUSHCC(VgpSkinExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002379 vg_assert(SK_(expensive_sanity_check)());
njn37cea302002-09-30 11:24:00 +00002380 VGP_POPCC(VgpSkinExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002381 }
2382 /*
nethercote297effd2004-08-02 15:07:57 +00002383 if ((sanity_fast_count % 500) == 0) VG_(mallocSanityCheckAll)();
njn25e49d8e72002-09-23 09:36:25 +00002384 */
njn37cea302002-09-30 11:24:00 +00002385 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002386 }
2387
nethercote27fec902004-06-16 21:26:32 +00002388 if (VG_(clo_sanity_level) > 1) {
njn37cea302002-09-30 11:24:00 +00002389 VGP_PUSHCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002390 /* Check sanity of the low-level memory manager. Note that bugs
2391 in the client's code can cause this to fail, so we don't do
2392 this check unless specially asked for. And because it's
2393 potentially very expensive. */
nethercote885dd912004-08-03 23:14:00 +00002394 VG_(sanity_check_malloc_all)();
njn37cea302002-09-30 11:24:00 +00002395 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002396 }
njn37cea302002-09-30 11:24:00 +00002397 VGP_POPCC(VgpCoreCheapSanity);
njn25e49d8e72002-09-23 09:36:25 +00002398}
nethercote71980f02004-01-24 18:18:54 +00002399
2400
2401/*====================================================================*/
2402/*=== main() ===*/
2403/*====================================================================*/
2404
nethercotec314eba2004-07-15 12:59:41 +00002405/*
2406 This code decides on the layout of the client and Valgrind address
nethercote996901a2004-08-03 13:29:09 +00002407 spaces, loads valgrind.so and the tool.so into the valgrind part,
nethercotec314eba2004-07-15 12:59:41 +00002408 loads the client executable (and the dynamic linker, if necessary)
2409 into the client part, and calls into Valgrind proper.
2410
2411 The code is careful not to allow spurious mappings to appear in the
2412 wrong parts of the address space. In particular, to make sure
2413 dlopen puts things in the right place, it will pad out the forbidden
2414 chunks of address space so that dlopen is forced to put things where
2415 we want them.
2416
2417 The memory map it creates is:
2418
2419 CLIENT_BASE +-------------------------+
2420 | client address space |
2421 : :
2422 : :
2423 | client stack |
2424 client_end +-------------------------+
2425 | redzone |
2426 shadow_base +-------------------------+
2427 | |
nethercote996901a2004-08-03 13:29:09 +00002428 : shadow memory for tools :
nethercotec314eba2004-07-15 12:59:41 +00002429 | (may be 0 sized) |
2430 shadow_end +-------------------------+
nethercotec314eba2004-07-15 12:59:41 +00002431 valgrind_base +-------------------------+
2432 | kickstart executable |
2433 | valgrind heap vvvvvvvvv| (barely used)
2434 - -
2435 | valgrind .so files |
2436 | and mappings |
2437 - -
2438 | valgrind stack ^^^^^^^^^|
nethercote820bd8c2004-09-07 23:04:49 +00002439 valgrind_last +-------------------------+
nethercotec314eba2004-07-15 12:59:41 +00002440 : kernel :
2441
2442 Nb: Before we can do general allocations with VG_(arena_malloc)() and
2443 VG_(mmap)(), we need to build the segment skip-list, so we know where
2444 we can put things. However, building that structure requires
2445 allocating memory. So we need to a bootstrapping process. It's done
2446 by making VG_(arena_malloc)() have a special static superblock that's
2447 used for the first 1MB's worth of allocations. This is enough to
2448 build the segment skip-list.
2449*/
2450
nethercote31779c72004-07-30 21:50:15 +00002451static int prmap(char *start, char *end, const char *perm, off_t off,
2452 int maj, int min, int ino, void* dummy) {
thughes4ad52d02004-06-27 17:37:21 +00002453 printf("mapping %10p-%10p %s %02x:%02x %d\n",
2454 start, end, perm, maj, min, ino);
2455 return True;
2456}
2457
nethercote71980f02004-01-24 18:18:54 +00002458int main(int argc, char **argv)
2459{
2460 char **cl_argv;
2461 const char *tool = NULL;
2462 const char *exec = NULL;
2463 char *preload; /* tool-specific LD_PRELOAD .so */
2464 char **env;
nethercote6c999f22004-01-31 22:55:15 +00002465 Int need_help = 0; // 0 = no, 1 = --help, 2 = --help-debug
nethercote71980f02004-01-24 18:18:54 +00002466 struct exeinfo info;
2467 ToolInfo *toolinfo = NULL;
2468 void *tool_dlhandle;
2469 Addr client_eip;
2470 Addr esp_at_startup; /* client's %esp at the point we gained control. */
2471 UInt * client_auxv;
2472 VgSchedReturnCode src;
nethercote47dd12c2004-06-22 14:18:42 +00002473 Int exitcode = 0;
nethercote238a3c32004-08-09 13:13:31 +00002474 Int fatal_sigNo = -1;
fitzhardingeb50068f2004-02-24 23:42:55 +00002475 vki_rlimit zero = { 0, 0 };
nethercote31779c72004-07-30 21:50:15 +00002476 Int padfile;
nethercote759dda32004-08-07 18:16:56 +00002477 ThreadId last_run_tid = 0; // Last thread the scheduler ran.
2478
nethercote71980f02004-01-24 18:18:54 +00002479
2480 //============================================================
2481 // Nb: startup is complex. Prerequisites are shown at every step.
2482 //
2483 // *** Be very careful when messing with the order ***
2484 //============================================================
2485
nethercotef4928da2004-06-15 10:54:40 +00002486 //============================================================
2487 // Command line argument handling order:
2488 // * If --help/--help-debug are present, show usage message
2489 // (if --tool is also present, that includes the tool-specific usage)
2490 // * Then, if --tool is missing, abort with error msg
2491 // * Then, if client is missing, abort with error msg
2492 // * Then, if any cmdline args are bad, abort with error msg
2493 //============================================================
2494
fitzhardingeb50068f2004-02-24 23:42:55 +00002495 // Get the current process datasize rlimit, and set it to zero.
2496 // This prevents any internal uses of brk() from having any effect.
2497 // We remember the old value so we can restore it on exec, so that
2498 // child processes will have a reasonable brk value.
2499 VG_(getrlimit)(VKI_RLIMIT_DATA, &VG_(client_rlimit_data));
2500 zero.rlim_max = VG_(client_rlimit_data).rlim_max;
2501 VG_(setrlimit)(VKI_RLIMIT_DATA, &zero);
thughesc37184f2004-09-11 14:16:57 +00002502
2503 // Get the current process stack rlimit.
2504 VG_(getrlimit)(VKI_RLIMIT_STACK, &VG_(client_rlimit_stack));
2505
nethercote71980f02004-01-24 18:18:54 +00002506 //--------------------------------------------------------------
2507 // Check we were launched by stage1
nethercotec314eba2004-07-15 12:59:41 +00002508 // p: n/a
nethercote71980f02004-01-24 18:18:54 +00002509 //--------------------------------------------------------------
nethercote31779c72004-07-30 21:50:15 +00002510 padfile = scan_auxv();
nethercote71980f02004-01-24 18:18:54 +00002511
2512 if (0) {
nethercote71980f02004-01-24 18:18:54 +00002513 printf("========== main() ==========\n");
nethercote31779c72004-07-30 21:50:15 +00002514 foreach_map(prmap, /*dummy*/NULL);
nethercote71980f02004-01-24 18:18:54 +00002515 }
2516
2517 //--------------------------------------------------------------
2518 // Look for alternative libdir
2519 // p: n/a
2520 //--------------------------------------------------------------
2521 { char *cp = getenv(VALGRINDLIB);
2522 if (cp != NULL)
2523 VG_(libdir) = cp;
2524 }
2525
2526 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002527 // Get valgrind args + client args (inc. from VALGRIND_OPTS/.valgrindrc).
2528 // Pre-process the command line.
2529 // p: n/a
2530 //--------------------------------------------------------------
nethercotef6a1d502004-08-09 12:21:57 +00002531 get_command_line(argc, argv, &vg_argc, &vg_argv, &cl_argv);
nethercote71980f02004-01-24 18:18:54 +00002532 pre_process_cmd_line_options(&need_help, &tool, &exec);
2533
2534 //==============================================================
2535 // Nb: once a tool is specified, the tool.so must be loaded even if
2536 // they specified --help or didn't specify a client program.
2537 //==============================================================
2538
2539 //--------------------------------------------------------------
2540 // With client padded out, map in tool
nethercote71980f02004-01-24 18:18:54 +00002541 // p: set-libdir [for VG_(libdir)]
2542 // p: pre_process_cmd_line_options() [for 'tool']
2543 //--------------------------------------------------------------
2544 load_tool(tool, &tool_dlhandle, &toolinfo, &preload);
2545
2546 //==============================================================
2547 // Can use VG_(malloc)() and VG_(arena_malloc)() only after load_tool()
nethercotec314eba2004-07-15 12:59:41 +00002548 // -- redzone size is now set. This is checked by vg_malloc2.c.
nethercote71980f02004-01-24 18:18:54 +00002549 //==============================================================
2550
2551 //--------------------------------------------------------------
2552 // Finalise address space layout
nethercote31779c72004-07-30 21:50:15 +00002553 // p: load_tool() [for 'toolinfo']
nethercote71980f02004-01-24 18:18:54 +00002554 //--------------------------------------------------------------
nethercote31779c72004-07-30 21:50:15 +00002555 layout_remaining_space( (Addr) & argc, toolinfo->shadow_ratio );
nethercote71980f02004-01-24 18:18:54 +00002556
2557 //--------------------------------------------------------------
2558 // Load client executable, finding in $PATH if necessary
nethercote71980f02004-01-24 18:18:54 +00002559 // p: pre_process_cmd_line_options() [for 'exec', 'need_help']
2560 // p: layout_remaining_space [so there's space]
2561 //--------------------------------------------------------------
nethercotef4928da2004-06-15 10:54:40 +00002562 load_client(cl_argv, exec, need_help, &info, &client_eip);
nethercote71980f02004-01-24 18:18:54 +00002563
2564 //--------------------------------------------------------------
2565 // Everything in place, unpad us
2566 // p: layout_remaining_space() [everything must be mapped in before now]
2567 // p: load_client() [ditto]
2568 //--------------------------------------------------------------
nethercote31779c72004-07-30 21:50:15 +00002569 as_unpad((void *)VG_(shadow_end), (void *)~0, padfile);
2570 as_closepadfile(padfile); // no more padding
nethercote71980f02004-01-24 18:18:54 +00002571
2572 //--------------------------------------------------------------
2573 // Set up client's environment
2574 // p: set-libdir [for VG_(libdir)]
2575 // p: load_tool() [for 'preload']
2576 //--------------------------------------------------------------
2577 env = fix_environment(environ, preload);
2578
2579 //--------------------------------------------------------------
nethercote5ee67ca2004-06-22 14:00:09 +00002580 // Setup client stack, eip, and VG_(client_arg[cv])
nethercote71980f02004-01-24 18:18:54 +00002581 // p: load_client() [for 'info']
2582 // p: fix_environment() [for 'env']
2583 //--------------------------------------------------------------
2584 esp_at_startup = setup_client_stack(cl_argv, env, &info, &client_auxv);
2585
2586 if (0)
nethercote6a27d832004-09-07 10:17:02 +00002587 printf("entry=%p client esp=%p vg_argc=%d brkbase=%p\n",
2588 (void*)client_eip, (void*)esp_at_startup, vg_argc,
2589 (void*)VG_(brk_base));
nethercote71980f02004-01-24 18:18:54 +00002590
2591 //==============================================================
2592 // Finished setting up operating environment. Now initialise
2593 // Valgrind. (This is where the old VG_(main)() started.)
2594 //==============================================================
2595
2596 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002597 // atfork
2598 // p: n/a
2599 //--------------------------------------------------------------
2600 VG_(atfork)(NULL, NULL, newpid);
2601 newpid(VG_INVALID_THREADID);
2602
2603 //--------------------------------------------------------------
2604 // setup file descriptors
2605 // p: n/a
2606 //--------------------------------------------------------------
2607 setup_file_descriptors();
2608
2609 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002610 // Read /proc/self/maps into a buffer
2611 // p: all memory layout, environment setup [so memory maps are right]
2612 //--------------------------------------------------------------
2613 VG_(read_procselfmaps)();
2614
2615 //--------------------------------------------------------------
2616 // Build segment map (Valgrind segments only)
2617 // p: read proc/self/maps
2618 // p: sk_pre_clo_init() [to setup new_mem_startup tracker]
2619 //--------------------------------------------------------------
2620 VG_(parse_procselfmaps) ( build_valgrind_map_callback );
2621
2622 //==============================================================
2623 // Can use VG_(arena_malloc)() with non-CORE arena after segments set up
2624 //==============================================================
2625
2626 //--------------------------------------------------------------
2627 // Init tool: pre_clo_init, process cmd line, post_clo_init
2628 // p: setup_client_stack() [for 'VG_(client_arg[cv]']
2629 // p: load_tool() [for 'tool']
2630 // p: setup_file_descriptors() [for 'VG_(fd_xxx_limit)']
2631 // p: parse_procselfmaps [so VG segments are setup so tool can
2632 // call VG_(malloc)]
nethercote71980f02004-01-24 18:18:54 +00002633 //--------------------------------------------------------------
2634 (*toolinfo->sk_pre_clo_init)();
2635 VG_(tool_init_dlsym)(tool_dlhandle);
2636 VG_(sanity_check_needs)();
2637
nethercotef4928da2004-06-15 10:54:40 +00002638 // If --tool and --help/--help-debug was given, now give the core+tool
2639 // help message
nethercotef4928da2004-06-15 10:54:40 +00002640 if (need_help) {
2641 usage(/*--help-debug?*/2 == need_help);
2642 }
nethercotec314eba2004-07-15 12:59:41 +00002643 process_cmd_line_options(client_auxv, tool);
2644
2645 SK_(post_clo_init)();
nethercotef4928da2004-06-15 10:54:40 +00002646
2647 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002648 // Build segment map (all segments)
2649 // p: setup_client_stack() [for 'esp_at_startup']
2650 // p: init tool [for 'new_mem_startup']
nethercote71980f02004-01-24 18:18:54 +00002651 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002652 esp_at_startup___global_arg = esp_at_startup;
2653 VG_(parse_procselfmaps) ( build_segment_map_callback ); /* everything */
2654 esp_at_startup___global_arg = 0;
2655
2656 //--------------------------------------------------------------
nethercotef84f6952004-07-15 14:58:33 +00002657 // Protect client trampoline page (which is also sysinfo stuff)
2658 // p: segment stuff [otherwise get seg faults...]
nethercotec314eba2004-07-15 12:59:41 +00002659 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002660 VG_(mprotect)( (void *)VG_(client_trampoline_code),
2661 VG_(trampoline_code_length), VKI_PROT_READ|VKI_PROT_EXEC );
2662
2663 //==============================================================
2664 // Can use VG_(map)() after segments set up
2665 //==============================================================
nethercote71980f02004-01-24 18:18:54 +00002666
2667 //--------------------------------------------------------------
2668 // Allow GDB attach
2669 // p: process_cmd_line_options() [for VG_(clo_wait_for_gdb)]
2670 //--------------------------------------------------------------
2671 /* Hook to delay things long enough so we can get the pid and
2672 attach GDB in another shell. */
2673 if (VG_(clo_wait_for_gdb)) {
2674 VG_(printf)("pid=%d\n", VG_(getpid)());
2675 /* do "jump *$eip" to skip this in gdb */
2676 VG_(do_syscall)(__NR_pause);
2677 }
2678
2679 //--------------------------------------------------------------
nethercote1d447092004-02-01 17:29:59 +00002680 // Set up baseBlock
nethercote71980f02004-01-24 18:18:54 +00002681 // p: {pre,post}_clo_init() [for tool helper registration]
2682 // load_client() [for 'client_eip']
2683 // setup_client_stack() [for 'esp_at_startup']
2684 //--------------------------------------------------------------
2685 init_baseBlock(client_eip, esp_at_startup);
2686
2687 //--------------------------------------------------------------
2688 // Search for file descriptors that are inherited from our parent
2689 // p: process_cmd_line_options [for VG_(clo_track_fds)]
2690 //--------------------------------------------------------------
2691 if (VG_(clo_track_fds))
2692 VG_(init_preopened_fds)();
2693
2694 //--------------------------------------------------------------
2695 // Initialise the scheduler
2696 // p: init_baseBlock() [baseBlock regs copied into VG_(threads)[1]]
2697 // p: setup_file_descriptors() [else VG_(safe_fd)() breaks]
2698 //--------------------------------------------------------------
2699 VG_(scheduler_init)();
2700
2701 //--------------------------------------------------------------
2702 // Set up the ProxyLWP machinery
2703 // p: VG_(scheduler_init)()? [XXX: subtle dependency?]
nethercote71980f02004-01-24 18:18:54 +00002704 //--------------------------------------------------------------
2705 VG_(proxy_init)();
2706
2707 //--------------------------------------------------------------
2708 // Initialise the signal handling subsystem
2709 // p: VG_(atfork)(NULL, NULL, newpid) [else problems with sigmasks]
2710 // p: VG_(proxy_init)() [else breaks...]
2711 //--------------------------------------------------------------
2712 // Nb: temporarily parks the saved blocking-mask in saved_sigmask.
2713 VG_(sigstartup_actions)();
2714
2715 //--------------------------------------------------------------
2716 // Perhaps we're profiling Valgrind?
2717 // p: process_cmd_line_options() [for VG_(clo_profile)]
2718 // p: others?
2719 //
2720 // XXX: this seems to be broken? It always says the tool wasn't built
2721 // for profiling; vg_profile.c's functions don't seem to be overriding
2722 // vg_dummy_profile.c's?
2723 //
2724 // XXX: want this as early as possible. Looking for --profile
2725 // in pre_process_cmd_line_options() could get it earlier.
2726 //--------------------------------------------------------------
2727 if (VG_(clo_profile))
2728 VGP_(init_profiling)();
2729
2730 VGP_PUSHCC(VgpStartup);
2731
2732 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002733 // Read suppression file
2734 // p: process_cmd_line_options() [for VG_(clo_suppressions)]
2735 //--------------------------------------------------------------
2736 if (VG_(needs).core_errors || VG_(needs).skin_errors)
2737 VG_(load_suppressions)();
2738
2739 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002740 // Initialise translation table and translation cache
2741 // p: read_procselfmaps [so the anonymous mmaps for the TT/TC
2742 // aren't identified as part of the client, which would waste
2743 // > 20M of virtual address space.]
2744 //--------------------------------------------------------------
2745 VG_(init_tt_tc)();
2746
2747 //--------------------------------------------------------------
2748 // Read debug info to find glibc entry points to intercept
2749 // p: parse_procselfmaps? [XXX for debug info?]
2750 // p: init_tt_tc? [XXX ???]
2751 //--------------------------------------------------------------
2752 VG_(setup_code_redirect_table)();
2753
2754 //--------------------------------------------------------------
2755 // Verbosity message
2756 // p: end_rdtsc_calibration [so startup message is printed first]
2757 //--------------------------------------------------------------
2758 if (VG_(clo_verbosity) == 1)
2759 VG_(message)(Vg_UserMsg, "For more details, rerun with: -v");
2760 if (VG_(clo_verbosity) > 0)
2761 VG_(message)(Vg_UserMsg, "");
2762
2763 //--------------------------------------------------------------
2764 // Setup pointercheck
2765 // p: process_cmd_line_options() [for VG_(clo_pointercheck)]
2766 //--------------------------------------------------------------
nethercote775508a2004-09-07 22:38:23 +00002767 if (VG_(clo_pointercheck))
2768 VG_(clo_pointercheck) = VGA_(setup_pointercheck)();
nethercote71980f02004-01-24 18:18:54 +00002769
nethercote71980f02004-01-24 18:18:54 +00002770 //--------------------------------------------------------------
2771 // Run!
2772 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002773 VGP_POPCC(VgpStartup);
2774 VGP_PUSHCC(VgpSched);
2775
nethercote238a3c32004-08-09 13:13:31 +00002776 src = VG_(scheduler)( &exitcode, &last_run_tid, &fatal_sigNo );
nethercote71980f02004-01-24 18:18:54 +00002777
nethercote238a3c32004-08-09 13:13:31 +00002778 VGP_POPCC(VgpSched);
nethercote71980f02004-01-24 18:18:54 +00002779
2780
2781 //--------------------------------------------------------------
2782 // Finalisation: cleanup, messages, etc. Order no so important, only
2783 // affects what order the messages come.
2784 //--------------------------------------------------------------
2785 if (VG_(clo_verbosity) > 0)
2786 VG_(message)(Vg_UserMsg, "");
2787
2788 if (src == VgSrc_Deadlock) {
2789 VG_(message)(Vg_UserMsg,
2790 "Warning: pthread scheduler exited due to deadlock");
2791 }
2792
2793 /* Print out file descriptor summary and stats. */
2794 if (VG_(clo_track_fds))
nethercote3a42fb82004-08-03 18:08:50 +00002795 VG_(show_open_fds)();
nethercote71980f02004-01-24 18:18:54 +00002796
2797 if (VG_(needs).core_errors || VG_(needs).skin_errors)
2798 VG_(show_all_errors)();
2799
nethercote47dd12c2004-06-22 14:18:42 +00002800 SK_(fini)( exitcode );
nethercote71980f02004-01-24 18:18:54 +00002801
nethercote885dd912004-08-03 23:14:00 +00002802 VG_(sanity_check_general)( True /*include expensive checks*/ );
nethercote71980f02004-01-24 18:18:54 +00002803
2804 if (VG_(clo_verbosity) > 1)
nethercote3a42fb82004-08-03 18:08:50 +00002805 print_all_stats();
nethercote71980f02004-01-24 18:18:54 +00002806
nethercote71980f02004-01-24 18:18:54 +00002807 if (VG_(clo_profile))
2808 VGP_(done_profiling)();
2809
nethercote71980f02004-01-24 18:18:54 +00002810 /* We're exiting, so nuke all the threads and clean up the proxy LWPs */
2811 vg_assert(src == VgSrc_FatalSig ||
nethercote759dda32004-08-07 18:16:56 +00002812 VG_(threads)[last_run_tid].status == VgTs_Runnable ||
2813 VG_(threads)[last_run_tid].status == VgTs_WaitJoiner);
nethercote71980f02004-01-24 18:18:54 +00002814 VG_(nuke_all_threads_except)(VG_INVALID_THREADID);
2815
2816 //--------------------------------------------------------------
2817 // Exit, according to the scheduler's return code
2818 //--------------------------------------------------------------
2819 switch (src) {
2820 case VgSrc_ExitSyscall: /* the normal way out */
nethercote759dda32004-08-07 18:16:56 +00002821 vg_assert(last_run_tid > 0 && last_run_tid < VG_N_THREADS);
nethercote71980f02004-01-24 18:18:54 +00002822 VG_(proxy_shutdown)();
2823
2824 /* The thread's %EBX at the time it did __NR_exit() will hold
2825 the arg to __NR_exit(), so we just do __NR_exit() with
2826 that arg. */
nethercote47dd12c2004-06-22 14:18:42 +00002827 VG_(exit)( exitcode );
nethercote71980f02004-01-24 18:18:54 +00002828 /* NOT ALIVE HERE! */
2829 VG_(core_panic)("entered the afterlife in main() -- ExitSyscall");
2830 break; /* what the hell :) */
2831
2832 case VgSrc_Deadlock:
2833 /* Just exit now. No point in continuing. */
2834 VG_(proxy_shutdown)();
2835 VG_(exit)(0);
2836 VG_(core_panic)("entered the afterlife in main() -- Deadlock");
2837 break;
2838
nethercote71980f02004-01-24 18:18:54 +00002839 case VgSrc_FatalSig:
2840 /* We were killed by a fatal signal, so replicate the effect */
nethercote238a3c32004-08-09 13:13:31 +00002841 vg_assert(fatal_sigNo != -1);
2842 VG_(kill_self)(fatal_sigNo);
nethercote71980f02004-01-24 18:18:54 +00002843 VG_(core_panic)("main(): signal was supposed to be fatal");
2844 break;
2845
2846 default:
2847 VG_(core_panic)("main(): unexpected scheduler return code");
2848 }
2849
2850 abort();
2851}
2852
2853
sewardjde4a1d02002-03-22 01:27:54 +00002854/*--------------------------------------------------------------------*/
2855/*--- end vg_main.c ---*/
2856/*--------------------------------------------------------------------*/