blob: 4d53d2421a7cba4a4e32e58b5328eb23c1ca4daa [file] [log] [blame]
sewardjde4a1d02002-03-22 01:27:54 +00001
2/*--------------------------------------------------------------------*/
nethercote71980f02004-01-24 18:18:54 +00003/*--- Startup: the real stuff vg_main.c ---*/
sewardjde4a1d02002-03-22 01:27:54 +00004/*--------------------------------------------------------------------*/
5
6/*
njnc9539842002-10-02 13:26:35 +00007 This file is part of Valgrind, an extensible x86 protected-mode
8 emulator for monitoring program execution on x86-Unixes.
sewardjde4a1d02002-03-22 01:27:54 +00009
nethercotebb1c9912004-01-04 16:43:23 +000010 Copyright (C) 2000-2004 Julian Seward
sewardjde4a1d02002-03-22 01:27:54 +000011 jseward@acm.org
sewardjde4a1d02002-03-22 01:27:54 +000012
13 This program is free software; you can redistribute it and/or
14 modify it under the terms of the GNU General Public License as
15 published by the Free Software Foundation; either version 2 of the
16 License, or (at your option) any later version.
17
18 This program is distributed in the hope that it will be useful, but
19 WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 General Public License for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software
25 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
26 02111-1307, USA.
27
njn25e49d8e72002-09-23 09:36:25 +000028 The GNU General Public License is contained in the file COPYING.
sewardjde4a1d02002-03-22 01:27:54 +000029*/
30
nethercote71980f02004-01-24 18:18:54 +000031#define _FILE_OFFSET_BITS 64
sewardjde4a1d02002-03-22 01:27:54 +000032
nethercote71980f02004-01-24 18:18:54 +000033#include "vg_include.h"
34#include "ume.h"
35#include "ume_arch.h"
36#include "ume_archdefs.h"
37
38#include <dirent.h>
39#include <dlfcn.h>
40#include <errno.h>
41#include <fcntl.h>
42#include <stdio.h>
fitzhardingeb727d042004-01-06 00:18:21 +000043#include <stdlib.h>
nethercote71980f02004-01-24 18:18:54 +000044#include <string.h>
45#include <sys/mman.h>
46#include <sys/types.h>
47#include <sys/stat.h>
fitzhardingeb727d042004-01-06 00:18:21 +000048#include <sys/ptrace.h>
49#include <sys/signal.h>
fitzhardingeb727d042004-01-06 00:18:21 +000050#include <sys/wait.h>
51#include <unistd.h>
52
thughes74b8de22004-04-22 18:12:31 +000053#ifndef AT_DCACHEBSIZE
54#define AT_DCACHEBSIZE 19
55#endif /* AT_DCACHEBSIZE */
56
57#ifndef AT_ICACHEBSIZE
58#define AT_ICACHEBSIZE 20
59#endif /* AT_ICACHEBSIZE */
60
61#ifndef AT_UCACHEBSIZE
62#define AT_UCACHEBSIZE 21
63#endif /* AT_UCACHEBSIZE */
64
nethercote71980f02004-01-24 18:18:54 +000065#ifndef AT_SYSINFO
66#define AT_SYSINFO 32
67#endif /* AT_SYSINFO */
68
69#ifndef AT_SYSINFO_EHDR
70#define AT_SYSINFO_EHDR 33
71#endif /* AT_SYSINFO_EHDR */
72
73#ifndef AT_SECURE
74#define AT_SECURE 23 /* secure mode boolean */
75#endif /* AT_SECURE */
76
nethercote71980f02004-01-24 18:18:54 +000077/* Amount to reserve for Valgrind's internal mappings */
78#define VALGRIND_MAPSIZE (128*1024*1024)
79
80/* redzone gap between client address space and shadow */
81#define REDZONE_SIZE (1 * 1024*1024)
82
83/* size multiple for client address space */
nethercotee94b2de2004-06-23 16:15:06 +000084#define CLIENT_SIZE_MULTIPLE (1 * 1024*1024)
nethercote71980f02004-01-24 18:18:54 +000085
86#define ISSPACE(cc) ((cc) == ' ' || (cc) == '\t' || (cc) == '\n')
87
88/*====================================================================*/
89/*=== Global entities not referenced from generated code ===*/
90/*====================================================================*/
91
sewardjde4a1d02002-03-22 01:27:54 +000092/* ---------------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +000093 Startup stuff
sewardjde4a1d02002-03-22 01:27:54 +000094 ------------------------------------------------------------------ */
nethercote71980f02004-01-24 18:18:54 +000095/* linker-defined base address */
96extern char kickstart_base;
sewardjde4a1d02002-03-22 01:27:54 +000097
nethercote71980f02004-01-24 18:18:54 +000098/* Client address space, lowest to highest (see top of ume.c) */
99Addr VG_(client_base); /* client address space limits */
fitzhardinge98abfc72003-12-16 02:05:15 +0000100Addr VG_(client_end);
101Addr VG_(client_mapbase);
fitzhardinge92360792003-12-24 10:11:11 +0000102Addr VG_(client_trampoline_code);
fitzhardinge98abfc72003-12-16 02:05:15 +0000103Addr VG_(clstk_base);
104Addr VG_(clstk_end);
nethercote71980f02004-01-24 18:18:54 +0000105
106Addr VG_(brk_base); /* start of brk */
107Addr VG_(brk_limit); /* current brk */
108
109Addr VG_(shadow_base); /* skin's shadow memory */
fitzhardinge98abfc72003-12-16 02:05:15 +0000110Addr VG_(shadow_end);
nethercote71980f02004-01-24 18:18:54 +0000111
112Addr VG_(valgrind_base); /* valgrind's address range */
113Addr VG_(valgrind_mmap_end); /* valgrind's mmaps are between valgrind_base and here */
fitzhardinge98abfc72003-12-16 02:05:15 +0000114Addr VG_(valgrind_end);
115
fitzhardingeb50068f2004-02-24 23:42:55 +0000116vki_rlimit VG_(client_rlimit_data);
117
nethercote71980f02004-01-24 18:18:54 +0000118/* This is set early to indicate whether this CPU has the
119 SSE/fxsave/fxrestor features. */
120Bool VG_(have_ssestate);
121
122/* Indicates presence, and holds address of client's sysinfo page, a
123 feature of some modern kernels used to provide vsyscalls, etc. */
124Bool VG_(sysinfo_page_exists) = False;
125Addr VG_(sysinfo_page_addr) = 0;
126
fitzhardinge98abfc72003-12-16 02:05:15 +0000127/* stage1 (main) executable */
fitzhardingea49f9b52003-12-16 22:26:45 +0000128Int VG_(vgexecfd) = -1;
129
130/* client executable */
131Int VG_(clexecfd) = -1;
fitzhardinge98abfc72003-12-16 02:05:15 +0000132
133/* Path to library directory */
134const Char *VG_(libdir) = VG_LIBDIR;
135
136/* our argc/argv */
137Int VG_(vg_argc);
138Char **VG_(vg_argv);
139
jsgf855d93d2003-10-13 22:26:55 +0000140/* PID of the main thread */
141Int VG_(main_pid);
142
143/* PGRP of process */
144Int VG_(main_pgrp);
njn25e49d8e72002-09-23 09:36:25 +0000145
fitzhardingef0046f22003-12-18 02:39:22 +0000146/* Maximum allowed application-visible file descriptor */
fitzhardingeb791a192003-12-18 07:22:44 +0000147Int VG_(max_fd) = -1;
fitzhardingef0046f22003-12-18 02:39:22 +0000148
nethercote71980f02004-01-24 18:18:54 +0000149/* As deduced from esp_at_startup, the client's argc, argv[] and
150 envp[] as extracted from the client's stack at startup-time. */
151Int VG_(client_argc);
152Char** VG_(client_argv);
153Char** VG_(client_envp);
sewardjde4a1d02002-03-22 01:27:54 +0000154
155/* ---------------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +0000156 Running stuff
sewardjde4a1d02002-03-22 01:27:54 +0000157 ------------------------------------------------------------------ */
nethercote71980f02004-01-24 18:18:54 +0000158/* Our signal delivery stack. */
njn6eba4ef2003-05-01 08:06:41 +0000159UInt VG_(sigstack)[VG_SIGSTACK_SIZE_W];
sewardjde4a1d02002-03-22 01:27:54 +0000160
nethercote71980f02004-01-24 18:18:54 +0000161/* jmp_buf for fatal signals */
162Int VG_(fatal_sigNo) = -1;
163Bool VG_(fatal_signal_set) = False;
164jmp_buf VG_(fatal_signal_jmpbuf);
sewardjde4a1d02002-03-22 01:27:54 +0000165
nethercote71980f02004-01-24 18:18:54 +0000166/* Counts downwards in VG_(run_innerloop). */
167UInt VG_(dispatch_ctr);
sewardjde4a1d02002-03-22 01:27:54 +0000168
169/* 64-bit counter for the number of basic blocks done. */
170ULong VG_(bbs_done);
sewardjde4a1d02002-03-22 01:27:54 +0000171
sewardj7e87e382002-05-03 19:09:05 +0000172/* This is the ThreadId of the last thread the scheduler ran. */
173ThreadId VG_(last_run_tid) = 0;
174
nethercote71980f02004-01-24 18:18:54 +0000175/* Tell the logging mechanism whether we are logging to a file
176 descriptor or a socket descriptor. */
177Bool VG_(logging_to_filedes) = True;
178
sewardj73cf3bc2002-11-03 03:20:15 +0000179
nethercote71980f02004-01-24 18:18:54 +0000180/*====================================================================*/
181/*=== Counters, for profiling purposes only ===*/
182/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +0000183
184/* Number of lookups which miss the fast tt helper. */
185UInt VG_(tt_fast_misses) = 0;
186
187
sewardjc0d8f682002-11-30 00:49:43 +0000188/* Counts for TT/TC informational messages. */
sewardjde4a1d02002-03-22 01:27:54 +0000189
sewardjde4a1d02002-03-22 01:27:54 +0000190/* Number and total o/t size of translations overall. */
191UInt VG_(overall_in_count) = 0;
192UInt VG_(overall_in_osize) = 0;
193UInt VG_(overall_in_tsize) = 0;
194/* Number and total o/t size of discards overall. */
195UInt VG_(overall_out_count) = 0;
196UInt VG_(overall_out_osize) = 0;
197UInt VG_(overall_out_tsize) = 0;
sewardjc0d8f682002-11-30 00:49:43 +0000198/* The number of discards of TT/TC. */
199UInt VG_(number_of_tc_discards) = 0;
sewardj22854b92002-11-30 14:00:47 +0000200/* Counts of chain and unchain operations done. */
201UInt VG_(bb_enchain_count) = 0;
202UInt VG_(bb_dechain_count) = 0;
203/* Number of unchained jumps performed. */
204UInt VG_(unchained_jumps_done) = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000205
206
207/* Counts pertaining to the register allocator. */
208
209/* total number of uinstrs input to reg-alloc */
210UInt VG_(uinstrs_prealloc) = 0;
211
212/* total number of uinstrs added due to spill code */
213UInt VG_(uinstrs_spill) = 0;
214
215/* number of bbs requiring spill code */
216UInt VG_(translations_needing_spill) = 0;
217
218/* total of register ranks over all translations */
219UInt VG_(total_reg_rank) = 0;
220
221
sewardjde4a1d02002-03-22 01:27:54 +0000222/* Counts pertaining to internal sanity checking. */
sewardjde4a1d02002-03-22 01:27:54 +0000223UInt VG_(sanity_fast_count) = 0;
224UInt VG_(sanity_slow_count) = 0;
225
sewardj2e93c502002-04-12 11:12:52 +0000226/* Counts pertaining to the scheduler. */
227UInt VG_(num_scheduling_events_MINOR) = 0;
228UInt VG_(num_scheduling_events_MAJOR) = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000229
230
nethercote71980f02004-01-24 18:18:54 +0000231static __inline__ Int safe_idiv(Int a, Int b)
232{
233 return (b == 0 ? 0 : a / b);
234}
235
236static void show_counts ( void )
237{
238 VG_(message)(Vg_DebugMsg,
239 " TT/TC: %d tc sectors discarded.",
240 VG_(number_of_tc_discards) );
241 VG_(message)(Vg_DebugMsg,
242 " %d chainings, %d unchainings.",
243 VG_(bb_enchain_count), VG_(bb_dechain_count) );
244 VG_(message)(Vg_DebugMsg,
245 "translate: new %d (%d -> %d; ratio %d:10)",
246 VG_(overall_in_count),
247 VG_(overall_in_osize),
248 VG_(overall_in_tsize),
249 safe_idiv(10*VG_(overall_in_tsize), VG_(overall_in_osize)));
250 VG_(message)(Vg_DebugMsg,
251 " discard %d (%d -> %d; ratio %d:10).",
252 VG_(overall_out_count),
253 VG_(overall_out_osize),
254 VG_(overall_out_tsize),
255 safe_idiv(10*VG_(overall_out_tsize), VG_(overall_out_osize)));
256 VG_(message)(Vg_DebugMsg,
257 " dispatch: %llu jumps (bb entries), of which %u (%lu%%) were unchained.",
258 VG_(bbs_done),
259 VG_(unchained_jumps_done),
260 ((ULong)(100) * (ULong)(VG_(unchained_jumps_done)))
261 / ( VG_(bbs_done)==0 ? 1 : VG_(bbs_done) )
262 );
263
264 VG_(message)(Vg_DebugMsg,
265 " %d/%d major/minor sched events. %d tt_fast misses.",
266 VG_(num_scheduling_events_MAJOR),
267 VG_(num_scheduling_events_MINOR),
268 VG_(tt_fast_misses));
269
270 VG_(message)(Vg_DebugMsg,
271 "reg-alloc: %d t-req-spill, "
272 "%d+%d orig+spill uis, %d total-reg-r.",
273 VG_(translations_needing_spill),
274 VG_(uinstrs_prealloc),
275 VG_(uinstrs_spill),
276 VG_(total_reg_rank) );
277 VG_(message)(Vg_DebugMsg,
278 " sanity: %d cheap, %d expensive checks.",
279 VG_(sanity_fast_count),
280 VG_(sanity_slow_count) );
281 VG_(print_ccall_stats)();
282}
283
284
285/*====================================================================*/
286/*=== Miscellaneous global functions ===*/
287/*====================================================================*/
288
nethercote04d0fbc2004-01-26 16:48:06 +0000289/* Start debugger and get it to attach to this process. Called if the
290 user requests this service after an error has been shown, so she can
nethercote71980f02004-01-24 18:18:54 +0000291 poke around and look at parameters, memory, etc. You can't
nethercote04d0fbc2004-01-26 16:48:06 +0000292 meaningfully get the debugger to continue the program, though; to
293 continue, quit the debugger. */
294void VG_(start_debugger) ( Int tid )
nethercote71980f02004-01-24 18:18:54 +0000295{
296 Int pid;
297
298 if ((pid = fork()) == 0) {
299 ptrace(PTRACE_TRACEME, 0, NULL, NULL);
300 VG_(kkill)(VG_(getpid)(), VKI_SIGSTOP);
301
302 } else if (pid > 0) {
303 struct user_regs_struct regs;
304 Int status;
305 Int res;
306
307 if (VG_(is_running_thread)( tid )) {
fitzhardinged65dcad2004-03-13 02:06:58 +0000308 regs.cs = VG_(baseBlock)[VGOFF_(m_cs)];
309 regs.ss = VG_(baseBlock)[VGOFF_(m_ss)];
310 regs.ds = VG_(baseBlock)[VGOFF_(m_ds)];
311 regs.es = VG_(baseBlock)[VGOFF_(m_es)];
312 regs.fs = VG_(baseBlock)[VGOFF_(m_fs)];
313 regs.gs = VG_(baseBlock)[VGOFF_(m_gs)];
nethercote71980f02004-01-24 18:18:54 +0000314 regs.eax = VG_(baseBlock)[VGOFF_(m_eax)];
315 regs.ebx = VG_(baseBlock)[VGOFF_(m_ebx)];
316 regs.ecx = VG_(baseBlock)[VGOFF_(m_ecx)];
317 regs.edx = VG_(baseBlock)[VGOFF_(m_edx)];
318 regs.esi = VG_(baseBlock)[VGOFF_(m_esi)];
319 regs.edi = VG_(baseBlock)[VGOFF_(m_edi)];
320 regs.ebp = VG_(baseBlock)[VGOFF_(m_ebp)];
321 regs.esp = VG_(baseBlock)[VGOFF_(m_esp)];
322 regs.eflags = VG_(baseBlock)[VGOFF_(m_eflags)];
323 regs.eip = VG_(baseBlock)[VGOFF_(m_eip)];
324 } else {
325 ThreadState* tst = & VG_(threads)[ tid ];
326
fitzhardinged65dcad2004-03-13 02:06:58 +0000327 regs.cs = tst->m_cs;
328 regs.ss = tst->m_ss;
329 regs.ds = tst->m_ds;
330 regs.es = tst->m_es;
331 regs.fs = tst->m_fs;
332 regs.gs = tst->m_gs;
nethercote71980f02004-01-24 18:18:54 +0000333 regs.eax = tst->m_eax;
334 regs.ebx = tst->m_ebx;
335 regs.ecx = tst->m_ecx;
336 regs.edx = tst->m_edx;
337 regs.esi = tst->m_esi;
338 regs.edi = tst->m_edi;
339 regs.ebp = tst->m_ebp;
340 regs.esp = tst->m_esp;
341 regs.eflags = tst->m_eflags;
342 regs.eip = tst->m_eip;
343 }
344
345 if ((res = VG_(waitpid)(pid, &status, 0)) == pid &&
346 WIFSTOPPED(status) && WSTOPSIG(status) == SIGSTOP &&
347 ptrace(PTRACE_SETREGS, pid, NULL, &regs) == 0 &&
thughes1d160052004-04-21 15:39:57 +0000348 kill(pid, SIGSTOP) == 0 &&
349 ptrace(PTRACE_DETACH, pid, NULL, 0) == 0) {
nethercote04d0fbc2004-01-26 16:48:06 +0000350 Char pidbuf[15];
351 Char file[30];
352 Char buf[100];
353 Char *bufptr;
354 Char *cmdptr;
355
356 VG_(sprintf)(pidbuf, "%d", pid);
357 VG_(sprintf)(file, "/proc/%d/fd/%d", pid, VG_(clexecfd));
358
359 bufptr = buf;
360 cmdptr = VG_(clo_db_command);
361
362 while (*cmdptr) {
363 switch (*cmdptr) {
364 case '%':
365 switch (*++cmdptr) {
366 case 'f':
367 VG_(memcpy)(bufptr, file, VG_(strlen)(file));
368 bufptr += VG_(strlen)(file);
369 cmdptr++;
370 break;
371 case 'p':
372 VG_(memcpy)(bufptr, pidbuf, VG_(strlen)(pidbuf));
373 bufptr += VG_(strlen)(pidbuf);
374 cmdptr++;
375 break;
376 default:
377 *bufptr++ = *cmdptr++;
378 break;
379 }
380 break;
381 default:
382 *bufptr++ = *cmdptr++;
383 break;
384 }
385 }
386
387 *bufptr++ = '\0';
388
389 VG_(message)(Vg_UserMsg, "starting debugger with cmd: %s", buf);
nethercote71980f02004-01-24 18:18:54 +0000390 res = VG_(system)(buf);
391 if (res == 0) {
392 VG_(message)(Vg_UserMsg, "");
393 VG_(message)(Vg_UserMsg,
nethercote04d0fbc2004-01-26 16:48:06 +0000394 "Debugger has detached. Valgrind regains control. We continue.");
nethercote71980f02004-01-24 18:18:54 +0000395 } else {
396 VG_(message)(Vg_UserMsg, "Apparently failed!");
397 VG_(message)(Vg_UserMsg, "");
398 }
399 }
400
401 VG_(kkill)(pid, VKI_SIGKILL);
402 VG_(waitpid)(pid, &status, 0);
403 }
404}
405
406
407/* Print some helpful-ish text about unimplemented things, and give
408 up. */
409void VG_(unimplemented) ( Char* msg )
410{
411 VG_(message)(Vg_UserMsg, "");
412 VG_(message)(Vg_UserMsg,
413 "Valgrind detected that your program requires");
414 VG_(message)(Vg_UserMsg,
415 "the following unimplemented functionality:");
416 VG_(message)(Vg_UserMsg, " %s", msg);
417 VG_(message)(Vg_UserMsg,
418 "This may be because the functionality is hard to implement,");
419 VG_(message)(Vg_UserMsg,
420 "or because no reasonable program would behave this way,");
421 VG_(message)(Vg_UserMsg,
422 "or because nobody has yet needed it. In any case, let us know at");
423 VG_(message)(Vg_UserMsg,
424 "%s and/or try to work around the problem, if you can.", VG_BUGS_TO);
425 VG_(message)(Vg_UserMsg,
426 "");
427 VG_(message)(Vg_UserMsg,
428 "Valgrind has to exit now. Sorry. Bye!");
429 VG_(message)(Vg_UserMsg,
430 "");
431 VG_(pp_sched_status)();
432 VG_(exit)(1);
433}
434
435Addr VG_(get_stack_pointer) ( void )
436{
437 return VG_(baseBlock)[VGOFF_(m_esp)];
438}
439
440/* Debugging thing .. can be called from assembly with OYNK macro. */
441void VG_(oynk) ( Int n )
442{
443 OINK(n);
444}
445
446/* Initialize the PID and PGRP of scheduler LWP; this is also called
447 in any new children after fork. */
448static void newpid(ThreadId unused)
449{
450 /* PID of scheduler LWP */
451 VG_(main_pid) = VG_(getpid)();
452 VG_(main_pgrp) = VG_(getpgrp)();
453}
454
455/*====================================================================*/
456/*=== Check we were launched by stage 1 ===*/
457/*====================================================================*/
458
459/* Look for our AUXV table */
460static void scan_auxv(void)
461{
462 const struct ume_auxv *auxv = find_auxv((int *)ume_exec_esp);
463 int found = 0;
464
465 for (; auxv->a_type != AT_NULL; auxv++)
466 switch(auxv->a_type) {
467 case AT_UME_PADFD:
468 as_setpadfd(auxv->u.a_val);
469 found |= 1;
470 break;
471
472 case AT_UME_EXECFD:
473 VG_(vgexecfd) = auxv->u.a_val;
474 found |= 2;
475 break;
476 }
477
478 if ( ! (1|2) ) {
479 fprintf(stderr, "stage2 must be launched by stage1\n");
480 exit(127);
481 }
482}
483
484
485/*====================================================================*/
486/*=== Address space determination ===*/
487/*====================================================================*/
488
489/* Pad client space so it doesn't get filled in before the right time */
490static void layout_client_space(Addr argc_addr)
491{
492 VG_(client_base) = CLIENT_BASE;
493 VG_(valgrind_mmap_end) = (addr_t)&kickstart_base; /* end of V's mmaps */
494 VG_(valgrind_base) = VG_(valgrind_mmap_end) - VALGRIND_MAPSIZE;
495 VG_(valgrind_end) = ROUNDUP(argc_addr, 0x10000); /* stack */
496
497 if (0)
498 printf("client base: %x\n"
499 "valgrind base--end: %x--%x (%x)\n"
500 "valgrind mmap end: %x\n\n",
501 VG_(client_base),
502 VG_(valgrind_base), VG_(valgrind_end),
503 VG_(valgrind_end) - VG_(valgrind_base),
504 VG_(valgrind_mmap_end));
505
506 as_pad((void *)VG_(client_base), (void *)VG_(valgrind_base));
507}
508
509static void layout_remaining_space(float ratio)
510{
511 /* This tries to give the client as large as possible address space while
512 * taking into account the tool's shadow needs. */
513 addr_t client_size = ROUNDDN((VG_(valgrind_base) - REDZONE_SIZE) / (1. + ratio),
514 CLIENT_SIZE_MULTIPLE);
515 addr_t shadow_size = PGROUNDUP(client_size * ratio);
516
517 VG_(client_end) = VG_(client_base) + client_size;
518 VG_(client_mapbase) = PGROUNDDN((client_size/4)*3); /* where !FIXED mmap goes */
519 VG_(client_trampoline_code) = VG_(client_end) - VKI_BYTES_PER_PAGE;
520
521 VG_(shadow_base) = VG_(client_end) + REDZONE_SIZE;
522 VG_(shadow_end) = VG_(shadow_base) + shadow_size;
523
524 if (0)
525 printf("client base--end: %x--%x (%x)\n"
526 "client mapbase: %x\n"
527 "shadow base--end: %x--%x (%x)\n\n",
528 VG_(client_base), VG_(client_end), client_size,
529 VG_(client_mapbase),
530 VG_(shadow_base), VG_(shadow_end), shadow_size);
531
532 // Ban redzone
533 mmap((void *)VG_(client_end), REDZONE_SIZE, PROT_NONE,
534 MAP_FIXED|MAP_ANON|MAP_PRIVATE, -1, 0);
535
536 // Make client hole
537 munmap((void*)VG_(client_base), client_size);
538
539 // Map shadow memory.
540 // Initially all inaccessible, incrementally initialized as it is used
541 if (shadow_size != 0)
542 mmap((char *)VG_(shadow_base), shadow_size, PROT_NONE,
543 MAP_PRIVATE|MAP_ANON|MAP_FIXED, -1, 0);
544}
545
546/*====================================================================*/
547/*=== Command line setup ===*/
548/*====================================================================*/
549
550/* Nb: malloc'd memory never freed -- kept throughout like argv, envp */
551static char* get_file_clo(char* dir)
552{
553# define FLEN 512
554 Int fd, n;
555 struct stat s1;
556 char* f_clo = NULL;
557 char filename[FLEN];
558
559 snprintf(filename, FLEN, "%s/.valgrindrc", ( NULL == dir ? "" : dir ) );
560 fd = VG_(open)(filename, 0, VKI_S_IRUSR);
561 if ( fd > 0 ) {
562 if ( 0 == fstat(fd, &s1) ) {
563 f_clo = malloc(s1.st_size+1);
564 vg_assert(f_clo);
565 n = read(fd, f_clo, s1.st_size);
566 if (n == -1) n = 0;
567 f_clo[n] = '\0';
568 }
569 close(fd);
570 }
571 return f_clo;
572# undef FLEN
573}
574
575static Int count_args(char* s)
576{
577 Int n = 0;
578 if (s) {
579 char* cp = s;
580 while (True) {
581 // We have alternating sequences: blanks, non-blanks, blanks...
582 // count the non-blanks sequences.
583 while ( ISSPACE(*cp) ) cp++;
584 if ( !*cp ) break;
585 n++;
586 while ( !ISSPACE(*cp) && *cp ) cp++;
587 }
588 }
589 return n;
590}
591
592/* add args out of environment, skipping multiple spaces and -- args */
593static char** copy_args( char* s, char** to )
594{
595 if (s) {
596 char* cp = s;
597 while (True) {
598 // We have alternating sequences: blanks, non-blanks, blanks...
599 // copy the non-blanks sequences, and add terminating '\0'
600 while ( ISSPACE(*cp) ) cp++;
601 if ( !*cp ) break;
602 *to++ = cp;
603 while ( !ISSPACE(*cp) && *cp ) cp++;
604 if ( *cp ) *cp++ = '\0'; // terminate if necessary
605 if (VG_STREQ(to[-1], "--")) to--; // undo any '--' arg
606 }
607 }
608 return to;
609}
610
611// Augment command line with arguments from environment and .valgrindrc
612// files.
613static void augment_command_line(Int* vg_argc_inout, char*** vg_argv_inout)
614{
615 int vg_argc = *vg_argc_inout;
616 char** vg_argv = *vg_argv_inout;
617
618 char* env_clo = getenv(VALGRINDOPTS);
619 char* f1_clo = get_file_clo( getenv("HOME") );
620 char* f2_clo = get_file_clo(".");
621
622 /* copy any extra args from file or environment, if present */
623 if ( (env_clo && *env_clo) || (f1_clo && *f1_clo) || (f2_clo && *f2_clo) ) {
624 /* ' ' separated extra options */
625 char **from;
626 char **to;
627 int env_arg_count, f1_arg_count, f2_arg_count;
628
629 env_arg_count = count_args(env_clo);
630 f1_arg_count = count_args(f1_clo);
631 f2_arg_count = count_args(f2_clo);
632
633 if (0)
634 printf("extra-argc=%d %d %d\n",
635 env_arg_count, f1_arg_count, f2_arg_count);
636
637 /* +2: +1 for null-termination, +1 for added '--' */
638 from = vg_argv;
639 vg_argv = malloc( (vg_argc + env_arg_count + f1_arg_count
640 + f2_arg_count + 2) * sizeof(char **));
641 to = vg_argv;
642
643 /* copy argv[0] */
644 *to++ = *from++;
645
646 /* Copy extra args from env var and file, in the order: ~/.valgrindrc,
647 * $VALGRIND_OPTS, ./.valgrindrc -- more local options are put later
648 * to override less local ones. */
649 to = copy_args(f1_clo, to);
650 to = copy_args(env_clo, to);
651 to = copy_args(f2_clo, to);
652
653 /* copy original arguments, stopping at command or -- */
654 while (*from) {
655 if (**from != '-')
656 break;
657 if (VG_STREQ(*from, "--")) {
658 from++; /* skip -- */
659 break;
660 }
661 *to++ = *from++;
662 }
663
664 /* add -- */
665 *to++ = "--";
666
667 vg_argc = to - vg_argv;
668
669 /* copy rest of original command line, then NULL */
670 while (*from) *to++ = *from++;
671 *to = NULL;
672 }
673
674 *vg_argc_inout = vg_argc;
675 *vg_argv_inout = vg_argv;
676}
677
678static void get_command_line( int argc, char** argv,
679 Int* vg_argc_out, Char*** vg_argv_out,
680 char*** cl_argv_out )
681{
682 int vg_argc;
683 char** vg_argv;
684 char** cl_argv;
685 char* env_clo = getenv(VALGRINDCLO);
686
687 if (env_clo != NULL && *env_clo != '\0') {
688 char *cp;
689 char **cpp;
690
691 /* OK, we're getting all our arguments from the environment - the
692 entire command line belongs to the client (including argv[0]) */
693 vg_argc = 1; /* argv[0] */
694 for (cp = env_clo; *cp; cp++)
695 if (*cp == '\01')
696 vg_argc++;
697
698 vg_argv = malloc(sizeof(char **) * (vg_argc + 1));
699
700 cpp = vg_argv;
701
702 *cpp++ = "valgrind"; /* nominal argv[0] */
703 *cpp++ = env_clo;
704
705 for (cp = env_clo; *cp; cp++) {
706 if (*cp == '\01') {
707 *cp++ = '\0'; /* chop it up in place */
708 *cpp++ = cp;
709 }
710 }
711 *cpp = NULL;
712 cl_argv = argv;
713
714 } else {
715 /* Count the arguments on the command line. */
716 vg_argv = argv;
717
718 for (vg_argc = 1; vg_argc < argc; vg_argc++) {
719 if (argv[vg_argc][0] != '-') /* exe name */
720 break;
721 if (VG_STREQ(argv[vg_argc], "--")) { /* dummy arg */
722 vg_argc++;
723 break;
724 }
725 }
726 cl_argv = &argv[vg_argc];
727
728 /* Get extra args from VALGRIND_OPTS and .valgrindrc files.
729 * Note we don't do this if getting args from VALGRINDCLO. */
730 augment_command_line(&vg_argc, &vg_argv);
731 }
732
733 if (0) {
734 Int i;
735 for (i = 0; i < vg_argc; i++)
736 printf("vg_argv[%d]=\"%s\"\n", i, vg_argv[i]);
737 }
738
739 *vg_argc_out = vg_argc;
740 *vg_argv_out = (Char**)vg_argv;
741 *cl_argv_out = cl_argv;
742}
743
744
745/*====================================================================*/
746/*=== Environment and stack setup ===*/
747/*====================================================================*/
748
749/* Scan a colon-separated list, and call a function on each element.
750 The string must be mutable, because we insert a temporary '\0', but
751 the string will end up unmodified. (*func) should return 1 if it
752 doesn't need to see any more.
753*/
754static void scan_colsep(char *colsep, int (*func)(const char *))
755{
756 char *cp, *entry;
757 int end;
758
759 if (colsep == NULL ||
760 *colsep == '\0')
761 return;
762
763 entry = cp = colsep;
764
765 do {
766 end = (*cp == '\0');
767
768 if (*cp == ':' || *cp == '\0') {
769 char save = *cp;
770
771 *cp = '\0';
772 if ((*func)(entry))
773 end = 1;
774 *cp = save;
775 entry = cp+1;
776 }
777 cp++;
778 } while(!end);
779}
780
781/* Prepare the client's environment. This is basically a copy of our
782 environment, except:
783 1. LD_LIBRARY_PATH=$VALGRINDLIB:$LD_LIBRARY_PATH
784 2. LD_PRELOAD=$VALGRINDLIB/vg_inject.so:($VALGRINDLIB/vgpreload_TOOL.so:)?$LD_PRELOAD
785
786 If any of these is missing, then it is added.
787
788 Yummy. String hacking in C.
789
790 If this needs to handle any more variables it should be hacked
791 into something table driven.
792 */
793static char **fix_environment(char **origenv, const char *preload)
794{
795 static const char inject_so[] = "vg_inject.so";
796 static const char ld_library_path[] = "LD_LIBRARY_PATH=";
797 static const char ld_preload[] = "LD_PRELOAD=";
798 static const char valgrind_clo[] = VALGRINDCLO "=";
799 static const int ld_library_path_len = sizeof(ld_library_path)-1;
800 static const int ld_preload_len = sizeof(ld_preload)-1;
801 static const int valgrind_clo_len = sizeof(valgrind_clo)-1;
802 int ld_preload_done = 0;
803 int ld_library_path_done = 0;
804 char *inject_path;
805 int inject_path_len;
806 int vgliblen = strlen(VG_(libdir));
807 char **cpp;
808 char **ret;
809 int envc;
810 const int preloadlen = (preload == NULL) ? 0 : strlen(preload);
811
812 /* Find the vg_inject.so; also make room for the tool preload
813 library */
814 inject_path_len = sizeof(inject_so) + vgliblen + preloadlen + 16;
815 inject_path = malloc(inject_path_len);
816
817 if (preload)
818 snprintf(inject_path, inject_path_len, "%s/%s:%s",
819 VG_(libdir), inject_so, preload);
820 else
821 snprintf(inject_path, inject_path_len, "%s/%s",
822 VG_(libdir), inject_so);
823
824 /* Count the original size of the env */
825 envc = 0; /* trailing NULL */
826 for (cpp = origenv; cpp && *cpp; cpp++)
827 envc++;
828
829 /* Allocate a new space */
830 ret = malloc(sizeof(char *) * (envc+3+1)); /* 3 new entries + NULL */
831
832 /* copy it over */
833 for (cpp = ret; *origenv; )
834 *cpp++ = *origenv++;
835 *cpp = NULL;
836
837 vg_assert(envc == (cpp - ret));
838
839 /* Walk over the new environment, mashing as we go */
840 for (cpp = ret; cpp && *cpp; cpp++) {
841 if (memcmp(*cpp, ld_library_path, ld_library_path_len) == 0) {
842 int done = 0;
843 int contains(const char *p) {
844 if (VG_STREQ(p, VG_(libdir))) {
845 done = 1;
846 return 1;
847 }
848 return 0;
849 }
850
851 /* If the LD_LIBRARY_PATH already contains libdir, then don't
852 bother adding it again, even if it isn't the first (it
853 seems that the Java runtime will keep reexecing itself
854 unless its paths are at the front of LD_LIBRARY_PATH) */
855 scan_colsep(*cpp + ld_library_path_len, contains);
856
857 if (!done) {
858 int len = strlen(*cpp) + vgliblen*2 + 16;
859 char *cp = malloc(len);
860
861 snprintf(cp, len, "%s%s:%s",
862 ld_library_path, VG_(libdir),
863 (*cpp)+ld_library_path_len);
864
865 *cpp = cp;
866 }
867
868 ld_library_path_done = 1;
869 } else if (memcmp(*cpp, ld_preload, ld_preload_len) == 0) {
870 int len = strlen(*cpp) + inject_path_len;
871 char *cp = malloc(len);
872
873 snprintf(cp, len, "%s%s:%s",
874 ld_preload, inject_path, (*cpp)+ld_preload_len);
875
876 *cpp = cp;
877
878 ld_preload_done = 1;
879 } else if (memcmp(*cpp, valgrind_clo, valgrind_clo_len) == 0) {
880 *cpp = "";
881 }
882 }
883
884 /* Add the missing bits */
885
886 if (!ld_library_path_done) {
887 int len = ld_library_path_len + vgliblen*2 + 16;
888 char *cp = malloc(len);
889
890 snprintf(cp, len, "%s%s", ld_library_path, VG_(libdir));
891
892 ret[envc++] = cp;
893 }
894
895 if (!ld_preload_done) {
896 int len = ld_preload_len + inject_path_len;
897 char *cp = malloc(len);
898
899 snprintf(cp, len, "%s%s",
900 ld_preload, inject_path);
901
902 ret[envc++] = cp;
903 }
904
905 ret[envc] = NULL;
906
907 return ret;
908}
909
910extern char **environ; /* our environment */
911//#include <error.h>
912
913/* Add a string onto the string table, and return its address */
914static char *copy_str(char **tab, const char *str)
915{
916 char *cp = *tab;
917 char *orig = cp;
918
919 while(*str)
920 *cp++ = *str++;
921 *cp++ = '\0';
922
923 if (0)
924 printf("copied %p \"%s\" len %d\n",
925 orig, orig, cp-orig);
926
927 *tab = cp;
928
929 return orig;
930}
931
932/*
933 This sets up the client's initial stack, containing the args,
934 environment and aux vector.
935
936 The format of the stack is:
937
938 higher address +-----------------+
939 | Trampoline code |
940 +-----------------+
941 | |
942 : string table :
943 | |
944 +-----------------+
945 | AT_NULL |
946 - -
947 | auxv |
948 +-----------------+
949 | NULL |
950 - -
951 | envp |
952 +-----------------+
953 | NULL |
954 - -
955 | argv |
956 +-----------------+
957 | argc |
958 lower address +-----------------+ <- esp
959 | undefined |
960 : :
961 */
962static Addr setup_client_stack(char **orig_argv, char **orig_envp,
963 const struct exeinfo *info,
964 UInt** client_auxv)
965{
966 char **cpp;
967 char *strtab; /* string table */
968 char *stringbase;
969 addr_t *ptr;
970 struct ume_auxv *auxv;
971 const struct ume_auxv *orig_auxv;
972 const struct ume_auxv *cauxv;
973 unsigned stringsize; /* total size of strings in bytes */
974 unsigned auxsize; /* total size of auxv in bytes */
975 int argc; /* total argc */
976 int envc; /* total number of env vars */
977 unsigned stacksize; /* total client stack size */
978 addr_t cl_esp; /* client stack base (initial esp) */
979
980 /* use our own auxv as a prototype */
981 orig_auxv = find_auxv(ume_exec_esp);
982
983 /* ==================== compute sizes ==================== */
984
985 /* first of all, work out how big the client stack will be */
986 stringsize = 0;
987
988 /* paste on the extra args if the loader needs them (ie, the #!
989 interpreter and its argument) */
990 argc = 0;
991 if (info->argv0 != NULL) {
992 argc++;
993 stringsize += strlen(info->argv0) + 1;
994 }
995 if (info->argv1 != NULL) {
996 argc++;
997 stringsize += strlen(info->argv1) + 1;
998 }
999
1000 /* now scan the args we're given... */
1001 for (cpp = orig_argv; *cpp; cpp++) {
1002 argc++;
1003 stringsize += strlen(*cpp) + 1;
1004 }
1005
1006 /* ...and the environment */
1007 envc = 0;
1008 for (cpp = orig_envp; cpp && *cpp; cpp++) {
1009 envc++;
1010 stringsize += strlen(*cpp) + 1;
1011 }
1012
1013 /* now, how big is the auxv? */
1014 auxsize = sizeof(*auxv); /* there's always at least one entry: AT_NULL */
1015 for (cauxv = orig_auxv; cauxv->a_type != AT_NULL; cauxv++) {
1016 if (cauxv->a_type == AT_PLATFORM)
1017 stringsize += strlen(cauxv->u.a_ptr) + 1;
1018 auxsize += sizeof(*cauxv);
1019 }
1020
1021 /* OK, now we know how big the client stack is */
1022 stacksize =
1023 sizeof(int) + /* argc */
1024 sizeof(char **)*argc + /* argv */
1025 sizeof(char **) + /* terminal NULL */
1026 sizeof(char **)*envc + /* envp */
1027 sizeof(char **) + /* terminal NULL */
1028 auxsize + /* auxv */
1029 ROUNDUP(stringsize, sizeof(int)) +/* strings (aligned) */
1030 VKI_BYTES_PER_PAGE; /* page for trampoline code */
1031
1032 /* cl_esp is the client's stack pointer */
1033 cl_esp = VG_(client_end) - stacksize;
1034 cl_esp = ROUNDDN(cl_esp, 16); /* make stack 16 byte aligned */
1035
nethercote71980f02004-01-24 18:18:54 +00001036 /* base of the string table (aligned) */
1037 stringbase = strtab = (char *)(VG_(client_trampoline_code) - ROUNDUP(stringsize, sizeof(int)));
1038
1039 VG_(clstk_base) = PGROUNDDN(cl_esp);
1040 VG_(clstk_end) = VG_(client_end);
1041
nethercote5ee67ca2004-06-22 14:00:09 +00001042 if (0)
1043 printf("stringsize=%d auxsize=%d stacksize=%d\n"
1044 "clstk_base %x\n"
1045 "clstk_end %x\n",
1046 stringsize, auxsize, stacksize, VG_(clstk_base), VG_(clstk_end));
1047
1048
nethercote71980f02004-01-24 18:18:54 +00001049 /* ==================== allocate space ==================== */
1050
1051 /* allocate a stack - mmap enough space for the stack */
1052 mmap((void *)PGROUNDDN(cl_esp),
1053 VG_(client_end) - PGROUNDDN(cl_esp),
1054 PROT_READ | PROT_WRITE | PROT_EXEC,
1055 MAP_PRIVATE | MAP_ANON | MAP_FIXED, -1, 0);
1056
1057
1058 /* ==================== copy client stack ==================== */
1059
1060 ptr = (addr_t *)cl_esp;
1061
1062 /* --- argc --- */
1063 *ptr++ = argc; /* client argc */
1064
1065 /* --- argv --- */
1066 if (info->argv0) {
1067 *ptr++ = (addr_t)copy_str(&strtab, info->argv0);
1068 free(info->argv0);
1069 }
1070 if (info->argv1) {
1071 *ptr++ = (addr_t)copy_str(&strtab, info->argv1);
1072 free(info->argv1);
1073 }
1074 for (cpp = orig_argv; *cpp; ptr++, cpp++) {
1075 *ptr = (addr_t)copy_str(&strtab, *cpp);
1076 }
1077 *ptr++ = 0;
1078
1079 /* --- envp --- */
1080 VG_(client_envp) = (Char **)ptr;
1081 for (cpp = orig_envp; cpp && *cpp; ptr++, cpp++)
1082 *ptr = (addr_t)copy_str(&strtab, *cpp);
1083 *ptr++ = 0;
1084
1085 /* --- auxv --- */
1086 auxv = (struct ume_auxv *)ptr;
1087 *client_auxv = (UInt *)auxv;
1088
1089 for (; orig_auxv->a_type != AT_NULL; auxv++, orig_auxv++) {
1090 /* copy the entry... */
1091 *auxv = *orig_auxv;
1092
1093 /* ...and fix up the copy */
1094 switch(auxv->a_type) {
1095 case AT_PHDR:
1096 if (info->phdr == 0)
1097 auxv->a_type = AT_IGNORE;
1098 else
1099 auxv->u.a_val = info->phdr;
1100 break;
1101
1102 case AT_PHNUM:
1103 if (info->phdr == 0)
1104 auxv->a_type = AT_IGNORE;
1105 else
1106 auxv->u.a_val = info->phnum;
1107 break;
1108
1109 case AT_BASE:
1110 if (info->interp_base == 0)
1111 auxv->a_type = AT_IGNORE;
1112 else
1113 auxv->u.a_val = info->interp_base;
1114 break;
1115
1116 case AT_PLATFORM: /* points to a platform description string */
1117 auxv->u.a_ptr = copy_str(&strtab, orig_auxv->u.a_ptr);
1118 break;
1119
1120 case AT_ENTRY:
1121 auxv->u.a_val = info->entry;
1122 break;
1123
1124 case AT_IGNORE:
1125 case AT_EXECFD:
1126 case AT_PHENT:
1127 case AT_PAGESZ:
1128 case AT_FLAGS:
1129 case AT_NOTELF:
1130 case AT_UID:
1131 case AT_EUID:
1132 case AT_GID:
1133 case AT_EGID:
1134 case AT_CLKTCK:
1135 case AT_HWCAP:
1136 case AT_FPUCW:
1137 case AT_DCACHEBSIZE:
1138 case AT_ICACHEBSIZE:
1139 case AT_UCACHEBSIZE:
1140 /* All these are pointerless, so we don't need to do anything
1141 about them. */
1142 break;
1143
1144 case AT_SECURE:
1145 /* If this is 1, then it means that this program is running
1146 suid, and therefore the dynamic linker should be careful
1147 about LD_PRELOAD, etc. However, since stage1 (the thing
1148 the kernel actually execve's) should never be SUID, and we
1149 need LD_PRELOAD/LD_LIBRARY_PATH to work for the client, we
1150 set AT_SECURE to 0. */
1151 auxv->u.a_val = 0;
1152 break;
1153
1154 case AT_SYSINFO:
1155 /* Leave this unmolested for now, but we'll update it later
1156 when we set up the client trampoline code page */
1157 break;
1158
1159 case AT_SYSINFO_EHDR:
1160 /* Trash this, because we don't reproduce it */
1161 auxv->a_type = AT_IGNORE;
1162 break;
1163
1164 default:
1165 /* stomp out anything we don't know about */
1166 if (0)
1167 printf("stomping auxv entry %d\n", auxv->a_type);
1168 auxv->a_type = AT_IGNORE;
1169 break;
1170
1171 }
1172 }
1173 *auxv = *orig_auxv;
1174 vg_assert(auxv->a_type == AT_NULL);
1175
1176 vg_assert((strtab-stringbase) == stringsize);
1177
nethercote5ee67ca2004-06-22 14:00:09 +00001178 /* We know the initial ESP is pointing at argc/argv */
1179 VG_(client_argc) = *(Int*)cl_esp;
1180 VG_(client_argv) = (Char**)(cl_esp + sizeof(Int));
1181
nethercote71980f02004-01-24 18:18:54 +00001182 return cl_esp;
1183}
1184
1185/*====================================================================*/
1186/*=== Find executable ===*/
1187/*====================================================================*/
1188
1189static const char* find_executable(const char* exec)
1190{
1191 vg_assert(NULL != exec);
1192 if (strchr(exec, '/') == NULL) {
1193 /* no '/' - we need to search the path */
1194 char *path = getenv("PATH");
1195 int pathlen = path ? strlen(path) : 0;
1196
1197 int match_exe(const char *entry) {
1198 char buf[pathlen + strlen(entry) + 3];
1199
1200 /* empty PATH element means . */
1201 if (*entry == '\0')
1202 entry = ".";
1203
1204 snprintf(buf, sizeof(buf), "%s/%s", entry, exec);
1205
1206 if (access(buf, R_OK|X_OK) == 0) {
1207 exec = strdup(buf);
1208 vg_assert(NULL != exec);
1209 return 1;
1210 }
1211 return 0;
1212 }
1213 scan_colsep(path, match_exe);
1214 }
1215 return exec;
1216}
1217
1218
1219/*====================================================================*/
1220/*=== Loading tools ===*/
1221/*====================================================================*/
1222
1223static void list_tools(void)
1224{
1225 DIR *dir = opendir(VG_(libdir));
1226 struct dirent *de;
1227 int first = 1;
1228
1229 if (dir == NULL) {
1230 fprintf(stderr, "Can't open %s: %s (installation problem?)\n",
nethercotef4928da2004-06-15 10:54:40 +00001231 VG_(libdir), strerror(errno));
nethercote71980f02004-01-24 18:18:54 +00001232 return;
1233 }
1234
nethercotef4928da2004-06-15 10:54:40 +00001235 while ((de = readdir(dir)) != NULL) {
nethercote71980f02004-01-24 18:18:54 +00001236 int len = strlen(de->d_name);
1237
1238 /* look for vgskin_TOOL.so names */
1239 if (len > (7+1+3) && /* "vgskin_" + at least 1-char toolname + ".so" */
nethercotef4928da2004-06-15 10:54:40 +00001240 strncmp(de->d_name, "vgskin_", 7) == 0 &&
1241 VG_STREQ(de->d_name + len - 3, ".so")) {
1242 if (first) {
1243 fprintf(stderr, "Available tools:\n");
1244 first = 0;
1245 }
1246 de->d_name[len-3] = '\0';
1247 fprintf(stderr, "\t%s\n", de->d_name+7);
nethercote71980f02004-01-24 18:18:54 +00001248 }
1249 }
1250
1251 closedir(dir);
1252
1253 if (first)
nethercotef4928da2004-06-15 10:54:40 +00001254 fprintf(stderr, "No tools available in \"%s\" (installation problem?)\n",
1255 VG_(libdir));
nethercote71980f02004-01-24 18:18:54 +00001256}
1257
1258
1259/* Find and load a tool, and check it looks ok. Also looks to see if there's
1260 * a matching vgpreload_*.so file, and returns its name in *preloadpath. */
1261static void load_tool( const char *toolname, void** handle_out,
1262 ToolInfo** toolinfo_out, char **preloadpath_out )
1263{
1264 Bool ok;
1265 int len = strlen(VG_(libdir)) + strlen(toolname)*2 + 16;
1266 char buf[len];
1267 void* handle;
1268 ToolInfo* toolinfo;
1269 char* preloadpath = NULL;
1270 Int* vg_malloc_redzonep;
1271
1272 // XXX: allowing full paths for --tool option -- does it make sense?
1273 // Doesn't allow for vgpreload_<tool>.so.
1274
1275 if (strchr(toolname, '/') != 0) {
1276 /* toolname contains '/', and so must be a pathname */
1277 handle = dlopen(toolname, RTLD_NOW);
1278 } else {
1279 /* just try in the libdir */
1280 snprintf(buf, len, "%s/vgskin_%s.so", VG_(libdir), toolname);
1281 handle = dlopen(buf, RTLD_NOW);
1282
1283 if (handle != NULL) {
1284 snprintf(buf, len, "%s/vgpreload_%s.so", VG_(libdir), toolname);
1285 if (access(buf, R_OK) == 0) {
1286 preloadpath = strdup(buf);
1287 vg_assert(NULL != preloadpath);
1288 }
1289 }
1290 }
1291
1292 ok = (NULL != handle);
1293 if (!ok) {
1294 fprintf(stderr, "Can't open tool \"%s\": %s\n", toolname, dlerror());
1295 goto bad_load;
1296 }
1297
1298 toolinfo = dlsym(handle, "vgSkin_tool_info");
1299 ok = (NULL != toolinfo);
1300 if (!ok) {
1301 fprintf(stderr, "Tool \"%s\" doesn't define SK_(tool_info) - "
1302 "add VG_DETERMINE_INTERFACE_VERSION?\n", toolname);
1303 goto bad_load;
1304 }
1305
1306 ok = (toolinfo->sizeof_ToolInfo == sizeof(*toolinfo) &&
1307 toolinfo->interface_major_version == VG_CORE_INTERFACE_MAJOR_VERSION &&
1308 toolinfo->sk_pre_clo_init != NULL);
1309 if (!ok) {
1310 fprintf(stderr, "Error:\n"
1311 " Tool and core interface versions do not match.\n"
1312 " Interface version used by core is: %d.%d (size %d)\n"
1313 " Interface version used by tool is: %d.%d (size %d)\n"
1314 " The major version numbers must match.\n",
1315 VG_CORE_INTERFACE_MAJOR_VERSION,
1316 VG_CORE_INTERFACE_MINOR_VERSION,
1317 sizeof(*toolinfo),
1318 toolinfo->interface_major_version,
1319 toolinfo->interface_minor_version,
1320 toolinfo->sizeof_ToolInfo);
1321 fprintf(stderr, " You need to at least recompile, and possibly update,\n");
1322 if (VG_CORE_INTERFACE_MAJOR_VERSION > toolinfo->interface_major_version)
1323 fprintf(stderr, " your skin to work with this version of Valgrind.\n");
1324 else
1325 fprintf(stderr, " your version of Valgrind to work with this skin.\n");
1326 goto bad_load;
1327 }
1328
1329 // Set redzone size for V's allocator
1330 vg_malloc_redzonep = dlsym(handle, STR(VG_(vg_malloc_redzone_szB)));
1331 if ( NULL != vg_malloc_redzonep ) {
1332 VG_(vg_malloc_redzone_szB) = *vg_malloc_redzonep;
1333 }
1334
1335 vg_assert(NULL != handle && NULL != toolinfo);
1336 *handle_out = handle;
1337 *toolinfo_out = toolinfo;
1338 *preloadpath_out = preloadpath;
1339 return;
1340
1341
1342 bad_load:
1343 if (handle != NULL)
1344 dlclose(handle);
1345
nethercotef4928da2004-06-15 10:54:40 +00001346 fprintf(stderr, "valgrind: couldn't load tool\n");
nethercote71980f02004-01-24 18:18:54 +00001347 list_tools();
1348 exit(127);
1349}
1350
nethercotef4928da2004-06-15 10:54:40 +00001351
1352/*====================================================================*/
1353/*=== Command line errors ===*/
1354/*====================================================================*/
1355
1356static void abort_msg ( void )
1357{
nethercotef8548672004-06-21 12:42:35 +00001358 VG_(clo_log_to) = VgLogTo_Fd;
1359 VG_(clo_log_fd) = 2; /* stderr */
nethercotef4928da2004-06-15 10:54:40 +00001360}
1361
1362void VG_(bad_option) ( Char* opt )
1363{
1364 abort_msg();
1365 VG_(printf)("valgrind: Bad option `%s'; aborting.\n", opt);
1366 VG_(printf)("valgrind: Use --help for more information.\n");
1367 VG_(exit)(1);
1368}
1369
1370static void missing_tool_option ( void )
1371{
1372 abort_msg();
1373 VG_(printf)("valgrind: Missing --tool option\n");
1374 list_tools();
1375 VG_(printf)("valgrind: Use --help for more information.\n");
1376 VG_(exit)(1);
1377}
1378
1379static void missing_prog ( void )
1380{
1381 abort_msg();
1382 VG_(printf)("valgrind: no program specified\n");
1383 VG_(printf)("valgrind: Use --help for more information.\n");
1384 VG_(exit)(1);
1385}
1386
1387static void config_error ( Char* msg )
1388{
1389 abort_msg();
1390 VG_(printf)("valgrind: Startup or configuration error:\n %s\n", msg);
1391 VG_(printf)("valgrind: Unable to start up properly. Giving up.\n");
1392 VG_(exit)(1);
1393}
1394
1395
nethercote71980f02004-01-24 18:18:54 +00001396/*====================================================================*/
1397/*=== Loading the client ===*/
1398/*====================================================================*/
1399
nethercotef4928da2004-06-15 10:54:40 +00001400static void load_client(char* cl_argv[], const char* exec, Int need_help,
nethercote71980f02004-01-24 18:18:54 +00001401 /*out*/struct exeinfo* info, /*out*/Addr* client_eip)
1402{
1403 // If they didn't specify an executable with --exec, and didn't specify
1404 // --help, then use client argv[0] (searching $PATH if necessary).
nethercotef4928da2004-06-15 10:54:40 +00001405 if (NULL == exec && !need_help) {
nethercote71980f02004-01-24 18:18:54 +00001406 if (cl_argv[0] == NULL ||
1407 ( NULL == (exec = find_executable(cl_argv[0])) ) )
1408 {
nethercotef4928da2004-06-15 10:54:40 +00001409 missing_prog();
nethercote71980f02004-01-24 18:18:54 +00001410 }
1411 }
1412
1413 info->map_base = VG_(client_mapbase);
nethercote71980f02004-01-24 18:18:54 +00001414
1415 info->exe_base = VG_(client_base);
1416 info->exe_end = VG_(client_end);
1417 info->argv = cl_argv;
1418
nethercotef4928da2004-06-15 10:54:40 +00001419 if (need_help) {
nethercote71980f02004-01-24 18:18:54 +00001420 VG_(clexecfd) = -1;
1421 info->argv0 = NULL;
1422 info->argv1 = NULL;
1423 } else {
1424 Int ret;
1425 VG_(clexecfd) = VG_(open)(exec, O_RDONLY, VKI_S_IRUSR);
1426 ret = do_exec(exec, info);
1427 if (ret != 0) {
nethercotef4928da2004-06-15 10:54:40 +00001428 fprintf(stderr, "valgrind: do_exec(%s) failed: %s\n", exec, strerror(ret));
nethercote71980f02004-01-24 18:18:54 +00001429 exit(127);
1430 }
1431 }
1432
1433 /* Copy necessary bits of 'info' that were filled in */
1434 *client_eip = info->init_eip;
1435 VG_(brk_base) = VG_(brk_limit) = info->brkbase;
1436}
1437
1438
1439/*====================================================================*/
1440/*=== Command-line: variables, processing ===*/
1441/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +00001442
njn25e49d8e72002-09-23 09:36:25 +00001443/* Define, and set defaults. */
1444Bool VG_(clo_error_limit) = True;
nethercote04d0fbc2004-01-26 16:48:06 +00001445Bool VG_(clo_db_attach) = False;
1446Char* VG_(clo_db_command) = VG_CLO_DEFAULT_DBCOMMAND;
njn43c799e2003-04-08 00:08:52 +00001447Bool VG_(clo_gen_suppressions) = False;
nethercote27fec902004-06-16 21:26:32 +00001448Int VG_(clo_sanity_level) = 1;
njn25e49d8e72002-09-23 09:36:25 +00001449Int VG_(clo_verbosity) = 1;
1450Bool VG_(clo_demangle) = True;
njn25e49d8e72002-09-23 09:36:25 +00001451Bool VG_(clo_trace_children) = False;
sewardj4cf05692002-10-27 20:28:29 +00001452
nethercotee1730692003-11-20 10:38:07 +00001453/* See big comment in vg_include.h for meaning of these three.
1454 fd is initially stdout, for --help, but gets moved to stderr by default
1455 immediately afterwards. */
sewardj4cf05692002-10-27 20:28:29 +00001456VgLogTo VG_(clo_log_to) = VgLogTo_Fd;
nethercotef8548672004-06-21 12:42:35 +00001457Int VG_(clo_log_fd) = 1;
1458Char* VG_(clo_log_name) = NULL;
sewardj4cf05692002-10-27 20:28:29 +00001459
sewardj6024b212003-07-13 10:54:33 +00001460Int VG_(clo_input_fd) = 0; /* stdin */
njn25e49d8e72002-09-23 09:36:25 +00001461Int VG_(clo_n_suppressions) = 0;
sewardjde4a1d02002-03-22 01:27:54 +00001462Char* VG_(clo_suppressions)[VG_CLO_MAX_SFILES];
njn25e49d8e72002-09-23 09:36:25 +00001463Bool VG_(clo_profile) = False;
1464Bool VG_(clo_single_step) = False;
1465Bool VG_(clo_optimise) = True;
1466UChar VG_(clo_trace_codegen) = 0; // 00000000b
1467Bool VG_(clo_trace_syscalls) = False;
1468Bool VG_(clo_trace_signals) = False;
1469Bool VG_(clo_trace_symtab) = False;
njn25e49d8e72002-09-23 09:36:25 +00001470Bool VG_(clo_trace_sched) = False;
1471Int VG_(clo_trace_pthread_level) = 0;
njn25e49d8e72002-09-23 09:36:25 +00001472Int VG_(clo_dump_error) = 0;
1473Int VG_(clo_backtrace_size) = 4;
1474Char* VG_(clo_weird_hacks) = NULL;
sewardj858964b2002-10-05 14:15:43 +00001475Bool VG_(clo_run_libc_freeres) = True;
rjwalshf5f536f2003-11-17 17:45:00 +00001476Bool VG_(clo_track_fds) = False;
sewardj22854b92002-11-30 14:00:47 +00001477Bool VG_(clo_chain_bb) = True;
nethercote77eba602003-11-13 17:35:04 +00001478Bool VG_(clo_show_below_main) = False;
fitzhardinge98abfc72003-12-16 02:05:15 +00001479Bool VG_(clo_pointercheck) = True;
fitzhardinge462f4f92003-12-18 02:10:54 +00001480Bool VG_(clo_branchpred) = False;
sewardj2370f3b2002-11-30 15:01:01 +00001481
jsgf855d93d2003-10-13 22:26:55 +00001482static Bool VG_(clo_wait_for_gdb) = False;
1483
1484/* If we're doing signal routing, poll for signals every 50mS by
1485 default. */
1486Int VG_(clo_signal_polltime) = 50;
1487
1488/* These flags reduce thread wakeup latency on syscall completion and
1489 signal delivery, respectively. The downside is possible unfairness. */
1490Bool VG_(clo_lowlat_syscalls) = False; /* low-latency syscalls */
1491Bool VG_(clo_lowlat_signals) = False; /* low-latency signals */
1492
sewardjde4a1d02002-03-22 01:27:54 +00001493
nethercote6c999f22004-01-31 22:55:15 +00001494void usage ( Bool debug_help )
njn7cf0bd32002-06-08 13:36:03 +00001495{
njn25e49d8e72002-09-23 09:36:25 +00001496 Char* usage1 =
nethercote71980f02004-01-24 18:18:54 +00001497"usage: valgrind --tool=<toolname> [options] prog-and-args\n"
njn25e49d8e72002-09-23 09:36:25 +00001498"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001499" common user options for all Valgrind tools, with defaults in [ ]:\n"
nethercote0d588502004-06-21 13:27:11 +00001500" --tool=<name> use the Valgrind tool named <name>\n"
nethercotea76368b2004-06-16 11:56:29 +00001501" -h --help show this message\n"
nethercote6c999f22004-01-31 22:55:15 +00001502" --help-debug show this message, plus debugging options\n"
njn25e49d8e72002-09-23 09:36:25 +00001503" --version show version\n"
njn25e49d8e72002-09-23 09:36:25 +00001504" -q --quiet run silently; only print error msgs\n"
1505" -v --verbose be more verbose, incl counts of errors\n"
nethercote77eba602003-11-13 17:35:04 +00001506" --trace-children=no|yes Valgrind-ise child processes? [no]\n"
nethercote0d588502004-06-21 13:27:11 +00001507" --track-fds=no|yes track open file descriptors? [no]\n"
nethercote2b0793f2003-12-02 10:41:18 +00001508"\n"
1509" uncommon user options for all Valgrind tools:\n"
nethercote0d588502004-06-21 13:27:11 +00001510" --run-libc-freeres=no|yes free up glibc memory at exit? [yes]\n"
1511" --weird-hacks=hack1,hack2,... recognised hacks: lax-ioctls [none]\n"
1512" --signal-polltime=<time> signal poll period (mS) for older kernels [50]\n"
1513" --lowlat-signals=no|yes improve thread signal wake-up latency [no]\n"
1514" --lowlat-syscalls=no|yes improve thread syscall wake-up latency [no]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001515" --pointercheck=no|yes enforce client address space limits [yes]\n"
njn25e49d8e72002-09-23 09:36:25 +00001516"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001517" user options for Valgrind tools that report errors:\n"
nethercotef8548672004-06-21 12:42:35 +00001518" --log-fd=<number> log messages to file descriptor [2=stderr]\n"
1519" --log-file=<file> log messages to <file>.pid<pid>\n"
1520" --log-socket=ipaddr:port log messages to socket ipaddr:port\n"
nethercote2b0793f2003-12-02 10:41:18 +00001521" --demangle=no|yes automatically demangle C++ names? [yes]\n"
1522" --num-callers=<number> show <num> callers in stack traces [4]\n"
1523" --error-limit=no|yes stop showing new errors if too many? [yes]\n"
1524" --show-below-main=no|yes continue stack traces below main() [no]\n"
1525" --suppressions=<filename> suppress errors described in <filename>\n"
1526" --gen-suppressions=no|yes print suppressions for errors detected [no]\n"
nethercote04d0fbc2004-01-26 16:48:06 +00001527" --db-attach=no|yes start debugger when errors detected? [no]\n"
1528" --db-command=<command> command to start debugger [gdb -nw %%f %%p]\n"
1529" --input-fd=<number> file descriptor for input [0=stdin]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001530"\n";
njn7cf0bd32002-06-08 13:36:03 +00001531
njn25e49d8e72002-09-23 09:36:25 +00001532 Char* usage2 =
1533"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001534" debugging options for all Valgrind tools:\n"
njn25e49d8e72002-09-23 09:36:25 +00001535" --sanity-level=<number> level of sanity checking to do [1]\n"
1536" --single-step=no|yes translate each instr separately? [no]\n"
1537" --optimise=no|yes improve intermediate code? [yes]\n"
nethercote137bc552003-11-14 17:47:54 +00001538" --profile=no|yes profile? (tool must be built for it) [no]\n"
sewardj22854b92002-11-30 14:00:47 +00001539" --chain-bb=no|yes do basic-block chaining? [yes]\n"
fitzhardinge462f4f92003-12-18 02:10:54 +00001540" --branchpred=yes|no generate branch prediction hints [no]\n"
njn25e49d8e72002-09-23 09:36:25 +00001541" --trace-codegen=<XXXXX> show generated code? (X = 0|1) [00000]\n"
1542" --trace-syscalls=no|yes show all system calls? [no]\n"
1543" --trace-signals=no|yes show signal handling details? [no]\n"
1544" --trace-symtab=no|yes show symbol table details? [no]\n"
njn25e49d8e72002-09-23 09:36:25 +00001545" --trace-sched=no|yes show thread scheduler details? [no]\n"
njn3e884182003-04-15 13:03:23 +00001546" --trace-pthread=none|some|all show pthread event details? [none]\n"
jsgf855d93d2003-10-13 22:26:55 +00001547" --wait-for-gdb=yes|no pause on startup to wait for gdb attach\n"
njn25e49d8e72002-09-23 09:36:25 +00001548"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001549" debugging options for Valgrind tools that report errors\n"
1550" --dump-error=<number> show translation for basic block associated\n"
1551" with <number>'th error context [0=show none]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001552"\n";
njn3e884182003-04-15 13:03:23 +00001553
1554 Char* usage3 =
1555"\n"
nethercote71980f02004-01-24 18:18:54 +00001556" Extra options read from ~/.valgrindrc, $VALGRIND_OPTS, ./.valgrindrc\n"
njn25e49d8e72002-09-23 09:36:25 +00001557"\n"
nethercotebb1c9912004-01-04 16:43:23 +00001558" Valgrind is Copyright (C) 2000-2004 Julian Seward\n"
njn25e49d8e72002-09-23 09:36:25 +00001559" and licensed under the GNU General Public License, version 2.\n"
1560" Bug reports, feedback, admiration, abuse, etc, to: %s.\n"
njnd04b7c62002-10-03 14:05:52 +00001561"\n"
nethercote137bc552003-11-14 17:47:54 +00001562" Tools are copyright and licensed by their authors. See each\n"
1563" tool's start-up message for more information.\n"
njn25e49d8e72002-09-23 09:36:25 +00001564"\n";
njn7cf0bd32002-06-08 13:36:03 +00001565
fitzhardinge98abfc72003-12-16 02:05:15 +00001566 VG_(printf)(usage1);
1567 if (VG_(details).name) {
1568 VG_(printf)(" user options for %s:\n", VG_(details).name);
fitzhardinge98abfc72003-12-16 02:05:15 +00001569 if (VG_(needs).command_line_options)
1570 SK_(print_usage)();
1571 else
1572 VG_(printf)(" (none)\n");
1573 }
nethercote6c999f22004-01-31 22:55:15 +00001574 if (debug_help) {
1575 VG_(printf)(usage2);
fitzhardinge98abfc72003-12-16 02:05:15 +00001576
nethercote6c999f22004-01-31 22:55:15 +00001577 if (VG_(details).name) {
1578 VG_(printf)(" debugging options for %s:\n", VG_(details).name);
1579
1580 if (VG_(needs).command_line_options)
1581 SK_(print_debug_usage)();
1582 else
1583 VG_(printf)(" (none)\n");
1584 }
fitzhardinge98abfc72003-12-16 02:05:15 +00001585 }
nethercote421281e2003-11-20 16:20:55 +00001586 VG_(printf)(usage3, VG_BUGS_TO);
nethercotef4928da2004-06-15 10:54:40 +00001587 VG_(exit)(0);
njn7cf0bd32002-06-08 13:36:03 +00001588}
sewardjde4a1d02002-03-22 01:27:54 +00001589
nethercote71980f02004-01-24 18:18:54 +00001590static void pre_process_cmd_line_options
nethercote6c999f22004-01-31 22:55:15 +00001591 ( Int* need_help, const char** tool, const char** exec )
sewardj1c1b1162003-02-23 01:25:51 +00001592{
nethercote71980f02004-01-24 18:18:54 +00001593 UInt i;
sewardjde4a1d02002-03-22 01:27:54 +00001594
nethercote71980f02004-01-24 18:18:54 +00001595 /* parse the options we have (only the options we care about now) */
1596 for (i = 1; i < VG_(vg_argc); i++) {
1597
1598 if (strcmp(VG_(vg_argv)[i], "--version") == 0) {
1599 printf("valgrind-" VERSION "\n");
nethercotef4928da2004-06-15 10:54:40 +00001600 exit(0);
nethercote71980f02004-01-24 18:18:54 +00001601
nethercotea76368b2004-06-16 11:56:29 +00001602 } else if (VG_CLO_STREQ(VG_(vg_argv)[i], "--help") ||
1603 VG_CLO_STREQ(VG_(vg_argv)[i], "-h")) {
nethercote6c999f22004-01-31 22:55:15 +00001604 *need_help = 1;
1605
nethercotef4928da2004-06-15 10:54:40 +00001606 } else if (VG_CLO_STREQ(VG_(vg_argv)[i], "--help-debug")) {
nethercote6c999f22004-01-31 22:55:15 +00001607 *need_help = 2;
nethercote71980f02004-01-24 18:18:54 +00001608
nethercotef4928da2004-06-15 10:54:40 +00001609 } else if (VG_CLO_STREQN(7, VG_(vg_argv)[i], "--tool=") ||
1610 VG_CLO_STREQN(7, VG_(vg_argv)[i], "--skin=")) {
nethercote71980f02004-01-24 18:18:54 +00001611 *tool = &VG_(vg_argv)[i][7];
1612
nethercotef4928da2004-06-15 10:54:40 +00001613 } else if (VG_CLO_STREQN(7, VG_(vg_argv)[i], "--exec=")) {
nethercote71980f02004-01-24 18:18:54 +00001614 *exec = &VG_(vg_argv)[i][7];
1615 }
1616 }
1617
nethercotef4928da2004-06-15 10:54:40 +00001618 /* If no tool specified, can act appropriately without loading tool */
nethercote71980f02004-01-24 18:18:54 +00001619 if (*tool == NULL) {
nethercotef4928da2004-06-15 10:54:40 +00001620 if (0 == *need_help) {
1621 // neither --tool nor --help/--help-debug specified
1622 missing_tool_option();
1623 } else {
1624 // Give help message, without any tool-specific help
1625 usage(/*help-debug?*/2 == *need_help);
1626 }
nethercote71980f02004-01-24 18:18:54 +00001627 }
1628}
1629
nethercote5ee67ca2004-06-22 14:00:09 +00001630static void process_cmd_line_options( UInt* client_auxv, const char* toolname )
nethercote71980f02004-01-24 18:18:54 +00001631{
nethercotef8548672004-06-21 12:42:35 +00001632 Int i, eventually_log_fd;
nethercote71980f02004-01-24 18:18:54 +00001633 Int *auxp;
1634 Int toolname_len = VG_(strlen)(toolname);
sewardjde4a1d02002-03-22 01:27:54 +00001635
nethercotee1730692003-11-20 10:38:07 +00001636 /* log to stderr by default, but usage message goes to stdout */
nethercotef8548672004-06-21 12:42:35 +00001637 eventually_log_fd = 2;
sewardjde4a1d02002-03-22 01:27:54 +00001638
sewardj19d81412002-06-03 01:10:40 +00001639 /* Check for sane path in ./configure --prefix=... */
fitzhardinge98abfc72003-12-16 02:05:15 +00001640 if (VG_LIBDIR[0] != '/')
sewardj19d81412002-06-03 01:10:40 +00001641 config_error("Please use absolute paths in "
1642 "./configure --prefix=... or --libdir=...");
sewardj38170912002-05-10 21:07:22 +00001643
nethercote71980f02004-01-24 18:18:54 +00001644 for (auxp = client_auxv; auxp[0] != VKI_AT_NULL; auxp += 2) {
fitzhardinge98abfc72003-12-16 02:05:15 +00001645 switch(auxp[0]) {
1646 case VKI_AT_SYSINFO:
1647 VG_(sysinfo_page_exists) = True;
fitzhardinge92360792003-12-24 10:11:11 +00001648 auxp[1] = (Int)(VG_(client_trampoline_code) + VG_(tramp_syscall_offset));
fitzhardinge98abfc72003-12-16 02:05:15 +00001649 VG_(sysinfo_page_addr) = auxp[1];
1650 break;
sewardjde4a1d02002-03-22 01:27:54 +00001651 }
fitzhardinge98abfc72003-12-16 02:05:15 +00001652 }
sewardjde4a1d02002-03-22 01:27:54 +00001653
nethercote71980f02004-01-24 18:18:54 +00001654 for (i = 1; i < VG_(vg_argc); i++) {
1655
1656 Char* arg = VG_(vg_argv)[i];
1657
1658 // XXX: allow colons in options, for Josef
1659
1660 /* Look for matching "--toolname:foo" */
1661 if (VG_(strstr)(arg, ":")) {
1662 if (VG_CLO_STREQN(2, arg, "--") &&
1663 VG_CLO_STREQN(toolname_len, arg+2, toolname) &&
1664 VG_CLO_STREQN(1, arg+2+toolname_len, ":"))
1665 {
1666 // prefix matches, convert "--toolname:foo" to "--foo"
1667 if (0)
1668 VG_(printf)("tool-specific arg: %s\n", arg);
1669 arg += toolname_len + 1;
1670 arg[0] = '-';
1671 arg[1] = '-';
1672
1673 } else {
1674 // prefix doesn't match, skip to next arg
1675 continue;
1676 }
1677 }
1678
fitzhardinge98abfc72003-12-16 02:05:15 +00001679 /* Ignore these options - they've already been handled */
nethercote71980f02004-01-24 18:18:54 +00001680 if (VG_CLO_STREQN(7, arg, "--tool=") ||
1681 VG_CLO_STREQN(7, arg, "--skin="))
fitzhardinge98abfc72003-12-16 02:05:15 +00001682 continue;
nethercote71980f02004-01-24 18:18:54 +00001683 if (VG_CLO_STREQN(7, arg, "--exec="))
fitzhardinge98abfc72003-12-16 02:05:15 +00001684 continue;
1685
nethercote71980f02004-01-24 18:18:54 +00001686 if ( VG_CLO_STREQ(arg, "--"))
fitzhardinge98abfc72003-12-16 02:05:15 +00001687 continue;
nethercote27fec902004-06-16 21:26:32 +00001688
nethercote71980f02004-01-24 18:18:54 +00001689 else if (VG_CLO_STREQ(arg, "-v") ||
1690 VG_CLO_STREQ(arg, "--verbose"))
sewardjde4a1d02002-03-22 01:27:54 +00001691 VG_(clo_verbosity)++;
nethercote27fec902004-06-16 21:26:32 +00001692
nethercote71980f02004-01-24 18:18:54 +00001693 else if (VG_CLO_STREQ(arg, "-q") ||
1694 VG_CLO_STREQ(arg, "--quiet"))
sewardjde4a1d02002-03-22 01:27:54 +00001695 VG_(clo_verbosity)--;
1696
nethercote27fec902004-06-16 21:26:32 +00001697 else VG_BOOL_CLO("--branchpred", VG_(clo_branchpred))
1698 else VG_BOOL_CLO("--chain-bb", VG_(clo_chain_bb))
1699 else VG_BOOL_CLO("--db-attach", VG_(clo_db_attach))
1700 else VG_BOOL_CLO("--demangle", VG_(clo_demangle))
1701 else VG_BOOL_CLO("--error-limit", VG_(clo_error_limit))
1702 else VG_BOOL_CLO("--gen-suppressions", VG_(clo_gen_suppressions))
1703 else VG_BOOL_CLO("--lowlat-signals", VG_(clo_lowlat_signals))
1704 else VG_BOOL_CLO("--lowlat-syscalls", VG_(clo_lowlat_syscalls))
1705 else VG_BOOL_CLO("--optimise", VG_(clo_optimise))
1706 else VG_BOOL_CLO("--pointercheck", VG_(clo_pointercheck))
1707 else VG_BOOL_CLO("--profile", VG_(clo_profile))
1708 else VG_BOOL_CLO("--run-libc-freeres", VG_(clo_run_libc_freeres))
1709 else VG_BOOL_CLO("--show-below-main", VG_(clo_show_below_main))
1710 else VG_BOOL_CLO("--single-step", VG_(clo_single_step))
1711 else VG_BOOL_CLO("--track-fds", VG_(clo_track_fds))
1712 else VG_BOOL_CLO("--trace-children", VG_(clo_trace_children))
1713 else VG_BOOL_CLO("--trace-sched", VG_(clo_trace_sched))
1714 else VG_BOOL_CLO("--trace-signals", VG_(clo_trace_signals))
1715 else VG_BOOL_CLO("--trace-symtab", VG_(clo_trace_symtab))
1716 else VG_BOOL_CLO("--trace-syscalls", VG_(clo_trace_syscalls))
1717 else VG_BOOL_CLO("--wait-for-gdb", VG_(clo_wait_for_gdb))
sewardj72f98ff2002-06-13 17:23:38 +00001718
nethercote27fec902004-06-16 21:26:32 +00001719 else VG_STR_CLO ("--db-command", VG_(clo_db_command))
1720 else VG_STR_CLO ("--weird-hacks", VG_(clo_weird_hacks))
sewardjde4a1d02002-03-22 01:27:54 +00001721
nethercote27fec902004-06-16 21:26:32 +00001722 else VG_NUM_CLO ("--dump-error", VG_(clo_dump_error))
1723 else VG_NUM_CLO ("--input-fd", VG_(clo_input_fd))
1724 else VG_NUM_CLO ("--sanity-level", VG_(clo_sanity_level))
1725 else VG_NUM_CLO ("--signal­polltime", VG_(clo_signal_polltime))
1726 else VG_BNUM_CLO("--num-callers", VG_(clo_backtrace_size), 1,
1727 VG_DEEPEST_BACKTRACE)
sewardjde4a1d02002-03-22 01:27:54 +00001728
nethercotef8548672004-06-21 12:42:35 +00001729 // for backwards compatibility, replaced by --log-fd
nethercote71980f02004-01-24 18:18:54 +00001730 else if (VG_CLO_STREQN(13, arg, "--logfile-fd=")) {
nethercotef8548672004-06-21 12:42:35 +00001731 VG_(clo_log_to) = VgLogTo_Fd;
1732 VG_(clo_log_name) = NULL;
1733 eventually_log_fd = (Int)VG_(atoll)(&arg[13]);
1734 }
1735 else if (VG_CLO_STREQN(9, arg, "--log-fd=")) {
1736 VG_(clo_log_to) = VgLogTo_Fd;
1737 VG_(clo_log_name) = NULL;
1738 eventually_log_fd = (Int)VG_(atoll)(&arg[9]);
sewardj4cf05692002-10-27 20:28:29 +00001739 }
1740
nethercotef8548672004-06-21 12:42:35 +00001741 // for backwards compatibility, replaced by --log-file
nethercote71980f02004-01-24 18:18:54 +00001742 else if (VG_CLO_STREQN(10, arg, "--logfile=")) {
nethercotef8548672004-06-21 12:42:35 +00001743 VG_(clo_log_to) = VgLogTo_File;
1744 VG_(clo_log_name) = &arg[10];
1745 }
1746 else if (VG_CLO_STREQN(11, arg, "--log-file=")) {
1747 VG_(clo_log_to) = VgLogTo_File;
1748 VG_(clo_log_name) = &arg[11];
sewardj4cf05692002-10-27 20:28:29 +00001749 }
sewardjde4a1d02002-03-22 01:27:54 +00001750
nethercotef8548672004-06-21 12:42:35 +00001751 // for backwards compatibility, replaced by --log-socket
nethercote71980f02004-01-24 18:18:54 +00001752 else if (VG_CLO_STREQN(12, arg, "--logsocket=")) {
nethercotef8548672004-06-21 12:42:35 +00001753 VG_(clo_log_to) = VgLogTo_Socket;
1754 VG_(clo_log_name) = &arg[12];
1755 }
1756 else if (VG_CLO_STREQN(13, arg, "--log-socket=")) {
1757 VG_(clo_log_to) = VgLogTo_Socket;
1758 VG_(clo_log_name) = &arg[13];
sewardj73cf3bc2002-11-03 03:20:15 +00001759 }
1760
nethercote71980f02004-01-24 18:18:54 +00001761 else if (VG_CLO_STREQN(15, arg, "--suppressions=")) {
sewardjde4a1d02002-03-22 01:27:54 +00001762 if (VG_(clo_n_suppressions) >= VG_CLO_MAX_SFILES) {
njn25e49d8e72002-09-23 09:36:25 +00001763 VG_(message)(Vg_UserMsg, "Too many suppression files specified.");
sewardjde4a1d02002-03-22 01:27:54 +00001764 VG_(message)(Vg_UserMsg,
1765 "Increase VG_CLO_MAX_SFILES and recompile.");
nethercote71980f02004-01-24 18:18:54 +00001766 VG_(bad_option)(arg);
sewardjde4a1d02002-03-22 01:27:54 +00001767 }
nethercote71980f02004-01-24 18:18:54 +00001768 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = &arg[15];
sewardjde4a1d02002-03-22 01:27:54 +00001769 VG_(clo_n_suppressions)++;
1770 }
sewardjde4a1d02002-03-22 01:27:54 +00001771
njn25e49d8e72002-09-23 09:36:25 +00001772 /* "vwxyz" --> 000zyxwv (binary) */
nethercote71980f02004-01-24 18:18:54 +00001773 else if (VG_CLO_STREQN(16, arg, "--trace-codegen=")) {
njn25e49d8e72002-09-23 09:36:25 +00001774 Int j;
nethercote71980f02004-01-24 18:18:54 +00001775 char* opt = & arg[16];
njn25e49d8e72002-09-23 09:36:25 +00001776
1777 if (5 != VG_(strlen)(opt)) {
1778 VG_(message)(Vg_UserMsg,
1779 "--trace-codegen argument must have 5 digits");
nethercote71980f02004-01-24 18:18:54 +00001780 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001781 }
1782 for (j = 0; j < 5; j++) {
1783 if ('0' == opt[j]) { /* do nothing */ }
1784 else if ('1' == opt[j]) VG_(clo_trace_codegen) |= (1 << j);
1785 else {
1786 VG_(message)(Vg_UserMsg, "--trace-codegen argument can only "
1787 "contain 0s and 1s");
nethercote71980f02004-01-24 18:18:54 +00001788 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001789 }
1790 }
1791 }
sewardjde4a1d02002-03-22 01:27:54 +00001792
nethercote71980f02004-01-24 18:18:54 +00001793 else if (VG_CLO_STREQ(arg, "--trace-pthread=none"))
sewardj45b4b372002-04-16 22:50:32 +00001794 VG_(clo_trace_pthread_level) = 0;
nethercote71980f02004-01-24 18:18:54 +00001795 else if (VG_CLO_STREQ(arg, "--trace-pthread=some"))
sewardj45b4b372002-04-16 22:50:32 +00001796 VG_(clo_trace_pthread_level) = 1;
nethercote71980f02004-01-24 18:18:54 +00001797 else if (VG_CLO_STREQ(arg, "--trace-pthread=all"))
sewardj45b4b372002-04-16 22:50:32 +00001798 VG_(clo_trace_pthread_level) = 2;
sewardj8937c812002-04-12 20:12:20 +00001799
nethercote71980f02004-01-24 18:18:54 +00001800 else if ( ! VG_(needs).command_line_options
1801 || ! SK_(process_cmd_line_option)(arg) ) {
nethercotef4928da2004-06-15 10:54:40 +00001802 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001803 }
sewardjde4a1d02002-03-22 01:27:54 +00001804 }
1805
nethercote27fec902004-06-16 21:26:32 +00001806 // Check various option values
1807
njnf9ebf672003-05-12 21:41:30 +00001808 if (VG_(clo_verbosity) < 0)
sewardjde4a1d02002-03-22 01:27:54 +00001809 VG_(clo_verbosity) = 0;
1810
nethercote04d0fbc2004-01-26 16:48:06 +00001811 if (VG_(clo_db_attach) && VG_(clo_trace_children)) {
sewardjde4a1d02002-03-22 01:27:54 +00001812 VG_(message)(Vg_UserMsg, "");
1813 VG_(message)(Vg_UserMsg,
nethercote04d0fbc2004-01-26 16:48:06 +00001814 "--db-attach=yes conflicts with --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001815 VG_(message)(Vg_UserMsg,
1816 "Please choose one or the other, but not both.");
nethercote04d0fbc2004-01-26 16:48:06 +00001817 VG_(bad_option)("--db-attach=yes and --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001818 }
1819
nethercotef8548672004-06-21 12:42:35 +00001820 /* Set up logging now. After this is done, VG_(clo_log_fd)
sewardj4cf05692002-10-27 20:28:29 +00001821 should be connected to whatever sink has been selected, and we
1822 indiscriminately chuck stuff into it without worrying what the
1823 nature of it is. Oh the wonder of Unix streams. */
1824
nethercotee1730692003-11-20 10:38:07 +00001825 /* So far we should be still attached to stdout, so we can show on
sewardj4cf05692002-10-27 20:28:29 +00001826 the terminal any problems to do with processing command line
1827 opts. */
nethercotef8548672004-06-21 12:42:35 +00001828 vg_assert(VG_(clo_log_fd) == 1 /* stdout */);
sewardj73cf3bc2002-11-03 03:20:15 +00001829 vg_assert(VG_(logging_to_filedes) == True);
sewardj4cf05692002-10-27 20:28:29 +00001830
1831 switch (VG_(clo_log_to)) {
sewardj73cf3bc2002-11-03 03:20:15 +00001832
sewardj4cf05692002-10-27 20:28:29 +00001833 case VgLogTo_Fd:
nethercotef8548672004-06-21 12:42:35 +00001834 vg_assert(VG_(clo_log_name) == NULL);
1835 VG_(clo_log_fd) = eventually_log_fd;
sewardj4cf05692002-10-27 20:28:29 +00001836 break;
sewardj73cf3bc2002-11-03 03:20:15 +00001837
sewardj4cf05692002-10-27 20:28:29 +00001838 case VgLogTo_File: {
1839 Char logfilename[1000];
jsgff3c3f1a2003-10-14 22:13:28 +00001840 Int seq = 0;
1841 Int pid = VG_(getpid)();
1842
nethercotef8548672004-06-21 12:42:35 +00001843 vg_assert(VG_(clo_log_name) != NULL);
1844 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
jsgff3c3f1a2003-10-14 22:13:28 +00001845
nethercote71980f02004-01-24 18:18:54 +00001846 for (;;) {
jsgff3c3f1a2003-10-14 22:13:28 +00001847 if (seq == 0)
1848 VG_(sprintf)(logfilename, "%s.pid%d",
nethercotef8548672004-06-21 12:42:35 +00001849 VG_(clo_log_name), pid );
jsgff3c3f1a2003-10-14 22:13:28 +00001850 else
1851 VG_(sprintf)(logfilename, "%s.pid%d.%d",
nethercotef8548672004-06-21 12:42:35 +00001852 VG_(clo_log_name), pid, seq );
jsgff3c3f1a2003-10-14 22:13:28 +00001853 seq++;
1854
nethercotef8548672004-06-21 12:42:35 +00001855 eventually_log_fd
jsgff3c3f1a2003-10-14 22:13:28 +00001856 = VG_(open)(logfilename,
1857 VKI_O_CREAT|VKI_O_WRONLY|VKI_O_EXCL|VKI_O_TRUNC,
1858 VKI_S_IRUSR|VKI_S_IWUSR);
nethercotef8548672004-06-21 12:42:35 +00001859 if (eventually_log_fd >= 0) {
1860 VG_(clo_log_fd) = VG_(safe_fd)(eventually_log_fd);
jsgff3c3f1a2003-10-14 22:13:28 +00001861 break;
1862 } else {
nethercotef8548672004-06-21 12:42:35 +00001863 if (eventually_log_fd != -VKI_EEXIST) {
jsgff3c3f1a2003-10-14 22:13:28 +00001864 VG_(message)(Vg_UserMsg,
1865 "Can't create/open log file `%s.pid%d'; giving up!",
nethercotef8548672004-06-21 12:42:35 +00001866 VG_(clo_log_name), pid);
jsgff3c3f1a2003-10-14 22:13:28 +00001867 VG_(bad_option)(
nethercotef8548672004-06-21 12:42:35 +00001868 "--log-file=<file> didn't work out for some reason.");
jsgff3c3f1a2003-10-14 22:13:28 +00001869 break;
1870 }
1871 }
1872 }
sewardj4cf05692002-10-27 20:28:29 +00001873 break;
sewardj73cf3bc2002-11-03 03:20:15 +00001874 }
1875
1876 case VgLogTo_Socket: {
nethercotef8548672004-06-21 12:42:35 +00001877 vg_assert(VG_(clo_log_name) != NULL);
1878 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
1879 eventually_log_fd = VG_(connect_via_socket)( VG_(clo_log_name) );
1880 if (eventually_log_fd == -1) {
sewardj73cf3bc2002-11-03 03:20:15 +00001881 VG_(message)(Vg_UserMsg,
nethercotef8548672004-06-21 12:42:35 +00001882 "Invalid --log-socket=ipaddr or --log-socket=ipaddr:port spec");
sewardj73cf3bc2002-11-03 03:20:15 +00001883 VG_(message)(Vg_UserMsg,
nethercotef8548672004-06-21 12:42:35 +00001884 "of `%s'; giving up!", VG_(clo_log_name) );
sewardj73cf3bc2002-11-03 03:20:15 +00001885 VG_(bad_option)(
nethercotef8548672004-06-21 12:42:35 +00001886 "--log-socket=");
sewardj4cf05692002-10-27 20:28:29 +00001887 }
nethercotef8548672004-06-21 12:42:35 +00001888 if (eventually_log_fd == -2) {
sewardj73cf3bc2002-11-03 03:20:15 +00001889 VG_(message)(Vg_UserMsg,
sewardj570f8902002-11-03 11:44:36 +00001890 "valgrind: failed to connect to logging server `%s'.",
nethercotef8548672004-06-21 12:42:35 +00001891 VG_(clo_log_name) );
sewardj570f8902002-11-03 11:44:36 +00001892 VG_(message)(Vg_UserMsg,
1893 "Log messages will sent to stderr instead." );
1894 VG_(message)(Vg_UserMsg,
1895 "" );
1896 /* We don't change anything here. */
1897 } else {
nethercotef8548672004-06-21 12:42:35 +00001898 vg_assert(eventually_log_fd > 0);
1899 VG_(clo_log_fd) = eventually_log_fd;
sewardj570f8902002-11-03 11:44:36 +00001900 VG_(logging_to_filedes) = False;
1901 }
sewardj73cf3bc2002-11-03 03:20:15 +00001902 break;
1903 }
1904
sewardj4cf05692002-10-27 20:28:29 +00001905 }
1906
nethercotef8548672004-06-21 12:42:35 +00001907 /* Move log_fd into the safe range, so it doesn't conflict with any app fds */
1908 eventually_log_fd = VG_(fcntl)(VG_(clo_log_fd), VKI_F_DUPFD, VG_(max_fd)+1);
1909 if (eventually_log_fd < 0)
jsgf855d93d2003-10-13 22:26:55 +00001910 VG_(message)(Vg_UserMsg, "valgrind: failed to move logfile fd into safe range");
1911 else {
nethercotef8548672004-06-21 12:42:35 +00001912 VG_(clo_log_fd) = eventually_log_fd;
1913 VG_(fcntl)(VG_(clo_log_fd), VKI_F_SETFD, VKI_FD_CLOEXEC);
jsgf855d93d2003-10-13 22:26:55 +00001914 }
1915
sewardj4cf05692002-10-27 20:28:29 +00001916 /* Ok, the logging sink is running now. Print a suitable preamble.
1917 If logging to file or a socket, write details of parent PID and
1918 command line args, to help people trying to interpret the
1919 results of a run which encompasses multiple processes. */
sewardjde4a1d02002-03-22 01:27:54 +00001920
sewardj83adf412002-05-01 01:25:45 +00001921 if (VG_(clo_verbosity > 0)) {
njnd04b7c62002-10-03 14:05:52 +00001922 /* Skin details */
1923 VG_(message)(Vg_UserMsg, "%s%s%s, %s for x86-linux.",
1924 VG_(details).name,
1925 NULL == VG_(details).version ? "" : "-",
1926 NULL == VG_(details).version
1927 ? (Char*)"" : VG_(details).version,
1928 VG_(details).description);
1929 VG_(message)(Vg_UserMsg, "%s", VG_(details).copyright_author);
sewardj3b2736a2002-03-24 12:18:35 +00001930
njnd04b7c62002-10-03 14:05:52 +00001931 /* Core details */
1932 VG_(message)(Vg_UserMsg,
njn3e884182003-04-15 13:03:23 +00001933 "Using valgrind-%s, a program supervision framework for x86-linux.",
sewardj4aa62ba2002-10-05 15:49:27 +00001934 VERSION);
sewardjde4a1d02002-03-22 01:27:54 +00001935 VG_(message)(Vg_UserMsg,
nethercotebb1c9912004-01-04 16:43:23 +00001936 "Copyright (C) 2000-2004, and GNU GPL'd, by Julian Seward.");
njnd04b7c62002-10-03 14:05:52 +00001937 }
1938
nethercotec1e395d2003-11-10 13:26:49 +00001939 if (VG_(clo_verbosity) > 0 && VG_(clo_log_to) != VgLogTo_Fd) {
sewardj4cf05692002-10-27 20:28:29 +00001940 VG_(message)(Vg_UserMsg, "");
1941 VG_(message)(Vg_UserMsg,
1942 "My PID = %d, parent PID = %d. Prog and args are:",
1943 VG_(getpid)(), VG_(getppid)() );
1944 for (i = 0; i < VG_(client_argc); i++)
1945 VG_(message)(Vg_UserMsg, " %s", VG_(client_argv)[i]);
1946 }
1947
sewardjde4a1d02002-03-22 01:27:54 +00001948 if (VG_(clo_verbosity) > 1) {
nethercotea70f7352004-04-18 12:08:46 +00001949 Int fd;
sewardj4cf05692002-10-27 20:28:29 +00001950 if (VG_(clo_log_to) != VgLogTo_Fd)
1951 VG_(message)(Vg_UserMsg, "");
fitzhardinge98abfc72003-12-16 02:05:15 +00001952 VG_(message)(Vg_UserMsg, "Valgrind library directory: %s", VG_(libdir));
njn86dc2bc2003-09-09 07:26:21 +00001953 VG_(message)(Vg_UserMsg, "Command line");
1954 for (i = 0; i < VG_(client_argc); i++)
1955 VG_(message)(Vg_UserMsg, " %s", VG_(client_argv)[i]);
1956
sewardjde4a1d02002-03-22 01:27:54 +00001957 VG_(message)(Vg_UserMsg, "Startup, with flags:");
nethercote71980f02004-01-24 18:18:54 +00001958 for (i = 1; i < VG_(vg_argc); i++) {
1959 VG_(message)(Vg_UserMsg, " %s", VG_(vg_argv)[i]);
sewardjde4a1d02002-03-22 01:27:54 +00001960 }
nethercotea70f7352004-04-18 12:08:46 +00001961
1962 VG_(message)(Vg_UserMsg, "Contents of /proc/version:");
1963 fd = VG_(open) ( "/proc/version", VKI_O_RDONLY, 0 );
1964 if (fd < 0) {
1965 VG_(message)(Vg_UserMsg, " can't open /proc/version");
1966 } else {
1967 #define BUF_LEN 256
1968 Char version_buf[BUF_LEN];
1969 Int n = VG_(read) ( fd, version_buf, BUF_LEN );
1970 vg_assert(n <= 256);
1971 if (n > 0) {
1972 version_buf[n-1] = '\0';
1973 VG_(message)(Vg_UserMsg, " %s", version_buf);
1974 } else {
1975 VG_(message)(Vg_UserMsg, " (empty?)");
1976 }
1977 VG_(close)(fd);
1978 #undef BUF_LEN
1979 }
sewardjde4a1d02002-03-22 01:27:54 +00001980 }
1981
fitzhardinge98abfc72003-12-16 02:05:15 +00001982 if (VG_(clo_n_suppressions) < VG_CLO_MAX_SFILES-1 &&
njn25e49d8e72002-09-23 09:36:25 +00001983 (VG_(needs).core_errors || VG_(needs).skin_errors)) {
fitzhardinge98abfc72003-12-16 02:05:15 +00001984 /* If there are no suppression files specified and the skin
1985 needs one, load the default */
1986 static const Char default_supp[] = "default.supp";
1987 Int len = VG_(strlen)(VG_(libdir)) + 1 + sizeof(default_supp);
1988 Char *buf = VG_(arena_malloc)(VG_AR_CORE, len);
1989 VG_(sprintf)(buf, "%s/%s", VG_(libdir), default_supp);
1990 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = buf;
1991 VG_(clo_n_suppressions)++;
sewardjde4a1d02002-03-22 01:27:54 +00001992 }
sewardj4cf05692002-10-27 20:28:29 +00001993
njn6a230532003-07-21 10:38:23 +00001994 if (VG_(clo_gen_suppressions) &&
1995 !VG_(needs).core_errors && !VG_(needs).skin_errors) {
nethercotef4928da2004-06-15 10:54:40 +00001996 VG_(message)(Vg_UserMsg,
1997 "Can't use --gen-suppressions=yes with this tool,");
1998 VG_(message)(Vg_UserMsg,
1999 "as it doesn't generate errors.");
2000 VG_(bad_option)("--gen-suppressions=yes");
njn6a230532003-07-21 10:38:23 +00002001 }
sewardjde4a1d02002-03-22 01:27:54 +00002002}
2003
sewardjde4a1d02002-03-22 01:27:54 +00002004
nethercote71980f02004-01-24 18:18:54 +00002005/*====================================================================*/
2006/*=== File descriptor setup ===*/
2007/*====================================================================*/
2008
2009static void setup_file_descriptors(void)
2010{
2011 struct vki_rlimit rl;
2012
2013 /* Get the current file descriptor limits. */
2014 if (VG_(getrlimit)(VKI_RLIMIT_NOFILE, &rl) < 0) {
2015 rl.rlim_cur = 1024;
2016 rl.rlim_max = 1024;
2017 }
2018
2019 /* Work out where to move the soft limit to. */
2020 if (rl.rlim_cur + VG_N_RESERVED_FDS <= rl.rlim_max) {
2021 rl.rlim_cur = rl.rlim_cur + VG_N_RESERVED_FDS;
2022 } else {
2023 rl.rlim_cur = rl.rlim_max;
2024 }
2025
2026 /* Reserve some file descriptors for our use. */
2027 VG_(max_fd) = rl.rlim_cur - VG_N_RESERVED_FDS;
2028
2029 /* Update the soft limit. */
2030 VG_(setrlimit)(VKI_RLIMIT_NOFILE, &rl);
2031
2032 if (VG_(vgexecfd) != -1)
2033 VG_(vgexecfd) = VG_(safe_fd)( VG_(vgexecfd) );
2034 if (VG_(clexecfd) != -1)
2035 VG_(clexecfd) = VG_(safe_fd)( VG_(clexecfd) );
2036}
2037
2038
2039/*====================================================================*/
nethercote1d447092004-02-01 17:29:59 +00002040/*=== baseBlock: definition + setup ===*/
nethercote71980f02004-01-24 18:18:54 +00002041/*====================================================================*/
2042
2043/* The variables storing offsets. */
2044
2045#define INVALID_OFFSET (-1)
2046
2047Int VGOFF_(m_eax) = INVALID_OFFSET;
2048Int VGOFF_(m_ecx) = INVALID_OFFSET;
2049Int VGOFF_(m_edx) = INVALID_OFFSET;
2050Int VGOFF_(m_ebx) = INVALID_OFFSET;
2051Int VGOFF_(m_esp) = INVALID_OFFSET;
2052Int VGOFF_(m_ebp) = INVALID_OFFSET;
2053Int VGOFF_(m_esi) = INVALID_OFFSET;
2054Int VGOFF_(m_edi) = INVALID_OFFSET;
2055Int VGOFF_(m_eflags) = INVALID_OFFSET;
2056Int VGOFF_(m_dflag) = INVALID_OFFSET;
2057Int VGOFF_(m_ssestate) = INVALID_OFFSET;
2058Int VGOFF_(ldt) = INVALID_OFFSET;
2059Int VGOFF_(tls) = INVALID_OFFSET;
2060Int VGOFF_(m_cs) = INVALID_OFFSET;
2061Int VGOFF_(m_ss) = INVALID_OFFSET;
2062Int VGOFF_(m_ds) = INVALID_OFFSET;
2063Int VGOFF_(m_es) = INVALID_OFFSET;
2064Int VGOFF_(m_fs) = INVALID_OFFSET;
2065Int VGOFF_(m_gs) = INVALID_OFFSET;
2066Int VGOFF_(m_eip) = INVALID_OFFSET;
2067Int VGOFF_(spillslots) = INVALID_OFFSET;
2068Int VGOFF_(sh_eax) = INVALID_OFFSET;
2069Int VGOFF_(sh_ecx) = INVALID_OFFSET;
2070Int VGOFF_(sh_edx) = INVALID_OFFSET;
2071Int VGOFF_(sh_ebx) = INVALID_OFFSET;
2072Int VGOFF_(sh_esp) = INVALID_OFFSET;
2073Int VGOFF_(sh_ebp) = INVALID_OFFSET;
2074Int VGOFF_(sh_esi) = INVALID_OFFSET;
2075Int VGOFF_(sh_edi) = INVALID_OFFSET;
2076Int VGOFF_(sh_eflags) = INVALID_OFFSET;
2077
2078Int VGOFF_(helper_idiv_64_32) = INVALID_OFFSET;
2079Int VGOFF_(helper_div_64_32) = INVALID_OFFSET;
2080Int VGOFF_(helper_idiv_32_16) = INVALID_OFFSET;
2081Int VGOFF_(helper_div_32_16) = INVALID_OFFSET;
2082Int VGOFF_(helper_idiv_16_8) = INVALID_OFFSET;
2083Int VGOFF_(helper_div_16_8) = INVALID_OFFSET;
2084Int VGOFF_(helper_imul_32_64) = INVALID_OFFSET;
2085Int VGOFF_(helper_mul_32_64) = INVALID_OFFSET;
2086Int VGOFF_(helper_imul_16_32) = INVALID_OFFSET;
2087Int VGOFF_(helper_mul_16_32) = INVALID_OFFSET;
2088Int VGOFF_(helper_imul_8_16) = INVALID_OFFSET;
2089Int VGOFF_(helper_mul_8_16) = INVALID_OFFSET;
2090Int VGOFF_(helper_CLD) = INVALID_OFFSET;
2091Int VGOFF_(helper_STD) = INVALID_OFFSET;
2092Int VGOFF_(helper_get_dirflag) = INVALID_OFFSET;
2093Int VGOFF_(helper_CLC) = INVALID_OFFSET;
2094Int VGOFF_(helper_STC) = INVALID_OFFSET;
nethercote1018bdd2004-02-11 23:33:29 +00002095Int VGOFF_(helper_CMC) = INVALID_OFFSET;
nethercote71980f02004-01-24 18:18:54 +00002096Int VGOFF_(helper_shldl) = INVALID_OFFSET;
2097Int VGOFF_(helper_shldw) = INVALID_OFFSET;
2098Int VGOFF_(helper_shrdl) = INVALID_OFFSET;
2099Int VGOFF_(helper_shrdw) = INVALID_OFFSET;
2100Int VGOFF_(helper_IN) = INVALID_OFFSET;
2101Int VGOFF_(helper_OUT) = INVALID_OFFSET;
2102Int VGOFF_(helper_RDTSC) = INVALID_OFFSET;
2103Int VGOFF_(helper_CPUID) = INVALID_OFFSET;
2104Int VGOFF_(helper_BSWAP) = INVALID_OFFSET;
nethercote1018bdd2004-02-11 23:33:29 +00002105Int VGOFF_(helper_bsfw) = INVALID_OFFSET;
2106Int VGOFF_(helper_bsfl) = INVALID_OFFSET;
2107Int VGOFF_(helper_bsrw) = INVALID_OFFSET;
2108Int VGOFF_(helper_bsrl) = INVALID_OFFSET;
nethercote71980f02004-01-24 18:18:54 +00002109Int VGOFF_(helper_fstsw_AX) = INVALID_OFFSET;
2110Int VGOFF_(helper_SAHF) = INVALID_OFFSET;
2111Int VGOFF_(helper_LAHF) = INVALID_OFFSET;
2112Int VGOFF_(helper_DAS) = INVALID_OFFSET;
2113Int VGOFF_(helper_DAA) = INVALID_OFFSET;
nethercote1018bdd2004-02-11 23:33:29 +00002114Int VGOFF_(helper_AAS) = INVALID_OFFSET;
2115Int VGOFF_(helper_AAA) = INVALID_OFFSET;
2116Int VGOFF_(helper_AAD) = INVALID_OFFSET;
2117Int VGOFF_(helper_AAM) = INVALID_OFFSET;
nethercote71980f02004-01-24 18:18:54 +00002118Int VGOFF_(helper_cmpxchg8b) = INVALID_OFFSET;
2119Int VGOFF_(helper_undefined_instruction) = INVALID_OFFSET;
2120
2121/* MAX_NONCOMPACT_HELPERS can be increased easily. If MAX_COMPACT_HELPERS is
2122 * increased too much, they won't really be compact any more... */
2123#define MAX_COMPACT_HELPERS 8
2124#define MAX_NONCOMPACT_HELPERS 50
2125
2126UInt VG_(n_compact_helpers) = 0;
2127UInt VG_(n_noncompact_helpers) = 0;
2128
2129Addr VG_(compact_helper_addrs) [MAX_COMPACT_HELPERS];
2130Int VG_(compact_helper_offsets)[MAX_COMPACT_HELPERS];
2131Addr VG_(noncompact_helper_addrs) [MAX_NONCOMPACT_HELPERS];
2132Int VG_(noncompact_helper_offsets)[MAX_NONCOMPACT_HELPERS];
2133
2134/* This is the actual defn of baseblock. */
2135UInt VG_(baseBlock)[VG_BASEBLOCK_WORDS];
2136
nethercote71980f02004-01-24 18:18:54 +00002137/* Words. */
2138static Int baB_off = 0;
2139
2140
sewardjfa492d42002-12-08 18:20:01 +00002141UInt VG_(insertDflag)(UInt eflags, Int d)
2142{
2143 vg_assert(d == 1 || d == -1);
2144 eflags &= ~EFlagD;
2145
2146 if (d < 0)
2147 eflags |= EFlagD;
2148
2149 return eflags;
2150}
2151
2152Int VG_(extractDflag)(UInt eflags)
2153{
2154 Int ret;
2155
2156 if (eflags & EFlagD)
2157 ret = -1;
2158 else
2159 ret = 1;
2160
2161 return ret;
2162}
2163
nethercote71980f02004-01-24 18:18:54 +00002164/* Returns the offset, in words. */
2165static Int alloc_BaB ( Int words )
sewardjde4a1d02002-03-22 01:27:54 +00002166{
nethercote71980f02004-01-24 18:18:54 +00002167 Int off = baB_off;
2168 baB_off += words;
2169 if (baB_off >= VG_BASEBLOCK_WORDS)
2170 VG_(core_panic)( "alloc_BaB: baseBlock is too small");
sewardjde4a1d02002-03-22 01:27:54 +00002171
nethercote71980f02004-01-24 18:18:54 +00002172 return off;
sewardjde4a1d02002-03-22 01:27:54 +00002173}
2174
nethercote71980f02004-01-24 18:18:54 +00002175/* Align offset, in *bytes* */
2176static void align_BaB ( UInt align )
njn25e49d8e72002-09-23 09:36:25 +00002177{
nethercote71980f02004-01-24 18:18:54 +00002178 vg_assert(2 == align || 4 == align || 8 == align || 16 == align);
2179 baB_off += (align-1);
2180 baB_off &= ~(align-1);
njn25e49d8e72002-09-23 09:36:25 +00002181}
2182
nethercote71980f02004-01-24 18:18:54 +00002183/* Allocate 1 word in baseBlock and set it to the given value. */
2184static Int alloc_BaB_1_set ( Addr a )
njn25e49d8e72002-09-23 09:36:25 +00002185{
nethercote71980f02004-01-24 18:18:54 +00002186 Int off = alloc_BaB(1);
2187 VG_(baseBlock)[off] = (UInt)a;
2188 return off;
njn25e49d8e72002-09-23 09:36:25 +00002189}
2190
nethercote71980f02004-01-24 18:18:54 +00002191/* Registers a function in compact_helper_addrs; compact_helper_offsets is
2192 filled in later. */
2193void VG_(register_compact_helper)(Addr a)
sewardjde4a1d02002-03-22 01:27:54 +00002194{
nethercote71980f02004-01-24 18:18:54 +00002195 if (MAX_COMPACT_HELPERS <= VG_(n_compact_helpers)) {
2196 VG_(printf)("Can only register %d compact helpers\n",
2197 MAX_COMPACT_HELPERS);
2198 VG_(core_panic)("Too many compact helpers registered");
2199 }
2200 VG_(compact_helper_addrs)[VG_(n_compact_helpers)] = a;
2201 VG_(n_compact_helpers)++;
2202}
2203
2204/* Registers a function in noncompact_helper_addrs; noncompact_helper_offsets
2205 * is filled in later.
2206 */
2207void VG_(register_noncompact_helper)(Addr a)
2208{
2209 if (MAX_NONCOMPACT_HELPERS <= VG_(n_noncompact_helpers)) {
2210 VG_(printf)("Can only register %d non-compact helpers\n",
2211 MAX_NONCOMPACT_HELPERS);
2212 VG_(printf)("Try increasing MAX_NON_COMPACT_HELPERS\n");
2213 VG_(core_panic)("Too many non-compact helpers registered");
2214 }
2215 VG_(noncompact_helper_addrs)[VG_(n_noncompact_helpers)] = a;
2216 VG_(n_noncompact_helpers)++;
2217}
2218
2219/* Allocate offsets in baseBlock for the skin helpers */
2220static
2221void assign_helpers_in_baseBlock(UInt n, Int offsets[], Addr addrs[])
2222{
2223 UInt i;
2224 for (i = 0; i < n; i++)
2225 offsets[i] = alloc_BaB_1_set( addrs[i] );
2226}
2227
2228Bool VG_(need_to_handle_esp_assignment)(void)
2229{
2230 return ( VG_(defined_new_mem_stack_4)() ||
2231 VG_(defined_die_mem_stack_4)() ||
2232 VG_(defined_new_mem_stack_8)() ||
2233 VG_(defined_die_mem_stack_8)() ||
2234 VG_(defined_new_mem_stack_12)() ||
2235 VG_(defined_die_mem_stack_12)() ||
2236 VG_(defined_new_mem_stack_16)() ||
2237 VG_(defined_die_mem_stack_16)() ||
2238 VG_(defined_new_mem_stack_32)() ||
2239 VG_(defined_die_mem_stack_32)() ||
2240 VG_(defined_new_mem_stack)() ||
2241 VG_(defined_die_mem_stack)()
2242 );
2243}
2244
2245/* Here we assign actual offsets. It's important to get the most
2246 popular referents within 128 bytes of the start, so we can take
2247 advantage of short addressing modes relative to %ebp. Popularity
2248 of offsets was measured on 22 Feb 02 running a KDE application, and
2249 the slots rearranged accordingly, with a 1.5% reduction in total
2250 size of translations. */
2251static void init_baseBlock ( Addr client_eip, Addr esp_at_startup )
2252{
2253 /* Those with offsets under 128 are carefully chosen. */
2254
2255 /* WORD offsets in this column */
2256 /* 0 */ VGOFF_(m_eax) = alloc_BaB_1_set(0);
2257 /* 1 */ VGOFF_(m_ecx) = alloc_BaB_1_set(0);
2258 /* 2 */ VGOFF_(m_edx) = alloc_BaB_1_set(0);
2259 /* 3 */ VGOFF_(m_ebx) = alloc_BaB_1_set(0);
2260 /* 4 */ VGOFF_(m_esp) = alloc_BaB_1_set(esp_at_startup);
2261 /* 5 */ VGOFF_(m_ebp) = alloc_BaB_1_set(0);
2262 /* 6 */ VGOFF_(m_esi) = alloc_BaB_1_set(0);
2263 /* 7 */ VGOFF_(m_edi) = alloc_BaB_1_set(0);
2264 /* 8 */ VGOFF_(m_eflags) = alloc_BaB_1_set(0);
2265
2266 if (VG_(needs).shadow_regs) {
2267 /* 9 */ VGOFF_(sh_eax) = alloc_BaB_1_set(0);
2268 /* 10 */ VGOFF_(sh_ecx) = alloc_BaB_1_set(0);
2269 /* 11 */ VGOFF_(sh_edx) = alloc_BaB_1_set(0);
2270 /* 12 */ VGOFF_(sh_ebx) = alloc_BaB_1_set(0);
2271 /* 13 */ VGOFF_(sh_esp) = alloc_BaB_1_set(0);
2272 /* 14 */ VGOFF_(sh_ebp) = alloc_BaB_1_set(0);
2273 /* 15 */ VGOFF_(sh_esi) = alloc_BaB_1_set(0);
2274 /* 16 */ VGOFF_(sh_edi) = alloc_BaB_1_set(0);
2275 /* 17 */ VGOFF_(sh_eflags) = alloc_BaB_1_set(0);
2276 VG_TRACK( post_regs_write_init );
2277 }
2278
2279 /* 9,10,11 or 18,19,20... depends on number whether shadow regs are used
2280 * and on compact helpers registered */
2281
2282 /* Make these most-frequently-called specialised ones compact, if they
2283 are used. */
2284 if (VG_(defined_new_mem_stack_4)())
2285 VG_(register_compact_helper)( (Addr) VG_(tool_interface).track_new_mem_stack_4);
2286
2287 if (VG_(defined_die_mem_stack_4)())
2288 VG_(register_compact_helper)( (Addr) VG_(tool_interface).track_die_mem_stack_4);
2289
2290 /* (9 or 18) + n_compact_helpers */
2291 /* Allocate slots for compact helpers */
2292 assign_helpers_in_baseBlock(VG_(n_compact_helpers),
2293 VG_(compact_helper_offsets),
2294 VG_(compact_helper_addrs));
2295
2296 /* (9/10 or 18/19) + n_compact_helpers */
2297 VGOFF_(m_eip) = alloc_BaB_1_set(client_eip);
2298
2299 /* There are currently 24 spill slots */
2300 /* (11+/20+ .. 32+/43+) + n_compact_helpers. This can overlap the magic
2301 * boundary at >= 32 words, but most spills are to low numbered spill
2302 * slots, so the ones above the boundary don't see much action. */
2303 VGOFF_(spillslots) = alloc_BaB(VG_MAX_SPILLSLOTS);
2304
2305 /* I gave up counting at this point. Since they're above the
2306 short-amode-boundary, there's no point. */
2307
2308 VGOFF_(m_dflag) = alloc_BaB_1_set(1); // 1 == forward D-flag
2309
2310 /* The FPU/SSE state. This _must_ be 16-byte aligned. Initial
2311 state doesn't matter much, as long as it's not totally borked. */
2312 align_BaB(16);
2313 VGOFF_(m_ssestate) = alloc_BaB(VG_SIZE_OF_SSESTATE_W);
2314 vg_assert(
2315 0 == ( ((UInt)(& VG_(baseBlock)[VGOFF_(m_ssestate)])) % 16 )
sewardj22854b92002-11-30 14:00:47 +00002316 );
2317
fitzhardingec2dbbac2004-01-23 23:09:01 +00002318 /* I assume that if we have SSE2 we also have SSE */
2319 VG_(have_ssestate) =
2320 VG_(cpu_has_feature)(VG_X86_FEAT_FXSR) &&
2321 VG_(cpu_has_feature)(VG_X86_FEAT_SSE);
2322
fitzhardinge98abfc72003-12-16 02:05:15 +00002323 /* set up an initial FPU state (doesn't really matter what it is,
2324 so long as it's somewhat valid) */
2325 if (!VG_(have_ssestate))
nethercote71980f02004-01-24 18:18:54 +00002326 asm volatile("fwait; fnsave %0; fwait; frstor %0; fwait"
2327 :
2328 : "m" (VG_(baseBlock)[VGOFF_(m_ssestate)])
2329 : "cc", "memory");
fitzhardinge98abfc72003-12-16 02:05:15 +00002330 else
nethercote71980f02004-01-24 18:18:54 +00002331 asm volatile("fwait; fxsave %0; fwait; andl $0xffbf, %1;"
2332 "fxrstor %0; fwait"
2333 :
2334 : "m" (VG_(baseBlock)[VGOFF_(m_ssestate)]),
2335 "m" (VG_(baseBlock)[VGOFF_(m_ssestate)+(24/4)])
2336 : "cc", "memory");
fitzhardinge98abfc72003-12-16 02:05:15 +00002337
njn0c7a5b52003-04-30 09:00:33 +00002338 if (0) {
2339 if (VG_(have_ssestate))
2340 VG_(printf)("Looks like a SSE-capable CPU\n");
2341 else
2342 VG_(printf)("Looks like a MMX-only CPU\n");
2343 }
sewardjb91ae7f2003-04-29 23:50:00 +00002344
nethercote71980f02004-01-24 18:18:54 +00002345 /* LDT pointer: pretend the root thread has an empty LDT to start with. */
2346 VGOFF_(ldt) = alloc_BaB_1_set((UInt)NULL);
jsgf855d93d2003-10-13 22:26:55 +00002347
nethercote71980f02004-01-24 18:18:54 +00002348 /* TLS pointer: pretend the root thread has no TLS array for now. */
2349 VGOFF_(tls) = alloc_BaB_1_set((UInt)NULL);
fitzhardingef0046f22003-12-18 02:39:22 +00002350
nethercote71980f02004-01-24 18:18:54 +00002351 /* segment registers */
2352 VGOFF_(m_cs) = alloc_BaB_1_set(0);
2353 VGOFF_(m_ss) = alloc_BaB_1_set(0);
2354 VGOFF_(m_ds) = alloc_BaB_1_set(0);
2355 VGOFF_(m_es) = alloc_BaB_1_set(0);
2356 VGOFF_(m_fs) = alloc_BaB_1_set(0);
2357 VGOFF_(m_gs) = alloc_BaB_1_set(0);
fitzhardingef0046f22003-12-18 02:39:22 +00002358
thughes35cec982004-04-21 15:16:43 +00002359 /* initialise %cs, %ds and %ss to point at the operating systems
2360 default code, data and stack segments */
2361 asm volatile("movw %%cs, %0"
2362 :
2363 : "m" (VG_(baseBlock)[VGOFF_(m_cs)]));
2364 asm volatile("movw %%ds, %0"
2365 :
2366 : "m" (VG_(baseBlock)[VGOFF_(m_ds)]));
2367 asm volatile("movw %%ss, %0"
2368 :
2369 : "m" (VG_(baseBlock)[VGOFF_(m_ss)]));
2370
nethercote71980f02004-01-24 18:18:54 +00002371 VG_(register_noncompact_helper)( (Addr) & VG_(do_useseg) );
fitzhardingef0046f22003-12-18 02:39:22 +00002372
nethercote71980f02004-01-24 18:18:54 +00002373#define REG(kind, size) \
2374 if (VG_(defined_##kind##_mem_stack##size)()) \
2375 VG_(register_noncompact_helper)( \
2376 (Addr) VG_(tool_interface).track_##kind##_mem_stack##size );
2377 REG(new, _8);
2378 REG(new, _12);
2379 REG(new, _16);
2380 REG(new, _32);
2381 REG(new, );
2382 REG(die, _8);
2383 REG(die, _12);
2384 REG(die, _16);
2385 REG(die, _32);
2386 REG(die, );
2387#undef REG
fitzhardingef0046f22003-12-18 02:39:22 +00002388
nethercote71980f02004-01-24 18:18:54 +00002389 if (VG_(need_to_handle_esp_assignment)())
2390 VG_(register_noncompact_helper)((Addr) VG_(unknown_esp_update));
fitzhardingeb791a192003-12-18 07:22:44 +00002391
nethercote71980f02004-01-24 18:18:54 +00002392# define HELPER(name) \
2393 VGOFF_(helper_##name) = alloc_BaB_1_set( (Addr) & VG_(helper_##name))
njn3e884182003-04-15 13:03:23 +00002394
nethercote71980f02004-01-24 18:18:54 +00002395 /* Helper functions. */
2396 HELPER(idiv_64_32); HELPER(div_64_32);
2397 HELPER(idiv_32_16); HELPER(div_32_16);
2398 HELPER(idiv_16_8); HELPER(div_16_8);
fitzhardinge98abfc72003-12-16 02:05:15 +00002399
nethercote71980f02004-01-24 18:18:54 +00002400 HELPER(imul_32_64); HELPER(mul_32_64);
2401 HELPER(imul_16_32); HELPER(mul_16_32);
2402 HELPER(imul_8_16); HELPER(mul_8_16);
njn25e49d8e72002-09-23 09:36:25 +00002403
nethercote71980f02004-01-24 18:18:54 +00002404 HELPER(CLD); HELPER(STD);
2405 HELPER(get_dirflag);
sewardjde4a1d02002-03-22 01:27:54 +00002406
nethercote71980f02004-01-24 18:18:54 +00002407 HELPER(CLC); HELPER(STC);
nethercote1018bdd2004-02-11 23:33:29 +00002408 HELPER(CMC);
jsgf855d93d2003-10-13 22:26:55 +00002409
nethercote71980f02004-01-24 18:18:54 +00002410 HELPER(shldl); HELPER(shldw);
2411 HELPER(shrdl); HELPER(shrdw);
njncc7bb472002-10-14 09:25:19 +00002412
nethercote71980f02004-01-24 18:18:54 +00002413 HELPER(RDTSC); HELPER(CPUID);
njncc7bb472002-10-14 09:25:19 +00002414
nethercote1018bdd2004-02-11 23:33:29 +00002415 HELPER(bsfw); HELPER(bsfl);
2416 HELPER(bsrw); HELPER(bsrl);
rjwalshf5f536f2003-11-17 17:45:00 +00002417
nethercote71980f02004-01-24 18:18:54 +00002418 HELPER(fstsw_AX);
2419 HELPER(SAHF); HELPER(LAHF);
2420 HELPER(DAS); HELPER(DAA);
nethercote1018bdd2004-02-11 23:33:29 +00002421 HELPER(AAS); HELPER(AAA);
2422 HELPER(AAD); HELPER(AAM);
nethercote71980f02004-01-24 18:18:54 +00002423 HELPER(IN); HELPER(OUT);
2424 HELPER(cmpxchg8b);
sewardj018f7622002-05-15 21:13:39 +00002425
nethercote71980f02004-01-24 18:18:54 +00002426 HELPER(undefined_instruction);
jsgf855d93d2003-10-13 22:26:55 +00002427
nethercote71980f02004-01-24 18:18:54 +00002428# undef HELPER
sewardjde4a1d02002-03-22 01:27:54 +00002429
nethercote71980f02004-01-24 18:18:54 +00002430 /* Allocate slots for noncompact helpers */
2431 assign_helpers_in_baseBlock(VG_(n_noncompact_helpers),
2432 VG_(noncompact_helper_offsets),
2433 VG_(noncompact_helper_addrs));
2434}
sewardjde4a1d02002-03-22 01:27:54 +00002435
sewardj5f07b662002-04-23 16:52:51 +00002436
nethercote71980f02004-01-24 18:18:54 +00002437/*====================================================================*/
2438/*=== Setup pointercheck ===*/
2439/*====================================================================*/
njn25e49d8e72002-09-23 09:36:25 +00002440
nethercote71980f02004-01-24 18:18:54 +00002441static void setup_pointercheck(void)
2442{
2443 int ret;
sewardj2e93c502002-04-12 11:12:52 +00002444
fitzhardinge98abfc72003-12-16 02:05:15 +00002445 if (VG_(clo_pointercheck)) {
nethercote71980f02004-01-24 18:18:54 +00002446 vki_modify_ldt_t ldt = {
2447 VG_POINTERCHECK_SEGIDX, // entry_number
2448 VG_(client_base), // base_addr
2449 (VG_(client_end)-VG_(client_base)) / VKI_BYTES_PER_PAGE, // limit
2450 1, // seg_32bit
2451 0, // contents: data, RW, non-expanding
2452 0, // ! read_exec_only
2453 1, // limit_in_pages
2454 0, // ! seg not present
2455 1, // useable
fitzhardinge98abfc72003-12-16 02:05:15 +00002456 };
nethercote71980f02004-01-24 18:18:54 +00002457 ret = VG_(do_syscall)(__NR_modify_ldt, 1, &ldt, sizeof(ldt));
fitzhardinge98abfc72003-12-16 02:05:15 +00002458 if (ret < 0) {
2459 VG_(message)(Vg_UserMsg,
2460 "Warning: ignoring --pointercheck=yes, "
2461 "because modify_ldt failed (errno=%d)", -ret);
2462 VG_(clo_pointercheck) = False;
2463 }
2464 }
sewardjde4a1d02002-03-22 01:27:54 +00002465}
2466
nethercote71980f02004-01-24 18:18:54 +00002467/*====================================================================*/
2468/*=== Initialise program data/text, etc. ===*/
2469/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +00002470
nethercote71980f02004-01-24 18:18:54 +00002471static void build_valgrind_map_callback
2472 ( Addr start, UInt size, Char rr, Char ww, Char xx,
2473 UInt dev, UInt ino, ULong foffset, const UChar* filename )
sewardjde4a1d02002-03-22 01:27:54 +00002474{
nethercote71980f02004-01-24 18:18:54 +00002475 UInt prot = 0;
2476 UInt flags = SF_MMAP|SF_NOSYMS;
2477 Bool is_stack_segment;
2478
2479 is_stack_segment =
2480 (start == VG_(clstk_base) && (start+size) == VG_(clstk_end));
2481
2482 /* Only record valgrind mappings for now, without loading any
2483 symbols. This is so we know where the free space is before we
2484 start allocating more memory (note: heap is OK, it's just mmap
2485 which is the problem here). */
2486 if (start >= VG_(valgrind_base) && (start+size) <= VG_(valgrind_end)) {
2487 flags |= SF_VALGRIND;
2488 VG_(map_file_segment)(start, size, prot, flags, dev, ino, foffset, filename);
2489 }
sewardjde4a1d02002-03-22 01:27:54 +00002490}
2491
nethercote71980f02004-01-24 18:18:54 +00002492// Global var used to pass local data to callback
2493Addr esp_at_startup___global_arg = 0;
sewardjde4a1d02002-03-22 01:27:54 +00002494
nethercote71980f02004-01-24 18:18:54 +00002495static void build_segment_map_callback
2496 ( Addr start, UInt size, Char rr, Char ww, Char xx,
2497 UInt dev, UInt ino, ULong foffset, const UChar* filename )
sewardj45b672d2003-07-25 19:58:11 +00002498{
nethercote71980f02004-01-24 18:18:54 +00002499 UInt prot = 0;
2500 UInt flags;
2501 Bool is_stack_segment;
2502 Addr r_esp;
sewardj45b672d2003-07-25 19:58:11 +00002503
nethercote71980f02004-01-24 18:18:54 +00002504 is_stack_segment
2505 = (start == VG_(clstk_base) && (start+size) == VG_(clstk_end));
fitzhardinge98abfc72003-12-16 02:05:15 +00002506
nethercote71980f02004-01-24 18:18:54 +00002507 if (rr == 'r') prot |= VKI_PROT_READ;
2508 if (ww == 'w') prot |= VKI_PROT_WRITE;
2509 if (xx == 'x') prot |= VKI_PROT_EXEC;
fitzhardinge98abfc72003-12-16 02:05:15 +00002510
nethercote71980f02004-01-24 18:18:54 +00002511 if (is_stack_segment)
2512 flags = SF_STACK | SF_GROWDOWN;
2513 else
2514 flags = SF_EXEC|SF_MMAP;
fitzhardinge98abfc72003-12-16 02:05:15 +00002515
nethercote71980f02004-01-24 18:18:54 +00002516 if (filename != NULL)
2517 flags |= SF_FILE;
fitzhardinge98abfc72003-12-16 02:05:15 +00002518
nethercote71980f02004-01-24 18:18:54 +00002519 if (start >= VG_(valgrind_base) && (start+size) <= VG_(valgrind_end))
2520 flags |= SF_VALGRIND;
fitzhardinge98abfc72003-12-16 02:05:15 +00002521
nethercote71980f02004-01-24 18:18:54 +00002522 VG_(map_file_segment)(start, size, prot, flags, dev, ino, foffset, filename);
fitzhardinge98abfc72003-12-16 02:05:15 +00002523
nethercote71980f02004-01-24 18:18:54 +00002524 if (VG_(is_client_addr)(start) && VG_(is_client_addr)(start+size-1))
2525 VG_TRACK( new_mem_startup, start, size, rr=='r', ww=='w', xx=='x' );
sewardj3e1eb1f2002-05-18 13:14:17 +00002526
nethercote71980f02004-01-24 18:18:54 +00002527 /* If this is the stack segment mark all below %esp as noaccess. */
2528 r_esp = esp_at_startup___global_arg;
2529 vg_assert(0 != r_esp);
2530 if (is_stack_segment) {
2531 if (0)
2532 VG_(message)(Vg_DebugMsg, "invalidating stack area: %x .. %x",
2533 start,r_esp);
2534 VG_TRACK( die_mem_stack, start, r_esp-start );
sewardjde4a1d02002-03-22 01:27:54 +00002535 }
sewardjde4a1d02002-03-22 01:27:54 +00002536}
2537
2538
nethercote71980f02004-01-24 18:18:54 +00002539/*====================================================================*/
2540/*=== Sanity check machinery (permanently engaged) ===*/
2541/*====================================================================*/
njn25e49d8e72002-09-23 09:36:25 +00002542
2543/* A fast sanity check -- suitable for calling circa once per
2544 millisecond. */
2545
2546void VG_(do_sanity_checks) ( Bool force_expensive )
2547{
njn37cea302002-09-30 11:24:00 +00002548 VGP_PUSHCC(VgpCoreCheapSanity);
2549
nethercote27fec902004-06-16 21:26:32 +00002550 if (VG_(clo_sanity_level) < 1) return;
njn25e49d8e72002-09-23 09:36:25 +00002551
2552 /* --- First do all the tests that we can do quickly. ---*/
2553
2554 VG_(sanity_fast_count)++;
2555
njn25e49d8e72002-09-23 09:36:25 +00002556 /* Check stuff pertaining to the memory check system. */
2557
2558 /* Check that nobody has spuriously claimed that the first or
2559 last 16 pages of memory have become accessible [...] */
njn37cea302002-09-30 11:24:00 +00002560 if (VG_(needs).sanity_checks) {
2561 VGP_PUSHCC(VgpSkinCheapSanity);
njn25e49d8e72002-09-23 09:36:25 +00002562 vg_assert(SK_(cheap_sanity_check)());
njn37cea302002-09-30 11:24:00 +00002563 VGP_POPCC(VgpSkinCheapSanity);
2564 }
njn25e49d8e72002-09-23 09:36:25 +00002565
2566 /* --- Now some more expensive checks. ---*/
2567
2568 /* Once every 25 times, check some more expensive stuff. */
2569 if ( force_expensive
nethercote27fec902004-06-16 21:26:32 +00002570 || VG_(clo_sanity_level) > 1
2571 || (VG_(clo_sanity_level) == 1 && (VG_(sanity_fast_count) % 25) == 0)) {
njn25e49d8e72002-09-23 09:36:25 +00002572
njn37cea302002-09-30 11:24:00 +00002573 VGP_PUSHCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002574 VG_(sanity_slow_count)++;
2575
jsgf855d93d2003-10-13 22:26:55 +00002576 VG_(proxy_sanity)();
2577
njn25e49d8e72002-09-23 09:36:25 +00002578# if 0
2579 { void zzzmemscan(void); zzzmemscan(); }
2580# endif
2581
2582 if ((VG_(sanity_fast_count) % 250) == 0)
2583 VG_(sanity_check_tc_tt)();
2584
2585 if (VG_(needs).sanity_checks) {
njn37cea302002-09-30 11:24:00 +00002586 VGP_PUSHCC(VgpSkinExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002587 vg_assert(SK_(expensive_sanity_check)());
njn37cea302002-09-30 11:24:00 +00002588 VGP_POPCC(VgpSkinExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002589 }
2590 /*
2591 if ((VG_(sanity_fast_count) % 500) == 0) VG_(mallocSanityCheckAll)();
2592 */
njn37cea302002-09-30 11:24:00 +00002593 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002594 }
2595
nethercote27fec902004-06-16 21:26:32 +00002596 if (VG_(clo_sanity_level) > 1) {
njn37cea302002-09-30 11:24:00 +00002597 VGP_PUSHCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002598 /* Check sanity of the low-level memory manager. Note that bugs
2599 in the client's code can cause this to fail, so we don't do
2600 this check unless specially asked for. And because it's
2601 potentially very expensive. */
2602 VG_(mallocSanityCheckAll)();
njn37cea302002-09-30 11:24:00 +00002603 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002604 }
njn37cea302002-09-30 11:24:00 +00002605 VGP_POPCC(VgpCoreCheapSanity);
njn25e49d8e72002-09-23 09:36:25 +00002606}
nethercote71980f02004-01-24 18:18:54 +00002607
2608
2609/*====================================================================*/
2610/*=== main() ===*/
2611/*====================================================================*/
2612
2613int main(int argc, char **argv)
2614{
2615 char **cl_argv;
2616 const char *tool = NULL;
2617 const char *exec = NULL;
2618 char *preload; /* tool-specific LD_PRELOAD .so */
2619 char **env;
nethercote6c999f22004-01-31 22:55:15 +00002620 Int need_help = 0; // 0 = no, 1 = --help, 2 = --help-debug
nethercote71980f02004-01-24 18:18:54 +00002621 struct exeinfo info;
2622 ToolInfo *toolinfo = NULL;
2623 void *tool_dlhandle;
2624 Addr client_eip;
2625 Addr esp_at_startup; /* client's %esp at the point we gained control. */
2626 UInt * client_auxv;
2627 VgSchedReturnCode src;
nethercote47dd12c2004-06-22 14:18:42 +00002628 Int exitcode = 0;
fitzhardingeb50068f2004-02-24 23:42:55 +00002629 vki_rlimit zero = { 0, 0 };
nethercote71980f02004-01-24 18:18:54 +00002630
2631 //============================================================
2632 // Nb: startup is complex. Prerequisites are shown at every step.
2633 //
2634 // *** Be very careful when messing with the order ***
2635 //============================================================
2636
nethercotef4928da2004-06-15 10:54:40 +00002637 //============================================================
2638 // Command line argument handling order:
2639 // * If --help/--help-debug are present, show usage message
2640 // (if --tool is also present, that includes the tool-specific usage)
2641 // * Then, if --tool is missing, abort with error msg
2642 // * Then, if client is missing, abort with error msg
2643 // * Then, if any cmdline args are bad, abort with error msg
2644 //============================================================
2645
fitzhardingeb50068f2004-02-24 23:42:55 +00002646 // Get the current process datasize rlimit, and set it to zero.
2647 // This prevents any internal uses of brk() from having any effect.
2648 // We remember the old value so we can restore it on exec, so that
2649 // child processes will have a reasonable brk value.
2650 VG_(getrlimit)(VKI_RLIMIT_DATA, &VG_(client_rlimit_data));
2651 zero.rlim_max = VG_(client_rlimit_data).rlim_max;
2652 VG_(setrlimit)(VKI_RLIMIT_DATA, &zero);
2653
nethercote71980f02004-01-24 18:18:54 +00002654 //--------------------------------------------------------------
2655 // Check we were launched by stage1
2656 // p: n/a [must be first step]
2657 //--------------------------------------------------------------
2658 scan_auxv();
2659
2660 if (0) {
2661 int prmap(void *start, void *end, const char *perm, off_t off,
2662 int maj, int min, int ino) {
2663 printf("mapping %10p-%10p %s %02x:%02x %d\n",
2664 start, end, perm, maj, min, ino);
2665 return True;
2666 }
2667 printf("========== main() ==========\n");
2668 foreach_map(prmap);
2669 }
2670
2671 //--------------------------------------------------------------
2672 // Look for alternative libdir
2673 // p: n/a
2674 //--------------------------------------------------------------
2675 { char *cp = getenv(VALGRINDLIB);
2676 if (cp != NULL)
2677 VG_(libdir) = cp;
2678 }
2679
2680 //--------------------------------------------------------------
2681 // Begin working out address space layout
2682 // p: n/a
2683 //--------------------------------------------------------------
2684 layout_client_space( (Addr) & argc );
2685
2686 //--------------------------------------------------------------
2687 // Get valgrind args + client args (inc. from VALGRIND_OPTS/.valgrindrc).
2688 // Pre-process the command line.
2689 // p: n/a
2690 //--------------------------------------------------------------
2691 get_command_line(argc, argv, &VG_(vg_argc), &VG_(vg_argv), &cl_argv);
2692 pre_process_cmd_line_options(&need_help, &tool, &exec);
2693
2694 //==============================================================
2695 // Nb: once a tool is specified, the tool.so must be loaded even if
2696 // they specified --help or didn't specify a client program.
2697 //==============================================================
2698
2699 //--------------------------------------------------------------
2700 // With client padded out, map in tool
2701 // p: layout_client_space() [for padding]
2702 // p: set-libdir [for VG_(libdir)]
2703 // p: pre_process_cmd_line_options() [for 'tool']
2704 //--------------------------------------------------------------
2705 load_tool(tool, &tool_dlhandle, &toolinfo, &preload);
2706
2707 //==============================================================
2708 // Can use VG_(malloc)() and VG_(arena_malloc)() only after load_tool()
2709 // -- redzone size is now set.
2710 //==============================================================
2711
2712 //--------------------------------------------------------------
2713 // Finalise address space layout
2714 // p: layout_client_space(), load_tool() [for 'toolinfo']
2715 //--------------------------------------------------------------
2716 layout_remaining_space( toolinfo->shadow_ratio );
2717
2718 //--------------------------------------------------------------
2719 // Load client executable, finding in $PATH if necessary
2720 // p: layout_client_space() [so there's space]
2721 // p: pre_process_cmd_line_options() [for 'exec', 'need_help']
2722 // p: layout_remaining_space [so there's space]
2723 //--------------------------------------------------------------
nethercotef4928da2004-06-15 10:54:40 +00002724 load_client(cl_argv, exec, need_help, &info, &client_eip);
nethercote71980f02004-01-24 18:18:54 +00002725
2726 //--------------------------------------------------------------
2727 // Everything in place, unpad us
2728 // p: layout_remaining_space() [everything must be mapped in before now]
2729 // p: load_client() [ditto]
2730 //--------------------------------------------------------------
2731 as_unpad((void *)VG_(shadow_end), (void *)~0);
2732 as_closepadfile(); /* no more padding */
2733
2734 //--------------------------------------------------------------
2735 // Set up client's environment
2736 // p: set-libdir [for VG_(libdir)]
2737 // p: load_tool() [for 'preload']
2738 //--------------------------------------------------------------
2739 env = fix_environment(environ, preload);
2740
2741 //--------------------------------------------------------------
nethercote5ee67ca2004-06-22 14:00:09 +00002742 // Setup client stack, eip, and VG_(client_arg[cv])
nethercote71980f02004-01-24 18:18:54 +00002743 // p: load_client() [for 'info']
2744 // p: fix_environment() [for 'env']
2745 //--------------------------------------------------------------
2746 esp_at_startup = setup_client_stack(cl_argv, env, &info, &client_auxv);
2747
2748 if (0)
2749 printf("entry=%x client esp=%x vg_argc=%d brkbase=%x\n",
2750 client_eip, esp_at_startup, VG_(vg_argc), VG_(brk_base));
2751
2752 //==============================================================
2753 // Finished setting up operating environment. Now initialise
2754 // Valgrind. (This is where the old VG_(main)() started.)
2755 //==============================================================
2756
2757 //--------------------------------------------------------------
2758 // Read /proc/self/maps into a buffer
2759 // p: all memory layout, environment setup [so memory maps are right]
2760 //--------------------------------------------------------------
2761 VG_(read_procselfmaps)();
2762
2763 //--------------------------------------------------------------
2764 // atfork
2765 // p: n/a
2766 //--------------------------------------------------------------
2767 VG_(atfork)(NULL, NULL, newpid);
2768 newpid(VG_INVALID_THREADID);
2769
2770 //--------------------------------------------------------------
2771 // setup file descriptors
2772 // p: n/a
2773 //--------------------------------------------------------------
2774 setup_file_descriptors();
2775
2776 //--------------------------------------------------------------
2777 // Setup tool
2778 // p: VG_(read_procselfmaps)() [so if sk_pre_clo_init calls
2779 // VG_(malloc), any mmap'd superblocks aren't erroneously
2780 // identified later as being owned by the client]
2781 // XXX: is that necessary, now that we look for V's segments separately?
2782 // XXX: alternatively, if sk_pre_clo_init does use VG_(malloc)(), is it
2783 // wrong to ignore any segments that might add in parse_procselfmaps?
nethercote5ee67ca2004-06-22 14:00:09 +00002784 // p: setup_client_stack() [for 'VG_(client_arg[cv]']
nethercote71980f02004-01-24 18:18:54 +00002785 //--------------------------------------------------------------
2786 (*toolinfo->sk_pre_clo_init)();
2787 VG_(tool_init_dlsym)(tool_dlhandle);
2788 VG_(sanity_check_needs)();
2789
2790 //--------------------------------------------------------------
nethercotef4928da2004-06-15 10:54:40 +00002791 // If --tool and --help/--help-debug was given, now give the core+tool
2792 // help message
2793 // p: pre_clo_init()
2794 //--------------------------------------------------------------
2795 if (need_help) {
2796 usage(/*--help-debug?*/2 == need_help);
2797 }
2798
2799 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002800 // Process Valgrind's + tool's command-line options
2801 // p: load_tool() [for 'tool']
nethercote71980f02004-01-24 18:18:54 +00002802 // p: setup_file_descriptors() [for 'VG_(max_fd)']
2803 // p: sk_pre_clo_init [to set 'command_line_options' need]
2804 //--------------------------------------------------------------
nethercote5ee67ca2004-06-22 14:00:09 +00002805 process_cmd_line_options(client_auxv, tool);
nethercote71980f02004-01-24 18:18:54 +00002806
2807 //--------------------------------------------------------------
2808 // Allow GDB attach
2809 // p: process_cmd_line_options() [for VG_(clo_wait_for_gdb)]
2810 //--------------------------------------------------------------
2811 /* Hook to delay things long enough so we can get the pid and
2812 attach GDB in another shell. */
2813 if (VG_(clo_wait_for_gdb)) {
2814 VG_(printf)("pid=%d\n", VG_(getpid)());
2815 /* do "jump *$eip" to skip this in gdb */
2816 VG_(do_syscall)(__NR_pause);
2817 }
2818
2819 //--------------------------------------------------------------
2820 // Setup tool, post command-line processing
2821 // p: process_cmd_line_options [tool assumes it]
2822 //--------------------------------------------------------------
2823 SK_(post_clo_init)();
2824
2825 //--------------------------------------------------------------
nethercote1d447092004-02-01 17:29:59 +00002826 // Set up baseBlock
nethercote71980f02004-01-24 18:18:54 +00002827 // p: {pre,post}_clo_init() [for tool helper registration]
2828 // load_client() [for 'client_eip']
2829 // setup_client_stack() [for 'esp_at_startup']
2830 //--------------------------------------------------------------
2831 init_baseBlock(client_eip, esp_at_startup);
2832
2833 //--------------------------------------------------------------
2834 // Search for file descriptors that are inherited from our parent
2835 // p: process_cmd_line_options [for VG_(clo_track_fds)]
2836 //--------------------------------------------------------------
2837 if (VG_(clo_track_fds))
2838 VG_(init_preopened_fds)();
2839
2840 //--------------------------------------------------------------
2841 // Initialise the scheduler
2842 // p: init_baseBlock() [baseBlock regs copied into VG_(threads)[1]]
2843 // p: setup_file_descriptors() [else VG_(safe_fd)() breaks]
2844 //--------------------------------------------------------------
2845 VG_(scheduler_init)();
2846
2847 //--------------------------------------------------------------
2848 // Set up the ProxyLWP machinery
2849 // p: VG_(scheduler_init)()? [XXX: subtle dependency?]
2850 // - subs: VG_(sigstartup_actions)()?
2851 //--------------------------------------------------------------
2852 VG_(proxy_init)();
2853
2854 //--------------------------------------------------------------
2855 // Initialise the signal handling subsystem
2856 // p: VG_(atfork)(NULL, NULL, newpid) [else problems with sigmasks]
2857 // p: VG_(proxy_init)() [else breaks...]
2858 //--------------------------------------------------------------
2859 // Nb: temporarily parks the saved blocking-mask in saved_sigmask.
2860 VG_(sigstartup_actions)();
2861
2862 //--------------------------------------------------------------
2863 // Perhaps we're profiling Valgrind?
2864 // p: process_cmd_line_options() [for VG_(clo_profile)]
2865 // p: others?
2866 //
2867 // XXX: this seems to be broken? It always says the tool wasn't built
2868 // for profiling; vg_profile.c's functions don't seem to be overriding
2869 // vg_dummy_profile.c's?
2870 //
2871 // XXX: want this as early as possible. Looking for --profile
2872 // in pre_process_cmd_line_options() could get it earlier.
2873 //--------------------------------------------------------------
2874 if (VG_(clo_profile))
2875 VGP_(init_profiling)();
2876
2877 VGP_PUSHCC(VgpStartup);
2878
2879 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002880 // Reserve Valgrind's kickstart, heap and stack
2881 // p: XXX ???
2882 //--------------------------------------------------------------
2883 VG_(map_segment)(VG_(valgrind_mmap_end),
2884 VG_(valgrind_end)-VG_(valgrind_mmap_end),
2885 VKI_PROT_NONE, SF_VALGRIND|SF_FIXED);
2886
2887 //--------------------------------------------------------------
2888 // Identify Valgrind's segments
2889 // p: read proc/self/maps
2890 // p: VG_(map_segment) [XXX ???]
2891 // p: sk_pre_clo_init() [to setup new_mem_startup tracker]
2892 //--------------------------------------------------------------
2893 VG_(parse_procselfmaps) ( build_valgrind_map_callback );
2894
2895 // XXX: I can't see why these two need to be separate; could they be
2896 // folded together? If not, need a comment explaining why.
2897 //
2898 // XXX: can we merge reading and parsing of /proc/self/maps?
2899 //
2900 // XXX: can we dynamically allocate the /proc/self/maps buffer? (or mmap
2901 // it?) Or does that disturb its contents...
2902
2903 //--------------------------------------------------------------
2904 // Build segment map (all segments)
2905 // p: setup_client_stack() [for 'esp_at_startup']
2906 //--------------------------------------------------------------
2907 esp_at_startup___global_arg = esp_at_startup;
2908 VG_(parse_procselfmaps) ( build_segment_map_callback ); /* everything */
2909 esp_at_startup___global_arg = 0;
2910
2911 //==============================================================
2912 // Can only use VG_(map)() after VG_(map_segment)() [XXX ???]
2913 //==============================================================
2914
2915 //--------------------------------------------------------------
2916 // Build segment map (all segments)
2917 // p: setup_client_stack() [for 'esp_at_startup']
2918 //--------------------------------------------------------------
2919 /* Initialize our trampoline page (which is also sysinfo stuff) */
2920 VG_(memcpy)( (void *)VG_(client_trampoline_code),
2921 &VG_(trampoline_code_start), VG_(trampoline_code_length) );
2922 VG_(mprotect)( (void *)VG_(client_trampoline_code),
2923 VG_(trampoline_code_length), VKI_PROT_READ|VKI_PROT_EXEC );
2924
2925 //--------------------------------------------------------------
2926 // Read suppression file
2927 // p: process_cmd_line_options() [for VG_(clo_suppressions)]
2928 //--------------------------------------------------------------
2929 if (VG_(needs).core_errors || VG_(needs).skin_errors)
2930 VG_(load_suppressions)();
2931
2932 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002933 // Initialise translation table and translation cache
2934 // p: read_procselfmaps [so the anonymous mmaps for the TT/TC
2935 // aren't identified as part of the client, which would waste
2936 // > 20M of virtual address space.]
2937 //--------------------------------------------------------------
2938 VG_(init_tt_tc)();
2939
2940 //--------------------------------------------------------------
2941 // Read debug info to find glibc entry points to intercept
2942 // p: parse_procselfmaps? [XXX for debug info?]
2943 // p: init_tt_tc? [XXX ???]
2944 //--------------------------------------------------------------
2945 VG_(setup_code_redirect_table)();
2946
2947 //--------------------------------------------------------------
2948 // Verbosity message
2949 // p: end_rdtsc_calibration [so startup message is printed first]
2950 //--------------------------------------------------------------
2951 if (VG_(clo_verbosity) == 1)
2952 VG_(message)(Vg_UserMsg, "For more details, rerun with: -v");
2953 if (VG_(clo_verbosity) > 0)
2954 VG_(message)(Vg_UserMsg, "");
2955
2956 //--------------------------------------------------------------
2957 // Setup pointercheck
2958 // p: process_cmd_line_options() [for VG_(clo_pointercheck)]
2959 //--------------------------------------------------------------
2960 setup_pointercheck();
2961
2962
2963
2964 //--------------------------------------------------------------
2965 // Run!
2966 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002967 VGP_POPCC(VgpStartup);
2968 VGP_PUSHCC(VgpSched);
2969
2970 if (__builtin_setjmp(&VG_(fatal_signal_jmpbuf)) == 0) {
2971 VG_(fatal_signal_set) = True;
nethercote47dd12c2004-06-22 14:18:42 +00002972 src = VG_(scheduler)( &exitcode );
nethercote71980f02004-01-24 18:18:54 +00002973 } else
2974 src = VgSrc_FatalSig;
2975
2976 VGP_POPCC(VgpSched);
nethercote71980f02004-01-24 18:18:54 +00002977
2978
2979
2980 //--------------------------------------------------------------
2981 // Finalisation: cleanup, messages, etc. Order no so important, only
2982 // affects what order the messages come.
2983 //--------------------------------------------------------------
2984 if (VG_(clo_verbosity) > 0)
2985 VG_(message)(Vg_UserMsg, "");
2986
2987 if (src == VgSrc_Deadlock) {
2988 VG_(message)(Vg_UserMsg,
2989 "Warning: pthread scheduler exited due to deadlock");
2990 }
2991
2992 /* Print out file descriptor summary and stats. */
2993 if (VG_(clo_track_fds))
2994 VG_(fd_stats)();
2995
2996 if (VG_(needs).core_errors || VG_(needs).skin_errors)
2997 VG_(show_all_errors)();
2998
nethercote47dd12c2004-06-22 14:18:42 +00002999 SK_(fini)( exitcode );
nethercote71980f02004-01-24 18:18:54 +00003000
3001 VG_(do_sanity_checks)( True /*include expensive checks*/ );
3002
3003 if (VG_(clo_verbosity) > 1)
3004 show_counts();
3005
3006 if (VG_(clo_verbosity) > 3)
3007 VG_(print_UInstr_histogram)();
3008
3009 if (0) {
3010 VG_(message)(Vg_DebugMsg, "");
3011 VG_(message)(Vg_DebugMsg,
3012 "------ Valgrind's internal memory use stats follow ------" );
3013 VG_(mallocSanityCheckAll)();
3014 VG_(show_all_arena_stats)();
3015 VG_(message)(Vg_DebugMsg,
3016 "------ Valgrind's ExeContext management stats follow ------" );
3017 VG_(show_ExeContext_stats)();
3018 }
3019
3020 if (VG_(clo_profile))
3021 VGP_(done_profiling)();
3022
nethercote71980f02004-01-24 18:18:54 +00003023 /* We're exiting, so nuke all the threads and clean up the proxy LWPs */
3024 vg_assert(src == VgSrc_FatalSig ||
3025 VG_(threads)[VG_(last_run_tid)].status == VgTs_Runnable ||
3026 VG_(threads)[VG_(last_run_tid)].status == VgTs_WaitJoiner);
3027 VG_(nuke_all_threads_except)(VG_INVALID_THREADID);
3028
3029 //--------------------------------------------------------------
3030 // Exit, according to the scheduler's return code
3031 //--------------------------------------------------------------
3032 switch (src) {
3033 case VgSrc_ExitSyscall: /* the normal way out */
3034 vg_assert(VG_(last_run_tid) > 0
3035 && VG_(last_run_tid) < VG_N_THREADS);
3036 VG_(proxy_shutdown)();
3037
3038 /* The thread's %EBX at the time it did __NR_exit() will hold
3039 the arg to __NR_exit(), so we just do __NR_exit() with
3040 that arg. */
nethercote47dd12c2004-06-22 14:18:42 +00003041 VG_(exit)( exitcode );
nethercote71980f02004-01-24 18:18:54 +00003042 /* NOT ALIVE HERE! */
3043 VG_(core_panic)("entered the afterlife in main() -- ExitSyscall");
3044 break; /* what the hell :) */
3045
3046 case VgSrc_Deadlock:
3047 /* Just exit now. No point in continuing. */
3048 VG_(proxy_shutdown)();
3049 VG_(exit)(0);
3050 VG_(core_panic)("entered the afterlife in main() -- Deadlock");
3051 break;
3052
nethercote71980f02004-01-24 18:18:54 +00003053 case VgSrc_FatalSig:
3054 /* We were killed by a fatal signal, so replicate the effect */
3055 vg_assert(VG_(fatal_sigNo) != -1);
3056 VG_(kill_self)(VG_(fatal_sigNo));
3057 VG_(core_panic)("main(): signal was supposed to be fatal");
3058 break;
3059
3060 default:
3061 VG_(core_panic)("main(): unexpected scheduler return code");
3062 }
3063
3064 abort();
3065}
3066
3067
sewardjde4a1d02002-03-22 01:27:54 +00003068/*--------------------------------------------------------------------*/
3069/*--- end vg_main.c ---*/
3070/*--------------------------------------------------------------------*/