blob: c7b81549bf1e44869898b072e96c428fc015a3d0 [file] [log] [blame]
sewardjde4a1d02002-03-22 01:27:54 +00001
2/*--------------------------------------------------------------------*/
nethercote71980f02004-01-24 18:18:54 +00003/*--- Startup: the real stuff vg_main.c ---*/
sewardjde4a1d02002-03-22 01:27:54 +00004/*--------------------------------------------------------------------*/
5
6/*
njnc9539842002-10-02 13:26:35 +00007 This file is part of Valgrind, an extensible x86 protected-mode
8 emulator for monitoring program execution on x86-Unixes.
sewardjde4a1d02002-03-22 01:27:54 +00009
nethercotebb1c9912004-01-04 16:43:23 +000010 Copyright (C) 2000-2004 Julian Seward
sewardjde4a1d02002-03-22 01:27:54 +000011 jseward@acm.org
sewardjde4a1d02002-03-22 01:27:54 +000012
13 This program is free software; you can redistribute it and/or
14 modify it under the terms of the GNU General Public License as
15 published by the Free Software Foundation; either version 2 of the
16 License, or (at your option) any later version.
17
18 This program is distributed in the hope that it will be useful, but
19 WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 General Public License for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software
25 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
26 02111-1307, USA.
27
njn25e49d8e72002-09-23 09:36:25 +000028 The GNU General Public License is contained in the file COPYING.
sewardjde4a1d02002-03-22 01:27:54 +000029*/
30
nethercote71980f02004-01-24 18:18:54 +000031#define _FILE_OFFSET_BITS 64
sewardjde4a1d02002-03-22 01:27:54 +000032
nethercotef1e5e152004-09-01 23:58:16 +000033#include "core.h"
nethercote71980f02004-01-24 18:18:54 +000034#include "ume.h"
35#include "ume_arch.h"
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 */
rjwalsh18b66312004-08-23 18:15:12 +0000111
112// VG_(valgrind_end) has a slightly different meaning to all the other
113// VG_(*_end) vars -- ie. it names the last byte, whereas the others
114// go one byte past the end.
115
fitzhardinge98abfc72003-12-16 02:05:15 +0000116Addr VG_(valgrind_end);
117
fitzhardingeb50068f2004-02-24 23:42:55 +0000118vki_rlimit VG_(client_rlimit_data);
119
nethercote71980f02004-01-24 18:18:54 +0000120/* This is set early to indicate whether this CPU has the
121 SSE/fxsave/fxrestor features. */
122Bool VG_(have_ssestate);
123
fitzhardinge98abfc72003-12-16 02:05:15 +0000124/* stage1 (main) executable */
nethercotef6a1d502004-08-09 12:21:57 +0000125static Int vgexecfd = -1;
fitzhardingea49f9b52003-12-16 22:26:45 +0000126
127/* client executable */
128Int VG_(clexecfd) = -1;
fitzhardinge98abfc72003-12-16 02:05:15 +0000129
130/* Path to library directory */
131const Char *VG_(libdir) = VG_LIBDIR;
132
133/* our argc/argv */
nethercotef6a1d502004-08-09 12:21:57 +0000134static Int vg_argc;
135static Char **vg_argv;
fitzhardinge98abfc72003-12-16 02:05:15 +0000136
jsgf855d93d2003-10-13 22:26:55 +0000137/* PID of the main thread */
138Int VG_(main_pid);
139
140/* PGRP of process */
141Int VG_(main_pgrp);
njn25e49d8e72002-09-23 09:36:25 +0000142
thughesad1c9562004-06-26 11:27:52 +0000143/* Application-visible file descriptor limits */
144Int VG_(fd_soft_limit) = -1;
145Int VG_(fd_hard_limit) = -1;
fitzhardingef0046f22003-12-18 02:39:22 +0000146
nethercote71980f02004-01-24 18:18:54 +0000147/* As deduced from esp_at_startup, the client's argc, argv[] and
148 envp[] as extracted from the client's stack at startup-time. */
149Int VG_(client_argc);
150Char** VG_(client_argv);
151Char** VG_(client_envp);
sewardjde4a1d02002-03-22 01:27:54 +0000152
153/* ---------------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +0000154 Running stuff
sewardjde4a1d02002-03-22 01:27:54 +0000155 ------------------------------------------------------------------ */
sewardjde4a1d02002-03-22 01:27:54 +0000156
nethercote71980f02004-01-24 18:18:54 +0000157/* Counts downwards in VG_(run_innerloop). */
158UInt VG_(dispatch_ctr);
sewardjde4a1d02002-03-22 01:27:54 +0000159
160/* 64-bit counter for the number of basic blocks done. */
161ULong VG_(bbs_done);
sewardjde4a1d02002-03-22 01:27:54 +0000162
nethercote71980f02004-01-24 18:18:54 +0000163/* Tell the logging mechanism whether we are logging to a file
164 descriptor or a socket descriptor. */
165Bool VG_(logging_to_filedes) = True;
166
sewardj73cf3bc2002-11-03 03:20:15 +0000167
nethercote71980f02004-01-24 18:18:54 +0000168/*====================================================================*/
169/*=== Counters, for profiling purposes only ===*/
170/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +0000171
nethercote92e7b7f2004-08-07 17:52:25 +0000172// These ones maintained by vg_dispatch.S
173UInt VG_(bb_enchain_count) = 0; // Number of chain operations done
174UInt VG_(bb_dechain_count) = 0; // Number of unchain operations done
175UInt VG_(unchained_jumps_done) = 0; // Number of unchained jumps done
sewardjde4a1d02002-03-22 01:27:54 +0000176
sewardjde4a1d02002-03-22 01:27:54 +0000177/* Counts pertaining to internal sanity checking. */
nethercote297effd2004-08-02 15:07:57 +0000178static UInt sanity_fast_count = 0;
179static UInt sanity_slow_count = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000180
nethercote3a42fb82004-08-03 18:08:50 +0000181static void print_all_stats ( void )
nethercote71980f02004-01-24 18:18:54 +0000182{
nethercote3a42fb82004-08-03 18:08:50 +0000183 // Translation stats
nethercote92e7b7f2004-08-07 17:52:25 +0000184 VG_(print_tt_tc_stats)();
nethercote71980f02004-01-24 18:18:54 +0000185 VG_(message)(Vg_DebugMsg,
nethercote92e7b7f2004-08-07 17:52:25 +0000186 "chainings: %d chainings, %d unchainings.",
nethercote71980f02004-01-24 18:18:54 +0000187 VG_(bb_enchain_count), VG_(bb_dechain_count) );
188 VG_(message)(Vg_DebugMsg,
nethercote3a42fb82004-08-03 18:08:50 +0000189 " dispatch: %llu jumps (bb entries); of them %u (%lu%%) unchained.",
nethercote71980f02004-01-24 18:18:54 +0000190 VG_(bbs_done),
191 VG_(unchained_jumps_done),
192 ((ULong)(100) * (ULong)(VG_(unchained_jumps_done)))
193 / ( VG_(bbs_done)==0 ? 1 : VG_(bbs_done) )
194 );
195
nethercote3a42fb82004-08-03 18:08:50 +0000196 // Scheduler stats
nethercote844e7122004-08-02 15:27:22 +0000197 VG_(print_scheduler_stats)();
nethercote71980f02004-01-24 18:18:54 +0000198
nethercote3a42fb82004-08-03 18:08:50 +0000199 // Reg-alloc stats
nethercotebee3fd92004-08-02 15:17:43 +0000200 VG_(print_reg_alloc_stats)();
nethercote71980f02004-01-24 18:18:54 +0000201 VG_(message)(Vg_DebugMsg,
202 " sanity: %d cheap, %d expensive checks.",
nethercote297effd2004-08-02 15:07:57 +0000203 sanity_fast_count, sanity_slow_count );
nethercote3a42fb82004-08-03 18:08:50 +0000204
205 // C call stats
nethercote71980f02004-01-24 18:18:54 +0000206 VG_(print_ccall_stats)();
nethercote3a42fb82004-08-03 18:08:50 +0000207
208 // UInstr histogram
209 if (VG_(clo_verbosity) > 3)
210 VG_(print_UInstr_histogram)();
211
212 // Memory stats
nethercote885dd912004-08-03 23:14:00 +0000213 if (VG_(clo_verbosity) > 2) {
nethercote3a42fb82004-08-03 18:08:50 +0000214 VG_(message)(Vg_DebugMsg, "");
215 VG_(message)(Vg_DebugMsg,
216 "------ Valgrind's internal memory use stats follow ------" );
nethercote885dd912004-08-03 23:14:00 +0000217 VG_(sanity_check_malloc_all)();
nethercote3a42fb82004-08-03 18:08:50 +0000218 VG_(print_all_arena_stats)();
nethercote885dd912004-08-03 23:14:00 +0000219 VG_(message)(Vg_DebugMsg, "");
nethercote3a42fb82004-08-03 18:08:50 +0000220 VG_(message)(Vg_DebugMsg,
221 "------ Valgrind's ExeContext management stats follow ------" );
222 VG_(print_ExeContext_stats)();
223 }
nethercote71980f02004-01-24 18:18:54 +0000224}
225
226
227/*====================================================================*/
228/*=== Miscellaneous global functions ===*/
229/*====================================================================*/
230
nethercote04d0fbc2004-01-26 16:48:06 +0000231/* Start debugger and get it to attach to this process. Called if the
232 user requests this service after an error has been shown, so she can
nethercote71980f02004-01-24 18:18:54 +0000233 poke around and look at parameters, memory, etc. You can't
nethercote04d0fbc2004-01-26 16:48:06 +0000234 meaningfully get the debugger to continue the program, though; to
235 continue, quit the debugger. */
236void VG_(start_debugger) ( Int tid )
nethercote71980f02004-01-24 18:18:54 +0000237{
238 Int pid;
239
240 if ((pid = fork()) == 0) {
241 ptrace(PTRACE_TRACEME, 0, NULL, NULL);
242 VG_(kkill)(VG_(getpid)(), VKI_SIGSTOP);
243
244 } else if (pid > 0) {
245 struct user_regs_struct regs;
246 Int status;
247 Int res;
248
249 if (VG_(is_running_thread)( tid )) {
fitzhardinged65dcad2004-03-13 02:06:58 +0000250 regs.cs = VG_(baseBlock)[VGOFF_(m_cs)];
251 regs.ss = VG_(baseBlock)[VGOFF_(m_ss)];
252 regs.ds = VG_(baseBlock)[VGOFF_(m_ds)];
253 regs.es = VG_(baseBlock)[VGOFF_(m_es)];
254 regs.fs = VG_(baseBlock)[VGOFF_(m_fs)];
255 regs.gs = VG_(baseBlock)[VGOFF_(m_gs)];
nethercote71980f02004-01-24 18:18:54 +0000256 regs.eax = VG_(baseBlock)[VGOFF_(m_eax)];
257 regs.ebx = VG_(baseBlock)[VGOFF_(m_ebx)];
258 regs.ecx = VG_(baseBlock)[VGOFF_(m_ecx)];
259 regs.edx = VG_(baseBlock)[VGOFF_(m_edx)];
260 regs.esi = VG_(baseBlock)[VGOFF_(m_esi)];
261 regs.edi = VG_(baseBlock)[VGOFF_(m_edi)];
262 regs.ebp = VG_(baseBlock)[VGOFF_(m_ebp)];
263 regs.esp = VG_(baseBlock)[VGOFF_(m_esp)];
264 regs.eflags = VG_(baseBlock)[VGOFF_(m_eflags)];
265 regs.eip = VG_(baseBlock)[VGOFF_(m_eip)];
266 } else {
267 ThreadState* tst = & VG_(threads)[ tid ];
268
fitzhardinged65dcad2004-03-13 02:06:58 +0000269 regs.cs = tst->m_cs;
270 regs.ss = tst->m_ss;
271 regs.ds = tst->m_ds;
272 regs.es = tst->m_es;
273 regs.fs = tst->m_fs;
274 regs.gs = tst->m_gs;
nethercote71980f02004-01-24 18:18:54 +0000275 regs.eax = tst->m_eax;
276 regs.ebx = tst->m_ebx;
277 regs.ecx = tst->m_ecx;
278 regs.edx = tst->m_edx;
279 regs.esi = tst->m_esi;
280 regs.edi = tst->m_edi;
281 regs.ebp = tst->m_ebp;
282 regs.esp = tst->m_esp;
283 regs.eflags = tst->m_eflags;
284 regs.eip = tst->m_eip;
285 }
286
287 if ((res = VG_(waitpid)(pid, &status, 0)) == pid &&
288 WIFSTOPPED(status) && WSTOPSIG(status) == SIGSTOP &&
289 ptrace(PTRACE_SETREGS, pid, NULL, &regs) == 0 &&
thughes1d160052004-04-21 15:39:57 +0000290 kill(pid, SIGSTOP) == 0 &&
291 ptrace(PTRACE_DETACH, pid, NULL, 0) == 0) {
nethercote04d0fbc2004-01-26 16:48:06 +0000292 Char pidbuf[15];
293 Char file[30];
294 Char buf[100];
295 Char *bufptr;
296 Char *cmdptr;
297
298 VG_(sprintf)(pidbuf, "%d", pid);
299 VG_(sprintf)(file, "/proc/%d/fd/%d", pid, VG_(clexecfd));
300
301 bufptr = buf;
302 cmdptr = VG_(clo_db_command);
303
304 while (*cmdptr) {
305 switch (*cmdptr) {
306 case '%':
307 switch (*++cmdptr) {
308 case 'f':
309 VG_(memcpy)(bufptr, file, VG_(strlen)(file));
310 bufptr += VG_(strlen)(file);
311 cmdptr++;
312 break;
313 case 'p':
314 VG_(memcpy)(bufptr, pidbuf, VG_(strlen)(pidbuf));
315 bufptr += VG_(strlen)(pidbuf);
316 cmdptr++;
317 break;
318 default:
319 *bufptr++ = *cmdptr++;
320 break;
321 }
322 break;
323 default:
324 *bufptr++ = *cmdptr++;
325 break;
326 }
327 }
328
329 *bufptr++ = '\0';
330
331 VG_(message)(Vg_UserMsg, "starting debugger with cmd: %s", buf);
nethercote71980f02004-01-24 18:18:54 +0000332 res = VG_(system)(buf);
333 if (res == 0) {
334 VG_(message)(Vg_UserMsg, "");
335 VG_(message)(Vg_UserMsg,
nethercote04d0fbc2004-01-26 16:48:06 +0000336 "Debugger has detached. Valgrind regains control. We continue.");
nethercote71980f02004-01-24 18:18:54 +0000337 } else {
338 VG_(message)(Vg_UserMsg, "Apparently failed!");
339 VG_(message)(Vg_UserMsg, "");
340 }
341 }
342
343 VG_(kkill)(pid, VKI_SIGKILL);
344 VG_(waitpid)(pid, &status, 0);
345 }
346}
347
348
349/* Print some helpful-ish text about unimplemented things, and give
350 up. */
351void VG_(unimplemented) ( Char* msg )
352{
353 VG_(message)(Vg_UserMsg, "");
354 VG_(message)(Vg_UserMsg,
355 "Valgrind detected that your program requires");
356 VG_(message)(Vg_UserMsg,
357 "the following unimplemented functionality:");
358 VG_(message)(Vg_UserMsg, " %s", msg);
359 VG_(message)(Vg_UserMsg,
360 "This may be because the functionality is hard to implement,");
361 VG_(message)(Vg_UserMsg,
362 "or because no reasonable program would behave this way,");
363 VG_(message)(Vg_UserMsg,
364 "or because nobody has yet needed it. In any case, let us know at");
365 VG_(message)(Vg_UserMsg,
366 "%s and/or try to work around the problem, if you can.", VG_BUGS_TO);
367 VG_(message)(Vg_UserMsg,
368 "");
369 VG_(message)(Vg_UserMsg,
370 "Valgrind has to exit now. Sorry. Bye!");
371 VG_(message)(Vg_UserMsg,
372 "");
373 VG_(pp_sched_status)();
374 VG_(exit)(1);
375}
376
377Addr VG_(get_stack_pointer) ( void )
378{
379 return VG_(baseBlock)[VGOFF_(m_esp)];
380}
381
382/* Debugging thing .. can be called from assembly with OYNK macro. */
383void VG_(oynk) ( Int n )
384{
385 OINK(n);
386}
387
388/* Initialize the PID and PGRP of scheduler LWP; this is also called
389 in any new children after fork. */
390static void newpid(ThreadId unused)
391{
392 /* PID of scheduler LWP */
393 VG_(main_pid) = VG_(getpid)();
394 VG_(main_pgrp) = VG_(getpgrp)();
395}
396
397/*====================================================================*/
398/*=== Check we were launched by stage 1 ===*/
399/*====================================================================*/
400
401/* Look for our AUXV table */
nethercote31779c72004-07-30 21:50:15 +0000402int scan_auxv(void)
nethercote71980f02004-01-24 18:18:54 +0000403{
404 const struct ume_auxv *auxv = find_auxv((int *)ume_exec_esp);
nethercote31779c72004-07-30 21:50:15 +0000405 int padfile = -1, found = 0;
nethercote71980f02004-01-24 18:18:54 +0000406
407 for (; auxv->a_type != AT_NULL; auxv++)
408 switch(auxv->a_type) {
409 case AT_UME_PADFD:
nethercote31779c72004-07-30 21:50:15 +0000410 padfile = auxv->u.a_val;
nethercote71980f02004-01-24 18:18:54 +0000411 found |= 1;
412 break;
413
414 case AT_UME_EXECFD:
nethercotef6a1d502004-08-09 12:21:57 +0000415 vgexecfd = auxv->u.a_val;
nethercote71980f02004-01-24 18:18:54 +0000416 found |= 2;
417 break;
418 }
419
nethercote361a14e2004-07-26 11:11:56 +0000420 if ( found != (1|2) ) {
421 fprintf(stderr, "valgrind: stage2 must be launched by stage1\n");
nethercote71980f02004-01-24 18:18:54 +0000422 exit(127);
423 }
nethercote31779c72004-07-30 21:50:15 +0000424 vg_assert(padfile >= 0);
425 return padfile;
nethercote71980f02004-01-24 18:18:54 +0000426}
427
428
429/*====================================================================*/
430/*=== Address space determination ===*/
431/*====================================================================*/
432
nethercote31779c72004-07-30 21:50:15 +0000433static void layout_remaining_space(Addr argc_addr, float ratio)
nethercote71980f02004-01-24 18:18:54 +0000434{
nethercote31779c72004-07-30 21:50:15 +0000435 Int ires;
436 void* vres;
437 addr_t client_size, shadow_size;
nethercote71980f02004-01-24 18:18:54 +0000438
nethercote31779c72004-07-30 21:50:15 +0000439 VG_(valgrind_base) = (addr_t)&kickstart_base;
rjwalsh18b66312004-08-23 18:15:12 +0000440
441 // VG_(valgrind_end) has a slightly different meaning to all the other
442 // VG_(*_end) vars -- ie. it names the last byte, whereas the others
443 // go one byte past the end.
444
rjwalshebca8b42004-08-23 18:13:16 +0000445 VG_(valgrind_end) = ROUNDUP(argc_addr, 0x10000) - 1; // stack
nethercote71980f02004-01-24 18:18:54 +0000446
nethercote31779c72004-07-30 21:50:15 +0000447 // This gives the client the largest possible address space while
448 // taking into account the tool's shadow needs.
449 client_size = ROUNDDN((VG_(valgrind_base)-REDZONE_SIZE) / (1.+ratio),
nethercote71980f02004-01-24 18:18:54 +0000450 CLIENT_SIZE_MULTIPLE);
nethercote31779c72004-07-30 21:50:15 +0000451 VG_(client_base) = CLIENT_BASE;
nethercote71980f02004-01-24 18:18:54 +0000452 VG_(client_end) = VG_(client_base) + client_size;
nethercotee2097312004-06-27 12:29:56 +0000453 /* where !FIXED mmap goes */
nethercotebc7b4f42004-07-26 12:44:35 +0000454 VG_(client_mapbase) = VG_(client_base) +
455 PGROUNDDN((addr_t)(client_size * CLIENT_HEAP_PROPORTION));
nethercote71980f02004-01-24 18:18:54 +0000456
nethercote31779c72004-07-30 21:50:15 +0000457 shadow_size = PGROUNDUP(client_size * ratio);
458 VG_(shadow_base) = VG_(client_end) + REDZONE_SIZE;
459 VG_(shadow_end) = VG_(shadow_base) + shadow_size;
nethercote71980f02004-01-24 18:18:54 +0000460
nethercotee2097312004-06-27 12:29:56 +0000461#define SEGSIZE(a,b) ((VG_(b) - VG_(a))/(1024*1024))
462
nethercote71980f02004-01-24 18:18:54 +0000463 if (0)
nethercotee2097312004-06-27 12:29:56 +0000464 VG_(printf)(
465 "client_base %8x (%dMB)\n"
466 "client_mapbase %8x (%dMB)\n"
467 "client_end %8x (%dMB)\n"
468 "shadow_base %8x (%dMB)\n"
469 "shadow_end %8x (%dMB)\n"
470 "valgrind_base %8x (%dMB)\n"
nethercotee2097312004-06-27 12:29:56 +0000471 "valgrind_end %8x\n",
472 VG_(client_base), SEGSIZE(client_base, client_mapbase),
473 VG_(client_mapbase), SEGSIZE(client_mapbase, client_end),
474 VG_(client_end), SEGSIZE(client_end, shadow_base),
475 VG_(shadow_base), SEGSIZE(shadow_base, shadow_end),
476 VG_(shadow_end), SEGSIZE(shadow_end, valgrind_base),
nethercotec314eba2004-07-15 12:59:41 +0000477 VG_(valgrind_base), SEGSIZE(valgrind_base, valgrind_end),
nethercotee2097312004-06-27 12:29:56 +0000478 VG_(valgrind_end)
479 );
480
481#undef SEGSIZE
nethercote71980f02004-01-24 18:18:54 +0000482
483 // Ban redzone
nethercotee567e702004-07-10 17:49:17 +0000484 vres = mmap((void *)VG_(client_end), REDZONE_SIZE, PROT_NONE,
485 MAP_FIXED|MAP_ANON|MAP_PRIVATE, -1, 0);
486 vg_assert((void*)-1 != vres);
nethercote71980f02004-01-24 18:18:54 +0000487
488 // Make client hole
nethercotee567e702004-07-10 17:49:17 +0000489 ires = munmap((void*)VG_(client_base), client_size);
490 vg_assert(0 == ires);
nethercote71980f02004-01-24 18:18:54 +0000491
492 // Map shadow memory.
493 // Initially all inaccessible, incrementally initialized as it is used
nethercotee567e702004-07-10 17:49:17 +0000494 if (shadow_size != 0) {
495 vres = mmap((char *)VG_(shadow_base), shadow_size, PROT_NONE,
496 MAP_PRIVATE|MAP_ANON|MAP_FIXED, -1, 0);
nethercoted4722622004-08-30 19:36:42 +0000497 if ((void*)-1 == vres) {
498 fprintf(stderr,
499 "valgrind: Couldn't allocate address space for shadow memory\n"
500 "valgrind: Are you using a kernel with a small user address space,\n"
501 "valgrind: or do you have your virtual memory size limited?\n");
502 exit(1);
503 }
nethercotee567e702004-07-10 17:49:17 +0000504 }
nethercote71980f02004-01-24 18:18:54 +0000505}
506
507/*====================================================================*/
508/*=== Command line setup ===*/
509/*====================================================================*/
510
511/* Nb: malloc'd memory never freed -- kept throughout like argv, envp */
512static char* get_file_clo(char* dir)
513{
514# define FLEN 512
515 Int fd, n;
516 struct stat s1;
517 char* f_clo = NULL;
518 char filename[FLEN];
519
520 snprintf(filename, FLEN, "%s/.valgrindrc", ( NULL == dir ? "" : dir ) );
521 fd = VG_(open)(filename, 0, VKI_S_IRUSR);
522 if ( fd > 0 ) {
523 if ( 0 == fstat(fd, &s1) ) {
524 f_clo = malloc(s1.st_size+1);
525 vg_assert(f_clo);
526 n = read(fd, f_clo, s1.st_size);
527 if (n == -1) n = 0;
528 f_clo[n] = '\0';
529 }
530 close(fd);
531 }
532 return f_clo;
533# undef FLEN
534}
535
nethercotee2097312004-06-27 12:29:56 +0000536#define ISSPACE(cc) ((cc) == ' ' || (cc) == '\t' || (cc) == '\n')
537
nethercote71980f02004-01-24 18:18:54 +0000538static Int count_args(char* s)
539{
540 Int n = 0;
541 if (s) {
542 char* cp = s;
543 while (True) {
544 // We have alternating sequences: blanks, non-blanks, blanks...
545 // count the non-blanks sequences.
546 while ( ISSPACE(*cp) ) cp++;
547 if ( !*cp ) break;
548 n++;
549 while ( !ISSPACE(*cp) && *cp ) cp++;
550 }
551 }
552 return n;
553}
554
555/* add args out of environment, skipping multiple spaces and -- args */
556static char** copy_args( char* s, char** to )
557{
558 if (s) {
559 char* cp = s;
560 while (True) {
561 // We have alternating sequences: blanks, non-blanks, blanks...
562 // copy the non-blanks sequences, and add terminating '\0'
563 while ( ISSPACE(*cp) ) cp++;
564 if ( !*cp ) break;
565 *to++ = cp;
566 while ( !ISSPACE(*cp) && *cp ) cp++;
567 if ( *cp ) *cp++ = '\0'; // terminate if necessary
568 if (VG_STREQ(to[-1], "--")) to--; // undo any '--' arg
569 }
570 }
571 return to;
572}
573
nethercotee2097312004-06-27 12:29:56 +0000574#undef ISSPACE
575
nethercote71980f02004-01-24 18:18:54 +0000576// Augment command line with arguments from environment and .valgrindrc
577// files.
578static void augment_command_line(Int* vg_argc_inout, char*** vg_argv_inout)
579{
nethercotef6a1d502004-08-09 12:21:57 +0000580 int vg_argc0 = *vg_argc_inout;
581 char** vg_argv0 = *vg_argv_inout;
nethercote71980f02004-01-24 18:18:54 +0000582
583 char* env_clo = getenv(VALGRINDOPTS);
584 char* f1_clo = get_file_clo( getenv("HOME") );
585 char* f2_clo = get_file_clo(".");
586
587 /* copy any extra args from file or environment, if present */
588 if ( (env_clo && *env_clo) || (f1_clo && *f1_clo) || (f2_clo && *f2_clo) ) {
589 /* ' ' separated extra options */
590 char **from;
591 char **to;
592 int env_arg_count, f1_arg_count, f2_arg_count;
593
594 env_arg_count = count_args(env_clo);
595 f1_arg_count = count_args(f1_clo);
596 f2_arg_count = count_args(f2_clo);
597
598 if (0)
599 printf("extra-argc=%d %d %d\n",
600 env_arg_count, f1_arg_count, f2_arg_count);
601
602 /* +2: +1 for null-termination, +1 for added '--' */
nethercotef6a1d502004-08-09 12:21:57 +0000603 from = vg_argv0;
604 vg_argv0 = malloc( (vg_argc0 + env_arg_count + f1_arg_count
nethercote71980f02004-01-24 18:18:54 +0000605 + f2_arg_count + 2) * sizeof(char **));
nethercotef6a1d502004-08-09 12:21:57 +0000606 vg_assert(vg_argv0);
607 to = vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000608
609 /* copy argv[0] */
610 *to++ = *from++;
611
612 /* Copy extra args from env var and file, in the order: ~/.valgrindrc,
613 * $VALGRIND_OPTS, ./.valgrindrc -- more local options are put later
614 * to override less local ones. */
615 to = copy_args(f1_clo, to);
616 to = copy_args(env_clo, to);
617 to = copy_args(f2_clo, to);
618
619 /* copy original arguments, stopping at command or -- */
620 while (*from) {
621 if (**from != '-')
622 break;
623 if (VG_STREQ(*from, "--")) {
624 from++; /* skip -- */
625 break;
626 }
627 *to++ = *from++;
628 }
629
630 /* add -- */
631 *to++ = "--";
632
nethercotef6a1d502004-08-09 12:21:57 +0000633 vg_argc0 = to - vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000634
635 /* copy rest of original command line, then NULL */
636 while (*from) *to++ = *from++;
637 *to = NULL;
638 }
639
nethercotef6a1d502004-08-09 12:21:57 +0000640 *vg_argc_inout = vg_argc0;
641 *vg_argv_inout = vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000642}
643
nethercotef6a1d502004-08-09 12:21:57 +0000644#define VG_CLO_SEP '\01'
645
nethercote71980f02004-01-24 18:18:54 +0000646static void get_command_line( int argc, char** argv,
647 Int* vg_argc_out, Char*** vg_argv_out,
648 char*** cl_argv_out )
649{
nethercotef6a1d502004-08-09 12:21:57 +0000650 int vg_argc0;
651 char** vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000652 char** cl_argv;
653 char* env_clo = getenv(VALGRINDCLO);
654
655 if (env_clo != NULL && *env_clo != '\0') {
656 char *cp;
657 char **cpp;
658
nethercotef6a1d502004-08-09 12:21:57 +0000659 /* OK, VALGRINDCLO is set, which means we must be a child of another
660 Valgrind process using --trace-children, so we're getting all our
661 arguments from VALGRINDCLO, and the entire command line belongs to
662 the client (including argv[0]) */
663 vg_argc0 = 1; /* argv[0] */
nethercote71980f02004-01-24 18:18:54 +0000664 for (cp = env_clo; *cp; cp++)
nethercotef6a1d502004-08-09 12:21:57 +0000665 if (*cp == VG_CLO_SEP)
666 vg_argc0++;
nethercote71980f02004-01-24 18:18:54 +0000667
nethercotef6a1d502004-08-09 12:21:57 +0000668 vg_argv0 = malloc(sizeof(char **) * (vg_argc0 + 1));
669 vg_assert(vg_argv0);
nethercote71980f02004-01-24 18:18:54 +0000670
nethercotef6a1d502004-08-09 12:21:57 +0000671 cpp = vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000672
673 *cpp++ = "valgrind"; /* nominal argv[0] */
674 *cpp++ = env_clo;
675
nethercotef6a1d502004-08-09 12:21:57 +0000676 // Replace the VG_CLO_SEP args separator with '\0'
nethercote71980f02004-01-24 18:18:54 +0000677 for (cp = env_clo; *cp; cp++) {
nethercotef6a1d502004-08-09 12:21:57 +0000678 if (*cp == VG_CLO_SEP) {
nethercote71980f02004-01-24 18:18:54 +0000679 *cp++ = '\0'; /* chop it up in place */
680 *cpp++ = cp;
681 }
682 }
683 *cpp = NULL;
684 cl_argv = argv;
685
686 } else {
687 /* Count the arguments on the command line. */
nethercotef6a1d502004-08-09 12:21:57 +0000688 vg_argv0 = argv;
nethercote71980f02004-01-24 18:18:54 +0000689
nethercotef6a1d502004-08-09 12:21:57 +0000690 for (vg_argc0 = 1; vg_argc0 < argc; vg_argc0++) {
691 if (argv[vg_argc0][0] != '-') /* exe name */
nethercote71980f02004-01-24 18:18:54 +0000692 break;
nethercotef6a1d502004-08-09 12:21:57 +0000693 if (VG_STREQ(argv[vg_argc0], "--")) { /* dummy arg */
694 vg_argc0++;
nethercote71980f02004-01-24 18:18:54 +0000695 break;
696 }
697 }
nethercotef6a1d502004-08-09 12:21:57 +0000698 cl_argv = &argv[vg_argc0];
nethercote71980f02004-01-24 18:18:54 +0000699
700 /* Get extra args from VALGRIND_OPTS and .valgrindrc files.
nethercotef6a1d502004-08-09 12:21:57 +0000701 Note we don't do this if getting args from VALGRINDCLO, as
702 those extra args will already be present in VALGRINDCLO. */
703 augment_command_line(&vg_argc0, &vg_argv0);
nethercote71980f02004-01-24 18:18:54 +0000704 }
705
706 if (0) {
707 Int i;
nethercotef6a1d502004-08-09 12:21:57 +0000708 for (i = 0; i < vg_argc0; i++)
709 printf("vg_argv0[%d]=\"%s\"\n", i, vg_argv0[i]);
nethercote71980f02004-01-24 18:18:54 +0000710 }
711
nethercotef6a1d502004-08-09 12:21:57 +0000712 *vg_argc_out = vg_argc0;
713 *vg_argv_out = (Char**)vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000714 *cl_argv_out = cl_argv;
715}
716
717
718/*====================================================================*/
719/*=== Environment and stack setup ===*/
720/*====================================================================*/
721
722/* Scan a colon-separated list, and call a function on each element.
723 The string must be mutable, because we insert a temporary '\0', but
thughes4ad52d02004-06-27 17:37:21 +0000724 the string will end up unmodified. (*func) should return True if it
nethercote71980f02004-01-24 18:18:54 +0000725 doesn't need to see any more.
thughes4ad52d02004-06-27 17:37:21 +0000726
727 This routine will return True if (*func) returns True and False if
728 it reaches the end of the list without that happening.
nethercote71980f02004-01-24 18:18:54 +0000729*/
thughes4ad52d02004-06-27 17:37:21 +0000730static Bool scan_colsep(char *colsep, Bool (*func)(const char *))
nethercote71980f02004-01-24 18:18:54 +0000731{
732 char *cp, *entry;
733 int end;
734
735 if (colsep == NULL ||
736 *colsep == '\0')
thughes4ad52d02004-06-27 17:37:21 +0000737 return False;
nethercote71980f02004-01-24 18:18:54 +0000738
739 entry = cp = colsep;
740
741 do {
742 end = (*cp == '\0');
743
744 if (*cp == ':' || *cp == '\0') {
745 char save = *cp;
746
747 *cp = '\0';
thughes21942d92004-07-12 09:35:37 +0000748 if ((*func)(entry)) {
749 *cp = save;
thughes4ad52d02004-06-27 17:37:21 +0000750 return True;
thughes21942d92004-07-12 09:35:37 +0000751 }
nethercote71980f02004-01-24 18:18:54 +0000752 *cp = save;
753 entry = cp+1;
754 }
755 cp++;
756 } while(!end);
thughes4ad52d02004-06-27 17:37:21 +0000757
758 return False;
759}
760
761static Bool contains(const char *p) {
762 if (VG_STREQ(p, VG_(libdir))) {
763 return True;
764 }
765 return False;
nethercote71980f02004-01-24 18:18:54 +0000766}
767
768/* Prepare the client's environment. This is basically a copy of our
769 environment, except:
770 1. LD_LIBRARY_PATH=$VALGRINDLIB:$LD_LIBRARY_PATH
771 2. LD_PRELOAD=$VALGRINDLIB/vg_inject.so:($VALGRINDLIB/vgpreload_TOOL.so:)?$LD_PRELOAD
772
773 If any of these is missing, then it is added.
774
775 Yummy. String hacking in C.
776
777 If this needs to handle any more variables it should be hacked
778 into something table driven.
779 */
780static char **fix_environment(char **origenv, const char *preload)
781{
782 static const char inject_so[] = "vg_inject.so";
783 static const char ld_library_path[] = "LD_LIBRARY_PATH=";
784 static const char ld_preload[] = "LD_PRELOAD=";
785 static const char valgrind_clo[] = VALGRINDCLO "=";
786 static const int ld_library_path_len = sizeof(ld_library_path)-1;
787 static const int ld_preload_len = sizeof(ld_preload)-1;
788 static const int valgrind_clo_len = sizeof(valgrind_clo)-1;
789 int ld_preload_done = 0;
790 int ld_library_path_done = 0;
791 char *inject_path;
792 int inject_path_len;
793 int vgliblen = strlen(VG_(libdir));
794 char **cpp;
795 char **ret;
796 int envc;
797 const int preloadlen = (preload == NULL) ? 0 : strlen(preload);
798
799 /* Find the vg_inject.so; also make room for the tool preload
800 library */
801 inject_path_len = sizeof(inject_so) + vgliblen + preloadlen + 16;
802 inject_path = malloc(inject_path_len);
nethercote7c018f42004-07-17 16:40:50 +0000803 vg_assert(inject_path);
nethercote71980f02004-01-24 18:18:54 +0000804
805 if (preload)
806 snprintf(inject_path, inject_path_len, "%s/%s:%s",
807 VG_(libdir), inject_so, preload);
808 else
809 snprintf(inject_path, inject_path_len, "%s/%s",
810 VG_(libdir), inject_so);
811
812 /* Count the original size of the env */
813 envc = 0; /* trailing NULL */
814 for (cpp = origenv; cpp && *cpp; cpp++)
815 envc++;
816
817 /* Allocate a new space */
818 ret = malloc(sizeof(char *) * (envc+3+1)); /* 3 new entries + NULL */
nethercote7c018f42004-07-17 16:40:50 +0000819 vg_assert(ret);
nethercote71980f02004-01-24 18:18:54 +0000820
821 /* copy it over */
822 for (cpp = ret; *origenv; )
823 *cpp++ = *origenv++;
824 *cpp = NULL;
825
826 vg_assert(envc == (cpp - ret));
827
828 /* Walk over the new environment, mashing as we go */
829 for (cpp = ret; cpp && *cpp; cpp++) {
830 if (memcmp(*cpp, ld_library_path, ld_library_path_len) == 0) {
nethercote71980f02004-01-24 18:18:54 +0000831 /* If the LD_LIBRARY_PATH already contains libdir, then don't
832 bother adding it again, even if it isn't the first (it
833 seems that the Java runtime will keep reexecing itself
834 unless its paths are at the front of LD_LIBRARY_PATH) */
thughes4ad52d02004-06-27 17:37:21 +0000835 if (!scan_colsep(*cpp + ld_library_path_len, contains)) {
nethercote71980f02004-01-24 18:18:54 +0000836 int len = strlen(*cpp) + vgliblen*2 + 16;
837 char *cp = malloc(len);
nethercote7c018f42004-07-17 16:40:50 +0000838 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000839
840 snprintf(cp, len, "%s%s:%s",
841 ld_library_path, VG_(libdir),
842 (*cpp)+ld_library_path_len);
843
844 *cpp = cp;
845 }
846
847 ld_library_path_done = 1;
848 } else if (memcmp(*cpp, ld_preload, ld_preload_len) == 0) {
849 int len = strlen(*cpp) + inject_path_len;
850 char *cp = malloc(len);
nethercote7c018f42004-07-17 16:40:50 +0000851 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000852
853 snprintf(cp, len, "%s%s:%s",
854 ld_preload, inject_path, (*cpp)+ld_preload_len);
855
856 *cpp = cp;
857
858 ld_preload_done = 1;
859 } else if (memcmp(*cpp, valgrind_clo, valgrind_clo_len) == 0) {
860 *cpp = "";
861 }
862 }
863
864 /* Add the missing bits */
865
866 if (!ld_library_path_done) {
867 int len = ld_library_path_len + vgliblen*2 + 16;
868 char *cp = malloc(len);
nethercote7c018f42004-07-17 16:40:50 +0000869 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000870
871 snprintf(cp, len, "%s%s", ld_library_path, VG_(libdir));
872
873 ret[envc++] = cp;
874 }
875
876 if (!ld_preload_done) {
877 int len = ld_preload_len + inject_path_len;
878 char *cp = malloc(len);
nethercote7c018f42004-07-17 16:40:50 +0000879 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000880
881 snprintf(cp, len, "%s%s",
882 ld_preload, inject_path);
883
884 ret[envc++] = cp;
885 }
886
887 ret[envc] = NULL;
888
889 return ret;
890}
891
892extern char **environ; /* our environment */
893//#include <error.h>
894
895/* Add a string onto the string table, and return its address */
896static char *copy_str(char **tab, const char *str)
897{
898 char *cp = *tab;
899 char *orig = cp;
900
901 while(*str)
902 *cp++ = *str++;
903 *cp++ = '\0';
904
905 if (0)
nethercotef84f6952004-07-15 14:58:33 +0000906 printf("copied %p \"%s\" len %d\n", orig, orig, cp-orig);
nethercote71980f02004-01-24 18:18:54 +0000907
908 *tab = cp;
909
910 return orig;
911}
912
913/*
914 This sets up the client's initial stack, containing the args,
915 environment and aux vector.
916
917 The format of the stack is:
918
919 higher address +-----------------+
920 | Trampoline code |
921 +-----------------+
922 | |
923 : string table :
924 | |
925 +-----------------+
926 | AT_NULL |
927 - -
928 | auxv |
929 +-----------------+
930 | NULL |
931 - -
932 | envp |
933 +-----------------+
934 | NULL |
935 - -
936 | argv |
937 +-----------------+
938 | argc |
939 lower address +-----------------+ <- esp
940 | undefined |
941 : :
942 */
943static Addr setup_client_stack(char **orig_argv, char **orig_envp,
944 const struct exeinfo *info,
945 UInt** client_auxv)
946{
nethercotee567e702004-07-10 17:49:17 +0000947 void* res;
nethercote71980f02004-01-24 18:18:54 +0000948 char **cpp;
949 char *strtab; /* string table */
950 char *stringbase;
951 addr_t *ptr;
952 struct ume_auxv *auxv;
953 const struct ume_auxv *orig_auxv;
954 const struct ume_auxv *cauxv;
955 unsigned stringsize; /* total size of strings in bytes */
956 unsigned auxsize; /* total size of auxv in bytes */
957 int argc; /* total argc */
958 int envc; /* total number of env vars */
959 unsigned stacksize; /* total client stack size */
960 addr_t cl_esp; /* client stack base (initial esp) */
961
962 /* use our own auxv as a prototype */
963 orig_auxv = find_auxv(ume_exec_esp);
964
965 /* ==================== compute sizes ==================== */
966
967 /* first of all, work out how big the client stack will be */
968 stringsize = 0;
969
970 /* paste on the extra args if the loader needs them (ie, the #!
971 interpreter and its argument) */
972 argc = 0;
nethercoted6a56872004-07-26 15:32:47 +0000973 if (info->interp_name != NULL) {
nethercote71980f02004-01-24 18:18:54 +0000974 argc++;
nethercoted6a56872004-07-26 15:32:47 +0000975 stringsize += strlen(info->interp_name) + 1;
nethercote71980f02004-01-24 18:18:54 +0000976 }
nethercoted6a56872004-07-26 15:32:47 +0000977 if (info->interp_args != NULL) {
nethercote71980f02004-01-24 18:18:54 +0000978 argc++;
nethercoted6a56872004-07-26 15:32:47 +0000979 stringsize += strlen(info->interp_args) + 1;
nethercote71980f02004-01-24 18:18:54 +0000980 }
981
982 /* now scan the args we're given... */
983 for (cpp = orig_argv; *cpp; cpp++) {
984 argc++;
985 stringsize += strlen(*cpp) + 1;
986 }
987
988 /* ...and the environment */
989 envc = 0;
990 for (cpp = orig_envp; cpp && *cpp; cpp++) {
991 envc++;
992 stringsize += strlen(*cpp) + 1;
993 }
994
995 /* now, how big is the auxv? */
996 auxsize = sizeof(*auxv); /* there's always at least one entry: AT_NULL */
997 for (cauxv = orig_auxv; cauxv->a_type != AT_NULL; cauxv++) {
998 if (cauxv->a_type == AT_PLATFORM)
999 stringsize += strlen(cauxv->u.a_ptr) + 1;
1000 auxsize += sizeof(*cauxv);
1001 }
1002
1003 /* OK, now we know how big the client stack is */
1004 stacksize =
1005 sizeof(int) + /* argc */
1006 sizeof(char **)*argc + /* argv */
1007 sizeof(char **) + /* terminal NULL */
1008 sizeof(char **)*envc + /* envp */
1009 sizeof(char **) + /* terminal NULL */
1010 auxsize + /* auxv */
1011 ROUNDUP(stringsize, sizeof(int)) +/* strings (aligned) */
1012 VKI_BYTES_PER_PAGE; /* page for trampoline code */
1013
nethercotef84f6952004-07-15 14:58:33 +00001014 // decide where stack goes!
1015 VG_(clstk_end) = VG_(client_end);
1016
1017 VG_(client_trampoline_code) = VG_(clstk_end) - VKI_BYTES_PER_PAGE;
1018
nethercote71980f02004-01-24 18:18:54 +00001019 /* cl_esp is the client's stack pointer */
nethercotef84f6952004-07-15 14:58:33 +00001020 cl_esp = VG_(clstk_end) - stacksize;
nethercote71980f02004-01-24 18:18:54 +00001021 cl_esp = ROUNDDN(cl_esp, 16); /* make stack 16 byte aligned */
1022
nethercote71980f02004-01-24 18:18:54 +00001023 /* base of the string table (aligned) */
1024 stringbase = strtab = (char *)(VG_(client_trampoline_code) - ROUNDUP(stringsize, sizeof(int)));
1025
1026 VG_(clstk_base) = PGROUNDDN(cl_esp);
nethercote71980f02004-01-24 18:18:54 +00001027
nethercote5ee67ca2004-06-22 14:00:09 +00001028 if (0)
1029 printf("stringsize=%d auxsize=%d stacksize=%d\n"
1030 "clstk_base %x\n"
1031 "clstk_end %x\n",
1032 stringsize, auxsize, stacksize, VG_(clstk_base), VG_(clstk_end));
1033
1034
nethercote71980f02004-01-24 18:18:54 +00001035 /* ==================== allocate space ==================== */
1036
1037 /* allocate a stack - mmap enough space for the stack */
nethercotef84f6952004-07-15 14:58:33 +00001038 res = mmap((void *)PGROUNDDN(cl_esp), VG_(clstk_end) - PGROUNDDN(cl_esp),
nethercotee567e702004-07-10 17:49:17 +00001039 PROT_READ | PROT_WRITE | PROT_EXEC,
1040 MAP_PRIVATE | MAP_ANON | MAP_FIXED, -1, 0);
1041 vg_assert((void*)-1 != res);
nethercote71980f02004-01-24 18:18:54 +00001042
1043 /* ==================== copy client stack ==================== */
1044
1045 ptr = (addr_t *)cl_esp;
1046
1047 /* --- argc --- */
1048 *ptr++ = argc; /* client argc */
1049
1050 /* --- argv --- */
nethercoted6a56872004-07-26 15:32:47 +00001051 if (info->interp_name) {
1052 *ptr++ = (addr_t)copy_str(&strtab, info->interp_name);
1053 free(info->interp_name);
nethercote71980f02004-01-24 18:18:54 +00001054 }
nethercoted6a56872004-07-26 15:32:47 +00001055 if (info->interp_args) {
1056 *ptr++ = (addr_t)copy_str(&strtab, info->interp_args);
1057 free(info->interp_args);
nethercote71980f02004-01-24 18:18:54 +00001058 }
1059 for (cpp = orig_argv; *cpp; ptr++, cpp++) {
1060 *ptr = (addr_t)copy_str(&strtab, *cpp);
1061 }
1062 *ptr++ = 0;
1063
1064 /* --- envp --- */
1065 VG_(client_envp) = (Char **)ptr;
1066 for (cpp = orig_envp; cpp && *cpp; ptr++, cpp++)
1067 *ptr = (addr_t)copy_str(&strtab, *cpp);
1068 *ptr++ = 0;
1069
1070 /* --- auxv --- */
1071 auxv = (struct ume_auxv *)ptr;
1072 *client_auxv = (UInt *)auxv;
1073
1074 for (; orig_auxv->a_type != AT_NULL; auxv++, orig_auxv++) {
1075 /* copy the entry... */
1076 *auxv = *orig_auxv;
1077
1078 /* ...and fix up the copy */
1079 switch(auxv->a_type) {
1080 case AT_PHDR:
1081 if (info->phdr == 0)
1082 auxv->a_type = AT_IGNORE;
1083 else
1084 auxv->u.a_val = info->phdr;
1085 break;
1086
1087 case AT_PHNUM:
1088 if (info->phdr == 0)
1089 auxv->a_type = AT_IGNORE;
1090 else
1091 auxv->u.a_val = info->phnum;
1092 break;
1093
1094 case AT_BASE:
1095 if (info->interp_base == 0)
1096 auxv->a_type = AT_IGNORE;
1097 else
1098 auxv->u.a_val = info->interp_base;
1099 break;
1100
1101 case AT_PLATFORM: /* points to a platform description string */
1102 auxv->u.a_ptr = copy_str(&strtab, orig_auxv->u.a_ptr);
1103 break;
1104
1105 case AT_ENTRY:
1106 auxv->u.a_val = info->entry;
1107 break;
1108
1109 case AT_IGNORE:
1110 case AT_EXECFD:
1111 case AT_PHENT:
1112 case AT_PAGESZ:
1113 case AT_FLAGS:
1114 case AT_NOTELF:
1115 case AT_UID:
1116 case AT_EUID:
1117 case AT_GID:
1118 case AT_EGID:
1119 case AT_CLKTCK:
1120 case AT_HWCAP:
1121 case AT_FPUCW:
1122 case AT_DCACHEBSIZE:
1123 case AT_ICACHEBSIZE:
1124 case AT_UCACHEBSIZE:
1125 /* All these are pointerless, so we don't need to do anything
1126 about them. */
1127 break;
1128
1129 case AT_SECURE:
1130 /* If this is 1, then it means that this program is running
1131 suid, and therefore the dynamic linker should be careful
1132 about LD_PRELOAD, etc. However, since stage1 (the thing
1133 the kernel actually execve's) should never be SUID, and we
1134 need LD_PRELOAD/LD_LIBRARY_PATH to work for the client, we
1135 set AT_SECURE to 0. */
1136 auxv->u.a_val = 0;
1137 break;
1138
1139 case AT_SYSINFO:
1140 /* Leave this unmolested for now, but we'll update it later
1141 when we set up the client trampoline code page */
1142 break;
1143
1144 case AT_SYSINFO_EHDR:
1145 /* Trash this, because we don't reproduce it */
1146 auxv->a_type = AT_IGNORE;
1147 break;
1148
1149 default:
1150 /* stomp out anything we don't know about */
1151 if (0)
1152 printf("stomping auxv entry %d\n", auxv->a_type);
1153 auxv->a_type = AT_IGNORE;
1154 break;
1155
1156 }
1157 }
1158 *auxv = *orig_auxv;
1159 vg_assert(auxv->a_type == AT_NULL);
1160
nethercotef84f6952004-07-15 14:58:33 +00001161 /* --- trampoline page --- */
1162 VG_(memcpy)( (void *)VG_(client_trampoline_code),
1163 &VG_(trampoline_code_start), VG_(trampoline_code_length) );
1164
nethercote71980f02004-01-24 18:18:54 +00001165 vg_assert((strtab-stringbase) == stringsize);
1166
nethercote5ee67ca2004-06-22 14:00:09 +00001167 /* We know the initial ESP is pointing at argc/argv */
1168 VG_(client_argc) = *(Int*)cl_esp;
1169 VG_(client_argv) = (Char**)(cl_esp + sizeof(Int));
1170
nethercote71980f02004-01-24 18:18:54 +00001171 return cl_esp;
1172}
1173
1174/*====================================================================*/
1175/*=== Find executable ===*/
1176/*====================================================================*/
1177
thughes4ad52d02004-06-27 17:37:21 +00001178static const char* executable_name;
1179
1180static Bool match_executable(const char *entry) {
1181 char buf[strlen(entry) + strlen(executable_name) + 2];
1182
1183 /* empty PATH element means . */
1184 if (*entry == '\0')
1185 entry = ".";
1186
1187 snprintf(buf, sizeof(buf), "%s/%s", entry, executable_name);
1188
1189 if (access(buf, R_OK|X_OK) == 0) {
1190 executable_name = strdup(buf);
1191 vg_assert(NULL != executable_name);
1192 return True;
1193 }
1194 return False;
1195}
1196
nethercote71980f02004-01-24 18:18:54 +00001197static const char* find_executable(const char* exec)
1198{
1199 vg_assert(NULL != exec);
thughes4ad52d02004-06-27 17:37:21 +00001200 executable_name = exec;
1201 if (strchr(executable_name, '/') == NULL) {
nethercote71980f02004-01-24 18:18:54 +00001202 /* no '/' - we need to search the path */
1203 char *path = getenv("PATH");
thughes4ad52d02004-06-27 17:37:21 +00001204 scan_colsep(path, match_executable);
nethercote71980f02004-01-24 18:18:54 +00001205 }
thughes4ad52d02004-06-27 17:37:21 +00001206 return executable_name;
nethercote71980f02004-01-24 18:18:54 +00001207}
1208
1209
1210/*====================================================================*/
1211/*=== Loading tools ===*/
1212/*====================================================================*/
1213
1214static void list_tools(void)
1215{
1216 DIR *dir = opendir(VG_(libdir));
1217 struct dirent *de;
1218 int first = 1;
1219
1220 if (dir == NULL) {
1221 fprintf(stderr, "Can't open %s: %s (installation problem?)\n",
nethercotef4928da2004-06-15 10:54:40 +00001222 VG_(libdir), strerror(errno));
nethercote71980f02004-01-24 18:18:54 +00001223 return;
1224 }
1225
nethercotef4928da2004-06-15 10:54:40 +00001226 while ((de = readdir(dir)) != NULL) {
nethercote71980f02004-01-24 18:18:54 +00001227 int len = strlen(de->d_name);
1228
1229 /* look for vgskin_TOOL.so names */
1230 if (len > (7+1+3) && /* "vgskin_" + at least 1-char toolname + ".so" */
nethercotef4928da2004-06-15 10:54:40 +00001231 strncmp(de->d_name, "vgskin_", 7) == 0 &&
1232 VG_STREQ(de->d_name + len - 3, ".so")) {
1233 if (first) {
1234 fprintf(stderr, "Available tools:\n");
1235 first = 0;
1236 }
1237 de->d_name[len-3] = '\0';
1238 fprintf(stderr, "\t%s\n", de->d_name+7);
nethercote71980f02004-01-24 18:18:54 +00001239 }
1240 }
1241
1242 closedir(dir);
1243
1244 if (first)
nethercotef4928da2004-06-15 10:54:40 +00001245 fprintf(stderr, "No tools available in \"%s\" (installation problem?)\n",
1246 VG_(libdir));
nethercote71980f02004-01-24 18:18:54 +00001247}
1248
1249
1250/* Find and load a tool, and check it looks ok. Also looks to see if there's
1251 * a matching vgpreload_*.so file, and returns its name in *preloadpath. */
1252static void load_tool( const char *toolname, void** handle_out,
1253 ToolInfo** toolinfo_out, char **preloadpath_out )
1254{
1255 Bool ok;
1256 int len = strlen(VG_(libdir)) + strlen(toolname)*2 + 16;
1257 char buf[len];
1258 void* handle;
1259 ToolInfo* toolinfo;
1260 char* preloadpath = NULL;
1261 Int* vg_malloc_redzonep;
1262
1263 // XXX: allowing full paths for --tool option -- does it make sense?
1264 // Doesn't allow for vgpreload_<tool>.so.
1265
1266 if (strchr(toolname, '/') != 0) {
1267 /* toolname contains '/', and so must be a pathname */
1268 handle = dlopen(toolname, RTLD_NOW);
1269 } else {
1270 /* just try in the libdir */
1271 snprintf(buf, len, "%s/vgskin_%s.so", VG_(libdir), toolname);
1272 handle = dlopen(buf, RTLD_NOW);
1273
1274 if (handle != NULL) {
1275 snprintf(buf, len, "%s/vgpreload_%s.so", VG_(libdir), toolname);
1276 if (access(buf, R_OK) == 0) {
1277 preloadpath = strdup(buf);
1278 vg_assert(NULL != preloadpath);
1279 }
1280 }
1281 }
1282
1283 ok = (NULL != handle);
1284 if (!ok) {
1285 fprintf(stderr, "Can't open tool \"%s\": %s\n", toolname, dlerror());
1286 goto bad_load;
1287 }
1288
1289 toolinfo = dlsym(handle, "vgSkin_tool_info");
1290 ok = (NULL != toolinfo);
1291 if (!ok) {
1292 fprintf(stderr, "Tool \"%s\" doesn't define SK_(tool_info) - "
1293 "add VG_DETERMINE_INTERFACE_VERSION?\n", toolname);
1294 goto bad_load;
1295 }
1296
1297 ok = (toolinfo->sizeof_ToolInfo == sizeof(*toolinfo) &&
1298 toolinfo->interface_major_version == VG_CORE_INTERFACE_MAJOR_VERSION &&
1299 toolinfo->sk_pre_clo_init != NULL);
1300 if (!ok) {
1301 fprintf(stderr, "Error:\n"
1302 " Tool and core interface versions do not match.\n"
1303 " Interface version used by core is: %d.%d (size %d)\n"
1304 " Interface version used by tool is: %d.%d (size %d)\n"
1305 " The major version numbers must match.\n",
1306 VG_CORE_INTERFACE_MAJOR_VERSION,
1307 VG_CORE_INTERFACE_MINOR_VERSION,
1308 sizeof(*toolinfo),
1309 toolinfo->interface_major_version,
1310 toolinfo->interface_minor_version,
1311 toolinfo->sizeof_ToolInfo);
1312 fprintf(stderr, " You need to at least recompile, and possibly update,\n");
1313 if (VG_CORE_INTERFACE_MAJOR_VERSION > toolinfo->interface_major_version)
nethercote996901a2004-08-03 13:29:09 +00001314 fprintf(stderr, " your tool to work with this version of Valgrind.\n");
nethercote71980f02004-01-24 18:18:54 +00001315 else
nethercote996901a2004-08-03 13:29:09 +00001316 fprintf(stderr, " your version of Valgrind to work with this tool.\n");
nethercote71980f02004-01-24 18:18:54 +00001317 goto bad_load;
1318 }
1319
1320 // Set redzone size for V's allocator
1321 vg_malloc_redzonep = dlsym(handle, STR(VG_(vg_malloc_redzone_szB)));
1322 if ( NULL != vg_malloc_redzonep ) {
1323 VG_(vg_malloc_redzone_szB) = *vg_malloc_redzonep;
1324 }
1325
1326 vg_assert(NULL != handle && NULL != toolinfo);
1327 *handle_out = handle;
1328 *toolinfo_out = toolinfo;
1329 *preloadpath_out = preloadpath;
1330 return;
1331
1332
1333 bad_load:
1334 if (handle != NULL)
1335 dlclose(handle);
1336
nethercotef4928da2004-06-15 10:54:40 +00001337 fprintf(stderr, "valgrind: couldn't load tool\n");
nethercote71980f02004-01-24 18:18:54 +00001338 list_tools();
1339 exit(127);
1340}
1341
nethercotef4928da2004-06-15 10:54:40 +00001342
1343/*====================================================================*/
1344/*=== Command line errors ===*/
1345/*====================================================================*/
1346
1347static void abort_msg ( void )
1348{
nethercotef8548672004-06-21 12:42:35 +00001349 VG_(clo_log_to) = VgLogTo_Fd;
1350 VG_(clo_log_fd) = 2; /* stderr */
nethercotef4928da2004-06-15 10:54:40 +00001351}
1352
1353void VG_(bad_option) ( Char* opt )
1354{
1355 abort_msg();
1356 VG_(printf)("valgrind: Bad option `%s'; aborting.\n", opt);
1357 VG_(printf)("valgrind: Use --help for more information.\n");
1358 VG_(exit)(1);
1359}
1360
1361static void missing_tool_option ( void )
1362{
1363 abort_msg();
1364 VG_(printf)("valgrind: Missing --tool option\n");
1365 list_tools();
1366 VG_(printf)("valgrind: Use --help for more information.\n");
1367 VG_(exit)(1);
1368}
1369
1370static void missing_prog ( void )
1371{
1372 abort_msg();
1373 VG_(printf)("valgrind: no program specified\n");
1374 VG_(printf)("valgrind: Use --help for more information.\n");
1375 VG_(exit)(1);
1376}
1377
1378static void config_error ( Char* msg )
1379{
1380 abort_msg();
1381 VG_(printf)("valgrind: Startup or configuration error:\n %s\n", msg);
1382 VG_(printf)("valgrind: Unable to start up properly. Giving up.\n");
1383 VG_(exit)(1);
1384}
1385
1386
nethercote71980f02004-01-24 18:18:54 +00001387/*====================================================================*/
1388/*=== Loading the client ===*/
1389/*====================================================================*/
1390
nethercotef4928da2004-06-15 10:54:40 +00001391static void load_client(char* cl_argv[], const char* exec, Int need_help,
nethercote71980f02004-01-24 18:18:54 +00001392 /*out*/struct exeinfo* info, /*out*/Addr* client_eip)
1393{
1394 // If they didn't specify an executable with --exec, and didn't specify
1395 // --help, then use client argv[0] (searching $PATH if necessary).
nethercotef4928da2004-06-15 10:54:40 +00001396 if (NULL == exec && !need_help) {
nethercote71980f02004-01-24 18:18:54 +00001397 if (cl_argv[0] == NULL ||
1398 ( NULL == (exec = find_executable(cl_argv[0])) ) )
1399 {
nethercotef4928da2004-06-15 10:54:40 +00001400 missing_prog();
nethercote71980f02004-01-24 18:18:54 +00001401 }
1402 }
1403
1404 info->map_base = VG_(client_mapbase);
nethercote71980f02004-01-24 18:18:54 +00001405 info->exe_base = VG_(client_base);
1406 info->exe_end = VG_(client_end);
1407 info->argv = cl_argv;
1408
nethercotef4928da2004-06-15 10:54:40 +00001409 if (need_help) {
nethercote71980f02004-01-24 18:18:54 +00001410 VG_(clexecfd) = -1;
nethercoteea147e72004-07-26 15:43:57 +00001411 // Set the minimal number of entries in 'info' to continue.
nethercoted6a56872004-07-26 15:32:47 +00001412 info->interp_name = NULL;
1413 info->interp_args = NULL;
nethercote71980f02004-01-24 18:18:54 +00001414 } else {
1415 Int ret;
1416 VG_(clexecfd) = VG_(open)(exec, O_RDONLY, VKI_S_IRUSR);
1417 ret = do_exec(exec, info);
1418 if (ret != 0) {
nethercoteea147e72004-07-26 15:43:57 +00001419 fprintf(stderr, "valgrind: do_exec(%s) failed: %s\n",
1420 exec, strerror(ret));
nethercote71980f02004-01-24 18:18:54 +00001421 exit(127);
1422 }
1423 }
1424
1425 /* Copy necessary bits of 'info' that were filled in */
1426 *client_eip = info->init_eip;
1427 VG_(brk_base) = VG_(brk_limit) = info->brkbase;
1428}
1429
1430
1431/*====================================================================*/
nethercotef6a1d502004-08-09 12:21:57 +00001432/*=== Command-line: variables, processing, etc ===*/
nethercote71980f02004-01-24 18:18:54 +00001433/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +00001434
njn25e49d8e72002-09-23 09:36:25 +00001435/* Define, and set defaults. */
1436Bool VG_(clo_error_limit) = True;
nethercote04d0fbc2004-01-26 16:48:06 +00001437Bool VG_(clo_db_attach) = False;
1438Char* VG_(clo_db_command) = VG_CLO_DEFAULT_DBCOMMAND;
njn43c799e2003-04-08 00:08:52 +00001439Bool VG_(clo_gen_suppressions) = False;
nethercote27fec902004-06-16 21:26:32 +00001440Int VG_(clo_sanity_level) = 1;
njn25e49d8e72002-09-23 09:36:25 +00001441Int VG_(clo_verbosity) = 1;
1442Bool VG_(clo_demangle) = True;
njn25e49d8e72002-09-23 09:36:25 +00001443Bool VG_(clo_trace_children) = False;
sewardj4cf05692002-10-27 20:28:29 +00001444
nethercotef1e5e152004-09-01 23:58:16 +00001445/* See big comment in core.h for meaning of these three.
nethercotee1730692003-11-20 10:38:07 +00001446 fd is initially stdout, for --help, but gets moved to stderr by default
1447 immediately afterwards. */
sewardj4cf05692002-10-27 20:28:29 +00001448VgLogTo VG_(clo_log_to) = VgLogTo_Fd;
nethercotef8548672004-06-21 12:42:35 +00001449Int VG_(clo_log_fd) = 1;
1450Char* VG_(clo_log_name) = NULL;
sewardj4cf05692002-10-27 20:28:29 +00001451
thughes6233a382004-08-21 11:10:44 +00001452Bool VG_(clo_time_stamp) = False;
1453
sewardj6024b212003-07-13 10:54:33 +00001454Int VG_(clo_input_fd) = 0; /* stdin */
njn25e49d8e72002-09-23 09:36:25 +00001455Int VG_(clo_n_suppressions) = 0;
sewardjde4a1d02002-03-22 01:27:54 +00001456Char* VG_(clo_suppressions)[VG_CLO_MAX_SFILES];
njn25e49d8e72002-09-23 09:36:25 +00001457Bool VG_(clo_profile) = False;
1458Bool VG_(clo_single_step) = False;
1459Bool VG_(clo_optimise) = True;
1460UChar VG_(clo_trace_codegen) = 0; // 00000000b
1461Bool VG_(clo_trace_syscalls) = False;
1462Bool VG_(clo_trace_signals) = False;
1463Bool VG_(clo_trace_symtab) = False;
njn25e49d8e72002-09-23 09:36:25 +00001464Bool VG_(clo_trace_sched) = False;
1465Int VG_(clo_trace_pthread_level) = 0;
njn25e49d8e72002-09-23 09:36:25 +00001466Int VG_(clo_dump_error) = 0;
1467Int VG_(clo_backtrace_size) = 4;
1468Char* VG_(clo_weird_hacks) = NULL;
sewardj858964b2002-10-05 14:15:43 +00001469Bool VG_(clo_run_libc_freeres) = True;
rjwalshf5f536f2003-11-17 17:45:00 +00001470Bool VG_(clo_track_fds) = False;
sewardj22854b92002-11-30 14:00:47 +00001471Bool VG_(clo_chain_bb) = True;
nethercote77eba602003-11-13 17:35:04 +00001472Bool VG_(clo_show_below_main) = False;
fitzhardinge98abfc72003-12-16 02:05:15 +00001473Bool VG_(clo_pointercheck) = True;
fitzhardinge462f4f92003-12-18 02:10:54 +00001474Bool VG_(clo_branchpred) = False;
sewardj2370f3b2002-11-30 15:01:01 +00001475
jsgf855d93d2003-10-13 22:26:55 +00001476static Bool VG_(clo_wait_for_gdb) = False;
1477
1478/* If we're doing signal routing, poll for signals every 50mS by
1479 default. */
1480Int VG_(clo_signal_polltime) = 50;
1481
1482/* These flags reduce thread wakeup latency on syscall completion and
1483 signal delivery, respectively. The downside is possible unfairness. */
1484Bool VG_(clo_lowlat_syscalls) = False; /* low-latency syscalls */
1485Bool VG_(clo_lowlat_signals) = False; /* low-latency signals */
1486
sewardjde4a1d02002-03-22 01:27:54 +00001487
nethercote6c999f22004-01-31 22:55:15 +00001488void usage ( Bool debug_help )
njn7cf0bd32002-06-08 13:36:03 +00001489{
njn25e49d8e72002-09-23 09:36:25 +00001490 Char* usage1 =
nethercote71980f02004-01-24 18:18:54 +00001491"usage: valgrind --tool=<toolname> [options] prog-and-args\n"
njn25e49d8e72002-09-23 09:36:25 +00001492"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001493" common user options for all Valgrind tools, with defaults in [ ]:\n"
nethercote0d588502004-06-21 13:27:11 +00001494" --tool=<name> use the Valgrind tool named <name>\n"
nethercotea76368b2004-06-16 11:56:29 +00001495" -h --help show this message\n"
nethercote6c999f22004-01-31 22:55:15 +00001496" --help-debug show this message, plus debugging options\n"
njn25e49d8e72002-09-23 09:36:25 +00001497" --version show version\n"
njn25e49d8e72002-09-23 09:36:25 +00001498" -q --quiet run silently; only print error msgs\n"
1499" -v --verbose be more verbose, incl counts of errors\n"
nethercote77eba602003-11-13 17:35:04 +00001500" --trace-children=no|yes Valgrind-ise child processes? [no]\n"
nethercote0d588502004-06-21 13:27:11 +00001501" --track-fds=no|yes track open file descriptors? [no]\n"
thughes6233a382004-08-21 11:10:44 +00001502" --time-stamp=no|yes add timestamps to log messages? [no]\n"
nethercote2b0793f2003-12-02 10:41:18 +00001503"\n"
1504" uncommon user options for all Valgrind tools:\n"
nethercote0d588502004-06-21 13:27:11 +00001505" --run-libc-freeres=no|yes free up glibc memory at exit? [yes]\n"
1506" --weird-hacks=hack1,hack2,... recognised hacks: lax-ioctls [none]\n"
1507" --signal-polltime=<time> signal poll period (mS) for older kernels [50]\n"
1508" --lowlat-signals=no|yes improve thread signal wake-up latency [no]\n"
1509" --lowlat-syscalls=no|yes improve thread syscall wake-up latency [no]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001510" --pointercheck=no|yes enforce client address space limits [yes]\n"
njn25e49d8e72002-09-23 09:36:25 +00001511"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001512" user options for Valgrind tools that report errors:\n"
nethercotef8548672004-06-21 12:42:35 +00001513" --log-fd=<number> log messages to file descriptor [2=stderr]\n"
1514" --log-file=<file> log messages to <file>.pid<pid>\n"
1515" --log-socket=ipaddr:port log messages to socket ipaddr:port\n"
nethercote2b0793f2003-12-02 10:41:18 +00001516" --demangle=no|yes automatically demangle C++ names? [yes]\n"
1517" --num-callers=<number> show <num> callers in stack traces [4]\n"
1518" --error-limit=no|yes stop showing new errors if too many? [yes]\n"
1519" --show-below-main=no|yes continue stack traces below main() [no]\n"
1520" --suppressions=<filename> suppress errors described in <filename>\n"
1521" --gen-suppressions=no|yes print suppressions for errors detected [no]\n"
nethercote04d0fbc2004-01-26 16:48:06 +00001522" --db-attach=no|yes start debugger when errors detected? [no]\n"
1523" --db-command=<command> command to start debugger [gdb -nw %%f %%p]\n"
1524" --input-fd=<number> file descriptor for input [0=stdin]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001525"\n";
njn7cf0bd32002-06-08 13:36:03 +00001526
njn25e49d8e72002-09-23 09:36:25 +00001527 Char* usage2 =
1528"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001529" debugging options for all Valgrind tools:\n"
njn25e49d8e72002-09-23 09:36:25 +00001530" --sanity-level=<number> level of sanity checking to do [1]\n"
1531" --single-step=no|yes translate each instr separately? [no]\n"
1532" --optimise=no|yes improve intermediate code? [yes]\n"
nethercote137bc552003-11-14 17:47:54 +00001533" --profile=no|yes profile? (tool must be built for it) [no]\n"
sewardj22854b92002-11-30 14:00:47 +00001534" --chain-bb=no|yes do basic-block chaining? [yes]\n"
fitzhardinge462f4f92003-12-18 02:10:54 +00001535" --branchpred=yes|no generate branch prediction hints [no]\n"
njn25e49d8e72002-09-23 09:36:25 +00001536" --trace-codegen=<XXXXX> show generated code? (X = 0|1) [00000]\n"
1537" --trace-syscalls=no|yes show all system calls? [no]\n"
1538" --trace-signals=no|yes show signal handling details? [no]\n"
1539" --trace-symtab=no|yes show symbol table details? [no]\n"
njn25e49d8e72002-09-23 09:36:25 +00001540" --trace-sched=no|yes show thread scheduler details? [no]\n"
njn3e884182003-04-15 13:03:23 +00001541" --trace-pthread=none|some|all show pthread event details? [none]\n"
jsgf855d93d2003-10-13 22:26:55 +00001542" --wait-for-gdb=yes|no pause on startup to wait for gdb attach\n"
njn25e49d8e72002-09-23 09:36:25 +00001543"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001544" debugging options for Valgrind tools that report errors\n"
1545" --dump-error=<number> show translation for basic block associated\n"
1546" with <number>'th error context [0=show none]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001547"\n";
njn3e884182003-04-15 13:03:23 +00001548
1549 Char* usage3 =
1550"\n"
nethercote71980f02004-01-24 18:18:54 +00001551" Extra options read from ~/.valgrindrc, $VALGRIND_OPTS, ./.valgrindrc\n"
njn25e49d8e72002-09-23 09:36:25 +00001552"\n"
nethercote08fa9a72004-07-16 17:44:00 +00001553" Valgrind is Copyright (C) 2000-2004 Julian Seward et al.\n"
njn25e49d8e72002-09-23 09:36:25 +00001554" and licensed under the GNU General Public License, version 2.\n"
1555" Bug reports, feedback, admiration, abuse, etc, to: %s.\n"
njnd04b7c62002-10-03 14:05:52 +00001556"\n"
nethercote137bc552003-11-14 17:47:54 +00001557" Tools are copyright and licensed by their authors. See each\n"
1558" tool's start-up message for more information.\n"
njn25e49d8e72002-09-23 09:36:25 +00001559"\n";
njn7cf0bd32002-06-08 13:36:03 +00001560
fitzhardinge98abfc72003-12-16 02:05:15 +00001561 VG_(printf)(usage1);
1562 if (VG_(details).name) {
1563 VG_(printf)(" user options for %s:\n", VG_(details).name);
fitzhardinge98abfc72003-12-16 02:05:15 +00001564 if (VG_(needs).command_line_options)
1565 SK_(print_usage)();
1566 else
1567 VG_(printf)(" (none)\n");
1568 }
nethercote6c999f22004-01-31 22:55:15 +00001569 if (debug_help) {
1570 VG_(printf)(usage2);
fitzhardinge98abfc72003-12-16 02:05:15 +00001571
nethercote6c999f22004-01-31 22:55:15 +00001572 if (VG_(details).name) {
1573 VG_(printf)(" debugging options for %s:\n", VG_(details).name);
1574
1575 if (VG_(needs).command_line_options)
1576 SK_(print_debug_usage)();
1577 else
1578 VG_(printf)(" (none)\n");
1579 }
fitzhardinge98abfc72003-12-16 02:05:15 +00001580 }
nethercote421281e2003-11-20 16:20:55 +00001581 VG_(printf)(usage3, VG_BUGS_TO);
nethercotef4928da2004-06-15 10:54:40 +00001582 VG_(exit)(0);
njn7cf0bd32002-06-08 13:36:03 +00001583}
sewardjde4a1d02002-03-22 01:27:54 +00001584
nethercote71980f02004-01-24 18:18:54 +00001585static void pre_process_cmd_line_options
nethercote6c999f22004-01-31 22:55:15 +00001586 ( Int* need_help, const char** tool, const char** exec )
sewardj1c1b1162003-02-23 01:25:51 +00001587{
nethercote71980f02004-01-24 18:18:54 +00001588 UInt i;
sewardjde4a1d02002-03-22 01:27:54 +00001589
nethercote71980f02004-01-24 18:18:54 +00001590 /* parse the options we have (only the options we care about now) */
nethercotef6a1d502004-08-09 12:21:57 +00001591 for (i = 1; i < vg_argc; i++) {
nethercote71980f02004-01-24 18:18:54 +00001592
nethercotef6a1d502004-08-09 12:21:57 +00001593 if (strcmp(vg_argv[i], "--version") == 0) {
nethercote71980f02004-01-24 18:18:54 +00001594 printf("valgrind-" VERSION "\n");
nethercotef4928da2004-06-15 10:54:40 +00001595 exit(0);
nethercote71980f02004-01-24 18:18:54 +00001596
nethercotef6a1d502004-08-09 12:21:57 +00001597 } else if (VG_CLO_STREQ(vg_argv[i], "--help") ||
1598 VG_CLO_STREQ(vg_argv[i], "-h")) {
nethercote6c999f22004-01-31 22:55:15 +00001599 *need_help = 1;
1600
nethercotef6a1d502004-08-09 12:21:57 +00001601 } else if (VG_CLO_STREQ(vg_argv[i], "--help-debug")) {
nethercote6c999f22004-01-31 22:55:15 +00001602 *need_help = 2;
nethercote71980f02004-01-24 18:18:54 +00001603
nethercotef6a1d502004-08-09 12:21:57 +00001604 } else if (VG_CLO_STREQN(7, vg_argv[i], "--tool=") ||
1605 VG_CLO_STREQN(7, vg_argv[i], "--skin=")) {
1606 *tool = &vg_argv[i][7];
nethercote71980f02004-01-24 18:18:54 +00001607
nethercotef6a1d502004-08-09 12:21:57 +00001608 } else if (VG_CLO_STREQN(7, vg_argv[i], "--exec=")) {
1609 *exec = &vg_argv[i][7];
nethercote71980f02004-01-24 18:18:54 +00001610 }
1611 }
1612
nethercotef4928da2004-06-15 10:54:40 +00001613 /* If no tool specified, can act appropriately without loading tool */
nethercote71980f02004-01-24 18:18:54 +00001614 if (*tool == NULL) {
nethercotef4928da2004-06-15 10:54:40 +00001615 if (0 == *need_help) {
1616 // neither --tool nor --help/--help-debug specified
1617 missing_tool_option();
1618 } else {
1619 // Give help message, without any tool-specific help
1620 usage(/*help-debug?*/2 == *need_help);
1621 }
nethercote71980f02004-01-24 18:18:54 +00001622 }
1623}
1624
nethercote5ee67ca2004-06-22 14:00:09 +00001625static void process_cmd_line_options( UInt* client_auxv, const char* toolname )
nethercote71980f02004-01-24 18:18:54 +00001626{
nethercotef8548672004-06-21 12:42:35 +00001627 Int i, eventually_log_fd;
nethercote71980f02004-01-24 18:18:54 +00001628 Int *auxp;
1629 Int toolname_len = VG_(strlen)(toolname);
sewardjde4a1d02002-03-22 01:27:54 +00001630
nethercotee1730692003-11-20 10:38:07 +00001631 /* log to stderr by default, but usage message goes to stdout */
nethercotef8548672004-06-21 12:42:35 +00001632 eventually_log_fd = 2;
sewardjde4a1d02002-03-22 01:27:54 +00001633
sewardj19d81412002-06-03 01:10:40 +00001634 /* Check for sane path in ./configure --prefix=... */
fitzhardinge98abfc72003-12-16 02:05:15 +00001635 if (VG_LIBDIR[0] != '/')
sewardj19d81412002-06-03 01:10:40 +00001636 config_error("Please use absolute paths in "
1637 "./configure --prefix=... or --libdir=...");
sewardj38170912002-05-10 21:07:22 +00001638
nethercote71980f02004-01-24 18:18:54 +00001639 for (auxp = client_auxv; auxp[0] != VKI_AT_NULL; auxp += 2) {
fitzhardinge98abfc72003-12-16 02:05:15 +00001640 switch(auxp[0]) {
1641 case VKI_AT_SYSINFO:
fitzhardinge92360792003-12-24 10:11:11 +00001642 auxp[1] = (Int)(VG_(client_trampoline_code) + VG_(tramp_syscall_offset));
fitzhardinge98abfc72003-12-16 02:05:15 +00001643 break;
sewardjde4a1d02002-03-22 01:27:54 +00001644 }
fitzhardinge98abfc72003-12-16 02:05:15 +00001645 }
sewardjde4a1d02002-03-22 01:27:54 +00001646
nethercotef6a1d502004-08-09 12:21:57 +00001647 for (i = 1; i < vg_argc; i++) {
nethercote71980f02004-01-24 18:18:54 +00001648
nethercotef6a1d502004-08-09 12:21:57 +00001649 Char* arg = vg_argv[i];
thughes3bfd5a02004-07-18 08:05:44 +00001650 Char* colon = arg;
nethercote71980f02004-01-24 18:18:54 +00001651
thughes3bfd5a02004-07-18 08:05:44 +00001652 /* Look for a colon in the switch name */
1653 while (*colon && *colon != ':' && *colon != '=')
1654 colon++;
nethercote71980f02004-01-24 18:18:54 +00001655
1656 /* Look for matching "--toolname:foo" */
thughes3bfd5a02004-07-18 08:05:44 +00001657 if (*colon == ':') {
nethercote71980f02004-01-24 18:18:54 +00001658 if (VG_CLO_STREQN(2, arg, "--") &&
1659 VG_CLO_STREQN(toolname_len, arg+2, toolname) &&
1660 VG_CLO_STREQN(1, arg+2+toolname_len, ":"))
1661 {
1662 // prefix matches, convert "--toolname:foo" to "--foo"
1663 if (0)
1664 VG_(printf)("tool-specific arg: %s\n", arg);
1665 arg += toolname_len + 1;
1666 arg[0] = '-';
1667 arg[1] = '-';
1668
1669 } else {
1670 // prefix doesn't match, skip to next arg
1671 continue;
1672 }
1673 }
1674
fitzhardinge98abfc72003-12-16 02:05:15 +00001675 /* Ignore these options - they've already been handled */
nethercote71980f02004-01-24 18:18:54 +00001676 if (VG_CLO_STREQN(7, arg, "--tool=") ||
1677 VG_CLO_STREQN(7, arg, "--skin="))
fitzhardinge98abfc72003-12-16 02:05:15 +00001678 continue;
nethercote71980f02004-01-24 18:18:54 +00001679 if (VG_CLO_STREQN(7, arg, "--exec="))
fitzhardinge98abfc72003-12-16 02:05:15 +00001680 continue;
1681
nethercote71980f02004-01-24 18:18:54 +00001682 if ( VG_CLO_STREQ(arg, "--"))
fitzhardinge98abfc72003-12-16 02:05:15 +00001683 continue;
nethercote27fec902004-06-16 21:26:32 +00001684
nethercote71980f02004-01-24 18:18:54 +00001685 else if (VG_CLO_STREQ(arg, "-v") ||
1686 VG_CLO_STREQ(arg, "--verbose"))
sewardjde4a1d02002-03-22 01:27:54 +00001687 VG_(clo_verbosity)++;
nethercote27fec902004-06-16 21:26:32 +00001688
nethercote71980f02004-01-24 18:18:54 +00001689 else if (VG_CLO_STREQ(arg, "-q") ||
1690 VG_CLO_STREQ(arg, "--quiet"))
sewardjde4a1d02002-03-22 01:27:54 +00001691 VG_(clo_verbosity)--;
1692
nethercote27fec902004-06-16 21:26:32 +00001693 else VG_BOOL_CLO("--branchpred", VG_(clo_branchpred))
1694 else VG_BOOL_CLO("--chain-bb", VG_(clo_chain_bb))
1695 else VG_BOOL_CLO("--db-attach", VG_(clo_db_attach))
1696 else VG_BOOL_CLO("--demangle", VG_(clo_demangle))
1697 else VG_BOOL_CLO("--error-limit", VG_(clo_error_limit))
1698 else VG_BOOL_CLO("--gen-suppressions", VG_(clo_gen_suppressions))
1699 else VG_BOOL_CLO("--lowlat-signals", VG_(clo_lowlat_signals))
1700 else VG_BOOL_CLO("--lowlat-syscalls", VG_(clo_lowlat_syscalls))
1701 else VG_BOOL_CLO("--optimise", VG_(clo_optimise))
1702 else VG_BOOL_CLO("--pointercheck", VG_(clo_pointercheck))
1703 else VG_BOOL_CLO("--profile", VG_(clo_profile))
1704 else VG_BOOL_CLO("--run-libc-freeres", VG_(clo_run_libc_freeres))
1705 else VG_BOOL_CLO("--show-below-main", VG_(clo_show_below_main))
1706 else VG_BOOL_CLO("--single-step", VG_(clo_single_step))
thughes6233a382004-08-21 11:10:44 +00001707 else VG_BOOL_CLO("--time-stamp", VG_(clo_time_stamp))
nethercote27fec902004-06-16 21:26:32 +00001708 else VG_BOOL_CLO("--track-fds", VG_(clo_track_fds))
1709 else VG_BOOL_CLO("--trace-children", VG_(clo_trace_children))
1710 else VG_BOOL_CLO("--trace-sched", VG_(clo_trace_sched))
1711 else VG_BOOL_CLO("--trace-signals", VG_(clo_trace_signals))
1712 else VG_BOOL_CLO("--trace-symtab", VG_(clo_trace_symtab))
1713 else VG_BOOL_CLO("--trace-syscalls", VG_(clo_trace_syscalls))
1714 else VG_BOOL_CLO("--wait-for-gdb", VG_(clo_wait_for_gdb))
sewardj72f98ff2002-06-13 17:23:38 +00001715
nethercote27fec902004-06-16 21:26:32 +00001716 else VG_STR_CLO ("--db-command", VG_(clo_db_command))
1717 else VG_STR_CLO ("--weird-hacks", VG_(clo_weird_hacks))
sewardjde4a1d02002-03-22 01:27:54 +00001718
nethercote27fec902004-06-16 21:26:32 +00001719 else VG_NUM_CLO ("--dump-error", VG_(clo_dump_error))
1720 else VG_NUM_CLO ("--input-fd", VG_(clo_input_fd))
1721 else VG_NUM_CLO ("--sanity-level", VG_(clo_sanity_level))
1722 else VG_NUM_CLO ("--signal­polltime", VG_(clo_signal_polltime))
1723 else VG_BNUM_CLO("--num-callers", VG_(clo_backtrace_size), 1,
1724 VG_DEEPEST_BACKTRACE)
sewardjde4a1d02002-03-22 01:27:54 +00001725
nethercotef8548672004-06-21 12:42:35 +00001726 // for backwards compatibility, replaced by --log-fd
nethercote71980f02004-01-24 18:18:54 +00001727 else if (VG_CLO_STREQN(13, arg, "--logfile-fd=")) {
nethercotef8548672004-06-21 12:42:35 +00001728 VG_(clo_log_to) = VgLogTo_Fd;
1729 VG_(clo_log_name) = NULL;
1730 eventually_log_fd = (Int)VG_(atoll)(&arg[13]);
1731 }
1732 else if (VG_CLO_STREQN(9, arg, "--log-fd=")) {
1733 VG_(clo_log_to) = VgLogTo_Fd;
1734 VG_(clo_log_name) = NULL;
1735 eventually_log_fd = (Int)VG_(atoll)(&arg[9]);
sewardj4cf05692002-10-27 20:28:29 +00001736 }
1737
nethercotef8548672004-06-21 12:42:35 +00001738 // for backwards compatibility, replaced by --log-file
nethercote71980f02004-01-24 18:18:54 +00001739 else if (VG_CLO_STREQN(10, arg, "--logfile=")) {
nethercotef8548672004-06-21 12:42:35 +00001740 VG_(clo_log_to) = VgLogTo_File;
1741 VG_(clo_log_name) = &arg[10];
1742 }
1743 else if (VG_CLO_STREQN(11, arg, "--log-file=")) {
1744 VG_(clo_log_to) = VgLogTo_File;
1745 VG_(clo_log_name) = &arg[11];
sewardj4cf05692002-10-27 20:28:29 +00001746 }
sewardjde4a1d02002-03-22 01:27:54 +00001747
nethercotef8548672004-06-21 12:42:35 +00001748 // for backwards compatibility, replaced by --log-socket
nethercote71980f02004-01-24 18:18:54 +00001749 else if (VG_CLO_STREQN(12, arg, "--logsocket=")) {
nethercotef8548672004-06-21 12:42:35 +00001750 VG_(clo_log_to) = VgLogTo_Socket;
1751 VG_(clo_log_name) = &arg[12];
1752 }
1753 else if (VG_CLO_STREQN(13, arg, "--log-socket=")) {
1754 VG_(clo_log_to) = VgLogTo_Socket;
1755 VG_(clo_log_name) = &arg[13];
sewardj73cf3bc2002-11-03 03:20:15 +00001756 }
1757
nethercote71980f02004-01-24 18:18:54 +00001758 else if (VG_CLO_STREQN(15, arg, "--suppressions=")) {
sewardjde4a1d02002-03-22 01:27:54 +00001759 if (VG_(clo_n_suppressions) >= VG_CLO_MAX_SFILES) {
njn25e49d8e72002-09-23 09:36:25 +00001760 VG_(message)(Vg_UserMsg, "Too many suppression files specified.");
sewardjde4a1d02002-03-22 01:27:54 +00001761 VG_(message)(Vg_UserMsg,
1762 "Increase VG_CLO_MAX_SFILES and recompile.");
nethercote71980f02004-01-24 18:18:54 +00001763 VG_(bad_option)(arg);
sewardjde4a1d02002-03-22 01:27:54 +00001764 }
nethercote71980f02004-01-24 18:18:54 +00001765 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = &arg[15];
sewardjde4a1d02002-03-22 01:27:54 +00001766 VG_(clo_n_suppressions)++;
1767 }
sewardjde4a1d02002-03-22 01:27:54 +00001768
njn25e49d8e72002-09-23 09:36:25 +00001769 /* "vwxyz" --> 000zyxwv (binary) */
nethercote71980f02004-01-24 18:18:54 +00001770 else if (VG_CLO_STREQN(16, arg, "--trace-codegen=")) {
njn25e49d8e72002-09-23 09:36:25 +00001771 Int j;
nethercote71980f02004-01-24 18:18:54 +00001772 char* opt = & arg[16];
njn25e49d8e72002-09-23 09:36:25 +00001773
1774 if (5 != VG_(strlen)(opt)) {
1775 VG_(message)(Vg_UserMsg,
1776 "--trace-codegen argument must have 5 digits");
nethercote71980f02004-01-24 18:18:54 +00001777 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001778 }
1779 for (j = 0; j < 5; j++) {
1780 if ('0' == opt[j]) { /* do nothing */ }
1781 else if ('1' == opt[j]) VG_(clo_trace_codegen) |= (1 << j);
1782 else {
1783 VG_(message)(Vg_UserMsg, "--trace-codegen argument can only "
1784 "contain 0s and 1s");
nethercote71980f02004-01-24 18:18:54 +00001785 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001786 }
1787 }
1788 }
sewardjde4a1d02002-03-22 01:27:54 +00001789
nethercote71980f02004-01-24 18:18:54 +00001790 else if (VG_CLO_STREQ(arg, "--trace-pthread=none"))
sewardj45b4b372002-04-16 22:50:32 +00001791 VG_(clo_trace_pthread_level) = 0;
nethercote71980f02004-01-24 18:18:54 +00001792 else if (VG_CLO_STREQ(arg, "--trace-pthread=some"))
sewardj45b4b372002-04-16 22:50:32 +00001793 VG_(clo_trace_pthread_level) = 1;
nethercote71980f02004-01-24 18:18:54 +00001794 else if (VG_CLO_STREQ(arg, "--trace-pthread=all"))
sewardj45b4b372002-04-16 22:50:32 +00001795 VG_(clo_trace_pthread_level) = 2;
sewardj8937c812002-04-12 20:12:20 +00001796
nethercote71980f02004-01-24 18:18:54 +00001797 else if ( ! VG_(needs).command_line_options
1798 || ! SK_(process_cmd_line_option)(arg) ) {
nethercotef4928da2004-06-15 10:54:40 +00001799 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001800 }
sewardjde4a1d02002-03-22 01:27:54 +00001801 }
1802
nethercote27fec902004-06-16 21:26:32 +00001803 // Check various option values
1804
njnf9ebf672003-05-12 21:41:30 +00001805 if (VG_(clo_verbosity) < 0)
sewardjde4a1d02002-03-22 01:27:54 +00001806 VG_(clo_verbosity) = 0;
1807
nethercote04d0fbc2004-01-26 16:48:06 +00001808 if (VG_(clo_db_attach) && VG_(clo_trace_children)) {
sewardjde4a1d02002-03-22 01:27:54 +00001809 VG_(message)(Vg_UserMsg, "");
1810 VG_(message)(Vg_UserMsg,
nethercote04d0fbc2004-01-26 16:48:06 +00001811 "--db-attach=yes conflicts with --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001812 VG_(message)(Vg_UserMsg,
1813 "Please choose one or the other, but not both.");
nethercote04d0fbc2004-01-26 16:48:06 +00001814 VG_(bad_option)("--db-attach=yes and --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001815 }
1816
nethercotef8548672004-06-21 12:42:35 +00001817 /* Set up logging now. After this is done, VG_(clo_log_fd)
sewardj4cf05692002-10-27 20:28:29 +00001818 should be connected to whatever sink has been selected, and we
1819 indiscriminately chuck stuff into it without worrying what the
1820 nature of it is. Oh the wonder of Unix streams. */
1821
nethercotee1730692003-11-20 10:38:07 +00001822 /* So far we should be still attached to stdout, so we can show on
sewardj4cf05692002-10-27 20:28:29 +00001823 the terminal any problems to do with processing command line
1824 opts. */
nethercotef8548672004-06-21 12:42:35 +00001825 vg_assert(VG_(clo_log_fd) == 1 /* stdout */);
sewardj73cf3bc2002-11-03 03:20:15 +00001826 vg_assert(VG_(logging_to_filedes) == True);
sewardj4cf05692002-10-27 20:28:29 +00001827
1828 switch (VG_(clo_log_to)) {
sewardj73cf3bc2002-11-03 03:20:15 +00001829
sewardj4cf05692002-10-27 20:28:29 +00001830 case VgLogTo_Fd:
nethercotef8548672004-06-21 12:42:35 +00001831 vg_assert(VG_(clo_log_name) == NULL);
1832 VG_(clo_log_fd) = eventually_log_fd;
sewardj4cf05692002-10-27 20:28:29 +00001833 break;
sewardj73cf3bc2002-11-03 03:20:15 +00001834
sewardj4cf05692002-10-27 20:28:29 +00001835 case VgLogTo_File: {
1836 Char logfilename[1000];
jsgff3c3f1a2003-10-14 22:13:28 +00001837 Int seq = 0;
1838 Int pid = VG_(getpid)();
1839
nethercotef8548672004-06-21 12:42:35 +00001840 vg_assert(VG_(clo_log_name) != NULL);
1841 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
jsgff3c3f1a2003-10-14 22:13:28 +00001842
nethercote71980f02004-01-24 18:18:54 +00001843 for (;;) {
jsgff3c3f1a2003-10-14 22:13:28 +00001844 if (seq == 0)
1845 VG_(sprintf)(logfilename, "%s.pid%d",
nethercotef8548672004-06-21 12:42:35 +00001846 VG_(clo_log_name), pid );
jsgff3c3f1a2003-10-14 22:13:28 +00001847 else
1848 VG_(sprintf)(logfilename, "%s.pid%d.%d",
nethercotef8548672004-06-21 12:42:35 +00001849 VG_(clo_log_name), pid, seq );
jsgff3c3f1a2003-10-14 22:13:28 +00001850 seq++;
1851
nethercotef8548672004-06-21 12:42:35 +00001852 eventually_log_fd
jsgff3c3f1a2003-10-14 22:13:28 +00001853 = VG_(open)(logfilename,
1854 VKI_O_CREAT|VKI_O_WRONLY|VKI_O_EXCL|VKI_O_TRUNC,
1855 VKI_S_IRUSR|VKI_S_IWUSR);
nethercotef8548672004-06-21 12:42:35 +00001856 if (eventually_log_fd >= 0) {
1857 VG_(clo_log_fd) = VG_(safe_fd)(eventually_log_fd);
jsgff3c3f1a2003-10-14 22:13:28 +00001858 break;
1859 } else {
nethercotef8548672004-06-21 12:42:35 +00001860 if (eventually_log_fd != -VKI_EEXIST) {
jsgff3c3f1a2003-10-14 22:13:28 +00001861 VG_(message)(Vg_UserMsg,
1862 "Can't create/open log file `%s.pid%d'; giving up!",
nethercotef8548672004-06-21 12:42:35 +00001863 VG_(clo_log_name), pid);
jsgff3c3f1a2003-10-14 22:13:28 +00001864 VG_(bad_option)(
nethercotef8548672004-06-21 12:42:35 +00001865 "--log-file=<file> didn't work out for some reason.");
jsgff3c3f1a2003-10-14 22:13:28 +00001866 break;
1867 }
1868 }
1869 }
sewardj4cf05692002-10-27 20:28:29 +00001870 break;
sewardj73cf3bc2002-11-03 03:20:15 +00001871 }
1872
1873 case VgLogTo_Socket: {
nethercotef8548672004-06-21 12:42:35 +00001874 vg_assert(VG_(clo_log_name) != NULL);
1875 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
1876 eventually_log_fd = VG_(connect_via_socket)( VG_(clo_log_name) );
1877 if (eventually_log_fd == -1) {
sewardj73cf3bc2002-11-03 03:20:15 +00001878 VG_(message)(Vg_UserMsg,
nethercotef8548672004-06-21 12:42:35 +00001879 "Invalid --log-socket=ipaddr or --log-socket=ipaddr:port spec");
sewardj73cf3bc2002-11-03 03:20:15 +00001880 VG_(message)(Vg_UserMsg,
nethercotef8548672004-06-21 12:42:35 +00001881 "of `%s'; giving up!", VG_(clo_log_name) );
sewardj73cf3bc2002-11-03 03:20:15 +00001882 VG_(bad_option)(
nethercotef8548672004-06-21 12:42:35 +00001883 "--log-socket=");
sewardj4cf05692002-10-27 20:28:29 +00001884 }
nethercotef8548672004-06-21 12:42:35 +00001885 if (eventually_log_fd == -2) {
sewardj73cf3bc2002-11-03 03:20:15 +00001886 VG_(message)(Vg_UserMsg,
sewardj570f8902002-11-03 11:44:36 +00001887 "valgrind: failed to connect to logging server `%s'.",
nethercotef8548672004-06-21 12:42:35 +00001888 VG_(clo_log_name) );
sewardj570f8902002-11-03 11:44:36 +00001889 VG_(message)(Vg_UserMsg,
1890 "Log messages will sent to stderr instead." );
1891 VG_(message)(Vg_UserMsg,
1892 "" );
1893 /* We don't change anything here. */
1894 } else {
nethercotef8548672004-06-21 12:42:35 +00001895 vg_assert(eventually_log_fd > 0);
1896 VG_(clo_log_fd) = eventually_log_fd;
sewardj570f8902002-11-03 11:44:36 +00001897 VG_(logging_to_filedes) = False;
1898 }
sewardj73cf3bc2002-11-03 03:20:15 +00001899 break;
1900 }
1901
sewardj4cf05692002-10-27 20:28:29 +00001902 }
1903
nethercotef8548672004-06-21 12:42:35 +00001904 /* Move log_fd into the safe range, so it doesn't conflict with any app fds */
thughesad1c9562004-06-26 11:27:52 +00001905 eventually_log_fd = VG_(fcntl)(VG_(clo_log_fd), VKI_F_DUPFD, VG_(fd_hard_limit));
nethercotef8548672004-06-21 12:42:35 +00001906 if (eventually_log_fd < 0)
jsgf855d93d2003-10-13 22:26:55 +00001907 VG_(message)(Vg_UserMsg, "valgrind: failed to move logfile fd into safe range");
1908 else {
nethercotef8548672004-06-21 12:42:35 +00001909 VG_(clo_log_fd) = eventually_log_fd;
1910 VG_(fcntl)(VG_(clo_log_fd), VKI_F_SETFD, VKI_FD_CLOEXEC);
jsgf855d93d2003-10-13 22:26:55 +00001911 }
1912
sewardj4cf05692002-10-27 20:28:29 +00001913 /* Ok, the logging sink is running now. Print a suitable preamble.
1914 If logging to file or a socket, write details of parent PID and
1915 command line args, to help people trying to interpret the
1916 results of a run which encompasses multiple processes. */
sewardjde4a1d02002-03-22 01:27:54 +00001917
sewardj83adf412002-05-01 01:25:45 +00001918 if (VG_(clo_verbosity > 0)) {
nethercote996901a2004-08-03 13:29:09 +00001919 /* Tool details */
njnd04b7c62002-10-03 14:05:52 +00001920 VG_(message)(Vg_UserMsg, "%s%s%s, %s for x86-linux.",
1921 VG_(details).name,
1922 NULL == VG_(details).version ? "" : "-",
1923 NULL == VG_(details).version
1924 ? (Char*)"" : VG_(details).version,
1925 VG_(details).description);
1926 VG_(message)(Vg_UserMsg, "%s", VG_(details).copyright_author);
sewardj3b2736a2002-03-24 12:18:35 +00001927
njnd04b7c62002-10-03 14:05:52 +00001928 /* Core details */
1929 VG_(message)(Vg_UserMsg,
njn3e884182003-04-15 13:03:23 +00001930 "Using valgrind-%s, a program supervision framework for x86-linux.",
sewardj4aa62ba2002-10-05 15:49:27 +00001931 VERSION);
sewardjde4a1d02002-03-22 01:27:54 +00001932 VG_(message)(Vg_UserMsg,
nethercote08fa9a72004-07-16 17:44:00 +00001933 "Copyright (C) 2000-2004, and GNU GPL'd, by Julian Seward et al.");
njnd04b7c62002-10-03 14:05:52 +00001934 }
1935
nethercotec1e395d2003-11-10 13:26:49 +00001936 if (VG_(clo_verbosity) > 0 && VG_(clo_log_to) != VgLogTo_Fd) {
sewardj4cf05692002-10-27 20:28:29 +00001937 VG_(message)(Vg_UserMsg, "");
1938 VG_(message)(Vg_UserMsg,
1939 "My PID = %d, parent PID = %d. Prog and args are:",
1940 VG_(getpid)(), VG_(getppid)() );
1941 for (i = 0; i < VG_(client_argc); i++)
1942 VG_(message)(Vg_UserMsg, " %s", VG_(client_argv)[i]);
1943 }
1944
sewardjde4a1d02002-03-22 01:27:54 +00001945 if (VG_(clo_verbosity) > 1) {
nethercotea70f7352004-04-18 12:08:46 +00001946 Int fd;
sewardj4cf05692002-10-27 20:28:29 +00001947 if (VG_(clo_log_to) != VgLogTo_Fd)
1948 VG_(message)(Vg_UserMsg, "");
fitzhardinge98abfc72003-12-16 02:05:15 +00001949 VG_(message)(Vg_UserMsg, "Valgrind library directory: %s", VG_(libdir));
njn86dc2bc2003-09-09 07:26:21 +00001950 VG_(message)(Vg_UserMsg, "Command line");
1951 for (i = 0; i < VG_(client_argc); i++)
1952 VG_(message)(Vg_UserMsg, " %s", VG_(client_argv)[i]);
1953
sewardjde4a1d02002-03-22 01:27:54 +00001954 VG_(message)(Vg_UserMsg, "Startup, with flags:");
nethercotef6a1d502004-08-09 12:21:57 +00001955 for (i = 1; i < vg_argc; i++) {
1956 VG_(message)(Vg_UserMsg, " %s", vg_argv[i]);
sewardjde4a1d02002-03-22 01:27:54 +00001957 }
nethercotea70f7352004-04-18 12:08:46 +00001958
1959 VG_(message)(Vg_UserMsg, "Contents of /proc/version:");
1960 fd = VG_(open) ( "/proc/version", VKI_O_RDONLY, 0 );
1961 if (fd < 0) {
1962 VG_(message)(Vg_UserMsg, " can't open /proc/version");
1963 } else {
1964 #define BUF_LEN 256
1965 Char version_buf[BUF_LEN];
1966 Int n = VG_(read) ( fd, version_buf, BUF_LEN );
1967 vg_assert(n <= 256);
1968 if (n > 0) {
1969 version_buf[n-1] = '\0';
1970 VG_(message)(Vg_UserMsg, " %s", version_buf);
1971 } else {
1972 VG_(message)(Vg_UserMsg, " (empty?)");
1973 }
1974 VG_(close)(fd);
1975 #undef BUF_LEN
1976 }
sewardjde4a1d02002-03-22 01:27:54 +00001977 }
1978
fitzhardinge98abfc72003-12-16 02:05:15 +00001979 if (VG_(clo_n_suppressions) < VG_CLO_MAX_SFILES-1 &&
njn25e49d8e72002-09-23 09:36:25 +00001980 (VG_(needs).core_errors || VG_(needs).skin_errors)) {
nethercote996901a2004-08-03 13:29:09 +00001981 /* If there are no suppression files specified and the tool
fitzhardinge98abfc72003-12-16 02:05:15 +00001982 needs one, load the default */
1983 static const Char default_supp[] = "default.supp";
1984 Int len = VG_(strlen)(VG_(libdir)) + 1 + sizeof(default_supp);
1985 Char *buf = VG_(arena_malloc)(VG_AR_CORE, len);
1986 VG_(sprintf)(buf, "%s/%s", VG_(libdir), default_supp);
1987 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = buf;
1988 VG_(clo_n_suppressions)++;
sewardjde4a1d02002-03-22 01:27:54 +00001989 }
sewardj4cf05692002-10-27 20:28:29 +00001990
njn6a230532003-07-21 10:38:23 +00001991 if (VG_(clo_gen_suppressions) &&
1992 !VG_(needs).core_errors && !VG_(needs).skin_errors) {
nethercotef4928da2004-06-15 10:54:40 +00001993 VG_(message)(Vg_UserMsg,
1994 "Can't use --gen-suppressions=yes with this tool,");
1995 VG_(message)(Vg_UserMsg,
1996 "as it doesn't generate errors.");
1997 VG_(bad_option)("--gen-suppressions=yes");
njn6a230532003-07-21 10:38:23 +00001998 }
sewardjde4a1d02002-03-22 01:27:54 +00001999}
2000
nethercotef6a1d502004-08-09 12:21:57 +00002001// Build the string for VALGRINDCLO.
2002Char* VG_(build_child_VALGRINDCLO)( Char* exename )
2003{
2004 /* If we're tracing the children, then we need to start it
2005 with our starter+arguments, which are copied into VALGRINDCLO,
2006 except the --exec= option is changed if present.
2007 */
2008 Int i;
2009 Char *exec;
2010 Char *cp;
2011 Char *optvar;
2012 Int optlen, execlen;
2013
2014 // All these allocated blocks are not free - because we're either
2015 // going to exec, or panic when we fail.
2016
2017 // Create --exec= option: "--exec=<exename>"
2018 exec = VG_(arena_malloc)(VG_AR_CORE,
2019 VG_(strlen)( exename ) + 7/*--exec=*/ + 1/*\0*/);
2020 vg_assert(NULL != exec);
2021 VG_(sprintf)(exec, "--exec=%s", exename);
2022
2023 // Allocate space for optvar (may overestimate by counting --exec twice,
2024 // no matter)
2025 optlen = 1;
2026 for (i = 0; i < vg_argc; i++)
2027 optlen += VG_(strlen)(vg_argv[i]) + 1;
2028 optlen += VG_(strlen)(exec)+1;
2029 optvar = VG_(arena_malloc)(VG_AR_CORE, optlen);
2030
2031 // Copy all valgrind args except the old --exec (if present)
2032 // VG_CLO_SEP is the separator.
2033 cp = optvar;
2034 for (i = 1; i < vg_argc; i++) {
2035 Char *arg = vg_argv[i];
2036
2037 if (VG_(memcmp)(arg, "--exec=", 7) == 0) {
2038 // don't copy existing --exec= arg
2039 } else if (VG_(strcmp)(arg, "--") == 0) {
2040 // stop at "--"
2041 break;
2042 } else {
2043 // copy non "--exec" arg
2044 Int len = VG_(strlen)(arg);
2045 VG_(memcpy)(cp, arg, len);
2046 cp += len;
2047 *cp++ = VG_CLO_SEP;
2048 }
2049 }
2050 // Add the new --exec= option
2051 execlen = VG_(strlen)(exec);
2052 VG_(memcpy)(cp, exec, execlen);
2053 cp += execlen;
2054 *cp++ = VG_CLO_SEP;
2055
2056 *cp = '\0';
2057
2058 return optvar;
2059}
2060
2061// Build "/proc/self/fd/<execfd>".
2062Char* VG_(build_child_exename)( void )
2063{
2064 Char* exename = VG_(arena_malloc)(VG_AR_CORE, 64);
2065 vg_assert(NULL != exename);
2066 VG_(sprintf)(exename, "/proc/self/fd/%d", vgexecfd);
2067 return exename;
2068}
2069
sewardjde4a1d02002-03-22 01:27:54 +00002070
nethercote71980f02004-01-24 18:18:54 +00002071/*====================================================================*/
2072/*=== File descriptor setup ===*/
2073/*====================================================================*/
2074
2075static void setup_file_descriptors(void)
2076{
2077 struct vki_rlimit rl;
2078
2079 /* Get the current file descriptor limits. */
2080 if (VG_(getrlimit)(VKI_RLIMIT_NOFILE, &rl) < 0) {
2081 rl.rlim_cur = 1024;
2082 rl.rlim_max = 1024;
2083 }
2084
2085 /* Work out where to move the soft limit to. */
2086 if (rl.rlim_cur + VG_N_RESERVED_FDS <= rl.rlim_max) {
2087 rl.rlim_cur = rl.rlim_cur + VG_N_RESERVED_FDS;
2088 } else {
2089 rl.rlim_cur = rl.rlim_max;
2090 }
2091
2092 /* Reserve some file descriptors for our use. */
thughesad1c9562004-06-26 11:27:52 +00002093 VG_(fd_soft_limit) = rl.rlim_cur - VG_N_RESERVED_FDS;
2094 VG_(fd_hard_limit) = rl.rlim_cur - VG_N_RESERVED_FDS;
nethercote71980f02004-01-24 18:18:54 +00002095
2096 /* Update the soft limit. */
2097 VG_(setrlimit)(VKI_RLIMIT_NOFILE, &rl);
2098
nethercotef6a1d502004-08-09 12:21:57 +00002099 if (vgexecfd != -1)
2100 vgexecfd = VG_(safe_fd)( vgexecfd );
nethercote71980f02004-01-24 18:18:54 +00002101 if (VG_(clexecfd) != -1)
2102 VG_(clexecfd) = VG_(safe_fd)( VG_(clexecfd) );
2103}
2104
2105
2106/*====================================================================*/
nethercote1d447092004-02-01 17:29:59 +00002107/*=== baseBlock: definition + setup ===*/
nethercote71980f02004-01-24 18:18:54 +00002108/*====================================================================*/
2109
2110/* The variables storing offsets. */
2111
2112#define INVALID_OFFSET (-1)
2113
2114Int VGOFF_(m_eax) = INVALID_OFFSET;
2115Int VGOFF_(m_ecx) = INVALID_OFFSET;
2116Int VGOFF_(m_edx) = INVALID_OFFSET;
2117Int VGOFF_(m_ebx) = INVALID_OFFSET;
2118Int VGOFF_(m_esp) = INVALID_OFFSET;
2119Int VGOFF_(m_ebp) = INVALID_OFFSET;
2120Int VGOFF_(m_esi) = INVALID_OFFSET;
2121Int VGOFF_(m_edi) = INVALID_OFFSET;
2122Int VGOFF_(m_eflags) = INVALID_OFFSET;
2123Int VGOFF_(m_dflag) = INVALID_OFFSET;
2124Int VGOFF_(m_ssestate) = INVALID_OFFSET;
2125Int VGOFF_(ldt) = INVALID_OFFSET;
nethercoted8510ec2004-08-18 23:11:45 +00002126Int VGOFF_(tls_ptr) = INVALID_OFFSET;
nethercote71980f02004-01-24 18:18:54 +00002127Int VGOFF_(m_cs) = INVALID_OFFSET;
2128Int VGOFF_(m_ss) = INVALID_OFFSET;
2129Int VGOFF_(m_ds) = INVALID_OFFSET;
2130Int VGOFF_(m_es) = INVALID_OFFSET;
2131Int VGOFF_(m_fs) = INVALID_OFFSET;
2132Int VGOFF_(m_gs) = INVALID_OFFSET;
2133Int VGOFF_(m_eip) = INVALID_OFFSET;
2134Int VGOFF_(spillslots) = INVALID_OFFSET;
2135Int VGOFF_(sh_eax) = INVALID_OFFSET;
2136Int VGOFF_(sh_ecx) = INVALID_OFFSET;
2137Int VGOFF_(sh_edx) = INVALID_OFFSET;
2138Int VGOFF_(sh_ebx) = INVALID_OFFSET;
2139Int VGOFF_(sh_esp) = INVALID_OFFSET;
2140Int VGOFF_(sh_ebp) = INVALID_OFFSET;
2141Int VGOFF_(sh_esi) = INVALID_OFFSET;
2142Int VGOFF_(sh_edi) = INVALID_OFFSET;
2143Int VGOFF_(sh_eflags) = INVALID_OFFSET;
2144
2145Int VGOFF_(helper_idiv_64_32) = INVALID_OFFSET;
2146Int VGOFF_(helper_div_64_32) = INVALID_OFFSET;
2147Int VGOFF_(helper_idiv_32_16) = INVALID_OFFSET;
2148Int VGOFF_(helper_div_32_16) = INVALID_OFFSET;
2149Int VGOFF_(helper_idiv_16_8) = INVALID_OFFSET;
2150Int VGOFF_(helper_div_16_8) = INVALID_OFFSET;
2151Int VGOFF_(helper_imul_32_64) = INVALID_OFFSET;
2152Int VGOFF_(helper_mul_32_64) = INVALID_OFFSET;
2153Int VGOFF_(helper_imul_16_32) = INVALID_OFFSET;
2154Int VGOFF_(helper_mul_16_32) = INVALID_OFFSET;
2155Int VGOFF_(helper_imul_8_16) = INVALID_OFFSET;
2156Int VGOFF_(helper_mul_8_16) = INVALID_OFFSET;
2157Int VGOFF_(helper_CLD) = INVALID_OFFSET;
2158Int VGOFF_(helper_STD) = INVALID_OFFSET;
2159Int VGOFF_(helper_get_dirflag) = INVALID_OFFSET;
2160Int VGOFF_(helper_CLC) = INVALID_OFFSET;
2161Int VGOFF_(helper_STC) = INVALID_OFFSET;
nethercote1018bdd2004-02-11 23:33:29 +00002162Int VGOFF_(helper_CMC) = INVALID_OFFSET;
nethercote71980f02004-01-24 18:18:54 +00002163Int VGOFF_(helper_shldl) = INVALID_OFFSET;
2164Int VGOFF_(helper_shldw) = INVALID_OFFSET;
2165Int VGOFF_(helper_shrdl) = INVALID_OFFSET;
2166Int VGOFF_(helper_shrdw) = INVALID_OFFSET;
2167Int VGOFF_(helper_IN) = INVALID_OFFSET;
2168Int VGOFF_(helper_OUT) = INVALID_OFFSET;
2169Int VGOFF_(helper_RDTSC) = INVALID_OFFSET;
2170Int VGOFF_(helper_CPUID) = INVALID_OFFSET;
2171Int VGOFF_(helper_BSWAP) = INVALID_OFFSET;
nethercote1018bdd2004-02-11 23:33:29 +00002172Int VGOFF_(helper_bsfw) = INVALID_OFFSET;
2173Int VGOFF_(helper_bsfl) = INVALID_OFFSET;
2174Int VGOFF_(helper_bsrw) = INVALID_OFFSET;
2175Int VGOFF_(helper_bsrl) = INVALID_OFFSET;
nethercote71980f02004-01-24 18:18:54 +00002176Int VGOFF_(helper_fstsw_AX) = INVALID_OFFSET;
2177Int VGOFF_(helper_SAHF) = INVALID_OFFSET;
2178Int VGOFF_(helper_LAHF) = INVALID_OFFSET;
2179Int VGOFF_(helper_DAS) = INVALID_OFFSET;
2180Int VGOFF_(helper_DAA) = INVALID_OFFSET;
nethercote1018bdd2004-02-11 23:33:29 +00002181Int VGOFF_(helper_AAS) = INVALID_OFFSET;
2182Int VGOFF_(helper_AAA) = INVALID_OFFSET;
2183Int VGOFF_(helper_AAD) = INVALID_OFFSET;
2184Int VGOFF_(helper_AAM) = INVALID_OFFSET;
nethercote71980f02004-01-24 18:18:54 +00002185Int VGOFF_(helper_cmpxchg8b) = INVALID_OFFSET;
2186Int VGOFF_(helper_undefined_instruction) = INVALID_OFFSET;
2187
2188/* MAX_NONCOMPACT_HELPERS can be increased easily. If MAX_COMPACT_HELPERS is
2189 * increased too much, they won't really be compact any more... */
2190#define MAX_COMPACT_HELPERS 8
2191#define MAX_NONCOMPACT_HELPERS 50
2192
nethercote81f9a6f2004-08-03 15:45:46 +00002193/* For storing tool-specific helpers, determined at runtime. The addr
2194 * and offset arrays together form a (addr, offset) map that allows a
2195 * helper's baseBlock offset to be computed from its address. It's done
2196 * like this so CCALLs can use the function address rather than having to
2197 * muck around with offsets. */
2198static UInt VG_(n_compact_helpers) = 0;
2199static UInt VG_(n_noncompact_helpers) = 0;
2200static Addr VG_(compact_helper_addrs) [MAX_COMPACT_HELPERS];
2201static Int VG_(compact_helper_offsets)[MAX_COMPACT_HELPERS];
2202static Addr VG_(noncompact_helper_addrs) [MAX_NONCOMPACT_HELPERS];
2203static Int VG_(noncompact_helper_offsets)[MAX_NONCOMPACT_HELPERS];
nethercote71980f02004-01-24 18:18:54 +00002204
2205/* This is the actual defn of baseblock. */
2206UInt VG_(baseBlock)[VG_BASEBLOCK_WORDS];
2207
nethercote71980f02004-01-24 18:18:54 +00002208/* Words. */
2209static Int baB_off = 0;
2210
2211
nethercote71980f02004-01-24 18:18:54 +00002212/* Returns the offset, in words. */
2213static Int alloc_BaB ( Int words )
sewardjde4a1d02002-03-22 01:27:54 +00002214{
nethercote71980f02004-01-24 18:18:54 +00002215 Int off = baB_off;
2216 baB_off += words;
2217 if (baB_off >= VG_BASEBLOCK_WORDS)
2218 VG_(core_panic)( "alloc_BaB: baseBlock is too small");
sewardjde4a1d02002-03-22 01:27:54 +00002219
nethercote71980f02004-01-24 18:18:54 +00002220 return off;
sewardjde4a1d02002-03-22 01:27:54 +00002221}
2222
nethercote71980f02004-01-24 18:18:54 +00002223/* Align offset, in *bytes* */
2224static void align_BaB ( UInt align )
njn25e49d8e72002-09-23 09:36:25 +00002225{
nethercote71980f02004-01-24 18:18:54 +00002226 vg_assert(2 == align || 4 == align || 8 == align || 16 == align);
2227 baB_off += (align-1);
2228 baB_off &= ~(align-1);
njn25e49d8e72002-09-23 09:36:25 +00002229}
2230
nethercote71980f02004-01-24 18:18:54 +00002231/* Allocate 1 word in baseBlock and set it to the given value. */
2232static Int alloc_BaB_1_set ( Addr a )
njn25e49d8e72002-09-23 09:36:25 +00002233{
nethercote71980f02004-01-24 18:18:54 +00002234 Int off = alloc_BaB(1);
2235 VG_(baseBlock)[off] = (UInt)a;
2236 return off;
njn25e49d8e72002-09-23 09:36:25 +00002237}
2238
nethercote71980f02004-01-24 18:18:54 +00002239/* Registers a function in compact_helper_addrs; compact_helper_offsets is
2240 filled in later. */
2241void VG_(register_compact_helper)(Addr a)
sewardjde4a1d02002-03-22 01:27:54 +00002242{
nethercote71980f02004-01-24 18:18:54 +00002243 if (MAX_COMPACT_HELPERS <= VG_(n_compact_helpers)) {
2244 VG_(printf)("Can only register %d compact helpers\n",
2245 MAX_COMPACT_HELPERS);
2246 VG_(core_panic)("Too many compact helpers registered");
2247 }
2248 VG_(compact_helper_addrs)[VG_(n_compact_helpers)] = a;
2249 VG_(n_compact_helpers)++;
2250}
2251
2252/* Registers a function in noncompact_helper_addrs; noncompact_helper_offsets
2253 * is filled in later.
2254 */
2255void VG_(register_noncompact_helper)(Addr a)
2256{
2257 if (MAX_NONCOMPACT_HELPERS <= VG_(n_noncompact_helpers)) {
2258 VG_(printf)("Can only register %d non-compact helpers\n",
2259 MAX_NONCOMPACT_HELPERS);
2260 VG_(printf)("Try increasing MAX_NON_COMPACT_HELPERS\n");
2261 VG_(core_panic)("Too many non-compact helpers registered");
2262 }
2263 VG_(noncompact_helper_addrs)[VG_(n_noncompact_helpers)] = a;
2264 VG_(n_noncompact_helpers)++;
2265}
2266
nethercote996901a2004-08-03 13:29:09 +00002267/* Allocate offsets in baseBlock for the tool helpers */
nethercote71980f02004-01-24 18:18:54 +00002268static
2269void assign_helpers_in_baseBlock(UInt n, Int offsets[], Addr addrs[])
2270{
2271 UInt i;
2272 for (i = 0; i < n; i++)
2273 offsets[i] = alloc_BaB_1_set( addrs[i] );
2274}
2275
2276Bool VG_(need_to_handle_esp_assignment)(void)
2277{
2278 return ( VG_(defined_new_mem_stack_4)() ||
2279 VG_(defined_die_mem_stack_4)() ||
2280 VG_(defined_new_mem_stack_8)() ||
2281 VG_(defined_die_mem_stack_8)() ||
2282 VG_(defined_new_mem_stack_12)() ||
2283 VG_(defined_die_mem_stack_12)() ||
2284 VG_(defined_new_mem_stack_16)() ||
2285 VG_(defined_die_mem_stack_16)() ||
2286 VG_(defined_new_mem_stack_32)() ||
2287 VG_(defined_die_mem_stack_32)() ||
2288 VG_(defined_new_mem_stack)() ||
2289 VG_(defined_die_mem_stack)()
2290 );
2291}
2292
2293/* Here we assign actual offsets. It's important to get the most
2294 popular referents within 128 bytes of the start, so we can take
2295 advantage of short addressing modes relative to %ebp. Popularity
2296 of offsets was measured on 22 Feb 02 running a KDE application, and
2297 the slots rearranged accordingly, with a 1.5% reduction in total
2298 size of translations. */
2299static void init_baseBlock ( Addr client_eip, Addr esp_at_startup )
2300{
2301 /* Those with offsets under 128 are carefully chosen. */
2302
2303 /* WORD offsets in this column */
2304 /* 0 */ VGOFF_(m_eax) = alloc_BaB_1_set(0);
2305 /* 1 */ VGOFF_(m_ecx) = alloc_BaB_1_set(0);
2306 /* 2 */ VGOFF_(m_edx) = alloc_BaB_1_set(0);
2307 /* 3 */ VGOFF_(m_ebx) = alloc_BaB_1_set(0);
2308 /* 4 */ VGOFF_(m_esp) = alloc_BaB_1_set(esp_at_startup);
2309 /* 5 */ VGOFF_(m_ebp) = alloc_BaB_1_set(0);
2310 /* 6 */ VGOFF_(m_esi) = alloc_BaB_1_set(0);
2311 /* 7 */ VGOFF_(m_edi) = alloc_BaB_1_set(0);
2312 /* 8 */ VGOFF_(m_eflags) = alloc_BaB_1_set(0);
2313
2314 if (VG_(needs).shadow_regs) {
2315 /* 9 */ VGOFF_(sh_eax) = alloc_BaB_1_set(0);
2316 /* 10 */ VGOFF_(sh_ecx) = alloc_BaB_1_set(0);
2317 /* 11 */ VGOFF_(sh_edx) = alloc_BaB_1_set(0);
2318 /* 12 */ VGOFF_(sh_ebx) = alloc_BaB_1_set(0);
2319 /* 13 */ VGOFF_(sh_esp) = alloc_BaB_1_set(0);
2320 /* 14 */ VGOFF_(sh_ebp) = alloc_BaB_1_set(0);
2321 /* 15 */ VGOFF_(sh_esi) = alloc_BaB_1_set(0);
2322 /* 16 */ VGOFF_(sh_edi) = alloc_BaB_1_set(0);
2323 /* 17 */ VGOFF_(sh_eflags) = alloc_BaB_1_set(0);
2324 VG_TRACK( post_regs_write_init );
2325 }
2326
2327 /* 9,10,11 or 18,19,20... depends on number whether shadow regs are used
2328 * and on compact helpers registered */
2329
2330 /* Make these most-frequently-called specialised ones compact, if they
2331 are used. */
2332 if (VG_(defined_new_mem_stack_4)())
2333 VG_(register_compact_helper)( (Addr) VG_(tool_interface).track_new_mem_stack_4);
2334
2335 if (VG_(defined_die_mem_stack_4)())
2336 VG_(register_compact_helper)( (Addr) VG_(tool_interface).track_die_mem_stack_4);
2337
2338 /* (9 or 18) + n_compact_helpers */
2339 /* Allocate slots for compact helpers */
2340 assign_helpers_in_baseBlock(VG_(n_compact_helpers),
2341 VG_(compact_helper_offsets),
2342 VG_(compact_helper_addrs));
2343
2344 /* (9/10 or 18/19) + n_compact_helpers */
2345 VGOFF_(m_eip) = alloc_BaB_1_set(client_eip);
2346
2347 /* There are currently 24 spill slots */
2348 /* (11+/20+ .. 32+/43+) + n_compact_helpers. This can overlap the magic
2349 * boundary at >= 32 words, but most spills are to low numbered spill
2350 * slots, so the ones above the boundary don't see much action. */
2351 VGOFF_(spillslots) = alloc_BaB(VG_MAX_SPILLSLOTS);
2352
2353 /* I gave up counting at this point. Since they're above the
2354 short-amode-boundary, there's no point. */
2355
2356 VGOFF_(m_dflag) = alloc_BaB_1_set(1); // 1 == forward D-flag
2357
2358 /* The FPU/SSE state. This _must_ be 16-byte aligned. Initial
2359 state doesn't matter much, as long as it's not totally borked. */
2360 align_BaB(16);
2361 VGOFF_(m_ssestate) = alloc_BaB(VG_SIZE_OF_SSESTATE_W);
2362 vg_assert(
2363 0 == ( ((UInt)(& VG_(baseBlock)[VGOFF_(m_ssestate)])) % 16 )
sewardj22854b92002-11-30 14:00:47 +00002364 );
2365
fitzhardingec2dbbac2004-01-23 23:09:01 +00002366 /* I assume that if we have SSE2 we also have SSE */
2367 VG_(have_ssestate) =
2368 VG_(cpu_has_feature)(VG_X86_FEAT_FXSR) &&
2369 VG_(cpu_has_feature)(VG_X86_FEAT_SSE);
2370
fitzhardinge98abfc72003-12-16 02:05:15 +00002371 /* set up an initial FPU state (doesn't really matter what it is,
2372 so long as it's somewhat valid) */
2373 if (!VG_(have_ssestate))
nethercote71980f02004-01-24 18:18:54 +00002374 asm volatile("fwait; fnsave %0; fwait; frstor %0; fwait"
2375 :
2376 : "m" (VG_(baseBlock)[VGOFF_(m_ssestate)])
2377 : "cc", "memory");
fitzhardinge98abfc72003-12-16 02:05:15 +00002378 else
nethercote71980f02004-01-24 18:18:54 +00002379 asm volatile("fwait; fxsave %0; fwait; andl $0xffbf, %1;"
2380 "fxrstor %0; fwait"
2381 :
2382 : "m" (VG_(baseBlock)[VGOFF_(m_ssestate)]),
2383 "m" (VG_(baseBlock)[VGOFF_(m_ssestate)+(24/4)])
2384 : "cc", "memory");
fitzhardinge98abfc72003-12-16 02:05:15 +00002385
njn0c7a5b52003-04-30 09:00:33 +00002386 if (0) {
2387 if (VG_(have_ssestate))
2388 VG_(printf)("Looks like a SSE-capable CPU\n");
2389 else
2390 VG_(printf)("Looks like a MMX-only CPU\n");
2391 }
sewardjb91ae7f2003-04-29 23:50:00 +00002392
nethercote71980f02004-01-24 18:18:54 +00002393 /* LDT pointer: pretend the root thread has an empty LDT to start with. */
2394 VGOFF_(ldt) = alloc_BaB_1_set((UInt)NULL);
jsgf855d93d2003-10-13 22:26:55 +00002395
nethercote71980f02004-01-24 18:18:54 +00002396 /* TLS pointer: pretend the root thread has no TLS array for now. */
nethercoted8510ec2004-08-18 23:11:45 +00002397 VGOFF_(tls_ptr) = alloc_BaB_1_set((UInt)NULL);
fitzhardingef0046f22003-12-18 02:39:22 +00002398
nethercote71980f02004-01-24 18:18:54 +00002399 /* segment registers */
2400 VGOFF_(m_cs) = alloc_BaB_1_set(0);
2401 VGOFF_(m_ss) = alloc_BaB_1_set(0);
2402 VGOFF_(m_ds) = alloc_BaB_1_set(0);
2403 VGOFF_(m_es) = alloc_BaB_1_set(0);
2404 VGOFF_(m_fs) = alloc_BaB_1_set(0);
2405 VGOFF_(m_gs) = alloc_BaB_1_set(0);
fitzhardingef0046f22003-12-18 02:39:22 +00002406
thughes35cec982004-04-21 15:16:43 +00002407 /* initialise %cs, %ds and %ss to point at the operating systems
2408 default code, data and stack segments */
2409 asm volatile("movw %%cs, %0"
2410 :
2411 : "m" (VG_(baseBlock)[VGOFF_(m_cs)]));
2412 asm volatile("movw %%ds, %0"
2413 :
2414 : "m" (VG_(baseBlock)[VGOFF_(m_ds)]));
2415 asm volatile("movw %%ss, %0"
2416 :
2417 : "m" (VG_(baseBlock)[VGOFF_(m_ss)]));
2418
nethercote71980f02004-01-24 18:18:54 +00002419 VG_(register_noncompact_helper)( (Addr) & VG_(do_useseg) );
fitzhardingef0046f22003-12-18 02:39:22 +00002420
nethercote71980f02004-01-24 18:18:54 +00002421#define REG(kind, size) \
2422 if (VG_(defined_##kind##_mem_stack##size)()) \
2423 VG_(register_noncompact_helper)( \
2424 (Addr) VG_(tool_interface).track_##kind##_mem_stack##size );
2425 REG(new, _8);
2426 REG(new, _12);
2427 REG(new, _16);
2428 REG(new, _32);
2429 REG(new, );
2430 REG(die, _8);
2431 REG(die, _12);
2432 REG(die, _16);
2433 REG(die, _32);
2434 REG(die, );
2435#undef REG
fitzhardingef0046f22003-12-18 02:39:22 +00002436
nethercote71980f02004-01-24 18:18:54 +00002437 if (VG_(need_to_handle_esp_assignment)())
2438 VG_(register_noncompact_helper)((Addr) VG_(unknown_esp_update));
fitzhardingeb791a192003-12-18 07:22:44 +00002439
nethercote71980f02004-01-24 18:18:54 +00002440# define HELPER(name) \
2441 VGOFF_(helper_##name) = alloc_BaB_1_set( (Addr) & VG_(helper_##name))
njn3e884182003-04-15 13:03:23 +00002442
nethercote71980f02004-01-24 18:18:54 +00002443 /* Helper functions. */
2444 HELPER(idiv_64_32); HELPER(div_64_32);
2445 HELPER(idiv_32_16); HELPER(div_32_16);
2446 HELPER(idiv_16_8); HELPER(div_16_8);
fitzhardinge98abfc72003-12-16 02:05:15 +00002447
nethercote71980f02004-01-24 18:18:54 +00002448 HELPER(imul_32_64); HELPER(mul_32_64);
2449 HELPER(imul_16_32); HELPER(mul_16_32);
2450 HELPER(imul_8_16); HELPER(mul_8_16);
njn25e49d8e72002-09-23 09:36:25 +00002451
nethercote71980f02004-01-24 18:18:54 +00002452 HELPER(CLD); HELPER(STD);
2453 HELPER(get_dirflag);
sewardjde4a1d02002-03-22 01:27:54 +00002454
nethercote71980f02004-01-24 18:18:54 +00002455 HELPER(CLC); HELPER(STC);
nethercote1018bdd2004-02-11 23:33:29 +00002456 HELPER(CMC);
jsgf855d93d2003-10-13 22:26:55 +00002457
nethercote71980f02004-01-24 18:18:54 +00002458 HELPER(shldl); HELPER(shldw);
2459 HELPER(shrdl); HELPER(shrdw);
njncc7bb472002-10-14 09:25:19 +00002460
nethercote71980f02004-01-24 18:18:54 +00002461 HELPER(RDTSC); HELPER(CPUID);
njncc7bb472002-10-14 09:25:19 +00002462
nethercote1018bdd2004-02-11 23:33:29 +00002463 HELPER(bsfw); HELPER(bsfl);
2464 HELPER(bsrw); HELPER(bsrl);
rjwalshf5f536f2003-11-17 17:45:00 +00002465
nethercote71980f02004-01-24 18:18:54 +00002466 HELPER(fstsw_AX);
2467 HELPER(SAHF); HELPER(LAHF);
2468 HELPER(DAS); HELPER(DAA);
nethercote1018bdd2004-02-11 23:33:29 +00002469 HELPER(AAS); HELPER(AAA);
2470 HELPER(AAD); HELPER(AAM);
nethercote71980f02004-01-24 18:18:54 +00002471 HELPER(IN); HELPER(OUT);
2472 HELPER(cmpxchg8b);
sewardj018f7622002-05-15 21:13:39 +00002473
nethercote71980f02004-01-24 18:18:54 +00002474 HELPER(undefined_instruction);
jsgf855d93d2003-10-13 22:26:55 +00002475
nethercote71980f02004-01-24 18:18:54 +00002476# undef HELPER
sewardjde4a1d02002-03-22 01:27:54 +00002477
nethercote71980f02004-01-24 18:18:54 +00002478 /* Allocate slots for noncompact helpers */
2479 assign_helpers_in_baseBlock(VG_(n_noncompact_helpers),
2480 VG_(noncompact_helper_offsets),
2481 VG_(noncompact_helper_addrs));
2482}
sewardjde4a1d02002-03-22 01:27:54 +00002483
nethercote81f9a6f2004-08-03 15:45:46 +00002484// Finds the baseBlock offset of a tool-specified helper.
2485// Searches through compacts first, then non-compacts.
2486Int VG_(helper_offset)(Addr a)
2487{
2488 UInt i;
2489 Char buf[100];
2490
2491 for (i = 0; i < VG_(n_compact_helpers); i++)
2492 if (VG_(compact_helper_addrs)[i] == a)
2493 return VG_(compact_helper_offsets)[i];
2494 for (i = 0; i < VG_(n_noncompact_helpers); i++)
2495 if (VG_(noncompact_helper_addrs)[i] == a)
2496 return VG_(noncompact_helper_offsets)[i];
2497
2498 /* Shouldn't get here */
2499 VG_(get_fnname) ( a, buf, 100 );
2500
2501 VG_(printf)(
2502 "\nCouldn't find offset of helper from its address (%p: %s).\n"
2503 "A helper function probably used hasn't been registered?\n\n", a, buf);
2504
2505 VG_(printf)(" compact helpers: ");
2506 for (i = 0; i < VG_(n_compact_helpers); i++)
2507 VG_(printf)("%p ", VG_(compact_helper_addrs)[i]);
2508
2509 VG_(printf)("\n non-compact helpers: ");
2510 for (i = 0; i < VG_(n_noncompact_helpers); i++)
2511 VG_(printf)("%p ", VG_(noncompact_helper_addrs)[i]);
2512
2513 VG_(printf)("\n");
2514 VG_(skin_panic)("Unfound helper");
2515}
2516
sewardj5f07b662002-04-23 16:52:51 +00002517
nethercote71980f02004-01-24 18:18:54 +00002518/*====================================================================*/
2519/*=== Setup pointercheck ===*/
2520/*====================================================================*/
njn25e49d8e72002-09-23 09:36:25 +00002521
nethercote71980f02004-01-24 18:18:54 +00002522static void setup_pointercheck(void)
2523{
2524 int ret;
sewardj2e93c502002-04-12 11:12:52 +00002525
fitzhardinge98abfc72003-12-16 02:05:15 +00002526 if (VG_(clo_pointercheck)) {
nethercote71980f02004-01-24 18:18:54 +00002527 vki_modify_ldt_t ldt = {
2528 VG_POINTERCHECK_SEGIDX, // entry_number
2529 VG_(client_base), // base_addr
2530 (VG_(client_end)-VG_(client_base)) / VKI_BYTES_PER_PAGE, // limit
2531 1, // seg_32bit
2532 0, // contents: data, RW, non-expanding
2533 0, // ! read_exec_only
2534 1, // limit_in_pages
2535 0, // ! seg not present
2536 1, // useable
fitzhardinge98abfc72003-12-16 02:05:15 +00002537 };
nethercote71980f02004-01-24 18:18:54 +00002538 ret = VG_(do_syscall)(__NR_modify_ldt, 1, &ldt, sizeof(ldt));
fitzhardinge98abfc72003-12-16 02:05:15 +00002539 if (ret < 0) {
2540 VG_(message)(Vg_UserMsg,
2541 "Warning: ignoring --pointercheck=yes, "
2542 "because modify_ldt failed (errno=%d)", -ret);
2543 VG_(clo_pointercheck) = False;
2544 }
2545 }
sewardjde4a1d02002-03-22 01:27:54 +00002546}
2547
nethercote71980f02004-01-24 18:18:54 +00002548/*====================================================================*/
2549/*=== Initialise program data/text, etc. ===*/
2550/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +00002551
nethercote71980f02004-01-24 18:18:54 +00002552static void build_valgrind_map_callback
2553 ( Addr start, UInt size, Char rr, Char ww, Char xx,
2554 UInt dev, UInt ino, ULong foffset, const UChar* filename )
sewardjde4a1d02002-03-22 01:27:54 +00002555{
nethercote71980f02004-01-24 18:18:54 +00002556 UInt prot = 0;
2557 UInt flags = SF_MMAP|SF_NOSYMS;
2558 Bool is_stack_segment;
2559
2560 is_stack_segment =
2561 (start == VG_(clstk_base) && (start+size) == VG_(clstk_end));
2562
2563 /* Only record valgrind mappings for now, without loading any
2564 symbols. This is so we know where the free space is before we
2565 start allocating more memory (note: heap is OK, it's just mmap
2566 which is the problem here). */
2567 if (start >= VG_(valgrind_base) && (start+size) <= VG_(valgrind_end)) {
2568 flags |= SF_VALGRIND;
2569 VG_(map_file_segment)(start, size, prot, flags, dev, ino, foffset, filename);
2570 }
sewardjde4a1d02002-03-22 01:27:54 +00002571}
2572
nethercote71980f02004-01-24 18:18:54 +00002573// Global var used to pass local data to callback
2574Addr esp_at_startup___global_arg = 0;
sewardjde4a1d02002-03-22 01:27:54 +00002575
nethercote71980f02004-01-24 18:18:54 +00002576static void build_segment_map_callback
2577 ( Addr start, UInt size, Char rr, Char ww, Char xx,
2578 UInt dev, UInt ino, ULong foffset, const UChar* filename )
sewardj45b672d2003-07-25 19:58:11 +00002579{
nethercote71980f02004-01-24 18:18:54 +00002580 UInt prot = 0;
2581 UInt flags;
2582 Bool is_stack_segment;
2583 Addr r_esp;
sewardj45b672d2003-07-25 19:58:11 +00002584
nethercote71980f02004-01-24 18:18:54 +00002585 is_stack_segment
2586 = (start == VG_(clstk_base) && (start+size) == VG_(clstk_end));
fitzhardinge98abfc72003-12-16 02:05:15 +00002587
nethercote71980f02004-01-24 18:18:54 +00002588 if (rr == 'r') prot |= VKI_PROT_READ;
2589 if (ww == 'w') prot |= VKI_PROT_WRITE;
2590 if (xx == 'x') prot |= VKI_PROT_EXEC;
fitzhardinge98abfc72003-12-16 02:05:15 +00002591
nethercote71980f02004-01-24 18:18:54 +00002592 if (is_stack_segment)
2593 flags = SF_STACK | SF_GROWDOWN;
2594 else
2595 flags = SF_EXEC|SF_MMAP;
fitzhardinge98abfc72003-12-16 02:05:15 +00002596
nethercote71980f02004-01-24 18:18:54 +00002597 if (filename != NULL)
2598 flags |= SF_FILE;
fitzhardinge98abfc72003-12-16 02:05:15 +00002599
nethercote71980f02004-01-24 18:18:54 +00002600 if (start >= VG_(valgrind_base) && (start+size) <= VG_(valgrind_end))
2601 flags |= SF_VALGRIND;
fitzhardinge98abfc72003-12-16 02:05:15 +00002602
nethercote71980f02004-01-24 18:18:54 +00002603 VG_(map_file_segment)(start, size, prot, flags, dev, ino, foffset, filename);
fitzhardinge98abfc72003-12-16 02:05:15 +00002604
nethercote71980f02004-01-24 18:18:54 +00002605 if (VG_(is_client_addr)(start) && VG_(is_client_addr)(start+size-1))
2606 VG_TRACK( new_mem_startup, start, size, rr=='r', ww=='w', xx=='x' );
sewardj3e1eb1f2002-05-18 13:14:17 +00002607
nethercote71980f02004-01-24 18:18:54 +00002608 /* If this is the stack segment mark all below %esp as noaccess. */
2609 r_esp = esp_at_startup___global_arg;
2610 vg_assert(0 != r_esp);
2611 if (is_stack_segment) {
2612 if (0)
2613 VG_(message)(Vg_DebugMsg, "invalidating stack area: %x .. %x",
2614 start,r_esp);
2615 VG_TRACK( die_mem_stack, start, r_esp-start );
sewardjde4a1d02002-03-22 01:27:54 +00002616 }
sewardjde4a1d02002-03-22 01:27:54 +00002617}
2618
2619
nethercote71980f02004-01-24 18:18:54 +00002620/*====================================================================*/
2621/*=== Sanity check machinery (permanently engaged) ===*/
2622/*====================================================================*/
njn25e49d8e72002-09-23 09:36:25 +00002623
2624/* A fast sanity check -- suitable for calling circa once per
2625 millisecond. */
2626
nethercote885dd912004-08-03 23:14:00 +00002627void VG_(sanity_check_general) ( Bool force_expensive )
njn25e49d8e72002-09-23 09:36:25 +00002628{
njn37cea302002-09-30 11:24:00 +00002629 VGP_PUSHCC(VgpCoreCheapSanity);
2630
nethercote27fec902004-06-16 21:26:32 +00002631 if (VG_(clo_sanity_level) < 1) return;
njn25e49d8e72002-09-23 09:36:25 +00002632
2633 /* --- First do all the tests that we can do quickly. ---*/
2634
nethercote297effd2004-08-02 15:07:57 +00002635 sanity_fast_count++;
njn25e49d8e72002-09-23 09:36:25 +00002636
njn25e49d8e72002-09-23 09:36:25 +00002637 /* Check stuff pertaining to the memory check system. */
2638
2639 /* Check that nobody has spuriously claimed that the first or
2640 last 16 pages of memory have become accessible [...] */
njn37cea302002-09-30 11:24:00 +00002641 if (VG_(needs).sanity_checks) {
2642 VGP_PUSHCC(VgpSkinCheapSanity);
njn25e49d8e72002-09-23 09:36:25 +00002643 vg_assert(SK_(cheap_sanity_check)());
njn37cea302002-09-30 11:24:00 +00002644 VGP_POPCC(VgpSkinCheapSanity);
2645 }
njn25e49d8e72002-09-23 09:36:25 +00002646
2647 /* --- Now some more expensive checks. ---*/
2648
2649 /* Once every 25 times, check some more expensive stuff. */
2650 if ( force_expensive
nethercote27fec902004-06-16 21:26:32 +00002651 || VG_(clo_sanity_level) > 1
nethercote297effd2004-08-02 15:07:57 +00002652 || (VG_(clo_sanity_level) == 1 && (sanity_fast_count % 25) == 0)) {
njn25e49d8e72002-09-23 09:36:25 +00002653
njn37cea302002-09-30 11:24:00 +00002654 VGP_PUSHCC(VgpCoreExpensiveSanity);
nethercote297effd2004-08-02 15:07:57 +00002655 sanity_slow_count++;
njn25e49d8e72002-09-23 09:36:25 +00002656
nethercote885dd912004-08-03 23:14:00 +00002657 VG_(sanity_check_proxy)();
jsgf855d93d2003-10-13 22:26:55 +00002658
njn25e49d8e72002-09-23 09:36:25 +00002659# if 0
2660 { void zzzmemscan(void); zzzmemscan(); }
2661# endif
2662
nethercote297effd2004-08-02 15:07:57 +00002663 if ((sanity_fast_count % 250) == 0)
nethercote92e7b7f2004-08-07 17:52:25 +00002664 VG_(sanity_check_tt_tc)();
njn25e49d8e72002-09-23 09:36:25 +00002665
2666 if (VG_(needs).sanity_checks) {
njn37cea302002-09-30 11:24:00 +00002667 VGP_PUSHCC(VgpSkinExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002668 vg_assert(SK_(expensive_sanity_check)());
njn37cea302002-09-30 11:24:00 +00002669 VGP_POPCC(VgpSkinExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002670 }
2671 /*
nethercote297effd2004-08-02 15:07:57 +00002672 if ((sanity_fast_count % 500) == 0) VG_(mallocSanityCheckAll)();
njn25e49d8e72002-09-23 09:36:25 +00002673 */
njn37cea302002-09-30 11:24:00 +00002674 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002675 }
2676
nethercote27fec902004-06-16 21:26:32 +00002677 if (VG_(clo_sanity_level) > 1) {
njn37cea302002-09-30 11:24:00 +00002678 VGP_PUSHCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002679 /* Check sanity of the low-level memory manager. Note that bugs
2680 in the client's code can cause this to fail, so we don't do
2681 this check unless specially asked for. And because it's
2682 potentially very expensive. */
nethercote885dd912004-08-03 23:14:00 +00002683 VG_(sanity_check_malloc_all)();
njn37cea302002-09-30 11:24:00 +00002684 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002685 }
njn37cea302002-09-30 11:24:00 +00002686 VGP_POPCC(VgpCoreCheapSanity);
njn25e49d8e72002-09-23 09:36:25 +00002687}
nethercote71980f02004-01-24 18:18:54 +00002688
2689
2690/*====================================================================*/
2691/*=== main() ===*/
2692/*====================================================================*/
2693
nethercotec314eba2004-07-15 12:59:41 +00002694/*
2695 This code decides on the layout of the client and Valgrind address
nethercote996901a2004-08-03 13:29:09 +00002696 spaces, loads valgrind.so and the tool.so into the valgrind part,
nethercotec314eba2004-07-15 12:59:41 +00002697 loads the client executable (and the dynamic linker, if necessary)
2698 into the client part, and calls into Valgrind proper.
2699
2700 The code is careful not to allow spurious mappings to appear in the
2701 wrong parts of the address space. In particular, to make sure
2702 dlopen puts things in the right place, it will pad out the forbidden
2703 chunks of address space so that dlopen is forced to put things where
2704 we want them.
2705
2706 The memory map it creates is:
2707
2708 CLIENT_BASE +-------------------------+
2709 | client address space |
2710 : :
2711 : :
2712 | client stack |
2713 client_end +-------------------------+
2714 | redzone |
2715 shadow_base +-------------------------+
2716 | |
nethercote996901a2004-08-03 13:29:09 +00002717 : shadow memory for tools :
nethercotec314eba2004-07-15 12:59:41 +00002718 | (may be 0 sized) |
2719 shadow_end +-------------------------+
2720 : gap (may be 0 sized) :
2721 valgrind_base +-------------------------+
2722 | kickstart executable |
2723 | valgrind heap vvvvvvvvv| (barely used)
2724 - -
2725 | valgrind .so files |
2726 | and mappings |
2727 - -
2728 | valgrind stack ^^^^^^^^^|
2729 valgrind_end +-------------------------+
2730 : kernel :
2731
2732 Nb: Before we can do general allocations with VG_(arena_malloc)() and
2733 VG_(mmap)(), we need to build the segment skip-list, so we know where
2734 we can put things. However, building that structure requires
2735 allocating memory. So we need to a bootstrapping process. It's done
2736 by making VG_(arena_malloc)() have a special static superblock that's
2737 used for the first 1MB's worth of allocations. This is enough to
2738 build the segment skip-list.
2739*/
2740
nethercote31779c72004-07-30 21:50:15 +00002741static int prmap(char *start, char *end, const char *perm, off_t off,
2742 int maj, int min, int ino, void* dummy) {
thughes4ad52d02004-06-27 17:37:21 +00002743 printf("mapping %10p-%10p %s %02x:%02x %d\n",
2744 start, end, perm, maj, min, ino);
2745 return True;
2746}
2747
nethercote71980f02004-01-24 18:18:54 +00002748int main(int argc, char **argv)
2749{
2750 char **cl_argv;
2751 const char *tool = NULL;
2752 const char *exec = NULL;
2753 char *preload; /* tool-specific LD_PRELOAD .so */
2754 char **env;
nethercote6c999f22004-01-31 22:55:15 +00002755 Int need_help = 0; // 0 = no, 1 = --help, 2 = --help-debug
nethercote71980f02004-01-24 18:18:54 +00002756 struct exeinfo info;
2757 ToolInfo *toolinfo = NULL;
2758 void *tool_dlhandle;
2759 Addr client_eip;
2760 Addr esp_at_startup; /* client's %esp at the point we gained control. */
2761 UInt * client_auxv;
2762 VgSchedReturnCode src;
nethercote47dd12c2004-06-22 14:18:42 +00002763 Int exitcode = 0;
nethercote238a3c32004-08-09 13:13:31 +00002764 Int fatal_sigNo = -1;
fitzhardingeb50068f2004-02-24 23:42:55 +00002765 vki_rlimit zero = { 0, 0 };
nethercote31779c72004-07-30 21:50:15 +00002766 Int padfile;
nethercote759dda32004-08-07 18:16:56 +00002767 ThreadId last_run_tid = 0; // Last thread the scheduler ran.
2768
nethercote71980f02004-01-24 18:18:54 +00002769
2770 //============================================================
2771 // Nb: startup is complex. Prerequisites are shown at every step.
2772 //
2773 // *** Be very careful when messing with the order ***
2774 //============================================================
2775
nethercotef4928da2004-06-15 10:54:40 +00002776 //============================================================
2777 // Command line argument handling order:
2778 // * If --help/--help-debug are present, show usage message
2779 // (if --tool is also present, that includes the tool-specific usage)
2780 // * Then, if --tool is missing, abort with error msg
2781 // * Then, if client is missing, abort with error msg
2782 // * Then, if any cmdline args are bad, abort with error msg
2783 //============================================================
2784
fitzhardingeb50068f2004-02-24 23:42:55 +00002785 // Get the current process datasize rlimit, and set it to zero.
2786 // This prevents any internal uses of brk() from having any effect.
2787 // We remember the old value so we can restore it on exec, so that
2788 // child processes will have a reasonable brk value.
2789 VG_(getrlimit)(VKI_RLIMIT_DATA, &VG_(client_rlimit_data));
2790 zero.rlim_max = VG_(client_rlimit_data).rlim_max;
2791 VG_(setrlimit)(VKI_RLIMIT_DATA, &zero);
2792
nethercote71980f02004-01-24 18:18:54 +00002793 //--------------------------------------------------------------
2794 // Check we were launched by stage1
nethercotec314eba2004-07-15 12:59:41 +00002795 // p: n/a
nethercote71980f02004-01-24 18:18:54 +00002796 //--------------------------------------------------------------
nethercote31779c72004-07-30 21:50:15 +00002797 padfile = scan_auxv();
nethercote71980f02004-01-24 18:18:54 +00002798
2799 if (0) {
nethercote71980f02004-01-24 18:18:54 +00002800 printf("========== main() ==========\n");
nethercote31779c72004-07-30 21:50:15 +00002801 foreach_map(prmap, /*dummy*/NULL);
nethercote71980f02004-01-24 18:18:54 +00002802 }
2803
2804 //--------------------------------------------------------------
2805 // Look for alternative libdir
2806 // p: n/a
2807 //--------------------------------------------------------------
2808 { char *cp = getenv(VALGRINDLIB);
2809 if (cp != NULL)
2810 VG_(libdir) = cp;
2811 }
2812
2813 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002814 // Get valgrind args + client args (inc. from VALGRIND_OPTS/.valgrindrc).
2815 // Pre-process the command line.
2816 // p: n/a
2817 //--------------------------------------------------------------
nethercotef6a1d502004-08-09 12:21:57 +00002818 get_command_line(argc, argv, &vg_argc, &vg_argv, &cl_argv);
nethercote71980f02004-01-24 18:18:54 +00002819 pre_process_cmd_line_options(&need_help, &tool, &exec);
2820
2821 //==============================================================
2822 // Nb: once a tool is specified, the tool.so must be loaded even if
2823 // they specified --help or didn't specify a client program.
2824 //==============================================================
2825
2826 //--------------------------------------------------------------
2827 // With client padded out, map in tool
nethercote71980f02004-01-24 18:18:54 +00002828 // p: set-libdir [for VG_(libdir)]
2829 // p: pre_process_cmd_line_options() [for 'tool']
2830 //--------------------------------------------------------------
2831 load_tool(tool, &tool_dlhandle, &toolinfo, &preload);
2832
2833 //==============================================================
2834 // Can use VG_(malloc)() and VG_(arena_malloc)() only after load_tool()
nethercotec314eba2004-07-15 12:59:41 +00002835 // -- redzone size is now set. This is checked by vg_malloc2.c.
nethercote71980f02004-01-24 18:18:54 +00002836 //==============================================================
2837
2838 //--------------------------------------------------------------
2839 // Finalise address space layout
nethercote31779c72004-07-30 21:50:15 +00002840 // p: load_tool() [for 'toolinfo']
nethercote71980f02004-01-24 18:18:54 +00002841 //--------------------------------------------------------------
nethercote31779c72004-07-30 21:50:15 +00002842 layout_remaining_space( (Addr) & argc, toolinfo->shadow_ratio );
nethercote71980f02004-01-24 18:18:54 +00002843
2844 //--------------------------------------------------------------
2845 // Load client executable, finding in $PATH if necessary
nethercote71980f02004-01-24 18:18:54 +00002846 // p: pre_process_cmd_line_options() [for 'exec', 'need_help']
2847 // p: layout_remaining_space [so there's space]
2848 //--------------------------------------------------------------
nethercotef4928da2004-06-15 10:54:40 +00002849 load_client(cl_argv, exec, need_help, &info, &client_eip);
nethercote71980f02004-01-24 18:18:54 +00002850
2851 //--------------------------------------------------------------
2852 // Everything in place, unpad us
2853 // p: layout_remaining_space() [everything must be mapped in before now]
2854 // p: load_client() [ditto]
2855 //--------------------------------------------------------------
nethercote31779c72004-07-30 21:50:15 +00002856 as_unpad((void *)VG_(shadow_end), (void *)~0, padfile);
2857 as_closepadfile(padfile); // no more padding
nethercote71980f02004-01-24 18:18:54 +00002858
2859 //--------------------------------------------------------------
2860 // Set up client's environment
2861 // p: set-libdir [for VG_(libdir)]
2862 // p: load_tool() [for 'preload']
2863 //--------------------------------------------------------------
2864 env = fix_environment(environ, preload);
2865
2866 //--------------------------------------------------------------
nethercote5ee67ca2004-06-22 14:00:09 +00002867 // Setup client stack, eip, and VG_(client_arg[cv])
nethercote71980f02004-01-24 18:18:54 +00002868 // p: load_client() [for 'info']
2869 // p: fix_environment() [for 'env']
2870 //--------------------------------------------------------------
2871 esp_at_startup = setup_client_stack(cl_argv, env, &info, &client_auxv);
2872
2873 if (0)
2874 printf("entry=%x client esp=%x vg_argc=%d brkbase=%x\n",
nethercotef6a1d502004-08-09 12:21:57 +00002875 client_eip, esp_at_startup, vg_argc, VG_(brk_base));
nethercote71980f02004-01-24 18:18:54 +00002876
2877 //==============================================================
2878 // Finished setting up operating environment. Now initialise
2879 // Valgrind. (This is where the old VG_(main)() started.)
2880 //==============================================================
2881
2882 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002883 // atfork
2884 // p: n/a
2885 //--------------------------------------------------------------
2886 VG_(atfork)(NULL, NULL, newpid);
2887 newpid(VG_INVALID_THREADID);
2888
2889 //--------------------------------------------------------------
2890 // setup file descriptors
2891 // p: n/a
2892 //--------------------------------------------------------------
2893 setup_file_descriptors();
2894
2895 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002896 // Read /proc/self/maps into a buffer
2897 // p: all memory layout, environment setup [so memory maps are right]
2898 //--------------------------------------------------------------
2899 VG_(read_procselfmaps)();
2900
2901 //--------------------------------------------------------------
2902 // Build segment map (Valgrind segments only)
2903 // p: read proc/self/maps
2904 // p: sk_pre_clo_init() [to setup new_mem_startup tracker]
2905 //--------------------------------------------------------------
2906 VG_(parse_procselfmaps) ( build_valgrind_map_callback );
2907
2908 //==============================================================
2909 // Can use VG_(arena_malloc)() with non-CORE arena after segments set up
2910 //==============================================================
2911
2912 //--------------------------------------------------------------
2913 // Init tool: pre_clo_init, process cmd line, post_clo_init
2914 // p: setup_client_stack() [for 'VG_(client_arg[cv]']
2915 // p: load_tool() [for 'tool']
2916 // p: setup_file_descriptors() [for 'VG_(fd_xxx_limit)']
2917 // p: parse_procselfmaps [so VG segments are setup so tool can
2918 // call VG_(malloc)]
nethercote71980f02004-01-24 18:18:54 +00002919 //--------------------------------------------------------------
2920 (*toolinfo->sk_pre_clo_init)();
2921 VG_(tool_init_dlsym)(tool_dlhandle);
2922 VG_(sanity_check_needs)();
2923
nethercotef4928da2004-06-15 10:54:40 +00002924 // If --tool and --help/--help-debug was given, now give the core+tool
2925 // help message
nethercotef4928da2004-06-15 10:54:40 +00002926 if (need_help) {
2927 usage(/*--help-debug?*/2 == need_help);
2928 }
nethercotec314eba2004-07-15 12:59:41 +00002929 process_cmd_line_options(client_auxv, tool);
2930
2931 SK_(post_clo_init)();
nethercotef4928da2004-06-15 10:54:40 +00002932
2933 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002934 // Build segment map (all segments)
2935 // p: setup_client_stack() [for 'esp_at_startup']
2936 // p: init tool [for 'new_mem_startup']
nethercote71980f02004-01-24 18:18:54 +00002937 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002938 esp_at_startup___global_arg = esp_at_startup;
2939 VG_(parse_procselfmaps) ( build_segment_map_callback ); /* everything */
2940 esp_at_startup___global_arg = 0;
2941
2942 //--------------------------------------------------------------
nethercotef84f6952004-07-15 14:58:33 +00002943 // Protect client trampoline page (which is also sysinfo stuff)
2944 // p: segment stuff [otherwise get seg faults...]
nethercotec314eba2004-07-15 12:59:41 +00002945 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002946 VG_(mprotect)( (void *)VG_(client_trampoline_code),
2947 VG_(trampoline_code_length), VKI_PROT_READ|VKI_PROT_EXEC );
2948
2949 //==============================================================
2950 // Can use VG_(map)() after segments set up
2951 //==============================================================
nethercote71980f02004-01-24 18:18:54 +00002952
2953 //--------------------------------------------------------------
2954 // Allow GDB attach
2955 // p: process_cmd_line_options() [for VG_(clo_wait_for_gdb)]
2956 //--------------------------------------------------------------
2957 /* Hook to delay things long enough so we can get the pid and
2958 attach GDB in another shell. */
2959 if (VG_(clo_wait_for_gdb)) {
2960 VG_(printf)("pid=%d\n", VG_(getpid)());
2961 /* do "jump *$eip" to skip this in gdb */
2962 VG_(do_syscall)(__NR_pause);
2963 }
2964
2965 //--------------------------------------------------------------
nethercote1d447092004-02-01 17:29:59 +00002966 // Set up baseBlock
nethercote71980f02004-01-24 18:18:54 +00002967 // p: {pre,post}_clo_init() [for tool helper registration]
2968 // load_client() [for 'client_eip']
2969 // setup_client_stack() [for 'esp_at_startup']
2970 //--------------------------------------------------------------
2971 init_baseBlock(client_eip, esp_at_startup);
2972
2973 //--------------------------------------------------------------
2974 // Search for file descriptors that are inherited from our parent
2975 // p: process_cmd_line_options [for VG_(clo_track_fds)]
2976 //--------------------------------------------------------------
2977 if (VG_(clo_track_fds))
2978 VG_(init_preopened_fds)();
2979
2980 //--------------------------------------------------------------
2981 // Initialise the scheduler
2982 // p: init_baseBlock() [baseBlock regs copied into VG_(threads)[1]]
2983 // p: setup_file_descriptors() [else VG_(safe_fd)() breaks]
2984 //--------------------------------------------------------------
2985 VG_(scheduler_init)();
2986
2987 //--------------------------------------------------------------
2988 // Set up the ProxyLWP machinery
2989 // p: VG_(scheduler_init)()? [XXX: subtle dependency?]
nethercote71980f02004-01-24 18:18:54 +00002990 //--------------------------------------------------------------
2991 VG_(proxy_init)();
2992
2993 //--------------------------------------------------------------
2994 // Initialise the signal handling subsystem
2995 // p: VG_(atfork)(NULL, NULL, newpid) [else problems with sigmasks]
2996 // p: VG_(proxy_init)() [else breaks...]
2997 //--------------------------------------------------------------
2998 // Nb: temporarily parks the saved blocking-mask in saved_sigmask.
2999 VG_(sigstartup_actions)();
3000
3001 //--------------------------------------------------------------
3002 // Perhaps we're profiling Valgrind?
3003 // p: process_cmd_line_options() [for VG_(clo_profile)]
3004 // p: others?
3005 //
3006 // XXX: this seems to be broken? It always says the tool wasn't built
3007 // for profiling; vg_profile.c's functions don't seem to be overriding
3008 // vg_dummy_profile.c's?
3009 //
3010 // XXX: want this as early as possible. Looking for --profile
3011 // in pre_process_cmd_line_options() could get it earlier.
3012 //--------------------------------------------------------------
3013 if (VG_(clo_profile))
3014 VGP_(init_profiling)();
3015
3016 VGP_PUSHCC(VgpStartup);
3017
3018 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00003019 // Read suppression file
3020 // p: process_cmd_line_options() [for VG_(clo_suppressions)]
3021 //--------------------------------------------------------------
3022 if (VG_(needs).core_errors || VG_(needs).skin_errors)
3023 VG_(load_suppressions)();
3024
3025 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00003026 // Initialise translation table and translation cache
3027 // p: read_procselfmaps [so the anonymous mmaps for the TT/TC
3028 // aren't identified as part of the client, which would waste
3029 // > 20M of virtual address space.]
3030 //--------------------------------------------------------------
3031 VG_(init_tt_tc)();
3032
3033 //--------------------------------------------------------------
3034 // Read debug info to find glibc entry points to intercept
3035 // p: parse_procselfmaps? [XXX for debug info?]
3036 // p: init_tt_tc? [XXX ???]
3037 //--------------------------------------------------------------
3038 VG_(setup_code_redirect_table)();
3039
3040 //--------------------------------------------------------------
3041 // Verbosity message
3042 // p: end_rdtsc_calibration [so startup message is printed first]
3043 //--------------------------------------------------------------
3044 if (VG_(clo_verbosity) == 1)
3045 VG_(message)(Vg_UserMsg, "For more details, rerun with: -v");
3046 if (VG_(clo_verbosity) > 0)
3047 VG_(message)(Vg_UserMsg, "");
3048
3049 //--------------------------------------------------------------
3050 // Setup pointercheck
3051 // p: process_cmd_line_options() [for VG_(clo_pointercheck)]
3052 //--------------------------------------------------------------
3053 setup_pointercheck();
3054
nethercote71980f02004-01-24 18:18:54 +00003055 //--------------------------------------------------------------
3056 // Run!
3057 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00003058 VGP_POPCC(VgpStartup);
3059 VGP_PUSHCC(VgpSched);
3060
nethercote238a3c32004-08-09 13:13:31 +00003061 src = VG_(scheduler)( &exitcode, &last_run_tid, &fatal_sigNo );
nethercote71980f02004-01-24 18:18:54 +00003062
nethercote238a3c32004-08-09 13:13:31 +00003063 VGP_POPCC(VgpSched);
nethercote71980f02004-01-24 18:18:54 +00003064
3065
3066 //--------------------------------------------------------------
3067 // Finalisation: cleanup, messages, etc. Order no so important, only
3068 // affects what order the messages come.
3069 //--------------------------------------------------------------
3070 if (VG_(clo_verbosity) > 0)
3071 VG_(message)(Vg_UserMsg, "");
3072
3073 if (src == VgSrc_Deadlock) {
3074 VG_(message)(Vg_UserMsg,
3075 "Warning: pthread scheduler exited due to deadlock");
3076 }
3077
3078 /* Print out file descriptor summary and stats. */
3079 if (VG_(clo_track_fds))
nethercote3a42fb82004-08-03 18:08:50 +00003080 VG_(show_open_fds)();
nethercote71980f02004-01-24 18:18:54 +00003081
3082 if (VG_(needs).core_errors || VG_(needs).skin_errors)
3083 VG_(show_all_errors)();
3084
nethercote47dd12c2004-06-22 14:18:42 +00003085 SK_(fini)( exitcode );
nethercote71980f02004-01-24 18:18:54 +00003086
nethercote885dd912004-08-03 23:14:00 +00003087 VG_(sanity_check_general)( True /*include expensive checks*/ );
nethercote71980f02004-01-24 18:18:54 +00003088
3089 if (VG_(clo_verbosity) > 1)
nethercote3a42fb82004-08-03 18:08:50 +00003090 print_all_stats();
nethercote71980f02004-01-24 18:18:54 +00003091
nethercote71980f02004-01-24 18:18:54 +00003092 if (VG_(clo_profile))
3093 VGP_(done_profiling)();
3094
nethercote71980f02004-01-24 18:18:54 +00003095 /* We're exiting, so nuke all the threads and clean up the proxy LWPs */
3096 vg_assert(src == VgSrc_FatalSig ||
nethercote759dda32004-08-07 18:16:56 +00003097 VG_(threads)[last_run_tid].status == VgTs_Runnable ||
3098 VG_(threads)[last_run_tid].status == VgTs_WaitJoiner);
nethercote71980f02004-01-24 18:18:54 +00003099 VG_(nuke_all_threads_except)(VG_INVALID_THREADID);
3100
3101 //--------------------------------------------------------------
3102 // Exit, according to the scheduler's return code
3103 //--------------------------------------------------------------
3104 switch (src) {
3105 case VgSrc_ExitSyscall: /* the normal way out */
nethercote759dda32004-08-07 18:16:56 +00003106 vg_assert(last_run_tid > 0 && last_run_tid < VG_N_THREADS);
nethercote71980f02004-01-24 18:18:54 +00003107 VG_(proxy_shutdown)();
3108
3109 /* The thread's %EBX at the time it did __NR_exit() will hold
3110 the arg to __NR_exit(), so we just do __NR_exit() with
3111 that arg. */
nethercote47dd12c2004-06-22 14:18:42 +00003112 VG_(exit)( exitcode );
nethercote71980f02004-01-24 18:18:54 +00003113 /* NOT ALIVE HERE! */
3114 VG_(core_panic)("entered the afterlife in main() -- ExitSyscall");
3115 break; /* what the hell :) */
3116
3117 case VgSrc_Deadlock:
3118 /* Just exit now. No point in continuing. */
3119 VG_(proxy_shutdown)();
3120 VG_(exit)(0);
3121 VG_(core_panic)("entered the afterlife in main() -- Deadlock");
3122 break;
3123
nethercote71980f02004-01-24 18:18:54 +00003124 case VgSrc_FatalSig:
3125 /* We were killed by a fatal signal, so replicate the effect */
nethercote238a3c32004-08-09 13:13:31 +00003126 vg_assert(fatal_sigNo != -1);
3127 VG_(kill_self)(fatal_sigNo);
nethercote71980f02004-01-24 18:18:54 +00003128 VG_(core_panic)("main(): signal was supposed to be fatal");
3129 break;
3130
3131 default:
3132 VG_(core_panic)("main(): unexpected scheduler return code");
3133 }
3134
3135 abort();
3136}
3137
3138
sewardjde4a1d02002-03-22 01:27:54 +00003139/*--------------------------------------------------------------------*/
3140/*--- end vg_main.c ---*/
3141/*--------------------------------------------------------------------*/