blob: 10d50d11b05ccad999ecef2e43c672bb86ad08ae [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
nethercote71980f02004-01-24 18:18:54 +0000152/* Counts downwards in VG_(run_innerloop). */
153UInt VG_(dispatch_ctr);
sewardjde4a1d02002-03-22 01:27:54 +0000154
155/* 64-bit counter for the number of basic blocks done. */
156ULong VG_(bbs_done);
sewardjde4a1d02002-03-22 01:27:54 +0000157
nethercote71980f02004-01-24 18:18:54 +0000158/* Tell the logging mechanism whether we are logging to a file
159 descriptor or a socket descriptor. */
160Bool VG_(logging_to_filedes) = True;
161
sewardj73cf3bc2002-11-03 03:20:15 +0000162
nethercote71980f02004-01-24 18:18:54 +0000163/*====================================================================*/
164/*=== Counters, for profiling purposes only ===*/
165/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +0000166
nethercote92e7b7f2004-08-07 17:52:25 +0000167// These ones maintained by vg_dispatch.S
168UInt VG_(bb_enchain_count) = 0; // Number of chain operations done
169UInt VG_(bb_dechain_count) = 0; // Number of unchain operations done
170UInt VG_(unchained_jumps_done) = 0; // Number of unchained jumps done
sewardjde4a1d02002-03-22 01:27:54 +0000171
sewardjde4a1d02002-03-22 01:27:54 +0000172/* Counts pertaining to internal sanity checking. */
nethercote297effd2004-08-02 15:07:57 +0000173static UInt sanity_fast_count = 0;
174static UInt sanity_slow_count = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000175
nethercote3a42fb82004-08-03 18:08:50 +0000176static void print_all_stats ( void )
nethercote71980f02004-01-24 18:18:54 +0000177{
nethercote3a42fb82004-08-03 18:08:50 +0000178 // Translation stats
nethercote92e7b7f2004-08-07 17:52:25 +0000179 VG_(print_tt_tc_stats)();
nethercote71980f02004-01-24 18:18:54 +0000180 VG_(message)(Vg_DebugMsg,
nethercote92e7b7f2004-08-07 17:52:25 +0000181 "chainings: %d chainings, %d unchainings.",
nethercote71980f02004-01-24 18:18:54 +0000182 VG_(bb_enchain_count), VG_(bb_dechain_count) );
183 VG_(message)(Vg_DebugMsg,
nethercote3a42fb82004-08-03 18:08:50 +0000184 " dispatch: %llu jumps (bb entries); of them %u (%lu%%) unchained.",
nethercote71980f02004-01-24 18:18:54 +0000185 VG_(bbs_done),
186 VG_(unchained_jumps_done),
187 ((ULong)(100) * (ULong)(VG_(unchained_jumps_done)))
188 / ( VG_(bbs_done)==0 ? 1 : VG_(bbs_done) )
189 );
190
nethercote3a42fb82004-08-03 18:08:50 +0000191 // Scheduler stats
nethercote844e7122004-08-02 15:27:22 +0000192 VG_(print_scheduler_stats)();
nethercote71980f02004-01-24 18:18:54 +0000193
nethercote3a42fb82004-08-03 18:08:50 +0000194 // Reg-alloc stats
nethercotebee3fd92004-08-02 15:17:43 +0000195 VG_(print_reg_alloc_stats)();
nethercote71980f02004-01-24 18:18:54 +0000196 VG_(message)(Vg_DebugMsg,
197 " sanity: %d cheap, %d expensive checks.",
nethercote297effd2004-08-02 15:07:57 +0000198 sanity_fast_count, sanity_slow_count );
nethercote3a42fb82004-08-03 18:08:50 +0000199
200 // C call stats
nethercote71980f02004-01-24 18:18:54 +0000201 VG_(print_ccall_stats)();
nethercote3a42fb82004-08-03 18:08:50 +0000202
203 // UInstr histogram
204 if (VG_(clo_verbosity) > 3)
205 VG_(print_UInstr_histogram)();
206
207 // Memory stats
nethercote885dd912004-08-03 23:14:00 +0000208 if (VG_(clo_verbosity) > 2) {
nethercote3a42fb82004-08-03 18:08:50 +0000209 VG_(message)(Vg_DebugMsg, "");
210 VG_(message)(Vg_DebugMsg,
211 "------ Valgrind's internal memory use stats follow ------" );
nethercote885dd912004-08-03 23:14:00 +0000212 VG_(sanity_check_malloc_all)();
nethercote3a42fb82004-08-03 18:08:50 +0000213 VG_(print_all_arena_stats)();
nethercote885dd912004-08-03 23:14:00 +0000214 VG_(message)(Vg_DebugMsg, "");
nethercote3a42fb82004-08-03 18:08:50 +0000215 VG_(message)(Vg_DebugMsg,
216 "------ Valgrind's ExeContext management stats follow ------" );
217 VG_(print_ExeContext_stats)();
218 }
nethercote71980f02004-01-24 18:18:54 +0000219}
220
221
222/*====================================================================*/
223/*=== Miscellaneous global functions ===*/
224/*====================================================================*/
225
nethercote04d0fbc2004-01-26 16:48:06 +0000226/* Start debugger and get it to attach to this process. Called if the
227 user requests this service after an error has been shown, so she can
nethercote71980f02004-01-24 18:18:54 +0000228 poke around and look at parameters, memory, etc. You can't
nethercote04d0fbc2004-01-26 16:48:06 +0000229 meaningfully get the debugger to continue the program, though; to
230 continue, quit the debugger. */
231void VG_(start_debugger) ( Int tid )
nethercote71980f02004-01-24 18:18:54 +0000232{
233 Int pid;
234
235 if ((pid = fork()) == 0) {
236 ptrace(PTRACE_TRACEME, 0, NULL, NULL);
237 VG_(kkill)(VG_(getpid)(), VKI_SIGSTOP);
238
239 } else if (pid > 0) {
240 struct user_regs_struct regs;
241 Int status;
242 Int res;
243
244 if (VG_(is_running_thread)( tid )) {
fitzhardinged65dcad2004-03-13 02:06:58 +0000245 regs.cs = VG_(baseBlock)[VGOFF_(m_cs)];
246 regs.ss = VG_(baseBlock)[VGOFF_(m_ss)];
247 regs.ds = VG_(baseBlock)[VGOFF_(m_ds)];
248 regs.es = VG_(baseBlock)[VGOFF_(m_es)];
249 regs.fs = VG_(baseBlock)[VGOFF_(m_fs)];
250 regs.gs = VG_(baseBlock)[VGOFF_(m_gs)];
nethercote71980f02004-01-24 18:18:54 +0000251 regs.eax = VG_(baseBlock)[VGOFF_(m_eax)];
252 regs.ebx = VG_(baseBlock)[VGOFF_(m_ebx)];
253 regs.ecx = VG_(baseBlock)[VGOFF_(m_ecx)];
254 regs.edx = VG_(baseBlock)[VGOFF_(m_edx)];
255 regs.esi = VG_(baseBlock)[VGOFF_(m_esi)];
256 regs.edi = VG_(baseBlock)[VGOFF_(m_edi)];
257 regs.ebp = VG_(baseBlock)[VGOFF_(m_ebp)];
258 regs.esp = VG_(baseBlock)[VGOFF_(m_esp)];
259 regs.eflags = VG_(baseBlock)[VGOFF_(m_eflags)];
260 regs.eip = VG_(baseBlock)[VGOFF_(m_eip)];
261 } else {
262 ThreadState* tst = & VG_(threads)[ tid ];
263
fitzhardinged65dcad2004-03-13 02:06:58 +0000264 regs.cs = tst->m_cs;
265 regs.ss = tst->m_ss;
266 regs.ds = tst->m_ds;
267 regs.es = tst->m_es;
268 regs.fs = tst->m_fs;
269 regs.gs = tst->m_gs;
nethercote71980f02004-01-24 18:18:54 +0000270 regs.eax = tst->m_eax;
271 regs.ebx = tst->m_ebx;
272 regs.ecx = tst->m_ecx;
273 regs.edx = tst->m_edx;
274 regs.esi = tst->m_esi;
275 regs.edi = tst->m_edi;
276 regs.ebp = tst->m_ebp;
277 regs.esp = tst->m_esp;
278 regs.eflags = tst->m_eflags;
279 regs.eip = tst->m_eip;
280 }
281
282 if ((res = VG_(waitpid)(pid, &status, 0)) == pid &&
283 WIFSTOPPED(status) && WSTOPSIG(status) == SIGSTOP &&
284 ptrace(PTRACE_SETREGS, pid, NULL, &regs) == 0 &&
thughes1d160052004-04-21 15:39:57 +0000285 kill(pid, SIGSTOP) == 0 &&
286 ptrace(PTRACE_DETACH, pid, NULL, 0) == 0) {
nethercote04d0fbc2004-01-26 16:48:06 +0000287 Char pidbuf[15];
288 Char file[30];
289 Char buf[100];
290 Char *bufptr;
291 Char *cmdptr;
292
293 VG_(sprintf)(pidbuf, "%d", pid);
294 VG_(sprintf)(file, "/proc/%d/fd/%d", pid, VG_(clexecfd));
295
296 bufptr = buf;
297 cmdptr = VG_(clo_db_command);
298
299 while (*cmdptr) {
300 switch (*cmdptr) {
301 case '%':
302 switch (*++cmdptr) {
303 case 'f':
304 VG_(memcpy)(bufptr, file, VG_(strlen)(file));
305 bufptr += VG_(strlen)(file);
306 cmdptr++;
307 break;
308 case 'p':
309 VG_(memcpy)(bufptr, pidbuf, VG_(strlen)(pidbuf));
310 bufptr += VG_(strlen)(pidbuf);
311 cmdptr++;
312 break;
313 default:
314 *bufptr++ = *cmdptr++;
315 break;
316 }
317 break;
318 default:
319 *bufptr++ = *cmdptr++;
320 break;
321 }
322 }
323
324 *bufptr++ = '\0';
325
326 VG_(message)(Vg_UserMsg, "starting debugger with cmd: %s", buf);
nethercote71980f02004-01-24 18:18:54 +0000327 res = VG_(system)(buf);
328 if (res == 0) {
329 VG_(message)(Vg_UserMsg, "");
330 VG_(message)(Vg_UserMsg,
nethercote04d0fbc2004-01-26 16:48:06 +0000331 "Debugger has detached. Valgrind regains control. We continue.");
nethercote71980f02004-01-24 18:18:54 +0000332 } else {
333 VG_(message)(Vg_UserMsg, "Apparently failed!");
334 VG_(message)(Vg_UserMsg, "");
335 }
336 }
337
338 VG_(kkill)(pid, VKI_SIGKILL);
339 VG_(waitpid)(pid, &status, 0);
340 }
341}
342
343
344/* Print some helpful-ish text about unimplemented things, and give
345 up. */
346void VG_(unimplemented) ( Char* msg )
347{
348 VG_(message)(Vg_UserMsg, "");
349 VG_(message)(Vg_UserMsg,
350 "Valgrind detected that your program requires");
351 VG_(message)(Vg_UserMsg,
352 "the following unimplemented functionality:");
353 VG_(message)(Vg_UserMsg, " %s", msg);
354 VG_(message)(Vg_UserMsg,
355 "This may be because the functionality is hard to implement,");
356 VG_(message)(Vg_UserMsg,
357 "or because no reasonable program would behave this way,");
358 VG_(message)(Vg_UserMsg,
359 "or because nobody has yet needed it. In any case, let us know at");
360 VG_(message)(Vg_UserMsg,
361 "%s and/or try to work around the problem, if you can.", VG_BUGS_TO);
362 VG_(message)(Vg_UserMsg,
363 "");
364 VG_(message)(Vg_UserMsg,
365 "Valgrind has to exit now. Sorry. Bye!");
366 VG_(message)(Vg_UserMsg,
367 "");
368 VG_(pp_sched_status)();
369 VG_(exit)(1);
370}
371
372Addr VG_(get_stack_pointer) ( void )
373{
374 return VG_(baseBlock)[VGOFF_(m_esp)];
375}
376
377/* Debugging thing .. can be called from assembly with OYNK macro. */
378void VG_(oynk) ( Int n )
379{
380 OINK(n);
381}
382
383/* Initialize the PID and PGRP of scheduler LWP; this is also called
384 in any new children after fork. */
385static void newpid(ThreadId unused)
386{
387 /* PID of scheduler LWP */
388 VG_(main_pid) = VG_(getpid)();
389 VG_(main_pgrp) = VG_(getpgrp)();
390}
391
392/*====================================================================*/
393/*=== Check we were launched by stage 1 ===*/
394/*====================================================================*/
395
396/* Look for our AUXV table */
nethercote31779c72004-07-30 21:50:15 +0000397int scan_auxv(void)
nethercote71980f02004-01-24 18:18:54 +0000398{
399 const struct ume_auxv *auxv = find_auxv((int *)ume_exec_esp);
nethercote31779c72004-07-30 21:50:15 +0000400 int padfile = -1, found = 0;
nethercote71980f02004-01-24 18:18:54 +0000401
402 for (; auxv->a_type != AT_NULL; auxv++)
403 switch(auxv->a_type) {
404 case AT_UME_PADFD:
nethercote31779c72004-07-30 21:50:15 +0000405 padfile = auxv->u.a_val;
nethercote71980f02004-01-24 18:18:54 +0000406 found |= 1;
407 break;
408
409 case AT_UME_EXECFD:
nethercotef6a1d502004-08-09 12:21:57 +0000410 vgexecfd = auxv->u.a_val;
nethercote71980f02004-01-24 18:18:54 +0000411 found |= 2;
412 break;
413 }
414
nethercote361a14e2004-07-26 11:11:56 +0000415 if ( found != (1|2) ) {
416 fprintf(stderr, "valgrind: stage2 must be launched by stage1\n");
nethercote71980f02004-01-24 18:18:54 +0000417 exit(127);
418 }
nethercote31779c72004-07-30 21:50:15 +0000419 vg_assert(padfile >= 0);
420 return padfile;
nethercote71980f02004-01-24 18:18:54 +0000421}
422
423
424/*====================================================================*/
425/*=== Address space determination ===*/
426/*====================================================================*/
427
nethercote31779c72004-07-30 21:50:15 +0000428static void layout_remaining_space(Addr argc_addr, float ratio)
nethercote71980f02004-01-24 18:18:54 +0000429{
nethercote31779c72004-07-30 21:50:15 +0000430 Int ires;
431 void* vres;
432 addr_t client_size, shadow_size;
nethercote71980f02004-01-24 18:18:54 +0000433
nethercote31779c72004-07-30 21:50:15 +0000434 VG_(valgrind_base) = (addr_t)&kickstart_base;
rjwalshebca8b42004-08-23 18:13:16 +0000435 VG_(valgrind_end) = ROUNDUP(argc_addr, 0x10000) - 1; // stack
nethercote71980f02004-01-24 18:18:54 +0000436
nethercote31779c72004-07-30 21:50:15 +0000437 // This gives the client the largest possible address space while
438 // taking into account the tool's shadow needs.
439 client_size = ROUNDDN((VG_(valgrind_base)-REDZONE_SIZE) / (1.+ratio),
nethercote71980f02004-01-24 18:18:54 +0000440 CLIENT_SIZE_MULTIPLE);
nethercote31779c72004-07-30 21:50:15 +0000441 VG_(client_base) = CLIENT_BASE;
nethercote71980f02004-01-24 18:18:54 +0000442 VG_(client_end) = VG_(client_base) + client_size;
nethercotee2097312004-06-27 12:29:56 +0000443 /* where !FIXED mmap goes */
nethercotebc7b4f42004-07-26 12:44:35 +0000444 VG_(client_mapbase) = VG_(client_base) +
445 PGROUNDDN((addr_t)(client_size * CLIENT_HEAP_PROPORTION));
nethercote71980f02004-01-24 18:18:54 +0000446
nethercote31779c72004-07-30 21:50:15 +0000447 shadow_size = PGROUNDUP(client_size * ratio);
448 VG_(shadow_base) = VG_(client_end) + REDZONE_SIZE;
449 VG_(shadow_end) = VG_(shadow_base) + shadow_size;
nethercote71980f02004-01-24 18:18:54 +0000450
nethercotee2097312004-06-27 12:29:56 +0000451#define SEGSIZE(a,b) ((VG_(b) - VG_(a))/(1024*1024))
452
nethercote71980f02004-01-24 18:18:54 +0000453 if (0)
nethercotee2097312004-06-27 12:29:56 +0000454 VG_(printf)(
455 "client_base %8x (%dMB)\n"
456 "client_mapbase %8x (%dMB)\n"
457 "client_end %8x (%dMB)\n"
458 "shadow_base %8x (%dMB)\n"
459 "shadow_end %8x (%dMB)\n"
460 "valgrind_base %8x (%dMB)\n"
nethercotee2097312004-06-27 12:29:56 +0000461 "valgrind_end %8x\n",
462 VG_(client_base), SEGSIZE(client_base, client_mapbase),
463 VG_(client_mapbase), SEGSIZE(client_mapbase, client_end),
464 VG_(client_end), SEGSIZE(client_end, shadow_base),
465 VG_(shadow_base), SEGSIZE(shadow_base, shadow_end),
466 VG_(shadow_end), SEGSIZE(shadow_end, valgrind_base),
nethercotec314eba2004-07-15 12:59:41 +0000467 VG_(valgrind_base), SEGSIZE(valgrind_base, valgrind_end),
nethercotee2097312004-06-27 12:29:56 +0000468 VG_(valgrind_end)
469 );
470
471#undef SEGSIZE
nethercote71980f02004-01-24 18:18:54 +0000472
473 // Ban redzone
nethercotee567e702004-07-10 17:49:17 +0000474 vres = mmap((void *)VG_(client_end), REDZONE_SIZE, PROT_NONE,
475 MAP_FIXED|MAP_ANON|MAP_PRIVATE, -1, 0);
476 vg_assert((void*)-1 != vres);
nethercote71980f02004-01-24 18:18:54 +0000477
478 // Make client hole
nethercotee567e702004-07-10 17:49:17 +0000479 ires = munmap((void*)VG_(client_base), client_size);
480 vg_assert(0 == ires);
nethercote71980f02004-01-24 18:18:54 +0000481
482 // Map shadow memory.
483 // Initially all inaccessible, incrementally initialized as it is used
nethercotee567e702004-07-10 17:49:17 +0000484 if (shadow_size != 0) {
485 vres = mmap((char *)VG_(shadow_base), shadow_size, PROT_NONE,
486 MAP_PRIVATE|MAP_ANON|MAP_FIXED, -1, 0);
487 vg_assert((void*)-1 != vres);
488 }
nethercote71980f02004-01-24 18:18:54 +0000489}
490
491/*====================================================================*/
492/*=== Command line setup ===*/
493/*====================================================================*/
494
495/* Nb: malloc'd memory never freed -- kept throughout like argv, envp */
496static char* get_file_clo(char* dir)
497{
498# define FLEN 512
499 Int fd, n;
500 struct stat s1;
501 char* f_clo = NULL;
502 char filename[FLEN];
503
504 snprintf(filename, FLEN, "%s/.valgrindrc", ( NULL == dir ? "" : dir ) );
505 fd = VG_(open)(filename, 0, VKI_S_IRUSR);
506 if ( fd > 0 ) {
507 if ( 0 == fstat(fd, &s1) ) {
508 f_clo = malloc(s1.st_size+1);
509 vg_assert(f_clo);
510 n = read(fd, f_clo, s1.st_size);
511 if (n == -1) n = 0;
512 f_clo[n] = '\0';
513 }
514 close(fd);
515 }
516 return f_clo;
517# undef FLEN
518}
519
nethercotee2097312004-06-27 12:29:56 +0000520#define ISSPACE(cc) ((cc) == ' ' || (cc) == '\t' || (cc) == '\n')
521
nethercote71980f02004-01-24 18:18:54 +0000522static Int count_args(char* s)
523{
524 Int n = 0;
525 if (s) {
526 char* cp = s;
527 while (True) {
528 // We have alternating sequences: blanks, non-blanks, blanks...
529 // count the non-blanks sequences.
530 while ( ISSPACE(*cp) ) cp++;
531 if ( !*cp ) break;
532 n++;
533 while ( !ISSPACE(*cp) && *cp ) cp++;
534 }
535 }
536 return n;
537}
538
539/* add args out of environment, skipping multiple spaces and -- args */
540static char** copy_args( char* s, char** to )
541{
542 if (s) {
543 char* cp = s;
544 while (True) {
545 // We have alternating sequences: blanks, non-blanks, blanks...
546 // copy the non-blanks sequences, and add terminating '\0'
547 while ( ISSPACE(*cp) ) cp++;
548 if ( !*cp ) break;
549 *to++ = cp;
550 while ( !ISSPACE(*cp) && *cp ) cp++;
551 if ( *cp ) *cp++ = '\0'; // terminate if necessary
552 if (VG_STREQ(to[-1], "--")) to--; // undo any '--' arg
553 }
554 }
555 return to;
556}
557
nethercotee2097312004-06-27 12:29:56 +0000558#undef ISSPACE
559
nethercote71980f02004-01-24 18:18:54 +0000560// Augment command line with arguments from environment and .valgrindrc
561// files.
562static void augment_command_line(Int* vg_argc_inout, char*** vg_argv_inout)
563{
nethercotef6a1d502004-08-09 12:21:57 +0000564 int vg_argc0 = *vg_argc_inout;
565 char** vg_argv0 = *vg_argv_inout;
nethercote71980f02004-01-24 18:18:54 +0000566
567 char* env_clo = getenv(VALGRINDOPTS);
568 char* f1_clo = get_file_clo( getenv("HOME") );
569 char* f2_clo = get_file_clo(".");
570
571 /* copy any extra args from file or environment, if present */
572 if ( (env_clo && *env_clo) || (f1_clo && *f1_clo) || (f2_clo && *f2_clo) ) {
573 /* ' ' separated extra options */
574 char **from;
575 char **to;
576 int env_arg_count, f1_arg_count, f2_arg_count;
577
578 env_arg_count = count_args(env_clo);
579 f1_arg_count = count_args(f1_clo);
580 f2_arg_count = count_args(f2_clo);
581
582 if (0)
583 printf("extra-argc=%d %d %d\n",
584 env_arg_count, f1_arg_count, f2_arg_count);
585
586 /* +2: +1 for null-termination, +1 for added '--' */
nethercotef6a1d502004-08-09 12:21:57 +0000587 from = vg_argv0;
588 vg_argv0 = malloc( (vg_argc0 + env_arg_count + f1_arg_count
nethercote71980f02004-01-24 18:18:54 +0000589 + f2_arg_count + 2) * sizeof(char **));
nethercotef6a1d502004-08-09 12:21:57 +0000590 vg_assert(vg_argv0);
591 to = vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000592
593 /* copy argv[0] */
594 *to++ = *from++;
595
596 /* Copy extra args from env var and file, in the order: ~/.valgrindrc,
597 * $VALGRIND_OPTS, ./.valgrindrc -- more local options are put later
598 * to override less local ones. */
599 to = copy_args(f1_clo, to);
600 to = copy_args(env_clo, to);
601 to = copy_args(f2_clo, to);
602
603 /* copy original arguments, stopping at command or -- */
604 while (*from) {
605 if (**from != '-')
606 break;
607 if (VG_STREQ(*from, "--")) {
608 from++; /* skip -- */
609 break;
610 }
611 *to++ = *from++;
612 }
613
614 /* add -- */
615 *to++ = "--";
616
nethercotef6a1d502004-08-09 12:21:57 +0000617 vg_argc0 = to - vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000618
619 /* copy rest of original command line, then NULL */
620 while (*from) *to++ = *from++;
621 *to = NULL;
622 }
623
nethercotef6a1d502004-08-09 12:21:57 +0000624 *vg_argc_inout = vg_argc0;
625 *vg_argv_inout = vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000626}
627
nethercotef6a1d502004-08-09 12:21:57 +0000628#define VG_CLO_SEP '\01'
629
nethercote71980f02004-01-24 18:18:54 +0000630static void get_command_line( int argc, char** argv,
631 Int* vg_argc_out, Char*** vg_argv_out,
632 char*** cl_argv_out )
633{
nethercotef6a1d502004-08-09 12:21:57 +0000634 int vg_argc0;
635 char** vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000636 char** cl_argv;
637 char* env_clo = getenv(VALGRINDCLO);
638
639 if (env_clo != NULL && *env_clo != '\0') {
640 char *cp;
641 char **cpp;
642
nethercotef6a1d502004-08-09 12:21:57 +0000643 /* OK, VALGRINDCLO is set, which means we must be a child of another
644 Valgrind process using --trace-children, so we're getting all our
645 arguments from VALGRINDCLO, and the entire command line belongs to
646 the client (including argv[0]) */
647 vg_argc0 = 1; /* argv[0] */
nethercote71980f02004-01-24 18:18:54 +0000648 for (cp = env_clo; *cp; cp++)
nethercotef6a1d502004-08-09 12:21:57 +0000649 if (*cp == VG_CLO_SEP)
650 vg_argc0++;
nethercote71980f02004-01-24 18:18:54 +0000651
nethercotef6a1d502004-08-09 12:21:57 +0000652 vg_argv0 = malloc(sizeof(char **) * (vg_argc0 + 1));
653 vg_assert(vg_argv0);
nethercote71980f02004-01-24 18:18:54 +0000654
nethercotef6a1d502004-08-09 12:21:57 +0000655 cpp = vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000656
657 *cpp++ = "valgrind"; /* nominal argv[0] */
658 *cpp++ = env_clo;
659
nethercotef6a1d502004-08-09 12:21:57 +0000660 // Replace the VG_CLO_SEP args separator with '\0'
nethercote71980f02004-01-24 18:18:54 +0000661 for (cp = env_clo; *cp; cp++) {
nethercotef6a1d502004-08-09 12:21:57 +0000662 if (*cp == VG_CLO_SEP) {
nethercote71980f02004-01-24 18:18:54 +0000663 *cp++ = '\0'; /* chop it up in place */
664 *cpp++ = cp;
665 }
666 }
667 *cpp = NULL;
668 cl_argv = argv;
669
670 } else {
671 /* Count the arguments on the command line. */
nethercotef6a1d502004-08-09 12:21:57 +0000672 vg_argv0 = argv;
nethercote71980f02004-01-24 18:18:54 +0000673
nethercotef6a1d502004-08-09 12:21:57 +0000674 for (vg_argc0 = 1; vg_argc0 < argc; vg_argc0++) {
675 if (argv[vg_argc0][0] != '-') /* exe name */
nethercote71980f02004-01-24 18:18:54 +0000676 break;
nethercotef6a1d502004-08-09 12:21:57 +0000677 if (VG_STREQ(argv[vg_argc0], "--")) { /* dummy arg */
678 vg_argc0++;
nethercote71980f02004-01-24 18:18:54 +0000679 break;
680 }
681 }
nethercotef6a1d502004-08-09 12:21:57 +0000682 cl_argv = &argv[vg_argc0];
nethercote71980f02004-01-24 18:18:54 +0000683
684 /* Get extra args from VALGRIND_OPTS and .valgrindrc files.
nethercotef6a1d502004-08-09 12:21:57 +0000685 Note we don't do this if getting args from VALGRINDCLO, as
686 those extra args will already be present in VALGRINDCLO. */
687 augment_command_line(&vg_argc0, &vg_argv0);
nethercote71980f02004-01-24 18:18:54 +0000688 }
689
690 if (0) {
691 Int i;
nethercotef6a1d502004-08-09 12:21:57 +0000692 for (i = 0; i < vg_argc0; i++)
693 printf("vg_argv0[%d]=\"%s\"\n", i, vg_argv0[i]);
nethercote71980f02004-01-24 18:18:54 +0000694 }
695
nethercotef6a1d502004-08-09 12:21:57 +0000696 *vg_argc_out = vg_argc0;
697 *vg_argv_out = (Char**)vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000698 *cl_argv_out = cl_argv;
699}
700
701
702/*====================================================================*/
703/*=== Environment and stack setup ===*/
704/*====================================================================*/
705
706/* Scan a colon-separated list, and call a function on each element.
707 The string must be mutable, because we insert a temporary '\0', but
thughes4ad52d02004-06-27 17:37:21 +0000708 the string will end up unmodified. (*func) should return True if it
nethercote71980f02004-01-24 18:18:54 +0000709 doesn't need to see any more.
thughes4ad52d02004-06-27 17:37:21 +0000710
711 This routine will return True if (*func) returns True and False if
712 it reaches the end of the list without that happening.
nethercote71980f02004-01-24 18:18:54 +0000713*/
thughes4ad52d02004-06-27 17:37:21 +0000714static Bool scan_colsep(char *colsep, Bool (*func)(const char *))
nethercote71980f02004-01-24 18:18:54 +0000715{
716 char *cp, *entry;
717 int end;
718
719 if (colsep == NULL ||
720 *colsep == '\0')
thughes4ad52d02004-06-27 17:37:21 +0000721 return False;
nethercote71980f02004-01-24 18:18:54 +0000722
723 entry = cp = colsep;
724
725 do {
726 end = (*cp == '\0');
727
728 if (*cp == ':' || *cp == '\0') {
729 char save = *cp;
730
731 *cp = '\0';
thughes21942d92004-07-12 09:35:37 +0000732 if ((*func)(entry)) {
733 *cp = save;
thughes4ad52d02004-06-27 17:37:21 +0000734 return True;
thughes21942d92004-07-12 09:35:37 +0000735 }
nethercote71980f02004-01-24 18:18:54 +0000736 *cp = save;
737 entry = cp+1;
738 }
739 cp++;
740 } while(!end);
thughes4ad52d02004-06-27 17:37:21 +0000741
742 return False;
743}
744
745static Bool contains(const char *p) {
746 if (VG_STREQ(p, VG_(libdir))) {
747 return True;
748 }
749 return False;
nethercote71980f02004-01-24 18:18:54 +0000750}
751
752/* Prepare the client's environment. This is basically a copy of our
753 environment, except:
754 1. LD_LIBRARY_PATH=$VALGRINDLIB:$LD_LIBRARY_PATH
755 2. LD_PRELOAD=$VALGRINDLIB/vg_inject.so:($VALGRINDLIB/vgpreload_TOOL.so:)?$LD_PRELOAD
756
757 If any of these is missing, then it is added.
758
759 Yummy. String hacking in C.
760
761 If this needs to handle any more variables it should be hacked
762 into something table driven.
763 */
764static char **fix_environment(char **origenv, const char *preload)
765{
766 static const char inject_so[] = "vg_inject.so";
767 static const char ld_library_path[] = "LD_LIBRARY_PATH=";
768 static const char ld_preload[] = "LD_PRELOAD=";
769 static const char valgrind_clo[] = VALGRINDCLO "=";
770 static const int ld_library_path_len = sizeof(ld_library_path)-1;
771 static const int ld_preload_len = sizeof(ld_preload)-1;
772 static const int valgrind_clo_len = sizeof(valgrind_clo)-1;
773 int ld_preload_done = 0;
774 int ld_library_path_done = 0;
775 char *inject_path;
776 int inject_path_len;
777 int vgliblen = strlen(VG_(libdir));
778 char **cpp;
779 char **ret;
780 int envc;
781 const int preloadlen = (preload == NULL) ? 0 : strlen(preload);
782
783 /* Find the vg_inject.so; also make room for the tool preload
784 library */
785 inject_path_len = sizeof(inject_so) + vgliblen + preloadlen + 16;
786 inject_path = malloc(inject_path_len);
nethercote7c018f42004-07-17 16:40:50 +0000787 vg_assert(inject_path);
nethercote71980f02004-01-24 18:18:54 +0000788
789 if (preload)
790 snprintf(inject_path, inject_path_len, "%s/%s:%s",
791 VG_(libdir), inject_so, preload);
792 else
793 snprintf(inject_path, inject_path_len, "%s/%s",
794 VG_(libdir), inject_so);
795
796 /* Count the original size of the env */
797 envc = 0; /* trailing NULL */
798 for (cpp = origenv; cpp && *cpp; cpp++)
799 envc++;
800
801 /* Allocate a new space */
802 ret = malloc(sizeof(char *) * (envc+3+1)); /* 3 new entries + NULL */
nethercote7c018f42004-07-17 16:40:50 +0000803 vg_assert(ret);
nethercote71980f02004-01-24 18:18:54 +0000804
805 /* copy it over */
806 for (cpp = ret; *origenv; )
807 *cpp++ = *origenv++;
808 *cpp = NULL;
809
810 vg_assert(envc == (cpp - ret));
811
812 /* Walk over the new environment, mashing as we go */
813 for (cpp = ret; cpp && *cpp; cpp++) {
814 if (memcmp(*cpp, ld_library_path, ld_library_path_len) == 0) {
nethercote71980f02004-01-24 18:18:54 +0000815 /* If the LD_LIBRARY_PATH already contains libdir, then don't
816 bother adding it again, even if it isn't the first (it
817 seems that the Java runtime will keep reexecing itself
818 unless its paths are at the front of LD_LIBRARY_PATH) */
thughes4ad52d02004-06-27 17:37:21 +0000819 if (!scan_colsep(*cpp + ld_library_path_len, contains)) {
nethercote71980f02004-01-24 18:18:54 +0000820 int len = strlen(*cpp) + vgliblen*2 + 16;
821 char *cp = malloc(len);
nethercote7c018f42004-07-17 16:40:50 +0000822 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000823
824 snprintf(cp, len, "%s%s:%s",
825 ld_library_path, VG_(libdir),
826 (*cpp)+ld_library_path_len);
827
828 *cpp = cp;
829 }
830
831 ld_library_path_done = 1;
832 } else if (memcmp(*cpp, ld_preload, ld_preload_len) == 0) {
833 int len = strlen(*cpp) + inject_path_len;
834 char *cp = malloc(len);
nethercote7c018f42004-07-17 16:40:50 +0000835 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000836
837 snprintf(cp, len, "%s%s:%s",
838 ld_preload, inject_path, (*cpp)+ld_preload_len);
839
840 *cpp = cp;
841
842 ld_preload_done = 1;
843 } else if (memcmp(*cpp, valgrind_clo, valgrind_clo_len) == 0) {
844 *cpp = "";
845 }
846 }
847
848 /* Add the missing bits */
849
850 if (!ld_library_path_done) {
851 int len = ld_library_path_len + vgliblen*2 + 16;
852 char *cp = malloc(len);
nethercote7c018f42004-07-17 16:40:50 +0000853 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000854
855 snprintf(cp, len, "%s%s", ld_library_path, VG_(libdir));
856
857 ret[envc++] = cp;
858 }
859
860 if (!ld_preload_done) {
861 int len = ld_preload_len + inject_path_len;
862 char *cp = malloc(len);
nethercote7c018f42004-07-17 16:40:50 +0000863 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000864
865 snprintf(cp, len, "%s%s",
866 ld_preload, inject_path);
867
868 ret[envc++] = cp;
869 }
870
871 ret[envc] = NULL;
872
873 return ret;
874}
875
876extern char **environ; /* our environment */
877//#include <error.h>
878
879/* Add a string onto the string table, and return its address */
880static char *copy_str(char **tab, const char *str)
881{
882 char *cp = *tab;
883 char *orig = cp;
884
885 while(*str)
886 *cp++ = *str++;
887 *cp++ = '\0';
888
889 if (0)
nethercotef84f6952004-07-15 14:58:33 +0000890 printf("copied %p \"%s\" len %d\n", orig, orig, cp-orig);
nethercote71980f02004-01-24 18:18:54 +0000891
892 *tab = cp;
893
894 return orig;
895}
896
897/*
898 This sets up the client's initial stack, containing the args,
899 environment and aux vector.
900
901 The format of the stack is:
902
903 higher address +-----------------+
904 | Trampoline code |
905 +-----------------+
906 | |
907 : string table :
908 | |
909 +-----------------+
910 | AT_NULL |
911 - -
912 | auxv |
913 +-----------------+
914 | NULL |
915 - -
916 | envp |
917 +-----------------+
918 | NULL |
919 - -
920 | argv |
921 +-----------------+
922 | argc |
923 lower address +-----------------+ <- esp
924 | undefined |
925 : :
926 */
927static Addr setup_client_stack(char **orig_argv, char **orig_envp,
928 const struct exeinfo *info,
929 UInt** client_auxv)
930{
nethercotee567e702004-07-10 17:49:17 +0000931 void* res;
nethercote71980f02004-01-24 18:18:54 +0000932 char **cpp;
933 char *strtab; /* string table */
934 char *stringbase;
935 addr_t *ptr;
936 struct ume_auxv *auxv;
937 const struct ume_auxv *orig_auxv;
938 const struct ume_auxv *cauxv;
939 unsigned stringsize; /* total size of strings in bytes */
940 unsigned auxsize; /* total size of auxv in bytes */
941 int argc; /* total argc */
942 int envc; /* total number of env vars */
943 unsigned stacksize; /* total client stack size */
944 addr_t cl_esp; /* client stack base (initial esp) */
945
946 /* use our own auxv as a prototype */
947 orig_auxv = find_auxv(ume_exec_esp);
948
949 /* ==================== compute sizes ==================== */
950
951 /* first of all, work out how big the client stack will be */
952 stringsize = 0;
953
954 /* paste on the extra args if the loader needs them (ie, the #!
955 interpreter and its argument) */
956 argc = 0;
nethercoted6a56872004-07-26 15:32:47 +0000957 if (info->interp_name != NULL) {
nethercote71980f02004-01-24 18:18:54 +0000958 argc++;
nethercoted6a56872004-07-26 15:32:47 +0000959 stringsize += strlen(info->interp_name) + 1;
nethercote71980f02004-01-24 18:18:54 +0000960 }
nethercoted6a56872004-07-26 15:32:47 +0000961 if (info->interp_args != NULL) {
nethercote71980f02004-01-24 18:18:54 +0000962 argc++;
nethercoted6a56872004-07-26 15:32:47 +0000963 stringsize += strlen(info->interp_args) + 1;
nethercote71980f02004-01-24 18:18:54 +0000964 }
965
966 /* now scan the args we're given... */
967 for (cpp = orig_argv; *cpp; cpp++) {
968 argc++;
969 stringsize += strlen(*cpp) + 1;
970 }
971
972 /* ...and the environment */
973 envc = 0;
974 for (cpp = orig_envp; cpp && *cpp; cpp++) {
975 envc++;
976 stringsize += strlen(*cpp) + 1;
977 }
978
979 /* now, how big is the auxv? */
980 auxsize = sizeof(*auxv); /* there's always at least one entry: AT_NULL */
981 for (cauxv = orig_auxv; cauxv->a_type != AT_NULL; cauxv++) {
982 if (cauxv->a_type == AT_PLATFORM)
983 stringsize += strlen(cauxv->u.a_ptr) + 1;
984 auxsize += sizeof(*cauxv);
985 }
986
987 /* OK, now we know how big the client stack is */
988 stacksize =
989 sizeof(int) + /* argc */
990 sizeof(char **)*argc + /* argv */
991 sizeof(char **) + /* terminal NULL */
992 sizeof(char **)*envc + /* envp */
993 sizeof(char **) + /* terminal NULL */
994 auxsize + /* auxv */
995 ROUNDUP(stringsize, sizeof(int)) +/* strings (aligned) */
996 VKI_BYTES_PER_PAGE; /* page for trampoline code */
997
nethercotef84f6952004-07-15 14:58:33 +0000998 // decide where stack goes!
999 VG_(clstk_end) = VG_(client_end);
1000
1001 VG_(client_trampoline_code) = VG_(clstk_end) - VKI_BYTES_PER_PAGE;
1002
nethercote71980f02004-01-24 18:18:54 +00001003 /* cl_esp is the client's stack pointer */
nethercotef84f6952004-07-15 14:58:33 +00001004 cl_esp = VG_(clstk_end) - stacksize;
nethercote71980f02004-01-24 18:18:54 +00001005 cl_esp = ROUNDDN(cl_esp, 16); /* make stack 16 byte aligned */
1006
nethercote71980f02004-01-24 18:18:54 +00001007 /* base of the string table (aligned) */
1008 stringbase = strtab = (char *)(VG_(client_trampoline_code) - ROUNDUP(stringsize, sizeof(int)));
1009
1010 VG_(clstk_base) = PGROUNDDN(cl_esp);
nethercote71980f02004-01-24 18:18:54 +00001011
nethercote5ee67ca2004-06-22 14:00:09 +00001012 if (0)
1013 printf("stringsize=%d auxsize=%d stacksize=%d\n"
1014 "clstk_base %x\n"
1015 "clstk_end %x\n",
1016 stringsize, auxsize, stacksize, VG_(clstk_base), VG_(clstk_end));
1017
1018
nethercote71980f02004-01-24 18:18:54 +00001019 /* ==================== allocate space ==================== */
1020
1021 /* allocate a stack - mmap enough space for the stack */
nethercotef84f6952004-07-15 14:58:33 +00001022 res = mmap((void *)PGROUNDDN(cl_esp), VG_(clstk_end) - PGROUNDDN(cl_esp),
nethercotee567e702004-07-10 17:49:17 +00001023 PROT_READ | PROT_WRITE | PROT_EXEC,
1024 MAP_PRIVATE | MAP_ANON | MAP_FIXED, -1, 0);
1025 vg_assert((void*)-1 != res);
nethercote71980f02004-01-24 18:18:54 +00001026
1027 /* ==================== copy client stack ==================== */
1028
1029 ptr = (addr_t *)cl_esp;
1030
1031 /* --- argc --- */
1032 *ptr++ = argc; /* client argc */
1033
1034 /* --- argv --- */
nethercoted6a56872004-07-26 15:32:47 +00001035 if (info->interp_name) {
1036 *ptr++ = (addr_t)copy_str(&strtab, info->interp_name);
1037 free(info->interp_name);
nethercote71980f02004-01-24 18:18:54 +00001038 }
nethercoted6a56872004-07-26 15:32:47 +00001039 if (info->interp_args) {
1040 *ptr++ = (addr_t)copy_str(&strtab, info->interp_args);
1041 free(info->interp_args);
nethercote71980f02004-01-24 18:18:54 +00001042 }
1043 for (cpp = orig_argv; *cpp; ptr++, cpp++) {
1044 *ptr = (addr_t)copy_str(&strtab, *cpp);
1045 }
1046 *ptr++ = 0;
1047
1048 /* --- envp --- */
1049 VG_(client_envp) = (Char **)ptr;
1050 for (cpp = orig_envp; cpp && *cpp; ptr++, cpp++)
1051 *ptr = (addr_t)copy_str(&strtab, *cpp);
1052 *ptr++ = 0;
1053
1054 /* --- auxv --- */
1055 auxv = (struct ume_auxv *)ptr;
1056 *client_auxv = (UInt *)auxv;
1057
1058 for (; orig_auxv->a_type != AT_NULL; auxv++, orig_auxv++) {
1059 /* copy the entry... */
1060 *auxv = *orig_auxv;
1061
1062 /* ...and fix up the copy */
1063 switch(auxv->a_type) {
1064 case AT_PHDR:
1065 if (info->phdr == 0)
1066 auxv->a_type = AT_IGNORE;
1067 else
1068 auxv->u.a_val = info->phdr;
1069 break;
1070
1071 case AT_PHNUM:
1072 if (info->phdr == 0)
1073 auxv->a_type = AT_IGNORE;
1074 else
1075 auxv->u.a_val = info->phnum;
1076 break;
1077
1078 case AT_BASE:
1079 if (info->interp_base == 0)
1080 auxv->a_type = AT_IGNORE;
1081 else
1082 auxv->u.a_val = info->interp_base;
1083 break;
1084
1085 case AT_PLATFORM: /* points to a platform description string */
1086 auxv->u.a_ptr = copy_str(&strtab, orig_auxv->u.a_ptr);
1087 break;
1088
1089 case AT_ENTRY:
1090 auxv->u.a_val = info->entry;
1091 break;
1092
1093 case AT_IGNORE:
1094 case AT_EXECFD:
1095 case AT_PHENT:
1096 case AT_PAGESZ:
1097 case AT_FLAGS:
1098 case AT_NOTELF:
1099 case AT_UID:
1100 case AT_EUID:
1101 case AT_GID:
1102 case AT_EGID:
1103 case AT_CLKTCK:
1104 case AT_HWCAP:
1105 case AT_FPUCW:
1106 case AT_DCACHEBSIZE:
1107 case AT_ICACHEBSIZE:
1108 case AT_UCACHEBSIZE:
1109 /* All these are pointerless, so we don't need to do anything
1110 about them. */
1111 break;
1112
1113 case AT_SECURE:
1114 /* If this is 1, then it means that this program is running
1115 suid, and therefore the dynamic linker should be careful
1116 about LD_PRELOAD, etc. However, since stage1 (the thing
1117 the kernel actually execve's) should never be SUID, and we
1118 need LD_PRELOAD/LD_LIBRARY_PATH to work for the client, we
1119 set AT_SECURE to 0. */
1120 auxv->u.a_val = 0;
1121 break;
1122
1123 case AT_SYSINFO:
1124 /* Leave this unmolested for now, but we'll update it later
1125 when we set up the client trampoline code page */
1126 break;
1127
1128 case AT_SYSINFO_EHDR:
1129 /* Trash this, because we don't reproduce it */
1130 auxv->a_type = AT_IGNORE;
1131 break;
1132
1133 default:
1134 /* stomp out anything we don't know about */
1135 if (0)
1136 printf("stomping auxv entry %d\n", auxv->a_type);
1137 auxv->a_type = AT_IGNORE;
1138 break;
1139
1140 }
1141 }
1142 *auxv = *orig_auxv;
1143 vg_assert(auxv->a_type == AT_NULL);
1144
nethercotef84f6952004-07-15 14:58:33 +00001145 /* --- trampoline page --- */
1146 VG_(memcpy)( (void *)VG_(client_trampoline_code),
1147 &VG_(trampoline_code_start), VG_(trampoline_code_length) );
1148
nethercote71980f02004-01-24 18:18:54 +00001149 vg_assert((strtab-stringbase) == stringsize);
1150
nethercote5ee67ca2004-06-22 14:00:09 +00001151 /* We know the initial ESP is pointing at argc/argv */
1152 VG_(client_argc) = *(Int*)cl_esp;
1153 VG_(client_argv) = (Char**)(cl_esp + sizeof(Int));
1154
nethercote71980f02004-01-24 18:18:54 +00001155 return cl_esp;
1156}
1157
1158/*====================================================================*/
1159/*=== Find executable ===*/
1160/*====================================================================*/
1161
thughes4ad52d02004-06-27 17:37:21 +00001162static const char* executable_name;
1163
1164static Bool match_executable(const char *entry) {
1165 char buf[strlen(entry) + strlen(executable_name) + 2];
1166
1167 /* empty PATH element means . */
1168 if (*entry == '\0')
1169 entry = ".";
1170
1171 snprintf(buf, sizeof(buf), "%s/%s", entry, executable_name);
1172
1173 if (access(buf, R_OK|X_OK) == 0) {
1174 executable_name = strdup(buf);
1175 vg_assert(NULL != executable_name);
1176 return True;
1177 }
1178 return False;
1179}
1180
nethercote71980f02004-01-24 18:18:54 +00001181static const char* find_executable(const char* exec)
1182{
1183 vg_assert(NULL != exec);
thughes4ad52d02004-06-27 17:37:21 +00001184 executable_name = exec;
1185 if (strchr(executable_name, '/') == NULL) {
nethercote71980f02004-01-24 18:18:54 +00001186 /* no '/' - we need to search the path */
1187 char *path = getenv("PATH");
thughes4ad52d02004-06-27 17:37:21 +00001188 scan_colsep(path, match_executable);
nethercote71980f02004-01-24 18:18:54 +00001189 }
thughes4ad52d02004-06-27 17:37:21 +00001190 return executable_name;
nethercote71980f02004-01-24 18:18:54 +00001191}
1192
1193
1194/*====================================================================*/
1195/*=== Loading tools ===*/
1196/*====================================================================*/
1197
1198static void list_tools(void)
1199{
1200 DIR *dir = opendir(VG_(libdir));
1201 struct dirent *de;
1202 int first = 1;
1203
1204 if (dir == NULL) {
1205 fprintf(stderr, "Can't open %s: %s (installation problem?)\n",
nethercotef4928da2004-06-15 10:54:40 +00001206 VG_(libdir), strerror(errno));
nethercote71980f02004-01-24 18:18:54 +00001207 return;
1208 }
1209
nethercotef4928da2004-06-15 10:54:40 +00001210 while ((de = readdir(dir)) != NULL) {
nethercote71980f02004-01-24 18:18:54 +00001211 int len = strlen(de->d_name);
1212
1213 /* look for vgskin_TOOL.so names */
1214 if (len > (7+1+3) && /* "vgskin_" + at least 1-char toolname + ".so" */
nethercotef4928da2004-06-15 10:54:40 +00001215 strncmp(de->d_name, "vgskin_", 7) == 0 &&
1216 VG_STREQ(de->d_name + len - 3, ".so")) {
1217 if (first) {
1218 fprintf(stderr, "Available tools:\n");
1219 first = 0;
1220 }
1221 de->d_name[len-3] = '\0';
1222 fprintf(stderr, "\t%s\n", de->d_name+7);
nethercote71980f02004-01-24 18:18:54 +00001223 }
1224 }
1225
1226 closedir(dir);
1227
1228 if (first)
nethercotef4928da2004-06-15 10:54:40 +00001229 fprintf(stderr, "No tools available in \"%s\" (installation problem?)\n",
1230 VG_(libdir));
nethercote71980f02004-01-24 18:18:54 +00001231}
1232
1233
1234/* Find and load a tool, and check it looks ok. Also looks to see if there's
1235 * a matching vgpreload_*.so file, and returns its name in *preloadpath. */
1236static void load_tool( const char *toolname, void** handle_out,
1237 ToolInfo** toolinfo_out, char **preloadpath_out )
1238{
1239 Bool ok;
1240 int len = strlen(VG_(libdir)) + strlen(toolname)*2 + 16;
1241 char buf[len];
1242 void* handle;
1243 ToolInfo* toolinfo;
1244 char* preloadpath = NULL;
1245 Int* vg_malloc_redzonep;
1246
1247 // XXX: allowing full paths for --tool option -- does it make sense?
1248 // Doesn't allow for vgpreload_<tool>.so.
1249
1250 if (strchr(toolname, '/') != 0) {
1251 /* toolname contains '/', and so must be a pathname */
1252 handle = dlopen(toolname, RTLD_NOW);
1253 } else {
1254 /* just try in the libdir */
1255 snprintf(buf, len, "%s/vgskin_%s.so", VG_(libdir), toolname);
1256 handle = dlopen(buf, RTLD_NOW);
1257
1258 if (handle != NULL) {
1259 snprintf(buf, len, "%s/vgpreload_%s.so", VG_(libdir), toolname);
1260 if (access(buf, R_OK) == 0) {
1261 preloadpath = strdup(buf);
1262 vg_assert(NULL != preloadpath);
1263 }
1264 }
1265 }
1266
1267 ok = (NULL != handle);
1268 if (!ok) {
1269 fprintf(stderr, "Can't open tool \"%s\": %s\n", toolname, dlerror());
1270 goto bad_load;
1271 }
1272
1273 toolinfo = dlsym(handle, "vgSkin_tool_info");
1274 ok = (NULL != toolinfo);
1275 if (!ok) {
1276 fprintf(stderr, "Tool \"%s\" doesn't define SK_(tool_info) - "
1277 "add VG_DETERMINE_INTERFACE_VERSION?\n", toolname);
1278 goto bad_load;
1279 }
1280
1281 ok = (toolinfo->sizeof_ToolInfo == sizeof(*toolinfo) &&
1282 toolinfo->interface_major_version == VG_CORE_INTERFACE_MAJOR_VERSION &&
1283 toolinfo->sk_pre_clo_init != NULL);
1284 if (!ok) {
1285 fprintf(stderr, "Error:\n"
1286 " Tool and core interface versions do not match.\n"
1287 " Interface version used by core is: %d.%d (size %d)\n"
1288 " Interface version used by tool is: %d.%d (size %d)\n"
1289 " The major version numbers must match.\n",
1290 VG_CORE_INTERFACE_MAJOR_VERSION,
1291 VG_CORE_INTERFACE_MINOR_VERSION,
1292 sizeof(*toolinfo),
1293 toolinfo->interface_major_version,
1294 toolinfo->interface_minor_version,
1295 toolinfo->sizeof_ToolInfo);
1296 fprintf(stderr, " You need to at least recompile, and possibly update,\n");
1297 if (VG_CORE_INTERFACE_MAJOR_VERSION > toolinfo->interface_major_version)
nethercote996901a2004-08-03 13:29:09 +00001298 fprintf(stderr, " your tool to work with this version of Valgrind.\n");
nethercote71980f02004-01-24 18:18:54 +00001299 else
nethercote996901a2004-08-03 13:29:09 +00001300 fprintf(stderr, " your version of Valgrind to work with this tool.\n");
nethercote71980f02004-01-24 18:18:54 +00001301 goto bad_load;
1302 }
1303
1304 // Set redzone size for V's allocator
1305 vg_malloc_redzonep = dlsym(handle, STR(VG_(vg_malloc_redzone_szB)));
1306 if ( NULL != vg_malloc_redzonep ) {
1307 VG_(vg_malloc_redzone_szB) = *vg_malloc_redzonep;
1308 }
1309
1310 vg_assert(NULL != handle && NULL != toolinfo);
1311 *handle_out = handle;
1312 *toolinfo_out = toolinfo;
1313 *preloadpath_out = preloadpath;
1314 return;
1315
1316
1317 bad_load:
1318 if (handle != NULL)
1319 dlclose(handle);
1320
nethercotef4928da2004-06-15 10:54:40 +00001321 fprintf(stderr, "valgrind: couldn't load tool\n");
nethercote71980f02004-01-24 18:18:54 +00001322 list_tools();
1323 exit(127);
1324}
1325
nethercotef4928da2004-06-15 10:54:40 +00001326
1327/*====================================================================*/
1328/*=== Command line errors ===*/
1329/*====================================================================*/
1330
1331static void abort_msg ( void )
1332{
nethercotef8548672004-06-21 12:42:35 +00001333 VG_(clo_log_to) = VgLogTo_Fd;
1334 VG_(clo_log_fd) = 2; /* stderr */
nethercotef4928da2004-06-15 10:54:40 +00001335}
1336
1337void VG_(bad_option) ( Char* opt )
1338{
1339 abort_msg();
1340 VG_(printf)("valgrind: Bad option `%s'; aborting.\n", opt);
1341 VG_(printf)("valgrind: Use --help for more information.\n");
1342 VG_(exit)(1);
1343}
1344
1345static void missing_tool_option ( void )
1346{
1347 abort_msg();
1348 VG_(printf)("valgrind: Missing --tool option\n");
1349 list_tools();
1350 VG_(printf)("valgrind: Use --help for more information.\n");
1351 VG_(exit)(1);
1352}
1353
1354static void missing_prog ( void )
1355{
1356 abort_msg();
1357 VG_(printf)("valgrind: no program specified\n");
1358 VG_(printf)("valgrind: Use --help for more information.\n");
1359 VG_(exit)(1);
1360}
1361
1362static void config_error ( Char* msg )
1363{
1364 abort_msg();
1365 VG_(printf)("valgrind: Startup or configuration error:\n %s\n", msg);
1366 VG_(printf)("valgrind: Unable to start up properly. Giving up.\n");
1367 VG_(exit)(1);
1368}
1369
1370
nethercote71980f02004-01-24 18:18:54 +00001371/*====================================================================*/
1372/*=== Loading the client ===*/
1373/*====================================================================*/
1374
nethercotef4928da2004-06-15 10:54:40 +00001375static void load_client(char* cl_argv[], const char* exec, Int need_help,
nethercote71980f02004-01-24 18:18:54 +00001376 /*out*/struct exeinfo* info, /*out*/Addr* client_eip)
1377{
1378 // If they didn't specify an executable with --exec, and didn't specify
1379 // --help, then use client argv[0] (searching $PATH if necessary).
nethercotef4928da2004-06-15 10:54:40 +00001380 if (NULL == exec && !need_help) {
nethercote71980f02004-01-24 18:18:54 +00001381 if (cl_argv[0] == NULL ||
1382 ( NULL == (exec = find_executable(cl_argv[0])) ) )
1383 {
nethercotef4928da2004-06-15 10:54:40 +00001384 missing_prog();
nethercote71980f02004-01-24 18:18:54 +00001385 }
1386 }
1387
1388 info->map_base = VG_(client_mapbase);
nethercote71980f02004-01-24 18:18:54 +00001389 info->exe_base = VG_(client_base);
1390 info->exe_end = VG_(client_end);
1391 info->argv = cl_argv;
1392
nethercotef4928da2004-06-15 10:54:40 +00001393 if (need_help) {
nethercote71980f02004-01-24 18:18:54 +00001394 VG_(clexecfd) = -1;
nethercoteea147e72004-07-26 15:43:57 +00001395 // Set the minimal number of entries in 'info' to continue.
nethercoted6a56872004-07-26 15:32:47 +00001396 info->interp_name = NULL;
1397 info->interp_args = NULL;
nethercote71980f02004-01-24 18:18:54 +00001398 } else {
1399 Int ret;
1400 VG_(clexecfd) = VG_(open)(exec, O_RDONLY, VKI_S_IRUSR);
1401 ret = do_exec(exec, info);
1402 if (ret != 0) {
nethercoteea147e72004-07-26 15:43:57 +00001403 fprintf(stderr, "valgrind: do_exec(%s) failed: %s\n",
1404 exec, strerror(ret));
nethercote71980f02004-01-24 18:18:54 +00001405 exit(127);
1406 }
1407 }
1408
1409 /* Copy necessary bits of 'info' that were filled in */
1410 *client_eip = info->init_eip;
1411 VG_(brk_base) = VG_(brk_limit) = info->brkbase;
1412}
1413
1414
1415/*====================================================================*/
nethercotef6a1d502004-08-09 12:21:57 +00001416/*=== Command-line: variables, processing, etc ===*/
nethercote71980f02004-01-24 18:18:54 +00001417/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +00001418
njn25e49d8e72002-09-23 09:36:25 +00001419/* Define, and set defaults. */
1420Bool VG_(clo_error_limit) = True;
nethercote04d0fbc2004-01-26 16:48:06 +00001421Bool VG_(clo_db_attach) = False;
1422Char* VG_(clo_db_command) = VG_CLO_DEFAULT_DBCOMMAND;
njn43c799e2003-04-08 00:08:52 +00001423Bool VG_(clo_gen_suppressions) = False;
nethercote27fec902004-06-16 21:26:32 +00001424Int VG_(clo_sanity_level) = 1;
njn25e49d8e72002-09-23 09:36:25 +00001425Int VG_(clo_verbosity) = 1;
1426Bool VG_(clo_demangle) = True;
njn25e49d8e72002-09-23 09:36:25 +00001427Bool VG_(clo_trace_children) = False;
sewardj4cf05692002-10-27 20:28:29 +00001428
nethercotee1730692003-11-20 10:38:07 +00001429/* See big comment in vg_include.h for meaning of these three.
1430 fd is initially stdout, for --help, but gets moved to stderr by default
1431 immediately afterwards. */
sewardj4cf05692002-10-27 20:28:29 +00001432VgLogTo VG_(clo_log_to) = VgLogTo_Fd;
nethercotef8548672004-06-21 12:42:35 +00001433Int VG_(clo_log_fd) = 1;
1434Char* VG_(clo_log_name) = NULL;
sewardj4cf05692002-10-27 20:28:29 +00001435
thughes6233a382004-08-21 11:10:44 +00001436Bool VG_(clo_time_stamp) = False;
1437
sewardj6024b212003-07-13 10:54:33 +00001438Int VG_(clo_input_fd) = 0; /* stdin */
njn25e49d8e72002-09-23 09:36:25 +00001439Int VG_(clo_n_suppressions) = 0;
sewardjde4a1d02002-03-22 01:27:54 +00001440Char* VG_(clo_suppressions)[VG_CLO_MAX_SFILES];
njn25e49d8e72002-09-23 09:36:25 +00001441Bool VG_(clo_profile) = False;
1442Bool VG_(clo_single_step) = False;
1443Bool VG_(clo_optimise) = True;
1444UChar VG_(clo_trace_codegen) = 0; // 00000000b
1445Bool VG_(clo_trace_syscalls) = False;
1446Bool VG_(clo_trace_signals) = False;
1447Bool VG_(clo_trace_symtab) = False;
njn25e49d8e72002-09-23 09:36:25 +00001448Bool VG_(clo_trace_sched) = False;
1449Int VG_(clo_trace_pthread_level) = 0;
njn25e49d8e72002-09-23 09:36:25 +00001450Int VG_(clo_dump_error) = 0;
1451Int VG_(clo_backtrace_size) = 4;
1452Char* VG_(clo_weird_hacks) = NULL;
sewardj858964b2002-10-05 14:15:43 +00001453Bool VG_(clo_run_libc_freeres) = True;
rjwalshf5f536f2003-11-17 17:45:00 +00001454Bool VG_(clo_track_fds) = False;
sewardj22854b92002-11-30 14:00:47 +00001455Bool VG_(clo_chain_bb) = True;
nethercote77eba602003-11-13 17:35:04 +00001456Bool VG_(clo_show_below_main) = False;
fitzhardinge98abfc72003-12-16 02:05:15 +00001457Bool VG_(clo_pointercheck) = True;
fitzhardinge462f4f92003-12-18 02:10:54 +00001458Bool VG_(clo_branchpred) = False;
sewardj2370f3b2002-11-30 15:01:01 +00001459
jsgf855d93d2003-10-13 22:26:55 +00001460static Bool VG_(clo_wait_for_gdb) = False;
1461
1462/* If we're doing signal routing, poll for signals every 50mS by
1463 default. */
1464Int VG_(clo_signal_polltime) = 50;
1465
1466/* These flags reduce thread wakeup latency on syscall completion and
1467 signal delivery, respectively. The downside is possible unfairness. */
1468Bool VG_(clo_lowlat_syscalls) = False; /* low-latency syscalls */
1469Bool VG_(clo_lowlat_signals) = False; /* low-latency signals */
1470
sewardjde4a1d02002-03-22 01:27:54 +00001471
nethercote6c999f22004-01-31 22:55:15 +00001472void usage ( Bool debug_help )
njn7cf0bd32002-06-08 13:36:03 +00001473{
njn25e49d8e72002-09-23 09:36:25 +00001474 Char* usage1 =
nethercote71980f02004-01-24 18:18:54 +00001475"usage: valgrind --tool=<toolname> [options] prog-and-args\n"
njn25e49d8e72002-09-23 09:36:25 +00001476"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001477" common user options for all Valgrind tools, with defaults in [ ]:\n"
nethercote0d588502004-06-21 13:27:11 +00001478" --tool=<name> use the Valgrind tool named <name>\n"
nethercotea76368b2004-06-16 11:56:29 +00001479" -h --help show this message\n"
nethercote6c999f22004-01-31 22:55:15 +00001480" --help-debug show this message, plus debugging options\n"
njn25e49d8e72002-09-23 09:36:25 +00001481" --version show version\n"
njn25e49d8e72002-09-23 09:36:25 +00001482" -q --quiet run silently; only print error msgs\n"
1483" -v --verbose be more verbose, incl counts of errors\n"
nethercote77eba602003-11-13 17:35:04 +00001484" --trace-children=no|yes Valgrind-ise child processes? [no]\n"
nethercote0d588502004-06-21 13:27:11 +00001485" --track-fds=no|yes track open file descriptors? [no]\n"
thughes6233a382004-08-21 11:10:44 +00001486" --time-stamp=no|yes add timestamps to log messages? [no]\n"
nethercote2b0793f2003-12-02 10:41:18 +00001487"\n"
1488" uncommon user options for all Valgrind tools:\n"
nethercote0d588502004-06-21 13:27:11 +00001489" --run-libc-freeres=no|yes free up glibc memory at exit? [yes]\n"
1490" --weird-hacks=hack1,hack2,... recognised hacks: lax-ioctls [none]\n"
1491" --signal-polltime=<time> signal poll period (mS) for older kernels [50]\n"
1492" --lowlat-signals=no|yes improve thread signal wake-up latency [no]\n"
1493" --lowlat-syscalls=no|yes improve thread syscall wake-up latency [no]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001494" --pointercheck=no|yes enforce client address space limits [yes]\n"
njn25e49d8e72002-09-23 09:36:25 +00001495"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001496" user options for Valgrind tools that report errors:\n"
nethercotef8548672004-06-21 12:42:35 +00001497" --log-fd=<number> log messages to file descriptor [2=stderr]\n"
1498" --log-file=<file> log messages to <file>.pid<pid>\n"
1499" --log-socket=ipaddr:port log messages to socket ipaddr:port\n"
nethercote2b0793f2003-12-02 10:41:18 +00001500" --demangle=no|yes automatically demangle C++ names? [yes]\n"
1501" --num-callers=<number> show <num> callers in stack traces [4]\n"
1502" --error-limit=no|yes stop showing new errors if too many? [yes]\n"
1503" --show-below-main=no|yes continue stack traces below main() [no]\n"
1504" --suppressions=<filename> suppress errors described in <filename>\n"
1505" --gen-suppressions=no|yes print suppressions for errors detected [no]\n"
nethercote04d0fbc2004-01-26 16:48:06 +00001506" --db-attach=no|yes start debugger when errors detected? [no]\n"
1507" --db-command=<command> command to start debugger [gdb -nw %%f %%p]\n"
1508" --input-fd=<number> file descriptor for input [0=stdin]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001509"\n";
njn7cf0bd32002-06-08 13:36:03 +00001510
njn25e49d8e72002-09-23 09:36:25 +00001511 Char* usage2 =
1512"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001513" debugging options for all Valgrind tools:\n"
njn25e49d8e72002-09-23 09:36:25 +00001514" --sanity-level=<number> level of sanity checking to do [1]\n"
1515" --single-step=no|yes translate each instr separately? [no]\n"
1516" --optimise=no|yes improve intermediate code? [yes]\n"
nethercote137bc552003-11-14 17:47:54 +00001517" --profile=no|yes profile? (tool must be built for it) [no]\n"
sewardj22854b92002-11-30 14:00:47 +00001518" --chain-bb=no|yes do basic-block chaining? [yes]\n"
fitzhardinge462f4f92003-12-18 02:10:54 +00001519" --branchpred=yes|no generate branch prediction hints [no]\n"
njn25e49d8e72002-09-23 09:36:25 +00001520" --trace-codegen=<XXXXX> show generated code? (X = 0|1) [00000]\n"
1521" --trace-syscalls=no|yes show all system calls? [no]\n"
1522" --trace-signals=no|yes show signal handling details? [no]\n"
1523" --trace-symtab=no|yes show symbol table details? [no]\n"
njn25e49d8e72002-09-23 09:36:25 +00001524" --trace-sched=no|yes show thread scheduler details? [no]\n"
njn3e884182003-04-15 13:03:23 +00001525" --trace-pthread=none|some|all show pthread event details? [none]\n"
jsgf855d93d2003-10-13 22:26:55 +00001526" --wait-for-gdb=yes|no pause on startup to wait for gdb attach\n"
njn25e49d8e72002-09-23 09:36:25 +00001527"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001528" debugging options for Valgrind tools that report errors\n"
1529" --dump-error=<number> show translation for basic block associated\n"
1530" with <number>'th error context [0=show none]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001531"\n";
njn3e884182003-04-15 13:03:23 +00001532
1533 Char* usage3 =
1534"\n"
nethercote71980f02004-01-24 18:18:54 +00001535" Extra options read from ~/.valgrindrc, $VALGRIND_OPTS, ./.valgrindrc\n"
njn25e49d8e72002-09-23 09:36:25 +00001536"\n"
nethercote08fa9a72004-07-16 17:44:00 +00001537" Valgrind is Copyright (C) 2000-2004 Julian Seward et al.\n"
njn25e49d8e72002-09-23 09:36:25 +00001538" and licensed under the GNU General Public License, version 2.\n"
1539" Bug reports, feedback, admiration, abuse, etc, to: %s.\n"
njnd04b7c62002-10-03 14:05:52 +00001540"\n"
nethercote137bc552003-11-14 17:47:54 +00001541" Tools are copyright and licensed by their authors. See each\n"
1542" tool's start-up message for more information.\n"
njn25e49d8e72002-09-23 09:36:25 +00001543"\n";
njn7cf0bd32002-06-08 13:36:03 +00001544
fitzhardinge98abfc72003-12-16 02:05:15 +00001545 VG_(printf)(usage1);
1546 if (VG_(details).name) {
1547 VG_(printf)(" user options for %s:\n", VG_(details).name);
fitzhardinge98abfc72003-12-16 02:05:15 +00001548 if (VG_(needs).command_line_options)
1549 SK_(print_usage)();
1550 else
1551 VG_(printf)(" (none)\n");
1552 }
nethercote6c999f22004-01-31 22:55:15 +00001553 if (debug_help) {
1554 VG_(printf)(usage2);
fitzhardinge98abfc72003-12-16 02:05:15 +00001555
nethercote6c999f22004-01-31 22:55:15 +00001556 if (VG_(details).name) {
1557 VG_(printf)(" debugging options for %s:\n", VG_(details).name);
1558
1559 if (VG_(needs).command_line_options)
1560 SK_(print_debug_usage)();
1561 else
1562 VG_(printf)(" (none)\n");
1563 }
fitzhardinge98abfc72003-12-16 02:05:15 +00001564 }
nethercote421281e2003-11-20 16:20:55 +00001565 VG_(printf)(usage3, VG_BUGS_TO);
nethercotef4928da2004-06-15 10:54:40 +00001566 VG_(exit)(0);
njn7cf0bd32002-06-08 13:36:03 +00001567}
sewardjde4a1d02002-03-22 01:27:54 +00001568
nethercote71980f02004-01-24 18:18:54 +00001569static void pre_process_cmd_line_options
nethercote6c999f22004-01-31 22:55:15 +00001570 ( Int* need_help, const char** tool, const char** exec )
sewardj1c1b1162003-02-23 01:25:51 +00001571{
nethercote71980f02004-01-24 18:18:54 +00001572 UInt i;
sewardjde4a1d02002-03-22 01:27:54 +00001573
nethercote71980f02004-01-24 18:18:54 +00001574 /* parse the options we have (only the options we care about now) */
nethercotef6a1d502004-08-09 12:21:57 +00001575 for (i = 1; i < vg_argc; i++) {
nethercote71980f02004-01-24 18:18:54 +00001576
nethercotef6a1d502004-08-09 12:21:57 +00001577 if (strcmp(vg_argv[i], "--version") == 0) {
nethercote71980f02004-01-24 18:18:54 +00001578 printf("valgrind-" VERSION "\n");
nethercotef4928da2004-06-15 10:54:40 +00001579 exit(0);
nethercote71980f02004-01-24 18:18:54 +00001580
nethercotef6a1d502004-08-09 12:21:57 +00001581 } else if (VG_CLO_STREQ(vg_argv[i], "--help") ||
1582 VG_CLO_STREQ(vg_argv[i], "-h")) {
nethercote6c999f22004-01-31 22:55:15 +00001583 *need_help = 1;
1584
nethercotef6a1d502004-08-09 12:21:57 +00001585 } else if (VG_CLO_STREQ(vg_argv[i], "--help-debug")) {
nethercote6c999f22004-01-31 22:55:15 +00001586 *need_help = 2;
nethercote71980f02004-01-24 18:18:54 +00001587
nethercotef6a1d502004-08-09 12:21:57 +00001588 } else if (VG_CLO_STREQN(7, vg_argv[i], "--tool=") ||
1589 VG_CLO_STREQN(7, vg_argv[i], "--skin=")) {
1590 *tool = &vg_argv[i][7];
nethercote71980f02004-01-24 18:18:54 +00001591
nethercotef6a1d502004-08-09 12:21:57 +00001592 } else if (VG_CLO_STREQN(7, vg_argv[i], "--exec=")) {
1593 *exec = &vg_argv[i][7];
nethercote71980f02004-01-24 18:18:54 +00001594 }
1595 }
1596
nethercotef4928da2004-06-15 10:54:40 +00001597 /* If no tool specified, can act appropriately without loading tool */
nethercote71980f02004-01-24 18:18:54 +00001598 if (*tool == NULL) {
nethercotef4928da2004-06-15 10:54:40 +00001599 if (0 == *need_help) {
1600 // neither --tool nor --help/--help-debug specified
1601 missing_tool_option();
1602 } else {
1603 // Give help message, without any tool-specific help
1604 usage(/*help-debug?*/2 == *need_help);
1605 }
nethercote71980f02004-01-24 18:18:54 +00001606 }
1607}
1608
nethercote5ee67ca2004-06-22 14:00:09 +00001609static void process_cmd_line_options( UInt* client_auxv, const char* toolname )
nethercote71980f02004-01-24 18:18:54 +00001610{
nethercotef8548672004-06-21 12:42:35 +00001611 Int i, eventually_log_fd;
nethercote71980f02004-01-24 18:18:54 +00001612 Int *auxp;
1613 Int toolname_len = VG_(strlen)(toolname);
sewardjde4a1d02002-03-22 01:27:54 +00001614
nethercotee1730692003-11-20 10:38:07 +00001615 /* log to stderr by default, but usage message goes to stdout */
nethercotef8548672004-06-21 12:42:35 +00001616 eventually_log_fd = 2;
sewardjde4a1d02002-03-22 01:27:54 +00001617
sewardj19d81412002-06-03 01:10:40 +00001618 /* Check for sane path in ./configure --prefix=... */
fitzhardinge98abfc72003-12-16 02:05:15 +00001619 if (VG_LIBDIR[0] != '/')
sewardj19d81412002-06-03 01:10:40 +00001620 config_error("Please use absolute paths in "
1621 "./configure --prefix=... or --libdir=...");
sewardj38170912002-05-10 21:07:22 +00001622
nethercote71980f02004-01-24 18:18:54 +00001623 for (auxp = client_auxv; auxp[0] != VKI_AT_NULL; auxp += 2) {
fitzhardinge98abfc72003-12-16 02:05:15 +00001624 switch(auxp[0]) {
1625 case VKI_AT_SYSINFO:
fitzhardinge92360792003-12-24 10:11:11 +00001626 auxp[1] = (Int)(VG_(client_trampoline_code) + VG_(tramp_syscall_offset));
fitzhardinge98abfc72003-12-16 02:05:15 +00001627 break;
sewardjde4a1d02002-03-22 01:27:54 +00001628 }
fitzhardinge98abfc72003-12-16 02:05:15 +00001629 }
sewardjde4a1d02002-03-22 01:27:54 +00001630
nethercotef6a1d502004-08-09 12:21:57 +00001631 for (i = 1; i < vg_argc; i++) {
nethercote71980f02004-01-24 18:18:54 +00001632
nethercotef6a1d502004-08-09 12:21:57 +00001633 Char* arg = vg_argv[i];
thughes3bfd5a02004-07-18 08:05:44 +00001634 Char* colon = arg;
nethercote71980f02004-01-24 18:18:54 +00001635
thughes3bfd5a02004-07-18 08:05:44 +00001636 /* Look for a colon in the switch name */
1637 while (*colon && *colon != ':' && *colon != '=')
1638 colon++;
nethercote71980f02004-01-24 18:18:54 +00001639
1640 /* Look for matching "--toolname:foo" */
thughes3bfd5a02004-07-18 08:05:44 +00001641 if (*colon == ':') {
nethercote71980f02004-01-24 18:18:54 +00001642 if (VG_CLO_STREQN(2, arg, "--") &&
1643 VG_CLO_STREQN(toolname_len, arg+2, toolname) &&
1644 VG_CLO_STREQN(1, arg+2+toolname_len, ":"))
1645 {
1646 // prefix matches, convert "--toolname:foo" to "--foo"
1647 if (0)
1648 VG_(printf)("tool-specific arg: %s\n", arg);
1649 arg += toolname_len + 1;
1650 arg[0] = '-';
1651 arg[1] = '-';
1652
1653 } else {
1654 // prefix doesn't match, skip to next arg
1655 continue;
1656 }
1657 }
1658
fitzhardinge98abfc72003-12-16 02:05:15 +00001659 /* Ignore these options - they've already been handled */
nethercote71980f02004-01-24 18:18:54 +00001660 if (VG_CLO_STREQN(7, arg, "--tool=") ||
1661 VG_CLO_STREQN(7, arg, "--skin="))
fitzhardinge98abfc72003-12-16 02:05:15 +00001662 continue;
nethercote71980f02004-01-24 18:18:54 +00001663 if (VG_CLO_STREQN(7, arg, "--exec="))
fitzhardinge98abfc72003-12-16 02:05:15 +00001664 continue;
1665
nethercote71980f02004-01-24 18:18:54 +00001666 if ( VG_CLO_STREQ(arg, "--"))
fitzhardinge98abfc72003-12-16 02:05:15 +00001667 continue;
nethercote27fec902004-06-16 21:26:32 +00001668
nethercote71980f02004-01-24 18:18:54 +00001669 else if (VG_CLO_STREQ(arg, "-v") ||
1670 VG_CLO_STREQ(arg, "--verbose"))
sewardjde4a1d02002-03-22 01:27:54 +00001671 VG_(clo_verbosity)++;
nethercote27fec902004-06-16 21:26:32 +00001672
nethercote71980f02004-01-24 18:18:54 +00001673 else if (VG_CLO_STREQ(arg, "-q") ||
1674 VG_CLO_STREQ(arg, "--quiet"))
sewardjde4a1d02002-03-22 01:27:54 +00001675 VG_(clo_verbosity)--;
1676
nethercote27fec902004-06-16 21:26:32 +00001677 else VG_BOOL_CLO("--branchpred", VG_(clo_branchpred))
1678 else VG_BOOL_CLO("--chain-bb", VG_(clo_chain_bb))
1679 else VG_BOOL_CLO("--db-attach", VG_(clo_db_attach))
1680 else VG_BOOL_CLO("--demangle", VG_(clo_demangle))
1681 else VG_BOOL_CLO("--error-limit", VG_(clo_error_limit))
1682 else VG_BOOL_CLO("--gen-suppressions", VG_(clo_gen_suppressions))
1683 else VG_BOOL_CLO("--lowlat-signals", VG_(clo_lowlat_signals))
1684 else VG_BOOL_CLO("--lowlat-syscalls", VG_(clo_lowlat_syscalls))
1685 else VG_BOOL_CLO("--optimise", VG_(clo_optimise))
1686 else VG_BOOL_CLO("--pointercheck", VG_(clo_pointercheck))
1687 else VG_BOOL_CLO("--profile", VG_(clo_profile))
1688 else VG_BOOL_CLO("--run-libc-freeres", VG_(clo_run_libc_freeres))
1689 else VG_BOOL_CLO("--show-below-main", VG_(clo_show_below_main))
1690 else VG_BOOL_CLO("--single-step", VG_(clo_single_step))
thughes6233a382004-08-21 11:10:44 +00001691 else VG_BOOL_CLO("--time-stamp", VG_(clo_time_stamp))
nethercote27fec902004-06-16 21:26:32 +00001692 else VG_BOOL_CLO("--track-fds", VG_(clo_track_fds))
1693 else VG_BOOL_CLO("--trace-children", VG_(clo_trace_children))
1694 else VG_BOOL_CLO("--trace-sched", VG_(clo_trace_sched))
1695 else VG_BOOL_CLO("--trace-signals", VG_(clo_trace_signals))
1696 else VG_BOOL_CLO("--trace-symtab", VG_(clo_trace_symtab))
1697 else VG_BOOL_CLO("--trace-syscalls", VG_(clo_trace_syscalls))
1698 else VG_BOOL_CLO("--wait-for-gdb", VG_(clo_wait_for_gdb))
sewardj72f98ff2002-06-13 17:23:38 +00001699
nethercote27fec902004-06-16 21:26:32 +00001700 else VG_STR_CLO ("--db-command", VG_(clo_db_command))
1701 else VG_STR_CLO ("--weird-hacks", VG_(clo_weird_hacks))
sewardjde4a1d02002-03-22 01:27:54 +00001702
nethercote27fec902004-06-16 21:26:32 +00001703 else VG_NUM_CLO ("--dump-error", VG_(clo_dump_error))
1704 else VG_NUM_CLO ("--input-fd", VG_(clo_input_fd))
1705 else VG_NUM_CLO ("--sanity-level", VG_(clo_sanity_level))
1706 else VG_NUM_CLO ("--signal­polltime", VG_(clo_signal_polltime))
1707 else VG_BNUM_CLO("--num-callers", VG_(clo_backtrace_size), 1,
1708 VG_DEEPEST_BACKTRACE)
sewardjde4a1d02002-03-22 01:27:54 +00001709
nethercotef8548672004-06-21 12:42:35 +00001710 // for backwards compatibility, replaced by --log-fd
nethercote71980f02004-01-24 18:18:54 +00001711 else if (VG_CLO_STREQN(13, arg, "--logfile-fd=")) {
nethercotef8548672004-06-21 12:42:35 +00001712 VG_(clo_log_to) = VgLogTo_Fd;
1713 VG_(clo_log_name) = NULL;
1714 eventually_log_fd = (Int)VG_(atoll)(&arg[13]);
1715 }
1716 else if (VG_CLO_STREQN(9, arg, "--log-fd=")) {
1717 VG_(clo_log_to) = VgLogTo_Fd;
1718 VG_(clo_log_name) = NULL;
1719 eventually_log_fd = (Int)VG_(atoll)(&arg[9]);
sewardj4cf05692002-10-27 20:28:29 +00001720 }
1721
nethercotef8548672004-06-21 12:42:35 +00001722 // for backwards compatibility, replaced by --log-file
nethercote71980f02004-01-24 18:18:54 +00001723 else if (VG_CLO_STREQN(10, arg, "--logfile=")) {
nethercotef8548672004-06-21 12:42:35 +00001724 VG_(clo_log_to) = VgLogTo_File;
1725 VG_(clo_log_name) = &arg[10];
1726 }
1727 else if (VG_CLO_STREQN(11, arg, "--log-file=")) {
1728 VG_(clo_log_to) = VgLogTo_File;
1729 VG_(clo_log_name) = &arg[11];
sewardj4cf05692002-10-27 20:28:29 +00001730 }
sewardjde4a1d02002-03-22 01:27:54 +00001731
nethercotef8548672004-06-21 12:42:35 +00001732 // for backwards compatibility, replaced by --log-socket
nethercote71980f02004-01-24 18:18:54 +00001733 else if (VG_CLO_STREQN(12, arg, "--logsocket=")) {
nethercotef8548672004-06-21 12:42:35 +00001734 VG_(clo_log_to) = VgLogTo_Socket;
1735 VG_(clo_log_name) = &arg[12];
1736 }
1737 else if (VG_CLO_STREQN(13, arg, "--log-socket=")) {
1738 VG_(clo_log_to) = VgLogTo_Socket;
1739 VG_(clo_log_name) = &arg[13];
sewardj73cf3bc2002-11-03 03:20:15 +00001740 }
1741
nethercote71980f02004-01-24 18:18:54 +00001742 else if (VG_CLO_STREQN(15, arg, "--suppressions=")) {
sewardjde4a1d02002-03-22 01:27:54 +00001743 if (VG_(clo_n_suppressions) >= VG_CLO_MAX_SFILES) {
njn25e49d8e72002-09-23 09:36:25 +00001744 VG_(message)(Vg_UserMsg, "Too many suppression files specified.");
sewardjde4a1d02002-03-22 01:27:54 +00001745 VG_(message)(Vg_UserMsg,
1746 "Increase VG_CLO_MAX_SFILES and recompile.");
nethercote71980f02004-01-24 18:18:54 +00001747 VG_(bad_option)(arg);
sewardjde4a1d02002-03-22 01:27:54 +00001748 }
nethercote71980f02004-01-24 18:18:54 +00001749 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = &arg[15];
sewardjde4a1d02002-03-22 01:27:54 +00001750 VG_(clo_n_suppressions)++;
1751 }
sewardjde4a1d02002-03-22 01:27:54 +00001752
njn25e49d8e72002-09-23 09:36:25 +00001753 /* "vwxyz" --> 000zyxwv (binary) */
nethercote71980f02004-01-24 18:18:54 +00001754 else if (VG_CLO_STREQN(16, arg, "--trace-codegen=")) {
njn25e49d8e72002-09-23 09:36:25 +00001755 Int j;
nethercote71980f02004-01-24 18:18:54 +00001756 char* opt = & arg[16];
njn25e49d8e72002-09-23 09:36:25 +00001757
1758 if (5 != VG_(strlen)(opt)) {
1759 VG_(message)(Vg_UserMsg,
1760 "--trace-codegen argument must have 5 digits");
nethercote71980f02004-01-24 18:18:54 +00001761 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001762 }
1763 for (j = 0; j < 5; j++) {
1764 if ('0' == opt[j]) { /* do nothing */ }
1765 else if ('1' == opt[j]) VG_(clo_trace_codegen) |= (1 << j);
1766 else {
1767 VG_(message)(Vg_UserMsg, "--trace-codegen argument can only "
1768 "contain 0s and 1s");
nethercote71980f02004-01-24 18:18:54 +00001769 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001770 }
1771 }
1772 }
sewardjde4a1d02002-03-22 01:27:54 +00001773
nethercote71980f02004-01-24 18:18:54 +00001774 else if (VG_CLO_STREQ(arg, "--trace-pthread=none"))
sewardj45b4b372002-04-16 22:50:32 +00001775 VG_(clo_trace_pthread_level) = 0;
nethercote71980f02004-01-24 18:18:54 +00001776 else if (VG_CLO_STREQ(arg, "--trace-pthread=some"))
sewardj45b4b372002-04-16 22:50:32 +00001777 VG_(clo_trace_pthread_level) = 1;
nethercote71980f02004-01-24 18:18:54 +00001778 else if (VG_CLO_STREQ(arg, "--trace-pthread=all"))
sewardj45b4b372002-04-16 22:50:32 +00001779 VG_(clo_trace_pthread_level) = 2;
sewardj8937c812002-04-12 20:12:20 +00001780
nethercote71980f02004-01-24 18:18:54 +00001781 else if ( ! VG_(needs).command_line_options
1782 || ! SK_(process_cmd_line_option)(arg) ) {
nethercotef4928da2004-06-15 10:54:40 +00001783 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001784 }
sewardjde4a1d02002-03-22 01:27:54 +00001785 }
1786
nethercote27fec902004-06-16 21:26:32 +00001787 // Check various option values
1788
njnf9ebf672003-05-12 21:41:30 +00001789 if (VG_(clo_verbosity) < 0)
sewardjde4a1d02002-03-22 01:27:54 +00001790 VG_(clo_verbosity) = 0;
1791
nethercote04d0fbc2004-01-26 16:48:06 +00001792 if (VG_(clo_db_attach) && VG_(clo_trace_children)) {
sewardjde4a1d02002-03-22 01:27:54 +00001793 VG_(message)(Vg_UserMsg, "");
1794 VG_(message)(Vg_UserMsg,
nethercote04d0fbc2004-01-26 16:48:06 +00001795 "--db-attach=yes conflicts with --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001796 VG_(message)(Vg_UserMsg,
1797 "Please choose one or the other, but not both.");
nethercote04d0fbc2004-01-26 16:48:06 +00001798 VG_(bad_option)("--db-attach=yes and --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001799 }
1800
nethercotef8548672004-06-21 12:42:35 +00001801 /* Set up logging now. After this is done, VG_(clo_log_fd)
sewardj4cf05692002-10-27 20:28:29 +00001802 should be connected to whatever sink has been selected, and we
1803 indiscriminately chuck stuff into it without worrying what the
1804 nature of it is. Oh the wonder of Unix streams. */
1805
nethercotee1730692003-11-20 10:38:07 +00001806 /* So far we should be still attached to stdout, so we can show on
sewardj4cf05692002-10-27 20:28:29 +00001807 the terminal any problems to do with processing command line
1808 opts. */
nethercotef8548672004-06-21 12:42:35 +00001809 vg_assert(VG_(clo_log_fd) == 1 /* stdout */);
sewardj73cf3bc2002-11-03 03:20:15 +00001810 vg_assert(VG_(logging_to_filedes) == True);
sewardj4cf05692002-10-27 20:28:29 +00001811
1812 switch (VG_(clo_log_to)) {
sewardj73cf3bc2002-11-03 03:20:15 +00001813
sewardj4cf05692002-10-27 20:28:29 +00001814 case VgLogTo_Fd:
nethercotef8548672004-06-21 12:42:35 +00001815 vg_assert(VG_(clo_log_name) == NULL);
1816 VG_(clo_log_fd) = eventually_log_fd;
sewardj4cf05692002-10-27 20:28:29 +00001817 break;
sewardj73cf3bc2002-11-03 03:20:15 +00001818
sewardj4cf05692002-10-27 20:28:29 +00001819 case VgLogTo_File: {
1820 Char logfilename[1000];
jsgff3c3f1a2003-10-14 22:13:28 +00001821 Int seq = 0;
1822 Int pid = VG_(getpid)();
1823
nethercotef8548672004-06-21 12:42:35 +00001824 vg_assert(VG_(clo_log_name) != NULL);
1825 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
jsgff3c3f1a2003-10-14 22:13:28 +00001826
nethercote71980f02004-01-24 18:18:54 +00001827 for (;;) {
jsgff3c3f1a2003-10-14 22:13:28 +00001828 if (seq == 0)
1829 VG_(sprintf)(logfilename, "%s.pid%d",
nethercotef8548672004-06-21 12:42:35 +00001830 VG_(clo_log_name), pid );
jsgff3c3f1a2003-10-14 22:13:28 +00001831 else
1832 VG_(sprintf)(logfilename, "%s.pid%d.%d",
nethercotef8548672004-06-21 12:42:35 +00001833 VG_(clo_log_name), pid, seq );
jsgff3c3f1a2003-10-14 22:13:28 +00001834 seq++;
1835
nethercotef8548672004-06-21 12:42:35 +00001836 eventually_log_fd
jsgff3c3f1a2003-10-14 22:13:28 +00001837 = VG_(open)(logfilename,
1838 VKI_O_CREAT|VKI_O_WRONLY|VKI_O_EXCL|VKI_O_TRUNC,
1839 VKI_S_IRUSR|VKI_S_IWUSR);
nethercotef8548672004-06-21 12:42:35 +00001840 if (eventually_log_fd >= 0) {
1841 VG_(clo_log_fd) = VG_(safe_fd)(eventually_log_fd);
jsgff3c3f1a2003-10-14 22:13:28 +00001842 break;
1843 } else {
nethercotef8548672004-06-21 12:42:35 +00001844 if (eventually_log_fd != -VKI_EEXIST) {
jsgff3c3f1a2003-10-14 22:13:28 +00001845 VG_(message)(Vg_UserMsg,
1846 "Can't create/open log file `%s.pid%d'; giving up!",
nethercotef8548672004-06-21 12:42:35 +00001847 VG_(clo_log_name), pid);
jsgff3c3f1a2003-10-14 22:13:28 +00001848 VG_(bad_option)(
nethercotef8548672004-06-21 12:42:35 +00001849 "--log-file=<file> didn't work out for some reason.");
jsgff3c3f1a2003-10-14 22:13:28 +00001850 break;
1851 }
1852 }
1853 }
sewardj4cf05692002-10-27 20:28:29 +00001854 break;
sewardj73cf3bc2002-11-03 03:20:15 +00001855 }
1856
1857 case VgLogTo_Socket: {
nethercotef8548672004-06-21 12:42:35 +00001858 vg_assert(VG_(clo_log_name) != NULL);
1859 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
1860 eventually_log_fd = VG_(connect_via_socket)( VG_(clo_log_name) );
1861 if (eventually_log_fd == -1) {
sewardj73cf3bc2002-11-03 03:20:15 +00001862 VG_(message)(Vg_UserMsg,
nethercotef8548672004-06-21 12:42:35 +00001863 "Invalid --log-socket=ipaddr or --log-socket=ipaddr:port spec");
sewardj73cf3bc2002-11-03 03:20:15 +00001864 VG_(message)(Vg_UserMsg,
nethercotef8548672004-06-21 12:42:35 +00001865 "of `%s'; giving up!", VG_(clo_log_name) );
sewardj73cf3bc2002-11-03 03:20:15 +00001866 VG_(bad_option)(
nethercotef8548672004-06-21 12:42:35 +00001867 "--log-socket=");
sewardj4cf05692002-10-27 20:28:29 +00001868 }
nethercotef8548672004-06-21 12:42:35 +00001869 if (eventually_log_fd == -2) {
sewardj73cf3bc2002-11-03 03:20:15 +00001870 VG_(message)(Vg_UserMsg,
sewardj570f8902002-11-03 11:44:36 +00001871 "valgrind: failed to connect to logging server `%s'.",
nethercotef8548672004-06-21 12:42:35 +00001872 VG_(clo_log_name) );
sewardj570f8902002-11-03 11:44:36 +00001873 VG_(message)(Vg_UserMsg,
1874 "Log messages will sent to stderr instead." );
1875 VG_(message)(Vg_UserMsg,
1876 "" );
1877 /* We don't change anything here. */
1878 } else {
nethercotef8548672004-06-21 12:42:35 +00001879 vg_assert(eventually_log_fd > 0);
1880 VG_(clo_log_fd) = eventually_log_fd;
sewardj570f8902002-11-03 11:44:36 +00001881 VG_(logging_to_filedes) = False;
1882 }
sewardj73cf3bc2002-11-03 03:20:15 +00001883 break;
1884 }
1885
sewardj4cf05692002-10-27 20:28:29 +00001886 }
1887
nethercotef8548672004-06-21 12:42:35 +00001888 /* Move log_fd into the safe range, so it doesn't conflict with any app fds */
thughesad1c9562004-06-26 11:27:52 +00001889 eventually_log_fd = VG_(fcntl)(VG_(clo_log_fd), VKI_F_DUPFD, VG_(fd_hard_limit));
nethercotef8548672004-06-21 12:42:35 +00001890 if (eventually_log_fd < 0)
jsgf855d93d2003-10-13 22:26:55 +00001891 VG_(message)(Vg_UserMsg, "valgrind: failed to move logfile fd into safe range");
1892 else {
nethercotef8548672004-06-21 12:42:35 +00001893 VG_(clo_log_fd) = eventually_log_fd;
1894 VG_(fcntl)(VG_(clo_log_fd), VKI_F_SETFD, VKI_FD_CLOEXEC);
jsgf855d93d2003-10-13 22:26:55 +00001895 }
1896
sewardj4cf05692002-10-27 20:28:29 +00001897 /* Ok, the logging sink is running now. Print a suitable preamble.
1898 If logging to file or a socket, write details of parent PID and
1899 command line args, to help people trying to interpret the
1900 results of a run which encompasses multiple processes. */
sewardjde4a1d02002-03-22 01:27:54 +00001901
sewardj83adf412002-05-01 01:25:45 +00001902 if (VG_(clo_verbosity > 0)) {
nethercote996901a2004-08-03 13:29:09 +00001903 /* Tool details */
njnd04b7c62002-10-03 14:05:52 +00001904 VG_(message)(Vg_UserMsg, "%s%s%s, %s for x86-linux.",
1905 VG_(details).name,
1906 NULL == VG_(details).version ? "" : "-",
1907 NULL == VG_(details).version
1908 ? (Char*)"" : VG_(details).version,
1909 VG_(details).description);
1910 VG_(message)(Vg_UserMsg, "%s", VG_(details).copyright_author);
sewardj3b2736a2002-03-24 12:18:35 +00001911
njnd04b7c62002-10-03 14:05:52 +00001912 /* Core details */
1913 VG_(message)(Vg_UserMsg,
njn3e884182003-04-15 13:03:23 +00001914 "Using valgrind-%s, a program supervision framework for x86-linux.",
sewardj4aa62ba2002-10-05 15:49:27 +00001915 VERSION);
sewardjde4a1d02002-03-22 01:27:54 +00001916 VG_(message)(Vg_UserMsg,
nethercote08fa9a72004-07-16 17:44:00 +00001917 "Copyright (C) 2000-2004, and GNU GPL'd, by Julian Seward et al.");
njnd04b7c62002-10-03 14:05:52 +00001918 }
1919
nethercotec1e395d2003-11-10 13:26:49 +00001920 if (VG_(clo_verbosity) > 0 && VG_(clo_log_to) != VgLogTo_Fd) {
sewardj4cf05692002-10-27 20:28:29 +00001921 VG_(message)(Vg_UserMsg, "");
1922 VG_(message)(Vg_UserMsg,
1923 "My PID = %d, parent PID = %d. Prog and args are:",
1924 VG_(getpid)(), VG_(getppid)() );
1925 for (i = 0; i < VG_(client_argc); i++)
1926 VG_(message)(Vg_UserMsg, " %s", VG_(client_argv)[i]);
1927 }
1928
sewardjde4a1d02002-03-22 01:27:54 +00001929 if (VG_(clo_verbosity) > 1) {
nethercotea70f7352004-04-18 12:08:46 +00001930 Int fd;
sewardj4cf05692002-10-27 20:28:29 +00001931 if (VG_(clo_log_to) != VgLogTo_Fd)
1932 VG_(message)(Vg_UserMsg, "");
fitzhardinge98abfc72003-12-16 02:05:15 +00001933 VG_(message)(Vg_UserMsg, "Valgrind library directory: %s", VG_(libdir));
njn86dc2bc2003-09-09 07:26:21 +00001934 VG_(message)(Vg_UserMsg, "Command line");
1935 for (i = 0; i < VG_(client_argc); i++)
1936 VG_(message)(Vg_UserMsg, " %s", VG_(client_argv)[i]);
1937
sewardjde4a1d02002-03-22 01:27:54 +00001938 VG_(message)(Vg_UserMsg, "Startup, with flags:");
nethercotef6a1d502004-08-09 12:21:57 +00001939 for (i = 1; i < vg_argc; i++) {
1940 VG_(message)(Vg_UserMsg, " %s", vg_argv[i]);
sewardjde4a1d02002-03-22 01:27:54 +00001941 }
nethercotea70f7352004-04-18 12:08:46 +00001942
1943 VG_(message)(Vg_UserMsg, "Contents of /proc/version:");
1944 fd = VG_(open) ( "/proc/version", VKI_O_RDONLY, 0 );
1945 if (fd < 0) {
1946 VG_(message)(Vg_UserMsg, " can't open /proc/version");
1947 } else {
1948 #define BUF_LEN 256
1949 Char version_buf[BUF_LEN];
1950 Int n = VG_(read) ( fd, version_buf, BUF_LEN );
1951 vg_assert(n <= 256);
1952 if (n > 0) {
1953 version_buf[n-1] = '\0';
1954 VG_(message)(Vg_UserMsg, " %s", version_buf);
1955 } else {
1956 VG_(message)(Vg_UserMsg, " (empty?)");
1957 }
1958 VG_(close)(fd);
1959 #undef BUF_LEN
1960 }
sewardjde4a1d02002-03-22 01:27:54 +00001961 }
1962
fitzhardinge98abfc72003-12-16 02:05:15 +00001963 if (VG_(clo_n_suppressions) < VG_CLO_MAX_SFILES-1 &&
njn25e49d8e72002-09-23 09:36:25 +00001964 (VG_(needs).core_errors || VG_(needs).skin_errors)) {
nethercote996901a2004-08-03 13:29:09 +00001965 /* If there are no suppression files specified and the tool
fitzhardinge98abfc72003-12-16 02:05:15 +00001966 needs one, load the default */
1967 static const Char default_supp[] = "default.supp";
1968 Int len = VG_(strlen)(VG_(libdir)) + 1 + sizeof(default_supp);
1969 Char *buf = VG_(arena_malloc)(VG_AR_CORE, len);
1970 VG_(sprintf)(buf, "%s/%s", VG_(libdir), default_supp);
1971 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = buf;
1972 VG_(clo_n_suppressions)++;
sewardjde4a1d02002-03-22 01:27:54 +00001973 }
sewardj4cf05692002-10-27 20:28:29 +00001974
njn6a230532003-07-21 10:38:23 +00001975 if (VG_(clo_gen_suppressions) &&
1976 !VG_(needs).core_errors && !VG_(needs).skin_errors) {
nethercotef4928da2004-06-15 10:54:40 +00001977 VG_(message)(Vg_UserMsg,
1978 "Can't use --gen-suppressions=yes with this tool,");
1979 VG_(message)(Vg_UserMsg,
1980 "as it doesn't generate errors.");
1981 VG_(bad_option)("--gen-suppressions=yes");
njn6a230532003-07-21 10:38:23 +00001982 }
sewardjde4a1d02002-03-22 01:27:54 +00001983}
1984
nethercotef6a1d502004-08-09 12:21:57 +00001985// Build the string for VALGRINDCLO.
1986Char* VG_(build_child_VALGRINDCLO)( Char* exename )
1987{
1988 /* If we're tracing the children, then we need to start it
1989 with our starter+arguments, which are copied into VALGRINDCLO,
1990 except the --exec= option is changed if present.
1991 */
1992 Int i;
1993 Char *exec;
1994 Char *cp;
1995 Char *optvar;
1996 Int optlen, execlen;
1997
1998 // All these allocated blocks are not free - because we're either
1999 // going to exec, or panic when we fail.
2000
2001 // Create --exec= option: "--exec=<exename>"
2002 exec = VG_(arena_malloc)(VG_AR_CORE,
2003 VG_(strlen)( exename ) + 7/*--exec=*/ + 1/*\0*/);
2004 vg_assert(NULL != exec);
2005 VG_(sprintf)(exec, "--exec=%s", exename);
2006
2007 // Allocate space for optvar (may overestimate by counting --exec twice,
2008 // no matter)
2009 optlen = 1;
2010 for (i = 0; i < vg_argc; i++)
2011 optlen += VG_(strlen)(vg_argv[i]) + 1;
2012 optlen += VG_(strlen)(exec)+1;
2013 optvar = VG_(arena_malloc)(VG_AR_CORE, optlen);
2014
2015 // Copy all valgrind args except the old --exec (if present)
2016 // VG_CLO_SEP is the separator.
2017 cp = optvar;
2018 for (i = 1; i < vg_argc; i++) {
2019 Char *arg = vg_argv[i];
2020
2021 if (VG_(memcmp)(arg, "--exec=", 7) == 0) {
2022 // don't copy existing --exec= arg
2023 } else if (VG_(strcmp)(arg, "--") == 0) {
2024 // stop at "--"
2025 break;
2026 } else {
2027 // copy non "--exec" arg
2028 Int len = VG_(strlen)(arg);
2029 VG_(memcpy)(cp, arg, len);
2030 cp += len;
2031 *cp++ = VG_CLO_SEP;
2032 }
2033 }
2034 // Add the new --exec= option
2035 execlen = VG_(strlen)(exec);
2036 VG_(memcpy)(cp, exec, execlen);
2037 cp += execlen;
2038 *cp++ = VG_CLO_SEP;
2039
2040 *cp = '\0';
2041
2042 return optvar;
2043}
2044
2045// Build "/proc/self/fd/<execfd>".
2046Char* VG_(build_child_exename)( void )
2047{
2048 Char* exename = VG_(arena_malloc)(VG_AR_CORE, 64);
2049 vg_assert(NULL != exename);
2050 VG_(sprintf)(exename, "/proc/self/fd/%d", vgexecfd);
2051 return exename;
2052}
2053
sewardjde4a1d02002-03-22 01:27:54 +00002054
nethercote71980f02004-01-24 18:18:54 +00002055/*====================================================================*/
2056/*=== File descriptor setup ===*/
2057/*====================================================================*/
2058
2059static void setup_file_descriptors(void)
2060{
2061 struct vki_rlimit rl;
2062
2063 /* Get the current file descriptor limits. */
2064 if (VG_(getrlimit)(VKI_RLIMIT_NOFILE, &rl) < 0) {
2065 rl.rlim_cur = 1024;
2066 rl.rlim_max = 1024;
2067 }
2068
2069 /* Work out where to move the soft limit to. */
2070 if (rl.rlim_cur + VG_N_RESERVED_FDS <= rl.rlim_max) {
2071 rl.rlim_cur = rl.rlim_cur + VG_N_RESERVED_FDS;
2072 } else {
2073 rl.rlim_cur = rl.rlim_max;
2074 }
2075
2076 /* Reserve some file descriptors for our use. */
thughesad1c9562004-06-26 11:27:52 +00002077 VG_(fd_soft_limit) = rl.rlim_cur - VG_N_RESERVED_FDS;
2078 VG_(fd_hard_limit) = rl.rlim_cur - VG_N_RESERVED_FDS;
nethercote71980f02004-01-24 18:18:54 +00002079
2080 /* Update the soft limit. */
2081 VG_(setrlimit)(VKI_RLIMIT_NOFILE, &rl);
2082
nethercotef6a1d502004-08-09 12:21:57 +00002083 if (vgexecfd != -1)
2084 vgexecfd = VG_(safe_fd)( vgexecfd );
nethercote71980f02004-01-24 18:18:54 +00002085 if (VG_(clexecfd) != -1)
2086 VG_(clexecfd) = VG_(safe_fd)( VG_(clexecfd) );
2087}
2088
2089
2090/*====================================================================*/
nethercote1d447092004-02-01 17:29:59 +00002091/*=== baseBlock: definition + setup ===*/
nethercote71980f02004-01-24 18:18:54 +00002092/*====================================================================*/
2093
2094/* The variables storing offsets. */
2095
2096#define INVALID_OFFSET (-1)
2097
2098Int VGOFF_(m_eax) = INVALID_OFFSET;
2099Int VGOFF_(m_ecx) = INVALID_OFFSET;
2100Int VGOFF_(m_edx) = INVALID_OFFSET;
2101Int VGOFF_(m_ebx) = INVALID_OFFSET;
2102Int VGOFF_(m_esp) = INVALID_OFFSET;
2103Int VGOFF_(m_ebp) = INVALID_OFFSET;
2104Int VGOFF_(m_esi) = INVALID_OFFSET;
2105Int VGOFF_(m_edi) = INVALID_OFFSET;
2106Int VGOFF_(m_eflags) = INVALID_OFFSET;
2107Int VGOFF_(m_dflag) = INVALID_OFFSET;
2108Int VGOFF_(m_ssestate) = INVALID_OFFSET;
2109Int VGOFF_(ldt) = INVALID_OFFSET;
nethercoted8510ec2004-08-18 23:11:45 +00002110Int VGOFF_(tls_ptr) = INVALID_OFFSET;
nethercote71980f02004-01-24 18:18:54 +00002111Int VGOFF_(m_cs) = INVALID_OFFSET;
2112Int VGOFF_(m_ss) = INVALID_OFFSET;
2113Int VGOFF_(m_ds) = INVALID_OFFSET;
2114Int VGOFF_(m_es) = INVALID_OFFSET;
2115Int VGOFF_(m_fs) = INVALID_OFFSET;
2116Int VGOFF_(m_gs) = INVALID_OFFSET;
2117Int VGOFF_(m_eip) = INVALID_OFFSET;
2118Int VGOFF_(spillslots) = INVALID_OFFSET;
2119Int VGOFF_(sh_eax) = INVALID_OFFSET;
2120Int VGOFF_(sh_ecx) = INVALID_OFFSET;
2121Int VGOFF_(sh_edx) = INVALID_OFFSET;
2122Int VGOFF_(sh_ebx) = INVALID_OFFSET;
2123Int VGOFF_(sh_esp) = INVALID_OFFSET;
2124Int VGOFF_(sh_ebp) = INVALID_OFFSET;
2125Int VGOFF_(sh_esi) = INVALID_OFFSET;
2126Int VGOFF_(sh_edi) = INVALID_OFFSET;
2127Int VGOFF_(sh_eflags) = INVALID_OFFSET;
2128
2129Int VGOFF_(helper_idiv_64_32) = INVALID_OFFSET;
2130Int VGOFF_(helper_div_64_32) = INVALID_OFFSET;
2131Int VGOFF_(helper_idiv_32_16) = INVALID_OFFSET;
2132Int VGOFF_(helper_div_32_16) = INVALID_OFFSET;
2133Int VGOFF_(helper_idiv_16_8) = INVALID_OFFSET;
2134Int VGOFF_(helper_div_16_8) = INVALID_OFFSET;
2135Int VGOFF_(helper_imul_32_64) = INVALID_OFFSET;
2136Int VGOFF_(helper_mul_32_64) = INVALID_OFFSET;
2137Int VGOFF_(helper_imul_16_32) = INVALID_OFFSET;
2138Int VGOFF_(helper_mul_16_32) = INVALID_OFFSET;
2139Int VGOFF_(helper_imul_8_16) = INVALID_OFFSET;
2140Int VGOFF_(helper_mul_8_16) = INVALID_OFFSET;
2141Int VGOFF_(helper_CLD) = INVALID_OFFSET;
2142Int VGOFF_(helper_STD) = INVALID_OFFSET;
2143Int VGOFF_(helper_get_dirflag) = INVALID_OFFSET;
2144Int VGOFF_(helper_CLC) = INVALID_OFFSET;
2145Int VGOFF_(helper_STC) = INVALID_OFFSET;
nethercote1018bdd2004-02-11 23:33:29 +00002146Int VGOFF_(helper_CMC) = INVALID_OFFSET;
nethercote71980f02004-01-24 18:18:54 +00002147Int VGOFF_(helper_shldl) = INVALID_OFFSET;
2148Int VGOFF_(helper_shldw) = INVALID_OFFSET;
2149Int VGOFF_(helper_shrdl) = INVALID_OFFSET;
2150Int VGOFF_(helper_shrdw) = INVALID_OFFSET;
2151Int VGOFF_(helper_IN) = INVALID_OFFSET;
2152Int VGOFF_(helper_OUT) = INVALID_OFFSET;
2153Int VGOFF_(helper_RDTSC) = INVALID_OFFSET;
2154Int VGOFF_(helper_CPUID) = INVALID_OFFSET;
2155Int VGOFF_(helper_BSWAP) = INVALID_OFFSET;
nethercote1018bdd2004-02-11 23:33:29 +00002156Int VGOFF_(helper_bsfw) = INVALID_OFFSET;
2157Int VGOFF_(helper_bsfl) = INVALID_OFFSET;
2158Int VGOFF_(helper_bsrw) = INVALID_OFFSET;
2159Int VGOFF_(helper_bsrl) = INVALID_OFFSET;
nethercote71980f02004-01-24 18:18:54 +00002160Int VGOFF_(helper_fstsw_AX) = INVALID_OFFSET;
2161Int VGOFF_(helper_SAHF) = INVALID_OFFSET;
2162Int VGOFF_(helper_LAHF) = INVALID_OFFSET;
2163Int VGOFF_(helper_DAS) = INVALID_OFFSET;
2164Int VGOFF_(helper_DAA) = INVALID_OFFSET;
nethercote1018bdd2004-02-11 23:33:29 +00002165Int VGOFF_(helper_AAS) = INVALID_OFFSET;
2166Int VGOFF_(helper_AAA) = INVALID_OFFSET;
2167Int VGOFF_(helper_AAD) = INVALID_OFFSET;
2168Int VGOFF_(helper_AAM) = INVALID_OFFSET;
nethercote71980f02004-01-24 18:18:54 +00002169Int VGOFF_(helper_cmpxchg8b) = INVALID_OFFSET;
2170Int VGOFF_(helper_undefined_instruction) = INVALID_OFFSET;
2171
2172/* MAX_NONCOMPACT_HELPERS can be increased easily. If MAX_COMPACT_HELPERS is
2173 * increased too much, they won't really be compact any more... */
2174#define MAX_COMPACT_HELPERS 8
2175#define MAX_NONCOMPACT_HELPERS 50
2176
nethercote81f9a6f2004-08-03 15:45:46 +00002177/* For storing tool-specific helpers, determined at runtime. The addr
2178 * and offset arrays together form a (addr, offset) map that allows a
2179 * helper's baseBlock offset to be computed from its address. It's done
2180 * like this so CCALLs can use the function address rather than having to
2181 * muck around with offsets. */
2182static UInt VG_(n_compact_helpers) = 0;
2183static UInt VG_(n_noncompact_helpers) = 0;
2184static Addr VG_(compact_helper_addrs) [MAX_COMPACT_HELPERS];
2185static Int VG_(compact_helper_offsets)[MAX_COMPACT_HELPERS];
2186static Addr VG_(noncompact_helper_addrs) [MAX_NONCOMPACT_HELPERS];
2187static Int VG_(noncompact_helper_offsets)[MAX_NONCOMPACT_HELPERS];
nethercote71980f02004-01-24 18:18:54 +00002188
2189/* This is the actual defn of baseblock. */
2190UInt VG_(baseBlock)[VG_BASEBLOCK_WORDS];
2191
nethercote71980f02004-01-24 18:18:54 +00002192/* Words. */
2193static Int baB_off = 0;
2194
2195
nethercote71980f02004-01-24 18:18:54 +00002196/* Returns the offset, in words. */
2197static Int alloc_BaB ( Int words )
sewardjde4a1d02002-03-22 01:27:54 +00002198{
nethercote71980f02004-01-24 18:18:54 +00002199 Int off = baB_off;
2200 baB_off += words;
2201 if (baB_off >= VG_BASEBLOCK_WORDS)
2202 VG_(core_panic)( "alloc_BaB: baseBlock is too small");
sewardjde4a1d02002-03-22 01:27:54 +00002203
nethercote71980f02004-01-24 18:18:54 +00002204 return off;
sewardjde4a1d02002-03-22 01:27:54 +00002205}
2206
nethercote71980f02004-01-24 18:18:54 +00002207/* Align offset, in *bytes* */
2208static void align_BaB ( UInt align )
njn25e49d8e72002-09-23 09:36:25 +00002209{
nethercote71980f02004-01-24 18:18:54 +00002210 vg_assert(2 == align || 4 == align || 8 == align || 16 == align);
2211 baB_off += (align-1);
2212 baB_off &= ~(align-1);
njn25e49d8e72002-09-23 09:36:25 +00002213}
2214
nethercote71980f02004-01-24 18:18:54 +00002215/* Allocate 1 word in baseBlock and set it to the given value. */
2216static Int alloc_BaB_1_set ( Addr a )
njn25e49d8e72002-09-23 09:36:25 +00002217{
nethercote71980f02004-01-24 18:18:54 +00002218 Int off = alloc_BaB(1);
2219 VG_(baseBlock)[off] = (UInt)a;
2220 return off;
njn25e49d8e72002-09-23 09:36:25 +00002221}
2222
nethercote71980f02004-01-24 18:18:54 +00002223/* Registers a function in compact_helper_addrs; compact_helper_offsets is
2224 filled in later. */
2225void VG_(register_compact_helper)(Addr a)
sewardjde4a1d02002-03-22 01:27:54 +00002226{
nethercote71980f02004-01-24 18:18:54 +00002227 if (MAX_COMPACT_HELPERS <= VG_(n_compact_helpers)) {
2228 VG_(printf)("Can only register %d compact helpers\n",
2229 MAX_COMPACT_HELPERS);
2230 VG_(core_panic)("Too many compact helpers registered");
2231 }
2232 VG_(compact_helper_addrs)[VG_(n_compact_helpers)] = a;
2233 VG_(n_compact_helpers)++;
2234}
2235
2236/* Registers a function in noncompact_helper_addrs; noncompact_helper_offsets
2237 * is filled in later.
2238 */
2239void VG_(register_noncompact_helper)(Addr a)
2240{
2241 if (MAX_NONCOMPACT_HELPERS <= VG_(n_noncompact_helpers)) {
2242 VG_(printf)("Can only register %d non-compact helpers\n",
2243 MAX_NONCOMPACT_HELPERS);
2244 VG_(printf)("Try increasing MAX_NON_COMPACT_HELPERS\n");
2245 VG_(core_panic)("Too many non-compact helpers registered");
2246 }
2247 VG_(noncompact_helper_addrs)[VG_(n_noncompact_helpers)] = a;
2248 VG_(n_noncompact_helpers)++;
2249}
2250
nethercote996901a2004-08-03 13:29:09 +00002251/* Allocate offsets in baseBlock for the tool helpers */
nethercote71980f02004-01-24 18:18:54 +00002252static
2253void assign_helpers_in_baseBlock(UInt n, Int offsets[], Addr addrs[])
2254{
2255 UInt i;
2256 for (i = 0; i < n; i++)
2257 offsets[i] = alloc_BaB_1_set( addrs[i] );
2258}
2259
2260Bool VG_(need_to_handle_esp_assignment)(void)
2261{
2262 return ( VG_(defined_new_mem_stack_4)() ||
2263 VG_(defined_die_mem_stack_4)() ||
2264 VG_(defined_new_mem_stack_8)() ||
2265 VG_(defined_die_mem_stack_8)() ||
2266 VG_(defined_new_mem_stack_12)() ||
2267 VG_(defined_die_mem_stack_12)() ||
2268 VG_(defined_new_mem_stack_16)() ||
2269 VG_(defined_die_mem_stack_16)() ||
2270 VG_(defined_new_mem_stack_32)() ||
2271 VG_(defined_die_mem_stack_32)() ||
2272 VG_(defined_new_mem_stack)() ||
2273 VG_(defined_die_mem_stack)()
2274 );
2275}
2276
2277/* Here we assign actual offsets. It's important to get the most
2278 popular referents within 128 bytes of the start, so we can take
2279 advantage of short addressing modes relative to %ebp. Popularity
2280 of offsets was measured on 22 Feb 02 running a KDE application, and
2281 the slots rearranged accordingly, with a 1.5% reduction in total
2282 size of translations. */
2283static void init_baseBlock ( Addr client_eip, Addr esp_at_startup )
2284{
2285 /* Those with offsets under 128 are carefully chosen. */
2286
2287 /* WORD offsets in this column */
2288 /* 0 */ VGOFF_(m_eax) = alloc_BaB_1_set(0);
2289 /* 1 */ VGOFF_(m_ecx) = alloc_BaB_1_set(0);
2290 /* 2 */ VGOFF_(m_edx) = alloc_BaB_1_set(0);
2291 /* 3 */ VGOFF_(m_ebx) = alloc_BaB_1_set(0);
2292 /* 4 */ VGOFF_(m_esp) = alloc_BaB_1_set(esp_at_startup);
2293 /* 5 */ VGOFF_(m_ebp) = alloc_BaB_1_set(0);
2294 /* 6 */ VGOFF_(m_esi) = alloc_BaB_1_set(0);
2295 /* 7 */ VGOFF_(m_edi) = alloc_BaB_1_set(0);
2296 /* 8 */ VGOFF_(m_eflags) = alloc_BaB_1_set(0);
2297
2298 if (VG_(needs).shadow_regs) {
2299 /* 9 */ VGOFF_(sh_eax) = alloc_BaB_1_set(0);
2300 /* 10 */ VGOFF_(sh_ecx) = alloc_BaB_1_set(0);
2301 /* 11 */ VGOFF_(sh_edx) = alloc_BaB_1_set(0);
2302 /* 12 */ VGOFF_(sh_ebx) = alloc_BaB_1_set(0);
2303 /* 13 */ VGOFF_(sh_esp) = alloc_BaB_1_set(0);
2304 /* 14 */ VGOFF_(sh_ebp) = alloc_BaB_1_set(0);
2305 /* 15 */ VGOFF_(sh_esi) = alloc_BaB_1_set(0);
2306 /* 16 */ VGOFF_(sh_edi) = alloc_BaB_1_set(0);
2307 /* 17 */ VGOFF_(sh_eflags) = alloc_BaB_1_set(0);
2308 VG_TRACK( post_regs_write_init );
2309 }
2310
2311 /* 9,10,11 or 18,19,20... depends on number whether shadow regs are used
2312 * and on compact helpers registered */
2313
2314 /* Make these most-frequently-called specialised ones compact, if they
2315 are used. */
2316 if (VG_(defined_new_mem_stack_4)())
2317 VG_(register_compact_helper)( (Addr) VG_(tool_interface).track_new_mem_stack_4);
2318
2319 if (VG_(defined_die_mem_stack_4)())
2320 VG_(register_compact_helper)( (Addr) VG_(tool_interface).track_die_mem_stack_4);
2321
2322 /* (9 or 18) + n_compact_helpers */
2323 /* Allocate slots for compact helpers */
2324 assign_helpers_in_baseBlock(VG_(n_compact_helpers),
2325 VG_(compact_helper_offsets),
2326 VG_(compact_helper_addrs));
2327
2328 /* (9/10 or 18/19) + n_compact_helpers */
2329 VGOFF_(m_eip) = alloc_BaB_1_set(client_eip);
2330
2331 /* There are currently 24 spill slots */
2332 /* (11+/20+ .. 32+/43+) + n_compact_helpers. This can overlap the magic
2333 * boundary at >= 32 words, but most spills are to low numbered spill
2334 * slots, so the ones above the boundary don't see much action. */
2335 VGOFF_(spillslots) = alloc_BaB(VG_MAX_SPILLSLOTS);
2336
2337 /* I gave up counting at this point. Since they're above the
2338 short-amode-boundary, there's no point. */
2339
2340 VGOFF_(m_dflag) = alloc_BaB_1_set(1); // 1 == forward D-flag
2341
2342 /* The FPU/SSE state. This _must_ be 16-byte aligned. Initial
2343 state doesn't matter much, as long as it's not totally borked. */
2344 align_BaB(16);
2345 VGOFF_(m_ssestate) = alloc_BaB(VG_SIZE_OF_SSESTATE_W);
2346 vg_assert(
2347 0 == ( ((UInt)(& VG_(baseBlock)[VGOFF_(m_ssestate)])) % 16 )
sewardj22854b92002-11-30 14:00:47 +00002348 );
2349
fitzhardingec2dbbac2004-01-23 23:09:01 +00002350 /* I assume that if we have SSE2 we also have SSE */
2351 VG_(have_ssestate) =
2352 VG_(cpu_has_feature)(VG_X86_FEAT_FXSR) &&
2353 VG_(cpu_has_feature)(VG_X86_FEAT_SSE);
2354
fitzhardinge98abfc72003-12-16 02:05:15 +00002355 /* set up an initial FPU state (doesn't really matter what it is,
2356 so long as it's somewhat valid) */
2357 if (!VG_(have_ssestate))
nethercote71980f02004-01-24 18:18:54 +00002358 asm volatile("fwait; fnsave %0; fwait; frstor %0; fwait"
2359 :
2360 : "m" (VG_(baseBlock)[VGOFF_(m_ssestate)])
2361 : "cc", "memory");
fitzhardinge98abfc72003-12-16 02:05:15 +00002362 else
nethercote71980f02004-01-24 18:18:54 +00002363 asm volatile("fwait; fxsave %0; fwait; andl $0xffbf, %1;"
2364 "fxrstor %0; fwait"
2365 :
2366 : "m" (VG_(baseBlock)[VGOFF_(m_ssestate)]),
2367 "m" (VG_(baseBlock)[VGOFF_(m_ssestate)+(24/4)])
2368 : "cc", "memory");
fitzhardinge98abfc72003-12-16 02:05:15 +00002369
njn0c7a5b52003-04-30 09:00:33 +00002370 if (0) {
2371 if (VG_(have_ssestate))
2372 VG_(printf)("Looks like a SSE-capable CPU\n");
2373 else
2374 VG_(printf)("Looks like a MMX-only CPU\n");
2375 }
sewardjb91ae7f2003-04-29 23:50:00 +00002376
nethercote71980f02004-01-24 18:18:54 +00002377 /* LDT pointer: pretend the root thread has an empty LDT to start with. */
2378 VGOFF_(ldt) = alloc_BaB_1_set((UInt)NULL);
jsgf855d93d2003-10-13 22:26:55 +00002379
nethercote71980f02004-01-24 18:18:54 +00002380 /* TLS pointer: pretend the root thread has no TLS array for now. */
nethercoted8510ec2004-08-18 23:11:45 +00002381 VGOFF_(tls_ptr) = alloc_BaB_1_set((UInt)NULL);
fitzhardingef0046f22003-12-18 02:39:22 +00002382
nethercote71980f02004-01-24 18:18:54 +00002383 /* segment registers */
2384 VGOFF_(m_cs) = alloc_BaB_1_set(0);
2385 VGOFF_(m_ss) = alloc_BaB_1_set(0);
2386 VGOFF_(m_ds) = alloc_BaB_1_set(0);
2387 VGOFF_(m_es) = alloc_BaB_1_set(0);
2388 VGOFF_(m_fs) = alloc_BaB_1_set(0);
2389 VGOFF_(m_gs) = alloc_BaB_1_set(0);
fitzhardingef0046f22003-12-18 02:39:22 +00002390
thughes35cec982004-04-21 15:16:43 +00002391 /* initialise %cs, %ds and %ss to point at the operating systems
2392 default code, data and stack segments */
2393 asm volatile("movw %%cs, %0"
2394 :
2395 : "m" (VG_(baseBlock)[VGOFF_(m_cs)]));
2396 asm volatile("movw %%ds, %0"
2397 :
2398 : "m" (VG_(baseBlock)[VGOFF_(m_ds)]));
2399 asm volatile("movw %%ss, %0"
2400 :
2401 : "m" (VG_(baseBlock)[VGOFF_(m_ss)]));
2402
nethercote71980f02004-01-24 18:18:54 +00002403 VG_(register_noncompact_helper)( (Addr) & VG_(do_useseg) );
fitzhardingef0046f22003-12-18 02:39:22 +00002404
nethercote71980f02004-01-24 18:18:54 +00002405#define REG(kind, size) \
2406 if (VG_(defined_##kind##_mem_stack##size)()) \
2407 VG_(register_noncompact_helper)( \
2408 (Addr) VG_(tool_interface).track_##kind##_mem_stack##size );
2409 REG(new, _8);
2410 REG(new, _12);
2411 REG(new, _16);
2412 REG(new, _32);
2413 REG(new, );
2414 REG(die, _8);
2415 REG(die, _12);
2416 REG(die, _16);
2417 REG(die, _32);
2418 REG(die, );
2419#undef REG
fitzhardingef0046f22003-12-18 02:39:22 +00002420
nethercote71980f02004-01-24 18:18:54 +00002421 if (VG_(need_to_handle_esp_assignment)())
2422 VG_(register_noncompact_helper)((Addr) VG_(unknown_esp_update));
fitzhardingeb791a192003-12-18 07:22:44 +00002423
nethercote71980f02004-01-24 18:18:54 +00002424# define HELPER(name) \
2425 VGOFF_(helper_##name) = alloc_BaB_1_set( (Addr) & VG_(helper_##name))
njn3e884182003-04-15 13:03:23 +00002426
nethercote71980f02004-01-24 18:18:54 +00002427 /* Helper functions. */
2428 HELPER(idiv_64_32); HELPER(div_64_32);
2429 HELPER(idiv_32_16); HELPER(div_32_16);
2430 HELPER(idiv_16_8); HELPER(div_16_8);
fitzhardinge98abfc72003-12-16 02:05:15 +00002431
nethercote71980f02004-01-24 18:18:54 +00002432 HELPER(imul_32_64); HELPER(mul_32_64);
2433 HELPER(imul_16_32); HELPER(mul_16_32);
2434 HELPER(imul_8_16); HELPER(mul_8_16);
njn25e49d8e72002-09-23 09:36:25 +00002435
nethercote71980f02004-01-24 18:18:54 +00002436 HELPER(CLD); HELPER(STD);
2437 HELPER(get_dirflag);
sewardjde4a1d02002-03-22 01:27:54 +00002438
nethercote71980f02004-01-24 18:18:54 +00002439 HELPER(CLC); HELPER(STC);
nethercote1018bdd2004-02-11 23:33:29 +00002440 HELPER(CMC);
jsgf855d93d2003-10-13 22:26:55 +00002441
nethercote71980f02004-01-24 18:18:54 +00002442 HELPER(shldl); HELPER(shldw);
2443 HELPER(shrdl); HELPER(shrdw);
njncc7bb472002-10-14 09:25:19 +00002444
nethercote71980f02004-01-24 18:18:54 +00002445 HELPER(RDTSC); HELPER(CPUID);
njncc7bb472002-10-14 09:25:19 +00002446
nethercote1018bdd2004-02-11 23:33:29 +00002447 HELPER(bsfw); HELPER(bsfl);
2448 HELPER(bsrw); HELPER(bsrl);
rjwalshf5f536f2003-11-17 17:45:00 +00002449
nethercote71980f02004-01-24 18:18:54 +00002450 HELPER(fstsw_AX);
2451 HELPER(SAHF); HELPER(LAHF);
2452 HELPER(DAS); HELPER(DAA);
nethercote1018bdd2004-02-11 23:33:29 +00002453 HELPER(AAS); HELPER(AAA);
2454 HELPER(AAD); HELPER(AAM);
nethercote71980f02004-01-24 18:18:54 +00002455 HELPER(IN); HELPER(OUT);
2456 HELPER(cmpxchg8b);
sewardj018f7622002-05-15 21:13:39 +00002457
nethercote71980f02004-01-24 18:18:54 +00002458 HELPER(undefined_instruction);
jsgf855d93d2003-10-13 22:26:55 +00002459
nethercote71980f02004-01-24 18:18:54 +00002460# undef HELPER
sewardjde4a1d02002-03-22 01:27:54 +00002461
nethercote71980f02004-01-24 18:18:54 +00002462 /* Allocate slots for noncompact helpers */
2463 assign_helpers_in_baseBlock(VG_(n_noncompact_helpers),
2464 VG_(noncompact_helper_offsets),
2465 VG_(noncompact_helper_addrs));
2466}
sewardjde4a1d02002-03-22 01:27:54 +00002467
nethercote81f9a6f2004-08-03 15:45:46 +00002468// Finds the baseBlock offset of a tool-specified helper.
2469// Searches through compacts first, then non-compacts.
2470Int VG_(helper_offset)(Addr a)
2471{
2472 UInt i;
2473 Char buf[100];
2474
2475 for (i = 0; i < VG_(n_compact_helpers); i++)
2476 if (VG_(compact_helper_addrs)[i] == a)
2477 return VG_(compact_helper_offsets)[i];
2478 for (i = 0; i < VG_(n_noncompact_helpers); i++)
2479 if (VG_(noncompact_helper_addrs)[i] == a)
2480 return VG_(noncompact_helper_offsets)[i];
2481
2482 /* Shouldn't get here */
2483 VG_(get_fnname) ( a, buf, 100 );
2484
2485 VG_(printf)(
2486 "\nCouldn't find offset of helper from its address (%p: %s).\n"
2487 "A helper function probably used hasn't been registered?\n\n", a, buf);
2488
2489 VG_(printf)(" compact helpers: ");
2490 for (i = 0; i < VG_(n_compact_helpers); i++)
2491 VG_(printf)("%p ", VG_(compact_helper_addrs)[i]);
2492
2493 VG_(printf)("\n non-compact helpers: ");
2494 for (i = 0; i < VG_(n_noncompact_helpers); i++)
2495 VG_(printf)("%p ", VG_(noncompact_helper_addrs)[i]);
2496
2497 VG_(printf)("\n");
2498 VG_(skin_panic)("Unfound helper");
2499}
2500
sewardj5f07b662002-04-23 16:52:51 +00002501
nethercote71980f02004-01-24 18:18:54 +00002502/*====================================================================*/
2503/*=== Setup pointercheck ===*/
2504/*====================================================================*/
njn25e49d8e72002-09-23 09:36:25 +00002505
nethercote71980f02004-01-24 18:18:54 +00002506static void setup_pointercheck(void)
2507{
2508 int ret;
sewardj2e93c502002-04-12 11:12:52 +00002509
fitzhardinge98abfc72003-12-16 02:05:15 +00002510 if (VG_(clo_pointercheck)) {
nethercote71980f02004-01-24 18:18:54 +00002511 vki_modify_ldt_t ldt = {
2512 VG_POINTERCHECK_SEGIDX, // entry_number
2513 VG_(client_base), // base_addr
2514 (VG_(client_end)-VG_(client_base)) / VKI_BYTES_PER_PAGE, // limit
2515 1, // seg_32bit
2516 0, // contents: data, RW, non-expanding
2517 0, // ! read_exec_only
2518 1, // limit_in_pages
2519 0, // ! seg not present
2520 1, // useable
fitzhardinge98abfc72003-12-16 02:05:15 +00002521 };
nethercote71980f02004-01-24 18:18:54 +00002522 ret = VG_(do_syscall)(__NR_modify_ldt, 1, &ldt, sizeof(ldt));
fitzhardinge98abfc72003-12-16 02:05:15 +00002523 if (ret < 0) {
2524 VG_(message)(Vg_UserMsg,
2525 "Warning: ignoring --pointercheck=yes, "
2526 "because modify_ldt failed (errno=%d)", -ret);
2527 VG_(clo_pointercheck) = False;
2528 }
2529 }
sewardjde4a1d02002-03-22 01:27:54 +00002530}
2531
nethercote71980f02004-01-24 18:18:54 +00002532/*====================================================================*/
2533/*=== Initialise program data/text, etc. ===*/
2534/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +00002535
nethercote71980f02004-01-24 18:18:54 +00002536static void build_valgrind_map_callback
2537 ( Addr start, UInt size, Char rr, Char ww, Char xx,
2538 UInt dev, UInt ino, ULong foffset, const UChar* filename )
sewardjde4a1d02002-03-22 01:27:54 +00002539{
nethercote71980f02004-01-24 18:18:54 +00002540 UInt prot = 0;
2541 UInt flags = SF_MMAP|SF_NOSYMS;
2542 Bool is_stack_segment;
2543
2544 is_stack_segment =
2545 (start == VG_(clstk_base) && (start+size) == VG_(clstk_end));
2546
2547 /* Only record valgrind mappings for now, without loading any
2548 symbols. This is so we know where the free space is before we
2549 start allocating more memory (note: heap is OK, it's just mmap
2550 which is the problem here). */
2551 if (start >= VG_(valgrind_base) && (start+size) <= VG_(valgrind_end)) {
2552 flags |= SF_VALGRIND;
2553 VG_(map_file_segment)(start, size, prot, flags, dev, ino, foffset, filename);
2554 }
sewardjde4a1d02002-03-22 01:27:54 +00002555}
2556
nethercote71980f02004-01-24 18:18:54 +00002557// Global var used to pass local data to callback
2558Addr esp_at_startup___global_arg = 0;
sewardjde4a1d02002-03-22 01:27:54 +00002559
nethercote71980f02004-01-24 18:18:54 +00002560static void build_segment_map_callback
2561 ( Addr start, UInt size, Char rr, Char ww, Char xx,
2562 UInt dev, UInt ino, ULong foffset, const UChar* filename )
sewardj45b672d2003-07-25 19:58:11 +00002563{
nethercote71980f02004-01-24 18:18:54 +00002564 UInt prot = 0;
2565 UInt flags;
2566 Bool is_stack_segment;
2567 Addr r_esp;
sewardj45b672d2003-07-25 19:58:11 +00002568
nethercote71980f02004-01-24 18:18:54 +00002569 is_stack_segment
2570 = (start == VG_(clstk_base) && (start+size) == VG_(clstk_end));
fitzhardinge98abfc72003-12-16 02:05:15 +00002571
nethercote71980f02004-01-24 18:18:54 +00002572 if (rr == 'r') prot |= VKI_PROT_READ;
2573 if (ww == 'w') prot |= VKI_PROT_WRITE;
2574 if (xx == 'x') prot |= VKI_PROT_EXEC;
fitzhardinge98abfc72003-12-16 02:05:15 +00002575
nethercote71980f02004-01-24 18:18:54 +00002576 if (is_stack_segment)
2577 flags = SF_STACK | SF_GROWDOWN;
2578 else
2579 flags = SF_EXEC|SF_MMAP;
fitzhardinge98abfc72003-12-16 02:05:15 +00002580
nethercote71980f02004-01-24 18:18:54 +00002581 if (filename != NULL)
2582 flags |= SF_FILE;
fitzhardinge98abfc72003-12-16 02:05:15 +00002583
nethercote71980f02004-01-24 18:18:54 +00002584 if (start >= VG_(valgrind_base) && (start+size) <= VG_(valgrind_end))
2585 flags |= SF_VALGRIND;
fitzhardinge98abfc72003-12-16 02:05:15 +00002586
nethercote71980f02004-01-24 18:18:54 +00002587 VG_(map_file_segment)(start, size, prot, flags, dev, ino, foffset, filename);
fitzhardinge98abfc72003-12-16 02:05:15 +00002588
nethercote71980f02004-01-24 18:18:54 +00002589 if (VG_(is_client_addr)(start) && VG_(is_client_addr)(start+size-1))
2590 VG_TRACK( new_mem_startup, start, size, rr=='r', ww=='w', xx=='x' );
sewardj3e1eb1f2002-05-18 13:14:17 +00002591
nethercote71980f02004-01-24 18:18:54 +00002592 /* If this is the stack segment mark all below %esp as noaccess. */
2593 r_esp = esp_at_startup___global_arg;
2594 vg_assert(0 != r_esp);
2595 if (is_stack_segment) {
2596 if (0)
2597 VG_(message)(Vg_DebugMsg, "invalidating stack area: %x .. %x",
2598 start,r_esp);
2599 VG_TRACK( die_mem_stack, start, r_esp-start );
sewardjde4a1d02002-03-22 01:27:54 +00002600 }
sewardjde4a1d02002-03-22 01:27:54 +00002601}
2602
2603
nethercote71980f02004-01-24 18:18:54 +00002604/*====================================================================*/
2605/*=== Sanity check machinery (permanently engaged) ===*/
2606/*====================================================================*/
njn25e49d8e72002-09-23 09:36:25 +00002607
2608/* A fast sanity check -- suitable for calling circa once per
2609 millisecond. */
2610
nethercote885dd912004-08-03 23:14:00 +00002611void VG_(sanity_check_general) ( Bool force_expensive )
njn25e49d8e72002-09-23 09:36:25 +00002612{
njn37cea302002-09-30 11:24:00 +00002613 VGP_PUSHCC(VgpCoreCheapSanity);
2614
nethercote27fec902004-06-16 21:26:32 +00002615 if (VG_(clo_sanity_level) < 1) return;
njn25e49d8e72002-09-23 09:36:25 +00002616
2617 /* --- First do all the tests that we can do quickly. ---*/
2618
nethercote297effd2004-08-02 15:07:57 +00002619 sanity_fast_count++;
njn25e49d8e72002-09-23 09:36:25 +00002620
njn25e49d8e72002-09-23 09:36:25 +00002621 /* Check stuff pertaining to the memory check system. */
2622
2623 /* Check that nobody has spuriously claimed that the first or
2624 last 16 pages of memory have become accessible [...] */
njn37cea302002-09-30 11:24:00 +00002625 if (VG_(needs).sanity_checks) {
2626 VGP_PUSHCC(VgpSkinCheapSanity);
njn25e49d8e72002-09-23 09:36:25 +00002627 vg_assert(SK_(cheap_sanity_check)());
njn37cea302002-09-30 11:24:00 +00002628 VGP_POPCC(VgpSkinCheapSanity);
2629 }
njn25e49d8e72002-09-23 09:36:25 +00002630
2631 /* --- Now some more expensive checks. ---*/
2632
2633 /* Once every 25 times, check some more expensive stuff. */
2634 if ( force_expensive
nethercote27fec902004-06-16 21:26:32 +00002635 || VG_(clo_sanity_level) > 1
nethercote297effd2004-08-02 15:07:57 +00002636 || (VG_(clo_sanity_level) == 1 && (sanity_fast_count % 25) == 0)) {
njn25e49d8e72002-09-23 09:36:25 +00002637
njn37cea302002-09-30 11:24:00 +00002638 VGP_PUSHCC(VgpCoreExpensiveSanity);
nethercote297effd2004-08-02 15:07:57 +00002639 sanity_slow_count++;
njn25e49d8e72002-09-23 09:36:25 +00002640
nethercote885dd912004-08-03 23:14:00 +00002641 VG_(sanity_check_proxy)();
jsgf855d93d2003-10-13 22:26:55 +00002642
njn25e49d8e72002-09-23 09:36:25 +00002643# if 0
2644 { void zzzmemscan(void); zzzmemscan(); }
2645# endif
2646
nethercote297effd2004-08-02 15:07:57 +00002647 if ((sanity_fast_count % 250) == 0)
nethercote92e7b7f2004-08-07 17:52:25 +00002648 VG_(sanity_check_tt_tc)();
njn25e49d8e72002-09-23 09:36:25 +00002649
2650 if (VG_(needs).sanity_checks) {
njn37cea302002-09-30 11:24:00 +00002651 VGP_PUSHCC(VgpSkinExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002652 vg_assert(SK_(expensive_sanity_check)());
njn37cea302002-09-30 11:24:00 +00002653 VGP_POPCC(VgpSkinExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002654 }
2655 /*
nethercote297effd2004-08-02 15:07:57 +00002656 if ((sanity_fast_count % 500) == 0) VG_(mallocSanityCheckAll)();
njn25e49d8e72002-09-23 09:36:25 +00002657 */
njn37cea302002-09-30 11:24:00 +00002658 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002659 }
2660
nethercote27fec902004-06-16 21:26:32 +00002661 if (VG_(clo_sanity_level) > 1) {
njn37cea302002-09-30 11:24:00 +00002662 VGP_PUSHCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002663 /* Check sanity of the low-level memory manager. Note that bugs
2664 in the client's code can cause this to fail, so we don't do
2665 this check unless specially asked for. And because it's
2666 potentially very expensive. */
nethercote885dd912004-08-03 23:14:00 +00002667 VG_(sanity_check_malloc_all)();
njn37cea302002-09-30 11:24:00 +00002668 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002669 }
njn37cea302002-09-30 11:24:00 +00002670 VGP_POPCC(VgpCoreCheapSanity);
njn25e49d8e72002-09-23 09:36:25 +00002671}
nethercote71980f02004-01-24 18:18:54 +00002672
2673
2674/*====================================================================*/
2675/*=== main() ===*/
2676/*====================================================================*/
2677
nethercotec314eba2004-07-15 12:59:41 +00002678/*
2679 This code decides on the layout of the client and Valgrind address
nethercote996901a2004-08-03 13:29:09 +00002680 spaces, loads valgrind.so and the tool.so into the valgrind part,
nethercotec314eba2004-07-15 12:59:41 +00002681 loads the client executable (and the dynamic linker, if necessary)
2682 into the client part, and calls into Valgrind proper.
2683
2684 The code is careful not to allow spurious mappings to appear in the
2685 wrong parts of the address space. In particular, to make sure
2686 dlopen puts things in the right place, it will pad out the forbidden
2687 chunks of address space so that dlopen is forced to put things where
2688 we want them.
2689
2690 The memory map it creates is:
2691
2692 CLIENT_BASE +-------------------------+
2693 | client address space |
2694 : :
2695 : :
2696 | client stack |
2697 client_end +-------------------------+
2698 | redzone |
2699 shadow_base +-------------------------+
2700 | |
nethercote996901a2004-08-03 13:29:09 +00002701 : shadow memory for tools :
nethercotec314eba2004-07-15 12:59:41 +00002702 | (may be 0 sized) |
2703 shadow_end +-------------------------+
2704 : gap (may be 0 sized) :
2705 valgrind_base +-------------------------+
2706 | kickstart executable |
2707 | valgrind heap vvvvvvvvv| (barely used)
2708 - -
2709 | valgrind .so files |
2710 | and mappings |
2711 - -
2712 | valgrind stack ^^^^^^^^^|
2713 valgrind_end +-------------------------+
2714 : kernel :
2715
2716 Nb: Before we can do general allocations with VG_(arena_malloc)() and
2717 VG_(mmap)(), we need to build the segment skip-list, so we know where
2718 we can put things. However, building that structure requires
2719 allocating memory. So we need to a bootstrapping process. It's done
2720 by making VG_(arena_malloc)() have a special static superblock that's
2721 used for the first 1MB's worth of allocations. This is enough to
2722 build the segment skip-list.
2723*/
2724
nethercote31779c72004-07-30 21:50:15 +00002725static int prmap(char *start, char *end, const char *perm, off_t off,
2726 int maj, int min, int ino, void* dummy) {
thughes4ad52d02004-06-27 17:37:21 +00002727 printf("mapping %10p-%10p %s %02x:%02x %d\n",
2728 start, end, perm, maj, min, ino);
2729 return True;
2730}
2731
nethercote71980f02004-01-24 18:18:54 +00002732int main(int argc, char **argv)
2733{
2734 char **cl_argv;
2735 const char *tool = NULL;
2736 const char *exec = NULL;
2737 char *preload; /* tool-specific LD_PRELOAD .so */
2738 char **env;
nethercote6c999f22004-01-31 22:55:15 +00002739 Int need_help = 0; // 0 = no, 1 = --help, 2 = --help-debug
nethercote71980f02004-01-24 18:18:54 +00002740 struct exeinfo info;
2741 ToolInfo *toolinfo = NULL;
2742 void *tool_dlhandle;
2743 Addr client_eip;
2744 Addr esp_at_startup; /* client's %esp at the point we gained control. */
2745 UInt * client_auxv;
2746 VgSchedReturnCode src;
nethercote47dd12c2004-06-22 14:18:42 +00002747 Int exitcode = 0;
nethercote238a3c32004-08-09 13:13:31 +00002748 Int fatal_sigNo = -1;
fitzhardingeb50068f2004-02-24 23:42:55 +00002749 vki_rlimit zero = { 0, 0 };
nethercote31779c72004-07-30 21:50:15 +00002750 Int padfile;
nethercote759dda32004-08-07 18:16:56 +00002751 ThreadId last_run_tid = 0; // Last thread the scheduler ran.
2752
nethercote71980f02004-01-24 18:18:54 +00002753
2754 //============================================================
2755 // Nb: startup is complex. Prerequisites are shown at every step.
2756 //
2757 // *** Be very careful when messing with the order ***
2758 //============================================================
2759
nethercotef4928da2004-06-15 10:54:40 +00002760 //============================================================
2761 // Command line argument handling order:
2762 // * If --help/--help-debug are present, show usage message
2763 // (if --tool is also present, that includes the tool-specific usage)
2764 // * Then, if --tool is missing, abort with error msg
2765 // * Then, if client is missing, abort with error msg
2766 // * Then, if any cmdline args are bad, abort with error msg
2767 //============================================================
2768
fitzhardingeb50068f2004-02-24 23:42:55 +00002769 // Get the current process datasize rlimit, and set it to zero.
2770 // This prevents any internal uses of brk() from having any effect.
2771 // We remember the old value so we can restore it on exec, so that
2772 // child processes will have a reasonable brk value.
2773 VG_(getrlimit)(VKI_RLIMIT_DATA, &VG_(client_rlimit_data));
2774 zero.rlim_max = VG_(client_rlimit_data).rlim_max;
2775 VG_(setrlimit)(VKI_RLIMIT_DATA, &zero);
2776
nethercote71980f02004-01-24 18:18:54 +00002777 //--------------------------------------------------------------
2778 // Check we were launched by stage1
nethercotec314eba2004-07-15 12:59:41 +00002779 // p: n/a
nethercote71980f02004-01-24 18:18:54 +00002780 //--------------------------------------------------------------
nethercote31779c72004-07-30 21:50:15 +00002781 padfile = scan_auxv();
nethercote71980f02004-01-24 18:18:54 +00002782
2783 if (0) {
nethercote71980f02004-01-24 18:18:54 +00002784 printf("========== main() ==========\n");
nethercote31779c72004-07-30 21:50:15 +00002785 foreach_map(prmap, /*dummy*/NULL);
nethercote71980f02004-01-24 18:18:54 +00002786 }
2787
2788 //--------------------------------------------------------------
2789 // Look for alternative libdir
2790 // p: n/a
2791 //--------------------------------------------------------------
2792 { char *cp = getenv(VALGRINDLIB);
2793 if (cp != NULL)
2794 VG_(libdir) = cp;
2795 }
2796
2797 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002798 // Get valgrind args + client args (inc. from VALGRIND_OPTS/.valgrindrc).
2799 // Pre-process the command line.
2800 // p: n/a
2801 //--------------------------------------------------------------
nethercotef6a1d502004-08-09 12:21:57 +00002802 get_command_line(argc, argv, &vg_argc, &vg_argv, &cl_argv);
nethercote71980f02004-01-24 18:18:54 +00002803 pre_process_cmd_line_options(&need_help, &tool, &exec);
2804
2805 //==============================================================
2806 // Nb: once a tool is specified, the tool.so must be loaded even if
2807 // they specified --help or didn't specify a client program.
2808 //==============================================================
2809
2810 //--------------------------------------------------------------
2811 // With client padded out, map in tool
nethercote71980f02004-01-24 18:18:54 +00002812 // p: set-libdir [for VG_(libdir)]
2813 // p: pre_process_cmd_line_options() [for 'tool']
2814 //--------------------------------------------------------------
2815 load_tool(tool, &tool_dlhandle, &toolinfo, &preload);
2816
2817 //==============================================================
2818 // Can use VG_(malloc)() and VG_(arena_malloc)() only after load_tool()
nethercotec314eba2004-07-15 12:59:41 +00002819 // -- redzone size is now set. This is checked by vg_malloc2.c.
nethercote71980f02004-01-24 18:18:54 +00002820 //==============================================================
2821
2822 //--------------------------------------------------------------
2823 // Finalise address space layout
nethercote31779c72004-07-30 21:50:15 +00002824 // p: load_tool() [for 'toolinfo']
nethercote71980f02004-01-24 18:18:54 +00002825 //--------------------------------------------------------------
nethercote31779c72004-07-30 21:50:15 +00002826 layout_remaining_space( (Addr) & argc, toolinfo->shadow_ratio );
nethercote71980f02004-01-24 18:18:54 +00002827
2828 //--------------------------------------------------------------
2829 // Load client executable, finding in $PATH if necessary
nethercote71980f02004-01-24 18:18:54 +00002830 // p: pre_process_cmd_line_options() [for 'exec', 'need_help']
2831 // p: layout_remaining_space [so there's space]
2832 //--------------------------------------------------------------
nethercotef4928da2004-06-15 10:54:40 +00002833 load_client(cl_argv, exec, need_help, &info, &client_eip);
nethercote71980f02004-01-24 18:18:54 +00002834
2835 //--------------------------------------------------------------
2836 // Everything in place, unpad us
2837 // p: layout_remaining_space() [everything must be mapped in before now]
2838 // p: load_client() [ditto]
2839 //--------------------------------------------------------------
nethercote31779c72004-07-30 21:50:15 +00002840 as_unpad((void *)VG_(shadow_end), (void *)~0, padfile);
2841 as_closepadfile(padfile); // no more padding
nethercote71980f02004-01-24 18:18:54 +00002842
2843 //--------------------------------------------------------------
2844 // Set up client's environment
2845 // p: set-libdir [for VG_(libdir)]
2846 // p: load_tool() [for 'preload']
2847 //--------------------------------------------------------------
2848 env = fix_environment(environ, preload);
2849
2850 //--------------------------------------------------------------
nethercote5ee67ca2004-06-22 14:00:09 +00002851 // Setup client stack, eip, and VG_(client_arg[cv])
nethercote71980f02004-01-24 18:18:54 +00002852 // p: load_client() [for 'info']
2853 // p: fix_environment() [for 'env']
2854 //--------------------------------------------------------------
2855 esp_at_startup = setup_client_stack(cl_argv, env, &info, &client_auxv);
2856
2857 if (0)
2858 printf("entry=%x client esp=%x vg_argc=%d brkbase=%x\n",
nethercotef6a1d502004-08-09 12:21:57 +00002859 client_eip, esp_at_startup, vg_argc, VG_(brk_base));
nethercote71980f02004-01-24 18:18:54 +00002860
2861 //==============================================================
2862 // Finished setting up operating environment. Now initialise
2863 // Valgrind. (This is where the old VG_(main)() started.)
2864 //==============================================================
2865
2866 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002867 // atfork
2868 // p: n/a
2869 //--------------------------------------------------------------
2870 VG_(atfork)(NULL, NULL, newpid);
2871 newpid(VG_INVALID_THREADID);
2872
2873 //--------------------------------------------------------------
2874 // setup file descriptors
2875 // p: n/a
2876 //--------------------------------------------------------------
2877 setup_file_descriptors();
2878
2879 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002880 // Read /proc/self/maps into a buffer
2881 // p: all memory layout, environment setup [so memory maps are right]
2882 //--------------------------------------------------------------
2883 VG_(read_procselfmaps)();
2884
2885 //--------------------------------------------------------------
2886 // Build segment map (Valgrind segments only)
2887 // p: read proc/self/maps
2888 // p: sk_pre_clo_init() [to setup new_mem_startup tracker]
2889 //--------------------------------------------------------------
2890 VG_(parse_procselfmaps) ( build_valgrind_map_callback );
2891
2892 //==============================================================
2893 // Can use VG_(arena_malloc)() with non-CORE arena after segments set up
2894 //==============================================================
2895
2896 //--------------------------------------------------------------
2897 // Init tool: pre_clo_init, process cmd line, post_clo_init
2898 // p: setup_client_stack() [for 'VG_(client_arg[cv]']
2899 // p: load_tool() [for 'tool']
2900 // p: setup_file_descriptors() [for 'VG_(fd_xxx_limit)']
2901 // p: parse_procselfmaps [so VG segments are setup so tool can
2902 // call VG_(malloc)]
nethercote71980f02004-01-24 18:18:54 +00002903 //--------------------------------------------------------------
2904 (*toolinfo->sk_pre_clo_init)();
2905 VG_(tool_init_dlsym)(tool_dlhandle);
2906 VG_(sanity_check_needs)();
2907
nethercotef4928da2004-06-15 10:54:40 +00002908 // If --tool and --help/--help-debug was given, now give the core+tool
2909 // help message
nethercotef4928da2004-06-15 10:54:40 +00002910 if (need_help) {
2911 usage(/*--help-debug?*/2 == need_help);
2912 }
nethercotec314eba2004-07-15 12:59:41 +00002913 process_cmd_line_options(client_auxv, tool);
2914
2915 SK_(post_clo_init)();
nethercotef4928da2004-06-15 10:54:40 +00002916
2917 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002918 // Build segment map (all segments)
2919 // p: setup_client_stack() [for 'esp_at_startup']
2920 // p: init tool [for 'new_mem_startup']
nethercote71980f02004-01-24 18:18:54 +00002921 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002922 esp_at_startup___global_arg = esp_at_startup;
2923 VG_(parse_procselfmaps) ( build_segment_map_callback ); /* everything */
2924 esp_at_startup___global_arg = 0;
2925
2926 //--------------------------------------------------------------
nethercotef84f6952004-07-15 14:58:33 +00002927 // Protect client trampoline page (which is also sysinfo stuff)
2928 // p: segment stuff [otherwise get seg faults...]
nethercotec314eba2004-07-15 12:59:41 +00002929 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002930 VG_(mprotect)( (void *)VG_(client_trampoline_code),
2931 VG_(trampoline_code_length), VKI_PROT_READ|VKI_PROT_EXEC );
2932
2933 //==============================================================
2934 // Can use VG_(map)() after segments set up
2935 //==============================================================
nethercote71980f02004-01-24 18:18:54 +00002936
2937 //--------------------------------------------------------------
2938 // Allow GDB attach
2939 // p: process_cmd_line_options() [for VG_(clo_wait_for_gdb)]
2940 //--------------------------------------------------------------
2941 /* Hook to delay things long enough so we can get the pid and
2942 attach GDB in another shell. */
2943 if (VG_(clo_wait_for_gdb)) {
2944 VG_(printf)("pid=%d\n", VG_(getpid)());
2945 /* do "jump *$eip" to skip this in gdb */
2946 VG_(do_syscall)(__NR_pause);
2947 }
2948
2949 //--------------------------------------------------------------
nethercote1d447092004-02-01 17:29:59 +00002950 // Set up baseBlock
nethercote71980f02004-01-24 18:18:54 +00002951 // p: {pre,post}_clo_init() [for tool helper registration]
2952 // load_client() [for 'client_eip']
2953 // setup_client_stack() [for 'esp_at_startup']
2954 //--------------------------------------------------------------
2955 init_baseBlock(client_eip, esp_at_startup);
2956
2957 //--------------------------------------------------------------
2958 // Search for file descriptors that are inherited from our parent
2959 // p: process_cmd_line_options [for VG_(clo_track_fds)]
2960 //--------------------------------------------------------------
2961 if (VG_(clo_track_fds))
2962 VG_(init_preopened_fds)();
2963
2964 //--------------------------------------------------------------
2965 // Initialise the scheduler
2966 // p: init_baseBlock() [baseBlock regs copied into VG_(threads)[1]]
2967 // p: setup_file_descriptors() [else VG_(safe_fd)() breaks]
2968 //--------------------------------------------------------------
2969 VG_(scheduler_init)();
2970
2971 //--------------------------------------------------------------
2972 // Set up the ProxyLWP machinery
2973 // p: VG_(scheduler_init)()? [XXX: subtle dependency?]
nethercote71980f02004-01-24 18:18:54 +00002974 //--------------------------------------------------------------
2975 VG_(proxy_init)();
2976
2977 //--------------------------------------------------------------
2978 // Initialise the signal handling subsystem
2979 // p: VG_(atfork)(NULL, NULL, newpid) [else problems with sigmasks]
2980 // p: VG_(proxy_init)() [else breaks...]
2981 //--------------------------------------------------------------
2982 // Nb: temporarily parks the saved blocking-mask in saved_sigmask.
2983 VG_(sigstartup_actions)();
2984
2985 //--------------------------------------------------------------
2986 // Perhaps we're profiling Valgrind?
2987 // p: process_cmd_line_options() [for VG_(clo_profile)]
2988 // p: others?
2989 //
2990 // XXX: this seems to be broken? It always says the tool wasn't built
2991 // for profiling; vg_profile.c's functions don't seem to be overriding
2992 // vg_dummy_profile.c's?
2993 //
2994 // XXX: want this as early as possible. Looking for --profile
2995 // in pre_process_cmd_line_options() could get it earlier.
2996 //--------------------------------------------------------------
2997 if (VG_(clo_profile))
2998 VGP_(init_profiling)();
2999
3000 VGP_PUSHCC(VgpStartup);
3001
3002 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00003003 // Read suppression file
3004 // p: process_cmd_line_options() [for VG_(clo_suppressions)]
3005 //--------------------------------------------------------------
3006 if (VG_(needs).core_errors || VG_(needs).skin_errors)
3007 VG_(load_suppressions)();
3008
3009 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00003010 // Initialise translation table and translation cache
3011 // p: read_procselfmaps [so the anonymous mmaps for the TT/TC
3012 // aren't identified as part of the client, which would waste
3013 // > 20M of virtual address space.]
3014 //--------------------------------------------------------------
3015 VG_(init_tt_tc)();
3016
3017 //--------------------------------------------------------------
3018 // Read debug info to find glibc entry points to intercept
3019 // p: parse_procselfmaps? [XXX for debug info?]
3020 // p: init_tt_tc? [XXX ???]
3021 //--------------------------------------------------------------
3022 VG_(setup_code_redirect_table)();
3023
3024 //--------------------------------------------------------------
3025 // Verbosity message
3026 // p: end_rdtsc_calibration [so startup message is printed first]
3027 //--------------------------------------------------------------
3028 if (VG_(clo_verbosity) == 1)
3029 VG_(message)(Vg_UserMsg, "For more details, rerun with: -v");
3030 if (VG_(clo_verbosity) > 0)
3031 VG_(message)(Vg_UserMsg, "");
3032
3033 //--------------------------------------------------------------
3034 // Setup pointercheck
3035 // p: process_cmd_line_options() [for VG_(clo_pointercheck)]
3036 //--------------------------------------------------------------
3037 setup_pointercheck();
3038
nethercote71980f02004-01-24 18:18:54 +00003039 //--------------------------------------------------------------
3040 // Run!
3041 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00003042 VGP_POPCC(VgpStartup);
3043 VGP_PUSHCC(VgpSched);
3044
nethercote238a3c32004-08-09 13:13:31 +00003045 src = VG_(scheduler)( &exitcode, &last_run_tid, &fatal_sigNo );
nethercote71980f02004-01-24 18:18:54 +00003046
nethercote238a3c32004-08-09 13:13:31 +00003047 VGP_POPCC(VgpSched);
nethercote71980f02004-01-24 18:18:54 +00003048
3049
3050 //--------------------------------------------------------------
3051 // Finalisation: cleanup, messages, etc. Order no so important, only
3052 // affects what order the messages come.
3053 //--------------------------------------------------------------
3054 if (VG_(clo_verbosity) > 0)
3055 VG_(message)(Vg_UserMsg, "");
3056
3057 if (src == VgSrc_Deadlock) {
3058 VG_(message)(Vg_UserMsg,
3059 "Warning: pthread scheduler exited due to deadlock");
3060 }
3061
3062 /* Print out file descriptor summary and stats. */
3063 if (VG_(clo_track_fds))
nethercote3a42fb82004-08-03 18:08:50 +00003064 VG_(show_open_fds)();
nethercote71980f02004-01-24 18:18:54 +00003065
3066 if (VG_(needs).core_errors || VG_(needs).skin_errors)
3067 VG_(show_all_errors)();
3068
nethercote47dd12c2004-06-22 14:18:42 +00003069 SK_(fini)( exitcode );
nethercote71980f02004-01-24 18:18:54 +00003070
nethercote885dd912004-08-03 23:14:00 +00003071 VG_(sanity_check_general)( True /*include expensive checks*/ );
nethercote71980f02004-01-24 18:18:54 +00003072
3073 if (VG_(clo_verbosity) > 1)
nethercote3a42fb82004-08-03 18:08:50 +00003074 print_all_stats();
nethercote71980f02004-01-24 18:18:54 +00003075
nethercote71980f02004-01-24 18:18:54 +00003076 if (VG_(clo_profile))
3077 VGP_(done_profiling)();
3078
nethercote71980f02004-01-24 18:18:54 +00003079 /* We're exiting, so nuke all the threads and clean up the proxy LWPs */
3080 vg_assert(src == VgSrc_FatalSig ||
nethercote759dda32004-08-07 18:16:56 +00003081 VG_(threads)[last_run_tid].status == VgTs_Runnable ||
3082 VG_(threads)[last_run_tid].status == VgTs_WaitJoiner);
nethercote71980f02004-01-24 18:18:54 +00003083 VG_(nuke_all_threads_except)(VG_INVALID_THREADID);
3084
3085 //--------------------------------------------------------------
3086 // Exit, according to the scheduler's return code
3087 //--------------------------------------------------------------
3088 switch (src) {
3089 case VgSrc_ExitSyscall: /* the normal way out */
nethercote759dda32004-08-07 18:16:56 +00003090 vg_assert(last_run_tid > 0 && last_run_tid < VG_N_THREADS);
nethercote71980f02004-01-24 18:18:54 +00003091 VG_(proxy_shutdown)();
3092
3093 /* The thread's %EBX at the time it did __NR_exit() will hold
3094 the arg to __NR_exit(), so we just do __NR_exit() with
3095 that arg. */
nethercote47dd12c2004-06-22 14:18:42 +00003096 VG_(exit)( exitcode );
nethercote71980f02004-01-24 18:18:54 +00003097 /* NOT ALIVE HERE! */
3098 VG_(core_panic)("entered the afterlife in main() -- ExitSyscall");
3099 break; /* what the hell :) */
3100
3101 case VgSrc_Deadlock:
3102 /* Just exit now. No point in continuing. */
3103 VG_(proxy_shutdown)();
3104 VG_(exit)(0);
3105 VG_(core_panic)("entered the afterlife in main() -- Deadlock");
3106 break;
3107
nethercote71980f02004-01-24 18:18:54 +00003108 case VgSrc_FatalSig:
3109 /* We were killed by a fatal signal, so replicate the effect */
nethercote238a3c32004-08-09 13:13:31 +00003110 vg_assert(fatal_sigNo != -1);
3111 VG_(kill_self)(fatal_sigNo);
nethercote71980f02004-01-24 18:18:54 +00003112 VG_(core_panic)("main(): signal was supposed to be fatal");
3113 break;
3114
3115 default:
3116 VG_(core_panic)("main(): unexpected scheduler return code");
3117 }
3118
3119 abort();
3120}
3121
3122
sewardjde4a1d02002-03-22 01:27:54 +00003123/*--------------------------------------------------------------------*/
3124/*--- end vg_main.c ---*/
3125/*--------------------------------------------------------------------*/