blob: 4535c7b540030b17b7f49490115042c2cfb8dddc [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
fitzhardingeb50068f2004-02-24 23:42:55 +0000109vki_rlimit VG_(client_rlimit_data);
thughesc37184f2004-09-11 14:16:57 +0000110vki_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
nethercote71980f02004-01-24 18:18:54 +0000139/* As deduced from esp_at_startup, the client's argc, argv[] and
140 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);
242 VG_(kkill)(VG_(getpid)(), VKI_SIGSTOP);
243
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
304 VG_(kkill)(pid, VKI_SIGKILL);
305 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) {
409 OINK(1);
410 VG_(valgrind_base) = PGROUNDDN(&_start);
411 }
412
nethercote820bd8c2004-09-07 23:04:49 +0000413 VG_(valgrind_last) = ROUNDUP(argc_addr, 0x10000) - 1; // stack
nethercote71980f02004-01-24 18:18:54 +0000414
nethercote31779c72004-07-30 21:50:15 +0000415 // This gives the client the largest possible address space while
416 // taking into account the tool's shadow needs.
417 client_size = ROUNDDN((VG_(valgrind_base)-REDZONE_SIZE) / (1.+ratio),
nethercote71980f02004-01-24 18:18:54 +0000418 CLIENT_SIZE_MULTIPLE);
nethercote31779c72004-07-30 21:50:15 +0000419 VG_(client_base) = CLIENT_BASE;
nethercote71980f02004-01-24 18:18:54 +0000420 VG_(client_end) = VG_(client_base) + client_size;
nethercotee2097312004-06-27 12:29:56 +0000421 /* where !FIXED mmap goes */
nethercotebc7b4f42004-07-26 12:44:35 +0000422 VG_(client_mapbase) = VG_(client_base) +
423 PGROUNDDN((addr_t)(client_size * CLIENT_HEAP_PROPORTION));
nethercote71980f02004-01-24 18:18:54 +0000424
nethercote31779c72004-07-30 21:50:15 +0000425 VG_(shadow_base) = VG_(client_end) + REDZONE_SIZE;
nethercote410bfe62004-09-04 15:53:35 +0000426 VG_(shadow_end) = VG_(valgrind_base);
427 shadow_size = VG_(shadow_end) - VG_(shadow_base);
nethercote71980f02004-01-24 18:18:54 +0000428
nethercotee2097312004-06-27 12:29:56 +0000429#define SEGSIZE(a,b) ((VG_(b) - VG_(a))/(1024*1024))
430
nethercote71980f02004-01-24 18:18:54 +0000431 if (0)
nethercotee2097312004-06-27 12:29:56 +0000432 VG_(printf)(
433 "client_base %8x (%dMB)\n"
434 "client_mapbase %8x (%dMB)\n"
435 "client_end %8x (%dMB)\n"
436 "shadow_base %8x (%dMB)\n"
nethercote410bfe62004-09-04 15:53:35 +0000437 "shadow_end %8x\n"
nethercotee2097312004-06-27 12:29:56 +0000438 "valgrind_base %8x (%dMB)\n"
nethercote820bd8c2004-09-07 23:04:49 +0000439 "valgrind_last %8x\n",
nethercotee2097312004-06-27 12:29:56 +0000440 VG_(client_base), SEGSIZE(client_base, client_mapbase),
441 VG_(client_mapbase), SEGSIZE(client_mapbase, client_end),
442 VG_(client_end), SEGSIZE(client_end, shadow_base),
443 VG_(shadow_base), SEGSIZE(shadow_base, shadow_end),
nethercote410bfe62004-09-04 15:53:35 +0000444 VG_(shadow_end),
nethercote820bd8c2004-09-07 23:04:49 +0000445 VG_(valgrind_base), SEGSIZE(valgrind_base, valgrind_last),
446 VG_(valgrind_last)
nethercotee2097312004-06-27 12:29:56 +0000447 );
448
449#undef SEGSIZE
nethercote71980f02004-01-24 18:18:54 +0000450
451 // Ban redzone
nethercotee567e702004-07-10 17:49:17 +0000452 vres = mmap((void *)VG_(client_end), REDZONE_SIZE, PROT_NONE,
fitzhardinge72ddff62004-09-08 20:03:51 +0000453 MAP_FIXED|MAP_ANON|MAP_PRIVATE|MAP_NORESERVE, -1, 0);
nethercotee567e702004-07-10 17:49:17 +0000454 vg_assert((void*)-1 != vres);
nethercote71980f02004-01-24 18:18:54 +0000455
456 // Make client hole
nethercotee567e702004-07-10 17:49:17 +0000457 ires = munmap((void*)VG_(client_base), client_size);
458 vg_assert(0 == ires);
nethercote71980f02004-01-24 18:18:54 +0000459
460 // Map shadow memory.
461 // Initially all inaccessible, incrementally initialized as it is used
nethercotee567e702004-07-10 17:49:17 +0000462 if (shadow_size != 0) {
463 vres = mmap((char *)VG_(shadow_base), shadow_size, PROT_NONE,
fitzhardinge72ddff62004-09-08 20:03:51 +0000464 MAP_PRIVATE|MAP_ANON|MAP_FIXED|MAP_NORESERVE, -1, 0);
nethercoted4722622004-08-30 19:36:42 +0000465 if ((void*)-1 == vres) {
466 fprintf(stderr,
nethercote8c1ce432004-10-08 14:01:14 +0000467 "valgrind: Could not allocate address space (%p bytes)\n"
468 "valgrind: for shadow memory\n"
469 "valgrind: Possible causes:\n"
470 "valgrind: - For some systems (especially under RedHat 8), Valgrind\n"
471 "valgrind: needs at least 1.5GB swap space.\n"
472 "valgrind: - Or, your virtual memory size may be limited (check\n"
473 "valgrind: with 'ulimit -v').\n"
474 "valgrind: - Or, your system may use a kernel that provides only a\n"
475 "valgrind: too-small (eg. 2GB) user address space.\n"
476 , (void*)shadow_size
477 );
nethercoted4722622004-08-30 19:36:42 +0000478 exit(1);
479 }
nethercotee567e702004-07-10 17:49:17 +0000480 }
nethercote71980f02004-01-24 18:18:54 +0000481}
482
483/*====================================================================*/
484/*=== Command line setup ===*/
485/*====================================================================*/
486
487/* Nb: malloc'd memory never freed -- kept throughout like argv, envp */
488static char* get_file_clo(char* dir)
489{
490# define FLEN 512
491 Int fd, n;
492 struct stat s1;
493 char* f_clo = NULL;
494 char filename[FLEN];
495
496 snprintf(filename, FLEN, "%s/.valgrindrc", ( NULL == dir ? "" : dir ) );
497 fd = VG_(open)(filename, 0, VKI_S_IRUSR);
498 if ( fd > 0 ) {
499 if ( 0 == fstat(fd, &s1) ) {
500 f_clo = malloc(s1.st_size+1);
501 vg_assert(f_clo);
502 n = read(fd, f_clo, s1.st_size);
503 if (n == -1) n = 0;
504 f_clo[n] = '\0';
505 }
506 close(fd);
507 }
508 return f_clo;
509# undef FLEN
510}
511
nethercotee2097312004-06-27 12:29:56 +0000512#define ISSPACE(cc) ((cc) == ' ' || (cc) == '\t' || (cc) == '\n')
513
nethercote71980f02004-01-24 18:18:54 +0000514static Int count_args(char* s)
515{
516 Int n = 0;
517 if (s) {
518 char* cp = s;
519 while (True) {
520 // We have alternating sequences: blanks, non-blanks, blanks...
521 // count the non-blanks sequences.
522 while ( ISSPACE(*cp) ) cp++;
523 if ( !*cp ) break;
524 n++;
525 while ( !ISSPACE(*cp) && *cp ) cp++;
526 }
527 }
528 return n;
529}
530
531/* add args out of environment, skipping multiple spaces and -- args */
532static char** copy_args( char* s, char** to )
533{
534 if (s) {
535 char* cp = s;
536 while (True) {
537 // We have alternating sequences: blanks, non-blanks, blanks...
538 // copy the non-blanks sequences, and add terminating '\0'
539 while ( ISSPACE(*cp) ) cp++;
540 if ( !*cp ) break;
541 *to++ = cp;
542 while ( !ISSPACE(*cp) && *cp ) cp++;
543 if ( *cp ) *cp++ = '\0'; // terminate if necessary
544 if (VG_STREQ(to[-1], "--")) to--; // undo any '--' arg
545 }
546 }
547 return to;
548}
549
nethercotee2097312004-06-27 12:29:56 +0000550#undef ISSPACE
551
nethercote71980f02004-01-24 18:18:54 +0000552// Augment command line with arguments from environment and .valgrindrc
553// files.
554static void augment_command_line(Int* vg_argc_inout, char*** vg_argv_inout)
555{
nethercotef6a1d502004-08-09 12:21:57 +0000556 int vg_argc0 = *vg_argc_inout;
557 char** vg_argv0 = *vg_argv_inout;
nethercote71980f02004-01-24 18:18:54 +0000558
559 char* env_clo = getenv(VALGRINDOPTS);
560 char* f1_clo = get_file_clo( getenv("HOME") );
561 char* f2_clo = get_file_clo(".");
562
563 /* copy any extra args from file or environment, if present */
564 if ( (env_clo && *env_clo) || (f1_clo && *f1_clo) || (f2_clo && *f2_clo) ) {
565 /* ' ' separated extra options */
566 char **from;
567 char **to;
thughescaca0022004-09-13 10:20:34 +0000568 int orig_arg_count, env_arg_count, f1_arg_count, f2_arg_count;
569
570 for ( orig_arg_count = 0; vg_argv0[orig_arg_count]; orig_arg_count++ );
571
nethercote71980f02004-01-24 18:18:54 +0000572 env_arg_count = count_args(env_clo);
573 f1_arg_count = count_args(f1_clo);
574 f2_arg_count = count_args(f2_clo);
575
576 if (0)
577 printf("extra-argc=%d %d %d\n",
578 env_arg_count, f1_arg_count, f2_arg_count);
579
580 /* +2: +1 for null-termination, +1 for added '--' */
nethercotef6a1d502004-08-09 12:21:57 +0000581 from = vg_argv0;
thughescaca0022004-09-13 10:20:34 +0000582 vg_argv0 = malloc( (orig_arg_count + env_arg_count + f1_arg_count
nethercote71980f02004-01-24 18:18:54 +0000583 + f2_arg_count + 2) * sizeof(char **));
nethercotef6a1d502004-08-09 12:21:57 +0000584 vg_assert(vg_argv0);
585 to = vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000586
587 /* copy argv[0] */
588 *to++ = *from++;
589
590 /* Copy extra args from env var and file, in the order: ~/.valgrindrc,
591 * $VALGRIND_OPTS, ./.valgrindrc -- more local options are put later
592 * to override less local ones. */
593 to = copy_args(f1_clo, to);
594 to = copy_args(env_clo, to);
595 to = copy_args(f2_clo, to);
596
597 /* copy original arguments, stopping at command or -- */
598 while (*from) {
599 if (**from != '-')
600 break;
601 if (VG_STREQ(*from, "--")) {
602 from++; /* skip -- */
603 break;
604 }
605 *to++ = *from++;
606 }
607
608 /* add -- */
609 *to++ = "--";
610
nethercotef6a1d502004-08-09 12:21:57 +0000611 vg_argc0 = to - vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000612
613 /* copy rest of original command line, then NULL */
614 while (*from) *to++ = *from++;
615 *to = NULL;
616 }
617
nethercotef6a1d502004-08-09 12:21:57 +0000618 *vg_argc_inout = vg_argc0;
619 *vg_argv_inout = vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000620}
621
nethercotef6a1d502004-08-09 12:21:57 +0000622#define VG_CLO_SEP '\01'
623
nethercote71980f02004-01-24 18:18:54 +0000624static void get_command_line( int argc, char** argv,
625 Int* vg_argc_out, Char*** vg_argv_out,
626 char*** cl_argv_out )
627{
nethercotef6a1d502004-08-09 12:21:57 +0000628 int vg_argc0;
629 char** vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000630 char** cl_argv;
631 char* env_clo = getenv(VALGRINDCLO);
632
633 if (env_clo != NULL && *env_clo != '\0') {
634 char *cp;
635 char **cpp;
636
nethercotef6a1d502004-08-09 12:21:57 +0000637 /* OK, VALGRINDCLO is set, which means we must be a child of another
638 Valgrind process using --trace-children, so we're getting all our
639 arguments from VALGRINDCLO, and the entire command line belongs to
640 the client (including argv[0]) */
641 vg_argc0 = 1; /* argv[0] */
nethercote71980f02004-01-24 18:18:54 +0000642 for (cp = env_clo; *cp; cp++)
nethercotef6a1d502004-08-09 12:21:57 +0000643 if (*cp == VG_CLO_SEP)
644 vg_argc0++;
nethercote71980f02004-01-24 18:18:54 +0000645
nethercotef6a1d502004-08-09 12:21:57 +0000646 vg_argv0 = malloc(sizeof(char **) * (vg_argc0 + 1));
647 vg_assert(vg_argv0);
nethercote71980f02004-01-24 18:18:54 +0000648
nethercotef6a1d502004-08-09 12:21:57 +0000649 cpp = vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000650
651 *cpp++ = "valgrind"; /* nominal argv[0] */
652 *cpp++ = env_clo;
653
nethercotef6a1d502004-08-09 12:21:57 +0000654 // Replace the VG_CLO_SEP args separator with '\0'
nethercote71980f02004-01-24 18:18:54 +0000655 for (cp = env_clo; *cp; cp++) {
nethercotef6a1d502004-08-09 12:21:57 +0000656 if (*cp == VG_CLO_SEP) {
nethercote71980f02004-01-24 18:18:54 +0000657 *cp++ = '\0'; /* chop it up in place */
658 *cpp++ = cp;
659 }
660 }
661 *cpp = NULL;
662 cl_argv = argv;
663
664 } else {
665 /* Count the arguments on the command line. */
nethercotef6a1d502004-08-09 12:21:57 +0000666 vg_argv0 = argv;
nethercote71980f02004-01-24 18:18:54 +0000667
nethercotef6a1d502004-08-09 12:21:57 +0000668 for (vg_argc0 = 1; vg_argc0 < argc; vg_argc0++) {
669 if (argv[vg_argc0][0] != '-') /* exe name */
nethercote71980f02004-01-24 18:18:54 +0000670 break;
nethercotef6a1d502004-08-09 12:21:57 +0000671 if (VG_STREQ(argv[vg_argc0], "--")) { /* dummy arg */
672 vg_argc0++;
nethercote71980f02004-01-24 18:18:54 +0000673 break;
674 }
675 }
nethercotef6a1d502004-08-09 12:21:57 +0000676 cl_argv = &argv[vg_argc0];
nethercote71980f02004-01-24 18:18:54 +0000677
678 /* Get extra args from VALGRIND_OPTS and .valgrindrc files.
nethercotef6a1d502004-08-09 12:21:57 +0000679 Note we don't do this if getting args from VALGRINDCLO, as
680 those extra args will already be present in VALGRINDCLO. */
681 augment_command_line(&vg_argc0, &vg_argv0);
nethercote71980f02004-01-24 18:18:54 +0000682 }
683
684 if (0) {
685 Int i;
nethercotef6a1d502004-08-09 12:21:57 +0000686 for (i = 0; i < vg_argc0; i++)
687 printf("vg_argv0[%d]=\"%s\"\n", i, vg_argv0[i]);
nethercote71980f02004-01-24 18:18:54 +0000688 }
689
nethercotef6a1d502004-08-09 12:21:57 +0000690 *vg_argc_out = vg_argc0;
691 *vg_argv_out = (Char**)vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000692 *cl_argv_out = cl_argv;
693}
694
695
696/*====================================================================*/
697/*=== Environment and stack setup ===*/
698/*====================================================================*/
699
700/* Scan a colon-separated list, and call a function on each element.
701 The string must be mutable, because we insert a temporary '\0', but
thughes4ad52d02004-06-27 17:37:21 +0000702 the string will end up unmodified. (*func) should return True if it
nethercote71980f02004-01-24 18:18:54 +0000703 doesn't need to see any more.
thughes4ad52d02004-06-27 17:37:21 +0000704
705 This routine will return True if (*func) returns True and False if
706 it reaches the end of the list without that happening.
nethercote71980f02004-01-24 18:18:54 +0000707*/
thughes4ad52d02004-06-27 17:37:21 +0000708static Bool scan_colsep(char *colsep, Bool (*func)(const char *))
nethercote71980f02004-01-24 18:18:54 +0000709{
710 char *cp, *entry;
711 int end;
712
713 if (colsep == NULL ||
714 *colsep == '\0')
thughes4ad52d02004-06-27 17:37:21 +0000715 return False;
nethercote71980f02004-01-24 18:18:54 +0000716
717 entry = cp = colsep;
718
719 do {
720 end = (*cp == '\0');
721
722 if (*cp == ':' || *cp == '\0') {
723 char save = *cp;
724
725 *cp = '\0';
thughes21942d92004-07-12 09:35:37 +0000726 if ((*func)(entry)) {
727 *cp = save;
thughes4ad52d02004-06-27 17:37:21 +0000728 return True;
thughes21942d92004-07-12 09:35:37 +0000729 }
nethercote71980f02004-01-24 18:18:54 +0000730 *cp = save;
731 entry = cp+1;
732 }
733 cp++;
734 } while(!end);
thughes4ad52d02004-06-27 17:37:21 +0000735
736 return False;
737}
738
739static Bool contains(const char *p) {
740 if (VG_STREQ(p, VG_(libdir))) {
741 return True;
742 }
743 return False;
nethercote71980f02004-01-24 18:18:54 +0000744}
745
746/* Prepare the client's environment. This is basically a copy of our
747 environment, except:
748 1. LD_LIBRARY_PATH=$VALGRINDLIB:$LD_LIBRARY_PATH
749 2. LD_PRELOAD=$VALGRINDLIB/vg_inject.so:($VALGRINDLIB/vgpreload_TOOL.so:)?$LD_PRELOAD
750
751 If any of these is missing, then it is added.
752
753 Yummy. String hacking in C.
754
755 If this needs to handle any more variables it should be hacked
756 into something table driven.
757 */
758static char **fix_environment(char **origenv, const char *preload)
759{
760 static const char inject_so[] = "vg_inject.so";
761 static const char ld_library_path[] = "LD_LIBRARY_PATH=";
762 static const char ld_preload[] = "LD_PRELOAD=";
763 static const char valgrind_clo[] = VALGRINDCLO "=";
764 static const int ld_library_path_len = sizeof(ld_library_path)-1;
765 static const int ld_preload_len = sizeof(ld_preload)-1;
766 static const int valgrind_clo_len = sizeof(valgrind_clo)-1;
767 int ld_preload_done = 0;
768 int ld_library_path_done = 0;
769 char *inject_path;
770 int inject_path_len;
771 int vgliblen = strlen(VG_(libdir));
772 char **cpp;
773 char **ret;
774 int envc;
775 const int preloadlen = (preload == NULL) ? 0 : strlen(preload);
776
777 /* Find the vg_inject.so; also make room for the tool preload
778 library */
779 inject_path_len = sizeof(inject_so) + vgliblen + preloadlen + 16;
780 inject_path = malloc(inject_path_len);
nethercote7c018f42004-07-17 16:40:50 +0000781 vg_assert(inject_path);
nethercote71980f02004-01-24 18:18:54 +0000782
783 if (preload)
784 snprintf(inject_path, inject_path_len, "%s/%s:%s",
785 VG_(libdir), inject_so, preload);
786 else
787 snprintf(inject_path, inject_path_len, "%s/%s",
788 VG_(libdir), inject_so);
789
790 /* Count the original size of the env */
791 envc = 0; /* trailing NULL */
792 for (cpp = origenv; cpp && *cpp; cpp++)
793 envc++;
794
795 /* Allocate a new space */
796 ret = malloc(sizeof(char *) * (envc+3+1)); /* 3 new entries + NULL */
nethercote7c018f42004-07-17 16:40:50 +0000797 vg_assert(ret);
nethercote71980f02004-01-24 18:18:54 +0000798
799 /* copy it over */
800 for (cpp = ret; *origenv; )
801 *cpp++ = *origenv++;
802 *cpp = NULL;
803
804 vg_assert(envc == (cpp - ret));
805
806 /* Walk over the new environment, mashing as we go */
807 for (cpp = ret; cpp && *cpp; cpp++) {
808 if (memcmp(*cpp, ld_library_path, ld_library_path_len) == 0) {
nethercote71980f02004-01-24 18:18:54 +0000809 /* If the LD_LIBRARY_PATH already contains libdir, then don't
810 bother adding it again, even if it isn't the first (it
811 seems that the Java runtime will keep reexecing itself
812 unless its paths are at the front of LD_LIBRARY_PATH) */
thughes4ad52d02004-06-27 17:37:21 +0000813 if (!scan_colsep(*cpp + ld_library_path_len, contains)) {
nethercote71980f02004-01-24 18:18:54 +0000814 int len = strlen(*cpp) + vgliblen*2 + 16;
815 char *cp = malloc(len);
nethercote7c018f42004-07-17 16:40:50 +0000816 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000817
818 snprintf(cp, len, "%s%s:%s",
819 ld_library_path, VG_(libdir),
820 (*cpp)+ld_library_path_len);
821
822 *cpp = cp;
823 }
824
825 ld_library_path_done = 1;
826 } else if (memcmp(*cpp, ld_preload, ld_preload_len) == 0) {
827 int len = strlen(*cpp) + inject_path_len;
828 char *cp = malloc(len);
nethercote7c018f42004-07-17 16:40:50 +0000829 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000830
831 snprintf(cp, len, "%s%s:%s",
832 ld_preload, inject_path, (*cpp)+ld_preload_len);
833
834 *cpp = cp;
835
836 ld_preload_done = 1;
837 } else if (memcmp(*cpp, valgrind_clo, valgrind_clo_len) == 0) {
838 *cpp = "";
839 }
840 }
841
842 /* Add the missing bits */
843
844 if (!ld_library_path_done) {
845 int len = ld_library_path_len + vgliblen*2 + 16;
846 char *cp = malloc(len);
nethercote7c018f42004-07-17 16:40:50 +0000847 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000848
849 snprintf(cp, len, "%s%s", ld_library_path, VG_(libdir));
850
851 ret[envc++] = cp;
852 }
853
854 if (!ld_preload_done) {
855 int len = ld_preload_len + inject_path_len;
856 char *cp = malloc(len);
nethercote7c018f42004-07-17 16:40:50 +0000857 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000858
859 snprintf(cp, len, "%s%s",
860 ld_preload, inject_path);
861
862 ret[envc++] = cp;
863 }
864
865 ret[envc] = NULL;
866
867 return ret;
868}
869
870extern char **environ; /* our environment */
871//#include <error.h>
872
873/* Add a string onto the string table, and return its address */
874static char *copy_str(char **tab, const char *str)
875{
876 char *cp = *tab;
877 char *orig = cp;
878
879 while(*str)
880 *cp++ = *str++;
881 *cp++ = '\0';
882
883 if (0)
nethercotef84f6952004-07-15 14:58:33 +0000884 printf("copied %p \"%s\" len %d\n", orig, orig, cp-orig);
nethercote71980f02004-01-24 18:18:54 +0000885
886 *tab = cp;
887
888 return orig;
889}
890
891/*
892 This sets up the client's initial stack, containing the args,
893 environment and aux vector.
894
895 The format of the stack is:
896
897 higher address +-----------------+
898 | Trampoline code |
899 +-----------------+
900 | |
901 : string table :
902 | |
903 +-----------------+
904 | AT_NULL |
905 - -
906 | auxv |
907 +-----------------+
908 | NULL |
909 - -
910 | envp |
911 +-----------------+
912 | NULL |
913 - -
914 | argv |
915 +-----------------+
916 | argc |
917 lower address +-----------------+ <- esp
918 | undefined |
919 : :
920 */
nethercotec25c4492004-10-18 11:52:17 +0000921static Addr setup_client_stack(void* init_sp,
922 char **orig_argv, char **orig_envp,
nethercote71980f02004-01-24 18:18:54 +0000923 const struct exeinfo *info,
924 UInt** client_auxv)
925{
nethercotee567e702004-07-10 17:49:17 +0000926 void* res;
nethercote71980f02004-01-24 18:18:54 +0000927 char **cpp;
928 char *strtab; /* string table */
929 char *stringbase;
930 addr_t *ptr;
931 struct ume_auxv *auxv;
932 const struct ume_auxv *orig_auxv;
933 const struct ume_auxv *cauxv;
934 unsigned stringsize; /* total size of strings in bytes */
935 unsigned auxsize; /* total size of auxv in bytes */
936 int argc; /* total argc */
937 int envc; /* total number of env vars */
938 unsigned stacksize; /* total client stack size */
939 addr_t cl_esp; /* client stack base (initial esp) */
940
941 /* use our own auxv as a prototype */
nethercotec25c4492004-10-18 11:52:17 +0000942 orig_auxv = find_auxv(init_sp);
nethercote71980f02004-01-24 18:18:54 +0000943
944 /* ==================== compute sizes ==================== */
945
946 /* first of all, work out how big the client stack will be */
947 stringsize = 0;
948
949 /* paste on the extra args if the loader needs them (ie, the #!
950 interpreter and its argument) */
951 argc = 0;
nethercoted6a56872004-07-26 15:32:47 +0000952 if (info->interp_name != NULL) {
nethercote71980f02004-01-24 18:18:54 +0000953 argc++;
nethercoted6a56872004-07-26 15:32:47 +0000954 stringsize += strlen(info->interp_name) + 1;
nethercote71980f02004-01-24 18:18:54 +0000955 }
nethercoted6a56872004-07-26 15:32:47 +0000956 if (info->interp_args != NULL) {
nethercote71980f02004-01-24 18:18:54 +0000957 argc++;
nethercoted6a56872004-07-26 15:32:47 +0000958 stringsize += strlen(info->interp_args) + 1;
nethercote71980f02004-01-24 18:18:54 +0000959 }
960
961 /* now scan the args we're given... */
962 for (cpp = orig_argv; *cpp; cpp++) {
963 argc++;
964 stringsize += strlen(*cpp) + 1;
965 }
966
967 /* ...and the environment */
968 envc = 0;
969 for (cpp = orig_envp; cpp && *cpp; cpp++) {
970 envc++;
971 stringsize += strlen(*cpp) + 1;
972 }
973
974 /* now, how big is the auxv? */
975 auxsize = sizeof(*auxv); /* there's always at least one entry: AT_NULL */
976 for (cauxv = orig_auxv; cauxv->a_type != AT_NULL; cauxv++) {
977 if (cauxv->a_type == AT_PLATFORM)
978 stringsize += strlen(cauxv->u.a_ptr) + 1;
979 auxsize += sizeof(*cauxv);
980 }
981
982 /* OK, now we know how big the client stack is */
983 stacksize =
984 sizeof(int) + /* argc */
985 sizeof(char **)*argc + /* argv */
986 sizeof(char **) + /* terminal NULL */
987 sizeof(char **)*envc + /* envp */
988 sizeof(char **) + /* terminal NULL */
989 auxsize + /* auxv */
990 ROUNDUP(stringsize, sizeof(int)) +/* strings (aligned) */
991 VKI_BYTES_PER_PAGE; /* page for trampoline code */
992
nethercotef84f6952004-07-15 14:58:33 +0000993 // decide where stack goes!
994 VG_(clstk_end) = VG_(client_end);
995
996 VG_(client_trampoline_code) = VG_(clstk_end) - VKI_BYTES_PER_PAGE;
997
nethercote71980f02004-01-24 18:18:54 +0000998 /* cl_esp is the client's stack pointer */
nethercotef84f6952004-07-15 14:58:33 +0000999 cl_esp = VG_(clstk_end) - stacksize;
nethercote71980f02004-01-24 18:18:54 +00001000 cl_esp = ROUNDDN(cl_esp, 16); /* make stack 16 byte aligned */
1001
nethercote71980f02004-01-24 18:18:54 +00001002 /* base of the string table (aligned) */
1003 stringbase = strtab = (char *)(VG_(client_trampoline_code) - ROUNDUP(stringsize, sizeof(int)));
1004
1005 VG_(clstk_base) = PGROUNDDN(cl_esp);
nethercote71980f02004-01-24 18:18:54 +00001006
nethercote5ee67ca2004-06-22 14:00:09 +00001007 if (0)
1008 printf("stringsize=%d auxsize=%d stacksize=%d\n"
nethercote6a27d832004-09-07 10:17:02 +00001009 "clstk_base %p\n"
1010 "clstk_end %p\n",
1011 stringsize, auxsize, stacksize,
1012 (void*)VG_(clstk_base), (void*)VG_(clstk_end));
nethercote5ee67ca2004-06-22 14:00:09 +00001013
1014
nethercote71980f02004-01-24 18:18:54 +00001015 /* ==================== allocate space ==================== */
1016
1017 /* allocate a stack - mmap enough space for the stack */
nethercotef84f6952004-07-15 14:58:33 +00001018 res = mmap((void *)PGROUNDDN(cl_esp), VG_(clstk_end) - PGROUNDDN(cl_esp),
nethercotee567e702004-07-10 17:49:17 +00001019 PROT_READ | PROT_WRITE | PROT_EXEC,
1020 MAP_PRIVATE | MAP_ANON | MAP_FIXED, -1, 0);
1021 vg_assert((void*)-1 != res);
nethercote71980f02004-01-24 18:18:54 +00001022
1023 /* ==================== copy client stack ==================== */
1024
1025 ptr = (addr_t *)cl_esp;
1026
1027 /* --- argc --- */
1028 *ptr++ = argc; /* client argc */
1029
1030 /* --- argv --- */
nethercoted6a56872004-07-26 15:32:47 +00001031 if (info->interp_name) {
1032 *ptr++ = (addr_t)copy_str(&strtab, info->interp_name);
1033 free(info->interp_name);
nethercote71980f02004-01-24 18:18:54 +00001034 }
nethercoted6a56872004-07-26 15:32:47 +00001035 if (info->interp_args) {
1036 *ptr++ = (addr_t)copy_str(&strtab, info->interp_args);
1037 free(info->interp_args);
nethercote71980f02004-01-24 18:18:54 +00001038 }
1039 for (cpp = orig_argv; *cpp; ptr++, cpp++) {
1040 *ptr = (addr_t)copy_str(&strtab, *cpp);
1041 }
1042 *ptr++ = 0;
1043
1044 /* --- envp --- */
1045 VG_(client_envp) = (Char **)ptr;
1046 for (cpp = orig_envp; cpp && *cpp; ptr++, cpp++)
1047 *ptr = (addr_t)copy_str(&strtab, *cpp);
1048 *ptr++ = 0;
1049
1050 /* --- auxv --- */
1051 auxv = (struct ume_auxv *)ptr;
1052 *client_auxv = (UInt *)auxv;
1053
1054 for (; orig_auxv->a_type != AT_NULL; auxv++, orig_auxv++) {
1055 /* copy the entry... */
1056 *auxv = *orig_auxv;
1057
1058 /* ...and fix up the copy */
1059 switch(auxv->a_type) {
1060 case AT_PHDR:
1061 if (info->phdr == 0)
1062 auxv->a_type = AT_IGNORE;
1063 else
1064 auxv->u.a_val = info->phdr;
1065 break;
1066
1067 case AT_PHNUM:
1068 if (info->phdr == 0)
1069 auxv->a_type = AT_IGNORE;
1070 else
1071 auxv->u.a_val = info->phnum;
1072 break;
1073
1074 case AT_BASE:
1075 if (info->interp_base == 0)
1076 auxv->a_type = AT_IGNORE;
1077 else
1078 auxv->u.a_val = info->interp_base;
1079 break;
1080
1081 case AT_PLATFORM: /* points to a platform description string */
1082 auxv->u.a_ptr = copy_str(&strtab, orig_auxv->u.a_ptr);
1083 break;
1084
1085 case AT_ENTRY:
1086 auxv->u.a_val = info->entry;
1087 break;
1088
1089 case AT_IGNORE:
1090 case AT_EXECFD:
1091 case AT_PHENT:
1092 case AT_PAGESZ:
1093 case AT_FLAGS:
1094 case AT_NOTELF:
1095 case AT_UID:
1096 case AT_EUID:
1097 case AT_GID:
1098 case AT_EGID:
1099 case AT_CLKTCK:
1100 case AT_HWCAP:
1101 case AT_FPUCW:
1102 case AT_DCACHEBSIZE:
1103 case AT_ICACHEBSIZE:
1104 case AT_UCACHEBSIZE:
1105 /* All these are pointerless, so we don't need to do anything
1106 about them. */
1107 break;
1108
1109 case AT_SECURE:
1110 /* If this is 1, then it means that this program is running
1111 suid, and therefore the dynamic linker should be careful
1112 about LD_PRELOAD, etc. However, since stage1 (the thing
1113 the kernel actually execve's) should never be SUID, and we
1114 need LD_PRELOAD/LD_LIBRARY_PATH to work for the client, we
1115 set AT_SECURE to 0. */
1116 auxv->u.a_val = 0;
1117 break;
1118
1119 case AT_SYSINFO:
1120 /* Leave this unmolested for now, but we'll update it later
1121 when we set up the client trampoline code page */
1122 break;
1123
1124 case AT_SYSINFO_EHDR:
1125 /* Trash this, because we don't reproduce it */
1126 auxv->a_type = AT_IGNORE;
1127 break;
1128
1129 default:
1130 /* stomp out anything we don't know about */
1131 if (0)
1132 printf("stomping auxv entry %d\n", auxv->a_type);
1133 auxv->a_type = AT_IGNORE;
1134 break;
1135
1136 }
1137 }
1138 *auxv = *orig_auxv;
1139 vg_assert(auxv->a_type == AT_NULL);
1140
nethercotef84f6952004-07-15 14:58:33 +00001141 /* --- trampoline page --- */
1142 VG_(memcpy)( (void *)VG_(client_trampoline_code),
1143 &VG_(trampoline_code_start), VG_(trampoline_code_length) );
1144
nethercote71980f02004-01-24 18:18:54 +00001145 vg_assert((strtab-stringbase) == stringsize);
1146
nethercote5ee67ca2004-06-22 14:00:09 +00001147 /* We know the initial ESP is pointing at argc/argv */
1148 VG_(client_argc) = *(Int*)cl_esp;
1149 VG_(client_argv) = (Char**)(cl_esp + sizeof(Int));
1150
nethercote71980f02004-01-24 18:18:54 +00001151 return cl_esp;
1152}
1153
1154/*====================================================================*/
1155/*=== Find executable ===*/
1156/*====================================================================*/
1157
thughes4ad52d02004-06-27 17:37:21 +00001158static const char* executable_name;
1159
1160static Bool match_executable(const char *entry) {
1161 char buf[strlen(entry) + strlen(executable_name) + 2];
1162
1163 /* empty PATH element means . */
1164 if (*entry == '\0')
1165 entry = ".";
1166
1167 snprintf(buf, sizeof(buf), "%s/%s", entry, executable_name);
1168
1169 if (access(buf, R_OK|X_OK) == 0) {
1170 executable_name = strdup(buf);
1171 vg_assert(NULL != executable_name);
1172 return True;
1173 }
1174 return False;
1175}
1176
nethercote71980f02004-01-24 18:18:54 +00001177static const char* find_executable(const char* exec)
1178{
1179 vg_assert(NULL != exec);
thughes4ad52d02004-06-27 17:37:21 +00001180 executable_name = exec;
1181 if (strchr(executable_name, '/') == NULL) {
nethercote71980f02004-01-24 18:18:54 +00001182 /* no '/' - we need to search the path */
1183 char *path = getenv("PATH");
thughes4ad52d02004-06-27 17:37:21 +00001184 scan_colsep(path, match_executable);
nethercote71980f02004-01-24 18:18:54 +00001185 }
thughes4ad52d02004-06-27 17:37:21 +00001186 return executable_name;
nethercote71980f02004-01-24 18:18:54 +00001187}
1188
1189
1190/*====================================================================*/
1191/*=== Loading tools ===*/
1192/*====================================================================*/
1193
1194static void list_tools(void)
1195{
1196 DIR *dir = opendir(VG_(libdir));
1197 struct dirent *de;
1198 int first = 1;
1199
1200 if (dir == NULL) {
1201 fprintf(stderr, "Can't open %s: %s (installation problem?)\n",
nethercotef4928da2004-06-15 10:54:40 +00001202 VG_(libdir), strerror(errno));
nethercote71980f02004-01-24 18:18:54 +00001203 return;
1204 }
1205
nethercotef4928da2004-06-15 10:54:40 +00001206 while ((de = readdir(dir)) != NULL) {
nethercote71980f02004-01-24 18:18:54 +00001207 int len = strlen(de->d_name);
1208
1209 /* look for vgskin_TOOL.so names */
1210 if (len > (7+1+3) && /* "vgskin_" + at least 1-char toolname + ".so" */
nethercotef4928da2004-06-15 10:54:40 +00001211 strncmp(de->d_name, "vgskin_", 7) == 0 &&
1212 VG_STREQ(de->d_name + len - 3, ".so")) {
1213 if (first) {
1214 fprintf(stderr, "Available tools:\n");
1215 first = 0;
1216 }
1217 de->d_name[len-3] = '\0';
1218 fprintf(stderr, "\t%s\n", de->d_name+7);
nethercote71980f02004-01-24 18:18:54 +00001219 }
1220 }
1221
1222 closedir(dir);
1223
1224 if (first)
nethercotef4928da2004-06-15 10:54:40 +00001225 fprintf(stderr, "No tools available in \"%s\" (installation problem?)\n",
1226 VG_(libdir));
nethercote71980f02004-01-24 18:18:54 +00001227}
1228
1229
1230/* Find and load a tool, and check it looks ok. Also looks to see if there's
1231 * a matching vgpreload_*.so file, and returns its name in *preloadpath. */
1232static void load_tool( const char *toolname, void** handle_out,
1233 ToolInfo** toolinfo_out, char **preloadpath_out )
1234{
1235 Bool ok;
1236 int len = strlen(VG_(libdir)) + strlen(toolname)*2 + 16;
1237 char buf[len];
1238 void* handle;
1239 ToolInfo* toolinfo;
1240 char* preloadpath = NULL;
1241 Int* vg_malloc_redzonep;
1242
1243 // XXX: allowing full paths for --tool option -- does it make sense?
1244 // Doesn't allow for vgpreload_<tool>.so.
1245
1246 if (strchr(toolname, '/') != 0) {
1247 /* toolname contains '/', and so must be a pathname */
1248 handle = dlopen(toolname, RTLD_NOW);
1249 } else {
1250 /* just try in the libdir */
1251 snprintf(buf, len, "%s/vgskin_%s.so", VG_(libdir), toolname);
1252 handle = dlopen(buf, RTLD_NOW);
1253
1254 if (handle != NULL) {
1255 snprintf(buf, len, "%s/vgpreload_%s.so", VG_(libdir), toolname);
1256 if (access(buf, R_OK) == 0) {
1257 preloadpath = strdup(buf);
1258 vg_assert(NULL != preloadpath);
1259 }
1260 }
1261 }
1262
1263 ok = (NULL != handle);
1264 if (!ok) {
1265 fprintf(stderr, "Can't open tool \"%s\": %s\n", toolname, dlerror());
1266 goto bad_load;
1267 }
1268
1269 toolinfo = dlsym(handle, "vgSkin_tool_info");
1270 ok = (NULL != toolinfo);
1271 if (!ok) {
1272 fprintf(stderr, "Tool \"%s\" doesn't define SK_(tool_info) - "
1273 "add VG_DETERMINE_INTERFACE_VERSION?\n", toolname);
1274 goto bad_load;
1275 }
1276
1277 ok = (toolinfo->sizeof_ToolInfo == sizeof(*toolinfo) &&
1278 toolinfo->interface_major_version == VG_CORE_INTERFACE_MAJOR_VERSION &&
1279 toolinfo->sk_pre_clo_init != NULL);
1280 if (!ok) {
1281 fprintf(stderr, "Error:\n"
1282 " Tool and core interface versions do not match.\n"
1283 " Interface version used by core is: %d.%d (size %d)\n"
1284 " Interface version used by tool is: %d.%d (size %d)\n"
1285 " The major version numbers must match.\n",
1286 VG_CORE_INTERFACE_MAJOR_VERSION,
1287 VG_CORE_INTERFACE_MINOR_VERSION,
1288 sizeof(*toolinfo),
1289 toolinfo->interface_major_version,
1290 toolinfo->interface_minor_version,
1291 toolinfo->sizeof_ToolInfo);
1292 fprintf(stderr, " You need to at least recompile, and possibly update,\n");
1293 if (VG_CORE_INTERFACE_MAJOR_VERSION > toolinfo->interface_major_version)
nethercote996901a2004-08-03 13:29:09 +00001294 fprintf(stderr, " your tool to work with this version of Valgrind.\n");
nethercote71980f02004-01-24 18:18:54 +00001295 else
nethercote996901a2004-08-03 13:29:09 +00001296 fprintf(stderr, " your version of Valgrind to work with this tool.\n");
nethercote71980f02004-01-24 18:18:54 +00001297 goto bad_load;
1298 }
1299
1300 // Set redzone size for V's allocator
1301 vg_malloc_redzonep = dlsym(handle, STR(VG_(vg_malloc_redzone_szB)));
1302 if ( NULL != vg_malloc_redzonep ) {
1303 VG_(vg_malloc_redzone_szB) = *vg_malloc_redzonep;
1304 }
1305
1306 vg_assert(NULL != handle && NULL != toolinfo);
1307 *handle_out = handle;
1308 *toolinfo_out = toolinfo;
1309 *preloadpath_out = preloadpath;
1310 return;
1311
1312
1313 bad_load:
1314 if (handle != NULL)
1315 dlclose(handle);
1316
nethercotef4928da2004-06-15 10:54:40 +00001317 fprintf(stderr, "valgrind: couldn't load tool\n");
nethercote71980f02004-01-24 18:18:54 +00001318 list_tools();
1319 exit(127);
1320}
1321
nethercotef4928da2004-06-15 10:54:40 +00001322
1323/*====================================================================*/
1324/*=== Command line errors ===*/
1325/*====================================================================*/
1326
1327static void abort_msg ( void )
1328{
nethercotef8548672004-06-21 12:42:35 +00001329 VG_(clo_log_to) = VgLogTo_Fd;
1330 VG_(clo_log_fd) = 2; /* stderr */
nethercotef4928da2004-06-15 10:54:40 +00001331}
1332
1333void VG_(bad_option) ( Char* opt )
1334{
1335 abort_msg();
1336 VG_(printf)("valgrind: Bad option `%s'; aborting.\n", opt);
1337 VG_(printf)("valgrind: Use --help for more information.\n");
1338 VG_(exit)(1);
1339}
1340
1341static void missing_tool_option ( void )
1342{
1343 abort_msg();
1344 VG_(printf)("valgrind: Missing --tool option\n");
1345 list_tools();
1346 VG_(printf)("valgrind: Use --help for more information.\n");
1347 VG_(exit)(1);
1348}
1349
1350static void missing_prog ( void )
1351{
1352 abort_msg();
1353 VG_(printf)("valgrind: no program specified\n");
1354 VG_(printf)("valgrind: Use --help for more information.\n");
1355 VG_(exit)(1);
1356}
1357
1358static void config_error ( Char* msg )
1359{
1360 abort_msg();
1361 VG_(printf)("valgrind: Startup or configuration error:\n %s\n", msg);
1362 VG_(printf)("valgrind: Unable to start up properly. Giving up.\n");
1363 VG_(exit)(1);
1364}
1365
1366
nethercote71980f02004-01-24 18:18:54 +00001367/*====================================================================*/
1368/*=== Loading the client ===*/
1369/*====================================================================*/
1370
nethercotef4928da2004-06-15 10:54:40 +00001371static void load_client(char* cl_argv[], const char* exec, Int need_help,
nethercote71980f02004-01-24 18:18:54 +00001372 /*out*/struct exeinfo* info, /*out*/Addr* client_eip)
1373{
1374 // If they didn't specify an executable with --exec, and didn't specify
1375 // --help, then use client argv[0] (searching $PATH if necessary).
nethercotef4928da2004-06-15 10:54:40 +00001376 if (NULL == exec && !need_help) {
nethercote71980f02004-01-24 18:18:54 +00001377 if (cl_argv[0] == NULL ||
1378 ( NULL == (exec = find_executable(cl_argv[0])) ) )
1379 {
nethercotef4928da2004-06-15 10:54:40 +00001380 missing_prog();
nethercote71980f02004-01-24 18:18:54 +00001381 }
1382 }
1383
1384 info->map_base = VG_(client_mapbase);
nethercote71980f02004-01-24 18:18:54 +00001385 info->exe_base = VG_(client_base);
1386 info->exe_end = VG_(client_end);
1387 info->argv = cl_argv;
1388
nethercotef4928da2004-06-15 10:54:40 +00001389 if (need_help) {
nethercote71980f02004-01-24 18:18:54 +00001390 VG_(clexecfd) = -1;
nethercoteea147e72004-07-26 15:43:57 +00001391 // Set the minimal number of entries in 'info' to continue.
nethercoted6a56872004-07-26 15:32:47 +00001392 info->interp_name = NULL;
1393 info->interp_args = NULL;
nethercote71980f02004-01-24 18:18:54 +00001394 } else {
1395 Int ret;
nethercote4ec0af42004-10-16 15:31:49 +00001396 VG_(clexecfd) = VG_(open)(exec, VKI_O_RDONLY, VKI_S_IRUSR);
nethercote71980f02004-01-24 18:18:54 +00001397 ret = do_exec(exec, info);
1398 if (ret != 0) {
nethercoteea147e72004-07-26 15:43:57 +00001399 fprintf(stderr, "valgrind: do_exec(%s) failed: %s\n",
1400 exec, strerror(ret));
nethercote71980f02004-01-24 18:18:54 +00001401 exit(127);
1402 }
1403 }
1404
1405 /* Copy necessary bits of 'info' that were filled in */
1406 *client_eip = info->init_eip;
1407 VG_(brk_base) = VG_(brk_limit) = info->brkbase;
1408}
1409
nethercote969ecf12004-10-13 17:29:01 +00001410/*====================================================================*/
1411/*=== Address space unpadding ===*/
1412/*====================================================================*/
1413
1414typedef struct {
1415 char* killpad_start;
1416 char* killpad_end;
1417 struct stat* killpad_padstat;
1418} killpad_extra;
1419
1420static int killpad(char *segstart, char *segend, const char *perm, off_t off,
1421 int maj, int min, int ino, void* ex)
1422{
1423 killpad_extra* extra = ex;
1424 void *b, *e;
1425 int res;
1426
1427 vg_assert(NULL != extra->killpad_padstat);
1428
1429 if (extra->killpad_padstat->st_dev != makedev(maj, min) ||
1430 extra->killpad_padstat->st_ino != ino)
1431 return 1;
1432
1433 if (segend <= extra->killpad_start || segstart >= extra->killpad_end)
1434 return 1;
1435
1436 if (segstart <= extra->killpad_start)
1437 b = extra->killpad_start;
1438 else
1439 b = segstart;
1440
1441 if (segend >= extra->killpad_end)
1442 e = extra->killpad_end;
1443 else
1444 e = segend;
1445
1446 res = munmap(b, (char *)e-(char *)b);
1447 vg_assert(0 == res);
1448
1449 return 1;
1450}
1451
1452// Remove padding of 'padfile' from a range of address space.
1453void as_unpad(void *start, void *end, int padfile)
1454{
1455 static struct stat padstat;
1456 killpad_extra extra;
1457 int res;
1458
1459 vg_assert(padfile > 0);
1460
1461 res = fstat(padfile, &padstat);
1462 vg_assert(0 == res);
1463 extra.killpad_padstat = &padstat;
1464 extra.killpad_start = start;
1465 extra.killpad_end = end;
1466 foreach_map(killpad, &extra);
1467}
1468
1469void as_closepadfile(int padfile)
1470{
1471 int res = close(padfile);
1472 vg_assert(0 == res);
1473}
1474
nethercote71980f02004-01-24 18:18:54 +00001475
1476/*====================================================================*/
nethercotef6a1d502004-08-09 12:21:57 +00001477/*=== Command-line: variables, processing, etc ===*/
nethercote71980f02004-01-24 18:18:54 +00001478/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +00001479
njn25e49d8e72002-09-23 09:36:25 +00001480/* Define, and set defaults. */
1481Bool VG_(clo_error_limit) = True;
nethercote04d0fbc2004-01-26 16:48:06 +00001482Bool VG_(clo_db_attach) = False;
1483Char* VG_(clo_db_command) = VG_CLO_DEFAULT_DBCOMMAND;
njn43c799e2003-04-08 00:08:52 +00001484Bool VG_(clo_gen_suppressions) = False;
nethercote27fec902004-06-16 21:26:32 +00001485Int VG_(clo_sanity_level) = 1;
njn25e49d8e72002-09-23 09:36:25 +00001486Int VG_(clo_verbosity) = 1;
1487Bool VG_(clo_demangle) = True;
njn25e49d8e72002-09-23 09:36:25 +00001488Bool VG_(clo_trace_children) = False;
sewardj4cf05692002-10-27 20:28:29 +00001489
nethercotef1e5e152004-09-01 23:58:16 +00001490/* See big comment in core.h for meaning of these three.
nethercotee1730692003-11-20 10:38:07 +00001491 fd is initially stdout, for --help, but gets moved to stderr by default
1492 immediately afterwards. */
sewardj4cf05692002-10-27 20:28:29 +00001493VgLogTo VG_(clo_log_to) = VgLogTo_Fd;
nethercotef8548672004-06-21 12:42:35 +00001494Int VG_(clo_log_fd) = 1;
1495Char* VG_(clo_log_name) = NULL;
sewardj4cf05692002-10-27 20:28:29 +00001496
thughes6233a382004-08-21 11:10:44 +00001497Bool VG_(clo_time_stamp) = False;
1498
sewardj6024b212003-07-13 10:54:33 +00001499Int VG_(clo_input_fd) = 0; /* stdin */
njn25e49d8e72002-09-23 09:36:25 +00001500Int VG_(clo_n_suppressions) = 0;
sewardjde4a1d02002-03-22 01:27:54 +00001501Char* VG_(clo_suppressions)[VG_CLO_MAX_SFILES];
njn25e49d8e72002-09-23 09:36:25 +00001502Bool VG_(clo_profile) = False;
1503Bool VG_(clo_single_step) = False;
1504Bool VG_(clo_optimise) = True;
1505UChar VG_(clo_trace_codegen) = 0; // 00000000b
1506Bool VG_(clo_trace_syscalls) = False;
1507Bool VG_(clo_trace_signals) = False;
1508Bool VG_(clo_trace_symtab) = False;
njn25e49d8e72002-09-23 09:36:25 +00001509Bool VG_(clo_trace_sched) = False;
1510Int VG_(clo_trace_pthread_level) = 0;
njn25e49d8e72002-09-23 09:36:25 +00001511Int VG_(clo_dump_error) = 0;
1512Int VG_(clo_backtrace_size) = 4;
1513Char* VG_(clo_weird_hacks) = NULL;
sewardj858964b2002-10-05 14:15:43 +00001514Bool VG_(clo_run_libc_freeres) = True;
rjwalshf5f536f2003-11-17 17:45:00 +00001515Bool VG_(clo_track_fds) = False;
sewardj22854b92002-11-30 14:00:47 +00001516Bool VG_(clo_chain_bb) = True;
nethercote77eba602003-11-13 17:35:04 +00001517Bool VG_(clo_show_below_main) = False;
fitzhardinge98abfc72003-12-16 02:05:15 +00001518Bool VG_(clo_pointercheck) = True;
fitzhardinge462f4f92003-12-18 02:10:54 +00001519Bool VG_(clo_branchpred) = False;
sewardj2370f3b2002-11-30 15:01:01 +00001520
jsgf855d93d2003-10-13 22:26:55 +00001521static Bool VG_(clo_wait_for_gdb) = False;
1522
1523/* If we're doing signal routing, poll for signals every 50mS by
1524 default. */
1525Int VG_(clo_signal_polltime) = 50;
1526
1527/* These flags reduce thread wakeup latency on syscall completion and
1528 signal delivery, respectively. The downside is possible unfairness. */
1529Bool VG_(clo_lowlat_syscalls) = False; /* low-latency syscalls */
1530Bool VG_(clo_lowlat_signals) = False; /* low-latency signals */
1531
sewardjde4a1d02002-03-22 01:27:54 +00001532
nethercote6c999f22004-01-31 22:55:15 +00001533void usage ( Bool debug_help )
njn7cf0bd32002-06-08 13:36:03 +00001534{
njn25e49d8e72002-09-23 09:36:25 +00001535 Char* usage1 =
nethercote71980f02004-01-24 18:18:54 +00001536"usage: valgrind --tool=<toolname> [options] prog-and-args\n"
njn25e49d8e72002-09-23 09:36:25 +00001537"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001538" common user options for all Valgrind tools, with defaults in [ ]:\n"
nethercote0d588502004-06-21 13:27:11 +00001539" --tool=<name> use the Valgrind tool named <name>\n"
nethercotea76368b2004-06-16 11:56:29 +00001540" -h --help show this message\n"
nethercote6c999f22004-01-31 22:55:15 +00001541" --help-debug show this message, plus debugging options\n"
njn25e49d8e72002-09-23 09:36:25 +00001542" --version show version\n"
njn25e49d8e72002-09-23 09:36:25 +00001543" -q --quiet run silently; only print error msgs\n"
1544" -v --verbose be more verbose, incl counts of errors\n"
nethercote77eba602003-11-13 17:35:04 +00001545" --trace-children=no|yes Valgrind-ise child processes? [no]\n"
nethercote0d588502004-06-21 13:27:11 +00001546" --track-fds=no|yes track open file descriptors? [no]\n"
thughes6233a382004-08-21 11:10:44 +00001547" --time-stamp=no|yes add timestamps to log messages? [no]\n"
nethercote2b0793f2003-12-02 10:41:18 +00001548"\n"
1549" uncommon user options for all Valgrind tools:\n"
nethercote0d588502004-06-21 13:27:11 +00001550" --run-libc-freeres=no|yes free up glibc memory at exit? [yes]\n"
1551" --weird-hacks=hack1,hack2,... recognised hacks: lax-ioctls [none]\n"
1552" --signal-polltime=<time> signal poll period (mS) for older kernels [50]\n"
1553" --lowlat-signals=no|yes improve thread signal wake-up latency [no]\n"
1554" --lowlat-syscalls=no|yes improve thread syscall wake-up latency [no]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001555" --pointercheck=no|yes enforce client address space limits [yes]\n"
njn25e49d8e72002-09-23 09:36:25 +00001556"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001557" user options for Valgrind tools that report errors:\n"
nethercotef8548672004-06-21 12:42:35 +00001558" --log-fd=<number> log messages to file descriptor [2=stderr]\n"
1559" --log-file=<file> log messages to <file>.pid<pid>\n"
1560" --log-socket=ipaddr:port log messages to socket ipaddr:port\n"
nethercote2b0793f2003-12-02 10:41:18 +00001561" --demangle=no|yes automatically demangle C++ names? [yes]\n"
1562" --num-callers=<number> show <num> callers in stack traces [4]\n"
1563" --error-limit=no|yes stop showing new errors if too many? [yes]\n"
1564" --show-below-main=no|yes continue stack traces below main() [no]\n"
1565" --suppressions=<filename> suppress errors described in <filename>\n"
1566" --gen-suppressions=no|yes print suppressions for errors detected [no]\n"
nethercote04d0fbc2004-01-26 16:48:06 +00001567" --db-attach=no|yes start debugger when errors detected? [no]\n"
1568" --db-command=<command> command to start debugger [gdb -nw %%f %%p]\n"
1569" --input-fd=<number> file descriptor for input [0=stdin]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001570"\n";
njn7cf0bd32002-06-08 13:36:03 +00001571
njn25e49d8e72002-09-23 09:36:25 +00001572 Char* usage2 =
1573"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001574" debugging options for all Valgrind tools:\n"
njn25e49d8e72002-09-23 09:36:25 +00001575" --sanity-level=<number> level of sanity checking to do [1]\n"
1576" --single-step=no|yes translate each instr separately? [no]\n"
1577" --optimise=no|yes improve intermediate code? [yes]\n"
nethercote137bc552003-11-14 17:47:54 +00001578" --profile=no|yes profile? (tool must be built for it) [no]\n"
sewardj22854b92002-11-30 14:00:47 +00001579" --chain-bb=no|yes do basic-block chaining? [yes]\n"
fitzhardinge462f4f92003-12-18 02:10:54 +00001580" --branchpred=yes|no generate branch prediction hints [no]\n"
njn25e49d8e72002-09-23 09:36:25 +00001581" --trace-codegen=<XXXXX> show generated code? (X = 0|1) [00000]\n"
1582" --trace-syscalls=no|yes show all system calls? [no]\n"
1583" --trace-signals=no|yes show signal handling details? [no]\n"
1584" --trace-symtab=no|yes show symbol table details? [no]\n"
njn25e49d8e72002-09-23 09:36:25 +00001585" --trace-sched=no|yes show thread scheduler details? [no]\n"
njn3e884182003-04-15 13:03:23 +00001586" --trace-pthread=none|some|all show pthread event details? [none]\n"
jsgf855d93d2003-10-13 22:26:55 +00001587" --wait-for-gdb=yes|no pause on startup to wait for gdb attach\n"
njn25e49d8e72002-09-23 09:36:25 +00001588"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001589" debugging options for Valgrind tools that report errors\n"
1590" --dump-error=<number> show translation for basic block associated\n"
1591" with <number>'th error context [0=show none]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001592"\n";
njn3e884182003-04-15 13:03:23 +00001593
1594 Char* usage3 =
1595"\n"
nethercote71980f02004-01-24 18:18:54 +00001596" Extra options read from ~/.valgrindrc, $VALGRIND_OPTS, ./.valgrindrc\n"
njn25e49d8e72002-09-23 09:36:25 +00001597"\n"
nethercote08fa9a72004-07-16 17:44:00 +00001598" Valgrind is Copyright (C) 2000-2004 Julian Seward et al.\n"
njn25e49d8e72002-09-23 09:36:25 +00001599" and licensed under the GNU General Public License, version 2.\n"
1600" Bug reports, feedback, admiration, abuse, etc, to: %s.\n"
njnd04b7c62002-10-03 14:05:52 +00001601"\n"
nethercote137bc552003-11-14 17:47:54 +00001602" Tools are copyright and licensed by their authors. See each\n"
1603" tool's start-up message for more information.\n"
njn25e49d8e72002-09-23 09:36:25 +00001604"\n";
njn7cf0bd32002-06-08 13:36:03 +00001605
fitzhardinge98abfc72003-12-16 02:05:15 +00001606 VG_(printf)(usage1);
1607 if (VG_(details).name) {
1608 VG_(printf)(" user options for %s:\n", VG_(details).name);
fitzhardinge98abfc72003-12-16 02:05:15 +00001609 if (VG_(needs).command_line_options)
1610 SK_(print_usage)();
1611 else
1612 VG_(printf)(" (none)\n");
1613 }
nethercote6c999f22004-01-31 22:55:15 +00001614 if (debug_help) {
1615 VG_(printf)(usage2);
fitzhardinge98abfc72003-12-16 02:05:15 +00001616
nethercote6c999f22004-01-31 22:55:15 +00001617 if (VG_(details).name) {
1618 VG_(printf)(" debugging options for %s:\n", VG_(details).name);
1619
1620 if (VG_(needs).command_line_options)
1621 SK_(print_debug_usage)();
1622 else
1623 VG_(printf)(" (none)\n");
1624 }
fitzhardinge98abfc72003-12-16 02:05:15 +00001625 }
nethercote421281e2003-11-20 16:20:55 +00001626 VG_(printf)(usage3, VG_BUGS_TO);
nethercotef4928da2004-06-15 10:54:40 +00001627 VG_(exit)(0);
njn7cf0bd32002-06-08 13:36:03 +00001628}
sewardjde4a1d02002-03-22 01:27:54 +00001629
nethercote71980f02004-01-24 18:18:54 +00001630static void pre_process_cmd_line_options
nethercote6c999f22004-01-31 22:55:15 +00001631 ( Int* need_help, const char** tool, const char** exec )
sewardj1c1b1162003-02-23 01:25:51 +00001632{
nethercote71980f02004-01-24 18:18:54 +00001633 UInt i;
sewardjde4a1d02002-03-22 01:27:54 +00001634
nethercote71980f02004-01-24 18:18:54 +00001635 /* parse the options we have (only the options we care about now) */
nethercotef6a1d502004-08-09 12:21:57 +00001636 for (i = 1; i < vg_argc; i++) {
nethercote71980f02004-01-24 18:18:54 +00001637
nethercotef6a1d502004-08-09 12:21:57 +00001638 if (strcmp(vg_argv[i], "--version") == 0) {
nethercote71980f02004-01-24 18:18:54 +00001639 printf("valgrind-" VERSION "\n");
nethercotef4928da2004-06-15 10:54:40 +00001640 exit(0);
nethercote71980f02004-01-24 18:18:54 +00001641
nethercotef6a1d502004-08-09 12:21:57 +00001642 } else if (VG_CLO_STREQ(vg_argv[i], "--help") ||
1643 VG_CLO_STREQ(vg_argv[i], "-h")) {
nethercote6c999f22004-01-31 22:55:15 +00001644 *need_help = 1;
1645
nethercotef6a1d502004-08-09 12:21:57 +00001646 } else if (VG_CLO_STREQ(vg_argv[i], "--help-debug")) {
nethercote6c999f22004-01-31 22:55:15 +00001647 *need_help = 2;
nethercote71980f02004-01-24 18:18:54 +00001648
nethercotef6a1d502004-08-09 12:21:57 +00001649 } else if (VG_CLO_STREQN(7, vg_argv[i], "--tool=") ||
1650 VG_CLO_STREQN(7, vg_argv[i], "--skin=")) {
1651 *tool = &vg_argv[i][7];
nethercote71980f02004-01-24 18:18:54 +00001652
nethercotef6a1d502004-08-09 12:21:57 +00001653 } else if (VG_CLO_STREQN(7, vg_argv[i], "--exec=")) {
1654 *exec = &vg_argv[i][7];
nethercote71980f02004-01-24 18:18:54 +00001655 }
1656 }
1657
nethercotef4928da2004-06-15 10:54:40 +00001658 /* If no tool specified, can act appropriately without loading tool */
nethercote71980f02004-01-24 18:18:54 +00001659 if (*tool == NULL) {
nethercotef4928da2004-06-15 10:54:40 +00001660 if (0 == *need_help) {
1661 // neither --tool nor --help/--help-debug specified
1662 missing_tool_option();
1663 } else {
1664 // Give help message, without any tool-specific help
1665 usage(/*help-debug?*/2 == *need_help);
1666 }
nethercote71980f02004-01-24 18:18:54 +00001667 }
1668}
1669
nethercote5ee67ca2004-06-22 14:00:09 +00001670static void process_cmd_line_options( UInt* client_auxv, const char* toolname )
nethercote71980f02004-01-24 18:18:54 +00001671{
nethercotef8548672004-06-21 12:42:35 +00001672 Int i, eventually_log_fd;
nethercote71980f02004-01-24 18:18:54 +00001673 Int *auxp;
1674 Int toolname_len = VG_(strlen)(toolname);
sewardjde4a1d02002-03-22 01:27:54 +00001675
nethercotee1730692003-11-20 10:38:07 +00001676 /* log to stderr by default, but usage message goes to stdout */
nethercotef8548672004-06-21 12:42:35 +00001677 eventually_log_fd = 2;
sewardjde4a1d02002-03-22 01:27:54 +00001678
sewardj19d81412002-06-03 01:10:40 +00001679 /* Check for sane path in ./configure --prefix=... */
fitzhardinge98abfc72003-12-16 02:05:15 +00001680 if (VG_LIBDIR[0] != '/')
sewardj19d81412002-06-03 01:10:40 +00001681 config_error("Please use absolute paths in "
1682 "./configure --prefix=... or --libdir=...");
sewardj38170912002-05-10 21:07:22 +00001683
nethercote71980f02004-01-24 18:18:54 +00001684 for (auxp = client_auxv; auxp[0] != VKI_AT_NULL; auxp += 2) {
fitzhardinge98abfc72003-12-16 02:05:15 +00001685 switch(auxp[0]) {
1686 case VKI_AT_SYSINFO:
fitzhardinge92360792003-12-24 10:11:11 +00001687 auxp[1] = (Int)(VG_(client_trampoline_code) + VG_(tramp_syscall_offset));
fitzhardinge98abfc72003-12-16 02:05:15 +00001688 break;
sewardjde4a1d02002-03-22 01:27:54 +00001689 }
fitzhardinge98abfc72003-12-16 02:05:15 +00001690 }
sewardjde4a1d02002-03-22 01:27:54 +00001691
nethercotef6a1d502004-08-09 12:21:57 +00001692 for (i = 1; i < vg_argc; i++) {
nethercote71980f02004-01-24 18:18:54 +00001693
nethercotef6a1d502004-08-09 12:21:57 +00001694 Char* arg = vg_argv[i];
thughes3bfd5a02004-07-18 08:05:44 +00001695 Char* colon = arg;
nethercote71980f02004-01-24 18:18:54 +00001696
thughes3bfd5a02004-07-18 08:05:44 +00001697 /* Look for a colon in the switch name */
1698 while (*colon && *colon != ':' && *colon != '=')
1699 colon++;
nethercote71980f02004-01-24 18:18:54 +00001700
1701 /* Look for matching "--toolname:foo" */
thughes3bfd5a02004-07-18 08:05:44 +00001702 if (*colon == ':') {
nethercote71980f02004-01-24 18:18:54 +00001703 if (VG_CLO_STREQN(2, arg, "--") &&
1704 VG_CLO_STREQN(toolname_len, arg+2, toolname) &&
1705 VG_CLO_STREQN(1, arg+2+toolname_len, ":"))
1706 {
1707 // prefix matches, convert "--toolname:foo" to "--foo"
1708 if (0)
1709 VG_(printf)("tool-specific arg: %s\n", arg);
1710 arg += toolname_len + 1;
1711 arg[0] = '-';
1712 arg[1] = '-';
1713
1714 } else {
1715 // prefix doesn't match, skip to next arg
1716 continue;
1717 }
1718 }
1719
fitzhardinge98abfc72003-12-16 02:05:15 +00001720 /* Ignore these options - they've already been handled */
nethercote71980f02004-01-24 18:18:54 +00001721 if (VG_CLO_STREQN(7, arg, "--tool=") ||
1722 VG_CLO_STREQN(7, arg, "--skin="))
fitzhardinge98abfc72003-12-16 02:05:15 +00001723 continue;
nethercote71980f02004-01-24 18:18:54 +00001724 if (VG_CLO_STREQN(7, arg, "--exec="))
fitzhardinge98abfc72003-12-16 02:05:15 +00001725 continue;
1726
nethercote71980f02004-01-24 18:18:54 +00001727 if ( VG_CLO_STREQ(arg, "--"))
fitzhardinge98abfc72003-12-16 02:05:15 +00001728 continue;
nethercote27fec902004-06-16 21:26:32 +00001729
nethercote71980f02004-01-24 18:18:54 +00001730 else if (VG_CLO_STREQ(arg, "-v") ||
1731 VG_CLO_STREQ(arg, "--verbose"))
sewardjde4a1d02002-03-22 01:27:54 +00001732 VG_(clo_verbosity)++;
nethercote27fec902004-06-16 21:26:32 +00001733
nethercote71980f02004-01-24 18:18:54 +00001734 else if (VG_CLO_STREQ(arg, "-q") ||
1735 VG_CLO_STREQ(arg, "--quiet"))
sewardjde4a1d02002-03-22 01:27:54 +00001736 VG_(clo_verbosity)--;
1737
nethercote27fec902004-06-16 21:26:32 +00001738 else VG_BOOL_CLO("--branchpred", VG_(clo_branchpred))
1739 else VG_BOOL_CLO("--chain-bb", VG_(clo_chain_bb))
1740 else VG_BOOL_CLO("--db-attach", VG_(clo_db_attach))
1741 else VG_BOOL_CLO("--demangle", VG_(clo_demangle))
1742 else VG_BOOL_CLO("--error-limit", VG_(clo_error_limit))
1743 else VG_BOOL_CLO("--gen-suppressions", VG_(clo_gen_suppressions))
1744 else VG_BOOL_CLO("--lowlat-signals", VG_(clo_lowlat_signals))
1745 else VG_BOOL_CLO("--lowlat-syscalls", VG_(clo_lowlat_syscalls))
1746 else VG_BOOL_CLO("--optimise", VG_(clo_optimise))
1747 else VG_BOOL_CLO("--pointercheck", VG_(clo_pointercheck))
1748 else VG_BOOL_CLO("--profile", VG_(clo_profile))
1749 else VG_BOOL_CLO("--run-libc-freeres", VG_(clo_run_libc_freeres))
1750 else VG_BOOL_CLO("--show-below-main", VG_(clo_show_below_main))
1751 else VG_BOOL_CLO("--single-step", VG_(clo_single_step))
thughes6233a382004-08-21 11:10:44 +00001752 else VG_BOOL_CLO("--time-stamp", VG_(clo_time_stamp))
nethercote27fec902004-06-16 21:26:32 +00001753 else VG_BOOL_CLO("--track-fds", VG_(clo_track_fds))
1754 else VG_BOOL_CLO("--trace-children", VG_(clo_trace_children))
1755 else VG_BOOL_CLO("--trace-sched", VG_(clo_trace_sched))
1756 else VG_BOOL_CLO("--trace-signals", VG_(clo_trace_signals))
1757 else VG_BOOL_CLO("--trace-symtab", VG_(clo_trace_symtab))
1758 else VG_BOOL_CLO("--trace-syscalls", VG_(clo_trace_syscalls))
1759 else VG_BOOL_CLO("--wait-for-gdb", VG_(clo_wait_for_gdb))
sewardj72f98ff2002-06-13 17:23:38 +00001760
nethercote27fec902004-06-16 21:26:32 +00001761 else VG_STR_CLO ("--db-command", VG_(clo_db_command))
1762 else VG_STR_CLO ("--weird-hacks", VG_(clo_weird_hacks))
sewardjde4a1d02002-03-22 01:27:54 +00001763
nethercote27fec902004-06-16 21:26:32 +00001764 else VG_NUM_CLO ("--dump-error", VG_(clo_dump_error))
1765 else VG_NUM_CLO ("--input-fd", VG_(clo_input_fd))
1766 else VG_NUM_CLO ("--sanity-level", VG_(clo_sanity_level))
1767 else VG_NUM_CLO ("--signal­polltime", VG_(clo_signal_polltime))
1768 else VG_BNUM_CLO("--num-callers", VG_(clo_backtrace_size), 1,
1769 VG_DEEPEST_BACKTRACE)
sewardjde4a1d02002-03-22 01:27:54 +00001770
nethercotef8548672004-06-21 12:42:35 +00001771 // for backwards compatibility, replaced by --log-fd
nethercote71980f02004-01-24 18:18:54 +00001772 else if (VG_CLO_STREQN(13, arg, "--logfile-fd=")) {
nethercotef8548672004-06-21 12:42:35 +00001773 VG_(clo_log_to) = VgLogTo_Fd;
1774 VG_(clo_log_name) = NULL;
1775 eventually_log_fd = (Int)VG_(atoll)(&arg[13]);
1776 }
1777 else if (VG_CLO_STREQN(9, arg, "--log-fd=")) {
1778 VG_(clo_log_to) = VgLogTo_Fd;
1779 VG_(clo_log_name) = NULL;
1780 eventually_log_fd = (Int)VG_(atoll)(&arg[9]);
sewardj4cf05692002-10-27 20:28:29 +00001781 }
1782
nethercotef8548672004-06-21 12:42:35 +00001783 // for backwards compatibility, replaced by --log-file
nethercote71980f02004-01-24 18:18:54 +00001784 else if (VG_CLO_STREQN(10, arg, "--logfile=")) {
nethercotef8548672004-06-21 12:42:35 +00001785 VG_(clo_log_to) = VgLogTo_File;
1786 VG_(clo_log_name) = &arg[10];
1787 }
1788 else if (VG_CLO_STREQN(11, arg, "--log-file=")) {
1789 VG_(clo_log_to) = VgLogTo_File;
1790 VG_(clo_log_name) = &arg[11];
sewardj4cf05692002-10-27 20:28:29 +00001791 }
sewardjde4a1d02002-03-22 01:27:54 +00001792
nethercotef8548672004-06-21 12:42:35 +00001793 // for backwards compatibility, replaced by --log-socket
nethercote71980f02004-01-24 18:18:54 +00001794 else if (VG_CLO_STREQN(12, arg, "--logsocket=")) {
nethercotef8548672004-06-21 12:42:35 +00001795 VG_(clo_log_to) = VgLogTo_Socket;
1796 VG_(clo_log_name) = &arg[12];
1797 }
1798 else if (VG_CLO_STREQN(13, arg, "--log-socket=")) {
1799 VG_(clo_log_to) = VgLogTo_Socket;
1800 VG_(clo_log_name) = &arg[13];
sewardj73cf3bc2002-11-03 03:20:15 +00001801 }
1802
nethercote71980f02004-01-24 18:18:54 +00001803 else if (VG_CLO_STREQN(15, arg, "--suppressions=")) {
sewardjde4a1d02002-03-22 01:27:54 +00001804 if (VG_(clo_n_suppressions) >= VG_CLO_MAX_SFILES) {
njn25e49d8e72002-09-23 09:36:25 +00001805 VG_(message)(Vg_UserMsg, "Too many suppression files specified.");
sewardjde4a1d02002-03-22 01:27:54 +00001806 VG_(message)(Vg_UserMsg,
1807 "Increase VG_CLO_MAX_SFILES and recompile.");
nethercote71980f02004-01-24 18:18:54 +00001808 VG_(bad_option)(arg);
sewardjde4a1d02002-03-22 01:27:54 +00001809 }
nethercote71980f02004-01-24 18:18:54 +00001810 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = &arg[15];
sewardjde4a1d02002-03-22 01:27:54 +00001811 VG_(clo_n_suppressions)++;
1812 }
sewardjde4a1d02002-03-22 01:27:54 +00001813
njn25e49d8e72002-09-23 09:36:25 +00001814 /* "vwxyz" --> 000zyxwv (binary) */
nethercote71980f02004-01-24 18:18:54 +00001815 else if (VG_CLO_STREQN(16, arg, "--trace-codegen=")) {
njn25e49d8e72002-09-23 09:36:25 +00001816 Int j;
nethercote71980f02004-01-24 18:18:54 +00001817 char* opt = & arg[16];
njn25e49d8e72002-09-23 09:36:25 +00001818
1819 if (5 != VG_(strlen)(opt)) {
1820 VG_(message)(Vg_UserMsg,
1821 "--trace-codegen argument must have 5 digits");
nethercote71980f02004-01-24 18:18:54 +00001822 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001823 }
1824 for (j = 0; j < 5; j++) {
1825 if ('0' == opt[j]) { /* do nothing */ }
1826 else if ('1' == opt[j]) VG_(clo_trace_codegen) |= (1 << j);
1827 else {
1828 VG_(message)(Vg_UserMsg, "--trace-codegen argument can only "
1829 "contain 0s and 1s");
nethercote71980f02004-01-24 18:18:54 +00001830 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001831 }
1832 }
1833 }
sewardjde4a1d02002-03-22 01:27:54 +00001834
nethercote71980f02004-01-24 18:18:54 +00001835 else if (VG_CLO_STREQ(arg, "--trace-pthread=none"))
sewardj45b4b372002-04-16 22:50:32 +00001836 VG_(clo_trace_pthread_level) = 0;
nethercote71980f02004-01-24 18:18:54 +00001837 else if (VG_CLO_STREQ(arg, "--trace-pthread=some"))
sewardj45b4b372002-04-16 22:50:32 +00001838 VG_(clo_trace_pthread_level) = 1;
nethercote71980f02004-01-24 18:18:54 +00001839 else if (VG_CLO_STREQ(arg, "--trace-pthread=all"))
sewardj45b4b372002-04-16 22:50:32 +00001840 VG_(clo_trace_pthread_level) = 2;
sewardj8937c812002-04-12 20:12:20 +00001841
nethercote71980f02004-01-24 18:18:54 +00001842 else if ( ! VG_(needs).command_line_options
1843 || ! SK_(process_cmd_line_option)(arg) ) {
nethercotef4928da2004-06-15 10:54:40 +00001844 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001845 }
sewardjde4a1d02002-03-22 01:27:54 +00001846 }
1847
nethercote27fec902004-06-16 21:26:32 +00001848 // Check various option values
1849
njnf9ebf672003-05-12 21:41:30 +00001850 if (VG_(clo_verbosity) < 0)
sewardjde4a1d02002-03-22 01:27:54 +00001851 VG_(clo_verbosity) = 0;
1852
nethercote04d0fbc2004-01-26 16:48:06 +00001853 if (VG_(clo_db_attach) && VG_(clo_trace_children)) {
sewardjde4a1d02002-03-22 01:27:54 +00001854 VG_(message)(Vg_UserMsg, "");
1855 VG_(message)(Vg_UserMsg,
nethercote04d0fbc2004-01-26 16:48:06 +00001856 "--db-attach=yes conflicts with --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001857 VG_(message)(Vg_UserMsg,
1858 "Please choose one or the other, but not both.");
nethercote04d0fbc2004-01-26 16:48:06 +00001859 VG_(bad_option)("--db-attach=yes and --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001860 }
1861
nethercotef8548672004-06-21 12:42:35 +00001862 /* Set up logging now. After this is done, VG_(clo_log_fd)
sewardj4cf05692002-10-27 20:28:29 +00001863 should be connected to whatever sink has been selected, and we
1864 indiscriminately chuck stuff into it without worrying what the
1865 nature of it is. Oh the wonder of Unix streams. */
1866
nethercotee1730692003-11-20 10:38:07 +00001867 /* So far we should be still attached to stdout, so we can show on
sewardj4cf05692002-10-27 20:28:29 +00001868 the terminal any problems to do with processing command line
1869 opts. */
nethercotef8548672004-06-21 12:42:35 +00001870 vg_assert(VG_(clo_log_fd) == 1 /* stdout */);
sewardj73cf3bc2002-11-03 03:20:15 +00001871 vg_assert(VG_(logging_to_filedes) == True);
sewardj4cf05692002-10-27 20:28:29 +00001872
1873 switch (VG_(clo_log_to)) {
sewardj73cf3bc2002-11-03 03:20:15 +00001874
sewardj4cf05692002-10-27 20:28:29 +00001875 case VgLogTo_Fd:
nethercotef8548672004-06-21 12:42:35 +00001876 vg_assert(VG_(clo_log_name) == NULL);
1877 VG_(clo_log_fd) = eventually_log_fd;
sewardj4cf05692002-10-27 20:28:29 +00001878 break;
sewardj73cf3bc2002-11-03 03:20:15 +00001879
sewardj4cf05692002-10-27 20:28:29 +00001880 case VgLogTo_File: {
1881 Char logfilename[1000];
jsgff3c3f1a2003-10-14 22:13:28 +00001882 Int seq = 0;
1883 Int pid = VG_(getpid)();
1884
nethercotef8548672004-06-21 12:42:35 +00001885 vg_assert(VG_(clo_log_name) != NULL);
1886 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
jsgff3c3f1a2003-10-14 22:13:28 +00001887
nethercote71980f02004-01-24 18:18:54 +00001888 for (;;) {
jsgff3c3f1a2003-10-14 22:13:28 +00001889 if (seq == 0)
1890 VG_(sprintf)(logfilename, "%s.pid%d",
nethercotef8548672004-06-21 12:42:35 +00001891 VG_(clo_log_name), pid );
jsgff3c3f1a2003-10-14 22:13:28 +00001892 else
1893 VG_(sprintf)(logfilename, "%s.pid%d.%d",
nethercotef8548672004-06-21 12:42:35 +00001894 VG_(clo_log_name), pid, seq );
jsgff3c3f1a2003-10-14 22:13:28 +00001895 seq++;
1896
nethercotef8548672004-06-21 12:42:35 +00001897 eventually_log_fd
jsgff3c3f1a2003-10-14 22:13:28 +00001898 = VG_(open)(logfilename,
1899 VKI_O_CREAT|VKI_O_WRONLY|VKI_O_EXCL|VKI_O_TRUNC,
1900 VKI_S_IRUSR|VKI_S_IWUSR);
nethercotef8548672004-06-21 12:42:35 +00001901 if (eventually_log_fd >= 0) {
1902 VG_(clo_log_fd) = VG_(safe_fd)(eventually_log_fd);
jsgff3c3f1a2003-10-14 22:13:28 +00001903 break;
1904 } else {
nethercotef8548672004-06-21 12:42:35 +00001905 if (eventually_log_fd != -VKI_EEXIST) {
jsgff3c3f1a2003-10-14 22:13:28 +00001906 VG_(message)(Vg_UserMsg,
1907 "Can't create/open log file `%s.pid%d'; giving up!",
nethercotef8548672004-06-21 12:42:35 +00001908 VG_(clo_log_name), pid);
jsgff3c3f1a2003-10-14 22:13:28 +00001909 VG_(bad_option)(
nethercotef8548672004-06-21 12:42:35 +00001910 "--log-file=<file> didn't work out for some reason.");
jsgff3c3f1a2003-10-14 22:13:28 +00001911 break;
1912 }
1913 }
1914 }
sewardj4cf05692002-10-27 20:28:29 +00001915 break;
sewardj73cf3bc2002-11-03 03:20:15 +00001916 }
1917
1918 case VgLogTo_Socket: {
nethercotef8548672004-06-21 12:42:35 +00001919 vg_assert(VG_(clo_log_name) != NULL);
1920 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
1921 eventually_log_fd = VG_(connect_via_socket)( VG_(clo_log_name) );
1922 if (eventually_log_fd == -1) {
sewardj73cf3bc2002-11-03 03:20:15 +00001923 VG_(message)(Vg_UserMsg,
nethercotef8548672004-06-21 12:42:35 +00001924 "Invalid --log-socket=ipaddr or --log-socket=ipaddr:port spec");
sewardj73cf3bc2002-11-03 03:20:15 +00001925 VG_(message)(Vg_UserMsg,
nethercotef8548672004-06-21 12:42:35 +00001926 "of `%s'; giving up!", VG_(clo_log_name) );
sewardj73cf3bc2002-11-03 03:20:15 +00001927 VG_(bad_option)(
nethercotef8548672004-06-21 12:42:35 +00001928 "--log-socket=");
sewardj4cf05692002-10-27 20:28:29 +00001929 }
nethercotef8548672004-06-21 12:42:35 +00001930 if (eventually_log_fd == -2) {
sewardj73cf3bc2002-11-03 03:20:15 +00001931 VG_(message)(Vg_UserMsg,
sewardj570f8902002-11-03 11:44:36 +00001932 "valgrind: failed to connect to logging server `%s'.",
nethercotef8548672004-06-21 12:42:35 +00001933 VG_(clo_log_name) );
sewardj570f8902002-11-03 11:44:36 +00001934 VG_(message)(Vg_UserMsg,
1935 "Log messages will sent to stderr instead." );
1936 VG_(message)(Vg_UserMsg,
1937 "" );
1938 /* We don't change anything here. */
1939 } else {
nethercotef8548672004-06-21 12:42:35 +00001940 vg_assert(eventually_log_fd > 0);
1941 VG_(clo_log_fd) = eventually_log_fd;
sewardj570f8902002-11-03 11:44:36 +00001942 VG_(logging_to_filedes) = False;
1943 }
sewardj73cf3bc2002-11-03 03:20:15 +00001944 break;
1945 }
1946
sewardj4cf05692002-10-27 20:28:29 +00001947 }
1948
nethercotef8548672004-06-21 12:42:35 +00001949 /* Move log_fd into the safe range, so it doesn't conflict with any app fds */
thughesad1c9562004-06-26 11:27:52 +00001950 eventually_log_fd = VG_(fcntl)(VG_(clo_log_fd), VKI_F_DUPFD, VG_(fd_hard_limit));
nethercotef8548672004-06-21 12:42:35 +00001951 if (eventually_log_fd < 0)
jsgf855d93d2003-10-13 22:26:55 +00001952 VG_(message)(Vg_UserMsg, "valgrind: failed to move logfile fd into safe range");
1953 else {
nethercotef8548672004-06-21 12:42:35 +00001954 VG_(clo_log_fd) = eventually_log_fd;
1955 VG_(fcntl)(VG_(clo_log_fd), VKI_F_SETFD, VKI_FD_CLOEXEC);
jsgf855d93d2003-10-13 22:26:55 +00001956 }
1957
sewardj4cf05692002-10-27 20:28:29 +00001958 /* Ok, the logging sink is running now. Print a suitable preamble.
1959 If logging to file or a socket, write details of parent PID and
1960 command line args, to help people trying to interpret the
1961 results of a run which encompasses multiple processes. */
sewardjde4a1d02002-03-22 01:27:54 +00001962
sewardj83adf412002-05-01 01:25:45 +00001963 if (VG_(clo_verbosity > 0)) {
nethercote996901a2004-08-03 13:29:09 +00001964 /* Tool details */
nethercotea131bb82004-09-06 15:34:37 +00001965 VG_(message)(Vg_UserMsg, "%s%s%s, %s for %s.",
njnd04b7c62002-10-03 14:05:52 +00001966 VG_(details).name,
1967 NULL == VG_(details).version ? "" : "-",
1968 NULL == VG_(details).version
1969 ? (Char*)"" : VG_(details).version,
nethercotea131bb82004-09-06 15:34:37 +00001970 VG_(details).description,
1971 VG_PLATFORM);
njnd04b7c62002-10-03 14:05:52 +00001972 VG_(message)(Vg_UserMsg, "%s", VG_(details).copyright_author);
sewardj3b2736a2002-03-24 12:18:35 +00001973
njnd04b7c62002-10-03 14:05:52 +00001974 /* Core details */
1975 VG_(message)(Vg_UserMsg,
nethercotea131bb82004-09-06 15:34:37 +00001976 "Using valgrind-%s, a program supervision framework for %s.",
1977 VERSION, VG_PLATFORM);
sewardjde4a1d02002-03-22 01:27:54 +00001978 VG_(message)(Vg_UserMsg,
nethercote08fa9a72004-07-16 17:44:00 +00001979 "Copyright (C) 2000-2004, and GNU GPL'd, by Julian Seward et al.");
njnd04b7c62002-10-03 14:05:52 +00001980 }
1981
nethercotec1e395d2003-11-10 13:26:49 +00001982 if (VG_(clo_verbosity) > 0 && VG_(clo_log_to) != VgLogTo_Fd) {
sewardj4cf05692002-10-27 20:28:29 +00001983 VG_(message)(Vg_UserMsg, "");
1984 VG_(message)(Vg_UserMsg,
1985 "My PID = %d, parent PID = %d. Prog and args are:",
1986 VG_(getpid)(), VG_(getppid)() );
1987 for (i = 0; i < VG_(client_argc); i++)
1988 VG_(message)(Vg_UserMsg, " %s", VG_(client_argv)[i]);
1989 }
1990
sewardjde4a1d02002-03-22 01:27:54 +00001991 if (VG_(clo_verbosity) > 1) {
nethercotea70f7352004-04-18 12:08:46 +00001992 Int fd;
sewardj4cf05692002-10-27 20:28:29 +00001993 if (VG_(clo_log_to) != VgLogTo_Fd)
1994 VG_(message)(Vg_UserMsg, "");
fitzhardinge98abfc72003-12-16 02:05:15 +00001995 VG_(message)(Vg_UserMsg, "Valgrind library directory: %s", VG_(libdir));
njn86dc2bc2003-09-09 07:26:21 +00001996 VG_(message)(Vg_UserMsg, "Command line");
1997 for (i = 0; i < VG_(client_argc); i++)
1998 VG_(message)(Vg_UserMsg, " %s", VG_(client_argv)[i]);
1999
sewardjde4a1d02002-03-22 01:27:54 +00002000 VG_(message)(Vg_UserMsg, "Startup, with flags:");
nethercotef6a1d502004-08-09 12:21:57 +00002001 for (i = 1; i < vg_argc; i++) {
2002 VG_(message)(Vg_UserMsg, " %s", vg_argv[i]);
sewardjde4a1d02002-03-22 01:27:54 +00002003 }
nethercotea70f7352004-04-18 12:08:46 +00002004
2005 VG_(message)(Vg_UserMsg, "Contents of /proc/version:");
2006 fd = VG_(open) ( "/proc/version", VKI_O_RDONLY, 0 );
2007 if (fd < 0) {
2008 VG_(message)(Vg_UserMsg, " can't open /proc/version");
2009 } else {
2010 #define BUF_LEN 256
2011 Char version_buf[BUF_LEN];
2012 Int n = VG_(read) ( fd, version_buf, BUF_LEN );
2013 vg_assert(n <= 256);
2014 if (n > 0) {
2015 version_buf[n-1] = '\0';
2016 VG_(message)(Vg_UserMsg, " %s", version_buf);
2017 } else {
2018 VG_(message)(Vg_UserMsg, " (empty?)");
2019 }
2020 VG_(close)(fd);
2021 #undef BUF_LEN
2022 }
sewardjde4a1d02002-03-22 01:27:54 +00002023 }
2024
fitzhardinge98abfc72003-12-16 02:05:15 +00002025 if (VG_(clo_n_suppressions) < VG_CLO_MAX_SFILES-1 &&
njn25e49d8e72002-09-23 09:36:25 +00002026 (VG_(needs).core_errors || VG_(needs).skin_errors)) {
nethercote996901a2004-08-03 13:29:09 +00002027 /* If there are no suppression files specified and the tool
fitzhardinge98abfc72003-12-16 02:05:15 +00002028 needs one, load the default */
2029 static const Char default_supp[] = "default.supp";
2030 Int len = VG_(strlen)(VG_(libdir)) + 1 + sizeof(default_supp);
2031 Char *buf = VG_(arena_malloc)(VG_AR_CORE, len);
2032 VG_(sprintf)(buf, "%s/%s", VG_(libdir), default_supp);
2033 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = buf;
2034 VG_(clo_n_suppressions)++;
sewardjde4a1d02002-03-22 01:27:54 +00002035 }
sewardj4cf05692002-10-27 20:28:29 +00002036
njn6a230532003-07-21 10:38:23 +00002037 if (VG_(clo_gen_suppressions) &&
2038 !VG_(needs).core_errors && !VG_(needs).skin_errors) {
nethercotef4928da2004-06-15 10:54:40 +00002039 VG_(message)(Vg_UserMsg,
2040 "Can't use --gen-suppressions=yes with this tool,");
2041 VG_(message)(Vg_UserMsg,
2042 "as it doesn't generate errors.");
2043 VG_(bad_option)("--gen-suppressions=yes");
njn6a230532003-07-21 10:38:23 +00002044 }
sewardjde4a1d02002-03-22 01:27:54 +00002045}
2046
nethercotef6a1d502004-08-09 12:21:57 +00002047// Build the string for VALGRINDCLO.
2048Char* VG_(build_child_VALGRINDCLO)( Char* exename )
2049{
2050 /* If we're tracing the children, then we need to start it
2051 with our starter+arguments, which are copied into VALGRINDCLO,
2052 except the --exec= option is changed if present.
2053 */
2054 Int i;
2055 Char *exec;
2056 Char *cp;
2057 Char *optvar;
2058 Int optlen, execlen;
2059
2060 // All these allocated blocks are not free - because we're either
2061 // going to exec, or panic when we fail.
2062
2063 // Create --exec= option: "--exec=<exename>"
2064 exec = VG_(arena_malloc)(VG_AR_CORE,
2065 VG_(strlen)( exename ) + 7/*--exec=*/ + 1/*\0*/);
2066 vg_assert(NULL != exec);
2067 VG_(sprintf)(exec, "--exec=%s", exename);
2068
2069 // Allocate space for optvar (may overestimate by counting --exec twice,
2070 // no matter)
2071 optlen = 1;
2072 for (i = 0; i < vg_argc; i++)
2073 optlen += VG_(strlen)(vg_argv[i]) + 1;
2074 optlen += VG_(strlen)(exec)+1;
2075 optvar = VG_(arena_malloc)(VG_AR_CORE, optlen);
2076
2077 // Copy all valgrind args except the old --exec (if present)
2078 // VG_CLO_SEP is the separator.
2079 cp = optvar;
2080 for (i = 1; i < vg_argc; i++) {
2081 Char *arg = vg_argv[i];
2082
2083 if (VG_(memcmp)(arg, "--exec=", 7) == 0) {
2084 // don't copy existing --exec= arg
2085 } else if (VG_(strcmp)(arg, "--") == 0) {
2086 // stop at "--"
2087 break;
2088 } else {
2089 // copy non "--exec" arg
2090 Int len = VG_(strlen)(arg);
2091 VG_(memcpy)(cp, arg, len);
2092 cp += len;
2093 *cp++ = VG_CLO_SEP;
2094 }
2095 }
2096 // Add the new --exec= option
2097 execlen = VG_(strlen)(exec);
2098 VG_(memcpy)(cp, exec, execlen);
2099 cp += execlen;
2100 *cp++ = VG_CLO_SEP;
2101
2102 *cp = '\0';
2103
2104 return optvar;
2105}
2106
2107// Build "/proc/self/fd/<execfd>".
2108Char* VG_(build_child_exename)( void )
2109{
2110 Char* exename = VG_(arena_malloc)(VG_AR_CORE, 64);
2111 vg_assert(NULL != exename);
2112 VG_(sprintf)(exename, "/proc/self/fd/%d", vgexecfd);
2113 return exename;
2114}
2115
sewardjde4a1d02002-03-22 01:27:54 +00002116
nethercote71980f02004-01-24 18:18:54 +00002117/*====================================================================*/
2118/*=== File descriptor setup ===*/
2119/*====================================================================*/
2120
2121static void setup_file_descriptors(void)
2122{
2123 struct vki_rlimit rl;
2124
2125 /* Get the current file descriptor limits. */
2126 if (VG_(getrlimit)(VKI_RLIMIT_NOFILE, &rl) < 0) {
2127 rl.rlim_cur = 1024;
2128 rl.rlim_max = 1024;
2129 }
2130
2131 /* Work out where to move the soft limit to. */
2132 if (rl.rlim_cur + VG_N_RESERVED_FDS <= rl.rlim_max) {
2133 rl.rlim_cur = rl.rlim_cur + VG_N_RESERVED_FDS;
2134 } else {
2135 rl.rlim_cur = rl.rlim_max;
2136 }
2137
2138 /* Reserve some file descriptors for our use. */
thughesad1c9562004-06-26 11:27:52 +00002139 VG_(fd_soft_limit) = rl.rlim_cur - VG_N_RESERVED_FDS;
2140 VG_(fd_hard_limit) = rl.rlim_cur - VG_N_RESERVED_FDS;
nethercote71980f02004-01-24 18:18:54 +00002141
2142 /* Update the soft limit. */
2143 VG_(setrlimit)(VKI_RLIMIT_NOFILE, &rl);
2144
nethercotef6a1d502004-08-09 12:21:57 +00002145 if (vgexecfd != -1)
2146 vgexecfd = VG_(safe_fd)( vgexecfd );
nethercote71980f02004-01-24 18:18:54 +00002147 if (VG_(clexecfd) != -1)
2148 VG_(clexecfd) = VG_(safe_fd)( VG_(clexecfd) );
2149}
2150
2151
2152/*====================================================================*/
nethercote1d447092004-02-01 17:29:59 +00002153/*=== baseBlock: definition + setup ===*/
nethercote71980f02004-01-24 18:18:54 +00002154/*====================================================================*/
2155
nethercote71980f02004-01-24 18:18:54 +00002156Int VGOFF_(helper_undefined_instruction) = INVALID_OFFSET;
2157
2158/* MAX_NONCOMPACT_HELPERS can be increased easily. If MAX_COMPACT_HELPERS is
2159 * increased too much, they won't really be compact any more... */
2160#define MAX_COMPACT_HELPERS 8
2161#define MAX_NONCOMPACT_HELPERS 50
2162
nethercote81f9a6f2004-08-03 15:45:46 +00002163/* For storing tool-specific helpers, determined at runtime. The addr
2164 * and offset arrays together form a (addr, offset) map that allows a
2165 * helper's baseBlock offset to be computed from its address. It's done
2166 * like this so CCALLs can use the function address rather than having to
2167 * muck around with offsets. */
2168static UInt VG_(n_compact_helpers) = 0;
2169static UInt VG_(n_noncompact_helpers) = 0;
2170static Addr VG_(compact_helper_addrs) [MAX_COMPACT_HELPERS];
2171static Int VG_(compact_helper_offsets)[MAX_COMPACT_HELPERS];
2172static Addr VG_(noncompact_helper_addrs) [MAX_NONCOMPACT_HELPERS];
2173static Int VG_(noncompact_helper_offsets)[MAX_NONCOMPACT_HELPERS];
nethercote71980f02004-01-24 18:18:54 +00002174
2175/* This is the actual defn of baseblock. */
2176UInt VG_(baseBlock)[VG_BASEBLOCK_WORDS];
2177
nethercote71980f02004-01-24 18:18:54 +00002178/* Words. */
2179static Int baB_off = 0;
2180
2181
nethercote71980f02004-01-24 18:18:54 +00002182/* Returns the offset, in words. */
nethercote2e05c332004-09-06 16:43:37 +00002183Int VG_(alloc_BaB) ( Int words )
sewardjde4a1d02002-03-22 01:27:54 +00002184{
nethercote71980f02004-01-24 18:18:54 +00002185 Int off = baB_off;
2186 baB_off += words;
2187 if (baB_off >= VG_BASEBLOCK_WORDS)
nethercote2e05c332004-09-06 16:43:37 +00002188 VG_(core_panic)( "VG_(alloc_BaB): baseBlock is too small");
sewardjde4a1d02002-03-22 01:27:54 +00002189
nethercote71980f02004-01-24 18:18:54 +00002190 return off;
sewardjde4a1d02002-03-22 01:27:54 +00002191}
2192
nethercote71980f02004-01-24 18:18:54 +00002193/* Align offset, in *bytes* */
nethercote2e05c332004-09-06 16:43:37 +00002194void VG_(align_BaB) ( UInt align )
njn25e49d8e72002-09-23 09:36:25 +00002195{
nethercote71980f02004-01-24 18:18:54 +00002196 vg_assert(2 == align || 4 == align || 8 == align || 16 == align);
2197 baB_off += (align-1);
2198 baB_off &= ~(align-1);
njn25e49d8e72002-09-23 09:36:25 +00002199}
2200
nethercote71980f02004-01-24 18:18:54 +00002201/* Allocate 1 word in baseBlock and set it to the given value. */
nethercote2e05c332004-09-06 16:43:37 +00002202Int VG_(alloc_BaB_1_set) ( Addr a )
njn25e49d8e72002-09-23 09:36:25 +00002203{
nethercote2e05c332004-09-06 16:43:37 +00002204 Int off = VG_(alloc_BaB)(1);
nethercote71980f02004-01-24 18:18:54 +00002205 VG_(baseBlock)[off] = (UInt)a;
2206 return off;
njn25e49d8e72002-09-23 09:36:25 +00002207}
2208
nethercote71980f02004-01-24 18:18:54 +00002209/* Registers a function in compact_helper_addrs; compact_helper_offsets is
2210 filled in later. */
2211void VG_(register_compact_helper)(Addr a)
sewardjde4a1d02002-03-22 01:27:54 +00002212{
nethercote71980f02004-01-24 18:18:54 +00002213 if (MAX_COMPACT_HELPERS <= VG_(n_compact_helpers)) {
2214 VG_(printf)("Can only register %d compact helpers\n",
2215 MAX_COMPACT_HELPERS);
2216 VG_(core_panic)("Too many compact helpers registered");
2217 }
2218 VG_(compact_helper_addrs)[VG_(n_compact_helpers)] = a;
2219 VG_(n_compact_helpers)++;
2220}
2221
2222/* Registers a function in noncompact_helper_addrs; noncompact_helper_offsets
2223 * is filled in later.
2224 */
2225void VG_(register_noncompact_helper)(Addr a)
2226{
2227 if (MAX_NONCOMPACT_HELPERS <= VG_(n_noncompact_helpers)) {
2228 VG_(printf)("Can only register %d non-compact helpers\n",
2229 MAX_NONCOMPACT_HELPERS);
2230 VG_(printf)("Try increasing MAX_NON_COMPACT_HELPERS\n");
2231 VG_(core_panic)("Too many non-compact helpers registered");
2232 }
2233 VG_(noncompact_helper_addrs)[VG_(n_noncompact_helpers)] = a;
2234 VG_(n_noncompact_helpers)++;
2235}
2236
nethercote996901a2004-08-03 13:29:09 +00002237/* Allocate offsets in baseBlock for the tool helpers */
nethercote71980f02004-01-24 18:18:54 +00002238static
2239void assign_helpers_in_baseBlock(UInt n, Int offsets[], Addr addrs[])
2240{
2241 UInt i;
2242 for (i = 0; i < n; i++)
nethercote2e05c332004-09-06 16:43:37 +00002243 offsets[i] = VG_(alloc_BaB_1_set)( addrs[i] );
nethercote71980f02004-01-24 18:18:54 +00002244}
2245
2246Bool VG_(need_to_handle_esp_assignment)(void)
2247{
2248 return ( VG_(defined_new_mem_stack_4)() ||
2249 VG_(defined_die_mem_stack_4)() ||
2250 VG_(defined_new_mem_stack_8)() ||
2251 VG_(defined_die_mem_stack_8)() ||
2252 VG_(defined_new_mem_stack_12)() ||
2253 VG_(defined_die_mem_stack_12)() ||
2254 VG_(defined_new_mem_stack_16)() ||
2255 VG_(defined_die_mem_stack_16)() ||
2256 VG_(defined_new_mem_stack_32)() ||
2257 VG_(defined_die_mem_stack_32)() ||
2258 VG_(defined_new_mem_stack)() ||
2259 VG_(defined_die_mem_stack)()
2260 );
2261}
2262
nethercote2e05c332004-09-06 16:43:37 +00002263// The low/high split is for x86, so that the more common helpers can be
2264// in the first 128 bytes of the start, which allows the use of a more
2265// compact addressing mode.
nethercote71980f02004-01-24 18:18:54 +00002266static void init_baseBlock ( Addr client_eip, Addr esp_at_startup )
2267{
nethercote2e05c332004-09-06 16:43:37 +00002268 VGA_(init_low_baseBlock)(client_eip, esp_at_startup);
nethercote71980f02004-01-24 18:18:54 +00002269
nethercote71980f02004-01-24 18:18:54 +00002270 /* Allocate slots for compact helpers */
2271 assign_helpers_in_baseBlock(VG_(n_compact_helpers),
2272 VG_(compact_helper_offsets),
2273 VG_(compact_helper_addrs));
2274
nethercote2e05c332004-09-06 16:43:37 +00002275 VGA_(init_high_baseBlock)(client_eip, esp_at_startup);
fitzhardingef0046f22003-12-18 02:39:22 +00002276
nethercote71980f02004-01-24 18:18:54 +00002277#define REG(kind, size) \
2278 if (VG_(defined_##kind##_mem_stack##size)()) \
2279 VG_(register_noncompact_helper)( \
2280 (Addr) VG_(tool_interface).track_##kind##_mem_stack##size );
2281 REG(new, _8);
2282 REG(new, _12);
2283 REG(new, _16);
2284 REG(new, _32);
2285 REG(new, );
2286 REG(die, _8);
2287 REG(die, _12);
2288 REG(die, _16);
2289 REG(die, _32);
2290 REG(die, );
2291#undef REG
fitzhardingef0046f22003-12-18 02:39:22 +00002292
nethercote71980f02004-01-24 18:18:54 +00002293 if (VG_(need_to_handle_esp_assignment)())
2294 VG_(register_noncompact_helper)((Addr) VG_(unknown_esp_update));
fitzhardingeb791a192003-12-18 07:22:44 +00002295
nethercote2e05c332004-09-06 16:43:37 +00002296 VGOFF_(helper_undefined_instruction)
2297 = VG_(alloc_BaB_1_set)( (Addr) & VG_(helper_undefined_instruction));
sewardjde4a1d02002-03-22 01:27:54 +00002298
nethercote71980f02004-01-24 18:18:54 +00002299 /* Allocate slots for noncompact helpers */
2300 assign_helpers_in_baseBlock(VG_(n_noncompact_helpers),
2301 VG_(noncompact_helper_offsets),
2302 VG_(noncompact_helper_addrs));
2303}
sewardjde4a1d02002-03-22 01:27:54 +00002304
nethercote81f9a6f2004-08-03 15:45:46 +00002305// Finds the baseBlock offset of a tool-specified helper.
2306// Searches through compacts first, then non-compacts.
2307Int VG_(helper_offset)(Addr a)
2308{
2309 UInt i;
2310 Char buf[100];
2311
2312 for (i = 0; i < VG_(n_compact_helpers); i++)
2313 if (VG_(compact_helper_addrs)[i] == a)
2314 return VG_(compact_helper_offsets)[i];
2315 for (i = 0; i < VG_(n_noncompact_helpers); i++)
2316 if (VG_(noncompact_helper_addrs)[i] == a)
2317 return VG_(noncompact_helper_offsets)[i];
2318
2319 /* Shouldn't get here */
2320 VG_(get_fnname) ( a, buf, 100 );
2321
2322 VG_(printf)(
2323 "\nCouldn't find offset of helper from its address (%p: %s).\n"
2324 "A helper function probably used hasn't been registered?\n\n", a, buf);
2325
2326 VG_(printf)(" compact helpers: ");
2327 for (i = 0; i < VG_(n_compact_helpers); i++)
2328 VG_(printf)("%p ", VG_(compact_helper_addrs)[i]);
2329
2330 VG_(printf)("\n non-compact helpers: ");
2331 for (i = 0; i < VG_(n_noncompact_helpers); i++)
2332 VG_(printf)("%p ", VG_(noncompact_helper_addrs)[i]);
2333
2334 VG_(printf)("\n");
2335 VG_(skin_panic)("Unfound helper");
2336}
2337
sewardj5f07b662002-04-23 16:52:51 +00002338
nethercote71980f02004-01-24 18:18:54 +00002339/*====================================================================*/
nethercote71980f02004-01-24 18:18:54 +00002340/*=== Initialise program data/text, etc. ===*/
2341/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +00002342
nethercote71980f02004-01-24 18:18:54 +00002343static void build_valgrind_map_callback
2344 ( Addr start, UInt size, Char rr, Char ww, Char xx,
2345 UInt dev, UInt ino, ULong foffset, const UChar* filename )
sewardjde4a1d02002-03-22 01:27:54 +00002346{
nethercote71980f02004-01-24 18:18:54 +00002347 UInt prot = 0;
2348 UInt flags = SF_MMAP|SF_NOSYMS;
2349 Bool is_stack_segment;
2350
2351 is_stack_segment =
2352 (start == VG_(clstk_base) && (start+size) == VG_(clstk_end));
2353
2354 /* Only record valgrind mappings for now, without loading any
2355 symbols. This is so we know where the free space is before we
2356 start allocating more memory (note: heap is OK, it's just mmap
2357 which is the problem here). */
nethercote820bd8c2004-09-07 23:04:49 +00002358 if (start >= VG_(valgrind_base) && (start+size-1) <= VG_(valgrind_last)) {
nethercote71980f02004-01-24 18:18:54 +00002359 flags |= SF_VALGRIND;
2360 VG_(map_file_segment)(start, size, prot, flags, dev, ino, foffset, filename);
2361 }
sewardjde4a1d02002-03-22 01:27:54 +00002362}
2363
nethercote71980f02004-01-24 18:18:54 +00002364// Global var used to pass local data to callback
2365Addr esp_at_startup___global_arg = 0;
sewardjde4a1d02002-03-22 01:27:54 +00002366
nethercote71980f02004-01-24 18:18:54 +00002367static void build_segment_map_callback
2368 ( Addr start, UInt size, Char rr, Char ww, Char xx,
2369 UInt dev, UInt ino, ULong foffset, const UChar* filename )
sewardj45b672d2003-07-25 19:58:11 +00002370{
nethercote71980f02004-01-24 18:18:54 +00002371 UInt prot = 0;
2372 UInt flags;
2373 Bool is_stack_segment;
2374 Addr r_esp;
sewardj45b672d2003-07-25 19:58:11 +00002375
nethercote71980f02004-01-24 18:18:54 +00002376 is_stack_segment
2377 = (start == VG_(clstk_base) && (start+size) == VG_(clstk_end));
fitzhardinge98abfc72003-12-16 02:05:15 +00002378
nethercote71980f02004-01-24 18:18:54 +00002379 if (rr == 'r') prot |= VKI_PROT_READ;
2380 if (ww == 'w') prot |= VKI_PROT_WRITE;
2381 if (xx == 'x') prot |= VKI_PROT_EXEC;
fitzhardinge98abfc72003-12-16 02:05:15 +00002382
nethercote71980f02004-01-24 18:18:54 +00002383 if (is_stack_segment)
2384 flags = SF_STACK | SF_GROWDOWN;
2385 else
2386 flags = SF_EXEC|SF_MMAP;
fitzhardinge98abfc72003-12-16 02:05:15 +00002387
nethercote71980f02004-01-24 18:18:54 +00002388 if (filename != NULL)
2389 flags |= SF_FILE;
fitzhardinge98abfc72003-12-16 02:05:15 +00002390
nethercote820bd8c2004-09-07 23:04:49 +00002391 if (start >= VG_(valgrind_base) && (start+size-1) <= VG_(valgrind_last))
nethercote71980f02004-01-24 18:18:54 +00002392 flags |= SF_VALGRIND;
fitzhardinge98abfc72003-12-16 02:05:15 +00002393
nethercote71980f02004-01-24 18:18:54 +00002394 VG_(map_file_segment)(start, size, prot, flags, dev, ino, foffset, filename);
fitzhardinge98abfc72003-12-16 02:05:15 +00002395
nethercote71980f02004-01-24 18:18:54 +00002396 if (VG_(is_client_addr)(start) && VG_(is_client_addr)(start+size-1))
2397 VG_TRACK( new_mem_startup, start, size, rr=='r', ww=='w', xx=='x' );
sewardj3e1eb1f2002-05-18 13:14:17 +00002398
nethercote71980f02004-01-24 18:18:54 +00002399 /* If this is the stack segment mark all below %esp as noaccess. */
2400 r_esp = esp_at_startup___global_arg;
2401 vg_assert(0 != r_esp);
2402 if (is_stack_segment) {
2403 if (0)
2404 VG_(message)(Vg_DebugMsg, "invalidating stack area: %x .. %x",
2405 start,r_esp);
2406 VG_TRACK( die_mem_stack, start, r_esp-start );
sewardjde4a1d02002-03-22 01:27:54 +00002407 }
sewardjde4a1d02002-03-22 01:27:54 +00002408}
2409
2410
nethercote71980f02004-01-24 18:18:54 +00002411/*====================================================================*/
2412/*=== Sanity check machinery (permanently engaged) ===*/
2413/*====================================================================*/
njn25e49d8e72002-09-23 09:36:25 +00002414
2415/* A fast sanity check -- suitable for calling circa once per
2416 millisecond. */
2417
nethercote885dd912004-08-03 23:14:00 +00002418void VG_(sanity_check_general) ( Bool force_expensive )
njn25e49d8e72002-09-23 09:36:25 +00002419{
njn37cea302002-09-30 11:24:00 +00002420 VGP_PUSHCC(VgpCoreCheapSanity);
2421
nethercote27fec902004-06-16 21:26:32 +00002422 if (VG_(clo_sanity_level) < 1) return;
njn25e49d8e72002-09-23 09:36:25 +00002423
2424 /* --- First do all the tests that we can do quickly. ---*/
2425
nethercote297effd2004-08-02 15:07:57 +00002426 sanity_fast_count++;
njn25e49d8e72002-09-23 09:36:25 +00002427
njn25e49d8e72002-09-23 09:36:25 +00002428 /* Check stuff pertaining to the memory check system. */
2429
2430 /* Check that nobody has spuriously claimed that the first or
2431 last 16 pages of memory have become accessible [...] */
njn37cea302002-09-30 11:24:00 +00002432 if (VG_(needs).sanity_checks) {
2433 VGP_PUSHCC(VgpSkinCheapSanity);
njn25e49d8e72002-09-23 09:36:25 +00002434 vg_assert(SK_(cheap_sanity_check)());
njn37cea302002-09-30 11:24:00 +00002435 VGP_POPCC(VgpSkinCheapSanity);
2436 }
njn25e49d8e72002-09-23 09:36:25 +00002437
2438 /* --- Now some more expensive checks. ---*/
2439
2440 /* Once every 25 times, check some more expensive stuff. */
2441 if ( force_expensive
nethercote27fec902004-06-16 21:26:32 +00002442 || VG_(clo_sanity_level) > 1
nethercote297effd2004-08-02 15:07:57 +00002443 || (VG_(clo_sanity_level) == 1 && (sanity_fast_count % 25) == 0)) {
njn25e49d8e72002-09-23 09:36:25 +00002444
njn37cea302002-09-30 11:24:00 +00002445 VGP_PUSHCC(VgpCoreExpensiveSanity);
nethercote297effd2004-08-02 15:07:57 +00002446 sanity_slow_count++;
njn25e49d8e72002-09-23 09:36:25 +00002447
nethercote885dd912004-08-03 23:14:00 +00002448 VG_(sanity_check_proxy)();
jsgf855d93d2003-10-13 22:26:55 +00002449
njn25e49d8e72002-09-23 09:36:25 +00002450# if 0
2451 { void zzzmemscan(void); zzzmemscan(); }
2452# endif
2453
nethercote297effd2004-08-02 15:07:57 +00002454 if ((sanity_fast_count % 250) == 0)
nethercote92e7b7f2004-08-07 17:52:25 +00002455 VG_(sanity_check_tt_tc)();
njn25e49d8e72002-09-23 09:36:25 +00002456
2457 if (VG_(needs).sanity_checks) {
njn37cea302002-09-30 11:24:00 +00002458 VGP_PUSHCC(VgpSkinExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002459 vg_assert(SK_(expensive_sanity_check)());
njn37cea302002-09-30 11:24:00 +00002460 VGP_POPCC(VgpSkinExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002461 }
2462 /*
nethercote297effd2004-08-02 15:07:57 +00002463 if ((sanity_fast_count % 500) == 0) VG_(mallocSanityCheckAll)();
njn25e49d8e72002-09-23 09:36:25 +00002464 */
njn37cea302002-09-30 11:24:00 +00002465 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002466 }
2467
nethercote27fec902004-06-16 21:26:32 +00002468 if (VG_(clo_sanity_level) > 1) {
njn37cea302002-09-30 11:24:00 +00002469 VGP_PUSHCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002470 /* Check sanity of the low-level memory manager. Note that bugs
2471 in the client's code can cause this to fail, so we don't do
2472 this check unless specially asked for. And because it's
2473 potentially very expensive. */
nethercote885dd912004-08-03 23:14:00 +00002474 VG_(sanity_check_malloc_all)();
njn37cea302002-09-30 11:24:00 +00002475 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002476 }
njn37cea302002-09-30 11:24:00 +00002477 VGP_POPCC(VgpCoreCheapSanity);
njn25e49d8e72002-09-23 09:36:25 +00002478}
nethercote71980f02004-01-24 18:18:54 +00002479
2480
2481/*====================================================================*/
2482/*=== main() ===*/
2483/*====================================================================*/
2484
nethercotec314eba2004-07-15 12:59:41 +00002485/*
2486 This code decides on the layout of the client and Valgrind address
nethercote996901a2004-08-03 13:29:09 +00002487 spaces, loads valgrind.so and the tool.so into the valgrind part,
nethercotec314eba2004-07-15 12:59:41 +00002488 loads the client executable (and the dynamic linker, if necessary)
2489 into the client part, and calls into Valgrind proper.
2490
2491 The code is careful not to allow spurious mappings to appear in the
2492 wrong parts of the address space. In particular, to make sure
2493 dlopen puts things in the right place, it will pad out the forbidden
2494 chunks of address space so that dlopen is forced to put things where
2495 we want them.
2496
2497 The memory map it creates is:
2498
2499 CLIENT_BASE +-------------------------+
2500 | client address space |
2501 : :
2502 : :
2503 | client stack |
2504 client_end +-------------------------+
2505 | redzone |
2506 shadow_base +-------------------------+
2507 | |
nethercote996901a2004-08-03 13:29:09 +00002508 : shadow memory for tools :
nethercotec314eba2004-07-15 12:59:41 +00002509 | (may be 0 sized) |
2510 shadow_end +-------------------------+
nethercotec314eba2004-07-15 12:59:41 +00002511 valgrind_base +-------------------------+
2512 | kickstart executable |
2513 | valgrind heap vvvvvvvvv| (barely used)
2514 - -
2515 | valgrind .so files |
2516 | and mappings |
2517 - -
2518 | valgrind stack ^^^^^^^^^|
nethercote820bd8c2004-09-07 23:04:49 +00002519 valgrind_last +-------------------------+
nethercotec314eba2004-07-15 12:59:41 +00002520 : kernel :
2521
2522 Nb: Before we can do general allocations with VG_(arena_malloc)() and
2523 VG_(mmap)(), we need to build the segment skip-list, so we know where
2524 we can put things. However, building that structure requires
2525 allocating memory. So we need to a bootstrapping process. It's done
2526 by making VG_(arena_malloc)() have a special static superblock that's
2527 used for the first 1MB's worth of allocations. This is enough to
2528 build the segment skip-list.
2529*/
2530
nethercote31779c72004-07-30 21:50:15 +00002531static int prmap(char *start, char *end, const char *perm, off_t off,
2532 int maj, int min, int ino, void* dummy) {
thughes4ad52d02004-06-27 17:37:21 +00002533 printf("mapping %10p-%10p %s %02x:%02x %d\n",
2534 start, end, perm, maj, min, ino);
2535 return True;
2536}
2537
nethercote71980f02004-01-24 18:18:54 +00002538int main(int argc, char **argv)
2539{
2540 char **cl_argv;
2541 const char *tool = NULL;
2542 const char *exec = NULL;
2543 char *preload; /* tool-specific LD_PRELOAD .so */
2544 char **env;
nethercote6c999f22004-01-31 22:55:15 +00002545 Int need_help = 0; // 0 = no, 1 = --help, 2 = --help-debug
nethercote71980f02004-01-24 18:18:54 +00002546 struct exeinfo info;
2547 ToolInfo *toolinfo = NULL;
2548 void *tool_dlhandle;
2549 Addr client_eip;
2550 Addr esp_at_startup; /* client's %esp at the point we gained control. */
2551 UInt * client_auxv;
2552 VgSchedReturnCode src;
nethercote47dd12c2004-06-22 14:18:42 +00002553 Int exitcode = 0;
nethercote238a3c32004-08-09 13:13:31 +00002554 Int fatal_sigNo = -1;
fitzhardingeb50068f2004-02-24 23:42:55 +00002555 vki_rlimit zero = { 0, 0 };
nethercote31779c72004-07-30 21:50:15 +00002556 Int padfile;
nethercote759dda32004-08-07 18:16:56 +00002557 ThreadId last_run_tid = 0; // Last thread the scheduler ran.
2558
nethercote71980f02004-01-24 18:18:54 +00002559
2560 //============================================================
2561 // Nb: startup is complex. Prerequisites are shown at every step.
2562 //
2563 // *** Be very careful when messing with the order ***
2564 //============================================================
2565
nethercotef4928da2004-06-15 10:54:40 +00002566 //============================================================
2567 // Command line argument handling order:
2568 // * If --help/--help-debug are present, show usage message
2569 // (if --tool is also present, that includes the tool-specific usage)
2570 // * Then, if --tool is missing, abort with error msg
2571 // * Then, if client is missing, abort with error msg
2572 // * Then, if any cmdline args are bad, abort with error msg
2573 //============================================================
2574
fitzhardingeb50068f2004-02-24 23:42:55 +00002575 // Get the current process datasize rlimit, and set it to zero.
2576 // This prevents any internal uses of brk() from having any effect.
2577 // We remember the old value so we can restore it on exec, so that
2578 // child processes will have a reasonable brk value.
2579 VG_(getrlimit)(VKI_RLIMIT_DATA, &VG_(client_rlimit_data));
2580 zero.rlim_max = VG_(client_rlimit_data).rlim_max;
2581 VG_(setrlimit)(VKI_RLIMIT_DATA, &zero);
thughesc37184f2004-09-11 14:16:57 +00002582
2583 // Get the current process stack rlimit.
2584 VG_(getrlimit)(VKI_RLIMIT_STACK, &VG_(client_rlimit_stack));
2585
nethercote71980f02004-01-24 18:18:54 +00002586 //--------------------------------------------------------------
2587 // Check we were launched by stage1
nethercotec314eba2004-07-15 12:59:41 +00002588 // p: n/a
nethercote71980f02004-01-24 18:18:54 +00002589 //--------------------------------------------------------------
nethercotec25c4492004-10-18 11:52:17 +00002590 {
2591 void* init_sp = argv - 1;
2592 padfile = scan_auxv(init_sp);
2593 }
nethercote71980f02004-01-24 18:18:54 +00002594
2595 if (0) {
nethercote71980f02004-01-24 18:18:54 +00002596 printf("========== main() ==========\n");
nethercote31779c72004-07-30 21:50:15 +00002597 foreach_map(prmap, /*dummy*/NULL);
nethercote71980f02004-01-24 18:18:54 +00002598 }
2599
2600 //--------------------------------------------------------------
2601 // Look for alternative libdir
2602 // p: n/a
2603 //--------------------------------------------------------------
2604 { char *cp = getenv(VALGRINDLIB);
2605 if (cp != NULL)
2606 VG_(libdir) = cp;
2607 }
2608
2609 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002610 // Get valgrind args + client args (inc. from VALGRIND_OPTS/.valgrindrc).
2611 // Pre-process the command line.
2612 // p: n/a
2613 //--------------------------------------------------------------
nethercotef6a1d502004-08-09 12:21:57 +00002614 get_command_line(argc, argv, &vg_argc, &vg_argv, &cl_argv);
nethercote71980f02004-01-24 18:18:54 +00002615 pre_process_cmd_line_options(&need_help, &tool, &exec);
2616
2617 //==============================================================
2618 // Nb: once a tool is specified, the tool.so must be loaded even if
2619 // they specified --help or didn't specify a client program.
2620 //==============================================================
2621
2622 //--------------------------------------------------------------
2623 // With client padded out, map in tool
nethercote71980f02004-01-24 18:18:54 +00002624 // p: set-libdir [for VG_(libdir)]
2625 // p: pre_process_cmd_line_options() [for 'tool']
2626 //--------------------------------------------------------------
2627 load_tool(tool, &tool_dlhandle, &toolinfo, &preload);
2628
2629 //==============================================================
2630 // Can use VG_(malloc)() and VG_(arena_malloc)() only after load_tool()
nethercotec314eba2004-07-15 12:59:41 +00002631 // -- redzone size is now set. This is checked by vg_malloc2.c.
nethercote71980f02004-01-24 18:18:54 +00002632 //==============================================================
2633
2634 //--------------------------------------------------------------
2635 // Finalise address space layout
nethercote31779c72004-07-30 21:50:15 +00002636 // p: load_tool() [for 'toolinfo']
nethercote71980f02004-01-24 18:18:54 +00002637 //--------------------------------------------------------------
nethercote31779c72004-07-30 21:50:15 +00002638 layout_remaining_space( (Addr) & argc, toolinfo->shadow_ratio );
nethercote71980f02004-01-24 18:18:54 +00002639
2640 //--------------------------------------------------------------
2641 // Load client executable, finding in $PATH if necessary
nethercote71980f02004-01-24 18:18:54 +00002642 // p: pre_process_cmd_line_options() [for 'exec', 'need_help']
2643 // p: layout_remaining_space [so there's space]
2644 //--------------------------------------------------------------
nethercotef4928da2004-06-15 10:54:40 +00002645 load_client(cl_argv, exec, need_help, &info, &client_eip);
nethercote71980f02004-01-24 18:18:54 +00002646
2647 //--------------------------------------------------------------
nethercote969ecf12004-10-13 17:29:01 +00002648 // Everything in place, remove padding done by stage1
nethercote71980f02004-01-24 18:18:54 +00002649 // p: layout_remaining_space() [everything must be mapped in before now]
2650 // p: load_client() [ditto]
2651 //--------------------------------------------------------------
nethercote31779c72004-07-30 21:50:15 +00002652 as_unpad((void *)VG_(shadow_end), (void *)~0, padfile);
2653 as_closepadfile(padfile); // no more padding
nethercote71980f02004-01-24 18:18:54 +00002654
2655 //--------------------------------------------------------------
2656 // Set up client's environment
2657 // p: set-libdir [for VG_(libdir)]
2658 // p: load_tool() [for 'preload']
2659 //--------------------------------------------------------------
2660 env = fix_environment(environ, preload);
2661
2662 //--------------------------------------------------------------
nethercote5ee67ca2004-06-22 14:00:09 +00002663 // Setup client stack, eip, and VG_(client_arg[cv])
nethercote71980f02004-01-24 18:18:54 +00002664 // p: load_client() [for 'info']
2665 // p: fix_environment() [for 'env']
2666 //--------------------------------------------------------------
nethercotec25c4492004-10-18 11:52:17 +00002667 {
2668 void* init_sp = argv - 1;
2669 esp_at_startup = setup_client_stack(init_sp, cl_argv, env, &info,
2670 &client_auxv);
2671 }
nethercote71980f02004-01-24 18:18:54 +00002672
2673 if (0)
nethercote6a27d832004-09-07 10:17:02 +00002674 printf("entry=%p client esp=%p vg_argc=%d brkbase=%p\n",
2675 (void*)client_eip, (void*)esp_at_startup, vg_argc,
2676 (void*)VG_(brk_base));
nethercote71980f02004-01-24 18:18:54 +00002677
2678 //==============================================================
2679 // Finished setting up operating environment. Now initialise
2680 // Valgrind. (This is where the old VG_(main)() started.)
2681 //==============================================================
2682
2683 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002684 // atfork
2685 // p: n/a
2686 //--------------------------------------------------------------
2687 VG_(atfork)(NULL, NULL, newpid);
2688 newpid(VG_INVALID_THREADID);
2689
2690 //--------------------------------------------------------------
2691 // setup file descriptors
2692 // p: n/a
2693 //--------------------------------------------------------------
2694 setup_file_descriptors();
2695
2696 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002697 // Read /proc/self/maps into a buffer
2698 // p: all memory layout, environment setup [so memory maps are right]
2699 //--------------------------------------------------------------
2700 VG_(read_procselfmaps)();
2701
2702 //--------------------------------------------------------------
2703 // Build segment map (Valgrind segments only)
2704 // p: read proc/self/maps
2705 // p: sk_pre_clo_init() [to setup new_mem_startup tracker]
2706 //--------------------------------------------------------------
2707 VG_(parse_procselfmaps) ( build_valgrind_map_callback );
2708
2709 //==============================================================
2710 // Can use VG_(arena_malloc)() with non-CORE arena after segments set up
2711 //==============================================================
2712
2713 //--------------------------------------------------------------
2714 // Init tool: pre_clo_init, process cmd line, post_clo_init
2715 // p: setup_client_stack() [for 'VG_(client_arg[cv]']
2716 // p: load_tool() [for 'tool']
2717 // p: setup_file_descriptors() [for 'VG_(fd_xxx_limit)']
2718 // p: parse_procselfmaps [so VG segments are setup so tool can
2719 // call VG_(malloc)]
nethercote71980f02004-01-24 18:18:54 +00002720 //--------------------------------------------------------------
2721 (*toolinfo->sk_pre_clo_init)();
2722 VG_(tool_init_dlsym)(tool_dlhandle);
2723 VG_(sanity_check_needs)();
2724
nethercotef4928da2004-06-15 10:54:40 +00002725 // If --tool and --help/--help-debug was given, now give the core+tool
2726 // help message
nethercotef4928da2004-06-15 10:54:40 +00002727 if (need_help) {
2728 usage(/*--help-debug?*/2 == need_help);
2729 }
nethercotec314eba2004-07-15 12:59:41 +00002730 process_cmd_line_options(client_auxv, tool);
2731
2732 SK_(post_clo_init)();
nethercotef4928da2004-06-15 10:54:40 +00002733
2734 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002735 // Build segment map (all segments)
2736 // p: setup_client_stack() [for 'esp_at_startup']
2737 // p: init tool [for 'new_mem_startup']
nethercote71980f02004-01-24 18:18:54 +00002738 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002739 esp_at_startup___global_arg = esp_at_startup;
2740 VG_(parse_procselfmaps) ( build_segment_map_callback ); /* everything */
2741 esp_at_startup___global_arg = 0;
2742
2743 //--------------------------------------------------------------
nethercotef84f6952004-07-15 14:58:33 +00002744 // Protect client trampoline page (which is also sysinfo stuff)
2745 // p: segment stuff [otherwise get seg faults...]
nethercotec314eba2004-07-15 12:59:41 +00002746 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002747 VG_(mprotect)( (void *)VG_(client_trampoline_code),
2748 VG_(trampoline_code_length), VKI_PROT_READ|VKI_PROT_EXEC );
2749
2750 //==============================================================
2751 // Can use VG_(map)() after segments set up
2752 //==============================================================
nethercote71980f02004-01-24 18:18:54 +00002753
2754 //--------------------------------------------------------------
2755 // Allow GDB attach
2756 // p: process_cmd_line_options() [for VG_(clo_wait_for_gdb)]
2757 //--------------------------------------------------------------
2758 /* Hook to delay things long enough so we can get the pid and
2759 attach GDB in another shell. */
2760 if (VG_(clo_wait_for_gdb)) {
2761 VG_(printf)("pid=%d\n", VG_(getpid)());
2762 /* do "jump *$eip" to skip this in gdb */
2763 VG_(do_syscall)(__NR_pause);
2764 }
2765
2766 //--------------------------------------------------------------
nethercote1d447092004-02-01 17:29:59 +00002767 // Set up baseBlock
nethercote71980f02004-01-24 18:18:54 +00002768 // p: {pre,post}_clo_init() [for tool helper registration]
2769 // load_client() [for 'client_eip']
2770 // setup_client_stack() [for 'esp_at_startup']
2771 //--------------------------------------------------------------
2772 init_baseBlock(client_eip, esp_at_startup);
2773
2774 //--------------------------------------------------------------
2775 // Search for file descriptors that are inherited from our parent
2776 // p: process_cmd_line_options [for VG_(clo_track_fds)]
2777 //--------------------------------------------------------------
2778 if (VG_(clo_track_fds))
2779 VG_(init_preopened_fds)();
2780
2781 //--------------------------------------------------------------
2782 // Initialise the scheduler
2783 // p: init_baseBlock() [baseBlock regs copied into VG_(threads)[1]]
2784 // p: setup_file_descriptors() [else VG_(safe_fd)() breaks]
2785 //--------------------------------------------------------------
2786 VG_(scheduler_init)();
2787
2788 //--------------------------------------------------------------
2789 // Set up the ProxyLWP machinery
2790 // p: VG_(scheduler_init)()? [XXX: subtle dependency?]
nethercote71980f02004-01-24 18:18:54 +00002791 //--------------------------------------------------------------
2792 VG_(proxy_init)();
2793
2794 //--------------------------------------------------------------
2795 // Initialise the signal handling subsystem
2796 // p: VG_(atfork)(NULL, NULL, newpid) [else problems with sigmasks]
2797 // p: VG_(proxy_init)() [else breaks...]
2798 //--------------------------------------------------------------
2799 // Nb: temporarily parks the saved blocking-mask in saved_sigmask.
2800 VG_(sigstartup_actions)();
2801
2802 //--------------------------------------------------------------
2803 // Perhaps we're profiling Valgrind?
2804 // p: process_cmd_line_options() [for VG_(clo_profile)]
2805 // p: others?
2806 //
2807 // XXX: this seems to be broken? It always says the tool wasn't built
2808 // for profiling; vg_profile.c's functions don't seem to be overriding
2809 // vg_dummy_profile.c's?
2810 //
2811 // XXX: want this as early as possible. Looking for --profile
2812 // in pre_process_cmd_line_options() could get it earlier.
2813 //--------------------------------------------------------------
2814 if (VG_(clo_profile))
2815 VGP_(init_profiling)();
2816
2817 VGP_PUSHCC(VgpStartup);
2818
2819 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002820 // Read suppression file
2821 // p: process_cmd_line_options() [for VG_(clo_suppressions)]
2822 //--------------------------------------------------------------
2823 if (VG_(needs).core_errors || VG_(needs).skin_errors)
2824 VG_(load_suppressions)();
2825
2826 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002827 // Initialise translation table and translation cache
2828 // p: read_procselfmaps [so the anonymous mmaps for the TT/TC
2829 // aren't identified as part of the client, which would waste
2830 // > 20M of virtual address space.]
2831 //--------------------------------------------------------------
2832 VG_(init_tt_tc)();
2833
2834 //--------------------------------------------------------------
2835 // Read debug info to find glibc entry points to intercept
2836 // p: parse_procselfmaps? [XXX for debug info?]
2837 // p: init_tt_tc? [XXX ???]
2838 //--------------------------------------------------------------
2839 VG_(setup_code_redirect_table)();
2840
2841 //--------------------------------------------------------------
2842 // Verbosity message
2843 // p: end_rdtsc_calibration [so startup message is printed first]
2844 //--------------------------------------------------------------
2845 if (VG_(clo_verbosity) == 1)
2846 VG_(message)(Vg_UserMsg, "For more details, rerun with: -v");
2847 if (VG_(clo_verbosity) > 0)
2848 VG_(message)(Vg_UserMsg, "");
2849
2850 //--------------------------------------------------------------
2851 // Setup pointercheck
2852 // p: process_cmd_line_options() [for VG_(clo_pointercheck)]
2853 //--------------------------------------------------------------
nethercote775508a2004-09-07 22:38:23 +00002854 if (VG_(clo_pointercheck))
2855 VG_(clo_pointercheck) = VGA_(setup_pointercheck)();
nethercote71980f02004-01-24 18:18:54 +00002856
nethercote71980f02004-01-24 18:18:54 +00002857 //--------------------------------------------------------------
2858 // Run!
2859 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002860 VGP_POPCC(VgpStartup);
2861 VGP_PUSHCC(VgpSched);
2862
nethercote238a3c32004-08-09 13:13:31 +00002863 src = VG_(scheduler)( &exitcode, &last_run_tid, &fatal_sigNo );
nethercote71980f02004-01-24 18:18:54 +00002864
nethercote238a3c32004-08-09 13:13:31 +00002865 VGP_POPCC(VgpSched);
nethercote71980f02004-01-24 18:18:54 +00002866
2867
2868 //--------------------------------------------------------------
2869 // Finalisation: cleanup, messages, etc. Order no so important, only
2870 // affects what order the messages come.
2871 //--------------------------------------------------------------
2872 if (VG_(clo_verbosity) > 0)
2873 VG_(message)(Vg_UserMsg, "");
2874
2875 if (src == VgSrc_Deadlock) {
2876 VG_(message)(Vg_UserMsg,
2877 "Warning: pthread scheduler exited due to deadlock");
2878 }
2879
2880 /* Print out file descriptor summary and stats. */
2881 if (VG_(clo_track_fds))
nethercote3a42fb82004-08-03 18:08:50 +00002882 VG_(show_open_fds)();
nethercote71980f02004-01-24 18:18:54 +00002883
2884 if (VG_(needs).core_errors || VG_(needs).skin_errors)
2885 VG_(show_all_errors)();
2886
nethercote47dd12c2004-06-22 14:18:42 +00002887 SK_(fini)( exitcode );
nethercote71980f02004-01-24 18:18:54 +00002888
nethercote885dd912004-08-03 23:14:00 +00002889 VG_(sanity_check_general)( True /*include expensive checks*/ );
nethercote71980f02004-01-24 18:18:54 +00002890
2891 if (VG_(clo_verbosity) > 1)
nethercote3a42fb82004-08-03 18:08:50 +00002892 print_all_stats();
nethercote71980f02004-01-24 18:18:54 +00002893
nethercote71980f02004-01-24 18:18:54 +00002894 if (VG_(clo_profile))
2895 VGP_(done_profiling)();
2896
nethercote71980f02004-01-24 18:18:54 +00002897 /* We're exiting, so nuke all the threads and clean up the proxy LWPs */
2898 vg_assert(src == VgSrc_FatalSig ||
nethercote759dda32004-08-07 18:16:56 +00002899 VG_(threads)[last_run_tid].status == VgTs_Runnable ||
2900 VG_(threads)[last_run_tid].status == VgTs_WaitJoiner);
nethercote71980f02004-01-24 18:18:54 +00002901 VG_(nuke_all_threads_except)(VG_INVALID_THREADID);
2902
2903 //--------------------------------------------------------------
2904 // Exit, according to the scheduler's return code
2905 //--------------------------------------------------------------
2906 switch (src) {
2907 case VgSrc_ExitSyscall: /* the normal way out */
nethercote759dda32004-08-07 18:16:56 +00002908 vg_assert(last_run_tid > 0 && last_run_tid < VG_N_THREADS);
nethercote71980f02004-01-24 18:18:54 +00002909 VG_(proxy_shutdown)();
2910
2911 /* The thread's %EBX at the time it did __NR_exit() will hold
2912 the arg to __NR_exit(), so we just do __NR_exit() with
2913 that arg. */
nethercote47dd12c2004-06-22 14:18:42 +00002914 VG_(exit)( exitcode );
nethercote71980f02004-01-24 18:18:54 +00002915 /* NOT ALIVE HERE! */
2916 VG_(core_panic)("entered the afterlife in main() -- ExitSyscall");
2917 break; /* what the hell :) */
2918
2919 case VgSrc_Deadlock:
2920 /* Just exit now. No point in continuing. */
2921 VG_(proxy_shutdown)();
2922 VG_(exit)(0);
2923 VG_(core_panic)("entered the afterlife in main() -- Deadlock");
2924 break;
2925
nethercote71980f02004-01-24 18:18:54 +00002926 case VgSrc_FatalSig:
2927 /* We were killed by a fatal signal, so replicate the effect */
nethercote238a3c32004-08-09 13:13:31 +00002928 vg_assert(fatal_sigNo != -1);
2929 VG_(kill_self)(fatal_sigNo);
nethercote71980f02004-01-24 18:18:54 +00002930 VG_(core_panic)("main(): signal was supposed to be fatal");
2931 break;
2932
2933 default:
2934 VG_(core_panic)("main(): unexpected scheduler return code");
2935 }
2936
2937 abort();
2938}
2939
2940
sewardjde4a1d02002-03-22 01:27:54 +00002941/*--------------------------------------------------------------------*/
2942/*--- end vg_main.c ---*/
2943/*--------------------------------------------------------------------*/