blob: 8ef52cce478e58417d079936d755d138dffe5c91 [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);
116
nethercote71980f02004-01-24 18:18:54 +0000117/* This is set early to indicate whether this CPU has the
118 SSE/fxsave/fxrestor features. */
119Bool VG_(have_ssestate);
120
fitzhardinge98abfc72003-12-16 02:05:15 +0000121/* stage1 (main) executable */
nethercotef6a1d502004-08-09 12:21:57 +0000122static Int vgexecfd = -1;
fitzhardingea49f9b52003-12-16 22:26:45 +0000123
124/* client executable */
125Int VG_(clexecfd) = -1;
fitzhardinge98abfc72003-12-16 02:05:15 +0000126
127/* Path to library directory */
128const Char *VG_(libdir) = VG_LIBDIR;
129
130/* our argc/argv */
nethercotef6a1d502004-08-09 12:21:57 +0000131static Int vg_argc;
132static Char **vg_argv;
fitzhardinge98abfc72003-12-16 02:05:15 +0000133
jsgf855d93d2003-10-13 22:26:55 +0000134/* PID of the main thread */
135Int VG_(main_pid);
136
137/* PGRP of process */
138Int VG_(main_pgrp);
njn25e49d8e72002-09-23 09:36:25 +0000139
thughesad1c9562004-06-26 11:27:52 +0000140/* Application-visible file descriptor limits */
141Int VG_(fd_soft_limit) = -1;
142Int VG_(fd_hard_limit) = -1;
fitzhardingef0046f22003-12-18 02:39:22 +0000143
nethercote71980f02004-01-24 18:18:54 +0000144/* As deduced from esp_at_startup, the client's argc, argv[] and
145 envp[] as extracted from the client's stack at startup-time. */
146Int VG_(client_argc);
147Char** VG_(client_argv);
148Char** VG_(client_envp);
sewardjde4a1d02002-03-22 01:27:54 +0000149
150/* ---------------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +0000151 Running stuff
sewardjde4a1d02002-03-22 01:27:54 +0000152 ------------------------------------------------------------------ */
sewardjde4a1d02002-03-22 01:27:54 +0000153
nethercote71980f02004-01-24 18:18:54 +0000154/* Counts downwards in VG_(run_innerloop). */
155UInt VG_(dispatch_ctr);
sewardjde4a1d02002-03-22 01:27:54 +0000156
157/* 64-bit counter for the number of basic blocks done. */
158ULong VG_(bbs_done);
sewardjde4a1d02002-03-22 01:27:54 +0000159
nethercote71980f02004-01-24 18:18:54 +0000160/* Tell the logging mechanism whether we are logging to a file
161 descriptor or a socket descriptor. */
162Bool VG_(logging_to_filedes) = True;
163
sewardj73cf3bc2002-11-03 03:20:15 +0000164
nethercote71980f02004-01-24 18:18:54 +0000165/*====================================================================*/
166/*=== Counters, for profiling purposes only ===*/
167/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +0000168
nethercote92e7b7f2004-08-07 17:52:25 +0000169// These ones maintained by vg_dispatch.S
170UInt VG_(bb_enchain_count) = 0; // Number of chain operations done
171UInt VG_(bb_dechain_count) = 0; // Number of unchain operations done
172UInt VG_(unchained_jumps_done) = 0; // Number of unchained jumps done
sewardjde4a1d02002-03-22 01:27:54 +0000173
sewardjde4a1d02002-03-22 01:27:54 +0000174/* Counts pertaining to internal sanity checking. */
nethercote297effd2004-08-02 15:07:57 +0000175static UInt sanity_fast_count = 0;
176static UInt sanity_slow_count = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000177
nethercote3a42fb82004-08-03 18:08:50 +0000178static void print_all_stats ( void )
nethercote71980f02004-01-24 18:18:54 +0000179{
nethercote3a42fb82004-08-03 18:08:50 +0000180 // Translation stats
nethercote92e7b7f2004-08-07 17:52:25 +0000181 VG_(print_tt_tc_stats)();
nethercote71980f02004-01-24 18:18:54 +0000182 VG_(message)(Vg_DebugMsg,
nethercote92e7b7f2004-08-07 17:52:25 +0000183 "chainings: %d chainings, %d unchainings.",
nethercote71980f02004-01-24 18:18:54 +0000184 VG_(bb_enchain_count), VG_(bb_dechain_count) );
185 VG_(message)(Vg_DebugMsg,
nethercote3a42fb82004-08-03 18:08:50 +0000186 " dispatch: %llu jumps (bb entries); of them %u (%lu%%) unchained.",
nethercote71980f02004-01-24 18:18:54 +0000187 VG_(bbs_done),
188 VG_(unchained_jumps_done),
189 ((ULong)(100) * (ULong)(VG_(unchained_jumps_done)))
190 / ( VG_(bbs_done)==0 ? 1 : VG_(bbs_done) )
191 );
192
nethercote3a42fb82004-08-03 18:08:50 +0000193 // Scheduler stats
nethercote844e7122004-08-02 15:27:22 +0000194 VG_(print_scheduler_stats)();
nethercote71980f02004-01-24 18:18:54 +0000195
nethercote3a42fb82004-08-03 18:08:50 +0000196 // Reg-alloc stats
nethercotebee3fd92004-08-02 15:17:43 +0000197 VG_(print_reg_alloc_stats)();
nethercote71980f02004-01-24 18:18:54 +0000198 VG_(message)(Vg_DebugMsg,
199 " sanity: %d cheap, %d expensive checks.",
nethercote297effd2004-08-02 15:07:57 +0000200 sanity_fast_count, sanity_slow_count );
nethercote3a42fb82004-08-03 18:08:50 +0000201
202 // C call stats
nethercote71980f02004-01-24 18:18:54 +0000203 VG_(print_ccall_stats)();
nethercote3a42fb82004-08-03 18:08:50 +0000204
205 // UInstr histogram
206 if (VG_(clo_verbosity) > 3)
207 VG_(print_UInstr_histogram)();
208
209 // Memory stats
nethercote885dd912004-08-03 23:14:00 +0000210 if (VG_(clo_verbosity) > 2) {
nethercote3a42fb82004-08-03 18:08:50 +0000211 VG_(message)(Vg_DebugMsg, "");
212 VG_(message)(Vg_DebugMsg,
213 "------ Valgrind's internal memory use stats follow ------" );
nethercote885dd912004-08-03 23:14:00 +0000214 VG_(sanity_check_malloc_all)();
nethercote3a42fb82004-08-03 18:08:50 +0000215 VG_(print_all_arena_stats)();
nethercote885dd912004-08-03 23:14:00 +0000216 VG_(message)(Vg_DebugMsg, "");
nethercote3a42fb82004-08-03 18:08:50 +0000217 VG_(message)(Vg_DebugMsg,
218 "------ Valgrind's ExeContext management stats follow ------" );
219 VG_(print_ExeContext_stats)();
220 }
nethercote71980f02004-01-24 18:18:54 +0000221}
222
223
224/*====================================================================*/
225/*=== Miscellaneous global functions ===*/
226/*====================================================================*/
227
nethercote04d0fbc2004-01-26 16:48:06 +0000228/* Start debugger and get it to attach to this process. Called if the
229 user requests this service after an error has been shown, so she can
nethercote71980f02004-01-24 18:18:54 +0000230 poke around and look at parameters, memory, etc. You can't
nethercote04d0fbc2004-01-26 16:48:06 +0000231 meaningfully get the debugger to continue the program, though; to
232 continue, quit the debugger. */
233void VG_(start_debugger) ( Int tid )
nethercote71980f02004-01-24 18:18:54 +0000234{
235 Int pid;
236
237 if ((pid = fork()) == 0) {
238 ptrace(PTRACE_TRACEME, 0, NULL, NULL);
239 VG_(kkill)(VG_(getpid)(), VKI_SIGSTOP);
240
241 } else if (pid > 0) {
242 struct user_regs_struct regs;
243 Int status;
244 Int res;
245
nethercote9380b4a2004-09-07 22:22:39 +0000246 if (VG_(is_running_thread)( tid ))
247 VGA_(regs_for_ptrace_from_BB)(&regs);
248 else
249 VGA_(regs_for_ptrace_from_tst)(&VG_(threads)[tid].arch, &regs);
nethercote71980f02004-01-24 18:18:54 +0000250
251 if ((res = VG_(waitpid)(pid, &status, 0)) == pid &&
252 WIFSTOPPED(status) && WSTOPSIG(status) == SIGSTOP &&
253 ptrace(PTRACE_SETREGS, pid, NULL, &regs) == 0 &&
thughes1d160052004-04-21 15:39:57 +0000254 kill(pid, SIGSTOP) == 0 &&
255 ptrace(PTRACE_DETACH, pid, NULL, 0) == 0) {
nethercote04d0fbc2004-01-26 16:48:06 +0000256 Char pidbuf[15];
257 Char file[30];
258 Char buf[100];
259 Char *bufptr;
260 Char *cmdptr;
261
262 VG_(sprintf)(pidbuf, "%d", pid);
263 VG_(sprintf)(file, "/proc/%d/fd/%d", pid, VG_(clexecfd));
264
265 bufptr = buf;
266 cmdptr = VG_(clo_db_command);
267
268 while (*cmdptr) {
269 switch (*cmdptr) {
270 case '%':
271 switch (*++cmdptr) {
272 case 'f':
273 VG_(memcpy)(bufptr, file, VG_(strlen)(file));
274 bufptr += VG_(strlen)(file);
275 cmdptr++;
276 break;
277 case 'p':
278 VG_(memcpy)(bufptr, pidbuf, VG_(strlen)(pidbuf));
279 bufptr += VG_(strlen)(pidbuf);
280 cmdptr++;
281 break;
282 default:
283 *bufptr++ = *cmdptr++;
284 break;
285 }
286 break;
287 default:
288 *bufptr++ = *cmdptr++;
289 break;
290 }
291 }
292
293 *bufptr++ = '\0';
294
295 VG_(message)(Vg_UserMsg, "starting debugger with cmd: %s", buf);
nethercote71980f02004-01-24 18:18:54 +0000296 res = VG_(system)(buf);
297 if (res == 0) {
298 VG_(message)(Vg_UserMsg, "");
299 VG_(message)(Vg_UserMsg,
nethercote04d0fbc2004-01-26 16:48:06 +0000300 "Debugger has detached. Valgrind regains control. We continue.");
nethercote71980f02004-01-24 18:18:54 +0000301 } else {
302 VG_(message)(Vg_UserMsg, "Apparently failed!");
303 VG_(message)(Vg_UserMsg, "");
304 }
305 }
306
307 VG_(kkill)(pid, VKI_SIGKILL);
308 VG_(waitpid)(pid, &status, 0);
309 }
310}
311
312
313/* Print some helpful-ish text about unimplemented things, and give
314 up. */
315void VG_(unimplemented) ( Char* msg )
316{
317 VG_(message)(Vg_UserMsg, "");
318 VG_(message)(Vg_UserMsg,
319 "Valgrind detected that your program requires");
320 VG_(message)(Vg_UserMsg,
321 "the following unimplemented functionality:");
322 VG_(message)(Vg_UserMsg, " %s", msg);
323 VG_(message)(Vg_UserMsg,
324 "This may be because the functionality is hard to implement,");
325 VG_(message)(Vg_UserMsg,
326 "or because no reasonable program would behave this way,");
327 VG_(message)(Vg_UserMsg,
328 "or because nobody has yet needed it. In any case, let us know at");
329 VG_(message)(Vg_UserMsg,
330 "%s and/or try to work around the problem, if you can.", VG_BUGS_TO);
331 VG_(message)(Vg_UserMsg,
332 "");
333 VG_(message)(Vg_UserMsg,
334 "Valgrind has to exit now. Sorry. Bye!");
335 VG_(message)(Vg_UserMsg,
336 "");
337 VG_(pp_sched_status)();
338 VG_(exit)(1);
339}
340
341Addr VG_(get_stack_pointer) ( void )
342{
343 return VG_(baseBlock)[VGOFF_(m_esp)];
344}
345
346/* Debugging thing .. can be called from assembly with OYNK macro. */
347void VG_(oynk) ( Int n )
348{
349 OINK(n);
350}
351
352/* Initialize the PID and PGRP of scheduler LWP; this is also called
353 in any new children after fork. */
354static void newpid(ThreadId unused)
355{
356 /* PID of scheduler LWP */
357 VG_(main_pid) = VG_(getpid)();
358 VG_(main_pgrp) = VG_(getpgrp)();
359}
360
361/*====================================================================*/
362/*=== Check we were launched by stage 1 ===*/
363/*====================================================================*/
364
365/* Look for our AUXV table */
nethercote31779c72004-07-30 21:50:15 +0000366int scan_auxv(void)
nethercote71980f02004-01-24 18:18:54 +0000367{
368 const struct ume_auxv *auxv = find_auxv((int *)ume_exec_esp);
nethercote31779c72004-07-30 21:50:15 +0000369 int padfile = -1, found = 0;
nethercote71980f02004-01-24 18:18:54 +0000370
371 for (; auxv->a_type != AT_NULL; auxv++)
372 switch(auxv->a_type) {
373 case AT_UME_PADFD:
nethercote31779c72004-07-30 21:50:15 +0000374 padfile = auxv->u.a_val;
nethercote71980f02004-01-24 18:18:54 +0000375 found |= 1;
376 break;
377
378 case AT_UME_EXECFD:
nethercotef6a1d502004-08-09 12:21:57 +0000379 vgexecfd = auxv->u.a_val;
nethercote71980f02004-01-24 18:18:54 +0000380 found |= 2;
381 break;
382 }
383
nethercote361a14e2004-07-26 11:11:56 +0000384 if ( found != (1|2) ) {
385 fprintf(stderr, "valgrind: stage2 must be launched by stage1\n");
nethercote71980f02004-01-24 18:18:54 +0000386 exit(127);
387 }
nethercote31779c72004-07-30 21:50:15 +0000388 vg_assert(padfile >= 0);
389 return padfile;
nethercote71980f02004-01-24 18:18:54 +0000390}
391
392
393/*====================================================================*/
394/*=== Address space determination ===*/
395/*====================================================================*/
396
nethercote31779c72004-07-30 21:50:15 +0000397static void layout_remaining_space(Addr argc_addr, float ratio)
nethercote71980f02004-01-24 18:18:54 +0000398{
nethercote31779c72004-07-30 21:50:15 +0000399 Int ires;
400 void* vres;
401 addr_t client_size, shadow_size;
nethercote71980f02004-01-24 18:18:54 +0000402
nethercote31779c72004-07-30 21:50:15 +0000403 VG_(valgrind_base) = (addr_t)&kickstart_base;
nethercote820bd8c2004-09-07 23:04:49 +0000404 VG_(valgrind_last) = ROUNDUP(argc_addr, 0x10000) - 1; // stack
nethercote71980f02004-01-24 18:18:54 +0000405
nethercote31779c72004-07-30 21:50:15 +0000406 // This gives the client the largest possible address space while
407 // taking into account the tool's shadow needs.
408 client_size = ROUNDDN((VG_(valgrind_base)-REDZONE_SIZE) / (1.+ratio),
nethercote71980f02004-01-24 18:18:54 +0000409 CLIENT_SIZE_MULTIPLE);
nethercote31779c72004-07-30 21:50:15 +0000410 VG_(client_base) = CLIENT_BASE;
nethercote71980f02004-01-24 18:18:54 +0000411 VG_(client_end) = VG_(client_base) + client_size;
nethercotee2097312004-06-27 12:29:56 +0000412 /* where !FIXED mmap goes */
nethercotebc7b4f42004-07-26 12:44:35 +0000413 VG_(client_mapbase) = VG_(client_base) +
414 PGROUNDDN((addr_t)(client_size * CLIENT_HEAP_PROPORTION));
nethercote71980f02004-01-24 18:18:54 +0000415
nethercote31779c72004-07-30 21:50:15 +0000416 VG_(shadow_base) = VG_(client_end) + REDZONE_SIZE;
nethercote410bfe62004-09-04 15:53:35 +0000417 VG_(shadow_end) = VG_(valgrind_base);
418 shadow_size = VG_(shadow_end) - VG_(shadow_base);
nethercote71980f02004-01-24 18:18:54 +0000419
nethercotee2097312004-06-27 12:29:56 +0000420#define SEGSIZE(a,b) ((VG_(b) - VG_(a))/(1024*1024))
421
nethercote71980f02004-01-24 18:18:54 +0000422 if (0)
nethercotee2097312004-06-27 12:29:56 +0000423 VG_(printf)(
424 "client_base %8x (%dMB)\n"
425 "client_mapbase %8x (%dMB)\n"
426 "client_end %8x (%dMB)\n"
427 "shadow_base %8x (%dMB)\n"
nethercote410bfe62004-09-04 15:53:35 +0000428 "shadow_end %8x\n"
nethercotee2097312004-06-27 12:29:56 +0000429 "valgrind_base %8x (%dMB)\n"
nethercote820bd8c2004-09-07 23:04:49 +0000430 "valgrind_last %8x\n",
nethercotee2097312004-06-27 12:29:56 +0000431 VG_(client_base), SEGSIZE(client_base, client_mapbase),
432 VG_(client_mapbase), SEGSIZE(client_mapbase, client_end),
433 VG_(client_end), SEGSIZE(client_end, shadow_base),
434 VG_(shadow_base), SEGSIZE(shadow_base, shadow_end),
nethercote410bfe62004-09-04 15:53:35 +0000435 VG_(shadow_end),
nethercote820bd8c2004-09-07 23:04:49 +0000436 VG_(valgrind_base), SEGSIZE(valgrind_base, valgrind_last),
437 VG_(valgrind_last)
nethercotee2097312004-06-27 12:29:56 +0000438 );
439
440#undef SEGSIZE
nethercote71980f02004-01-24 18:18:54 +0000441
442 // Ban redzone
nethercotee567e702004-07-10 17:49:17 +0000443 vres = mmap((void *)VG_(client_end), REDZONE_SIZE, PROT_NONE,
444 MAP_FIXED|MAP_ANON|MAP_PRIVATE, -1, 0);
445 vg_assert((void*)-1 != vres);
nethercote71980f02004-01-24 18:18:54 +0000446
447 // Make client hole
nethercotee567e702004-07-10 17:49:17 +0000448 ires = munmap((void*)VG_(client_base), client_size);
449 vg_assert(0 == ires);
nethercote71980f02004-01-24 18:18:54 +0000450
451 // Map shadow memory.
452 // Initially all inaccessible, incrementally initialized as it is used
nethercotee567e702004-07-10 17:49:17 +0000453 if (shadow_size != 0) {
454 vres = mmap((char *)VG_(shadow_base), shadow_size, PROT_NONE,
455 MAP_PRIVATE|MAP_ANON|MAP_FIXED, -1, 0);
nethercoted4722622004-08-30 19:36:42 +0000456 if ((void*)-1 == vres) {
457 fprintf(stderr,
458 "valgrind: Couldn't allocate address space for shadow memory\n"
459 "valgrind: Are you using a kernel with a small user address space,\n"
460 "valgrind: or do you have your virtual memory size limited?\n");
461 exit(1);
462 }
nethercotee567e702004-07-10 17:49:17 +0000463 }
nethercote71980f02004-01-24 18:18:54 +0000464}
465
466/*====================================================================*/
467/*=== Command line setup ===*/
468/*====================================================================*/
469
470/* Nb: malloc'd memory never freed -- kept throughout like argv, envp */
471static char* get_file_clo(char* dir)
472{
473# define FLEN 512
474 Int fd, n;
475 struct stat s1;
476 char* f_clo = NULL;
477 char filename[FLEN];
478
479 snprintf(filename, FLEN, "%s/.valgrindrc", ( NULL == dir ? "" : dir ) );
480 fd = VG_(open)(filename, 0, VKI_S_IRUSR);
481 if ( fd > 0 ) {
482 if ( 0 == fstat(fd, &s1) ) {
483 f_clo = malloc(s1.st_size+1);
484 vg_assert(f_clo);
485 n = read(fd, f_clo, s1.st_size);
486 if (n == -1) n = 0;
487 f_clo[n] = '\0';
488 }
489 close(fd);
490 }
491 return f_clo;
492# undef FLEN
493}
494
nethercotee2097312004-06-27 12:29:56 +0000495#define ISSPACE(cc) ((cc) == ' ' || (cc) == '\t' || (cc) == '\n')
496
nethercote71980f02004-01-24 18:18:54 +0000497static Int count_args(char* s)
498{
499 Int n = 0;
500 if (s) {
501 char* cp = s;
502 while (True) {
503 // We have alternating sequences: blanks, non-blanks, blanks...
504 // count the non-blanks sequences.
505 while ( ISSPACE(*cp) ) cp++;
506 if ( !*cp ) break;
507 n++;
508 while ( !ISSPACE(*cp) && *cp ) cp++;
509 }
510 }
511 return n;
512}
513
514/* add args out of environment, skipping multiple spaces and -- args */
515static char** copy_args( char* s, char** to )
516{
517 if (s) {
518 char* cp = s;
519 while (True) {
520 // We have alternating sequences: blanks, non-blanks, blanks...
521 // copy the non-blanks sequences, and add terminating '\0'
522 while ( ISSPACE(*cp) ) cp++;
523 if ( !*cp ) break;
524 *to++ = cp;
525 while ( !ISSPACE(*cp) && *cp ) cp++;
526 if ( *cp ) *cp++ = '\0'; // terminate if necessary
527 if (VG_STREQ(to[-1], "--")) to--; // undo any '--' arg
528 }
529 }
530 return to;
531}
532
nethercotee2097312004-06-27 12:29:56 +0000533#undef ISSPACE
534
nethercote71980f02004-01-24 18:18:54 +0000535// Augment command line with arguments from environment and .valgrindrc
536// files.
537static void augment_command_line(Int* vg_argc_inout, char*** vg_argv_inout)
538{
nethercotef6a1d502004-08-09 12:21:57 +0000539 int vg_argc0 = *vg_argc_inout;
540 char** vg_argv0 = *vg_argv_inout;
nethercote71980f02004-01-24 18:18:54 +0000541
542 char* env_clo = getenv(VALGRINDOPTS);
543 char* f1_clo = get_file_clo( getenv("HOME") );
544 char* f2_clo = get_file_clo(".");
545
546 /* copy any extra args from file or environment, if present */
547 if ( (env_clo && *env_clo) || (f1_clo && *f1_clo) || (f2_clo && *f2_clo) ) {
548 /* ' ' separated extra options */
549 char **from;
550 char **to;
551 int env_arg_count, f1_arg_count, f2_arg_count;
552
553 env_arg_count = count_args(env_clo);
554 f1_arg_count = count_args(f1_clo);
555 f2_arg_count = count_args(f2_clo);
556
557 if (0)
558 printf("extra-argc=%d %d %d\n",
559 env_arg_count, f1_arg_count, f2_arg_count);
560
561 /* +2: +1 for null-termination, +1 for added '--' */
nethercotef6a1d502004-08-09 12:21:57 +0000562 from = vg_argv0;
563 vg_argv0 = malloc( (vg_argc0 + env_arg_count + f1_arg_count
nethercote71980f02004-01-24 18:18:54 +0000564 + f2_arg_count + 2) * sizeof(char **));
nethercotef6a1d502004-08-09 12:21:57 +0000565 vg_assert(vg_argv0);
566 to = vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000567
568 /* copy argv[0] */
569 *to++ = *from++;
570
571 /* Copy extra args from env var and file, in the order: ~/.valgrindrc,
572 * $VALGRIND_OPTS, ./.valgrindrc -- more local options are put later
573 * to override less local ones. */
574 to = copy_args(f1_clo, to);
575 to = copy_args(env_clo, to);
576 to = copy_args(f2_clo, to);
577
578 /* copy original arguments, stopping at command or -- */
579 while (*from) {
580 if (**from != '-')
581 break;
582 if (VG_STREQ(*from, "--")) {
583 from++; /* skip -- */
584 break;
585 }
586 *to++ = *from++;
587 }
588
589 /* add -- */
590 *to++ = "--";
591
nethercotef6a1d502004-08-09 12:21:57 +0000592 vg_argc0 = to - vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000593
594 /* copy rest of original command line, then NULL */
595 while (*from) *to++ = *from++;
596 *to = NULL;
597 }
598
nethercotef6a1d502004-08-09 12:21:57 +0000599 *vg_argc_inout = vg_argc0;
600 *vg_argv_inout = vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000601}
602
nethercotef6a1d502004-08-09 12:21:57 +0000603#define VG_CLO_SEP '\01'
604
nethercote71980f02004-01-24 18:18:54 +0000605static void get_command_line( int argc, char** argv,
606 Int* vg_argc_out, Char*** vg_argv_out,
607 char*** cl_argv_out )
608{
nethercotef6a1d502004-08-09 12:21:57 +0000609 int vg_argc0;
610 char** vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000611 char** cl_argv;
612 char* env_clo = getenv(VALGRINDCLO);
613
614 if (env_clo != NULL && *env_clo != '\0') {
615 char *cp;
616 char **cpp;
617
nethercotef6a1d502004-08-09 12:21:57 +0000618 /* OK, VALGRINDCLO is set, which means we must be a child of another
619 Valgrind process using --trace-children, so we're getting all our
620 arguments from VALGRINDCLO, and the entire command line belongs to
621 the client (including argv[0]) */
622 vg_argc0 = 1; /* argv[0] */
nethercote71980f02004-01-24 18:18:54 +0000623 for (cp = env_clo; *cp; cp++)
nethercotef6a1d502004-08-09 12:21:57 +0000624 if (*cp == VG_CLO_SEP)
625 vg_argc0++;
nethercote71980f02004-01-24 18:18:54 +0000626
nethercotef6a1d502004-08-09 12:21:57 +0000627 vg_argv0 = malloc(sizeof(char **) * (vg_argc0 + 1));
628 vg_assert(vg_argv0);
nethercote71980f02004-01-24 18:18:54 +0000629
nethercotef6a1d502004-08-09 12:21:57 +0000630 cpp = vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000631
632 *cpp++ = "valgrind"; /* nominal argv[0] */
633 *cpp++ = env_clo;
634
nethercotef6a1d502004-08-09 12:21:57 +0000635 // Replace the VG_CLO_SEP args separator with '\0'
nethercote71980f02004-01-24 18:18:54 +0000636 for (cp = env_clo; *cp; cp++) {
nethercotef6a1d502004-08-09 12:21:57 +0000637 if (*cp == VG_CLO_SEP) {
nethercote71980f02004-01-24 18:18:54 +0000638 *cp++ = '\0'; /* chop it up in place */
639 *cpp++ = cp;
640 }
641 }
642 *cpp = NULL;
643 cl_argv = argv;
644
645 } else {
646 /* Count the arguments on the command line. */
nethercotef6a1d502004-08-09 12:21:57 +0000647 vg_argv0 = argv;
nethercote71980f02004-01-24 18:18:54 +0000648
nethercotef6a1d502004-08-09 12:21:57 +0000649 for (vg_argc0 = 1; vg_argc0 < argc; vg_argc0++) {
650 if (argv[vg_argc0][0] != '-') /* exe name */
nethercote71980f02004-01-24 18:18:54 +0000651 break;
nethercotef6a1d502004-08-09 12:21:57 +0000652 if (VG_STREQ(argv[vg_argc0], "--")) { /* dummy arg */
653 vg_argc0++;
nethercote71980f02004-01-24 18:18:54 +0000654 break;
655 }
656 }
nethercotef6a1d502004-08-09 12:21:57 +0000657 cl_argv = &argv[vg_argc0];
nethercote71980f02004-01-24 18:18:54 +0000658
659 /* Get extra args from VALGRIND_OPTS and .valgrindrc files.
nethercotef6a1d502004-08-09 12:21:57 +0000660 Note we don't do this if getting args from VALGRINDCLO, as
661 those extra args will already be present in VALGRINDCLO. */
662 augment_command_line(&vg_argc0, &vg_argv0);
nethercote71980f02004-01-24 18:18:54 +0000663 }
664
665 if (0) {
666 Int i;
nethercotef6a1d502004-08-09 12:21:57 +0000667 for (i = 0; i < vg_argc0; i++)
668 printf("vg_argv0[%d]=\"%s\"\n", i, vg_argv0[i]);
nethercote71980f02004-01-24 18:18:54 +0000669 }
670
nethercotef6a1d502004-08-09 12:21:57 +0000671 *vg_argc_out = vg_argc0;
672 *vg_argv_out = (Char**)vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000673 *cl_argv_out = cl_argv;
674}
675
676
677/*====================================================================*/
678/*=== Environment and stack setup ===*/
679/*====================================================================*/
680
681/* Scan a colon-separated list, and call a function on each element.
682 The string must be mutable, because we insert a temporary '\0', but
thughes4ad52d02004-06-27 17:37:21 +0000683 the string will end up unmodified. (*func) should return True if it
nethercote71980f02004-01-24 18:18:54 +0000684 doesn't need to see any more.
thughes4ad52d02004-06-27 17:37:21 +0000685
686 This routine will return True if (*func) returns True and False if
687 it reaches the end of the list without that happening.
nethercote71980f02004-01-24 18:18:54 +0000688*/
thughes4ad52d02004-06-27 17:37:21 +0000689static Bool scan_colsep(char *colsep, Bool (*func)(const char *))
nethercote71980f02004-01-24 18:18:54 +0000690{
691 char *cp, *entry;
692 int end;
693
694 if (colsep == NULL ||
695 *colsep == '\0')
thughes4ad52d02004-06-27 17:37:21 +0000696 return False;
nethercote71980f02004-01-24 18:18:54 +0000697
698 entry = cp = colsep;
699
700 do {
701 end = (*cp == '\0');
702
703 if (*cp == ':' || *cp == '\0') {
704 char save = *cp;
705
706 *cp = '\0';
thughes21942d92004-07-12 09:35:37 +0000707 if ((*func)(entry)) {
708 *cp = save;
thughes4ad52d02004-06-27 17:37:21 +0000709 return True;
thughes21942d92004-07-12 09:35:37 +0000710 }
nethercote71980f02004-01-24 18:18:54 +0000711 *cp = save;
712 entry = cp+1;
713 }
714 cp++;
715 } while(!end);
thughes4ad52d02004-06-27 17:37:21 +0000716
717 return False;
718}
719
720static Bool contains(const char *p) {
721 if (VG_STREQ(p, VG_(libdir))) {
722 return True;
723 }
724 return False;
nethercote71980f02004-01-24 18:18:54 +0000725}
726
727/* Prepare the client's environment. This is basically a copy of our
728 environment, except:
729 1. LD_LIBRARY_PATH=$VALGRINDLIB:$LD_LIBRARY_PATH
730 2. LD_PRELOAD=$VALGRINDLIB/vg_inject.so:($VALGRINDLIB/vgpreload_TOOL.so:)?$LD_PRELOAD
731
732 If any of these is missing, then it is added.
733
734 Yummy. String hacking in C.
735
736 If this needs to handle any more variables it should be hacked
737 into something table driven.
738 */
739static char **fix_environment(char **origenv, const char *preload)
740{
741 static const char inject_so[] = "vg_inject.so";
742 static const char ld_library_path[] = "LD_LIBRARY_PATH=";
743 static const char ld_preload[] = "LD_PRELOAD=";
744 static const char valgrind_clo[] = VALGRINDCLO "=";
745 static const int ld_library_path_len = sizeof(ld_library_path)-1;
746 static const int ld_preload_len = sizeof(ld_preload)-1;
747 static const int valgrind_clo_len = sizeof(valgrind_clo)-1;
748 int ld_preload_done = 0;
749 int ld_library_path_done = 0;
750 char *inject_path;
751 int inject_path_len;
752 int vgliblen = strlen(VG_(libdir));
753 char **cpp;
754 char **ret;
755 int envc;
756 const int preloadlen = (preload == NULL) ? 0 : strlen(preload);
757
758 /* Find the vg_inject.so; also make room for the tool preload
759 library */
760 inject_path_len = sizeof(inject_so) + vgliblen + preloadlen + 16;
761 inject_path = malloc(inject_path_len);
nethercote7c018f42004-07-17 16:40:50 +0000762 vg_assert(inject_path);
nethercote71980f02004-01-24 18:18:54 +0000763
764 if (preload)
765 snprintf(inject_path, inject_path_len, "%s/%s:%s",
766 VG_(libdir), inject_so, preload);
767 else
768 snprintf(inject_path, inject_path_len, "%s/%s",
769 VG_(libdir), inject_so);
770
771 /* Count the original size of the env */
772 envc = 0; /* trailing NULL */
773 for (cpp = origenv; cpp && *cpp; cpp++)
774 envc++;
775
776 /* Allocate a new space */
777 ret = malloc(sizeof(char *) * (envc+3+1)); /* 3 new entries + NULL */
nethercote7c018f42004-07-17 16:40:50 +0000778 vg_assert(ret);
nethercote71980f02004-01-24 18:18:54 +0000779
780 /* copy it over */
781 for (cpp = ret; *origenv; )
782 *cpp++ = *origenv++;
783 *cpp = NULL;
784
785 vg_assert(envc == (cpp - ret));
786
787 /* Walk over the new environment, mashing as we go */
788 for (cpp = ret; cpp && *cpp; cpp++) {
789 if (memcmp(*cpp, ld_library_path, ld_library_path_len) == 0) {
nethercote71980f02004-01-24 18:18:54 +0000790 /* If the LD_LIBRARY_PATH already contains libdir, then don't
791 bother adding it again, even if it isn't the first (it
792 seems that the Java runtime will keep reexecing itself
793 unless its paths are at the front of LD_LIBRARY_PATH) */
thughes4ad52d02004-06-27 17:37:21 +0000794 if (!scan_colsep(*cpp + ld_library_path_len, contains)) {
nethercote71980f02004-01-24 18:18:54 +0000795 int len = strlen(*cpp) + vgliblen*2 + 16;
796 char *cp = malloc(len);
nethercote7c018f42004-07-17 16:40:50 +0000797 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000798
799 snprintf(cp, len, "%s%s:%s",
800 ld_library_path, VG_(libdir),
801 (*cpp)+ld_library_path_len);
802
803 *cpp = cp;
804 }
805
806 ld_library_path_done = 1;
807 } else if (memcmp(*cpp, ld_preload, ld_preload_len) == 0) {
808 int len = strlen(*cpp) + inject_path_len;
809 char *cp = malloc(len);
nethercote7c018f42004-07-17 16:40:50 +0000810 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000811
812 snprintf(cp, len, "%s%s:%s",
813 ld_preload, inject_path, (*cpp)+ld_preload_len);
814
815 *cpp = cp;
816
817 ld_preload_done = 1;
818 } else if (memcmp(*cpp, valgrind_clo, valgrind_clo_len) == 0) {
819 *cpp = "";
820 }
821 }
822
823 /* Add the missing bits */
824
825 if (!ld_library_path_done) {
826 int len = ld_library_path_len + vgliblen*2 + 16;
827 char *cp = malloc(len);
nethercote7c018f42004-07-17 16:40:50 +0000828 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000829
830 snprintf(cp, len, "%s%s", ld_library_path, VG_(libdir));
831
832 ret[envc++] = cp;
833 }
834
835 if (!ld_preload_done) {
836 int len = ld_preload_len + inject_path_len;
837 char *cp = malloc(len);
nethercote7c018f42004-07-17 16:40:50 +0000838 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000839
840 snprintf(cp, len, "%s%s",
841 ld_preload, inject_path);
842
843 ret[envc++] = cp;
844 }
845
846 ret[envc] = NULL;
847
848 return ret;
849}
850
851extern char **environ; /* our environment */
852//#include <error.h>
853
854/* Add a string onto the string table, and return its address */
855static char *copy_str(char **tab, const char *str)
856{
857 char *cp = *tab;
858 char *orig = cp;
859
860 while(*str)
861 *cp++ = *str++;
862 *cp++ = '\0';
863
864 if (0)
nethercotef84f6952004-07-15 14:58:33 +0000865 printf("copied %p \"%s\" len %d\n", orig, orig, cp-orig);
nethercote71980f02004-01-24 18:18:54 +0000866
867 *tab = cp;
868
869 return orig;
870}
871
872/*
873 This sets up the client's initial stack, containing the args,
874 environment and aux vector.
875
876 The format of the stack is:
877
878 higher address +-----------------+
879 | Trampoline code |
880 +-----------------+
881 | |
882 : string table :
883 | |
884 +-----------------+
885 | AT_NULL |
886 - -
887 | auxv |
888 +-----------------+
889 | NULL |
890 - -
891 | envp |
892 +-----------------+
893 | NULL |
894 - -
895 | argv |
896 +-----------------+
897 | argc |
898 lower address +-----------------+ <- esp
899 | undefined |
900 : :
901 */
902static Addr setup_client_stack(char **orig_argv, char **orig_envp,
903 const struct exeinfo *info,
904 UInt** client_auxv)
905{
nethercotee567e702004-07-10 17:49:17 +0000906 void* res;
nethercote71980f02004-01-24 18:18:54 +0000907 char **cpp;
908 char *strtab; /* string table */
909 char *stringbase;
910 addr_t *ptr;
911 struct ume_auxv *auxv;
912 const struct ume_auxv *orig_auxv;
913 const struct ume_auxv *cauxv;
914 unsigned stringsize; /* total size of strings in bytes */
915 unsigned auxsize; /* total size of auxv in bytes */
916 int argc; /* total argc */
917 int envc; /* total number of env vars */
918 unsigned stacksize; /* total client stack size */
919 addr_t cl_esp; /* client stack base (initial esp) */
920
921 /* use our own auxv as a prototype */
922 orig_auxv = find_auxv(ume_exec_esp);
923
924 /* ==================== compute sizes ==================== */
925
926 /* first of all, work out how big the client stack will be */
927 stringsize = 0;
928
929 /* paste on the extra args if the loader needs them (ie, the #!
930 interpreter and its argument) */
931 argc = 0;
nethercoted6a56872004-07-26 15:32:47 +0000932 if (info->interp_name != NULL) {
nethercote71980f02004-01-24 18:18:54 +0000933 argc++;
nethercoted6a56872004-07-26 15:32:47 +0000934 stringsize += strlen(info->interp_name) + 1;
nethercote71980f02004-01-24 18:18:54 +0000935 }
nethercoted6a56872004-07-26 15:32:47 +0000936 if (info->interp_args != NULL) {
nethercote71980f02004-01-24 18:18:54 +0000937 argc++;
nethercoted6a56872004-07-26 15:32:47 +0000938 stringsize += strlen(info->interp_args) + 1;
nethercote71980f02004-01-24 18:18:54 +0000939 }
940
941 /* now scan the args we're given... */
942 for (cpp = orig_argv; *cpp; cpp++) {
943 argc++;
944 stringsize += strlen(*cpp) + 1;
945 }
946
947 /* ...and the environment */
948 envc = 0;
949 for (cpp = orig_envp; cpp && *cpp; cpp++) {
950 envc++;
951 stringsize += strlen(*cpp) + 1;
952 }
953
954 /* now, how big is the auxv? */
955 auxsize = sizeof(*auxv); /* there's always at least one entry: AT_NULL */
956 for (cauxv = orig_auxv; cauxv->a_type != AT_NULL; cauxv++) {
957 if (cauxv->a_type == AT_PLATFORM)
958 stringsize += strlen(cauxv->u.a_ptr) + 1;
959 auxsize += sizeof(*cauxv);
960 }
961
962 /* OK, now we know how big the client stack is */
963 stacksize =
964 sizeof(int) + /* argc */
965 sizeof(char **)*argc + /* argv */
966 sizeof(char **) + /* terminal NULL */
967 sizeof(char **)*envc + /* envp */
968 sizeof(char **) + /* terminal NULL */
969 auxsize + /* auxv */
970 ROUNDUP(stringsize, sizeof(int)) +/* strings (aligned) */
971 VKI_BYTES_PER_PAGE; /* page for trampoline code */
972
nethercotef84f6952004-07-15 14:58:33 +0000973 // decide where stack goes!
974 VG_(clstk_end) = VG_(client_end);
975
976 VG_(client_trampoline_code) = VG_(clstk_end) - VKI_BYTES_PER_PAGE;
977
nethercote71980f02004-01-24 18:18:54 +0000978 /* cl_esp is the client's stack pointer */
nethercotef84f6952004-07-15 14:58:33 +0000979 cl_esp = VG_(clstk_end) - stacksize;
nethercote71980f02004-01-24 18:18:54 +0000980 cl_esp = ROUNDDN(cl_esp, 16); /* make stack 16 byte aligned */
981
nethercote71980f02004-01-24 18:18:54 +0000982 /* base of the string table (aligned) */
983 stringbase = strtab = (char *)(VG_(client_trampoline_code) - ROUNDUP(stringsize, sizeof(int)));
984
985 VG_(clstk_base) = PGROUNDDN(cl_esp);
nethercote71980f02004-01-24 18:18:54 +0000986
nethercote5ee67ca2004-06-22 14:00:09 +0000987 if (0)
988 printf("stringsize=%d auxsize=%d stacksize=%d\n"
nethercote6a27d832004-09-07 10:17:02 +0000989 "clstk_base %p\n"
990 "clstk_end %p\n",
991 stringsize, auxsize, stacksize,
992 (void*)VG_(clstk_base), (void*)VG_(clstk_end));
nethercote5ee67ca2004-06-22 14:00:09 +0000993
994
nethercote71980f02004-01-24 18:18:54 +0000995 /* ==================== allocate space ==================== */
996
997 /* allocate a stack - mmap enough space for the stack */
nethercotef84f6952004-07-15 14:58:33 +0000998 res = mmap((void *)PGROUNDDN(cl_esp), VG_(clstk_end) - PGROUNDDN(cl_esp),
nethercotee567e702004-07-10 17:49:17 +0000999 PROT_READ | PROT_WRITE | PROT_EXEC,
1000 MAP_PRIVATE | MAP_ANON | MAP_FIXED, -1, 0);
1001 vg_assert((void*)-1 != res);
nethercote71980f02004-01-24 18:18:54 +00001002
1003 /* ==================== copy client stack ==================== */
1004
1005 ptr = (addr_t *)cl_esp;
1006
1007 /* --- argc --- */
1008 *ptr++ = argc; /* client argc */
1009
1010 /* --- argv --- */
nethercoted6a56872004-07-26 15:32:47 +00001011 if (info->interp_name) {
1012 *ptr++ = (addr_t)copy_str(&strtab, info->interp_name);
1013 free(info->interp_name);
nethercote71980f02004-01-24 18:18:54 +00001014 }
nethercoted6a56872004-07-26 15:32:47 +00001015 if (info->interp_args) {
1016 *ptr++ = (addr_t)copy_str(&strtab, info->interp_args);
1017 free(info->interp_args);
nethercote71980f02004-01-24 18:18:54 +00001018 }
1019 for (cpp = orig_argv; *cpp; ptr++, cpp++) {
1020 *ptr = (addr_t)copy_str(&strtab, *cpp);
1021 }
1022 *ptr++ = 0;
1023
1024 /* --- envp --- */
1025 VG_(client_envp) = (Char **)ptr;
1026 for (cpp = orig_envp; cpp && *cpp; ptr++, cpp++)
1027 *ptr = (addr_t)copy_str(&strtab, *cpp);
1028 *ptr++ = 0;
1029
1030 /* --- auxv --- */
1031 auxv = (struct ume_auxv *)ptr;
1032 *client_auxv = (UInt *)auxv;
1033
1034 for (; orig_auxv->a_type != AT_NULL; auxv++, orig_auxv++) {
1035 /* copy the entry... */
1036 *auxv = *orig_auxv;
1037
1038 /* ...and fix up the copy */
1039 switch(auxv->a_type) {
1040 case AT_PHDR:
1041 if (info->phdr == 0)
1042 auxv->a_type = AT_IGNORE;
1043 else
1044 auxv->u.a_val = info->phdr;
1045 break;
1046
1047 case AT_PHNUM:
1048 if (info->phdr == 0)
1049 auxv->a_type = AT_IGNORE;
1050 else
1051 auxv->u.a_val = info->phnum;
1052 break;
1053
1054 case AT_BASE:
1055 if (info->interp_base == 0)
1056 auxv->a_type = AT_IGNORE;
1057 else
1058 auxv->u.a_val = info->interp_base;
1059 break;
1060
1061 case AT_PLATFORM: /* points to a platform description string */
1062 auxv->u.a_ptr = copy_str(&strtab, orig_auxv->u.a_ptr);
1063 break;
1064
1065 case AT_ENTRY:
1066 auxv->u.a_val = info->entry;
1067 break;
1068
1069 case AT_IGNORE:
1070 case AT_EXECFD:
1071 case AT_PHENT:
1072 case AT_PAGESZ:
1073 case AT_FLAGS:
1074 case AT_NOTELF:
1075 case AT_UID:
1076 case AT_EUID:
1077 case AT_GID:
1078 case AT_EGID:
1079 case AT_CLKTCK:
1080 case AT_HWCAP:
1081 case AT_FPUCW:
1082 case AT_DCACHEBSIZE:
1083 case AT_ICACHEBSIZE:
1084 case AT_UCACHEBSIZE:
1085 /* All these are pointerless, so we don't need to do anything
1086 about them. */
1087 break;
1088
1089 case AT_SECURE:
1090 /* If this is 1, then it means that this program is running
1091 suid, and therefore the dynamic linker should be careful
1092 about LD_PRELOAD, etc. However, since stage1 (the thing
1093 the kernel actually execve's) should never be SUID, and we
1094 need LD_PRELOAD/LD_LIBRARY_PATH to work for the client, we
1095 set AT_SECURE to 0. */
1096 auxv->u.a_val = 0;
1097 break;
1098
1099 case AT_SYSINFO:
1100 /* Leave this unmolested for now, but we'll update it later
1101 when we set up the client trampoline code page */
1102 break;
1103
1104 case AT_SYSINFO_EHDR:
1105 /* Trash this, because we don't reproduce it */
1106 auxv->a_type = AT_IGNORE;
1107 break;
1108
1109 default:
1110 /* stomp out anything we don't know about */
1111 if (0)
1112 printf("stomping auxv entry %d\n", auxv->a_type);
1113 auxv->a_type = AT_IGNORE;
1114 break;
1115
1116 }
1117 }
1118 *auxv = *orig_auxv;
1119 vg_assert(auxv->a_type == AT_NULL);
1120
nethercotef84f6952004-07-15 14:58:33 +00001121 /* --- trampoline page --- */
1122 VG_(memcpy)( (void *)VG_(client_trampoline_code),
1123 &VG_(trampoline_code_start), VG_(trampoline_code_length) );
1124
nethercote71980f02004-01-24 18:18:54 +00001125 vg_assert((strtab-stringbase) == stringsize);
1126
nethercote5ee67ca2004-06-22 14:00:09 +00001127 /* We know the initial ESP is pointing at argc/argv */
1128 VG_(client_argc) = *(Int*)cl_esp;
1129 VG_(client_argv) = (Char**)(cl_esp + sizeof(Int));
1130
nethercote71980f02004-01-24 18:18:54 +00001131 return cl_esp;
1132}
1133
1134/*====================================================================*/
1135/*=== Find executable ===*/
1136/*====================================================================*/
1137
thughes4ad52d02004-06-27 17:37:21 +00001138static const char* executable_name;
1139
1140static Bool match_executable(const char *entry) {
1141 char buf[strlen(entry) + strlen(executable_name) + 2];
1142
1143 /* empty PATH element means . */
1144 if (*entry == '\0')
1145 entry = ".";
1146
1147 snprintf(buf, sizeof(buf), "%s/%s", entry, executable_name);
1148
1149 if (access(buf, R_OK|X_OK) == 0) {
1150 executable_name = strdup(buf);
1151 vg_assert(NULL != executable_name);
1152 return True;
1153 }
1154 return False;
1155}
1156
nethercote71980f02004-01-24 18:18:54 +00001157static const char* find_executable(const char* exec)
1158{
1159 vg_assert(NULL != exec);
thughes4ad52d02004-06-27 17:37:21 +00001160 executable_name = exec;
1161 if (strchr(executable_name, '/') == NULL) {
nethercote71980f02004-01-24 18:18:54 +00001162 /* no '/' - we need to search the path */
1163 char *path = getenv("PATH");
thughes4ad52d02004-06-27 17:37:21 +00001164 scan_colsep(path, match_executable);
nethercote71980f02004-01-24 18:18:54 +00001165 }
thughes4ad52d02004-06-27 17:37:21 +00001166 return executable_name;
nethercote71980f02004-01-24 18:18:54 +00001167}
1168
1169
1170/*====================================================================*/
1171/*=== Loading tools ===*/
1172/*====================================================================*/
1173
1174static void list_tools(void)
1175{
1176 DIR *dir = opendir(VG_(libdir));
1177 struct dirent *de;
1178 int first = 1;
1179
1180 if (dir == NULL) {
1181 fprintf(stderr, "Can't open %s: %s (installation problem?)\n",
nethercotef4928da2004-06-15 10:54:40 +00001182 VG_(libdir), strerror(errno));
nethercote71980f02004-01-24 18:18:54 +00001183 return;
1184 }
1185
nethercotef4928da2004-06-15 10:54:40 +00001186 while ((de = readdir(dir)) != NULL) {
nethercote71980f02004-01-24 18:18:54 +00001187 int len = strlen(de->d_name);
1188
1189 /* look for vgskin_TOOL.so names */
1190 if (len > (7+1+3) && /* "vgskin_" + at least 1-char toolname + ".so" */
nethercotef4928da2004-06-15 10:54:40 +00001191 strncmp(de->d_name, "vgskin_", 7) == 0 &&
1192 VG_STREQ(de->d_name + len - 3, ".so")) {
1193 if (first) {
1194 fprintf(stderr, "Available tools:\n");
1195 first = 0;
1196 }
1197 de->d_name[len-3] = '\0';
1198 fprintf(stderr, "\t%s\n", de->d_name+7);
nethercote71980f02004-01-24 18:18:54 +00001199 }
1200 }
1201
1202 closedir(dir);
1203
1204 if (first)
nethercotef4928da2004-06-15 10:54:40 +00001205 fprintf(stderr, "No tools available in \"%s\" (installation problem?)\n",
1206 VG_(libdir));
nethercote71980f02004-01-24 18:18:54 +00001207}
1208
1209
1210/* Find and load a tool, and check it looks ok. Also looks to see if there's
1211 * a matching vgpreload_*.so file, and returns its name in *preloadpath. */
1212static void load_tool( const char *toolname, void** handle_out,
1213 ToolInfo** toolinfo_out, char **preloadpath_out )
1214{
1215 Bool ok;
1216 int len = strlen(VG_(libdir)) + strlen(toolname)*2 + 16;
1217 char buf[len];
1218 void* handle;
1219 ToolInfo* toolinfo;
1220 char* preloadpath = NULL;
1221 Int* vg_malloc_redzonep;
1222
1223 // XXX: allowing full paths for --tool option -- does it make sense?
1224 // Doesn't allow for vgpreload_<tool>.so.
1225
1226 if (strchr(toolname, '/') != 0) {
1227 /* toolname contains '/', and so must be a pathname */
1228 handle = dlopen(toolname, RTLD_NOW);
1229 } else {
1230 /* just try in the libdir */
1231 snprintf(buf, len, "%s/vgskin_%s.so", VG_(libdir), toolname);
1232 handle = dlopen(buf, RTLD_NOW);
1233
1234 if (handle != NULL) {
1235 snprintf(buf, len, "%s/vgpreload_%s.so", VG_(libdir), toolname);
1236 if (access(buf, R_OK) == 0) {
1237 preloadpath = strdup(buf);
1238 vg_assert(NULL != preloadpath);
1239 }
1240 }
1241 }
1242
1243 ok = (NULL != handle);
1244 if (!ok) {
1245 fprintf(stderr, "Can't open tool \"%s\": %s\n", toolname, dlerror());
1246 goto bad_load;
1247 }
1248
1249 toolinfo = dlsym(handle, "vgSkin_tool_info");
1250 ok = (NULL != toolinfo);
1251 if (!ok) {
1252 fprintf(stderr, "Tool \"%s\" doesn't define SK_(tool_info) - "
1253 "add VG_DETERMINE_INTERFACE_VERSION?\n", toolname);
1254 goto bad_load;
1255 }
1256
1257 ok = (toolinfo->sizeof_ToolInfo == sizeof(*toolinfo) &&
1258 toolinfo->interface_major_version == VG_CORE_INTERFACE_MAJOR_VERSION &&
1259 toolinfo->sk_pre_clo_init != NULL);
1260 if (!ok) {
1261 fprintf(stderr, "Error:\n"
1262 " Tool and core interface versions do not match.\n"
1263 " Interface version used by core is: %d.%d (size %d)\n"
1264 " Interface version used by tool is: %d.%d (size %d)\n"
1265 " The major version numbers must match.\n",
1266 VG_CORE_INTERFACE_MAJOR_VERSION,
1267 VG_CORE_INTERFACE_MINOR_VERSION,
1268 sizeof(*toolinfo),
1269 toolinfo->interface_major_version,
1270 toolinfo->interface_minor_version,
1271 toolinfo->sizeof_ToolInfo);
1272 fprintf(stderr, " You need to at least recompile, and possibly update,\n");
1273 if (VG_CORE_INTERFACE_MAJOR_VERSION > toolinfo->interface_major_version)
nethercote996901a2004-08-03 13:29:09 +00001274 fprintf(stderr, " your tool to work with this version of Valgrind.\n");
nethercote71980f02004-01-24 18:18:54 +00001275 else
nethercote996901a2004-08-03 13:29:09 +00001276 fprintf(stderr, " your version of Valgrind to work with this tool.\n");
nethercote71980f02004-01-24 18:18:54 +00001277 goto bad_load;
1278 }
1279
1280 // Set redzone size for V's allocator
1281 vg_malloc_redzonep = dlsym(handle, STR(VG_(vg_malloc_redzone_szB)));
1282 if ( NULL != vg_malloc_redzonep ) {
1283 VG_(vg_malloc_redzone_szB) = *vg_malloc_redzonep;
1284 }
1285
1286 vg_assert(NULL != handle && NULL != toolinfo);
1287 *handle_out = handle;
1288 *toolinfo_out = toolinfo;
1289 *preloadpath_out = preloadpath;
1290 return;
1291
1292
1293 bad_load:
1294 if (handle != NULL)
1295 dlclose(handle);
1296
nethercotef4928da2004-06-15 10:54:40 +00001297 fprintf(stderr, "valgrind: couldn't load tool\n");
nethercote71980f02004-01-24 18:18:54 +00001298 list_tools();
1299 exit(127);
1300}
1301
nethercotef4928da2004-06-15 10:54:40 +00001302
1303/*====================================================================*/
1304/*=== Command line errors ===*/
1305/*====================================================================*/
1306
1307static void abort_msg ( void )
1308{
nethercotef8548672004-06-21 12:42:35 +00001309 VG_(clo_log_to) = VgLogTo_Fd;
1310 VG_(clo_log_fd) = 2; /* stderr */
nethercotef4928da2004-06-15 10:54:40 +00001311}
1312
1313void VG_(bad_option) ( Char* opt )
1314{
1315 abort_msg();
1316 VG_(printf)("valgrind: Bad option `%s'; aborting.\n", opt);
1317 VG_(printf)("valgrind: Use --help for more information.\n");
1318 VG_(exit)(1);
1319}
1320
1321static void missing_tool_option ( void )
1322{
1323 abort_msg();
1324 VG_(printf)("valgrind: Missing --tool option\n");
1325 list_tools();
1326 VG_(printf)("valgrind: Use --help for more information.\n");
1327 VG_(exit)(1);
1328}
1329
1330static void missing_prog ( void )
1331{
1332 abort_msg();
1333 VG_(printf)("valgrind: no program specified\n");
1334 VG_(printf)("valgrind: Use --help for more information.\n");
1335 VG_(exit)(1);
1336}
1337
1338static void config_error ( Char* msg )
1339{
1340 abort_msg();
1341 VG_(printf)("valgrind: Startup or configuration error:\n %s\n", msg);
1342 VG_(printf)("valgrind: Unable to start up properly. Giving up.\n");
1343 VG_(exit)(1);
1344}
1345
1346
nethercote71980f02004-01-24 18:18:54 +00001347/*====================================================================*/
1348/*=== Loading the client ===*/
1349/*====================================================================*/
1350
nethercotef4928da2004-06-15 10:54:40 +00001351static void load_client(char* cl_argv[], const char* exec, Int need_help,
nethercote71980f02004-01-24 18:18:54 +00001352 /*out*/struct exeinfo* info, /*out*/Addr* client_eip)
1353{
1354 // If they didn't specify an executable with --exec, and didn't specify
1355 // --help, then use client argv[0] (searching $PATH if necessary).
nethercotef4928da2004-06-15 10:54:40 +00001356 if (NULL == exec && !need_help) {
nethercote71980f02004-01-24 18:18:54 +00001357 if (cl_argv[0] == NULL ||
1358 ( NULL == (exec = find_executable(cl_argv[0])) ) )
1359 {
nethercotef4928da2004-06-15 10:54:40 +00001360 missing_prog();
nethercote71980f02004-01-24 18:18:54 +00001361 }
1362 }
1363
1364 info->map_base = VG_(client_mapbase);
nethercote71980f02004-01-24 18:18:54 +00001365 info->exe_base = VG_(client_base);
1366 info->exe_end = VG_(client_end);
1367 info->argv = cl_argv;
1368
nethercotef4928da2004-06-15 10:54:40 +00001369 if (need_help) {
nethercote71980f02004-01-24 18:18:54 +00001370 VG_(clexecfd) = -1;
nethercoteea147e72004-07-26 15:43:57 +00001371 // Set the minimal number of entries in 'info' to continue.
nethercoted6a56872004-07-26 15:32:47 +00001372 info->interp_name = NULL;
1373 info->interp_args = NULL;
nethercote71980f02004-01-24 18:18:54 +00001374 } else {
1375 Int ret;
1376 VG_(clexecfd) = VG_(open)(exec, O_RDONLY, VKI_S_IRUSR);
1377 ret = do_exec(exec, info);
1378 if (ret != 0) {
nethercoteea147e72004-07-26 15:43:57 +00001379 fprintf(stderr, "valgrind: do_exec(%s) failed: %s\n",
1380 exec, strerror(ret));
nethercote71980f02004-01-24 18:18:54 +00001381 exit(127);
1382 }
1383 }
1384
1385 /* Copy necessary bits of 'info' that were filled in */
1386 *client_eip = info->init_eip;
1387 VG_(brk_base) = VG_(brk_limit) = info->brkbase;
1388}
1389
1390
1391/*====================================================================*/
nethercotef6a1d502004-08-09 12:21:57 +00001392/*=== Command-line: variables, processing, etc ===*/
nethercote71980f02004-01-24 18:18:54 +00001393/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +00001394
njn25e49d8e72002-09-23 09:36:25 +00001395/* Define, and set defaults. */
1396Bool VG_(clo_error_limit) = True;
nethercote04d0fbc2004-01-26 16:48:06 +00001397Bool VG_(clo_db_attach) = False;
1398Char* VG_(clo_db_command) = VG_CLO_DEFAULT_DBCOMMAND;
njn43c799e2003-04-08 00:08:52 +00001399Bool VG_(clo_gen_suppressions) = False;
nethercote27fec902004-06-16 21:26:32 +00001400Int VG_(clo_sanity_level) = 1;
njn25e49d8e72002-09-23 09:36:25 +00001401Int VG_(clo_verbosity) = 1;
1402Bool VG_(clo_demangle) = True;
njn25e49d8e72002-09-23 09:36:25 +00001403Bool VG_(clo_trace_children) = False;
sewardj4cf05692002-10-27 20:28:29 +00001404
nethercotef1e5e152004-09-01 23:58:16 +00001405/* See big comment in core.h for meaning of these three.
nethercotee1730692003-11-20 10:38:07 +00001406 fd is initially stdout, for --help, but gets moved to stderr by default
1407 immediately afterwards. */
sewardj4cf05692002-10-27 20:28:29 +00001408VgLogTo VG_(clo_log_to) = VgLogTo_Fd;
nethercotef8548672004-06-21 12:42:35 +00001409Int VG_(clo_log_fd) = 1;
1410Char* VG_(clo_log_name) = NULL;
sewardj4cf05692002-10-27 20:28:29 +00001411
thughes6233a382004-08-21 11:10:44 +00001412Bool VG_(clo_time_stamp) = False;
1413
sewardj6024b212003-07-13 10:54:33 +00001414Int VG_(clo_input_fd) = 0; /* stdin */
njn25e49d8e72002-09-23 09:36:25 +00001415Int VG_(clo_n_suppressions) = 0;
sewardjde4a1d02002-03-22 01:27:54 +00001416Char* VG_(clo_suppressions)[VG_CLO_MAX_SFILES];
njn25e49d8e72002-09-23 09:36:25 +00001417Bool VG_(clo_profile) = False;
1418Bool VG_(clo_single_step) = False;
1419Bool VG_(clo_optimise) = True;
1420UChar VG_(clo_trace_codegen) = 0; // 00000000b
1421Bool VG_(clo_trace_syscalls) = False;
1422Bool VG_(clo_trace_signals) = False;
1423Bool VG_(clo_trace_symtab) = False;
njn25e49d8e72002-09-23 09:36:25 +00001424Bool VG_(clo_trace_sched) = False;
1425Int VG_(clo_trace_pthread_level) = 0;
njn25e49d8e72002-09-23 09:36:25 +00001426Int VG_(clo_dump_error) = 0;
1427Int VG_(clo_backtrace_size) = 4;
1428Char* VG_(clo_weird_hacks) = NULL;
sewardj858964b2002-10-05 14:15:43 +00001429Bool VG_(clo_run_libc_freeres) = True;
rjwalshf5f536f2003-11-17 17:45:00 +00001430Bool VG_(clo_track_fds) = False;
sewardj22854b92002-11-30 14:00:47 +00001431Bool VG_(clo_chain_bb) = True;
nethercote77eba602003-11-13 17:35:04 +00001432Bool VG_(clo_show_below_main) = False;
fitzhardinge98abfc72003-12-16 02:05:15 +00001433Bool VG_(clo_pointercheck) = True;
fitzhardinge462f4f92003-12-18 02:10:54 +00001434Bool VG_(clo_branchpred) = False;
sewardj2370f3b2002-11-30 15:01:01 +00001435
jsgf855d93d2003-10-13 22:26:55 +00001436static Bool VG_(clo_wait_for_gdb) = False;
1437
1438/* If we're doing signal routing, poll for signals every 50mS by
1439 default. */
1440Int VG_(clo_signal_polltime) = 50;
1441
1442/* These flags reduce thread wakeup latency on syscall completion and
1443 signal delivery, respectively. The downside is possible unfairness. */
1444Bool VG_(clo_lowlat_syscalls) = False; /* low-latency syscalls */
1445Bool VG_(clo_lowlat_signals) = False; /* low-latency signals */
1446
sewardjde4a1d02002-03-22 01:27:54 +00001447
nethercote6c999f22004-01-31 22:55:15 +00001448void usage ( Bool debug_help )
njn7cf0bd32002-06-08 13:36:03 +00001449{
njn25e49d8e72002-09-23 09:36:25 +00001450 Char* usage1 =
nethercote71980f02004-01-24 18:18:54 +00001451"usage: valgrind --tool=<toolname> [options] prog-and-args\n"
njn25e49d8e72002-09-23 09:36:25 +00001452"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001453" common user options for all Valgrind tools, with defaults in [ ]:\n"
nethercote0d588502004-06-21 13:27:11 +00001454" --tool=<name> use the Valgrind tool named <name>\n"
nethercotea76368b2004-06-16 11:56:29 +00001455" -h --help show this message\n"
nethercote6c999f22004-01-31 22:55:15 +00001456" --help-debug show this message, plus debugging options\n"
njn25e49d8e72002-09-23 09:36:25 +00001457" --version show version\n"
njn25e49d8e72002-09-23 09:36:25 +00001458" -q --quiet run silently; only print error msgs\n"
1459" -v --verbose be more verbose, incl counts of errors\n"
nethercote77eba602003-11-13 17:35:04 +00001460" --trace-children=no|yes Valgrind-ise child processes? [no]\n"
nethercote0d588502004-06-21 13:27:11 +00001461" --track-fds=no|yes track open file descriptors? [no]\n"
thughes6233a382004-08-21 11:10:44 +00001462" --time-stamp=no|yes add timestamps to log messages? [no]\n"
nethercote2b0793f2003-12-02 10:41:18 +00001463"\n"
1464" uncommon user options for all Valgrind tools:\n"
nethercote0d588502004-06-21 13:27:11 +00001465" --run-libc-freeres=no|yes free up glibc memory at exit? [yes]\n"
1466" --weird-hacks=hack1,hack2,... recognised hacks: lax-ioctls [none]\n"
1467" --signal-polltime=<time> signal poll period (mS) for older kernels [50]\n"
1468" --lowlat-signals=no|yes improve thread signal wake-up latency [no]\n"
1469" --lowlat-syscalls=no|yes improve thread syscall wake-up latency [no]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001470" --pointercheck=no|yes enforce client address space limits [yes]\n"
njn25e49d8e72002-09-23 09:36:25 +00001471"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001472" user options for Valgrind tools that report errors:\n"
nethercotef8548672004-06-21 12:42:35 +00001473" --log-fd=<number> log messages to file descriptor [2=stderr]\n"
1474" --log-file=<file> log messages to <file>.pid<pid>\n"
1475" --log-socket=ipaddr:port log messages to socket ipaddr:port\n"
nethercote2b0793f2003-12-02 10:41:18 +00001476" --demangle=no|yes automatically demangle C++ names? [yes]\n"
1477" --num-callers=<number> show <num> callers in stack traces [4]\n"
1478" --error-limit=no|yes stop showing new errors if too many? [yes]\n"
1479" --show-below-main=no|yes continue stack traces below main() [no]\n"
1480" --suppressions=<filename> suppress errors described in <filename>\n"
1481" --gen-suppressions=no|yes print suppressions for errors detected [no]\n"
nethercote04d0fbc2004-01-26 16:48:06 +00001482" --db-attach=no|yes start debugger when errors detected? [no]\n"
1483" --db-command=<command> command to start debugger [gdb -nw %%f %%p]\n"
1484" --input-fd=<number> file descriptor for input [0=stdin]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001485"\n";
njn7cf0bd32002-06-08 13:36:03 +00001486
njn25e49d8e72002-09-23 09:36:25 +00001487 Char* usage2 =
1488"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001489" debugging options for all Valgrind tools:\n"
njn25e49d8e72002-09-23 09:36:25 +00001490" --sanity-level=<number> level of sanity checking to do [1]\n"
1491" --single-step=no|yes translate each instr separately? [no]\n"
1492" --optimise=no|yes improve intermediate code? [yes]\n"
nethercote137bc552003-11-14 17:47:54 +00001493" --profile=no|yes profile? (tool must be built for it) [no]\n"
sewardj22854b92002-11-30 14:00:47 +00001494" --chain-bb=no|yes do basic-block chaining? [yes]\n"
fitzhardinge462f4f92003-12-18 02:10:54 +00001495" --branchpred=yes|no generate branch prediction hints [no]\n"
njn25e49d8e72002-09-23 09:36:25 +00001496" --trace-codegen=<XXXXX> show generated code? (X = 0|1) [00000]\n"
1497" --trace-syscalls=no|yes show all system calls? [no]\n"
1498" --trace-signals=no|yes show signal handling details? [no]\n"
1499" --trace-symtab=no|yes show symbol table details? [no]\n"
njn25e49d8e72002-09-23 09:36:25 +00001500" --trace-sched=no|yes show thread scheduler details? [no]\n"
njn3e884182003-04-15 13:03:23 +00001501" --trace-pthread=none|some|all show pthread event details? [none]\n"
jsgf855d93d2003-10-13 22:26:55 +00001502" --wait-for-gdb=yes|no pause on startup to wait for gdb attach\n"
njn25e49d8e72002-09-23 09:36:25 +00001503"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001504" debugging options for Valgrind tools that report errors\n"
1505" --dump-error=<number> show translation for basic block associated\n"
1506" with <number>'th error context [0=show none]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001507"\n";
njn3e884182003-04-15 13:03:23 +00001508
1509 Char* usage3 =
1510"\n"
nethercote71980f02004-01-24 18:18:54 +00001511" Extra options read from ~/.valgrindrc, $VALGRIND_OPTS, ./.valgrindrc\n"
njn25e49d8e72002-09-23 09:36:25 +00001512"\n"
nethercote08fa9a72004-07-16 17:44:00 +00001513" Valgrind is Copyright (C) 2000-2004 Julian Seward et al.\n"
njn25e49d8e72002-09-23 09:36:25 +00001514" and licensed under the GNU General Public License, version 2.\n"
1515" Bug reports, feedback, admiration, abuse, etc, to: %s.\n"
njnd04b7c62002-10-03 14:05:52 +00001516"\n"
nethercote137bc552003-11-14 17:47:54 +00001517" Tools are copyright and licensed by their authors. See each\n"
1518" tool's start-up message for more information.\n"
njn25e49d8e72002-09-23 09:36:25 +00001519"\n";
njn7cf0bd32002-06-08 13:36:03 +00001520
fitzhardinge98abfc72003-12-16 02:05:15 +00001521 VG_(printf)(usage1);
1522 if (VG_(details).name) {
1523 VG_(printf)(" user options for %s:\n", VG_(details).name);
fitzhardinge98abfc72003-12-16 02:05:15 +00001524 if (VG_(needs).command_line_options)
1525 SK_(print_usage)();
1526 else
1527 VG_(printf)(" (none)\n");
1528 }
nethercote6c999f22004-01-31 22:55:15 +00001529 if (debug_help) {
1530 VG_(printf)(usage2);
fitzhardinge98abfc72003-12-16 02:05:15 +00001531
nethercote6c999f22004-01-31 22:55:15 +00001532 if (VG_(details).name) {
1533 VG_(printf)(" debugging options for %s:\n", VG_(details).name);
1534
1535 if (VG_(needs).command_line_options)
1536 SK_(print_debug_usage)();
1537 else
1538 VG_(printf)(" (none)\n");
1539 }
fitzhardinge98abfc72003-12-16 02:05:15 +00001540 }
nethercote421281e2003-11-20 16:20:55 +00001541 VG_(printf)(usage3, VG_BUGS_TO);
nethercotef4928da2004-06-15 10:54:40 +00001542 VG_(exit)(0);
njn7cf0bd32002-06-08 13:36:03 +00001543}
sewardjde4a1d02002-03-22 01:27:54 +00001544
nethercote71980f02004-01-24 18:18:54 +00001545static void pre_process_cmd_line_options
nethercote6c999f22004-01-31 22:55:15 +00001546 ( Int* need_help, const char** tool, const char** exec )
sewardj1c1b1162003-02-23 01:25:51 +00001547{
nethercote71980f02004-01-24 18:18:54 +00001548 UInt i;
sewardjde4a1d02002-03-22 01:27:54 +00001549
nethercote71980f02004-01-24 18:18:54 +00001550 /* parse the options we have (only the options we care about now) */
nethercotef6a1d502004-08-09 12:21:57 +00001551 for (i = 1; i < vg_argc; i++) {
nethercote71980f02004-01-24 18:18:54 +00001552
nethercotef6a1d502004-08-09 12:21:57 +00001553 if (strcmp(vg_argv[i], "--version") == 0) {
nethercote71980f02004-01-24 18:18:54 +00001554 printf("valgrind-" VERSION "\n");
nethercotef4928da2004-06-15 10:54:40 +00001555 exit(0);
nethercote71980f02004-01-24 18:18:54 +00001556
nethercotef6a1d502004-08-09 12:21:57 +00001557 } else if (VG_CLO_STREQ(vg_argv[i], "--help") ||
1558 VG_CLO_STREQ(vg_argv[i], "-h")) {
nethercote6c999f22004-01-31 22:55:15 +00001559 *need_help = 1;
1560
nethercotef6a1d502004-08-09 12:21:57 +00001561 } else if (VG_CLO_STREQ(vg_argv[i], "--help-debug")) {
nethercote6c999f22004-01-31 22:55:15 +00001562 *need_help = 2;
nethercote71980f02004-01-24 18:18:54 +00001563
nethercotef6a1d502004-08-09 12:21:57 +00001564 } else if (VG_CLO_STREQN(7, vg_argv[i], "--tool=") ||
1565 VG_CLO_STREQN(7, vg_argv[i], "--skin=")) {
1566 *tool = &vg_argv[i][7];
nethercote71980f02004-01-24 18:18:54 +00001567
nethercotef6a1d502004-08-09 12:21:57 +00001568 } else if (VG_CLO_STREQN(7, vg_argv[i], "--exec=")) {
1569 *exec = &vg_argv[i][7];
nethercote71980f02004-01-24 18:18:54 +00001570 }
1571 }
1572
nethercotef4928da2004-06-15 10:54:40 +00001573 /* If no tool specified, can act appropriately without loading tool */
nethercote71980f02004-01-24 18:18:54 +00001574 if (*tool == NULL) {
nethercotef4928da2004-06-15 10:54:40 +00001575 if (0 == *need_help) {
1576 // neither --tool nor --help/--help-debug specified
1577 missing_tool_option();
1578 } else {
1579 // Give help message, without any tool-specific help
1580 usage(/*help-debug?*/2 == *need_help);
1581 }
nethercote71980f02004-01-24 18:18:54 +00001582 }
1583}
1584
nethercote5ee67ca2004-06-22 14:00:09 +00001585static void process_cmd_line_options( UInt* client_auxv, const char* toolname )
nethercote71980f02004-01-24 18:18:54 +00001586{
nethercotef8548672004-06-21 12:42:35 +00001587 Int i, eventually_log_fd;
nethercote71980f02004-01-24 18:18:54 +00001588 Int *auxp;
1589 Int toolname_len = VG_(strlen)(toolname);
sewardjde4a1d02002-03-22 01:27:54 +00001590
nethercotee1730692003-11-20 10:38:07 +00001591 /* log to stderr by default, but usage message goes to stdout */
nethercotef8548672004-06-21 12:42:35 +00001592 eventually_log_fd = 2;
sewardjde4a1d02002-03-22 01:27:54 +00001593
sewardj19d81412002-06-03 01:10:40 +00001594 /* Check for sane path in ./configure --prefix=... */
fitzhardinge98abfc72003-12-16 02:05:15 +00001595 if (VG_LIBDIR[0] != '/')
sewardj19d81412002-06-03 01:10:40 +00001596 config_error("Please use absolute paths in "
1597 "./configure --prefix=... or --libdir=...");
sewardj38170912002-05-10 21:07:22 +00001598
nethercote71980f02004-01-24 18:18:54 +00001599 for (auxp = client_auxv; auxp[0] != VKI_AT_NULL; auxp += 2) {
fitzhardinge98abfc72003-12-16 02:05:15 +00001600 switch(auxp[0]) {
1601 case VKI_AT_SYSINFO:
fitzhardinge92360792003-12-24 10:11:11 +00001602 auxp[1] = (Int)(VG_(client_trampoline_code) + VG_(tramp_syscall_offset));
fitzhardinge98abfc72003-12-16 02:05:15 +00001603 break;
sewardjde4a1d02002-03-22 01:27:54 +00001604 }
fitzhardinge98abfc72003-12-16 02:05:15 +00001605 }
sewardjde4a1d02002-03-22 01:27:54 +00001606
nethercotef6a1d502004-08-09 12:21:57 +00001607 for (i = 1; i < vg_argc; i++) {
nethercote71980f02004-01-24 18:18:54 +00001608
nethercotef6a1d502004-08-09 12:21:57 +00001609 Char* arg = vg_argv[i];
thughes3bfd5a02004-07-18 08:05:44 +00001610 Char* colon = arg;
nethercote71980f02004-01-24 18:18:54 +00001611
thughes3bfd5a02004-07-18 08:05:44 +00001612 /* Look for a colon in the switch name */
1613 while (*colon && *colon != ':' && *colon != '=')
1614 colon++;
nethercote71980f02004-01-24 18:18:54 +00001615
1616 /* Look for matching "--toolname:foo" */
thughes3bfd5a02004-07-18 08:05:44 +00001617 if (*colon == ':') {
nethercote71980f02004-01-24 18:18:54 +00001618 if (VG_CLO_STREQN(2, arg, "--") &&
1619 VG_CLO_STREQN(toolname_len, arg+2, toolname) &&
1620 VG_CLO_STREQN(1, arg+2+toolname_len, ":"))
1621 {
1622 // prefix matches, convert "--toolname:foo" to "--foo"
1623 if (0)
1624 VG_(printf)("tool-specific arg: %s\n", arg);
1625 arg += toolname_len + 1;
1626 arg[0] = '-';
1627 arg[1] = '-';
1628
1629 } else {
1630 // prefix doesn't match, skip to next arg
1631 continue;
1632 }
1633 }
1634
fitzhardinge98abfc72003-12-16 02:05:15 +00001635 /* Ignore these options - they've already been handled */
nethercote71980f02004-01-24 18:18:54 +00001636 if (VG_CLO_STREQN(7, arg, "--tool=") ||
1637 VG_CLO_STREQN(7, arg, "--skin="))
fitzhardinge98abfc72003-12-16 02:05:15 +00001638 continue;
nethercote71980f02004-01-24 18:18:54 +00001639 if (VG_CLO_STREQN(7, arg, "--exec="))
fitzhardinge98abfc72003-12-16 02:05:15 +00001640 continue;
1641
nethercote71980f02004-01-24 18:18:54 +00001642 if ( VG_CLO_STREQ(arg, "--"))
fitzhardinge98abfc72003-12-16 02:05:15 +00001643 continue;
nethercote27fec902004-06-16 21:26:32 +00001644
nethercote71980f02004-01-24 18:18:54 +00001645 else if (VG_CLO_STREQ(arg, "-v") ||
1646 VG_CLO_STREQ(arg, "--verbose"))
sewardjde4a1d02002-03-22 01:27:54 +00001647 VG_(clo_verbosity)++;
nethercote27fec902004-06-16 21:26:32 +00001648
nethercote71980f02004-01-24 18:18:54 +00001649 else if (VG_CLO_STREQ(arg, "-q") ||
1650 VG_CLO_STREQ(arg, "--quiet"))
sewardjde4a1d02002-03-22 01:27:54 +00001651 VG_(clo_verbosity)--;
1652
nethercote27fec902004-06-16 21:26:32 +00001653 else VG_BOOL_CLO("--branchpred", VG_(clo_branchpred))
1654 else VG_BOOL_CLO("--chain-bb", VG_(clo_chain_bb))
1655 else VG_BOOL_CLO("--db-attach", VG_(clo_db_attach))
1656 else VG_BOOL_CLO("--demangle", VG_(clo_demangle))
1657 else VG_BOOL_CLO("--error-limit", VG_(clo_error_limit))
1658 else VG_BOOL_CLO("--gen-suppressions", VG_(clo_gen_suppressions))
1659 else VG_BOOL_CLO("--lowlat-signals", VG_(clo_lowlat_signals))
1660 else VG_BOOL_CLO("--lowlat-syscalls", VG_(clo_lowlat_syscalls))
1661 else VG_BOOL_CLO("--optimise", VG_(clo_optimise))
1662 else VG_BOOL_CLO("--pointercheck", VG_(clo_pointercheck))
1663 else VG_BOOL_CLO("--profile", VG_(clo_profile))
1664 else VG_BOOL_CLO("--run-libc-freeres", VG_(clo_run_libc_freeres))
1665 else VG_BOOL_CLO("--show-below-main", VG_(clo_show_below_main))
1666 else VG_BOOL_CLO("--single-step", VG_(clo_single_step))
thughes6233a382004-08-21 11:10:44 +00001667 else VG_BOOL_CLO("--time-stamp", VG_(clo_time_stamp))
nethercote27fec902004-06-16 21:26:32 +00001668 else VG_BOOL_CLO("--track-fds", VG_(clo_track_fds))
1669 else VG_BOOL_CLO("--trace-children", VG_(clo_trace_children))
1670 else VG_BOOL_CLO("--trace-sched", VG_(clo_trace_sched))
1671 else VG_BOOL_CLO("--trace-signals", VG_(clo_trace_signals))
1672 else VG_BOOL_CLO("--trace-symtab", VG_(clo_trace_symtab))
1673 else VG_BOOL_CLO("--trace-syscalls", VG_(clo_trace_syscalls))
1674 else VG_BOOL_CLO("--wait-for-gdb", VG_(clo_wait_for_gdb))
sewardj72f98ff2002-06-13 17:23:38 +00001675
nethercote27fec902004-06-16 21:26:32 +00001676 else VG_STR_CLO ("--db-command", VG_(clo_db_command))
1677 else VG_STR_CLO ("--weird-hacks", VG_(clo_weird_hacks))
sewardjde4a1d02002-03-22 01:27:54 +00001678
nethercote27fec902004-06-16 21:26:32 +00001679 else VG_NUM_CLO ("--dump-error", VG_(clo_dump_error))
1680 else VG_NUM_CLO ("--input-fd", VG_(clo_input_fd))
1681 else VG_NUM_CLO ("--sanity-level", VG_(clo_sanity_level))
1682 else VG_NUM_CLO ("--signal­polltime", VG_(clo_signal_polltime))
1683 else VG_BNUM_CLO("--num-callers", VG_(clo_backtrace_size), 1,
1684 VG_DEEPEST_BACKTRACE)
sewardjde4a1d02002-03-22 01:27:54 +00001685
nethercotef8548672004-06-21 12:42:35 +00001686 // for backwards compatibility, replaced by --log-fd
nethercote71980f02004-01-24 18:18:54 +00001687 else if (VG_CLO_STREQN(13, arg, "--logfile-fd=")) {
nethercotef8548672004-06-21 12:42:35 +00001688 VG_(clo_log_to) = VgLogTo_Fd;
1689 VG_(clo_log_name) = NULL;
1690 eventually_log_fd = (Int)VG_(atoll)(&arg[13]);
1691 }
1692 else if (VG_CLO_STREQN(9, arg, "--log-fd=")) {
1693 VG_(clo_log_to) = VgLogTo_Fd;
1694 VG_(clo_log_name) = NULL;
1695 eventually_log_fd = (Int)VG_(atoll)(&arg[9]);
sewardj4cf05692002-10-27 20:28:29 +00001696 }
1697
nethercotef8548672004-06-21 12:42:35 +00001698 // for backwards compatibility, replaced by --log-file
nethercote71980f02004-01-24 18:18:54 +00001699 else if (VG_CLO_STREQN(10, arg, "--logfile=")) {
nethercotef8548672004-06-21 12:42:35 +00001700 VG_(clo_log_to) = VgLogTo_File;
1701 VG_(clo_log_name) = &arg[10];
1702 }
1703 else if (VG_CLO_STREQN(11, arg, "--log-file=")) {
1704 VG_(clo_log_to) = VgLogTo_File;
1705 VG_(clo_log_name) = &arg[11];
sewardj4cf05692002-10-27 20:28:29 +00001706 }
sewardjde4a1d02002-03-22 01:27:54 +00001707
nethercotef8548672004-06-21 12:42:35 +00001708 // for backwards compatibility, replaced by --log-socket
nethercote71980f02004-01-24 18:18:54 +00001709 else if (VG_CLO_STREQN(12, arg, "--logsocket=")) {
nethercotef8548672004-06-21 12:42:35 +00001710 VG_(clo_log_to) = VgLogTo_Socket;
1711 VG_(clo_log_name) = &arg[12];
1712 }
1713 else if (VG_CLO_STREQN(13, arg, "--log-socket=")) {
1714 VG_(clo_log_to) = VgLogTo_Socket;
1715 VG_(clo_log_name) = &arg[13];
sewardj73cf3bc2002-11-03 03:20:15 +00001716 }
1717
nethercote71980f02004-01-24 18:18:54 +00001718 else if (VG_CLO_STREQN(15, arg, "--suppressions=")) {
sewardjde4a1d02002-03-22 01:27:54 +00001719 if (VG_(clo_n_suppressions) >= VG_CLO_MAX_SFILES) {
njn25e49d8e72002-09-23 09:36:25 +00001720 VG_(message)(Vg_UserMsg, "Too many suppression files specified.");
sewardjde4a1d02002-03-22 01:27:54 +00001721 VG_(message)(Vg_UserMsg,
1722 "Increase VG_CLO_MAX_SFILES and recompile.");
nethercote71980f02004-01-24 18:18:54 +00001723 VG_(bad_option)(arg);
sewardjde4a1d02002-03-22 01:27:54 +00001724 }
nethercote71980f02004-01-24 18:18:54 +00001725 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = &arg[15];
sewardjde4a1d02002-03-22 01:27:54 +00001726 VG_(clo_n_suppressions)++;
1727 }
sewardjde4a1d02002-03-22 01:27:54 +00001728
njn25e49d8e72002-09-23 09:36:25 +00001729 /* "vwxyz" --> 000zyxwv (binary) */
nethercote71980f02004-01-24 18:18:54 +00001730 else if (VG_CLO_STREQN(16, arg, "--trace-codegen=")) {
njn25e49d8e72002-09-23 09:36:25 +00001731 Int j;
nethercote71980f02004-01-24 18:18:54 +00001732 char* opt = & arg[16];
njn25e49d8e72002-09-23 09:36:25 +00001733
1734 if (5 != VG_(strlen)(opt)) {
1735 VG_(message)(Vg_UserMsg,
1736 "--trace-codegen argument must have 5 digits");
nethercote71980f02004-01-24 18:18:54 +00001737 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001738 }
1739 for (j = 0; j < 5; j++) {
1740 if ('0' == opt[j]) { /* do nothing */ }
1741 else if ('1' == opt[j]) VG_(clo_trace_codegen) |= (1 << j);
1742 else {
1743 VG_(message)(Vg_UserMsg, "--trace-codegen argument can only "
1744 "contain 0s and 1s");
nethercote71980f02004-01-24 18:18:54 +00001745 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001746 }
1747 }
1748 }
sewardjde4a1d02002-03-22 01:27:54 +00001749
nethercote71980f02004-01-24 18:18:54 +00001750 else if (VG_CLO_STREQ(arg, "--trace-pthread=none"))
sewardj45b4b372002-04-16 22:50:32 +00001751 VG_(clo_trace_pthread_level) = 0;
nethercote71980f02004-01-24 18:18:54 +00001752 else if (VG_CLO_STREQ(arg, "--trace-pthread=some"))
sewardj45b4b372002-04-16 22:50:32 +00001753 VG_(clo_trace_pthread_level) = 1;
nethercote71980f02004-01-24 18:18:54 +00001754 else if (VG_CLO_STREQ(arg, "--trace-pthread=all"))
sewardj45b4b372002-04-16 22:50:32 +00001755 VG_(clo_trace_pthread_level) = 2;
sewardj8937c812002-04-12 20:12:20 +00001756
nethercote71980f02004-01-24 18:18:54 +00001757 else if ( ! VG_(needs).command_line_options
1758 || ! SK_(process_cmd_line_option)(arg) ) {
nethercotef4928da2004-06-15 10:54:40 +00001759 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001760 }
sewardjde4a1d02002-03-22 01:27:54 +00001761 }
1762
nethercote27fec902004-06-16 21:26:32 +00001763 // Check various option values
1764
njnf9ebf672003-05-12 21:41:30 +00001765 if (VG_(clo_verbosity) < 0)
sewardjde4a1d02002-03-22 01:27:54 +00001766 VG_(clo_verbosity) = 0;
1767
nethercote04d0fbc2004-01-26 16:48:06 +00001768 if (VG_(clo_db_attach) && VG_(clo_trace_children)) {
sewardjde4a1d02002-03-22 01:27:54 +00001769 VG_(message)(Vg_UserMsg, "");
1770 VG_(message)(Vg_UserMsg,
nethercote04d0fbc2004-01-26 16:48:06 +00001771 "--db-attach=yes conflicts with --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001772 VG_(message)(Vg_UserMsg,
1773 "Please choose one or the other, but not both.");
nethercote04d0fbc2004-01-26 16:48:06 +00001774 VG_(bad_option)("--db-attach=yes and --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001775 }
1776
nethercotef8548672004-06-21 12:42:35 +00001777 /* Set up logging now. After this is done, VG_(clo_log_fd)
sewardj4cf05692002-10-27 20:28:29 +00001778 should be connected to whatever sink has been selected, and we
1779 indiscriminately chuck stuff into it without worrying what the
1780 nature of it is. Oh the wonder of Unix streams. */
1781
nethercotee1730692003-11-20 10:38:07 +00001782 /* So far we should be still attached to stdout, so we can show on
sewardj4cf05692002-10-27 20:28:29 +00001783 the terminal any problems to do with processing command line
1784 opts. */
nethercotef8548672004-06-21 12:42:35 +00001785 vg_assert(VG_(clo_log_fd) == 1 /* stdout */);
sewardj73cf3bc2002-11-03 03:20:15 +00001786 vg_assert(VG_(logging_to_filedes) == True);
sewardj4cf05692002-10-27 20:28:29 +00001787
1788 switch (VG_(clo_log_to)) {
sewardj73cf3bc2002-11-03 03:20:15 +00001789
sewardj4cf05692002-10-27 20:28:29 +00001790 case VgLogTo_Fd:
nethercotef8548672004-06-21 12:42:35 +00001791 vg_assert(VG_(clo_log_name) == NULL);
1792 VG_(clo_log_fd) = eventually_log_fd;
sewardj4cf05692002-10-27 20:28:29 +00001793 break;
sewardj73cf3bc2002-11-03 03:20:15 +00001794
sewardj4cf05692002-10-27 20:28:29 +00001795 case VgLogTo_File: {
1796 Char logfilename[1000];
jsgff3c3f1a2003-10-14 22:13:28 +00001797 Int seq = 0;
1798 Int pid = VG_(getpid)();
1799
nethercotef8548672004-06-21 12:42:35 +00001800 vg_assert(VG_(clo_log_name) != NULL);
1801 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
jsgff3c3f1a2003-10-14 22:13:28 +00001802
nethercote71980f02004-01-24 18:18:54 +00001803 for (;;) {
jsgff3c3f1a2003-10-14 22:13:28 +00001804 if (seq == 0)
1805 VG_(sprintf)(logfilename, "%s.pid%d",
nethercotef8548672004-06-21 12:42:35 +00001806 VG_(clo_log_name), pid );
jsgff3c3f1a2003-10-14 22:13:28 +00001807 else
1808 VG_(sprintf)(logfilename, "%s.pid%d.%d",
nethercotef8548672004-06-21 12:42:35 +00001809 VG_(clo_log_name), pid, seq );
jsgff3c3f1a2003-10-14 22:13:28 +00001810 seq++;
1811
nethercotef8548672004-06-21 12:42:35 +00001812 eventually_log_fd
jsgff3c3f1a2003-10-14 22:13:28 +00001813 = VG_(open)(logfilename,
1814 VKI_O_CREAT|VKI_O_WRONLY|VKI_O_EXCL|VKI_O_TRUNC,
1815 VKI_S_IRUSR|VKI_S_IWUSR);
nethercotef8548672004-06-21 12:42:35 +00001816 if (eventually_log_fd >= 0) {
1817 VG_(clo_log_fd) = VG_(safe_fd)(eventually_log_fd);
jsgff3c3f1a2003-10-14 22:13:28 +00001818 break;
1819 } else {
nethercotef8548672004-06-21 12:42:35 +00001820 if (eventually_log_fd != -VKI_EEXIST) {
jsgff3c3f1a2003-10-14 22:13:28 +00001821 VG_(message)(Vg_UserMsg,
1822 "Can't create/open log file `%s.pid%d'; giving up!",
nethercotef8548672004-06-21 12:42:35 +00001823 VG_(clo_log_name), pid);
jsgff3c3f1a2003-10-14 22:13:28 +00001824 VG_(bad_option)(
nethercotef8548672004-06-21 12:42:35 +00001825 "--log-file=<file> didn't work out for some reason.");
jsgff3c3f1a2003-10-14 22:13:28 +00001826 break;
1827 }
1828 }
1829 }
sewardj4cf05692002-10-27 20:28:29 +00001830 break;
sewardj73cf3bc2002-11-03 03:20:15 +00001831 }
1832
1833 case VgLogTo_Socket: {
nethercotef8548672004-06-21 12:42:35 +00001834 vg_assert(VG_(clo_log_name) != NULL);
1835 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
1836 eventually_log_fd = VG_(connect_via_socket)( VG_(clo_log_name) );
1837 if (eventually_log_fd == -1) {
sewardj73cf3bc2002-11-03 03:20:15 +00001838 VG_(message)(Vg_UserMsg,
nethercotef8548672004-06-21 12:42:35 +00001839 "Invalid --log-socket=ipaddr or --log-socket=ipaddr:port spec");
sewardj73cf3bc2002-11-03 03:20:15 +00001840 VG_(message)(Vg_UserMsg,
nethercotef8548672004-06-21 12:42:35 +00001841 "of `%s'; giving up!", VG_(clo_log_name) );
sewardj73cf3bc2002-11-03 03:20:15 +00001842 VG_(bad_option)(
nethercotef8548672004-06-21 12:42:35 +00001843 "--log-socket=");
sewardj4cf05692002-10-27 20:28:29 +00001844 }
nethercotef8548672004-06-21 12:42:35 +00001845 if (eventually_log_fd == -2) {
sewardj73cf3bc2002-11-03 03:20:15 +00001846 VG_(message)(Vg_UserMsg,
sewardj570f8902002-11-03 11:44:36 +00001847 "valgrind: failed to connect to logging server `%s'.",
nethercotef8548672004-06-21 12:42:35 +00001848 VG_(clo_log_name) );
sewardj570f8902002-11-03 11:44:36 +00001849 VG_(message)(Vg_UserMsg,
1850 "Log messages will sent to stderr instead." );
1851 VG_(message)(Vg_UserMsg,
1852 "" );
1853 /* We don't change anything here. */
1854 } else {
nethercotef8548672004-06-21 12:42:35 +00001855 vg_assert(eventually_log_fd > 0);
1856 VG_(clo_log_fd) = eventually_log_fd;
sewardj570f8902002-11-03 11:44:36 +00001857 VG_(logging_to_filedes) = False;
1858 }
sewardj73cf3bc2002-11-03 03:20:15 +00001859 break;
1860 }
1861
sewardj4cf05692002-10-27 20:28:29 +00001862 }
1863
nethercotef8548672004-06-21 12:42:35 +00001864 /* Move log_fd into the safe range, so it doesn't conflict with any app fds */
thughesad1c9562004-06-26 11:27:52 +00001865 eventually_log_fd = VG_(fcntl)(VG_(clo_log_fd), VKI_F_DUPFD, VG_(fd_hard_limit));
nethercotef8548672004-06-21 12:42:35 +00001866 if (eventually_log_fd < 0)
jsgf855d93d2003-10-13 22:26:55 +00001867 VG_(message)(Vg_UserMsg, "valgrind: failed to move logfile fd into safe range");
1868 else {
nethercotef8548672004-06-21 12:42:35 +00001869 VG_(clo_log_fd) = eventually_log_fd;
1870 VG_(fcntl)(VG_(clo_log_fd), VKI_F_SETFD, VKI_FD_CLOEXEC);
jsgf855d93d2003-10-13 22:26:55 +00001871 }
1872
sewardj4cf05692002-10-27 20:28:29 +00001873 /* Ok, the logging sink is running now. Print a suitable preamble.
1874 If logging to file or a socket, write details of parent PID and
1875 command line args, to help people trying to interpret the
1876 results of a run which encompasses multiple processes. */
sewardjde4a1d02002-03-22 01:27:54 +00001877
sewardj83adf412002-05-01 01:25:45 +00001878 if (VG_(clo_verbosity > 0)) {
nethercote996901a2004-08-03 13:29:09 +00001879 /* Tool details */
nethercotea131bb82004-09-06 15:34:37 +00001880 VG_(message)(Vg_UserMsg, "%s%s%s, %s for %s.",
njnd04b7c62002-10-03 14:05:52 +00001881 VG_(details).name,
1882 NULL == VG_(details).version ? "" : "-",
1883 NULL == VG_(details).version
1884 ? (Char*)"" : VG_(details).version,
nethercotea131bb82004-09-06 15:34:37 +00001885 VG_(details).description,
1886 VG_PLATFORM);
njnd04b7c62002-10-03 14:05:52 +00001887 VG_(message)(Vg_UserMsg, "%s", VG_(details).copyright_author);
sewardj3b2736a2002-03-24 12:18:35 +00001888
njnd04b7c62002-10-03 14:05:52 +00001889 /* Core details */
1890 VG_(message)(Vg_UserMsg,
nethercotea131bb82004-09-06 15:34:37 +00001891 "Using valgrind-%s, a program supervision framework for %s.",
1892 VERSION, VG_PLATFORM);
sewardjde4a1d02002-03-22 01:27:54 +00001893 VG_(message)(Vg_UserMsg,
nethercote08fa9a72004-07-16 17:44:00 +00001894 "Copyright (C) 2000-2004, and GNU GPL'd, by Julian Seward et al.");
njnd04b7c62002-10-03 14:05:52 +00001895 }
1896
nethercotec1e395d2003-11-10 13:26:49 +00001897 if (VG_(clo_verbosity) > 0 && VG_(clo_log_to) != VgLogTo_Fd) {
sewardj4cf05692002-10-27 20:28:29 +00001898 VG_(message)(Vg_UserMsg, "");
1899 VG_(message)(Vg_UserMsg,
1900 "My PID = %d, parent PID = %d. Prog and args are:",
1901 VG_(getpid)(), VG_(getppid)() );
1902 for (i = 0; i < VG_(client_argc); i++)
1903 VG_(message)(Vg_UserMsg, " %s", VG_(client_argv)[i]);
1904 }
1905
sewardjde4a1d02002-03-22 01:27:54 +00001906 if (VG_(clo_verbosity) > 1) {
nethercotea70f7352004-04-18 12:08:46 +00001907 Int fd;
sewardj4cf05692002-10-27 20:28:29 +00001908 if (VG_(clo_log_to) != VgLogTo_Fd)
1909 VG_(message)(Vg_UserMsg, "");
fitzhardinge98abfc72003-12-16 02:05:15 +00001910 VG_(message)(Vg_UserMsg, "Valgrind library directory: %s", VG_(libdir));
njn86dc2bc2003-09-09 07:26:21 +00001911 VG_(message)(Vg_UserMsg, "Command line");
1912 for (i = 0; i < VG_(client_argc); i++)
1913 VG_(message)(Vg_UserMsg, " %s", VG_(client_argv)[i]);
1914
sewardjde4a1d02002-03-22 01:27:54 +00001915 VG_(message)(Vg_UserMsg, "Startup, with flags:");
nethercotef6a1d502004-08-09 12:21:57 +00001916 for (i = 1; i < vg_argc; i++) {
1917 VG_(message)(Vg_UserMsg, " %s", vg_argv[i]);
sewardjde4a1d02002-03-22 01:27:54 +00001918 }
nethercotea70f7352004-04-18 12:08:46 +00001919
1920 VG_(message)(Vg_UserMsg, "Contents of /proc/version:");
1921 fd = VG_(open) ( "/proc/version", VKI_O_RDONLY, 0 );
1922 if (fd < 0) {
1923 VG_(message)(Vg_UserMsg, " can't open /proc/version");
1924 } else {
1925 #define BUF_LEN 256
1926 Char version_buf[BUF_LEN];
1927 Int n = VG_(read) ( fd, version_buf, BUF_LEN );
1928 vg_assert(n <= 256);
1929 if (n > 0) {
1930 version_buf[n-1] = '\0';
1931 VG_(message)(Vg_UserMsg, " %s", version_buf);
1932 } else {
1933 VG_(message)(Vg_UserMsg, " (empty?)");
1934 }
1935 VG_(close)(fd);
1936 #undef BUF_LEN
1937 }
sewardjde4a1d02002-03-22 01:27:54 +00001938 }
1939
fitzhardinge98abfc72003-12-16 02:05:15 +00001940 if (VG_(clo_n_suppressions) < VG_CLO_MAX_SFILES-1 &&
njn25e49d8e72002-09-23 09:36:25 +00001941 (VG_(needs).core_errors || VG_(needs).skin_errors)) {
nethercote996901a2004-08-03 13:29:09 +00001942 /* If there are no suppression files specified and the tool
fitzhardinge98abfc72003-12-16 02:05:15 +00001943 needs one, load the default */
1944 static const Char default_supp[] = "default.supp";
1945 Int len = VG_(strlen)(VG_(libdir)) + 1 + sizeof(default_supp);
1946 Char *buf = VG_(arena_malloc)(VG_AR_CORE, len);
1947 VG_(sprintf)(buf, "%s/%s", VG_(libdir), default_supp);
1948 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = buf;
1949 VG_(clo_n_suppressions)++;
sewardjde4a1d02002-03-22 01:27:54 +00001950 }
sewardj4cf05692002-10-27 20:28:29 +00001951
njn6a230532003-07-21 10:38:23 +00001952 if (VG_(clo_gen_suppressions) &&
1953 !VG_(needs).core_errors && !VG_(needs).skin_errors) {
nethercotef4928da2004-06-15 10:54:40 +00001954 VG_(message)(Vg_UserMsg,
1955 "Can't use --gen-suppressions=yes with this tool,");
1956 VG_(message)(Vg_UserMsg,
1957 "as it doesn't generate errors.");
1958 VG_(bad_option)("--gen-suppressions=yes");
njn6a230532003-07-21 10:38:23 +00001959 }
sewardjde4a1d02002-03-22 01:27:54 +00001960}
1961
nethercotef6a1d502004-08-09 12:21:57 +00001962// Build the string for VALGRINDCLO.
1963Char* VG_(build_child_VALGRINDCLO)( Char* exename )
1964{
1965 /* If we're tracing the children, then we need to start it
1966 with our starter+arguments, which are copied into VALGRINDCLO,
1967 except the --exec= option is changed if present.
1968 */
1969 Int i;
1970 Char *exec;
1971 Char *cp;
1972 Char *optvar;
1973 Int optlen, execlen;
1974
1975 // All these allocated blocks are not free - because we're either
1976 // going to exec, or panic when we fail.
1977
1978 // Create --exec= option: "--exec=<exename>"
1979 exec = VG_(arena_malloc)(VG_AR_CORE,
1980 VG_(strlen)( exename ) + 7/*--exec=*/ + 1/*\0*/);
1981 vg_assert(NULL != exec);
1982 VG_(sprintf)(exec, "--exec=%s", exename);
1983
1984 // Allocate space for optvar (may overestimate by counting --exec twice,
1985 // no matter)
1986 optlen = 1;
1987 for (i = 0; i < vg_argc; i++)
1988 optlen += VG_(strlen)(vg_argv[i]) + 1;
1989 optlen += VG_(strlen)(exec)+1;
1990 optvar = VG_(arena_malloc)(VG_AR_CORE, optlen);
1991
1992 // Copy all valgrind args except the old --exec (if present)
1993 // VG_CLO_SEP is the separator.
1994 cp = optvar;
1995 for (i = 1; i < vg_argc; i++) {
1996 Char *arg = vg_argv[i];
1997
1998 if (VG_(memcmp)(arg, "--exec=", 7) == 0) {
1999 // don't copy existing --exec= arg
2000 } else if (VG_(strcmp)(arg, "--") == 0) {
2001 // stop at "--"
2002 break;
2003 } else {
2004 // copy non "--exec" arg
2005 Int len = VG_(strlen)(arg);
2006 VG_(memcpy)(cp, arg, len);
2007 cp += len;
2008 *cp++ = VG_CLO_SEP;
2009 }
2010 }
2011 // Add the new --exec= option
2012 execlen = VG_(strlen)(exec);
2013 VG_(memcpy)(cp, exec, execlen);
2014 cp += execlen;
2015 *cp++ = VG_CLO_SEP;
2016
2017 *cp = '\0';
2018
2019 return optvar;
2020}
2021
2022// Build "/proc/self/fd/<execfd>".
2023Char* VG_(build_child_exename)( void )
2024{
2025 Char* exename = VG_(arena_malloc)(VG_AR_CORE, 64);
2026 vg_assert(NULL != exename);
2027 VG_(sprintf)(exename, "/proc/self/fd/%d", vgexecfd);
2028 return exename;
2029}
2030
sewardjde4a1d02002-03-22 01:27:54 +00002031
nethercote71980f02004-01-24 18:18:54 +00002032/*====================================================================*/
2033/*=== File descriptor setup ===*/
2034/*====================================================================*/
2035
2036static void setup_file_descriptors(void)
2037{
2038 struct vki_rlimit rl;
2039
2040 /* Get the current file descriptor limits. */
2041 if (VG_(getrlimit)(VKI_RLIMIT_NOFILE, &rl) < 0) {
2042 rl.rlim_cur = 1024;
2043 rl.rlim_max = 1024;
2044 }
2045
2046 /* Work out where to move the soft limit to. */
2047 if (rl.rlim_cur + VG_N_RESERVED_FDS <= rl.rlim_max) {
2048 rl.rlim_cur = rl.rlim_cur + VG_N_RESERVED_FDS;
2049 } else {
2050 rl.rlim_cur = rl.rlim_max;
2051 }
2052
2053 /* Reserve some file descriptors for our use. */
thughesad1c9562004-06-26 11:27:52 +00002054 VG_(fd_soft_limit) = rl.rlim_cur - VG_N_RESERVED_FDS;
2055 VG_(fd_hard_limit) = rl.rlim_cur - VG_N_RESERVED_FDS;
nethercote71980f02004-01-24 18:18:54 +00002056
2057 /* Update the soft limit. */
2058 VG_(setrlimit)(VKI_RLIMIT_NOFILE, &rl);
2059
nethercotef6a1d502004-08-09 12:21:57 +00002060 if (vgexecfd != -1)
2061 vgexecfd = VG_(safe_fd)( vgexecfd );
nethercote71980f02004-01-24 18:18:54 +00002062 if (VG_(clexecfd) != -1)
2063 VG_(clexecfd) = VG_(safe_fd)( VG_(clexecfd) );
2064}
2065
2066
2067/*====================================================================*/
nethercote1d447092004-02-01 17:29:59 +00002068/*=== baseBlock: definition + setup ===*/
nethercote71980f02004-01-24 18:18:54 +00002069/*====================================================================*/
2070
nethercote71980f02004-01-24 18:18:54 +00002071Int VGOFF_(helper_undefined_instruction) = INVALID_OFFSET;
2072
2073/* MAX_NONCOMPACT_HELPERS can be increased easily. If MAX_COMPACT_HELPERS is
2074 * increased too much, they won't really be compact any more... */
2075#define MAX_COMPACT_HELPERS 8
2076#define MAX_NONCOMPACT_HELPERS 50
2077
nethercote81f9a6f2004-08-03 15:45:46 +00002078/* For storing tool-specific helpers, determined at runtime. The addr
2079 * and offset arrays together form a (addr, offset) map that allows a
2080 * helper's baseBlock offset to be computed from its address. It's done
2081 * like this so CCALLs can use the function address rather than having to
2082 * muck around with offsets. */
2083static UInt VG_(n_compact_helpers) = 0;
2084static UInt VG_(n_noncompact_helpers) = 0;
2085static Addr VG_(compact_helper_addrs) [MAX_COMPACT_HELPERS];
2086static Int VG_(compact_helper_offsets)[MAX_COMPACT_HELPERS];
2087static Addr VG_(noncompact_helper_addrs) [MAX_NONCOMPACT_HELPERS];
2088static Int VG_(noncompact_helper_offsets)[MAX_NONCOMPACT_HELPERS];
nethercote71980f02004-01-24 18:18:54 +00002089
2090/* This is the actual defn of baseblock. */
2091UInt VG_(baseBlock)[VG_BASEBLOCK_WORDS];
2092
nethercote71980f02004-01-24 18:18:54 +00002093/* Words. */
2094static Int baB_off = 0;
2095
2096
nethercote71980f02004-01-24 18:18:54 +00002097/* Returns the offset, in words. */
nethercote2e05c332004-09-06 16:43:37 +00002098Int VG_(alloc_BaB) ( Int words )
sewardjde4a1d02002-03-22 01:27:54 +00002099{
nethercote71980f02004-01-24 18:18:54 +00002100 Int off = baB_off;
2101 baB_off += words;
2102 if (baB_off >= VG_BASEBLOCK_WORDS)
nethercote2e05c332004-09-06 16:43:37 +00002103 VG_(core_panic)( "VG_(alloc_BaB): baseBlock is too small");
sewardjde4a1d02002-03-22 01:27:54 +00002104
nethercote71980f02004-01-24 18:18:54 +00002105 return off;
sewardjde4a1d02002-03-22 01:27:54 +00002106}
2107
nethercote71980f02004-01-24 18:18:54 +00002108/* Align offset, in *bytes* */
nethercote2e05c332004-09-06 16:43:37 +00002109void VG_(align_BaB) ( UInt align )
njn25e49d8e72002-09-23 09:36:25 +00002110{
nethercote71980f02004-01-24 18:18:54 +00002111 vg_assert(2 == align || 4 == align || 8 == align || 16 == align);
2112 baB_off += (align-1);
2113 baB_off &= ~(align-1);
njn25e49d8e72002-09-23 09:36:25 +00002114}
2115
nethercote71980f02004-01-24 18:18:54 +00002116/* Allocate 1 word in baseBlock and set it to the given value. */
nethercote2e05c332004-09-06 16:43:37 +00002117Int VG_(alloc_BaB_1_set) ( Addr a )
njn25e49d8e72002-09-23 09:36:25 +00002118{
nethercote2e05c332004-09-06 16:43:37 +00002119 Int off = VG_(alloc_BaB)(1);
nethercote71980f02004-01-24 18:18:54 +00002120 VG_(baseBlock)[off] = (UInt)a;
2121 return off;
njn25e49d8e72002-09-23 09:36:25 +00002122}
2123
nethercote71980f02004-01-24 18:18:54 +00002124/* Registers a function in compact_helper_addrs; compact_helper_offsets is
2125 filled in later. */
2126void VG_(register_compact_helper)(Addr a)
sewardjde4a1d02002-03-22 01:27:54 +00002127{
nethercote71980f02004-01-24 18:18:54 +00002128 if (MAX_COMPACT_HELPERS <= VG_(n_compact_helpers)) {
2129 VG_(printf)("Can only register %d compact helpers\n",
2130 MAX_COMPACT_HELPERS);
2131 VG_(core_panic)("Too many compact helpers registered");
2132 }
2133 VG_(compact_helper_addrs)[VG_(n_compact_helpers)] = a;
2134 VG_(n_compact_helpers)++;
2135}
2136
2137/* Registers a function in noncompact_helper_addrs; noncompact_helper_offsets
2138 * is filled in later.
2139 */
2140void VG_(register_noncompact_helper)(Addr a)
2141{
2142 if (MAX_NONCOMPACT_HELPERS <= VG_(n_noncompact_helpers)) {
2143 VG_(printf)("Can only register %d non-compact helpers\n",
2144 MAX_NONCOMPACT_HELPERS);
2145 VG_(printf)("Try increasing MAX_NON_COMPACT_HELPERS\n");
2146 VG_(core_panic)("Too many non-compact helpers registered");
2147 }
2148 VG_(noncompact_helper_addrs)[VG_(n_noncompact_helpers)] = a;
2149 VG_(n_noncompact_helpers)++;
2150}
2151
nethercote996901a2004-08-03 13:29:09 +00002152/* Allocate offsets in baseBlock for the tool helpers */
nethercote71980f02004-01-24 18:18:54 +00002153static
2154void assign_helpers_in_baseBlock(UInt n, Int offsets[], Addr addrs[])
2155{
2156 UInt i;
2157 for (i = 0; i < n; i++)
nethercote2e05c332004-09-06 16:43:37 +00002158 offsets[i] = VG_(alloc_BaB_1_set)( addrs[i] );
nethercote71980f02004-01-24 18:18:54 +00002159}
2160
2161Bool VG_(need_to_handle_esp_assignment)(void)
2162{
2163 return ( VG_(defined_new_mem_stack_4)() ||
2164 VG_(defined_die_mem_stack_4)() ||
2165 VG_(defined_new_mem_stack_8)() ||
2166 VG_(defined_die_mem_stack_8)() ||
2167 VG_(defined_new_mem_stack_12)() ||
2168 VG_(defined_die_mem_stack_12)() ||
2169 VG_(defined_new_mem_stack_16)() ||
2170 VG_(defined_die_mem_stack_16)() ||
2171 VG_(defined_new_mem_stack_32)() ||
2172 VG_(defined_die_mem_stack_32)() ||
2173 VG_(defined_new_mem_stack)() ||
2174 VG_(defined_die_mem_stack)()
2175 );
2176}
2177
nethercote2e05c332004-09-06 16:43:37 +00002178// The low/high split is for x86, so that the more common helpers can be
2179// in the first 128 bytes of the start, which allows the use of a more
2180// compact addressing mode.
nethercote71980f02004-01-24 18:18:54 +00002181static void init_baseBlock ( Addr client_eip, Addr esp_at_startup )
2182{
nethercote2e05c332004-09-06 16:43:37 +00002183 VGA_(init_low_baseBlock)(client_eip, esp_at_startup);
nethercote71980f02004-01-24 18:18:54 +00002184
nethercote71980f02004-01-24 18:18:54 +00002185 /* Allocate slots for compact helpers */
2186 assign_helpers_in_baseBlock(VG_(n_compact_helpers),
2187 VG_(compact_helper_offsets),
2188 VG_(compact_helper_addrs));
2189
nethercote2e05c332004-09-06 16:43:37 +00002190 VGA_(init_high_baseBlock)(client_eip, esp_at_startup);
fitzhardingef0046f22003-12-18 02:39:22 +00002191
nethercote71980f02004-01-24 18:18:54 +00002192#define REG(kind, size) \
2193 if (VG_(defined_##kind##_mem_stack##size)()) \
2194 VG_(register_noncompact_helper)( \
2195 (Addr) VG_(tool_interface).track_##kind##_mem_stack##size );
2196 REG(new, _8);
2197 REG(new, _12);
2198 REG(new, _16);
2199 REG(new, _32);
2200 REG(new, );
2201 REG(die, _8);
2202 REG(die, _12);
2203 REG(die, _16);
2204 REG(die, _32);
2205 REG(die, );
2206#undef REG
fitzhardingef0046f22003-12-18 02:39:22 +00002207
nethercote71980f02004-01-24 18:18:54 +00002208 if (VG_(need_to_handle_esp_assignment)())
2209 VG_(register_noncompact_helper)((Addr) VG_(unknown_esp_update));
fitzhardingeb791a192003-12-18 07:22:44 +00002210
nethercote2e05c332004-09-06 16:43:37 +00002211 VGOFF_(helper_undefined_instruction)
2212 = VG_(alloc_BaB_1_set)( (Addr) & VG_(helper_undefined_instruction));
sewardjde4a1d02002-03-22 01:27:54 +00002213
nethercote71980f02004-01-24 18:18:54 +00002214 /* Allocate slots for noncompact helpers */
2215 assign_helpers_in_baseBlock(VG_(n_noncompact_helpers),
2216 VG_(noncompact_helper_offsets),
2217 VG_(noncompact_helper_addrs));
2218}
sewardjde4a1d02002-03-22 01:27:54 +00002219
nethercote81f9a6f2004-08-03 15:45:46 +00002220// Finds the baseBlock offset of a tool-specified helper.
2221// Searches through compacts first, then non-compacts.
2222Int VG_(helper_offset)(Addr a)
2223{
2224 UInt i;
2225 Char buf[100];
2226
2227 for (i = 0; i < VG_(n_compact_helpers); i++)
2228 if (VG_(compact_helper_addrs)[i] == a)
2229 return VG_(compact_helper_offsets)[i];
2230 for (i = 0; i < VG_(n_noncompact_helpers); i++)
2231 if (VG_(noncompact_helper_addrs)[i] == a)
2232 return VG_(noncompact_helper_offsets)[i];
2233
2234 /* Shouldn't get here */
2235 VG_(get_fnname) ( a, buf, 100 );
2236
2237 VG_(printf)(
2238 "\nCouldn't find offset of helper from its address (%p: %s).\n"
2239 "A helper function probably used hasn't been registered?\n\n", a, buf);
2240
2241 VG_(printf)(" compact helpers: ");
2242 for (i = 0; i < VG_(n_compact_helpers); i++)
2243 VG_(printf)("%p ", VG_(compact_helper_addrs)[i]);
2244
2245 VG_(printf)("\n non-compact helpers: ");
2246 for (i = 0; i < VG_(n_noncompact_helpers); i++)
2247 VG_(printf)("%p ", VG_(noncompact_helper_addrs)[i]);
2248
2249 VG_(printf)("\n");
2250 VG_(skin_panic)("Unfound helper");
2251}
2252
sewardj5f07b662002-04-23 16:52:51 +00002253
nethercote71980f02004-01-24 18:18:54 +00002254/*====================================================================*/
nethercote71980f02004-01-24 18:18:54 +00002255/*=== Initialise program data/text, etc. ===*/
2256/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +00002257
nethercote71980f02004-01-24 18:18:54 +00002258static void build_valgrind_map_callback
2259 ( Addr start, UInt size, Char rr, Char ww, Char xx,
2260 UInt dev, UInt ino, ULong foffset, const UChar* filename )
sewardjde4a1d02002-03-22 01:27:54 +00002261{
nethercote71980f02004-01-24 18:18:54 +00002262 UInt prot = 0;
2263 UInt flags = SF_MMAP|SF_NOSYMS;
2264 Bool is_stack_segment;
2265
2266 is_stack_segment =
2267 (start == VG_(clstk_base) && (start+size) == VG_(clstk_end));
2268
2269 /* Only record valgrind mappings for now, without loading any
2270 symbols. This is so we know where the free space is before we
2271 start allocating more memory (note: heap is OK, it's just mmap
2272 which is the problem here). */
nethercote820bd8c2004-09-07 23:04:49 +00002273 if (start >= VG_(valgrind_base) && (start+size-1) <= VG_(valgrind_last)) {
nethercote71980f02004-01-24 18:18:54 +00002274 flags |= SF_VALGRIND;
2275 VG_(map_file_segment)(start, size, prot, flags, dev, ino, foffset, filename);
2276 }
sewardjde4a1d02002-03-22 01:27:54 +00002277}
2278
nethercote71980f02004-01-24 18:18:54 +00002279// Global var used to pass local data to callback
2280Addr esp_at_startup___global_arg = 0;
sewardjde4a1d02002-03-22 01:27:54 +00002281
nethercote71980f02004-01-24 18:18:54 +00002282static void build_segment_map_callback
2283 ( Addr start, UInt size, Char rr, Char ww, Char xx,
2284 UInt dev, UInt ino, ULong foffset, const UChar* filename )
sewardj45b672d2003-07-25 19:58:11 +00002285{
nethercote71980f02004-01-24 18:18:54 +00002286 UInt prot = 0;
2287 UInt flags;
2288 Bool is_stack_segment;
2289 Addr r_esp;
sewardj45b672d2003-07-25 19:58:11 +00002290
nethercote71980f02004-01-24 18:18:54 +00002291 is_stack_segment
2292 = (start == VG_(clstk_base) && (start+size) == VG_(clstk_end));
fitzhardinge98abfc72003-12-16 02:05:15 +00002293
nethercote71980f02004-01-24 18:18:54 +00002294 if (rr == 'r') prot |= VKI_PROT_READ;
2295 if (ww == 'w') prot |= VKI_PROT_WRITE;
2296 if (xx == 'x') prot |= VKI_PROT_EXEC;
fitzhardinge98abfc72003-12-16 02:05:15 +00002297
nethercote71980f02004-01-24 18:18:54 +00002298 if (is_stack_segment)
2299 flags = SF_STACK | SF_GROWDOWN;
2300 else
2301 flags = SF_EXEC|SF_MMAP;
fitzhardinge98abfc72003-12-16 02:05:15 +00002302
nethercote71980f02004-01-24 18:18:54 +00002303 if (filename != NULL)
2304 flags |= SF_FILE;
fitzhardinge98abfc72003-12-16 02:05:15 +00002305
nethercote820bd8c2004-09-07 23:04:49 +00002306 if (start >= VG_(valgrind_base) && (start+size-1) <= VG_(valgrind_last))
nethercote71980f02004-01-24 18:18:54 +00002307 flags |= SF_VALGRIND;
fitzhardinge98abfc72003-12-16 02:05:15 +00002308
nethercote71980f02004-01-24 18:18:54 +00002309 VG_(map_file_segment)(start, size, prot, flags, dev, ino, foffset, filename);
fitzhardinge98abfc72003-12-16 02:05:15 +00002310
nethercote71980f02004-01-24 18:18:54 +00002311 if (VG_(is_client_addr)(start) && VG_(is_client_addr)(start+size-1))
2312 VG_TRACK( new_mem_startup, start, size, rr=='r', ww=='w', xx=='x' );
sewardj3e1eb1f2002-05-18 13:14:17 +00002313
nethercote71980f02004-01-24 18:18:54 +00002314 /* If this is the stack segment mark all below %esp as noaccess. */
2315 r_esp = esp_at_startup___global_arg;
2316 vg_assert(0 != r_esp);
2317 if (is_stack_segment) {
2318 if (0)
2319 VG_(message)(Vg_DebugMsg, "invalidating stack area: %x .. %x",
2320 start,r_esp);
2321 VG_TRACK( die_mem_stack, start, r_esp-start );
sewardjde4a1d02002-03-22 01:27:54 +00002322 }
sewardjde4a1d02002-03-22 01:27:54 +00002323}
2324
2325
nethercote71980f02004-01-24 18:18:54 +00002326/*====================================================================*/
2327/*=== Sanity check machinery (permanently engaged) ===*/
2328/*====================================================================*/
njn25e49d8e72002-09-23 09:36:25 +00002329
2330/* A fast sanity check -- suitable for calling circa once per
2331 millisecond. */
2332
nethercote885dd912004-08-03 23:14:00 +00002333void VG_(sanity_check_general) ( Bool force_expensive )
njn25e49d8e72002-09-23 09:36:25 +00002334{
njn37cea302002-09-30 11:24:00 +00002335 VGP_PUSHCC(VgpCoreCheapSanity);
2336
nethercote27fec902004-06-16 21:26:32 +00002337 if (VG_(clo_sanity_level) < 1) return;
njn25e49d8e72002-09-23 09:36:25 +00002338
2339 /* --- First do all the tests that we can do quickly. ---*/
2340
nethercote297effd2004-08-02 15:07:57 +00002341 sanity_fast_count++;
njn25e49d8e72002-09-23 09:36:25 +00002342
njn25e49d8e72002-09-23 09:36:25 +00002343 /* Check stuff pertaining to the memory check system. */
2344
2345 /* Check that nobody has spuriously claimed that the first or
2346 last 16 pages of memory have become accessible [...] */
njn37cea302002-09-30 11:24:00 +00002347 if (VG_(needs).sanity_checks) {
2348 VGP_PUSHCC(VgpSkinCheapSanity);
njn25e49d8e72002-09-23 09:36:25 +00002349 vg_assert(SK_(cheap_sanity_check)());
njn37cea302002-09-30 11:24:00 +00002350 VGP_POPCC(VgpSkinCheapSanity);
2351 }
njn25e49d8e72002-09-23 09:36:25 +00002352
2353 /* --- Now some more expensive checks. ---*/
2354
2355 /* Once every 25 times, check some more expensive stuff. */
2356 if ( force_expensive
nethercote27fec902004-06-16 21:26:32 +00002357 || VG_(clo_sanity_level) > 1
nethercote297effd2004-08-02 15:07:57 +00002358 || (VG_(clo_sanity_level) == 1 && (sanity_fast_count % 25) == 0)) {
njn25e49d8e72002-09-23 09:36:25 +00002359
njn37cea302002-09-30 11:24:00 +00002360 VGP_PUSHCC(VgpCoreExpensiveSanity);
nethercote297effd2004-08-02 15:07:57 +00002361 sanity_slow_count++;
njn25e49d8e72002-09-23 09:36:25 +00002362
nethercote885dd912004-08-03 23:14:00 +00002363 VG_(sanity_check_proxy)();
jsgf855d93d2003-10-13 22:26:55 +00002364
njn25e49d8e72002-09-23 09:36:25 +00002365# if 0
2366 { void zzzmemscan(void); zzzmemscan(); }
2367# endif
2368
nethercote297effd2004-08-02 15:07:57 +00002369 if ((sanity_fast_count % 250) == 0)
nethercote92e7b7f2004-08-07 17:52:25 +00002370 VG_(sanity_check_tt_tc)();
njn25e49d8e72002-09-23 09:36:25 +00002371
2372 if (VG_(needs).sanity_checks) {
njn37cea302002-09-30 11:24:00 +00002373 VGP_PUSHCC(VgpSkinExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002374 vg_assert(SK_(expensive_sanity_check)());
njn37cea302002-09-30 11:24:00 +00002375 VGP_POPCC(VgpSkinExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002376 }
2377 /*
nethercote297effd2004-08-02 15:07:57 +00002378 if ((sanity_fast_count % 500) == 0) VG_(mallocSanityCheckAll)();
njn25e49d8e72002-09-23 09:36:25 +00002379 */
njn37cea302002-09-30 11:24:00 +00002380 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002381 }
2382
nethercote27fec902004-06-16 21:26:32 +00002383 if (VG_(clo_sanity_level) > 1) {
njn37cea302002-09-30 11:24:00 +00002384 VGP_PUSHCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002385 /* Check sanity of the low-level memory manager. Note that bugs
2386 in the client's code can cause this to fail, so we don't do
2387 this check unless specially asked for. And because it's
2388 potentially very expensive. */
nethercote885dd912004-08-03 23:14:00 +00002389 VG_(sanity_check_malloc_all)();
njn37cea302002-09-30 11:24:00 +00002390 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002391 }
njn37cea302002-09-30 11:24:00 +00002392 VGP_POPCC(VgpCoreCheapSanity);
njn25e49d8e72002-09-23 09:36:25 +00002393}
nethercote71980f02004-01-24 18:18:54 +00002394
2395
2396/*====================================================================*/
2397/*=== main() ===*/
2398/*====================================================================*/
2399
nethercotec314eba2004-07-15 12:59:41 +00002400/*
2401 This code decides on the layout of the client and Valgrind address
nethercote996901a2004-08-03 13:29:09 +00002402 spaces, loads valgrind.so and the tool.so into the valgrind part,
nethercotec314eba2004-07-15 12:59:41 +00002403 loads the client executable (and the dynamic linker, if necessary)
2404 into the client part, and calls into Valgrind proper.
2405
2406 The code is careful not to allow spurious mappings to appear in the
2407 wrong parts of the address space. In particular, to make sure
2408 dlopen puts things in the right place, it will pad out the forbidden
2409 chunks of address space so that dlopen is forced to put things where
2410 we want them.
2411
2412 The memory map it creates is:
2413
2414 CLIENT_BASE +-------------------------+
2415 | client address space |
2416 : :
2417 : :
2418 | client stack |
2419 client_end +-------------------------+
2420 | redzone |
2421 shadow_base +-------------------------+
2422 | |
nethercote996901a2004-08-03 13:29:09 +00002423 : shadow memory for tools :
nethercotec314eba2004-07-15 12:59:41 +00002424 | (may be 0 sized) |
2425 shadow_end +-------------------------+
nethercotec314eba2004-07-15 12:59:41 +00002426 valgrind_base +-------------------------+
2427 | kickstart executable |
2428 | valgrind heap vvvvvvvvv| (barely used)
2429 - -
2430 | valgrind .so files |
2431 | and mappings |
2432 - -
2433 | valgrind stack ^^^^^^^^^|
nethercote820bd8c2004-09-07 23:04:49 +00002434 valgrind_last +-------------------------+
nethercotec314eba2004-07-15 12:59:41 +00002435 : kernel :
2436
2437 Nb: Before we can do general allocations with VG_(arena_malloc)() and
2438 VG_(mmap)(), we need to build the segment skip-list, so we know where
2439 we can put things. However, building that structure requires
2440 allocating memory. So we need to a bootstrapping process. It's done
2441 by making VG_(arena_malloc)() have a special static superblock that's
2442 used for the first 1MB's worth of allocations. This is enough to
2443 build the segment skip-list.
2444*/
2445
nethercote31779c72004-07-30 21:50:15 +00002446static int prmap(char *start, char *end, const char *perm, off_t off,
2447 int maj, int min, int ino, void* dummy) {
thughes4ad52d02004-06-27 17:37:21 +00002448 printf("mapping %10p-%10p %s %02x:%02x %d\n",
2449 start, end, perm, maj, min, ino);
2450 return True;
2451}
2452
nethercote71980f02004-01-24 18:18:54 +00002453int main(int argc, char **argv)
2454{
2455 char **cl_argv;
2456 const char *tool = NULL;
2457 const char *exec = NULL;
2458 char *preload; /* tool-specific LD_PRELOAD .so */
2459 char **env;
nethercote6c999f22004-01-31 22:55:15 +00002460 Int need_help = 0; // 0 = no, 1 = --help, 2 = --help-debug
nethercote71980f02004-01-24 18:18:54 +00002461 struct exeinfo info;
2462 ToolInfo *toolinfo = NULL;
2463 void *tool_dlhandle;
2464 Addr client_eip;
2465 Addr esp_at_startup; /* client's %esp at the point we gained control. */
2466 UInt * client_auxv;
2467 VgSchedReturnCode src;
nethercote47dd12c2004-06-22 14:18:42 +00002468 Int exitcode = 0;
nethercote238a3c32004-08-09 13:13:31 +00002469 Int fatal_sigNo = -1;
fitzhardingeb50068f2004-02-24 23:42:55 +00002470 vki_rlimit zero = { 0, 0 };
nethercote31779c72004-07-30 21:50:15 +00002471 Int padfile;
nethercote759dda32004-08-07 18:16:56 +00002472 ThreadId last_run_tid = 0; // Last thread the scheduler ran.
2473
nethercote71980f02004-01-24 18:18:54 +00002474
2475 //============================================================
2476 // Nb: startup is complex. Prerequisites are shown at every step.
2477 //
2478 // *** Be very careful when messing with the order ***
2479 //============================================================
2480
nethercotef4928da2004-06-15 10:54:40 +00002481 //============================================================
2482 // Command line argument handling order:
2483 // * If --help/--help-debug are present, show usage message
2484 // (if --tool is also present, that includes the tool-specific usage)
2485 // * Then, if --tool is missing, abort with error msg
2486 // * Then, if client is missing, abort with error msg
2487 // * Then, if any cmdline args are bad, abort with error msg
2488 //============================================================
2489
fitzhardingeb50068f2004-02-24 23:42:55 +00002490 // Get the current process datasize rlimit, and set it to zero.
2491 // This prevents any internal uses of brk() from having any effect.
2492 // We remember the old value so we can restore it on exec, so that
2493 // child processes will have a reasonable brk value.
2494 VG_(getrlimit)(VKI_RLIMIT_DATA, &VG_(client_rlimit_data));
2495 zero.rlim_max = VG_(client_rlimit_data).rlim_max;
2496 VG_(setrlimit)(VKI_RLIMIT_DATA, &zero);
2497
nethercote71980f02004-01-24 18:18:54 +00002498 //--------------------------------------------------------------
2499 // Check we were launched by stage1
nethercotec314eba2004-07-15 12:59:41 +00002500 // p: n/a
nethercote71980f02004-01-24 18:18:54 +00002501 //--------------------------------------------------------------
nethercote31779c72004-07-30 21:50:15 +00002502 padfile = scan_auxv();
nethercote71980f02004-01-24 18:18:54 +00002503
2504 if (0) {
nethercote71980f02004-01-24 18:18:54 +00002505 printf("========== main() ==========\n");
nethercote31779c72004-07-30 21:50:15 +00002506 foreach_map(prmap, /*dummy*/NULL);
nethercote71980f02004-01-24 18:18:54 +00002507 }
2508
2509 //--------------------------------------------------------------
2510 // Look for alternative libdir
2511 // p: n/a
2512 //--------------------------------------------------------------
2513 { char *cp = getenv(VALGRINDLIB);
2514 if (cp != NULL)
2515 VG_(libdir) = cp;
2516 }
2517
2518 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002519 // Get valgrind args + client args (inc. from VALGRIND_OPTS/.valgrindrc).
2520 // Pre-process the command line.
2521 // p: n/a
2522 //--------------------------------------------------------------
nethercotef6a1d502004-08-09 12:21:57 +00002523 get_command_line(argc, argv, &vg_argc, &vg_argv, &cl_argv);
nethercote71980f02004-01-24 18:18:54 +00002524 pre_process_cmd_line_options(&need_help, &tool, &exec);
2525
2526 //==============================================================
2527 // Nb: once a tool is specified, the tool.so must be loaded even if
2528 // they specified --help or didn't specify a client program.
2529 //==============================================================
2530
2531 //--------------------------------------------------------------
2532 // With client padded out, map in tool
nethercote71980f02004-01-24 18:18:54 +00002533 // p: set-libdir [for VG_(libdir)]
2534 // p: pre_process_cmd_line_options() [for 'tool']
2535 //--------------------------------------------------------------
2536 load_tool(tool, &tool_dlhandle, &toolinfo, &preload);
2537
2538 //==============================================================
2539 // Can use VG_(malloc)() and VG_(arena_malloc)() only after load_tool()
nethercotec314eba2004-07-15 12:59:41 +00002540 // -- redzone size is now set. This is checked by vg_malloc2.c.
nethercote71980f02004-01-24 18:18:54 +00002541 //==============================================================
2542
2543 //--------------------------------------------------------------
2544 // Finalise address space layout
nethercote31779c72004-07-30 21:50:15 +00002545 // p: load_tool() [for 'toolinfo']
nethercote71980f02004-01-24 18:18:54 +00002546 //--------------------------------------------------------------
nethercote31779c72004-07-30 21:50:15 +00002547 layout_remaining_space( (Addr) & argc, toolinfo->shadow_ratio );
nethercote71980f02004-01-24 18:18:54 +00002548
2549 //--------------------------------------------------------------
2550 // Load client executable, finding in $PATH if necessary
nethercote71980f02004-01-24 18:18:54 +00002551 // p: pre_process_cmd_line_options() [for 'exec', 'need_help']
2552 // p: layout_remaining_space [so there's space]
2553 //--------------------------------------------------------------
nethercotef4928da2004-06-15 10:54:40 +00002554 load_client(cl_argv, exec, need_help, &info, &client_eip);
nethercote71980f02004-01-24 18:18:54 +00002555
2556 //--------------------------------------------------------------
2557 // Everything in place, unpad us
2558 // p: layout_remaining_space() [everything must be mapped in before now]
2559 // p: load_client() [ditto]
2560 //--------------------------------------------------------------
nethercote31779c72004-07-30 21:50:15 +00002561 as_unpad((void *)VG_(shadow_end), (void *)~0, padfile);
2562 as_closepadfile(padfile); // no more padding
nethercote71980f02004-01-24 18:18:54 +00002563
2564 //--------------------------------------------------------------
2565 // Set up client's environment
2566 // p: set-libdir [for VG_(libdir)]
2567 // p: load_tool() [for 'preload']
2568 //--------------------------------------------------------------
2569 env = fix_environment(environ, preload);
2570
2571 //--------------------------------------------------------------
nethercote5ee67ca2004-06-22 14:00:09 +00002572 // Setup client stack, eip, and VG_(client_arg[cv])
nethercote71980f02004-01-24 18:18:54 +00002573 // p: load_client() [for 'info']
2574 // p: fix_environment() [for 'env']
2575 //--------------------------------------------------------------
2576 esp_at_startup = setup_client_stack(cl_argv, env, &info, &client_auxv);
2577
2578 if (0)
nethercote6a27d832004-09-07 10:17:02 +00002579 printf("entry=%p client esp=%p vg_argc=%d brkbase=%p\n",
2580 (void*)client_eip, (void*)esp_at_startup, vg_argc,
2581 (void*)VG_(brk_base));
nethercote71980f02004-01-24 18:18:54 +00002582
2583 //==============================================================
2584 // Finished setting up operating environment. Now initialise
2585 // Valgrind. (This is where the old VG_(main)() started.)
2586 //==============================================================
2587
2588 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002589 // atfork
2590 // p: n/a
2591 //--------------------------------------------------------------
2592 VG_(atfork)(NULL, NULL, newpid);
2593 newpid(VG_INVALID_THREADID);
2594
2595 //--------------------------------------------------------------
2596 // setup file descriptors
2597 // p: n/a
2598 //--------------------------------------------------------------
2599 setup_file_descriptors();
2600
2601 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002602 // Read /proc/self/maps into a buffer
2603 // p: all memory layout, environment setup [so memory maps are right]
2604 //--------------------------------------------------------------
2605 VG_(read_procselfmaps)();
2606
2607 //--------------------------------------------------------------
2608 // Build segment map (Valgrind segments only)
2609 // p: read proc/self/maps
2610 // p: sk_pre_clo_init() [to setup new_mem_startup tracker]
2611 //--------------------------------------------------------------
2612 VG_(parse_procselfmaps) ( build_valgrind_map_callback );
2613
2614 //==============================================================
2615 // Can use VG_(arena_malloc)() with non-CORE arena after segments set up
2616 //==============================================================
2617
2618 //--------------------------------------------------------------
2619 // Init tool: pre_clo_init, process cmd line, post_clo_init
2620 // p: setup_client_stack() [for 'VG_(client_arg[cv]']
2621 // p: load_tool() [for 'tool']
2622 // p: setup_file_descriptors() [for 'VG_(fd_xxx_limit)']
2623 // p: parse_procselfmaps [so VG segments are setup so tool can
2624 // call VG_(malloc)]
nethercote71980f02004-01-24 18:18:54 +00002625 //--------------------------------------------------------------
2626 (*toolinfo->sk_pre_clo_init)();
2627 VG_(tool_init_dlsym)(tool_dlhandle);
2628 VG_(sanity_check_needs)();
2629
nethercotef4928da2004-06-15 10:54:40 +00002630 // If --tool and --help/--help-debug was given, now give the core+tool
2631 // help message
nethercotef4928da2004-06-15 10:54:40 +00002632 if (need_help) {
2633 usage(/*--help-debug?*/2 == need_help);
2634 }
nethercotec314eba2004-07-15 12:59:41 +00002635 process_cmd_line_options(client_auxv, tool);
2636
2637 SK_(post_clo_init)();
nethercotef4928da2004-06-15 10:54:40 +00002638
2639 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002640 // Build segment map (all segments)
2641 // p: setup_client_stack() [for 'esp_at_startup']
2642 // p: init tool [for 'new_mem_startup']
nethercote71980f02004-01-24 18:18:54 +00002643 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002644 esp_at_startup___global_arg = esp_at_startup;
2645 VG_(parse_procselfmaps) ( build_segment_map_callback ); /* everything */
2646 esp_at_startup___global_arg = 0;
2647
2648 //--------------------------------------------------------------
nethercotef84f6952004-07-15 14:58:33 +00002649 // Protect client trampoline page (which is also sysinfo stuff)
2650 // p: segment stuff [otherwise get seg faults...]
nethercotec314eba2004-07-15 12:59:41 +00002651 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002652 VG_(mprotect)( (void *)VG_(client_trampoline_code),
2653 VG_(trampoline_code_length), VKI_PROT_READ|VKI_PROT_EXEC );
2654
2655 //==============================================================
2656 // Can use VG_(map)() after segments set up
2657 //==============================================================
nethercote71980f02004-01-24 18:18:54 +00002658
2659 //--------------------------------------------------------------
2660 // Allow GDB attach
2661 // p: process_cmd_line_options() [for VG_(clo_wait_for_gdb)]
2662 //--------------------------------------------------------------
2663 /* Hook to delay things long enough so we can get the pid and
2664 attach GDB in another shell. */
2665 if (VG_(clo_wait_for_gdb)) {
2666 VG_(printf)("pid=%d\n", VG_(getpid)());
2667 /* do "jump *$eip" to skip this in gdb */
2668 VG_(do_syscall)(__NR_pause);
2669 }
2670
2671 //--------------------------------------------------------------
nethercote1d447092004-02-01 17:29:59 +00002672 // Set up baseBlock
nethercote71980f02004-01-24 18:18:54 +00002673 // p: {pre,post}_clo_init() [for tool helper registration]
2674 // load_client() [for 'client_eip']
2675 // setup_client_stack() [for 'esp_at_startup']
2676 //--------------------------------------------------------------
2677 init_baseBlock(client_eip, esp_at_startup);
2678
2679 //--------------------------------------------------------------
2680 // Search for file descriptors that are inherited from our parent
2681 // p: process_cmd_line_options [for VG_(clo_track_fds)]
2682 //--------------------------------------------------------------
2683 if (VG_(clo_track_fds))
2684 VG_(init_preopened_fds)();
2685
2686 //--------------------------------------------------------------
2687 // Initialise the scheduler
2688 // p: init_baseBlock() [baseBlock regs copied into VG_(threads)[1]]
2689 // p: setup_file_descriptors() [else VG_(safe_fd)() breaks]
2690 //--------------------------------------------------------------
2691 VG_(scheduler_init)();
2692
2693 //--------------------------------------------------------------
2694 // Set up the ProxyLWP machinery
2695 // p: VG_(scheduler_init)()? [XXX: subtle dependency?]
nethercote71980f02004-01-24 18:18:54 +00002696 //--------------------------------------------------------------
2697 VG_(proxy_init)();
2698
2699 //--------------------------------------------------------------
2700 // Initialise the signal handling subsystem
2701 // p: VG_(atfork)(NULL, NULL, newpid) [else problems with sigmasks]
2702 // p: VG_(proxy_init)() [else breaks...]
2703 //--------------------------------------------------------------
2704 // Nb: temporarily parks the saved blocking-mask in saved_sigmask.
2705 VG_(sigstartup_actions)();
2706
2707 //--------------------------------------------------------------
2708 // Perhaps we're profiling Valgrind?
2709 // p: process_cmd_line_options() [for VG_(clo_profile)]
2710 // p: others?
2711 //
2712 // XXX: this seems to be broken? It always says the tool wasn't built
2713 // for profiling; vg_profile.c's functions don't seem to be overriding
2714 // vg_dummy_profile.c's?
2715 //
2716 // XXX: want this as early as possible. Looking for --profile
2717 // in pre_process_cmd_line_options() could get it earlier.
2718 //--------------------------------------------------------------
2719 if (VG_(clo_profile))
2720 VGP_(init_profiling)();
2721
2722 VGP_PUSHCC(VgpStartup);
2723
2724 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002725 // Read suppression file
2726 // p: process_cmd_line_options() [for VG_(clo_suppressions)]
2727 //--------------------------------------------------------------
2728 if (VG_(needs).core_errors || VG_(needs).skin_errors)
2729 VG_(load_suppressions)();
2730
2731 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002732 // Initialise translation table and translation cache
2733 // p: read_procselfmaps [so the anonymous mmaps for the TT/TC
2734 // aren't identified as part of the client, which would waste
2735 // > 20M of virtual address space.]
2736 //--------------------------------------------------------------
2737 VG_(init_tt_tc)();
2738
2739 //--------------------------------------------------------------
2740 // Read debug info to find glibc entry points to intercept
2741 // p: parse_procselfmaps? [XXX for debug info?]
2742 // p: init_tt_tc? [XXX ???]
2743 //--------------------------------------------------------------
2744 VG_(setup_code_redirect_table)();
2745
2746 //--------------------------------------------------------------
2747 // Verbosity message
2748 // p: end_rdtsc_calibration [so startup message is printed first]
2749 //--------------------------------------------------------------
2750 if (VG_(clo_verbosity) == 1)
2751 VG_(message)(Vg_UserMsg, "For more details, rerun with: -v");
2752 if (VG_(clo_verbosity) > 0)
2753 VG_(message)(Vg_UserMsg, "");
2754
2755 //--------------------------------------------------------------
2756 // Setup pointercheck
2757 // p: process_cmd_line_options() [for VG_(clo_pointercheck)]
2758 //--------------------------------------------------------------
nethercote775508a2004-09-07 22:38:23 +00002759 if (VG_(clo_pointercheck))
2760 VG_(clo_pointercheck) = VGA_(setup_pointercheck)();
nethercote71980f02004-01-24 18:18:54 +00002761
nethercote71980f02004-01-24 18:18:54 +00002762 //--------------------------------------------------------------
2763 // Run!
2764 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002765 VGP_POPCC(VgpStartup);
2766 VGP_PUSHCC(VgpSched);
2767
nethercote238a3c32004-08-09 13:13:31 +00002768 src = VG_(scheduler)( &exitcode, &last_run_tid, &fatal_sigNo );
nethercote71980f02004-01-24 18:18:54 +00002769
nethercote238a3c32004-08-09 13:13:31 +00002770 VGP_POPCC(VgpSched);
nethercote71980f02004-01-24 18:18:54 +00002771
2772
2773 //--------------------------------------------------------------
2774 // Finalisation: cleanup, messages, etc. Order no so important, only
2775 // affects what order the messages come.
2776 //--------------------------------------------------------------
2777 if (VG_(clo_verbosity) > 0)
2778 VG_(message)(Vg_UserMsg, "");
2779
2780 if (src == VgSrc_Deadlock) {
2781 VG_(message)(Vg_UserMsg,
2782 "Warning: pthread scheduler exited due to deadlock");
2783 }
2784
2785 /* Print out file descriptor summary and stats. */
2786 if (VG_(clo_track_fds))
nethercote3a42fb82004-08-03 18:08:50 +00002787 VG_(show_open_fds)();
nethercote71980f02004-01-24 18:18:54 +00002788
2789 if (VG_(needs).core_errors || VG_(needs).skin_errors)
2790 VG_(show_all_errors)();
2791
nethercote47dd12c2004-06-22 14:18:42 +00002792 SK_(fini)( exitcode );
nethercote71980f02004-01-24 18:18:54 +00002793
nethercote885dd912004-08-03 23:14:00 +00002794 VG_(sanity_check_general)( True /*include expensive checks*/ );
nethercote71980f02004-01-24 18:18:54 +00002795
2796 if (VG_(clo_verbosity) > 1)
nethercote3a42fb82004-08-03 18:08:50 +00002797 print_all_stats();
nethercote71980f02004-01-24 18:18:54 +00002798
nethercote71980f02004-01-24 18:18:54 +00002799 if (VG_(clo_profile))
2800 VGP_(done_profiling)();
2801
nethercote71980f02004-01-24 18:18:54 +00002802 /* We're exiting, so nuke all the threads and clean up the proxy LWPs */
2803 vg_assert(src == VgSrc_FatalSig ||
nethercote759dda32004-08-07 18:16:56 +00002804 VG_(threads)[last_run_tid].status == VgTs_Runnable ||
2805 VG_(threads)[last_run_tid].status == VgTs_WaitJoiner);
nethercote71980f02004-01-24 18:18:54 +00002806 VG_(nuke_all_threads_except)(VG_INVALID_THREADID);
2807
2808 //--------------------------------------------------------------
2809 // Exit, according to the scheduler's return code
2810 //--------------------------------------------------------------
2811 switch (src) {
2812 case VgSrc_ExitSyscall: /* the normal way out */
nethercote759dda32004-08-07 18:16:56 +00002813 vg_assert(last_run_tid > 0 && last_run_tid < VG_N_THREADS);
nethercote71980f02004-01-24 18:18:54 +00002814 VG_(proxy_shutdown)();
2815
2816 /* The thread's %EBX at the time it did __NR_exit() will hold
2817 the arg to __NR_exit(), so we just do __NR_exit() with
2818 that arg. */
nethercote47dd12c2004-06-22 14:18:42 +00002819 VG_(exit)( exitcode );
nethercote71980f02004-01-24 18:18:54 +00002820 /* NOT ALIVE HERE! */
2821 VG_(core_panic)("entered the afterlife in main() -- ExitSyscall");
2822 break; /* what the hell :) */
2823
2824 case VgSrc_Deadlock:
2825 /* Just exit now. No point in continuing. */
2826 VG_(proxy_shutdown)();
2827 VG_(exit)(0);
2828 VG_(core_panic)("entered the afterlife in main() -- Deadlock");
2829 break;
2830
nethercote71980f02004-01-24 18:18:54 +00002831 case VgSrc_FatalSig:
2832 /* We were killed by a fatal signal, so replicate the effect */
nethercote238a3c32004-08-09 13:13:31 +00002833 vg_assert(fatal_sigNo != -1);
2834 VG_(kill_self)(fatal_sigNo);
nethercote71980f02004-01-24 18:18:54 +00002835 VG_(core_panic)("main(): signal was supposed to be fatal");
2836 break;
2837
2838 default:
2839 VG_(core_panic)("main(): unexpected scheduler return code");
2840 }
2841
2842 abort();
2843}
2844
2845
sewardjde4a1d02002-03-22 01:27:54 +00002846/*--------------------------------------------------------------------*/
2847/*--- end vg_main.c ---*/
2848/*--------------------------------------------------------------------*/