blob: a077d58c0d9d0d3e0a01845bc3de0669f6453916 [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;
554 int env_arg_count, f1_arg_count, f2_arg_count;
555
556 env_arg_count = count_args(env_clo);
557 f1_arg_count = count_args(f1_clo);
558 f2_arg_count = count_args(f2_clo);
559
560 if (0)
561 printf("extra-argc=%d %d %d\n",
562 env_arg_count, f1_arg_count, f2_arg_count);
563
564 /* +2: +1 for null-termination, +1 for added '--' */
nethercotef6a1d502004-08-09 12:21:57 +0000565 from = vg_argv0;
566 vg_argv0 = malloc( (vg_argc0 + env_arg_count + f1_arg_count
nethercote71980f02004-01-24 18:18:54 +0000567 + f2_arg_count + 2) * sizeof(char **));
nethercotef6a1d502004-08-09 12:21:57 +0000568 vg_assert(vg_argv0);
569 to = vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000570
571 /* copy argv[0] */
572 *to++ = *from++;
573
574 /* Copy extra args from env var and file, in the order: ~/.valgrindrc,
575 * $VALGRIND_OPTS, ./.valgrindrc -- more local options are put later
576 * to override less local ones. */
577 to = copy_args(f1_clo, to);
578 to = copy_args(env_clo, to);
579 to = copy_args(f2_clo, to);
580
581 /* copy original arguments, stopping at command or -- */
582 while (*from) {
583 if (**from != '-')
584 break;
585 if (VG_STREQ(*from, "--")) {
586 from++; /* skip -- */
587 break;
588 }
589 *to++ = *from++;
590 }
591
592 /* add -- */
593 *to++ = "--";
594
nethercotef6a1d502004-08-09 12:21:57 +0000595 vg_argc0 = to - vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000596
597 /* copy rest of original command line, then NULL */
598 while (*from) *to++ = *from++;
599 *to = NULL;
600 }
601
nethercotef6a1d502004-08-09 12:21:57 +0000602 *vg_argc_inout = vg_argc0;
603 *vg_argv_inout = vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000604}
605
nethercotef6a1d502004-08-09 12:21:57 +0000606#define VG_CLO_SEP '\01'
607
nethercote71980f02004-01-24 18:18:54 +0000608static void get_command_line( int argc, char** argv,
609 Int* vg_argc_out, Char*** vg_argv_out,
610 char*** cl_argv_out )
611{
nethercotef6a1d502004-08-09 12:21:57 +0000612 int vg_argc0;
613 char** vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000614 char** cl_argv;
615 char* env_clo = getenv(VALGRINDCLO);
616
617 if (env_clo != NULL && *env_clo != '\0') {
618 char *cp;
619 char **cpp;
620
nethercotef6a1d502004-08-09 12:21:57 +0000621 /* OK, VALGRINDCLO is set, which means we must be a child of another
622 Valgrind process using --trace-children, so we're getting all our
623 arguments from VALGRINDCLO, and the entire command line belongs to
624 the client (including argv[0]) */
625 vg_argc0 = 1; /* argv[0] */
nethercote71980f02004-01-24 18:18:54 +0000626 for (cp = env_clo; *cp; cp++)
nethercotef6a1d502004-08-09 12:21:57 +0000627 if (*cp == VG_CLO_SEP)
628 vg_argc0++;
nethercote71980f02004-01-24 18:18:54 +0000629
nethercotef6a1d502004-08-09 12:21:57 +0000630 vg_argv0 = malloc(sizeof(char **) * (vg_argc0 + 1));
631 vg_assert(vg_argv0);
nethercote71980f02004-01-24 18:18:54 +0000632
nethercotef6a1d502004-08-09 12:21:57 +0000633 cpp = vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000634
635 *cpp++ = "valgrind"; /* nominal argv[0] */
636 *cpp++ = env_clo;
637
nethercotef6a1d502004-08-09 12:21:57 +0000638 // Replace the VG_CLO_SEP args separator with '\0'
nethercote71980f02004-01-24 18:18:54 +0000639 for (cp = env_clo; *cp; cp++) {
nethercotef6a1d502004-08-09 12:21:57 +0000640 if (*cp == VG_CLO_SEP) {
nethercote71980f02004-01-24 18:18:54 +0000641 *cp++ = '\0'; /* chop it up in place */
642 *cpp++ = cp;
643 }
644 }
645 *cpp = NULL;
646 cl_argv = argv;
647
648 } else {
649 /* Count the arguments on the command line. */
nethercotef6a1d502004-08-09 12:21:57 +0000650 vg_argv0 = argv;
nethercote71980f02004-01-24 18:18:54 +0000651
nethercotef6a1d502004-08-09 12:21:57 +0000652 for (vg_argc0 = 1; vg_argc0 < argc; vg_argc0++) {
653 if (argv[vg_argc0][0] != '-') /* exe name */
nethercote71980f02004-01-24 18:18:54 +0000654 break;
nethercotef6a1d502004-08-09 12:21:57 +0000655 if (VG_STREQ(argv[vg_argc0], "--")) { /* dummy arg */
656 vg_argc0++;
nethercote71980f02004-01-24 18:18:54 +0000657 break;
658 }
659 }
nethercotef6a1d502004-08-09 12:21:57 +0000660 cl_argv = &argv[vg_argc0];
nethercote71980f02004-01-24 18:18:54 +0000661
662 /* Get extra args from VALGRIND_OPTS and .valgrindrc files.
nethercotef6a1d502004-08-09 12:21:57 +0000663 Note we don't do this if getting args from VALGRINDCLO, as
664 those extra args will already be present in VALGRINDCLO. */
665 augment_command_line(&vg_argc0, &vg_argv0);
nethercote71980f02004-01-24 18:18:54 +0000666 }
667
668 if (0) {
669 Int i;
nethercotef6a1d502004-08-09 12:21:57 +0000670 for (i = 0; i < vg_argc0; i++)
671 printf("vg_argv0[%d]=\"%s\"\n", i, vg_argv0[i]);
nethercote71980f02004-01-24 18:18:54 +0000672 }
673
nethercotef6a1d502004-08-09 12:21:57 +0000674 *vg_argc_out = vg_argc0;
675 *vg_argv_out = (Char**)vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000676 *cl_argv_out = cl_argv;
677}
678
679
680/*====================================================================*/
681/*=== Environment and stack setup ===*/
682/*====================================================================*/
683
684/* Scan a colon-separated list, and call a function on each element.
685 The string must be mutable, because we insert a temporary '\0', but
thughes4ad52d02004-06-27 17:37:21 +0000686 the string will end up unmodified. (*func) should return True if it
nethercote71980f02004-01-24 18:18:54 +0000687 doesn't need to see any more.
thughes4ad52d02004-06-27 17:37:21 +0000688
689 This routine will return True if (*func) returns True and False if
690 it reaches the end of the list without that happening.
nethercote71980f02004-01-24 18:18:54 +0000691*/
thughes4ad52d02004-06-27 17:37:21 +0000692static Bool scan_colsep(char *colsep, Bool (*func)(const char *))
nethercote71980f02004-01-24 18:18:54 +0000693{
694 char *cp, *entry;
695 int end;
696
697 if (colsep == NULL ||
698 *colsep == '\0')
thughes4ad52d02004-06-27 17:37:21 +0000699 return False;
nethercote71980f02004-01-24 18:18:54 +0000700
701 entry = cp = colsep;
702
703 do {
704 end = (*cp == '\0');
705
706 if (*cp == ':' || *cp == '\0') {
707 char save = *cp;
708
709 *cp = '\0';
thughes21942d92004-07-12 09:35:37 +0000710 if ((*func)(entry)) {
711 *cp = save;
thughes4ad52d02004-06-27 17:37:21 +0000712 return True;
thughes21942d92004-07-12 09:35:37 +0000713 }
nethercote71980f02004-01-24 18:18:54 +0000714 *cp = save;
715 entry = cp+1;
716 }
717 cp++;
718 } while(!end);
thughes4ad52d02004-06-27 17:37:21 +0000719
720 return False;
721}
722
723static Bool contains(const char *p) {
724 if (VG_STREQ(p, VG_(libdir))) {
725 return True;
726 }
727 return False;
nethercote71980f02004-01-24 18:18:54 +0000728}
729
730/* Prepare the client's environment. This is basically a copy of our
731 environment, except:
732 1. LD_LIBRARY_PATH=$VALGRINDLIB:$LD_LIBRARY_PATH
733 2. LD_PRELOAD=$VALGRINDLIB/vg_inject.so:($VALGRINDLIB/vgpreload_TOOL.so:)?$LD_PRELOAD
734
735 If any of these is missing, then it is added.
736
737 Yummy. String hacking in C.
738
739 If this needs to handle any more variables it should be hacked
740 into something table driven.
741 */
742static char **fix_environment(char **origenv, const char *preload)
743{
744 static const char inject_so[] = "vg_inject.so";
745 static const char ld_library_path[] = "LD_LIBRARY_PATH=";
746 static const char ld_preload[] = "LD_PRELOAD=";
747 static const char valgrind_clo[] = VALGRINDCLO "=";
748 static const int ld_library_path_len = sizeof(ld_library_path)-1;
749 static const int ld_preload_len = sizeof(ld_preload)-1;
750 static const int valgrind_clo_len = sizeof(valgrind_clo)-1;
751 int ld_preload_done = 0;
752 int ld_library_path_done = 0;
753 char *inject_path;
754 int inject_path_len;
755 int vgliblen = strlen(VG_(libdir));
756 char **cpp;
757 char **ret;
758 int envc;
759 const int preloadlen = (preload == NULL) ? 0 : strlen(preload);
760
761 /* Find the vg_inject.so; also make room for the tool preload
762 library */
763 inject_path_len = sizeof(inject_so) + vgliblen + preloadlen + 16;
764 inject_path = malloc(inject_path_len);
nethercote7c018f42004-07-17 16:40:50 +0000765 vg_assert(inject_path);
nethercote71980f02004-01-24 18:18:54 +0000766
767 if (preload)
768 snprintf(inject_path, inject_path_len, "%s/%s:%s",
769 VG_(libdir), inject_so, preload);
770 else
771 snprintf(inject_path, inject_path_len, "%s/%s",
772 VG_(libdir), inject_so);
773
774 /* Count the original size of the env */
775 envc = 0; /* trailing NULL */
776 for (cpp = origenv; cpp && *cpp; cpp++)
777 envc++;
778
779 /* Allocate a new space */
780 ret = malloc(sizeof(char *) * (envc+3+1)); /* 3 new entries + NULL */
nethercote7c018f42004-07-17 16:40:50 +0000781 vg_assert(ret);
nethercote71980f02004-01-24 18:18:54 +0000782
783 /* copy it over */
784 for (cpp = ret; *origenv; )
785 *cpp++ = *origenv++;
786 *cpp = NULL;
787
788 vg_assert(envc == (cpp - ret));
789
790 /* Walk over the new environment, mashing as we go */
791 for (cpp = ret; cpp && *cpp; cpp++) {
792 if (memcmp(*cpp, ld_library_path, ld_library_path_len) == 0) {
nethercote71980f02004-01-24 18:18:54 +0000793 /* If the LD_LIBRARY_PATH already contains libdir, then don't
794 bother adding it again, even if it isn't the first (it
795 seems that the Java runtime will keep reexecing itself
796 unless its paths are at the front of LD_LIBRARY_PATH) */
thughes4ad52d02004-06-27 17:37:21 +0000797 if (!scan_colsep(*cpp + ld_library_path_len, contains)) {
nethercote71980f02004-01-24 18:18:54 +0000798 int len = strlen(*cpp) + vgliblen*2 + 16;
799 char *cp = malloc(len);
nethercote7c018f42004-07-17 16:40:50 +0000800 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000801
802 snprintf(cp, len, "%s%s:%s",
803 ld_library_path, VG_(libdir),
804 (*cpp)+ld_library_path_len);
805
806 *cpp = cp;
807 }
808
809 ld_library_path_done = 1;
810 } else if (memcmp(*cpp, ld_preload, ld_preload_len) == 0) {
811 int len = strlen(*cpp) + inject_path_len;
812 char *cp = malloc(len);
nethercote7c018f42004-07-17 16:40:50 +0000813 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000814
815 snprintf(cp, len, "%s%s:%s",
816 ld_preload, inject_path, (*cpp)+ld_preload_len);
817
818 *cpp = cp;
819
820 ld_preload_done = 1;
821 } else if (memcmp(*cpp, valgrind_clo, valgrind_clo_len) == 0) {
822 *cpp = "";
823 }
824 }
825
826 /* Add the missing bits */
827
828 if (!ld_library_path_done) {
829 int len = ld_library_path_len + vgliblen*2 + 16;
830 char *cp = malloc(len);
nethercote7c018f42004-07-17 16:40:50 +0000831 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000832
833 snprintf(cp, len, "%s%s", ld_library_path, VG_(libdir));
834
835 ret[envc++] = cp;
836 }
837
838 if (!ld_preload_done) {
839 int len = ld_preload_len + inject_path_len;
840 char *cp = malloc(len);
nethercote7c018f42004-07-17 16:40:50 +0000841 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000842
843 snprintf(cp, len, "%s%s",
844 ld_preload, inject_path);
845
846 ret[envc++] = cp;
847 }
848
849 ret[envc] = NULL;
850
851 return ret;
852}
853
854extern char **environ; /* our environment */
855//#include <error.h>
856
857/* Add a string onto the string table, and return its address */
858static char *copy_str(char **tab, const char *str)
859{
860 char *cp = *tab;
861 char *orig = cp;
862
863 while(*str)
864 *cp++ = *str++;
865 *cp++ = '\0';
866
867 if (0)
nethercotef84f6952004-07-15 14:58:33 +0000868 printf("copied %p \"%s\" len %d\n", orig, orig, cp-orig);
nethercote71980f02004-01-24 18:18:54 +0000869
870 *tab = cp;
871
872 return orig;
873}
874
875/*
876 This sets up the client's initial stack, containing the args,
877 environment and aux vector.
878
879 The format of the stack is:
880
881 higher address +-----------------+
882 | Trampoline code |
883 +-----------------+
884 | |
885 : string table :
886 | |
887 +-----------------+
888 | AT_NULL |
889 - -
890 | auxv |
891 +-----------------+
892 | NULL |
893 - -
894 | envp |
895 +-----------------+
896 | NULL |
897 - -
898 | argv |
899 +-----------------+
900 | argc |
901 lower address +-----------------+ <- esp
902 | undefined |
903 : :
904 */
905static Addr setup_client_stack(char **orig_argv, char **orig_envp,
906 const struct exeinfo *info,
907 UInt** client_auxv)
908{
nethercotee567e702004-07-10 17:49:17 +0000909 void* res;
nethercote71980f02004-01-24 18:18:54 +0000910 char **cpp;
911 char *strtab; /* string table */
912 char *stringbase;
913 addr_t *ptr;
914 struct ume_auxv *auxv;
915 const struct ume_auxv *orig_auxv;
916 const struct ume_auxv *cauxv;
917 unsigned stringsize; /* total size of strings in bytes */
918 unsigned auxsize; /* total size of auxv in bytes */
919 int argc; /* total argc */
920 int envc; /* total number of env vars */
921 unsigned stacksize; /* total client stack size */
922 addr_t cl_esp; /* client stack base (initial esp) */
923
924 /* use our own auxv as a prototype */
925 orig_auxv = find_auxv(ume_exec_esp);
926
927 /* ==================== compute sizes ==================== */
928
929 /* first of all, work out how big the client stack will be */
930 stringsize = 0;
931
932 /* paste on the extra args if the loader needs them (ie, the #!
933 interpreter and its argument) */
934 argc = 0;
nethercoted6a56872004-07-26 15:32:47 +0000935 if (info->interp_name != NULL) {
nethercote71980f02004-01-24 18:18:54 +0000936 argc++;
nethercoted6a56872004-07-26 15:32:47 +0000937 stringsize += strlen(info->interp_name) + 1;
nethercote71980f02004-01-24 18:18:54 +0000938 }
nethercoted6a56872004-07-26 15:32:47 +0000939 if (info->interp_args != NULL) {
nethercote71980f02004-01-24 18:18:54 +0000940 argc++;
nethercoted6a56872004-07-26 15:32:47 +0000941 stringsize += strlen(info->interp_args) + 1;
nethercote71980f02004-01-24 18:18:54 +0000942 }
943
944 /* now scan the args we're given... */
945 for (cpp = orig_argv; *cpp; cpp++) {
946 argc++;
947 stringsize += strlen(*cpp) + 1;
948 }
949
950 /* ...and the environment */
951 envc = 0;
952 for (cpp = orig_envp; cpp && *cpp; cpp++) {
953 envc++;
954 stringsize += strlen(*cpp) + 1;
955 }
956
957 /* now, how big is the auxv? */
958 auxsize = sizeof(*auxv); /* there's always at least one entry: AT_NULL */
959 for (cauxv = orig_auxv; cauxv->a_type != AT_NULL; cauxv++) {
960 if (cauxv->a_type == AT_PLATFORM)
961 stringsize += strlen(cauxv->u.a_ptr) + 1;
962 auxsize += sizeof(*cauxv);
963 }
964
965 /* OK, now we know how big the client stack is */
966 stacksize =
967 sizeof(int) + /* argc */
968 sizeof(char **)*argc + /* argv */
969 sizeof(char **) + /* terminal NULL */
970 sizeof(char **)*envc + /* envp */
971 sizeof(char **) + /* terminal NULL */
972 auxsize + /* auxv */
973 ROUNDUP(stringsize, sizeof(int)) +/* strings (aligned) */
974 VKI_BYTES_PER_PAGE; /* page for trampoline code */
975
nethercotef84f6952004-07-15 14:58:33 +0000976 // decide where stack goes!
977 VG_(clstk_end) = VG_(client_end);
978
979 VG_(client_trampoline_code) = VG_(clstk_end) - VKI_BYTES_PER_PAGE;
980
nethercote71980f02004-01-24 18:18:54 +0000981 /* cl_esp is the client's stack pointer */
nethercotef84f6952004-07-15 14:58:33 +0000982 cl_esp = VG_(clstk_end) - stacksize;
nethercote71980f02004-01-24 18:18:54 +0000983 cl_esp = ROUNDDN(cl_esp, 16); /* make stack 16 byte aligned */
984
nethercote71980f02004-01-24 18:18:54 +0000985 /* base of the string table (aligned) */
986 stringbase = strtab = (char *)(VG_(client_trampoline_code) - ROUNDUP(stringsize, sizeof(int)));
987
988 VG_(clstk_base) = PGROUNDDN(cl_esp);
nethercote71980f02004-01-24 18:18:54 +0000989
nethercote5ee67ca2004-06-22 14:00:09 +0000990 if (0)
991 printf("stringsize=%d auxsize=%d stacksize=%d\n"
nethercote6a27d832004-09-07 10:17:02 +0000992 "clstk_base %p\n"
993 "clstk_end %p\n",
994 stringsize, auxsize, stacksize,
995 (void*)VG_(clstk_base), (void*)VG_(clstk_end));
nethercote5ee67ca2004-06-22 14:00:09 +0000996
997
nethercote71980f02004-01-24 18:18:54 +0000998 /* ==================== allocate space ==================== */
999
1000 /* allocate a stack - mmap enough space for the stack */
nethercotef84f6952004-07-15 14:58:33 +00001001 res = mmap((void *)PGROUNDDN(cl_esp), VG_(clstk_end) - PGROUNDDN(cl_esp),
nethercotee567e702004-07-10 17:49:17 +00001002 PROT_READ | PROT_WRITE | PROT_EXEC,
1003 MAP_PRIVATE | MAP_ANON | MAP_FIXED, -1, 0);
1004 vg_assert((void*)-1 != res);
nethercote71980f02004-01-24 18:18:54 +00001005
1006 /* ==================== copy client stack ==================== */
1007
1008 ptr = (addr_t *)cl_esp;
1009
1010 /* --- argc --- */
1011 *ptr++ = argc; /* client argc */
1012
1013 /* --- argv --- */
nethercoted6a56872004-07-26 15:32:47 +00001014 if (info->interp_name) {
1015 *ptr++ = (addr_t)copy_str(&strtab, info->interp_name);
1016 free(info->interp_name);
nethercote71980f02004-01-24 18:18:54 +00001017 }
nethercoted6a56872004-07-26 15:32:47 +00001018 if (info->interp_args) {
1019 *ptr++ = (addr_t)copy_str(&strtab, info->interp_args);
1020 free(info->interp_args);
nethercote71980f02004-01-24 18:18:54 +00001021 }
1022 for (cpp = orig_argv; *cpp; ptr++, cpp++) {
1023 *ptr = (addr_t)copy_str(&strtab, *cpp);
1024 }
1025 *ptr++ = 0;
1026
1027 /* --- envp --- */
1028 VG_(client_envp) = (Char **)ptr;
1029 for (cpp = orig_envp; cpp && *cpp; ptr++, cpp++)
1030 *ptr = (addr_t)copy_str(&strtab, *cpp);
1031 *ptr++ = 0;
1032
1033 /* --- auxv --- */
1034 auxv = (struct ume_auxv *)ptr;
1035 *client_auxv = (UInt *)auxv;
1036
1037 for (; orig_auxv->a_type != AT_NULL; auxv++, orig_auxv++) {
1038 /* copy the entry... */
1039 *auxv = *orig_auxv;
1040
1041 /* ...and fix up the copy */
1042 switch(auxv->a_type) {
1043 case AT_PHDR:
1044 if (info->phdr == 0)
1045 auxv->a_type = AT_IGNORE;
1046 else
1047 auxv->u.a_val = info->phdr;
1048 break;
1049
1050 case AT_PHNUM:
1051 if (info->phdr == 0)
1052 auxv->a_type = AT_IGNORE;
1053 else
1054 auxv->u.a_val = info->phnum;
1055 break;
1056
1057 case AT_BASE:
1058 if (info->interp_base == 0)
1059 auxv->a_type = AT_IGNORE;
1060 else
1061 auxv->u.a_val = info->interp_base;
1062 break;
1063
1064 case AT_PLATFORM: /* points to a platform description string */
1065 auxv->u.a_ptr = copy_str(&strtab, orig_auxv->u.a_ptr);
1066 break;
1067
1068 case AT_ENTRY:
1069 auxv->u.a_val = info->entry;
1070 break;
1071
1072 case AT_IGNORE:
1073 case AT_EXECFD:
1074 case AT_PHENT:
1075 case AT_PAGESZ:
1076 case AT_FLAGS:
1077 case AT_NOTELF:
1078 case AT_UID:
1079 case AT_EUID:
1080 case AT_GID:
1081 case AT_EGID:
1082 case AT_CLKTCK:
1083 case AT_HWCAP:
1084 case AT_FPUCW:
1085 case AT_DCACHEBSIZE:
1086 case AT_ICACHEBSIZE:
1087 case AT_UCACHEBSIZE:
1088 /* All these are pointerless, so we don't need to do anything
1089 about them. */
1090 break;
1091
1092 case AT_SECURE:
1093 /* If this is 1, then it means that this program is running
1094 suid, and therefore the dynamic linker should be careful
1095 about LD_PRELOAD, etc. However, since stage1 (the thing
1096 the kernel actually execve's) should never be SUID, and we
1097 need LD_PRELOAD/LD_LIBRARY_PATH to work for the client, we
1098 set AT_SECURE to 0. */
1099 auxv->u.a_val = 0;
1100 break;
1101
1102 case AT_SYSINFO:
1103 /* Leave this unmolested for now, but we'll update it later
1104 when we set up the client trampoline code page */
1105 break;
1106
1107 case AT_SYSINFO_EHDR:
1108 /* Trash this, because we don't reproduce it */
1109 auxv->a_type = AT_IGNORE;
1110 break;
1111
1112 default:
1113 /* stomp out anything we don't know about */
1114 if (0)
1115 printf("stomping auxv entry %d\n", auxv->a_type);
1116 auxv->a_type = AT_IGNORE;
1117 break;
1118
1119 }
1120 }
1121 *auxv = *orig_auxv;
1122 vg_assert(auxv->a_type == AT_NULL);
1123
nethercotef84f6952004-07-15 14:58:33 +00001124 /* --- trampoline page --- */
1125 VG_(memcpy)( (void *)VG_(client_trampoline_code),
1126 &VG_(trampoline_code_start), VG_(trampoline_code_length) );
1127
nethercote71980f02004-01-24 18:18:54 +00001128 vg_assert((strtab-stringbase) == stringsize);
1129
nethercote5ee67ca2004-06-22 14:00:09 +00001130 /* We know the initial ESP is pointing at argc/argv */
1131 VG_(client_argc) = *(Int*)cl_esp;
1132 VG_(client_argv) = (Char**)(cl_esp + sizeof(Int));
1133
nethercote71980f02004-01-24 18:18:54 +00001134 return cl_esp;
1135}
1136
1137/*====================================================================*/
1138/*=== Find executable ===*/
1139/*====================================================================*/
1140
thughes4ad52d02004-06-27 17:37:21 +00001141static const char* executable_name;
1142
1143static Bool match_executable(const char *entry) {
1144 char buf[strlen(entry) + strlen(executable_name) + 2];
1145
1146 /* empty PATH element means . */
1147 if (*entry == '\0')
1148 entry = ".";
1149
1150 snprintf(buf, sizeof(buf), "%s/%s", entry, executable_name);
1151
1152 if (access(buf, R_OK|X_OK) == 0) {
1153 executable_name = strdup(buf);
1154 vg_assert(NULL != executable_name);
1155 return True;
1156 }
1157 return False;
1158}
1159
nethercote71980f02004-01-24 18:18:54 +00001160static const char* find_executable(const char* exec)
1161{
1162 vg_assert(NULL != exec);
thughes4ad52d02004-06-27 17:37:21 +00001163 executable_name = exec;
1164 if (strchr(executable_name, '/') == NULL) {
nethercote71980f02004-01-24 18:18:54 +00001165 /* no '/' - we need to search the path */
1166 char *path = getenv("PATH");
thughes4ad52d02004-06-27 17:37:21 +00001167 scan_colsep(path, match_executable);
nethercote71980f02004-01-24 18:18:54 +00001168 }
thughes4ad52d02004-06-27 17:37:21 +00001169 return executable_name;
nethercote71980f02004-01-24 18:18:54 +00001170}
1171
1172
1173/*====================================================================*/
1174/*=== Loading tools ===*/
1175/*====================================================================*/
1176
1177static void list_tools(void)
1178{
1179 DIR *dir = opendir(VG_(libdir));
1180 struct dirent *de;
1181 int first = 1;
1182
1183 if (dir == NULL) {
1184 fprintf(stderr, "Can't open %s: %s (installation problem?)\n",
nethercotef4928da2004-06-15 10:54:40 +00001185 VG_(libdir), strerror(errno));
nethercote71980f02004-01-24 18:18:54 +00001186 return;
1187 }
1188
nethercotef4928da2004-06-15 10:54:40 +00001189 while ((de = readdir(dir)) != NULL) {
nethercote71980f02004-01-24 18:18:54 +00001190 int len = strlen(de->d_name);
1191
1192 /* look for vgskin_TOOL.so names */
1193 if (len > (7+1+3) && /* "vgskin_" + at least 1-char toolname + ".so" */
nethercotef4928da2004-06-15 10:54:40 +00001194 strncmp(de->d_name, "vgskin_", 7) == 0 &&
1195 VG_STREQ(de->d_name + len - 3, ".so")) {
1196 if (first) {
1197 fprintf(stderr, "Available tools:\n");
1198 first = 0;
1199 }
1200 de->d_name[len-3] = '\0';
1201 fprintf(stderr, "\t%s\n", de->d_name+7);
nethercote71980f02004-01-24 18:18:54 +00001202 }
1203 }
1204
1205 closedir(dir);
1206
1207 if (first)
nethercotef4928da2004-06-15 10:54:40 +00001208 fprintf(stderr, "No tools available in \"%s\" (installation problem?)\n",
1209 VG_(libdir));
nethercote71980f02004-01-24 18:18:54 +00001210}
1211
1212
1213/* Find and load a tool, and check it looks ok. Also looks to see if there's
1214 * a matching vgpreload_*.so file, and returns its name in *preloadpath. */
1215static void load_tool( const char *toolname, void** handle_out,
1216 ToolInfo** toolinfo_out, char **preloadpath_out )
1217{
1218 Bool ok;
1219 int len = strlen(VG_(libdir)) + strlen(toolname)*2 + 16;
1220 char buf[len];
1221 void* handle;
1222 ToolInfo* toolinfo;
1223 char* preloadpath = NULL;
1224 Int* vg_malloc_redzonep;
1225
1226 // XXX: allowing full paths for --tool option -- does it make sense?
1227 // Doesn't allow for vgpreload_<tool>.so.
1228
1229 if (strchr(toolname, '/') != 0) {
1230 /* toolname contains '/', and so must be a pathname */
1231 handle = dlopen(toolname, RTLD_NOW);
1232 } else {
1233 /* just try in the libdir */
1234 snprintf(buf, len, "%s/vgskin_%s.so", VG_(libdir), toolname);
1235 handle = dlopen(buf, RTLD_NOW);
1236
1237 if (handle != NULL) {
1238 snprintf(buf, len, "%s/vgpreload_%s.so", VG_(libdir), toolname);
1239 if (access(buf, R_OK) == 0) {
1240 preloadpath = strdup(buf);
1241 vg_assert(NULL != preloadpath);
1242 }
1243 }
1244 }
1245
1246 ok = (NULL != handle);
1247 if (!ok) {
1248 fprintf(stderr, "Can't open tool \"%s\": %s\n", toolname, dlerror());
1249 goto bad_load;
1250 }
1251
1252 toolinfo = dlsym(handle, "vgSkin_tool_info");
1253 ok = (NULL != toolinfo);
1254 if (!ok) {
1255 fprintf(stderr, "Tool \"%s\" doesn't define SK_(tool_info) - "
1256 "add VG_DETERMINE_INTERFACE_VERSION?\n", toolname);
1257 goto bad_load;
1258 }
1259
1260 ok = (toolinfo->sizeof_ToolInfo == sizeof(*toolinfo) &&
1261 toolinfo->interface_major_version == VG_CORE_INTERFACE_MAJOR_VERSION &&
1262 toolinfo->sk_pre_clo_init != NULL);
1263 if (!ok) {
1264 fprintf(stderr, "Error:\n"
1265 " Tool and core interface versions do not match.\n"
1266 " Interface version used by core is: %d.%d (size %d)\n"
1267 " Interface version used by tool is: %d.%d (size %d)\n"
1268 " The major version numbers must match.\n",
1269 VG_CORE_INTERFACE_MAJOR_VERSION,
1270 VG_CORE_INTERFACE_MINOR_VERSION,
1271 sizeof(*toolinfo),
1272 toolinfo->interface_major_version,
1273 toolinfo->interface_minor_version,
1274 toolinfo->sizeof_ToolInfo);
1275 fprintf(stderr, " You need to at least recompile, and possibly update,\n");
1276 if (VG_CORE_INTERFACE_MAJOR_VERSION > toolinfo->interface_major_version)
nethercote996901a2004-08-03 13:29:09 +00001277 fprintf(stderr, " your tool to work with this version of Valgrind.\n");
nethercote71980f02004-01-24 18:18:54 +00001278 else
nethercote996901a2004-08-03 13:29:09 +00001279 fprintf(stderr, " your version of Valgrind to work with this tool.\n");
nethercote71980f02004-01-24 18:18:54 +00001280 goto bad_load;
1281 }
1282
1283 // Set redzone size for V's allocator
1284 vg_malloc_redzonep = dlsym(handle, STR(VG_(vg_malloc_redzone_szB)));
1285 if ( NULL != vg_malloc_redzonep ) {
1286 VG_(vg_malloc_redzone_szB) = *vg_malloc_redzonep;
1287 }
1288
1289 vg_assert(NULL != handle && NULL != toolinfo);
1290 *handle_out = handle;
1291 *toolinfo_out = toolinfo;
1292 *preloadpath_out = preloadpath;
1293 return;
1294
1295
1296 bad_load:
1297 if (handle != NULL)
1298 dlclose(handle);
1299
nethercotef4928da2004-06-15 10:54:40 +00001300 fprintf(stderr, "valgrind: couldn't load tool\n");
nethercote71980f02004-01-24 18:18:54 +00001301 list_tools();
1302 exit(127);
1303}
1304
nethercotef4928da2004-06-15 10:54:40 +00001305
1306/*====================================================================*/
1307/*=== Command line errors ===*/
1308/*====================================================================*/
1309
1310static void abort_msg ( void )
1311{
nethercotef8548672004-06-21 12:42:35 +00001312 VG_(clo_log_to) = VgLogTo_Fd;
1313 VG_(clo_log_fd) = 2; /* stderr */
nethercotef4928da2004-06-15 10:54:40 +00001314}
1315
1316void VG_(bad_option) ( Char* opt )
1317{
1318 abort_msg();
1319 VG_(printf)("valgrind: Bad option `%s'; aborting.\n", opt);
1320 VG_(printf)("valgrind: Use --help for more information.\n");
1321 VG_(exit)(1);
1322}
1323
1324static void missing_tool_option ( void )
1325{
1326 abort_msg();
1327 VG_(printf)("valgrind: Missing --tool option\n");
1328 list_tools();
1329 VG_(printf)("valgrind: Use --help for more information.\n");
1330 VG_(exit)(1);
1331}
1332
1333static void missing_prog ( void )
1334{
1335 abort_msg();
1336 VG_(printf)("valgrind: no program specified\n");
1337 VG_(printf)("valgrind: Use --help for more information.\n");
1338 VG_(exit)(1);
1339}
1340
1341static void config_error ( Char* msg )
1342{
1343 abort_msg();
1344 VG_(printf)("valgrind: Startup or configuration error:\n %s\n", msg);
1345 VG_(printf)("valgrind: Unable to start up properly. Giving up.\n");
1346 VG_(exit)(1);
1347}
1348
1349
nethercote71980f02004-01-24 18:18:54 +00001350/*====================================================================*/
1351/*=== Loading the client ===*/
1352/*====================================================================*/
1353
nethercotef4928da2004-06-15 10:54:40 +00001354static void load_client(char* cl_argv[], const char* exec, Int need_help,
nethercote71980f02004-01-24 18:18:54 +00001355 /*out*/struct exeinfo* info, /*out*/Addr* client_eip)
1356{
1357 // If they didn't specify an executable with --exec, and didn't specify
1358 // --help, then use client argv[0] (searching $PATH if necessary).
nethercotef4928da2004-06-15 10:54:40 +00001359 if (NULL == exec && !need_help) {
nethercote71980f02004-01-24 18:18:54 +00001360 if (cl_argv[0] == NULL ||
1361 ( NULL == (exec = find_executable(cl_argv[0])) ) )
1362 {
nethercotef4928da2004-06-15 10:54:40 +00001363 missing_prog();
nethercote71980f02004-01-24 18:18:54 +00001364 }
1365 }
1366
1367 info->map_base = VG_(client_mapbase);
nethercote71980f02004-01-24 18:18:54 +00001368 info->exe_base = VG_(client_base);
1369 info->exe_end = VG_(client_end);
1370 info->argv = cl_argv;
1371
nethercotef4928da2004-06-15 10:54:40 +00001372 if (need_help) {
nethercote71980f02004-01-24 18:18:54 +00001373 VG_(clexecfd) = -1;
nethercoteea147e72004-07-26 15:43:57 +00001374 // Set the minimal number of entries in 'info' to continue.
nethercoted6a56872004-07-26 15:32:47 +00001375 info->interp_name = NULL;
1376 info->interp_args = NULL;
nethercote71980f02004-01-24 18:18:54 +00001377 } else {
1378 Int ret;
1379 VG_(clexecfd) = VG_(open)(exec, O_RDONLY, VKI_S_IRUSR);
1380 ret = do_exec(exec, info);
1381 if (ret != 0) {
nethercoteea147e72004-07-26 15:43:57 +00001382 fprintf(stderr, "valgrind: do_exec(%s) failed: %s\n",
1383 exec, strerror(ret));
nethercote71980f02004-01-24 18:18:54 +00001384 exit(127);
1385 }
1386 }
1387
1388 /* Copy necessary bits of 'info' that were filled in */
1389 *client_eip = info->init_eip;
1390 VG_(brk_base) = VG_(brk_limit) = info->brkbase;
1391}
1392
1393
1394/*====================================================================*/
nethercotef6a1d502004-08-09 12:21:57 +00001395/*=== Command-line: variables, processing, etc ===*/
nethercote71980f02004-01-24 18:18:54 +00001396/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +00001397
njn25e49d8e72002-09-23 09:36:25 +00001398/* Define, and set defaults. */
1399Bool VG_(clo_error_limit) = True;
nethercote04d0fbc2004-01-26 16:48:06 +00001400Bool VG_(clo_db_attach) = False;
1401Char* VG_(clo_db_command) = VG_CLO_DEFAULT_DBCOMMAND;
njn43c799e2003-04-08 00:08:52 +00001402Bool VG_(clo_gen_suppressions) = False;
nethercote27fec902004-06-16 21:26:32 +00001403Int VG_(clo_sanity_level) = 1;
njn25e49d8e72002-09-23 09:36:25 +00001404Int VG_(clo_verbosity) = 1;
1405Bool VG_(clo_demangle) = True;
njn25e49d8e72002-09-23 09:36:25 +00001406Bool VG_(clo_trace_children) = False;
sewardj4cf05692002-10-27 20:28:29 +00001407
nethercotef1e5e152004-09-01 23:58:16 +00001408/* See big comment in core.h for meaning of these three.
nethercotee1730692003-11-20 10:38:07 +00001409 fd is initially stdout, for --help, but gets moved to stderr by default
1410 immediately afterwards. */
sewardj4cf05692002-10-27 20:28:29 +00001411VgLogTo VG_(clo_log_to) = VgLogTo_Fd;
nethercotef8548672004-06-21 12:42:35 +00001412Int VG_(clo_log_fd) = 1;
1413Char* VG_(clo_log_name) = NULL;
sewardj4cf05692002-10-27 20:28:29 +00001414
thughes6233a382004-08-21 11:10:44 +00001415Bool VG_(clo_time_stamp) = False;
1416
sewardj6024b212003-07-13 10:54:33 +00001417Int VG_(clo_input_fd) = 0; /* stdin */
njn25e49d8e72002-09-23 09:36:25 +00001418Int VG_(clo_n_suppressions) = 0;
sewardjde4a1d02002-03-22 01:27:54 +00001419Char* VG_(clo_suppressions)[VG_CLO_MAX_SFILES];
njn25e49d8e72002-09-23 09:36:25 +00001420Bool VG_(clo_profile) = False;
1421Bool VG_(clo_single_step) = False;
1422Bool VG_(clo_optimise) = True;
1423UChar VG_(clo_trace_codegen) = 0; // 00000000b
1424Bool VG_(clo_trace_syscalls) = False;
1425Bool VG_(clo_trace_signals) = False;
1426Bool VG_(clo_trace_symtab) = False;
njn25e49d8e72002-09-23 09:36:25 +00001427Bool VG_(clo_trace_sched) = False;
1428Int VG_(clo_trace_pthread_level) = 0;
njn25e49d8e72002-09-23 09:36:25 +00001429Int VG_(clo_dump_error) = 0;
1430Int VG_(clo_backtrace_size) = 4;
1431Char* VG_(clo_weird_hacks) = NULL;
sewardj858964b2002-10-05 14:15:43 +00001432Bool VG_(clo_run_libc_freeres) = True;
rjwalshf5f536f2003-11-17 17:45:00 +00001433Bool VG_(clo_track_fds) = False;
sewardj22854b92002-11-30 14:00:47 +00001434Bool VG_(clo_chain_bb) = True;
nethercote77eba602003-11-13 17:35:04 +00001435Bool VG_(clo_show_below_main) = False;
fitzhardinge98abfc72003-12-16 02:05:15 +00001436Bool VG_(clo_pointercheck) = True;
fitzhardinge462f4f92003-12-18 02:10:54 +00001437Bool VG_(clo_branchpred) = False;
sewardj2370f3b2002-11-30 15:01:01 +00001438
jsgf855d93d2003-10-13 22:26:55 +00001439static Bool VG_(clo_wait_for_gdb) = False;
1440
1441/* If we're doing signal routing, poll for signals every 50mS by
1442 default. */
1443Int VG_(clo_signal_polltime) = 50;
1444
1445/* These flags reduce thread wakeup latency on syscall completion and
1446 signal delivery, respectively. The downside is possible unfairness. */
1447Bool VG_(clo_lowlat_syscalls) = False; /* low-latency syscalls */
1448Bool VG_(clo_lowlat_signals) = False; /* low-latency signals */
1449
sewardjde4a1d02002-03-22 01:27:54 +00001450
nethercote6c999f22004-01-31 22:55:15 +00001451void usage ( Bool debug_help )
njn7cf0bd32002-06-08 13:36:03 +00001452{
njn25e49d8e72002-09-23 09:36:25 +00001453 Char* usage1 =
nethercote71980f02004-01-24 18:18:54 +00001454"usage: valgrind --tool=<toolname> [options] prog-and-args\n"
njn25e49d8e72002-09-23 09:36:25 +00001455"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001456" common user options for all Valgrind tools, with defaults in [ ]:\n"
nethercote0d588502004-06-21 13:27:11 +00001457" --tool=<name> use the Valgrind tool named <name>\n"
nethercotea76368b2004-06-16 11:56:29 +00001458" -h --help show this message\n"
nethercote6c999f22004-01-31 22:55:15 +00001459" --help-debug show this message, plus debugging options\n"
njn25e49d8e72002-09-23 09:36:25 +00001460" --version show version\n"
njn25e49d8e72002-09-23 09:36:25 +00001461" -q --quiet run silently; only print error msgs\n"
1462" -v --verbose be more verbose, incl counts of errors\n"
nethercote77eba602003-11-13 17:35:04 +00001463" --trace-children=no|yes Valgrind-ise child processes? [no]\n"
nethercote0d588502004-06-21 13:27:11 +00001464" --track-fds=no|yes track open file descriptors? [no]\n"
thughes6233a382004-08-21 11:10:44 +00001465" --time-stamp=no|yes add timestamps to log messages? [no]\n"
nethercote2b0793f2003-12-02 10:41:18 +00001466"\n"
1467" uncommon user options for all Valgrind tools:\n"
nethercote0d588502004-06-21 13:27:11 +00001468" --run-libc-freeres=no|yes free up glibc memory at exit? [yes]\n"
1469" --weird-hacks=hack1,hack2,... recognised hacks: lax-ioctls [none]\n"
1470" --signal-polltime=<time> signal poll period (mS) for older kernels [50]\n"
1471" --lowlat-signals=no|yes improve thread signal wake-up latency [no]\n"
1472" --lowlat-syscalls=no|yes improve thread syscall wake-up latency [no]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001473" --pointercheck=no|yes enforce client address space limits [yes]\n"
njn25e49d8e72002-09-23 09:36:25 +00001474"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001475" user options for Valgrind tools that report errors:\n"
nethercotef8548672004-06-21 12:42:35 +00001476" --log-fd=<number> log messages to file descriptor [2=stderr]\n"
1477" --log-file=<file> log messages to <file>.pid<pid>\n"
1478" --log-socket=ipaddr:port log messages to socket ipaddr:port\n"
nethercote2b0793f2003-12-02 10:41:18 +00001479" --demangle=no|yes automatically demangle C++ names? [yes]\n"
1480" --num-callers=<number> show <num> callers in stack traces [4]\n"
1481" --error-limit=no|yes stop showing new errors if too many? [yes]\n"
1482" --show-below-main=no|yes continue stack traces below main() [no]\n"
1483" --suppressions=<filename> suppress errors described in <filename>\n"
1484" --gen-suppressions=no|yes print suppressions for errors detected [no]\n"
nethercote04d0fbc2004-01-26 16:48:06 +00001485" --db-attach=no|yes start debugger when errors detected? [no]\n"
1486" --db-command=<command> command to start debugger [gdb -nw %%f %%p]\n"
1487" --input-fd=<number> file descriptor for input [0=stdin]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001488"\n";
njn7cf0bd32002-06-08 13:36:03 +00001489
njn25e49d8e72002-09-23 09:36:25 +00001490 Char* usage2 =
1491"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001492" debugging options for all Valgrind tools:\n"
njn25e49d8e72002-09-23 09:36:25 +00001493" --sanity-level=<number> level of sanity checking to do [1]\n"
1494" --single-step=no|yes translate each instr separately? [no]\n"
1495" --optimise=no|yes improve intermediate code? [yes]\n"
nethercote137bc552003-11-14 17:47:54 +00001496" --profile=no|yes profile? (tool must be built for it) [no]\n"
sewardj22854b92002-11-30 14:00:47 +00001497" --chain-bb=no|yes do basic-block chaining? [yes]\n"
fitzhardinge462f4f92003-12-18 02:10:54 +00001498" --branchpred=yes|no generate branch prediction hints [no]\n"
njn25e49d8e72002-09-23 09:36:25 +00001499" --trace-codegen=<XXXXX> show generated code? (X = 0|1) [00000]\n"
1500" --trace-syscalls=no|yes show all system calls? [no]\n"
1501" --trace-signals=no|yes show signal handling details? [no]\n"
1502" --trace-symtab=no|yes show symbol table details? [no]\n"
njn25e49d8e72002-09-23 09:36:25 +00001503" --trace-sched=no|yes show thread scheduler details? [no]\n"
njn3e884182003-04-15 13:03:23 +00001504" --trace-pthread=none|some|all show pthread event details? [none]\n"
jsgf855d93d2003-10-13 22:26:55 +00001505" --wait-for-gdb=yes|no pause on startup to wait for gdb attach\n"
njn25e49d8e72002-09-23 09:36:25 +00001506"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001507" debugging options for Valgrind tools that report errors\n"
1508" --dump-error=<number> show translation for basic block associated\n"
1509" with <number>'th error context [0=show none]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001510"\n";
njn3e884182003-04-15 13:03:23 +00001511
1512 Char* usage3 =
1513"\n"
nethercote71980f02004-01-24 18:18:54 +00001514" Extra options read from ~/.valgrindrc, $VALGRIND_OPTS, ./.valgrindrc\n"
njn25e49d8e72002-09-23 09:36:25 +00001515"\n"
nethercote08fa9a72004-07-16 17:44:00 +00001516" Valgrind is Copyright (C) 2000-2004 Julian Seward et al.\n"
njn25e49d8e72002-09-23 09:36:25 +00001517" and licensed under the GNU General Public License, version 2.\n"
1518" Bug reports, feedback, admiration, abuse, etc, to: %s.\n"
njnd04b7c62002-10-03 14:05:52 +00001519"\n"
nethercote137bc552003-11-14 17:47:54 +00001520" Tools are copyright and licensed by their authors. See each\n"
1521" tool's start-up message for more information.\n"
njn25e49d8e72002-09-23 09:36:25 +00001522"\n";
njn7cf0bd32002-06-08 13:36:03 +00001523
fitzhardinge98abfc72003-12-16 02:05:15 +00001524 VG_(printf)(usage1);
1525 if (VG_(details).name) {
1526 VG_(printf)(" user options for %s:\n", VG_(details).name);
fitzhardinge98abfc72003-12-16 02:05:15 +00001527 if (VG_(needs).command_line_options)
1528 SK_(print_usage)();
1529 else
1530 VG_(printf)(" (none)\n");
1531 }
nethercote6c999f22004-01-31 22:55:15 +00001532 if (debug_help) {
1533 VG_(printf)(usage2);
fitzhardinge98abfc72003-12-16 02:05:15 +00001534
nethercote6c999f22004-01-31 22:55:15 +00001535 if (VG_(details).name) {
1536 VG_(printf)(" debugging options for %s:\n", VG_(details).name);
1537
1538 if (VG_(needs).command_line_options)
1539 SK_(print_debug_usage)();
1540 else
1541 VG_(printf)(" (none)\n");
1542 }
fitzhardinge98abfc72003-12-16 02:05:15 +00001543 }
nethercote421281e2003-11-20 16:20:55 +00001544 VG_(printf)(usage3, VG_BUGS_TO);
nethercotef4928da2004-06-15 10:54:40 +00001545 VG_(exit)(0);
njn7cf0bd32002-06-08 13:36:03 +00001546}
sewardjde4a1d02002-03-22 01:27:54 +00001547
nethercote71980f02004-01-24 18:18:54 +00001548static void pre_process_cmd_line_options
nethercote6c999f22004-01-31 22:55:15 +00001549 ( Int* need_help, const char** tool, const char** exec )
sewardj1c1b1162003-02-23 01:25:51 +00001550{
nethercote71980f02004-01-24 18:18:54 +00001551 UInt i;
sewardjde4a1d02002-03-22 01:27:54 +00001552
nethercote71980f02004-01-24 18:18:54 +00001553 /* parse the options we have (only the options we care about now) */
nethercotef6a1d502004-08-09 12:21:57 +00001554 for (i = 1; i < vg_argc; i++) {
nethercote71980f02004-01-24 18:18:54 +00001555
nethercotef6a1d502004-08-09 12:21:57 +00001556 if (strcmp(vg_argv[i], "--version") == 0) {
nethercote71980f02004-01-24 18:18:54 +00001557 printf("valgrind-" VERSION "\n");
nethercotef4928da2004-06-15 10:54:40 +00001558 exit(0);
nethercote71980f02004-01-24 18:18:54 +00001559
nethercotef6a1d502004-08-09 12:21:57 +00001560 } else if (VG_CLO_STREQ(vg_argv[i], "--help") ||
1561 VG_CLO_STREQ(vg_argv[i], "-h")) {
nethercote6c999f22004-01-31 22:55:15 +00001562 *need_help = 1;
1563
nethercotef6a1d502004-08-09 12:21:57 +00001564 } else if (VG_CLO_STREQ(vg_argv[i], "--help-debug")) {
nethercote6c999f22004-01-31 22:55:15 +00001565 *need_help = 2;
nethercote71980f02004-01-24 18:18:54 +00001566
nethercotef6a1d502004-08-09 12:21:57 +00001567 } else if (VG_CLO_STREQN(7, vg_argv[i], "--tool=") ||
1568 VG_CLO_STREQN(7, vg_argv[i], "--skin=")) {
1569 *tool = &vg_argv[i][7];
nethercote71980f02004-01-24 18:18:54 +00001570
nethercotef6a1d502004-08-09 12:21:57 +00001571 } else if (VG_CLO_STREQN(7, vg_argv[i], "--exec=")) {
1572 *exec = &vg_argv[i][7];
nethercote71980f02004-01-24 18:18:54 +00001573 }
1574 }
1575
nethercotef4928da2004-06-15 10:54:40 +00001576 /* If no tool specified, can act appropriately without loading tool */
nethercote71980f02004-01-24 18:18:54 +00001577 if (*tool == NULL) {
nethercotef4928da2004-06-15 10:54:40 +00001578 if (0 == *need_help) {
1579 // neither --tool nor --help/--help-debug specified
1580 missing_tool_option();
1581 } else {
1582 // Give help message, without any tool-specific help
1583 usage(/*help-debug?*/2 == *need_help);
1584 }
nethercote71980f02004-01-24 18:18:54 +00001585 }
1586}
1587
nethercote5ee67ca2004-06-22 14:00:09 +00001588static void process_cmd_line_options( UInt* client_auxv, const char* toolname )
nethercote71980f02004-01-24 18:18:54 +00001589{
nethercotef8548672004-06-21 12:42:35 +00001590 Int i, eventually_log_fd;
nethercote71980f02004-01-24 18:18:54 +00001591 Int *auxp;
1592 Int toolname_len = VG_(strlen)(toolname);
sewardjde4a1d02002-03-22 01:27:54 +00001593
nethercotee1730692003-11-20 10:38:07 +00001594 /* log to stderr by default, but usage message goes to stdout */
nethercotef8548672004-06-21 12:42:35 +00001595 eventually_log_fd = 2;
sewardjde4a1d02002-03-22 01:27:54 +00001596
sewardj19d81412002-06-03 01:10:40 +00001597 /* Check for sane path in ./configure --prefix=... */
fitzhardinge98abfc72003-12-16 02:05:15 +00001598 if (VG_LIBDIR[0] != '/')
sewardj19d81412002-06-03 01:10:40 +00001599 config_error("Please use absolute paths in "
1600 "./configure --prefix=... or --libdir=...");
sewardj38170912002-05-10 21:07:22 +00001601
nethercote71980f02004-01-24 18:18:54 +00001602 for (auxp = client_auxv; auxp[0] != VKI_AT_NULL; auxp += 2) {
fitzhardinge98abfc72003-12-16 02:05:15 +00001603 switch(auxp[0]) {
1604 case VKI_AT_SYSINFO:
fitzhardinge92360792003-12-24 10:11:11 +00001605 auxp[1] = (Int)(VG_(client_trampoline_code) + VG_(tramp_syscall_offset));
fitzhardinge98abfc72003-12-16 02:05:15 +00001606 break;
sewardjde4a1d02002-03-22 01:27:54 +00001607 }
fitzhardinge98abfc72003-12-16 02:05:15 +00001608 }
sewardjde4a1d02002-03-22 01:27:54 +00001609
nethercotef6a1d502004-08-09 12:21:57 +00001610 for (i = 1; i < vg_argc; i++) {
nethercote71980f02004-01-24 18:18:54 +00001611
nethercotef6a1d502004-08-09 12:21:57 +00001612 Char* arg = vg_argv[i];
thughes3bfd5a02004-07-18 08:05:44 +00001613 Char* colon = arg;
nethercote71980f02004-01-24 18:18:54 +00001614
thughes3bfd5a02004-07-18 08:05:44 +00001615 /* Look for a colon in the switch name */
1616 while (*colon && *colon != ':' && *colon != '=')
1617 colon++;
nethercote71980f02004-01-24 18:18:54 +00001618
1619 /* Look for matching "--toolname:foo" */
thughes3bfd5a02004-07-18 08:05:44 +00001620 if (*colon == ':') {
nethercote71980f02004-01-24 18:18:54 +00001621 if (VG_CLO_STREQN(2, arg, "--") &&
1622 VG_CLO_STREQN(toolname_len, arg+2, toolname) &&
1623 VG_CLO_STREQN(1, arg+2+toolname_len, ":"))
1624 {
1625 // prefix matches, convert "--toolname:foo" to "--foo"
1626 if (0)
1627 VG_(printf)("tool-specific arg: %s\n", arg);
1628 arg += toolname_len + 1;
1629 arg[0] = '-';
1630 arg[1] = '-';
1631
1632 } else {
1633 // prefix doesn't match, skip to next arg
1634 continue;
1635 }
1636 }
1637
fitzhardinge98abfc72003-12-16 02:05:15 +00001638 /* Ignore these options - they've already been handled */
nethercote71980f02004-01-24 18:18:54 +00001639 if (VG_CLO_STREQN(7, arg, "--tool=") ||
1640 VG_CLO_STREQN(7, arg, "--skin="))
fitzhardinge98abfc72003-12-16 02:05:15 +00001641 continue;
nethercote71980f02004-01-24 18:18:54 +00001642 if (VG_CLO_STREQN(7, arg, "--exec="))
fitzhardinge98abfc72003-12-16 02:05:15 +00001643 continue;
1644
nethercote71980f02004-01-24 18:18:54 +00001645 if ( VG_CLO_STREQ(arg, "--"))
fitzhardinge98abfc72003-12-16 02:05:15 +00001646 continue;
nethercote27fec902004-06-16 21:26:32 +00001647
nethercote71980f02004-01-24 18:18:54 +00001648 else if (VG_CLO_STREQ(arg, "-v") ||
1649 VG_CLO_STREQ(arg, "--verbose"))
sewardjde4a1d02002-03-22 01:27:54 +00001650 VG_(clo_verbosity)++;
nethercote27fec902004-06-16 21:26:32 +00001651
nethercote71980f02004-01-24 18:18:54 +00001652 else if (VG_CLO_STREQ(arg, "-q") ||
1653 VG_CLO_STREQ(arg, "--quiet"))
sewardjde4a1d02002-03-22 01:27:54 +00001654 VG_(clo_verbosity)--;
1655
nethercote27fec902004-06-16 21:26:32 +00001656 else VG_BOOL_CLO("--branchpred", VG_(clo_branchpred))
1657 else VG_BOOL_CLO("--chain-bb", VG_(clo_chain_bb))
1658 else VG_BOOL_CLO("--db-attach", VG_(clo_db_attach))
1659 else VG_BOOL_CLO("--demangle", VG_(clo_demangle))
1660 else VG_BOOL_CLO("--error-limit", VG_(clo_error_limit))
1661 else VG_BOOL_CLO("--gen-suppressions", VG_(clo_gen_suppressions))
1662 else VG_BOOL_CLO("--lowlat-signals", VG_(clo_lowlat_signals))
1663 else VG_BOOL_CLO("--lowlat-syscalls", VG_(clo_lowlat_syscalls))
1664 else VG_BOOL_CLO("--optimise", VG_(clo_optimise))
1665 else VG_BOOL_CLO("--pointercheck", VG_(clo_pointercheck))
1666 else VG_BOOL_CLO("--profile", VG_(clo_profile))
1667 else VG_BOOL_CLO("--run-libc-freeres", VG_(clo_run_libc_freeres))
1668 else VG_BOOL_CLO("--show-below-main", VG_(clo_show_below_main))
1669 else VG_BOOL_CLO("--single-step", VG_(clo_single_step))
thughes6233a382004-08-21 11:10:44 +00001670 else VG_BOOL_CLO("--time-stamp", VG_(clo_time_stamp))
nethercote27fec902004-06-16 21:26:32 +00001671 else VG_BOOL_CLO("--track-fds", VG_(clo_track_fds))
1672 else VG_BOOL_CLO("--trace-children", VG_(clo_trace_children))
1673 else VG_BOOL_CLO("--trace-sched", VG_(clo_trace_sched))
1674 else VG_BOOL_CLO("--trace-signals", VG_(clo_trace_signals))
1675 else VG_BOOL_CLO("--trace-symtab", VG_(clo_trace_symtab))
1676 else VG_BOOL_CLO("--trace-syscalls", VG_(clo_trace_syscalls))
1677 else VG_BOOL_CLO("--wait-for-gdb", VG_(clo_wait_for_gdb))
sewardj72f98ff2002-06-13 17:23:38 +00001678
nethercote27fec902004-06-16 21:26:32 +00001679 else VG_STR_CLO ("--db-command", VG_(clo_db_command))
1680 else VG_STR_CLO ("--weird-hacks", VG_(clo_weird_hacks))
sewardjde4a1d02002-03-22 01:27:54 +00001681
nethercote27fec902004-06-16 21:26:32 +00001682 else VG_NUM_CLO ("--dump-error", VG_(clo_dump_error))
1683 else VG_NUM_CLO ("--input-fd", VG_(clo_input_fd))
1684 else VG_NUM_CLO ("--sanity-level", VG_(clo_sanity_level))
1685 else VG_NUM_CLO ("--signal­polltime", VG_(clo_signal_polltime))
1686 else VG_BNUM_CLO("--num-callers", VG_(clo_backtrace_size), 1,
1687 VG_DEEPEST_BACKTRACE)
sewardjde4a1d02002-03-22 01:27:54 +00001688
nethercotef8548672004-06-21 12:42:35 +00001689 // for backwards compatibility, replaced by --log-fd
nethercote71980f02004-01-24 18:18:54 +00001690 else if (VG_CLO_STREQN(13, arg, "--logfile-fd=")) {
nethercotef8548672004-06-21 12:42:35 +00001691 VG_(clo_log_to) = VgLogTo_Fd;
1692 VG_(clo_log_name) = NULL;
1693 eventually_log_fd = (Int)VG_(atoll)(&arg[13]);
1694 }
1695 else if (VG_CLO_STREQN(9, arg, "--log-fd=")) {
1696 VG_(clo_log_to) = VgLogTo_Fd;
1697 VG_(clo_log_name) = NULL;
1698 eventually_log_fd = (Int)VG_(atoll)(&arg[9]);
sewardj4cf05692002-10-27 20:28:29 +00001699 }
1700
nethercotef8548672004-06-21 12:42:35 +00001701 // for backwards compatibility, replaced by --log-file
nethercote71980f02004-01-24 18:18:54 +00001702 else if (VG_CLO_STREQN(10, arg, "--logfile=")) {
nethercotef8548672004-06-21 12:42:35 +00001703 VG_(clo_log_to) = VgLogTo_File;
1704 VG_(clo_log_name) = &arg[10];
1705 }
1706 else if (VG_CLO_STREQN(11, arg, "--log-file=")) {
1707 VG_(clo_log_to) = VgLogTo_File;
1708 VG_(clo_log_name) = &arg[11];
sewardj4cf05692002-10-27 20:28:29 +00001709 }
sewardjde4a1d02002-03-22 01:27:54 +00001710
nethercotef8548672004-06-21 12:42:35 +00001711 // for backwards compatibility, replaced by --log-socket
nethercote71980f02004-01-24 18:18:54 +00001712 else if (VG_CLO_STREQN(12, arg, "--logsocket=")) {
nethercotef8548672004-06-21 12:42:35 +00001713 VG_(clo_log_to) = VgLogTo_Socket;
1714 VG_(clo_log_name) = &arg[12];
1715 }
1716 else if (VG_CLO_STREQN(13, arg, "--log-socket=")) {
1717 VG_(clo_log_to) = VgLogTo_Socket;
1718 VG_(clo_log_name) = &arg[13];
sewardj73cf3bc2002-11-03 03:20:15 +00001719 }
1720
nethercote71980f02004-01-24 18:18:54 +00001721 else if (VG_CLO_STREQN(15, arg, "--suppressions=")) {
sewardjde4a1d02002-03-22 01:27:54 +00001722 if (VG_(clo_n_suppressions) >= VG_CLO_MAX_SFILES) {
njn25e49d8e72002-09-23 09:36:25 +00001723 VG_(message)(Vg_UserMsg, "Too many suppression files specified.");
sewardjde4a1d02002-03-22 01:27:54 +00001724 VG_(message)(Vg_UserMsg,
1725 "Increase VG_CLO_MAX_SFILES and recompile.");
nethercote71980f02004-01-24 18:18:54 +00001726 VG_(bad_option)(arg);
sewardjde4a1d02002-03-22 01:27:54 +00001727 }
nethercote71980f02004-01-24 18:18:54 +00001728 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = &arg[15];
sewardjde4a1d02002-03-22 01:27:54 +00001729 VG_(clo_n_suppressions)++;
1730 }
sewardjde4a1d02002-03-22 01:27:54 +00001731
njn25e49d8e72002-09-23 09:36:25 +00001732 /* "vwxyz" --> 000zyxwv (binary) */
nethercote71980f02004-01-24 18:18:54 +00001733 else if (VG_CLO_STREQN(16, arg, "--trace-codegen=")) {
njn25e49d8e72002-09-23 09:36:25 +00001734 Int j;
nethercote71980f02004-01-24 18:18:54 +00001735 char* opt = & arg[16];
njn25e49d8e72002-09-23 09:36:25 +00001736
1737 if (5 != VG_(strlen)(opt)) {
1738 VG_(message)(Vg_UserMsg,
1739 "--trace-codegen argument must have 5 digits");
nethercote71980f02004-01-24 18:18:54 +00001740 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001741 }
1742 for (j = 0; j < 5; j++) {
1743 if ('0' == opt[j]) { /* do nothing */ }
1744 else if ('1' == opt[j]) VG_(clo_trace_codegen) |= (1 << j);
1745 else {
1746 VG_(message)(Vg_UserMsg, "--trace-codegen argument can only "
1747 "contain 0s and 1s");
nethercote71980f02004-01-24 18:18:54 +00001748 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001749 }
1750 }
1751 }
sewardjde4a1d02002-03-22 01:27:54 +00001752
nethercote71980f02004-01-24 18:18:54 +00001753 else if (VG_CLO_STREQ(arg, "--trace-pthread=none"))
sewardj45b4b372002-04-16 22:50:32 +00001754 VG_(clo_trace_pthread_level) = 0;
nethercote71980f02004-01-24 18:18:54 +00001755 else if (VG_CLO_STREQ(arg, "--trace-pthread=some"))
sewardj45b4b372002-04-16 22:50:32 +00001756 VG_(clo_trace_pthread_level) = 1;
nethercote71980f02004-01-24 18:18:54 +00001757 else if (VG_CLO_STREQ(arg, "--trace-pthread=all"))
sewardj45b4b372002-04-16 22:50:32 +00001758 VG_(clo_trace_pthread_level) = 2;
sewardj8937c812002-04-12 20:12:20 +00001759
nethercote71980f02004-01-24 18:18:54 +00001760 else if ( ! VG_(needs).command_line_options
1761 || ! SK_(process_cmd_line_option)(arg) ) {
nethercotef4928da2004-06-15 10:54:40 +00001762 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001763 }
sewardjde4a1d02002-03-22 01:27:54 +00001764 }
1765
nethercote27fec902004-06-16 21:26:32 +00001766 // Check various option values
1767
njnf9ebf672003-05-12 21:41:30 +00001768 if (VG_(clo_verbosity) < 0)
sewardjde4a1d02002-03-22 01:27:54 +00001769 VG_(clo_verbosity) = 0;
1770
nethercote04d0fbc2004-01-26 16:48:06 +00001771 if (VG_(clo_db_attach) && VG_(clo_trace_children)) {
sewardjde4a1d02002-03-22 01:27:54 +00001772 VG_(message)(Vg_UserMsg, "");
1773 VG_(message)(Vg_UserMsg,
nethercote04d0fbc2004-01-26 16:48:06 +00001774 "--db-attach=yes conflicts with --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001775 VG_(message)(Vg_UserMsg,
1776 "Please choose one or the other, but not both.");
nethercote04d0fbc2004-01-26 16:48:06 +00001777 VG_(bad_option)("--db-attach=yes and --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001778 }
1779
nethercotef8548672004-06-21 12:42:35 +00001780 /* Set up logging now. After this is done, VG_(clo_log_fd)
sewardj4cf05692002-10-27 20:28:29 +00001781 should be connected to whatever sink has been selected, and we
1782 indiscriminately chuck stuff into it without worrying what the
1783 nature of it is. Oh the wonder of Unix streams. */
1784
nethercotee1730692003-11-20 10:38:07 +00001785 /* So far we should be still attached to stdout, so we can show on
sewardj4cf05692002-10-27 20:28:29 +00001786 the terminal any problems to do with processing command line
1787 opts. */
nethercotef8548672004-06-21 12:42:35 +00001788 vg_assert(VG_(clo_log_fd) == 1 /* stdout */);
sewardj73cf3bc2002-11-03 03:20:15 +00001789 vg_assert(VG_(logging_to_filedes) == True);
sewardj4cf05692002-10-27 20:28:29 +00001790
1791 switch (VG_(clo_log_to)) {
sewardj73cf3bc2002-11-03 03:20:15 +00001792
sewardj4cf05692002-10-27 20:28:29 +00001793 case VgLogTo_Fd:
nethercotef8548672004-06-21 12:42:35 +00001794 vg_assert(VG_(clo_log_name) == NULL);
1795 VG_(clo_log_fd) = eventually_log_fd;
sewardj4cf05692002-10-27 20:28:29 +00001796 break;
sewardj73cf3bc2002-11-03 03:20:15 +00001797
sewardj4cf05692002-10-27 20:28:29 +00001798 case VgLogTo_File: {
1799 Char logfilename[1000];
jsgff3c3f1a2003-10-14 22:13:28 +00001800 Int seq = 0;
1801 Int pid = VG_(getpid)();
1802
nethercotef8548672004-06-21 12:42:35 +00001803 vg_assert(VG_(clo_log_name) != NULL);
1804 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
jsgff3c3f1a2003-10-14 22:13:28 +00001805
nethercote71980f02004-01-24 18:18:54 +00001806 for (;;) {
jsgff3c3f1a2003-10-14 22:13:28 +00001807 if (seq == 0)
1808 VG_(sprintf)(logfilename, "%s.pid%d",
nethercotef8548672004-06-21 12:42:35 +00001809 VG_(clo_log_name), pid );
jsgff3c3f1a2003-10-14 22:13:28 +00001810 else
1811 VG_(sprintf)(logfilename, "%s.pid%d.%d",
nethercotef8548672004-06-21 12:42:35 +00001812 VG_(clo_log_name), pid, seq );
jsgff3c3f1a2003-10-14 22:13:28 +00001813 seq++;
1814
nethercotef8548672004-06-21 12:42:35 +00001815 eventually_log_fd
jsgff3c3f1a2003-10-14 22:13:28 +00001816 = VG_(open)(logfilename,
1817 VKI_O_CREAT|VKI_O_WRONLY|VKI_O_EXCL|VKI_O_TRUNC,
1818 VKI_S_IRUSR|VKI_S_IWUSR);
nethercotef8548672004-06-21 12:42:35 +00001819 if (eventually_log_fd >= 0) {
1820 VG_(clo_log_fd) = VG_(safe_fd)(eventually_log_fd);
jsgff3c3f1a2003-10-14 22:13:28 +00001821 break;
1822 } else {
nethercotef8548672004-06-21 12:42:35 +00001823 if (eventually_log_fd != -VKI_EEXIST) {
jsgff3c3f1a2003-10-14 22:13:28 +00001824 VG_(message)(Vg_UserMsg,
1825 "Can't create/open log file `%s.pid%d'; giving up!",
nethercotef8548672004-06-21 12:42:35 +00001826 VG_(clo_log_name), pid);
jsgff3c3f1a2003-10-14 22:13:28 +00001827 VG_(bad_option)(
nethercotef8548672004-06-21 12:42:35 +00001828 "--log-file=<file> didn't work out for some reason.");
jsgff3c3f1a2003-10-14 22:13:28 +00001829 break;
1830 }
1831 }
1832 }
sewardj4cf05692002-10-27 20:28:29 +00001833 break;
sewardj73cf3bc2002-11-03 03:20:15 +00001834 }
1835
1836 case VgLogTo_Socket: {
nethercotef8548672004-06-21 12:42:35 +00001837 vg_assert(VG_(clo_log_name) != NULL);
1838 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
1839 eventually_log_fd = VG_(connect_via_socket)( VG_(clo_log_name) );
1840 if (eventually_log_fd == -1) {
sewardj73cf3bc2002-11-03 03:20:15 +00001841 VG_(message)(Vg_UserMsg,
nethercotef8548672004-06-21 12:42:35 +00001842 "Invalid --log-socket=ipaddr or --log-socket=ipaddr:port spec");
sewardj73cf3bc2002-11-03 03:20:15 +00001843 VG_(message)(Vg_UserMsg,
nethercotef8548672004-06-21 12:42:35 +00001844 "of `%s'; giving up!", VG_(clo_log_name) );
sewardj73cf3bc2002-11-03 03:20:15 +00001845 VG_(bad_option)(
nethercotef8548672004-06-21 12:42:35 +00001846 "--log-socket=");
sewardj4cf05692002-10-27 20:28:29 +00001847 }
nethercotef8548672004-06-21 12:42:35 +00001848 if (eventually_log_fd == -2) {
sewardj73cf3bc2002-11-03 03:20:15 +00001849 VG_(message)(Vg_UserMsg,
sewardj570f8902002-11-03 11:44:36 +00001850 "valgrind: failed to connect to logging server `%s'.",
nethercotef8548672004-06-21 12:42:35 +00001851 VG_(clo_log_name) );
sewardj570f8902002-11-03 11:44:36 +00001852 VG_(message)(Vg_UserMsg,
1853 "Log messages will sent to stderr instead." );
1854 VG_(message)(Vg_UserMsg,
1855 "" );
1856 /* We don't change anything here. */
1857 } else {
nethercotef8548672004-06-21 12:42:35 +00001858 vg_assert(eventually_log_fd > 0);
1859 VG_(clo_log_fd) = eventually_log_fd;
sewardj570f8902002-11-03 11:44:36 +00001860 VG_(logging_to_filedes) = False;
1861 }
sewardj73cf3bc2002-11-03 03:20:15 +00001862 break;
1863 }
1864
sewardj4cf05692002-10-27 20:28:29 +00001865 }
1866
nethercotef8548672004-06-21 12:42:35 +00001867 /* Move log_fd into the safe range, so it doesn't conflict with any app fds */
thughesad1c9562004-06-26 11:27:52 +00001868 eventually_log_fd = VG_(fcntl)(VG_(clo_log_fd), VKI_F_DUPFD, VG_(fd_hard_limit));
nethercotef8548672004-06-21 12:42:35 +00001869 if (eventually_log_fd < 0)
jsgf855d93d2003-10-13 22:26:55 +00001870 VG_(message)(Vg_UserMsg, "valgrind: failed to move logfile fd into safe range");
1871 else {
nethercotef8548672004-06-21 12:42:35 +00001872 VG_(clo_log_fd) = eventually_log_fd;
1873 VG_(fcntl)(VG_(clo_log_fd), VKI_F_SETFD, VKI_FD_CLOEXEC);
jsgf855d93d2003-10-13 22:26:55 +00001874 }
1875
sewardj4cf05692002-10-27 20:28:29 +00001876 /* Ok, the logging sink is running now. Print a suitable preamble.
1877 If logging to file or a socket, write details of parent PID and
1878 command line args, to help people trying to interpret the
1879 results of a run which encompasses multiple processes. */
sewardjde4a1d02002-03-22 01:27:54 +00001880
sewardj83adf412002-05-01 01:25:45 +00001881 if (VG_(clo_verbosity > 0)) {
nethercote996901a2004-08-03 13:29:09 +00001882 /* Tool details */
nethercotea131bb82004-09-06 15:34:37 +00001883 VG_(message)(Vg_UserMsg, "%s%s%s, %s for %s.",
njnd04b7c62002-10-03 14:05:52 +00001884 VG_(details).name,
1885 NULL == VG_(details).version ? "" : "-",
1886 NULL == VG_(details).version
1887 ? (Char*)"" : VG_(details).version,
nethercotea131bb82004-09-06 15:34:37 +00001888 VG_(details).description,
1889 VG_PLATFORM);
njnd04b7c62002-10-03 14:05:52 +00001890 VG_(message)(Vg_UserMsg, "%s", VG_(details).copyright_author);
sewardj3b2736a2002-03-24 12:18:35 +00001891
njnd04b7c62002-10-03 14:05:52 +00001892 /* Core details */
1893 VG_(message)(Vg_UserMsg,
nethercotea131bb82004-09-06 15:34:37 +00001894 "Using valgrind-%s, a program supervision framework for %s.",
1895 VERSION, VG_PLATFORM);
sewardjde4a1d02002-03-22 01:27:54 +00001896 VG_(message)(Vg_UserMsg,
nethercote08fa9a72004-07-16 17:44:00 +00001897 "Copyright (C) 2000-2004, and GNU GPL'd, by Julian Seward et al.");
njnd04b7c62002-10-03 14:05:52 +00001898 }
1899
nethercotec1e395d2003-11-10 13:26:49 +00001900 if (VG_(clo_verbosity) > 0 && VG_(clo_log_to) != VgLogTo_Fd) {
sewardj4cf05692002-10-27 20:28:29 +00001901 VG_(message)(Vg_UserMsg, "");
1902 VG_(message)(Vg_UserMsg,
1903 "My PID = %d, parent PID = %d. Prog and args are:",
1904 VG_(getpid)(), VG_(getppid)() );
1905 for (i = 0; i < VG_(client_argc); i++)
1906 VG_(message)(Vg_UserMsg, " %s", VG_(client_argv)[i]);
1907 }
1908
sewardjde4a1d02002-03-22 01:27:54 +00001909 if (VG_(clo_verbosity) > 1) {
nethercotea70f7352004-04-18 12:08:46 +00001910 Int fd;
sewardj4cf05692002-10-27 20:28:29 +00001911 if (VG_(clo_log_to) != VgLogTo_Fd)
1912 VG_(message)(Vg_UserMsg, "");
fitzhardinge98abfc72003-12-16 02:05:15 +00001913 VG_(message)(Vg_UserMsg, "Valgrind library directory: %s", VG_(libdir));
njn86dc2bc2003-09-09 07:26:21 +00001914 VG_(message)(Vg_UserMsg, "Command line");
1915 for (i = 0; i < VG_(client_argc); i++)
1916 VG_(message)(Vg_UserMsg, " %s", VG_(client_argv)[i]);
1917
sewardjde4a1d02002-03-22 01:27:54 +00001918 VG_(message)(Vg_UserMsg, "Startup, with flags:");
nethercotef6a1d502004-08-09 12:21:57 +00001919 for (i = 1; i < vg_argc; i++) {
1920 VG_(message)(Vg_UserMsg, " %s", vg_argv[i]);
sewardjde4a1d02002-03-22 01:27:54 +00001921 }
nethercotea70f7352004-04-18 12:08:46 +00001922
1923 VG_(message)(Vg_UserMsg, "Contents of /proc/version:");
1924 fd = VG_(open) ( "/proc/version", VKI_O_RDONLY, 0 );
1925 if (fd < 0) {
1926 VG_(message)(Vg_UserMsg, " can't open /proc/version");
1927 } else {
1928 #define BUF_LEN 256
1929 Char version_buf[BUF_LEN];
1930 Int n = VG_(read) ( fd, version_buf, BUF_LEN );
1931 vg_assert(n <= 256);
1932 if (n > 0) {
1933 version_buf[n-1] = '\0';
1934 VG_(message)(Vg_UserMsg, " %s", version_buf);
1935 } else {
1936 VG_(message)(Vg_UserMsg, " (empty?)");
1937 }
1938 VG_(close)(fd);
1939 #undef BUF_LEN
1940 }
sewardjde4a1d02002-03-22 01:27:54 +00001941 }
1942
fitzhardinge98abfc72003-12-16 02:05:15 +00001943 if (VG_(clo_n_suppressions) < VG_CLO_MAX_SFILES-1 &&
njn25e49d8e72002-09-23 09:36:25 +00001944 (VG_(needs).core_errors || VG_(needs).skin_errors)) {
nethercote996901a2004-08-03 13:29:09 +00001945 /* If there are no suppression files specified and the tool
fitzhardinge98abfc72003-12-16 02:05:15 +00001946 needs one, load the default */
1947 static const Char default_supp[] = "default.supp";
1948 Int len = VG_(strlen)(VG_(libdir)) + 1 + sizeof(default_supp);
1949 Char *buf = VG_(arena_malloc)(VG_AR_CORE, len);
1950 VG_(sprintf)(buf, "%s/%s", VG_(libdir), default_supp);
1951 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = buf;
1952 VG_(clo_n_suppressions)++;
sewardjde4a1d02002-03-22 01:27:54 +00001953 }
sewardj4cf05692002-10-27 20:28:29 +00001954
njn6a230532003-07-21 10:38:23 +00001955 if (VG_(clo_gen_suppressions) &&
1956 !VG_(needs).core_errors && !VG_(needs).skin_errors) {
nethercotef4928da2004-06-15 10:54:40 +00001957 VG_(message)(Vg_UserMsg,
1958 "Can't use --gen-suppressions=yes with this tool,");
1959 VG_(message)(Vg_UserMsg,
1960 "as it doesn't generate errors.");
1961 VG_(bad_option)("--gen-suppressions=yes");
njn6a230532003-07-21 10:38:23 +00001962 }
sewardjde4a1d02002-03-22 01:27:54 +00001963}
1964
nethercotef6a1d502004-08-09 12:21:57 +00001965// Build the string for VALGRINDCLO.
1966Char* VG_(build_child_VALGRINDCLO)( Char* exename )
1967{
1968 /* If we're tracing the children, then we need to start it
1969 with our starter+arguments, which are copied into VALGRINDCLO,
1970 except the --exec= option is changed if present.
1971 */
1972 Int i;
1973 Char *exec;
1974 Char *cp;
1975 Char *optvar;
1976 Int optlen, execlen;
1977
1978 // All these allocated blocks are not free - because we're either
1979 // going to exec, or panic when we fail.
1980
1981 // Create --exec= option: "--exec=<exename>"
1982 exec = VG_(arena_malloc)(VG_AR_CORE,
1983 VG_(strlen)( exename ) + 7/*--exec=*/ + 1/*\0*/);
1984 vg_assert(NULL != exec);
1985 VG_(sprintf)(exec, "--exec=%s", exename);
1986
1987 // Allocate space for optvar (may overestimate by counting --exec twice,
1988 // no matter)
1989 optlen = 1;
1990 for (i = 0; i < vg_argc; i++)
1991 optlen += VG_(strlen)(vg_argv[i]) + 1;
1992 optlen += VG_(strlen)(exec)+1;
1993 optvar = VG_(arena_malloc)(VG_AR_CORE, optlen);
1994
1995 // Copy all valgrind args except the old --exec (if present)
1996 // VG_CLO_SEP is the separator.
1997 cp = optvar;
1998 for (i = 1; i < vg_argc; i++) {
1999 Char *arg = vg_argv[i];
2000
2001 if (VG_(memcmp)(arg, "--exec=", 7) == 0) {
2002 // don't copy existing --exec= arg
2003 } else if (VG_(strcmp)(arg, "--") == 0) {
2004 // stop at "--"
2005 break;
2006 } else {
2007 // copy non "--exec" arg
2008 Int len = VG_(strlen)(arg);
2009 VG_(memcpy)(cp, arg, len);
2010 cp += len;
2011 *cp++ = VG_CLO_SEP;
2012 }
2013 }
2014 // Add the new --exec= option
2015 execlen = VG_(strlen)(exec);
2016 VG_(memcpy)(cp, exec, execlen);
2017 cp += execlen;
2018 *cp++ = VG_CLO_SEP;
2019
2020 *cp = '\0';
2021
2022 return optvar;
2023}
2024
2025// Build "/proc/self/fd/<execfd>".
2026Char* VG_(build_child_exename)( void )
2027{
2028 Char* exename = VG_(arena_malloc)(VG_AR_CORE, 64);
2029 vg_assert(NULL != exename);
2030 VG_(sprintf)(exename, "/proc/self/fd/%d", vgexecfd);
2031 return exename;
2032}
2033
sewardjde4a1d02002-03-22 01:27:54 +00002034
nethercote71980f02004-01-24 18:18:54 +00002035/*====================================================================*/
2036/*=== File descriptor setup ===*/
2037/*====================================================================*/
2038
2039static void setup_file_descriptors(void)
2040{
2041 struct vki_rlimit rl;
2042
2043 /* Get the current file descriptor limits. */
2044 if (VG_(getrlimit)(VKI_RLIMIT_NOFILE, &rl) < 0) {
2045 rl.rlim_cur = 1024;
2046 rl.rlim_max = 1024;
2047 }
2048
2049 /* Work out where to move the soft limit to. */
2050 if (rl.rlim_cur + VG_N_RESERVED_FDS <= rl.rlim_max) {
2051 rl.rlim_cur = rl.rlim_cur + VG_N_RESERVED_FDS;
2052 } else {
2053 rl.rlim_cur = rl.rlim_max;
2054 }
2055
2056 /* Reserve some file descriptors for our use. */
thughesad1c9562004-06-26 11:27:52 +00002057 VG_(fd_soft_limit) = rl.rlim_cur - VG_N_RESERVED_FDS;
2058 VG_(fd_hard_limit) = rl.rlim_cur - VG_N_RESERVED_FDS;
nethercote71980f02004-01-24 18:18:54 +00002059
2060 /* Update the soft limit. */
2061 VG_(setrlimit)(VKI_RLIMIT_NOFILE, &rl);
2062
nethercotef6a1d502004-08-09 12:21:57 +00002063 if (vgexecfd != -1)
2064 vgexecfd = VG_(safe_fd)( vgexecfd );
nethercote71980f02004-01-24 18:18:54 +00002065 if (VG_(clexecfd) != -1)
2066 VG_(clexecfd) = VG_(safe_fd)( VG_(clexecfd) );
2067}
2068
2069
2070/*====================================================================*/
nethercote1d447092004-02-01 17:29:59 +00002071/*=== baseBlock: definition + setup ===*/
nethercote71980f02004-01-24 18:18:54 +00002072/*====================================================================*/
2073
nethercote71980f02004-01-24 18:18:54 +00002074Int VGOFF_(helper_undefined_instruction) = INVALID_OFFSET;
2075
2076/* MAX_NONCOMPACT_HELPERS can be increased easily. If MAX_COMPACT_HELPERS is
2077 * increased too much, they won't really be compact any more... */
2078#define MAX_COMPACT_HELPERS 8
2079#define MAX_NONCOMPACT_HELPERS 50
2080
nethercote81f9a6f2004-08-03 15:45:46 +00002081/* For storing tool-specific helpers, determined at runtime. The addr
2082 * and offset arrays together form a (addr, offset) map that allows a
2083 * helper's baseBlock offset to be computed from its address. It's done
2084 * like this so CCALLs can use the function address rather than having to
2085 * muck around with offsets. */
2086static UInt VG_(n_compact_helpers) = 0;
2087static UInt VG_(n_noncompact_helpers) = 0;
2088static Addr VG_(compact_helper_addrs) [MAX_COMPACT_HELPERS];
2089static Int VG_(compact_helper_offsets)[MAX_COMPACT_HELPERS];
2090static Addr VG_(noncompact_helper_addrs) [MAX_NONCOMPACT_HELPERS];
2091static Int VG_(noncompact_helper_offsets)[MAX_NONCOMPACT_HELPERS];
nethercote71980f02004-01-24 18:18:54 +00002092
2093/* This is the actual defn of baseblock. */
2094UInt VG_(baseBlock)[VG_BASEBLOCK_WORDS];
2095
nethercote71980f02004-01-24 18:18:54 +00002096/* Words. */
2097static Int baB_off = 0;
2098
2099
nethercote71980f02004-01-24 18:18:54 +00002100/* Returns the offset, in words. */
nethercote2e05c332004-09-06 16:43:37 +00002101Int VG_(alloc_BaB) ( Int words )
sewardjde4a1d02002-03-22 01:27:54 +00002102{
nethercote71980f02004-01-24 18:18:54 +00002103 Int off = baB_off;
2104 baB_off += words;
2105 if (baB_off >= VG_BASEBLOCK_WORDS)
nethercote2e05c332004-09-06 16:43:37 +00002106 VG_(core_panic)( "VG_(alloc_BaB): baseBlock is too small");
sewardjde4a1d02002-03-22 01:27:54 +00002107
nethercote71980f02004-01-24 18:18:54 +00002108 return off;
sewardjde4a1d02002-03-22 01:27:54 +00002109}
2110
nethercote71980f02004-01-24 18:18:54 +00002111/* Align offset, in *bytes* */
nethercote2e05c332004-09-06 16:43:37 +00002112void VG_(align_BaB) ( UInt align )
njn25e49d8e72002-09-23 09:36:25 +00002113{
nethercote71980f02004-01-24 18:18:54 +00002114 vg_assert(2 == align || 4 == align || 8 == align || 16 == align);
2115 baB_off += (align-1);
2116 baB_off &= ~(align-1);
njn25e49d8e72002-09-23 09:36:25 +00002117}
2118
nethercote71980f02004-01-24 18:18:54 +00002119/* Allocate 1 word in baseBlock and set it to the given value. */
nethercote2e05c332004-09-06 16:43:37 +00002120Int VG_(alloc_BaB_1_set) ( Addr a )
njn25e49d8e72002-09-23 09:36:25 +00002121{
nethercote2e05c332004-09-06 16:43:37 +00002122 Int off = VG_(alloc_BaB)(1);
nethercote71980f02004-01-24 18:18:54 +00002123 VG_(baseBlock)[off] = (UInt)a;
2124 return off;
njn25e49d8e72002-09-23 09:36:25 +00002125}
2126
nethercote71980f02004-01-24 18:18:54 +00002127/* Registers a function in compact_helper_addrs; compact_helper_offsets is
2128 filled in later. */
2129void VG_(register_compact_helper)(Addr a)
sewardjde4a1d02002-03-22 01:27:54 +00002130{
nethercote71980f02004-01-24 18:18:54 +00002131 if (MAX_COMPACT_HELPERS <= VG_(n_compact_helpers)) {
2132 VG_(printf)("Can only register %d compact helpers\n",
2133 MAX_COMPACT_HELPERS);
2134 VG_(core_panic)("Too many compact helpers registered");
2135 }
2136 VG_(compact_helper_addrs)[VG_(n_compact_helpers)] = a;
2137 VG_(n_compact_helpers)++;
2138}
2139
2140/* Registers a function in noncompact_helper_addrs; noncompact_helper_offsets
2141 * is filled in later.
2142 */
2143void VG_(register_noncompact_helper)(Addr a)
2144{
2145 if (MAX_NONCOMPACT_HELPERS <= VG_(n_noncompact_helpers)) {
2146 VG_(printf)("Can only register %d non-compact helpers\n",
2147 MAX_NONCOMPACT_HELPERS);
2148 VG_(printf)("Try increasing MAX_NON_COMPACT_HELPERS\n");
2149 VG_(core_panic)("Too many non-compact helpers registered");
2150 }
2151 VG_(noncompact_helper_addrs)[VG_(n_noncompact_helpers)] = a;
2152 VG_(n_noncompact_helpers)++;
2153}
2154
nethercote996901a2004-08-03 13:29:09 +00002155/* Allocate offsets in baseBlock for the tool helpers */
nethercote71980f02004-01-24 18:18:54 +00002156static
2157void assign_helpers_in_baseBlock(UInt n, Int offsets[], Addr addrs[])
2158{
2159 UInt i;
2160 for (i = 0; i < n; i++)
nethercote2e05c332004-09-06 16:43:37 +00002161 offsets[i] = VG_(alloc_BaB_1_set)( addrs[i] );
nethercote71980f02004-01-24 18:18:54 +00002162}
2163
2164Bool VG_(need_to_handle_esp_assignment)(void)
2165{
2166 return ( VG_(defined_new_mem_stack_4)() ||
2167 VG_(defined_die_mem_stack_4)() ||
2168 VG_(defined_new_mem_stack_8)() ||
2169 VG_(defined_die_mem_stack_8)() ||
2170 VG_(defined_new_mem_stack_12)() ||
2171 VG_(defined_die_mem_stack_12)() ||
2172 VG_(defined_new_mem_stack_16)() ||
2173 VG_(defined_die_mem_stack_16)() ||
2174 VG_(defined_new_mem_stack_32)() ||
2175 VG_(defined_die_mem_stack_32)() ||
2176 VG_(defined_new_mem_stack)() ||
2177 VG_(defined_die_mem_stack)()
2178 );
2179}
2180
nethercote2e05c332004-09-06 16:43:37 +00002181// The low/high split is for x86, so that the more common helpers can be
2182// in the first 128 bytes of the start, which allows the use of a more
2183// compact addressing mode.
nethercote71980f02004-01-24 18:18:54 +00002184static void init_baseBlock ( Addr client_eip, Addr esp_at_startup )
2185{
nethercote2e05c332004-09-06 16:43:37 +00002186 VGA_(init_low_baseBlock)(client_eip, esp_at_startup);
nethercote71980f02004-01-24 18:18:54 +00002187
nethercote71980f02004-01-24 18:18:54 +00002188 /* Allocate slots for compact helpers */
2189 assign_helpers_in_baseBlock(VG_(n_compact_helpers),
2190 VG_(compact_helper_offsets),
2191 VG_(compact_helper_addrs));
2192
nethercote2e05c332004-09-06 16:43:37 +00002193 VGA_(init_high_baseBlock)(client_eip, esp_at_startup);
fitzhardingef0046f22003-12-18 02:39:22 +00002194
nethercote71980f02004-01-24 18:18:54 +00002195#define REG(kind, size) \
2196 if (VG_(defined_##kind##_mem_stack##size)()) \
2197 VG_(register_noncompact_helper)( \
2198 (Addr) VG_(tool_interface).track_##kind##_mem_stack##size );
2199 REG(new, _8);
2200 REG(new, _12);
2201 REG(new, _16);
2202 REG(new, _32);
2203 REG(new, );
2204 REG(die, _8);
2205 REG(die, _12);
2206 REG(die, _16);
2207 REG(die, _32);
2208 REG(die, );
2209#undef REG
fitzhardingef0046f22003-12-18 02:39:22 +00002210
nethercote71980f02004-01-24 18:18:54 +00002211 if (VG_(need_to_handle_esp_assignment)())
2212 VG_(register_noncompact_helper)((Addr) VG_(unknown_esp_update));
fitzhardingeb791a192003-12-18 07:22:44 +00002213
nethercote2e05c332004-09-06 16:43:37 +00002214 VGOFF_(helper_undefined_instruction)
2215 = VG_(alloc_BaB_1_set)( (Addr) & VG_(helper_undefined_instruction));
sewardjde4a1d02002-03-22 01:27:54 +00002216
nethercote71980f02004-01-24 18:18:54 +00002217 /* Allocate slots for noncompact helpers */
2218 assign_helpers_in_baseBlock(VG_(n_noncompact_helpers),
2219 VG_(noncompact_helper_offsets),
2220 VG_(noncompact_helper_addrs));
2221}
sewardjde4a1d02002-03-22 01:27:54 +00002222
nethercote81f9a6f2004-08-03 15:45:46 +00002223// Finds the baseBlock offset of a tool-specified helper.
2224// Searches through compacts first, then non-compacts.
2225Int VG_(helper_offset)(Addr a)
2226{
2227 UInt i;
2228 Char buf[100];
2229
2230 for (i = 0; i < VG_(n_compact_helpers); i++)
2231 if (VG_(compact_helper_addrs)[i] == a)
2232 return VG_(compact_helper_offsets)[i];
2233 for (i = 0; i < VG_(n_noncompact_helpers); i++)
2234 if (VG_(noncompact_helper_addrs)[i] == a)
2235 return VG_(noncompact_helper_offsets)[i];
2236
2237 /* Shouldn't get here */
2238 VG_(get_fnname) ( a, buf, 100 );
2239
2240 VG_(printf)(
2241 "\nCouldn't find offset of helper from its address (%p: %s).\n"
2242 "A helper function probably used hasn't been registered?\n\n", a, buf);
2243
2244 VG_(printf)(" compact helpers: ");
2245 for (i = 0; i < VG_(n_compact_helpers); i++)
2246 VG_(printf)("%p ", VG_(compact_helper_addrs)[i]);
2247
2248 VG_(printf)("\n non-compact helpers: ");
2249 for (i = 0; i < VG_(n_noncompact_helpers); i++)
2250 VG_(printf)("%p ", VG_(noncompact_helper_addrs)[i]);
2251
2252 VG_(printf)("\n");
2253 VG_(skin_panic)("Unfound helper");
2254}
2255
sewardj5f07b662002-04-23 16:52:51 +00002256
nethercote71980f02004-01-24 18:18:54 +00002257/*====================================================================*/
nethercote71980f02004-01-24 18:18:54 +00002258/*=== Initialise program data/text, etc. ===*/
2259/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +00002260
nethercote71980f02004-01-24 18:18:54 +00002261static void build_valgrind_map_callback
2262 ( Addr start, UInt size, Char rr, Char ww, Char xx,
2263 UInt dev, UInt ino, ULong foffset, const UChar* filename )
sewardjde4a1d02002-03-22 01:27:54 +00002264{
nethercote71980f02004-01-24 18:18:54 +00002265 UInt prot = 0;
2266 UInt flags = SF_MMAP|SF_NOSYMS;
2267 Bool is_stack_segment;
2268
2269 is_stack_segment =
2270 (start == VG_(clstk_base) && (start+size) == VG_(clstk_end));
2271
2272 /* Only record valgrind mappings for now, without loading any
2273 symbols. This is so we know where the free space is before we
2274 start allocating more memory (note: heap is OK, it's just mmap
2275 which is the problem here). */
nethercote820bd8c2004-09-07 23:04:49 +00002276 if (start >= VG_(valgrind_base) && (start+size-1) <= VG_(valgrind_last)) {
nethercote71980f02004-01-24 18:18:54 +00002277 flags |= SF_VALGRIND;
2278 VG_(map_file_segment)(start, size, prot, flags, dev, ino, foffset, filename);
2279 }
sewardjde4a1d02002-03-22 01:27:54 +00002280}
2281
nethercote71980f02004-01-24 18:18:54 +00002282// Global var used to pass local data to callback
2283Addr esp_at_startup___global_arg = 0;
sewardjde4a1d02002-03-22 01:27:54 +00002284
nethercote71980f02004-01-24 18:18:54 +00002285static void build_segment_map_callback
2286 ( Addr start, UInt size, Char rr, Char ww, Char xx,
2287 UInt dev, UInt ino, ULong foffset, const UChar* filename )
sewardj45b672d2003-07-25 19:58:11 +00002288{
nethercote71980f02004-01-24 18:18:54 +00002289 UInt prot = 0;
2290 UInt flags;
2291 Bool is_stack_segment;
2292 Addr r_esp;
sewardj45b672d2003-07-25 19:58:11 +00002293
nethercote71980f02004-01-24 18:18:54 +00002294 is_stack_segment
2295 = (start == VG_(clstk_base) && (start+size) == VG_(clstk_end));
fitzhardinge98abfc72003-12-16 02:05:15 +00002296
nethercote71980f02004-01-24 18:18:54 +00002297 if (rr == 'r') prot |= VKI_PROT_READ;
2298 if (ww == 'w') prot |= VKI_PROT_WRITE;
2299 if (xx == 'x') prot |= VKI_PROT_EXEC;
fitzhardinge98abfc72003-12-16 02:05:15 +00002300
nethercote71980f02004-01-24 18:18:54 +00002301 if (is_stack_segment)
2302 flags = SF_STACK | SF_GROWDOWN;
2303 else
2304 flags = SF_EXEC|SF_MMAP;
fitzhardinge98abfc72003-12-16 02:05:15 +00002305
nethercote71980f02004-01-24 18:18:54 +00002306 if (filename != NULL)
2307 flags |= SF_FILE;
fitzhardinge98abfc72003-12-16 02:05:15 +00002308
nethercote820bd8c2004-09-07 23:04:49 +00002309 if (start >= VG_(valgrind_base) && (start+size-1) <= VG_(valgrind_last))
nethercote71980f02004-01-24 18:18:54 +00002310 flags |= SF_VALGRIND;
fitzhardinge98abfc72003-12-16 02:05:15 +00002311
nethercote71980f02004-01-24 18:18:54 +00002312 VG_(map_file_segment)(start, size, prot, flags, dev, ino, foffset, filename);
fitzhardinge98abfc72003-12-16 02:05:15 +00002313
nethercote71980f02004-01-24 18:18:54 +00002314 if (VG_(is_client_addr)(start) && VG_(is_client_addr)(start+size-1))
2315 VG_TRACK( new_mem_startup, start, size, rr=='r', ww=='w', xx=='x' );
sewardj3e1eb1f2002-05-18 13:14:17 +00002316
nethercote71980f02004-01-24 18:18:54 +00002317 /* If this is the stack segment mark all below %esp as noaccess. */
2318 r_esp = esp_at_startup___global_arg;
2319 vg_assert(0 != r_esp);
2320 if (is_stack_segment) {
2321 if (0)
2322 VG_(message)(Vg_DebugMsg, "invalidating stack area: %x .. %x",
2323 start,r_esp);
2324 VG_TRACK( die_mem_stack, start, r_esp-start );
sewardjde4a1d02002-03-22 01:27:54 +00002325 }
sewardjde4a1d02002-03-22 01:27:54 +00002326}
2327
2328
nethercote71980f02004-01-24 18:18:54 +00002329/*====================================================================*/
2330/*=== Sanity check machinery (permanently engaged) ===*/
2331/*====================================================================*/
njn25e49d8e72002-09-23 09:36:25 +00002332
2333/* A fast sanity check -- suitable for calling circa once per
2334 millisecond. */
2335
nethercote885dd912004-08-03 23:14:00 +00002336void VG_(sanity_check_general) ( Bool force_expensive )
njn25e49d8e72002-09-23 09:36:25 +00002337{
njn37cea302002-09-30 11:24:00 +00002338 VGP_PUSHCC(VgpCoreCheapSanity);
2339
nethercote27fec902004-06-16 21:26:32 +00002340 if (VG_(clo_sanity_level) < 1) return;
njn25e49d8e72002-09-23 09:36:25 +00002341
2342 /* --- First do all the tests that we can do quickly. ---*/
2343
nethercote297effd2004-08-02 15:07:57 +00002344 sanity_fast_count++;
njn25e49d8e72002-09-23 09:36:25 +00002345
njn25e49d8e72002-09-23 09:36:25 +00002346 /* Check stuff pertaining to the memory check system. */
2347
2348 /* Check that nobody has spuriously claimed that the first or
2349 last 16 pages of memory have become accessible [...] */
njn37cea302002-09-30 11:24:00 +00002350 if (VG_(needs).sanity_checks) {
2351 VGP_PUSHCC(VgpSkinCheapSanity);
njn25e49d8e72002-09-23 09:36:25 +00002352 vg_assert(SK_(cheap_sanity_check)());
njn37cea302002-09-30 11:24:00 +00002353 VGP_POPCC(VgpSkinCheapSanity);
2354 }
njn25e49d8e72002-09-23 09:36:25 +00002355
2356 /* --- Now some more expensive checks. ---*/
2357
2358 /* Once every 25 times, check some more expensive stuff. */
2359 if ( force_expensive
nethercote27fec902004-06-16 21:26:32 +00002360 || VG_(clo_sanity_level) > 1
nethercote297effd2004-08-02 15:07:57 +00002361 || (VG_(clo_sanity_level) == 1 && (sanity_fast_count % 25) == 0)) {
njn25e49d8e72002-09-23 09:36:25 +00002362
njn37cea302002-09-30 11:24:00 +00002363 VGP_PUSHCC(VgpCoreExpensiveSanity);
nethercote297effd2004-08-02 15:07:57 +00002364 sanity_slow_count++;
njn25e49d8e72002-09-23 09:36:25 +00002365
nethercote885dd912004-08-03 23:14:00 +00002366 VG_(sanity_check_proxy)();
jsgf855d93d2003-10-13 22:26:55 +00002367
njn25e49d8e72002-09-23 09:36:25 +00002368# if 0
2369 { void zzzmemscan(void); zzzmemscan(); }
2370# endif
2371
nethercote297effd2004-08-02 15:07:57 +00002372 if ((sanity_fast_count % 250) == 0)
nethercote92e7b7f2004-08-07 17:52:25 +00002373 VG_(sanity_check_tt_tc)();
njn25e49d8e72002-09-23 09:36:25 +00002374
2375 if (VG_(needs).sanity_checks) {
njn37cea302002-09-30 11:24:00 +00002376 VGP_PUSHCC(VgpSkinExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002377 vg_assert(SK_(expensive_sanity_check)());
njn37cea302002-09-30 11:24:00 +00002378 VGP_POPCC(VgpSkinExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002379 }
2380 /*
nethercote297effd2004-08-02 15:07:57 +00002381 if ((sanity_fast_count % 500) == 0) VG_(mallocSanityCheckAll)();
njn25e49d8e72002-09-23 09:36:25 +00002382 */
njn37cea302002-09-30 11:24:00 +00002383 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002384 }
2385
nethercote27fec902004-06-16 21:26:32 +00002386 if (VG_(clo_sanity_level) > 1) {
njn37cea302002-09-30 11:24:00 +00002387 VGP_PUSHCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002388 /* Check sanity of the low-level memory manager. Note that bugs
2389 in the client's code can cause this to fail, so we don't do
2390 this check unless specially asked for. And because it's
2391 potentially very expensive. */
nethercote885dd912004-08-03 23:14:00 +00002392 VG_(sanity_check_malloc_all)();
njn37cea302002-09-30 11:24:00 +00002393 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002394 }
njn37cea302002-09-30 11:24:00 +00002395 VGP_POPCC(VgpCoreCheapSanity);
njn25e49d8e72002-09-23 09:36:25 +00002396}
nethercote71980f02004-01-24 18:18:54 +00002397
2398
2399/*====================================================================*/
2400/*=== main() ===*/
2401/*====================================================================*/
2402
nethercotec314eba2004-07-15 12:59:41 +00002403/*
2404 This code decides on the layout of the client and Valgrind address
nethercote996901a2004-08-03 13:29:09 +00002405 spaces, loads valgrind.so and the tool.so into the valgrind part,
nethercotec314eba2004-07-15 12:59:41 +00002406 loads the client executable (and the dynamic linker, if necessary)
2407 into the client part, and calls into Valgrind proper.
2408
2409 The code is careful not to allow spurious mappings to appear in the
2410 wrong parts of the address space. In particular, to make sure
2411 dlopen puts things in the right place, it will pad out the forbidden
2412 chunks of address space so that dlopen is forced to put things where
2413 we want them.
2414
2415 The memory map it creates is:
2416
2417 CLIENT_BASE +-------------------------+
2418 | client address space |
2419 : :
2420 : :
2421 | client stack |
2422 client_end +-------------------------+
2423 | redzone |
2424 shadow_base +-------------------------+
2425 | |
nethercote996901a2004-08-03 13:29:09 +00002426 : shadow memory for tools :
nethercotec314eba2004-07-15 12:59:41 +00002427 | (may be 0 sized) |
2428 shadow_end +-------------------------+
nethercotec314eba2004-07-15 12:59:41 +00002429 valgrind_base +-------------------------+
2430 | kickstart executable |
2431 | valgrind heap vvvvvvvvv| (barely used)
2432 - -
2433 | valgrind .so files |
2434 | and mappings |
2435 - -
2436 | valgrind stack ^^^^^^^^^|
nethercote820bd8c2004-09-07 23:04:49 +00002437 valgrind_last +-------------------------+
nethercotec314eba2004-07-15 12:59:41 +00002438 : kernel :
2439
2440 Nb: Before we can do general allocations with VG_(arena_malloc)() and
2441 VG_(mmap)(), we need to build the segment skip-list, so we know where
2442 we can put things. However, building that structure requires
2443 allocating memory. So we need to a bootstrapping process. It's done
2444 by making VG_(arena_malloc)() have a special static superblock that's
2445 used for the first 1MB's worth of allocations. This is enough to
2446 build the segment skip-list.
2447*/
2448
nethercote31779c72004-07-30 21:50:15 +00002449static int prmap(char *start, char *end, const char *perm, off_t off,
2450 int maj, int min, int ino, void* dummy) {
thughes4ad52d02004-06-27 17:37:21 +00002451 printf("mapping %10p-%10p %s %02x:%02x %d\n",
2452 start, end, perm, maj, min, ino);
2453 return True;
2454}
2455
nethercote71980f02004-01-24 18:18:54 +00002456int main(int argc, char **argv)
2457{
2458 char **cl_argv;
2459 const char *tool = NULL;
2460 const char *exec = NULL;
2461 char *preload; /* tool-specific LD_PRELOAD .so */
2462 char **env;
nethercote6c999f22004-01-31 22:55:15 +00002463 Int need_help = 0; // 0 = no, 1 = --help, 2 = --help-debug
nethercote71980f02004-01-24 18:18:54 +00002464 struct exeinfo info;
2465 ToolInfo *toolinfo = NULL;
2466 void *tool_dlhandle;
2467 Addr client_eip;
2468 Addr esp_at_startup; /* client's %esp at the point we gained control. */
2469 UInt * client_auxv;
2470 VgSchedReturnCode src;
nethercote47dd12c2004-06-22 14:18:42 +00002471 Int exitcode = 0;
nethercote238a3c32004-08-09 13:13:31 +00002472 Int fatal_sigNo = -1;
fitzhardingeb50068f2004-02-24 23:42:55 +00002473 vki_rlimit zero = { 0, 0 };
nethercote31779c72004-07-30 21:50:15 +00002474 Int padfile;
nethercote759dda32004-08-07 18:16:56 +00002475 ThreadId last_run_tid = 0; // Last thread the scheduler ran.
2476
nethercote71980f02004-01-24 18:18:54 +00002477
2478 //============================================================
2479 // Nb: startup is complex. Prerequisites are shown at every step.
2480 //
2481 // *** Be very careful when messing with the order ***
2482 //============================================================
2483
nethercotef4928da2004-06-15 10:54:40 +00002484 //============================================================
2485 // Command line argument handling order:
2486 // * If --help/--help-debug are present, show usage message
2487 // (if --tool is also present, that includes the tool-specific usage)
2488 // * Then, if --tool is missing, abort with error msg
2489 // * Then, if client is missing, abort with error msg
2490 // * Then, if any cmdline args are bad, abort with error msg
2491 //============================================================
2492
fitzhardingeb50068f2004-02-24 23:42:55 +00002493 // Get the current process datasize rlimit, and set it to zero.
2494 // This prevents any internal uses of brk() from having any effect.
2495 // We remember the old value so we can restore it on exec, so that
2496 // child processes will have a reasonable brk value.
2497 VG_(getrlimit)(VKI_RLIMIT_DATA, &VG_(client_rlimit_data));
2498 zero.rlim_max = VG_(client_rlimit_data).rlim_max;
2499 VG_(setrlimit)(VKI_RLIMIT_DATA, &zero);
thughesc37184f2004-09-11 14:16:57 +00002500
2501 // Get the current process stack rlimit.
2502 VG_(getrlimit)(VKI_RLIMIT_STACK, &VG_(client_rlimit_stack));
2503
nethercote71980f02004-01-24 18:18:54 +00002504 //--------------------------------------------------------------
2505 // Check we were launched by stage1
nethercotec314eba2004-07-15 12:59:41 +00002506 // p: n/a
nethercote71980f02004-01-24 18:18:54 +00002507 //--------------------------------------------------------------
nethercote31779c72004-07-30 21:50:15 +00002508 padfile = scan_auxv();
nethercote71980f02004-01-24 18:18:54 +00002509
2510 if (0) {
nethercote71980f02004-01-24 18:18:54 +00002511 printf("========== main() ==========\n");
nethercote31779c72004-07-30 21:50:15 +00002512 foreach_map(prmap, /*dummy*/NULL);
nethercote71980f02004-01-24 18:18:54 +00002513 }
2514
2515 //--------------------------------------------------------------
2516 // Look for alternative libdir
2517 // p: n/a
2518 //--------------------------------------------------------------
2519 { char *cp = getenv(VALGRINDLIB);
2520 if (cp != NULL)
2521 VG_(libdir) = cp;
2522 }
2523
2524 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002525 // Get valgrind args + client args (inc. from VALGRIND_OPTS/.valgrindrc).
2526 // Pre-process the command line.
2527 // p: n/a
2528 //--------------------------------------------------------------
nethercotef6a1d502004-08-09 12:21:57 +00002529 get_command_line(argc, argv, &vg_argc, &vg_argv, &cl_argv);
nethercote71980f02004-01-24 18:18:54 +00002530 pre_process_cmd_line_options(&need_help, &tool, &exec);
2531
2532 //==============================================================
2533 // Nb: once a tool is specified, the tool.so must be loaded even if
2534 // they specified --help or didn't specify a client program.
2535 //==============================================================
2536
2537 //--------------------------------------------------------------
2538 // With client padded out, map in tool
nethercote71980f02004-01-24 18:18:54 +00002539 // p: set-libdir [for VG_(libdir)]
2540 // p: pre_process_cmd_line_options() [for 'tool']
2541 //--------------------------------------------------------------
2542 load_tool(tool, &tool_dlhandle, &toolinfo, &preload);
2543
2544 //==============================================================
2545 // Can use VG_(malloc)() and VG_(arena_malloc)() only after load_tool()
nethercotec314eba2004-07-15 12:59:41 +00002546 // -- redzone size is now set. This is checked by vg_malloc2.c.
nethercote71980f02004-01-24 18:18:54 +00002547 //==============================================================
2548
2549 //--------------------------------------------------------------
2550 // Finalise address space layout
nethercote31779c72004-07-30 21:50:15 +00002551 // p: load_tool() [for 'toolinfo']
nethercote71980f02004-01-24 18:18:54 +00002552 //--------------------------------------------------------------
nethercote31779c72004-07-30 21:50:15 +00002553 layout_remaining_space( (Addr) & argc, toolinfo->shadow_ratio );
nethercote71980f02004-01-24 18:18:54 +00002554
2555 //--------------------------------------------------------------
2556 // Load client executable, finding in $PATH if necessary
nethercote71980f02004-01-24 18:18:54 +00002557 // p: pre_process_cmd_line_options() [for 'exec', 'need_help']
2558 // p: layout_remaining_space [so there's space]
2559 //--------------------------------------------------------------
nethercotef4928da2004-06-15 10:54:40 +00002560 load_client(cl_argv, exec, need_help, &info, &client_eip);
nethercote71980f02004-01-24 18:18:54 +00002561
2562 //--------------------------------------------------------------
2563 // Everything in place, unpad us
2564 // p: layout_remaining_space() [everything must be mapped in before now]
2565 // p: load_client() [ditto]
2566 //--------------------------------------------------------------
nethercote31779c72004-07-30 21:50:15 +00002567 as_unpad((void *)VG_(shadow_end), (void *)~0, padfile);
2568 as_closepadfile(padfile); // no more padding
nethercote71980f02004-01-24 18:18:54 +00002569
2570 //--------------------------------------------------------------
2571 // Set up client's environment
2572 // p: set-libdir [for VG_(libdir)]
2573 // p: load_tool() [for 'preload']
2574 //--------------------------------------------------------------
2575 env = fix_environment(environ, preload);
2576
2577 //--------------------------------------------------------------
nethercote5ee67ca2004-06-22 14:00:09 +00002578 // Setup client stack, eip, and VG_(client_arg[cv])
nethercote71980f02004-01-24 18:18:54 +00002579 // p: load_client() [for 'info']
2580 // p: fix_environment() [for 'env']
2581 //--------------------------------------------------------------
2582 esp_at_startup = setup_client_stack(cl_argv, env, &info, &client_auxv);
2583
2584 if (0)
nethercote6a27d832004-09-07 10:17:02 +00002585 printf("entry=%p client esp=%p vg_argc=%d brkbase=%p\n",
2586 (void*)client_eip, (void*)esp_at_startup, vg_argc,
2587 (void*)VG_(brk_base));
nethercote71980f02004-01-24 18:18:54 +00002588
2589 //==============================================================
2590 // Finished setting up operating environment. Now initialise
2591 // Valgrind. (This is where the old VG_(main)() started.)
2592 //==============================================================
2593
2594 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002595 // atfork
2596 // p: n/a
2597 //--------------------------------------------------------------
2598 VG_(atfork)(NULL, NULL, newpid);
2599 newpid(VG_INVALID_THREADID);
2600
2601 //--------------------------------------------------------------
2602 // setup file descriptors
2603 // p: n/a
2604 //--------------------------------------------------------------
2605 setup_file_descriptors();
2606
2607 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002608 // Read /proc/self/maps into a buffer
2609 // p: all memory layout, environment setup [so memory maps are right]
2610 //--------------------------------------------------------------
2611 VG_(read_procselfmaps)();
2612
2613 //--------------------------------------------------------------
2614 // Build segment map (Valgrind segments only)
2615 // p: read proc/self/maps
2616 // p: sk_pre_clo_init() [to setup new_mem_startup tracker]
2617 //--------------------------------------------------------------
2618 VG_(parse_procselfmaps) ( build_valgrind_map_callback );
2619
2620 //==============================================================
2621 // Can use VG_(arena_malloc)() with non-CORE arena after segments set up
2622 //==============================================================
2623
2624 //--------------------------------------------------------------
2625 // Init tool: pre_clo_init, process cmd line, post_clo_init
2626 // p: setup_client_stack() [for 'VG_(client_arg[cv]']
2627 // p: load_tool() [for 'tool']
2628 // p: setup_file_descriptors() [for 'VG_(fd_xxx_limit)']
2629 // p: parse_procselfmaps [so VG segments are setup so tool can
2630 // call VG_(malloc)]
nethercote71980f02004-01-24 18:18:54 +00002631 //--------------------------------------------------------------
2632 (*toolinfo->sk_pre_clo_init)();
2633 VG_(tool_init_dlsym)(tool_dlhandle);
2634 VG_(sanity_check_needs)();
2635
nethercotef4928da2004-06-15 10:54:40 +00002636 // If --tool and --help/--help-debug was given, now give the core+tool
2637 // help message
nethercotef4928da2004-06-15 10:54:40 +00002638 if (need_help) {
2639 usage(/*--help-debug?*/2 == need_help);
2640 }
nethercotec314eba2004-07-15 12:59:41 +00002641 process_cmd_line_options(client_auxv, tool);
2642
2643 SK_(post_clo_init)();
nethercotef4928da2004-06-15 10:54:40 +00002644
2645 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002646 // Build segment map (all segments)
2647 // p: setup_client_stack() [for 'esp_at_startup']
2648 // p: init tool [for 'new_mem_startup']
nethercote71980f02004-01-24 18:18:54 +00002649 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002650 esp_at_startup___global_arg = esp_at_startup;
2651 VG_(parse_procselfmaps) ( build_segment_map_callback ); /* everything */
2652 esp_at_startup___global_arg = 0;
2653
2654 //--------------------------------------------------------------
nethercotef84f6952004-07-15 14:58:33 +00002655 // Protect client trampoline page (which is also sysinfo stuff)
2656 // p: segment stuff [otherwise get seg faults...]
nethercotec314eba2004-07-15 12:59:41 +00002657 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002658 VG_(mprotect)( (void *)VG_(client_trampoline_code),
2659 VG_(trampoline_code_length), VKI_PROT_READ|VKI_PROT_EXEC );
2660
2661 //==============================================================
2662 // Can use VG_(map)() after segments set up
2663 //==============================================================
nethercote71980f02004-01-24 18:18:54 +00002664
2665 //--------------------------------------------------------------
2666 // Allow GDB attach
2667 // p: process_cmd_line_options() [for VG_(clo_wait_for_gdb)]
2668 //--------------------------------------------------------------
2669 /* Hook to delay things long enough so we can get the pid and
2670 attach GDB in another shell. */
2671 if (VG_(clo_wait_for_gdb)) {
2672 VG_(printf)("pid=%d\n", VG_(getpid)());
2673 /* do "jump *$eip" to skip this in gdb */
2674 VG_(do_syscall)(__NR_pause);
2675 }
2676
2677 //--------------------------------------------------------------
nethercote1d447092004-02-01 17:29:59 +00002678 // Set up baseBlock
nethercote71980f02004-01-24 18:18:54 +00002679 // p: {pre,post}_clo_init() [for tool helper registration]
2680 // load_client() [for 'client_eip']
2681 // setup_client_stack() [for 'esp_at_startup']
2682 //--------------------------------------------------------------
2683 init_baseBlock(client_eip, esp_at_startup);
2684
2685 //--------------------------------------------------------------
2686 // Search for file descriptors that are inherited from our parent
2687 // p: process_cmd_line_options [for VG_(clo_track_fds)]
2688 //--------------------------------------------------------------
2689 if (VG_(clo_track_fds))
2690 VG_(init_preopened_fds)();
2691
2692 //--------------------------------------------------------------
2693 // Initialise the scheduler
2694 // p: init_baseBlock() [baseBlock regs copied into VG_(threads)[1]]
2695 // p: setup_file_descriptors() [else VG_(safe_fd)() breaks]
2696 //--------------------------------------------------------------
2697 VG_(scheduler_init)();
2698
2699 //--------------------------------------------------------------
2700 // Set up the ProxyLWP machinery
2701 // p: VG_(scheduler_init)()? [XXX: subtle dependency?]
nethercote71980f02004-01-24 18:18:54 +00002702 //--------------------------------------------------------------
2703 VG_(proxy_init)();
2704
2705 //--------------------------------------------------------------
2706 // Initialise the signal handling subsystem
2707 // p: VG_(atfork)(NULL, NULL, newpid) [else problems with sigmasks]
2708 // p: VG_(proxy_init)() [else breaks...]
2709 //--------------------------------------------------------------
2710 // Nb: temporarily parks the saved blocking-mask in saved_sigmask.
2711 VG_(sigstartup_actions)();
2712
2713 //--------------------------------------------------------------
2714 // Perhaps we're profiling Valgrind?
2715 // p: process_cmd_line_options() [for VG_(clo_profile)]
2716 // p: others?
2717 //
2718 // XXX: this seems to be broken? It always says the tool wasn't built
2719 // for profiling; vg_profile.c's functions don't seem to be overriding
2720 // vg_dummy_profile.c's?
2721 //
2722 // XXX: want this as early as possible. Looking for --profile
2723 // in pre_process_cmd_line_options() could get it earlier.
2724 //--------------------------------------------------------------
2725 if (VG_(clo_profile))
2726 VGP_(init_profiling)();
2727
2728 VGP_PUSHCC(VgpStartup);
2729
2730 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002731 // Read suppression file
2732 // p: process_cmd_line_options() [for VG_(clo_suppressions)]
2733 //--------------------------------------------------------------
2734 if (VG_(needs).core_errors || VG_(needs).skin_errors)
2735 VG_(load_suppressions)();
2736
2737 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002738 // Initialise translation table and translation cache
2739 // p: read_procselfmaps [so the anonymous mmaps for the TT/TC
2740 // aren't identified as part of the client, which would waste
2741 // > 20M of virtual address space.]
2742 //--------------------------------------------------------------
2743 VG_(init_tt_tc)();
2744
2745 //--------------------------------------------------------------
2746 // Read debug info to find glibc entry points to intercept
2747 // p: parse_procselfmaps? [XXX for debug info?]
2748 // p: init_tt_tc? [XXX ???]
2749 //--------------------------------------------------------------
2750 VG_(setup_code_redirect_table)();
2751
2752 //--------------------------------------------------------------
2753 // Verbosity message
2754 // p: end_rdtsc_calibration [so startup message is printed first]
2755 //--------------------------------------------------------------
2756 if (VG_(clo_verbosity) == 1)
2757 VG_(message)(Vg_UserMsg, "For more details, rerun with: -v");
2758 if (VG_(clo_verbosity) > 0)
2759 VG_(message)(Vg_UserMsg, "");
2760
2761 //--------------------------------------------------------------
2762 // Setup pointercheck
2763 // p: process_cmd_line_options() [for VG_(clo_pointercheck)]
2764 //--------------------------------------------------------------
nethercote775508a2004-09-07 22:38:23 +00002765 if (VG_(clo_pointercheck))
2766 VG_(clo_pointercheck) = VGA_(setup_pointercheck)();
nethercote71980f02004-01-24 18:18:54 +00002767
nethercote71980f02004-01-24 18:18:54 +00002768 //--------------------------------------------------------------
2769 // Run!
2770 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002771 VGP_POPCC(VgpStartup);
2772 VGP_PUSHCC(VgpSched);
2773
nethercote238a3c32004-08-09 13:13:31 +00002774 src = VG_(scheduler)( &exitcode, &last_run_tid, &fatal_sigNo );
nethercote71980f02004-01-24 18:18:54 +00002775
nethercote238a3c32004-08-09 13:13:31 +00002776 VGP_POPCC(VgpSched);
nethercote71980f02004-01-24 18:18:54 +00002777
2778
2779 //--------------------------------------------------------------
2780 // Finalisation: cleanup, messages, etc. Order no so important, only
2781 // affects what order the messages come.
2782 //--------------------------------------------------------------
2783 if (VG_(clo_verbosity) > 0)
2784 VG_(message)(Vg_UserMsg, "");
2785
2786 if (src == VgSrc_Deadlock) {
2787 VG_(message)(Vg_UserMsg,
2788 "Warning: pthread scheduler exited due to deadlock");
2789 }
2790
2791 /* Print out file descriptor summary and stats. */
2792 if (VG_(clo_track_fds))
nethercote3a42fb82004-08-03 18:08:50 +00002793 VG_(show_open_fds)();
nethercote71980f02004-01-24 18:18:54 +00002794
2795 if (VG_(needs).core_errors || VG_(needs).skin_errors)
2796 VG_(show_all_errors)();
2797
nethercote47dd12c2004-06-22 14:18:42 +00002798 SK_(fini)( exitcode );
nethercote71980f02004-01-24 18:18:54 +00002799
nethercote885dd912004-08-03 23:14:00 +00002800 VG_(sanity_check_general)( True /*include expensive checks*/ );
nethercote71980f02004-01-24 18:18:54 +00002801
2802 if (VG_(clo_verbosity) > 1)
nethercote3a42fb82004-08-03 18:08:50 +00002803 print_all_stats();
nethercote71980f02004-01-24 18:18:54 +00002804
nethercote71980f02004-01-24 18:18:54 +00002805 if (VG_(clo_profile))
2806 VGP_(done_profiling)();
2807
nethercote71980f02004-01-24 18:18:54 +00002808 /* We're exiting, so nuke all the threads and clean up the proxy LWPs */
2809 vg_assert(src == VgSrc_FatalSig ||
nethercote759dda32004-08-07 18:16:56 +00002810 VG_(threads)[last_run_tid].status == VgTs_Runnable ||
2811 VG_(threads)[last_run_tid].status == VgTs_WaitJoiner);
nethercote71980f02004-01-24 18:18:54 +00002812 VG_(nuke_all_threads_except)(VG_INVALID_THREADID);
2813
2814 //--------------------------------------------------------------
2815 // Exit, according to the scheduler's return code
2816 //--------------------------------------------------------------
2817 switch (src) {
2818 case VgSrc_ExitSyscall: /* the normal way out */
nethercote759dda32004-08-07 18:16:56 +00002819 vg_assert(last_run_tid > 0 && last_run_tid < VG_N_THREADS);
nethercote71980f02004-01-24 18:18:54 +00002820 VG_(proxy_shutdown)();
2821
2822 /* The thread's %EBX at the time it did __NR_exit() will hold
2823 the arg to __NR_exit(), so we just do __NR_exit() with
2824 that arg. */
nethercote47dd12c2004-06-22 14:18:42 +00002825 VG_(exit)( exitcode );
nethercote71980f02004-01-24 18:18:54 +00002826 /* NOT ALIVE HERE! */
2827 VG_(core_panic)("entered the afterlife in main() -- ExitSyscall");
2828 break; /* what the hell :) */
2829
2830 case VgSrc_Deadlock:
2831 /* Just exit now. No point in continuing. */
2832 VG_(proxy_shutdown)();
2833 VG_(exit)(0);
2834 VG_(core_panic)("entered the afterlife in main() -- Deadlock");
2835 break;
2836
nethercote71980f02004-01-24 18:18:54 +00002837 case VgSrc_FatalSig:
2838 /* We were killed by a fatal signal, so replicate the effect */
nethercote238a3c32004-08-09 13:13:31 +00002839 vg_assert(fatal_sigNo != -1);
2840 VG_(kill_self)(fatal_sigNo);
nethercote71980f02004-01-24 18:18:54 +00002841 VG_(core_panic)("main(): signal was supposed to be fatal");
2842 break;
2843
2844 default:
2845 VG_(core_panic)("main(): unexpected scheduler return code");
2846 }
2847
2848 abort();
2849}
2850
2851
sewardjde4a1d02002-03-22 01:27:54 +00002852/*--------------------------------------------------------------------*/
2853/*--- end vg_main.c ---*/
2854/*--------------------------------------------------------------------*/