blob: 929220e06cd553c87cab87176d13e79a9c411e57 [file] [log] [blame]
sewardjde4a1d02002-03-22 01:27:54 +00001
2/*--------------------------------------------------------------------*/
nethercote71980f02004-01-24 18:18:54 +00003/*--- Startup: the real stuff vg_main.c ---*/
sewardjde4a1d02002-03-22 01:27:54 +00004/*--------------------------------------------------------------------*/
5
6/*
njnc9539842002-10-02 13:26:35 +00007 This file is part of Valgrind, an extensible x86 protected-mode
8 emulator for monitoring program execution on x86-Unixes.
sewardjde4a1d02002-03-22 01:27:54 +00009
nethercotebb1c9912004-01-04 16:43:23 +000010 Copyright (C) 2000-2004 Julian Seward
sewardjde4a1d02002-03-22 01:27:54 +000011 jseward@acm.org
sewardjde4a1d02002-03-22 01:27:54 +000012
13 This program is free software; you can redistribute it and/or
14 modify it under the terms of the GNU General Public License as
15 published by the Free Software Foundation; either version 2 of the
16 License, or (at your option) any later version.
17
18 This program is distributed in the hope that it will be useful, but
19 WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 General Public License for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software
25 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
26 02111-1307, USA.
27
njn25e49d8e72002-09-23 09:36:25 +000028 The GNU General Public License is contained in the file COPYING.
sewardjde4a1d02002-03-22 01:27:54 +000029*/
30
nethercote71980f02004-01-24 18:18:54 +000031#define _FILE_OFFSET_BITS 64
sewardjde4a1d02002-03-22 01:27:54 +000032
nethercote71980f02004-01-24 18:18:54 +000033#include "vg_include.h"
34#include "ume.h"
35#include "ume_arch.h"
36#include "ume_archdefs.h"
37
38#include <dirent.h>
39#include <dlfcn.h>
40#include <errno.h>
41#include <fcntl.h>
42#include <stdio.h>
fitzhardingeb727d042004-01-06 00:18:21 +000043#include <stdlib.h>
nethercote71980f02004-01-24 18:18:54 +000044#include <string.h>
45#include <sys/mman.h>
46#include <sys/types.h>
47#include <sys/stat.h>
fitzhardingeb727d042004-01-06 00:18:21 +000048#include <sys/ptrace.h>
49#include <sys/signal.h>
fitzhardingeb727d042004-01-06 00:18:21 +000050#include <sys/wait.h>
51#include <unistd.h>
52
thughes74b8de22004-04-22 18:12:31 +000053#ifndef AT_DCACHEBSIZE
54#define AT_DCACHEBSIZE 19
55#endif /* AT_DCACHEBSIZE */
56
57#ifndef AT_ICACHEBSIZE
58#define AT_ICACHEBSIZE 20
59#endif /* AT_ICACHEBSIZE */
60
61#ifndef AT_UCACHEBSIZE
62#define AT_UCACHEBSIZE 21
63#endif /* AT_UCACHEBSIZE */
64
nethercote71980f02004-01-24 18:18:54 +000065#ifndef AT_SYSINFO
66#define AT_SYSINFO 32
67#endif /* AT_SYSINFO */
68
69#ifndef AT_SYSINFO_EHDR
70#define AT_SYSINFO_EHDR 33
71#endif /* AT_SYSINFO_EHDR */
72
73#ifndef AT_SECURE
74#define AT_SECURE 23 /* secure mode boolean */
75#endif /* AT_SECURE */
76
77/* Amount to reserve for Valgrind's internal heap */
78#define VALGRIND_HEAPSIZE (128*1024*1024)
79
80/* Amount to reserve for Valgrind's internal mappings */
81#define VALGRIND_MAPSIZE (128*1024*1024)
82
83/* redzone gap between client address space and shadow */
84#define REDZONE_SIZE (1 * 1024*1024)
85
86/* size multiple for client address space */
87#define CLIENT_SIZE_MULTIPLE (64 * 1024*1024)
88
89#define ISSPACE(cc) ((cc) == ' ' || (cc) == '\t' || (cc) == '\n')
90
91/*====================================================================*/
92/*=== Global entities not referenced from generated code ===*/
93/*====================================================================*/
94
sewardjde4a1d02002-03-22 01:27:54 +000095/* ---------------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +000096 Startup stuff
sewardjde4a1d02002-03-22 01:27:54 +000097 ------------------------------------------------------------------ */
nethercote71980f02004-01-24 18:18:54 +000098/* linker-defined base address */
99extern char kickstart_base;
sewardjde4a1d02002-03-22 01:27:54 +0000100
nethercote71980f02004-01-24 18:18:54 +0000101/* Client address space, lowest to highest (see top of ume.c) */
102Addr VG_(client_base); /* client address space limits */
fitzhardinge98abfc72003-12-16 02:05:15 +0000103Addr VG_(client_end);
104Addr VG_(client_mapbase);
fitzhardinge92360792003-12-24 10:11:11 +0000105Addr VG_(client_trampoline_code);
fitzhardinge98abfc72003-12-16 02:05:15 +0000106Addr VG_(clstk_base);
107Addr VG_(clstk_end);
nethercote71980f02004-01-24 18:18:54 +0000108
109Addr VG_(brk_base); /* start of brk */
110Addr VG_(brk_limit); /* current brk */
111
112Addr VG_(shadow_base); /* skin's shadow memory */
fitzhardinge98abfc72003-12-16 02:05:15 +0000113Addr VG_(shadow_end);
nethercote71980f02004-01-24 18:18:54 +0000114
115Addr VG_(valgrind_base); /* valgrind's address range */
116Addr VG_(valgrind_mmap_end); /* valgrind's mmaps are between valgrind_base and here */
fitzhardinge98abfc72003-12-16 02:05:15 +0000117Addr VG_(valgrind_end);
118
fitzhardingeb50068f2004-02-24 23:42:55 +0000119vki_rlimit VG_(client_rlimit_data);
120
nethercote71980f02004-01-24 18:18:54 +0000121/* This is set early to indicate whether this CPU has the
122 SSE/fxsave/fxrestor features. */
123Bool VG_(have_ssestate);
124
125/* Indicates presence, and holds address of client's sysinfo page, a
126 feature of some modern kernels used to provide vsyscalls, etc. */
127Bool VG_(sysinfo_page_exists) = False;
128Addr VG_(sysinfo_page_addr) = 0;
129
fitzhardinge98abfc72003-12-16 02:05:15 +0000130/* stage1 (main) executable */
fitzhardingea49f9b52003-12-16 22:26:45 +0000131Int VG_(vgexecfd) = -1;
132
133/* client executable */
134Int VG_(clexecfd) = -1;
fitzhardinge98abfc72003-12-16 02:05:15 +0000135
136/* Path to library directory */
137const Char *VG_(libdir) = VG_LIBDIR;
138
139/* our argc/argv */
140Int VG_(vg_argc);
141Char **VG_(vg_argv);
142
jsgf855d93d2003-10-13 22:26:55 +0000143/* PID of the main thread */
144Int VG_(main_pid);
145
146/* PGRP of process */
147Int VG_(main_pgrp);
njn25e49d8e72002-09-23 09:36:25 +0000148
fitzhardingef0046f22003-12-18 02:39:22 +0000149/* Maximum allowed application-visible file descriptor */
fitzhardingeb791a192003-12-18 07:22:44 +0000150Int VG_(max_fd) = -1;
fitzhardingef0046f22003-12-18 02:39:22 +0000151
nethercote71980f02004-01-24 18:18:54 +0000152/* As deduced from esp_at_startup, the client's argc, argv[] and
153 envp[] as extracted from the client's stack at startup-time. */
154Int VG_(client_argc);
155Char** VG_(client_argv);
156Char** VG_(client_envp);
sewardjde4a1d02002-03-22 01:27:54 +0000157
158/* ---------------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +0000159 Running stuff
sewardjde4a1d02002-03-22 01:27:54 +0000160 ------------------------------------------------------------------ */
nethercote71980f02004-01-24 18:18:54 +0000161/* Our signal delivery stack. */
njn6eba4ef2003-05-01 08:06:41 +0000162UInt VG_(sigstack)[VG_SIGSTACK_SIZE_W];
sewardjde4a1d02002-03-22 01:27:54 +0000163
nethercote71980f02004-01-24 18:18:54 +0000164/* jmp_buf for fatal signals */
165Int VG_(fatal_sigNo) = -1;
166Bool VG_(fatal_signal_set) = False;
167jmp_buf VG_(fatal_signal_jmpbuf);
sewardjde4a1d02002-03-22 01:27:54 +0000168
nethercote71980f02004-01-24 18:18:54 +0000169/* Counts downwards in VG_(run_innerloop). */
170UInt VG_(dispatch_ctr);
sewardjde4a1d02002-03-22 01:27:54 +0000171
172/* 64-bit counter for the number of basic blocks done. */
173ULong VG_(bbs_done);
sewardjde4a1d02002-03-22 01:27:54 +0000174
sewardj7e87e382002-05-03 19:09:05 +0000175/* This is the ThreadId of the last thread the scheduler ran. */
176ThreadId VG_(last_run_tid) = 0;
177
nethercote71980f02004-01-24 18:18:54 +0000178/* Tell the logging mechanism whether we are logging to a file
179 descriptor or a socket descriptor. */
180Bool VG_(logging_to_filedes) = True;
181
182/* This Bool is needed by wrappers in vg_clientmalloc.c to decide how
183 to behave. Initially we say False. */
184Bool VG_(running_on_simd_CPU) = False;
185
njn25e49d8e72002-09-23 09:36:25 +0000186/* This is the argument to __NR_exit() supplied by the first thread to
187 call that syscall. We eventually pass that to __NR_exit() for
188 real. */
njn633de322003-05-12 20:40:13 +0000189Int VG_(exitcode) = 0;
njn25e49d8e72002-09-23 09:36:25 +0000190
sewardj73cf3bc2002-11-03 03:20:15 +0000191
nethercote71980f02004-01-24 18:18:54 +0000192/*====================================================================*/
193/*=== Counters, for profiling purposes only ===*/
194/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +0000195
196/* Number of lookups which miss the fast tt helper. */
197UInt VG_(tt_fast_misses) = 0;
198
199
sewardjc0d8f682002-11-30 00:49:43 +0000200/* Counts for TT/TC informational messages. */
sewardjde4a1d02002-03-22 01:27:54 +0000201
sewardjde4a1d02002-03-22 01:27:54 +0000202/* Number and total o/t size of translations overall. */
203UInt VG_(overall_in_count) = 0;
204UInt VG_(overall_in_osize) = 0;
205UInt VG_(overall_in_tsize) = 0;
206/* Number and total o/t size of discards overall. */
207UInt VG_(overall_out_count) = 0;
208UInt VG_(overall_out_osize) = 0;
209UInt VG_(overall_out_tsize) = 0;
sewardjc0d8f682002-11-30 00:49:43 +0000210/* The number of discards of TT/TC. */
211UInt VG_(number_of_tc_discards) = 0;
sewardj22854b92002-11-30 14:00:47 +0000212/* Counts of chain and unchain operations done. */
213UInt VG_(bb_enchain_count) = 0;
214UInt VG_(bb_dechain_count) = 0;
215/* Number of unchained jumps performed. */
216UInt VG_(unchained_jumps_done) = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000217
218
219/* Counts pertaining to the register allocator. */
220
221/* total number of uinstrs input to reg-alloc */
222UInt VG_(uinstrs_prealloc) = 0;
223
224/* total number of uinstrs added due to spill code */
225UInt VG_(uinstrs_spill) = 0;
226
227/* number of bbs requiring spill code */
228UInt VG_(translations_needing_spill) = 0;
229
230/* total of register ranks over all translations */
231UInt VG_(total_reg_rank) = 0;
232
233
sewardjde4a1d02002-03-22 01:27:54 +0000234/* Counts pertaining to internal sanity checking. */
sewardjde4a1d02002-03-22 01:27:54 +0000235UInt VG_(sanity_fast_count) = 0;
236UInt VG_(sanity_slow_count) = 0;
237
sewardj2e93c502002-04-12 11:12:52 +0000238/* Counts pertaining to the scheduler. */
239UInt VG_(num_scheduling_events_MINOR) = 0;
240UInt VG_(num_scheduling_events_MAJOR) = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000241
242
nethercote71980f02004-01-24 18:18:54 +0000243static __inline__ Int safe_idiv(Int a, Int b)
244{
245 return (b == 0 ? 0 : a / b);
246}
247
248static void show_counts ( void )
249{
250 VG_(message)(Vg_DebugMsg,
251 " TT/TC: %d tc sectors discarded.",
252 VG_(number_of_tc_discards) );
253 VG_(message)(Vg_DebugMsg,
254 " %d chainings, %d unchainings.",
255 VG_(bb_enchain_count), VG_(bb_dechain_count) );
256 VG_(message)(Vg_DebugMsg,
257 "translate: new %d (%d -> %d; ratio %d:10)",
258 VG_(overall_in_count),
259 VG_(overall_in_osize),
260 VG_(overall_in_tsize),
261 safe_idiv(10*VG_(overall_in_tsize), VG_(overall_in_osize)));
262 VG_(message)(Vg_DebugMsg,
263 " discard %d (%d -> %d; ratio %d:10).",
264 VG_(overall_out_count),
265 VG_(overall_out_osize),
266 VG_(overall_out_tsize),
267 safe_idiv(10*VG_(overall_out_tsize), VG_(overall_out_osize)));
268 VG_(message)(Vg_DebugMsg,
269 " dispatch: %llu jumps (bb entries), of which %u (%lu%%) were unchained.",
270 VG_(bbs_done),
271 VG_(unchained_jumps_done),
272 ((ULong)(100) * (ULong)(VG_(unchained_jumps_done)))
273 / ( VG_(bbs_done)==0 ? 1 : VG_(bbs_done) )
274 );
275
276 VG_(message)(Vg_DebugMsg,
277 " %d/%d major/minor sched events. %d tt_fast misses.",
278 VG_(num_scheduling_events_MAJOR),
279 VG_(num_scheduling_events_MINOR),
280 VG_(tt_fast_misses));
281
282 VG_(message)(Vg_DebugMsg,
283 "reg-alloc: %d t-req-spill, "
284 "%d+%d orig+spill uis, %d total-reg-r.",
285 VG_(translations_needing_spill),
286 VG_(uinstrs_prealloc),
287 VG_(uinstrs_spill),
288 VG_(total_reg_rank) );
289 VG_(message)(Vg_DebugMsg,
290 " sanity: %d cheap, %d expensive checks.",
291 VG_(sanity_fast_count),
292 VG_(sanity_slow_count) );
293 VG_(print_ccall_stats)();
294}
295
296
297/*====================================================================*/
298/*=== Miscellaneous global functions ===*/
299/*====================================================================*/
300
nethercote04d0fbc2004-01-26 16:48:06 +0000301/* Start debugger and get it to attach to this process. Called if the
302 user requests this service after an error has been shown, so she can
nethercote71980f02004-01-24 18:18:54 +0000303 poke around and look at parameters, memory, etc. You can't
nethercote04d0fbc2004-01-26 16:48:06 +0000304 meaningfully get the debugger to continue the program, though; to
305 continue, quit the debugger. */
306void VG_(start_debugger) ( Int tid )
nethercote71980f02004-01-24 18:18:54 +0000307{
308 Int pid;
309
310 if ((pid = fork()) == 0) {
311 ptrace(PTRACE_TRACEME, 0, NULL, NULL);
312 VG_(kkill)(VG_(getpid)(), VKI_SIGSTOP);
313
314 } else if (pid > 0) {
315 struct user_regs_struct regs;
316 Int status;
317 Int res;
318
319 if (VG_(is_running_thread)( tid )) {
fitzhardinged65dcad2004-03-13 02:06:58 +0000320 regs.cs = VG_(baseBlock)[VGOFF_(m_cs)];
321 regs.ss = VG_(baseBlock)[VGOFF_(m_ss)];
322 regs.ds = VG_(baseBlock)[VGOFF_(m_ds)];
323 regs.es = VG_(baseBlock)[VGOFF_(m_es)];
324 regs.fs = VG_(baseBlock)[VGOFF_(m_fs)];
325 regs.gs = VG_(baseBlock)[VGOFF_(m_gs)];
nethercote71980f02004-01-24 18:18:54 +0000326 regs.eax = VG_(baseBlock)[VGOFF_(m_eax)];
327 regs.ebx = VG_(baseBlock)[VGOFF_(m_ebx)];
328 regs.ecx = VG_(baseBlock)[VGOFF_(m_ecx)];
329 regs.edx = VG_(baseBlock)[VGOFF_(m_edx)];
330 regs.esi = VG_(baseBlock)[VGOFF_(m_esi)];
331 regs.edi = VG_(baseBlock)[VGOFF_(m_edi)];
332 regs.ebp = VG_(baseBlock)[VGOFF_(m_ebp)];
333 regs.esp = VG_(baseBlock)[VGOFF_(m_esp)];
334 regs.eflags = VG_(baseBlock)[VGOFF_(m_eflags)];
335 regs.eip = VG_(baseBlock)[VGOFF_(m_eip)];
336 } else {
337 ThreadState* tst = & VG_(threads)[ tid ];
338
fitzhardinged65dcad2004-03-13 02:06:58 +0000339 regs.cs = tst->m_cs;
340 regs.ss = tst->m_ss;
341 regs.ds = tst->m_ds;
342 regs.es = tst->m_es;
343 regs.fs = tst->m_fs;
344 regs.gs = tst->m_gs;
nethercote71980f02004-01-24 18:18:54 +0000345 regs.eax = tst->m_eax;
346 regs.ebx = tst->m_ebx;
347 regs.ecx = tst->m_ecx;
348 regs.edx = tst->m_edx;
349 regs.esi = tst->m_esi;
350 regs.edi = tst->m_edi;
351 regs.ebp = tst->m_ebp;
352 regs.esp = tst->m_esp;
353 regs.eflags = tst->m_eflags;
354 regs.eip = tst->m_eip;
355 }
356
357 if ((res = VG_(waitpid)(pid, &status, 0)) == pid &&
358 WIFSTOPPED(status) && WSTOPSIG(status) == SIGSTOP &&
359 ptrace(PTRACE_SETREGS, pid, NULL, &regs) == 0 &&
thughes1d160052004-04-21 15:39:57 +0000360 kill(pid, SIGSTOP) == 0 &&
361 ptrace(PTRACE_DETACH, pid, NULL, 0) == 0) {
nethercote04d0fbc2004-01-26 16:48:06 +0000362 Char pidbuf[15];
363 Char file[30];
364 Char buf[100];
365 Char *bufptr;
366 Char *cmdptr;
367
368 VG_(sprintf)(pidbuf, "%d", pid);
369 VG_(sprintf)(file, "/proc/%d/fd/%d", pid, VG_(clexecfd));
370
371 bufptr = buf;
372 cmdptr = VG_(clo_db_command);
373
374 while (*cmdptr) {
375 switch (*cmdptr) {
376 case '%':
377 switch (*++cmdptr) {
378 case 'f':
379 VG_(memcpy)(bufptr, file, VG_(strlen)(file));
380 bufptr += VG_(strlen)(file);
381 cmdptr++;
382 break;
383 case 'p':
384 VG_(memcpy)(bufptr, pidbuf, VG_(strlen)(pidbuf));
385 bufptr += VG_(strlen)(pidbuf);
386 cmdptr++;
387 break;
388 default:
389 *bufptr++ = *cmdptr++;
390 break;
391 }
392 break;
393 default:
394 *bufptr++ = *cmdptr++;
395 break;
396 }
397 }
398
399 *bufptr++ = '\0';
400
401 VG_(message)(Vg_UserMsg, "starting debugger with cmd: %s", buf);
nethercote71980f02004-01-24 18:18:54 +0000402 res = VG_(system)(buf);
403 if (res == 0) {
404 VG_(message)(Vg_UserMsg, "");
405 VG_(message)(Vg_UserMsg,
nethercote04d0fbc2004-01-26 16:48:06 +0000406 "Debugger has detached. Valgrind regains control. We continue.");
nethercote71980f02004-01-24 18:18:54 +0000407 } else {
408 VG_(message)(Vg_UserMsg, "Apparently failed!");
409 VG_(message)(Vg_UserMsg, "");
410 }
411 }
412
413 VG_(kkill)(pid, VKI_SIGKILL);
414 VG_(waitpid)(pid, &status, 0);
415 }
416}
417
418
419/* Print some helpful-ish text about unimplemented things, and give
420 up. */
421void VG_(unimplemented) ( Char* msg )
422{
423 VG_(message)(Vg_UserMsg, "");
424 VG_(message)(Vg_UserMsg,
425 "Valgrind detected that your program requires");
426 VG_(message)(Vg_UserMsg,
427 "the following unimplemented functionality:");
428 VG_(message)(Vg_UserMsg, " %s", msg);
429 VG_(message)(Vg_UserMsg,
430 "This may be because the functionality is hard to implement,");
431 VG_(message)(Vg_UserMsg,
432 "or because no reasonable program would behave this way,");
433 VG_(message)(Vg_UserMsg,
434 "or because nobody has yet needed it. In any case, let us know at");
435 VG_(message)(Vg_UserMsg,
436 "%s and/or try to work around the problem, if you can.", VG_BUGS_TO);
437 VG_(message)(Vg_UserMsg,
438 "");
439 VG_(message)(Vg_UserMsg,
440 "Valgrind has to exit now. Sorry. Bye!");
441 VG_(message)(Vg_UserMsg,
442 "");
443 VG_(pp_sched_status)();
444 VG_(exit)(1);
445}
446
447Addr VG_(get_stack_pointer) ( void )
448{
449 return VG_(baseBlock)[VGOFF_(m_esp)];
450}
451
452/* Debugging thing .. can be called from assembly with OYNK macro. */
453void VG_(oynk) ( Int n )
454{
455 OINK(n);
456}
457
458/* Initialize the PID and PGRP of scheduler LWP; this is also called
459 in any new children after fork. */
460static void newpid(ThreadId unused)
461{
462 /* PID of scheduler LWP */
463 VG_(main_pid) = VG_(getpid)();
464 VG_(main_pgrp) = VG_(getpgrp)();
465}
466
467/*====================================================================*/
468/*=== Check we were launched by stage 1 ===*/
469/*====================================================================*/
470
471/* Look for our AUXV table */
472static void scan_auxv(void)
473{
474 const struct ume_auxv *auxv = find_auxv((int *)ume_exec_esp);
475 int found = 0;
476
477 for (; auxv->a_type != AT_NULL; auxv++)
478 switch(auxv->a_type) {
479 case AT_UME_PADFD:
480 as_setpadfd(auxv->u.a_val);
481 found |= 1;
482 break;
483
484 case AT_UME_EXECFD:
485 VG_(vgexecfd) = auxv->u.a_val;
486 found |= 2;
487 break;
488 }
489
490 if ( ! (1|2) ) {
491 fprintf(stderr, "stage2 must be launched by stage1\n");
492 exit(127);
493 }
494}
495
496
497/*====================================================================*/
498/*=== Address space determination ===*/
499/*====================================================================*/
500
501/* Pad client space so it doesn't get filled in before the right time */
502static void layout_client_space(Addr argc_addr)
503{
504 VG_(client_base) = CLIENT_BASE;
505 VG_(valgrind_mmap_end) = (addr_t)&kickstart_base; /* end of V's mmaps */
506 VG_(valgrind_base) = VG_(valgrind_mmap_end) - VALGRIND_MAPSIZE;
507 VG_(valgrind_end) = ROUNDUP(argc_addr, 0x10000); /* stack */
508
509 if (0)
510 printf("client base: %x\n"
511 "valgrind base--end: %x--%x (%x)\n"
512 "valgrind mmap end: %x\n\n",
513 VG_(client_base),
514 VG_(valgrind_base), VG_(valgrind_end),
515 VG_(valgrind_end) - VG_(valgrind_base),
516 VG_(valgrind_mmap_end));
517
518 as_pad((void *)VG_(client_base), (void *)VG_(valgrind_base));
519}
520
521static void layout_remaining_space(float ratio)
522{
523 /* This tries to give the client as large as possible address space while
524 * taking into account the tool's shadow needs. */
525 addr_t client_size = ROUNDDN((VG_(valgrind_base) - REDZONE_SIZE) / (1. + ratio),
526 CLIENT_SIZE_MULTIPLE);
527 addr_t shadow_size = PGROUNDUP(client_size * ratio);
528
529 VG_(client_end) = VG_(client_base) + client_size;
530 VG_(client_mapbase) = PGROUNDDN((client_size/4)*3); /* where !FIXED mmap goes */
531 VG_(client_trampoline_code) = VG_(client_end) - VKI_BYTES_PER_PAGE;
532
533 VG_(shadow_base) = VG_(client_end) + REDZONE_SIZE;
534 VG_(shadow_end) = VG_(shadow_base) + shadow_size;
535
536 if (0)
537 printf("client base--end: %x--%x (%x)\n"
538 "client mapbase: %x\n"
539 "shadow base--end: %x--%x (%x)\n\n",
540 VG_(client_base), VG_(client_end), client_size,
541 VG_(client_mapbase),
542 VG_(shadow_base), VG_(shadow_end), shadow_size);
543
544 // Ban redzone
545 mmap((void *)VG_(client_end), REDZONE_SIZE, PROT_NONE,
546 MAP_FIXED|MAP_ANON|MAP_PRIVATE, -1, 0);
547
548 // Make client hole
549 munmap((void*)VG_(client_base), client_size);
550
551 // Map shadow memory.
552 // Initially all inaccessible, incrementally initialized as it is used
553 if (shadow_size != 0)
554 mmap((char *)VG_(shadow_base), shadow_size, PROT_NONE,
555 MAP_PRIVATE|MAP_ANON|MAP_FIXED, -1, 0);
556}
557
558/*====================================================================*/
559/*=== Command line setup ===*/
560/*====================================================================*/
561
562/* Nb: malloc'd memory never freed -- kept throughout like argv, envp */
563static char* get_file_clo(char* dir)
564{
565# define FLEN 512
566 Int fd, n;
567 struct stat s1;
568 char* f_clo = NULL;
569 char filename[FLEN];
570
571 snprintf(filename, FLEN, "%s/.valgrindrc", ( NULL == dir ? "" : dir ) );
572 fd = VG_(open)(filename, 0, VKI_S_IRUSR);
573 if ( fd > 0 ) {
574 if ( 0 == fstat(fd, &s1) ) {
575 f_clo = malloc(s1.st_size+1);
576 vg_assert(f_clo);
577 n = read(fd, f_clo, s1.st_size);
578 if (n == -1) n = 0;
579 f_clo[n] = '\0';
580 }
581 close(fd);
582 }
583 return f_clo;
584# undef FLEN
585}
586
587static Int count_args(char* s)
588{
589 Int n = 0;
590 if (s) {
591 char* cp = s;
592 while (True) {
593 // We have alternating sequences: blanks, non-blanks, blanks...
594 // count the non-blanks sequences.
595 while ( ISSPACE(*cp) ) cp++;
596 if ( !*cp ) break;
597 n++;
598 while ( !ISSPACE(*cp) && *cp ) cp++;
599 }
600 }
601 return n;
602}
603
604/* add args out of environment, skipping multiple spaces and -- args */
605static char** copy_args( char* s, char** to )
606{
607 if (s) {
608 char* cp = s;
609 while (True) {
610 // We have alternating sequences: blanks, non-blanks, blanks...
611 // copy the non-blanks sequences, and add terminating '\0'
612 while ( ISSPACE(*cp) ) cp++;
613 if ( !*cp ) break;
614 *to++ = cp;
615 while ( !ISSPACE(*cp) && *cp ) cp++;
616 if ( *cp ) *cp++ = '\0'; // terminate if necessary
617 if (VG_STREQ(to[-1], "--")) to--; // undo any '--' arg
618 }
619 }
620 return to;
621}
622
623// Augment command line with arguments from environment and .valgrindrc
624// files.
625static void augment_command_line(Int* vg_argc_inout, char*** vg_argv_inout)
626{
627 int vg_argc = *vg_argc_inout;
628 char** vg_argv = *vg_argv_inout;
629
630 char* env_clo = getenv(VALGRINDOPTS);
631 char* f1_clo = get_file_clo( getenv("HOME") );
632 char* f2_clo = get_file_clo(".");
633
634 /* copy any extra args from file or environment, if present */
635 if ( (env_clo && *env_clo) || (f1_clo && *f1_clo) || (f2_clo && *f2_clo) ) {
636 /* ' ' separated extra options */
637 char **from;
638 char **to;
639 int env_arg_count, f1_arg_count, f2_arg_count;
640
641 env_arg_count = count_args(env_clo);
642 f1_arg_count = count_args(f1_clo);
643 f2_arg_count = count_args(f2_clo);
644
645 if (0)
646 printf("extra-argc=%d %d %d\n",
647 env_arg_count, f1_arg_count, f2_arg_count);
648
649 /* +2: +1 for null-termination, +1 for added '--' */
650 from = vg_argv;
651 vg_argv = malloc( (vg_argc + env_arg_count + f1_arg_count
652 + f2_arg_count + 2) * sizeof(char **));
653 to = vg_argv;
654
655 /* copy argv[0] */
656 *to++ = *from++;
657
658 /* Copy extra args from env var and file, in the order: ~/.valgrindrc,
659 * $VALGRIND_OPTS, ./.valgrindrc -- more local options are put later
660 * to override less local ones. */
661 to = copy_args(f1_clo, to);
662 to = copy_args(env_clo, to);
663 to = copy_args(f2_clo, to);
664
665 /* copy original arguments, stopping at command or -- */
666 while (*from) {
667 if (**from != '-')
668 break;
669 if (VG_STREQ(*from, "--")) {
670 from++; /* skip -- */
671 break;
672 }
673 *to++ = *from++;
674 }
675
676 /* add -- */
677 *to++ = "--";
678
679 vg_argc = to - vg_argv;
680
681 /* copy rest of original command line, then NULL */
682 while (*from) *to++ = *from++;
683 *to = NULL;
684 }
685
686 *vg_argc_inout = vg_argc;
687 *vg_argv_inout = vg_argv;
688}
689
690static void get_command_line( int argc, char** argv,
691 Int* vg_argc_out, Char*** vg_argv_out,
692 char*** cl_argv_out )
693{
694 int vg_argc;
695 char** vg_argv;
696 char** cl_argv;
697 char* env_clo = getenv(VALGRINDCLO);
698
699 if (env_clo != NULL && *env_clo != '\0') {
700 char *cp;
701 char **cpp;
702
703 /* OK, we're getting all our arguments from the environment - the
704 entire command line belongs to the client (including argv[0]) */
705 vg_argc = 1; /* argv[0] */
706 for (cp = env_clo; *cp; cp++)
707 if (*cp == '\01')
708 vg_argc++;
709
710 vg_argv = malloc(sizeof(char **) * (vg_argc + 1));
711
712 cpp = vg_argv;
713
714 *cpp++ = "valgrind"; /* nominal argv[0] */
715 *cpp++ = env_clo;
716
717 for (cp = env_clo; *cp; cp++) {
718 if (*cp == '\01') {
719 *cp++ = '\0'; /* chop it up in place */
720 *cpp++ = cp;
721 }
722 }
723 *cpp = NULL;
724 cl_argv = argv;
725
726 } else {
727 /* Count the arguments on the command line. */
728 vg_argv = argv;
729
730 for (vg_argc = 1; vg_argc < argc; vg_argc++) {
731 if (argv[vg_argc][0] != '-') /* exe name */
732 break;
733 if (VG_STREQ(argv[vg_argc], "--")) { /* dummy arg */
734 vg_argc++;
735 break;
736 }
737 }
738 cl_argv = &argv[vg_argc];
739
740 /* Get extra args from VALGRIND_OPTS and .valgrindrc files.
741 * Note we don't do this if getting args from VALGRINDCLO. */
742 augment_command_line(&vg_argc, &vg_argv);
743 }
744
745 if (0) {
746 Int i;
747 for (i = 0; i < vg_argc; i++)
748 printf("vg_argv[%d]=\"%s\"\n", i, vg_argv[i]);
749 }
750
751 *vg_argc_out = vg_argc;
752 *vg_argv_out = (Char**)vg_argv;
753 *cl_argv_out = cl_argv;
754}
755
756
757/*====================================================================*/
758/*=== Environment and stack setup ===*/
759/*====================================================================*/
760
761/* Scan a colon-separated list, and call a function on each element.
762 The string must be mutable, because we insert a temporary '\0', but
763 the string will end up unmodified. (*func) should return 1 if it
764 doesn't need to see any more.
765*/
766static void scan_colsep(char *colsep, int (*func)(const char *))
767{
768 char *cp, *entry;
769 int end;
770
771 if (colsep == NULL ||
772 *colsep == '\0')
773 return;
774
775 entry = cp = colsep;
776
777 do {
778 end = (*cp == '\0');
779
780 if (*cp == ':' || *cp == '\0') {
781 char save = *cp;
782
783 *cp = '\0';
784 if ((*func)(entry))
785 end = 1;
786 *cp = save;
787 entry = cp+1;
788 }
789 cp++;
790 } while(!end);
791}
792
793/* Prepare the client's environment. This is basically a copy of our
794 environment, except:
795 1. LD_LIBRARY_PATH=$VALGRINDLIB:$LD_LIBRARY_PATH
796 2. LD_PRELOAD=$VALGRINDLIB/vg_inject.so:($VALGRINDLIB/vgpreload_TOOL.so:)?$LD_PRELOAD
797
798 If any of these is missing, then it is added.
799
800 Yummy. String hacking in C.
801
802 If this needs to handle any more variables it should be hacked
803 into something table driven.
804 */
805static char **fix_environment(char **origenv, const char *preload)
806{
807 static const char inject_so[] = "vg_inject.so";
808 static const char ld_library_path[] = "LD_LIBRARY_PATH=";
809 static const char ld_preload[] = "LD_PRELOAD=";
810 static const char valgrind_clo[] = VALGRINDCLO "=";
811 static const int ld_library_path_len = sizeof(ld_library_path)-1;
812 static const int ld_preload_len = sizeof(ld_preload)-1;
813 static const int valgrind_clo_len = sizeof(valgrind_clo)-1;
814 int ld_preload_done = 0;
815 int ld_library_path_done = 0;
816 char *inject_path;
817 int inject_path_len;
818 int vgliblen = strlen(VG_(libdir));
819 char **cpp;
820 char **ret;
821 int envc;
822 const int preloadlen = (preload == NULL) ? 0 : strlen(preload);
823
824 /* Find the vg_inject.so; also make room for the tool preload
825 library */
826 inject_path_len = sizeof(inject_so) + vgliblen + preloadlen + 16;
827 inject_path = malloc(inject_path_len);
828
829 if (preload)
830 snprintf(inject_path, inject_path_len, "%s/%s:%s",
831 VG_(libdir), inject_so, preload);
832 else
833 snprintf(inject_path, inject_path_len, "%s/%s",
834 VG_(libdir), inject_so);
835
836 /* Count the original size of the env */
837 envc = 0; /* trailing NULL */
838 for (cpp = origenv; cpp && *cpp; cpp++)
839 envc++;
840
841 /* Allocate a new space */
842 ret = malloc(sizeof(char *) * (envc+3+1)); /* 3 new entries + NULL */
843
844 /* copy it over */
845 for (cpp = ret; *origenv; )
846 *cpp++ = *origenv++;
847 *cpp = NULL;
848
849 vg_assert(envc == (cpp - ret));
850
851 /* Walk over the new environment, mashing as we go */
852 for (cpp = ret; cpp && *cpp; cpp++) {
853 if (memcmp(*cpp, ld_library_path, ld_library_path_len) == 0) {
854 int done = 0;
855 int contains(const char *p) {
856 if (VG_STREQ(p, VG_(libdir))) {
857 done = 1;
858 return 1;
859 }
860 return 0;
861 }
862
863 /* If the LD_LIBRARY_PATH already contains libdir, then don't
864 bother adding it again, even if it isn't the first (it
865 seems that the Java runtime will keep reexecing itself
866 unless its paths are at the front of LD_LIBRARY_PATH) */
867 scan_colsep(*cpp + ld_library_path_len, contains);
868
869 if (!done) {
870 int len = strlen(*cpp) + vgliblen*2 + 16;
871 char *cp = malloc(len);
872
873 snprintf(cp, len, "%s%s:%s",
874 ld_library_path, VG_(libdir),
875 (*cpp)+ld_library_path_len);
876
877 *cpp = cp;
878 }
879
880 ld_library_path_done = 1;
881 } else if (memcmp(*cpp, ld_preload, ld_preload_len) == 0) {
882 int len = strlen(*cpp) + inject_path_len;
883 char *cp = malloc(len);
884
885 snprintf(cp, len, "%s%s:%s",
886 ld_preload, inject_path, (*cpp)+ld_preload_len);
887
888 *cpp = cp;
889
890 ld_preload_done = 1;
891 } else if (memcmp(*cpp, valgrind_clo, valgrind_clo_len) == 0) {
892 *cpp = "";
893 }
894 }
895
896 /* Add the missing bits */
897
898 if (!ld_library_path_done) {
899 int len = ld_library_path_len + vgliblen*2 + 16;
900 char *cp = malloc(len);
901
902 snprintf(cp, len, "%s%s", ld_library_path, VG_(libdir));
903
904 ret[envc++] = cp;
905 }
906
907 if (!ld_preload_done) {
908 int len = ld_preload_len + inject_path_len;
909 char *cp = malloc(len);
910
911 snprintf(cp, len, "%s%s",
912 ld_preload, inject_path);
913
914 ret[envc++] = cp;
915 }
916
917 ret[envc] = NULL;
918
919 return ret;
920}
921
922extern char **environ; /* our environment */
923//#include <error.h>
924
925/* Add a string onto the string table, and return its address */
926static char *copy_str(char **tab, const char *str)
927{
928 char *cp = *tab;
929 char *orig = cp;
930
931 while(*str)
932 *cp++ = *str++;
933 *cp++ = '\0';
934
935 if (0)
936 printf("copied %p \"%s\" len %d\n",
937 orig, orig, cp-orig);
938
939 *tab = cp;
940
941 return orig;
942}
943
944/*
945 This sets up the client's initial stack, containing the args,
946 environment and aux vector.
947
948 The format of the stack is:
949
950 higher address +-----------------+
951 | Trampoline code |
952 +-----------------+
953 | |
954 : string table :
955 | |
956 +-----------------+
957 | AT_NULL |
958 - -
959 | auxv |
960 +-----------------+
961 | NULL |
962 - -
963 | envp |
964 +-----------------+
965 | NULL |
966 - -
967 | argv |
968 +-----------------+
969 | argc |
970 lower address +-----------------+ <- esp
971 | undefined |
972 : :
973 */
974static Addr setup_client_stack(char **orig_argv, char **orig_envp,
975 const struct exeinfo *info,
976 UInt** client_auxv)
977{
978 char **cpp;
979 char *strtab; /* string table */
980 char *stringbase;
981 addr_t *ptr;
982 struct ume_auxv *auxv;
983 const struct ume_auxv *orig_auxv;
984 const struct ume_auxv *cauxv;
985 unsigned stringsize; /* total size of strings in bytes */
986 unsigned auxsize; /* total size of auxv in bytes */
987 int argc; /* total argc */
988 int envc; /* total number of env vars */
989 unsigned stacksize; /* total client stack size */
990 addr_t cl_esp; /* client stack base (initial esp) */
991
992 /* use our own auxv as a prototype */
993 orig_auxv = find_auxv(ume_exec_esp);
994
995 /* ==================== compute sizes ==================== */
996
997 /* first of all, work out how big the client stack will be */
998 stringsize = 0;
999
1000 /* paste on the extra args if the loader needs them (ie, the #!
1001 interpreter and its argument) */
1002 argc = 0;
1003 if (info->argv0 != NULL) {
1004 argc++;
1005 stringsize += strlen(info->argv0) + 1;
1006 }
1007 if (info->argv1 != NULL) {
1008 argc++;
1009 stringsize += strlen(info->argv1) + 1;
1010 }
1011
1012 /* now scan the args we're given... */
1013 for (cpp = orig_argv; *cpp; cpp++) {
1014 argc++;
1015 stringsize += strlen(*cpp) + 1;
1016 }
1017
1018 /* ...and the environment */
1019 envc = 0;
1020 for (cpp = orig_envp; cpp && *cpp; cpp++) {
1021 envc++;
1022 stringsize += strlen(*cpp) + 1;
1023 }
1024
1025 /* now, how big is the auxv? */
1026 auxsize = sizeof(*auxv); /* there's always at least one entry: AT_NULL */
1027 for (cauxv = orig_auxv; cauxv->a_type != AT_NULL; cauxv++) {
1028 if (cauxv->a_type == AT_PLATFORM)
1029 stringsize += strlen(cauxv->u.a_ptr) + 1;
1030 auxsize += sizeof(*cauxv);
1031 }
1032
1033 /* OK, now we know how big the client stack is */
1034 stacksize =
1035 sizeof(int) + /* argc */
1036 sizeof(char **)*argc + /* argv */
1037 sizeof(char **) + /* terminal NULL */
1038 sizeof(char **)*envc + /* envp */
1039 sizeof(char **) + /* terminal NULL */
1040 auxsize + /* auxv */
1041 ROUNDUP(stringsize, sizeof(int)) +/* strings (aligned) */
1042 VKI_BYTES_PER_PAGE; /* page for trampoline code */
1043
1044 /* cl_esp is the client's stack pointer */
1045 cl_esp = VG_(client_end) - stacksize;
1046 cl_esp = ROUNDDN(cl_esp, 16); /* make stack 16 byte aligned */
1047
nethercote71980f02004-01-24 18:18:54 +00001048 /* base of the string table (aligned) */
1049 stringbase = strtab = (char *)(VG_(client_trampoline_code) - ROUNDUP(stringsize, sizeof(int)));
1050
1051 VG_(clstk_base) = PGROUNDDN(cl_esp);
1052 VG_(clstk_end) = VG_(client_end);
1053
nethercote5ee67ca2004-06-22 14:00:09 +00001054 if (0)
1055 printf("stringsize=%d auxsize=%d stacksize=%d\n"
1056 "clstk_base %x\n"
1057 "clstk_end %x\n",
1058 stringsize, auxsize, stacksize, VG_(clstk_base), VG_(clstk_end));
1059
1060
nethercote71980f02004-01-24 18:18:54 +00001061 /* ==================== allocate space ==================== */
1062
1063 /* allocate a stack - mmap enough space for the stack */
1064 mmap((void *)PGROUNDDN(cl_esp),
1065 VG_(client_end) - PGROUNDDN(cl_esp),
1066 PROT_READ | PROT_WRITE | PROT_EXEC,
1067 MAP_PRIVATE | MAP_ANON | MAP_FIXED, -1, 0);
1068
1069
1070 /* ==================== copy client stack ==================== */
1071
1072 ptr = (addr_t *)cl_esp;
1073
1074 /* --- argc --- */
1075 *ptr++ = argc; /* client argc */
1076
1077 /* --- argv --- */
1078 if (info->argv0) {
1079 *ptr++ = (addr_t)copy_str(&strtab, info->argv0);
1080 free(info->argv0);
1081 }
1082 if (info->argv1) {
1083 *ptr++ = (addr_t)copy_str(&strtab, info->argv1);
1084 free(info->argv1);
1085 }
1086 for (cpp = orig_argv; *cpp; ptr++, cpp++) {
1087 *ptr = (addr_t)copy_str(&strtab, *cpp);
1088 }
1089 *ptr++ = 0;
1090
1091 /* --- envp --- */
1092 VG_(client_envp) = (Char **)ptr;
1093 for (cpp = orig_envp; cpp && *cpp; ptr++, cpp++)
1094 *ptr = (addr_t)copy_str(&strtab, *cpp);
1095 *ptr++ = 0;
1096
1097 /* --- auxv --- */
1098 auxv = (struct ume_auxv *)ptr;
1099 *client_auxv = (UInt *)auxv;
1100
1101 for (; orig_auxv->a_type != AT_NULL; auxv++, orig_auxv++) {
1102 /* copy the entry... */
1103 *auxv = *orig_auxv;
1104
1105 /* ...and fix up the copy */
1106 switch(auxv->a_type) {
1107 case AT_PHDR:
1108 if (info->phdr == 0)
1109 auxv->a_type = AT_IGNORE;
1110 else
1111 auxv->u.a_val = info->phdr;
1112 break;
1113
1114 case AT_PHNUM:
1115 if (info->phdr == 0)
1116 auxv->a_type = AT_IGNORE;
1117 else
1118 auxv->u.a_val = info->phnum;
1119 break;
1120
1121 case AT_BASE:
1122 if (info->interp_base == 0)
1123 auxv->a_type = AT_IGNORE;
1124 else
1125 auxv->u.a_val = info->interp_base;
1126 break;
1127
1128 case AT_PLATFORM: /* points to a platform description string */
1129 auxv->u.a_ptr = copy_str(&strtab, orig_auxv->u.a_ptr);
1130 break;
1131
1132 case AT_ENTRY:
1133 auxv->u.a_val = info->entry;
1134 break;
1135
1136 case AT_IGNORE:
1137 case AT_EXECFD:
1138 case AT_PHENT:
1139 case AT_PAGESZ:
1140 case AT_FLAGS:
1141 case AT_NOTELF:
1142 case AT_UID:
1143 case AT_EUID:
1144 case AT_GID:
1145 case AT_EGID:
1146 case AT_CLKTCK:
1147 case AT_HWCAP:
1148 case AT_FPUCW:
1149 case AT_DCACHEBSIZE:
1150 case AT_ICACHEBSIZE:
1151 case AT_UCACHEBSIZE:
1152 /* All these are pointerless, so we don't need to do anything
1153 about them. */
1154 break;
1155
1156 case AT_SECURE:
1157 /* If this is 1, then it means that this program is running
1158 suid, and therefore the dynamic linker should be careful
1159 about LD_PRELOAD, etc. However, since stage1 (the thing
1160 the kernel actually execve's) should never be SUID, and we
1161 need LD_PRELOAD/LD_LIBRARY_PATH to work for the client, we
1162 set AT_SECURE to 0. */
1163 auxv->u.a_val = 0;
1164 break;
1165
1166 case AT_SYSINFO:
1167 /* Leave this unmolested for now, but we'll update it later
1168 when we set up the client trampoline code page */
1169 break;
1170
1171 case AT_SYSINFO_EHDR:
1172 /* Trash this, because we don't reproduce it */
1173 auxv->a_type = AT_IGNORE;
1174 break;
1175
1176 default:
1177 /* stomp out anything we don't know about */
1178 if (0)
1179 printf("stomping auxv entry %d\n", auxv->a_type);
1180 auxv->a_type = AT_IGNORE;
1181 break;
1182
1183 }
1184 }
1185 *auxv = *orig_auxv;
1186 vg_assert(auxv->a_type == AT_NULL);
1187
1188 vg_assert((strtab-stringbase) == stringsize);
1189
nethercote5ee67ca2004-06-22 14:00:09 +00001190 /* We know the initial ESP is pointing at argc/argv */
1191 VG_(client_argc) = *(Int*)cl_esp;
1192 VG_(client_argv) = (Char**)(cl_esp + sizeof(Int));
1193
nethercote71980f02004-01-24 18:18:54 +00001194 return cl_esp;
1195}
1196
1197/*====================================================================*/
1198/*=== Find executable ===*/
1199/*====================================================================*/
1200
1201static const char* find_executable(const char* exec)
1202{
1203 vg_assert(NULL != exec);
1204 if (strchr(exec, '/') == NULL) {
1205 /* no '/' - we need to search the path */
1206 char *path = getenv("PATH");
1207 int pathlen = path ? strlen(path) : 0;
1208
1209 int match_exe(const char *entry) {
1210 char buf[pathlen + strlen(entry) + 3];
1211
1212 /* empty PATH element means . */
1213 if (*entry == '\0')
1214 entry = ".";
1215
1216 snprintf(buf, sizeof(buf), "%s/%s", entry, exec);
1217
1218 if (access(buf, R_OK|X_OK) == 0) {
1219 exec = strdup(buf);
1220 vg_assert(NULL != exec);
1221 return 1;
1222 }
1223 return 0;
1224 }
1225 scan_colsep(path, match_exe);
1226 }
1227 return exec;
1228}
1229
1230
1231/*====================================================================*/
1232/*=== Loading tools ===*/
1233/*====================================================================*/
1234
1235static void list_tools(void)
1236{
1237 DIR *dir = opendir(VG_(libdir));
1238 struct dirent *de;
1239 int first = 1;
1240
1241 if (dir == NULL) {
1242 fprintf(stderr, "Can't open %s: %s (installation problem?)\n",
nethercotef4928da2004-06-15 10:54:40 +00001243 VG_(libdir), strerror(errno));
nethercote71980f02004-01-24 18:18:54 +00001244 return;
1245 }
1246
nethercotef4928da2004-06-15 10:54:40 +00001247 while ((de = readdir(dir)) != NULL) {
nethercote71980f02004-01-24 18:18:54 +00001248 int len = strlen(de->d_name);
1249
1250 /* look for vgskin_TOOL.so names */
1251 if (len > (7+1+3) && /* "vgskin_" + at least 1-char toolname + ".so" */
nethercotef4928da2004-06-15 10:54:40 +00001252 strncmp(de->d_name, "vgskin_", 7) == 0 &&
1253 VG_STREQ(de->d_name + len - 3, ".so")) {
1254 if (first) {
1255 fprintf(stderr, "Available tools:\n");
1256 first = 0;
1257 }
1258 de->d_name[len-3] = '\0';
1259 fprintf(stderr, "\t%s\n", de->d_name+7);
nethercote71980f02004-01-24 18:18:54 +00001260 }
1261 }
1262
1263 closedir(dir);
1264
1265 if (first)
nethercotef4928da2004-06-15 10:54:40 +00001266 fprintf(stderr, "No tools available in \"%s\" (installation problem?)\n",
1267 VG_(libdir));
nethercote71980f02004-01-24 18:18:54 +00001268}
1269
1270
1271/* Find and load a tool, and check it looks ok. Also looks to see if there's
1272 * a matching vgpreload_*.so file, and returns its name in *preloadpath. */
1273static void load_tool( const char *toolname, void** handle_out,
1274 ToolInfo** toolinfo_out, char **preloadpath_out )
1275{
1276 Bool ok;
1277 int len = strlen(VG_(libdir)) + strlen(toolname)*2 + 16;
1278 char buf[len];
1279 void* handle;
1280 ToolInfo* toolinfo;
1281 char* preloadpath = NULL;
1282 Int* vg_malloc_redzonep;
1283
1284 // XXX: allowing full paths for --tool option -- does it make sense?
1285 // Doesn't allow for vgpreload_<tool>.so.
1286
1287 if (strchr(toolname, '/') != 0) {
1288 /* toolname contains '/', and so must be a pathname */
1289 handle = dlopen(toolname, RTLD_NOW);
1290 } else {
1291 /* just try in the libdir */
1292 snprintf(buf, len, "%s/vgskin_%s.so", VG_(libdir), toolname);
1293 handle = dlopen(buf, RTLD_NOW);
1294
1295 if (handle != NULL) {
1296 snprintf(buf, len, "%s/vgpreload_%s.so", VG_(libdir), toolname);
1297 if (access(buf, R_OK) == 0) {
1298 preloadpath = strdup(buf);
1299 vg_assert(NULL != preloadpath);
1300 }
1301 }
1302 }
1303
1304 ok = (NULL != handle);
1305 if (!ok) {
1306 fprintf(stderr, "Can't open tool \"%s\": %s\n", toolname, dlerror());
1307 goto bad_load;
1308 }
1309
1310 toolinfo = dlsym(handle, "vgSkin_tool_info");
1311 ok = (NULL != toolinfo);
1312 if (!ok) {
1313 fprintf(stderr, "Tool \"%s\" doesn't define SK_(tool_info) - "
1314 "add VG_DETERMINE_INTERFACE_VERSION?\n", toolname);
1315 goto bad_load;
1316 }
1317
1318 ok = (toolinfo->sizeof_ToolInfo == sizeof(*toolinfo) &&
1319 toolinfo->interface_major_version == VG_CORE_INTERFACE_MAJOR_VERSION &&
1320 toolinfo->sk_pre_clo_init != NULL);
1321 if (!ok) {
1322 fprintf(stderr, "Error:\n"
1323 " Tool and core interface versions do not match.\n"
1324 " Interface version used by core is: %d.%d (size %d)\n"
1325 " Interface version used by tool is: %d.%d (size %d)\n"
1326 " The major version numbers must match.\n",
1327 VG_CORE_INTERFACE_MAJOR_VERSION,
1328 VG_CORE_INTERFACE_MINOR_VERSION,
1329 sizeof(*toolinfo),
1330 toolinfo->interface_major_version,
1331 toolinfo->interface_minor_version,
1332 toolinfo->sizeof_ToolInfo);
1333 fprintf(stderr, " You need to at least recompile, and possibly update,\n");
1334 if (VG_CORE_INTERFACE_MAJOR_VERSION > toolinfo->interface_major_version)
1335 fprintf(stderr, " your skin to work with this version of Valgrind.\n");
1336 else
1337 fprintf(stderr, " your version of Valgrind to work with this skin.\n");
1338 goto bad_load;
1339 }
1340
1341 // Set redzone size for V's allocator
1342 vg_malloc_redzonep = dlsym(handle, STR(VG_(vg_malloc_redzone_szB)));
1343 if ( NULL != vg_malloc_redzonep ) {
1344 VG_(vg_malloc_redzone_szB) = *vg_malloc_redzonep;
1345 }
1346
1347 vg_assert(NULL != handle && NULL != toolinfo);
1348 *handle_out = handle;
1349 *toolinfo_out = toolinfo;
1350 *preloadpath_out = preloadpath;
1351 return;
1352
1353
1354 bad_load:
1355 if (handle != NULL)
1356 dlclose(handle);
1357
nethercotef4928da2004-06-15 10:54:40 +00001358 fprintf(stderr, "valgrind: couldn't load tool\n");
nethercote71980f02004-01-24 18:18:54 +00001359 list_tools();
1360 exit(127);
1361}
1362
nethercotef4928da2004-06-15 10:54:40 +00001363
1364/*====================================================================*/
1365/*=== Command line errors ===*/
1366/*====================================================================*/
1367
1368static void abort_msg ( void )
1369{
nethercotef8548672004-06-21 12:42:35 +00001370 VG_(clo_log_to) = VgLogTo_Fd;
1371 VG_(clo_log_fd) = 2; /* stderr */
nethercotef4928da2004-06-15 10:54:40 +00001372}
1373
1374void VG_(bad_option) ( Char* opt )
1375{
1376 abort_msg();
1377 VG_(printf)("valgrind: Bad option `%s'; aborting.\n", opt);
1378 VG_(printf)("valgrind: Use --help for more information.\n");
1379 VG_(exit)(1);
1380}
1381
1382static void missing_tool_option ( void )
1383{
1384 abort_msg();
1385 VG_(printf)("valgrind: Missing --tool option\n");
1386 list_tools();
1387 VG_(printf)("valgrind: Use --help for more information.\n");
1388 VG_(exit)(1);
1389}
1390
1391static void missing_prog ( void )
1392{
1393 abort_msg();
1394 VG_(printf)("valgrind: no program specified\n");
1395 VG_(printf)("valgrind: Use --help for more information.\n");
1396 VG_(exit)(1);
1397}
1398
1399static void config_error ( Char* msg )
1400{
1401 abort_msg();
1402 VG_(printf)("valgrind: Startup or configuration error:\n %s\n", msg);
1403 VG_(printf)("valgrind: Unable to start up properly. Giving up.\n");
1404 VG_(exit)(1);
1405}
1406
1407
nethercote71980f02004-01-24 18:18:54 +00001408/*====================================================================*/
1409/*=== Loading the client ===*/
1410/*====================================================================*/
1411
nethercotef4928da2004-06-15 10:54:40 +00001412static void load_client(char* cl_argv[], const char* exec, Int need_help,
nethercote71980f02004-01-24 18:18:54 +00001413 /*out*/struct exeinfo* info, /*out*/Addr* client_eip)
1414{
1415 // If they didn't specify an executable with --exec, and didn't specify
1416 // --help, then use client argv[0] (searching $PATH if necessary).
nethercotef4928da2004-06-15 10:54:40 +00001417 if (NULL == exec && !need_help) {
nethercote71980f02004-01-24 18:18:54 +00001418 if (cl_argv[0] == NULL ||
1419 ( NULL == (exec = find_executable(cl_argv[0])) ) )
1420 {
nethercotef4928da2004-06-15 10:54:40 +00001421 missing_prog();
nethercote71980f02004-01-24 18:18:54 +00001422 }
1423 }
1424
1425 info->map_base = VG_(client_mapbase);
nethercote71980f02004-01-24 18:18:54 +00001426
1427 info->exe_base = VG_(client_base);
1428 info->exe_end = VG_(client_end);
1429 info->argv = cl_argv;
1430
nethercotef4928da2004-06-15 10:54:40 +00001431 if (need_help) {
nethercote71980f02004-01-24 18:18:54 +00001432 VG_(clexecfd) = -1;
1433 info->argv0 = NULL;
1434 info->argv1 = NULL;
1435 } else {
1436 Int ret;
1437 VG_(clexecfd) = VG_(open)(exec, O_RDONLY, VKI_S_IRUSR);
1438 ret = do_exec(exec, info);
1439 if (ret != 0) {
nethercotef4928da2004-06-15 10:54:40 +00001440 fprintf(stderr, "valgrind: do_exec(%s) failed: %s\n", exec, strerror(ret));
nethercote71980f02004-01-24 18:18:54 +00001441 exit(127);
1442 }
1443 }
1444
1445 /* Copy necessary bits of 'info' that were filled in */
1446 *client_eip = info->init_eip;
1447 VG_(brk_base) = VG_(brk_limit) = info->brkbase;
1448}
1449
1450
1451/*====================================================================*/
1452/*=== Command-line: variables, processing ===*/
1453/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +00001454
njn25e49d8e72002-09-23 09:36:25 +00001455/* Define, and set defaults. */
1456Bool VG_(clo_error_limit) = True;
nethercote04d0fbc2004-01-26 16:48:06 +00001457Bool VG_(clo_db_attach) = False;
1458Char* VG_(clo_db_command) = VG_CLO_DEFAULT_DBCOMMAND;
njn43c799e2003-04-08 00:08:52 +00001459Bool VG_(clo_gen_suppressions) = False;
nethercote27fec902004-06-16 21:26:32 +00001460Int VG_(clo_sanity_level) = 1;
njn25e49d8e72002-09-23 09:36:25 +00001461Int VG_(clo_verbosity) = 1;
1462Bool VG_(clo_demangle) = True;
njn25e49d8e72002-09-23 09:36:25 +00001463Bool VG_(clo_trace_children) = False;
sewardj4cf05692002-10-27 20:28:29 +00001464
nethercotee1730692003-11-20 10:38:07 +00001465/* See big comment in vg_include.h for meaning of these three.
1466 fd is initially stdout, for --help, but gets moved to stderr by default
1467 immediately afterwards. */
sewardj4cf05692002-10-27 20:28:29 +00001468VgLogTo VG_(clo_log_to) = VgLogTo_Fd;
nethercotef8548672004-06-21 12:42:35 +00001469Int VG_(clo_log_fd) = 1;
1470Char* VG_(clo_log_name) = NULL;
sewardj4cf05692002-10-27 20:28:29 +00001471
sewardj6024b212003-07-13 10:54:33 +00001472Int VG_(clo_input_fd) = 0; /* stdin */
njn25e49d8e72002-09-23 09:36:25 +00001473Int VG_(clo_n_suppressions) = 0;
sewardjde4a1d02002-03-22 01:27:54 +00001474Char* VG_(clo_suppressions)[VG_CLO_MAX_SFILES];
njn25e49d8e72002-09-23 09:36:25 +00001475Bool VG_(clo_profile) = False;
1476Bool VG_(clo_single_step) = False;
1477Bool VG_(clo_optimise) = True;
1478UChar VG_(clo_trace_codegen) = 0; // 00000000b
1479Bool VG_(clo_trace_syscalls) = False;
1480Bool VG_(clo_trace_signals) = False;
1481Bool VG_(clo_trace_symtab) = False;
njn25e49d8e72002-09-23 09:36:25 +00001482Bool VG_(clo_trace_sched) = False;
1483Int VG_(clo_trace_pthread_level) = 0;
njn25e49d8e72002-09-23 09:36:25 +00001484Int VG_(clo_dump_error) = 0;
1485Int VG_(clo_backtrace_size) = 4;
1486Char* VG_(clo_weird_hacks) = NULL;
sewardj858964b2002-10-05 14:15:43 +00001487Bool VG_(clo_run_libc_freeres) = True;
rjwalshf5f536f2003-11-17 17:45:00 +00001488Bool VG_(clo_track_fds) = False;
sewardj22854b92002-11-30 14:00:47 +00001489Bool VG_(clo_chain_bb) = True;
nethercote77eba602003-11-13 17:35:04 +00001490Bool VG_(clo_show_below_main) = False;
fitzhardinge98abfc72003-12-16 02:05:15 +00001491Bool VG_(clo_pointercheck) = True;
fitzhardinge462f4f92003-12-18 02:10:54 +00001492Bool VG_(clo_branchpred) = False;
sewardj2370f3b2002-11-30 15:01:01 +00001493
jsgf855d93d2003-10-13 22:26:55 +00001494static Bool VG_(clo_wait_for_gdb) = False;
1495
1496/* If we're doing signal routing, poll for signals every 50mS by
1497 default. */
1498Int VG_(clo_signal_polltime) = 50;
1499
1500/* These flags reduce thread wakeup latency on syscall completion and
1501 signal delivery, respectively. The downside is possible unfairness. */
1502Bool VG_(clo_lowlat_syscalls) = False; /* low-latency syscalls */
1503Bool VG_(clo_lowlat_signals) = False; /* low-latency signals */
1504
sewardjde4a1d02002-03-22 01:27:54 +00001505
nethercote6c999f22004-01-31 22:55:15 +00001506void usage ( Bool debug_help )
njn7cf0bd32002-06-08 13:36:03 +00001507{
njn25e49d8e72002-09-23 09:36:25 +00001508 Char* usage1 =
nethercote71980f02004-01-24 18:18:54 +00001509"usage: valgrind --tool=<toolname> [options] prog-and-args\n"
njn25e49d8e72002-09-23 09:36:25 +00001510"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001511" common user options for all Valgrind tools, with defaults in [ ]:\n"
nethercote0d588502004-06-21 13:27:11 +00001512" --tool=<name> use the Valgrind tool named <name>\n"
nethercotea76368b2004-06-16 11:56:29 +00001513" -h --help show this message\n"
nethercote6c999f22004-01-31 22:55:15 +00001514" --help-debug show this message, plus debugging options\n"
njn25e49d8e72002-09-23 09:36:25 +00001515" --version show version\n"
njn25e49d8e72002-09-23 09:36:25 +00001516" -q --quiet run silently; only print error msgs\n"
1517" -v --verbose be more verbose, incl counts of errors\n"
nethercote77eba602003-11-13 17:35:04 +00001518" --trace-children=no|yes Valgrind-ise child processes? [no]\n"
nethercote0d588502004-06-21 13:27:11 +00001519" --track-fds=no|yes track open file descriptors? [no]\n"
nethercote2b0793f2003-12-02 10:41:18 +00001520"\n"
1521" uncommon user options for all Valgrind tools:\n"
nethercote0d588502004-06-21 13:27:11 +00001522" --run-libc-freeres=no|yes free up glibc memory at exit? [yes]\n"
1523" --weird-hacks=hack1,hack2,... recognised hacks: lax-ioctls [none]\n"
1524" --signal-polltime=<time> signal poll period (mS) for older kernels [50]\n"
1525" --lowlat-signals=no|yes improve thread signal wake-up latency [no]\n"
1526" --lowlat-syscalls=no|yes improve thread syscall wake-up latency [no]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001527" --pointercheck=no|yes enforce client address space limits [yes]\n"
njn25e49d8e72002-09-23 09:36:25 +00001528"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001529" user options for Valgrind tools that report errors:\n"
nethercotef8548672004-06-21 12:42:35 +00001530" --log-fd=<number> log messages to file descriptor [2=stderr]\n"
1531" --log-file=<file> log messages to <file>.pid<pid>\n"
1532" --log-socket=ipaddr:port log messages to socket ipaddr:port\n"
nethercote2b0793f2003-12-02 10:41:18 +00001533" --demangle=no|yes automatically demangle C++ names? [yes]\n"
1534" --num-callers=<number> show <num> callers in stack traces [4]\n"
1535" --error-limit=no|yes stop showing new errors if too many? [yes]\n"
1536" --show-below-main=no|yes continue stack traces below main() [no]\n"
1537" --suppressions=<filename> suppress errors described in <filename>\n"
1538" --gen-suppressions=no|yes print suppressions for errors detected [no]\n"
nethercote04d0fbc2004-01-26 16:48:06 +00001539" --db-attach=no|yes start debugger when errors detected? [no]\n"
1540" --db-command=<command> command to start debugger [gdb -nw %%f %%p]\n"
1541" --input-fd=<number> file descriptor for input [0=stdin]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001542"\n";
njn7cf0bd32002-06-08 13:36:03 +00001543
njn25e49d8e72002-09-23 09:36:25 +00001544 Char* usage2 =
1545"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001546" debugging options for all Valgrind tools:\n"
njn25e49d8e72002-09-23 09:36:25 +00001547" --sanity-level=<number> level of sanity checking to do [1]\n"
1548" --single-step=no|yes translate each instr separately? [no]\n"
1549" --optimise=no|yes improve intermediate code? [yes]\n"
nethercote137bc552003-11-14 17:47:54 +00001550" --profile=no|yes profile? (tool must be built for it) [no]\n"
sewardj22854b92002-11-30 14:00:47 +00001551" --chain-bb=no|yes do basic-block chaining? [yes]\n"
fitzhardinge462f4f92003-12-18 02:10:54 +00001552" --branchpred=yes|no generate branch prediction hints [no]\n"
njn25e49d8e72002-09-23 09:36:25 +00001553" --trace-codegen=<XXXXX> show generated code? (X = 0|1) [00000]\n"
1554" --trace-syscalls=no|yes show all system calls? [no]\n"
1555" --trace-signals=no|yes show signal handling details? [no]\n"
1556" --trace-symtab=no|yes show symbol table details? [no]\n"
njn25e49d8e72002-09-23 09:36:25 +00001557" --trace-sched=no|yes show thread scheduler details? [no]\n"
njn3e884182003-04-15 13:03:23 +00001558" --trace-pthread=none|some|all show pthread event details? [none]\n"
jsgf855d93d2003-10-13 22:26:55 +00001559" --wait-for-gdb=yes|no pause on startup to wait for gdb attach\n"
njn25e49d8e72002-09-23 09:36:25 +00001560"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001561" debugging options for Valgrind tools that report errors\n"
1562" --dump-error=<number> show translation for basic block associated\n"
1563" with <number>'th error context [0=show none]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001564"\n";
njn3e884182003-04-15 13:03:23 +00001565
1566 Char* usage3 =
1567"\n"
nethercote71980f02004-01-24 18:18:54 +00001568" Extra options read from ~/.valgrindrc, $VALGRIND_OPTS, ./.valgrindrc\n"
njn25e49d8e72002-09-23 09:36:25 +00001569"\n"
nethercotebb1c9912004-01-04 16:43:23 +00001570" Valgrind is Copyright (C) 2000-2004 Julian Seward\n"
njn25e49d8e72002-09-23 09:36:25 +00001571" and licensed under the GNU General Public License, version 2.\n"
1572" Bug reports, feedback, admiration, abuse, etc, to: %s.\n"
njnd04b7c62002-10-03 14:05:52 +00001573"\n"
nethercote137bc552003-11-14 17:47:54 +00001574" Tools are copyright and licensed by their authors. See each\n"
1575" tool's start-up message for more information.\n"
njn25e49d8e72002-09-23 09:36:25 +00001576"\n";
njn7cf0bd32002-06-08 13:36:03 +00001577
fitzhardinge98abfc72003-12-16 02:05:15 +00001578 VG_(printf)(usage1);
1579 if (VG_(details).name) {
1580 VG_(printf)(" user options for %s:\n", VG_(details).name);
fitzhardinge98abfc72003-12-16 02:05:15 +00001581 if (VG_(needs).command_line_options)
1582 SK_(print_usage)();
1583 else
1584 VG_(printf)(" (none)\n");
1585 }
nethercote6c999f22004-01-31 22:55:15 +00001586 if (debug_help) {
1587 VG_(printf)(usage2);
fitzhardinge98abfc72003-12-16 02:05:15 +00001588
nethercote6c999f22004-01-31 22:55:15 +00001589 if (VG_(details).name) {
1590 VG_(printf)(" debugging options for %s:\n", VG_(details).name);
1591
1592 if (VG_(needs).command_line_options)
1593 SK_(print_debug_usage)();
1594 else
1595 VG_(printf)(" (none)\n");
1596 }
fitzhardinge98abfc72003-12-16 02:05:15 +00001597 }
nethercote421281e2003-11-20 16:20:55 +00001598 VG_(printf)(usage3, VG_BUGS_TO);
nethercotef4928da2004-06-15 10:54:40 +00001599 VG_(exit)(0);
njn7cf0bd32002-06-08 13:36:03 +00001600}
sewardjde4a1d02002-03-22 01:27:54 +00001601
nethercote71980f02004-01-24 18:18:54 +00001602static void pre_process_cmd_line_options
nethercote6c999f22004-01-31 22:55:15 +00001603 ( Int* need_help, const char** tool, const char** exec )
sewardj1c1b1162003-02-23 01:25:51 +00001604{
nethercote71980f02004-01-24 18:18:54 +00001605 UInt i;
sewardjde4a1d02002-03-22 01:27:54 +00001606
nethercote71980f02004-01-24 18:18:54 +00001607 /* parse the options we have (only the options we care about now) */
1608 for (i = 1; i < VG_(vg_argc); i++) {
1609
1610 if (strcmp(VG_(vg_argv)[i], "--version") == 0) {
1611 printf("valgrind-" VERSION "\n");
nethercotef4928da2004-06-15 10:54:40 +00001612 exit(0);
nethercote71980f02004-01-24 18:18:54 +00001613
nethercotea76368b2004-06-16 11:56:29 +00001614 } else if (VG_CLO_STREQ(VG_(vg_argv)[i], "--help") ||
1615 VG_CLO_STREQ(VG_(vg_argv)[i], "-h")) {
nethercote6c999f22004-01-31 22:55:15 +00001616 *need_help = 1;
1617
nethercotef4928da2004-06-15 10:54:40 +00001618 } else if (VG_CLO_STREQ(VG_(vg_argv)[i], "--help-debug")) {
nethercote6c999f22004-01-31 22:55:15 +00001619 *need_help = 2;
nethercote71980f02004-01-24 18:18:54 +00001620
nethercotef4928da2004-06-15 10:54:40 +00001621 } else if (VG_CLO_STREQN(7, VG_(vg_argv)[i], "--tool=") ||
1622 VG_CLO_STREQN(7, VG_(vg_argv)[i], "--skin=")) {
nethercote71980f02004-01-24 18:18:54 +00001623 *tool = &VG_(vg_argv)[i][7];
1624
nethercotef4928da2004-06-15 10:54:40 +00001625 } else if (VG_CLO_STREQN(7, VG_(vg_argv)[i], "--exec=")) {
nethercote71980f02004-01-24 18:18:54 +00001626 *exec = &VG_(vg_argv)[i][7];
1627 }
1628 }
1629
nethercotef4928da2004-06-15 10:54:40 +00001630 /* If no tool specified, can act appropriately without loading tool */
nethercote71980f02004-01-24 18:18:54 +00001631 if (*tool == NULL) {
nethercotef4928da2004-06-15 10:54:40 +00001632 if (0 == *need_help) {
1633 // neither --tool nor --help/--help-debug specified
1634 missing_tool_option();
1635 } else {
1636 // Give help message, without any tool-specific help
1637 usage(/*help-debug?*/2 == *need_help);
1638 }
nethercote71980f02004-01-24 18:18:54 +00001639 }
1640}
1641
nethercote5ee67ca2004-06-22 14:00:09 +00001642static void process_cmd_line_options( UInt* client_auxv, const char* toolname )
nethercote71980f02004-01-24 18:18:54 +00001643{
nethercotef8548672004-06-21 12:42:35 +00001644 Int i, eventually_log_fd;
nethercote71980f02004-01-24 18:18:54 +00001645 Int *auxp;
1646 Int toolname_len = VG_(strlen)(toolname);
sewardjde4a1d02002-03-22 01:27:54 +00001647
nethercotee1730692003-11-20 10:38:07 +00001648 /* log to stderr by default, but usage message goes to stdout */
nethercotef8548672004-06-21 12:42:35 +00001649 eventually_log_fd = 2;
sewardjde4a1d02002-03-22 01:27:54 +00001650
sewardj19d81412002-06-03 01:10:40 +00001651 /* Check for sane path in ./configure --prefix=... */
fitzhardinge98abfc72003-12-16 02:05:15 +00001652 if (VG_LIBDIR[0] != '/')
sewardj19d81412002-06-03 01:10:40 +00001653 config_error("Please use absolute paths in "
1654 "./configure --prefix=... or --libdir=...");
sewardj38170912002-05-10 21:07:22 +00001655
nethercote71980f02004-01-24 18:18:54 +00001656 for (auxp = client_auxv; auxp[0] != VKI_AT_NULL; auxp += 2) {
fitzhardinge98abfc72003-12-16 02:05:15 +00001657 switch(auxp[0]) {
1658 case VKI_AT_SYSINFO:
1659 VG_(sysinfo_page_exists) = True;
fitzhardinge92360792003-12-24 10:11:11 +00001660 auxp[1] = (Int)(VG_(client_trampoline_code) + VG_(tramp_syscall_offset));
fitzhardinge98abfc72003-12-16 02:05:15 +00001661 VG_(sysinfo_page_addr) = auxp[1];
1662 break;
sewardjde4a1d02002-03-22 01:27:54 +00001663 }
fitzhardinge98abfc72003-12-16 02:05:15 +00001664 }
sewardjde4a1d02002-03-22 01:27:54 +00001665
nethercote71980f02004-01-24 18:18:54 +00001666 for (i = 1; i < VG_(vg_argc); i++) {
1667
1668 Char* arg = VG_(vg_argv)[i];
1669
1670 // XXX: allow colons in options, for Josef
1671
1672 /* Look for matching "--toolname:foo" */
1673 if (VG_(strstr)(arg, ":")) {
1674 if (VG_CLO_STREQN(2, arg, "--") &&
1675 VG_CLO_STREQN(toolname_len, arg+2, toolname) &&
1676 VG_CLO_STREQN(1, arg+2+toolname_len, ":"))
1677 {
1678 // prefix matches, convert "--toolname:foo" to "--foo"
1679 if (0)
1680 VG_(printf)("tool-specific arg: %s\n", arg);
1681 arg += toolname_len + 1;
1682 arg[0] = '-';
1683 arg[1] = '-';
1684
1685 } else {
1686 // prefix doesn't match, skip to next arg
1687 continue;
1688 }
1689 }
1690
fitzhardinge98abfc72003-12-16 02:05:15 +00001691 /* Ignore these options - they've already been handled */
nethercote71980f02004-01-24 18:18:54 +00001692 if (VG_CLO_STREQN(7, arg, "--tool=") ||
1693 VG_CLO_STREQN(7, arg, "--skin="))
fitzhardinge98abfc72003-12-16 02:05:15 +00001694 continue;
nethercote71980f02004-01-24 18:18:54 +00001695 if (VG_CLO_STREQN(7, arg, "--exec="))
fitzhardinge98abfc72003-12-16 02:05:15 +00001696 continue;
1697
nethercote71980f02004-01-24 18:18:54 +00001698 if ( VG_CLO_STREQ(arg, "--"))
fitzhardinge98abfc72003-12-16 02:05:15 +00001699 continue;
nethercote27fec902004-06-16 21:26:32 +00001700
nethercote71980f02004-01-24 18:18:54 +00001701 else if (VG_CLO_STREQ(arg, "-v") ||
1702 VG_CLO_STREQ(arg, "--verbose"))
sewardjde4a1d02002-03-22 01:27:54 +00001703 VG_(clo_verbosity)++;
nethercote27fec902004-06-16 21:26:32 +00001704
nethercote71980f02004-01-24 18:18:54 +00001705 else if (VG_CLO_STREQ(arg, "-q") ||
1706 VG_CLO_STREQ(arg, "--quiet"))
sewardjde4a1d02002-03-22 01:27:54 +00001707 VG_(clo_verbosity)--;
1708
nethercote27fec902004-06-16 21:26:32 +00001709 else VG_BOOL_CLO("--branchpred", VG_(clo_branchpred))
1710 else VG_BOOL_CLO("--chain-bb", VG_(clo_chain_bb))
1711 else VG_BOOL_CLO("--db-attach", VG_(clo_db_attach))
1712 else VG_BOOL_CLO("--demangle", VG_(clo_demangle))
1713 else VG_BOOL_CLO("--error-limit", VG_(clo_error_limit))
1714 else VG_BOOL_CLO("--gen-suppressions", VG_(clo_gen_suppressions))
1715 else VG_BOOL_CLO("--lowlat-signals", VG_(clo_lowlat_signals))
1716 else VG_BOOL_CLO("--lowlat-syscalls", VG_(clo_lowlat_syscalls))
1717 else VG_BOOL_CLO("--optimise", VG_(clo_optimise))
1718 else VG_BOOL_CLO("--pointercheck", VG_(clo_pointercheck))
1719 else VG_BOOL_CLO("--profile", VG_(clo_profile))
1720 else VG_BOOL_CLO("--run-libc-freeres", VG_(clo_run_libc_freeres))
1721 else VG_BOOL_CLO("--show-below-main", VG_(clo_show_below_main))
1722 else VG_BOOL_CLO("--single-step", VG_(clo_single_step))
1723 else VG_BOOL_CLO("--track-fds", VG_(clo_track_fds))
1724 else VG_BOOL_CLO("--trace-children", VG_(clo_trace_children))
1725 else VG_BOOL_CLO("--trace-sched", VG_(clo_trace_sched))
1726 else VG_BOOL_CLO("--trace-signals", VG_(clo_trace_signals))
1727 else VG_BOOL_CLO("--trace-symtab", VG_(clo_trace_symtab))
1728 else VG_BOOL_CLO("--trace-syscalls", VG_(clo_trace_syscalls))
1729 else VG_BOOL_CLO("--wait-for-gdb", VG_(clo_wait_for_gdb))
sewardj72f98ff2002-06-13 17:23:38 +00001730
nethercote27fec902004-06-16 21:26:32 +00001731 else VG_STR_CLO ("--db-command", VG_(clo_db_command))
1732 else VG_STR_CLO ("--weird-hacks", VG_(clo_weird_hacks))
sewardjde4a1d02002-03-22 01:27:54 +00001733
nethercote27fec902004-06-16 21:26:32 +00001734 else VG_NUM_CLO ("--dump-error", VG_(clo_dump_error))
1735 else VG_NUM_CLO ("--input-fd", VG_(clo_input_fd))
1736 else VG_NUM_CLO ("--sanity-level", VG_(clo_sanity_level))
1737 else VG_NUM_CLO ("--signal­polltime", VG_(clo_signal_polltime))
1738 else VG_BNUM_CLO("--num-callers", VG_(clo_backtrace_size), 1,
1739 VG_DEEPEST_BACKTRACE)
sewardjde4a1d02002-03-22 01:27:54 +00001740
nethercotef8548672004-06-21 12:42:35 +00001741 // for backwards compatibility, replaced by --log-fd
nethercote71980f02004-01-24 18:18:54 +00001742 else if (VG_CLO_STREQN(13, arg, "--logfile-fd=")) {
nethercotef8548672004-06-21 12:42:35 +00001743 VG_(clo_log_to) = VgLogTo_Fd;
1744 VG_(clo_log_name) = NULL;
1745 eventually_log_fd = (Int)VG_(atoll)(&arg[13]);
1746 }
1747 else if (VG_CLO_STREQN(9, arg, "--log-fd=")) {
1748 VG_(clo_log_to) = VgLogTo_Fd;
1749 VG_(clo_log_name) = NULL;
1750 eventually_log_fd = (Int)VG_(atoll)(&arg[9]);
sewardj4cf05692002-10-27 20:28:29 +00001751 }
1752
nethercotef8548672004-06-21 12:42:35 +00001753 // for backwards compatibility, replaced by --log-file
nethercote71980f02004-01-24 18:18:54 +00001754 else if (VG_CLO_STREQN(10, arg, "--logfile=")) {
nethercotef8548672004-06-21 12:42:35 +00001755 VG_(clo_log_to) = VgLogTo_File;
1756 VG_(clo_log_name) = &arg[10];
1757 }
1758 else if (VG_CLO_STREQN(11, arg, "--log-file=")) {
1759 VG_(clo_log_to) = VgLogTo_File;
1760 VG_(clo_log_name) = &arg[11];
sewardj4cf05692002-10-27 20:28:29 +00001761 }
sewardjde4a1d02002-03-22 01:27:54 +00001762
nethercotef8548672004-06-21 12:42:35 +00001763 // for backwards compatibility, replaced by --log-socket
nethercote71980f02004-01-24 18:18:54 +00001764 else if (VG_CLO_STREQN(12, arg, "--logsocket=")) {
nethercotef8548672004-06-21 12:42:35 +00001765 VG_(clo_log_to) = VgLogTo_Socket;
1766 VG_(clo_log_name) = &arg[12];
1767 }
1768 else if (VG_CLO_STREQN(13, arg, "--log-socket=")) {
1769 VG_(clo_log_to) = VgLogTo_Socket;
1770 VG_(clo_log_name) = &arg[13];
sewardj73cf3bc2002-11-03 03:20:15 +00001771 }
1772
nethercote71980f02004-01-24 18:18:54 +00001773 else if (VG_CLO_STREQN(15, arg, "--suppressions=")) {
sewardjde4a1d02002-03-22 01:27:54 +00001774 if (VG_(clo_n_suppressions) >= VG_CLO_MAX_SFILES) {
njn25e49d8e72002-09-23 09:36:25 +00001775 VG_(message)(Vg_UserMsg, "Too many suppression files specified.");
sewardjde4a1d02002-03-22 01:27:54 +00001776 VG_(message)(Vg_UserMsg,
1777 "Increase VG_CLO_MAX_SFILES and recompile.");
nethercote71980f02004-01-24 18:18:54 +00001778 VG_(bad_option)(arg);
sewardjde4a1d02002-03-22 01:27:54 +00001779 }
nethercote71980f02004-01-24 18:18:54 +00001780 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = &arg[15];
sewardjde4a1d02002-03-22 01:27:54 +00001781 VG_(clo_n_suppressions)++;
1782 }
sewardjde4a1d02002-03-22 01:27:54 +00001783
njn25e49d8e72002-09-23 09:36:25 +00001784 /* "vwxyz" --> 000zyxwv (binary) */
nethercote71980f02004-01-24 18:18:54 +00001785 else if (VG_CLO_STREQN(16, arg, "--trace-codegen=")) {
njn25e49d8e72002-09-23 09:36:25 +00001786 Int j;
nethercote71980f02004-01-24 18:18:54 +00001787 char* opt = & arg[16];
njn25e49d8e72002-09-23 09:36:25 +00001788
1789 if (5 != VG_(strlen)(opt)) {
1790 VG_(message)(Vg_UserMsg,
1791 "--trace-codegen argument must have 5 digits");
nethercote71980f02004-01-24 18:18:54 +00001792 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001793 }
1794 for (j = 0; j < 5; j++) {
1795 if ('0' == opt[j]) { /* do nothing */ }
1796 else if ('1' == opt[j]) VG_(clo_trace_codegen) |= (1 << j);
1797 else {
1798 VG_(message)(Vg_UserMsg, "--trace-codegen argument can only "
1799 "contain 0s and 1s");
nethercote71980f02004-01-24 18:18:54 +00001800 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001801 }
1802 }
1803 }
sewardjde4a1d02002-03-22 01:27:54 +00001804
nethercote71980f02004-01-24 18:18:54 +00001805 else if (VG_CLO_STREQ(arg, "--trace-pthread=none"))
sewardj45b4b372002-04-16 22:50:32 +00001806 VG_(clo_trace_pthread_level) = 0;
nethercote71980f02004-01-24 18:18:54 +00001807 else if (VG_CLO_STREQ(arg, "--trace-pthread=some"))
sewardj45b4b372002-04-16 22:50:32 +00001808 VG_(clo_trace_pthread_level) = 1;
nethercote71980f02004-01-24 18:18:54 +00001809 else if (VG_CLO_STREQ(arg, "--trace-pthread=all"))
sewardj45b4b372002-04-16 22:50:32 +00001810 VG_(clo_trace_pthread_level) = 2;
sewardj8937c812002-04-12 20:12:20 +00001811
nethercote71980f02004-01-24 18:18:54 +00001812 else if ( ! VG_(needs).command_line_options
1813 || ! SK_(process_cmd_line_option)(arg) ) {
nethercotef4928da2004-06-15 10:54:40 +00001814 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001815 }
sewardjde4a1d02002-03-22 01:27:54 +00001816 }
1817
nethercote27fec902004-06-16 21:26:32 +00001818 // Check various option values
1819
njnf9ebf672003-05-12 21:41:30 +00001820 if (VG_(clo_verbosity) < 0)
sewardjde4a1d02002-03-22 01:27:54 +00001821 VG_(clo_verbosity) = 0;
1822
nethercote04d0fbc2004-01-26 16:48:06 +00001823 if (VG_(clo_db_attach) && VG_(clo_trace_children)) {
sewardjde4a1d02002-03-22 01:27:54 +00001824 VG_(message)(Vg_UserMsg, "");
1825 VG_(message)(Vg_UserMsg,
nethercote04d0fbc2004-01-26 16:48:06 +00001826 "--db-attach=yes conflicts with --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001827 VG_(message)(Vg_UserMsg,
1828 "Please choose one or the other, but not both.");
nethercote04d0fbc2004-01-26 16:48:06 +00001829 VG_(bad_option)("--db-attach=yes and --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001830 }
1831
nethercotef8548672004-06-21 12:42:35 +00001832 /* Set up logging now. After this is done, VG_(clo_log_fd)
sewardj4cf05692002-10-27 20:28:29 +00001833 should be connected to whatever sink has been selected, and we
1834 indiscriminately chuck stuff into it without worrying what the
1835 nature of it is. Oh the wonder of Unix streams. */
1836
nethercotee1730692003-11-20 10:38:07 +00001837 /* So far we should be still attached to stdout, so we can show on
sewardj4cf05692002-10-27 20:28:29 +00001838 the terminal any problems to do with processing command line
1839 opts. */
nethercotef8548672004-06-21 12:42:35 +00001840 vg_assert(VG_(clo_log_fd) == 1 /* stdout */);
sewardj73cf3bc2002-11-03 03:20:15 +00001841 vg_assert(VG_(logging_to_filedes) == True);
sewardj4cf05692002-10-27 20:28:29 +00001842
1843 switch (VG_(clo_log_to)) {
sewardj73cf3bc2002-11-03 03:20:15 +00001844
sewardj4cf05692002-10-27 20:28:29 +00001845 case VgLogTo_Fd:
nethercotef8548672004-06-21 12:42:35 +00001846 vg_assert(VG_(clo_log_name) == NULL);
1847 VG_(clo_log_fd) = eventually_log_fd;
sewardj4cf05692002-10-27 20:28:29 +00001848 break;
sewardj73cf3bc2002-11-03 03:20:15 +00001849
sewardj4cf05692002-10-27 20:28:29 +00001850 case VgLogTo_File: {
1851 Char logfilename[1000];
jsgff3c3f1a2003-10-14 22:13:28 +00001852 Int seq = 0;
1853 Int pid = VG_(getpid)();
1854
nethercotef8548672004-06-21 12:42:35 +00001855 vg_assert(VG_(clo_log_name) != NULL);
1856 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
jsgff3c3f1a2003-10-14 22:13:28 +00001857
nethercote71980f02004-01-24 18:18:54 +00001858 for (;;) {
jsgff3c3f1a2003-10-14 22:13:28 +00001859 if (seq == 0)
1860 VG_(sprintf)(logfilename, "%s.pid%d",
nethercotef8548672004-06-21 12:42:35 +00001861 VG_(clo_log_name), pid );
jsgff3c3f1a2003-10-14 22:13:28 +00001862 else
1863 VG_(sprintf)(logfilename, "%s.pid%d.%d",
nethercotef8548672004-06-21 12:42:35 +00001864 VG_(clo_log_name), pid, seq );
jsgff3c3f1a2003-10-14 22:13:28 +00001865 seq++;
1866
nethercotef8548672004-06-21 12:42:35 +00001867 eventually_log_fd
jsgff3c3f1a2003-10-14 22:13:28 +00001868 = VG_(open)(logfilename,
1869 VKI_O_CREAT|VKI_O_WRONLY|VKI_O_EXCL|VKI_O_TRUNC,
1870 VKI_S_IRUSR|VKI_S_IWUSR);
nethercotef8548672004-06-21 12:42:35 +00001871 if (eventually_log_fd >= 0) {
1872 VG_(clo_log_fd) = VG_(safe_fd)(eventually_log_fd);
jsgff3c3f1a2003-10-14 22:13:28 +00001873 break;
1874 } else {
nethercotef8548672004-06-21 12:42:35 +00001875 if (eventually_log_fd != -VKI_EEXIST) {
jsgff3c3f1a2003-10-14 22:13:28 +00001876 VG_(message)(Vg_UserMsg,
1877 "Can't create/open log file `%s.pid%d'; giving up!",
nethercotef8548672004-06-21 12:42:35 +00001878 VG_(clo_log_name), pid);
jsgff3c3f1a2003-10-14 22:13:28 +00001879 VG_(bad_option)(
nethercotef8548672004-06-21 12:42:35 +00001880 "--log-file=<file> didn't work out for some reason.");
jsgff3c3f1a2003-10-14 22:13:28 +00001881 break;
1882 }
1883 }
1884 }
sewardj4cf05692002-10-27 20:28:29 +00001885 break;
sewardj73cf3bc2002-11-03 03:20:15 +00001886 }
1887
1888 case VgLogTo_Socket: {
nethercotef8548672004-06-21 12:42:35 +00001889 vg_assert(VG_(clo_log_name) != NULL);
1890 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
1891 eventually_log_fd = VG_(connect_via_socket)( VG_(clo_log_name) );
1892 if (eventually_log_fd == -1) {
sewardj73cf3bc2002-11-03 03:20:15 +00001893 VG_(message)(Vg_UserMsg,
nethercotef8548672004-06-21 12:42:35 +00001894 "Invalid --log-socket=ipaddr or --log-socket=ipaddr:port spec");
sewardj73cf3bc2002-11-03 03:20:15 +00001895 VG_(message)(Vg_UserMsg,
nethercotef8548672004-06-21 12:42:35 +00001896 "of `%s'; giving up!", VG_(clo_log_name) );
sewardj73cf3bc2002-11-03 03:20:15 +00001897 VG_(bad_option)(
nethercotef8548672004-06-21 12:42:35 +00001898 "--log-socket=");
sewardj4cf05692002-10-27 20:28:29 +00001899 }
nethercotef8548672004-06-21 12:42:35 +00001900 if (eventually_log_fd == -2) {
sewardj73cf3bc2002-11-03 03:20:15 +00001901 VG_(message)(Vg_UserMsg,
sewardj570f8902002-11-03 11:44:36 +00001902 "valgrind: failed to connect to logging server `%s'.",
nethercotef8548672004-06-21 12:42:35 +00001903 VG_(clo_log_name) );
sewardj570f8902002-11-03 11:44:36 +00001904 VG_(message)(Vg_UserMsg,
1905 "Log messages will sent to stderr instead." );
1906 VG_(message)(Vg_UserMsg,
1907 "" );
1908 /* We don't change anything here. */
1909 } else {
nethercotef8548672004-06-21 12:42:35 +00001910 vg_assert(eventually_log_fd > 0);
1911 VG_(clo_log_fd) = eventually_log_fd;
sewardj570f8902002-11-03 11:44:36 +00001912 VG_(logging_to_filedes) = False;
1913 }
sewardj73cf3bc2002-11-03 03:20:15 +00001914 break;
1915 }
1916
sewardj4cf05692002-10-27 20:28:29 +00001917 }
1918
nethercotef8548672004-06-21 12:42:35 +00001919 /* Move log_fd into the safe range, so it doesn't conflict with any app fds */
1920 eventually_log_fd = VG_(fcntl)(VG_(clo_log_fd), VKI_F_DUPFD, VG_(max_fd)+1);
1921 if (eventually_log_fd < 0)
jsgf855d93d2003-10-13 22:26:55 +00001922 VG_(message)(Vg_UserMsg, "valgrind: failed to move logfile fd into safe range");
1923 else {
nethercotef8548672004-06-21 12:42:35 +00001924 VG_(clo_log_fd) = eventually_log_fd;
1925 VG_(fcntl)(VG_(clo_log_fd), VKI_F_SETFD, VKI_FD_CLOEXEC);
jsgf855d93d2003-10-13 22:26:55 +00001926 }
1927
sewardj4cf05692002-10-27 20:28:29 +00001928 /* Ok, the logging sink is running now. Print a suitable preamble.
1929 If logging to file or a socket, write details of parent PID and
1930 command line args, to help people trying to interpret the
1931 results of a run which encompasses multiple processes. */
sewardjde4a1d02002-03-22 01:27:54 +00001932
sewardj83adf412002-05-01 01:25:45 +00001933 if (VG_(clo_verbosity > 0)) {
njnd04b7c62002-10-03 14:05:52 +00001934 /* Skin details */
1935 VG_(message)(Vg_UserMsg, "%s%s%s, %s for x86-linux.",
1936 VG_(details).name,
1937 NULL == VG_(details).version ? "" : "-",
1938 NULL == VG_(details).version
1939 ? (Char*)"" : VG_(details).version,
1940 VG_(details).description);
1941 VG_(message)(Vg_UserMsg, "%s", VG_(details).copyright_author);
sewardj3b2736a2002-03-24 12:18:35 +00001942
njnd04b7c62002-10-03 14:05:52 +00001943 /* Core details */
1944 VG_(message)(Vg_UserMsg,
njn3e884182003-04-15 13:03:23 +00001945 "Using valgrind-%s, a program supervision framework for x86-linux.",
sewardj4aa62ba2002-10-05 15:49:27 +00001946 VERSION);
sewardjde4a1d02002-03-22 01:27:54 +00001947 VG_(message)(Vg_UserMsg,
nethercotebb1c9912004-01-04 16:43:23 +00001948 "Copyright (C) 2000-2004, and GNU GPL'd, by Julian Seward.");
njnd04b7c62002-10-03 14:05:52 +00001949 }
1950
nethercotec1e395d2003-11-10 13:26:49 +00001951 if (VG_(clo_verbosity) > 0 && VG_(clo_log_to) != VgLogTo_Fd) {
sewardj4cf05692002-10-27 20:28:29 +00001952 VG_(message)(Vg_UserMsg, "");
1953 VG_(message)(Vg_UserMsg,
1954 "My PID = %d, parent PID = %d. Prog and args are:",
1955 VG_(getpid)(), VG_(getppid)() );
1956 for (i = 0; i < VG_(client_argc); i++)
1957 VG_(message)(Vg_UserMsg, " %s", VG_(client_argv)[i]);
1958 }
1959
sewardjde4a1d02002-03-22 01:27:54 +00001960 if (VG_(clo_verbosity) > 1) {
nethercotea70f7352004-04-18 12:08:46 +00001961 Int fd;
sewardj4cf05692002-10-27 20:28:29 +00001962 if (VG_(clo_log_to) != VgLogTo_Fd)
1963 VG_(message)(Vg_UserMsg, "");
fitzhardinge98abfc72003-12-16 02:05:15 +00001964 VG_(message)(Vg_UserMsg, "Valgrind library directory: %s", VG_(libdir));
njn86dc2bc2003-09-09 07:26:21 +00001965 VG_(message)(Vg_UserMsg, "Command line");
1966 for (i = 0; i < VG_(client_argc); i++)
1967 VG_(message)(Vg_UserMsg, " %s", VG_(client_argv)[i]);
1968
sewardjde4a1d02002-03-22 01:27:54 +00001969 VG_(message)(Vg_UserMsg, "Startup, with flags:");
nethercote71980f02004-01-24 18:18:54 +00001970 for (i = 1; i < VG_(vg_argc); i++) {
1971 VG_(message)(Vg_UserMsg, " %s", VG_(vg_argv)[i]);
sewardjde4a1d02002-03-22 01:27:54 +00001972 }
nethercotea70f7352004-04-18 12:08:46 +00001973
1974 VG_(message)(Vg_UserMsg, "Contents of /proc/version:");
1975 fd = VG_(open) ( "/proc/version", VKI_O_RDONLY, 0 );
1976 if (fd < 0) {
1977 VG_(message)(Vg_UserMsg, " can't open /proc/version");
1978 } else {
1979 #define BUF_LEN 256
1980 Char version_buf[BUF_LEN];
1981 Int n = VG_(read) ( fd, version_buf, BUF_LEN );
1982 vg_assert(n <= 256);
1983 if (n > 0) {
1984 version_buf[n-1] = '\0';
1985 VG_(message)(Vg_UserMsg, " %s", version_buf);
1986 } else {
1987 VG_(message)(Vg_UserMsg, " (empty?)");
1988 }
1989 VG_(close)(fd);
1990 #undef BUF_LEN
1991 }
sewardjde4a1d02002-03-22 01:27:54 +00001992 }
1993
fitzhardinge98abfc72003-12-16 02:05:15 +00001994 if (VG_(clo_n_suppressions) < VG_CLO_MAX_SFILES-1 &&
njn25e49d8e72002-09-23 09:36:25 +00001995 (VG_(needs).core_errors || VG_(needs).skin_errors)) {
fitzhardinge98abfc72003-12-16 02:05:15 +00001996 /* If there are no suppression files specified and the skin
1997 needs one, load the default */
1998 static const Char default_supp[] = "default.supp";
1999 Int len = VG_(strlen)(VG_(libdir)) + 1 + sizeof(default_supp);
2000 Char *buf = VG_(arena_malloc)(VG_AR_CORE, len);
2001 VG_(sprintf)(buf, "%s/%s", VG_(libdir), default_supp);
2002 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = buf;
2003 VG_(clo_n_suppressions)++;
sewardjde4a1d02002-03-22 01:27:54 +00002004 }
sewardj4cf05692002-10-27 20:28:29 +00002005
njn6a230532003-07-21 10:38:23 +00002006 if (VG_(clo_gen_suppressions) &&
2007 !VG_(needs).core_errors && !VG_(needs).skin_errors) {
nethercotef4928da2004-06-15 10:54:40 +00002008 VG_(message)(Vg_UserMsg,
2009 "Can't use --gen-suppressions=yes with this tool,");
2010 VG_(message)(Vg_UserMsg,
2011 "as it doesn't generate errors.");
2012 VG_(bad_option)("--gen-suppressions=yes");
njn6a230532003-07-21 10:38:23 +00002013 }
sewardjde4a1d02002-03-22 01:27:54 +00002014}
2015
sewardjde4a1d02002-03-22 01:27:54 +00002016
nethercote71980f02004-01-24 18:18:54 +00002017/*====================================================================*/
2018/*=== File descriptor setup ===*/
2019/*====================================================================*/
2020
2021static void setup_file_descriptors(void)
2022{
2023 struct vki_rlimit rl;
2024
2025 /* Get the current file descriptor limits. */
2026 if (VG_(getrlimit)(VKI_RLIMIT_NOFILE, &rl) < 0) {
2027 rl.rlim_cur = 1024;
2028 rl.rlim_max = 1024;
2029 }
2030
2031 /* Work out where to move the soft limit to. */
2032 if (rl.rlim_cur + VG_N_RESERVED_FDS <= rl.rlim_max) {
2033 rl.rlim_cur = rl.rlim_cur + VG_N_RESERVED_FDS;
2034 } else {
2035 rl.rlim_cur = rl.rlim_max;
2036 }
2037
2038 /* Reserve some file descriptors for our use. */
2039 VG_(max_fd) = rl.rlim_cur - VG_N_RESERVED_FDS;
2040
2041 /* Update the soft limit. */
2042 VG_(setrlimit)(VKI_RLIMIT_NOFILE, &rl);
2043
2044 if (VG_(vgexecfd) != -1)
2045 VG_(vgexecfd) = VG_(safe_fd)( VG_(vgexecfd) );
2046 if (VG_(clexecfd) != -1)
2047 VG_(clexecfd) = VG_(safe_fd)( VG_(clexecfd) );
2048}
2049
2050
2051/*====================================================================*/
nethercote1d447092004-02-01 17:29:59 +00002052/*=== baseBlock: definition + setup ===*/
nethercote71980f02004-01-24 18:18:54 +00002053/*====================================================================*/
2054
2055/* The variables storing offsets. */
2056
2057#define INVALID_OFFSET (-1)
2058
2059Int VGOFF_(m_eax) = INVALID_OFFSET;
2060Int VGOFF_(m_ecx) = INVALID_OFFSET;
2061Int VGOFF_(m_edx) = INVALID_OFFSET;
2062Int VGOFF_(m_ebx) = INVALID_OFFSET;
2063Int VGOFF_(m_esp) = INVALID_OFFSET;
2064Int VGOFF_(m_ebp) = INVALID_OFFSET;
2065Int VGOFF_(m_esi) = INVALID_OFFSET;
2066Int VGOFF_(m_edi) = INVALID_OFFSET;
2067Int VGOFF_(m_eflags) = INVALID_OFFSET;
2068Int VGOFF_(m_dflag) = INVALID_OFFSET;
2069Int VGOFF_(m_ssestate) = INVALID_OFFSET;
2070Int VGOFF_(ldt) = INVALID_OFFSET;
2071Int VGOFF_(tls) = INVALID_OFFSET;
2072Int VGOFF_(m_cs) = INVALID_OFFSET;
2073Int VGOFF_(m_ss) = INVALID_OFFSET;
2074Int VGOFF_(m_ds) = INVALID_OFFSET;
2075Int VGOFF_(m_es) = INVALID_OFFSET;
2076Int VGOFF_(m_fs) = INVALID_OFFSET;
2077Int VGOFF_(m_gs) = INVALID_OFFSET;
2078Int VGOFF_(m_eip) = INVALID_OFFSET;
2079Int VGOFF_(spillslots) = INVALID_OFFSET;
2080Int VGOFF_(sh_eax) = INVALID_OFFSET;
2081Int VGOFF_(sh_ecx) = INVALID_OFFSET;
2082Int VGOFF_(sh_edx) = INVALID_OFFSET;
2083Int VGOFF_(sh_ebx) = INVALID_OFFSET;
2084Int VGOFF_(sh_esp) = INVALID_OFFSET;
2085Int VGOFF_(sh_ebp) = INVALID_OFFSET;
2086Int VGOFF_(sh_esi) = INVALID_OFFSET;
2087Int VGOFF_(sh_edi) = INVALID_OFFSET;
2088Int VGOFF_(sh_eflags) = INVALID_OFFSET;
2089
2090Int VGOFF_(helper_idiv_64_32) = INVALID_OFFSET;
2091Int VGOFF_(helper_div_64_32) = INVALID_OFFSET;
2092Int VGOFF_(helper_idiv_32_16) = INVALID_OFFSET;
2093Int VGOFF_(helper_div_32_16) = INVALID_OFFSET;
2094Int VGOFF_(helper_idiv_16_8) = INVALID_OFFSET;
2095Int VGOFF_(helper_div_16_8) = INVALID_OFFSET;
2096Int VGOFF_(helper_imul_32_64) = INVALID_OFFSET;
2097Int VGOFF_(helper_mul_32_64) = INVALID_OFFSET;
2098Int VGOFF_(helper_imul_16_32) = INVALID_OFFSET;
2099Int VGOFF_(helper_mul_16_32) = INVALID_OFFSET;
2100Int VGOFF_(helper_imul_8_16) = INVALID_OFFSET;
2101Int VGOFF_(helper_mul_8_16) = INVALID_OFFSET;
2102Int VGOFF_(helper_CLD) = INVALID_OFFSET;
2103Int VGOFF_(helper_STD) = INVALID_OFFSET;
2104Int VGOFF_(helper_get_dirflag) = INVALID_OFFSET;
2105Int VGOFF_(helper_CLC) = INVALID_OFFSET;
2106Int VGOFF_(helper_STC) = INVALID_OFFSET;
nethercote1018bdd2004-02-11 23:33:29 +00002107Int VGOFF_(helper_CMC) = INVALID_OFFSET;
nethercote71980f02004-01-24 18:18:54 +00002108Int VGOFF_(helper_shldl) = INVALID_OFFSET;
2109Int VGOFF_(helper_shldw) = INVALID_OFFSET;
2110Int VGOFF_(helper_shrdl) = INVALID_OFFSET;
2111Int VGOFF_(helper_shrdw) = INVALID_OFFSET;
2112Int VGOFF_(helper_IN) = INVALID_OFFSET;
2113Int VGOFF_(helper_OUT) = INVALID_OFFSET;
2114Int VGOFF_(helper_RDTSC) = INVALID_OFFSET;
2115Int VGOFF_(helper_CPUID) = INVALID_OFFSET;
2116Int VGOFF_(helper_BSWAP) = INVALID_OFFSET;
nethercote1018bdd2004-02-11 23:33:29 +00002117Int VGOFF_(helper_bsfw) = INVALID_OFFSET;
2118Int VGOFF_(helper_bsfl) = INVALID_OFFSET;
2119Int VGOFF_(helper_bsrw) = INVALID_OFFSET;
2120Int VGOFF_(helper_bsrl) = INVALID_OFFSET;
nethercote71980f02004-01-24 18:18:54 +00002121Int VGOFF_(helper_fstsw_AX) = INVALID_OFFSET;
2122Int VGOFF_(helper_SAHF) = INVALID_OFFSET;
2123Int VGOFF_(helper_LAHF) = INVALID_OFFSET;
2124Int VGOFF_(helper_DAS) = INVALID_OFFSET;
2125Int VGOFF_(helper_DAA) = INVALID_OFFSET;
nethercote1018bdd2004-02-11 23:33:29 +00002126Int VGOFF_(helper_AAS) = INVALID_OFFSET;
2127Int VGOFF_(helper_AAA) = INVALID_OFFSET;
2128Int VGOFF_(helper_AAD) = INVALID_OFFSET;
2129Int VGOFF_(helper_AAM) = INVALID_OFFSET;
nethercote71980f02004-01-24 18:18:54 +00002130Int VGOFF_(helper_cmpxchg8b) = INVALID_OFFSET;
2131Int VGOFF_(helper_undefined_instruction) = INVALID_OFFSET;
2132
2133/* MAX_NONCOMPACT_HELPERS can be increased easily. If MAX_COMPACT_HELPERS is
2134 * increased too much, they won't really be compact any more... */
2135#define MAX_COMPACT_HELPERS 8
2136#define MAX_NONCOMPACT_HELPERS 50
2137
2138UInt VG_(n_compact_helpers) = 0;
2139UInt VG_(n_noncompact_helpers) = 0;
2140
2141Addr VG_(compact_helper_addrs) [MAX_COMPACT_HELPERS];
2142Int VG_(compact_helper_offsets)[MAX_COMPACT_HELPERS];
2143Addr VG_(noncompact_helper_addrs) [MAX_NONCOMPACT_HELPERS];
2144Int VG_(noncompact_helper_offsets)[MAX_NONCOMPACT_HELPERS];
2145
2146/* This is the actual defn of baseblock. */
2147UInt VG_(baseBlock)[VG_BASEBLOCK_WORDS];
2148
nethercote71980f02004-01-24 18:18:54 +00002149/* Words. */
2150static Int baB_off = 0;
2151
2152
sewardjfa492d42002-12-08 18:20:01 +00002153UInt VG_(insertDflag)(UInt eflags, Int d)
2154{
2155 vg_assert(d == 1 || d == -1);
2156 eflags &= ~EFlagD;
2157
2158 if (d < 0)
2159 eflags |= EFlagD;
2160
2161 return eflags;
2162}
2163
2164Int VG_(extractDflag)(UInt eflags)
2165{
2166 Int ret;
2167
2168 if (eflags & EFlagD)
2169 ret = -1;
2170 else
2171 ret = 1;
2172
2173 return ret;
2174}
2175
nethercote71980f02004-01-24 18:18:54 +00002176/* Returns the offset, in words. */
2177static Int alloc_BaB ( Int words )
sewardjde4a1d02002-03-22 01:27:54 +00002178{
nethercote71980f02004-01-24 18:18:54 +00002179 Int off = baB_off;
2180 baB_off += words;
2181 if (baB_off >= VG_BASEBLOCK_WORDS)
2182 VG_(core_panic)( "alloc_BaB: baseBlock is too small");
sewardjde4a1d02002-03-22 01:27:54 +00002183
nethercote71980f02004-01-24 18:18:54 +00002184 return off;
sewardjde4a1d02002-03-22 01:27:54 +00002185}
2186
nethercote71980f02004-01-24 18:18:54 +00002187/* Align offset, in *bytes* */
2188static void align_BaB ( UInt align )
njn25e49d8e72002-09-23 09:36:25 +00002189{
nethercote71980f02004-01-24 18:18:54 +00002190 vg_assert(2 == align || 4 == align || 8 == align || 16 == align);
2191 baB_off += (align-1);
2192 baB_off &= ~(align-1);
njn25e49d8e72002-09-23 09:36:25 +00002193}
2194
nethercote71980f02004-01-24 18:18:54 +00002195/* Allocate 1 word in baseBlock and set it to the given value. */
2196static Int alloc_BaB_1_set ( Addr a )
njn25e49d8e72002-09-23 09:36:25 +00002197{
nethercote71980f02004-01-24 18:18:54 +00002198 Int off = alloc_BaB(1);
2199 VG_(baseBlock)[off] = (UInt)a;
2200 return off;
njn25e49d8e72002-09-23 09:36:25 +00002201}
2202
nethercote71980f02004-01-24 18:18:54 +00002203/* Registers a function in compact_helper_addrs; compact_helper_offsets is
2204 filled in later. */
2205void VG_(register_compact_helper)(Addr a)
sewardjde4a1d02002-03-22 01:27:54 +00002206{
nethercote71980f02004-01-24 18:18:54 +00002207 if (MAX_COMPACT_HELPERS <= VG_(n_compact_helpers)) {
2208 VG_(printf)("Can only register %d compact helpers\n",
2209 MAX_COMPACT_HELPERS);
2210 VG_(core_panic)("Too many compact helpers registered");
2211 }
2212 VG_(compact_helper_addrs)[VG_(n_compact_helpers)] = a;
2213 VG_(n_compact_helpers)++;
2214}
2215
2216/* Registers a function in noncompact_helper_addrs; noncompact_helper_offsets
2217 * is filled in later.
2218 */
2219void VG_(register_noncompact_helper)(Addr a)
2220{
2221 if (MAX_NONCOMPACT_HELPERS <= VG_(n_noncompact_helpers)) {
2222 VG_(printf)("Can only register %d non-compact helpers\n",
2223 MAX_NONCOMPACT_HELPERS);
2224 VG_(printf)("Try increasing MAX_NON_COMPACT_HELPERS\n");
2225 VG_(core_panic)("Too many non-compact helpers registered");
2226 }
2227 VG_(noncompact_helper_addrs)[VG_(n_noncompact_helpers)] = a;
2228 VG_(n_noncompact_helpers)++;
2229}
2230
2231/* Allocate offsets in baseBlock for the skin helpers */
2232static
2233void assign_helpers_in_baseBlock(UInt n, Int offsets[], Addr addrs[])
2234{
2235 UInt i;
2236 for (i = 0; i < n; i++)
2237 offsets[i] = alloc_BaB_1_set( addrs[i] );
2238}
2239
2240Bool VG_(need_to_handle_esp_assignment)(void)
2241{
2242 return ( VG_(defined_new_mem_stack_4)() ||
2243 VG_(defined_die_mem_stack_4)() ||
2244 VG_(defined_new_mem_stack_8)() ||
2245 VG_(defined_die_mem_stack_8)() ||
2246 VG_(defined_new_mem_stack_12)() ||
2247 VG_(defined_die_mem_stack_12)() ||
2248 VG_(defined_new_mem_stack_16)() ||
2249 VG_(defined_die_mem_stack_16)() ||
2250 VG_(defined_new_mem_stack_32)() ||
2251 VG_(defined_die_mem_stack_32)() ||
2252 VG_(defined_new_mem_stack)() ||
2253 VG_(defined_die_mem_stack)()
2254 );
2255}
2256
2257/* Here we assign actual offsets. It's important to get the most
2258 popular referents within 128 bytes of the start, so we can take
2259 advantage of short addressing modes relative to %ebp. Popularity
2260 of offsets was measured on 22 Feb 02 running a KDE application, and
2261 the slots rearranged accordingly, with a 1.5% reduction in total
2262 size of translations. */
2263static void init_baseBlock ( Addr client_eip, Addr esp_at_startup )
2264{
2265 /* Those with offsets under 128 are carefully chosen. */
2266
2267 /* WORD offsets in this column */
2268 /* 0 */ VGOFF_(m_eax) = alloc_BaB_1_set(0);
2269 /* 1 */ VGOFF_(m_ecx) = alloc_BaB_1_set(0);
2270 /* 2 */ VGOFF_(m_edx) = alloc_BaB_1_set(0);
2271 /* 3 */ VGOFF_(m_ebx) = alloc_BaB_1_set(0);
2272 /* 4 */ VGOFF_(m_esp) = alloc_BaB_1_set(esp_at_startup);
2273 /* 5 */ VGOFF_(m_ebp) = alloc_BaB_1_set(0);
2274 /* 6 */ VGOFF_(m_esi) = alloc_BaB_1_set(0);
2275 /* 7 */ VGOFF_(m_edi) = alloc_BaB_1_set(0);
2276 /* 8 */ VGOFF_(m_eflags) = alloc_BaB_1_set(0);
2277
2278 if (VG_(needs).shadow_regs) {
2279 /* 9 */ VGOFF_(sh_eax) = alloc_BaB_1_set(0);
2280 /* 10 */ VGOFF_(sh_ecx) = alloc_BaB_1_set(0);
2281 /* 11 */ VGOFF_(sh_edx) = alloc_BaB_1_set(0);
2282 /* 12 */ VGOFF_(sh_ebx) = alloc_BaB_1_set(0);
2283 /* 13 */ VGOFF_(sh_esp) = alloc_BaB_1_set(0);
2284 /* 14 */ VGOFF_(sh_ebp) = alloc_BaB_1_set(0);
2285 /* 15 */ VGOFF_(sh_esi) = alloc_BaB_1_set(0);
2286 /* 16 */ VGOFF_(sh_edi) = alloc_BaB_1_set(0);
2287 /* 17 */ VGOFF_(sh_eflags) = alloc_BaB_1_set(0);
2288 VG_TRACK( post_regs_write_init );
2289 }
2290
2291 /* 9,10,11 or 18,19,20... depends on number whether shadow regs are used
2292 * and on compact helpers registered */
2293
2294 /* Make these most-frequently-called specialised ones compact, if they
2295 are used. */
2296 if (VG_(defined_new_mem_stack_4)())
2297 VG_(register_compact_helper)( (Addr) VG_(tool_interface).track_new_mem_stack_4);
2298
2299 if (VG_(defined_die_mem_stack_4)())
2300 VG_(register_compact_helper)( (Addr) VG_(tool_interface).track_die_mem_stack_4);
2301
2302 /* (9 or 18) + n_compact_helpers */
2303 /* Allocate slots for compact helpers */
2304 assign_helpers_in_baseBlock(VG_(n_compact_helpers),
2305 VG_(compact_helper_offsets),
2306 VG_(compact_helper_addrs));
2307
2308 /* (9/10 or 18/19) + n_compact_helpers */
2309 VGOFF_(m_eip) = alloc_BaB_1_set(client_eip);
2310
2311 /* There are currently 24 spill slots */
2312 /* (11+/20+ .. 32+/43+) + n_compact_helpers. This can overlap the magic
2313 * boundary at >= 32 words, but most spills are to low numbered spill
2314 * slots, so the ones above the boundary don't see much action. */
2315 VGOFF_(spillslots) = alloc_BaB(VG_MAX_SPILLSLOTS);
2316
2317 /* I gave up counting at this point. Since they're above the
2318 short-amode-boundary, there's no point. */
2319
2320 VGOFF_(m_dflag) = alloc_BaB_1_set(1); // 1 == forward D-flag
2321
2322 /* The FPU/SSE state. This _must_ be 16-byte aligned. Initial
2323 state doesn't matter much, as long as it's not totally borked. */
2324 align_BaB(16);
2325 VGOFF_(m_ssestate) = alloc_BaB(VG_SIZE_OF_SSESTATE_W);
2326 vg_assert(
2327 0 == ( ((UInt)(& VG_(baseBlock)[VGOFF_(m_ssestate)])) % 16 )
sewardj22854b92002-11-30 14:00:47 +00002328 );
2329
fitzhardingec2dbbac2004-01-23 23:09:01 +00002330 /* I assume that if we have SSE2 we also have SSE */
2331 VG_(have_ssestate) =
2332 VG_(cpu_has_feature)(VG_X86_FEAT_FXSR) &&
2333 VG_(cpu_has_feature)(VG_X86_FEAT_SSE);
2334
fitzhardinge98abfc72003-12-16 02:05:15 +00002335 /* set up an initial FPU state (doesn't really matter what it is,
2336 so long as it's somewhat valid) */
2337 if (!VG_(have_ssestate))
nethercote71980f02004-01-24 18:18:54 +00002338 asm volatile("fwait; fnsave %0; fwait; frstor %0; fwait"
2339 :
2340 : "m" (VG_(baseBlock)[VGOFF_(m_ssestate)])
2341 : "cc", "memory");
fitzhardinge98abfc72003-12-16 02:05:15 +00002342 else
nethercote71980f02004-01-24 18:18:54 +00002343 asm volatile("fwait; fxsave %0; fwait; andl $0xffbf, %1;"
2344 "fxrstor %0; fwait"
2345 :
2346 : "m" (VG_(baseBlock)[VGOFF_(m_ssestate)]),
2347 "m" (VG_(baseBlock)[VGOFF_(m_ssestate)+(24/4)])
2348 : "cc", "memory");
fitzhardinge98abfc72003-12-16 02:05:15 +00002349
njn0c7a5b52003-04-30 09:00:33 +00002350 if (0) {
2351 if (VG_(have_ssestate))
2352 VG_(printf)("Looks like a SSE-capable CPU\n");
2353 else
2354 VG_(printf)("Looks like a MMX-only CPU\n");
2355 }
sewardjb91ae7f2003-04-29 23:50:00 +00002356
nethercote71980f02004-01-24 18:18:54 +00002357 /* LDT pointer: pretend the root thread has an empty LDT to start with. */
2358 VGOFF_(ldt) = alloc_BaB_1_set((UInt)NULL);
jsgf855d93d2003-10-13 22:26:55 +00002359
nethercote71980f02004-01-24 18:18:54 +00002360 /* TLS pointer: pretend the root thread has no TLS array for now. */
2361 VGOFF_(tls) = alloc_BaB_1_set((UInt)NULL);
fitzhardingef0046f22003-12-18 02:39:22 +00002362
nethercote71980f02004-01-24 18:18:54 +00002363 /* segment registers */
2364 VGOFF_(m_cs) = alloc_BaB_1_set(0);
2365 VGOFF_(m_ss) = alloc_BaB_1_set(0);
2366 VGOFF_(m_ds) = alloc_BaB_1_set(0);
2367 VGOFF_(m_es) = alloc_BaB_1_set(0);
2368 VGOFF_(m_fs) = alloc_BaB_1_set(0);
2369 VGOFF_(m_gs) = alloc_BaB_1_set(0);
fitzhardingef0046f22003-12-18 02:39:22 +00002370
thughes35cec982004-04-21 15:16:43 +00002371 /* initialise %cs, %ds and %ss to point at the operating systems
2372 default code, data and stack segments */
2373 asm volatile("movw %%cs, %0"
2374 :
2375 : "m" (VG_(baseBlock)[VGOFF_(m_cs)]));
2376 asm volatile("movw %%ds, %0"
2377 :
2378 : "m" (VG_(baseBlock)[VGOFF_(m_ds)]));
2379 asm volatile("movw %%ss, %0"
2380 :
2381 : "m" (VG_(baseBlock)[VGOFF_(m_ss)]));
2382
nethercote71980f02004-01-24 18:18:54 +00002383 VG_(register_noncompact_helper)( (Addr) & VG_(do_useseg) );
fitzhardingef0046f22003-12-18 02:39:22 +00002384
nethercote71980f02004-01-24 18:18:54 +00002385#define REG(kind, size) \
2386 if (VG_(defined_##kind##_mem_stack##size)()) \
2387 VG_(register_noncompact_helper)( \
2388 (Addr) VG_(tool_interface).track_##kind##_mem_stack##size );
2389 REG(new, _8);
2390 REG(new, _12);
2391 REG(new, _16);
2392 REG(new, _32);
2393 REG(new, );
2394 REG(die, _8);
2395 REG(die, _12);
2396 REG(die, _16);
2397 REG(die, _32);
2398 REG(die, );
2399#undef REG
fitzhardingef0046f22003-12-18 02:39:22 +00002400
nethercote71980f02004-01-24 18:18:54 +00002401 if (VG_(need_to_handle_esp_assignment)())
2402 VG_(register_noncompact_helper)((Addr) VG_(unknown_esp_update));
fitzhardingeb791a192003-12-18 07:22:44 +00002403
nethercote71980f02004-01-24 18:18:54 +00002404# define HELPER(name) \
2405 VGOFF_(helper_##name) = alloc_BaB_1_set( (Addr) & VG_(helper_##name))
njn3e884182003-04-15 13:03:23 +00002406
nethercote71980f02004-01-24 18:18:54 +00002407 /* Helper functions. */
2408 HELPER(idiv_64_32); HELPER(div_64_32);
2409 HELPER(idiv_32_16); HELPER(div_32_16);
2410 HELPER(idiv_16_8); HELPER(div_16_8);
fitzhardinge98abfc72003-12-16 02:05:15 +00002411
nethercote71980f02004-01-24 18:18:54 +00002412 HELPER(imul_32_64); HELPER(mul_32_64);
2413 HELPER(imul_16_32); HELPER(mul_16_32);
2414 HELPER(imul_8_16); HELPER(mul_8_16);
njn25e49d8e72002-09-23 09:36:25 +00002415
nethercote71980f02004-01-24 18:18:54 +00002416 HELPER(CLD); HELPER(STD);
2417 HELPER(get_dirflag);
sewardjde4a1d02002-03-22 01:27:54 +00002418
nethercote71980f02004-01-24 18:18:54 +00002419 HELPER(CLC); HELPER(STC);
nethercote1018bdd2004-02-11 23:33:29 +00002420 HELPER(CMC);
jsgf855d93d2003-10-13 22:26:55 +00002421
nethercote71980f02004-01-24 18:18:54 +00002422 HELPER(shldl); HELPER(shldw);
2423 HELPER(shrdl); HELPER(shrdw);
njncc7bb472002-10-14 09:25:19 +00002424
nethercote71980f02004-01-24 18:18:54 +00002425 HELPER(RDTSC); HELPER(CPUID);
njncc7bb472002-10-14 09:25:19 +00002426
nethercote1018bdd2004-02-11 23:33:29 +00002427 HELPER(bsfw); HELPER(bsfl);
2428 HELPER(bsrw); HELPER(bsrl);
rjwalshf5f536f2003-11-17 17:45:00 +00002429
nethercote71980f02004-01-24 18:18:54 +00002430 HELPER(fstsw_AX);
2431 HELPER(SAHF); HELPER(LAHF);
2432 HELPER(DAS); HELPER(DAA);
nethercote1018bdd2004-02-11 23:33:29 +00002433 HELPER(AAS); HELPER(AAA);
2434 HELPER(AAD); HELPER(AAM);
nethercote71980f02004-01-24 18:18:54 +00002435 HELPER(IN); HELPER(OUT);
2436 HELPER(cmpxchg8b);
sewardj018f7622002-05-15 21:13:39 +00002437
nethercote71980f02004-01-24 18:18:54 +00002438 HELPER(undefined_instruction);
jsgf855d93d2003-10-13 22:26:55 +00002439
nethercote71980f02004-01-24 18:18:54 +00002440# undef HELPER
sewardjde4a1d02002-03-22 01:27:54 +00002441
nethercote71980f02004-01-24 18:18:54 +00002442 /* Allocate slots for noncompact helpers */
2443 assign_helpers_in_baseBlock(VG_(n_noncompact_helpers),
2444 VG_(noncompact_helper_offsets),
2445 VG_(noncompact_helper_addrs));
2446}
sewardjde4a1d02002-03-22 01:27:54 +00002447
sewardj5f07b662002-04-23 16:52:51 +00002448
nethercote71980f02004-01-24 18:18:54 +00002449/*====================================================================*/
2450/*=== Setup pointercheck ===*/
2451/*====================================================================*/
njn25e49d8e72002-09-23 09:36:25 +00002452
nethercote71980f02004-01-24 18:18:54 +00002453static void setup_pointercheck(void)
2454{
2455 int ret;
sewardj2e93c502002-04-12 11:12:52 +00002456
fitzhardinge98abfc72003-12-16 02:05:15 +00002457 if (VG_(clo_pointercheck)) {
nethercote71980f02004-01-24 18:18:54 +00002458 vki_modify_ldt_t ldt = {
2459 VG_POINTERCHECK_SEGIDX, // entry_number
2460 VG_(client_base), // base_addr
2461 (VG_(client_end)-VG_(client_base)) / VKI_BYTES_PER_PAGE, // limit
2462 1, // seg_32bit
2463 0, // contents: data, RW, non-expanding
2464 0, // ! read_exec_only
2465 1, // limit_in_pages
2466 0, // ! seg not present
2467 1, // useable
fitzhardinge98abfc72003-12-16 02:05:15 +00002468 };
nethercote71980f02004-01-24 18:18:54 +00002469 ret = VG_(do_syscall)(__NR_modify_ldt, 1, &ldt, sizeof(ldt));
fitzhardinge98abfc72003-12-16 02:05:15 +00002470 if (ret < 0) {
2471 VG_(message)(Vg_UserMsg,
2472 "Warning: ignoring --pointercheck=yes, "
2473 "because modify_ldt failed (errno=%d)", -ret);
2474 VG_(clo_pointercheck) = False;
2475 }
2476 }
sewardjde4a1d02002-03-22 01:27:54 +00002477}
2478
nethercote71980f02004-01-24 18:18:54 +00002479/*====================================================================*/
2480/*=== Initialise program data/text, etc. ===*/
2481/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +00002482
nethercote71980f02004-01-24 18:18:54 +00002483static void build_valgrind_map_callback
2484 ( Addr start, UInt size, Char rr, Char ww, Char xx,
2485 UInt dev, UInt ino, ULong foffset, const UChar* filename )
sewardjde4a1d02002-03-22 01:27:54 +00002486{
nethercote71980f02004-01-24 18:18:54 +00002487 UInt prot = 0;
2488 UInt flags = SF_MMAP|SF_NOSYMS;
2489 Bool is_stack_segment;
2490
2491 is_stack_segment =
2492 (start == VG_(clstk_base) && (start+size) == VG_(clstk_end));
2493
2494 /* Only record valgrind mappings for now, without loading any
2495 symbols. This is so we know where the free space is before we
2496 start allocating more memory (note: heap is OK, it's just mmap
2497 which is the problem here). */
2498 if (start >= VG_(valgrind_base) && (start+size) <= VG_(valgrind_end)) {
2499 flags |= SF_VALGRIND;
2500 VG_(map_file_segment)(start, size, prot, flags, dev, ino, foffset, filename);
2501 }
sewardjde4a1d02002-03-22 01:27:54 +00002502}
2503
nethercote71980f02004-01-24 18:18:54 +00002504// Global var used to pass local data to callback
2505Addr esp_at_startup___global_arg = 0;
sewardjde4a1d02002-03-22 01:27:54 +00002506
nethercote71980f02004-01-24 18:18:54 +00002507static void build_segment_map_callback
2508 ( Addr start, UInt size, Char rr, Char ww, Char xx,
2509 UInt dev, UInt ino, ULong foffset, const UChar* filename )
sewardj45b672d2003-07-25 19:58:11 +00002510{
nethercote71980f02004-01-24 18:18:54 +00002511 UInt prot = 0;
2512 UInt flags;
2513 Bool is_stack_segment;
2514 Addr r_esp;
sewardj45b672d2003-07-25 19:58:11 +00002515
nethercote71980f02004-01-24 18:18:54 +00002516 is_stack_segment
2517 = (start == VG_(clstk_base) && (start+size) == VG_(clstk_end));
fitzhardinge98abfc72003-12-16 02:05:15 +00002518
nethercote71980f02004-01-24 18:18:54 +00002519 if (rr == 'r') prot |= VKI_PROT_READ;
2520 if (ww == 'w') prot |= VKI_PROT_WRITE;
2521 if (xx == 'x') prot |= VKI_PROT_EXEC;
fitzhardinge98abfc72003-12-16 02:05:15 +00002522
nethercote71980f02004-01-24 18:18:54 +00002523 if (is_stack_segment)
2524 flags = SF_STACK | SF_GROWDOWN;
2525 else
2526 flags = SF_EXEC|SF_MMAP;
fitzhardinge98abfc72003-12-16 02:05:15 +00002527
nethercote71980f02004-01-24 18:18:54 +00002528 if (filename != NULL)
2529 flags |= SF_FILE;
fitzhardinge98abfc72003-12-16 02:05:15 +00002530
nethercote71980f02004-01-24 18:18:54 +00002531 if (start >= VG_(valgrind_base) && (start+size) <= VG_(valgrind_end))
2532 flags |= SF_VALGRIND;
fitzhardinge98abfc72003-12-16 02:05:15 +00002533
nethercote71980f02004-01-24 18:18:54 +00002534 VG_(map_file_segment)(start, size, prot, flags, dev, ino, foffset, filename);
fitzhardinge98abfc72003-12-16 02:05:15 +00002535
nethercote71980f02004-01-24 18:18:54 +00002536 if (VG_(is_client_addr)(start) && VG_(is_client_addr)(start+size-1))
2537 VG_TRACK( new_mem_startup, start, size, rr=='r', ww=='w', xx=='x' );
sewardj3e1eb1f2002-05-18 13:14:17 +00002538
nethercote71980f02004-01-24 18:18:54 +00002539 /* If this is the stack segment mark all below %esp as noaccess. */
2540 r_esp = esp_at_startup___global_arg;
2541 vg_assert(0 != r_esp);
2542 if (is_stack_segment) {
2543 if (0)
2544 VG_(message)(Vg_DebugMsg, "invalidating stack area: %x .. %x",
2545 start,r_esp);
2546 VG_TRACK( die_mem_stack, start, r_esp-start );
sewardjde4a1d02002-03-22 01:27:54 +00002547 }
sewardjde4a1d02002-03-22 01:27:54 +00002548}
2549
2550
nethercote71980f02004-01-24 18:18:54 +00002551/*====================================================================*/
2552/*=== Sanity check machinery (permanently engaged) ===*/
2553/*====================================================================*/
njn25e49d8e72002-09-23 09:36:25 +00002554
2555/* A fast sanity check -- suitable for calling circa once per
2556 millisecond. */
2557
2558void VG_(do_sanity_checks) ( Bool force_expensive )
2559{
njn37cea302002-09-30 11:24:00 +00002560 VGP_PUSHCC(VgpCoreCheapSanity);
2561
nethercote27fec902004-06-16 21:26:32 +00002562 if (VG_(clo_sanity_level) < 1) return;
njn25e49d8e72002-09-23 09:36:25 +00002563
2564 /* --- First do all the tests that we can do quickly. ---*/
2565
2566 VG_(sanity_fast_count)++;
2567
njn25e49d8e72002-09-23 09:36:25 +00002568 /* Check stuff pertaining to the memory check system. */
2569
2570 /* Check that nobody has spuriously claimed that the first or
2571 last 16 pages of memory have become accessible [...] */
njn37cea302002-09-30 11:24:00 +00002572 if (VG_(needs).sanity_checks) {
2573 VGP_PUSHCC(VgpSkinCheapSanity);
njn25e49d8e72002-09-23 09:36:25 +00002574 vg_assert(SK_(cheap_sanity_check)());
njn37cea302002-09-30 11:24:00 +00002575 VGP_POPCC(VgpSkinCheapSanity);
2576 }
njn25e49d8e72002-09-23 09:36:25 +00002577
2578 /* --- Now some more expensive checks. ---*/
2579
2580 /* Once every 25 times, check some more expensive stuff. */
2581 if ( force_expensive
nethercote27fec902004-06-16 21:26:32 +00002582 || VG_(clo_sanity_level) > 1
2583 || (VG_(clo_sanity_level) == 1 && (VG_(sanity_fast_count) % 25) == 0)) {
njn25e49d8e72002-09-23 09:36:25 +00002584
njn37cea302002-09-30 11:24:00 +00002585 VGP_PUSHCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002586 VG_(sanity_slow_count)++;
2587
jsgf855d93d2003-10-13 22:26:55 +00002588 VG_(proxy_sanity)();
2589
njn25e49d8e72002-09-23 09:36:25 +00002590# if 0
2591 { void zzzmemscan(void); zzzmemscan(); }
2592# endif
2593
2594 if ((VG_(sanity_fast_count) % 250) == 0)
2595 VG_(sanity_check_tc_tt)();
2596
2597 if (VG_(needs).sanity_checks) {
njn37cea302002-09-30 11:24:00 +00002598 VGP_PUSHCC(VgpSkinExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002599 vg_assert(SK_(expensive_sanity_check)());
njn37cea302002-09-30 11:24:00 +00002600 VGP_POPCC(VgpSkinExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002601 }
2602 /*
2603 if ((VG_(sanity_fast_count) % 500) == 0) VG_(mallocSanityCheckAll)();
2604 */
njn37cea302002-09-30 11:24:00 +00002605 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002606 }
2607
nethercote27fec902004-06-16 21:26:32 +00002608 if (VG_(clo_sanity_level) > 1) {
njn37cea302002-09-30 11:24:00 +00002609 VGP_PUSHCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002610 /* Check sanity of the low-level memory manager. Note that bugs
2611 in the client's code can cause this to fail, so we don't do
2612 this check unless specially asked for. And because it's
2613 potentially very expensive. */
2614 VG_(mallocSanityCheckAll)();
njn37cea302002-09-30 11:24:00 +00002615 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002616 }
njn37cea302002-09-30 11:24:00 +00002617 VGP_POPCC(VgpCoreCheapSanity);
njn25e49d8e72002-09-23 09:36:25 +00002618}
nethercote71980f02004-01-24 18:18:54 +00002619
2620
2621/*====================================================================*/
2622/*=== main() ===*/
2623/*====================================================================*/
2624
2625int main(int argc, char **argv)
2626{
2627 char **cl_argv;
2628 const char *tool = NULL;
2629 const char *exec = NULL;
2630 char *preload; /* tool-specific LD_PRELOAD .so */
2631 char **env;
nethercote6c999f22004-01-31 22:55:15 +00002632 Int need_help = 0; // 0 = no, 1 = --help, 2 = --help-debug
nethercote71980f02004-01-24 18:18:54 +00002633 struct exeinfo info;
2634 ToolInfo *toolinfo = NULL;
2635 void *tool_dlhandle;
2636 Addr client_eip;
2637 Addr esp_at_startup; /* client's %esp at the point we gained control. */
2638 UInt * client_auxv;
2639 VgSchedReturnCode src;
fitzhardingeb50068f2004-02-24 23:42:55 +00002640 vki_rlimit zero = { 0, 0 };
nethercote71980f02004-01-24 18:18:54 +00002641
2642 //============================================================
2643 // Nb: startup is complex. Prerequisites are shown at every step.
2644 //
2645 // *** Be very careful when messing with the order ***
2646 //============================================================
2647
nethercotef4928da2004-06-15 10:54:40 +00002648 //============================================================
2649 // Command line argument handling order:
2650 // * If --help/--help-debug are present, show usage message
2651 // (if --tool is also present, that includes the tool-specific usage)
2652 // * Then, if --tool is missing, abort with error msg
2653 // * Then, if client is missing, abort with error msg
2654 // * Then, if any cmdline args are bad, abort with error msg
2655 //============================================================
2656
fitzhardingeb50068f2004-02-24 23:42:55 +00002657 // Get the current process datasize rlimit, and set it to zero.
2658 // This prevents any internal uses of brk() from having any effect.
2659 // We remember the old value so we can restore it on exec, so that
2660 // child processes will have a reasonable brk value.
2661 VG_(getrlimit)(VKI_RLIMIT_DATA, &VG_(client_rlimit_data));
2662 zero.rlim_max = VG_(client_rlimit_data).rlim_max;
2663 VG_(setrlimit)(VKI_RLIMIT_DATA, &zero);
2664
nethercote71980f02004-01-24 18:18:54 +00002665 //--------------------------------------------------------------
2666 // Check we were launched by stage1
2667 // p: n/a [must be first step]
2668 //--------------------------------------------------------------
2669 scan_auxv();
2670
2671 if (0) {
2672 int prmap(void *start, void *end, const char *perm, off_t off,
2673 int maj, int min, int ino) {
2674 printf("mapping %10p-%10p %s %02x:%02x %d\n",
2675 start, end, perm, maj, min, ino);
2676 return True;
2677 }
2678 printf("========== main() ==========\n");
2679 foreach_map(prmap);
2680 }
2681
2682 //--------------------------------------------------------------
2683 // Look for alternative libdir
2684 // p: n/a
2685 //--------------------------------------------------------------
2686 { char *cp = getenv(VALGRINDLIB);
2687 if (cp != NULL)
2688 VG_(libdir) = cp;
2689 }
2690
2691 //--------------------------------------------------------------
2692 // Begin working out address space layout
2693 // p: n/a
2694 //--------------------------------------------------------------
2695 layout_client_space( (Addr) & argc );
2696
2697 //--------------------------------------------------------------
2698 // Get valgrind args + client args (inc. from VALGRIND_OPTS/.valgrindrc).
2699 // Pre-process the command line.
2700 // p: n/a
2701 //--------------------------------------------------------------
2702 get_command_line(argc, argv, &VG_(vg_argc), &VG_(vg_argv), &cl_argv);
2703 pre_process_cmd_line_options(&need_help, &tool, &exec);
2704
2705 //==============================================================
2706 // Nb: once a tool is specified, the tool.so must be loaded even if
2707 // they specified --help or didn't specify a client program.
2708 //==============================================================
2709
2710 //--------------------------------------------------------------
2711 // With client padded out, map in tool
2712 // p: layout_client_space() [for padding]
2713 // p: set-libdir [for VG_(libdir)]
2714 // p: pre_process_cmd_line_options() [for 'tool']
2715 //--------------------------------------------------------------
2716 load_tool(tool, &tool_dlhandle, &toolinfo, &preload);
2717
2718 //==============================================================
2719 // Can use VG_(malloc)() and VG_(arena_malloc)() only after load_tool()
2720 // -- redzone size is now set.
2721 //==============================================================
2722
2723 //--------------------------------------------------------------
2724 // Finalise address space layout
2725 // p: layout_client_space(), load_tool() [for 'toolinfo']
2726 //--------------------------------------------------------------
2727 layout_remaining_space( toolinfo->shadow_ratio );
2728
2729 //--------------------------------------------------------------
2730 // Load client executable, finding in $PATH if necessary
2731 // p: layout_client_space() [so there's space]
2732 // p: pre_process_cmd_line_options() [for 'exec', 'need_help']
2733 // p: layout_remaining_space [so there's space]
2734 //--------------------------------------------------------------
nethercotef4928da2004-06-15 10:54:40 +00002735 load_client(cl_argv, exec, need_help, &info, &client_eip);
nethercote71980f02004-01-24 18:18:54 +00002736
2737 //--------------------------------------------------------------
2738 // Everything in place, unpad us
2739 // p: layout_remaining_space() [everything must be mapped in before now]
2740 // p: load_client() [ditto]
2741 //--------------------------------------------------------------
2742 as_unpad((void *)VG_(shadow_end), (void *)~0);
2743 as_closepadfile(); /* no more padding */
2744
2745 //--------------------------------------------------------------
2746 // Set up client's environment
2747 // p: set-libdir [for VG_(libdir)]
2748 // p: load_tool() [for 'preload']
2749 //--------------------------------------------------------------
2750 env = fix_environment(environ, preload);
2751
2752 //--------------------------------------------------------------
nethercote5ee67ca2004-06-22 14:00:09 +00002753 // Setup client stack, eip, and VG_(client_arg[cv])
nethercote71980f02004-01-24 18:18:54 +00002754 // p: load_client() [for 'info']
2755 // p: fix_environment() [for 'env']
2756 //--------------------------------------------------------------
2757 esp_at_startup = setup_client_stack(cl_argv, env, &info, &client_auxv);
2758
2759 if (0)
2760 printf("entry=%x client esp=%x vg_argc=%d brkbase=%x\n",
2761 client_eip, esp_at_startup, VG_(vg_argc), VG_(brk_base));
2762
2763 //==============================================================
2764 // Finished setting up operating environment. Now initialise
2765 // Valgrind. (This is where the old VG_(main)() started.)
2766 //==============================================================
2767
2768 //--------------------------------------------------------------
2769 // Read /proc/self/maps into a buffer
2770 // p: all memory layout, environment setup [so memory maps are right]
2771 //--------------------------------------------------------------
2772 VG_(read_procselfmaps)();
2773
2774 //--------------------------------------------------------------
2775 // atfork
2776 // p: n/a
2777 //--------------------------------------------------------------
2778 VG_(atfork)(NULL, NULL, newpid);
2779 newpid(VG_INVALID_THREADID);
2780
2781 //--------------------------------------------------------------
2782 // setup file descriptors
2783 // p: n/a
2784 //--------------------------------------------------------------
2785 setup_file_descriptors();
2786
2787 //--------------------------------------------------------------
2788 // Setup tool
2789 // p: VG_(read_procselfmaps)() [so if sk_pre_clo_init calls
2790 // VG_(malloc), any mmap'd superblocks aren't erroneously
2791 // identified later as being owned by the client]
2792 // XXX: is that necessary, now that we look for V's segments separately?
2793 // XXX: alternatively, if sk_pre_clo_init does use VG_(malloc)(), is it
2794 // wrong to ignore any segments that might add in parse_procselfmaps?
nethercote5ee67ca2004-06-22 14:00:09 +00002795 // p: setup_client_stack() [for 'VG_(client_arg[cv]']
nethercote71980f02004-01-24 18:18:54 +00002796 //--------------------------------------------------------------
2797 (*toolinfo->sk_pre_clo_init)();
2798 VG_(tool_init_dlsym)(tool_dlhandle);
2799 VG_(sanity_check_needs)();
2800
2801 //--------------------------------------------------------------
nethercotef4928da2004-06-15 10:54:40 +00002802 // If --tool and --help/--help-debug was given, now give the core+tool
2803 // help message
2804 // p: pre_clo_init()
2805 //--------------------------------------------------------------
2806 if (need_help) {
2807 usage(/*--help-debug?*/2 == need_help);
2808 }
2809
2810 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002811 // Process Valgrind's + tool's command-line options
2812 // p: load_tool() [for 'tool']
nethercote71980f02004-01-24 18:18:54 +00002813 // p: setup_file_descriptors() [for 'VG_(max_fd)']
2814 // p: sk_pre_clo_init [to set 'command_line_options' need]
2815 //--------------------------------------------------------------
nethercote5ee67ca2004-06-22 14:00:09 +00002816 process_cmd_line_options(client_auxv, tool);
nethercote71980f02004-01-24 18:18:54 +00002817
2818 //--------------------------------------------------------------
2819 // Allow GDB attach
2820 // p: process_cmd_line_options() [for VG_(clo_wait_for_gdb)]
2821 //--------------------------------------------------------------
2822 /* Hook to delay things long enough so we can get the pid and
2823 attach GDB in another shell. */
2824 if (VG_(clo_wait_for_gdb)) {
2825 VG_(printf)("pid=%d\n", VG_(getpid)());
2826 /* do "jump *$eip" to skip this in gdb */
2827 VG_(do_syscall)(__NR_pause);
2828 }
2829
2830 //--------------------------------------------------------------
2831 // Setup tool, post command-line processing
2832 // p: process_cmd_line_options [tool assumes it]
2833 //--------------------------------------------------------------
2834 SK_(post_clo_init)();
2835
2836 //--------------------------------------------------------------
nethercote1d447092004-02-01 17:29:59 +00002837 // Set up baseBlock
nethercote71980f02004-01-24 18:18:54 +00002838 // p: {pre,post}_clo_init() [for tool helper registration]
2839 // load_client() [for 'client_eip']
2840 // setup_client_stack() [for 'esp_at_startup']
2841 //--------------------------------------------------------------
2842 init_baseBlock(client_eip, esp_at_startup);
2843
2844 //--------------------------------------------------------------
2845 // Search for file descriptors that are inherited from our parent
2846 // p: process_cmd_line_options [for VG_(clo_track_fds)]
2847 //--------------------------------------------------------------
2848 if (VG_(clo_track_fds))
2849 VG_(init_preopened_fds)();
2850
2851 //--------------------------------------------------------------
2852 // Initialise the scheduler
2853 // p: init_baseBlock() [baseBlock regs copied into VG_(threads)[1]]
2854 // p: setup_file_descriptors() [else VG_(safe_fd)() breaks]
2855 //--------------------------------------------------------------
2856 VG_(scheduler_init)();
2857
2858 //--------------------------------------------------------------
2859 // Set up the ProxyLWP machinery
2860 // p: VG_(scheduler_init)()? [XXX: subtle dependency?]
2861 // - subs: VG_(sigstartup_actions)()?
2862 //--------------------------------------------------------------
2863 VG_(proxy_init)();
2864
2865 //--------------------------------------------------------------
2866 // Initialise the signal handling subsystem
2867 // p: VG_(atfork)(NULL, NULL, newpid) [else problems with sigmasks]
2868 // p: VG_(proxy_init)() [else breaks...]
2869 //--------------------------------------------------------------
2870 // Nb: temporarily parks the saved blocking-mask in saved_sigmask.
2871 VG_(sigstartup_actions)();
2872
2873 //--------------------------------------------------------------
2874 // Perhaps we're profiling Valgrind?
2875 // p: process_cmd_line_options() [for VG_(clo_profile)]
2876 // p: others?
2877 //
2878 // XXX: this seems to be broken? It always says the tool wasn't built
2879 // for profiling; vg_profile.c's functions don't seem to be overriding
2880 // vg_dummy_profile.c's?
2881 //
2882 // XXX: want this as early as possible. Looking for --profile
2883 // in pre_process_cmd_line_options() could get it earlier.
2884 //--------------------------------------------------------------
2885 if (VG_(clo_profile))
2886 VGP_(init_profiling)();
2887
2888 VGP_PUSHCC(VgpStartup);
2889
2890 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002891 // Reserve Valgrind's kickstart, heap and stack
2892 // p: XXX ???
2893 //--------------------------------------------------------------
2894 VG_(map_segment)(VG_(valgrind_mmap_end),
2895 VG_(valgrind_end)-VG_(valgrind_mmap_end),
2896 VKI_PROT_NONE, SF_VALGRIND|SF_FIXED);
2897
2898 //--------------------------------------------------------------
2899 // Identify Valgrind's segments
2900 // p: read proc/self/maps
2901 // p: VG_(map_segment) [XXX ???]
2902 // p: sk_pre_clo_init() [to setup new_mem_startup tracker]
2903 //--------------------------------------------------------------
2904 VG_(parse_procselfmaps) ( build_valgrind_map_callback );
2905
2906 // XXX: I can't see why these two need to be separate; could they be
2907 // folded together? If not, need a comment explaining why.
2908 //
2909 // XXX: can we merge reading and parsing of /proc/self/maps?
2910 //
2911 // XXX: can we dynamically allocate the /proc/self/maps buffer? (or mmap
2912 // it?) Or does that disturb its contents...
2913
2914 //--------------------------------------------------------------
2915 // Build segment map (all segments)
2916 // p: setup_client_stack() [for 'esp_at_startup']
2917 //--------------------------------------------------------------
2918 esp_at_startup___global_arg = esp_at_startup;
2919 VG_(parse_procselfmaps) ( build_segment_map_callback ); /* everything */
2920 esp_at_startup___global_arg = 0;
2921
2922 //==============================================================
2923 // Can only use VG_(map)() after VG_(map_segment)() [XXX ???]
2924 //==============================================================
2925
2926 //--------------------------------------------------------------
2927 // Build segment map (all segments)
2928 // p: setup_client_stack() [for 'esp_at_startup']
2929 //--------------------------------------------------------------
2930 /* Initialize our trampoline page (which is also sysinfo stuff) */
2931 VG_(memcpy)( (void *)VG_(client_trampoline_code),
2932 &VG_(trampoline_code_start), VG_(trampoline_code_length) );
2933 VG_(mprotect)( (void *)VG_(client_trampoline_code),
2934 VG_(trampoline_code_length), VKI_PROT_READ|VKI_PROT_EXEC );
2935
2936 //--------------------------------------------------------------
2937 // Read suppression file
2938 // p: process_cmd_line_options() [for VG_(clo_suppressions)]
2939 //--------------------------------------------------------------
2940 if (VG_(needs).core_errors || VG_(needs).skin_errors)
2941 VG_(load_suppressions)();
2942
2943 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002944 // Initialise translation table and translation cache
2945 // p: read_procselfmaps [so the anonymous mmaps for the TT/TC
2946 // aren't identified as part of the client, which would waste
2947 // > 20M of virtual address space.]
2948 //--------------------------------------------------------------
2949 VG_(init_tt_tc)();
2950
2951 //--------------------------------------------------------------
2952 // Read debug info to find glibc entry points to intercept
2953 // p: parse_procselfmaps? [XXX for debug info?]
2954 // p: init_tt_tc? [XXX ???]
2955 //--------------------------------------------------------------
2956 VG_(setup_code_redirect_table)();
2957
2958 //--------------------------------------------------------------
2959 // Verbosity message
2960 // p: end_rdtsc_calibration [so startup message is printed first]
2961 //--------------------------------------------------------------
2962 if (VG_(clo_verbosity) == 1)
2963 VG_(message)(Vg_UserMsg, "For more details, rerun with: -v");
2964 if (VG_(clo_verbosity) > 0)
2965 VG_(message)(Vg_UserMsg, "");
2966
2967 //--------------------------------------------------------------
2968 // Setup pointercheck
2969 // p: process_cmd_line_options() [for VG_(clo_pointercheck)]
2970 //--------------------------------------------------------------
2971 setup_pointercheck();
2972
2973
2974
2975 //--------------------------------------------------------------
2976 // Run!
2977 //--------------------------------------------------------------
2978 VG_(running_on_simd_CPU) = True;
2979 VGP_POPCC(VgpStartup);
2980 VGP_PUSHCC(VgpSched);
2981
2982 if (__builtin_setjmp(&VG_(fatal_signal_jmpbuf)) == 0) {
2983 VG_(fatal_signal_set) = True;
2984 src = VG_(scheduler)();
2985 } else
2986 src = VgSrc_FatalSig;
2987
2988 VGP_POPCC(VgpSched);
2989 VG_(running_on_simd_CPU) = False;
2990
2991
2992
2993 //--------------------------------------------------------------
2994 // Finalisation: cleanup, messages, etc. Order no so important, only
2995 // affects what order the messages come.
2996 //--------------------------------------------------------------
2997 if (VG_(clo_verbosity) > 0)
2998 VG_(message)(Vg_UserMsg, "");
2999
3000 if (src == VgSrc_Deadlock) {
3001 VG_(message)(Vg_UserMsg,
3002 "Warning: pthread scheduler exited due to deadlock");
3003 }
3004
3005 /* Print out file descriptor summary and stats. */
3006 if (VG_(clo_track_fds))
3007 VG_(fd_stats)();
3008
3009 if (VG_(needs).core_errors || VG_(needs).skin_errors)
3010 VG_(show_all_errors)();
3011
3012 SK_(fini)( VG_(exitcode) );
3013
3014 VG_(do_sanity_checks)( True /*include expensive checks*/ );
3015
3016 if (VG_(clo_verbosity) > 1)
3017 show_counts();
3018
3019 if (VG_(clo_verbosity) > 3)
3020 VG_(print_UInstr_histogram)();
3021
3022 if (0) {
3023 VG_(message)(Vg_DebugMsg, "");
3024 VG_(message)(Vg_DebugMsg,
3025 "------ Valgrind's internal memory use stats follow ------" );
3026 VG_(mallocSanityCheckAll)();
3027 VG_(show_all_arena_stats)();
3028 VG_(message)(Vg_DebugMsg,
3029 "------ Valgrind's ExeContext management stats follow ------" );
3030 VG_(show_ExeContext_stats)();
3031 }
3032
3033 if (VG_(clo_profile))
3034 VGP_(done_profiling)();
3035
nethercote71980f02004-01-24 18:18:54 +00003036 /* We're exiting, so nuke all the threads and clean up the proxy LWPs */
3037 vg_assert(src == VgSrc_FatalSig ||
3038 VG_(threads)[VG_(last_run_tid)].status == VgTs_Runnable ||
3039 VG_(threads)[VG_(last_run_tid)].status == VgTs_WaitJoiner);
3040 VG_(nuke_all_threads_except)(VG_INVALID_THREADID);
3041
3042 //--------------------------------------------------------------
3043 // Exit, according to the scheduler's return code
3044 //--------------------------------------------------------------
3045 switch (src) {
3046 case VgSrc_ExitSyscall: /* the normal way out */
3047 vg_assert(VG_(last_run_tid) > 0
3048 && VG_(last_run_tid) < VG_N_THREADS);
3049 VG_(proxy_shutdown)();
3050
3051 /* The thread's %EBX at the time it did __NR_exit() will hold
3052 the arg to __NR_exit(), so we just do __NR_exit() with
3053 that arg. */
3054 VG_(exit)( VG_(exitcode) );
3055 /* NOT ALIVE HERE! */
3056 VG_(core_panic)("entered the afterlife in main() -- ExitSyscall");
3057 break; /* what the hell :) */
3058
3059 case VgSrc_Deadlock:
3060 /* Just exit now. No point in continuing. */
3061 VG_(proxy_shutdown)();
3062 VG_(exit)(0);
3063 VG_(core_panic)("entered the afterlife in main() -- Deadlock");
3064 break;
3065
nethercote71980f02004-01-24 18:18:54 +00003066 case VgSrc_FatalSig:
3067 /* We were killed by a fatal signal, so replicate the effect */
3068 vg_assert(VG_(fatal_sigNo) != -1);
3069 VG_(kill_self)(VG_(fatal_sigNo));
3070 VG_(core_panic)("main(): signal was supposed to be fatal");
3071 break;
3072
3073 default:
3074 VG_(core_panic)("main(): unexpected scheduler return code");
3075 }
3076
3077 abort();
3078}
3079
3080
sewardjde4a1d02002-03-22 01:27:54 +00003081/*--------------------------------------------------------------------*/
3082/*--- end vg_main.c ---*/
3083/*--------------------------------------------------------------------*/