blob: cbe991f4c93fba86aaa257730c0204d8ead64bab [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"
nethercote71980f02004-01-24 18:18:54 +000035
36#include <dirent.h>
37#include <dlfcn.h>
38#include <errno.h>
nethercote71980f02004-01-24 18:18:54 +000039#include <stdio.h>
fitzhardingeb727d042004-01-06 00:18:21 +000040#include <stdlib.h>
nethercote71980f02004-01-24 18:18:54 +000041#include <string.h>
42#include <sys/mman.h>
nethercote71980f02004-01-24 18:18:54 +000043#include <sys/stat.h>
fitzhardingeb727d042004-01-06 00:18:21 +000044#include <sys/ptrace.h>
fitzhardingeb727d042004-01-06 00:18:21 +000045#include <sys/wait.h>
46#include <unistd.h>
47
thughes74b8de22004-04-22 18:12:31 +000048#ifndef AT_DCACHEBSIZE
49#define AT_DCACHEBSIZE 19
50#endif /* AT_DCACHEBSIZE */
51
52#ifndef AT_ICACHEBSIZE
53#define AT_ICACHEBSIZE 20
54#endif /* AT_ICACHEBSIZE */
55
56#ifndef AT_UCACHEBSIZE
57#define AT_UCACHEBSIZE 21
58#endif /* AT_UCACHEBSIZE */
59
nethercote71980f02004-01-24 18:18:54 +000060#ifndef AT_SYSINFO
61#define AT_SYSINFO 32
62#endif /* AT_SYSINFO */
63
64#ifndef AT_SYSINFO_EHDR
65#define AT_SYSINFO_EHDR 33
66#endif /* AT_SYSINFO_EHDR */
67
68#ifndef AT_SECURE
69#define AT_SECURE 23 /* secure mode boolean */
70#endif /* AT_SECURE */
71
nethercote71980f02004-01-24 18:18:54 +000072/* redzone gap between client address space and shadow */
73#define REDZONE_SIZE (1 * 1024*1024)
74
75/* size multiple for client address space */
nethercotee94b2de2004-06-23 16:15:06 +000076#define CLIENT_SIZE_MULTIPLE (1 * 1024*1024)
nethercote71980f02004-01-24 18:18:54 +000077
nethercotee2097312004-06-27 12:29:56 +000078/* Proportion of client space for its heap (rest is for mmaps + stack) */
79#define CLIENT_HEAP_PROPORTION 0.333
nethercote71980f02004-01-24 18:18:54 +000080
81/*====================================================================*/
82/*=== Global entities not referenced from generated code ===*/
83/*====================================================================*/
84
sewardjde4a1d02002-03-22 01:27:54 +000085/* ---------------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +000086 Startup stuff
sewardjde4a1d02002-03-22 01:27:54 +000087 ------------------------------------------------------------------ */
88
nethercote71980f02004-01-24 18:18:54 +000089/* Client address space, lowest to highest (see top of ume.c) */
90Addr VG_(client_base); /* client address space limits */
fitzhardinge98abfc72003-12-16 02:05:15 +000091Addr VG_(client_end);
92Addr VG_(client_mapbase);
fitzhardinge92360792003-12-24 10:11:11 +000093Addr VG_(client_trampoline_code);
fitzhardinge98abfc72003-12-16 02:05:15 +000094Addr VG_(clstk_base);
95Addr VG_(clstk_end);
nethercote71980f02004-01-24 18:18:54 +000096
97Addr VG_(brk_base); /* start of brk */
98Addr VG_(brk_limit); /* current brk */
99
nethercote996901a2004-08-03 13:29:09 +0000100Addr VG_(shadow_base); /* tool's shadow memory */
fitzhardinge98abfc72003-12-16 02:05:15 +0000101Addr VG_(shadow_end);
nethercote71980f02004-01-24 18:18:54 +0000102
103Addr VG_(valgrind_base); /* valgrind's address range */
rjwalsh18b66312004-08-23 18:15:12 +0000104
nethercote820bd8c2004-09-07 23:04:49 +0000105// Note that VG_(valgrind_last) names the last byte of the section, whereas
106// the VG_(*_end) vars name the byte one past the end of the section.
107Addr VG_(valgrind_last);
fitzhardinge98abfc72003-12-16 02:05:15 +0000108
nethercote73b526f2004-10-31 18:48:21 +0000109struct vki_rlimit VG_(client_rlimit_data);
110struct vki_rlimit VG_(client_rlimit_stack);
fitzhardingeb50068f2004-02-24 23:42:55 +0000111
nethercote71980f02004-01-24 18:18:54 +0000112/* This is set early to indicate whether this CPU has the
113 SSE/fxsave/fxrestor features. */
114Bool VG_(have_ssestate);
115
fitzhardinge98abfc72003-12-16 02:05:15 +0000116/* stage1 (main) executable */
nethercotef6a1d502004-08-09 12:21:57 +0000117static Int vgexecfd = -1;
fitzhardingea49f9b52003-12-16 22:26:45 +0000118
119/* client executable */
120Int VG_(clexecfd) = -1;
fitzhardinge98abfc72003-12-16 02:05:15 +0000121
122/* Path to library directory */
123const Char *VG_(libdir) = VG_LIBDIR;
124
125/* our argc/argv */
nethercotef6a1d502004-08-09 12:21:57 +0000126static Int vg_argc;
127static Char **vg_argv;
fitzhardinge98abfc72003-12-16 02:05:15 +0000128
jsgf855d93d2003-10-13 22:26:55 +0000129/* PID of the main thread */
130Int VG_(main_pid);
131
132/* PGRP of process */
133Int VG_(main_pgrp);
njn25e49d8e72002-09-23 09:36:25 +0000134
thughesad1c9562004-06-26 11:27:52 +0000135/* Application-visible file descriptor limits */
136Int VG_(fd_soft_limit) = -1;
137Int VG_(fd_hard_limit) = -1;
fitzhardingef0046f22003-12-18 02:39:22 +0000138
nethercote4ad74312004-10-26 09:59:49 +0000139/* As deduced from sp_at_startup, the client's argc, argv[] and
nethercote71980f02004-01-24 18:18:54 +0000140 envp[] as extracted from the client's stack at startup-time. */
141Int VG_(client_argc);
142Char** VG_(client_argv);
143Char** VG_(client_envp);
sewardjde4a1d02002-03-22 01:27:54 +0000144
145/* ---------------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +0000146 Running stuff
sewardjde4a1d02002-03-22 01:27:54 +0000147 ------------------------------------------------------------------ */
sewardjde4a1d02002-03-22 01:27:54 +0000148
nethercote71980f02004-01-24 18:18:54 +0000149/* Counts downwards in VG_(run_innerloop). */
150UInt VG_(dispatch_ctr);
sewardjde4a1d02002-03-22 01:27:54 +0000151
152/* 64-bit counter for the number of basic blocks done. */
153ULong VG_(bbs_done);
sewardjde4a1d02002-03-22 01:27:54 +0000154
nethercote71980f02004-01-24 18:18:54 +0000155/* Tell the logging mechanism whether we are logging to a file
156 descriptor or a socket descriptor. */
157Bool VG_(logging_to_filedes) = True;
158
sewardj73cf3bc2002-11-03 03:20:15 +0000159
nethercote71980f02004-01-24 18:18:54 +0000160/*====================================================================*/
161/*=== Counters, for profiling purposes only ===*/
162/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +0000163
nethercote92e7b7f2004-08-07 17:52:25 +0000164// These ones maintained by vg_dispatch.S
165UInt VG_(bb_enchain_count) = 0; // Number of chain operations done
166UInt VG_(bb_dechain_count) = 0; // Number of unchain operations done
167UInt VG_(unchained_jumps_done) = 0; // Number of unchained jumps done
sewardjde4a1d02002-03-22 01:27:54 +0000168
sewardjde4a1d02002-03-22 01:27:54 +0000169/* Counts pertaining to internal sanity checking. */
nethercote297effd2004-08-02 15:07:57 +0000170static UInt sanity_fast_count = 0;
171static UInt sanity_slow_count = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000172
nethercote3a42fb82004-08-03 18:08:50 +0000173static void print_all_stats ( void )
nethercote71980f02004-01-24 18:18:54 +0000174{
nethercote3a42fb82004-08-03 18:08:50 +0000175 // Translation stats
nethercote92e7b7f2004-08-07 17:52:25 +0000176 VG_(print_tt_tc_stats)();
nethercote71980f02004-01-24 18:18:54 +0000177 VG_(message)(Vg_DebugMsg,
nethercote92e7b7f2004-08-07 17:52:25 +0000178 "chainings: %d chainings, %d unchainings.",
nethercote71980f02004-01-24 18:18:54 +0000179 VG_(bb_enchain_count), VG_(bb_dechain_count) );
180 VG_(message)(Vg_DebugMsg,
nethercote3a42fb82004-08-03 18:08:50 +0000181 " dispatch: %llu jumps (bb entries); of them %u (%lu%%) unchained.",
nethercote71980f02004-01-24 18:18:54 +0000182 VG_(bbs_done),
183 VG_(unchained_jumps_done),
184 ((ULong)(100) * (ULong)(VG_(unchained_jumps_done)))
185 / ( VG_(bbs_done)==0 ? 1 : VG_(bbs_done) )
186 );
187
nethercote3a42fb82004-08-03 18:08:50 +0000188 // Scheduler stats
nethercote844e7122004-08-02 15:27:22 +0000189 VG_(print_scheduler_stats)();
nethercote71980f02004-01-24 18:18:54 +0000190
nethercote3a42fb82004-08-03 18:08:50 +0000191 // Reg-alloc stats
nethercotebee3fd92004-08-02 15:17:43 +0000192 VG_(print_reg_alloc_stats)();
nethercote71980f02004-01-24 18:18:54 +0000193 VG_(message)(Vg_DebugMsg,
194 " sanity: %d cheap, %d expensive checks.",
nethercote297effd2004-08-02 15:07:57 +0000195 sanity_fast_count, sanity_slow_count );
nethercote3a42fb82004-08-03 18:08:50 +0000196
197 // C call stats
nethercote71980f02004-01-24 18:18:54 +0000198 VG_(print_ccall_stats)();
nethercote3a42fb82004-08-03 18:08:50 +0000199
200 // UInstr histogram
201 if (VG_(clo_verbosity) > 3)
202 VG_(print_UInstr_histogram)();
203
204 // Memory stats
nethercote885dd912004-08-03 23:14:00 +0000205 if (VG_(clo_verbosity) > 2) {
nethercote3a42fb82004-08-03 18:08:50 +0000206 VG_(message)(Vg_DebugMsg, "");
207 VG_(message)(Vg_DebugMsg,
208 "------ Valgrind's internal memory use stats follow ------" );
nethercote885dd912004-08-03 23:14:00 +0000209 VG_(sanity_check_malloc_all)();
nethercote3a42fb82004-08-03 18:08:50 +0000210 VG_(print_all_arena_stats)();
nethercote885dd912004-08-03 23:14:00 +0000211 VG_(message)(Vg_DebugMsg, "");
nethercote3a42fb82004-08-03 18:08:50 +0000212 VG_(message)(Vg_DebugMsg,
213 "------ Valgrind's ExeContext management stats follow ------" );
214 VG_(print_ExeContext_stats)();
215 }
nethercote71980f02004-01-24 18:18:54 +0000216}
217
218
219/*====================================================================*/
220/*=== Miscellaneous global functions ===*/
221/*====================================================================*/
222
nethercotecf97ffb2004-09-09 13:40:31 +0000223static Int ptrace_setregs(Int pid, ThreadId tid)
224{
225 if (VG_(is_running_thread)( tid ))
226 return VGA_(ptrace_setregs_from_BB)(pid);
227 else
228 return VGA_(ptrace_setregs_from_tst)(pid, &VG_(threads)[tid].arch);
229}
230
nethercote04d0fbc2004-01-26 16:48:06 +0000231/* Start debugger and get it to attach to this process. Called if the
232 user requests this service after an error has been shown, so she can
nethercote71980f02004-01-24 18:18:54 +0000233 poke around and look at parameters, memory, etc. You can't
nethercote04d0fbc2004-01-26 16:48:06 +0000234 meaningfully get the debugger to continue the program, though; to
235 continue, quit the debugger. */
236void VG_(start_debugger) ( Int tid )
nethercote71980f02004-01-24 18:18:54 +0000237{
238 Int pid;
239
240 if ((pid = fork()) == 0) {
241 ptrace(PTRACE_TRACEME, 0, NULL, NULL);
nethercote73b526f2004-10-31 18:48:21 +0000242 VG_(kill)(VG_(getpid)(), VKI_SIGSTOP);
nethercote71980f02004-01-24 18:18:54 +0000243
244 } else if (pid > 0) {
nethercote71980f02004-01-24 18:18:54 +0000245 Int status;
246 Int res;
247
nethercote71980f02004-01-24 18:18:54 +0000248 if ((res = VG_(waitpid)(pid, &status, 0)) == pid &&
249 WIFSTOPPED(status) && WSTOPSIG(status) == SIGSTOP &&
nethercotecf97ffb2004-09-09 13:40:31 +0000250 ptrace_setregs(pid, tid) == 0 &&
thughes1d160052004-04-21 15:39:57 +0000251 kill(pid, SIGSTOP) == 0 &&
252 ptrace(PTRACE_DETACH, pid, NULL, 0) == 0) {
nethercote04d0fbc2004-01-26 16:48:06 +0000253 Char pidbuf[15];
254 Char file[30];
255 Char buf[100];
256 Char *bufptr;
257 Char *cmdptr;
258
259 VG_(sprintf)(pidbuf, "%d", pid);
260 VG_(sprintf)(file, "/proc/%d/fd/%d", pid, VG_(clexecfd));
261
262 bufptr = buf;
263 cmdptr = VG_(clo_db_command);
264
265 while (*cmdptr) {
266 switch (*cmdptr) {
267 case '%':
268 switch (*++cmdptr) {
269 case 'f':
270 VG_(memcpy)(bufptr, file, VG_(strlen)(file));
271 bufptr += VG_(strlen)(file);
272 cmdptr++;
273 break;
274 case 'p':
275 VG_(memcpy)(bufptr, pidbuf, VG_(strlen)(pidbuf));
276 bufptr += VG_(strlen)(pidbuf);
277 cmdptr++;
278 break;
279 default:
280 *bufptr++ = *cmdptr++;
281 break;
282 }
283 break;
284 default:
285 *bufptr++ = *cmdptr++;
286 break;
287 }
288 }
289
290 *bufptr++ = '\0';
291
292 VG_(message)(Vg_UserMsg, "starting debugger with cmd: %s", buf);
nethercote71980f02004-01-24 18:18:54 +0000293 res = VG_(system)(buf);
294 if (res == 0) {
295 VG_(message)(Vg_UserMsg, "");
296 VG_(message)(Vg_UserMsg,
nethercote04d0fbc2004-01-26 16:48:06 +0000297 "Debugger has detached. Valgrind regains control. We continue.");
nethercote71980f02004-01-24 18:18:54 +0000298 } else {
299 VG_(message)(Vg_UserMsg, "Apparently failed!");
300 VG_(message)(Vg_UserMsg, "");
301 }
302 }
303
nethercote73b526f2004-10-31 18:48:21 +0000304 VG_(kill)(pid, VKI_SIGKILL);
nethercote71980f02004-01-24 18:18:54 +0000305 VG_(waitpid)(pid, &status, 0);
306 }
307}
308
309
310/* Print some helpful-ish text about unimplemented things, and give
311 up. */
312void VG_(unimplemented) ( Char* msg )
313{
314 VG_(message)(Vg_UserMsg, "");
315 VG_(message)(Vg_UserMsg,
316 "Valgrind detected that your program requires");
317 VG_(message)(Vg_UserMsg,
318 "the following unimplemented functionality:");
319 VG_(message)(Vg_UserMsg, " %s", msg);
320 VG_(message)(Vg_UserMsg,
321 "This may be because the functionality is hard to implement,");
322 VG_(message)(Vg_UserMsg,
323 "or because no reasonable program would behave this way,");
324 VG_(message)(Vg_UserMsg,
325 "or because nobody has yet needed it. In any case, let us know at");
326 VG_(message)(Vg_UserMsg,
327 "%s and/or try to work around the problem, if you can.", VG_BUGS_TO);
328 VG_(message)(Vg_UserMsg,
329 "");
330 VG_(message)(Vg_UserMsg,
331 "Valgrind has to exit now. Sorry. Bye!");
332 VG_(message)(Vg_UserMsg,
333 "");
334 VG_(pp_sched_status)();
335 VG_(exit)(1);
336}
337
338Addr VG_(get_stack_pointer) ( void )
339{
nethercote3cf8d932004-10-20 11:05:34 +0000340 return VG_(baseBlock)[VGOFF_STACK_PTR];
nethercote71980f02004-01-24 18:18:54 +0000341}
342
343/* Debugging thing .. can be called from assembly with OYNK macro. */
344void VG_(oynk) ( Int n )
345{
346 OINK(n);
347}
348
349/* Initialize the PID and PGRP of scheduler LWP; this is also called
350 in any new children after fork. */
351static void newpid(ThreadId unused)
352{
353 /* PID of scheduler LWP */
354 VG_(main_pid) = VG_(getpid)();
355 VG_(main_pgrp) = VG_(getpgrp)();
356}
357
358/*====================================================================*/
359/*=== Check we were launched by stage 1 ===*/
360/*====================================================================*/
361
362/* Look for our AUXV table */
nethercotec25c4492004-10-18 11:52:17 +0000363int scan_auxv(void* init_sp)
nethercote71980f02004-01-24 18:18:54 +0000364{
nethercotec25c4492004-10-18 11:52:17 +0000365 const struct ume_auxv *auxv = find_auxv((int *)init_sp);
nethercote31779c72004-07-30 21:50:15 +0000366 int padfile = -1, found = 0;
nethercote71980f02004-01-24 18:18:54 +0000367
368 for (; auxv->a_type != AT_NULL; auxv++)
369 switch(auxv->a_type) {
370 case AT_UME_PADFD:
nethercote31779c72004-07-30 21:50:15 +0000371 padfile = auxv->u.a_val;
nethercote71980f02004-01-24 18:18:54 +0000372 found |= 1;
373 break;
374
375 case AT_UME_EXECFD:
nethercotef6a1d502004-08-09 12:21:57 +0000376 vgexecfd = auxv->u.a_val;
nethercote71980f02004-01-24 18:18:54 +0000377 found |= 2;
378 break;
nethercote7f390022004-10-25 17:18:24 +0000379
380 case AT_PHDR:
381 VG_(valgrind_base) = PGROUNDDN(auxv->u.a_val);
382 break;
nethercote71980f02004-01-24 18:18:54 +0000383 }
384
nethercote361a14e2004-07-26 11:11:56 +0000385 if ( found != (1|2) ) {
386 fprintf(stderr, "valgrind: stage2 must be launched by stage1\n");
nethercote71980f02004-01-24 18:18:54 +0000387 exit(127);
388 }
nethercote31779c72004-07-30 21:50:15 +0000389 vg_assert(padfile >= 0);
390 return padfile;
nethercote71980f02004-01-24 18:18:54 +0000391}
392
393
394/*====================================================================*/
395/*=== Address space determination ===*/
396/*====================================================================*/
397
nethercote7f390022004-10-25 17:18:24 +0000398extern char _start[];
399
nethercote31779c72004-07-30 21:50:15 +0000400static void layout_remaining_space(Addr argc_addr, float ratio)
nethercote71980f02004-01-24 18:18:54 +0000401{
nethercote31779c72004-07-30 21:50:15 +0000402 Int ires;
403 void* vres;
404 addr_t client_size, shadow_size;
nethercote71980f02004-01-24 18:18:54 +0000405
nethercote7f390022004-10-25 17:18:24 +0000406 // VG_(valgrind_base) should have been set by scan_auxv, but if not,
407 // this is a workable approximation
408 if (VG_(valgrind_base) == 0) {
nethercote7f390022004-10-25 17:18:24 +0000409 VG_(valgrind_base) = PGROUNDDN(&_start);
410 }
411
nethercote820bd8c2004-09-07 23:04:49 +0000412 VG_(valgrind_last) = ROUNDUP(argc_addr, 0x10000) - 1; // stack
nethercote71980f02004-01-24 18:18:54 +0000413
nethercote31779c72004-07-30 21:50:15 +0000414 // This gives the client the largest possible address space while
415 // taking into account the tool's shadow needs.
416 client_size = ROUNDDN((VG_(valgrind_base)-REDZONE_SIZE) / (1.+ratio),
nethercote71980f02004-01-24 18:18:54 +0000417 CLIENT_SIZE_MULTIPLE);
nethercote31779c72004-07-30 21:50:15 +0000418 VG_(client_base) = CLIENT_BASE;
nethercote71980f02004-01-24 18:18:54 +0000419 VG_(client_end) = VG_(client_base) + client_size;
nethercotee2097312004-06-27 12:29:56 +0000420 /* where !FIXED mmap goes */
nethercotebc7b4f42004-07-26 12:44:35 +0000421 VG_(client_mapbase) = VG_(client_base) +
422 PGROUNDDN((addr_t)(client_size * CLIENT_HEAP_PROPORTION));
nethercote71980f02004-01-24 18:18:54 +0000423
nethercote31779c72004-07-30 21:50:15 +0000424 VG_(shadow_base) = VG_(client_end) + REDZONE_SIZE;
nethercote410bfe62004-09-04 15:53:35 +0000425 VG_(shadow_end) = VG_(valgrind_base);
426 shadow_size = VG_(shadow_end) - VG_(shadow_base);
nethercote71980f02004-01-24 18:18:54 +0000427
nethercotee2097312004-06-27 12:29:56 +0000428#define SEGSIZE(a,b) ((VG_(b) - VG_(a))/(1024*1024))
429
nethercote71980f02004-01-24 18:18:54 +0000430 if (0)
nethercotee2097312004-06-27 12:29:56 +0000431 VG_(printf)(
432 "client_base %8x (%dMB)\n"
433 "client_mapbase %8x (%dMB)\n"
434 "client_end %8x (%dMB)\n"
435 "shadow_base %8x (%dMB)\n"
nethercote410bfe62004-09-04 15:53:35 +0000436 "shadow_end %8x\n"
nethercotee2097312004-06-27 12:29:56 +0000437 "valgrind_base %8x (%dMB)\n"
nethercote820bd8c2004-09-07 23:04:49 +0000438 "valgrind_last %8x\n",
nethercotee2097312004-06-27 12:29:56 +0000439 VG_(client_base), SEGSIZE(client_base, client_mapbase),
440 VG_(client_mapbase), SEGSIZE(client_mapbase, client_end),
441 VG_(client_end), SEGSIZE(client_end, shadow_base),
442 VG_(shadow_base), SEGSIZE(shadow_base, shadow_end),
nethercote410bfe62004-09-04 15:53:35 +0000443 VG_(shadow_end),
nethercote820bd8c2004-09-07 23:04:49 +0000444 VG_(valgrind_base), SEGSIZE(valgrind_base, valgrind_last),
445 VG_(valgrind_last)
nethercotee2097312004-06-27 12:29:56 +0000446 );
447
448#undef SEGSIZE
nethercote71980f02004-01-24 18:18:54 +0000449
450 // Ban redzone
nethercotee567e702004-07-10 17:49:17 +0000451 vres = mmap((void *)VG_(client_end), REDZONE_SIZE, PROT_NONE,
fitzhardinge72ddff62004-09-08 20:03:51 +0000452 MAP_FIXED|MAP_ANON|MAP_PRIVATE|MAP_NORESERVE, -1, 0);
nethercotee567e702004-07-10 17:49:17 +0000453 vg_assert((void*)-1 != vres);
nethercote71980f02004-01-24 18:18:54 +0000454
455 // Make client hole
nethercotee567e702004-07-10 17:49:17 +0000456 ires = munmap((void*)VG_(client_base), client_size);
457 vg_assert(0 == ires);
nethercote71980f02004-01-24 18:18:54 +0000458
459 // Map shadow memory.
460 // Initially all inaccessible, incrementally initialized as it is used
nethercotee567e702004-07-10 17:49:17 +0000461 if (shadow_size != 0) {
462 vres = mmap((char *)VG_(shadow_base), shadow_size, PROT_NONE,
fitzhardinge72ddff62004-09-08 20:03:51 +0000463 MAP_PRIVATE|MAP_ANON|MAP_FIXED|MAP_NORESERVE, -1, 0);
nethercoted4722622004-08-30 19:36:42 +0000464 if ((void*)-1 == vres) {
465 fprintf(stderr,
nethercote8c1ce432004-10-08 14:01:14 +0000466 "valgrind: Could not allocate address space (%p bytes)\n"
467 "valgrind: for shadow memory\n"
468 "valgrind: Possible causes:\n"
469 "valgrind: - For some systems (especially under RedHat 8), Valgrind\n"
470 "valgrind: needs at least 1.5GB swap space.\n"
471 "valgrind: - Or, your virtual memory size may be limited (check\n"
472 "valgrind: with 'ulimit -v').\n"
473 "valgrind: - Or, your system may use a kernel that provides only a\n"
474 "valgrind: too-small (eg. 2GB) user address space.\n"
475 , (void*)shadow_size
476 );
nethercoted4722622004-08-30 19:36:42 +0000477 exit(1);
478 }
nethercotee567e702004-07-10 17:49:17 +0000479 }
nethercote71980f02004-01-24 18:18:54 +0000480}
481
482/*====================================================================*/
483/*=== Command line setup ===*/
484/*====================================================================*/
485
486/* Nb: malloc'd memory never freed -- kept throughout like argv, envp */
487static char* get_file_clo(char* dir)
488{
489# define FLEN 512
490 Int fd, n;
491 struct stat s1;
492 char* f_clo = NULL;
493 char filename[FLEN];
494
495 snprintf(filename, FLEN, "%s/.valgrindrc", ( NULL == dir ? "" : dir ) );
496 fd = VG_(open)(filename, 0, VKI_S_IRUSR);
497 if ( fd > 0 ) {
498 if ( 0 == fstat(fd, &s1) ) {
499 f_clo = malloc(s1.st_size+1);
500 vg_assert(f_clo);
501 n = read(fd, f_clo, s1.st_size);
502 if (n == -1) n = 0;
503 f_clo[n] = '\0';
504 }
505 close(fd);
506 }
507 return f_clo;
508# undef FLEN
509}
510
nethercotee2097312004-06-27 12:29:56 +0000511#define ISSPACE(cc) ((cc) == ' ' || (cc) == '\t' || (cc) == '\n')
512
nethercote71980f02004-01-24 18:18:54 +0000513static Int count_args(char* s)
514{
515 Int n = 0;
516 if (s) {
517 char* cp = s;
518 while (True) {
519 // We have alternating sequences: blanks, non-blanks, blanks...
520 // count the non-blanks sequences.
521 while ( ISSPACE(*cp) ) cp++;
522 if ( !*cp ) break;
523 n++;
524 while ( !ISSPACE(*cp) && *cp ) cp++;
525 }
526 }
527 return n;
528}
529
530/* add args out of environment, skipping multiple spaces and -- args */
531static char** copy_args( char* s, char** to )
532{
533 if (s) {
534 char* cp = s;
535 while (True) {
536 // We have alternating sequences: blanks, non-blanks, blanks...
537 // copy the non-blanks sequences, and add terminating '\0'
538 while ( ISSPACE(*cp) ) cp++;
539 if ( !*cp ) break;
540 *to++ = cp;
541 while ( !ISSPACE(*cp) && *cp ) cp++;
542 if ( *cp ) *cp++ = '\0'; // terminate if necessary
543 if (VG_STREQ(to[-1], "--")) to--; // undo any '--' arg
544 }
545 }
546 return to;
547}
548
nethercotee2097312004-06-27 12:29:56 +0000549#undef ISSPACE
550
nethercote71980f02004-01-24 18:18:54 +0000551// Augment command line with arguments from environment and .valgrindrc
552// files.
553static void augment_command_line(Int* vg_argc_inout, char*** vg_argv_inout)
554{
nethercotef6a1d502004-08-09 12:21:57 +0000555 int vg_argc0 = *vg_argc_inout;
556 char** vg_argv0 = *vg_argv_inout;
nethercote71980f02004-01-24 18:18:54 +0000557
558 char* env_clo = getenv(VALGRINDOPTS);
559 char* f1_clo = get_file_clo( getenv("HOME") );
560 char* f2_clo = get_file_clo(".");
561
562 /* copy any extra args from file or environment, if present */
563 if ( (env_clo && *env_clo) || (f1_clo && *f1_clo) || (f2_clo && *f2_clo) ) {
564 /* ' ' separated extra options */
565 char **from;
566 char **to;
thughescaca0022004-09-13 10:20:34 +0000567 int orig_arg_count, env_arg_count, f1_arg_count, f2_arg_count;
568
569 for ( orig_arg_count = 0; vg_argv0[orig_arg_count]; orig_arg_count++ );
570
nethercote71980f02004-01-24 18:18:54 +0000571 env_arg_count = count_args(env_clo);
572 f1_arg_count = count_args(f1_clo);
573 f2_arg_count = count_args(f2_clo);
574
575 if (0)
576 printf("extra-argc=%d %d %d\n",
577 env_arg_count, f1_arg_count, f2_arg_count);
578
579 /* +2: +1 for null-termination, +1 for added '--' */
nethercotef6a1d502004-08-09 12:21:57 +0000580 from = vg_argv0;
thughescaca0022004-09-13 10:20:34 +0000581 vg_argv0 = malloc( (orig_arg_count + env_arg_count + f1_arg_count
nethercote71980f02004-01-24 18:18:54 +0000582 + f2_arg_count + 2) * sizeof(char **));
nethercotef6a1d502004-08-09 12:21:57 +0000583 vg_assert(vg_argv0);
584 to = vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000585
586 /* copy argv[0] */
587 *to++ = *from++;
588
589 /* Copy extra args from env var and file, in the order: ~/.valgrindrc,
590 * $VALGRIND_OPTS, ./.valgrindrc -- more local options are put later
591 * to override less local ones. */
592 to = copy_args(f1_clo, to);
593 to = copy_args(env_clo, to);
594 to = copy_args(f2_clo, to);
595
596 /* copy original arguments, stopping at command or -- */
597 while (*from) {
598 if (**from != '-')
599 break;
600 if (VG_STREQ(*from, "--")) {
601 from++; /* skip -- */
602 break;
603 }
604 *to++ = *from++;
605 }
606
607 /* add -- */
608 *to++ = "--";
609
nethercotef6a1d502004-08-09 12:21:57 +0000610 vg_argc0 = to - vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000611
612 /* copy rest of original command line, then NULL */
613 while (*from) *to++ = *from++;
614 *to = NULL;
615 }
616
nethercotef6a1d502004-08-09 12:21:57 +0000617 *vg_argc_inout = vg_argc0;
618 *vg_argv_inout = vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000619}
620
nethercotef6a1d502004-08-09 12:21:57 +0000621#define VG_CLO_SEP '\01'
622
nethercote71980f02004-01-24 18:18:54 +0000623static void get_command_line( int argc, char** argv,
624 Int* vg_argc_out, Char*** vg_argv_out,
625 char*** cl_argv_out )
626{
nethercotef6a1d502004-08-09 12:21:57 +0000627 int vg_argc0;
628 char** vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000629 char** cl_argv;
630 char* env_clo = getenv(VALGRINDCLO);
631
632 if (env_clo != NULL && *env_clo != '\0') {
633 char *cp;
634 char **cpp;
635
nethercotef6a1d502004-08-09 12:21:57 +0000636 /* OK, VALGRINDCLO is set, which means we must be a child of another
637 Valgrind process using --trace-children, so we're getting all our
638 arguments from VALGRINDCLO, and the entire command line belongs to
639 the client (including argv[0]) */
640 vg_argc0 = 1; /* argv[0] */
nethercote71980f02004-01-24 18:18:54 +0000641 for (cp = env_clo; *cp; cp++)
nethercotef6a1d502004-08-09 12:21:57 +0000642 if (*cp == VG_CLO_SEP)
643 vg_argc0++;
nethercote71980f02004-01-24 18:18:54 +0000644
nethercotef6a1d502004-08-09 12:21:57 +0000645 vg_argv0 = malloc(sizeof(char **) * (vg_argc0 + 1));
646 vg_assert(vg_argv0);
nethercote71980f02004-01-24 18:18:54 +0000647
nethercotef6a1d502004-08-09 12:21:57 +0000648 cpp = vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000649
650 *cpp++ = "valgrind"; /* nominal argv[0] */
651 *cpp++ = env_clo;
652
nethercotef6a1d502004-08-09 12:21:57 +0000653 // Replace the VG_CLO_SEP args separator with '\0'
nethercote71980f02004-01-24 18:18:54 +0000654 for (cp = env_clo; *cp; cp++) {
nethercotef6a1d502004-08-09 12:21:57 +0000655 if (*cp == VG_CLO_SEP) {
nethercote71980f02004-01-24 18:18:54 +0000656 *cp++ = '\0'; /* chop it up in place */
657 *cpp++ = cp;
658 }
659 }
660 *cpp = NULL;
661 cl_argv = argv;
662
663 } else {
664 /* Count the arguments on the command line. */
nethercotef6a1d502004-08-09 12:21:57 +0000665 vg_argv0 = argv;
nethercote71980f02004-01-24 18:18:54 +0000666
nethercotef6a1d502004-08-09 12:21:57 +0000667 for (vg_argc0 = 1; vg_argc0 < argc; vg_argc0++) {
668 if (argv[vg_argc0][0] != '-') /* exe name */
nethercote71980f02004-01-24 18:18:54 +0000669 break;
nethercotef6a1d502004-08-09 12:21:57 +0000670 if (VG_STREQ(argv[vg_argc0], "--")) { /* dummy arg */
671 vg_argc0++;
nethercote71980f02004-01-24 18:18:54 +0000672 break;
673 }
674 }
nethercotef6a1d502004-08-09 12:21:57 +0000675 cl_argv = &argv[vg_argc0];
nethercote71980f02004-01-24 18:18:54 +0000676
677 /* Get extra args from VALGRIND_OPTS and .valgrindrc files.
nethercotef6a1d502004-08-09 12:21:57 +0000678 Note we don't do this if getting args from VALGRINDCLO, as
679 those extra args will already be present in VALGRINDCLO. */
680 augment_command_line(&vg_argc0, &vg_argv0);
nethercote71980f02004-01-24 18:18:54 +0000681 }
682
683 if (0) {
684 Int i;
nethercotef6a1d502004-08-09 12:21:57 +0000685 for (i = 0; i < vg_argc0; i++)
686 printf("vg_argv0[%d]=\"%s\"\n", i, vg_argv0[i]);
nethercote71980f02004-01-24 18:18:54 +0000687 }
688
nethercotef6a1d502004-08-09 12:21:57 +0000689 *vg_argc_out = vg_argc0;
690 *vg_argv_out = (Char**)vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000691 *cl_argv_out = cl_argv;
692}
693
694
695/*====================================================================*/
696/*=== Environment and stack setup ===*/
697/*====================================================================*/
698
699/* Scan a colon-separated list, and call a function on each element.
700 The string must be mutable, because we insert a temporary '\0', but
thughes4ad52d02004-06-27 17:37:21 +0000701 the string will end up unmodified. (*func) should return True if it
nethercote71980f02004-01-24 18:18:54 +0000702 doesn't need to see any more.
thughes4ad52d02004-06-27 17:37:21 +0000703
704 This routine will return True if (*func) returns True and False if
705 it reaches the end of the list without that happening.
nethercote71980f02004-01-24 18:18:54 +0000706*/
thughes4ad52d02004-06-27 17:37:21 +0000707static Bool scan_colsep(char *colsep, Bool (*func)(const char *))
nethercote71980f02004-01-24 18:18:54 +0000708{
709 char *cp, *entry;
710 int end;
711
712 if (colsep == NULL ||
713 *colsep == '\0')
thughes4ad52d02004-06-27 17:37:21 +0000714 return False;
nethercote71980f02004-01-24 18:18:54 +0000715
716 entry = cp = colsep;
717
718 do {
719 end = (*cp == '\0');
720
721 if (*cp == ':' || *cp == '\0') {
722 char save = *cp;
723
724 *cp = '\0';
thughes21942d92004-07-12 09:35:37 +0000725 if ((*func)(entry)) {
726 *cp = save;
thughes4ad52d02004-06-27 17:37:21 +0000727 return True;
thughes21942d92004-07-12 09:35:37 +0000728 }
nethercote71980f02004-01-24 18:18:54 +0000729 *cp = save;
730 entry = cp+1;
731 }
732 cp++;
733 } while(!end);
thughes4ad52d02004-06-27 17:37:21 +0000734
735 return False;
736}
737
738static Bool contains(const char *p) {
739 if (VG_STREQ(p, VG_(libdir))) {
740 return True;
741 }
742 return False;
nethercote71980f02004-01-24 18:18:54 +0000743}
744
745/* Prepare the client's environment. This is basically a copy of our
746 environment, except:
747 1. LD_LIBRARY_PATH=$VALGRINDLIB:$LD_LIBRARY_PATH
748 2. LD_PRELOAD=$VALGRINDLIB/vg_inject.so:($VALGRINDLIB/vgpreload_TOOL.so:)?$LD_PRELOAD
749
750 If any of these is missing, then it is added.
751
752 Yummy. String hacking in C.
753
754 If this needs to handle any more variables it should be hacked
755 into something table driven.
756 */
757static char **fix_environment(char **origenv, const char *preload)
758{
759 static const char inject_so[] = "vg_inject.so";
760 static const char ld_library_path[] = "LD_LIBRARY_PATH=";
761 static const char ld_preload[] = "LD_PRELOAD=";
762 static const char valgrind_clo[] = VALGRINDCLO "=";
763 static const int ld_library_path_len = sizeof(ld_library_path)-1;
764 static const int ld_preload_len = sizeof(ld_preload)-1;
765 static const int valgrind_clo_len = sizeof(valgrind_clo)-1;
766 int ld_preload_done = 0;
767 int ld_library_path_done = 0;
768 char *inject_path;
769 int inject_path_len;
770 int vgliblen = strlen(VG_(libdir));
771 char **cpp;
772 char **ret;
773 int envc;
774 const int preloadlen = (preload == NULL) ? 0 : strlen(preload);
775
776 /* Find the vg_inject.so; also make room for the tool preload
777 library */
778 inject_path_len = sizeof(inject_so) + vgliblen + preloadlen + 16;
779 inject_path = malloc(inject_path_len);
nethercote7c018f42004-07-17 16:40:50 +0000780 vg_assert(inject_path);
nethercote71980f02004-01-24 18:18:54 +0000781
782 if (preload)
783 snprintf(inject_path, inject_path_len, "%s/%s:%s",
784 VG_(libdir), inject_so, preload);
785 else
786 snprintf(inject_path, inject_path_len, "%s/%s",
787 VG_(libdir), inject_so);
788
789 /* Count the original size of the env */
790 envc = 0; /* trailing NULL */
791 for (cpp = origenv; cpp && *cpp; cpp++)
792 envc++;
793
794 /* Allocate a new space */
795 ret = malloc(sizeof(char *) * (envc+3+1)); /* 3 new entries + NULL */
nethercote7c018f42004-07-17 16:40:50 +0000796 vg_assert(ret);
nethercote71980f02004-01-24 18:18:54 +0000797
798 /* copy it over */
799 for (cpp = ret; *origenv; )
800 *cpp++ = *origenv++;
801 *cpp = NULL;
802
803 vg_assert(envc == (cpp - ret));
804
805 /* Walk over the new environment, mashing as we go */
806 for (cpp = ret; cpp && *cpp; cpp++) {
807 if (memcmp(*cpp, ld_library_path, ld_library_path_len) == 0) {
nethercote71980f02004-01-24 18:18:54 +0000808 /* If the LD_LIBRARY_PATH already contains libdir, then don't
809 bother adding it again, even if it isn't the first (it
810 seems that the Java runtime will keep reexecing itself
811 unless its paths are at the front of LD_LIBRARY_PATH) */
thughes4ad52d02004-06-27 17:37:21 +0000812 if (!scan_colsep(*cpp + ld_library_path_len, contains)) {
nethercote71980f02004-01-24 18:18:54 +0000813 int len = strlen(*cpp) + vgliblen*2 + 16;
814 char *cp = malloc(len);
nethercote7c018f42004-07-17 16:40:50 +0000815 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000816
817 snprintf(cp, len, "%s%s:%s",
818 ld_library_path, VG_(libdir),
819 (*cpp)+ld_library_path_len);
820
821 *cpp = cp;
822 }
823
824 ld_library_path_done = 1;
825 } else if (memcmp(*cpp, ld_preload, ld_preload_len) == 0) {
826 int len = strlen(*cpp) + inject_path_len;
827 char *cp = malloc(len);
nethercote7c018f42004-07-17 16:40:50 +0000828 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000829
830 snprintf(cp, len, "%s%s:%s",
831 ld_preload, inject_path, (*cpp)+ld_preload_len);
832
833 *cpp = cp;
834
835 ld_preload_done = 1;
836 } else if (memcmp(*cpp, valgrind_clo, valgrind_clo_len) == 0) {
837 *cpp = "";
838 }
839 }
840
841 /* Add the missing bits */
842
843 if (!ld_library_path_done) {
844 int len = ld_library_path_len + vgliblen*2 + 16;
845 char *cp = malloc(len);
nethercote7c018f42004-07-17 16:40:50 +0000846 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000847
848 snprintf(cp, len, "%s%s", ld_library_path, VG_(libdir));
849
850 ret[envc++] = cp;
851 }
852
853 if (!ld_preload_done) {
854 int len = ld_preload_len + inject_path_len;
855 char *cp = malloc(len);
nethercote7c018f42004-07-17 16:40:50 +0000856 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000857
858 snprintf(cp, len, "%s%s",
859 ld_preload, inject_path);
860
861 ret[envc++] = cp;
862 }
863
864 ret[envc] = NULL;
865
866 return ret;
867}
868
869extern char **environ; /* our environment */
870//#include <error.h>
871
872/* Add a string onto the string table, and return its address */
873static char *copy_str(char **tab, const char *str)
874{
875 char *cp = *tab;
876 char *orig = cp;
877
878 while(*str)
879 *cp++ = *str++;
880 *cp++ = '\0';
881
882 if (0)
nethercote545fe672004-11-01 16:52:43 +0000883 printf("copied %p \"%s\" len %lld\n", orig, orig, (Long)(cp-orig));
nethercote71980f02004-01-24 18:18:54 +0000884
885 *tab = cp;
886
887 return orig;
888}
889
890/*
891 This sets up the client's initial stack, containing the args,
892 environment and aux vector.
893
894 The format of the stack is:
895
896 higher address +-----------------+
897 | Trampoline code |
898 +-----------------+
899 | |
900 : string table :
901 | |
902 +-----------------+
903 | AT_NULL |
904 - -
905 | auxv |
906 +-----------------+
907 | NULL |
908 - -
909 | envp |
910 +-----------------+
911 | NULL |
912 - -
913 | argv |
914 +-----------------+
915 | argc |
nethercote4ad74312004-10-26 09:59:49 +0000916 lower address +-----------------+ <- sp
nethercote71980f02004-01-24 18:18:54 +0000917 | undefined |
918 : :
919 */
nethercotec25c4492004-10-18 11:52:17 +0000920static Addr setup_client_stack(void* init_sp,
921 char **orig_argv, char **orig_envp,
nethercote71980f02004-01-24 18:18:54 +0000922 const struct exeinfo *info,
923 UInt** client_auxv)
924{
nethercotee567e702004-07-10 17:49:17 +0000925 void* res;
nethercote71980f02004-01-24 18:18:54 +0000926 char **cpp;
927 char *strtab; /* string table */
928 char *stringbase;
929 addr_t *ptr;
930 struct ume_auxv *auxv;
931 const struct ume_auxv *orig_auxv;
932 const struct ume_auxv *cauxv;
933 unsigned stringsize; /* total size of strings in bytes */
934 unsigned auxsize; /* total size of auxv in bytes */
935 int argc; /* total argc */
936 int envc; /* total number of env vars */
937 unsigned stacksize; /* total client stack size */
938 addr_t cl_esp; /* client stack base (initial esp) */
939
940 /* use our own auxv as a prototype */
nethercotec25c4492004-10-18 11:52:17 +0000941 orig_auxv = find_auxv(init_sp);
nethercote71980f02004-01-24 18:18:54 +0000942
943 /* ==================== compute sizes ==================== */
944
945 /* first of all, work out how big the client stack will be */
946 stringsize = 0;
947
948 /* paste on the extra args if the loader needs them (ie, the #!
949 interpreter and its argument) */
950 argc = 0;
nethercoted6a56872004-07-26 15:32:47 +0000951 if (info->interp_name != NULL) {
nethercote71980f02004-01-24 18:18:54 +0000952 argc++;
nethercoted6a56872004-07-26 15:32:47 +0000953 stringsize += strlen(info->interp_name) + 1;
nethercote71980f02004-01-24 18:18:54 +0000954 }
nethercoted6a56872004-07-26 15:32:47 +0000955 if (info->interp_args != NULL) {
nethercote71980f02004-01-24 18:18:54 +0000956 argc++;
nethercoted6a56872004-07-26 15:32:47 +0000957 stringsize += strlen(info->interp_args) + 1;
nethercote71980f02004-01-24 18:18:54 +0000958 }
959
960 /* now scan the args we're given... */
961 for (cpp = orig_argv; *cpp; cpp++) {
962 argc++;
963 stringsize += strlen(*cpp) + 1;
964 }
965
966 /* ...and the environment */
967 envc = 0;
968 for (cpp = orig_envp; cpp && *cpp; cpp++) {
969 envc++;
970 stringsize += strlen(*cpp) + 1;
971 }
972
973 /* now, how big is the auxv? */
974 auxsize = sizeof(*auxv); /* there's always at least one entry: AT_NULL */
975 for (cauxv = orig_auxv; cauxv->a_type != AT_NULL; cauxv++) {
976 if (cauxv->a_type == AT_PLATFORM)
977 stringsize += strlen(cauxv->u.a_ptr) + 1;
978 auxsize += sizeof(*cauxv);
979 }
980
981 /* OK, now we know how big the client stack is */
982 stacksize =
983 sizeof(int) + /* argc */
984 sizeof(char **)*argc + /* argv */
985 sizeof(char **) + /* terminal NULL */
986 sizeof(char **)*envc + /* envp */
987 sizeof(char **) + /* terminal NULL */
988 auxsize + /* auxv */
989 ROUNDUP(stringsize, sizeof(int)) +/* strings (aligned) */
nethercote73b526f2004-10-31 18:48:21 +0000990 VKI_PAGE_SIZE; /* page for trampoline code */
nethercote71980f02004-01-24 18:18:54 +0000991
nethercotef84f6952004-07-15 14:58:33 +0000992 // decide where stack goes!
993 VG_(clstk_end) = VG_(client_end);
994
nethercote73b526f2004-10-31 18:48:21 +0000995 VG_(client_trampoline_code) = VG_(clstk_end) - VKI_PAGE_SIZE;
nethercotef84f6952004-07-15 14:58:33 +0000996
nethercote71980f02004-01-24 18:18:54 +0000997 /* cl_esp is the client's stack pointer */
nethercotef84f6952004-07-15 14:58:33 +0000998 cl_esp = VG_(clstk_end) - stacksize;
nethercote71980f02004-01-24 18:18:54 +0000999 cl_esp = ROUNDDN(cl_esp, 16); /* make stack 16 byte aligned */
1000
nethercote71980f02004-01-24 18:18:54 +00001001 /* base of the string table (aligned) */
1002 stringbase = strtab = (char *)(VG_(client_trampoline_code) - ROUNDUP(stringsize, sizeof(int)));
1003
1004 VG_(clstk_base) = PGROUNDDN(cl_esp);
nethercote71980f02004-01-24 18:18:54 +00001005
nethercote5ee67ca2004-06-22 14:00:09 +00001006 if (0)
1007 printf("stringsize=%d auxsize=%d stacksize=%d\n"
nethercote6a27d832004-09-07 10:17:02 +00001008 "clstk_base %p\n"
1009 "clstk_end %p\n",
1010 stringsize, auxsize, stacksize,
1011 (void*)VG_(clstk_base), (void*)VG_(clstk_end));
nethercote5ee67ca2004-06-22 14:00:09 +00001012
1013
nethercote71980f02004-01-24 18:18:54 +00001014 /* ==================== allocate space ==================== */
1015
1016 /* allocate a stack - mmap enough space for the stack */
nethercotef84f6952004-07-15 14:58:33 +00001017 res = mmap((void *)PGROUNDDN(cl_esp), VG_(clstk_end) - PGROUNDDN(cl_esp),
nethercotee567e702004-07-10 17:49:17 +00001018 PROT_READ | PROT_WRITE | PROT_EXEC,
1019 MAP_PRIVATE | MAP_ANON | MAP_FIXED, -1, 0);
1020 vg_assert((void*)-1 != res);
nethercote71980f02004-01-24 18:18:54 +00001021
1022 /* ==================== copy client stack ==================== */
1023
1024 ptr = (addr_t *)cl_esp;
1025
1026 /* --- argc --- */
1027 *ptr++ = argc; /* client argc */
1028
1029 /* --- argv --- */
nethercoted6a56872004-07-26 15:32:47 +00001030 if (info->interp_name) {
1031 *ptr++ = (addr_t)copy_str(&strtab, info->interp_name);
1032 free(info->interp_name);
nethercote71980f02004-01-24 18:18:54 +00001033 }
nethercoted6a56872004-07-26 15:32:47 +00001034 if (info->interp_args) {
1035 *ptr++ = (addr_t)copy_str(&strtab, info->interp_args);
1036 free(info->interp_args);
nethercote71980f02004-01-24 18:18:54 +00001037 }
1038 for (cpp = orig_argv; *cpp; ptr++, cpp++) {
1039 *ptr = (addr_t)copy_str(&strtab, *cpp);
1040 }
1041 *ptr++ = 0;
1042
1043 /* --- envp --- */
1044 VG_(client_envp) = (Char **)ptr;
1045 for (cpp = orig_envp; cpp && *cpp; ptr++, cpp++)
1046 *ptr = (addr_t)copy_str(&strtab, *cpp);
1047 *ptr++ = 0;
1048
1049 /* --- auxv --- */
1050 auxv = (struct ume_auxv *)ptr;
1051 *client_auxv = (UInt *)auxv;
1052
1053 for (; orig_auxv->a_type != AT_NULL; auxv++, orig_auxv++) {
1054 /* copy the entry... */
1055 *auxv = *orig_auxv;
1056
1057 /* ...and fix up the copy */
1058 switch(auxv->a_type) {
1059 case AT_PHDR:
1060 if (info->phdr == 0)
1061 auxv->a_type = AT_IGNORE;
1062 else
1063 auxv->u.a_val = info->phdr;
1064 break;
1065
1066 case AT_PHNUM:
1067 if (info->phdr == 0)
1068 auxv->a_type = AT_IGNORE;
1069 else
1070 auxv->u.a_val = info->phnum;
1071 break;
1072
1073 case AT_BASE:
1074 if (info->interp_base == 0)
1075 auxv->a_type = AT_IGNORE;
1076 else
1077 auxv->u.a_val = info->interp_base;
1078 break;
1079
1080 case AT_PLATFORM: /* points to a platform description string */
1081 auxv->u.a_ptr = copy_str(&strtab, orig_auxv->u.a_ptr);
1082 break;
1083
1084 case AT_ENTRY:
1085 auxv->u.a_val = info->entry;
1086 break;
1087
1088 case AT_IGNORE:
1089 case AT_EXECFD:
1090 case AT_PHENT:
1091 case AT_PAGESZ:
1092 case AT_FLAGS:
1093 case AT_NOTELF:
1094 case AT_UID:
1095 case AT_EUID:
1096 case AT_GID:
1097 case AT_EGID:
1098 case AT_CLKTCK:
1099 case AT_HWCAP:
1100 case AT_FPUCW:
1101 case AT_DCACHEBSIZE:
1102 case AT_ICACHEBSIZE:
1103 case AT_UCACHEBSIZE:
1104 /* All these are pointerless, so we don't need to do anything
1105 about them. */
1106 break;
1107
1108 case AT_SECURE:
1109 /* If this is 1, then it means that this program is running
1110 suid, and therefore the dynamic linker should be careful
1111 about LD_PRELOAD, etc. However, since stage1 (the thing
1112 the kernel actually execve's) should never be SUID, and we
1113 need LD_PRELOAD/LD_LIBRARY_PATH to work for the client, we
1114 set AT_SECURE to 0. */
1115 auxv->u.a_val = 0;
1116 break;
1117
1118 case AT_SYSINFO:
1119 /* Leave this unmolested for now, but we'll update it later
1120 when we set up the client trampoline code page */
1121 break;
1122
1123 case AT_SYSINFO_EHDR:
1124 /* Trash this, because we don't reproduce it */
1125 auxv->a_type = AT_IGNORE;
1126 break;
1127
1128 default:
1129 /* stomp out anything we don't know about */
1130 if (0)
nethercote545fe672004-11-01 16:52:43 +00001131 printf("stomping auxv entry %lld\n", (ULong)auxv->a_type);
nethercote71980f02004-01-24 18:18:54 +00001132 auxv->a_type = AT_IGNORE;
1133 break;
1134
1135 }
1136 }
1137 *auxv = *orig_auxv;
1138 vg_assert(auxv->a_type == AT_NULL);
1139
nethercotef84f6952004-07-15 14:58:33 +00001140 /* --- trampoline page --- */
1141 VG_(memcpy)( (void *)VG_(client_trampoline_code),
1142 &VG_(trampoline_code_start), VG_(trampoline_code_length) );
1143
nethercote71980f02004-01-24 18:18:54 +00001144 vg_assert((strtab-stringbase) == stringsize);
1145
nethercote5ee67ca2004-06-22 14:00:09 +00001146 /* We know the initial ESP is pointing at argc/argv */
1147 VG_(client_argc) = *(Int*)cl_esp;
1148 VG_(client_argv) = (Char**)(cl_esp + sizeof(Int));
1149
nethercote71980f02004-01-24 18:18:54 +00001150 return cl_esp;
1151}
1152
1153/*====================================================================*/
1154/*=== Find executable ===*/
1155/*====================================================================*/
1156
thughes4ad52d02004-06-27 17:37:21 +00001157static const char* executable_name;
1158
1159static Bool match_executable(const char *entry) {
1160 char buf[strlen(entry) + strlen(executable_name) + 2];
1161
1162 /* empty PATH element means . */
1163 if (*entry == '\0')
1164 entry = ".";
1165
1166 snprintf(buf, sizeof(buf), "%s/%s", entry, executable_name);
1167
1168 if (access(buf, R_OK|X_OK) == 0) {
1169 executable_name = strdup(buf);
1170 vg_assert(NULL != executable_name);
1171 return True;
1172 }
1173 return False;
1174}
1175
nethercote71980f02004-01-24 18:18:54 +00001176static const char* find_executable(const char* exec)
1177{
1178 vg_assert(NULL != exec);
thughes4ad52d02004-06-27 17:37:21 +00001179 executable_name = exec;
1180 if (strchr(executable_name, '/') == NULL) {
nethercote71980f02004-01-24 18:18:54 +00001181 /* no '/' - we need to search the path */
1182 char *path = getenv("PATH");
thughes4ad52d02004-06-27 17:37:21 +00001183 scan_colsep(path, match_executable);
nethercote71980f02004-01-24 18:18:54 +00001184 }
thughes4ad52d02004-06-27 17:37:21 +00001185 return executable_name;
nethercote71980f02004-01-24 18:18:54 +00001186}
1187
1188
1189/*====================================================================*/
1190/*=== Loading tools ===*/
1191/*====================================================================*/
1192
1193static void list_tools(void)
1194{
1195 DIR *dir = opendir(VG_(libdir));
1196 struct dirent *de;
1197 int first = 1;
1198
1199 if (dir == NULL) {
1200 fprintf(stderr, "Can't open %s: %s (installation problem?)\n",
nethercotef4928da2004-06-15 10:54:40 +00001201 VG_(libdir), strerror(errno));
nethercote71980f02004-01-24 18:18:54 +00001202 return;
1203 }
1204
nethercotef4928da2004-06-15 10:54:40 +00001205 while ((de = readdir(dir)) != NULL) {
nethercote71980f02004-01-24 18:18:54 +00001206 int len = strlen(de->d_name);
1207
1208 /* look for vgskin_TOOL.so names */
1209 if (len > (7+1+3) && /* "vgskin_" + at least 1-char toolname + ".so" */
nethercotef4928da2004-06-15 10:54:40 +00001210 strncmp(de->d_name, "vgskin_", 7) == 0 &&
1211 VG_STREQ(de->d_name + len - 3, ".so")) {
1212 if (first) {
1213 fprintf(stderr, "Available tools:\n");
1214 first = 0;
1215 }
1216 de->d_name[len-3] = '\0';
1217 fprintf(stderr, "\t%s\n", de->d_name+7);
nethercote71980f02004-01-24 18:18:54 +00001218 }
1219 }
1220
1221 closedir(dir);
1222
1223 if (first)
nethercotef4928da2004-06-15 10:54:40 +00001224 fprintf(stderr, "No tools available in \"%s\" (installation problem?)\n",
1225 VG_(libdir));
nethercote71980f02004-01-24 18:18:54 +00001226}
1227
1228
1229/* Find and load a tool, and check it looks ok. Also looks to see if there's
1230 * a matching vgpreload_*.so file, and returns its name in *preloadpath. */
1231static void load_tool( const char *toolname, void** handle_out,
1232 ToolInfo** toolinfo_out, char **preloadpath_out )
1233{
1234 Bool ok;
1235 int len = strlen(VG_(libdir)) + strlen(toolname)*2 + 16;
1236 char buf[len];
1237 void* handle;
1238 ToolInfo* toolinfo;
1239 char* preloadpath = NULL;
1240 Int* vg_malloc_redzonep;
1241
1242 // XXX: allowing full paths for --tool option -- does it make sense?
1243 // Doesn't allow for vgpreload_<tool>.so.
1244
1245 if (strchr(toolname, '/') != 0) {
1246 /* toolname contains '/', and so must be a pathname */
1247 handle = dlopen(toolname, RTLD_NOW);
1248 } else {
1249 /* just try in the libdir */
1250 snprintf(buf, len, "%s/vgskin_%s.so", VG_(libdir), toolname);
1251 handle = dlopen(buf, RTLD_NOW);
1252
1253 if (handle != NULL) {
1254 snprintf(buf, len, "%s/vgpreload_%s.so", VG_(libdir), toolname);
1255 if (access(buf, R_OK) == 0) {
1256 preloadpath = strdup(buf);
1257 vg_assert(NULL != preloadpath);
1258 }
1259 }
1260 }
1261
1262 ok = (NULL != handle);
1263 if (!ok) {
1264 fprintf(stderr, "Can't open tool \"%s\": %s\n", toolname, dlerror());
1265 goto bad_load;
1266 }
1267
1268 toolinfo = dlsym(handle, "vgSkin_tool_info");
1269 ok = (NULL != toolinfo);
1270 if (!ok) {
1271 fprintf(stderr, "Tool \"%s\" doesn't define SK_(tool_info) - "
1272 "add VG_DETERMINE_INTERFACE_VERSION?\n", toolname);
1273 goto bad_load;
1274 }
1275
1276 ok = (toolinfo->sizeof_ToolInfo == sizeof(*toolinfo) &&
1277 toolinfo->interface_major_version == VG_CORE_INTERFACE_MAJOR_VERSION &&
1278 toolinfo->sk_pre_clo_init != NULL);
1279 if (!ok) {
1280 fprintf(stderr, "Error:\n"
1281 " Tool and core interface versions do not match.\n"
1282 " Interface version used by core is: %d.%d (size %d)\n"
1283 " Interface version used by tool is: %d.%d (size %d)\n"
1284 " The major version numbers must match.\n",
1285 VG_CORE_INTERFACE_MAJOR_VERSION,
1286 VG_CORE_INTERFACE_MINOR_VERSION,
nethercote545fe672004-11-01 16:52:43 +00001287 (Int)sizeof(*toolinfo),
nethercote71980f02004-01-24 18:18:54 +00001288 toolinfo->interface_major_version,
1289 toolinfo->interface_minor_version,
1290 toolinfo->sizeof_ToolInfo);
1291 fprintf(stderr, " You need to at least recompile, and possibly update,\n");
1292 if (VG_CORE_INTERFACE_MAJOR_VERSION > toolinfo->interface_major_version)
nethercote996901a2004-08-03 13:29:09 +00001293 fprintf(stderr, " your tool to work with this version of Valgrind.\n");
nethercote71980f02004-01-24 18:18:54 +00001294 else
nethercote996901a2004-08-03 13:29:09 +00001295 fprintf(stderr, " your version of Valgrind to work with this tool.\n");
nethercote71980f02004-01-24 18:18:54 +00001296 goto bad_load;
1297 }
1298
1299 // Set redzone size for V's allocator
1300 vg_malloc_redzonep = dlsym(handle, STR(VG_(vg_malloc_redzone_szB)));
1301 if ( NULL != vg_malloc_redzonep ) {
1302 VG_(vg_malloc_redzone_szB) = *vg_malloc_redzonep;
1303 }
1304
1305 vg_assert(NULL != handle && NULL != toolinfo);
1306 *handle_out = handle;
1307 *toolinfo_out = toolinfo;
1308 *preloadpath_out = preloadpath;
1309 return;
1310
1311
1312 bad_load:
1313 if (handle != NULL)
1314 dlclose(handle);
1315
nethercotef4928da2004-06-15 10:54:40 +00001316 fprintf(stderr, "valgrind: couldn't load tool\n");
nethercote71980f02004-01-24 18:18:54 +00001317 list_tools();
1318 exit(127);
1319}
1320
nethercotef4928da2004-06-15 10:54:40 +00001321
1322/*====================================================================*/
1323/*=== Command line errors ===*/
1324/*====================================================================*/
1325
1326static void abort_msg ( void )
1327{
nethercotef8548672004-06-21 12:42:35 +00001328 VG_(clo_log_to) = VgLogTo_Fd;
1329 VG_(clo_log_fd) = 2; /* stderr */
nethercotef4928da2004-06-15 10:54:40 +00001330}
1331
1332void VG_(bad_option) ( Char* opt )
1333{
1334 abort_msg();
1335 VG_(printf)("valgrind: Bad option `%s'; aborting.\n", opt);
1336 VG_(printf)("valgrind: Use --help for more information.\n");
1337 VG_(exit)(1);
1338}
1339
1340static void missing_tool_option ( void )
1341{
1342 abort_msg();
1343 VG_(printf)("valgrind: Missing --tool option\n");
1344 list_tools();
1345 VG_(printf)("valgrind: Use --help for more information.\n");
1346 VG_(exit)(1);
1347}
1348
1349static void missing_prog ( void )
1350{
1351 abort_msg();
1352 VG_(printf)("valgrind: no program specified\n");
1353 VG_(printf)("valgrind: Use --help for more information.\n");
1354 VG_(exit)(1);
1355}
1356
1357static void config_error ( Char* msg )
1358{
1359 abort_msg();
1360 VG_(printf)("valgrind: Startup or configuration error:\n %s\n", msg);
1361 VG_(printf)("valgrind: Unable to start up properly. Giving up.\n");
1362 VG_(exit)(1);
1363}
1364
1365
nethercote71980f02004-01-24 18:18:54 +00001366/*====================================================================*/
1367/*=== Loading the client ===*/
1368/*====================================================================*/
1369
nethercotef4928da2004-06-15 10:54:40 +00001370static void load_client(char* cl_argv[], const char* exec, Int need_help,
nethercote71980f02004-01-24 18:18:54 +00001371 /*out*/struct exeinfo* info, /*out*/Addr* client_eip)
1372{
1373 // If they didn't specify an executable with --exec, and didn't specify
1374 // --help, then use client argv[0] (searching $PATH if necessary).
nethercotef4928da2004-06-15 10:54:40 +00001375 if (NULL == exec && !need_help) {
nethercote71980f02004-01-24 18:18:54 +00001376 if (cl_argv[0] == NULL ||
1377 ( NULL == (exec = find_executable(cl_argv[0])) ) )
1378 {
nethercotef4928da2004-06-15 10:54:40 +00001379 missing_prog();
nethercote71980f02004-01-24 18:18:54 +00001380 }
1381 }
1382
1383 info->map_base = VG_(client_mapbase);
nethercote71980f02004-01-24 18:18:54 +00001384 info->exe_base = VG_(client_base);
1385 info->exe_end = VG_(client_end);
1386 info->argv = cl_argv;
1387
nethercotef4928da2004-06-15 10:54:40 +00001388 if (need_help) {
nethercote71980f02004-01-24 18:18:54 +00001389 VG_(clexecfd) = -1;
nethercoteea147e72004-07-26 15:43:57 +00001390 // Set the minimal number of entries in 'info' to continue.
nethercoted6a56872004-07-26 15:32:47 +00001391 info->interp_name = NULL;
1392 info->interp_args = NULL;
nethercote71980f02004-01-24 18:18:54 +00001393 } else {
1394 Int ret;
nethercote4ec0af42004-10-16 15:31:49 +00001395 VG_(clexecfd) = VG_(open)(exec, VKI_O_RDONLY, VKI_S_IRUSR);
nethercote71980f02004-01-24 18:18:54 +00001396 ret = do_exec(exec, info);
1397 if (ret != 0) {
nethercoteea147e72004-07-26 15:43:57 +00001398 fprintf(stderr, "valgrind: do_exec(%s) failed: %s\n",
1399 exec, strerror(ret));
nethercote71980f02004-01-24 18:18:54 +00001400 exit(127);
1401 }
1402 }
1403
1404 /* Copy necessary bits of 'info' that were filled in */
1405 *client_eip = info->init_eip;
1406 VG_(brk_base) = VG_(brk_limit) = info->brkbase;
1407}
1408
nethercote969ecf12004-10-13 17:29:01 +00001409/*====================================================================*/
1410/*=== Address space unpadding ===*/
1411/*====================================================================*/
1412
1413typedef struct {
1414 char* killpad_start;
1415 char* killpad_end;
1416 struct stat* killpad_padstat;
1417} killpad_extra;
1418
1419static int killpad(char *segstart, char *segend, const char *perm, off_t off,
1420 int maj, int min, int ino, void* ex)
1421{
1422 killpad_extra* extra = ex;
1423 void *b, *e;
1424 int res;
1425
1426 vg_assert(NULL != extra->killpad_padstat);
1427
1428 if (extra->killpad_padstat->st_dev != makedev(maj, min) ||
1429 extra->killpad_padstat->st_ino != ino)
1430 return 1;
1431
1432 if (segend <= extra->killpad_start || segstart >= extra->killpad_end)
1433 return 1;
1434
1435 if (segstart <= extra->killpad_start)
1436 b = extra->killpad_start;
1437 else
1438 b = segstart;
1439
1440 if (segend >= extra->killpad_end)
1441 e = extra->killpad_end;
1442 else
1443 e = segend;
1444
1445 res = munmap(b, (char *)e-(char *)b);
1446 vg_assert(0 == res);
1447
1448 return 1;
1449}
1450
1451// Remove padding of 'padfile' from a range of address space.
1452void as_unpad(void *start, void *end, int padfile)
1453{
1454 static struct stat padstat;
1455 killpad_extra extra;
1456 int res;
1457
1458 vg_assert(padfile > 0);
1459
1460 res = fstat(padfile, &padstat);
1461 vg_assert(0 == res);
1462 extra.killpad_padstat = &padstat;
1463 extra.killpad_start = start;
1464 extra.killpad_end = end;
1465 foreach_map(killpad, &extra);
1466}
1467
1468void as_closepadfile(int padfile)
1469{
1470 int res = close(padfile);
1471 vg_assert(0 == res);
1472}
1473
nethercote71980f02004-01-24 18:18:54 +00001474
1475/*====================================================================*/
nethercotef6a1d502004-08-09 12:21:57 +00001476/*=== Command-line: variables, processing, etc ===*/
nethercote71980f02004-01-24 18:18:54 +00001477/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +00001478
njn25e49d8e72002-09-23 09:36:25 +00001479/* Define, and set defaults. */
1480Bool VG_(clo_error_limit) = True;
nethercote04d0fbc2004-01-26 16:48:06 +00001481Bool VG_(clo_db_attach) = False;
1482Char* VG_(clo_db_command) = VG_CLO_DEFAULT_DBCOMMAND;
njn43c799e2003-04-08 00:08:52 +00001483Bool VG_(clo_gen_suppressions) = False;
nethercote27fec902004-06-16 21:26:32 +00001484Int VG_(clo_sanity_level) = 1;
njn25e49d8e72002-09-23 09:36:25 +00001485Int VG_(clo_verbosity) = 1;
1486Bool VG_(clo_demangle) = True;
njn25e49d8e72002-09-23 09:36:25 +00001487Bool VG_(clo_trace_children) = False;
sewardj4cf05692002-10-27 20:28:29 +00001488
nethercotef1e5e152004-09-01 23:58:16 +00001489/* See big comment in core.h for meaning of these three.
nethercotee1730692003-11-20 10:38:07 +00001490 fd is initially stdout, for --help, but gets moved to stderr by default
1491 immediately afterwards. */
sewardj4cf05692002-10-27 20:28:29 +00001492VgLogTo VG_(clo_log_to) = VgLogTo_Fd;
nethercotef8548672004-06-21 12:42:35 +00001493Int VG_(clo_log_fd) = 1;
1494Char* VG_(clo_log_name) = NULL;
sewardj4cf05692002-10-27 20:28:29 +00001495
thughes6233a382004-08-21 11:10:44 +00001496Bool VG_(clo_time_stamp) = False;
1497
sewardj6024b212003-07-13 10:54:33 +00001498Int VG_(clo_input_fd) = 0; /* stdin */
njn25e49d8e72002-09-23 09:36:25 +00001499Int VG_(clo_n_suppressions) = 0;
sewardjde4a1d02002-03-22 01:27:54 +00001500Char* VG_(clo_suppressions)[VG_CLO_MAX_SFILES];
njn25e49d8e72002-09-23 09:36:25 +00001501Bool VG_(clo_profile) = False;
1502Bool VG_(clo_single_step) = False;
1503Bool VG_(clo_optimise) = True;
1504UChar VG_(clo_trace_codegen) = 0; // 00000000b
1505Bool VG_(clo_trace_syscalls) = False;
1506Bool VG_(clo_trace_signals) = False;
1507Bool VG_(clo_trace_symtab) = False;
njn25e49d8e72002-09-23 09:36:25 +00001508Bool VG_(clo_trace_sched) = False;
1509Int VG_(clo_trace_pthread_level) = 0;
njn25e49d8e72002-09-23 09:36:25 +00001510Int VG_(clo_dump_error) = 0;
1511Int VG_(clo_backtrace_size) = 4;
1512Char* VG_(clo_weird_hacks) = NULL;
sewardj858964b2002-10-05 14:15:43 +00001513Bool VG_(clo_run_libc_freeres) = True;
rjwalshf5f536f2003-11-17 17:45:00 +00001514Bool VG_(clo_track_fds) = False;
sewardj22854b92002-11-30 14:00:47 +00001515Bool VG_(clo_chain_bb) = True;
nethercote77eba602003-11-13 17:35:04 +00001516Bool VG_(clo_show_below_main) = False;
fitzhardinge98abfc72003-12-16 02:05:15 +00001517Bool VG_(clo_pointercheck) = True;
fitzhardinge462f4f92003-12-18 02:10:54 +00001518Bool VG_(clo_branchpred) = False;
sewardj2370f3b2002-11-30 15:01:01 +00001519
jsgf855d93d2003-10-13 22:26:55 +00001520static Bool VG_(clo_wait_for_gdb) = False;
1521
1522/* If we're doing signal routing, poll for signals every 50mS by
1523 default. */
1524Int VG_(clo_signal_polltime) = 50;
1525
1526/* These flags reduce thread wakeup latency on syscall completion and
1527 signal delivery, respectively. The downside is possible unfairness. */
1528Bool VG_(clo_lowlat_syscalls) = False; /* low-latency syscalls */
1529Bool VG_(clo_lowlat_signals) = False; /* low-latency signals */
1530
sewardjde4a1d02002-03-22 01:27:54 +00001531
nethercote6c999f22004-01-31 22:55:15 +00001532void usage ( Bool debug_help )
njn7cf0bd32002-06-08 13:36:03 +00001533{
njn25e49d8e72002-09-23 09:36:25 +00001534 Char* usage1 =
nethercote71980f02004-01-24 18:18:54 +00001535"usage: valgrind --tool=<toolname> [options] prog-and-args\n"
njn25e49d8e72002-09-23 09:36:25 +00001536"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001537" common user options for all Valgrind tools, with defaults in [ ]:\n"
nethercote0d588502004-06-21 13:27:11 +00001538" --tool=<name> use the Valgrind tool named <name>\n"
nethercotea76368b2004-06-16 11:56:29 +00001539" -h --help show this message\n"
nethercote6c999f22004-01-31 22:55:15 +00001540" --help-debug show this message, plus debugging options\n"
njn25e49d8e72002-09-23 09:36:25 +00001541" --version show version\n"
njn25e49d8e72002-09-23 09:36:25 +00001542" -q --quiet run silently; only print error msgs\n"
1543" -v --verbose be more verbose, incl counts of errors\n"
nethercote77eba602003-11-13 17:35:04 +00001544" --trace-children=no|yes Valgrind-ise child processes? [no]\n"
nethercote0d588502004-06-21 13:27:11 +00001545" --track-fds=no|yes track open file descriptors? [no]\n"
thughes6233a382004-08-21 11:10:44 +00001546" --time-stamp=no|yes add timestamps to log messages? [no]\n"
nethercote2b0793f2003-12-02 10:41:18 +00001547"\n"
1548" uncommon user options for all Valgrind tools:\n"
nethercote0d588502004-06-21 13:27:11 +00001549" --run-libc-freeres=no|yes free up glibc memory at exit? [yes]\n"
1550" --weird-hacks=hack1,hack2,... recognised hacks: lax-ioctls [none]\n"
1551" --signal-polltime=<time> signal poll period (mS) for older kernels [50]\n"
1552" --lowlat-signals=no|yes improve thread signal wake-up latency [no]\n"
1553" --lowlat-syscalls=no|yes improve thread syscall wake-up latency [no]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001554" --pointercheck=no|yes enforce client address space limits [yes]\n"
njn25e49d8e72002-09-23 09:36:25 +00001555"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001556" user options for Valgrind tools that report errors:\n"
nethercotef8548672004-06-21 12:42:35 +00001557" --log-fd=<number> log messages to file descriptor [2=stderr]\n"
1558" --log-file=<file> log messages to <file>.pid<pid>\n"
1559" --log-socket=ipaddr:port log messages to socket ipaddr:port\n"
nethercote2b0793f2003-12-02 10:41:18 +00001560" --demangle=no|yes automatically demangle C++ names? [yes]\n"
1561" --num-callers=<number> show <num> callers in stack traces [4]\n"
1562" --error-limit=no|yes stop showing new errors if too many? [yes]\n"
1563" --show-below-main=no|yes continue stack traces below main() [no]\n"
1564" --suppressions=<filename> suppress errors described in <filename>\n"
1565" --gen-suppressions=no|yes print suppressions for errors detected [no]\n"
nethercote04d0fbc2004-01-26 16:48:06 +00001566" --db-attach=no|yes start debugger when errors detected? [no]\n"
1567" --db-command=<command> command to start debugger [gdb -nw %%f %%p]\n"
1568" --input-fd=<number> file descriptor for input [0=stdin]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001569"\n";
njn7cf0bd32002-06-08 13:36:03 +00001570
njn25e49d8e72002-09-23 09:36:25 +00001571 Char* usage2 =
1572"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001573" debugging options for all Valgrind tools:\n"
njn25e49d8e72002-09-23 09:36:25 +00001574" --sanity-level=<number> level of sanity checking to do [1]\n"
1575" --single-step=no|yes translate each instr separately? [no]\n"
1576" --optimise=no|yes improve intermediate code? [yes]\n"
nethercote137bc552003-11-14 17:47:54 +00001577" --profile=no|yes profile? (tool must be built for it) [no]\n"
sewardj22854b92002-11-30 14:00:47 +00001578" --chain-bb=no|yes do basic-block chaining? [yes]\n"
fitzhardinge462f4f92003-12-18 02:10:54 +00001579" --branchpred=yes|no generate branch prediction hints [no]\n"
njn25e49d8e72002-09-23 09:36:25 +00001580" --trace-codegen=<XXXXX> show generated code? (X = 0|1) [00000]\n"
1581" --trace-syscalls=no|yes show all system calls? [no]\n"
1582" --trace-signals=no|yes show signal handling details? [no]\n"
1583" --trace-symtab=no|yes show symbol table details? [no]\n"
njn25e49d8e72002-09-23 09:36:25 +00001584" --trace-sched=no|yes show thread scheduler details? [no]\n"
njn3e884182003-04-15 13:03:23 +00001585" --trace-pthread=none|some|all show pthread event details? [none]\n"
jsgf855d93d2003-10-13 22:26:55 +00001586" --wait-for-gdb=yes|no pause on startup to wait for gdb attach\n"
njn25e49d8e72002-09-23 09:36:25 +00001587"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001588" debugging options for Valgrind tools that report errors\n"
1589" --dump-error=<number> show translation for basic block associated\n"
1590" with <number>'th error context [0=show none]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001591"\n";
njn3e884182003-04-15 13:03:23 +00001592
1593 Char* usage3 =
1594"\n"
nethercote71980f02004-01-24 18:18:54 +00001595" Extra options read from ~/.valgrindrc, $VALGRIND_OPTS, ./.valgrindrc\n"
njn25e49d8e72002-09-23 09:36:25 +00001596"\n"
nethercote08fa9a72004-07-16 17:44:00 +00001597" Valgrind is Copyright (C) 2000-2004 Julian Seward et al.\n"
njn25e49d8e72002-09-23 09:36:25 +00001598" and licensed under the GNU General Public License, version 2.\n"
1599" Bug reports, feedback, admiration, abuse, etc, to: %s.\n"
njnd04b7c62002-10-03 14:05:52 +00001600"\n"
nethercote137bc552003-11-14 17:47:54 +00001601" Tools are copyright and licensed by their authors. See each\n"
1602" tool's start-up message for more information.\n"
njn25e49d8e72002-09-23 09:36:25 +00001603"\n";
njn7cf0bd32002-06-08 13:36:03 +00001604
fitzhardinge98abfc72003-12-16 02:05:15 +00001605 VG_(printf)(usage1);
1606 if (VG_(details).name) {
1607 VG_(printf)(" user options for %s:\n", VG_(details).name);
fitzhardinge98abfc72003-12-16 02:05:15 +00001608 if (VG_(needs).command_line_options)
1609 SK_(print_usage)();
1610 else
1611 VG_(printf)(" (none)\n");
1612 }
nethercote6c999f22004-01-31 22:55:15 +00001613 if (debug_help) {
1614 VG_(printf)(usage2);
fitzhardinge98abfc72003-12-16 02:05:15 +00001615
nethercote6c999f22004-01-31 22:55:15 +00001616 if (VG_(details).name) {
1617 VG_(printf)(" debugging options for %s:\n", VG_(details).name);
1618
1619 if (VG_(needs).command_line_options)
1620 SK_(print_debug_usage)();
1621 else
1622 VG_(printf)(" (none)\n");
1623 }
fitzhardinge98abfc72003-12-16 02:05:15 +00001624 }
nethercote421281e2003-11-20 16:20:55 +00001625 VG_(printf)(usage3, VG_BUGS_TO);
nethercotef4928da2004-06-15 10:54:40 +00001626 VG_(exit)(0);
njn7cf0bd32002-06-08 13:36:03 +00001627}
sewardjde4a1d02002-03-22 01:27:54 +00001628
nethercote71980f02004-01-24 18:18:54 +00001629static void pre_process_cmd_line_options
nethercote6c999f22004-01-31 22:55:15 +00001630 ( Int* need_help, const char** tool, const char** exec )
sewardj1c1b1162003-02-23 01:25:51 +00001631{
nethercote71980f02004-01-24 18:18:54 +00001632 UInt i;
sewardjde4a1d02002-03-22 01:27:54 +00001633
nethercote71980f02004-01-24 18:18:54 +00001634 /* parse the options we have (only the options we care about now) */
nethercotef6a1d502004-08-09 12:21:57 +00001635 for (i = 1; i < vg_argc; i++) {
nethercote71980f02004-01-24 18:18:54 +00001636
nethercotef6a1d502004-08-09 12:21:57 +00001637 if (strcmp(vg_argv[i], "--version") == 0) {
nethercote71980f02004-01-24 18:18:54 +00001638 printf("valgrind-" VERSION "\n");
nethercotef4928da2004-06-15 10:54:40 +00001639 exit(0);
nethercote71980f02004-01-24 18:18:54 +00001640
nethercotef6a1d502004-08-09 12:21:57 +00001641 } else if (VG_CLO_STREQ(vg_argv[i], "--help") ||
1642 VG_CLO_STREQ(vg_argv[i], "-h")) {
nethercote6c999f22004-01-31 22:55:15 +00001643 *need_help = 1;
1644
nethercotef6a1d502004-08-09 12:21:57 +00001645 } else if (VG_CLO_STREQ(vg_argv[i], "--help-debug")) {
nethercote6c999f22004-01-31 22:55:15 +00001646 *need_help = 2;
nethercote71980f02004-01-24 18:18:54 +00001647
nethercotef6a1d502004-08-09 12:21:57 +00001648 } else if (VG_CLO_STREQN(7, vg_argv[i], "--tool=") ||
1649 VG_CLO_STREQN(7, vg_argv[i], "--skin=")) {
1650 *tool = &vg_argv[i][7];
nethercote71980f02004-01-24 18:18:54 +00001651
nethercotef6a1d502004-08-09 12:21:57 +00001652 } else if (VG_CLO_STREQN(7, vg_argv[i], "--exec=")) {
1653 *exec = &vg_argv[i][7];
nethercote71980f02004-01-24 18:18:54 +00001654 }
1655 }
1656
nethercotef4928da2004-06-15 10:54:40 +00001657 /* If no tool specified, can act appropriately without loading tool */
nethercote71980f02004-01-24 18:18:54 +00001658 if (*tool == NULL) {
nethercotef4928da2004-06-15 10:54:40 +00001659 if (0 == *need_help) {
1660 // neither --tool nor --help/--help-debug specified
1661 missing_tool_option();
1662 } else {
1663 // Give help message, without any tool-specific help
1664 usage(/*help-debug?*/2 == *need_help);
1665 }
nethercote71980f02004-01-24 18:18:54 +00001666 }
1667}
1668
nethercote5ee67ca2004-06-22 14:00:09 +00001669static void process_cmd_line_options( UInt* client_auxv, const char* toolname )
nethercote71980f02004-01-24 18:18:54 +00001670{
nethercotef8548672004-06-21 12:42:35 +00001671 Int i, eventually_log_fd;
nethercote71980f02004-01-24 18:18:54 +00001672 Int *auxp;
1673 Int toolname_len = VG_(strlen)(toolname);
sewardjde4a1d02002-03-22 01:27:54 +00001674
nethercotee1730692003-11-20 10:38:07 +00001675 /* log to stderr by default, but usage message goes to stdout */
nethercotef8548672004-06-21 12:42:35 +00001676 eventually_log_fd = 2;
sewardjde4a1d02002-03-22 01:27:54 +00001677
sewardj19d81412002-06-03 01:10:40 +00001678 /* Check for sane path in ./configure --prefix=... */
fitzhardinge98abfc72003-12-16 02:05:15 +00001679 if (VG_LIBDIR[0] != '/')
sewardj19d81412002-06-03 01:10:40 +00001680 config_error("Please use absolute paths in "
1681 "./configure --prefix=... or --libdir=...");
sewardj38170912002-05-10 21:07:22 +00001682
nethercote73b526f2004-10-31 18:48:21 +00001683 for (auxp = client_auxv; auxp[0] != AT_NULL; auxp += 2) {
fitzhardinge98abfc72003-12-16 02:05:15 +00001684 switch(auxp[0]) {
nethercote73b526f2004-10-31 18:48:21 +00001685 case AT_SYSINFO:
fitzhardinge92360792003-12-24 10:11:11 +00001686 auxp[1] = (Int)(VG_(client_trampoline_code) + VG_(tramp_syscall_offset));
fitzhardinge98abfc72003-12-16 02:05:15 +00001687 break;
sewardjde4a1d02002-03-22 01:27:54 +00001688 }
fitzhardinge98abfc72003-12-16 02:05:15 +00001689 }
sewardjde4a1d02002-03-22 01:27:54 +00001690
nethercotef6a1d502004-08-09 12:21:57 +00001691 for (i = 1; i < vg_argc; i++) {
nethercote71980f02004-01-24 18:18:54 +00001692
nethercotef6a1d502004-08-09 12:21:57 +00001693 Char* arg = vg_argv[i];
thughes3bfd5a02004-07-18 08:05:44 +00001694 Char* colon = arg;
nethercote71980f02004-01-24 18:18:54 +00001695
thughes3bfd5a02004-07-18 08:05:44 +00001696 /* Look for a colon in the switch name */
1697 while (*colon && *colon != ':' && *colon != '=')
1698 colon++;
nethercote71980f02004-01-24 18:18:54 +00001699
1700 /* Look for matching "--toolname:foo" */
thughes3bfd5a02004-07-18 08:05:44 +00001701 if (*colon == ':') {
nethercote71980f02004-01-24 18:18:54 +00001702 if (VG_CLO_STREQN(2, arg, "--") &&
1703 VG_CLO_STREQN(toolname_len, arg+2, toolname) &&
1704 VG_CLO_STREQN(1, arg+2+toolname_len, ":"))
1705 {
1706 // prefix matches, convert "--toolname:foo" to "--foo"
1707 if (0)
1708 VG_(printf)("tool-specific arg: %s\n", arg);
1709 arg += toolname_len + 1;
1710 arg[0] = '-';
1711 arg[1] = '-';
1712
1713 } else {
1714 // prefix doesn't match, skip to next arg
1715 continue;
1716 }
1717 }
1718
fitzhardinge98abfc72003-12-16 02:05:15 +00001719 /* Ignore these options - they've already been handled */
nethercote71980f02004-01-24 18:18:54 +00001720 if (VG_CLO_STREQN(7, arg, "--tool=") ||
1721 VG_CLO_STREQN(7, arg, "--skin="))
fitzhardinge98abfc72003-12-16 02:05:15 +00001722 continue;
nethercote71980f02004-01-24 18:18:54 +00001723 if (VG_CLO_STREQN(7, arg, "--exec="))
fitzhardinge98abfc72003-12-16 02:05:15 +00001724 continue;
1725
nethercote71980f02004-01-24 18:18:54 +00001726 if ( VG_CLO_STREQ(arg, "--"))
fitzhardinge98abfc72003-12-16 02:05:15 +00001727 continue;
nethercote27fec902004-06-16 21:26:32 +00001728
nethercote71980f02004-01-24 18:18:54 +00001729 else if (VG_CLO_STREQ(arg, "-v") ||
1730 VG_CLO_STREQ(arg, "--verbose"))
sewardjde4a1d02002-03-22 01:27:54 +00001731 VG_(clo_verbosity)++;
nethercote27fec902004-06-16 21:26:32 +00001732
nethercote71980f02004-01-24 18:18:54 +00001733 else if (VG_CLO_STREQ(arg, "-q") ||
1734 VG_CLO_STREQ(arg, "--quiet"))
sewardjde4a1d02002-03-22 01:27:54 +00001735 VG_(clo_verbosity)--;
1736
nethercote27fec902004-06-16 21:26:32 +00001737 else VG_BOOL_CLO("--branchpred", VG_(clo_branchpred))
1738 else VG_BOOL_CLO("--chain-bb", VG_(clo_chain_bb))
1739 else VG_BOOL_CLO("--db-attach", VG_(clo_db_attach))
1740 else VG_BOOL_CLO("--demangle", VG_(clo_demangle))
1741 else VG_BOOL_CLO("--error-limit", VG_(clo_error_limit))
1742 else VG_BOOL_CLO("--gen-suppressions", VG_(clo_gen_suppressions))
1743 else VG_BOOL_CLO("--lowlat-signals", VG_(clo_lowlat_signals))
1744 else VG_BOOL_CLO("--lowlat-syscalls", VG_(clo_lowlat_syscalls))
1745 else VG_BOOL_CLO("--optimise", VG_(clo_optimise))
1746 else VG_BOOL_CLO("--pointercheck", VG_(clo_pointercheck))
1747 else VG_BOOL_CLO("--profile", VG_(clo_profile))
1748 else VG_BOOL_CLO("--run-libc-freeres", VG_(clo_run_libc_freeres))
1749 else VG_BOOL_CLO("--show-below-main", VG_(clo_show_below_main))
1750 else VG_BOOL_CLO("--single-step", VG_(clo_single_step))
thughes6233a382004-08-21 11:10:44 +00001751 else VG_BOOL_CLO("--time-stamp", VG_(clo_time_stamp))
nethercote27fec902004-06-16 21:26:32 +00001752 else VG_BOOL_CLO("--track-fds", VG_(clo_track_fds))
1753 else VG_BOOL_CLO("--trace-children", VG_(clo_trace_children))
1754 else VG_BOOL_CLO("--trace-sched", VG_(clo_trace_sched))
1755 else VG_BOOL_CLO("--trace-signals", VG_(clo_trace_signals))
1756 else VG_BOOL_CLO("--trace-symtab", VG_(clo_trace_symtab))
1757 else VG_BOOL_CLO("--trace-syscalls", VG_(clo_trace_syscalls))
1758 else VG_BOOL_CLO("--wait-for-gdb", VG_(clo_wait_for_gdb))
sewardj72f98ff2002-06-13 17:23:38 +00001759
nethercote27fec902004-06-16 21:26:32 +00001760 else VG_STR_CLO ("--db-command", VG_(clo_db_command))
1761 else VG_STR_CLO ("--weird-hacks", VG_(clo_weird_hacks))
sewardjde4a1d02002-03-22 01:27:54 +00001762
nethercote27fec902004-06-16 21:26:32 +00001763 else VG_NUM_CLO ("--dump-error", VG_(clo_dump_error))
1764 else VG_NUM_CLO ("--input-fd", VG_(clo_input_fd))
1765 else VG_NUM_CLO ("--sanity-level", VG_(clo_sanity_level))
nethercote69978792004-10-29 11:17:21 +00001766 else VG_NUM_CLO ("--signal-polltime", VG_(clo_signal_polltime))
nethercote27fec902004-06-16 21:26:32 +00001767 else VG_BNUM_CLO("--num-callers", VG_(clo_backtrace_size), 1,
1768 VG_DEEPEST_BACKTRACE)
sewardjde4a1d02002-03-22 01:27:54 +00001769
nethercotef8548672004-06-21 12:42:35 +00001770 // for backwards compatibility, replaced by --log-fd
nethercote71980f02004-01-24 18:18:54 +00001771 else if (VG_CLO_STREQN(13, arg, "--logfile-fd=")) {
nethercotef8548672004-06-21 12:42:35 +00001772 VG_(clo_log_to) = VgLogTo_Fd;
1773 VG_(clo_log_name) = NULL;
1774 eventually_log_fd = (Int)VG_(atoll)(&arg[13]);
1775 }
1776 else if (VG_CLO_STREQN(9, arg, "--log-fd=")) {
1777 VG_(clo_log_to) = VgLogTo_Fd;
1778 VG_(clo_log_name) = NULL;
1779 eventually_log_fd = (Int)VG_(atoll)(&arg[9]);
sewardj4cf05692002-10-27 20:28:29 +00001780 }
1781
nethercotef8548672004-06-21 12:42:35 +00001782 // for backwards compatibility, replaced by --log-file
nethercote71980f02004-01-24 18:18:54 +00001783 else if (VG_CLO_STREQN(10, arg, "--logfile=")) {
nethercotef8548672004-06-21 12:42:35 +00001784 VG_(clo_log_to) = VgLogTo_File;
1785 VG_(clo_log_name) = &arg[10];
1786 }
1787 else if (VG_CLO_STREQN(11, arg, "--log-file=")) {
1788 VG_(clo_log_to) = VgLogTo_File;
1789 VG_(clo_log_name) = &arg[11];
sewardj4cf05692002-10-27 20:28:29 +00001790 }
sewardjde4a1d02002-03-22 01:27:54 +00001791
nethercotef8548672004-06-21 12:42:35 +00001792 // for backwards compatibility, replaced by --log-socket
nethercote71980f02004-01-24 18:18:54 +00001793 else if (VG_CLO_STREQN(12, arg, "--logsocket=")) {
nethercotef8548672004-06-21 12:42:35 +00001794 VG_(clo_log_to) = VgLogTo_Socket;
1795 VG_(clo_log_name) = &arg[12];
1796 }
1797 else if (VG_CLO_STREQN(13, arg, "--log-socket=")) {
1798 VG_(clo_log_to) = VgLogTo_Socket;
1799 VG_(clo_log_name) = &arg[13];
sewardj73cf3bc2002-11-03 03:20:15 +00001800 }
1801
nethercote71980f02004-01-24 18:18:54 +00001802 else if (VG_CLO_STREQN(15, arg, "--suppressions=")) {
sewardjde4a1d02002-03-22 01:27:54 +00001803 if (VG_(clo_n_suppressions) >= VG_CLO_MAX_SFILES) {
njn25e49d8e72002-09-23 09:36:25 +00001804 VG_(message)(Vg_UserMsg, "Too many suppression files specified.");
sewardjde4a1d02002-03-22 01:27:54 +00001805 VG_(message)(Vg_UserMsg,
1806 "Increase VG_CLO_MAX_SFILES and recompile.");
nethercote71980f02004-01-24 18:18:54 +00001807 VG_(bad_option)(arg);
sewardjde4a1d02002-03-22 01:27:54 +00001808 }
nethercote71980f02004-01-24 18:18:54 +00001809 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = &arg[15];
sewardjde4a1d02002-03-22 01:27:54 +00001810 VG_(clo_n_suppressions)++;
1811 }
sewardjde4a1d02002-03-22 01:27:54 +00001812
njn25e49d8e72002-09-23 09:36:25 +00001813 /* "vwxyz" --> 000zyxwv (binary) */
nethercote71980f02004-01-24 18:18:54 +00001814 else if (VG_CLO_STREQN(16, arg, "--trace-codegen=")) {
njn25e49d8e72002-09-23 09:36:25 +00001815 Int j;
nethercote71980f02004-01-24 18:18:54 +00001816 char* opt = & arg[16];
njn25e49d8e72002-09-23 09:36:25 +00001817
1818 if (5 != VG_(strlen)(opt)) {
1819 VG_(message)(Vg_UserMsg,
1820 "--trace-codegen argument must have 5 digits");
nethercote71980f02004-01-24 18:18:54 +00001821 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001822 }
1823 for (j = 0; j < 5; j++) {
1824 if ('0' == opt[j]) { /* do nothing */ }
1825 else if ('1' == opt[j]) VG_(clo_trace_codegen) |= (1 << j);
1826 else {
1827 VG_(message)(Vg_UserMsg, "--trace-codegen argument can only "
1828 "contain 0s and 1s");
nethercote71980f02004-01-24 18:18:54 +00001829 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001830 }
1831 }
1832 }
sewardjde4a1d02002-03-22 01:27:54 +00001833
nethercote71980f02004-01-24 18:18:54 +00001834 else if (VG_CLO_STREQ(arg, "--trace-pthread=none"))
sewardj45b4b372002-04-16 22:50:32 +00001835 VG_(clo_trace_pthread_level) = 0;
nethercote71980f02004-01-24 18:18:54 +00001836 else if (VG_CLO_STREQ(arg, "--trace-pthread=some"))
sewardj45b4b372002-04-16 22:50:32 +00001837 VG_(clo_trace_pthread_level) = 1;
nethercote71980f02004-01-24 18:18:54 +00001838 else if (VG_CLO_STREQ(arg, "--trace-pthread=all"))
sewardj45b4b372002-04-16 22:50:32 +00001839 VG_(clo_trace_pthread_level) = 2;
sewardj8937c812002-04-12 20:12:20 +00001840
nethercote71980f02004-01-24 18:18:54 +00001841 else if ( ! VG_(needs).command_line_options
1842 || ! SK_(process_cmd_line_option)(arg) ) {
nethercotef4928da2004-06-15 10:54:40 +00001843 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001844 }
sewardjde4a1d02002-03-22 01:27:54 +00001845 }
1846
nethercote27fec902004-06-16 21:26:32 +00001847 // Check various option values
1848
njnf9ebf672003-05-12 21:41:30 +00001849 if (VG_(clo_verbosity) < 0)
sewardjde4a1d02002-03-22 01:27:54 +00001850 VG_(clo_verbosity) = 0;
1851
nethercote04d0fbc2004-01-26 16:48:06 +00001852 if (VG_(clo_db_attach) && VG_(clo_trace_children)) {
sewardjde4a1d02002-03-22 01:27:54 +00001853 VG_(message)(Vg_UserMsg, "");
1854 VG_(message)(Vg_UserMsg,
nethercote04d0fbc2004-01-26 16:48:06 +00001855 "--db-attach=yes conflicts with --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001856 VG_(message)(Vg_UserMsg,
1857 "Please choose one or the other, but not both.");
nethercote04d0fbc2004-01-26 16:48:06 +00001858 VG_(bad_option)("--db-attach=yes and --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001859 }
1860
nethercotef8548672004-06-21 12:42:35 +00001861 /* Set up logging now. After this is done, VG_(clo_log_fd)
sewardj4cf05692002-10-27 20:28:29 +00001862 should be connected to whatever sink has been selected, and we
1863 indiscriminately chuck stuff into it without worrying what the
1864 nature of it is. Oh the wonder of Unix streams. */
1865
nethercotee1730692003-11-20 10:38:07 +00001866 /* So far we should be still attached to stdout, so we can show on
sewardj4cf05692002-10-27 20:28:29 +00001867 the terminal any problems to do with processing command line
1868 opts. */
nethercotef8548672004-06-21 12:42:35 +00001869 vg_assert(VG_(clo_log_fd) == 1 /* stdout */);
sewardj73cf3bc2002-11-03 03:20:15 +00001870 vg_assert(VG_(logging_to_filedes) == True);
sewardj4cf05692002-10-27 20:28:29 +00001871
1872 switch (VG_(clo_log_to)) {
sewardj73cf3bc2002-11-03 03:20:15 +00001873
sewardj4cf05692002-10-27 20:28:29 +00001874 case VgLogTo_Fd:
nethercotef8548672004-06-21 12:42:35 +00001875 vg_assert(VG_(clo_log_name) == NULL);
1876 VG_(clo_log_fd) = eventually_log_fd;
sewardj4cf05692002-10-27 20:28:29 +00001877 break;
sewardj73cf3bc2002-11-03 03:20:15 +00001878
sewardj4cf05692002-10-27 20:28:29 +00001879 case VgLogTo_File: {
1880 Char logfilename[1000];
jsgff3c3f1a2003-10-14 22:13:28 +00001881 Int seq = 0;
1882 Int pid = VG_(getpid)();
1883
nethercotef8548672004-06-21 12:42:35 +00001884 vg_assert(VG_(clo_log_name) != NULL);
1885 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
jsgff3c3f1a2003-10-14 22:13:28 +00001886
nethercote71980f02004-01-24 18:18:54 +00001887 for (;;) {
jsgff3c3f1a2003-10-14 22:13:28 +00001888 if (seq == 0)
1889 VG_(sprintf)(logfilename, "%s.pid%d",
nethercotef8548672004-06-21 12:42:35 +00001890 VG_(clo_log_name), pid );
jsgff3c3f1a2003-10-14 22:13:28 +00001891 else
1892 VG_(sprintf)(logfilename, "%s.pid%d.%d",
nethercotef8548672004-06-21 12:42:35 +00001893 VG_(clo_log_name), pid, seq );
jsgff3c3f1a2003-10-14 22:13:28 +00001894 seq++;
1895
nethercotef8548672004-06-21 12:42:35 +00001896 eventually_log_fd
jsgff3c3f1a2003-10-14 22:13:28 +00001897 = VG_(open)(logfilename,
1898 VKI_O_CREAT|VKI_O_WRONLY|VKI_O_EXCL|VKI_O_TRUNC,
1899 VKI_S_IRUSR|VKI_S_IWUSR);
nethercotef8548672004-06-21 12:42:35 +00001900 if (eventually_log_fd >= 0) {
1901 VG_(clo_log_fd) = VG_(safe_fd)(eventually_log_fd);
jsgff3c3f1a2003-10-14 22:13:28 +00001902 break;
1903 } else {
nethercotef8548672004-06-21 12:42:35 +00001904 if (eventually_log_fd != -VKI_EEXIST) {
jsgff3c3f1a2003-10-14 22:13:28 +00001905 VG_(message)(Vg_UserMsg,
1906 "Can't create/open log file `%s.pid%d'; giving up!",
nethercotef8548672004-06-21 12:42:35 +00001907 VG_(clo_log_name), pid);
jsgff3c3f1a2003-10-14 22:13:28 +00001908 VG_(bad_option)(
nethercotef8548672004-06-21 12:42:35 +00001909 "--log-file=<file> didn't work out for some reason.");
jsgff3c3f1a2003-10-14 22:13:28 +00001910 break;
1911 }
1912 }
1913 }
sewardj4cf05692002-10-27 20:28:29 +00001914 break;
sewardj73cf3bc2002-11-03 03:20:15 +00001915 }
1916
1917 case VgLogTo_Socket: {
nethercotef8548672004-06-21 12:42:35 +00001918 vg_assert(VG_(clo_log_name) != NULL);
1919 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
1920 eventually_log_fd = VG_(connect_via_socket)( VG_(clo_log_name) );
1921 if (eventually_log_fd == -1) {
sewardj73cf3bc2002-11-03 03:20:15 +00001922 VG_(message)(Vg_UserMsg,
nethercotef8548672004-06-21 12:42:35 +00001923 "Invalid --log-socket=ipaddr or --log-socket=ipaddr:port spec");
sewardj73cf3bc2002-11-03 03:20:15 +00001924 VG_(message)(Vg_UserMsg,
nethercotef8548672004-06-21 12:42:35 +00001925 "of `%s'; giving up!", VG_(clo_log_name) );
sewardj73cf3bc2002-11-03 03:20:15 +00001926 VG_(bad_option)(
nethercotef8548672004-06-21 12:42:35 +00001927 "--log-socket=");
sewardj4cf05692002-10-27 20:28:29 +00001928 }
nethercotef8548672004-06-21 12:42:35 +00001929 if (eventually_log_fd == -2) {
sewardj73cf3bc2002-11-03 03:20:15 +00001930 VG_(message)(Vg_UserMsg,
sewardj570f8902002-11-03 11:44:36 +00001931 "valgrind: failed to connect to logging server `%s'.",
nethercotef8548672004-06-21 12:42:35 +00001932 VG_(clo_log_name) );
sewardj570f8902002-11-03 11:44:36 +00001933 VG_(message)(Vg_UserMsg,
1934 "Log messages will sent to stderr instead." );
1935 VG_(message)(Vg_UserMsg,
1936 "" );
1937 /* We don't change anything here. */
1938 } else {
nethercotef8548672004-06-21 12:42:35 +00001939 vg_assert(eventually_log_fd > 0);
1940 VG_(clo_log_fd) = eventually_log_fd;
sewardj570f8902002-11-03 11:44:36 +00001941 VG_(logging_to_filedes) = False;
1942 }
sewardj73cf3bc2002-11-03 03:20:15 +00001943 break;
1944 }
1945
sewardj4cf05692002-10-27 20:28:29 +00001946 }
1947
nethercotef8548672004-06-21 12:42:35 +00001948 /* Move log_fd into the safe range, so it doesn't conflict with any app fds */
thughesad1c9562004-06-26 11:27:52 +00001949 eventually_log_fd = VG_(fcntl)(VG_(clo_log_fd), VKI_F_DUPFD, VG_(fd_hard_limit));
nethercotef8548672004-06-21 12:42:35 +00001950 if (eventually_log_fd < 0)
jsgf855d93d2003-10-13 22:26:55 +00001951 VG_(message)(Vg_UserMsg, "valgrind: failed to move logfile fd into safe range");
1952 else {
nethercotef8548672004-06-21 12:42:35 +00001953 VG_(clo_log_fd) = eventually_log_fd;
1954 VG_(fcntl)(VG_(clo_log_fd), VKI_F_SETFD, VKI_FD_CLOEXEC);
jsgf855d93d2003-10-13 22:26:55 +00001955 }
1956
sewardj4cf05692002-10-27 20:28:29 +00001957 /* Ok, the logging sink is running now. Print a suitable preamble.
1958 If logging to file or a socket, write details of parent PID and
1959 command line args, to help people trying to interpret the
1960 results of a run which encompasses multiple processes. */
sewardjde4a1d02002-03-22 01:27:54 +00001961
sewardj83adf412002-05-01 01:25:45 +00001962 if (VG_(clo_verbosity > 0)) {
nethercote996901a2004-08-03 13:29:09 +00001963 /* Tool details */
nethercotea131bb82004-09-06 15:34:37 +00001964 VG_(message)(Vg_UserMsg, "%s%s%s, %s for %s.",
njnd04b7c62002-10-03 14:05:52 +00001965 VG_(details).name,
1966 NULL == VG_(details).version ? "" : "-",
1967 NULL == VG_(details).version
1968 ? (Char*)"" : VG_(details).version,
nethercotea131bb82004-09-06 15:34:37 +00001969 VG_(details).description,
1970 VG_PLATFORM);
njnd04b7c62002-10-03 14:05:52 +00001971 VG_(message)(Vg_UserMsg, "%s", VG_(details).copyright_author);
sewardj3b2736a2002-03-24 12:18:35 +00001972
njnd04b7c62002-10-03 14:05:52 +00001973 /* Core details */
1974 VG_(message)(Vg_UserMsg,
nethercotea131bb82004-09-06 15:34:37 +00001975 "Using valgrind-%s, a program supervision framework for %s.",
1976 VERSION, VG_PLATFORM);
sewardjde4a1d02002-03-22 01:27:54 +00001977 VG_(message)(Vg_UserMsg,
nethercote08fa9a72004-07-16 17:44:00 +00001978 "Copyright (C) 2000-2004, and GNU GPL'd, by Julian Seward et al.");
njnd04b7c62002-10-03 14:05:52 +00001979 }
1980
nethercotec1e395d2003-11-10 13:26:49 +00001981 if (VG_(clo_verbosity) > 0 && VG_(clo_log_to) != VgLogTo_Fd) {
sewardj4cf05692002-10-27 20:28:29 +00001982 VG_(message)(Vg_UserMsg, "");
1983 VG_(message)(Vg_UserMsg,
1984 "My PID = %d, parent PID = %d. Prog and args are:",
1985 VG_(getpid)(), VG_(getppid)() );
1986 for (i = 0; i < VG_(client_argc); i++)
1987 VG_(message)(Vg_UserMsg, " %s", VG_(client_argv)[i]);
1988 }
1989
sewardjde4a1d02002-03-22 01:27:54 +00001990 if (VG_(clo_verbosity) > 1) {
nethercotea70f7352004-04-18 12:08:46 +00001991 Int fd;
sewardj4cf05692002-10-27 20:28:29 +00001992 if (VG_(clo_log_to) != VgLogTo_Fd)
1993 VG_(message)(Vg_UserMsg, "");
fitzhardinge98abfc72003-12-16 02:05:15 +00001994 VG_(message)(Vg_UserMsg, "Valgrind library directory: %s", VG_(libdir));
njn86dc2bc2003-09-09 07:26:21 +00001995 VG_(message)(Vg_UserMsg, "Command line");
1996 for (i = 0; i < VG_(client_argc); i++)
1997 VG_(message)(Vg_UserMsg, " %s", VG_(client_argv)[i]);
1998
sewardjde4a1d02002-03-22 01:27:54 +00001999 VG_(message)(Vg_UserMsg, "Startup, with flags:");
nethercotef6a1d502004-08-09 12:21:57 +00002000 for (i = 1; i < vg_argc; i++) {
2001 VG_(message)(Vg_UserMsg, " %s", vg_argv[i]);
sewardjde4a1d02002-03-22 01:27:54 +00002002 }
nethercotea70f7352004-04-18 12:08:46 +00002003
2004 VG_(message)(Vg_UserMsg, "Contents of /proc/version:");
2005 fd = VG_(open) ( "/proc/version", VKI_O_RDONLY, 0 );
2006 if (fd < 0) {
2007 VG_(message)(Vg_UserMsg, " can't open /proc/version");
2008 } else {
2009 #define BUF_LEN 256
2010 Char version_buf[BUF_LEN];
2011 Int n = VG_(read) ( fd, version_buf, BUF_LEN );
2012 vg_assert(n <= 256);
2013 if (n > 0) {
2014 version_buf[n-1] = '\0';
2015 VG_(message)(Vg_UserMsg, " %s", version_buf);
2016 } else {
2017 VG_(message)(Vg_UserMsg, " (empty?)");
2018 }
2019 VG_(close)(fd);
2020 #undef BUF_LEN
2021 }
sewardjde4a1d02002-03-22 01:27:54 +00002022 }
2023
fitzhardinge98abfc72003-12-16 02:05:15 +00002024 if (VG_(clo_n_suppressions) < VG_CLO_MAX_SFILES-1 &&
njn25e49d8e72002-09-23 09:36:25 +00002025 (VG_(needs).core_errors || VG_(needs).skin_errors)) {
nethercote996901a2004-08-03 13:29:09 +00002026 /* If there are no suppression files specified and the tool
fitzhardinge98abfc72003-12-16 02:05:15 +00002027 needs one, load the default */
2028 static const Char default_supp[] = "default.supp";
2029 Int len = VG_(strlen)(VG_(libdir)) + 1 + sizeof(default_supp);
2030 Char *buf = VG_(arena_malloc)(VG_AR_CORE, len);
2031 VG_(sprintf)(buf, "%s/%s", VG_(libdir), default_supp);
2032 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = buf;
2033 VG_(clo_n_suppressions)++;
sewardjde4a1d02002-03-22 01:27:54 +00002034 }
sewardj4cf05692002-10-27 20:28:29 +00002035
njn6a230532003-07-21 10:38:23 +00002036 if (VG_(clo_gen_suppressions) &&
2037 !VG_(needs).core_errors && !VG_(needs).skin_errors) {
nethercotef4928da2004-06-15 10:54:40 +00002038 VG_(message)(Vg_UserMsg,
2039 "Can't use --gen-suppressions=yes with this tool,");
2040 VG_(message)(Vg_UserMsg,
2041 "as it doesn't generate errors.");
2042 VG_(bad_option)("--gen-suppressions=yes");
njn6a230532003-07-21 10:38:23 +00002043 }
sewardjde4a1d02002-03-22 01:27:54 +00002044}
2045
nethercotef6a1d502004-08-09 12:21:57 +00002046// Build the string for VALGRINDCLO.
2047Char* VG_(build_child_VALGRINDCLO)( Char* exename )
2048{
2049 /* If we're tracing the children, then we need to start it
2050 with our starter+arguments, which are copied into VALGRINDCLO,
2051 except the --exec= option is changed if present.
2052 */
2053 Int i;
2054 Char *exec;
2055 Char *cp;
2056 Char *optvar;
2057 Int optlen, execlen;
2058
2059 // All these allocated blocks are not free - because we're either
2060 // going to exec, or panic when we fail.
2061
2062 // Create --exec= option: "--exec=<exename>"
2063 exec = VG_(arena_malloc)(VG_AR_CORE,
2064 VG_(strlen)( exename ) + 7/*--exec=*/ + 1/*\0*/);
2065 vg_assert(NULL != exec);
2066 VG_(sprintf)(exec, "--exec=%s", exename);
2067
2068 // Allocate space for optvar (may overestimate by counting --exec twice,
2069 // no matter)
2070 optlen = 1;
2071 for (i = 0; i < vg_argc; i++)
2072 optlen += VG_(strlen)(vg_argv[i]) + 1;
2073 optlen += VG_(strlen)(exec)+1;
2074 optvar = VG_(arena_malloc)(VG_AR_CORE, optlen);
2075
2076 // Copy all valgrind args except the old --exec (if present)
2077 // VG_CLO_SEP is the separator.
2078 cp = optvar;
2079 for (i = 1; i < vg_argc; i++) {
2080 Char *arg = vg_argv[i];
2081
2082 if (VG_(memcmp)(arg, "--exec=", 7) == 0) {
2083 // don't copy existing --exec= arg
2084 } else if (VG_(strcmp)(arg, "--") == 0) {
2085 // stop at "--"
2086 break;
2087 } else {
2088 // copy non "--exec" arg
2089 Int len = VG_(strlen)(arg);
2090 VG_(memcpy)(cp, arg, len);
2091 cp += len;
2092 *cp++ = VG_CLO_SEP;
2093 }
2094 }
2095 // Add the new --exec= option
2096 execlen = VG_(strlen)(exec);
2097 VG_(memcpy)(cp, exec, execlen);
2098 cp += execlen;
2099 *cp++ = VG_CLO_SEP;
2100
2101 *cp = '\0';
2102
2103 return optvar;
2104}
2105
2106// Build "/proc/self/fd/<execfd>".
2107Char* VG_(build_child_exename)( void )
2108{
2109 Char* exename = VG_(arena_malloc)(VG_AR_CORE, 64);
2110 vg_assert(NULL != exename);
2111 VG_(sprintf)(exename, "/proc/self/fd/%d", vgexecfd);
2112 return exename;
2113}
2114
sewardjde4a1d02002-03-22 01:27:54 +00002115
nethercote71980f02004-01-24 18:18:54 +00002116/*====================================================================*/
2117/*=== File descriptor setup ===*/
2118/*====================================================================*/
2119
2120static void setup_file_descriptors(void)
2121{
2122 struct vki_rlimit rl;
2123
2124 /* Get the current file descriptor limits. */
2125 if (VG_(getrlimit)(VKI_RLIMIT_NOFILE, &rl) < 0) {
2126 rl.rlim_cur = 1024;
2127 rl.rlim_max = 1024;
2128 }
2129
2130 /* Work out where to move the soft limit to. */
2131 if (rl.rlim_cur + VG_N_RESERVED_FDS <= rl.rlim_max) {
2132 rl.rlim_cur = rl.rlim_cur + VG_N_RESERVED_FDS;
2133 } else {
2134 rl.rlim_cur = rl.rlim_max;
2135 }
2136
2137 /* Reserve some file descriptors for our use. */
thughesad1c9562004-06-26 11:27:52 +00002138 VG_(fd_soft_limit) = rl.rlim_cur - VG_N_RESERVED_FDS;
2139 VG_(fd_hard_limit) = rl.rlim_cur - VG_N_RESERVED_FDS;
nethercote71980f02004-01-24 18:18:54 +00002140
2141 /* Update the soft limit. */
2142 VG_(setrlimit)(VKI_RLIMIT_NOFILE, &rl);
2143
nethercotef6a1d502004-08-09 12:21:57 +00002144 if (vgexecfd != -1)
2145 vgexecfd = VG_(safe_fd)( vgexecfd );
nethercote71980f02004-01-24 18:18:54 +00002146 if (VG_(clexecfd) != -1)
2147 VG_(clexecfd) = VG_(safe_fd)( VG_(clexecfd) );
2148}
2149
2150
2151/*====================================================================*/
nethercote1d447092004-02-01 17:29:59 +00002152/*=== baseBlock: definition + setup ===*/
nethercote71980f02004-01-24 18:18:54 +00002153/*====================================================================*/
2154
nethercote71980f02004-01-24 18:18:54 +00002155Int VGOFF_(helper_undefined_instruction) = INVALID_OFFSET;
2156
2157/* MAX_NONCOMPACT_HELPERS can be increased easily. If MAX_COMPACT_HELPERS is
2158 * increased too much, they won't really be compact any more... */
2159#define MAX_COMPACT_HELPERS 8
2160#define MAX_NONCOMPACT_HELPERS 50
2161
nethercote81f9a6f2004-08-03 15:45:46 +00002162/* For storing tool-specific helpers, determined at runtime. The addr
2163 * and offset arrays together form a (addr, offset) map that allows a
2164 * helper's baseBlock offset to be computed from its address. It's done
2165 * like this so CCALLs can use the function address rather than having to
2166 * muck around with offsets. */
2167static UInt VG_(n_compact_helpers) = 0;
2168static UInt VG_(n_noncompact_helpers) = 0;
2169static Addr VG_(compact_helper_addrs) [MAX_COMPACT_HELPERS];
2170static Int VG_(compact_helper_offsets)[MAX_COMPACT_HELPERS];
2171static Addr VG_(noncompact_helper_addrs) [MAX_NONCOMPACT_HELPERS];
2172static Int VG_(noncompact_helper_offsets)[MAX_NONCOMPACT_HELPERS];
nethercote71980f02004-01-24 18:18:54 +00002173
2174/* This is the actual defn of baseblock. */
2175UInt VG_(baseBlock)[VG_BASEBLOCK_WORDS];
2176
nethercote71980f02004-01-24 18:18:54 +00002177/* Words. */
2178static Int baB_off = 0;
2179
2180
nethercote71980f02004-01-24 18:18:54 +00002181/* Returns the offset, in words. */
nethercote2e05c332004-09-06 16:43:37 +00002182Int VG_(alloc_BaB) ( Int words )
sewardjde4a1d02002-03-22 01:27:54 +00002183{
nethercote71980f02004-01-24 18:18:54 +00002184 Int off = baB_off;
2185 baB_off += words;
2186 if (baB_off >= VG_BASEBLOCK_WORDS)
nethercote2e05c332004-09-06 16:43:37 +00002187 VG_(core_panic)( "VG_(alloc_BaB): baseBlock is too small");
sewardjde4a1d02002-03-22 01:27:54 +00002188
nethercote71980f02004-01-24 18:18:54 +00002189 return off;
sewardjde4a1d02002-03-22 01:27:54 +00002190}
2191
nethercote71980f02004-01-24 18:18:54 +00002192/* Align offset, in *bytes* */
nethercote2e05c332004-09-06 16:43:37 +00002193void VG_(align_BaB) ( UInt align )
njn25e49d8e72002-09-23 09:36:25 +00002194{
nethercote71980f02004-01-24 18:18:54 +00002195 vg_assert(2 == align || 4 == align || 8 == align || 16 == align);
2196 baB_off += (align-1);
2197 baB_off &= ~(align-1);
njn25e49d8e72002-09-23 09:36:25 +00002198}
2199
nethercote71980f02004-01-24 18:18:54 +00002200/* Allocate 1 word in baseBlock and set it to the given value. */
nethercote2e05c332004-09-06 16:43:37 +00002201Int VG_(alloc_BaB_1_set) ( Addr a )
njn25e49d8e72002-09-23 09:36:25 +00002202{
nethercote2e05c332004-09-06 16:43:37 +00002203 Int off = VG_(alloc_BaB)(1);
nethercote71980f02004-01-24 18:18:54 +00002204 VG_(baseBlock)[off] = (UInt)a;
2205 return off;
njn25e49d8e72002-09-23 09:36:25 +00002206}
2207
nethercote71980f02004-01-24 18:18:54 +00002208/* Registers a function in compact_helper_addrs; compact_helper_offsets is
2209 filled in later. */
2210void VG_(register_compact_helper)(Addr a)
sewardjde4a1d02002-03-22 01:27:54 +00002211{
nethercote71980f02004-01-24 18:18:54 +00002212 if (MAX_COMPACT_HELPERS <= VG_(n_compact_helpers)) {
2213 VG_(printf)("Can only register %d compact helpers\n",
2214 MAX_COMPACT_HELPERS);
2215 VG_(core_panic)("Too many compact helpers registered");
2216 }
2217 VG_(compact_helper_addrs)[VG_(n_compact_helpers)] = a;
2218 VG_(n_compact_helpers)++;
2219}
2220
2221/* Registers a function in noncompact_helper_addrs; noncompact_helper_offsets
2222 * is filled in later.
2223 */
2224void VG_(register_noncompact_helper)(Addr a)
2225{
2226 if (MAX_NONCOMPACT_HELPERS <= VG_(n_noncompact_helpers)) {
2227 VG_(printf)("Can only register %d non-compact helpers\n",
2228 MAX_NONCOMPACT_HELPERS);
2229 VG_(printf)("Try increasing MAX_NON_COMPACT_HELPERS\n");
2230 VG_(core_panic)("Too many non-compact helpers registered");
2231 }
2232 VG_(noncompact_helper_addrs)[VG_(n_noncompact_helpers)] = a;
2233 VG_(n_noncompact_helpers)++;
2234}
2235
nethercote996901a2004-08-03 13:29:09 +00002236/* Allocate offsets in baseBlock for the tool helpers */
nethercote71980f02004-01-24 18:18:54 +00002237static
2238void assign_helpers_in_baseBlock(UInt n, Int offsets[], Addr addrs[])
2239{
2240 UInt i;
2241 for (i = 0; i < n; i++)
nethercote2e05c332004-09-06 16:43:37 +00002242 offsets[i] = VG_(alloc_BaB_1_set)( addrs[i] );
nethercote71980f02004-01-24 18:18:54 +00002243}
2244
nethercote4ad74312004-10-26 09:59:49 +00002245Bool VG_(need_to_handle_SP_assignment)(void)
nethercote71980f02004-01-24 18:18:54 +00002246{
2247 return ( VG_(defined_new_mem_stack_4)() ||
2248 VG_(defined_die_mem_stack_4)() ||
2249 VG_(defined_new_mem_stack_8)() ||
2250 VG_(defined_die_mem_stack_8)() ||
2251 VG_(defined_new_mem_stack_12)() ||
2252 VG_(defined_die_mem_stack_12)() ||
2253 VG_(defined_new_mem_stack_16)() ||
2254 VG_(defined_die_mem_stack_16)() ||
2255 VG_(defined_new_mem_stack_32)() ||
2256 VG_(defined_die_mem_stack_32)() ||
2257 VG_(defined_new_mem_stack)() ||
2258 VG_(defined_die_mem_stack)()
2259 );
2260}
2261
nethercote2e05c332004-09-06 16:43:37 +00002262// The low/high split is for x86, so that the more common helpers can be
2263// in the first 128 bytes of the start, which allows the use of a more
2264// compact addressing mode.
nethercote4ad74312004-10-26 09:59:49 +00002265static void init_baseBlock ( Addr client_eip, Addr sp_at_startup )
nethercote71980f02004-01-24 18:18:54 +00002266{
nethercote4ad74312004-10-26 09:59:49 +00002267 VGA_(init_low_baseBlock)(client_eip, sp_at_startup);
nethercote71980f02004-01-24 18:18:54 +00002268
nethercote71980f02004-01-24 18:18:54 +00002269 /* Allocate slots for compact helpers */
2270 assign_helpers_in_baseBlock(VG_(n_compact_helpers),
2271 VG_(compact_helper_offsets),
2272 VG_(compact_helper_addrs));
2273
nethercote4ad74312004-10-26 09:59:49 +00002274 VGA_(init_high_baseBlock)(client_eip, sp_at_startup);
fitzhardingef0046f22003-12-18 02:39:22 +00002275
nethercote71980f02004-01-24 18:18:54 +00002276#define REG(kind, size) \
2277 if (VG_(defined_##kind##_mem_stack##size)()) \
2278 VG_(register_noncompact_helper)( \
2279 (Addr) VG_(tool_interface).track_##kind##_mem_stack##size );
2280 REG(new, _8);
2281 REG(new, _12);
2282 REG(new, _16);
2283 REG(new, _32);
2284 REG(new, );
2285 REG(die, _8);
2286 REG(die, _12);
2287 REG(die, _16);
2288 REG(die, _32);
2289 REG(die, );
2290#undef REG
fitzhardingef0046f22003-12-18 02:39:22 +00002291
nethercote4ad74312004-10-26 09:59:49 +00002292 if (VG_(need_to_handle_SP_assignment)())
2293 VG_(register_noncompact_helper)((Addr) VG_(unknown_SP_update));
fitzhardingeb791a192003-12-18 07:22:44 +00002294
nethercote2e05c332004-09-06 16:43:37 +00002295 VGOFF_(helper_undefined_instruction)
2296 = VG_(alloc_BaB_1_set)( (Addr) & VG_(helper_undefined_instruction));
sewardjde4a1d02002-03-22 01:27:54 +00002297
nethercote71980f02004-01-24 18:18:54 +00002298 /* Allocate slots for noncompact helpers */
2299 assign_helpers_in_baseBlock(VG_(n_noncompact_helpers),
2300 VG_(noncompact_helper_offsets),
2301 VG_(noncompact_helper_addrs));
2302}
sewardjde4a1d02002-03-22 01:27:54 +00002303
nethercote81f9a6f2004-08-03 15:45:46 +00002304// Finds the baseBlock offset of a tool-specified helper.
2305// Searches through compacts first, then non-compacts.
2306Int VG_(helper_offset)(Addr a)
2307{
2308 UInt i;
2309 Char buf[100];
2310
2311 for (i = 0; i < VG_(n_compact_helpers); i++)
2312 if (VG_(compact_helper_addrs)[i] == a)
2313 return VG_(compact_helper_offsets)[i];
2314 for (i = 0; i < VG_(n_noncompact_helpers); i++)
2315 if (VG_(noncompact_helper_addrs)[i] == a)
2316 return VG_(noncompact_helper_offsets)[i];
2317
2318 /* Shouldn't get here */
2319 VG_(get_fnname) ( a, buf, 100 );
2320
2321 VG_(printf)(
2322 "\nCouldn't find offset of helper from its address (%p: %s).\n"
2323 "A helper function probably used hasn't been registered?\n\n", a, buf);
2324
2325 VG_(printf)(" compact helpers: ");
2326 for (i = 0; i < VG_(n_compact_helpers); i++)
2327 VG_(printf)("%p ", VG_(compact_helper_addrs)[i]);
2328
2329 VG_(printf)("\n non-compact helpers: ");
2330 for (i = 0; i < VG_(n_noncompact_helpers); i++)
2331 VG_(printf)("%p ", VG_(noncompact_helper_addrs)[i]);
2332
2333 VG_(printf)("\n");
2334 VG_(skin_panic)("Unfound helper");
2335}
2336
sewardj5f07b662002-04-23 16:52:51 +00002337
nethercote71980f02004-01-24 18:18:54 +00002338/*====================================================================*/
nethercote71980f02004-01-24 18:18:54 +00002339/*=== Initialise program data/text, etc. ===*/
2340/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +00002341
nethercote71980f02004-01-24 18:18:54 +00002342static void build_valgrind_map_callback
2343 ( Addr start, UInt size, Char rr, Char ww, Char xx,
2344 UInt dev, UInt ino, ULong foffset, const UChar* filename )
sewardjde4a1d02002-03-22 01:27:54 +00002345{
nethercote71980f02004-01-24 18:18:54 +00002346 UInt prot = 0;
2347 UInt flags = SF_MMAP|SF_NOSYMS;
2348 Bool is_stack_segment;
2349
2350 is_stack_segment =
2351 (start == VG_(clstk_base) && (start+size) == VG_(clstk_end));
2352
2353 /* Only record valgrind mappings for now, without loading any
2354 symbols. This is so we know where the free space is before we
2355 start allocating more memory (note: heap is OK, it's just mmap
2356 which is the problem here). */
nethercote820bd8c2004-09-07 23:04:49 +00002357 if (start >= VG_(valgrind_base) && (start+size-1) <= VG_(valgrind_last)) {
nethercote71980f02004-01-24 18:18:54 +00002358 flags |= SF_VALGRIND;
2359 VG_(map_file_segment)(start, size, prot, flags, dev, ino, foffset, filename);
2360 }
sewardjde4a1d02002-03-22 01:27:54 +00002361}
2362
nethercote71980f02004-01-24 18:18:54 +00002363// Global var used to pass local data to callback
nethercote4ad74312004-10-26 09:59:49 +00002364Addr sp_at_startup___global_arg = 0;
sewardjde4a1d02002-03-22 01:27:54 +00002365
nethercote71980f02004-01-24 18:18:54 +00002366static void build_segment_map_callback
2367 ( Addr start, UInt size, Char rr, Char ww, Char xx,
2368 UInt dev, UInt ino, ULong foffset, const UChar* filename )
sewardj45b672d2003-07-25 19:58:11 +00002369{
nethercote71980f02004-01-24 18:18:54 +00002370 UInt prot = 0;
2371 UInt flags;
2372 Bool is_stack_segment;
2373 Addr r_esp;
sewardj45b672d2003-07-25 19:58:11 +00002374
nethercote71980f02004-01-24 18:18:54 +00002375 is_stack_segment
2376 = (start == VG_(clstk_base) && (start+size) == VG_(clstk_end));
fitzhardinge98abfc72003-12-16 02:05:15 +00002377
nethercote71980f02004-01-24 18:18:54 +00002378 if (rr == 'r') prot |= VKI_PROT_READ;
2379 if (ww == 'w') prot |= VKI_PROT_WRITE;
2380 if (xx == 'x') prot |= VKI_PROT_EXEC;
fitzhardinge98abfc72003-12-16 02:05:15 +00002381
nethercote71980f02004-01-24 18:18:54 +00002382 if (is_stack_segment)
2383 flags = SF_STACK | SF_GROWDOWN;
2384 else
2385 flags = SF_EXEC|SF_MMAP;
fitzhardinge98abfc72003-12-16 02:05:15 +00002386
nethercote71980f02004-01-24 18:18:54 +00002387 if (filename != NULL)
2388 flags |= SF_FILE;
fitzhardinge98abfc72003-12-16 02:05:15 +00002389
nethercote820bd8c2004-09-07 23:04:49 +00002390 if (start >= VG_(valgrind_base) && (start+size-1) <= VG_(valgrind_last))
nethercote71980f02004-01-24 18:18:54 +00002391 flags |= SF_VALGRIND;
fitzhardinge98abfc72003-12-16 02:05:15 +00002392
nethercote71980f02004-01-24 18:18:54 +00002393 VG_(map_file_segment)(start, size, prot, flags, dev, ino, foffset, filename);
fitzhardinge98abfc72003-12-16 02:05:15 +00002394
nethercote71980f02004-01-24 18:18:54 +00002395 if (VG_(is_client_addr)(start) && VG_(is_client_addr)(start+size-1))
2396 VG_TRACK( new_mem_startup, start, size, rr=='r', ww=='w', xx=='x' );
sewardj3e1eb1f2002-05-18 13:14:17 +00002397
nethercote71980f02004-01-24 18:18:54 +00002398 /* If this is the stack segment mark all below %esp as noaccess. */
nethercote4ad74312004-10-26 09:59:49 +00002399 r_esp = sp_at_startup___global_arg;
nethercote71980f02004-01-24 18:18:54 +00002400 vg_assert(0 != r_esp);
2401 if (is_stack_segment) {
2402 if (0)
2403 VG_(message)(Vg_DebugMsg, "invalidating stack area: %x .. %x",
2404 start,r_esp);
2405 VG_TRACK( die_mem_stack, start, r_esp-start );
sewardjde4a1d02002-03-22 01:27:54 +00002406 }
sewardjde4a1d02002-03-22 01:27:54 +00002407}
2408
2409
nethercote71980f02004-01-24 18:18:54 +00002410/*====================================================================*/
2411/*=== Sanity check machinery (permanently engaged) ===*/
2412/*====================================================================*/
njn25e49d8e72002-09-23 09:36:25 +00002413
2414/* A fast sanity check -- suitable for calling circa once per
2415 millisecond. */
2416
nethercote885dd912004-08-03 23:14:00 +00002417void VG_(sanity_check_general) ( Bool force_expensive )
njn25e49d8e72002-09-23 09:36:25 +00002418{
njn37cea302002-09-30 11:24:00 +00002419 VGP_PUSHCC(VgpCoreCheapSanity);
2420
nethercote27fec902004-06-16 21:26:32 +00002421 if (VG_(clo_sanity_level) < 1) return;
njn25e49d8e72002-09-23 09:36:25 +00002422
2423 /* --- First do all the tests that we can do quickly. ---*/
2424
nethercote297effd2004-08-02 15:07:57 +00002425 sanity_fast_count++;
njn25e49d8e72002-09-23 09:36:25 +00002426
njn25e49d8e72002-09-23 09:36:25 +00002427 /* Check stuff pertaining to the memory check system. */
2428
2429 /* Check that nobody has spuriously claimed that the first or
2430 last 16 pages of memory have become accessible [...] */
njn37cea302002-09-30 11:24:00 +00002431 if (VG_(needs).sanity_checks) {
2432 VGP_PUSHCC(VgpSkinCheapSanity);
njn25e49d8e72002-09-23 09:36:25 +00002433 vg_assert(SK_(cheap_sanity_check)());
njn37cea302002-09-30 11:24:00 +00002434 VGP_POPCC(VgpSkinCheapSanity);
2435 }
njn25e49d8e72002-09-23 09:36:25 +00002436
2437 /* --- Now some more expensive checks. ---*/
2438
2439 /* Once every 25 times, check some more expensive stuff. */
2440 if ( force_expensive
nethercote27fec902004-06-16 21:26:32 +00002441 || VG_(clo_sanity_level) > 1
nethercote297effd2004-08-02 15:07:57 +00002442 || (VG_(clo_sanity_level) == 1 && (sanity_fast_count % 25) == 0)) {
njn25e49d8e72002-09-23 09:36:25 +00002443
njn37cea302002-09-30 11:24:00 +00002444 VGP_PUSHCC(VgpCoreExpensiveSanity);
nethercote297effd2004-08-02 15:07:57 +00002445 sanity_slow_count++;
njn25e49d8e72002-09-23 09:36:25 +00002446
nethercote885dd912004-08-03 23:14:00 +00002447 VG_(sanity_check_proxy)();
jsgf855d93d2003-10-13 22:26:55 +00002448
njn25e49d8e72002-09-23 09:36:25 +00002449# if 0
2450 { void zzzmemscan(void); zzzmemscan(); }
2451# endif
2452
nethercote297effd2004-08-02 15:07:57 +00002453 if ((sanity_fast_count % 250) == 0)
nethercote92e7b7f2004-08-07 17:52:25 +00002454 VG_(sanity_check_tt_tc)();
njn25e49d8e72002-09-23 09:36:25 +00002455
2456 if (VG_(needs).sanity_checks) {
njn37cea302002-09-30 11:24:00 +00002457 VGP_PUSHCC(VgpSkinExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002458 vg_assert(SK_(expensive_sanity_check)());
njn37cea302002-09-30 11:24:00 +00002459 VGP_POPCC(VgpSkinExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002460 }
2461 /*
nethercote297effd2004-08-02 15:07:57 +00002462 if ((sanity_fast_count % 500) == 0) VG_(mallocSanityCheckAll)();
njn25e49d8e72002-09-23 09:36:25 +00002463 */
njn37cea302002-09-30 11:24:00 +00002464 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002465 }
2466
nethercote27fec902004-06-16 21:26:32 +00002467 if (VG_(clo_sanity_level) > 1) {
njn37cea302002-09-30 11:24:00 +00002468 VGP_PUSHCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002469 /* Check sanity of the low-level memory manager. Note that bugs
2470 in the client's code can cause this to fail, so we don't do
2471 this check unless specially asked for. And because it's
2472 potentially very expensive. */
nethercote885dd912004-08-03 23:14:00 +00002473 VG_(sanity_check_malloc_all)();
njn37cea302002-09-30 11:24:00 +00002474 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002475 }
njn37cea302002-09-30 11:24:00 +00002476 VGP_POPCC(VgpCoreCheapSanity);
njn25e49d8e72002-09-23 09:36:25 +00002477}
nethercote71980f02004-01-24 18:18:54 +00002478
2479
2480/*====================================================================*/
2481/*=== main() ===*/
2482/*====================================================================*/
2483
nethercotec314eba2004-07-15 12:59:41 +00002484/*
2485 This code decides on the layout of the client and Valgrind address
nethercote996901a2004-08-03 13:29:09 +00002486 spaces, loads valgrind.so and the tool.so into the valgrind part,
nethercotec314eba2004-07-15 12:59:41 +00002487 loads the client executable (and the dynamic linker, if necessary)
2488 into the client part, and calls into Valgrind proper.
2489
2490 The code is careful not to allow spurious mappings to appear in the
2491 wrong parts of the address space. In particular, to make sure
2492 dlopen puts things in the right place, it will pad out the forbidden
2493 chunks of address space so that dlopen is forced to put things where
2494 we want them.
2495
2496 The memory map it creates is:
2497
2498 CLIENT_BASE +-------------------------+
2499 | client address space |
2500 : :
2501 : :
2502 | client stack |
2503 client_end +-------------------------+
2504 | redzone |
2505 shadow_base +-------------------------+
2506 | |
nethercote996901a2004-08-03 13:29:09 +00002507 : shadow memory for tools :
nethercotec314eba2004-07-15 12:59:41 +00002508 | (may be 0 sized) |
2509 shadow_end +-------------------------+
nethercotec314eba2004-07-15 12:59:41 +00002510 valgrind_base +-------------------------+
2511 | kickstart executable |
2512 | valgrind heap vvvvvvvvv| (barely used)
2513 - -
2514 | valgrind .so files |
2515 | and mappings |
2516 - -
2517 | valgrind stack ^^^^^^^^^|
nethercote820bd8c2004-09-07 23:04:49 +00002518 valgrind_last +-------------------------+
nethercotec314eba2004-07-15 12:59:41 +00002519 : kernel :
2520
2521 Nb: Before we can do general allocations with VG_(arena_malloc)() and
2522 VG_(mmap)(), we need to build the segment skip-list, so we know where
2523 we can put things. However, building that structure requires
2524 allocating memory. So we need to a bootstrapping process. It's done
2525 by making VG_(arena_malloc)() have a special static superblock that's
2526 used for the first 1MB's worth of allocations. This is enough to
2527 build the segment skip-list.
2528*/
2529
nethercote31779c72004-07-30 21:50:15 +00002530static int prmap(char *start, char *end, const char *perm, off_t off,
2531 int maj, int min, int ino, void* dummy) {
thughes4ad52d02004-06-27 17:37:21 +00002532 printf("mapping %10p-%10p %s %02x:%02x %d\n",
2533 start, end, perm, maj, min, ino);
2534 return True;
2535}
2536
nethercote71980f02004-01-24 18:18:54 +00002537int main(int argc, char **argv)
2538{
2539 char **cl_argv;
2540 const char *tool = NULL;
2541 const char *exec = NULL;
2542 char *preload; /* tool-specific LD_PRELOAD .so */
2543 char **env;
nethercote6c999f22004-01-31 22:55:15 +00002544 Int need_help = 0; // 0 = no, 1 = --help, 2 = --help-debug
nethercote71980f02004-01-24 18:18:54 +00002545 struct exeinfo info;
2546 ToolInfo *toolinfo = NULL;
2547 void *tool_dlhandle;
2548 Addr client_eip;
nethercote4ad74312004-10-26 09:59:49 +00002549 Addr sp_at_startup; /* client's SP at the point we gained control. */
nethercote71980f02004-01-24 18:18:54 +00002550 UInt * client_auxv;
2551 VgSchedReturnCode src;
nethercote47dd12c2004-06-22 14:18:42 +00002552 Int exitcode = 0;
nethercote238a3c32004-08-09 13:13:31 +00002553 Int fatal_sigNo = -1;
nethercote73b526f2004-10-31 18:48:21 +00002554 struct vki_rlimit zero = { 0, 0 };
nethercote31779c72004-07-30 21:50:15 +00002555 Int padfile;
nethercote759dda32004-08-07 18:16:56 +00002556 ThreadId last_run_tid = 0; // Last thread the scheduler ran.
2557
nethercote71980f02004-01-24 18:18:54 +00002558
2559 //============================================================
2560 // Nb: startup is complex. Prerequisites are shown at every step.
2561 //
2562 // *** Be very careful when messing with the order ***
2563 //============================================================
2564
nethercotef4928da2004-06-15 10:54:40 +00002565 //============================================================
2566 // Command line argument handling order:
2567 // * If --help/--help-debug are present, show usage message
2568 // (if --tool is also present, that includes the tool-specific usage)
2569 // * Then, if --tool is missing, abort with error msg
2570 // * Then, if client is missing, abort with error msg
2571 // * Then, if any cmdline args are bad, abort with error msg
2572 //============================================================
2573
fitzhardingeb50068f2004-02-24 23:42:55 +00002574 // Get the current process datasize rlimit, and set it to zero.
2575 // This prevents any internal uses of brk() from having any effect.
2576 // We remember the old value so we can restore it on exec, so that
2577 // child processes will have a reasonable brk value.
2578 VG_(getrlimit)(VKI_RLIMIT_DATA, &VG_(client_rlimit_data));
2579 zero.rlim_max = VG_(client_rlimit_data).rlim_max;
2580 VG_(setrlimit)(VKI_RLIMIT_DATA, &zero);
thughesc37184f2004-09-11 14:16:57 +00002581
2582 // Get the current process stack rlimit.
2583 VG_(getrlimit)(VKI_RLIMIT_STACK, &VG_(client_rlimit_stack));
2584
nethercote71980f02004-01-24 18:18:54 +00002585 //--------------------------------------------------------------
2586 // Check we were launched by stage1
nethercotec314eba2004-07-15 12:59:41 +00002587 // p: n/a
nethercote71980f02004-01-24 18:18:54 +00002588 //--------------------------------------------------------------
nethercotec25c4492004-10-18 11:52:17 +00002589 {
2590 void* init_sp = argv - 1;
2591 padfile = scan_auxv(init_sp);
2592 }
nethercote71980f02004-01-24 18:18:54 +00002593
2594 if (0) {
nethercote71980f02004-01-24 18:18:54 +00002595 printf("========== main() ==========\n");
nethercote31779c72004-07-30 21:50:15 +00002596 foreach_map(prmap, /*dummy*/NULL);
nethercote71980f02004-01-24 18:18:54 +00002597 }
2598
2599 //--------------------------------------------------------------
2600 // Look for alternative libdir
2601 // p: n/a
2602 //--------------------------------------------------------------
2603 { char *cp = getenv(VALGRINDLIB);
2604 if (cp != NULL)
2605 VG_(libdir) = cp;
2606 }
2607
2608 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002609 // Get valgrind args + client args (inc. from VALGRIND_OPTS/.valgrindrc).
2610 // Pre-process the command line.
2611 // p: n/a
2612 //--------------------------------------------------------------
nethercotef6a1d502004-08-09 12:21:57 +00002613 get_command_line(argc, argv, &vg_argc, &vg_argv, &cl_argv);
nethercote71980f02004-01-24 18:18:54 +00002614 pre_process_cmd_line_options(&need_help, &tool, &exec);
2615
2616 //==============================================================
2617 // Nb: once a tool is specified, the tool.so must be loaded even if
2618 // they specified --help or didn't specify a client program.
2619 //==============================================================
2620
2621 //--------------------------------------------------------------
2622 // With client padded out, map in tool
nethercote71980f02004-01-24 18:18:54 +00002623 // p: set-libdir [for VG_(libdir)]
2624 // p: pre_process_cmd_line_options() [for 'tool']
2625 //--------------------------------------------------------------
2626 load_tool(tool, &tool_dlhandle, &toolinfo, &preload);
2627
2628 //==============================================================
2629 // Can use VG_(malloc)() and VG_(arena_malloc)() only after load_tool()
nethercotec314eba2004-07-15 12:59:41 +00002630 // -- redzone size is now set. This is checked by vg_malloc2.c.
nethercote71980f02004-01-24 18:18:54 +00002631 //==============================================================
2632
2633 //--------------------------------------------------------------
2634 // Finalise address space layout
nethercote31779c72004-07-30 21:50:15 +00002635 // p: load_tool() [for 'toolinfo']
nethercote71980f02004-01-24 18:18:54 +00002636 //--------------------------------------------------------------
nethercote31779c72004-07-30 21:50:15 +00002637 layout_remaining_space( (Addr) & argc, toolinfo->shadow_ratio );
nethercote71980f02004-01-24 18:18:54 +00002638
2639 //--------------------------------------------------------------
2640 // Load client executable, finding in $PATH if necessary
nethercote71980f02004-01-24 18:18:54 +00002641 // p: pre_process_cmd_line_options() [for 'exec', 'need_help']
2642 // p: layout_remaining_space [so there's space]
2643 //--------------------------------------------------------------
nethercotef4928da2004-06-15 10:54:40 +00002644 load_client(cl_argv, exec, need_help, &info, &client_eip);
nethercote71980f02004-01-24 18:18:54 +00002645
2646 //--------------------------------------------------------------
nethercote969ecf12004-10-13 17:29:01 +00002647 // Everything in place, remove padding done by stage1
nethercote71980f02004-01-24 18:18:54 +00002648 // p: layout_remaining_space() [everything must be mapped in before now]
2649 // p: load_client() [ditto]
2650 //--------------------------------------------------------------
nethercote31779c72004-07-30 21:50:15 +00002651 as_unpad((void *)VG_(shadow_end), (void *)~0, padfile);
2652 as_closepadfile(padfile); // no more padding
nethercote71980f02004-01-24 18:18:54 +00002653
2654 //--------------------------------------------------------------
2655 // Set up client's environment
2656 // p: set-libdir [for VG_(libdir)]
2657 // p: load_tool() [for 'preload']
2658 //--------------------------------------------------------------
2659 env = fix_environment(environ, preload);
2660
2661 //--------------------------------------------------------------
nethercote5ee67ca2004-06-22 14:00:09 +00002662 // Setup client stack, eip, and VG_(client_arg[cv])
nethercote71980f02004-01-24 18:18:54 +00002663 // p: load_client() [for 'info']
2664 // p: fix_environment() [for 'env']
2665 //--------------------------------------------------------------
nethercotec25c4492004-10-18 11:52:17 +00002666 {
2667 void* init_sp = argv - 1;
nethercote4ad74312004-10-26 09:59:49 +00002668 sp_at_startup = setup_client_stack(init_sp, cl_argv, env, &info,
2669 &client_auxv);
nethercotec25c4492004-10-18 11:52:17 +00002670 }
nethercote71980f02004-01-24 18:18:54 +00002671
2672 if (0)
nethercote6a27d832004-09-07 10:17:02 +00002673 printf("entry=%p client esp=%p vg_argc=%d brkbase=%p\n",
nethercote4ad74312004-10-26 09:59:49 +00002674 (void*)client_eip, (void*)sp_at_startup, vg_argc,
nethercote6a27d832004-09-07 10:17:02 +00002675 (void*)VG_(brk_base));
nethercote71980f02004-01-24 18:18:54 +00002676
2677 //==============================================================
2678 // Finished setting up operating environment. Now initialise
2679 // Valgrind. (This is where the old VG_(main)() started.)
2680 //==============================================================
2681
2682 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002683 // atfork
2684 // p: n/a
2685 //--------------------------------------------------------------
2686 VG_(atfork)(NULL, NULL, newpid);
2687 newpid(VG_INVALID_THREADID);
2688
2689 //--------------------------------------------------------------
2690 // setup file descriptors
2691 // p: n/a
2692 //--------------------------------------------------------------
2693 setup_file_descriptors();
2694
2695 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002696 // Read /proc/self/maps into a buffer
2697 // p: all memory layout, environment setup [so memory maps are right]
2698 //--------------------------------------------------------------
2699 VG_(read_procselfmaps)();
2700
2701 //--------------------------------------------------------------
2702 // Build segment map (Valgrind segments only)
2703 // p: read proc/self/maps
2704 // p: sk_pre_clo_init() [to setup new_mem_startup tracker]
2705 //--------------------------------------------------------------
2706 VG_(parse_procselfmaps) ( build_valgrind_map_callback );
2707
2708 //==============================================================
2709 // Can use VG_(arena_malloc)() with non-CORE arena after segments set up
2710 //==============================================================
2711
2712 //--------------------------------------------------------------
2713 // Init tool: pre_clo_init, process cmd line, post_clo_init
2714 // p: setup_client_stack() [for 'VG_(client_arg[cv]']
2715 // p: load_tool() [for 'tool']
2716 // p: setup_file_descriptors() [for 'VG_(fd_xxx_limit)']
2717 // p: parse_procselfmaps [so VG segments are setup so tool can
2718 // call VG_(malloc)]
nethercote71980f02004-01-24 18:18:54 +00002719 //--------------------------------------------------------------
2720 (*toolinfo->sk_pre_clo_init)();
2721 VG_(tool_init_dlsym)(tool_dlhandle);
2722 VG_(sanity_check_needs)();
2723
nethercotef4928da2004-06-15 10:54:40 +00002724 // If --tool and --help/--help-debug was given, now give the core+tool
2725 // help message
nethercotef4928da2004-06-15 10:54:40 +00002726 if (need_help) {
2727 usage(/*--help-debug?*/2 == need_help);
2728 }
nethercotec314eba2004-07-15 12:59:41 +00002729 process_cmd_line_options(client_auxv, tool);
2730
2731 SK_(post_clo_init)();
nethercotef4928da2004-06-15 10:54:40 +00002732
2733 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002734 // Build segment map (all segments)
nethercote4ad74312004-10-26 09:59:49 +00002735 // p: setup_client_stack() [for 'sp_at_startup']
nethercotec314eba2004-07-15 12:59:41 +00002736 // p: init tool [for 'new_mem_startup']
nethercote71980f02004-01-24 18:18:54 +00002737 //--------------------------------------------------------------
nethercote4ad74312004-10-26 09:59:49 +00002738 sp_at_startup___global_arg = sp_at_startup;
nethercotec314eba2004-07-15 12:59:41 +00002739 VG_(parse_procselfmaps) ( build_segment_map_callback ); /* everything */
nethercote4ad74312004-10-26 09:59:49 +00002740 sp_at_startup___global_arg = 0;
nethercotec314eba2004-07-15 12:59:41 +00002741
2742 //--------------------------------------------------------------
nethercotef84f6952004-07-15 14:58:33 +00002743 // Protect client trampoline page (which is also sysinfo stuff)
2744 // p: segment stuff [otherwise get seg faults...]
nethercotec314eba2004-07-15 12:59:41 +00002745 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002746 VG_(mprotect)( (void *)VG_(client_trampoline_code),
2747 VG_(trampoline_code_length), VKI_PROT_READ|VKI_PROT_EXEC );
2748
2749 //==============================================================
2750 // Can use VG_(map)() after segments set up
2751 //==============================================================
nethercote71980f02004-01-24 18:18:54 +00002752
2753 //--------------------------------------------------------------
2754 // Allow GDB attach
2755 // p: process_cmd_line_options() [for VG_(clo_wait_for_gdb)]
2756 //--------------------------------------------------------------
2757 /* Hook to delay things long enough so we can get the pid and
2758 attach GDB in another shell. */
2759 if (VG_(clo_wait_for_gdb)) {
2760 VG_(printf)("pid=%d\n", VG_(getpid)());
2761 /* do "jump *$eip" to skip this in gdb */
2762 VG_(do_syscall)(__NR_pause);
2763 }
2764
2765 //--------------------------------------------------------------
nethercote1d447092004-02-01 17:29:59 +00002766 // Set up baseBlock
nethercote71980f02004-01-24 18:18:54 +00002767 // p: {pre,post}_clo_init() [for tool helper registration]
2768 // load_client() [for 'client_eip']
nethercote4ad74312004-10-26 09:59:49 +00002769 // setup_client_stack() [for 'sp_at_startup']
nethercote71980f02004-01-24 18:18:54 +00002770 //--------------------------------------------------------------
nethercote4ad74312004-10-26 09:59:49 +00002771 init_baseBlock(client_eip, sp_at_startup);
nethercote71980f02004-01-24 18:18:54 +00002772
2773 //--------------------------------------------------------------
2774 // Search for file descriptors that are inherited from our parent
2775 // p: process_cmd_line_options [for VG_(clo_track_fds)]
2776 //--------------------------------------------------------------
2777 if (VG_(clo_track_fds))
2778 VG_(init_preopened_fds)();
2779
2780 //--------------------------------------------------------------
2781 // Initialise the scheduler
2782 // p: init_baseBlock() [baseBlock regs copied into VG_(threads)[1]]
2783 // p: setup_file_descriptors() [else VG_(safe_fd)() breaks]
2784 //--------------------------------------------------------------
2785 VG_(scheduler_init)();
2786
2787 //--------------------------------------------------------------
2788 // Set up the ProxyLWP machinery
2789 // p: VG_(scheduler_init)()? [XXX: subtle dependency?]
nethercote71980f02004-01-24 18:18:54 +00002790 //--------------------------------------------------------------
2791 VG_(proxy_init)();
2792
2793 //--------------------------------------------------------------
2794 // Initialise the signal handling subsystem
2795 // p: VG_(atfork)(NULL, NULL, newpid) [else problems with sigmasks]
2796 // p: VG_(proxy_init)() [else breaks...]
2797 //--------------------------------------------------------------
2798 // Nb: temporarily parks the saved blocking-mask in saved_sigmask.
2799 VG_(sigstartup_actions)();
2800
2801 //--------------------------------------------------------------
2802 // Perhaps we're profiling Valgrind?
2803 // p: process_cmd_line_options() [for VG_(clo_profile)]
2804 // p: others?
2805 //
2806 // XXX: this seems to be broken? It always says the tool wasn't built
2807 // for profiling; vg_profile.c's functions don't seem to be overriding
2808 // vg_dummy_profile.c's?
2809 //
2810 // XXX: want this as early as possible. Looking for --profile
2811 // in pre_process_cmd_line_options() could get it earlier.
2812 //--------------------------------------------------------------
2813 if (VG_(clo_profile))
2814 VGP_(init_profiling)();
2815
2816 VGP_PUSHCC(VgpStartup);
2817
2818 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002819 // Read suppression file
2820 // p: process_cmd_line_options() [for VG_(clo_suppressions)]
2821 //--------------------------------------------------------------
2822 if (VG_(needs).core_errors || VG_(needs).skin_errors)
2823 VG_(load_suppressions)();
2824
2825 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002826 // Initialise translation table and translation cache
2827 // p: read_procselfmaps [so the anonymous mmaps for the TT/TC
2828 // aren't identified as part of the client, which would waste
2829 // > 20M of virtual address space.]
2830 //--------------------------------------------------------------
2831 VG_(init_tt_tc)();
2832
2833 //--------------------------------------------------------------
2834 // Read debug info to find glibc entry points to intercept
2835 // p: parse_procselfmaps? [XXX for debug info?]
2836 // p: init_tt_tc? [XXX ???]
2837 //--------------------------------------------------------------
2838 VG_(setup_code_redirect_table)();
2839
2840 //--------------------------------------------------------------
2841 // Verbosity message
2842 // p: end_rdtsc_calibration [so startup message is printed first]
2843 //--------------------------------------------------------------
2844 if (VG_(clo_verbosity) == 1)
2845 VG_(message)(Vg_UserMsg, "For more details, rerun with: -v");
2846 if (VG_(clo_verbosity) > 0)
2847 VG_(message)(Vg_UserMsg, "");
2848
2849 //--------------------------------------------------------------
2850 // Setup pointercheck
2851 // p: process_cmd_line_options() [for VG_(clo_pointercheck)]
2852 //--------------------------------------------------------------
nethercote775508a2004-09-07 22:38:23 +00002853 if (VG_(clo_pointercheck))
2854 VG_(clo_pointercheck) = VGA_(setup_pointercheck)();
nethercote71980f02004-01-24 18:18:54 +00002855
nethercote71980f02004-01-24 18:18:54 +00002856 //--------------------------------------------------------------
2857 // Run!
2858 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002859 VGP_POPCC(VgpStartup);
2860 VGP_PUSHCC(VgpSched);
2861
nethercote238a3c32004-08-09 13:13:31 +00002862 src = VG_(scheduler)( &exitcode, &last_run_tid, &fatal_sigNo );
nethercote71980f02004-01-24 18:18:54 +00002863
nethercote238a3c32004-08-09 13:13:31 +00002864 VGP_POPCC(VgpSched);
nethercote71980f02004-01-24 18:18:54 +00002865
2866
2867 //--------------------------------------------------------------
2868 // Finalisation: cleanup, messages, etc. Order no so important, only
2869 // affects what order the messages come.
2870 //--------------------------------------------------------------
2871 if (VG_(clo_verbosity) > 0)
2872 VG_(message)(Vg_UserMsg, "");
2873
2874 if (src == VgSrc_Deadlock) {
2875 VG_(message)(Vg_UserMsg,
2876 "Warning: pthread scheduler exited due to deadlock");
2877 }
2878
2879 /* Print out file descriptor summary and stats. */
2880 if (VG_(clo_track_fds))
nethercote3a42fb82004-08-03 18:08:50 +00002881 VG_(show_open_fds)();
nethercote71980f02004-01-24 18:18:54 +00002882
2883 if (VG_(needs).core_errors || VG_(needs).skin_errors)
2884 VG_(show_all_errors)();
2885
nethercote47dd12c2004-06-22 14:18:42 +00002886 SK_(fini)( exitcode );
nethercote71980f02004-01-24 18:18:54 +00002887
nethercote885dd912004-08-03 23:14:00 +00002888 VG_(sanity_check_general)( True /*include expensive checks*/ );
nethercote71980f02004-01-24 18:18:54 +00002889
2890 if (VG_(clo_verbosity) > 1)
nethercote3a42fb82004-08-03 18:08:50 +00002891 print_all_stats();
nethercote71980f02004-01-24 18:18:54 +00002892
nethercote71980f02004-01-24 18:18:54 +00002893 if (VG_(clo_profile))
2894 VGP_(done_profiling)();
2895
nethercote71980f02004-01-24 18:18:54 +00002896 /* We're exiting, so nuke all the threads and clean up the proxy LWPs */
2897 vg_assert(src == VgSrc_FatalSig ||
nethercote759dda32004-08-07 18:16:56 +00002898 VG_(threads)[last_run_tid].status == VgTs_Runnable ||
2899 VG_(threads)[last_run_tid].status == VgTs_WaitJoiner);
nethercote71980f02004-01-24 18:18:54 +00002900 VG_(nuke_all_threads_except)(VG_INVALID_THREADID);
2901
2902 //--------------------------------------------------------------
2903 // Exit, according to the scheduler's return code
2904 //--------------------------------------------------------------
2905 switch (src) {
2906 case VgSrc_ExitSyscall: /* the normal way out */
nethercote759dda32004-08-07 18:16:56 +00002907 vg_assert(last_run_tid > 0 && last_run_tid < VG_N_THREADS);
nethercote71980f02004-01-24 18:18:54 +00002908 VG_(proxy_shutdown)();
2909
2910 /* The thread's %EBX at the time it did __NR_exit() will hold
2911 the arg to __NR_exit(), so we just do __NR_exit() with
2912 that arg. */
nethercote47dd12c2004-06-22 14:18:42 +00002913 VG_(exit)( exitcode );
nethercote71980f02004-01-24 18:18:54 +00002914 /* NOT ALIVE HERE! */
2915 VG_(core_panic)("entered the afterlife in main() -- ExitSyscall");
2916 break; /* what the hell :) */
2917
2918 case VgSrc_Deadlock:
2919 /* Just exit now. No point in continuing. */
2920 VG_(proxy_shutdown)();
2921 VG_(exit)(0);
2922 VG_(core_panic)("entered the afterlife in main() -- Deadlock");
2923 break;
2924
nethercote71980f02004-01-24 18:18:54 +00002925 case VgSrc_FatalSig:
2926 /* We were killed by a fatal signal, so replicate the effect */
nethercote238a3c32004-08-09 13:13:31 +00002927 vg_assert(fatal_sigNo != -1);
2928 VG_(kill_self)(fatal_sigNo);
nethercote71980f02004-01-24 18:18:54 +00002929 VG_(core_panic)("main(): signal was supposed to be fatal");
2930 break;
2931
2932 default:
2933 VG_(core_panic)("main(): unexpected scheduler return code");
2934 }
2935
2936 abort();
2937}
2938
2939
sewardjde4a1d02002-03-22 01:27:54 +00002940/*--------------------------------------------------------------------*/
2941/*--- end vg_main.c ---*/
2942/*--------------------------------------------------------------------*/