blob: 183fa2ea1a15647dde2535e04e88c42b9d07ca2c [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
nethercotecf97ffb2004-09-09 13:40:31 +0000228static Int ptrace_setregs(Int pid, ThreadId tid)
229{
230 if (VG_(is_running_thread)( tid ))
231 return VGA_(ptrace_setregs_from_BB)(pid);
232 else
233 return VGA_(ptrace_setregs_from_tst)(pid, &VG_(threads)[tid].arch);
234}
235
nethercote04d0fbc2004-01-26 16:48:06 +0000236/* Start debugger and get it to attach to this process. Called if the
237 user requests this service after an error has been shown, so she can
nethercote71980f02004-01-24 18:18:54 +0000238 poke around and look at parameters, memory, etc. You can't
nethercote04d0fbc2004-01-26 16:48:06 +0000239 meaningfully get the debugger to continue the program, though; to
240 continue, quit the debugger. */
241void VG_(start_debugger) ( Int tid )
nethercote71980f02004-01-24 18:18:54 +0000242{
243 Int pid;
244
245 if ((pid = fork()) == 0) {
246 ptrace(PTRACE_TRACEME, 0, NULL, NULL);
247 VG_(kkill)(VG_(getpid)(), VKI_SIGSTOP);
248
249 } else if (pid > 0) {
nethercote71980f02004-01-24 18:18:54 +0000250 Int status;
251 Int res;
252
nethercote71980f02004-01-24 18:18:54 +0000253 if ((res = VG_(waitpid)(pid, &status, 0)) == pid &&
254 WIFSTOPPED(status) && WSTOPSIG(status) == SIGSTOP &&
nethercotecf97ffb2004-09-09 13:40:31 +0000255 ptrace_setregs(pid, tid) == 0 &&
thughes1d160052004-04-21 15:39:57 +0000256 kill(pid, SIGSTOP) == 0 &&
257 ptrace(PTRACE_DETACH, pid, NULL, 0) == 0) {
nethercote04d0fbc2004-01-26 16:48:06 +0000258 Char pidbuf[15];
259 Char file[30];
260 Char buf[100];
261 Char *bufptr;
262 Char *cmdptr;
263
264 VG_(sprintf)(pidbuf, "%d", pid);
265 VG_(sprintf)(file, "/proc/%d/fd/%d", pid, VG_(clexecfd));
266
267 bufptr = buf;
268 cmdptr = VG_(clo_db_command);
269
270 while (*cmdptr) {
271 switch (*cmdptr) {
272 case '%':
273 switch (*++cmdptr) {
274 case 'f':
275 VG_(memcpy)(bufptr, file, VG_(strlen)(file));
276 bufptr += VG_(strlen)(file);
277 cmdptr++;
278 break;
279 case 'p':
280 VG_(memcpy)(bufptr, pidbuf, VG_(strlen)(pidbuf));
281 bufptr += VG_(strlen)(pidbuf);
282 cmdptr++;
283 break;
284 default:
285 *bufptr++ = *cmdptr++;
286 break;
287 }
288 break;
289 default:
290 *bufptr++ = *cmdptr++;
291 break;
292 }
293 }
294
295 *bufptr++ = '\0';
296
297 VG_(message)(Vg_UserMsg, "starting debugger with cmd: %s", buf);
nethercote71980f02004-01-24 18:18:54 +0000298 res = VG_(system)(buf);
299 if (res == 0) {
300 VG_(message)(Vg_UserMsg, "");
301 VG_(message)(Vg_UserMsg,
nethercote04d0fbc2004-01-26 16:48:06 +0000302 "Debugger has detached. Valgrind regains control. We continue.");
nethercote71980f02004-01-24 18:18:54 +0000303 } else {
304 VG_(message)(Vg_UserMsg, "Apparently failed!");
305 VG_(message)(Vg_UserMsg, "");
306 }
307 }
308
309 VG_(kkill)(pid, VKI_SIGKILL);
310 VG_(waitpid)(pid, &status, 0);
311 }
312}
313
314
315/* Print some helpful-ish text about unimplemented things, and give
316 up. */
317void VG_(unimplemented) ( Char* msg )
318{
319 VG_(message)(Vg_UserMsg, "");
320 VG_(message)(Vg_UserMsg,
321 "Valgrind detected that your program requires");
322 VG_(message)(Vg_UserMsg,
323 "the following unimplemented functionality:");
324 VG_(message)(Vg_UserMsg, " %s", msg);
325 VG_(message)(Vg_UserMsg,
326 "This may be because the functionality is hard to implement,");
327 VG_(message)(Vg_UserMsg,
328 "or because no reasonable program would behave this way,");
329 VG_(message)(Vg_UserMsg,
330 "or because nobody has yet needed it. In any case, let us know at");
331 VG_(message)(Vg_UserMsg,
332 "%s and/or try to work around the problem, if you can.", VG_BUGS_TO);
333 VG_(message)(Vg_UserMsg,
334 "");
335 VG_(message)(Vg_UserMsg,
336 "Valgrind has to exit now. Sorry. Bye!");
337 VG_(message)(Vg_UserMsg,
338 "");
339 VG_(pp_sched_status)();
340 VG_(exit)(1);
341}
342
343Addr VG_(get_stack_pointer) ( void )
344{
345 return VG_(baseBlock)[VGOFF_(m_esp)];
346}
347
348/* Debugging thing .. can be called from assembly with OYNK macro. */
349void VG_(oynk) ( Int n )
350{
351 OINK(n);
352}
353
354/* Initialize the PID and PGRP of scheduler LWP; this is also called
355 in any new children after fork. */
356static void newpid(ThreadId unused)
357{
358 /* PID of scheduler LWP */
359 VG_(main_pid) = VG_(getpid)();
360 VG_(main_pgrp) = VG_(getpgrp)();
361}
362
363/*====================================================================*/
364/*=== Check we were launched by stage 1 ===*/
365/*====================================================================*/
366
367/* Look for our AUXV table */
nethercote31779c72004-07-30 21:50:15 +0000368int scan_auxv(void)
nethercote71980f02004-01-24 18:18:54 +0000369{
370 const struct ume_auxv *auxv = find_auxv((int *)ume_exec_esp);
nethercote31779c72004-07-30 21:50:15 +0000371 int padfile = -1, found = 0;
nethercote71980f02004-01-24 18:18:54 +0000372
373 for (; auxv->a_type != AT_NULL; auxv++)
374 switch(auxv->a_type) {
375 case AT_UME_PADFD:
nethercote31779c72004-07-30 21:50:15 +0000376 padfile = auxv->u.a_val;
nethercote71980f02004-01-24 18:18:54 +0000377 found |= 1;
378 break;
379
380 case AT_UME_EXECFD:
nethercotef6a1d502004-08-09 12:21:57 +0000381 vgexecfd = auxv->u.a_val;
nethercote71980f02004-01-24 18:18:54 +0000382 found |= 2;
383 break;
384 }
385
nethercote361a14e2004-07-26 11:11:56 +0000386 if ( found != (1|2) ) {
387 fprintf(stderr, "valgrind: stage2 must be launched by stage1\n");
nethercote71980f02004-01-24 18:18:54 +0000388 exit(127);
389 }
nethercote31779c72004-07-30 21:50:15 +0000390 vg_assert(padfile >= 0);
391 return padfile;
nethercote71980f02004-01-24 18:18:54 +0000392}
393
394
395/*====================================================================*/
396/*=== Address space determination ===*/
397/*====================================================================*/
398
nethercote31779c72004-07-30 21:50:15 +0000399static void layout_remaining_space(Addr argc_addr, float ratio)
nethercote71980f02004-01-24 18:18:54 +0000400{
nethercote31779c72004-07-30 21:50:15 +0000401 Int ires;
402 void* vres;
403 addr_t client_size, shadow_size;
nethercote71980f02004-01-24 18:18:54 +0000404
nethercote31779c72004-07-30 21:50:15 +0000405 VG_(valgrind_base) = (addr_t)&kickstart_base;
nethercote820bd8c2004-09-07 23:04:49 +0000406 VG_(valgrind_last) = ROUNDUP(argc_addr, 0x10000) - 1; // stack
nethercote71980f02004-01-24 18:18:54 +0000407
nethercote31779c72004-07-30 21:50:15 +0000408 // This gives the client the largest possible address space while
409 // taking into account the tool's shadow needs.
410 client_size = ROUNDDN((VG_(valgrind_base)-REDZONE_SIZE) / (1.+ratio),
nethercote71980f02004-01-24 18:18:54 +0000411 CLIENT_SIZE_MULTIPLE);
nethercote31779c72004-07-30 21:50:15 +0000412 VG_(client_base) = CLIENT_BASE;
nethercote71980f02004-01-24 18:18:54 +0000413 VG_(client_end) = VG_(client_base) + client_size;
nethercotee2097312004-06-27 12:29:56 +0000414 /* where !FIXED mmap goes */
nethercotebc7b4f42004-07-26 12:44:35 +0000415 VG_(client_mapbase) = VG_(client_base) +
416 PGROUNDDN((addr_t)(client_size * CLIENT_HEAP_PROPORTION));
nethercote71980f02004-01-24 18:18:54 +0000417
nethercote31779c72004-07-30 21:50:15 +0000418 VG_(shadow_base) = VG_(client_end) + REDZONE_SIZE;
nethercote410bfe62004-09-04 15:53:35 +0000419 VG_(shadow_end) = VG_(valgrind_base);
420 shadow_size = VG_(shadow_end) - VG_(shadow_base);
nethercote71980f02004-01-24 18:18:54 +0000421
nethercotee2097312004-06-27 12:29:56 +0000422#define SEGSIZE(a,b) ((VG_(b) - VG_(a))/(1024*1024))
423
nethercote71980f02004-01-24 18:18:54 +0000424 if (0)
nethercotee2097312004-06-27 12:29:56 +0000425 VG_(printf)(
426 "client_base %8x (%dMB)\n"
427 "client_mapbase %8x (%dMB)\n"
428 "client_end %8x (%dMB)\n"
429 "shadow_base %8x (%dMB)\n"
nethercote410bfe62004-09-04 15:53:35 +0000430 "shadow_end %8x\n"
nethercotee2097312004-06-27 12:29:56 +0000431 "valgrind_base %8x (%dMB)\n"
nethercote820bd8c2004-09-07 23:04:49 +0000432 "valgrind_last %8x\n",
nethercotee2097312004-06-27 12:29:56 +0000433 VG_(client_base), SEGSIZE(client_base, client_mapbase),
434 VG_(client_mapbase), SEGSIZE(client_mapbase, client_end),
435 VG_(client_end), SEGSIZE(client_end, shadow_base),
436 VG_(shadow_base), SEGSIZE(shadow_base, shadow_end),
nethercote410bfe62004-09-04 15:53:35 +0000437 VG_(shadow_end),
nethercote820bd8c2004-09-07 23:04:49 +0000438 VG_(valgrind_base), SEGSIZE(valgrind_base, valgrind_last),
439 VG_(valgrind_last)
nethercotee2097312004-06-27 12:29:56 +0000440 );
441
442#undef SEGSIZE
nethercote71980f02004-01-24 18:18:54 +0000443
444 // Ban redzone
nethercotee567e702004-07-10 17:49:17 +0000445 vres = mmap((void *)VG_(client_end), REDZONE_SIZE, PROT_NONE,
fitzhardinge72ddff62004-09-08 20:03:51 +0000446 MAP_FIXED|MAP_ANON|MAP_PRIVATE|MAP_NORESERVE, -1, 0);
nethercotee567e702004-07-10 17:49:17 +0000447 vg_assert((void*)-1 != vres);
nethercote71980f02004-01-24 18:18:54 +0000448
449 // Make client hole
nethercotee567e702004-07-10 17:49:17 +0000450 ires = munmap((void*)VG_(client_base), client_size);
451 vg_assert(0 == ires);
nethercote71980f02004-01-24 18:18:54 +0000452
453 // Map shadow memory.
454 // Initially all inaccessible, incrementally initialized as it is used
nethercotee567e702004-07-10 17:49:17 +0000455 if (shadow_size != 0) {
456 vres = mmap((char *)VG_(shadow_base), shadow_size, PROT_NONE,
fitzhardinge72ddff62004-09-08 20:03:51 +0000457 MAP_PRIVATE|MAP_ANON|MAP_FIXED|MAP_NORESERVE, -1, 0);
nethercoted4722622004-08-30 19:36:42 +0000458 if ((void*)-1 == vres) {
459 fprintf(stderr,
460 "valgrind: Couldn't allocate address space for shadow memory\n"
461 "valgrind: Are you using a kernel with a small user address space,\n"
462 "valgrind: or do you have your virtual memory size limited?\n");
463 exit(1);
464 }
nethercotee567e702004-07-10 17:49:17 +0000465 }
nethercote71980f02004-01-24 18:18:54 +0000466}
467
468/*====================================================================*/
469/*=== Command line setup ===*/
470/*====================================================================*/
471
472/* Nb: malloc'd memory never freed -- kept throughout like argv, envp */
473static char* get_file_clo(char* dir)
474{
475# define FLEN 512
476 Int fd, n;
477 struct stat s1;
478 char* f_clo = NULL;
479 char filename[FLEN];
480
481 snprintf(filename, FLEN, "%s/.valgrindrc", ( NULL == dir ? "" : dir ) );
482 fd = VG_(open)(filename, 0, VKI_S_IRUSR);
483 if ( fd > 0 ) {
484 if ( 0 == fstat(fd, &s1) ) {
485 f_clo = malloc(s1.st_size+1);
486 vg_assert(f_clo);
487 n = read(fd, f_clo, s1.st_size);
488 if (n == -1) n = 0;
489 f_clo[n] = '\0';
490 }
491 close(fd);
492 }
493 return f_clo;
494# undef FLEN
495}
496
nethercotee2097312004-06-27 12:29:56 +0000497#define ISSPACE(cc) ((cc) == ' ' || (cc) == '\t' || (cc) == '\n')
498
nethercote71980f02004-01-24 18:18:54 +0000499static Int count_args(char* s)
500{
501 Int n = 0;
502 if (s) {
503 char* cp = s;
504 while (True) {
505 // We have alternating sequences: blanks, non-blanks, blanks...
506 // count the non-blanks sequences.
507 while ( ISSPACE(*cp) ) cp++;
508 if ( !*cp ) break;
509 n++;
510 while ( !ISSPACE(*cp) && *cp ) cp++;
511 }
512 }
513 return n;
514}
515
516/* add args out of environment, skipping multiple spaces and -- args */
517static char** copy_args( char* s, char** to )
518{
519 if (s) {
520 char* cp = s;
521 while (True) {
522 // We have alternating sequences: blanks, non-blanks, blanks...
523 // copy the non-blanks sequences, and add terminating '\0'
524 while ( ISSPACE(*cp) ) cp++;
525 if ( !*cp ) break;
526 *to++ = cp;
527 while ( !ISSPACE(*cp) && *cp ) cp++;
528 if ( *cp ) *cp++ = '\0'; // terminate if necessary
529 if (VG_STREQ(to[-1], "--")) to--; // undo any '--' arg
530 }
531 }
532 return to;
533}
534
nethercotee2097312004-06-27 12:29:56 +0000535#undef ISSPACE
536
nethercote71980f02004-01-24 18:18:54 +0000537// Augment command line with arguments from environment and .valgrindrc
538// files.
539static void augment_command_line(Int* vg_argc_inout, char*** vg_argv_inout)
540{
nethercotef6a1d502004-08-09 12:21:57 +0000541 int vg_argc0 = *vg_argc_inout;
542 char** vg_argv0 = *vg_argv_inout;
nethercote71980f02004-01-24 18:18:54 +0000543
544 char* env_clo = getenv(VALGRINDOPTS);
545 char* f1_clo = get_file_clo( getenv("HOME") );
546 char* f2_clo = get_file_clo(".");
547
548 /* copy any extra args from file or environment, if present */
549 if ( (env_clo && *env_clo) || (f1_clo && *f1_clo) || (f2_clo && *f2_clo) ) {
550 /* ' ' separated extra options */
551 char **from;
552 char **to;
553 int env_arg_count, f1_arg_count, f2_arg_count;
554
555 env_arg_count = count_args(env_clo);
556 f1_arg_count = count_args(f1_clo);
557 f2_arg_count = count_args(f2_clo);
558
559 if (0)
560 printf("extra-argc=%d %d %d\n",
561 env_arg_count, f1_arg_count, f2_arg_count);
562
563 /* +2: +1 for null-termination, +1 for added '--' */
nethercotef6a1d502004-08-09 12:21:57 +0000564 from = vg_argv0;
565 vg_argv0 = malloc( (vg_argc0 + env_arg_count + f1_arg_count
nethercote71980f02004-01-24 18:18:54 +0000566 + f2_arg_count + 2) * sizeof(char **));
nethercotef6a1d502004-08-09 12:21:57 +0000567 vg_assert(vg_argv0);
568 to = vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000569
570 /* copy argv[0] */
571 *to++ = *from++;
572
573 /* Copy extra args from env var and file, in the order: ~/.valgrindrc,
574 * $VALGRIND_OPTS, ./.valgrindrc -- more local options are put later
575 * to override less local ones. */
576 to = copy_args(f1_clo, to);
577 to = copy_args(env_clo, to);
578 to = copy_args(f2_clo, to);
579
580 /* copy original arguments, stopping at command or -- */
581 while (*from) {
582 if (**from != '-')
583 break;
584 if (VG_STREQ(*from, "--")) {
585 from++; /* skip -- */
586 break;
587 }
588 *to++ = *from++;
589 }
590
591 /* add -- */
592 *to++ = "--";
593
nethercotef6a1d502004-08-09 12:21:57 +0000594 vg_argc0 = to - vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000595
596 /* copy rest of original command line, then NULL */
597 while (*from) *to++ = *from++;
598 *to = NULL;
599 }
600
nethercotef6a1d502004-08-09 12:21:57 +0000601 *vg_argc_inout = vg_argc0;
602 *vg_argv_inout = vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000603}
604
nethercotef6a1d502004-08-09 12:21:57 +0000605#define VG_CLO_SEP '\01'
606
nethercote71980f02004-01-24 18:18:54 +0000607static void get_command_line( int argc, char** argv,
608 Int* vg_argc_out, Char*** vg_argv_out,
609 char*** cl_argv_out )
610{
nethercotef6a1d502004-08-09 12:21:57 +0000611 int vg_argc0;
612 char** vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000613 char** cl_argv;
614 char* env_clo = getenv(VALGRINDCLO);
615
616 if (env_clo != NULL && *env_clo != '\0') {
617 char *cp;
618 char **cpp;
619
nethercotef6a1d502004-08-09 12:21:57 +0000620 /* OK, VALGRINDCLO is set, which means we must be a child of another
621 Valgrind process using --trace-children, so we're getting all our
622 arguments from VALGRINDCLO, and the entire command line belongs to
623 the client (including argv[0]) */
624 vg_argc0 = 1; /* argv[0] */
nethercote71980f02004-01-24 18:18:54 +0000625 for (cp = env_clo; *cp; cp++)
nethercotef6a1d502004-08-09 12:21:57 +0000626 if (*cp == VG_CLO_SEP)
627 vg_argc0++;
nethercote71980f02004-01-24 18:18:54 +0000628
nethercotef6a1d502004-08-09 12:21:57 +0000629 vg_argv0 = malloc(sizeof(char **) * (vg_argc0 + 1));
630 vg_assert(vg_argv0);
nethercote71980f02004-01-24 18:18:54 +0000631
nethercotef6a1d502004-08-09 12:21:57 +0000632 cpp = vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000633
634 *cpp++ = "valgrind"; /* nominal argv[0] */
635 *cpp++ = env_clo;
636
nethercotef6a1d502004-08-09 12:21:57 +0000637 // Replace the VG_CLO_SEP args separator with '\0'
nethercote71980f02004-01-24 18:18:54 +0000638 for (cp = env_clo; *cp; cp++) {
nethercotef6a1d502004-08-09 12:21:57 +0000639 if (*cp == VG_CLO_SEP) {
nethercote71980f02004-01-24 18:18:54 +0000640 *cp++ = '\0'; /* chop it up in place */
641 *cpp++ = cp;
642 }
643 }
644 *cpp = NULL;
645 cl_argv = argv;
646
647 } else {
648 /* Count the arguments on the command line. */
nethercotef6a1d502004-08-09 12:21:57 +0000649 vg_argv0 = argv;
nethercote71980f02004-01-24 18:18:54 +0000650
nethercotef6a1d502004-08-09 12:21:57 +0000651 for (vg_argc0 = 1; vg_argc0 < argc; vg_argc0++) {
652 if (argv[vg_argc0][0] != '-') /* exe name */
nethercote71980f02004-01-24 18:18:54 +0000653 break;
nethercotef6a1d502004-08-09 12:21:57 +0000654 if (VG_STREQ(argv[vg_argc0], "--")) { /* dummy arg */
655 vg_argc0++;
nethercote71980f02004-01-24 18:18:54 +0000656 break;
657 }
658 }
nethercotef6a1d502004-08-09 12:21:57 +0000659 cl_argv = &argv[vg_argc0];
nethercote71980f02004-01-24 18:18:54 +0000660
661 /* Get extra args from VALGRIND_OPTS and .valgrindrc files.
nethercotef6a1d502004-08-09 12:21:57 +0000662 Note we don't do this if getting args from VALGRINDCLO, as
663 those extra args will already be present in VALGRINDCLO. */
664 augment_command_line(&vg_argc0, &vg_argv0);
nethercote71980f02004-01-24 18:18:54 +0000665 }
666
667 if (0) {
668 Int i;
nethercotef6a1d502004-08-09 12:21:57 +0000669 for (i = 0; i < vg_argc0; i++)
670 printf("vg_argv0[%d]=\"%s\"\n", i, vg_argv0[i]);
nethercote71980f02004-01-24 18:18:54 +0000671 }
672
nethercotef6a1d502004-08-09 12:21:57 +0000673 *vg_argc_out = vg_argc0;
674 *vg_argv_out = (Char**)vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000675 *cl_argv_out = cl_argv;
676}
677
678
679/*====================================================================*/
680/*=== Environment and stack setup ===*/
681/*====================================================================*/
682
683/* Scan a colon-separated list, and call a function on each element.
684 The string must be mutable, because we insert a temporary '\0', but
thughes4ad52d02004-06-27 17:37:21 +0000685 the string will end up unmodified. (*func) should return True if it
nethercote71980f02004-01-24 18:18:54 +0000686 doesn't need to see any more.
thughes4ad52d02004-06-27 17:37:21 +0000687
688 This routine will return True if (*func) returns True and False if
689 it reaches the end of the list without that happening.
nethercote71980f02004-01-24 18:18:54 +0000690*/
thughes4ad52d02004-06-27 17:37:21 +0000691static Bool scan_colsep(char *colsep, Bool (*func)(const char *))
nethercote71980f02004-01-24 18:18:54 +0000692{
693 char *cp, *entry;
694 int end;
695
696 if (colsep == NULL ||
697 *colsep == '\0')
thughes4ad52d02004-06-27 17:37:21 +0000698 return False;
nethercote71980f02004-01-24 18:18:54 +0000699
700 entry = cp = colsep;
701
702 do {
703 end = (*cp == '\0');
704
705 if (*cp == ':' || *cp == '\0') {
706 char save = *cp;
707
708 *cp = '\0';
thughes21942d92004-07-12 09:35:37 +0000709 if ((*func)(entry)) {
710 *cp = save;
thughes4ad52d02004-06-27 17:37:21 +0000711 return True;
thughes21942d92004-07-12 09:35:37 +0000712 }
nethercote71980f02004-01-24 18:18:54 +0000713 *cp = save;
714 entry = cp+1;
715 }
716 cp++;
717 } while(!end);
thughes4ad52d02004-06-27 17:37:21 +0000718
719 return False;
720}
721
722static Bool contains(const char *p) {
723 if (VG_STREQ(p, VG_(libdir))) {
724 return True;
725 }
726 return False;
nethercote71980f02004-01-24 18:18:54 +0000727}
728
729/* Prepare the client's environment. This is basically a copy of our
730 environment, except:
731 1. LD_LIBRARY_PATH=$VALGRINDLIB:$LD_LIBRARY_PATH
732 2. LD_PRELOAD=$VALGRINDLIB/vg_inject.so:($VALGRINDLIB/vgpreload_TOOL.so:)?$LD_PRELOAD
733
734 If any of these is missing, then it is added.
735
736 Yummy. String hacking in C.
737
738 If this needs to handle any more variables it should be hacked
739 into something table driven.
740 */
741static char **fix_environment(char **origenv, const char *preload)
742{
743 static const char inject_so[] = "vg_inject.so";
744 static const char ld_library_path[] = "LD_LIBRARY_PATH=";
745 static const char ld_preload[] = "LD_PRELOAD=";
746 static const char valgrind_clo[] = VALGRINDCLO "=";
747 static const int ld_library_path_len = sizeof(ld_library_path)-1;
748 static const int ld_preload_len = sizeof(ld_preload)-1;
749 static const int valgrind_clo_len = sizeof(valgrind_clo)-1;
750 int ld_preload_done = 0;
751 int ld_library_path_done = 0;
752 char *inject_path;
753 int inject_path_len;
754 int vgliblen = strlen(VG_(libdir));
755 char **cpp;
756 char **ret;
757 int envc;
758 const int preloadlen = (preload == NULL) ? 0 : strlen(preload);
759
760 /* Find the vg_inject.so; also make room for the tool preload
761 library */
762 inject_path_len = sizeof(inject_so) + vgliblen + preloadlen + 16;
763 inject_path = malloc(inject_path_len);
nethercote7c018f42004-07-17 16:40:50 +0000764 vg_assert(inject_path);
nethercote71980f02004-01-24 18:18:54 +0000765
766 if (preload)
767 snprintf(inject_path, inject_path_len, "%s/%s:%s",
768 VG_(libdir), inject_so, preload);
769 else
770 snprintf(inject_path, inject_path_len, "%s/%s",
771 VG_(libdir), inject_so);
772
773 /* Count the original size of the env */
774 envc = 0; /* trailing NULL */
775 for (cpp = origenv; cpp && *cpp; cpp++)
776 envc++;
777
778 /* Allocate a new space */
779 ret = malloc(sizeof(char *) * (envc+3+1)); /* 3 new entries + NULL */
nethercote7c018f42004-07-17 16:40:50 +0000780 vg_assert(ret);
nethercote71980f02004-01-24 18:18:54 +0000781
782 /* copy it over */
783 for (cpp = ret; *origenv; )
784 *cpp++ = *origenv++;
785 *cpp = NULL;
786
787 vg_assert(envc == (cpp - ret));
788
789 /* Walk over the new environment, mashing as we go */
790 for (cpp = ret; cpp && *cpp; cpp++) {
791 if (memcmp(*cpp, ld_library_path, ld_library_path_len) == 0) {
nethercote71980f02004-01-24 18:18:54 +0000792 /* If the LD_LIBRARY_PATH already contains libdir, then don't
793 bother adding it again, even if it isn't the first (it
794 seems that the Java runtime will keep reexecing itself
795 unless its paths are at the front of LD_LIBRARY_PATH) */
thughes4ad52d02004-06-27 17:37:21 +0000796 if (!scan_colsep(*cpp + ld_library_path_len, contains)) {
nethercote71980f02004-01-24 18:18:54 +0000797 int len = strlen(*cpp) + vgliblen*2 + 16;
798 char *cp = malloc(len);
nethercote7c018f42004-07-17 16:40:50 +0000799 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000800
801 snprintf(cp, len, "%s%s:%s",
802 ld_library_path, VG_(libdir),
803 (*cpp)+ld_library_path_len);
804
805 *cpp = cp;
806 }
807
808 ld_library_path_done = 1;
809 } else if (memcmp(*cpp, ld_preload, ld_preload_len) == 0) {
810 int len = strlen(*cpp) + inject_path_len;
811 char *cp = malloc(len);
nethercote7c018f42004-07-17 16:40:50 +0000812 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000813
814 snprintf(cp, len, "%s%s:%s",
815 ld_preload, inject_path, (*cpp)+ld_preload_len);
816
817 *cpp = cp;
818
819 ld_preload_done = 1;
820 } else if (memcmp(*cpp, valgrind_clo, valgrind_clo_len) == 0) {
821 *cpp = "";
822 }
823 }
824
825 /* Add the missing bits */
826
827 if (!ld_library_path_done) {
828 int len = ld_library_path_len + vgliblen*2 + 16;
829 char *cp = malloc(len);
nethercote7c018f42004-07-17 16:40:50 +0000830 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000831
832 snprintf(cp, len, "%s%s", ld_library_path, VG_(libdir));
833
834 ret[envc++] = cp;
835 }
836
837 if (!ld_preload_done) {
838 int len = ld_preload_len + inject_path_len;
839 char *cp = malloc(len);
nethercote7c018f42004-07-17 16:40:50 +0000840 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000841
842 snprintf(cp, len, "%s%s",
843 ld_preload, inject_path);
844
845 ret[envc++] = cp;
846 }
847
848 ret[envc] = NULL;
849
850 return ret;
851}
852
853extern char **environ; /* our environment */
854//#include <error.h>
855
856/* Add a string onto the string table, and return its address */
857static char *copy_str(char **tab, const char *str)
858{
859 char *cp = *tab;
860 char *orig = cp;
861
862 while(*str)
863 *cp++ = *str++;
864 *cp++ = '\0';
865
866 if (0)
nethercotef84f6952004-07-15 14:58:33 +0000867 printf("copied %p \"%s\" len %d\n", orig, orig, cp-orig);
nethercote71980f02004-01-24 18:18:54 +0000868
869 *tab = cp;
870
871 return orig;
872}
873
874/*
875 This sets up the client's initial stack, containing the args,
876 environment and aux vector.
877
878 The format of the stack is:
879
880 higher address +-----------------+
881 | Trampoline code |
882 +-----------------+
883 | |
884 : string table :
885 | |
886 +-----------------+
887 | AT_NULL |
888 - -
889 | auxv |
890 +-----------------+
891 | NULL |
892 - -
893 | envp |
894 +-----------------+
895 | NULL |
896 - -
897 | argv |
898 +-----------------+
899 | argc |
900 lower address +-----------------+ <- esp
901 | undefined |
902 : :
903 */
904static Addr setup_client_stack(char **orig_argv, char **orig_envp,
905 const struct exeinfo *info,
906 UInt** client_auxv)
907{
nethercotee567e702004-07-10 17:49:17 +0000908 void* res;
nethercote71980f02004-01-24 18:18:54 +0000909 char **cpp;
910 char *strtab; /* string table */
911 char *stringbase;
912 addr_t *ptr;
913 struct ume_auxv *auxv;
914 const struct ume_auxv *orig_auxv;
915 const struct ume_auxv *cauxv;
916 unsigned stringsize; /* total size of strings in bytes */
917 unsigned auxsize; /* total size of auxv in bytes */
918 int argc; /* total argc */
919 int envc; /* total number of env vars */
920 unsigned stacksize; /* total client stack size */
921 addr_t cl_esp; /* client stack base (initial esp) */
922
923 /* use our own auxv as a prototype */
924 orig_auxv = find_auxv(ume_exec_esp);
925
926 /* ==================== compute sizes ==================== */
927
928 /* first of all, work out how big the client stack will be */
929 stringsize = 0;
930
931 /* paste on the extra args if the loader needs them (ie, the #!
932 interpreter and its argument) */
933 argc = 0;
nethercoted6a56872004-07-26 15:32:47 +0000934 if (info->interp_name != NULL) {
nethercote71980f02004-01-24 18:18:54 +0000935 argc++;
nethercoted6a56872004-07-26 15:32:47 +0000936 stringsize += strlen(info->interp_name) + 1;
nethercote71980f02004-01-24 18:18:54 +0000937 }
nethercoted6a56872004-07-26 15:32:47 +0000938 if (info->interp_args != NULL) {
nethercote71980f02004-01-24 18:18:54 +0000939 argc++;
nethercoted6a56872004-07-26 15:32:47 +0000940 stringsize += strlen(info->interp_args) + 1;
nethercote71980f02004-01-24 18:18:54 +0000941 }
942
943 /* now scan the args we're given... */
944 for (cpp = orig_argv; *cpp; cpp++) {
945 argc++;
946 stringsize += strlen(*cpp) + 1;
947 }
948
949 /* ...and the environment */
950 envc = 0;
951 for (cpp = orig_envp; cpp && *cpp; cpp++) {
952 envc++;
953 stringsize += strlen(*cpp) + 1;
954 }
955
956 /* now, how big is the auxv? */
957 auxsize = sizeof(*auxv); /* there's always at least one entry: AT_NULL */
958 for (cauxv = orig_auxv; cauxv->a_type != AT_NULL; cauxv++) {
959 if (cauxv->a_type == AT_PLATFORM)
960 stringsize += strlen(cauxv->u.a_ptr) + 1;
961 auxsize += sizeof(*cauxv);
962 }
963
964 /* OK, now we know how big the client stack is */
965 stacksize =
966 sizeof(int) + /* argc */
967 sizeof(char **)*argc + /* argv */
968 sizeof(char **) + /* terminal NULL */
969 sizeof(char **)*envc + /* envp */
970 sizeof(char **) + /* terminal NULL */
971 auxsize + /* auxv */
972 ROUNDUP(stringsize, sizeof(int)) +/* strings (aligned) */
973 VKI_BYTES_PER_PAGE; /* page for trampoline code */
974
nethercotef84f6952004-07-15 14:58:33 +0000975 // decide where stack goes!
976 VG_(clstk_end) = VG_(client_end);
977
978 VG_(client_trampoline_code) = VG_(clstk_end) - VKI_BYTES_PER_PAGE;
979
nethercote71980f02004-01-24 18:18:54 +0000980 /* cl_esp is the client's stack pointer */
nethercotef84f6952004-07-15 14:58:33 +0000981 cl_esp = VG_(clstk_end) - stacksize;
nethercote71980f02004-01-24 18:18:54 +0000982 cl_esp = ROUNDDN(cl_esp, 16); /* make stack 16 byte aligned */
983
nethercote71980f02004-01-24 18:18:54 +0000984 /* base of the string table (aligned) */
985 stringbase = strtab = (char *)(VG_(client_trampoline_code) - ROUNDUP(stringsize, sizeof(int)));
986
987 VG_(clstk_base) = PGROUNDDN(cl_esp);
nethercote71980f02004-01-24 18:18:54 +0000988
nethercote5ee67ca2004-06-22 14:00:09 +0000989 if (0)
990 printf("stringsize=%d auxsize=%d stacksize=%d\n"
nethercote6a27d832004-09-07 10:17:02 +0000991 "clstk_base %p\n"
992 "clstk_end %p\n",
993 stringsize, auxsize, stacksize,
994 (void*)VG_(clstk_base), (void*)VG_(clstk_end));
nethercote5ee67ca2004-06-22 14:00:09 +0000995
996
nethercote71980f02004-01-24 18:18:54 +0000997 /* ==================== allocate space ==================== */
998
999 /* allocate a stack - mmap enough space for the stack */
nethercotef84f6952004-07-15 14:58:33 +00001000 res = mmap((void *)PGROUNDDN(cl_esp), VG_(clstk_end) - PGROUNDDN(cl_esp),
nethercotee567e702004-07-10 17:49:17 +00001001 PROT_READ | PROT_WRITE | PROT_EXEC,
1002 MAP_PRIVATE | MAP_ANON | MAP_FIXED, -1, 0);
1003 vg_assert((void*)-1 != res);
nethercote71980f02004-01-24 18:18:54 +00001004
1005 /* ==================== copy client stack ==================== */
1006
1007 ptr = (addr_t *)cl_esp;
1008
1009 /* --- argc --- */
1010 *ptr++ = argc; /* client argc */
1011
1012 /* --- argv --- */
nethercoted6a56872004-07-26 15:32:47 +00001013 if (info->interp_name) {
1014 *ptr++ = (addr_t)copy_str(&strtab, info->interp_name);
1015 free(info->interp_name);
nethercote71980f02004-01-24 18:18:54 +00001016 }
nethercoted6a56872004-07-26 15:32:47 +00001017 if (info->interp_args) {
1018 *ptr++ = (addr_t)copy_str(&strtab, info->interp_args);
1019 free(info->interp_args);
nethercote71980f02004-01-24 18:18:54 +00001020 }
1021 for (cpp = orig_argv; *cpp; ptr++, cpp++) {
1022 *ptr = (addr_t)copy_str(&strtab, *cpp);
1023 }
1024 *ptr++ = 0;
1025
1026 /* --- envp --- */
1027 VG_(client_envp) = (Char **)ptr;
1028 for (cpp = orig_envp; cpp && *cpp; ptr++, cpp++)
1029 *ptr = (addr_t)copy_str(&strtab, *cpp);
1030 *ptr++ = 0;
1031
1032 /* --- auxv --- */
1033 auxv = (struct ume_auxv *)ptr;
1034 *client_auxv = (UInt *)auxv;
1035
1036 for (; orig_auxv->a_type != AT_NULL; auxv++, orig_auxv++) {
1037 /* copy the entry... */
1038 *auxv = *orig_auxv;
1039
1040 /* ...and fix up the copy */
1041 switch(auxv->a_type) {
1042 case AT_PHDR:
1043 if (info->phdr == 0)
1044 auxv->a_type = AT_IGNORE;
1045 else
1046 auxv->u.a_val = info->phdr;
1047 break;
1048
1049 case AT_PHNUM:
1050 if (info->phdr == 0)
1051 auxv->a_type = AT_IGNORE;
1052 else
1053 auxv->u.a_val = info->phnum;
1054 break;
1055
1056 case AT_BASE:
1057 if (info->interp_base == 0)
1058 auxv->a_type = AT_IGNORE;
1059 else
1060 auxv->u.a_val = info->interp_base;
1061 break;
1062
1063 case AT_PLATFORM: /* points to a platform description string */
1064 auxv->u.a_ptr = copy_str(&strtab, orig_auxv->u.a_ptr);
1065 break;
1066
1067 case AT_ENTRY:
1068 auxv->u.a_val = info->entry;
1069 break;
1070
1071 case AT_IGNORE:
1072 case AT_EXECFD:
1073 case AT_PHENT:
1074 case AT_PAGESZ:
1075 case AT_FLAGS:
1076 case AT_NOTELF:
1077 case AT_UID:
1078 case AT_EUID:
1079 case AT_GID:
1080 case AT_EGID:
1081 case AT_CLKTCK:
1082 case AT_HWCAP:
1083 case AT_FPUCW:
1084 case AT_DCACHEBSIZE:
1085 case AT_ICACHEBSIZE:
1086 case AT_UCACHEBSIZE:
1087 /* All these are pointerless, so we don't need to do anything
1088 about them. */
1089 break;
1090
1091 case AT_SECURE:
1092 /* If this is 1, then it means that this program is running
1093 suid, and therefore the dynamic linker should be careful
1094 about LD_PRELOAD, etc. However, since stage1 (the thing
1095 the kernel actually execve's) should never be SUID, and we
1096 need LD_PRELOAD/LD_LIBRARY_PATH to work for the client, we
1097 set AT_SECURE to 0. */
1098 auxv->u.a_val = 0;
1099 break;
1100
1101 case AT_SYSINFO:
1102 /* Leave this unmolested for now, but we'll update it later
1103 when we set up the client trampoline code page */
1104 break;
1105
1106 case AT_SYSINFO_EHDR:
1107 /* Trash this, because we don't reproduce it */
1108 auxv->a_type = AT_IGNORE;
1109 break;
1110
1111 default:
1112 /* stomp out anything we don't know about */
1113 if (0)
1114 printf("stomping auxv entry %d\n", auxv->a_type);
1115 auxv->a_type = AT_IGNORE;
1116 break;
1117
1118 }
1119 }
1120 *auxv = *orig_auxv;
1121 vg_assert(auxv->a_type == AT_NULL);
1122
nethercotef84f6952004-07-15 14:58:33 +00001123 /* --- trampoline page --- */
1124 VG_(memcpy)( (void *)VG_(client_trampoline_code),
1125 &VG_(trampoline_code_start), VG_(trampoline_code_length) );
1126
nethercote71980f02004-01-24 18:18:54 +00001127 vg_assert((strtab-stringbase) == stringsize);
1128
nethercote5ee67ca2004-06-22 14:00:09 +00001129 /* We know the initial ESP is pointing at argc/argv */
1130 VG_(client_argc) = *(Int*)cl_esp;
1131 VG_(client_argv) = (Char**)(cl_esp + sizeof(Int));
1132
nethercote71980f02004-01-24 18:18:54 +00001133 return cl_esp;
1134}
1135
1136/*====================================================================*/
1137/*=== Find executable ===*/
1138/*====================================================================*/
1139
thughes4ad52d02004-06-27 17:37:21 +00001140static const char* executable_name;
1141
1142static Bool match_executable(const char *entry) {
1143 char buf[strlen(entry) + strlen(executable_name) + 2];
1144
1145 /* empty PATH element means . */
1146 if (*entry == '\0')
1147 entry = ".";
1148
1149 snprintf(buf, sizeof(buf), "%s/%s", entry, executable_name);
1150
1151 if (access(buf, R_OK|X_OK) == 0) {
1152 executable_name = strdup(buf);
1153 vg_assert(NULL != executable_name);
1154 return True;
1155 }
1156 return False;
1157}
1158
nethercote71980f02004-01-24 18:18:54 +00001159static const char* find_executable(const char* exec)
1160{
1161 vg_assert(NULL != exec);
thughes4ad52d02004-06-27 17:37:21 +00001162 executable_name = exec;
1163 if (strchr(executable_name, '/') == NULL) {
nethercote71980f02004-01-24 18:18:54 +00001164 /* no '/' - we need to search the path */
1165 char *path = getenv("PATH");
thughes4ad52d02004-06-27 17:37:21 +00001166 scan_colsep(path, match_executable);
nethercote71980f02004-01-24 18:18:54 +00001167 }
thughes4ad52d02004-06-27 17:37:21 +00001168 return executable_name;
nethercote71980f02004-01-24 18:18:54 +00001169}
1170
1171
1172/*====================================================================*/
1173/*=== Loading tools ===*/
1174/*====================================================================*/
1175
1176static void list_tools(void)
1177{
1178 DIR *dir = opendir(VG_(libdir));
1179 struct dirent *de;
1180 int first = 1;
1181
1182 if (dir == NULL) {
1183 fprintf(stderr, "Can't open %s: %s (installation problem?)\n",
nethercotef4928da2004-06-15 10:54:40 +00001184 VG_(libdir), strerror(errno));
nethercote71980f02004-01-24 18:18:54 +00001185 return;
1186 }
1187
nethercotef4928da2004-06-15 10:54:40 +00001188 while ((de = readdir(dir)) != NULL) {
nethercote71980f02004-01-24 18:18:54 +00001189 int len = strlen(de->d_name);
1190
1191 /* look for vgskin_TOOL.so names */
1192 if (len > (7+1+3) && /* "vgskin_" + at least 1-char toolname + ".so" */
nethercotef4928da2004-06-15 10:54:40 +00001193 strncmp(de->d_name, "vgskin_", 7) == 0 &&
1194 VG_STREQ(de->d_name + len - 3, ".so")) {
1195 if (first) {
1196 fprintf(stderr, "Available tools:\n");
1197 first = 0;
1198 }
1199 de->d_name[len-3] = '\0';
1200 fprintf(stderr, "\t%s\n", de->d_name+7);
nethercote71980f02004-01-24 18:18:54 +00001201 }
1202 }
1203
1204 closedir(dir);
1205
1206 if (first)
nethercotef4928da2004-06-15 10:54:40 +00001207 fprintf(stderr, "No tools available in \"%s\" (installation problem?)\n",
1208 VG_(libdir));
nethercote71980f02004-01-24 18:18:54 +00001209}
1210
1211
1212/* Find and load a tool, and check it looks ok. Also looks to see if there's
1213 * a matching vgpreload_*.so file, and returns its name in *preloadpath. */
1214static void load_tool( const char *toolname, void** handle_out,
1215 ToolInfo** toolinfo_out, char **preloadpath_out )
1216{
1217 Bool ok;
1218 int len = strlen(VG_(libdir)) + strlen(toolname)*2 + 16;
1219 char buf[len];
1220 void* handle;
1221 ToolInfo* toolinfo;
1222 char* preloadpath = NULL;
1223 Int* vg_malloc_redzonep;
1224
1225 // XXX: allowing full paths for --tool option -- does it make sense?
1226 // Doesn't allow for vgpreload_<tool>.so.
1227
1228 if (strchr(toolname, '/') != 0) {
1229 /* toolname contains '/', and so must be a pathname */
1230 handle = dlopen(toolname, RTLD_NOW);
1231 } else {
1232 /* just try in the libdir */
1233 snprintf(buf, len, "%s/vgskin_%s.so", VG_(libdir), toolname);
1234 handle = dlopen(buf, RTLD_NOW);
1235
1236 if (handle != NULL) {
1237 snprintf(buf, len, "%s/vgpreload_%s.so", VG_(libdir), toolname);
1238 if (access(buf, R_OK) == 0) {
1239 preloadpath = strdup(buf);
1240 vg_assert(NULL != preloadpath);
1241 }
1242 }
1243 }
1244
1245 ok = (NULL != handle);
1246 if (!ok) {
1247 fprintf(stderr, "Can't open tool \"%s\": %s\n", toolname, dlerror());
1248 goto bad_load;
1249 }
1250
1251 toolinfo = dlsym(handle, "vgSkin_tool_info");
1252 ok = (NULL != toolinfo);
1253 if (!ok) {
1254 fprintf(stderr, "Tool \"%s\" doesn't define SK_(tool_info) - "
1255 "add VG_DETERMINE_INTERFACE_VERSION?\n", toolname);
1256 goto bad_load;
1257 }
1258
1259 ok = (toolinfo->sizeof_ToolInfo == sizeof(*toolinfo) &&
1260 toolinfo->interface_major_version == VG_CORE_INTERFACE_MAJOR_VERSION &&
1261 toolinfo->sk_pre_clo_init != NULL);
1262 if (!ok) {
1263 fprintf(stderr, "Error:\n"
1264 " Tool and core interface versions do not match.\n"
1265 " Interface version used by core is: %d.%d (size %d)\n"
1266 " Interface version used by tool is: %d.%d (size %d)\n"
1267 " The major version numbers must match.\n",
1268 VG_CORE_INTERFACE_MAJOR_VERSION,
1269 VG_CORE_INTERFACE_MINOR_VERSION,
1270 sizeof(*toolinfo),
1271 toolinfo->interface_major_version,
1272 toolinfo->interface_minor_version,
1273 toolinfo->sizeof_ToolInfo);
1274 fprintf(stderr, " You need to at least recompile, and possibly update,\n");
1275 if (VG_CORE_INTERFACE_MAJOR_VERSION > toolinfo->interface_major_version)
nethercote996901a2004-08-03 13:29:09 +00001276 fprintf(stderr, " your tool to work with this version of Valgrind.\n");
nethercote71980f02004-01-24 18:18:54 +00001277 else
nethercote996901a2004-08-03 13:29:09 +00001278 fprintf(stderr, " your version of Valgrind to work with this tool.\n");
nethercote71980f02004-01-24 18:18:54 +00001279 goto bad_load;
1280 }
1281
1282 // Set redzone size for V's allocator
1283 vg_malloc_redzonep = dlsym(handle, STR(VG_(vg_malloc_redzone_szB)));
1284 if ( NULL != vg_malloc_redzonep ) {
1285 VG_(vg_malloc_redzone_szB) = *vg_malloc_redzonep;
1286 }
1287
1288 vg_assert(NULL != handle && NULL != toolinfo);
1289 *handle_out = handle;
1290 *toolinfo_out = toolinfo;
1291 *preloadpath_out = preloadpath;
1292 return;
1293
1294
1295 bad_load:
1296 if (handle != NULL)
1297 dlclose(handle);
1298
nethercotef4928da2004-06-15 10:54:40 +00001299 fprintf(stderr, "valgrind: couldn't load tool\n");
nethercote71980f02004-01-24 18:18:54 +00001300 list_tools();
1301 exit(127);
1302}
1303
nethercotef4928da2004-06-15 10:54:40 +00001304
1305/*====================================================================*/
1306/*=== Command line errors ===*/
1307/*====================================================================*/
1308
1309static void abort_msg ( void )
1310{
nethercotef8548672004-06-21 12:42:35 +00001311 VG_(clo_log_to) = VgLogTo_Fd;
1312 VG_(clo_log_fd) = 2; /* stderr */
nethercotef4928da2004-06-15 10:54:40 +00001313}
1314
1315void VG_(bad_option) ( Char* opt )
1316{
1317 abort_msg();
1318 VG_(printf)("valgrind: Bad option `%s'; aborting.\n", opt);
1319 VG_(printf)("valgrind: Use --help for more information.\n");
1320 VG_(exit)(1);
1321}
1322
1323static void missing_tool_option ( void )
1324{
1325 abort_msg();
1326 VG_(printf)("valgrind: Missing --tool option\n");
1327 list_tools();
1328 VG_(printf)("valgrind: Use --help for more information.\n");
1329 VG_(exit)(1);
1330}
1331
1332static void missing_prog ( void )
1333{
1334 abort_msg();
1335 VG_(printf)("valgrind: no program specified\n");
1336 VG_(printf)("valgrind: Use --help for more information.\n");
1337 VG_(exit)(1);
1338}
1339
1340static void config_error ( Char* msg )
1341{
1342 abort_msg();
1343 VG_(printf)("valgrind: Startup or configuration error:\n %s\n", msg);
1344 VG_(printf)("valgrind: Unable to start up properly. Giving up.\n");
1345 VG_(exit)(1);
1346}
1347
1348
nethercote71980f02004-01-24 18:18:54 +00001349/*====================================================================*/
1350/*=== Loading the client ===*/
1351/*====================================================================*/
1352
nethercotef4928da2004-06-15 10:54:40 +00001353static void load_client(char* cl_argv[], const char* exec, Int need_help,
nethercote71980f02004-01-24 18:18:54 +00001354 /*out*/struct exeinfo* info, /*out*/Addr* client_eip)
1355{
1356 // If they didn't specify an executable with --exec, and didn't specify
1357 // --help, then use client argv[0] (searching $PATH if necessary).
nethercotef4928da2004-06-15 10:54:40 +00001358 if (NULL == exec && !need_help) {
nethercote71980f02004-01-24 18:18:54 +00001359 if (cl_argv[0] == NULL ||
1360 ( NULL == (exec = find_executable(cl_argv[0])) ) )
1361 {
nethercotef4928da2004-06-15 10:54:40 +00001362 missing_prog();
nethercote71980f02004-01-24 18:18:54 +00001363 }
1364 }
1365
1366 info->map_base = VG_(client_mapbase);
nethercote71980f02004-01-24 18:18:54 +00001367 info->exe_base = VG_(client_base);
1368 info->exe_end = VG_(client_end);
1369 info->argv = cl_argv;
1370
nethercotef4928da2004-06-15 10:54:40 +00001371 if (need_help) {
nethercote71980f02004-01-24 18:18:54 +00001372 VG_(clexecfd) = -1;
nethercoteea147e72004-07-26 15:43:57 +00001373 // Set the minimal number of entries in 'info' to continue.
nethercoted6a56872004-07-26 15:32:47 +00001374 info->interp_name = NULL;
1375 info->interp_args = NULL;
nethercote71980f02004-01-24 18:18:54 +00001376 } else {
1377 Int ret;
1378 VG_(clexecfd) = VG_(open)(exec, O_RDONLY, VKI_S_IRUSR);
1379 ret = do_exec(exec, info);
1380 if (ret != 0) {
nethercoteea147e72004-07-26 15:43:57 +00001381 fprintf(stderr, "valgrind: do_exec(%s) failed: %s\n",
1382 exec, strerror(ret));
nethercote71980f02004-01-24 18:18:54 +00001383 exit(127);
1384 }
1385 }
1386
1387 /* Copy necessary bits of 'info' that were filled in */
1388 *client_eip = info->init_eip;
1389 VG_(brk_base) = VG_(brk_limit) = info->brkbase;
1390}
1391
1392
1393/*====================================================================*/
nethercotef6a1d502004-08-09 12:21:57 +00001394/*=== Command-line: variables, processing, etc ===*/
nethercote71980f02004-01-24 18:18:54 +00001395/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +00001396
njn25e49d8e72002-09-23 09:36:25 +00001397/* Define, and set defaults. */
1398Bool VG_(clo_error_limit) = True;
nethercote04d0fbc2004-01-26 16:48:06 +00001399Bool VG_(clo_db_attach) = False;
1400Char* VG_(clo_db_command) = VG_CLO_DEFAULT_DBCOMMAND;
njn43c799e2003-04-08 00:08:52 +00001401Bool VG_(clo_gen_suppressions) = False;
nethercote27fec902004-06-16 21:26:32 +00001402Int VG_(clo_sanity_level) = 1;
njn25e49d8e72002-09-23 09:36:25 +00001403Int VG_(clo_verbosity) = 1;
1404Bool VG_(clo_demangle) = True;
njn25e49d8e72002-09-23 09:36:25 +00001405Bool VG_(clo_trace_children) = False;
sewardj4cf05692002-10-27 20:28:29 +00001406
nethercotef1e5e152004-09-01 23:58:16 +00001407/* See big comment in core.h for meaning of these three.
nethercotee1730692003-11-20 10:38:07 +00001408 fd is initially stdout, for --help, but gets moved to stderr by default
1409 immediately afterwards. */
sewardj4cf05692002-10-27 20:28:29 +00001410VgLogTo VG_(clo_log_to) = VgLogTo_Fd;
nethercotef8548672004-06-21 12:42:35 +00001411Int VG_(clo_log_fd) = 1;
1412Char* VG_(clo_log_name) = NULL;
sewardj4cf05692002-10-27 20:28:29 +00001413
thughes6233a382004-08-21 11:10:44 +00001414Bool VG_(clo_time_stamp) = False;
1415
sewardj6024b212003-07-13 10:54:33 +00001416Int VG_(clo_input_fd) = 0; /* stdin */
njn25e49d8e72002-09-23 09:36:25 +00001417Int VG_(clo_n_suppressions) = 0;
sewardjde4a1d02002-03-22 01:27:54 +00001418Char* VG_(clo_suppressions)[VG_CLO_MAX_SFILES];
njn25e49d8e72002-09-23 09:36:25 +00001419Bool VG_(clo_profile) = False;
1420Bool VG_(clo_single_step) = False;
1421Bool VG_(clo_optimise) = True;
1422UChar VG_(clo_trace_codegen) = 0; // 00000000b
1423Bool VG_(clo_trace_syscalls) = False;
1424Bool VG_(clo_trace_signals) = False;
1425Bool VG_(clo_trace_symtab) = False;
njn25e49d8e72002-09-23 09:36:25 +00001426Bool VG_(clo_trace_sched) = False;
1427Int VG_(clo_trace_pthread_level) = 0;
njn25e49d8e72002-09-23 09:36:25 +00001428Int VG_(clo_dump_error) = 0;
1429Int VG_(clo_backtrace_size) = 4;
1430Char* VG_(clo_weird_hacks) = NULL;
sewardj858964b2002-10-05 14:15:43 +00001431Bool VG_(clo_run_libc_freeres) = True;
rjwalshf5f536f2003-11-17 17:45:00 +00001432Bool VG_(clo_track_fds) = False;
sewardj22854b92002-11-30 14:00:47 +00001433Bool VG_(clo_chain_bb) = True;
nethercote77eba602003-11-13 17:35:04 +00001434Bool VG_(clo_show_below_main) = False;
fitzhardinge98abfc72003-12-16 02:05:15 +00001435Bool VG_(clo_pointercheck) = True;
fitzhardinge462f4f92003-12-18 02:10:54 +00001436Bool VG_(clo_branchpred) = False;
sewardj2370f3b2002-11-30 15:01:01 +00001437
jsgf855d93d2003-10-13 22:26:55 +00001438static Bool VG_(clo_wait_for_gdb) = False;
1439
1440/* If we're doing signal routing, poll for signals every 50mS by
1441 default. */
1442Int VG_(clo_signal_polltime) = 50;
1443
1444/* These flags reduce thread wakeup latency on syscall completion and
1445 signal delivery, respectively. The downside is possible unfairness. */
1446Bool VG_(clo_lowlat_syscalls) = False; /* low-latency syscalls */
1447Bool VG_(clo_lowlat_signals) = False; /* low-latency signals */
1448
sewardjde4a1d02002-03-22 01:27:54 +00001449
nethercote6c999f22004-01-31 22:55:15 +00001450void usage ( Bool debug_help )
njn7cf0bd32002-06-08 13:36:03 +00001451{
njn25e49d8e72002-09-23 09:36:25 +00001452 Char* usage1 =
nethercote71980f02004-01-24 18:18:54 +00001453"usage: valgrind --tool=<toolname> [options] prog-and-args\n"
njn25e49d8e72002-09-23 09:36:25 +00001454"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001455" common user options for all Valgrind tools, with defaults in [ ]:\n"
nethercote0d588502004-06-21 13:27:11 +00001456" --tool=<name> use the Valgrind tool named <name>\n"
nethercotea76368b2004-06-16 11:56:29 +00001457" -h --help show this message\n"
nethercote6c999f22004-01-31 22:55:15 +00001458" --help-debug show this message, plus debugging options\n"
njn25e49d8e72002-09-23 09:36:25 +00001459" --version show version\n"
njn25e49d8e72002-09-23 09:36:25 +00001460" -q --quiet run silently; only print error msgs\n"
1461" -v --verbose be more verbose, incl counts of errors\n"
nethercote77eba602003-11-13 17:35:04 +00001462" --trace-children=no|yes Valgrind-ise child processes? [no]\n"
nethercote0d588502004-06-21 13:27:11 +00001463" --track-fds=no|yes track open file descriptors? [no]\n"
thughes6233a382004-08-21 11:10:44 +00001464" --time-stamp=no|yes add timestamps to log messages? [no]\n"
nethercote2b0793f2003-12-02 10:41:18 +00001465"\n"
1466" uncommon user options for all Valgrind tools:\n"
nethercote0d588502004-06-21 13:27:11 +00001467" --run-libc-freeres=no|yes free up glibc memory at exit? [yes]\n"
1468" --weird-hacks=hack1,hack2,... recognised hacks: lax-ioctls [none]\n"
1469" --signal-polltime=<time> signal poll period (mS) for older kernels [50]\n"
1470" --lowlat-signals=no|yes improve thread signal wake-up latency [no]\n"
1471" --lowlat-syscalls=no|yes improve thread syscall wake-up latency [no]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001472" --pointercheck=no|yes enforce client address space limits [yes]\n"
njn25e49d8e72002-09-23 09:36:25 +00001473"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001474" user options for Valgrind tools that report errors:\n"
nethercotef8548672004-06-21 12:42:35 +00001475" --log-fd=<number> log messages to file descriptor [2=stderr]\n"
1476" --log-file=<file> log messages to <file>.pid<pid>\n"
1477" --log-socket=ipaddr:port log messages to socket ipaddr:port\n"
nethercote2b0793f2003-12-02 10:41:18 +00001478" --demangle=no|yes automatically demangle C++ names? [yes]\n"
1479" --num-callers=<number> show <num> callers in stack traces [4]\n"
1480" --error-limit=no|yes stop showing new errors if too many? [yes]\n"
1481" --show-below-main=no|yes continue stack traces below main() [no]\n"
1482" --suppressions=<filename> suppress errors described in <filename>\n"
1483" --gen-suppressions=no|yes print suppressions for errors detected [no]\n"
nethercote04d0fbc2004-01-26 16:48:06 +00001484" --db-attach=no|yes start debugger when errors detected? [no]\n"
1485" --db-command=<command> command to start debugger [gdb -nw %%f %%p]\n"
1486" --input-fd=<number> file descriptor for input [0=stdin]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001487"\n";
njn7cf0bd32002-06-08 13:36:03 +00001488
njn25e49d8e72002-09-23 09:36:25 +00001489 Char* usage2 =
1490"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001491" debugging options for all Valgrind tools:\n"
njn25e49d8e72002-09-23 09:36:25 +00001492" --sanity-level=<number> level of sanity checking to do [1]\n"
1493" --single-step=no|yes translate each instr separately? [no]\n"
1494" --optimise=no|yes improve intermediate code? [yes]\n"
nethercote137bc552003-11-14 17:47:54 +00001495" --profile=no|yes profile? (tool must be built for it) [no]\n"
sewardj22854b92002-11-30 14:00:47 +00001496" --chain-bb=no|yes do basic-block chaining? [yes]\n"
fitzhardinge462f4f92003-12-18 02:10:54 +00001497" --branchpred=yes|no generate branch prediction hints [no]\n"
njn25e49d8e72002-09-23 09:36:25 +00001498" --trace-codegen=<XXXXX> show generated code? (X = 0|1) [00000]\n"
1499" --trace-syscalls=no|yes show all system calls? [no]\n"
1500" --trace-signals=no|yes show signal handling details? [no]\n"
1501" --trace-symtab=no|yes show symbol table details? [no]\n"
njn25e49d8e72002-09-23 09:36:25 +00001502" --trace-sched=no|yes show thread scheduler details? [no]\n"
njn3e884182003-04-15 13:03:23 +00001503" --trace-pthread=none|some|all show pthread event details? [none]\n"
jsgf855d93d2003-10-13 22:26:55 +00001504" --wait-for-gdb=yes|no pause on startup to wait for gdb attach\n"
njn25e49d8e72002-09-23 09:36:25 +00001505"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001506" debugging options for Valgrind tools that report errors\n"
1507" --dump-error=<number> show translation for basic block associated\n"
1508" with <number>'th error context [0=show none]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001509"\n";
njn3e884182003-04-15 13:03:23 +00001510
1511 Char* usage3 =
1512"\n"
nethercote71980f02004-01-24 18:18:54 +00001513" Extra options read from ~/.valgrindrc, $VALGRIND_OPTS, ./.valgrindrc\n"
njn25e49d8e72002-09-23 09:36:25 +00001514"\n"
nethercote08fa9a72004-07-16 17:44:00 +00001515" Valgrind is Copyright (C) 2000-2004 Julian Seward et al.\n"
njn25e49d8e72002-09-23 09:36:25 +00001516" and licensed under the GNU General Public License, version 2.\n"
1517" Bug reports, feedback, admiration, abuse, etc, to: %s.\n"
njnd04b7c62002-10-03 14:05:52 +00001518"\n"
nethercote137bc552003-11-14 17:47:54 +00001519" Tools are copyright and licensed by their authors. See each\n"
1520" tool's start-up message for more information.\n"
njn25e49d8e72002-09-23 09:36:25 +00001521"\n";
njn7cf0bd32002-06-08 13:36:03 +00001522
fitzhardinge98abfc72003-12-16 02:05:15 +00001523 VG_(printf)(usage1);
1524 if (VG_(details).name) {
1525 VG_(printf)(" user options for %s:\n", VG_(details).name);
fitzhardinge98abfc72003-12-16 02:05:15 +00001526 if (VG_(needs).command_line_options)
1527 SK_(print_usage)();
1528 else
1529 VG_(printf)(" (none)\n");
1530 }
nethercote6c999f22004-01-31 22:55:15 +00001531 if (debug_help) {
1532 VG_(printf)(usage2);
fitzhardinge98abfc72003-12-16 02:05:15 +00001533
nethercote6c999f22004-01-31 22:55:15 +00001534 if (VG_(details).name) {
1535 VG_(printf)(" debugging options for %s:\n", VG_(details).name);
1536
1537 if (VG_(needs).command_line_options)
1538 SK_(print_debug_usage)();
1539 else
1540 VG_(printf)(" (none)\n");
1541 }
fitzhardinge98abfc72003-12-16 02:05:15 +00001542 }
nethercote421281e2003-11-20 16:20:55 +00001543 VG_(printf)(usage3, VG_BUGS_TO);
nethercotef4928da2004-06-15 10:54:40 +00001544 VG_(exit)(0);
njn7cf0bd32002-06-08 13:36:03 +00001545}
sewardjde4a1d02002-03-22 01:27:54 +00001546
nethercote71980f02004-01-24 18:18:54 +00001547static void pre_process_cmd_line_options
nethercote6c999f22004-01-31 22:55:15 +00001548 ( Int* need_help, const char** tool, const char** exec )
sewardj1c1b1162003-02-23 01:25:51 +00001549{
nethercote71980f02004-01-24 18:18:54 +00001550 UInt i;
sewardjde4a1d02002-03-22 01:27:54 +00001551
nethercote71980f02004-01-24 18:18:54 +00001552 /* parse the options we have (only the options we care about now) */
nethercotef6a1d502004-08-09 12:21:57 +00001553 for (i = 1; i < vg_argc; i++) {
nethercote71980f02004-01-24 18:18:54 +00001554
nethercotef6a1d502004-08-09 12:21:57 +00001555 if (strcmp(vg_argv[i], "--version") == 0) {
nethercote71980f02004-01-24 18:18:54 +00001556 printf("valgrind-" VERSION "\n");
nethercotef4928da2004-06-15 10:54:40 +00001557 exit(0);
nethercote71980f02004-01-24 18:18:54 +00001558
nethercotef6a1d502004-08-09 12:21:57 +00001559 } else if (VG_CLO_STREQ(vg_argv[i], "--help") ||
1560 VG_CLO_STREQ(vg_argv[i], "-h")) {
nethercote6c999f22004-01-31 22:55:15 +00001561 *need_help = 1;
1562
nethercotef6a1d502004-08-09 12:21:57 +00001563 } else if (VG_CLO_STREQ(vg_argv[i], "--help-debug")) {
nethercote6c999f22004-01-31 22:55:15 +00001564 *need_help = 2;
nethercote71980f02004-01-24 18:18:54 +00001565
nethercotef6a1d502004-08-09 12:21:57 +00001566 } else if (VG_CLO_STREQN(7, vg_argv[i], "--tool=") ||
1567 VG_CLO_STREQN(7, vg_argv[i], "--skin=")) {
1568 *tool = &vg_argv[i][7];
nethercote71980f02004-01-24 18:18:54 +00001569
nethercotef6a1d502004-08-09 12:21:57 +00001570 } else if (VG_CLO_STREQN(7, vg_argv[i], "--exec=")) {
1571 *exec = &vg_argv[i][7];
nethercote71980f02004-01-24 18:18:54 +00001572 }
1573 }
1574
nethercotef4928da2004-06-15 10:54:40 +00001575 /* If no tool specified, can act appropriately without loading tool */
nethercote71980f02004-01-24 18:18:54 +00001576 if (*tool == NULL) {
nethercotef4928da2004-06-15 10:54:40 +00001577 if (0 == *need_help) {
1578 // neither --tool nor --help/--help-debug specified
1579 missing_tool_option();
1580 } else {
1581 // Give help message, without any tool-specific help
1582 usage(/*help-debug?*/2 == *need_help);
1583 }
nethercote71980f02004-01-24 18:18:54 +00001584 }
1585}
1586
nethercote5ee67ca2004-06-22 14:00:09 +00001587static void process_cmd_line_options( UInt* client_auxv, const char* toolname )
nethercote71980f02004-01-24 18:18:54 +00001588{
nethercotef8548672004-06-21 12:42:35 +00001589 Int i, eventually_log_fd;
nethercote71980f02004-01-24 18:18:54 +00001590 Int *auxp;
1591 Int toolname_len = VG_(strlen)(toolname);
sewardjde4a1d02002-03-22 01:27:54 +00001592
nethercotee1730692003-11-20 10:38:07 +00001593 /* log to stderr by default, but usage message goes to stdout */
nethercotef8548672004-06-21 12:42:35 +00001594 eventually_log_fd = 2;
sewardjde4a1d02002-03-22 01:27:54 +00001595
sewardj19d81412002-06-03 01:10:40 +00001596 /* Check for sane path in ./configure --prefix=... */
fitzhardinge98abfc72003-12-16 02:05:15 +00001597 if (VG_LIBDIR[0] != '/')
sewardj19d81412002-06-03 01:10:40 +00001598 config_error("Please use absolute paths in "
1599 "./configure --prefix=... or --libdir=...");
sewardj38170912002-05-10 21:07:22 +00001600
nethercote71980f02004-01-24 18:18:54 +00001601 for (auxp = client_auxv; auxp[0] != VKI_AT_NULL; auxp += 2) {
fitzhardinge98abfc72003-12-16 02:05:15 +00001602 switch(auxp[0]) {
1603 case VKI_AT_SYSINFO:
fitzhardinge92360792003-12-24 10:11:11 +00001604 auxp[1] = (Int)(VG_(client_trampoline_code) + VG_(tramp_syscall_offset));
fitzhardinge98abfc72003-12-16 02:05:15 +00001605 break;
sewardjde4a1d02002-03-22 01:27:54 +00001606 }
fitzhardinge98abfc72003-12-16 02:05:15 +00001607 }
sewardjde4a1d02002-03-22 01:27:54 +00001608
nethercotef6a1d502004-08-09 12:21:57 +00001609 for (i = 1; i < vg_argc; i++) {
nethercote71980f02004-01-24 18:18:54 +00001610
nethercotef6a1d502004-08-09 12:21:57 +00001611 Char* arg = vg_argv[i];
thughes3bfd5a02004-07-18 08:05:44 +00001612 Char* colon = arg;
nethercote71980f02004-01-24 18:18:54 +00001613
thughes3bfd5a02004-07-18 08:05:44 +00001614 /* Look for a colon in the switch name */
1615 while (*colon && *colon != ':' && *colon != '=')
1616 colon++;
nethercote71980f02004-01-24 18:18:54 +00001617
1618 /* Look for matching "--toolname:foo" */
thughes3bfd5a02004-07-18 08:05:44 +00001619 if (*colon == ':') {
nethercote71980f02004-01-24 18:18:54 +00001620 if (VG_CLO_STREQN(2, arg, "--") &&
1621 VG_CLO_STREQN(toolname_len, arg+2, toolname) &&
1622 VG_CLO_STREQN(1, arg+2+toolname_len, ":"))
1623 {
1624 // prefix matches, convert "--toolname:foo" to "--foo"
1625 if (0)
1626 VG_(printf)("tool-specific arg: %s\n", arg);
1627 arg += toolname_len + 1;
1628 arg[0] = '-';
1629 arg[1] = '-';
1630
1631 } else {
1632 // prefix doesn't match, skip to next arg
1633 continue;
1634 }
1635 }
1636
fitzhardinge98abfc72003-12-16 02:05:15 +00001637 /* Ignore these options - they've already been handled */
nethercote71980f02004-01-24 18:18:54 +00001638 if (VG_CLO_STREQN(7, arg, "--tool=") ||
1639 VG_CLO_STREQN(7, arg, "--skin="))
fitzhardinge98abfc72003-12-16 02:05:15 +00001640 continue;
nethercote71980f02004-01-24 18:18:54 +00001641 if (VG_CLO_STREQN(7, arg, "--exec="))
fitzhardinge98abfc72003-12-16 02:05:15 +00001642 continue;
1643
nethercote71980f02004-01-24 18:18:54 +00001644 if ( VG_CLO_STREQ(arg, "--"))
fitzhardinge98abfc72003-12-16 02:05:15 +00001645 continue;
nethercote27fec902004-06-16 21:26:32 +00001646
nethercote71980f02004-01-24 18:18:54 +00001647 else if (VG_CLO_STREQ(arg, "-v") ||
1648 VG_CLO_STREQ(arg, "--verbose"))
sewardjde4a1d02002-03-22 01:27:54 +00001649 VG_(clo_verbosity)++;
nethercote27fec902004-06-16 21:26:32 +00001650
nethercote71980f02004-01-24 18:18:54 +00001651 else if (VG_CLO_STREQ(arg, "-q") ||
1652 VG_CLO_STREQ(arg, "--quiet"))
sewardjde4a1d02002-03-22 01:27:54 +00001653 VG_(clo_verbosity)--;
1654
nethercote27fec902004-06-16 21:26:32 +00001655 else VG_BOOL_CLO("--branchpred", VG_(clo_branchpred))
1656 else VG_BOOL_CLO("--chain-bb", VG_(clo_chain_bb))
1657 else VG_BOOL_CLO("--db-attach", VG_(clo_db_attach))
1658 else VG_BOOL_CLO("--demangle", VG_(clo_demangle))
1659 else VG_BOOL_CLO("--error-limit", VG_(clo_error_limit))
1660 else VG_BOOL_CLO("--gen-suppressions", VG_(clo_gen_suppressions))
1661 else VG_BOOL_CLO("--lowlat-signals", VG_(clo_lowlat_signals))
1662 else VG_BOOL_CLO("--lowlat-syscalls", VG_(clo_lowlat_syscalls))
1663 else VG_BOOL_CLO("--optimise", VG_(clo_optimise))
1664 else VG_BOOL_CLO("--pointercheck", VG_(clo_pointercheck))
1665 else VG_BOOL_CLO("--profile", VG_(clo_profile))
1666 else VG_BOOL_CLO("--run-libc-freeres", VG_(clo_run_libc_freeres))
1667 else VG_BOOL_CLO("--show-below-main", VG_(clo_show_below_main))
1668 else VG_BOOL_CLO("--single-step", VG_(clo_single_step))
thughes6233a382004-08-21 11:10:44 +00001669 else VG_BOOL_CLO("--time-stamp", VG_(clo_time_stamp))
nethercote27fec902004-06-16 21:26:32 +00001670 else VG_BOOL_CLO("--track-fds", VG_(clo_track_fds))
1671 else VG_BOOL_CLO("--trace-children", VG_(clo_trace_children))
1672 else VG_BOOL_CLO("--trace-sched", VG_(clo_trace_sched))
1673 else VG_BOOL_CLO("--trace-signals", VG_(clo_trace_signals))
1674 else VG_BOOL_CLO("--trace-symtab", VG_(clo_trace_symtab))
1675 else VG_BOOL_CLO("--trace-syscalls", VG_(clo_trace_syscalls))
1676 else VG_BOOL_CLO("--wait-for-gdb", VG_(clo_wait_for_gdb))
sewardj72f98ff2002-06-13 17:23:38 +00001677
nethercote27fec902004-06-16 21:26:32 +00001678 else VG_STR_CLO ("--db-command", VG_(clo_db_command))
1679 else VG_STR_CLO ("--weird-hacks", VG_(clo_weird_hacks))
sewardjde4a1d02002-03-22 01:27:54 +00001680
nethercote27fec902004-06-16 21:26:32 +00001681 else VG_NUM_CLO ("--dump-error", VG_(clo_dump_error))
1682 else VG_NUM_CLO ("--input-fd", VG_(clo_input_fd))
1683 else VG_NUM_CLO ("--sanity-level", VG_(clo_sanity_level))
1684 else VG_NUM_CLO ("--signal­polltime", VG_(clo_signal_polltime))
1685 else VG_BNUM_CLO("--num-callers", VG_(clo_backtrace_size), 1,
1686 VG_DEEPEST_BACKTRACE)
sewardjde4a1d02002-03-22 01:27:54 +00001687
nethercotef8548672004-06-21 12:42:35 +00001688 // for backwards compatibility, replaced by --log-fd
nethercote71980f02004-01-24 18:18:54 +00001689 else if (VG_CLO_STREQN(13, arg, "--logfile-fd=")) {
nethercotef8548672004-06-21 12:42:35 +00001690 VG_(clo_log_to) = VgLogTo_Fd;
1691 VG_(clo_log_name) = NULL;
1692 eventually_log_fd = (Int)VG_(atoll)(&arg[13]);
1693 }
1694 else if (VG_CLO_STREQN(9, arg, "--log-fd=")) {
1695 VG_(clo_log_to) = VgLogTo_Fd;
1696 VG_(clo_log_name) = NULL;
1697 eventually_log_fd = (Int)VG_(atoll)(&arg[9]);
sewardj4cf05692002-10-27 20:28:29 +00001698 }
1699
nethercotef8548672004-06-21 12:42:35 +00001700 // for backwards compatibility, replaced by --log-file
nethercote71980f02004-01-24 18:18:54 +00001701 else if (VG_CLO_STREQN(10, arg, "--logfile=")) {
nethercotef8548672004-06-21 12:42:35 +00001702 VG_(clo_log_to) = VgLogTo_File;
1703 VG_(clo_log_name) = &arg[10];
1704 }
1705 else if (VG_CLO_STREQN(11, arg, "--log-file=")) {
1706 VG_(clo_log_to) = VgLogTo_File;
1707 VG_(clo_log_name) = &arg[11];
sewardj4cf05692002-10-27 20:28:29 +00001708 }
sewardjde4a1d02002-03-22 01:27:54 +00001709
nethercotef8548672004-06-21 12:42:35 +00001710 // for backwards compatibility, replaced by --log-socket
nethercote71980f02004-01-24 18:18:54 +00001711 else if (VG_CLO_STREQN(12, arg, "--logsocket=")) {
nethercotef8548672004-06-21 12:42:35 +00001712 VG_(clo_log_to) = VgLogTo_Socket;
1713 VG_(clo_log_name) = &arg[12];
1714 }
1715 else if (VG_CLO_STREQN(13, arg, "--log-socket=")) {
1716 VG_(clo_log_to) = VgLogTo_Socket;
1717 VG_(clo_log_name) = &arg[13];
sewardj73cf3bc2002-11-03 03:20:15 +00001718 }
1719
nethercote71980f02004-01-24 18:18:54 +00001720 else if (VG_CLO_STREQN(15, arg, "--suppressions=")) {
sewardjde4a1d02002-03-22 01:27:54 +00001721 if (VG_(clo_n_suppressions) >= VG_CLO_MAX_SFILES) {
njn25e49d8e72002-09-23 09:36:25 +00001722 VG_(message)(Vg_UserMsg, "Too many suppression files specified.");
sewardjde4a1d02002-03-22 01:27:54 +00001723 VG_(message)(Vg_UserMsg,
1724 "Increase VG_CLO_MAX_SFILES and recompile.");
nethercote71980f02004-01-24 18:18:54 +00001725 VG_(bad_option)(arg);
sewardjde4a1d02002-03-22 01:27:54 +00001726 }
nethercote71980f02004-01-24 18:18:54 +00001727 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = &arg[15];
sewardjde4a1d02002-03-22 01:27:54 +00001728 VG_(clo_n_suppressions)++;
1729 }
sewardjde4a1d02002-03-22 01:27:54 +00001730
njn25e49d8e72002-09-23 09:36:25 +00001731 /* "vwxyz" --> 000zyxwv (binary) */
nethercote71980f02004-01-24 18:18:54 +00001732 else if (VG_CLO_STREQN(16, arg, "--trace-codegen=")) {
njn25e49d8e72002-09-23 09:36:25 +00001733 Int j;
nethercote71980f02004-01-24 18:18:54 +00001734 char* opt = & arg[16];
njn25e49d8e72002-09-23 09:36:25 +00001735
1736 if (5 != VG_(strlen)(opt)) {
1737 VG_(message)(Vg_UserMsg,
1738 "--trace-codegen argument must have 5 digits");
nethercote71980f02004-01-24 18:18:54 +00001739 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001740 }
1741 for (j = 0; j < 5; j++) {
1742 if ('0' == opt[j]) { /* do nothing */ }
1743 else if ('1' == opt[j]) VG_(clo_trace_codegen) |= (1 << j);
1744 else {
1745 VG_(message)(Vg_UserMsg, "--trace-codegen argument can only "
1746 "contain 0s and 1s");
nethercote71980f02004-01-24 18:18:54 +00001747 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001748 }
1749 }
1750 }
sewardjde4a1d02002-03-22 01:27:54 +00001751
nethercote71980f02004-01-24 18:18:54 +00001752 else if (VG_CLO_STREQ(arg, "--trace-pthread=none"))
sewardj45b4b372002-04-16 22:50:32 +00001753 VG_(clo_trace_pthread_level) = 0;
nethercote71980f02004-01-24 18:18:54 +00001754 else if (VG_CLO_STREQ(arg, "--trace-pthread=some"))
sewardj45b4b372002-04-16 22:50:32 +00001755 VG_(clo_trace_pthread_level) = 1;
nethercote71980f02004-01-24 18:18:54 +00001756 else if (VG_CLO_STREQ(arg, "--trace-pthread=all"))
sewardj45b4b372002-04-16 22:50:32 +00001757 VG_(clo_trace_pthread_level) = 2;
sewardj8937c812002-04-12 20:12:20 +00001758
nethercote71980f02004-01-24 18:18:54 +00001759 else if ( ! VG_(needs).command_line_options
1760 || ! SK_(process_cmd_line_option)(arg) ) {
nethercotef4928da2004-06-15 10:54:40 +00001761 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001762 }
sewardjde4a1d02002-03-22 01:27:54 +00001763 }
1764
nethercote27fec902004-06-16 21:26:32 +00001765 // Check various option values
1766
njnf9ebf672003-05-12 21:41:30 +00001767 if (VG_(clo_verbosity) < 0)
sewardjde4a1d02002-03-22 01:27:54 +00001768 VG_(clo_verbosity) = 0;
1769
nethercote04d0fbc2004-01-26 16:48:06 +00001770 if (VG_(clo_db_attach) && VG_(clo_trace_children)) {
sewardjde4a1d02002-03-22 01:27:54 +00001771 VG_(message)(Vg_UserMsg, "");
1772 VG_(message)(Vg_UserMsg,
nethercote04d0fbc2004-01-26 16:48:06 +00001773 "--db-attach=yes conflicts with --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001774 VG_(message)(Vg_UserMsg,
1775 "Please choose one or the other, but not both.");
nethercote04d0fbc2004-01-26 16:48:06 +00001776 VG_(bad_option)("--db-attach=yes and --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001777 }
1778
nethercotef8548672004-06-21 12:42:35 +00001779 /* Set up logging now. After this is done, VG_(clo_log_fd)
sewardj4cf05692002-10-27 20:28:29 +00001780 should be connected to whatever sink has been selected, and we
1781 indiscriminately chuck stuff into it without worrying what the
1782 nature of it is. Oh the wonder of Unix streams. */
1783
nethercotee1730692003-11-20 10:38:07 +00001784 /* So far we should be still attached to stdout, so we can show on
sewardj4cf05692002-10-27 20:28:29 +00001785 the terminal any problems to do with processing command line
1786 opts. */
nethercotef8548672004-06-21 12:42:35 +00001787 vg_assert(VG_(clo_log_fd) == 1 /* stdout */);
sewardj73cf3bc2002-11-03 03:20:15 +00001788 vg_assert(VG_(logging_to_filedes) == True);
sewardj4cf05692002-10-27 20:28:29 +00001789
1790 switch (VG_(clo_log_to)) {
sewardj73cf3bc2002-11-03 03:20:15 +00001791
sewardj4cf05692002-10-27 20:28:29 +00001792 case VgLogTo_Fd:
nethercotef8548672004-06-21 12:42:35 +00001793 vg_assert(VG_(clo_log_name) == NULL);
1794 VG_(clo_log_fd) = eventually_log_fd;
sewardj4cf05692002-10-27 20:28:29 +00001795 break;
sewardj73cf3bc2002-11-03 03:20:15 +00001796
sewardj4cf05692002-10-27 20:28:29 +00001797 case VgLogTo_File: {
1798 Char logfilename[1000];
jsgff3c3f1a2003-10-14 22:13:28 +00001799 Int seq = 0;
1800 Int pid = VG_(getpid)();
1801
nethercotef8548672004-06-21 12:42:35 +00001802 vg_assert(VG_(clo_log_name) != NULL);
1803 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
jsgff3c3f1a2003-10-14 22:13:28 +00001804
nethercote71980f02004-01-24 18:18:54 +00001805 for (;;) {
jsgff3c3f1a2003-10-14 22:13:28 +00001806 if (seq == 0)
1807 VG_(sprintf)(logfilename, "%s.pid%d",
nethercotef8548672004-06-21 12:42:35 +00001808 VG_(clo_log_name), pid );
jsgff3c3f1a2003-10-14 22:13:28 +00001809 else
1810 VG_(sprintf)(logfilename, "%s.pid%d.%d",
nethercotef8548672004-06-21 12:42:35 +00001811 VG_(clo_log_name), pid, seq );
jsgff3c3f1a2003-10-14 22:13:28 +00001812 seq++;
1813
nethercotef8548672004-06-21 12:42:35 +00001814 eventually_log_fd
jsgff3c3f1a2003-10-14 22:13:28 +00001815 = VG_(open)(logfilename,
1816 VKI_O_CREAT|VKI_O_WRONLY|VKI_O_EXCL|VKI_O_TRUNC,
1817 VKI_S_IRUSR|VKI_S_IWUSR);
nethercotef8548672004-06-21 12:42:35 +00001818 if (eventually_log_fd >= 0) {
1819 VG_(clo_log_fd) = VG_(safe_fd)(eventually_log_fd);
jsgff3c3f1a2003-10-14 22:13:28 +00001820 break;
1821 } else {
nethercotef8548672004-06-21 12:42:35 +00001822 if (eventually_log_fd != -VKI_EEXIST) {
jsgff3c3f1a2003-10-14 22:13:28 +00001823 VG_(message)(Vg_UserMsg,
1824 "Can't create/open log file `%s.pid%d'; giving up!",
nethercotef8548672004-06-21 12:42:35 +00001825 VG_(clo_log_name), pid);
jsgff3c3f1a2003-10-14 22:13:28 +00001826 VG_(bad_option)(
nethercotef8548672004-06-21 12:42:35 +00001827 "--log-file=<file> didn't work out for some reason.");
jsgff3c3f1a2003-10-14 22:13:28 +00001828 break;
1829 }
1830 }
1831 }
sewardj4cf05692002-10-27 20:28:29 +00001832 break;
sewardj73cf3bc2002-11-03 03:20:15 +00001833 }
1834
1835 case VgLogTo_Socket: {
nethercotef8548672004-06-21 12:42:35 +00001836 vg_assert(VG_(clo_log_name) != NULL);
1837 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
1838 eventually_log_fd = VG_(connect_via_socket)( VG_(clo_log_name) );
1839 if (eventually_log_fd == -1) {
sewardj73cf3bc2002-11-03 03:20:15 +00001840 VG_(message)(Vg_UserMsg,
nethercotef8548672004-06-21 12:42:35 +00001841 "Invalid --log-socket=ipaddr or --log-socket=ipaddr:port spec");
sewardj73cf3bc2002-11-03 03:20:15 +00001842 VG_(message)(Vg_UserMsg,
nethercotef8548672004-06-21 12:42:35 +00001843 "of `%s'; giving up!", VG_(clo_log_name) );
sewardj73cf3bc2002-11-03 03:20:15 +00001844 VG_(bad_option)(
nethercotef8548672004-06-21 12:42:35 +00001845 "--log-socket=");
sewardj4cf05692002-10-27 20:28:29 +00001846 }
nethercotef8548672004-06-21 12:42:35 +00001847 if (eventually_log_fd == -2) {
sewardj73cf3bc2002-11-03 03:20:15 +00001848 VG_(message)(Vg_UserMsg,
sewardj570f8902002-11-03 11:44:36 +00001849 "valgrind: failed to connect to logging server `%s'.",
nethercotef8548672004-06-21 12:42:35 +00001850 VG_(clo_log_name) );
sewardj570f8902002-11-03 11:44:36 +00001851 VG_(message)(Vg_UserMsg,
1852 "Log messages will sent to stderr instead." );
1853 VG_(message)(Vg_UserMsg,
1854 "" );
1855 /* We don't change anything here. */
1856 } else {
nethercotef8548672004-06-21 12:42:35 +00001857 vg_assert(eventually_log_fd > 0);
1858 VG_(clo_log_fd) = eventually_log_fd;
sewardj570f8902002-11-03 11:44:36 +00001859 VG_(logging_to_filedes) = False;
1860 }
sewardj73cf3bc2002-11-03 03:20:15 +00001861 break;
1862 }
1863
sewardj4cf05692002-10-27 20:28:29 +00001864 }
1865
nethercotef8548672004-06-21 12:42:35 +00001866 /* Move log_fd into the safe range, so it doesn't conflict with any app fds */
thughesad1c9562004-06-26 11:27:52 +00001867 eventually_log_fd = VG_(fcntl)(VG_(clo_log_fd), VKI_F_DUPFD, VG_(fd_hard_limit));
nethercotef8548672004-06-21 12:42:35 +00001868 if (eventually_log_fd < 0)
jsgf855d93d2003-10-13 22:26:55 +00001869 VG_(message)(Vg_UserMsg, "valgrind: failed to move logfile fd into safe range");
1870 else {
nethercotef8548672004-06-21 12:42:35 +00001871 VG_(clo_log_fd) = eventually_log_fd;
1872 VG_(fcntl)(VG_(clo_log_fd), VKI_F_SETFD, VKI_FD_CLOEXEC);
jsgf855d93d2003-10-13 22:26:55 +00001873 }
1874
sewardj4cf05692002-10-27 20:28:29 +00001875 /* Ok, the logging sink is running now. Print a suitable preamble.
1876 If logging to file or a socket, write details of parent PID and
1877 command line args, to help people trying to interpret the
1878 results of a run which encompasses multiple processes. */
sewardjde4a1d02002-03-22 01:27:54 +00001879
sewardj83adf412002-05-01 01:25:45 +00001880 if (VG_(clo_verbosity > 0)) {
nethercote996901a2004-08-03 13:29:09 +00001881 /* Tool details */
nethercotea131bb82004-09-06 15:34:37 +00001882 VG_(message)(Vg_UserMsg, "%s%s%s, %s for %s.",
njnd04b7c62002-10-03 14:05:52 +00001883 VG_(details).name,
1884 NULL == VG_(details).version ? "" : "-",
1885 NULL == VG_(details).version
1886 ? (Char*)"" : VG_(details).version,
nethercotea131bb82004-09-06 15:34:37 +00001887 VG_(details).description,
1888 VG_PLATFORM);
njnd04b7c62002-10-03 14:05:52 +00001889 VG_(message)(Vg_UserMsg, "%s", VG_(details).copyright_author);
sewardj3b2736a2002-03-24 12:18:35 +00001890
njnd04b7c62002-10-03 14:05:52 +00001891 /* Core details */
1892 VG_(message)(Vg_UserMsg,
nethercotea131bb82004-09-06 15:34:37 +00001893 "Using valgrind-%s, a program supervision framework for %s.",
1894 VERSION, VG_PLATFORM);
sewardjde4a1d02002-03-22 01:27:54 +00001895 VG_(message)(Vg_UserMsg,
nethercote08fa9a72004-07-16 17:44:00 +00001896 "Copyright (C) 2000-2004, and GNU GPL'd, by Julian Seward et al.");
njnd04b7c62002-10-03 14:05:52 +00001897 }
1898
nethercotec1e395d2003-11-10 13:26:49 +00001899 if (VG_(clo_verbosity) > 0 && VG_(clo_log_to) != VgLogTo_Fd) {
sewardj4cf05692002-10-27 20:28:29 +00001900 VG_(message)(Vg_UserMsg, "");
1901 VG_(message)(Vg_UserMsg,
1902 "My PID = %d, parent PID = %d. Prog and args are:",
1903 VG_(getpid)(), VG_(getppid)() );
1904 for (i = 0; i < VG_(client_argc); i++)
1905 VG_(message)(Vg_UserMsg, " %s", VG_(client_argv)[i]);
1906 }
1907
sewardjde4a1d02002-03-22 01:27:54 +00001908 if (VG_(clo_verbosity) > 1) {
nethercotea70f7352004-04-18 12:08:46 +00001909 Int fd;
sewardj4cf05692002-10-27 20:28:29 +00001910 if (VG_(clo_log_to) != VgLogTo_Fd)
1911 VG_(message)(Vg_UserMsg, "");
fitzhardinge98abfc72003-12-16 02:05:15 +00001912 VG_(message)(Vg_UserMsg, "Valgrind library directory: %s", VG_(libdir));
njn86dc2bc2003-09-09 07:26:21 +00001913 VG_(message)(Vg_UserMsg, "Command line");
1914 for (i = 0; i < VG_(client_argc); i++)
1915 VG_(message)(Vg_UserMsg, " %s", VG_(client_argv)[i]);
1916
sewardjde4a1d02002-03-22 01:27:54 +00001917 VG_(message)(Vg_UserMsg, "Startup, with flags:");
nethercotef6a1d502004-08-09 12:21:57 +00001918 for (i = 1; i < vg_argc; i++) {
1919 VG_(message)(Vg_UserMsg, " %s", vg_argv[i]);
sewardjde4a1d02002-03-22 01:27:54 +00001920 }
nethercotea70f7352004-04-18 12:08:46 +00001921
1922 VG_(message)(Vg_UserMsg, "Contents of /proc/version:");
1923 fd = VG_(open) ( "/proc/version", VKI_O_RDONLY, 0 );
1924 if (fd < 0) {
1925 VG_(message)(Vg_UserMsg, " can't open /proc/version");
1926 } else {
1927 #define BUF_LEN 256
1928 Char version_buf[BUF_LEN];
1929 Int n = VG_(read) ( fd, version_buf, BUF_LEN );
1930 vg_assert(n <= 256);
1931 if (n > 0) {
1932 version_buf[n-1] = '\0';
1933 VG_(message)(Vg_UserMsg, " %s", version_buf);
1934 } else {
1935 VG_(message)(Vg_UserMsg, " (empty?)");
1936 }
1937 VG_(close)(fd);
1938 #undef BUF_LEN
1939 }
sewardjde4a1d02002-03-22 01:27:54 +00001940 }
1941
fitzhardinge98abfc72003-12-16 02:05:15 +00001942 if (VG_(clo_n_suppressions) < VG_CLO_MAX_SFILES-1 &&
njn25e49d8e72002-09-23 09:36:25 +00001943 (VG_(needs).core_errors || VG_(needs).skin_errors)) {
nethercote996901a2004-08-03 13:29:09 +00001944 /* If there are no suppression files specified and the tool
fitzhardinge98abfc72003-12-16 02:05:15 +00001945 needs one, load the default */
1946 static const Char default_supp[] = "default.supp";
1947 Int len = VG_(strlen)(VG_(libdir)) + 1 + sizeof(default_supp);
1948 Char *buf = VG_(arena_malloc)(VG_AR_CORE, len);
1949 VG_(sprintf)(buf, "%s/%s", VG_(libdir), default_supp);
1950 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = buf;
1951 VG_(clo_n_suppressions)++;
sewardjde4a1d02002-03-22 01:27:54 +00001952 }
sewardj4cf05692002-10-27 20:28:29 +00001953
njn6a230532003-07-21 10:38:23 +00001954 if (VG_(clo_gen_suppressions) &&
1955 !VG_(needs).core_errors && !VG_(needs).skin_errors) {
nethercotef4928da2004-06-15 10:54:40 +00001956 VG_(message)(Vg_UserMsg,
1957 "Can't use --gen-suppressions=yes with this tool,");
1958 VG_(message)(Vg_UserMsg,
1959 "as it doesn't generate errors.");
1960 VG_(bad_option)("--gen-suppressions=yes");
njn6a230532003-07-21 10:38:23 +00001961 }
sewardjde4a1d02002-03-22 01:27:54 +00001962}
1963
nethercotef6a1d502004-08-09 12:21:57 +00001964// Build the string for VALGRINDCLO.
1965Char* VG_(build_child_VALGRINDCLO)( Char* exename )
1966{
1967 /* If we're tracing the children, then we need to start it
1968 with our starter+arguments, which are copied into VALGRINDCLO,
1969 except the --exec= option is changed if present.
1970 */
1971 Int i;
1972 Char *exec;
1973 Char *cp;
1974 Char *optvar;
1975 Int optlen, execlen;
1976
1977 // All these allocated blocks are not free - because we're either
1978 // going to exec, or panic when we fail.
1979
1980 // Create --exec= option: "--exec=<exename>"
1981 exec = VG_(arena_malloc)(VG_AR_CORE,
1982 VG_(strlen)( exename ) + 7/*--exec=*/ + 1/*\0*/);
1983 vg_assert(NULL != exec);
1984 VG_(sprintf)(exec, "--exec=%s", exename);
1985
1986 // Allocate space for optvar (may overestimate by counting --exec twice,
1987 // no matter)
1988 optlen = 1;
1989 for (i = 0; i < vg_argc; i++)
1990 optlen += VG_(strlen)(vg_argv[i]) + 1;
1991 optlen += VG_(strlen)(exec)+1;
1992 optvar = VG_(arena_malloc)(VG_AR_CORE, optlen);
1993
1994 // Copy all valgrind args except the old --exec (if present)
1995 // VG_CLO_SEP is the separator.
1996 cp = optvar;
1997 for (i = 1; i < vg_argc; i++) {
1998 Char *arg = vg_argv[i];
1999
2000 if (VG_(memcmp)(arg, "--exec=", 7) == 0) {
2001 // don't copy existing --exec= arg
2002 } else if (VG_(strcmp)(arg, "--") == 0) {
2003 // stop at "--"
2004 break;
2005 } else {
2006 // copy non "--exec" arg
2007 Int len = VG_(strlen)(arg);
2008 VG_(memcpy)(cp, arg, len);
2009 cp += len;
2010 *cp++ = VG_CLO_SEP;
2011 }
2012 }
2013 // Add the new --exec= option
2014 execlen = VG_(strlen)(exec);
2015 VG_(memcpy)(cp, exec, execlen);
2016 cp += execlen;
2017 *cp++ = VG_CLO_SEP;
2018
2019 *cp = '\0';
2020
2021 return optvar;
2022}
2023
2024// Build "/proc/self/fd/<execfd>".
2025Char* VG_(build_child_exename)( void )
2026{
2027 Char* exename = VG_(arena_malloc)(VG_AR_CORE, 64);
2028 vg_assert(NULL != exename);
2029 VG_(sprintf)(exename, "/proc/self/fd/%d", vgexecfd);
2030 return exename;
2031}
2032
sewardjde4a1d02002-03-22 01:27:54 +00002033
nethercote71980f02004-01-24 18:18:54 +00002034/*====================================================================*/
2035/*=== File descriptor setup ===*/
2036/*====================================================================*/
2037
2038static void setup_file_descriptors(void)
2039{
2040 struct vki_rlimit rl;
2041
2042 /* Get the current file descriptor limits. */
2043 if (VG_(getrlimit)(VKI_RLIMIT_NOFILE, &rl) < 0) {
2044 rl.rlim_cur = 1024;
2045 rl.rlim_max = 1024;
2046 }
2047
2048 /* Work out where to move the soft limit to. */
2049 if (rl.rlim_cur + VG_N_RESERVED_FDS <= rl.rlim_max) {
2050 rl.rlim_cur = rl.rlim_cur + VG_N_RESERVED_FDS;
2051 } else {
2052 rl.rlim_cur = rl.rlim_max;
2053 }
2054
2055 /* Reserve some file descriptors for our use. */
thughesad1c9562004-06-26 11:27:52 +00002056 VG_(fd_soft_limit) = rl.rlim_cur - VG_N_RESERVED_FDS;
2057 VG_(fd_hard_limit) = rl.rlim_cur - VG_N_RESERVED_FDS;
nethercote71980f02004-01-24 18:18:54 +00002058
2059 /* Update the soft limit. */
2060 VG_(setrlimit)(VKI_RLIMIT_NOFILE, &rl);
2061
nethercotef6a1d502004-08-09 12:21:57 +00002062 if (vgexecfd != -1)
2063 vgexecfd = VG_(safe_fd)( vgexecfd );
nethercote71980f02004-01-24 18:18:54 +00002064 if (VG_(clexecfd) != -1)
2065 VG_(clexecfd) = VG_(safe_fd)( VG_(clexecfd) );
2066}
2067
2068
2069/*====================================================================*/
nethercote1d447092004-02-01 17:29:59 +00002070/*=== baseBlock: definition + setup ===*/
nethercote71980f02004-01-24 18:18:54 +00002071/*====================================================================*/
2072
nethercote71980f02004-01-24 18:18:54 +00002073Int VGOFF_(helper_undefined_instruction) = INVALID_OFFSET;
2074
2075/* MAX_NONCOMPACT_HELPERS can be increased easily. If MAX_COMPACT_HELPERS is
2076 * increased too much, they won't really be compact any more... */
2077#define MAX_COMPACT_HELPERS 8
2078#define MAX_NONCOMPACT_HELPERS 50
2079
nethercote81f9a6f2004-08-03 15:45:46 +00002080/* For storing tool-specific helpers, determined at runtime. The addr
2081 * and offset arrays together form a (addr, offset) map that allows a
2082 * helper's baseBlock offset to be computed from its address. It's done
2083 * like this so CCALLs can use the function address rather than having to
2084 * muck around with offsets. */
2085static UInt VG_(n_compact_helpers) = 0;
2086static UInt VG_(n_noncompact_helpers) = 0;
2087static Addr VG_(compact_helper_addrs) [MAX_COMPACT_HELPERS];
2088static Int VG_(compact_helper_offsets)[MAX_COMPACT_HELPERS];
2089static Addr VG_(noncompact_helper_addrs) [MAX_NONCOMPACT_HELPERS];
2090static Int VG_(noncompact_helper_offsets)[MAX_NONCOMPACT_HELPERS];
nethercote71980f02004-01-24 18:18:54 +00002091
2092/* This is the actual defn of baseblock. */
2093UInt VG_(baseBlock)[VG_BASEBLOCK_WORDS];
2094
nethercote71980f02004-01-24 18:18:54 +00002095/* Words. */
2096static Int baB_off = 0;
2097
2098
nethercote71980f02004-01-24 18:18:54 +00002099/* Returns the offset, in words. */
nethercote2e05c332004-09-06 16:43:37 +00002100Int VG_(alloc_BaB) ( Int words )
sewardjde4a1d02002-03-22 01:27:54 +00002101{
nethercote71980f02004-01-24 18:18:54 +00002102 Int off = baB_off;
2103 baB_off += words;
2104 if (baB_off >= VG_BASEBLOCK_WORDS)
nethercote2e05c332004-09-06 16:43:37 +00002105 VG_(core_panic)( "VG_(alloc_BaB): baseBlock is too small");
sewardjde4a1d02002-03-22 01:27:54 +00002106
nethercote71980f02004-01-24 18:18:54 +00002107 return off;
sewardjde4a1d02002-03-22 01:27:54 +00002108}
2109
nethercote71980f02004-01-24 18:18:54 +00002110/* Align offset, in *bytes* */
nethercote2e05c332004-09-06 16:43:37 +00002111void VG_(align_BaB) ( UInt align )
njn25e49d8e72002-09-23 09:36:25 +00002112{
nethercote71980f02004-01-24 18:18:54 +00002113 vg_assert(2 == align || 4 == align || 8 == align || 16 == align);
2114 baB_off += (align-1);
2115 baB_off &= ~(align-1);
njn25e49d8e72002-09-23 09:36:25 +00002116}
2117
nethercote71980f02004-01-24 18:18:54 +00002118/* Allocate 1 word in baseBlock and set it to the given value. */
nethercote2e05c332004-09-06 16:43:37 +00002119Int VG_(alloc_BaB_1_set) ( Addr a )
njn25e49d8e72002-09-23 09:36:25 +00002120{
nethercote2e05c332004-09-06 16:43:37 +00002121 Int off = VG_(alloc_BaB)(1);
nethercote71980f02004-01-24 18:18:54 +00002122 VG_(baseBlock)[off] = (UInt)a;
2123 return off;
njn25e49d8e72002-09-23 09:36:25 +00002124}
2125
nethercote71980f02004-01-24 18:18:54 +00002126/* Registers a function in compact_helper_addrs; compact_helper_offsets is
2127 filled in later. */
2128void VG_(register_compact_helper)(Addr a)
sewardjde4a1d02002-03-22 01:27:54 +00002129{
nethercote71980f02004-01-24 18:18:54 +00002130 if (MAX_COMPACT_HELPERS <= VG_(n_compact_helpers)) {
2131 VG_(printf)("Can only register %d compact helpers\n",
2132 MAX_COMPACT_HELPERS);
2133 VG_(core_panic)("Too many compact helpers registered");
2134 }
2135 VG_(compact_helper_addrs)[VG_(n_compact_helpers)] = a;
2136 VG_(n_compact_helpers)++;
2137}
2138
2139/* Registers a function in noncompact_helper_addrs; noncompact_helper_offsets
2140 * is filled in later.
2141 */
2142void VG_(register_noncompact_helper)(Addr a)
2143{
2144 if (MAX_NONCOMPACT_HELPERS <= VG_(n_noncompact_helpers)) {
2145 VG_(printf)("Can only register %d non-compact helpers\n",
2146 MAX_NONCOMPACT_HELPERS);
2147 VG_(printf)("Try increasing MAX_NON_COMPACT_HELPERS\n");
2148 VG_(core_panic)("Too many non-compact helpers registered");
2149 }
2150 VG_(noncompact_helper_addrs)[VG_(n_noncompact_helpers)] = a;
2151 VG_(n_noncompact_helpers)++;
2152}
2153
nethercote996901a2004-08-03 13:29:09 +00002154/* Allocate offsets in baseBlock for the tool helpers */
nethercote71980f02004-01-24 18:18:54 +00002155static
2156void assign_helpers_in_baseBlock(UInt n, Int offsets[], Addr addrs[])
2157{
2158 UInt i;
2159 for (i = 0; i < n; i++)
nethercote2e05c332004-09-06 16:43:37 +00002160 offsets[i] = VG_(alloc_BaB_1_set)( addrs[i] );
nethercote71980f02004-01-24 18:18:54 +00002161}
2162
2163Bool VG_(need_to_handle_esp_assignment)(void)
2164{
2165 return ( VG_(defined_new_mem_stack_4)() ||
2166 VG_(defined_die_mem_stack_4)() ||
2167 VG_(defined_new_mem_stack_8)() ||
2168 VG_(defined_die_mem_stack_8)() ||
2169 VG_(defined_new_mem_stack_12)() ||
2170 VG_(defined_die_mem_stack_12)() ||
2171 VG_(defined_new_mem_stack_16)() ||
2172 VG_(defined_die_mem_stack_16)() ||
2173 VG_(defined_new_mem_stack_32)() ||
2174 VG_(defined_die_mem_stack_32)() ||
2175 VG_(defined_new_mem_stack)() ||
2176 VG_(defined_die_mem_stack)()
2177 );
2178}
2179
nethercote2e05c332004-09-06 16:43:37 +00002180// The low/high split is for x86, so that the more common helpers can be
2181// in the first 128 bytes of the start, which allows the use of a more
2182// compact addressing mode.
nethercote71980f02004-01-24 18:18:54 +00002183static void init_baseBlock ( Addr client_eip, Addr esp_at_startup )
2184{
nethercote2e05c332004-09-06 16:43:37 +00002185 VGA_(init_low_baseBlock)(client_eip, esp_at_startup);
nethercote71980f02004-01-24 18:18:54 +00002186
nethercote71980f02004-01-24 18:18:54 +00002187 /* Allocate slots for compact helpers */
2188 assign_helpers_in_baseBlock(VG_(n_compact_helpers),
2189 VG_(compact_helper_offsets),
2190 VG_(compact_helper_addrs));
2191
nethercote2e05c332004-09-06 16:43:37 +00002192 VGA_(init_high_baseBlock)(client_eip, esp_at_startup);
fitzhardingef0046f22003-12-18 02:39:22 +00002193
nethercote71980f02004-01-24 18:18:54 +00002194#define REG(kind, size) \
2195 if (VG_(defined_##kind##_mem_stack##size)()) \
2196 VG_(register_noncompact_helper)( \
2197 (Addr) VG_(tool_interface).track_##kind##_mem_stack##size );
2198 REG(new, _8);
2199 REG(new, _12);
2200 REG(new, _16);
2201 REG(new, _32);
2202 REG(new, );
2203 REG(die, _8);
2204 REG(die, _12);
2205 REG(die, _16);
2206 REG(die, _32);
2207 REG(die, );
2208#undef REG
fitzhardingef0046f22003-12-18 02:39:22 +00002209
nethercote71980f02004-01-24 18:18:54 +00002210 if (VG_(need_to_handle_esp_assignment)())
2211 VG_(register_noncompact_helper)((Addr) VG_(unknown_esp_update));
fitzhardingeb791a192003-12-18 07:22:44 +00002212
nethercote2e05c332004-09-06 16:43:37 +00002213 VGOFF_(helper_undefined_instruction)
2214 = VG_(alloc_BaB_1_set)( (Addr) & VG_(helper_undefined_instruction));
sewardjde4a1d02002-03-22 01:27:54 +00002215
nethercote71980f02004-01-24 18:18:54 +00002216 /* Allocate slots for noncompact helpers */
2217 assign_helpers_in_baseBlock(VG_(n_noncompact_helpers),
2218 VG_(noncompact_helper_offsets),
2219 VG_(noncompact_helper_addrs));
2220}
sewardjde4a1d02002-03-22 01:27:54 +00002221
nethercote81f9a6f2004-08-03 15:45:46 +00002222// Finds the baseBlock offset of a tool-specified helper.
2223// Searches through compacts first, then non-compacts.
2224Int VG_(helper_offset)(Addr a)
2225{
2226 UInt i;
2227 Char buf[100];
2228
2229 for (i = 0; i < VG_(n_compact_helpers); i++)
2230 if (VG_(compact_helper_addrs)[i] == a)
2231 return VG_(compact_helper_offsets)[i];
2232 for (i = 0; i < VG_(n_noncompact_helpers); i++)
2233 if (VG_(noncompact_helper_addrs)[i] == a)
2234 return VG_(noncompact_helper_offsets)[i];
2235
2236 /* Shouldn't get here */
2237 VG_(get_fnname) ( a, buf, 100 );
2238
2239 VG_(printf)(
2240 "\nCouldn't find offset of helper from its address (%p: %s).\n"
2241 "A helper function probably used hasn't been registered?\n\n", a, buf);
2242
2243 VG_(printf)(" compact helpers: ");
2244 for (i = 0; i < VG_(n_compact_helpers); i++)
2245 VG_(printf)("%p ", VG_(compact_helper_addrs)[i]);
2246
2247 VG_(printf)("\n non-compact helpers: ");
2248 for (i = 0; i < VG_(n_noncompact_helpers); i++)
2249 VG_(printf)("%p ", VG_(noncompact_helper_addrs)[i]);
2250
2251 VG_(printf)("\n");
2252 VG_(skin_panic)("Unfound helper");
2253}
2254
sewardj5f07b662002-04-23 16:52:51 +00002255
nethercote71980f02004-01-24 18:18:54 +00002256/*====================================================================*/
nethercote71980f02004-01-24 18:18:54 +00002257/*=== Initialise program data/text, etc. ===*/
2258/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +00002259
nethercote71980f02004-01-24 18:18:54 +00002260static void build_valgrind_map_callback
2261 ( Addr start, UInt size, Char rr, Char ww, Char xx,
2262 UInt dev, UInt ino, ULong foffset, const UChar* filename )
sewardjde4a1d02002-03-22 01:27:54 +00002263{
nethercote71980f02004-01-24 18:18:54 +00002264 UInt prot = 0;
2265 UInt flags = SF_MMAP|SF_NOSYMS;
2266 Bool is_stack_segment;
2267
2268 is_stack_segment =
2269 (start == VG_(clstk_base) && (start+size) == VG_(clstk_end));
2270
2271 /* Only record valgrind mappings for now, without loading any
2272 symbols. This is so we know where the free space is before we
2273 start allocating more memory (note: heap is OK, it's just mmap
2274 which is the problem here). */
nethercote820bd8c2004-09-07 23:04:49 +00002275 if (start >= VG_(valgrind_base) && (start+size-1) <= VG_(valgrind_last)) {
nethercote71980f02004-01-24 18:18:54 +00002276 flags |= SF_VALGRIND;
2277 VG_(map_file_segment)(start, size, prot, flags, dev, ino, foffset, filename);
2278 }
sewardjde4a1d02002-03-22 01:27:54 +00002279}
2280
nethercote71980f02004-01-24 18:18:54 +00002281// Global var used to pass local data to callback
2282Addr esp_at_startup___global_arg = 0;
sewardjde4a1d02002-03-22 01:27:54 +00002283
nethercote71980f02004-01-24 18:18:54 +00002284static void build_segment_map_callback
2285 ( Addr start, UInt size, Char rr, Char ww, Char xx,
2286 UInt dev, UInt ino, ULong foffset, const UChar* filename )
sewardj45b672d2003-07-25 19:58:11 +00002287{
nethercote71980f02004-01-24 18:18:54 +00002288 UInt prot = 0;
2289 UInt flags;
2290 Bool is_stack_segment;
2291 Addr r_esp;
sewardj45b672d2003-07-25 19:58:11 +00002292
nethercote71980f02004-01-24 18:18:54 +00002293 is_stack_segment
2294 = (start == VG_(clstk_base) && (start+size) == VG_(clstk_end));
fitzhardinge98abfc72003-12-16 02:05:15 +00002295
nethercote71980f02004-01-24 18:18:54 +00002296 if (rr == 'r') prot |= VKI_PROT_READ;
2297 if (ww == 'w') prot |= VKI_PROT_WRITE;
2298 if (xx == 'x') prot |= VKI_PROT_EXEC;
fitzhardinge98abfc72003-12-16 02:05:15 +00002299
nethercote71980f02004-01-24 18:18:54 +00002300 if (is_stack_segment)
2301 flags = SF_STACK | SF_GROWDOWN;
2302 else
2303 flags = SF_EXEC|SF_MMAP;
fitzhardinge98abfc72003-12-16 02:05:15 +00002304
nethercote71980f02004-01-24 18:18:54 +00002305 if (filename != NULL)
2306 flags |= SF_FILE;
fitzhardinge98abfc72003-12-16 02:05:15 +00002307
nethercote820bd8c2004-09-07 23:04:49 +00002308 if (start >= VG_(valgrind_base) && (start+size-1) <= VG_(valgrind_last))
nethercote71980f02004-01-24 18:18:54 +00002309 flags |= SF_VALGRIND;
fitzhardinge98abfc72003-12-16 02:05:15 +00002310
nethercote71980f02004-01-24 18:18:54 +00002311 VG_(map_file_segment)(start, size, prot, flags, dev, ino, foffset, filename);
fitzhardinge98abfc72003-12-16 02:05:15 +00002312
nethercote71980f02004-01-24 18:18:54 +00002313 if (VG_(is_client_addr)(start) && VG_(is_client_addr)(start+size-1))
2314 VG_TRACK( new_mem_startup, start, size, rr=='r', ww=='w', xx=='x' );
sewardj3e1eb1f2002-05-18 13:14:17 +00002315
nethercote71980f02004-01-24 18:18:54 +00002316 /* If this is the stack segment mark all below %esp as noaccess. */
2317 r_esp = esp_at_startup___global_arg;
2318 vg_assert(0 != r_esp);
2319 if (is_stack_segment) {
2320 if (0)
2321 VG_(message)(Vg_DebugMsg, "invalidating stack area: %x .. %x",
2322 start,r_esp);
2323 VG_TRACK( die_mem_stack, start, r_esp-start );
sewardjde4a1d02002-03-22 01:27:54 +00002324 }
sewardjde4a1d02002-03-22 01:27:54 +00002325}
2326
2327
nethercote71980f02004-01-24 18:18:54 +00002328/*====================================================================*/
2329/*=== Sanity check machinery (permanently engaged) ===*/
2330/*====================================================================*/
njn25e49d8e72002-09-23 09:36:25 +00002331
2332/* A fast sanity check -- suitable for calling circa once per
2333 millisecond. */
2334
nethercote885dd912004-08-03 23:14:00 +00002335void VG_(sanity_check_general) ( Bool force_expensive )
njn25e49d8e72002-09-23 09:36:25 +00002336{
njn37cea302002-09-30 11:24:00 +00002337 VGP_PUSHCC(VgpCoreCheapSanity);
2338
nethercote27fec902004-06-16 21:26:32 +00002339 if (VG_(clo_sanity_level) < 1) return;
njn25e49d8e72002-09-23 09:36:25 +00002340
2341 /* --- First do all the tests that we can do quickly. ---*/
2342
nethercote297effd2004-08-02 15:07:57 +00002343 sanity_fast_count++;
njn25e49d8e72002-09-23 09:36:25 +00002344
njn25e49d8e72002-09-23 09:36:25 +00002345 /* Check stuff pertaining to the memory check system. */
2346
2347 /* Check that nobody has spuriously claimed that the first or
2348 last 16 pages of memory have become accessible [...] */
njn37cea302002-09-30 11:24:00 +00002349 if (VG_(needs).sanity_checks) {
2350 VGP_PUSHCC(VgpSkinCheapSanity);
njn25e49d8e72002-09-23 09:36:25 +00002351 vg_assert(SK_(cheap_sanity_check)());
njn37cea302002-09-30 11:24:00 +00002352 VGP_POPCC(VgpSkinCheapSanity);
2353 }
njn25e49d8e72002-09-23 09:36:25 +00002354
2355 /* --- Now some more expensive checks. ---*/
2356
2357 /* Once every 25 times, check some more expensive stuff. */
2358 if ( force_expensive
nethercote27fec902004-06-16 21:26:32 +00002359 || VG_(clo_sanity_level) > 1
nethercote297effd2004-08-02 15:07:57 +00002360 || (VG_(clo_sanity_level) == 1 && (sanity_fast_count % 25) == 0)) {
njn25e49d8e72002-09-23 09:36:25 +00002361
njn37cea302002-09-30 11:24:00 +00002362 VGP_PUSHCC(VgpCoreExpensiveSanity);
nethercote297effd2004-08-02 15:07:57 +00002363 sanity_slow_count++;
njn25e49d8e72002-09-23 09:36:25 +00002364
nethercote885dd912004-08-03 23:14:00 +00002365 VG_(sanity_check_proxy)();
jsgf855d93d2003-10-13 22:26:55 +00002366
njn25e49d8e72002-09-23 09:36:25 +00002367# if 0
2368 { void zzzmemscan(void); zzzmemscan(); }
2369# endif
2370
nethercote297effd2004-08-02 15:07:57 +00002371 if ((sanity_fast_count % 250) == 0)
nethercote92e7b7f2004-08-07 17:52:25 +00002372 VG_(sanity_check_tt_tc)();
njn25e49d8e72002-09-23 09:36:25 +00002373
2374 if (VG_(needs).sanity_checks) {
njn37cea302002-09-30 11:24:00 +00002375 VGP_PUSHCC(VgpSkinExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002376 vg_assert(SK_(expensive_sanity_check)());
njn37cea302002-09-30 11:24:00 +00002377 VGP_POPCC(VgpSkinExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002378 }
2379 /*
nethercote297effd2004-08-02 15:07:57 +00002380 if ((sanity_fast_count % 500) == 0) VG_(mallocSanityCheckAll)();
njn25e49d8e72002-09-23 09:36:25 +00002381 */
njn37cea302002-09-30 11:24:00 +00002382 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002383 }
2384
nethercote27fec902004-06-16 21:26:32 +00002385 if (VG_(clo_sanity_level) > 1) {
njn37cea302002-09-30 11:24:00 +00002386 VGP_PUSHCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002387 /* Check sanity of the low-level memory manager. Note that bugs
2388 in the client's code can cause this to fail, so we don't do
2389 this check unless specially asked for. And because it's
2390 potentially very expensive. */
nethercote885dd912004-08-03 23:14:00 +00002391 VG_(sanity_check_malloc_all)();
njn37cea302002-09-30 11:24:00 +00002392 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002393 }
njn37cea302002-09-30 11:24:00 +00002394 VGP_POPCC(VgpCoreCheapSanity);
njn25e49d8e72002-09-23 09:36:25 +00002395}
nethercote71980f02004-01-24 18:18:54 +00002396
2397
2398/*====================================================================*/
2399/*=== main() ===*/
2400/*====================================================================*/
2401
nethercotec314eba2004-07-15 12:59:41 +00002402/*
2403 This code decides on the layout of the client and Valgrind address
nethercote996901a2004-08-03 13:29:09 +00002404 spaces, loads valgrind.so and the tool.so into the valgrind part,
nethercotec314eba2004-07-15 12:59:41 +00002405 loads the client executable (and the dynamic linker, if necessary)
2406 into the client part, and calls into Valgrind proper.
2407
2408 The code is careful not to allow spurious mappings to appear in the
2409 wrong parts of the address space. In particular, to make sure
2410 dlopen puts things in the right place, it will pad out the forbidden
2411 chunks of address space so that dlopen is forced to put things where
2412 we want them.
2413
2414 The memory map it creates is:
2415
2416 CLIENT_BASE +-------------------------+
2417 | client address space |
2418 : :
2419 : :
2420 | client stack |
2421 client_end +-------------------------+
2422 | redzone |
2423 shadow_base +-------------------------+
2424 | |
nethercote996901a2004-08-03 13:29:09 +00002425 : shadow memory for tools :
nethercotec314eba2004-07-15 12:59:41 +00002426 | (may be 0 sized) |
2427 shadow_end +-------------------------+
nethercotec314eba2004-07-15 12:59:41 +00002428 valgrind_base +-------------------------+
2429 | kickstart executable |
2430 | valgrind heap vvvvvvvvv| (barely used)
2431 - -
2432 | valgrind .so files |
2433 | and mappings |
2434 - -
2435 | valgrind stack ^^^^^^^^^|
nethercote820bd8c2004-09-07 23:04:49 +00002436 valgrind_last +-------------------------+
nethercotec314eba2004-07-15 12:59:41 +00002437 : kernel :
2438
2439 Nb: Before we can do general allocations with VG_(arena_malloc)() and
2440 VG_(mmap)(), we need to build the segment skip-list, so we know where
2441 we can put things. However, building that structure requires
2442 allocating memory. So we need to a bootstrapping process. It's done
2443 by making VG_(arena_malloc)() have a special static superblock that's
2444 used for the first 1MB's worth of allocations. This is enough to
2445 build the segment skip-list.
2446*/
2447
nethercote31779c72004-07-30 21:50:15 +00002448static int prmap(char *start, char *end, const char *perm, off_t off,
2449 int maj, int min, int ino, void* dummy) {
thughes4ad52d02004-06-27 17:37:21 +00002450 printf("mapping %10p-%10p %s %02x:%02x %d\n",
2451 start, end, perm, maj, min, ino);
2452 return True;
2453}
2454
nethercote71980f02004-01-24 18:18:54 +00002455int main(int argc, char **argv)
2456{
2457 char **cl_argv;
2458 const char *tool = NULL;
2459 const char *exec = NULL;
2460 char *preload; /* tool-specific LD_PRELOAD .so */
2461 char **env;
nethercote6c999f22004-01-31 22:55:15 +00002462 Int need_help = 0; // 0 = no, 1 = --help, 2 = --help-debug
nethercote71980f02004-01-24 18:18:54 +00002463 struct exeinfo info;
2464 ToolInfo *toolinfo = NULL;
2465 void *tool_dlhandle;
2466 Addr client_eip;
2467 Addr esp_at_startup; /* client's %esp at the point we gained control. */
2468 UInt * client_auxv;
2469 VgSchedReturnCode src;
nethercote47dd12c2004-06-22 14:18:42 +00002470 Int exitcode = 0;
nethercote238a3c32004-08-09 13:13:31 +00002471 Int fatal_sigNo = -1;
fitzhardingeb50068f2004-02-24 23:42:55 +00002472 vki_rlimit zero = { 0, 0 };
nethercote31779c72004-07-30 21:50:15 +00002473 Int padfile;
nethercote759dda32004-08-07 18:16:56 +00002474 ThreadId last_run_tid = 0; // Last thread the scheduler ran.
2475
nethercote71980f02004-01-24 18:18:54 +00002476
2477 //============================================================
2478 // Nb: startup is complex. Prerequisites are shown at every step.
2479 //
2480 // *** Be very careful when messing with the order ***
2481 //============================================================
2482
nethercotef4928da2004-06-15 10:54:40 +00002483 //============================================================
2484 // Command line argument handling order:
2485 // * If --help/--help-debug are present, show usage message
2486 // (if --tool is also present, that includes the tool-specific usage)
2487 // * Then, if --tool is missing, abort with error msg
2488 // * Then, if client is missing, abort with error msg
2489 // * Then, if any cmdline args are bad, abort with error msg
2490 //============================================================
2491
fitzhardingeb50068f2004-02-24 23:42:55 +00002492 // Get the current process datasize rlimit, and set it to zero.
2493 // This prevents any internal uses of brk() from having any effect.
2494 // We remember the old value so we can restore it on exec, so that
2495 // child processes will have a reasonable brk value.
2496 VG_(getrlimit)(VKI_RLIMIT_DATA, &VG_(client_rlimit_data));
2497 zero.rlim_max = VG_(client_rlimit_data).rlim_max;
2498 VG_(setrlimit)(VKI_RLIMIT_DATA, &zero);
2499
nethercote71980f02004-01-24 18:18:54 +00002500 //--------------------------------------------------------------
2501 // Check we were launched by stage1
nethercotec314eba2004-07-15 12:59:41 +00002502 // p: n/a
nethercote71980f02004-01-24 18:18:54 +00002503 //--------------------------------------------------------------
nethercote31779c72004-07-30 21:50:15 +00002504 padfile = scan_auxv();
nethercote71980f02004-01-24 18:18:54 +00002505
2506 if (0) {
nethercote71980f02004-01-24 18:18:54 +00002507 printf("========== main() ==========\n");
nethercote31779c72004-07-30 21:50:15 +00002508 foreach_map(prmap, /*dummy*/NULL);
nethercote71980f02004-01-24 18:18:54 +00002509 }
2510
2511 //--------------------------------------------------------------
2512 // Look for alternative libdir
2513 // p: n/a
2514 //--------------------------------------------------------------
2515 { char *cp = getenv(VALGRINDLIB);
2516 if (cp != NULL)
2517 VG_(libdir) = cp;
2518 }
2519
2520 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002521 // Get valgrind args + client args (inc. from VALGRIND_OPTS/.valgrindrc).
2522 // Pre-process the command line.
2523 // p: n/a
2524 //--------------------------------------------------------------
nethercotef6a1d502004-08-09 12:21:57 +00002525 get_command_line(argc, argv, &vg_argc, &vg_argv, &cl_argv);
nethercote71980f02004-01-24 18:18:54 +00002526 pre_process_cmd_line_options(&need_help, &tool, &exec);
2527
2528 //==============================================================
2529 // Nb: once a tool is specified, the tool.so must be loaded even if
2530 // they specified --help or didn't specify a client program.
2531 //==============================================================
2532
2533 //--------------------------------------------------------------
2534 // With client padded out, map in tool
nethercote71980f02004-01-24 18:18:54 +00002535 // p: set-libdir [for VG_(libdir)]
2536 // p: pre_process_cmd_line_options() [for 'tool']
2537 //--------------------------------------------------------------
2538 load_tool(tool, &tool_dlhandle, &toolinfo, &preload);
2539
2540 //==============================================================
2541 // Can use VG_(malloc)() and VG_(arena_malloc)() only after load_tool()
nethercotec314eba2004-07-15 12:59:41 +00002542 // -- redzone size is now set. This is checked by vg_malloc2.c.
nethercote71980f02004-01-24 18:18:54 +00002543 //==============================================================
2544
2545 //--------------------------------------------------------------
2546 // Finalise address space layout
nethercote31779c72004-07-30 21:50:15 +00002547 // p: load_tool() [for 'toolinfo']
nethercote71980f02004-01-24 18:18:54 +00002548 //--------------------------------------------------------------
nethercote31779c72004-07-30 21:50:15 +00002549 layout_remaining_space( (Addr) & argc, toolinfo->shadow_ratio );
nethercote71980f02004-01-24 18:18:54 +00002550
2551 //--------------------------------------------------------------
2552 // Load client executable, finding in $PATH if necessary
nethercote71980f02004-01-24 18:18:54 +00002553 // p: pre_process_cmd_line_options() [for 'exec', 'need_help']
2554 // p: layout_remaining_space [so there's space]
2555 //--------------------------------------------------------------
nethercotef4928da2004-06-15 10:54:40 +00002556 load_client(cl_argv, exec, need_help, &info, &client_eip);
nethercote71980f02004-01-24 18:18:54 +00002557
2558 //--------------------------------------------------------------
2559 // Everything in place, unpad us
2560 // p: layout_remaining_space() [everything must be mapped in before now]
2561 // p: load_client() [ditto]
2562 //--------------------------------------------------------------
nethercote31779c72004-07-30 21:50:15 +00002563 as_unpad((void *)VG_(shadow_end), (void *)~0, padfile);
2564 as_closepadfile(padfile); // no more padding
nethercote71980f02004-01-24 18:18:54 +00002565
2566 //--------------------------------------------------------------
2567 // Set up client's environment
2568 // p: set-libdir [for VG_(libdir)]
2569 // p: load_tool() [for 'preload']
2570 //--------------------------------------------------------------
2571 env = fix_environment(environ, preload);
2572
2573 //--------------------------------------------------------------
nethercote5ee67ca2004-06-22 14:00:09 +00002574 // Setup client stack, eip, and VG_(client_arg[cv])
nethercote71980f02004-01-24 18:18:54 +00002575 // p: load_client() [for 'info']
2576 // p: fix_environment() [for 'env']
2577 //--------------------------------------------------------------
2578 esp_at_startup = setup_client_stack(cl_argv, env, &info, &client_auxv);
2579
2580 if (0)
nethercote6a27d832004-09-07 10:17:02 +00002581 printf("entry=%p client esp=%p vg_argc=%d brkbase=%p\n",
2582 (void*)client_eip, (void*)esp_at_startup, vg_argc,
2583 (void*)VG_(brk_base));
nethercote71980f02004-01-24 18:18:54 +00002584
2585 //==============================================================
2586 // Finished setting up operating environment. Now initialise
2587 // Valgrind. (This is where the old VG_(main)() started.)
2588 //==============================================================
2589
2590 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002591 // atfork
2592 // p: n/a
2593 //--------------------------------------------------------------
2594 VG_(atfork)(NULL, NULL, newpid);
2595 newpid(VG_INVALID_THREADID);
2596
2597 //--------------------------------------------------------------
2598 // setup file descriptors
2599 // p: n/a
2600 //--------------------------------------------------------------
2601 setup_file_descriptors();
2602
2603 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002604 // Read /proc/self/maps into a buffer
2605 // p: all memory layout, environment setup [so memory maps are right]
2606 //--------------------------------------------------------------
2607 VG_(read_procselfmaps)();
2608
2609 //--------------------------------------------------------------
2610 // Build segment map (Valgrind segments only)
2611 // p: read proc/self/maps
2612 // p: sk_pre_clo_init() [to setup new_mem_startup tracker]
2613 //--------------------------------------------------------------
2614 VG_(parse_procselfmaps) ( build_valgrind_map_callback );
2615
2616 //==============================================================
2617 // Can use VG_(arena_malloc)() with non-CORE arena after segments set up
2618 //==============================================================
2619
2620 //--------------------------------------------------------------
2621 // Init tool: pre_clo_init, process cmd line, post_clo_init
2622 // p: setup_client_stack() [for 'VG_(client_arg[cv]']
2623 // p: load_tool() [for 'tool']
2624 // p: setup_file_descriptors() [for 'VG_(fd_xxx_limit)']
2625 // p: parse_procselfmaps [so VG segments are setup so tool can
2626 // call VG_(malloc)]
nethercote71980f02004-01-24 18:18:54 +00002627 //--------------------------------------------------------------
2628 (*toolinfo->sk_pre_clo_init)();
2629 VG_(tool_init_dlsym)(tool_dlhandle);
2630 VG_(sanity_check_needs)();
2631
nethercotef4928da2004-06-15 10:54:40 +00002632 // If --tool and --help/--help-debug was given, now give the core+tool
2633 // help message
nethercotef4928da2004-06-15 10:54:40 +00002634 if (need_help) {
2635 usage(/*--help-debug?*/2 == need_help);
2636 }
nethercotec314eba2004-07-15 12:59:41 +00002637 process_cmd_line_options(client_auxv, tool);
2638
2639 SK_(post_clo_init)();
nethercotef4928da2004-06-15 10:54:40 +00002640
2641 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002642 // Build segment map (all segments)
2643 // p: setup_client_stack() [for 'esp_at_startup']
2644 // p: init tool [for 'new_mem_startup']
nethercote71980f02004-01-24 18:18:54 +00002645 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002646 esp_at_startup___global_arg = esp_at_startup;
2647 VG_(parse_procselfmaps) ( build_segment_map_callback ); /* everything */
2648 esp_at_startup___global_arg = 0;
2649
2650 //--------------------------------------------------------------
nethercotef84f6952004-07-15 14:58:33 +00002651 // Protect client trampoline page (which is also sysinfo stuff)
2652 // p: segment stuff [otherwise get seg faults...]
nethercotec314eba2004-07-15 12:59:41 +00002653 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002654 VG_(mprotect)( (void *)VG_(client_trampoline_code),
2655 VG_(trampoline_code_length), VKI_PROT_READ|VKI_PROT_EXEC );
2656
2657 //==============================================================
2658 // Can use VG_(map)() after segments set up
2659 //==============================================================
nethercote71980f02004-01-24 18:18:54 +00002660
2661 //--------------------------------------------------------------
2662 // Allow GDB attach
2663 // p: process_cmd_line_options() [for VG_(clo_wait_for_gdb)]
2664 //--------------------------------------------------------------
2665 /* Hook to delay things long enough so we can get the pid and
2666 attach GDB in another shell. */
2667 if (VG_(clo_wait_for_gdb)) {
2668 VG_(printf)("pid=%d\n", VG_(getpid)());
2669 /* do "jump *$eip" to skip this in gdb */
2670 VG_(do_syscall)(__NR_pause);
2671 }
2672
2673 //--------------------------------------------------------------
nethercote1d447092004-02-01 17:29:59 +00002674 // Set up baseBlock
nethercote71980f02004-01-24 18:18:54 +00002675 // p: {pre,post}_clo_init() [for tool helper registration]
2676 // load_client() [for 'client_eip']
2677 // setup_client_stack() [for 'esp_at_startup']
2678 //--------------------------------------------------------------
2679 init_baseBlock(client_eip, esp_at_startup);
2680
2681 //--------------------------------------------------------------
2682 // Search for file descriptors that are inherited from our parent
2683 // p: process_cmd_line_options [for VG_(clo_track_fds)]
2684 //--------------------------------------------------------------
2685 if (VG_(clo_track_fds))
2686 VG_(init_preopened_fds)();
2687
2688 //--------------------------------------------------------------
2689 // Initialise the scheduler
2690 // p: init_baseBlock() [baseBlock regs copied into VG_(threads)[1]]
2691 // p: setup_file_descriptors() [else VG_(safe_fd)() breaks]
2692 //--------------------------------------------------------------
2693 VG_(scheduler_init)();
2694
2695 //--------------------------------------------------------------
2696 // Set up the ProxyLWP machinery
2697 // p: VG_(scheduler_init)()? [XXX: subtle dependency?]
nethercote71980f02004-01-24 18:18:54 +00002698 //--------------------------------------------------------------
2699 VG_(proxy_init)();
2700
2701 //--------------------------------------------------------------
2702 // Initialise the signal handling subsystem
2703 // p: VG_(atfork)(NULL, NULL, newpid) [else problems with sigmasks]
2704 // p: VG_(proxy_init)() [else breaks...]
2705 //--------------------------------------------------------------
2706 // Nb: temporarily parks the saved blocking-mask in saved_sigmask.
2707 VG_(sigstartup_actions)();
2708
2709 //--------------------------------------------------------------
2710 // Perhaps we're profiling Valgrind?
2711 // p: process_cmd_line_options() [for VG_(clo_profile)]
2712 // p: others?
2713 //
2714 // XXX: this seems to be broken? It always says the tool wasn't built
2715 // for profiling; vg_profile.c's functions don't seem to be overriding
2716 // vg_dummy_profile.c's?
2717 //
2718 // XXX: want this as early as possible. Looking for --profile
2719 // in pre_process_cmd_line_options() could get it earlier.
2720 //--------------------------------------------------------------
2721 if (VG_(clo_profile))
2722 VGP_(init_profiling)();
2723
2724 VGP_PUSHCC(VgpStartup);
2725
2726 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002727 // Read suppression file
2728 // p: process_cmd_line_options() [for VG_(clo_suppressions)]
2729 //--------------------------------------------------------------
2730 if (VG_(needs).core_errors || VG_(needs).skin_errors)
2731 VG_(load_suppressions)();
2732
2733 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002734 // Initialise translation table and translation cache
2735 // p: read_procselfmaps [so the anonymous mmaps for the TT/TC
2736 // aren't identified as part of the client, which would waste
2737 // > 20M of virtual address space.]
2738 //--------------------------------------------------------------
2739 VG_(init_tt_tc)();
2740
2741 //--------------------------------------------------------------
2742 // Read debug info to find glibc entry points to intercept
2743 // p: parse_procselfmaps? [XXX for debug info?]
2744 // p: init_tt_tc? [XXX ???]
2745 //--------------------------------------------------------------
2746 VG_(setup_code_redirect_table)();
2747
2748 //--------------------------------------------------------------
2749 // Verbosity message
2750 // p: end_rdtsc_calibration [so startup message is printed first]
2751 //--------------------------------------------------------------
2752 if (VG_(clo_verbosity) == 1)
2753 VG_(message)(Vg_UserMsg, "For more details, rerun with: -v");
2754 if (VG_(clo_verbosity) > 0)
2755 VG_(message)(Vg_UserMsg, "");
2756
2757 //--------------------------------------------------------------
2758 // Setup pointercheck
2759 // p: process_cmd_line_options() [for VG_(clo_pointercheck)]
2760 //--------------------------------------------------------------
nethercote775508a2004-09-07 22:38:23 +00002761 if (VG_(clo_pointercheck))
2762 VG_(clo_pointercheck) = VGA_(setup_pointercheck)();
nethercote71980f02004-01-24 18:18:54 +00002763
nethercote71980f02004-01-24 18:18:54 +00002764 //--------------------------------------------------------------
2765 // Run!
2766 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002767 VGP_POPCC(VgpStartup);
2768 VGP_PUSHCC(VgpSched);
2769
nethercote238a3c32004-08-09 13:13:31 +00002770 src = VG_(scheduler)( &exitcode, &last_run_tid, &fatal_sigNo );
nethercote71980f02004-01-24 18:18:54 +00002771
nethercote238a3c32004-08-09 13:13:31 +00002772 VGP_POPCC(VgpSched);
nethercote71980f02004-01-24 18:18:54 +00002773
2774
2775 //--------------------------------------------------------------
2776 // Finalisation: cleanup, messages, etc. Order no so important, only
2777 // affects what order the messages come.
2778 //--------------------------------------------------------------
2779 if (VG_(clo_verbosity) > 0)
2780 VG_(message)(Vg_UserMsg, "");
2781
2782 if (src == VgSrc_Deadlock) {
2783 VG_(message)(Vg_UserMsg,
2784 "Warning: pthread scheduler exited due to deadlock");
2785 }
2786
2787 /* Print out file descriptor summary and stats. */
2788 if (VG_(clo_track_fds))
nethercote3a42fb82004-08-03 18:08:50 +00002789 VG_(show_open_fds)();
nethercote71980f02004-01-24 18:18:54 +00002790
2791 if (VG_(needs).core_errors || VG_(needs).skin_errors)
2792 VG_(show_all_errors)();
2793
nethercote47dd12c2004-06-22 14:18:42 +00002794 SK_(fini)( exitcode );
nethercote71980f02004-01-24 18:18:54 +00002795
nethercote885dd912004-08-03 23:14:00 +00002796 VG_(sanity_check_general)( True /*include expensive checks*/ );
nethercote71980f02004-01-24 18:18:54 +00002797
2798 if (VG_(clo_verbosity) > 1)
nethercote3a42fb82004-08-03 18:08:50 +00002799 print_all_stats();
nethercote71980f02004-01-24 18:18:54 +00002800
nethercote71980f02004-01-24 18:18:54 +00002801 if (VG_(clo_profile))
2802 VGP_(done_profiling)();
2803
nethercote71980f02004-01-24 18:18:54 +00002804 /* We're exiting, so nuke all the threads and clean up the proxy LWPs */
2805 vg_assert(src == VgSrc_FatalSig ||
nethercote759dda32004-08-07 18:16:56 +00002806 VG_(threads)[last_run_tid].status == VgTs_Runnable ||
2807 VG_(threads)[last_run_tid].status == VgTs_WaitJoiner);
nethercote71980f02004-01-24 18:18:54 +00002808 VG_(nuke_all_threads_except)(VG_INVALID_THREADID);
2809
2810 //--------------------------------------------------------------
2811 // Exit, according to the scheduler's return code
2812 //--------------------------------------------------------------
2813 switch (src) {
2814 case VgSrc_ExitSyscall: /* the normal way out */
nethercote759dda32004-08-07 18:16:56 +00002815 vg_assert(last_run_tid > 0 && last_run_tid < VG_N_THREADS);
nethercote71980f02004-01-24 18:18:54 +00002816 VG_(proxy_shutdown)();
2817
2818 /* The thread's %EBX at the time it did __NR_exit() will hold
2819 the arg to __NR_exit(), so we just do __NR_exit() with
2820 that arg. */
nethercote47dd12c2004-06-22 14:18:42 +00002821 VG_(exit)( exitcode );
nethercote71980f02004-01-24 18:18:54 +00002822 /* NOT ALIVE HERE! */
2823 VG_(core_panic)("entered the afterlife in main() -- ExitSyscall");
2824 break; /* what the hell :) */
2825
2826 case VgSrc_Deadlock:
2827 /* Just exit now. No point in continuing. */
2828 VG_(proxy_shutdown)();
2829 VG_(exit)(0);
2830 VG_(core_panic)("entered the afterlife in main() -- Deadlock");
2831 break;
2832
nethercote71980f02004-01-24 18:18:54 +00002833 case VgSrc_FatalSig:
2834 /* We were killed by a fatal signal, so replicate the effect */
nethercote238a3c32004-08-09 13:13:31 +00002835 vg_assert(fatal_sigNo != -1);
2836 VG_(kill_self)(fatal_sigNo);
nethercote71980f02004-01-24 18:18:54 +00002837 VG_(core_panic)("main(): signal was supposed to be fatal");
2838 break;
2839
2840 default:
2841 VG_(core_panic)("main(): unexpected scheduler return code");
2842 }
2843
2844 abort();
2845}
2846
2847
sewardjde4a1d02002-03-22 01:27:54 +00002848/*--------------------------------------------------------------------*/
2849/*--- end vg_main.c ---*/
2850/*--------------------------------------------------------------------*/