blob: 465fd9af88d2e67e6795bd61e231dfffdb5a9498 [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
nethercote71980f02004-01-24 18:18:54 +000033#include "vg_include.h"
34#include "ume.h"
35#include "ume_arch.h"
36#include "ume_archdefs.h"
37
38#include <dirent.h>
39#include <dlfcn.h>
40#include <errno.h>
41#include <fcntl.h>
42#include <stdio.h>
fitzhardingeb727d042004-01-06 00:18:21 +000043#include <stdlib.h>
nethercote71980f02004-01-24 18:18:54 +000044#include <string.h>
45#include <sys/mman.h>
46#include <sys/types.h>
47#include <sys/stat.h>
fitzhardingeb727d042004-01-06 00:18:21 +000048#include <sys/ptrace.h>
49#include <sys/signal.h>
fitzhardingeb727d042004-01-06 00:18:21 +000050#include <sys/wait.h>
51#include <unistd.h>
52
thughes74b8de22004-04-22 18:12:31 +000053#ifndef AT_DCACHEBSIZE
54#define AT_DCACHEBSIZE 19
55#endif /* AT_DCACHEBSIZE */
56
57#ifndef AT_ICACHEBSIZE
58#define AT_ICACHEBSIZE 20
59#endif /* AT_ICACHEBSIZE */
60
61#ifndef AT_UCACHEBSIZE
62#define AT_UCACHEBSIZE 21
63#endif /* AT_UCACHEBSIZE */
64
nethercote71980f02004-01-24 18:18:54 +000065#ifndef AT_SYSINFO
66#define AT_SYSINFO 32
67#endif /* AT_SYSINFO */
68
69#ifndef AT_SYSINFO_EHDR
70#define AT_SYSINFO_EHDR 33
71#endif /* AT_SYSINFO_EHDR */
72
73#ifndef AT_SECURE
74#define AT_SECURE 23 /* secure mode boolean */
75#endif /* AT_SECURE */
76
nethercote71980f02004-01-24 18:18:54 +000077/* redzone gap between client address space and shadow */
78#define REDZONE_SIZE (1 * 1024*1024)
79
80/* size multiple for client address space */
nethercotee94b2de2004-06-23 16:15:06 +000081#define CLIENT_SIZE_MULTIPLE (1 * 1024*1024)
nethercote71980f02004-01-24 18:18:54 +000082
nethercotee2097312004-06-27 12:29:56 +000083/* Proportion of client space for its heap (rest is for mmaps + stack) */
84#define CLIENT_HEAP_PROPORTION 0.333
nethercote71980f02004-01-24 18:18:54 +000085
86/*====================================================================*/
87/*=== Global entities not referenced from generated code ===*/
88/*====================================================================*/
89
sewardjde4a1d02002-03-22 01:27:54 +000090/* ---------------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +000091 Startup stuff
sewardjde4a1d02002-03-22 01:27:54 +000092 ------------------------------------------------------------------ */
nethercote71980f02004-01-24 18:18:54 +000093/* linker-defined base address */
94extern char kickstart_base;
sewardjde4a1d02002-03-22 01:27:54 +000095
nethercote71980f02004-01-24 18:18:54 +000096/* Client address space, lowest to highest (see top of ume.c) */
97Addr VG_(client_base); /* client address space limits */
fitzhardinge98abfc72003-12-16 02:05:15 +000098Addr VG_(client_end);
99Addr VG_(client_mapbase);
fitzhardinge92360792003-12-24 10:11:11 +0000100Addr VG_(client_trampoline_code);
fitzhardinge98abfc72003-12-16 02:05:15 +0000101Addr VG_(clstk_base);
102Addr VG_(clstk_end);
nethercote71980f02004-01-24 18:18:54 +0000103
104Addr VG_(brk_base); /* start of brk */
105Addr VG_(brk_limit); /* current brk */
106
nethercote996901a2004-08-03 13:29:09 +0000107Addr VG_(shadow_base); /* tool's shadow memory */
fitzhardinge98abfc72003-12-16 02:05:15 +0000108Addr VG_(shadow_end);
nethercote71980f02004-01-24 18:18:54 +0000109
110Addr VG_(valgrind_base); /* valgrind's address range */
fitzhardinge98abfc72003-12-16 02:05:15 +0000111Addr VG_(valgrind_end);
112
fitzhardingeb50068f2004-02-24 23:42:55 +0000113vki_rlimit VG_(client_rlimit_data);
114
nethercote71980f02004-01-24 18:18:54 +0000115/* This is set early to indicate whether this CPU has the
116 SSE/fxsave/fxrestor features. */
117Bool VG_(have_ssestate);
118
fitzhardinge98abfc72003-12-16 02:05:15 +0000119/* stage1 (main) executable */
nethercotef6a1d502004-08-09 12:21:57 +0000120static Int vgexecfd = -1;
fitzhardingea49f9b52003-12-16 22:26:45 +0000121
122/* client executable */
123Int VG_(clexecfd) = -1;
fitzhardinge98abfc72003-12-16 02:05:15 +0000124
125/* Path to library directory */
126const Char *VG_(libdir) = VG_LIBDIR;
127
128/* our argc/argv */
nethercotef6a1d502004-08-09 12:21:57 +0000129static Int vg_argc;
130static Char **vg_argv;
fitzhardinge98abfc72003-12-16 02:05:15 +0000131
jsgf855d93d2003-10-13 22:26:55 +0000132/* PID of the main thread */
133Int VG_(main_pid);
134
135/* PGRP of process */
136Int VG_(main_pgrp);
njn25e49d8e72002-09-23 09:36:25 +0000137
thughesad1c9562004-06-26 11:27:52 +0000138/* Application-visible file descriptor limits */
139Int VG_(fd_soft_limit) = -1;
140Int VG_(fd_hard_limit) = -1;
fitzhardingef0046f22003-12-18 02:39:22 +0000141
nethercote71980f02004-01-24 18:18:54 +0000142/* As deduced from esp_at_startup, the client's argc, argv[] and
143 envp[] as extracted from the client's stack at startup-time. */
144Int VG_(client_argc);
145Char** VG_(client_argv);
146Char** VG_(client_envp);
sewardjde4a1d02002-03-22 01:27:54 +0000147
148/* ---------------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +0000149 Running stuff
sewardjde4a1d02002-03-22 01:27:54 +0000150 ------------------------------------------------------------------ */
sewardjde4a1d02002-03-22 01:27:54 +0000151
nethercote31294822004-08-02 13:15:26 +0000152/* jmp_buf for fatal signals; VG_(fatal_signal_jmpbuf_ptr) is NULL until
153 the time is right that it can be used. */
nethercote92e7b7f2004-08-07 17:52:25 +0000154 Int VG_(fatal_sigNo) = -1;
155 jmp_buf* VG_(fatal_signal_jmpbuf_ptr) = NULL;
156static jmp_buf fatal_signal_jmpbuf;
sewardjde4a1d02002-03-22 01:27:54 +0000157
nethercote71980f02004-01-24 18:18:54 +0000158/* Counts downwards in VG_(run_innerloop). */
159UInt VG_(dispatch_ctr);
sewardjde4a1d02002-03-22 01:27:54 +0000160
161/* 64-bit counter for the number of basic blocks done. */
162ULong VG_(bbs_done);
sewardjde4a1d02002-03-22 01:27:54 +0000163
nethercote71980f02004-01-24 18:18:54 +0000164/* Tell the logging mechanism whether we are logging to a file
165 descriptor or a socket descriptor. */
166Bool VG_(logging_to_filedes) = True;
167
sewardj73cf3bc2002-11-03 03:20:15 +0000168
nethercote71980f02004-01-24 18:18:54 +0000169/*====================================================================*/
170/*=== Counters, for profiling purposes only ===*/
171/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +0000172
nethercote92e7b7f2004-08-07 17:52:25 +0000173// These ones maintained by vg_dispatch.S
174UInt VG_(bb_enchain_count) = 0; // Number of chain operations done
175UInt VG_(bb_dechain_count) = 0; // Number of unchain operations done
176UInt VG_(unchained_jumps_done) = 0; // Number of unchained jumps done
sewardjde4a1d02002-03-22 01:27:54 +0000177
sewardjde4a1d02002-03-22 01:27:54 +0000178/* Counts pertaining to internal sanity checking. */
nethercote297effd2004-08-02 15:07:57 +0000179static UInt sanity_fast_count = 0;
180static UInt sanity_slow_count = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000181
nethercote3a42fb82004-08-03 18:08:50 +0000182static void print_all_stats ( void )
nethercote71980f02004-01-24 18:18:54 +0000183{
nethercote3a42fb82004-08-03 18:08:50 +0000184 // Translation stats
nethercote92e7b7f2004-08-07 17:52:25 +0000185 VG_(print_tt_tc_stats)();
nethercote71980f02004-01-24 18:18:54 +0000186 VG_(message)(Vg_DebugMsg,
nethercote92e7b7f2004-08-07 17:52:25 +0000187 "chainings: %d chainings, %d unchainings.",
nethercote71980f02004-01-24 18:18:54 +0000188 VG_(bb_enchain_count), VG_(bb_dechain_count) );
189 VG_(message)(Vg_DebugMsg,
nethercote3a42fb82004-08-03 18:08:50 +0000190 " dispatch: %llu jumps (bb entries); of them %u (%lu%%) unchained.",
nethercote71980f02004-01-24 18:18:54 +0000191 VG_(bbs_done),
192 VG_(unchained_jumps_done),
193 ((ULong)(100) * (ULong)(VG_(unchained_jumps_done)))
194 / ( VG_(bbs_done)==0 ? 1 : VG_(bbs_done) )
195 );
196
nethercote3a42fb82004-08-03 18:08:50 +0000197 // Scheduler stats
nethercote844e7122004-08-02 15:27:22 +0000198 VG_(print_scheduler_stats)();
nethercote71980f02004-01-24 18:18:54 +0000199
nethercote3a42fb82004-08-03 18:08:50 +0000200 // Reg-alloc stats
nethercotebee3fd92004-08-02 15:17:43 +0000201 VG_(print_reg_alloc_stats)();
nethercote71980f02004-01-24 18:18:54 +0000202 VG_(message)(Vg_DebugMsg,
203 " sanity: %d cheap, %d expensive checks.",
nethercote297effd2004-08-02 15:07:57 +0000204 sanity_fast_count, sanity_slow_count );
nethercote3a42fb82004-08-03 18:08:50 +0000205
206 // C call stats
nethercote71980f02004-01-24 18:18:54 +0000207 VG_(print_ccall_stats)();
nethercote3a42fb82004-08-03 18:08:50 +0000208
209 // UInstr histogram
210 if (VG_(clo_verbosity) > 3)
211 VG_(print_UInstr_histogram)();
212
213 // Memory stats
nethercote885dd912004-08-03 23:14:00 +0000214 if (VG_(clo_verbosity) > 2) {
nethercote3a42fb82004-08-03 18:08:50 +0000215 VG_(message)(Vg_DebugMsg, "");
216 VG_(message)(Vg_DebugMsg,
217 "------ Valgrind's internal memory use stats follow ------" );
nethercote885dd912004-08-03 23:14:00 +0000218 VG_(sanity_check_malloc_all)();
nethercote3a42fb82004-08-03 18:08:50 +0000219 VG_(print_all_arena_stats)();
nethercote885dd912004-08-03 23:14:00 +0000220 VG_(message)(Vg_DebugMsg, "");
nethercote3a42fb82004-08-03 18:08:50 +0000221 VG_(message)(Vg_DebugMsg,
222 "------ Valgrind's ExeContext management stats follow ------" );
223 VG_(print_ExeContext_stats)();
224 }
nethercote71980f02004-01-24 18:18:54 +0000225}
226
227
228/*====================================================================*/
229/*=== Miscellaneous global functions ===*/
230/*====================================================================*/
231
nethercote04d0fbc2004-01-26 16:48:06 +0000232/* Start debugger and get it to attach to this process. Called if the
233 user requests this service after an error has been shown, so she can
nethercote71980f02004-01-24 18:18:54 +0000234 poke around and look at parameters, memory, etc. You can't
nethercote04d0fbc2004-01-26 16:48:06 +0000235 meaningfully get the debugger to continue the program, though; to
236 continue, quit the debugger. */
237void VG_(start_debugger) ( Int tid )
nethercote71980f02004-01-24 18:18:54 +0000238{
239 Int pid;
240
241 if ((pid = fork()) == 0) {
242 ptrace(PTRACE_TRACEME, 0, NULL, NULL);
243 VG_(kkill)(VG_(getpid)(), VKI_SIGSTOP);
244
245 } else if (pid > 0) {
246 struct user_regs_struct regs;
247 Int status;
248 Int res;
249
250 if (VG_(is_running_thread)( tid )) {
fitzhardinged65dcad2004-03-13 02:06:58 +0000251 regs.cs = VG_(baseBlock)[VGOFF_(m_cs)];
252 regs.ss = VG_(baseBlock)[VGOFF_(m_ss)];
253 regs.ds = VG_(baseBlock)[VGOFF_(m_ds)];
254 regs.es = VG_(baseBlock)[VGOFF_(m_es)];
255 regs.fs = VG_(baseBlock)[VGOFF_(m_fs)];
256 regs.gs = VG_(baseBlock)[VGOFF_(m_gs)];
nethercote71980f02004-01-24 18:18:54 +0000257 regs.eax = VG_(baseBlock)[VGOFF_(m_eax)];
258 regs.ebx = VG_(baseBlock)[VGOFF_(m_ebx)];
259 regs.ecx = VG_(baseBlock)[VGOFF_(m_ecx)];
260 regs.edx = VG_(baseBlock)[VGOFF_(m_edx)];
261 regs.esi = VG_(baseBlock)[VGOFF_(m_esi)];
262 regs.edi = VG_(baseBlock)[VGOFF_(m_edi)];
263 regs.ebp = VG_(baseBlock)[VGOFF_(m_ebp)];
264 regs.esp = VG_(baseBlock)[VGOFF_(m_esp)];
265 regs.eflags = VG_(baseBlock)[VGOFF_(m_eflags)];
266 regs.eip = VG_(baseBlock)[VGOFF_(m_eip)];
267 } else {
268 ThreadState* tst = & VG_(threads)[ tid ];
269
fitzhardinged65dcad2004-03-13 02:06:58 +0000270 regs.cs = tst->m_cs;
271 regs.ss = tst->m_ss;
272 regs.ds = tst->m_ds;
273 regs.es = tst->m_es;
274 regs.fs = tst->m_fs;
275 regs.gs = tst->m_gs;
nethercote71980f02004-01-24 18:18:54 +0000276 regs.eax = tst->m_eax;
277 regs.ebx = tst->m_ebx;
278 regs.ecx = tst->m_ecx;
279 regs.edx = tst->m_edx;
280 regs.esi = tst->m_esi;
281 regs.edi = tst->m_edi;
282 regs.ebp = tst->m_ebp;
283 regs.esp = tst->m_esp;
284 regs.eflags = tst->m_eflags;
285 regs.eip = tst->m_eip;
286 }
287
288 if ((res = VG_(waitpid)(pid, &status, 0)) == pid &&
289 WIFSTOPPED(status) && WSTOPSIG(status) == SIGSTOP &&
290 ptrace(PTRACE_SETREGS, pid, NULL, &regs) == 0 &&
thughes1d160052004-04-21 15:39:57 +0000291 kill(pid, SIGSTOP) == 0 &&
292 ptrace(PTRACE_DETACH, pid, NULL, 0) == 0) {
nethercote04d0fbc2004-01-26 16:48:06 +0000293 Char pidbuf[15];
294 Char file[30];
295 Char buf[100];
296 Char *bufptr;
297 Char *cmdptr;
298
299 VG_(sprintf)(pidbuf, "%d", pid);
300 VG_(sprintf)(file, "/proc/%d/fd/%d", pid, VG_(clexecfd));
301
302 bufptr = buf;
303 cmdptr = VG_(clo_db_command);
304
305 while (*cmdptr) {
306 switch (*cmdptr) {
307 case '%':
308 switch (*++cmdptr) {
309 case 'f':
310 VG_(memcpy)(bufptr, file, VG_(strlen)(file));
311 bufptr += VG_(strlen)(file);
312 cmdptr++;
313 break;
314 case 'p':
315 VG_(memcpy)(bufptr, pidbuf, VG_(strlen)(pidbuf));
316 bufptr += VG_(strlen)(pidbuf);
317 cmdptr++;
318 break;
319 default:
320 *bufptr++ = *cmdptr++;
321 break;
322 }
323 break;
324 default:
325 *bufptr++ = *cmdptr++;
326 break;
327 }
328 }
329
330 *bufptr++ = '\0';
331
332 VG_(message)(Vg_UserMsg, "starting debugger with cmd: %s", buf);
nethercote71980f02004-01-24 18:18:54 +0000333 res = VG_(system)(buf);
334 if (res == 0) {
335 VG_(message)(Vg_UserMsg, "");
336 VG_(message)(Vg_UserMsg,
nethercote04d0fbc2004-01-26 16:48:06 +0000337 "Debugger has detached. Valgrind regains control. We continue.");
nethercote71980f02004-01-24 18:18:54 +0000338 } else {
339 VG_(message)(Vg_UserMsg, "Apparently failed!");
340 VG_(message)(Vg_UserMsg, "");
341 }
342 }
343
344 VG_(kkill)(pid, VKI_SIGKILL);
345 VG_(waitpid)(pid, &status, 0);
346 }
347}
348
349
350/* Print some helpful-ish text about unimplemented things, and give
351 up. */
352void VG_(unimplemented) ( Char* msg )
353{
354 VG_(message)(Vg_UserMsg, "");
355 VG_(message)(Vg_UserMsg,
356 "Valgrind detected that your program requires");
357 VG_(message)(Vg_UserMsg,
358 "the following unimplemented functionality:");
359 VG_(message)(Vg_UserMsg, " %s", msg);
360 VG_(message)(Vg_UserMsg,
361 "This may be because the functionality is hard to implement,");
362 VG_(message)(Vg_UserMsg,
363 "or because no reasonable program would behave this way,");
364 VG_(message)(Vg_UserMsg,
365 "or because nobody has yet needed it. In any case, let us know at");
366 VG_(message)(Vg_UserMsg,
367 "%s and/or try to work around the problem, if you can.", VG_BUGS_TO);
368 VG_(message)(Vg_UserMsg,
369 "");
370 VG_(message)(Vg_UserMsg,
371 "Valgrind has to exit now. Sorry. Bye!");
372 VG_(message)(Vg_UserMsg,
373 "");
374 VG_(pp_sched_status)();
375 VG_(exit)(1);
376}
377
378Addr VG_(get_stack_pointer) ( void )
379{
380 return VG_(baseBlock)[VGOFF_(m_esp)];
381}
382
383/* Debugging thing .. can be called from assembly with OYNK macro. */
384void VG_(oynk) ( Int n )
385{
386 OINK(n);
387}
388
389/* Initialize the PID and PGRP of scheduler LWP; this is also called
390 in any new children after fork. */
391static void newpid(ThreadId unused)
392{
393 /* PID of scheduler LWP */
394 VG_(main_pid) = VG_(getpid)();
395 VG_(main_pgrp) = VG_(getpgrp)();
396}
397
398/*====================================================================*/
399/*=== Check we were launched by stage 1 ===*/
400/*====================================================================*/
401
402/* Look for our AUXV table */
nethercote31779c72004-07-30 21:50:15 +0000403int scan_auxv(void)
nethercote71980f02004-01-24 18:18:54 +0000404{
405 const struct ume_auxv *auxv = find_auxv((int *)ume_exec_esp);
nethercote31779c72004-07-30 21:50:15 +0000406 int padfile = -1, found = 0;
nethercote71980f02004-01-24 18:18:54 +0000407
408 for (; auxv->a_type != AT_NULL; auxv++)
409 switch(auxv->a_type) {
410 case AT_UME_PADFD:
nethercote31779c72004-07-30 21:50:15 +0000411 padfile = auxv->u.a_val;
nethercote71980f02004-01-24 18:18:54 +0000412 found |= 1;
413 break;
414
415 case AT_UME_EXECFD:
nethercotef6a1d502004-08-09 12:21:57 +0000416 vgexecfd = auxv->u.a_val;
nethercote71980f02004-01-24 18:18:54 +0000417 found |= 2;
418 break;
419 }
420
nethercote361a14e2004-07-26 11:11:56 +0000421 if ( found != (1|2) ) {
422 fprintf(stderr, "valgrind: stage2 must be launched by stage1\n");
nethercote71980f02004-01-24 18:18:54 +0000423 exit(127);
424 }
nethercote31779c72004-07-30 21:50:15 +0000425 vg_assert(padfile >= 0);
426 return padfile;
nethercote71980f02004-01-24 18:18:54 +0000427}
428
429
430/*====================================================================*/
431/*=== Address space determination ===*/
432/*====================================================================*/
433
nethercote31779c72004-07-30 21:50:15 +0000434static void layout_remaining_space(Addr argc_addr, float ratio)
nethercote71980f02004-01-24 18:18:54 +0000435{
nethercote31779c72004-07-30 21:50:15 +0000436 Int ires;
437 void* vres;
438 addr_t client_size, shadow_size;
nethercote71980f02004-01-24 18:18:54 +0000439
nethercote31779c72004-07-30 21:50:15 +0000440 VG_(valgrind_base) = (addr_t)&kickstart_base;
441 VG_(valgrind_end) = ROUNDUP(argc_addr, 0x10000); // stack
nethercote71980f02004-01-24 18:18:54 +0000442
nethercote31779c72004-07-30 21:50:15 +0000443 // This gives the client the largest possible address space while
444 // taking into account the tool's shadow needs.
445 client_size = ROUNDDN((VG_(valgrind_base)-REDZONE_SIZE) / (1.+ratio),
nethercote71980f02004-01-24 18:18:54 +0000446 CLIENT_SIZE_MULTIPLE);
nethercote31779c72004-07-30 21:50:15 +0000447 VG_(client_base) = CLIENT_BASE;
nethercote71980f02004-01-24 18:18:54 +0000448 VG_(client_end) = VG_(client_base) + client_size;
nethercotee2097312004-06-27 12:29:56 +0000449 /* where !FIXED mmap goes */
nethercotebc7b4f42004-07-26 12:44:35 +0000450 VG_(client_mapbase) = VG_(client_base) +
451 PGROUNDDN((addr_t)(client_size * CLIENT_HEAP_PROPORTION));
nethercote71980f02004-01-24 18:18:54 +0000452
nethercote31779c72004-07-30 21:50:15 +0000453 shadow_size = PGROUNDUP(client_size * ratio);
454 VG_(shadow_base) = VG_(client_end) + REDZONE_SIZE;
455 VG_(shadow_end) = VG_(shadow_base) + shadow_size;
nethercote71980f02004-01-24 18:18:54 +0000456
nethercotee2097312004-06-27 12:29:56 +0000457#define SEGSIZE(a,b) ((VG_(b) - VG_(a))/(1024*1024))
458
nethercote71980f02004-01-24 18:18:54 +0000459 if (0)
nethercotee2097312004-06-27 12:29:56 +0000460 VG_(printf)(
461 "client_base %8x (%dMB)\n"
462 "client_mapbase %8x (%dMB)\n"
463 "client_end %8x (%dMB)\n"
464 "shadow_base %8x (%dMB)\n"
465 "shadow_end %8x (%dMB)\n"
466 "valgrind_base %8x (%dMB)\n"
nethercotee2097312004-06-27 12:29:56 +0000467 "valgrind_end %8x\n",
468 VG_(client_base), SEGSIZE(client_base, client_mapbase),
469 VG_(client_mapbase), SEGSIZE(client_mapbase, client_end),
470 VG_(client_end), SEGSIZE(client_end, shadow_base),
471 VG_(shadow_base), SEGSIZE(shadow_base, shadow_end),
472 VG_(shadow_end), SEGSIZE(shadow_end, valgrind_base),
nethercotec314eba2004-07-15 12:59:41 +0000473 VG_(valgrind_base), SEGSIZE(valgrind_base, valgrind_end),
nethercotee2097312004-06-27 12:29:56 +0000474 VG_(valgrind_end)
475 );
476
477#undef SEGSIZE
nethercote71980f02004-01-24 18:18:54 +0000478
479 // Ban redzone
nethercotee567e702004-07-10 17:49:17 +0000480 vres = mmap((void *)VG_(client_end), REDZONE_SIZE, PROT_NONE,
481 MAP_FIXED|MAP_ANON|MAP_PRIVATE, -1, 0);
482 vg_assert((void*)-1 != vres);
nethercote71980f02004-01-24 18:18:54 +0000483
484 // Make client hole
nethercotee567e702004-07-10 17:49:17 +0000485 ires = munmap((void*)VG_(client_base), client_size);
486 vg_assert(0 == ires);
nethercote71980f02004-01-24 18:18:54 +0000487
488 // Map shadow memory.
489 // Initially all inaccessible, incrementally initialized as it is used
nethercotee567e702004-07-10 17:49:17 +0000490 if (shadow_size != 0) {
491 vres = mmap((char *)VG_(shadow_base), shadow_size, PROT_NONE,
492 MAP_PRIVATE|MAP_ANON|MAP_FIXED, -1, 0);
493 vg_assert((void*)-1 != vres);
494 }
nethercote71980f02004-01-24 18:18:54 +0000495}
496
497/*====================================================================*/
498/*=== Command line setup ===*/
499/*====================================================================*/
500
501/* Nb: malloc'd memory never freed -- kept throughout like argv, envp */
502static char* get_file_clo(char* dir)
503{
504# define FLEN 512
505 Int fd, n;
506 struct stat s1;
507 char* f_clo = NULL;
508 char filename[FLEN];
509
510 snprintf(filename, FLEN, "%s/.valgrindrc", ( NULL == dir ? "" : dir ) );
511 fd = VG_(open)(filename, 0, VKI_S_IRUSR);
512 if ( fd > 0 ) {
513 if ( 0 == fstat(fd, &s1) ) {
514 f_clo = malloc(s1.st_size+1);
515 vg_assert(f_clo);
516 n = read(fd, f_clo, s1.st_size);
517 if (n == -1) n = 0;
518 f_clo[n] = '\0';
519 }
520 close(fd);
521 }
522 return f_clo;
523# undef FLEN
524}
525
nethercotee2097312004-06-27 12:29:56 +0000526#define ISSPACE(cc) ((cc) == ' ' || (cc) == '\t' || (cc) == '\n')
527
nethercote71980f02004-01-24 18:18:54 +0000528static Int count_args(char* s)
529{
530 Int n = 0;
531 if (s) {
532 char* cp = s;
533 while (True) {
534 // We have alternating sequences: blanks, non-blanks, blanks...
535 // count the non-blanks sequences.
536 while ( ISSPACE(*cp) ) cp++;
537 if ( !*cp ) break;
538 n++;
539 while ( !ISSPACE(*cp) && *cp ) cp++;
540 }
541 }
542 return n;
543}
544
545/* add args out of environment, skipping multiple spaces and -- args */
546static char** copy_args( char* s, char** to )
547{
548 if (s) {
549 char* cp = s;
550 while (True) {
551 // We have alternating sequences: blanks, non-blanks, blanks...
552 // copy the non-blanks sequences, and add terminating '\0'
553 while ( ISSPACE(*cp) ) cp++;
554 if ( !*cp ) break;
555 *to++ = cp;
556 while ( !ISSPACE(*cp) && *cp ) cp++;
557 if ( *cp ) *cp++ = '\0'; // terminate if necessary
558 if (VG_STREQ(to[-1], "--")) to--; // undo any '--' arg
559 }
560 }
561 return to;
562}
563
nethercotee2097312004-06-27 12:29:56 +0000564#undef ISSPACE
565
nethercote71980f02004-01-24 18:18:54 +0000566// Augment command line with arguments from environment and .valgrindrc
567// files.
568static void augment_command_line(Int* vg_argc_inout, char*** vg_argv_inout)
569{
nethercotef6a1d502004-08-09 12:21:57 +0000570 int vg_argc0 = *vg_argc_inout;
571 char** vg_argv0 = *vg_argv_inout;
nethercote71980f02004-01-24 18:18:54 +0000572
573 char* env_clo = getenv(VALGRINDOPTS);
574 char* f1_clo = get_file_clo( getenv("HOME") );
575 char* f2_clo = get_file_clo(".");
576
577 /* copy any extra args from file or environment, if present */
578 if ( (env_clo && *env_clo) || (f1_clo && *f1_clo) || (f2_clo && *f2_clo) ) {
579 /* ' ' separated extra options */
580 char **from;
581 char **to;
582 int env_arg_count, f1_arg_count, f2_arg_count;
583
584 env_arg_count = count_args(env_clo);
585 f1_arg_count = count_args(f1_clo);
586 f2_arg_count = count_args(f2_clo);
587
588 if (0)
589 printf("extra-argc=%d %d %d\n",
590 env_arg_count, f1_arg_count, f2_arg_count);
591
592 /* +2: +1 for null-termination, +1 for added '--' */
nethercotef6a1d502004-08-09 12:21:57 +0000593 from = vg_argv0;
594 vg_argv0 = malloc( (vg_argc0 + env_arg_count + f1_arg_count
nethercote71980f02004-01-24 18:18:54 +0000595 + f2_arg_count + 2) * sizeof(char **));
nethercotef6a1d502004-08-09 12:21:57 +0000596 vg_assert(vg_argv0);
597 to = vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000598
599 /* copy argv[0] */
600 *to++ = *from++;
601
602 /* Copy extra args from env var and file, in the order: ~/.valgrindrc,
603 * $VALGRIND_OPTS, ./.valgrindrc -- more local options are put later
604 * to override less local ones. */
605 to = copy_args(f1_clo, to);
606 to = copy_args(env_clo, to);
607 to = copy_args(f2_clo, to);
608
609 /* copy original arguments, stopping at command or -- */
610 while (*from) {
611 if (**from != '-')
612 break;
613 if (VG_STREQ(*from, "--")) {
614 from++; /* skip -- */
615 break;
616 }
617 *to++ = *from++;
618 }
619
620 /* add -- */
621 *to++ = "--";
622
nethercotef6a1d502004-08-09 12:21:57 +0000623 vg_argc0 = to - vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000624
625 /* copy rest of original command line, then NULL */
626 while (*from) *to++ = *from++;
627 *to = NULL;
628 }
629
nethercotef6a1d502004-08-09 12:21:57 +0000630 *vg_argc_inout = vg_argc0;
631 *vg_argv_inout = vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000632}
633
nethercotef6a1d502004-08-09 12:21:57 +0000634#define VG_CLO_SEP '\01'
635
nethercote71980f02004-01-24 18:18:54 +0000636static void get_command_line( int argc, char** argv,
637 Int* vg_argc_out, Char*** vg_argv_out,
638 char*** cl_argv_out )
639{
nethercotef6a1d502004-08-09 12:21:57 +0000640 int vg_argc0;
641 char** vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000642 char** cl_argv;
643 char* env_clo = getenv(VALGRINDCLO);
644
645 if (env_clo != NULL && *env_clo != '\0') {
646 char *cp;
647 char **cpp;
648
nethercotef6a1d502004-08-09 12:21:57 +0000649 /* OK, VALGRINDCLO is set, which means we must be a child of another
650 Valgrind process using --trace-children, so we're getting all our
651 arguments from VALGRINDCLO, and the entire command line belongs to
652 the client (including argv[0]) */
653 vg_argc0 = 1; /* argv[0] */
nethercote71980f02004-01-24 18:18:54 +0000654 for (cp = env_clo; *cp; cp++)
nethercotef6a1d502004-08-09 12:21:57 +0000655 if (*cp == VG_CLO_SEP)
656 vg_argc0++;
nethercote71980f02004-01-24 18:18:54 +0000657
nethercotef6a1d502004-08-09 12:21:57 +0000658 vg_argv0 = malloc(sizeof(char **) * (vg_argc0 + 1));
659 vg_assert(vg_argv0);
nethercote71980f02004-01-24 18:18:54 +0000660
nethercotef6a1d502004-08-09 12:21:57 +0000661 cpp = vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000662
663 *cpp++ = "valgrind"; /* nominal argv[0] */
664 *cpp++ = env_clo;
665
nethercotef6a1d502004-08-09 12:21:57 +0000666 // Replace the VG_CLO_SEP args separator with '\0'
nethercote71980f02004-01-24 18:18:54 +0000667 for (cp = env_clo; *cp; cp++) {
nethercotef6a1d502004-08-09 12:21:57 +0000668 if (*cp == VG_CLO_SEP) {
nethercote71980f02004-01-24 18:18:54 +0000669 *cp++ = '\0'; /* chop it up in place */
670 *cpp++ = cp;
671 }
672 }
673 *cpp = NULL;
674 cl_argv = argv;
675
676 } else {
677 /* Count the arguments on the command line. */
nethercotef6a1d502004-08-09 12:21:57 +0000678 vg_argv0 = argv;
nethercote71980f02004-01-24 18:18:54 +0000679
nethercotef6a1d502004-08-09 12:21:57 +0000680 for (vg_argc0 = 1; vg_argc0 < argc; vg_argc0++) {
681 if (argv[vg_argc0][0] != '-') /* exe name */
nethercote71980f02004-01-24 18:18:54 +0000682 break;
nethercotef6a1d502004-08-09 12:21:57 +0000683 if (VG_STREQ(argv[vg_argc0], "--")) { /* dummy arg */
684 vg_argc0++;
nethercote71980f02004-01-24 18:18:54 +0000685 break;
686 }
687 }
nethercotef6a1d502004-08-09 12:21:57 +0000688 cl_argv = &argv[vg_argc0];
nethercote71980f02004-01-24 18:18:54 +0000689
690 /* Get extra args from VALGRIND_OPTS and .valgrindrc files.
nethercotef6a1d502004-08-09 12:21:57 +0000691 Note we don't do this if getting args from VALGRINDCLO, as
692 those extra args will already be present in VALGRINDCLO. */
693 augment_command_line(&vg_argc0, &vg_argv0);
nethercote71980f02004-01-24 18:18:54 +0000694 }
695
696 if (0) {
697 Int i;
nethercotef6a1d502004-08-09 12:21:57 +0000698 for (i = 0; i < vg_argc0; i++)
699 printf("vg_argv0[%d]=\"%s\"\n", i, vg_argv0[i]);
nethercote71980f02004-01-24 18:18:54 +0000700 }
701
nethercotef6a1d502004-08-09 12:21:57 +0000702 *vg_argc_out = vg_argc0;
703 *vg_argv_out = (Char**)vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000704 *cl_argv_out = cl_argv;
705}
706
707
708/*====================================================================*/
709/*=== Environment and stack setup ===*/
710/*====================================================================*/
711
712/* Scan a colon-separated list, and call a function on each element.
713 The string must be mutable, because we insert a temporary '\0', but
thughes4ad52d02004-06-27 17:37:21 +0000714 the string will end up unmodified. (*func) should return True if it
nethercote71980f02004-01-24 18:18:54 +0000715 doesn't need to see any more.
thughes4ad52d02004-06-27 17:37:21 +0000716
717 This routine will return True if (*func) returns True and False if
718 it reaches the end of the list without that happening.
nethercote71980f02004-01-24 18:18:54 +0000719*/
thughes4ad52d02004-06-27 17:37:21 +0000720static Bool scan_colsep(char *colsep, Bool (*func)(const char *))
nethercote71980f02004-01-24 18:18:54 +0000721{
722 char *cp, *entry;
723 int end;
724
725 if (colsep == NULL ||
726 *colsep == '\0')
thughes4ad52d02004-06-27 17:37:21 +0000727 return False;
nethercote71980f02004-01-24 18:18:54 +0000728
729 entry = cp = colsep;
730
731 do {
732 end = (*cp == '\0');
733
734 if (*cp == ':' || *cp == '\0') {
735 char save = *cp;
736
737 *cp = '\0';
thughes21942d92004-07-12 09:35:37 +0000738 if ((*func)(entry)) {
739 *cp = save;
thughes4ad52d02004-06-27 17:37:21 +0000740 return True;
thughes21942d92004-07-12 09:35:37 +0000741 }
nethercote71980f02004-01-24 18:18:54 +0000742 *cp = save;
743 entry = cp+1;
744 }
745 cp++;
746 } while(!end);
thughes4ad52d02004-06-27 17:37:21 +0000747
748 return False;
749}
750
751static Bool contains(const char *p) {
752 if (VG_STREQ(p, VG_(libdir))) {
753 return True;
754 }
755 return False;
nethercote71980f02004-01-24 18:18:54 +0000756}
757
758/* Prepare the client's environment. This is basically a copy of our
759 environment, except:
760 1. LD_LIBRARY_PATH=$VALGRINDLIB:$LD_LIBRARY_PATH
761 2. LD_PRELOAD=$VALGRINDLIB/vg_inject.so:($VALGRINDLIB/vgpreload_TOOL.so:)?$LD_PRELOAD
762
763 If any of these is missing, then it is added.
764
765 Yummy. String hacking in C.
766
767 If this needs to handle any more variables it should be hacked
768 into something table driven.
769 */
770static char **fix_environment(char **origenv, const char *preload)
771{
772 static const char inject_so[] = "vg_inject.so";
773 static const char ld_library_path[] = "LD_LIBRARY_PATH=";
774 static const char ld_preload[] = "LD_PRELOAD=";
775 static const char valgrind_clo[] = VALGRINDCLO "=";
776 static const int ld_library_path_len = sizeof(ld_library_path)-1;
777 static const int ld_preload_len = sizeof(ld_preload)-1;
778 static const int valgrind_clo_len = sizeof(valgrind_clo)-1;
779 int ld_preload_done = 0;
780 int ld_library_path_done = 0;
781 char *inject_path;
782 int inject_path_len;
783 int vgliblen = strlen(VG_(libdir));
784 char **cpp;
785 char **ret;
786 int envc;
787 const int preloadlen = (preload == NULL) ? 0 : strlen(preload);
788
789 /* Find the vg_inject.so; also make room for the tool preload
790 library */
791 inject_path_len = sizeof(inject_so) + vgliblen + preloadlen + 16;
792 inject_path = malloc(inject_path_len);
nethercote7c018f42004-07-17 16:40:50 +0000793 vg_assert(inject_path);
nethercote71980f02004-01-24 18:18:54 +0000794
795 if (preload)
796 snprintf(inject_path, inject_path_len, "%s/%s:%s",
797 VG_(libdir), inject_so, preload);
798 else
799 snprintf(inject_path, inject_path_len, "%s/%s",
800 VG_(libdir), inject_so);
801
802 /* Count the original size of the env */
803 envc = 0; /* trailing NULL */
804 for (cpp = origenv; cpp && *cpp; cpp++)
805 envc++;
806
807 /* Allocate a new space */
808 ret = malloc(sizeof(char *) * (envc+3+1)); /* 3 new entries + NULL */
nethercote7c018f42004-07-17 16:40:50 +0000809 vg_assert(ret);
nethercote71980f02004-01-24 18:18:54 +0000810
811 /* copy it over */
812 for (cpp = ret; *origenv; )
813 *cpp++ = *origenv++;
814 *cpp = NULL;
815
816 vg_assert(envc == (cpp - ret));
817
818 /* Walk over the new environment, mashing as we go */
819 for (cpp = ret; cpp && *cpp; cpp++) {
820 if (memcmp(*cpp, ld_library_path, ld_library_path_len) == 0) {
nethercote71980f02004-01-24 18:18:54 +0000821 /* If the LD_LIBRARY_PATH already contains libdir, then don't
822 bother adding it again, even if it isn't the first (it
823 seems that the Java runtime will keep reexecing itself
824 unless its paths are at the front of LD_LIBRARY_PATH) */
thughes4ad52d02004-06-27 17:37:21 +0000825 if (!scan_colsep(*cpp + ld_library_path_len, contains)) {
nethercote71980f02004-01-24 18:18:54 +0000826 int len = strlen(*cpp) + vgliblen*2 + 16;
827 char *cp = malloc(len);
nethercote7c018f42004-07-17 16:40:50 +0000828 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000829
830 snprintf(cp, len, "%s%s:%s",
831 ld_library_path, VG_(libdir),
832 (*cpp)+ld_library_path_len);
833
834 *cpp = cp;
835 }
836
837 ld_library_path_done = 1;
838 } else if (memcmp(*cpp, ld_preload, ld_preload_len) == 0) {
839 int len = strlen(*cpp) + inject_path_len;
840 char *cp = malloc(len);
nethercote7c018f42004-07-17 16:40:50 +0000841 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000842
843 snprintf(cp, len, "%s%s:%s",
844 ld_preload, inject_path, (*cpp)+ld_preload_len);
845
846 *cpp = cp;
847
848 ld_preload_done = 1;
849 } else if (memcmp(*cpp, valgrind_clo, valgrind_clo_len) == 0) {
850 *cpp = "";
851 }
852 }
853
854 /* Add the missing bits */
855
856 if (!ld_library_path_done) {
857 int len = ld_library_path_len + vgliblen*2 + 16;
858 char *cp = malloc(len);
nethercote7c018f42004-07-17 16:40:50 +0000859 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000860
861 snprintf(cp, len, "%s%s", ld_library_path, VG_(libdir));
862
863 ret[envc++] = cp;
864 }
865
866 if (!ld_preload_done) {
867 int len = ld_preload_len + inject_path_len;
868 char *cp = malloc(len);
nethercote7c018f42004-07-17 16:40:50 +0000869 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000870
871 snprintf(cp, len, "%s%s",
872 ld_preload, inject_path);
873
874 ret[envc++] = cp;
875 }
876
877 ret[envc] = NULL;
878
879 return ret;
880}
881
882extern char **environ; /* our environment */
883//#include <error.h>
884
885/* Add a string onto the string table, and return its address */
886static char *copy_str(char **tab, const char *str)
887{
888 char *cp = *tab;
889 char *orig = cp;
890
891 while(*str)
892 *cp++ = *str++;
893 *cp++ = '\0';
894
895 if (0)
nethercotef84f6952004-07-15 14:58:33 +0000896 printf("copied %p \"%s\" len %d\n", orig, orig, cp-orig);
nethercote71980f02004-01-24 18:18:54 +0000897
898 *tab = cp;
899
900 return orig;
901}
902
903/*
904 This sets up the client's initial stack, containing the args,
905 environment and aux vector.
906
907 The format of the stack is:
908
909 higher address +-----------------+
910 | Trampoline code |
911 +-----------------+
912 | |
913 : string table :
914 | |
915 +-----------------+
916 | AT_NULL |
917 - -
918 | auxv |
919 +-----------------+
920 | NULL |
921 - -
922 | envp |
923 +-----------------+
924 | NULL |
925 - -
926 | argv |
927 +-----------------+
928 | argc |
929 lower address +-----------------+ <- esp
930 | undefined |
931 : :
932 */
933static Addr setup_client_stack(char **orig_argv, char **orig_envp,
934 const struct exeinfo *info,
935 UInt** client_auxv)
936{
nethercotee567e702004-07-10 17:49:17 +0000937 void* res;
nethercote71980f02004-01-24 18:18:54 +0000938 char **cpp;
939 char *strtab; /* string table */
940 char *stringbase;
941 addr_t *ptr;
942 struct ume_auxv *auxv;
943 const struct ume_auxv *orig_auxv;
944 const struct ume_auxv *cauxv;
945 unsigned stringsize; /* total size of strings in bytes */
946 unsigned auxsize; /* total size of auxv in bytes */
947 int argc; /* total argc */
948 int envc; /* total number of env vars */
949 unsigned stacksize; /* total client stack size */
950 addr_t cl_esp; /* client stack base (initial esp) */
951
952 /* use our own auxv as a prototype */
953 orig_auxv = find_auxv(ume_exec_esp);
954
955 /* ==================== compute sizes ==================== */
956
957 /* first of all, work out how big the client stack will be */
958 stringsize = 0;
959
960 /* paste on the extra args if the loader needs them (ie, the #!
961 interpreter and its argument) */
962 argc = 0;
nethercoted6a56872004-07-26 15:32:47 +0000963 if (info->interp_name != NULL) {
nethercote71980f02004-01-24 18:18:54 +0000964 argc++;
nethercoted6a56872004-07-26 15:32:47 +0000965 stringsize += strlen(info->interp_name) + 1;
nethercote71980f02004-01-24 18:18:54 +0000966 }
nethercoted6a56872004-07-26 15:32:47 +0000967 if (info->interp_args != NULL) {
nethercote71980f02004-01-24 18:18:54 +0000968 argc++;
nethercoted6a56872004-07-26 15:32:47 +0000969 stringsize += strlen(info->interp_args) + 1;
nethercote71980f02004-01-24 18:18:54 +0000970 }
971
972 /* now scan the args we're given... */
973 for (cpp = orig_argv; *cpp; cpp++) {
974 argc++;
975 stringsize += strlen(*cpp) + 1;
976 }
977
978 /* ...and the environment */
979 envc = 0;
980 for (cpp = orig_envp; cpp && *cpp; cpp++) {
981 envc++;
982 stringsize += strlen(*cpp) + 1;
983 }
984
985 /* now, how big is the auxv? */
986 auxsize = sizeof(*auxv); /* there's always at least one entry: AT_NULL */
987 for (cauxv = orig_auxv; cauxv->a_type != AT_NULL; cauxv++) {
988 if (cauxv->a_type == AT_PLATFORM)
989 stringsize += strlen(cauxv->u.a_ptr) + 1;
990 auxsize += sizeof(*cauxv);
991 }
992
993 /* OK, now we know how big the client stack is */
994 stacksize =
995 sizeof(int) + /* argc */
996 sizeof(char **)*argc + /* argv */
997 sizeof(char **) + /* terminal NULL */
998 sizeof(char **)*envc + /* envp */
999 sizeof(char **) + /* terminal NULL */
1000 auxsize + /* auxv */
1001 ROUNDUP(stringsize, sizeof(int)) +/* strings (aligned) */
1002 VKI_BYTES_PER_PAGE; /* page for trampoline code */
1003
nethercotef84f6952004-07-15 14:58:33 +00001004 // decide where stack goes!
1005 VG_(clstk_end) = VG_(client_end);
1006
1007 VG_(client_trampoline_code) = VG_(clstk_end) - VKI_BYTES_PER_PAGE;
1008
nethercote71980f02004-01-24 18:18:54 +00001009 /* cl_esp is the client's stack pointer */
nethercotef84f6952004-07-15 14:58:33 +00001010 cl_esp = VG_(clstk_end) - stacksize;
nethercote71980f02004-01-24 18:18:54 +00001011 cl_esp = ROUNDDN(cl_esp, 16); /* make stack 16 byte aligned */
1012
nethercote71980f02004-01-24 18:18:54 +00001013 /* base of the string table (aligned) */
1014 stringbase = strtab = (char *)(VG_(client_trampoline_code) - ROUNDUP(stringsize, sizeof(int)));
1015
1016 VG_(clstk_base) = PGROUNDDN(cl_esp);
nethercote71980f02004-01-24 18:18:54 +00001017
nethercote5ee67ca2004-06-22 14:00:09 +00001018 if (0)
1019 printf("stringsize=%d auxsize=%d stacksize=%d\n"
1020 "clstk_base %x\n"
1021 "clstk_end %x\n",
1022 stringsize, auxsize, stacksize, VG_(clstk_base), VG_(clstk_end));
1023
1024
nethercote71980f02004-01-24 18:18:54 +00001025 /* ==================== allocate space ==================== */
1026
1027 /* allocate a stack - mmap enough space for the stack */
nethercotef84f6952004-07-15 14:58:33 +00001028 res = mmap((void *)PGROUNDDN(cl_esp), VG_(clstk_end) - PGROUNDDN(cl_esp),
nethercotee567e702004-07-10 17:49:17 +00001029 PROT_READ | PROT_WRITE | PROT_EXEC,
1030 MAP_PRIVATE | MAP_ANON | MAP_FIXED, -1, 0);
1031 vg_assert((void*)-1 != res);
nethercote71980f02004-01-24 18:18:54 +00001032
1033 /* ==================== copy client stack ==================== */
1034
1035 ptr = (addr_t *)cl_esp;
1036
1037 /* --- argc --- */
1038 *ptr++ = argc; /* client argc */
1039
1040 /* --- argv --- */
nethercoted6a56872004-07-26 15:32:47 +00001041 if (info->interp_name) {
1042 *ptr++ = (addr_t)copy_str(&strtab, info->interp_name);
1043 free(info->interp_name);
nethercote71980f02004-01-24 18:18:54 +00001044 }
nethercoted6a56872004-07-26 15:32:47 +00001045 if (info->interp_args) {
1046 *ptr++ = (addr_t)copy_str(&strtab, info->interp_args);
1047 free(info->interp_args);
nethercote71980f02004-01-24 18:18:54 +00001048 }
1049 for (cpp = orig_argv; *cpp; ptr++, cpp++) {
1050 *ptr = (addr_t)copy_str(&strtab, *cpp);
1051 }
1052 *ptr++ = 0;
1053
1054 /* --- envp --- */
1055 VG_(client_envp) = (Char **)ptr;
1056 for (cpp = orig_envp; cpp && *cpp; ptr++, cpp++)
1057 *ptr = (addr_t)copy_str(&strtab, *cpp);
1058 *ptr++ = 0;
1059
1060 /* --- auxv --- */
1061 auxv = (struct ume_auxv *)ptr;
1062 *client_auxv = (UInt *)auxv;
1063
1064 for (; orig_auxv->a_type != AT_NULL; auxv++, orig_auxv++) {
1065 /* copy the entry... */
1066 *auxv = *orig_auxv;
1067
1068 /* ...and fix up the copy */
1069 switch(auxv->a_type) {
1070 case AT_PHDR:
1071 if (info->phdr == 0)
1072 auxv->a_type = AT_IGNORE;
1073 else
1074 auxv->u.a_val = info->phdr;
1075 break;
1076
1077 case AT_PHNUM:
1078 if (info->phdr == 0)
1079 auxv->a_type = AT_IGNORE;
1080 else
1081 auxv->u.a_val = info->phnum;
1082 break;
1083
1084 case AT_BASE:
1085 if (info->interp_base == 0)
1086 auxv->a_type = AT_IGNORE;
1087 else
1088 auxv->u.a_val = info->interp_base;
1089 break;
1090
1091 case AT_PLATFORM: /* points to a platform description string */
1092 auxv->u.a_ptr = copy_str(&strtab, orig_auxv->u.a_ptr);
1093 break;
1094
1095 case AT_ENTRY:
1096 auxv->u.a_val = info->entry;
1097 break;
1098
1099 case AT_IGNORE:
1100 case AT_EXECFD:
1101 case AT_PHENT:
1102 case AT_PAGESZ:
1103 case AT_FLAGS:
1104 case AT_NOTELF:
1105 case AT_UID:
1106 case AT_EUID:
1107 case AT_GID:
1108 case AT_EGID:
1109 case AT_CLKTCK:
1110 case AT_HWCAP:
1111 case AT_FPUCW:
1112 case AT_DCACHEBSIZE:
1113 case AT_ICACHEBSIZE:
1114 case AT_UCACHEBSIZE:
1115 /* All these are pointerless, so we don't need to do anything
1116 about them. */
1117 break;
1118
1119 case AT_SECURE:
1120 /* If this is 1, then it means that this program is running
1121 suid, and therefore the dynamic linker should be careful
1122 about LD_PRELOAD, etc. However, since stage1 (the thing
1123 the kernel actually execve's) should never be SUID, and we
1124 need LD_PRELOAD/LD_LIBRARY_PATH to work for the client, we
1125 set AT_SECURE to 0. */
1126 auxv->u.a_val = 0;
1127 break;
1128
1129 case AT_SYSINFO:
1130 /* Leave this unmolested for now, but we'll update it later
1131 when we set up the client trampoline code page */
1132 break;
1133
1134 case AT_SYSINFO_EHDR:
1135 /* Trash this, because we don't reproduce it */
1136 auxv->a_type = AT_IGNORE;
1137 break;
1138
1139 default:
1140 /* stomp out anything we don't know about */
1141 if (0)
1142 printf("stomping auxv entry %d\n", auxv->a_type);
1143 auxv->a_type = AT_IGNORE;
1144 break;
1145
1146 }
1147 }
1148 *auxv = *orig_auxv;
1149 vg_assert(auxv->a_type == AT_NULL);
1150
nethercotef84f6952004-07-15 14:58:33 +00001151 /* --- trampoline page --- */
1152 VG_(memcpy)( (void *)VG_(client_trampoline_code),
1153 &VG_(trampoline_code_start), VG_(trampoline_code_length) );
1154
nethercote71980f02004-01-24 18:18:54 +00001155 vg_assert((strtab-stringbase) == stringsize);
1156
nethercote5ee67ca2004-06-22 14:00:09 +00001157 /* We know the initial ESP is pointing at argc/argv */
1158 VG_(client_argc) = *(Int*)cl_esp;
1159 VG_(client_argv) = (Char**)(cl_esp + sizeof(Int));
1160
nethercote71980f02004-01-24 18:18:54 +00001161 return cl_esp;
1162}
1163
1164/*====================================================================*/
1165/*=== Find executable ===*/
1166/*====================================================================*/
1167
thughes4ad52d02004-06-27 17:37:21 +00001168static const char* executable_name;
1169
1170static Bool match_executable(const char *entry) {
1171 char buf[strlen(entry) + strlen(executable_name) + 2];
1172
1173 /* empty PATH element means . */
1174 if (*entry == '\0')
1175 entry = ".";
1176
1177 snprintf(buf, sizeof(buf), "%s/%s", entry, executable_name);
1178
1179 if (access(buf, R_OK|X_OK) == 0) {
1180 executable_name = strdup(buf);
1181 vg_assert(NULL != executable_name);
1182 return True;
1183 }
1184 return False;
1185}
1186
nethercote71980f02004-01-24 18:18:54 +00001187static const char* find_executable(const char* exec)
1188{
1189 vg_assert(NULL != exec);
thughes4ad52d02004-06-27 17:37:21 +00001190 executable_name = exec;
1191 if (strchr(executable_name, '/') == NULL) {
nethercote71980f02004-01-24 18:18:54 +00001192 /* no '/' - we need to search the path */
1193 char *path = getenv("PATH");
thughes4ad52d02004-06-27 17:37:21 +00001194 scan_colsep(path, match_executable);
nethercote71980f02004-01-24 18:18:54 +00001195 }
thughes4ad52d02004-06-27 17:37:21 +00001196 return executable_name;
nethercote71980f02004-01-24 18:18:54 +00001197}
1198
1199
1200/*====================================================================*/
1201/*=== Loading tools ===*/
1202/*====================================================================*/
1203
1204static void list_tools(void)
1205{
1206 DIR *dir = opendir(VG_(libdir));
1207 struct dirent *de;
1208 int first = 1;
1209
1210 if (dir == NULL) {
1211 fprintf(stderr, "Can't open %s: %s (installation problem?)\n",
nethercotef4928da2004-06-15 10:54:40 +00001212 VG_(libdir), strerror(errno));
nethercote71980f02004-01-24 18:18:54 +00001213 return;
1214 }
1215
nethercotef4928da2004-06-15 10:54:40 +00001216 while ((de = readdir(dir)) != NULL) {
nethercote71980f02004-01-24 18:18:54 +00001217 int len = strlen(de->d_name);
1218
1219 /* look for vgskin_TOOL.so names */
1220 if (len > (7+1+3) && /* "vgskin_" + at least 1-char toolname + ".so" */
nethercotef4928da2004-06-15 10:54:40 +00001221 strncmp(de->d_name, "vgskin_", 7) == 0 &&
1222 VG_STREQ(de->d_name + len - 3, ".so")) {
1223 if (first) {
1224 fprintf(stderr, "Available tools:\n");
1225 first = 0;
1226 }
1227 de->d_name[len-3] = '\0';
1228 fprintf(stderr, "\t%s\n", de->d_name+7);
nethercote71980f02004-01-24 18:18:54 +00001229 }
1230 }
1231
1232 closedir(dir);
1233
1234 if (first)
nethercotef4928da2004-06-15 10:54:40 +00001235 fprintf(stderr, "No tools available in \"%s\" (installation problem?)\n",
1236 VG_(libdir));
nethercote71980f02004-01-24 18:18:54 +00001237}
1238
1239
1240/* Find and load a tool, and check it looks ok. Also looks to see if there's
1241 * a matching vgpreload_*.so file, and returns its name in *preloadpath. */
1242static void load_tool( const char *toolname, void** handle_out,
1243 ToolInfo** toolinfo_out, char **preloadpath_out )
1244{
1245 Bool ok;
1246 int len = strlen(VG_(libdir)) + strlen(toolname)*2 + 16;
1247 char buf[len];
1248 void* handle;
1249 ToolInfo* toolinfo;
1250 char* preloadpath = NULL;
1251 Int* vg_malloc_redzonep;
1252
1253 // XXX: allowing full paths for --tool option -- does it make sense?
1254 // Doesn't allow for vgpreload_<tool>.so.
1255
1256 if (strchr(toolname, '/') != 0) {
1257 /* toolname contains '/', and so must be a pathname */
1258 handle = dlopen(toolname, RTLD_NOW);
1259 } else {
1260 /* just try in the libdir */
1261 snprintf(buf, len, "%s/vgskin_%s.so", VG_(libdir), toolname);
1262 handle = dlopen(buf, RTLD_NOW);
1263
1264 if (handle != NULL) {
1265 snprintf(buf, len, "%s/vgpreload_%s.so", VG_(libdir), toolname);
1266 if (access(buf, R_OK) == 0) {
1267 preloadpath = strdup(buf);
1268 vg_assert(NULL != preloadpath);
1269 }
1270 }
1271 }
1272
1273 ok = (NULL != handle);
1274 if (!ok) {
1275 fprintf(stderr, "Can't open tool \"%s\": %s\n", toolname, dlerror());
1276 goto bad_load;
1277 }
1278
1279 toolinfo = dlsym(handle, "vgSkin_tool_info");
1280 ok = (NULL != toolinfo);
1281 if (!ok) {
1282 fprintf(stderr, "Tool \"%s\" doesn't define SK_(tool_info) - "
1283 "add VG_DETERMINE_INTERFACE_VERSION?\n", toolname);
1284 goto bad_load;
1285 }
1286
1287 ok = (toolinfo->sizeof_ToolInfo == sizeof(*toolinfo) &&
1288 toolinfo->interface_major_version == VG_CORE_INTERFACE_MAJOR_VERSION &&
1289 toolinfo->sk_pre_clo_init != NULL);
1290 if (!ok) {
1291 fprintf(stderr, "Error:\n"
1292 " Tool and core interface versions do not match.\n"
1293 " Interface version used by core is: %d.%d (size %d)\n"
1294 " Interface version used by tool is: %d.%d (size %d)\n"
1295 " The major version numbers must match.\n",
1296 VG_CORE_INTERFACE_MAJOR_VERSION,
1297 VG_CORE_INTERFACE_MINOR_VERSION,
1298 sizeof(*toolinfo),
1299 toolinfo->interface_major_version,
1300 toolinfo->interface_minor_version,
1301 toolinfo->sizeof_ToolInfo);
1302 fprintf(stderr, " You need to at least recompile, and possibly update,\n");
1303 if (VG_CORE_INTERFACE_MAJOR_VERSION > toolinfo->interface_major_version)
nethercote996901a2004-08-03 13:29:09 +00001304 fprintf(stderr, " your tool to work with this version of Valgrind.\n");
nethercote71980f02004-01-24 18:18:54 +00001305 else
nethercote996901a2004-08-03 13:29:09 +00001306 fprintf(stderr, " your version of Valgrind to work with this tool.\n");
nethercote71980f02004-01-24 18:18:54 +00001307 goto bad_load;
1308 }
1309
1310 // Set redzone size for V's allocator
1311 vg_malloc_redzonep = dlsym(handle, STR(VG_(vg_malloc_redzone_szB)));
1312 if ( NULL != vg_malloc_redzonep ) {
1313 VG_(vg_malloc_redzone_szB) = *vg_malloc_redzonep;
1314 }
1315
1316 vg_assert(NULL != handle && NULL != toolinfo);
1317 *handle_out = handle;
1318 *toolinfo_out = toolinfo;
1319 *preloadpath_out = preloadpath;
1320 return;
1321
1322
1323 bad_load:
1324 if (handle != NULL)
1325 dlclose(handle);
1326
nethercotef4928da2004-06-15 10:54:40 +00001327 fprintf(stderr, "valgrind: couldn't load tool\n");
nethercote71980f02004-01-24 18:18:54 +00001328 list_tools();
1329 exit(127);
1330}
1331
nethercotef4928da2004-06-15 10:54:40 +00001332
1333/*====================================================================*/
1334/*=== Command line errors ===*/
1335/*====================================================================*/
1336
1337static void abort_msg ( void )
1338{
nethercotef8548672004-06-21 12:42:35 +00001339 VG_(clo_log_to) = VgLogTo_Fd;
1340 VG_(clo_log_fd) = 2; /* stderr */
nethercotef4928da2004-06-15 10:54:40 +00001341}
1342
1343void VG_(bad_option) ( Char* opt )
1344{
1345 abort_msg();
1346 VG_(printf)("valgrind: Bad option `%s'; aborting.\n", opt);
1347 VG_(printf)("valgrind: Use --help for more information.\n");
1348 VG_(exit)(1);
1349}
1350
1351static void missing_tool_option ( void )
1352{
1353 abort_msg();
1354 VG_(printf)("valgrind: Missing --tool option\n");
1355 list_tools();
1356 VG_(printf)("valgrind: Use --help for more information.\n");
1357 VG_(exit)(1);
1358}
1359
1360static void missing_prog ( void )
1361{
1362 abort_msg();
1363 VG_(printf)("valgrind: no program specified\n");
1364 VG_(printf)("valgrind: Use --help for more information.\n");
1365 VG_(exit)(1);
1366}
1367
1368static void config_error ( Char* msg )
1369{
1370 abort_msg();
1371 VG_(printf)("valgrind: Startup or configuration error:\n %s\n", msg);
1372 VG_(printf)("valgrind: Unable to start up properly. Giving up.\n");
1373 VG_(exit)(1);
1374}
1375
1376
nethercote71980f02004-01-24 18:18:54 +00001377/*====================================================================*/
1378/*=== Loading the client ===*/
1379/*====================================================================*/
1380
nethercotef4928da2004-06-15 10:54:40 +00001381static void load_client(char* cl_argv[], const char* exec, Int need_help,
nethercote71980f02004-01-24 18:18:54 +00001382 /*out*/struct exeinfo* info, /*out*/Addr* client_eip)
1383{
1384 // If they didn't specify an executable with --exec, and didn't specify
1385 // --help, then use client argv[0] (searching $PATH if necessary).
nethercotef4928da2004-06-15 10:54:40 +00001386 if (NULL == exec && !need_help) {
nethercote71980f02004-01-24 18:18:54 +00001387 if (cl_argv[0] == NULL ||
1388 ( NULL == (exec = find_executable(cl_argv[0])) ) )
1389 {
nethercotef4928da2004-06-15 10:54:40 +00001390 missing_prog();
nethercote71980f02004-01-24 18:18:54 +00001391 }
1392 }
1393
1394 info->map_base = VG_(client_mapbase);
nethercote71980f02004-01-24 18:18:54 +00001395 info->exe_base = VG_(client_base);
1396 info->exe_end = VG_(client_end);
1397 info->argv = cl_argv;
1398
nethercotef4928da2004-06-15 10:54:40 +00001399 if (need_help) {
nethercote71980f02004-01-24 18:18:54 +00001400 VG_(clexecfd) = -1;
nethercoteea147e72004-07-26 15:43:57 +00001401 // Set the minimal number of entries in 'info' to continue.
nethercoted6a56872004-07-26 15:32:47 +00001402 info->interp_name = NULL;
1403 info->interp_args = NULL;
nethercote71980f02004-01-24 18:18:54 +00001404 } else {
1405 Int ret;
1406 VG_(clexecfd) = VG_(open)(exec, O_RDONLY, VKI_S_IRUSR);
1407 ret = do_exec(exec, info);
1408 if (ret != 0) {
nethercoteea147e72004-07-26 15:43:57 +00001409 fprintf(stderr, "valgrind: do_exec(%s) failed: %s\n",
1410 exec, strerror(ret));
nethercote71980f02004-01-24 18:18:54 +00001411 exit(127);
1412 }
1413 }
1414
1415 /* Copy necessary bits of 'info' that were filled in */
1416 *client_eip = info->init_eip;
1417 VG_(brk_base) = VG_(brk_limit) = info->brkbase;
1418}
1419
1420
1421/*====================================================================*/
nethercotef6a1d502004-08-09 12:21:57 +00001422/*=== Command-line: variables, processing, etc ===*/
nethercote71980f02004-01-24 18:18:54 +00001423/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +00001424
njn25e49d8e72002-09-23 09:36:25 +00001425/* Define, and set defaults. */
1426Bool VG_(clo_error_limit) = True;
nethercote04d0fbc2004-01-26 16:48:06 +00001427Bool VG_(clo_db_attach) = False;
1428Char* VG_(clo_db_command) = VG_CLO_DEFAULT_DBCOMMAND;
njn43c799e2003-04-08 00:08:52 +00001429Bool VG_(clo_gen_suppressions) = False;
nethercote27fec902004-06-16 21:26:32 +00001430Int VG_(clo_sanity_level) = 1;
njn25e49d8e72002-09-23 09:36:25 +00001431Int VG_(clo_verbosity) = 1;
1432Bool VG_(clo_demangle) = True;
njn25e49d8e72002-09-23 09:36:25 +00001433Bool VG_(clo_trace_children) = False;
sewardj4cf05692002-10-27 20:28:29 +00001434
nethercotee1730692003-11-20 10:38:07 +00001435/* See big comment in vg_include.h for meaning of these three.
1436 fd is initially stdout, for --help, but gets moved to stderr by default
1437 immediately afterwards. */
sewardj4cf05692002-10-27 20:28:29 +00001438VgLogTo VG_(clo_log_to) = VgLogTo_Fd;
nethercotef8548672004-06-21 12:42:35 +00001439Int VG_(clo_log_fd) = 1;
1440Char* VG_(clo_log_name) = NULL;
sewardj4cf05692002-10-27 20:28:29 +00001441
sewardj6024b212003-07-13 10:54:33 +00001442Int VG_(clo_input_fd) = 0; /* stdin */
njn25e49d8e72002-09-23 09:36:25 +00001443Int VG_(clo_n_suppressions) = 0;
sewardjde4a1d02002-03-22 01:27:54 +00001444Char* VG_(clo_suppressions)[VG_CLO_MAX_SFILES];
njn25e49d8e72002-09-23 09:36:25 +00001445Bool VG_(clo_profile) = False;
1446Bool VG_(clo_single_step) = False;
1447Bool VG_(clo_optimise) = True;
1448UChar VG_(clo_trace_codegen) = 0; // 00000000b
1449Bool VG_(clo_trace_syscalls) = False;
1450Bool VG_(clo_trace_signals) = False;
1451Bool VG_(clo_trace_symtab) = False;
njn25e49d8e72002-09-23 09:36:25 +00001452Bool VG_(clo_trace_sched) = False;
1453Int VG_(clo_trace_pthread_level) = 0;
njn25e49d8e72002-09-23 09:36:25 +00001454Int VG_(clo_dump_error) = 0;
1455Int VG_(clo_backtrace_size) = 4;
1456Char* VG_(clo_weird_hacks) = NULL;
sewardj858964b2002-10-05 14:15:43 +00001457Bool VG_(clo_run_libc_freeres) = True;
rjwalshf5f536f2003-11-17 17:45:00 +00001458Bool VG_(clo_track_fds) = False;
sewardj22854b92002-11-30 14:00:47 +00001459Bool VG_(clo_chain_bb) = True;
nethercote77eba602003-11-13 17:35:04 +00001460Bool VG_(clo_show_below_main) = False;
fitzhardinge98abfc72003-12-16 02:05:15 +00001461Bool VG_(clo_pointercheck) = True;
fitzhardinge462f4f92003-12-18 02:10:54 +00001462Bool VG_(clo_branchpred) = False;
sewardj2370f3b2002-11-30 15:01:01 +00001463
jsgf855d93d2003-10-13 22:26:55 +00001464static Bool VG_(clo_wait_for_gdb) = False;
1465
1466/* If we're doing signal routing, poll for signals every 50mS by
1467 default. */
1468Int VG_(clo_signal_polltime) = 50;
1469
1470/* These flags reduce thread wakeup latency on syscall completion and
1471 signal delivery, respectively. The downside is possible unfairness. */
1472Bool VG_(clo_lowlat_syscalls) = False; /* low-latency syscalls */
1473Bool VG_(clo_lowlat_signals) = False; /* low-latency signals */
1474
sewardjde4a1d02002-03-22 01:27:54 +00001475
nethercote6c999f22004-01-31 22:55:15 +00001476void usage ( Bool debug_help )
njn7cf0bd32002-06-08 13:36:03 +00001477{
njn25e49d8e72002-09-23 09:36:25 +00001478 Char* usage1 =
nethercote71980f02004-01-24 18:18:54 +00001479"usage: valgrind --tool=<toolname> [options] prog-and-args\n"
njn25e49d8e72002-09-23 09:36:25 +00001480"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001481" common user options for all Valgrind tools, with defaults in [ ]:\n"
nethercote0d588502004-06-21 13:27:11 +00001482" --tool=<name> use the Valgrind tool named <name>\n"
nethercotea76368b2004-06-16 11:56:29 +00001483" -h --help show this message\n"
nethercote6c999f22004-01-31 22:55:15 +00001484" --help-debug show this message, plus debugging options\n"
njn25e49d8e72002-09-23 09:36:25 +00001485" --version show version\n"
njn25e49d8e72002-09-23 09:36:25 +00001486" -q --quiet run silently; only print error msgs\n"
1487" -v --verbose be more verbose, incl counts of errors\n"
nethercote77eba602003-11-13 17:35:04 +00001488" --trace-children=no|yes Valgrind-ise child processes? [no]\n"
nethercote0d588502004-06-21 13:27:11 +00001489" --track-fds=no|yes track open file descriptors? [no]\n"
nethercote2b0793f2003-12-02 10:41:18 +00001490"\n"
1491" uncommon user options for all Valgrind tools:\n"
nethercote0d588502004-06-21 13:27:11 +00001492" --run-libc-freeres=no|yes free up glibc memory at exit? [yes]\n"
1493" --weird-hacks=hack1,hack2,... recognised hacks: lax-ioctls [none]\n"
1494" --signal-polltime=<time> signal poll period (mS) for older kernels [50]\n"
1495" --lowlat-signals=no|yes improve thread signal wake-up latency [no]\n"
1496" --lowlat-syscalls=no|yes improve thread syscall wake-up latency [no]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001497" --pointercheck=no|yes enforce client address space limits [yes]\n"
njn25e49d8e72002-09-23 09:36:25 +00001498"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001499" user options for Valgrind tools that report errors:\n"
nethercotef8548672004-06-21 12:42:35 +00001500" --log-fd=<number> log messages to file descriptor [2=stderr]\n"
1501" --log-file=<file> log messages to <file>.pid<pid>\n"
1502" --log-socket=ipaddr:port log messages to socket ipaddr:port\n"
nethercote2b0793f2003-12-02 10:41:18 +00001503" --demangle=no|yes automatically demangle C++ names? [yes]\n"
1504" --num-callers=<number> show <num> callers in stack traces [4]\n"
1505" --error-limit=no|yes stop showing new errors if too many? [yes]\n"
1506" --show-below-main=no|yes continue stack traces below main() [no]\n"
1507" --suppressions=<filename> suppress errors described in <filename>\n"
1508" --gen-suppressions=no|yes print suppressions for errors detected [no]\n"
nethercote04d0fbc2004-01-26 16:48:06 +00001509" --db-attach=no|yes start debugger when errors detected? [no]\n"
1510" --db-command=<command> command to start debugger [gdb -nw %%f %%p]\n"
1511" --input-fd=<number> file descriptor for input [0=stdin]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001512"\n";
njn7cf0bd32002-06-08 13:36:03 +00001513
njn25e49d8e72002-09-23 09:36:25 +00001514 Char* usage2 =
1515"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001516" debugging options for all Valgrind tools:\n"
njn25e49d8e72002-09-23 09:36:25 +00001517" --sanity-level=<number> level of sanity checking to do [1]\n"
1518" --single-step=no|yes translate each instr separately? [no]\n"
1519" --optimise=no|yes improve intermediate code? [yes]\n"
nethercote137bc552003-11-14 17:47:54 +00001520" --profile=no|yes profile? (tool must be built for it) [no]\n"
sewardj22854b92002-11-30 14:00:47 +00001521" --chain-bb=no|yes do basic-block chaining? [yes]\n"
fitzhardinge462f4f92003-12-18 02:10:54 +00001522" --branchpred=yes|no generate branch prediction hints [no]\n"
njn25e49d8e72002-09-23 09:36:25 +00001523" --trace-codegen=<XXXXX> show generated code? (X = 0|1) [00000]\n"
1524" --trace-syscalls=no|yes show all system calls? [no]\n"
1525" --trace-signals=no|yes show signal handling details? [no]\n"
1526" --trace-symtab=no|yes show symbol table details? [no]\n"
njn25e49d8e72002-09-23 09:36:25 +00001527" --trace-sched=no|yes show thread scheduler details? [no]\n"
njn3e884182003-04-15 13:03:23 +00001528" --trace-pthread=none|some|all show pthread event details? [none]\n"
jsgf855d93d2003-10-13 22:26:55 +00001529" --wait-for-gdb=yes|no pause on startup to wait for gdb attach\n"
njn25e49d8e72002-09-23 09:36:25 +00001530"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001531" debugging options for Valgrind tools that report errors\n"
1532" --dump-error=<number> show translation for basic block associated\n"
1533" with <number>'th error context [0=show none]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001534"\n";
njn3e884182003-04-15 13:03:23 +00001535
1536 Char* usage3 =
1537"\n"
nethercote71980f02004-01-24 18:18:54 +00001538" Extra options read from ~/.valgrindrc, $VALGRIND_OPTS, ./.valgrindrc\n"
njn25e49d8e72002-09-23 09:36:25 +00001539"\n"
nethercote08fa9a72004-07-16 17:44:00 +00001540" Valgrind is Copyright (C) 2000-2004 Julian Seward et al.\n"
njn25e49d8e72002-09-23 09:36:25 +00001541" and licensed under the GNU General Public License, version 2.\n"
1542" Bug reports, feedback, admiration, abuse, etc, to: %s.\n"
njnd04b7c62002-10-03 14:05:52 +00001543"\n"
nethercote137bc552003-11-14 17:47:54 +00001544" Tools are copyright and licensed by their authors. See each\n"
1545" tool's start-up message for more information.\n"
njn25e49d8e72002-09-23 09:36:25 +00001546"\n";
njn7cf0bd32002-06-08 13:36:03 +00001547
fitzhardinge98abfc72003-12-16 02:05:15 +00001548 VG_(printf)(usage1);
1549 if (VG_(details).name) {
1550 VG_(printf)(" user options for %s:\n", VG_(details).name);
fitzhardinge98abfc72003-12-16 02:05:15 +00001551 if (VG_(needs).command_line_options)
1552 SK_(print_usage)();
1553 else
1554 VG_(printf)(" (none)\n");
1555 }
nethercote6c999f22004-01-31 22:55:15 +00001556 if (debug_help) {
1557 VG_(printf)(usage2);
fitzhardinge98abfc72003-12-16 02:05:15 +00001558
nethercote6c999f22004-01-31 22:55:15 +00001559 if (VG_(details).name) {
1560 VG_(printf)(" debugging options for %s:\n", VG_(details).name);
1561
1562 if (VG_(needs).command_line_options)
1563 SK_(print_debug_usage)();
1564 else
1565 VG_(printf)(" (none)\n");
1566 }
fitzhardinge98abfc72003-12-16 02:05:15 +00001567 }
nethercote421281e2003-11-20 16:20:55 +00001568 VG_(printf)(usage3, VG_BUGS_TO);
nethercotef4928da2004-06-15 10:54:40 +00001569 VG_(exit)(0);
njn7cf0bd32002-06-08 13:36:03 +00001570}
sewardjde4a1d02002-03-22 01:27:54 +00001571
nethercote71980f02004-01-24 18:18:54 +00001572static void pre_process_cmd_line_options
nethercote6c999f22004-01-31 22:55:15 +00001573 ( Int* need_help, const char** tool, const char** exec )
sewardj1c1b1162003-02-23 01:25:51 +00001574{
nethercote71980f02004-01-24 18:18:54 +00001575 UInt i;
sewardjde4a1d02002-03-22 01:27:54 +00001576
nethercote71980f02004-01-24 18:18:54 +00001577 /* parse the options we have (only the options we care about now) */
nethercotef6a1d502004-08-09 12:21:57 +00001578 for (i = 1; i < vg_argc; i++) {
nethercote71980f02004-01-24 18:18:54 +00001579
nethercotef6a1d502004-08-09 12:21:57 +00001580 if (strcmp(vg_argv[i], "--version") == 0) {
nethercote71980f02004-01-24 18:18:54 +00001581 printf("valgrind-" VERSION "\n");
nethercotef4928da2004-06-15 10:54:40 +00001582 exit(0);
nethercote71980f02004-01-24 18:18:54 +00001583
nethercotef6a1d502004-08-09 12:21:57 +00001584 } else if (VG_CLO_STREQ(vg_argv[i], "--help") ||
1585 VG_CLO_STREQ(vg_argv[i], "-h")) {
nethercote6c999f22004-01-31 22:55:15 +00001586 *need_help = 1;
1587
nethercotef6a1d502004-08-09 12:21:57 +00001588 } else if (VG_CLO_STREQ(vg_argv[i], "--help-debug")) {
nethercote6c999f22004-01-31 22:55:15 +00001589 *need_help = 2;
nethercote71980f02004-01-24 18:18:54 +00001590
nethercotef6a1d502004-08-09 12:21:57 +00001591 } else if (VG_CLO_STREQN(7, vg_argv[i], "--tool=") ||
1592 VG_CLO_STREQN(7, vg_argv[i], "--skin=")) {
1593 *tool = &vg_argv[i][7];
nethercote71980f02004-01-24 18:18:54 +00001594
nethercotef6a1d502004-08-09 12:21:57 +00001595 } else if (VG_CLO_STREQN(7, vg_argv[i], "--exec=")) {
1596 *exec = &vg_argv[i][7];
nethercote71980f02004-01-24 18:18:54 +00001597 }
1598 }
1599
nethercotef4928da2004-06-15 10:54:40 +00001600 /* If no tool specified, can act appropriately without loading tool */
nethercote71980f02004-01-24 18:18:54 +00001601 if (*tool == NULL) {
nethercotef4928da2004-06-15 10:54:40 +00001602 if (0 == *need_help) {
1603 // neither --tool nor --help/--help-debug specified
1604 missing_tool_option();
1605 } else {
1606 // Give help message, without any tool-specific help
1607 usage(/*help-debug?*/2 == *need_help);
1608 }
nethercote71980f02004-01-24 18:18:54 +00001609 }
1610}
1611
nethercote5ee67ca2004-06-22 14:00:09 +00001612static void process_cmd_line_options( UInt* client_auxv, const char* toolname )
nethercote71980f02004-01-24 18:18:54 +00001613{
nethercotef8548672004-06-21 12:42:35 +00001614 Int i, eventually_log_fd;
nethercote71980f02004-01-24 18:18:54 +00001615 Int *auxp;
1616 Int toolname_len = VG_(strlen)(toolname);
sewardjde4a1d02002-03-22 01:27:54 +00001617
nethercotee1730692003-11-20 10:38:07 +00001618 /* log to stderr by default, but usage message goes to stdout */
nethercotef8548672004-06-21 12:42:35 +00001619 eventually_log_fd = 2;
sewardjde4a1d02002-03-22 01:27:54 +00001620
sewardj19d81412002-06-03 01:10:40 +00001621 /* Check for sane path in ./configure --prefix=... */
fitzhardinge98abfc72003-12-16 02:05:15 +00001622 if (VG_LIBDIR[0] != '/')
sewardj19d81412002-06-03 01:10:40 +00001623 config_error("Please use absolute paths in "
1624 "./configure --prefix=... or --libdir=...");
sewardj38170912002-05-10 21:07:22 +00001625
nethercote71980f02004-01-24 18:18:54 +00001626 for (auxp = client_auxv; auxp[0] != VKI_AT_NULL; auxp += 2) {
fitzhardinge98abfc72003-12-16 02:05:15 +00001627 switch(auxp[0]) {
1628 case VKI_AT_SYSINFO:
fitzhardinge92360792003-12-24 10:11:11 +00001629 auxp[1] = (Int)(VG_(client_trampoline_code) + VG_(tramp_syscall_offset));
fitzhardinge98abfc72003-12-16 02:05:15 +00001630 break;
sewardjde4a1d02002-03-22 01:27:54 +00001631 }
fitzhardinge98abfc72003-12-16 02:05:15 +00001632 }
sewardjde4a1d02002-03-22 01:27:54 +00001633
nethercotef6a1d502004-08-09 12:21:57 +00001634 for (i = 1; i < vg_argc; i++) {
nethercote71980f02004-01-24 18:18:54 +00001635
nethercotef6a1d502004-08-09 12:21:57 +00001636 Char* arg = vg_argv[i];
thughes3bfd5a02004-07-18 08:05:44 +00001637 Char* colon = arg;
nethercote71980f02004-01-24 18:18:54 +00001638
thughes3bfd5a02004-07-18 08:05:44 +00001639 /* Look for a colon in the switch name */
1640 while (*colon && *colon != ':' && *colon != '=')
1641 colon++;
nethercote71980f02004-01-24 18:18:54 +00001642
1643 /* Look for matching "--toolname:foo" */
thughes3bfd5a02004-07-18 08:05:44 +00001644 if (*colon == ':') {
nethercote71980f02004-01-24 18:18:54 +00001645 if (VG_CLO_STREQN(2, arg, "--") &&
1646 VG_CLO_STREQN(toolname_len, arg+2, toolname) &&
1647 VG_CLO_STREQN(1, arg+2+toolname_len, ":"))
1648 {
1649 // prefix matches, convert "--toolname:foo" to "--foo"
1650 if (0)
1651 VG_(printf)("tool-specific arg: %s\n", arg);
1652 arg += toolname_len + 1;
1653 arg[0] = '-';
1654 arg[1] = '-';
1655
1656 } else {
1657 // prefix doesn't match, skip to next arg
1658 continue;
1659 }
1660 }
1661
fitzhardinge98abfc72003-12-16 02:05:15 +00001662 /* Ignore these options - they've already been handled */
nethercote71980f02004-01-24 18:18:54 +00001663 if (VG_CLO_STREQN(7, arg, "--tool=") ||
1664 VG_CLO_STREQN(7, arg, "--skin="))
fitzhardinge98abfc72003-12-16 02:05:15 +00001665 continue;
nethercote71980f02004-01-24 18:18:54 +00001666 if (VG_CLO_STREQN(7, arg, "--exec="))
fitzhardinge98abfc72003-12-16 02:05:15 +00001667 continue;
1668
nethercote71980f02004-01-24 18:18:54 +00001669 if ( VG_CLO_STREQ(arg, "--"))
fitzhardinge98abfc72003-12-16 02:05:15 +00001670 continue;
nethercote27fec902004-06-16 21:26:32 +00001671
nethercote71980f02004-01-24 18:18:54 +00001672 else if (VG_CLO_STREQ(arg, "-v") ||
1673 VG_CLO_STREQ(arg, "--verbose"))
sewardjde4a1d02002-03-22 01:27:54 +00001674 VG_(clo_verbosity)++;
nethercote27fec902004-06-16 21:26:32 +00001675
nethercote71980f02004-01-24 18:18:54 +00001676 else if (VG_CLO_STREQ(arg, "-q") ||
1677 VG_CLO_STREQ(arg, "--quiet"))
sewardjde4a1d02002-03-22 01:27:54 +00001678 VG_(clo_verbosity)--;
1679
nethercote27fec902004-06-16 21:26:32 +00001680 else VG_BOOL_CLO("--branchpred", VG_(clo_branchpred))
1681 else VG_BOOL_CLO("--chain-bb", VG_(clo_chain_bb))
1682 else VG_BOOL_CLO("--db-attach", VG_(clo_db_attach))
1683 else VG_BOOL_CLO("--demangle", VG_(clo_demangle))
1684 else VG_BOOL_CLO("--error-limit", VG_(clo_error_limit))
1685 else VG_BOOL_CLO("--gen-suppressions", VG_(clo_gen_suppressions))
1686 else VG_BOOL_CLO("--lowlat-signals", VG_(clo_lowlat_signals))
1687 else VG_BOOL_CLO("--lowlat-syscalls", VG_(clo_lowlat_syscalls))
1688 else VG_BOOL_CLO("--optimise", VG_(clo_optimise))
1689 else VG_BOOL_CLO("--pointercheck", VG_(clo_pointercheck))
1690 else VG_BOOL_CLO("--profile", VG_(clo_profile))
1691 else VG_BOOL_CLO("--run-libc-freeres", VG_(clo_run_libc_freeres))
1692 else VG_BOOL_CLO("--show-below-main", VG_(clo_show_below_main))
1693 else VG_BOOL_CLO("--single-step", VG_(clo_single_step))
1694 else VG_BOOL_CLO("--track-fds", VG_(clo_track_fds))
1695 else VG_BOOL_CLO("--trace-children", VG_(clo_trace_children))
1696 else VG_BOOL_CLO("--trace-sched", VG_(clo_trace_sched))
1697 else VG_BOOL_CLO("--trace-signals", VG_(clo_trace_signals))
1698 else VG_BOOL_CLO("--trace-symtab", VG_(clo_trace_symtab))
1699 else VG_BOOL_CLO("--trace-syscalls", VG_(clo_trace_syscalls))
1700 else VG_BOOL_CLO("--wait-for-gdb", VG_(clo_wait_for_gdb))
sewardj72f98ff2002-06-13 17:23:38 +00001701
nethercote27fec902004-06-16 21:26:32 +00001702 else VG_STR_CLO ("--db-command", VG_(clo_db_command))
1703 else VG_STR_CLO ("--weird-hacks", VG_(clo_weird_hacks))
sewardjde4a1d02002-03-22 01:27:54 +00001704
nethercote27fec902004-06-16 21:26:32 +00001705 else VG_NUM_CLO ("--dump-error", VG_(clo_dump_error))
1706 else VG_NUM_CLO ("--input-fd", VG_(clo_input_fd))
1707 else VG_NUM_CLO ("--sanity-level", VG_(clo_sanity_level))
1708 else VG_NUM_CLO ("--signal­polltime", VG_(clo_signal_polltime))
1709 else VG_BNUM_CLO("--num-callers", VG_(clo_backtrace_size), 1,
1710 VG_DEEPEST_BACKTRACE)
sewardjde4a1d02002-03-22 01:27:54 +00001711
nethercotef8548672004-06-21 12:42:35 +00001712 // for backwards compatibility, replaced by --log-fd
nethercote71980f02004-01-24 18:18:54 +00001713 else if (VG_CLO_STREQN(13, arg, "--logfile-fd=")) {
nethercotef8548672004-06-21 12:42:35 +00001714 VG_(clo_log_to) = VgLogTo_Fd;
1715 VG_(clo_log_name) = NULL;
1716 eventually_log_fd = (Int)VG_(atoll)(&arg[13]);
1717 }
1718 else if (VG_CLO_STREQN(9, arg, "--log-fd=")) {
1719 VG_(clo_log_to) = VgLogTo_Fd;
1720 VG_(clo_log_name) = NULL;
1721 eventually_log_fd = (Int)VG_(atoll)(&arg[9]);
sewardj4cf05692002-10-27 20:28:29 +00001722 }
1723
nethercotef8548672004-06-21 12:42:35 +00001724 // for backwards compatibility, replaced by --log-file
nethercote71980f02004-01-24 18:18:54 +00001725 else if (VG_CLO_STREQN(10, arg, "--logfile=")) {
nethercotef8548672004-06-21 12:42:35 +00001726 VG_(clo_log_to) = VgLogTo_File;
1727 VG_(clo_log_name) = &arg[10];
1728 }
1729 else if (VG_CLO_STREQN(11, arg, "--log-file=")) {
1730 VG_(clo_log_to) = VgLogTo_File;
1731 VG_(clo_log_name) = &arg[11];
sewardj4cf05692002-10-27 20:28:29 +00001732 }
sewardjde4a1d02002-03-22 01:27:54 +00001733
nethercotef8548672004-06-21 12:42:35 +00001734 // for backwards compatibility, replaced by --log-socket
nethercote71980f02004-01-24 18:18:54 +00001735 else if (VG_CLO_STREQN(12, arg, "--logsocket=")) {
nethercotef8548672004-06-21 12:42:35 +00001736 VG_(clo_log_to) = VgLogTo_Socket;
1737 VG_(clo_log_name) = &arg[12];
1738 }
1739 else if (VG_CLO_STREQN(13, arg, "--log-socket=")) {
1740 VG_(clo_log_to) = VgLogTo_Socket;
1741 VG_(clo_log_name) = &arg[13];
sewardj73cf3bc2002-11-03 03:20:15 +00001742 }
1743
nethercote71980f02004-01-24 18:18:54 +00001744 else if (VG_CLO_STREQN(15, arg, "--suppressions=")) {
sewardjde4a1d02002-03-22 01:27:54 +00001745 if (VG_(clo_n_suppressions) >= VG_CLO_MAX_SFILES) {
njn25e49d8e72002-09-23 09:36:25 +00001746 VG_(message)(Vg_UserMsg, "Too many suppression files specified.");
sewardjde4a1d02002-03-22 01:27:54 +00001747 VG_(message)(Vg_UserMsg,
1748 "Increase VG_CLO_MAX_SFILES and recompile.");
nethercote71980f02004-01-24 18:18:54 +00001749 VG_(bad_option)(arg);
sewardjde4a1d02002-03-22 01:27:54 +00001750 }
nethercote71980f02004-01-24 18:18:54 +00001751 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = &arg[15];
sewardjde4a1d02002-03-22 01:27:54 +00001752 VG_(clo_n_suppressions)++;
1753 }
sewardjde4a1d02002-03-22 01:27:54 +00001754
njn25e49d8e72002-09-23 09:36:25 +00001755 /* "vwxyz" --> 000zyxwv (binary) */
nethercote71980f02004-01-24 18:18:54 +00001756 else if (VG_CLO_STREQN(16, arg, "--trace-codegen=")) {
njn25e49d8e72002-09-23 09:36:25 +00001757 Int j;
nethercote71980f02004-01-24 18:18:54 +00001758 char* opt = & arg[16];
njn25e49d8e72002-09-23 09:36:25 +00001759
1760 if (5 != VG_(strlen)(opt)) {
1761 VG_(message)(Vg_UserMsg,
1762 "--trace-codegen argument must have 5 digits");
nethercote71980f02004-01-24 18:18:54 +00001763 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001764 }
1765 for (j = 0; j < 5; j++) {
1766 if ('0' == opt[j]) { /* do nothing */ }
1767 else if ('1' == opt[j]) VG_(clo_trace_codegen) |= (1 << j);
1768 else {
1769 VG_(message)(Vg_UserMsg, "--trace-codegen argument can only "
1770 "contain 0s and 1s");
nethercote71980f02004-01-24 18:18:54 +00001771 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001772 }
1773 }
1774 }
sewardjde4a1d02002-03-22 01:27:54 +00001775
nethercote71980f02004-01-24 18:18:54 +00001776 else if (VG_CLO_STREQ(arg, "--trace-pthread=none"))
sewardj45b4b372002-04-16 22:50:32 +00001777 VG_(clo_trace_pthread_level) = 0;
nethercote71980f02004-01-24 18:18:54 +00001778 else if (VG_CLO_STREQ(arg, "--trace-pthread=some"))
sewardj45b4b372002-04-16 22:50:32 +00001779 VG_(clo_trace_pthread_level) = 1;
nethercote71980f02004-01-24 18:18:54 +00001780 else if (VG_CLO_STREQ(arg, "--trace-pthread=all"))
sewardj45b4b372002-04-16 22:50:32 +00001781 VG_(clo_trace_pthread_level) = 2;
sewardj8937c812002-04-12 20:12:20 +00001782
nethercote71980f02004-01-24 18:18:54 +00001783 else if ( ! VG_(needs).command_line_options
1784 || ! SK_(process_cmd_line_option)(arg) ) {
nethercotef4928da2004-06-15 10:54:40 +00001785 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001786 }
sewardjde4a1d02002-03-22 01:27:54 +00001787 }
1788
nethercote27fec902004-06-16 21:26:32 +00001789 // Check various option values
1790
njnf9ebf672003-05-12 21:41:30 +00001791 if (VG_(clo_verbosity) < 0)
sewardjde4a1d02002-03-22 01:27:54 +00001792 VG_(clo_verbosity) = 0;
1793
nethercote04d0fbc2004-01-26 16:48:06 +00001794 if (VG_(clo_db_attach) && VG_(clo_trace_children)) {
sewardjde4a1d02002-03-22 01:27:54 +00001795 VG_(message)(Vg_UserMsg, "");
1796 VG_(message)(Vg_UserMsg,
nethercote04d0fbc2004-01-26 16:48:06 +00001797 "--db-attach=yes conflicts with --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001798 VG_(message)(Vg_UserMsg,
1799 "Please choose one or the other, but not both.");
nethercote04d0fbc2004-01-26 16:48:06 +00001800 VG_(bad_option)("--db-attach=yes and --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001801 }
1802
nethercotef8548672004-06-21 12:42:35 +00001803 /* Set up logging now. After this is done, VG_(clo_log_fd)
sewardj4cf05692002-10-27 20:28:29 +00001804 should be connected to whatever sink has been selected, and we
1805 indiscriminately chuck stuff into it without worrying what the
1806 nature of it is. Oh the wonder of Unix streams. */
1807
nethercotee1730692003-11-20 10:38:07 +00001808 /* So far we should be still attached to stdout, so we can show on
sewardj4cf05692002-10-27 20:28:29 +00001809 the terminal any problems to do with processing command line
1810 opts. */
nethercotef8548672004-06-21 12:42:35 +00001811 vg_assert(VG_(clo_log_fd) == 1 /* stdout */);
sewardj73cf3bc2002-11-03 03:20:15 +00001812 vg_assert(VG_(logging_to_filedes) == True);
sewardj4cf05692002-10-27 20:28:29 +00001813
1814 switch (VG_(clo_log_to)) {
sewardj73cf3bc2002-11-03 03:20:15 +00001815
sewardj4cf05692002-10-27 20:28:29 +00001816 case VgLogTo_Fd:
nethercotef8548672004-06-21 12:42:35 +00001817 vg_assert(VG_(clo_log_name) == NULL);
1818 VG_(clo_log_fd) = eventually_log_fd;
sewardj4cf05692002-10-27 20:28:29 +00001819 break;
sewardj73cf3bc2002-11-03 03:20:15 +00001820
sewardj4cf05692002-10-27 20:28:29 +00001821 case VgLogTo_File: {
1822 Char logfilename[1000];
jsgff3c3f1a2003-10-14 22:13:28 +00001823 Int seq = 0;
1824 Int pid = VG_(getpid)();
1825
nethercotef8548672004-06-21 12:42:35 +00001826 vg_assert(VG_(clo_log_name) != NULL);
1827 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
jsgff3c3f1a2003-10-14 22:13:28 +00001828
nethercote71980f02004-01-24 18:18:54 +00001829 for (;;) {
jsgff3c3f1a2003-10-14 22:13:28 +00001830 if (seq == 0)
1831 VG_(sprintf)(logfilename, "%s.pid%d",
nethercotef8548672004-06-21 12:42:35 +00001832 VG_(clo_log_name), pid );
jsgff3c3f1a2003-10-14 22:13:28 +00001833 else
1834 VG_(sprintf)(logfilename, "%s.pid%d.%d",
nethercotef8548672004-06-21 12:42:35 +00001835 VG_(clo_log_name), pid, seq );
jsgff3c3f1a2003-10-14 22:13:28 +00001836 seq++;
1837
nethercotef8548672004-06-21 12:42:35 +00001838 eventually_log_fd
jsgff3c3f1a2003-10-14 22:13:28 +00001839 = VG_(open)(logfilename,
1840 VKI_O_CREAT|VKI_O_WRONLY|VKI_O_EXCL|VKI_O_TRUNC,
1841 VKI_S_IRUSR|VKI_S_IWUSR);
nethercotef8548672004-06-21 12:42:35 +00001842 if (eventually_log_fd >= 0) {
1843 VG_(clo_log_fd) = VG_(safe_fd)(eventually_log_fd);
jsgff3c3f1a2003-10-14 22:13:28 +00001844 break;
1845 } else {
nethercotef8548672004-06-21 12:42:35 +00001846 if (eventually_log_fd != -VKI_EEXIST) {
jsgff3c3f1a2003-10-14 22:13:28 +00001847 VG_(message)(Vg_UserMsg,
1848 "Can't create/open log file `%s.pid%d'; giving up!",
nethercotef8548672004-06-21 12:42:35 +00001849 VG_(clo_log_name), pid);
jsgff3c3f1a2003-10-14 22:13:28 +00001850 VG_(bad_option)(
nethercotef8548672004-06-21 12:42:35 +00001851 "--log-file=<file> didn't work out for some reason.");
jsgff3c3f1a2003-10-14 22:13:28 +00001852 break;
1853 }
1854 }
1855 }
sewardj4cf05692002-10-27 20:28:29 +00001856 break;
sewardj73cf3bc2002-11-03 03:20:15 +00001857 }
1858
1859 case VgLogTo_Socket: {
nethercotef8548672004-06-21 12:42:35 +00001860 vg_assert(VG_(clo_log_name) != NULL);
1861 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
1862 eventually_log_fd = VG_(connect_via_socket)( VG_(clo_log_name) );
1863 if (eventually_log_fd == -1) {
sewardj73cf3bc2002-11-03 03:20:15 +00001864 VG_(message)(Vg_UserMsg,
nethercotef8548672004-06-21 12:42:35 +00001865 "Invalid --log-socket=ipaddr or --log-socket=ipaddr:port spec");
sewardj73cf3bc2002-11-03 03:20:15 +00001866 VG_(message)(Vg_UserMsg,
nethercotef8548672004-06-21 12:42:35 +00001867 "of `%s'; giving up!", VG_(clo_log_name) );
sewardj73cf3bc2002-11-03 03:20:15 +00001868 VG_(bad_option)(
nethercotef8548672004-06-21 12:42:35 +00001869 "--log-socket=");
sewardj4cf05692002-10-27 20:28:29 +00001870 }
nethercotef8548672004-06-21 12:42:35 +00001871 if (eventually_log_fd == -2) {
sewardj73cf3bc2002-11-03 03:20:15 +00001872 VG_(message)(Vg_UserMsg,
sewardj570f8902002-11-03 11:44:36 +00001873 "valgrind: failed to connect to logging server `%s'.",
nethercotef8548672004-06-21 12:42:35 +00001874 VG_(clo_log_name) );
sewardj570f8902002-11-03 11:44:36 +00001875 VG_(message)(Vg_UserMsg,
1876 "Log messages will sent to stderr instead." );
1877 VG_(message)(Vg_UserMsg,
1878 "" );
1879 /* We don't change anything here. */
1880 } else {
nethercotef8548672004-06-21 12:42:35 +00001881 vg_assert(eventually_log_fd > 0);
1882 VG_(clo_log_fd) = eventually_log_fd;
sewardj570f8902002-11-03 11:44:36 +00001883 VG_(logging_to_filedes) = False;
1884 }
sewardj73cf3bc2002-11-03 03:20:15 +00001885 break;
1886 }
1887
sewardj4cf05692002-10-27 20:28:29 +00001888 }
1889
nethercotef8548672004-06-21 12:42:35 +00001890 /* Move log_fd into the safe range, so it doesn't conflict with any app fds */
thughesad1c9562004-06-26 11:27:52 +00001891 eventually_log_fd = VG_(fcntl)(VG_(clo_log_fd), VKI_F_DUPFD, VG_(fd_hard_limit));
nethercotef8548672004-06-21 12:42:35 +00001892 if (eventually_log_fd < 0)
jsgf855d93d2003-10-13 22:26:55 +00001893 VG_(message)(Vg_UserMsg, "valgrind: failed to move logfile fd into safe range");
1894 else {
nethercotef8548672004-06-21 12:42:35 +00001895 VG_(clo_log_fd) = eventually_log_fd;
1896 VG_(fcntl)(VG_(clo_log_fd), VKI_F_SETFD, VKI_FD_CLOEXEC);
jsgf855d93d2003-10-13 22:26:55 +00001897 }
1898
sewardj4cf05692002-10-27 20:28:29 +00001899 /* Ok, the logging sink is running now. Print a suitable preamble.
1900 If logging to file or a socket, write details of parent PID and
1901 command line args, to help people trying to interpret the
1902 results of a run which encompasses multiple processes. */
sewardjde4a1d02002-03-22 01:27:54 +00001903
sewardj83adf412002-05-01 01:25:45 +00001904 if (VG_(clo_verbosity > 0)) {
nethercote996901a2004-08-03 13:29:09 +00001905 /* Tool details */
njnd04b7c62002-10-03 14:05:52 +00001906 VG_(message)(Vg_UserMsg, "%s%s%s, %s for x86-linux.",
1907 VG_(details).name,
1908 NULL == VG_(details).version ? "" : "-",
1909 NULL == VG_(details).version
1910 ? (Char*)"" : VG_(details).version,
1911 VG_(details).description);
1912 VG_(message)(Vg_UserMsg, "%s", VG_(details).copyright_author);
sewardj3b2736a2002-03-24 12:18:35 +00001913
njnd04b7c62002-10-03 14:05:52 +00001914 /* Core details */
1915 VG_(message)(Vg_UserMsg,
njn3e884182003-04-15 13:03:23 +00001916 "Using valgrind-%s, a program supervision framework for x86-linux.",
sewardj4aa62ba2002-10-05 15:49:27 +00001917 VERSION);
sewardjde4a1d02002-03-22 01:27:54 +00001918 VG_(message)(Vg_UserMsg,
nethercote08fa9a72004-07-16 17:44:00 +00001919 "Copyright (C) 2000-2004, and GNU GPL'd, by Julian Seward et al.");
njnd04b7c62002-10-03 14:05:52 +00001920 }
1921
nethercotec1e395d2003-11-10 13:26:49 +00001922 if (VG_(clo_verbosity) > 0 && VG_(clo_log_to) != VgLogTo_Fd) {
sewardj4cf05692002-10-27 20:28:29 +00001923 VG_(message)(Vg_UserMsg, "");
1924 VG_(message)(Vg_UserMsg,
1925 "My PID = %d, parent PID = %d. Prog and args are:",
1926 VG_(getpid)(), VG_(getppid)() );
1927 for (i = 0; i < VG_(client_argc); i++)
1928 VG_(message)(Vg_UserMsg, " %s", VG_(client_argv)[i]);
1929 }
1930
sewardjde4a1d02002-03-22 01:27:54 +00001931 if (VG_(clo_verbosity) > 1) {
nethercotea70f7352004-04-18 12:08:46 +00001932 Int fd;
sewardj4cf05692002-10-27 20:28:29 +00001933 if (VG_(clo_log_to) != VgLogTo_Fd)
1934 VG_(message)(Vg_UserMsg, "");
fitzhardinge98abfc72003-12-16 02:05:15 +00001935 VG_(message)(Vg_UserMsg, "Valgrind library directory: %s", VG_(libdir));
njn86dc2bc2003-09-09 07:26:21 +00001936 VG_(message)(Vg_UserMsg, "Command line");
1937 for (i = 0; i < VG_(client_argc); i++)
1938 VG_(message)(Vg_UserMsg, " %s", VG_(client_argv)[i]);
1939
sewardjde4a1d02002-03-22 01:27:54 +00001940 VG_(message)(Vg_UserMsg, "Startup, with flags:");
nethercotef6a1d502004-08-09 12:21:57 +00001941 for (i = 1; i < vg_argc; i++) {
1942 VG_(message)(Vg_UserMsg, " %s", vg_argv[i]);
sewardjde4a1d02002-03-22 01:27:54 +00001943 }
nethercotea70f7352004-04-18 12:08:46 +00001944
1945 VG_(message)(Vg_UserMsg, "Contents of /proc/version:");
1946 fd = VG_(open) ( "/proc/version", VKI_O_RDONLY, 0 );
1947 if (fd < 0) {
1948 VG_(message)(Vg_UserMsg, " can't open /proc/version");
1949 } else {
1950 #define BUF_LEN 256
1951 Char version_buf[BUF_LEN];
1952 Int n = VG_(read) ( fd, version_buf, BUF_LEN );
1953 vg_assert(n <= 256);
1954 if (n > 0) {
1955 version_buf[n-1] = '\0';
1956 VG_(message)(Vg_UserMsg, " %s", version_buf);
1957 } else {
1958 VG_(message)(Vg_UserMsg, " (empty?)");
1959 }
1960 VG_(close)(fd);
1961 #undef BUF_LEN
1962 }
sewardjde4a1d02002-03-22 01:27:54 +00001963 }
1964
fitzhardinge98abfc72003-12-16 02:05:15 +00001965 if (VG_(clo_n_suppressions) < VG_CLO_MAX_SFILES-1 &&
njn25e49d8e72002-09-23 09:36:25 +00001966 (VG_(needs).core_errors || VG_(needs).skin_errors)) {
nethercote996901a2004-08-03 13:29:09 +00001967 /* If there are no suppression files specified and the tool
fitzhardinge98abfc72003-12-16 02:05:15 +00001968 needs one, load the default */
1969 static const Char default_supp[] = "default.supp";
1970 Int len = VG_(strlen)(VG_(libdir)) + 1 + sizeof(default_supp);
1971 Char *buf = VG_(arena_malloc)(VG_AR_CORE, len);
1972 VG_(sprintf)(buf, "%s/%s", VG_(libdir), default_supp);
1973 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = buf;
1974 VG_(clo_n_suppressions)++;
sewardjde4a1d02002-03-22 01:27:54 +00001975 }
sewardj4cf05692002-10-27 20:28:29 +00001976
njn6a230532003-07-21 10:38:23 +00001977 if (VG_(clo_gen_suppressions) &&
1978 !VG_(needs).core_errors && !VG_(needs).skin_errors) {
nethercotef4928da2004-06-15 10:54:40 +00001979 VG_(message)(Vg_UserMsg,
1980 "Can't use --gen-suppressions=yes with this tool,");
1981 VG_(message)(Vg_UserMsg,
1982 "as it doesn't generate errors.");
1983 VG_(bad_option)("--gen-suppressions=yes");
njn6a230532003-07-21 10:38:23 +00001984 }
sewardjde4a1d02002-03-22 01:27:54 +00001985}
1986
nethercotef6a1d502004-08-09 12:21:57 +00001987// Build the string for VALGRINDCLO.
1988Char* VG_(build_child_VALGRINDCLO)( Char* exename )
1989{
1990 /* If we're tracing the children, then we need to start it
1991 with our starter+arguments, which are copied into VALGRINDCLO,
1992 except the --exec= option is changed if present.
1993 */
1994 Int i;
1995 Char *exec;
1996 Char *cp;
1997 Char *optvar;
1998 Int optlen, execlen;
1999
2000 // All these allocated blocks are not free - because we're either
2001 // going to exec, or panic when we fail.
2002
2003 // Create --exec= option: "--exec=<exename>"
2004 exec = VG_(arena_malloc)(VG_AR_CORE,
2005 VG_(strlen)( exename ) + 7/*--exec=*/ + 1/*\0*/);
2006 vg_assert(NULL != exec);
2007 VG_(sprintf)(exec, "--exec=%s", exename);
2008
2009 // Allocate space for optvar (may overestimate by counting --exec twice,
2010 // no matter)
2011 optlen = 1;
2012 for (i = 0; i < vg_argc; i++)
2013 optlen += VG_(strlen)(vg_argv[i]) + 1;
2014 optlen += VG_(strlen)(exec)+1;
2015 optvar = VG_(arena_malloc)(VG_AR_CORE, optlen);
2016
2017 // Copy all valgrind args except the old --exec (if present)
2018 // VG_CLO_SEP is the separator.
2019 cp = optvar;
2020 for (i = 1; i < vg_argc; i++) {
2021 Char *arg = vg_argv[i];
2022
2023 if (VG_(memcmp)(arg, "--exec=", 7) == 0) {
2024 // don't copy existing --exec= arg
2025 } else if (VG_(strcmp)(arg, "--") == 0) {
2026 // stop at "--"
2027 break;
2028 } else {
2029 // copy non "--exec" arg
2030 Int len = VG_(strlen)(arg);
2031 VG_(memcpy)(cp, arg, len);
2032 cp += len;
2033 *cp++ = VG_CLO_SEP;
2034 }
2035 }
2036 // Add the new --exec= option
2037 execlen = VG_(strlen)(exec);
2038 VG_(memcpy)(cp, exec, execlen);
2039 cp += execlen;
2040 *cp++ = VG_CLO_SEP;
2041
2042 *cp = '\0';
2043
2044 return optvar;
2045}
2046
2047// Build "/proc/self/fd/<execfd>".
2048Char* VG_(build_child_exename)( void )
2049{
2050 Char* exename = VG_(arena_malloc)(VG_AR_CORE, 64);
2051 vg_assert(NULL != exename);
2052 VG_(sprintf)(exename, "/proc/self/fd/%d", vgexecfd);
2053 return exename;
2054}
2055
sewardjde4a1d02002-03-22 01:27:54 +00002056
nethercote71980f02004-01-24 18:18:54 +00002057/*====================================================================*/
2058/*=== File descriptor setup ===*/
2059/*====================================================================*/
2060
2061static void setup_file_descriptors(void)
2062{
2063 struct vki_rlimit rl;
2064
2065 /* Get the current file descriptor limits. */
2066 if (VG_(getrlimit)(VKI_RLIMIT_NOFILE, &rl) < 0) {
2067 rl.rlim_cur = 1024;
2068 rl.rlim_max = 1024;
2069 }
2070
2071 /* Work out where to move the soft limit to. */
2072 if (rl.rlim_cur + VG_N_RESERVED_FDS <= rl.rlim_max) {
2073 rl.rlim_cur = rl.rlim_cur + VG_N_RESERVED_FDS;
2074 } else {
2075 rl.rlim_cur = rl.rlim_max;
2076 }
2077
2078 /* Reserve some file descriptors for our use. */
thughesad1c9562004-06-26 11:27:52 +00002079 VG_(fd_soft_limit) = rl.rlim_cur - VG_N_RESERVED_FDS;
2080 VG_(fd_hard_limit) = rl.rlim_cur - VG_N_RESERVED_FDS;
nethercote71980f02004-01-24 18:18:54 +00002081
2082 /* Update the soft limit. */
2083 VG_(setrlimit)(VKI_RLIMIT_NOFILE, &rl);
2084
nethercotef6a1d502004-08-09 12:21:57 +00002085 if (vgexecfd != -1)
2086 vgexecfd = VG_(safe_fd)( vgexecfd );
nethercote71980f02004-01-24 18:18:54 +00002087 if (VG_(clexecfd) != -1)
2088 VG_(clexecfd) = VG_(safe_fd)( VG_(clexecfd) );
2089}
2090
2091
2092/*====================================================================*/
nethercote1d447092004-02-01 17:29:59 +00002093/*=== baseBlock: definition + setup ===*/
nethercote71980f02004-01-24 18:18:54 +00002094/*====================================================================*/
2095
2096/* The variables storing offsets. */
2097
2098#define INVALID_OFFSET (-1)
2099
2100Int VGOFF_(m_eax) = INVALID_OFFSET;
2101Int VGOFF_(m_ecx) = INVALID_OFFSET;
2102Int VGOFF_(m_edx) = INVALID_OFFSET;
2103Int VGOFF_(m_ebx) = INVALID_OFFSET;
2104Int VGOFF_(m_esp) = INVALID_OFFSET;
2105Int VGOFF_(m_ebp) = INVALID_OFFSET;
2106Int VGOFF_(m_esi) = INVALID_OFFSET;
2107Int VGOFF_(m_edi) = INVALID_OFFSET;
2108Int VGOFF_(m_eflags) = INVALID_OFFSET;
2109Int VGOFF_(m_dflag) = INVALID_OFFSET;
2110Int VGOFF_(m_ssestate) = INVALID_OFFSET;
2111Int VGOFF_(ldt) = INVALID_OFFSET;
2112Int VGOFF_(tls) = INVALID_OFFSET;
2113Int VGOFF_(m_cs) = INVALID_OFFSET;
2114Int VGOFF_(m_ss) = INVALID_OFFSET;
2115Int VGOFF_(m_ds) = INVALID_OFFSET;
2116Int VGOFF_(m_es) = INVALID_OFFSET;
2117Int VGOFF_(m_fs) = INVALID_OFFSET;
2118Int VGOFF_(m_gs) = INVALID_OFFSET;
2119Int VGOFF_(m_eip) = INVALID_OFFSET;
2120Int VGOFF_(spillslots) = INVALID_OFFSET;
2121Int VGOFF_(sh_eax) = INVALID_OFFSET;
2122Int VGOFF_(sh_ecx) = INVALID_OFFSET;
2123Int VGOFF_(sh_edx) = INVALID_OFFSET;
2124Int VGOFF_(sh_ebx) = INVALID_OFFSET;
2125Int VGOFF_(sh_esp) = INVALID_OFFSET;
2126Int VGOFF_(sh_ebp) = INVALID_OFFSET;
2127Int VGOFF_(sh_esi) = INVALID_OFFSET;
2128Int VGOFF_(sh_edi) = INVALID_OFFSET;
2129Int VGOFF_(sh_eflags) = INVALID_OFFSET;
2130
2131Int VGOFF_(helper_idiv_64_32) = INVALID_OFFSET;
2132Int VGOFF_(helper_div_64_32) = INVALID_OFFSET;
2133Int VGOFF_(helper_idiv_32_16) = INVALID_OFFSET;
2134Int VGOFF_(helper_div_32_16) = INVALID_OFFSET;
2135Int VGOFF_(helper_idiv_16_8) = INVALID_OFFSET;
2136Int VGOFF_(helper_div_16_8) = INVALID_OFFSET;
2137Int VGOFF_(helper_imul_32_64) = INVALID_OFFSET;
2138Int VGOFF_(helper_mul_32_64) = INVALID_OFFSET;
2139Int VGOFF_(helper_imul_16_32) = INVALID_OFFSET;
2140Int VGOFF_(helper_mul_16_32) = INVALID_OFFSET;
2141Int VGOFF_(helper_imul_8_16) = INVALID_OFFSET;
2142Int VGOFF_(helper_mul_8_16) = INVALID_OFFSET;
2143Int VGOFF_(helper_CLD) = INVALID_OFFSET;
2144Int VGOFF_(helper_STD) = INVALID_OFFSET;
2145Int VGOFF_(helper_get_dirflag) = INVALID_OFFSET;
2146Int VGOFF_(helper_CLC) = INVALID_OFFSET;
2147Int VGOFF_(helper_STC) = INVALID_OFFSET;
nethercote1018bdd2004-02-11 23:33:29 +00002148Int VGOFF_(helper_CMC) = INVALID_OFFSET;
nethercote71980f02004-01-24 18:18:54 +00002149Int VGOFF_(helper_shldl) = INVALID_OFFSET;
2150Int VGOFF_(helper_shldw) = INVALID_OFFSET;
2151Int VGOFF_(helper_shrdl) = INVALID_OFFSET;
2152Int VGOFF_(helper_shrdw) = INVALID_OFFSET;
2153Int VGOFF_(helper_IN) = INVALID_OFFSET;
2154Int VGOFF_(helper_OUT) = INVALID_OFFSET;
2155Int VGOFF_(helper_RDTSC) = INVALID_OFFSET;
2156Int VGOFF_(helper_CPUID) = INVALID_OFFSET;
2157Int VGOFF_(helper_BSWAP) = INVALID_OFFSET;
nethercote1018bdd2004-02-11 23:33:29 +00002158Int VGOFF_(helper_bsfw) = INVALID_OFFSET;
2159Int VGOFF_(helper_bsfl) = INVALID_OFFSET;
2160Int VGOFF_(helper_bsrw) = INVALID_OFFSET;
2161Int VGOFF_(helper_bsrl) = INVALID_OFFSET;
nethercote71980f02004-01-24 18:18:54 +00002162Int VGOFF_(helper_fstsw_AX) = INVALID_OFFSET;
2163Int VGOFF_(helper_SAHF) = INVALID_OFFSET;
2164Int VGOFF_(helper_LAHF) = INVALID_OFFSET;
2165Int VGOFF_(helper_DAS) = INVALID_OFFSET;
2166Int VGOFF_(helper_DAA) = INVALID_OFFSET;
nethercote1018bdd2004-02-11 23:33:29 +00002167Int VGOFF_(helper_AAS) = INVALID_OFFSET;
2168Int VGOFF_(helper_AAA) = INVALID_OFFSET;
2169Int VGOFF_(helper_AAD) = INVALID_OFFSET;
2170Int VGOFF_(helper_AAM) = INVALID_OFFSET;
nethercote71980f02004-01-24 18:18:54 +00002171Int VGOFF_(helper_cmpxchg8b) = INVALID_OFFSET;
2172Int VGOFF_(helper_undefined_instruction) = INVALID_OFFSET;
2173
2174/* MAX_NONCOMPACT_HELPERS can be increased easily. If MAX_COMPACT_HELPERS is
2175 * increased too much, they won't really be compact any more... */
2176#define MAX_COMPACT_HELPERS 8
2177#define MAX_NONCOMPACT_HELPERS 50
2178
nethercote81f9a6f2004-08-03 15:45:46 +00002179/* For storing tool-specific helpers, determined at runtime. The addr
2180 * and offset arrays together form a (addr, offset) map that allows a
2181 * helper's baseBlock offset to be computed from its address. It's done
2182 * like this so CCALLs can use the function address rather than having to
2183 * muck around with offsets. */
2184static UInt VG_(n_compact_helpers) = 0;
2185static UInt VG_(n_noncompact_helpers) = 0;
2186static Addr VG_(compact_helper_addrs) [MAX_COMPACT_HELPERS];
2187static Int VG_(compact_helper_offsets)[MAX_COMPACT_HELPERS];
2188static Addr VG_(noncompact_helper_addrs) [MAX_NONCOMPACT_HELPERS];
2189static Int VG_(noncompact_helper_offsets)[MAX_NONCOMPACT_HELPERS];
nethercote71980f02004-01-24 18:18:54 +00002190
2191/* This is the actual defn of baseblock. */
2192UInt VG_(baseBlock)[VG_BASEBLOCK_WORDS];
2193
nethercote71980f02004-01-24 18:18:54 +00002194/* Words. */
2195static Int baB_off = 0;
2196
2197
nethercote71980f02004-01-24 18:18:54 +00002198/* Returns the offset, in words. */
2199static Int alloc_BaB ( Int words )
sewardjde4a1d02002-03-22 01:27:54 +00002200{
nethercote71980f02004-01-24 18:18:54 +00002201 Int off = baB_off;
2202 baB_off += words;
2203 if (baB_off >= VG_BASEBLOCK_WORDS)
2204 VG_(core_panic)( "alloc_BaB: baseBlock is too small");
sewardjde4a1d02002-03-22 01:27:54 +00002205
nethercote71980f02004-01-24 18:18:54 +00002206 return off;
sewardjde4a1d02002-03-22 01:27:54 +00002207}
2208
nethercote71980f02004-01-24 18:18:54 +00002209/* Align offset, in *bytes* */
2210static void align_BaB ( UInt align )
njn25e49d8e72002-09-23 09:36:25 +00002211{
nethercote71980f02004-01-24 18:18:54 +00002212 vg_assert(2 == align || 4 == align || 8 == align || 16 == align);
2213 baB_off += (align-1);
2214 baB_off &= ~(align-1);
njn25e49d8e72002-09-23 09:36:25 +00002215}
2216
nethercote71980f02004-01-24 18:18:54 +00002217/* Allocate 1 word in baseBlock and set it to the given value. */
2218static Int alloc_BaB_1_set ( Addr a )
njn25e49d8e72002-09-23 09:36:25 +00002219{
nethercote71980f02004-01-24 18:18:54 +00002220 Int off = alloc_BaB(1);
2221 VG_(baseBlock)[off] = (UInt)a;
2222 return off;
njn25e49d8e72002-09-23 09:36:25 +00002223}
2224
nethercote71980f02004-01-24 18:18:54 +00002225/* Registers a function in compact_helper_addrs; compact_helper_offsets is
2226 filled in later. */
2227void VG_(register_compact_helper)(Addr a)
sewardjde4a1d02002-03-22 01:27:54 +00002228{
nethercote71980f02004-01-24 18:18:54 +00002229 if (MAX_COMPACT_HELPERS <= VG_(n_compact_helpers)) {
2230 VG_(printf)("Can only register %d compact helpers\n",
2231 MAX_COMPACT_HELPERS);
2232 VG_(core_panic)("Too many compact helpers registered");
2233 }
2234 VG_(compact_helper_addrs)[VG_(n_compact_helpers)] = a;
2235 VG_(n_compact_helpers)++;
2236}
2237
2238/* Registers a function in noncompact_helper_addrs; noncompact_helper_offsets
2239 * is filled in later.
2240 */
2241void VG_(register_noncompact_helper)(Addr a)
2242{
2243 if (MAX_NONCOMPACT_HELPERS <= VG_(n_noncompact_helpers)) {
2244 VG_(printf)("Can only register %d non-compact helpers\n",
2245 MAX_NONCOMPACT_HELPERS);
2246 VG_(printf)("Try increasing MAX_NON_COMPACT_HELPERS\n");
2247 VG_(core_panic)("Too many non-compact helpers registered");
2248 }
2249 VG_(noncompact_helper_addrs)[VG_(n_noncompact_helpers)] = a;
2250 VG_(n_noncompact_helpers)++;
2251}
2252
nethercote996901a2004-08-03 13:29:09 +00002253/* Allocate offsets in baseBlock for the tool helpers */
nethercote71980f02004-01-24 18:18:54 +00002254static
2255void assign_helpers_in_baseBlock(UInt n, Int offsets[], Addr addrs[])
2256{
2257 UInt i;
2258 for (i = 0; i < n; i++)
2259 offsets[i] = alloc_BaB_1_set( addrs[i] );
2260}
2261
2262Bool VG_(need_to_handle_esp_assignment)(void)
2263{
2264 return ( VG_(defined_new_mem_stack_4)() ||
2265 VG_(defined_die_mem_stack_4)() ||
2266 VG_(defined_new_mem_stack_8)() ||
2267 VG_(defined_die_mem_stack_8)() ||
2268 VG_(defined_new_mem_stack_12)() ||
2269 VG_(defined_die_mem_stack_12)() ||
2270 VG_(defined_new_mem_stack_16)() ||
2271 VG_(defined_die_mem_stack_16)() ||
2272 VG_(defined_new_mem_stack_32)() ||
2273 VG_(defined_die_mem_stack_32)() ||
2274 VG_(defined_new_mem_stack)() ||
2275 VG_(defined_die_mem_stack)()
2276 );
2277}
2278
2279/* Here we assign actual offsets. It's important to get the most
2280 popular referents within 128 bytes of the start, so we can take
2281 advantage of short addressing modes relative to %ebp. Popularity
2282 of offsets was measured on 22 Feb 02 running a KDE application, and
2283 the slots rearranged accordingly, with a 1.5% reduction in total
2284 size of translations. */
2285static void init_baseBlock ( Addr client_eip, Addr esp_at_startup )
2286{
2287 /* Those with offsets under 128 are carefully chosen. */
2288
2289 /* WORD offsets in this column */
2290 /* 0 */ VGOFF_(m_eax) = alloc_BaB_1_set(0);
2291 /* 1 */ VGOFF_(m_ecx) = alloc_BaB_1_set(0);
2292 /* 2 */ VGOFF_(m_edx) = alloc_BaB_1_set(0);
2293 /* 3 */ VGOFF_(m_ebx) = alloc_BaB_1_set(0);
2294 /* 4 */ VGOFF_(m_esp) = alloc_BaB_1_set(esp_at_startup);
2295 /* 5 */ VGOFF_(m_ebp) = alloc_BaB_1_set(0);
2296 /* 6 */ VGOFF_(m_esi) = alloc_BaB_1_set(0);
2297 /* 7 */ VGOFF_(m_edi) = alloc_BaB_1_set(0);
2298 /* 8 */ VGOFF_(m_eflags) = alloc_BaB_1_set(0);
2299
2300 if (VG_(needs).shadow_regs) {
2301 /* 9 */ VGOFF_(sh_eax) = alloc_BaB_1_set(0);
2302 /* 10 */ VGOFF_(sh_ecx) = alloc_BaB_1_set(0);
2303 /* 11 */ VGOFF_(sh_edx) = alloc_BaB_1_set(0);
2304 /* 12 */ VGOFF_(sh_ebx) = alloc_BaB_1_set(0);
2305 /* 13 */ VGOFF_(sh_esp) = alloc_BaB_1_set(0);
2306 /* 14 */ VGOFF_(sh_ebp) = alloc_BaB_1_set(0);
2307 /* 15 */ VGOFF_(sh_esi) = alloc_BaB_1_set(0);
2308 /* 16 */ VGOFF_(sh_edi) = alloc_BaB_1_set(0);
2309 /* 17 */ VGOFF_(sh_eflags) = alloc_BaB_1_set(0);
2310 VG_TRACK( post_regs_write_init );
2311 }
2312
2313 /* 9,10,11 or 18,19,20... depends on number whether shadow regs are used
2314 * and on compact helpers registered */
2315
2316 /* Make these most-frequently-called specialised ones compact, if they
2317 are used. */
2318 if (VG_(defined_new_mem_stack_4)())
2319 VG_(register_compact_helper)( (Addr) VG_(tool_interface).track_new_mem_stack_4);
2320
2321 if (VG_(defined_die_mem_stack_4)())
2322 VG_(register_compact_helper)( (Addr) VG_(tool_interface).track_die_mem_stack_4);
2323
2324 /* (9 or 18) + n_compact_helpers */
2325 /* Allocate slots for compact helpers */
2326 assign_helpers_in_baseBlock(VG_(n_compact_helpers),
2327 VG_(compact_helper_offsets),
2328 VG_(compact_helper_addrs));
2329
2330 /* (9/10 or 18/19) + n_compact_helpers */
2331 VGOFF_(m_eip) = alloc_BaB_1_set(client_eip);
2332
2333 /* There are currently 24 spill slots */
2334 /* (11+/20+ .. 32+/43+) + n_compact_helpers. This can overlap the magic
2335 * boundary at >= 32 words, but most spills are to low numbered spill
2336 * slots, so the ones above the boundary don't see much action. */
2337 VGOFF_(spillslots) = alloc_BaB(VG_MAX_SPILLSLOTS);
2338
2339 /* I gave up counting at this point. Since they're above the
2340 short-amode-boundary, there's no point. */
2341
2342 VGOFF_(m_dflag) = alloc_BaB_1_set(1); // 1 == forward D-flag
2343
2344 /* The FPU/SSE state. This _must_ be 16-byte aligned. Initial
2345 state doesn't matter much, as long as it's not totally borked. */
2346 align_BaB(16);
2347 VGOFF_(m_ssestate) = alloc_BaB(VG_SIZE_OF_SSESTATE_W);
2348 vg_assert(
2349 0 == ( ((UInt)(& VG_(baseBlock)[VGOFF_(m_ssestate)])) % 16 )
sewardj22854b92002-11-30 14:00:47 +00002350 );
2351
fitzhardingec2dbbac2004-01-23 23:09:01 +00002352 /* I assume that if we have SSE2 we also have SSE */
2353 VG_(have_ssestate) =
2354 VG_(cpu_has_feature)(VG_X86_FEAT_FXSR) &&
2355 VG_(cpu_has_feature)(VG_X86_FEAT_SSE);
2356
fitzhardinge98abfc72003-12-16 02:05:15 +00002357 /* set up an initial FPU state (doesn't really matter what it is,
2358 so long as it's somewhat valid) */
2359 if (!VG_(have_ssestate))
nethercote71980f02004-01-24 18:18:54 +00002360 asm volatile("fwait; fnsave %0; fwait; frstor %0; fwait"
2361 :
2362 : "m" (VG_(baseBlock)[VGOFF_(m_ssestate)])
2363 : "cc", "memory");
fitzhardinge98abfc72003-12-16 02:05:15 +00002364 else
nethercote71980f02004-01-24 18:18:54 +00002365 asm volatile("fwait; fxsave %0; fwait; andl $0xffbf, %1;"
2366 "fxrstor %0; fwait"
2367 :
2368 : "m" (VG_(baseBlock)[VGOFF_(m_ssestate)]),
2369 "m" (VG_(baseBlock)[VGOFF_(m_ssestate)+(24/4)])
2370 : "cc", "memory");
fitzhardinge98abfc72003-12-16 02:05:15 +00002371
njn0c7a5b52003-04-30 09:00:33 +00002372 if (0) {
2373 if (VG_(have_ssestate))
2374 VG_(printf)("Looks like a SSE-capable CPU\n");
2375 else
2376 VG_(printf)("Looks like a MMX-only CPU\n");
2377 }
sewardjb91ae7f2003-04-29 23:50:00 +00002378
nethercote71980f02004-01-24 18:18:54 +00002379 /* LDT pointer: pretend the root thread has an empty LDT to start with. */
2380 VGOFF_(ldt) = alloc_BaB_1_set((UInt)NULL);
jsgf855d93d2003-10-13 22:26:55 +00002381
nethercote71980f02004-01-24 18:18:54 +00002382 /* TLS pointer: pretend the root thread has no TLS array for now. */
2383 VGOFF_(tls) = alloc_BaB_1_set((UInt)NULL);
fitzhardingef0046f22003-12-18 02:39:22 +00002384
nethercote71980f02004-01-24 18:18:54 +00002385 /* segment registers */
2386 VGOFF_(m_cs) = alloc_BaB_1_set(0);
2387 VGOFF_(m_ss) = alloc_BaB_1_set(0);
2388 VGOFF_(m_ds) = alloc_BaB_1_set(0);
2389 VGOFF_(m_es) = alloc_BaB_1_set(0);
2390 VGOFF_(m_fs) = alloc_BaB_1_set(0);
2391 VGOFF_(m_gs) = alloc_BaB_1_set(0);
fitzhardingef0046f22003-12-18 02:39:22 +00002392
thughes35cec982004-04-21 15:16:43 +00002393 /* initialise %cs, %ds and %ss to point at the operating systems
2394 default code, data and stack segments */
2395 asm volatile("movw %%cs, %0"
2396 :
2397 : "m" (VG_(baseBlock)[VGOFF_(m_cs)]));
2398 asm volatile("movw %%ds, %0"
2399 :
2400 : "m" (VG_(baseBlock)[VGOFF_(m_ds)]));
2401 asm volatile("movw %%ss, %0"
2402 :
2403 : "m" (VG_(baseBlock)[VGOFF_(m_ss)]));
2404
nethercote71980f02004-01-24 18:18:54 +00002405 VG_(register_noncompact_helper)( (Addr) & VG_(do_useseg) );
fitzhardingef0046f22003-12-18 02:39:22 +00002406
nethercote71980f02004-01-24 18:18:54 +00002407#define REG(kind, size) \
2408 if (VG_(defined_##kind##_mem_stack##size)()) \
2409 VG_(register_noncompact_helper)( \
2410 (Addr) VG_(tool_interface).track_##kind##_mem_stack##size );
2411 REG(new, _8);
2412 REG(new, _12);
2413 REG(new, _16);
2414 REG(new, _32);
2415 REG(new, );
2416 REG(die, _8);
2417 REG(die, _12);
2418 REG(die, _16);
2419 REG(die, _32);
2420 REG(die, );
2421#undef REG
fitzhardingef0046f22003-12-18 02:39:22 +00002422
nethercote71980f02004-01-24 18:18:54 +00002423 if (VG_(need_to_handle_esp_assignment)())
2424 VG_(register_noncompact_helper)((Addr) VG_(unknown_esp_update));
fitzhardingeb791a192003-12-18 07:22:44 +00002425
nethercote71980f02004-01-24 18:18:54 +00002426# define HELPER(name) \
2427 VGOFF_(helper_##name) = alloc_BaB_1_set( (Addr) & VG_(helper_##name))
njn3e884182003-04-15 13:03:23 +00002428
nethercote71980f02004-01-24 18:18:54 +00002429 /* Helper functions. */
2430 HELPER(idiv_64_32); HELPER(div_64_32);
2431 HELPER(idiv_32_16); HELPER(div_32_16);
2432 HELPER(idiv_16_8); HELPER(div_16_8);
fitzhardinge98abfc72003-12-16 02:05:15 +00002433
nethercote71980f02004-01-24 18:18:54 +00002434 HELPER(imul_32_64); HELPER(mul_32_64);
2435 HELPER(imul_16_32); HELPER(mul_16_32);
2436 HELPER(imul_8_16); HELPER(mul_8_16);
njn25e49d8e72002-09-23 09:36:25 +00002437
nethercote71980f02004-01-24 18:18:54 +00002438 HELPER(CLD); HELPER(STD);
2439 HELPER(get_dirflag);
sewardjde4a1d02002-03-22 01:27:54 +00002440
nethercote71980f02004-01-24 18:18:54 +00002441 HELPER(CLC); HELPER(STC);
nethercote1018bdd2004-02-11 23:33:29 +00002442 HELPER(CMC);
jsgf855d93d2003-10-13 22:26:55 +00002443
nethercote71980f02004-01-24 18:18:54 +00002444 HELPER(shldl); HELPER(shldw);
2445 HELPER(shrdl); HELPER(shrdw);
njncc7bb472002-10-14 09:25:19 +00002446
nethercote71980f02004-01-24 18:18:54 +00002447 HELPER(RDTSC); HELPER(CPUID);
njncc7bb472002-10-14 09:25:19 +00002448
nethercote1018bdd2004-02-11 23:33:29 +00002449 HELPER(bsfw); HELPER(bsfl);
2450 HELPER(bsrw); HELPER(bsrl);
rjwalshf5f536f2003-11-17 17:45:00 +00002451
nethercote71980f02004-01-24 18:18:54 +00002452 HELPER(fstsw_AX);
2453 HELPER(SAHF); HELPER(LAHF);
2454 HELPER(DAS); HELPER(DAA);
nethercote1018bdd2004-02-11 23:33:29 +00002455 HELPER(AAS); HELPER(AAA);
2456 HELPER(AAD); HELPER(AAM);
nethercote71980f02004-01-24 18:18:54 +00002457 HELPER(IN); HELPER(OUT);
2458 HELPER(cmpxchg8b);
sewardj018f7622002-05-15 21:13:39 +00002459
nethercote71980f02004-01-24 18:18:54 +00002460 HELPER(undefined_instruction);
jsgf855d93d2003-10-13 22:26:55 +00002461
nethercote71980f02004-01-24 18:18:54 +00002462# undef HELPER
sewardjde4a1d02002-03-22 01:27:54 +00002463
nethercote71980f02004-01-24 18:18:54 +00002464 /* Allocate slots for noncompact helpers */
2465 assign_helpers_in_baseBlock(VG_(n_noncompact_helpers),
2466 VG_(noncompact_helper_offsets),
2467 VG_(noncompact_helper_addrs));
2468}
sewardjde4a1d02002-03-22 01:27:54 +00002469
nethercote81f9a6f2004-08-03 15:45:46 +00002470// Finds the baseBlock offset of a tool-specified helper.
2471// Searches through compacts first, then non-compacts.
2472Int VG_(helper_offset)(Addr a)
2473{
2474 UInt i;
2475 Char buf[100];
2476
2477 for (i = 0; i < VG_(n_compact_helpers); i++)
2478 if (VG_(compact_helper_addrs)[i] == a)
2479 return VG_(compact_helper_offsets)[i];
2480 for (i = 0; i < VG_(n_noncompact_helpers); i++)
2481 if (VG_(noncompact_helper_addrs)[i] == a)
2482 return VG_(noncompact_helper_offsets)[i];
2483
2484 /* Shouldn't get here */
2485 VG_(get_fnname) ( a, buf, 100 );
2486
2487 VG_(printf)(
2488 "\nCouldn't find offset of helper from its address (%p: %s).\n"
2489 "A helper function probably used hasn't been registered?\n\n", a, buf);
2490
2491 VG_(printf)(" compact helpers: ");
2492 for (i = 0; i < VG_(n_compact_helpers); i++)
2493 VG_(printf)("%p ", VG_(compact_helper_addrs)[i]);
2494
2495 VG_(printf)("\n non-compact helpers: ");
2496 for (i = 0; i < VG_(n_noncompact_helpers); i++)
2497 VG_(printf)("%p ", VG_(noncompact_helper_addrs)[i]);
2498
2499 VG_(printf)("\n");
2500 VG_(skin_panic)("Unfound helper");
2501}
2502
sewardj5f07b662002-04-23 16:52:51 +00002503
nethercote71980f02004-01-24 18:18:54 +00002504/*====================================================================*/
2505/*=== Setup pointercheck ===*/
2506/*====================================================================*/
njn25e49d8e72002-09-23 09:36:25 +00002507
nethercote71980f02004-01-24 18:18:54 +00002508static void setup_pointercheck(void)
2509{
2510 int ret;
sewardj2e93c502002-04-12 11:12:52 +00002511
fitzhardinge98abfc72003-12-16 02:05:15 +00002512 if (VG_(clo_pointercheck)) {
nethercote71980f02004-01-24 18:18:54 +00002513 vki_modify_ldt_t ldt = {
2514 VG_POINTERCHECK_SEGIDX, // entry_number
2515 VG_(client_base), // base_addr
2516 (VG_(client_end)-VG_(client_base)) / VKI_BYTES_PER_PAGE, // limit
2517 1, // seg_32bit
2518 0, // contents: data, RW, non-expanding
2519 0, // ! read_exec_only
2520 1, // limit_in_pages
2521 0, // ! seg not present
2522 1, // useable
fitzhardinge98abfc72003-12-16 02:05:15 +00002523 };
nethercote71980f02004-01-24 18:18:54 +00002524 ret = VG_(do_syscall)(__NR_modify_ldt, 1, &ldt, sizeof(ldt));
fitzhardinge98abfc72003-12-16 02:05:15 +00002525 if (ret < 0) {
2526 VG_(message)(Vg_UserMsg,
2527 "Warning: ignoring --pointercheck=yes, "
2528 "because modify_ldt failed (errno=%d)", -ret);
2529 VG_(clo_pointercheck) = False;
2530 }
2531 }
sewardjde4a1d02002-03-22 01:27:54 +00002532}
2533
nethercote71980f02004-01-24 18:18:54 +00002534/*====================================================================*/
2535/*=== Initialise program data/text, etc. ===*/
2536/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +00002537
nethercote71980f02004-01-24 18:18:54 +00002538static void build_valgrind_map_callback
2539 ( Addr start, UInt size, Char rr, Char ww, Char xx,
2540 UInt dev, UInt ino, ULong foffset, const UChar* filename )
sewardjde4a1d02002-03-22 01:27:54 +00002541{
nethercote71980f02004-01-24 18:18:54 +00002542 UInt prot = 0;
2543 UInt flags = SF_MMAP|SF_NOSYMS;
2544 Bool is_stack_segment;
2545
2546 is_stack_segment =
2547 (start == VG_(clstk_base) && (start+size) == VG_(clstk_end));
2548
2549 /* Only record valgrind mappings for now, without loading any
2550 symbols. This is so we know where the free space is before we
2551 start allocating more memory (note: heap is OK, it's just mmap
2552 which is the problem here). */
2553 if (start >= VG_(valgrind_base) && (start+size) <= VG_(valgrind_end)) {
2554 flags |= SF_VALGRIND;
2555 VG_(map_file_segment)(start, size, prot, flags, dev, ino, foffset, filename);
2556 }
sewardjde4a1d02002-03-22 01:27:54 +00002557}
2558
nethercote71980f02004-01-24 18:18:54 +00002559// Global var used to pass local data to callback
2560Addr esp_at_startup___global_arg = 0;
sewardjde4a1d02002-03-22 01:27:54 +00002561
nethercote71980f02004-01-24 18:18:54 +00002562static void build_segment_map_callback
2563 ( Addr start, UInt size, Char rr, Char ww, Char xx,
2564 UInt dev, UInt ino, ULong foffset, const UChar* filename )
sewardj45b672d2003-07-25 19:58:11 +00002565{
nethercote71980f02004-01-24 18:18:54 +00002566 UInt prot = 0;
2567 UInt flags;
2568 Bool is_stack_segment;
2569 Addr r_esp;
sewardj45b672d2003-07-25 19:58:11 +00002570
nethercote71980f02004-01-24 18:18:54 +00002571 is_stack_segment
2572 = (start == VG_(clstk_base) && (start+size) == VG_(clstk_end));
fitzhardinge98abfc72003-12-16 02:05:15 +00002573
nethercote71980f02004-01-24 18:18:54 +00002574 if (rr == 'r') prot |= VKI_PROT_READ;
2575 if (ww == 'w') prot |= VKI_PROT_WRITE;
2576 if (xx == 'x') prot |= VKI_PROT_EXEC;
fitzhardinge98abfc72003-12-16 02:05:15 +00002577
nethercote71980f02004-01-24 18:18:54 +00002578 if (is_stack_segment)
2579 flags = SF_STACK | SF_GROWDOWN;
2580 else
2581 flags = SF_EXEC|SF_MMAP;
fitzhardinge98abfc72003-12-16 02:05:15 +00002582
nethercote71980f02004-01-24 18:18:54 +00002583 if (filename != NULL)
2584 flags |= SF_FILE;
fitzhardinge98abfc72003-12-16 02:05:15 +00002585
nethercote71980f02004-01-24 18:18:54 +00002586 if (start >= VG_(valgrind_base) && (start+size) <= VG_(valgrind_end))
2587 flags |= SF_VALGRIND;
fitzhardinge98abfc72003-12-16 02:05:15 +00002588
nethercote71980f02004-01-24 18:18:54 +00002589 VG_(map_file_segment)(start, size, prot, flags, dev, ino, foffset, filename);
fitzhardinge98abfc72003-12-16 02:05:15 +00002590
nethercote71980f02004-01-24 18:18:54 +00002591 if (VG_(is_client_addr)(start) && VG_(is_client_addr)(start+size-1))
2592 VG_TRACK( new_mem_startup, start, size, rr=='r', ww=='w', xx=='x' );
sewardj3e1eb1f2002-05-18 13:14:17 +00002593
nethercote71980f02004-01-24 18:18:54 +00002594 /* If this is the stack segment mark all below %esp as noaccess. */
2595 r_esp = esp_at_startup___global_arg;
2596 vg_assert(0 != r_esp);
2597 if (is_stack_segment) {
2598 if (0)
2599 VG_(message)(Vg_DebugMsg, "invalidating stack area: %x .. %x",
2600 start,r_esp);
2601 VG_TRACK( die_mem_stack, start, r_esp-start );
sewardjde4a1d02002-03-22 01:27:54 +00002602 }
sewardjde4a1d02002-03-22 01:27:54 +00002603}
2604
2605
nethercote71980f02004-01-24 18:18:54 +00002606/*====================================================================*/
2607/*=== Sanity check machinery (permanently engaged) ===*/
2608/*====================================================================*/
njn25e49d8e72002-09-23 09:36:25 +00002609
2610/* A fast sanity check -- suitable for calling circa once per
2611 millisecond. */
2612
nethercote885dd912004-08-03 23:14:00 +00002613void VG_(sanity_check_general) ( Bool force_expensive )
njn25e49d8e72002-09-23 09:36:25 +00002614{
njn37cea302002-09-30 11:24:00 +00002615 VGP_PUSHCC(VgpCoreCheapSanity);
2616
nethercote27fec902004-06-16 21:26:32 +00002617 if (VG_(clo_sanity_level) < 1) return;
njn25e49d8e72002-09-23 09:36:25 +00002618
2619 /* --- First do all the tests that we can do quickly. ---*/
2620
nethercote297effd2004-08-02 15:07:57 +00002621 sanity_fast_count++;
njn25e49d8e72002-09-23 09:36:25 +00002622
njn25e49d8e72002-09-23 09:36:25 +00002623 /* Check stuff pertaining to the memory check system. */
2624
2625 /* Check that nobody has spuriously claimed that the first or
2626 last 16 pages of memory have become accessible [...] */
njn37cea302002-09-30 11:24:00 +00002627 if (VG_(needs).sanity_checks) {
2628 VGP_PUSHCC(VgpSkinCheapSanity);
njn25e49d8e72002-09-23 09:36:25 +00002629 vg_assert(SK_(cheap_sanity_check)());
njn37cea302002-09-30 11:24:00 +00002630 VGP_POPCC(VgpSkinCheapSanity);
2631 }
njn25e49d8e72002-09-23 09:36:25 +00002632
2633 /* --- Now some more expensive checks. ---*/
2634
2635 /* Once every 25 times, check some more expensive stuff. */
2636 if ( force_expensive
nethercote27fec902004-06-16 21:26:32 +00002637 || VG_(clo_sanity_level) > 1
nethercote297effd2004-08-02 15:07:57 +00002638 || (VG_(clo_sanity_level) == 1 && (sanity_fast_count % 25) == 0)) {
njn25e49d8e72002-09-23 09:36:25 +00002639
njn37cea302002-09-30 11:24:00 +00002640 VGP_PUSHCC(VgpCoreExpensiveSanity);
nethercote297effd2004-08-02 15:07:57 +00002641 sanity_slow_count++;
njn25e49d8e72002-09-23 09:36:25 +00002642
nethercote885dd912004-08-03 23:14:00 +00002643 VG_(sanity_check_proxy)();
jsgf855d93d2003-10-13 22:26:55 +00002644
njn25e49d8e72002-09-23 09:36:25 +00002645# if 0
2646 { void zzzmemscan(void); zzzmemscan(); }
2647# endif
2648
nethercote297effd2004-08-02 15:07:57 +00002649 if ((sanity_fast_count % 250) == 0)
nethercote92e7b7f2004-08-07 17:52:25 +00002650 VG_(sanity_check_tt_tc)();
njn25e49d8e72002-09-23 09:36:25 +00002651
2652 if (VG_(needs).sanity_checks) {
njn37cea302002-09-30 11:24:00 +00002653 VGP_PUSHCC(VgpSkinExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002654 vg_assert(SK_(expensive_sanity_check)());
njn37cea302002-09-30 11:24:00 +00002655 VGP_POPCC(VgpSkinExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002656 }
2657 /*
nethercote297effd2004-08-02 15:07:57 +00002658 if ((sanity_fast_count % 500) == 0) VG_(mallocSanityCheckAll)();
njn25e49d8e72002-09-23 09:36:25 +00002659 */
njn37cea302002-09-30 11:24:00 +00002660 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002661 }
2662
nethercote27fec902004-06-16 21:26:32 +00002663 if (VG_(clo_sanity_level) > 1) {
njn37cea302002-09-30 11:24:00 +00002664 VGP_PUSHCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002665 /* Check sanity of the low-level memory manager. Note that bugs
2666 in the client's code can cause this to fail, so we don't do
2667 this check unless specially asked for. And because it's
2668 potentially very expensive. */
nethercote885dd912004-08-03 23:14:00 +00002669 VG_(sanity_check_malloc_all)();
njn37cea302002-09-30 11:24:00 +00002670 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002671 }
njn37cea302002-09-30 11:24:00 +00002672 VGP_POPCC(VgpCoreCheapSanity);
njn25e49d8e72002-09-23 09:36:25 +00002673}
nethercote71980f02004-01-24 18:18:54 +00002674
2675
2676/*====================================================================*/
2677/*=== main() ===*/
2678/*====================================================================*/
2679
nethercotec314eba2004-07-15 12:59:41 +00002680/*
2681 This code decides on the layout of the client and Valgrind address
nethercote996901a2004-08-03 13:29:09 +00002682 spaces, loads valgrind.so and the tool.so into the valgrind part,
nethercotec314eba2004-07-15 12:59:41 +00002683 loads the client executable (and the dynamic linker, if necessary)
2684 into the client part, and calls into Valgrind proper.
2685
2686 The code is careful not to allow spurious mappings to appear in the
2687 wrong parts of the address space. In particular, to make sure
2688 dlopen puts things in the right place, it will pad out the forbidden
2689 chunks of address space so that dlopen is forced to put things where
2690 we want them.
2691
2692 The memory map it creates is:
2693
2694 CLIENT_BASE +-------------------------+
2695 | client address space |
2696 : :
2697 : :
2698 | client stack |
2699 client_end +-------------------------+
2700 | redzone |
2701 shadow_base +-------------------------+
2702 | |
nethercote996901a2004-08-03 13:29:09 +00002703 : shadow memory for tools :
nethercotec314eba2004-07-15 12:59:41 +00002704 | (may be 0 sized) |
2705 shadow_end +-------------------------+
2706 : gap (may be 0 sized) :
2707 valgrind_base +-------------------------+
2708 | kickstart executable |
2709 | valgrind heap vvvvvvvvv| (barely used)
2710 - -
2711 | valgrind .so files |
2712 | and mappings |
2713 - -
2714 | valgrind stack ^^^^^^^^^|
2715 valgrind_end +-------------------------+
2716 : kernel :
2717
2718 Nb: Before we can do general allocations with VG_(arena_malloc)() and
2719 VG_(mmap)(), we need to build the segment skip-list, so we know where
2720 we can put things. However, building that structure requires
2721 allocating memory. So we need to a bootstrapping process. It's done
2722 by making VG_(arena_malloc)() have a special static superblock that's
2723 used for the first 1MB's worth of allocations. This is enough to
2724 build the segment skip-list.
2725*/
2726
nethercote31779c72004-07-30 21:50:15 +00002727static int prmap(char *start, char *end, const char *perm, off_t off,
2728 int maj, int min, int ino, void* dummy) {
thughes4ad52d02004-06-27 17:37:21 +00002729 printf("mapping %10p-%10p %s %02x:%02x %d\n",
2730 start, end, perm, maj, min, ino);
2731 return True;
2732}
2733
nethercote71980f02004-01-24 18:18:54 +00002734int main(int argc, char **argv)
2735{
2736 char **cl_argv;
2737 const char *tool = NULL;
2738 const char *exec = NULL;
2739 char *preload; /* tool-specific LD_PRELOAD .so */
2740 char **env;
nethercote6c999f22004-01-31 22:55:15 +00002741 Int need_help = 0; // 0 = no, 1 = --help, 2 = --help-debug
nethercote71980f02004-01-24 18:18:54 +00002742 struct exeinfo info;
2743 ToolInfo *toolinfo = NULL;
2744 void *tool_dlhandle;
2745 Addr client_eip;
2746 Addr esp_at_startup; /* client's %esp at the point we gained control. */
2747 UInt * client_auxv;
2748 VgSchedReturnCode src;
nethercote47dd12c2004-06-22 14:18:42 +00002749 Int exitcode = 0;
fitzhardingeb50068f2004-02-24 23:42:55 +00002750 vki_rlimit zero = { 0, 0 };
nethercote31779c72004-07-30 21:50:15 +00002751 Int padfile;
nethercote759dda32004-08-07 18:16:56 +00002752 ThreadId last_run_tid = 0; // Last thread the scheduler ran.
2753
nethercote71980f02004-01-24 18:18:54 +00002754
2755 //============================================================
2756 // Nb: startup is complex. Prerequisites are shown at every step.
2757 //
2758 // *** Be very careful when messing with the order ***
2759 //============================================================
2760
nethercotef4928da2004-06-15 10:54:40 +00002761 //============================================================
2762 // Command line argument handling order:
2763 // * If --help/--help-debug are present, show usage message
2764 // (if --tool is also present, that includes the tool-specific usage)
2765 // * Then, if --tool is missing, abort with error msg
2766 // * Then, if client is missing, abort with error msg
2767 // * Then, if any cmdline args are bad, abort with error msg
2768 //============================================================
2769
fitzhardingeb50068f2004-02-24 23:42:55 +00002770 // Get the current process datasize rlimit, and set it to zero.
2771 // This prevents any internal uses of brk() from having any effect.
2772 // We remember the old value so we can restore it on exec, so that
2773 // child processes will have a reasonable brk value.
2774 VG_(getrlimit)(VKI_RLIMIT_DATA, &VG_(client_rlimit_data));
2775 zero.rlim_max = VG_(client_rlimit_data).rlim_max;
2776 VG_(setrlimit)(VKI_RLIMIT_DATA, &zero);
2777
nethercote71980f02004-01-24 18:18:54 +00002778 //--------------------------------------------------------------
2779 // Check we were launched by stage1
nethercotec314eba2004-07-15 12:59:41 +00002780 // p: n/a
nethercote71980f02004-01-24 18:18:54 +00002781 //--------------------------------------------------------------
nethercote31779c72004-07-30 21:50:15 +00002782 padfile = scan_auxv();
nethercote71980f02004-01-24 18:18:54 +00002783
2784 if (0) {
nethercote71980f02004-01-24 18:18:54 +00002785 printf("========== main() ==========\n");
nethercote31779c72004-07-30 21:50:15 +00002786 foreach_map(prmap, /*dummy*/NULL);
nethercote71980f02004-01-24 18:18:54 +00002787 }
2788
2789 //--------------------------------------------------------------
2790 // Look for alternative libdir
2791 // p: n/a
2792 //--------------------------------------------------------------
2793 { char *cp = getenv(VALGRINDLIB);
2794 if (cp != NULL)
2795 VG_(libdir) = cp;
2796 }
2797
2798 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002799 // Get valgrind args + client args (inc. from VALGRIND_OPTS/.valgrindrc).
2800 // Pre-process the command line.
2801 // p: n/a
2802 //--------------------------------------------------------------
nethercotef6a1d502004-08-09 12:21:57 +00002803 get_command_line(argc, argv, &vg_argc, &vg_argv, &cl_argv);
nethercote71980f02004-01-24 18:18:54 +00002804 pre_process_cmd_line_options(&need_help, &tool, &exec);
2805
2806 //==============================================================
2807 // Nb: once a tool is specified, the tool.so must be loaded even if
2808 // they specified --help or didn't specify a client program.
2809 //==============================================================
2810
2811 //--------------------------------------------------------------
2812 // With client padded out, map in tool
nethercote71980f02004-01-24 18:18:54 +00002813 // p: set-libdir [for VG_(libdir)]
2814 // p: pre_process_cmd_line_options() [for 'tool']
2815 //--------------------------------------------------------------
2816 load_tool(tool, &tool_dlhandle, &toolinfo, &preload);
2817
2818 //==============================================================
2819 // Can use VG_(malloc)() and VG_(arena_malloc)() only after load_tool()
nethercotec314eba2004-07-15 12:59:41 +00002820 // -- redzone size is now set. This is checked by vg_malloc2.c.
nethercote71980f02004-01-24 18:18:54 +00002821 //==============================================================
2822
2823 //--------------------------------------------------------------
2824 // Finalise address space layout
nethercote31779c72004-07-30 21:50:15 +00002825 // p: load_tool() [for 'toolinfo']
nethercote71980f02004-01-24 18:18:54 +00002826 //--------------------------------------------------------------
nethercote31779c72004-07-30 21:50:15 +00002827 layout_remaining_space( (Addr) & argc, toolinfo->shadow_ratio );
nethercote71980f02004-01-24 18:18:54 +00002828
2829 //--------------------------------------------------------------
2830 // Load client executable, finding in $PATH if necessary
nethercote71980f02004-01-24 18:18:54 +00002831 // p: pre_process_cmd_line_options() [for 'exec', 'need_help']
2832 // p: layout_remaining_space [so there's space]
2833 //--------------------------------------------------------------
nethercotef4928da2004-06-15 10:54:40 +00002834 load_client(cl_argv, exec, need_help, &info, &client_eip);
nethercote71980f02004-01-24 18:18:54 +00002835
2836 //--------------------------------------------------------------
2837 // Everything in place, unpad us
2838 // p: layout_remaining_space() [everything must be mapped in before now]
2839 // p: load_client() [ditto]
2840 //--------------------------------------------------------------
nethercote31779c72004-07-30 21:50:15 +00002841 as_unpad((void *)VG_(shadow_end), (void *)~0, padfile);
2842 as_closepadfile(padfile); // no more padding
nethercote71980f02004-01-24 18:18:54 +00002843
2844 //--------------------------------------------------------------
2845 // Set up client's environment
2846 // p: set-libdir [for VG_(libdir)]
2847 // p: load_tool() [for 'preload']
2848 //--------------------------------------------------------------
2849 env = fix_environment(environ, preload);
2850
2851 //--------------------------------------------------------------
nethercote5ee67ca2004-06-22 14:00:09 +00002852 // Setup client stack, eip, and VG_(client_arg[cv])
nethercote71980f02004-01-24 18:18:54 +00002853 // p: load_client() [for 'info']
2854 // p: fix_environment() [for 'env']
2855 //--------------------------------------------------------------
2856 esp_at_startup = setup_client_stack(cl_argv, env, &info, &client_auxv);
2857
2858 if (0)
2859 printf("entry=%x client esp=%x vg_argc=%d brkbase=%x\n",
nethercotef6a1d502004-08-09 12:21:57 +00002860 client_eip, esp_at_startup, vg_argc, VG_(brk_base));
nethercote71980f02004-01-24 18:18:54 +00002861
2862 //==============================================================
2863 // Finished setting up operating environment. Now initialise
2864 // Valgrind. (This is where the old VG_(main)() started.)
2865 //==============================================================
2866
2867 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002868 // atfork
2869 // p: n/a
2870 //--------------------------------------------------------------
2871 VG_(atfork)(NULL, NULL, newpid);
2872 newpid(VG_INVALID_THREADID);
2873
2874 //--------------------------------------------------------------
2875 // setup file descriptors
2876 // p: n/a
2877 //--------------------------------------------------------------
2878 setup_file_descriptors();
2879
2880 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002881 // Read /proc/self/maps into a buffer
2882 // p: all memory layout, environment setup [so memory maps are right]
2883 //--------------------------------------------------------------
2884 VG_(read_procselfmaps)();
2885
2886 //--------------------------------------------------------------
2887 // Build segment map (Valgrind segments only)
2888 // p: read proc/self/maps
2889 // p: sk_pre_clo_init() [to setup new_mem_startup tracker]
2890 //--------------------------------------------------------------
2891 VG_(parse_procselfmaps) ( build_valgrind_map_callback );
2892
2893 //==============================================================
2894 // Can use VG_(arena_malloc)() with non-CORE arena after segments set up
2895 //==============================================================
2896
2897 //--------------------------------------------------------------
2898 // Init tool: pre_clo_init, process cmd line, post_clo_init
2899 // p: setup_client_stack() [for 'VG_(client_arg[cv]']
2900 // p: load_tool() [for 'tool']
2901 // p: setup_file_descriptors() [for 'VG_(fd_xxx_limit)']
2902 // p: parse_procselfmaps [so VG segments are setup so tool can
2903 // call VG_(malloc)]
nethercote71980f02004-01-24 18:18:54 +00002904 //--------------------------------------------------------------
2905 (*toolinfo->sk_pre_clo_init)();
2906 VG_(tool_init_dlsym)(tool_dlhandle);
2907 VG_(sanity_check_needs)();
2908
nethercotef4928da2004-06-15 10:54:40 +00002909 // If --tool and --help/--help-debug was given, now give the core+tool
2910 // help message
nethercotef4928da2004-06-15 10:54:40 +00002911 if (need_help) {
2912 usage(/*--help-debug?*/2 == need_help);
2913 }
nethercotec314eba2004-07-15 12:59:41 +00002914 process_cmd_line_options(client_auxv, tool);
2915
2916 SK_(post_clo_init)();
nethercotef4928da2004-06-15 10:54:40 +00002917
2918 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002919 // Build segment map (all segments)
2920 // p: setup_client_stack() [for 'esp_at_startup']
2921 // p: init tool [for 'new_mem_startup']
nethercote71980f02004-01-24 18:18:54 +00002922 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002923 esp_at_startup___global_arg = esp_at_startup;
2924 VG_(parse_procselfmaps) ( build_segment_map_callback ); /* everything */
2925 esp_at_startup___global_arg = 0;
2926
2927 //--------------------------------------------------------------
nethercotef84f6952004-07-15 14:58:33 +00002928 // Protect client trampoline page (which is also sysinfo stuff)
2929 // p: segment stuff [otherwise get seg faults...]
nethercotec314eba2004-07-15 12:59:41 +00002930 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002931 VG_(mprotect)( (void *)VG_(client_trampoline_code),
2932 VG_(trampoline_code_length), VKI_PROT_READ|VKI_PROT_EXEC );
2933
2934 //==============================================================
2935 // Can use VG_(map)() after segments set up
2936 //==============================================================
nethercote71980f02004-01-24 18:18:54 +00002937
2938 //--------------------------------------------------------------
2939 // Allow GDB attach
2940 // p: process_cmd_line_options() [for VG_(clo_wait_for_gdb)]
2941 //--------------------------------------------------------------
2942 /* Hook to delay things long enough so we can get the pid and
2943 attach GDB in another shell. */
2944 if (VG_(clo_wait_for_gdb)) {
2945 VG_(printf)("pid=%d\n", VG_(getpid)());
2946 /* do "jump *$eip" to skip this in gdb */
2947 VG_(do_syscall)(__NR_pause);
2948 }
2949
2950 //--------------------------------------------------------------
nethercote1d447092004-02-01 17:29:59 +00002951 // Set up baseBlock
nethercote71980f02004-01-24 18:18:54 +00002952 // p: {pre,post}_clo_init() [for tool helper registration]
2953 // load_client() [for 'client_eip']
2954 // setup_client_stack() [for 'esp_at_startup']
2955 //--------------------------------------------------------------
2956 init_baseBlock(client_eip, esp_at_startup);
2957
2958 //--------------------------------------------------------------
2959 // Search for file descriptors that are inherited from our parent
2960 // p: process_cmd_line_options [for VG_(clo_track_fds)]
2961 //--------------------------------------------------------------
2962 if (VG_(clo_track_fds))
2963 VG_(init_preopened_fds)();
2964
2965 //--------------------------------------------------------------
2966 // Initialise the scheduler
2967 // p: init_baseBlock() [baseBlock regs copied into VG_(threads)[1]]
2968 // p: setup_file_descriptors() [else VG_(safe_fd)() breaks]
2969 //--------------------------------------------------------------
2970 VG_(scheduler_init)();
2971
2972 //--------------------------------------------------------------
2973 // Set up the ProxyLWP machinery
2974 // p: VG_(scheduler_init)()? [XXX: subtle dependency?]
nethercote71980f02004-01-24 18:18:54 +00002975 //--------------------------------------------------------------
2976 VG_(proxy_init)();
2977
2978 //--------------------------------------------------------------
2979 // Initialise the signal handling subsystem
2980 // p: VG_(atfork)(NULL, NULL, newpid) [else problems with sigmasks]
2981 // p: VG_(proxy_init)() [else breaks...]
2982 //--------------------------------------------------------------
2983 // Nb: temporarily parks the saved blocking-mask in saved_sigmask.
2984 VG_(sigstartup_actions)();
2985
2986 //--------------------------------------------------------------
2987 // Perhaps we're profiling Valgrind?
2988 // p: process_cmd_line_options() [for VG_(clo_profile)]
2989 // p: others?
2990 //
2991 // XXX: this seems to be broken? It always says the tool wasn't built
2992 // for profiling; vg_profile.c's functions don't seem to be overriding
2993 // vg_dummy_profile.c's?
2994 //
2995 // XXX: want this as early as possible. Looking for --profile
2996 // in pre_process_cmd_line_options() could get it earlier.
2997 //--------------------------------------------------------------
2998 if (VG_(clo_profile))
2999 VGP_(init_profiling)();
3000
3001 VGP_PUSHCC(VgpStartup);
3002
3003 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00003004 // Read suppression file
3005 // p: process_cmd_line_options() [for VG_(clo_suppressions)]
3006 //--------------------------------------------------------------
3007 if (VG_(needs).core_errors || VG_(needs).skin_errors)
3008 VG_(load_suppressions)();
3009
3010 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00003011 // Initialise translation table and translation cache
3012 // p: read_procselfmaps [so the anonymous mmaps for the TT/TC
3013 // aren't identified as part of the client, which would waste
3014 // > 20M of virtual address space.]
3015 //--------------------------------------------------------------
3016 VG_(init_tt_tc)();
3017
3018 //--------------------------------------------------------------
3019 // Read debug info to find glibc entry points to intercept
3020 // p: parse_procselfmaps? [XXX for debug info?]
3021 // p: init_tt_tc? [XXX ???]
3022 //--------------------------------------------------------------
3023 VG_(setup_code_redirect_table)();
3024
3025 //--------------------------------------------------------------
3026 // Verbosity message
3027 // p: end_rdtsc_calibration [so startup message is printed first]
3028 //--------------------------------------------------------------
3029 if (VG_(clo_verbosity) == 1)
3030 VG_(message)(Vg_UserMsg, "For more details, rerun with: -v");
3031 if (VG_(clo_verbosity) > 0)
3032 VG_(message)(Vg_UserMsg, "");
3033
3034 //--------------------------------------------------------------
3035 // Setup pointercheck
3036 // p: process_cmd_line_options() [for VG_(clo_pointercheck)]
3037 //--------------------------------------------------------------
3038 setup_pointercheck();
3039
nethercote71980f02004-01-24 18:18:54 +00003040 //--------------------------------------------------------------
3041 // Run!
3042 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00003043 VGP_POPCC(VgpStartup);
3044 VGP_PUSHCC(VgpSched);
3045
nethercote31294822004-08-02 13:15:26 +00003046 VG_(fatal_signal_jmpbuf_ptr) = &fatal_signal_jmpbuf;
3047 if (__builtin_setjmp(VG_(fatal_signal_jmpbuf_ptr)) == 0) {
nethercote759dda32004-08-07 18:16:56 +00003048 src = VG_(scheduler)( &exitcode, &last_run_tid );
nethercote31294822004-08-02 13:15:26 +00003049 } else {
nethercote71980f02004-01-24 18:18:54 +00003050 src = VgSrc_FatalSig;
nethercote31294822004-08-02 13:15:26 +00003051 }
nethercote71980f02004-01-24 18:18:54 +00003052 VGP_POPCC(VgpSched);
nethercote71980f02004-01-24 18:18:54 +00003053
3054
3055
3056 //--------------------------------------------------------------
3057 // Finalisation: cleanup, messages, etc. Order no so important, only
3058 // affects what order the messages come.
3059 //--------------------------------------------------------------
3060 if (VG_(clo_verbosity) > 0)
3061 VG_(message)(Vg_UserMsg, "");
3062
3063 if (src == VgSrc_Deadlock) {
3064 VG_(message)(Vg_UserMsg,
3065 "Warning: pthread scheduler exited due to deadlock");
3066 }
3067
3068 /* Print out file descriptor summary and stats. */
3069 if (VG_(clo_track_fds))
nethercote3a42fb82004-08-03 18:08:50 +00003070 VG_(show_open_fds)();
nethercote71980f02004-01-24 18:18:54 +00003071
3072 if (VG_(needs).core_errors || VG_(needs).skin_errors)
3073 VG_(show_all_errors)();
3074
nethercote47dd12c2004-06-22 14:18:42 +00003075 SK_(fini)( exitcode );
nethercote71980f02004-01-24 18:18:54 +00003076
nethercote885dd912004-08-03 23:14:00 +00003077 VG_(sanity_check_general)( True /*include expensive checks*/ );
nethercote71980f02004-01-24 18:18:54 +00003078
3079 if (VG_(clo_verbosity) > 1)
nethercote3a42fb82004-08-03 18:08:50 +00003080 print_all_stats();
nethercote71980f02004-01-24 18:18:54 +00003081
nethercote71980f02004-01-24 18:18:54 +00003082 if (VG_(clo_profile))
3083 VGP_(done_profiling)();
3084
nethercote71980f02004-01-24 18:18:54 +00003085 /* We're exiting, so nuke all the threads and clean up the proxy LWPs */
3086 vg_assert(src == VgSrc_FatalSig ||
nethercote759dda32004-08-07 18:16:56 +00003087 VG_(threads)[last_run_tid].status == VgTs_Runnable ||
3088 VG_(threads)[last_run_tid].status == VgTs_WaitJoiner);
nethercote71980f02004-01-24 18:18:54 +00003089 VG_(nuke_all_threads_except)(VG_INVALID_THREADID);
3090
3091 //--------------------------------------------------------------
3092 // Exit, according to the scheduler's return code
3093 //--------------------------------------------------------------
3094 switch (src) {
3095 case VgSrc_ExitSyscall: /* the normal way out */
nethercote759dda32004-08-07 18:16:56 +00003096 vg_assert(last_run_tid > 0 && last_run_tid < VG_N_THREADS);
nethercote71980f02004-01-24 18:18:54 +00003097 VG_(proxy_shutdown)();
3098
3099 /* The thread's %EBX at the time it did __NR_exit() will hold
3100 the arg to __NR_exit(), so we just do __NR_exit() with
3101 that arg. */
nethercote47dd12c2004-06-22 14:18:42 +00003102 VG_(exit)( exitcode );
nethercote71980f02004-01-24 18:18:54 +00003103 /* NOT ALIVE HERE! */
3104 VG_(core_panic)("entered the afterlife in main() -- ExitSyscall");
3105 break; /* what the hell :) */
3106
3107 case VgSrc_Deadlock:
3108 /* Just exit now. No point in continuing. */
3109 VG_(proxy_shutdown)();
3110 VG_(exit)(0);
3111 VG_(core_panic)("entered the afterlife in main() -- Deadlock");
3112 break;
3113
nethercote71980f02004-01-24 18:18:54 +00003114 case VgSrc_FatalSig:
3115 /* We were killed by a fatal signal, so replicate the effect */
3116 vg_assert(VG_(fatal_sigNo) != -1);
3117 VG_(kill_self)(VG_(fatal_sigNo));
3118 VG_(core_panic)("main(): signal was supposed to be fatal");
3119 break;
3120
3121 default:
3122 VG_(core_panic)("main(): unexpected scheduler return code");
3123 }
3124
3125 abort();
3126}
3127
3128
sewardjde4a1d02002-03-22 01:27:54 +00003129/*--------------------------------------------------------------------*/
3130/*--- end vg_main.c ---*/
3131/*--------------------------------------------------------------------*/