blob: a02b930000cd1d09d82e620c34e062efd3fbd7fd [file] [log] [blame]
sewardjde4a1d02002-03-22 01:27:54 +00001
2/*--------------------------------------------------------------------*/
nethercote71980f02004-01-24 18:18:54 +00003/*--- Startup: the real stuff vg_main.c ---*/
sewardjde4a1d02002-03-22 01:27:54 +00004/*--------------------------------------------------------------------*/
5
6/*
njnc9539842002-10-02 13:26:35 +00007 This file is part of Valgrind, an extensible x86 protected-mode
8 emulator for monitoring program execution on x86-Unixes.
sewardjde4a1d02002-03-22 01:27:54 +00009
nethercotebb1c9912004-01-04 16:43:23 +000010 Copyright (C) 2000-2004 Julian Seward
sewardjde4a1d02002-03-22 01:27:54 +000011 jseward@acm.org
sewardjde4a1d02002-03-22 01:27:54 +000012
13 This program is free software; you can redistribute it and/or
14 modify it under the terms of the GNU General Public License as
15 published by the Free Software Foundation; either version 2 of the
16 License, or (at your option) any later version.
17
18 This program is distributed in the hope that it will be useful, but
19 WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 General Public License for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software
25 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
26 02111-1307, USA.
27
njn25e49d8e72002-09-23 09:36:25 +000028 The GNU General Public License is contained in the file COPYING.
sewardjde4a1d02002-03-22 01:27:54 +000029*/
30
nethercote71980f02004-01-24 18:18:54 +000031#define _FILE_OFFSET_BITS 64
sewardjde4a1d02002-03-22 01:27:54 +000032
nethercote71980f02004-01-24 18:18:54 +000033#include "vg_include.h"
34#include "ume.h"
35#include "ume_arch.h"
36#include "ume_archdefs.h"
37
38#include <dirent.h>
39#include <dlfcn.h>
40#include <errno.h>
41#include <fcntl.h>
42#include <stdio.h>
fitzhardingeb727d042004-01-06 00:18:21 +000043#include <stdlib.h>
nethercote71980f02004-01-24 18:18:54 +000044#include <string.h>
45#include <sys/mman.h>
46#include <sys/types.h>
47#include <sys/stat.h>
fitzhardingeb727d042004-01-06 00:18:21 +000048#include <sys/ptrace.h>
49#include <sys/signal.h>
fitzhardingeb727d042004-01-06 00:18:21 +000050#include <sys/wait.h>
51#include <unistd.h>
52
thughes74b8de22004-04-22 18:12:31 +000053#ifndef AT_DCACHEBSIZE
54#define AT_DCACHEBSIZE 19
55#endif /* AT_DCACHEBSIZE */
56
57#ifndef AT_ICACHEBSIZE
58#define AT_ICACHEBSIZE 20
59#endif /* AT_ICACHEBSIZE */
60
61#ifndef AT_UCACHEBSIZE
62#define AT_UCACHEBSIZE 21
63#endif /* AT_UCACHEBSIZE */
64
nethercote71980f02004-01-24 18:18:54 +000065#ifndef AT_SYSINFO
66#define AT_SYSINFO 32
67#endif /* AT_SYSINFO */
68
69#ifndef AT_SYSINFO_EHDR
70#define AT_SYSINFO_EHDR 33
71#endif /* AT_SYSINFO_EHDR */
72
73#ifndef AT_SECURE
74#define AT_SECURE 23 /* secure mode boolean */
75#endif /* AT_SECURE */
76
77/* Amount to reserve for Valgrind's internal heap */
78#define VALGRIND_HEAPSIZE (128*1024*1024)
79
80/* Amount to reserve for Valgrind's internal mappings */
81#define VALGRIND_MAPSIZE (128*1024*1024)
82
83/* redzone gap between client address space and shadow */
84#define REDZONE_SIZE (1 * 1024*1024)
85
86/* size multiple for client address space */
87#define CLIENT_SIZE_MULTIPLE (64 * 1024*1024)
88
89#define ISSPACE(cc) ((cc) == ' ' || (cc) == '\t' || (cc) == '\n')
90
91/*====================================================================*/
92/*=== Global entities not referenced from generated code ===*/
93/*====================================================================*/
94
sewardjde4a1d02002-03-22 01:27:54 +000095/* ---------------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +000096 Startup stuff
sewardjde4a1d02002-03-22 01:27:54 +000097 ------------------------------------------------------------------ */
nethercote71980f02004-01-24 18:18:54 +000098/* linker-defined base address */
99extern char kickstart_base;
sewardjde4a1d02002-03-22 01:27:54 +0000100
nethercote71980f02004-01-24 18:18:54 +0000101/* Client address space, lowest to highest (see top of ume.c) */
102Addr VG_(client_base); /* client address space limits */
fitzhardinge98abfc72003-12-16 02:05:15 +0000103Addr VG_(client_end);
104Addr VG_(client_mapbase);
fitzhardinge92360792003-12-24 10:11:11 +0000105Addr VG_(client_trampoline_code);
fitzhardinge98abfc72003-12-16 02:05:15 +0000106Addr VG_(clstk_base);
107Addr VG_(clstk_end);
nethercote71980f02004-01-24 18:18:54 +0000108
109Addr VG_(brk_base); /* start of brk */
110Addr VG_(brk_limit); /* current brk */
111
112Addr VG_(shadow_base); /* skin's shadow memory */
fitzhardinge98abfc72003-12-16 02:05:15 +0000113Addr VG_(shadow_end);
nethercote71980f02004-01-24 18:18:54 +0000114
115Addr VG_(valgrind_base); /* valgrind's address range */
116Addr VG_(valgrind_mmap_end); /* valgrind's mmaps are between valgrind_base and here */
fitzhardinge98abfc72003-12-16 02:05:15 +0000117Addr VG_(valgrind_end);
118
fitzhardingeb50068f2004-02-24 23:42:55 +0000119vki_rlimit VG_(client_rlimit_data);
120
nethercote71980f02004-01-24 18:18:54 +0000121/* This is set early to indicate whether this CPU has the
122 SSE/fxsave/fxrestor features. */
123Bool VG_(have_ssestate);
124
125/* Indicates presence, and holds address of client's sysinfo page, a
126 feature of some modern kernels used to provide vsyscalls, etc. */
127Bool VG_(sysinfo_page_exists) = False;
128Addr VG_(sysinfo_page_addr) = 0;
129
fitzhardinge98abfc72003-12-16 02:05:15 +0000130/* stage1 (main) executable */
fitzhardingea49f9b52003-12-16 22:26:45 +0000131Int VG_(vgexecfd) = -1;
132
133/* client executable */
134Int VG_(clexecfd) = -1;
fitzhardinge98abfc72003-12-16 02:05:15 +0000135
136/* Path to library directory */
137const Char *VG_(libdir) = VG_LIBDIR;
138
139/* our argc/argv */
140Int VG_(vg_argc);
141Char **VG_(vg_argv);
142
jsgf855d93d2003-10-13 22:26:55 +0000143/* PID of the main thread */
144Int VG_(main_pid);
145
146/* PGRP of process */
147Int VG_(main_pgrp);
njn25e49d8e72002-09-23 09:36:25 +0000148
fitzhardingef0046f22003-12-18 02:39:22 +0000149/* Maximum allowed application-visible file descriptor */
fitzhardingeb791a192003-12-18 07:22:44 +0000150Int VG_(max_fd) = -1;
fitzhardingef0046f22003-12-18 02:39:22 +0000151
nethercote71980f02004-01-24 18:18:54 +0000152/* As deduced from esp_at_startup, the client's argc, argv[] and
153 envp[] as extracted from the client's stack at startup-time. */
154Int VG_(client_argc);
155Char** VG_(client_argv);
156Char** VG_(client_envp);
sewardjde4a1d02002-03-22 01:27:54 +0000157
158/* ---------------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +0000159 Running stuff
sewardjde4a1d02002-03-22 01:27:54 +0000160 ------------------------------------------------------------------ */
nethercote71980f02004-01-24 18:18:54 +0000161/* Our signal delivery stack. */
njn6eba4ef2003-05-01 08:06:41 +0000162UInt VG_(sigstack)[VG_SIGSTACK_SIZE_W];
sewardjde4a1d02002-03-22 01:27:54 +0000163
164/* Saving stuff across system calls. */
sewardjb91ae7f2003-04-29 23:50:00 +0000165__attribute__ ((aligned (16)))
166UInt VG_(real_sse_state_saved_over_syscall)[VG_SIZE_OF_SSESTATE_W];
sewardj43c356f2002-06-02 00:21:08 +0000167Addr VG_(esp_saved_over_syscall);
sewardjde4a1d02002-03-22 01:27:54 +0000168
nethercote71980f02004-01-24 18:18:54 +0000169/* jmp_buf for fatal signals */
170Int VG_(fatal_sigNo) = -1;
171Bool VG_(fatal_signal_set) = False;
172jmp_buf VG_(fatal_signal_jmpbuf);
sewardjde4a1d02002-03-22 01:27:54 +0000173
nethercote71980f02004-01-24 18:18:54 +0000174/* Counts downwards in VG_(run_innerloop). */
175UInt VG_(dispatch_ctr);
sewardjde4a1d02002-03-22 01:27:54 +0000176
177/* 64-bit counter for the number of basic blocks done. */
178ULong VG_(bbs_done);
sewardjde4a1d02002-03-22 01:27:54 +0000179
sewardj7e87e382002-05-03 19:09:05 +0000180/* This is the ThreadId of the last thread the scheduler ran. */
181ThreadId VG_(last_run_tid) = 0;
182
nethercote71980f02004-01-24 18:18:54 +0000183/* Tell the logging mechanism whether we are logging to a file
184 descriptor or a socket descriptor. */
185Bool VG_(logging_to_filedes) = True;
186
187/* This Bool is needed by wrappers in vg_clientmalloc.c to decide how
188 to behave. Initially we say False. */
189Bool VG_(running_on_simd_CPU) = False;
190
njn25e49d8e72002-09-23 09:36:25 +0000191/* This is the argument to __NR_exit() supplied by the first thread to
192 call that syscall. We eventually pass that to __NR_exit() for
193 real. */
njn633de322003-05-12 20:40:13 +0000194Int VG_(exitcode) = 0;
njn25e49d8e72002-09-23 09:36:25 +0000195
sewardj73cf3bc2002-11-03 03:20:15 +0000196
nethercote71980f02004-01-24 18:18:54 +0000197/*====================================================================*/
198/*=== Counters, for profiling purposes only ===*/
199/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +0000200
201/* Number of lookups which miss the fast tt helper. */
202UInt VG_(tt_fast_misses) = 0;
203
204
sewardjc0d8f682002-11-30 00:49:43 +0000205/* Counts for TT/TC informational messages. */
sewardjde4a1d02002-03-22 01:27:54 +0000206
sewardjde4a1d02002-03-22 01:27:54 +0000207/* Number and total o/t size of translations overall. */
208UInt VG_(overall_in_count) = 0;
209UInt VG_(overall_in_osize) = 0;
210UInt VG_(overall_in_tsize) = 0;
211/* Number and total o/t size of discards overall. */
212UInt VG_(overall_out_count) = 0;
213UInt VG_(overall_out_osize) = 0;
214UInt VG_(overall_out_tsize) = 0;
sewardjc0d8f682002-11-30 00:49:43 +0000215/* The number of discards of TT/TC. */
216UInt VG_(number_of_tc_discards) = 0;
sewardj22854b92002-11-30 14:00:47 +0000217/* Counts of chain and unchain operations done. */
218UInt VG_(bb_enchain_count) = 0;
219UInt VG_(bb_dechain_count) = 0;
220/* Number of unchained jumps performed. */
221UInt VG_(unchained_jumps_done) = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000222
223
224/* Counts pertaining to the register allocator. */
225
226/* total number of uinstrs input to reg-alloc */
227UInt VG_(uinstrs_prealloc) = 0;
228
229/* total number of uinstrs added due to spill code */
230UInt VG_(uinstrs_spill) = 0;
231
232/* number of bbs requiring spill code */
233UInt VG_(translations_needing_spill) = 0;
234
235/* total of register ranks over all translations */
236UInt VG_(total_reg_rank) = 0;
237
238
sewardjde4a1d02002-03-22 01:27:54 +0000239/* Counts pertaining to internal sanity checking. */
sewardjde4a1d02002-03-22 01:27:54 +0000240UInt VG_(sanity_fast_count) = 0;
241UInt VG_(sanity_slow_count) = 0;
242
sewardj2e93c502002-04-12 11:12:52 +0000243/* Counts pertaining to the scheduler. */
244UInt VG_(num_scheduling_events_MINOR) = 0;
245UInt VG_(num_scheduling_events_MAJOR) = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000246
247
nethercote71980f02004-01-24 18:18:54 +0000248static __inline__ Int safe_idiv(Int a, Int b)
249{
250 return (b == 0 ? 0 : a / b);
251}
252
253static void show_counts ( void )
254{
255 VG_(message)(Vg_DebugMsg,
256 " TT/TC: %d tc sectors discarded.",
257 VG_(number_of_tc_discards) );
258 VG_(message)(Vg_DebugMsg,
259 " %d chainings, %d unchainings.",
260 VG_(bb_enchain_count), VG_(bb_dechain_count) );
261 VG_(message)(Vg_DebugMsg,
262 "translate: new %d (%d -> %d; ratio %d:10)",
263 VG_(overall_in_count),
264 VG_(overall_in_osize),
265 VG_(overall_in_tsize),
266 safe_idiv(10*VG_(overall_in_tsize), VG_(overall_in_osize)));
267 VG_(message)(Vg_DebugMsg,
268 " discard %d (%d -> %d; ratio %d:10).",
269 VG_(overall_out_count),
270 VG_(overall_out_osize),
271 VG_(overall_out_tsize),
272 safe_idiv(10*VG_(overall_out_tsize), VG_(overall_out_osize)));
273 VG_(message)(Vg_DebugMsg,
274 " dispatch: %llu jumps (bb entries), of which %u (%lu%%) were unchained.",
275 VG_(bbs_done),
276 VG_(unchained_jumps_done),
277 ((ULong)(100) * (ULong)(VG_(unchained_jumps_done)))
278 / ( VG_(bbs_done)==0 ? 1 : VG_(bbs_done) )
279 );
280
281 VG_(message)(Vg_DebugMsg,
282 " %d/%d major/minor sched events. %d tt_fast misses.",
283 VG_(num_scheduling_events_MAJOR),
284 VG_(num_scheduling_events_MINOR),
285 VG_(tt_fast_misses));
286
287 VG_(message)(Vg_DebugMsg,
288 "reg-alloc: %d t-req-spill, "
289 "%d+%d orig+spill uis, %d total-reg-r.",
290 VG_(translations_needing_spill),
291 VG_(uinstrs_prealloc),
292 VG_(uinstrs_spill),
293 VG_(total_reg_rank) );
294 VG_(message)(Vg_DebugMsg,
295 " sanity: %d cheap, %d expensive checks.",
296 VG_(sanity_fast_count),
297 VG_(sanity_slow_count) );
298 VG_(print_ccall_stats)();
299}
300
301
302/*====================================================================*/
303/*=== Miscellaneous global functions ===*/
304/*====================================================================*/
305
nethercote04d0fbc2004-01-26 16:48:06 +0000306/* Start debugger and get it to attach to this process. Called if the
307 user requests this service after an error has been shown, so she can
nethercote71980f02004-01-24 18:18:54 +0000308 poke around and look at parameters, memory, etc. You can't
nethercote04d0fbc2004-01-26 16:48:06 +0000309 meaningfully get the debugger to continue the program, though; to
310 continue, quit the debugger. */
311void VG_(start_debugger) ( Int tid )
nethercote71980f02004-01-24 18:18:54 +0000312{
313 Int pid;
314
315 if ((pid = fork()) == 0) {
316 ptrace(PTRACE_TRACEME, 0, NULL, NULL);
317 VG_(kkill)(VG_(getpid)(), VKI_SIGSTOP);
318
319 } else if (pid > 0) {
320 struct user_regs_struct regs;
321 Int status;
322 Int res;
323
324 if (VG_(is_running_thread)( tid )) {
fitzhardinged65dcad2004-03-13 02:06:58 +0000325 regs.cs = VG_(baseBlock)[VGOFF_(m_cs)];
326 regs.ss = VG_(baseBlock)[VGOFF_(m_ss)];
327 regs.ds = VG_(baseBlock)[VGOFF_(m_ds)];
328 regs.es = VG_(baseBlock)[VGOFF_(m_es)];
329 regs.fs = VG_(baseBlock)[VGOFF_(m_fs)];
330 regs.gs = VG_(baseBlock)[VGOFF_(m_gs)];
nethercote71980f02004-01-24 18:18:54 +0000331 regs.eax = VG_(baseBlock)[VGOFF_(m_eax)];
332 regs.ebx = VG_(baseBlock)[VGOFF_(m_ebx)];
333 regs.ecx = VG_(baseBlock)[VGOFF_(m_ecx)];
334 regs.edx = VG_(baseBlock)[VGOFF_(m_edx)];
335 regs.esi = VG_(baseBlock)[VGOFF_(m_esi)];
336 regs.edi = VG_(baseBlock)[VGOFF_(m_edi)];
337 regs.ebp = VG_(baseBlock)[VGOFF_(m_ebp)];
338 regs.esp = VG_(baseBlock)[VGOFF_(m_esp)];
339 regs.eflags = VG_(baseBlock)[VGOFF_(m_eflags)];
340 regs.eip = VG_(baseBlock)[VGOFF_(m_eip)];
341 } else {
342 ThreadState* tst = & VG_(threads)[ tid ];
343
fitzhardinged65dcad2004-03-13 02:06:58 +0000344 regs.cs = tst->m_cs;
345 regs.ss = tst->m_ss;
346 regs.ds = tst->m_ds;
347 regs.es = tst->m_es;
348 regs.fs = tst->m_fs;
349 regs.gs = tst->m_gs;
nethercote71980f02004-01-24 18:18:54 +0000350 regs.eax = tst->m_eax;
351 regs.ebx = tst->m_ebx;
352 regs.ecx = tst->m_ecx;
353 regs.edx = tst->m_edx;
354 regs.esi = tst->m_esi;
355 regs.edi = tst->m_edi;
356 regs.ebp = tst->m_ebp;
357 regs.esp = tst->m_esp;
358 regs.eflags = tst->m_eflags;
359 regs.eip = tst->m_eip;
360 }
361
362 if ((res = VG_(waitpid)(pid, &status, 0)) == pid &&
363 WIFSTOPPED(status) && WSTOPSIG(status) == SIGSTOP &&
364 ptrace(PTRACE_SETREGS, pid, NULL, &regs) == 0 &&
thughes1d160052004-04-21 15:39:57 +0000365 kill(pid, SIGSTOP) == 0 &&
366 ptrace(PTRACE_DETACH, pid, NULL, 0) == 0) {
nethercote04d0fbc2004-01-26 16:48:06 +0000367 Char pidbuf[15];
368 Char file[30];
369 Char buf[100];
370 Char *bufptr;
371 Char *cmdptr;
372
373 VG_(sprintf)(pidbuf, "%d", pid);
374 VG_(sprintf)(file, "/proc/%d/fd/%d", pid, VG_(clexecfd));
375
376 bufptr = buf;
377 cmdptr = VG_(clo_db_command);
378
379 while (*cmdptr) {
380 switch (*cmdptr) {
381 case '%':
382 switch (*++cmdptr) {
383 case 'f':
384 VG_(memcpy)(bufptr, file, VG_(strlen)(file));
385 bufptr += VG_(strlen)(file);
386 cmdptr++;
387 break;
388 case 'p':
389 VG_(memcpy)(bufptr, pidbuf, VG_(strlen)(pidbuf));
390 bufptr += VG_(strlen)(pidbuf);
391 cmdptr++;
392 break;
393 default:
394 *bufptr++ = *cmdptr++;
395 break;
396 }
397 break;
398 default:
399 *bufptr++ = *cmdptr++;
400 break;
401 }
402 }
403
404 *bufptr++ = '\0';
405
406 VG_(message)(Vg_UserMsg, "starting debugger with cmd: %s", buf);
nethercote71980f02004-01-24 18:18:54 +0000407 res = VG_(system)(buf);
408 if (res == 0) {
409 VG_(message)(Vg_UserMsg, "");
410 VG_(message)(Vg_UserMsg,
nethercote04d0fbc2004-01-26 16:48:06 +0000411 "Debugger has detached. Valgrind regains control. We continue.");
nethercote71980f02004-01-24 18:18:54 +0000412 } else {
413 VG_(message)(Vg_UserMsg, "Apparently failed!");
414 VG_(message)(Vg_UserMsg, "");
415 }
416 }
417
418 VG_(kkill)(pid, VKI_SIGKILL);
419 VG_(waitpid)(pid, &status, 0);
420 }
421}
422
423
424/* Print some helpful-ish text about unimplemented things, and give
425 up. */
426void VG_(unimplemented) ( Char* msg )
427{
428 VG_(message)(Vg_UserMsg, "");
429 VG_(message)(Vg_UserMsg,
430 "Valgrind detected that your program requires");
431 VG_(message)(Vg_UserMsg,
432 "the following unimplemented functionality:");
433 VG_(message)(Vg_UserMsg, " %s", msg);
434 VG_(message)(Vg_UserMsg,
435 "This may be because the functionality is hard to implement,");
436 VG_(message)(Vg_UserMsg,
437 "or because no reasonable program would behave this way,");
438 VG_(message)(Vg_UserMsg,
439 "or because nobody has yet needed it. In any case, let us know at");
440 VG_(message)(Vg_UserMsg,
441 "%s and/or try to work around the problem, if you can.", VG_BUGS_TO);
442 VG_(message)(Vg_UserMsg,
443 "");
444 VG_(message)(Vg_UserMsg,
445 "Valgrind has to exit now. Sorry. Bye!");
446 VG_(message)(Vg_UserMsg,
447 "");
448 VG_(pp_sched_status)();
449 VG_(exit)(1);
450}
451
452Addr VG_(get_stack_pointer) ( void )
453{
454 return VG_(baseBlock)[VGOFF_(m_esp)];
455}
456
457/* Debugging thing .. can be called from assembly with OYNK macro. */
458void VG_(oynk) ( Int n )
459{
460 OINK(n);
461}
462
463/* Initialize the PID and PGRP of scheduler LWP; this is also called
464 in any new children after fork. */
465static void newpid(ThreadId unused)
466{
467 /* PID of scheduler LWP */
468 VG_(main_pid) = VG_(getpid)();
469 VG_(main_pgrp) = VG_(getpgrp)();
470}
471
472/*====================================================================*/
473/*=== Check we were launched by stage 1 ===*/
474/*====================================================================*/
475
476/* Look for our AUXV table */
477static void scan_auxv(void)
478{
479 const struct ume_auxv *auxv = find_auxv((int *)ume_exec_esp);
480 int found = 0;
481
482 for (; auxv->a_type != AT_NULL; auxv++)
483 switch(auxv->a_type) {
484 case AT_UME_PADFD:
485 as_setpadfd(auxv->u.a_val);
486 found |= 1;
487 break;
488
489 case AT_UME_EXECFD:
490 VG_(vgexecfd) = auxv->u.a_val;
491 found |= 2;
492 break;
493 }
494
495 if ( ! (1|2) ) {
496 fprintf(stderr, "stage2 must be launched by stage1\n");
497 exit(127);
498 }
499}
500
501
502/*====================================================================*/
503/*=== Address space determination ===*/
504/*====================================================================*/
505
506/* Pad client space so it doesn't get filled in before the right time */
507static void layout_client_space(Addr argc_addr)
508{
509 VG_(client_base) = CLIENT_BASE;
510 VG_(valgrind_mmap_end) = (addr_t)&kickstart_base; /* end of V's mmaps */
511 VG_(valgrind_base) = VG_(valgrind_mmap_end) - VALGRIND_MAPSIZE;
512 VG_(valgrind_end) = ROUNDUP(argc_addr, 0x10000); /* stack */
513
514 if (0)
515 printf("client base: %x\n"
516 "valgrind base--end: %x--%x (%x)\n"
517 "valgrind mmap end: %x\n\n",
518 VG_(client_base),
519 VG_(valgrind_base), VG_(valgrind_end),
520 VG_(valgrind_end) - VG_(valgrind_base),
521 VG_(valgrind_mmap_end));
522
523 as_pad((void *)VG_(client_base), (void *)VG_(valgrind_base));
524}
525
526static void layout_remaining_space(float ratio)
527{
528 /* This tries to give the client as large as possible address space while
529 * taking into account the tool's shadow needs. */
530 addr_t client_size = ROUNDDN((VG_(valgrind_base) - REDZONE_SIZE) / (1. + ratio),
531 CLIENT_SIZE_MULTIPLE);
532 addr_t shadow_size = PGROUNDUP(client_size * ratio);
533
534 VG_(client_end) = VG_(client_base) + client_size;
535 VG_(client_mapbase) = PGROUNDDN((client_size/4)*3); /* where !FIXED mmap goes */
536 VG_(client_trampoline_code) = VG_(client_end) - VKI_BYTES_PER_PAGE;
537
538 VG_(shadow_base) = VG_(client_end) + REDZONE_SIZE;
539 VG_(shadow_end) = VG_(shadow_base) + shadow_size;
540
541 if (0)
542 printf("client base--end: %x--%x (%x)\n"
543 "client mapbase: %x\n"
544 "shadow base--end: %x--%x (%x)\n\n",
545 VG_(client_base), VG_(client_end), client_size,
546 VG_(client_mapbase),
547 VG_(shadow_base), VG_(shadow_end), shadow_size);
548
549 // Ban redzone
550 mmap((void *)VG_(client_end), REDZONE_SIZE, PROT_NONE,
551 MAP_FIXED|MAP_ANON|MAP_PRIVATE, -1, 0);
552
553 // Make client hole
554 munmap((void*)VG_(client_base), client_size);
555
556 // Map shadow memory.
557 // Initially all inaccessible, incrementally initialized as it is used
558 if (shadow_size != 0)
559 mmap((char *)VG_(shadow_base), shadow_size, PROT_NONE,
560 MAP_PRIVATE|MAP_ANON|MAP_FIXED, -1, 0);
561}
562
563/*====================================================================*/
564/*=== Command line setup ===*/
565/*====================================================================*/
566
567/* Nb: malloc'd memory never freed -- kept throughout like argv, envp */
568static char* get_file_clo(char* dir)
569{
570# define FLEN 512
571 Int fd, n;
572 struct stat s1;
573 char* f_clo = NULL;
574 char filename[FLEN];
575
576 snprintf(filename, FLEN, "%s/.valgrindrc", ( NULL == dir ? "" : dir ) );
577 fd = VG_(open)(filename, 0, VKI_S_IRUSR);
578 if ( fd > 0 ) {
579 if ( 0 == fstat(fd, &s1) ) {
580 f_clo = malloc(s1.st_size+1);
581 vg_assert(f_clo);
582 n = read(fd, f_clo, s1.st_size);
583 if (n == -1) n = 0;
584 f_clo[n] = '\0';
585 }
586 close(fd);
587 }
588 return f_clo;
589# undef FLEN
590}
591
592static Int count_args(char* s)
593{
594 Int n = 0;
595 if (s) {
596 char* cp = s;
597 while (True) {
598 // We have alternating sequences: blanks, non-blanks, blanks...
599 // count the non-blanks sequences.
600 while ( ISSPACE(*cp) ) cp++;
601 if ( !*cp ) break;
602 n++;
603 while ( !ISSPACE(*cp) && *cp ) cp++;
604 }
605 }
606 return n;
607}
608
609/* add args out of environment, skipping multiple spaces and -- args */
610static char** copy_args( char* s, char** to )
611{
612 if (s) {
613 char* cp = s;
614 while (True) {
615 // We have alternating sequences: blanks, non-blanks, blanks...
616 // copy the non-blanks sequences, and add terminating '\0'
617 while ( ISSPACE(*cp) ) cp++;
618 if ( !*cp ) break;
619 *to++ = cp;
620 while ( !ISSPACE(*cp) && *cp ) cp++;
621 if ( *cp ) *cp++ = '\0'; // terminate if necessary
622 if (VG_STREQ(to[-1], "--")) to--; // undo any '--' arg
623 }
624 }
625 return to;
626}
627
628// Augment command line with arguments from environment and .valgrindrc
629// files.
630static void augment_command_line(Int* vg_argc_inout, char*** vg_argv_inout)
631{
632 int vg_argc = *vg_argc_inout;
633 char** vg_argv = *vg_argv_inout;
634
635 char* env_clo = getenv(VALGRINDOPTS);
636 char* f1_clo = get_file_clo( getenv("HOME") );
637 char* f2_clo = get_file_clo(".");
638
639 /* copy any extra args from file or environment, if present */
640 if ( (env_clo && *env_clo) || (f1_clo && *f1_clo) || (f2_clo && *f2_clo) ) {
641 /* ' ' separated extra options */
642 char **from;
643 char **to;
644 int env_arg_count, f1_arg_count, f2_arg_count;
645
646 env_arg_count = count_args(env_clo);
647 f1_arg_count = count_args(f1_clo);
648 f2_arg_count = count_args(f2_clo);
649
650 if (0)
651 printf("extra-argc=%d %d %d\n",
652 env_arg_count, f1_arg_count, f2_arg_count);
653
654 /* +2: +1 for null-termination, +1 for added '--' */
655 from = vg_argv;
656 vg_argv = malloc( (vg_argc + env_arg_count + f1_arg_count
657 + f2_arg_count + 2) * sizeof(char **));
658 to = vg_argv;
659
660 /* copy argv[0] */
661 *to++ = *from++;
662
663 /* Copy extra args from env var and file, in the order: ~/.valgrindrc,
664 * $VALGRIND_OPTS, ./.valgrindrc -- more local options are put later
665 * to override less local ones. */
666 to = copy_args(f1_clo, to);
667 to = copy_args(env_clo, to);
668 to = copy_args(f2_clo, to);
669
670 /* copy original arguments, stopping at command or -- */
671 while (*from) {
672 if (**from != '-')
673 break;
674 if (VG_STREQ(*from, "--")) {
675 from++; /* skip -- */
676 break;
677 }
678 *to++ = *from++;
679 }
680
681 /* add -- */
682 *to++ = "--";
683
684 vg_argc = to - vg_argv;
685
686 /* copy rest of original command line, then NULL */
687 while (*from) *to++ = *from++;
688 *to = NULL;
689 }
690
691 *vg_argc_inout = vg_argc;
692 *vg_argv_inout = vg_argv;
693}
694
695static void get_command_line( int argc, char** argv,
696 Int* vg_argc_out, Char*** vg_argv_out,
697 char*** cl_argv_out )
698{
699 int vg_argc;
700 char** vg_argv;
701 char** cl_argv;
702 char* env_clo = getenv(VALGRINDCLO);
703
704 if (env_clo != NULL && *env_clo != '\0') {
705 char *cp;
706 char **cpp;
707
708 /* OK, we're getting all our arguments from the environment - the
709 entire command line belongs to the client (including argv[0]) */
710 vg_argc = 1; /* argv[0] */
711 for (cp = env_clo; *cp; cp++)
712 if (*cp == '\01')
713 vg_argc++;
714
715 vg_argv = malloc(sizeof(char **) * (vg_argc + 1));
716
717 cpp = vg_argv;
718
719 *cpp++ = "valgrind"; /* nominal argv[0] */
720 *cpp++ = env_clo;
721
722 for (cp = env_clo; *cp; cp++) {
723 if (*cp == '\01') {
724 *cp++ = '\0'; /* chop it up in place */
725 *cpp++ = cp;
726 }
727 }
728 *cpp = NULL;
729 cl_argv = argv;
730
731 } else {
732 /* Count the arguments on the command line. */
733 vg_argv = argv;
734
735 for (vg_argc = 1; vg_argc < argc; vg_argc++) {
736 if (argv[vg_argc][0] != '-') /* exe name */
737 break;
738 if (VG_STREQ(argv[vg_argc], "--")) { /* dummy arg */
739 vg_argc++;
740 break;
741 }
742 }
743 cl_argv = &argv[vg_argc];
744
745 /* Get extra args from VALGRIND_OPTS and .valgrindrc files.
746 * Note we don't do this if getting args from VALGRINDCLO. */
747 augment_command_line(&vg_argc, &vg_argv);
748 }
749
750 if (0) {
751 Int i;
752 for (i = 0; i < vg_argc; i++)
753 printf("vg_argv[%d]=\"%s\"\n", i, vg_argv[i]);
754 }
755
756 *vg_argc_out = vg_argc;
757 *vg_argv_out = (Char**)vg_argv;
758 *cl_argv_out = cl_argv;
759}
760
761
762/*====================================================================*/
763/*=== Environment and stack setup ===*/
764/*====================================================================*/
765
766/* Scan a colon-separated list, and call a function on each element.
767 The string must be mutable, because we insert a temporary '\0', but
768 the string will end up unmodified. (*func) should return 1 if it
769 doesn't need to see any more.
770*/
771static void scan_colsep(char *colsep, int (*func)(const char *))
772{
773 char *cp, *entry;
774 int end;
775
776 if (colsep == NULL ||
777 *colsep == '\0')
778 return;
779
780 entry = cp = colsep;
781
782 do {
783 end = (*cp == '\0');
784
785 if (*cp == ':' || *cp == '\0') {
786 char save = *cp;
787
788 *cp = '\0';
789 if ((*func)(entry))
790 end = 1;
791 *cp = save;
792 entry = cp+1;
793 }
794 cp++;
795 } while(!end);
796}
797
798/* Prepare the client's environment. This is basically a copy of our
799 environment, except:
800 1. LD_LIBRARY_PATH=$VALGRINDLIB:$LD_LIBRARY_PATH
801 2. LD_PRELOAD=$VALGRINDLIB/vg_inject.so:($VALGRINDLIB/vgpreload_TOOL.so:)?$LD_PRELOAD
802
803 If any of these is missing, then it is added.
804
805 Yummy. String hacking in C.
806
807 If this needs to handle any more variables it should be hacked
808 into something table driven.
809 */
810static char **fix_environment(char **origenv, const char *preload)
811{
812 static const char inject_so[] = "vg_inject.so";
813 static const char ld_library_path[] = "LD_LIBRARY_PATH=";
814 static const char ld_preload[] = "LD_PRELOAD=";
815 static const char valgrind_clo[] = VALGRINDCLO "=";
816 static const int ld_library_path_len = sizeof(ld_library_path)-1;
817 static const int ld_preload_len = sizeof(ld_preload)-1;
818 static const int valgrind_clo_len = sizeof(valgrind_clo)-1;
819 int ld_preload_done = 0;
820 int ld_library_path_done = 0;
821 char *inject_path;
822 int inject_path_len;
823 int vgliblen = strlen(VG_(libdir));
824 char **cpp;
825 char **ret;
826 int envc;
827 const int preloadlen = (preload == NULL) ? 0 : strlen(preload);
828
829 /* Find the vg_inject.so; also make room for the tool preload
830 library */
831 inject_path_len = sizeof(inject_so) + vgliblen + preloadlen + 16;
832 inject_path = malloc(inject_path_len);
833
834 if (preload)
835 snprintf(inject_path, inject_path_len, "%s/%s:%s",
836 VG_(libdir), inject_so, preload);
837 else
838 snprintf(inject_path, inject_path_len, "%s/%s",
839 VG_(libdir), inject_so);
840
841 /* Count the original size of the env */
842 envc = 0; /* trailing NULL */
843 for (cpp = origenv; cpp && *cpp; cpp++)
844 envc++;
845
846 /* Allocate a new space */
847 ret = malloc(sizeof(char *) * (envc+3+1)); /* 3 new entries + NULL */
848
849 /* copy it over */
850 for (cpp = ret; *origenv; )
851 *cpp++ = *origenv++;
852 *cpp = NULL;
853
854 vg_assert(envc == (cpp - ret));
855
856 /* Walk over the new environment, mashing as we go */
857 for (cpp = ret; cpp && *cpp; cpp++) {
858 if (memcmp(*cpp, ld_library_path, ld_library_path_len) == 0) {
859 int done = 0;
860 int contains(const char *p) {
861 if (VG_STREQ(p, VG_(libdir))) {
862 done = 1;
863 return 1;
864 }
865 return 0;
866 }
867
868 /* If the LD_LIBRARY_PATH already contains libdir, then don't
869 bother adding it again, even if it isn't the first (it
870 seems that the Java runtime will keep reexecing itself
871 unless its paths are at the front of LD_LIBRARY_PATH) */
872 scan_colsep(*cpp + ld_library_path_len, contains);
873
874 if (!done) {
875 int len = strlen(*cpp) + vgliblen*2 + 16;
876 char *cp = malloc(len);
877
878 snprintf(cp, len, "%s%s:%s",
879 ld_library_path, VG_(libdir),
880 (*cpp)+ld_library_path_len);
881
882 *cpp = cp;
883 }
884
885 ld_library_path_done = 1;
886 } else if (memcmp(*cpp, ld_preload, ld_preload_len) == 0) {
887 int len = strlen(*cpp) + inject_path_len;
888 char *cp = malloc(len);
889
890 snprintf(cp, len, "%s%s:%s",
891 ld_preload, inject_path, (*cpp)+ld_preload_len);
892
893 *cpp = cp;
894
895 ld_preload_done = 1;
896 } else if (memcmp(*cpp, valgrind_clo, valgrind_clo_len) == 0) {
897 *cpp = "";
898 }
899 }
900
901 /* Add the missing bits */
902
903 if (!ld_library_path_done) {
904 int len = ld_library_path_len + vgliblen*2 + 16;
905 char *cp = malloc(len);
906
907 snprintf(cp, len, "%s%s", ld_library_path, VG_(libdir));
908
909 ret[envc++] = cp;
910 }
911
912 if (!ld_preload_done) {
913 int len = ld_preload_len + inject_path_len;
914 char *cp = malloc(len);
915
916 snprintf(cp, len, "%s%s",
917 ld_preload, inject_path);
918
919 ret[envc++] = cp;
920 }
921
922 ret[envc] = NULL;
923
924 return ret;
925}
926
927extern char **environ; /* our environment */
928//#include <error.h>
929
930/* Add a string onto the string table, and return its address */
931static char *copy_str(char **tab, const char *str)
932{
933 char *cp = *tab;
934 char *orig = cp;
935
936 while(*str)
937 *cp++ = *str++;
938 *cp++ = '\0';
939
940 if (0)
941 printf("copied %p \"%s\" len %d\n",
942 orig, orig, cp-orig);
943
944 *tab = cp;
945
946 return orig;
947}
948
949/*
950 This sets up the client's initial stack, containing the args,
951 environment and aux vector.
952
953 The format of the stack is:
954
955 higher address +-----------------+
956 | Trampoline code |
957 +-----------------+
958 | |
959 : string table :
960 | |
961 +-----------------+
962 | AT_NULL |
963 - -
964 | auxv |
965 +-----------------+
966 | NULL |
967 - -
968 | envp |
969 +-----------------+
970 | NULL |
971 - -
972 | argv |
973 +-----------------+
974 | argc |
975 lower address +-----------------+ <- esp
976 | undefined |
977 : :
978 */
979static Addr setup_client_stack(char **orig_argv, char **orig_envp,
980 const struct exeinfo *info,
981 UInt** client_auxv)
982{
983 char **cpp;
984 char *strtab; /* string table */
985 char *stringbase;
986 addr_t *ptr;
987 struct ume_auxv *auxv;
988 const struct ume_auxv *orig_auxv;
989 const struct ume_auxv *cauxv;
990 unsigned stringsize; /* total size of strings in bytes */
991 unsigned auxsize; /* total size of auxv in bytes */
992 int argc; /* total argc */
993 int envc; /* total number of env vars */
994 unsigned stacksize; /* total client stack size */
995 addr_t cl_esp; /* client stack base (initial esp) */
996
997 /* use our own auxv as a prototype */
998 orig_auxv = find_auxv(ume_exec_esp);
999
1000 /* ==================== compute sizes ==================== */
1001
1002 /* first of all, work out how big the client stack will be */
1003 stringsize = 0;
1004
1005 /* paste on the extra args if the loader needs them (ie, the #!
1006 interpreter and its argument) */
1007 argc = 0;
1008 if (info->argv0 != NULL) {
1009 argc++;
1010 stringsize += strlen(info->argv0) + 1;
1011 }
1012 if (info->argv1 != NULL) {
1013 argc++;
1014 stringsize += strlen(info->argv1) + 1;
1015 }
1016
1017 /* now scan the args we're given... */
1018 for (cpp = orig_argv; *cpp; cpp++) {
1019 argc++;
1020 stringsize += strlen(*cpp) + 1;
1021 }
1022
1023 /* ...and the environment */
1024 envc = 0;
1025 for (cpp = orig_envp; cpp && *cpp; cpp++) {
1026 envc++;
1027 stringsize += strlen(*cpp) + 1;
1028 }
1029
1030 /* now, how big is the auxv? */
1031 auxsize = sizeof(*auxv); /* there's always at least one entry: AT_NULL */
1032 for (cauxv = orig_auxv; cauxv->a_type != AT_NULL; cauxv++) {
1033 if (cauxv->a_type == AT_PLATFORM)
1034 stringsize += strlen(cauxv->u.a_ptr) + 1;
1035 auxsize += sizeof(*cauxv);
1036 }
1037
1038 /* OK, now we know how big the client stack is */
1039 stacksize =
1040 sizeof(int) + /* argc */
1041 sizeof(char **)*argc + /* argv */
1042 sizeof(char **) + /* terminal NULL */
1043 sizeof(char **)*envc + /* envp */
1044 sizeof(char **) + /* terminal NULL */
1045 auxsize + /* auxv */
1046 ROUNDUP(stringsize, sizeof(int)) +/* strings (aligned) */
1047 VKI_BYTES_PER_PAGE; /* page for trampoline code */
1048
1049 /* cl_esp is the client's stack pointer */
1050 cl_esp = VG_(client_end) - stacksize;
1051 cl_esp = ROUNDDN(cl_esp, 16); /* make stack 16 byte aligned */
1052
1053 if (0)
1054 printf("stringsize=%d auxsize=%d stacksize=%d\n",
1055 stringsize, auxsize, stacksize);
1056
1057
1058 /* base of the string table (aligned) */
1059 stringbase = strtab = (char *)(VG_(client_trampoline_code) - ROUNDUP(stringsize, sizeof(int)));
1060
1061 VG_(clstk_base) = PGROUNDDN(cl_esp);
1062 VG_(clstk_end) = VG_(client_end);
1063
1064 /* ==================== allocate space ==================== */
1065
1066 /* allocate a stack - mmap enough space for the stack */
1067 mmap((void *)PGROUNDDN(cl_esp),
1068 VG_(client_end) - PGROUNDDN(cl_esp),
1069 PROT_READ | PROT_WRITE | PROT_EXEC,
1070 MAP_PRIVATE | MAP_ANON | MAP_FIXED, -1, 0);
1071
1072
1073 /* ==================== copy client stack ==================== */
1074
1075 ptr = (addr_t *)cl_esp;
1076
1077 /* --- argc --- */
1078 *ptr++ = argc; /* client argc */
1079
1080 /* --- argv --- */
1081 if (info->argv0) {
1082 *ptr++ = (addr_t)copy_str(&strtab, info->argv0);
1083 free(info->argv0);
1084 }
1085 if (info->argv1) {
1086 *ptr++ = (addr_t)copy_str(&strtab, info->argv1);
1087 free(info->argv1);
1088 }
1089 for (cpp = orig_argv; *cpp; ptr++, cpp++) {
1090 *ptr = (addr_t)copy_str(&strtab, *cpp);
1091 }
1092 *ptr++ = 0;
1093
1094 /* --- envp --- */
1095 VG_(client_envp) = (Char **)ptr;
1096 for (cpp = orig_envp; cpp && *cpp; ptr++, cpp++)
1097 *ptr = (addr_t)copy_str(&strtab, *cpp);
1098 *ptr++ = 0;
1099
1100 /* --- auxv --- */
1101 auxv = (struct ume_auxv *)ptr;
1102 *client_auxv = (UInt *)auxv;
1103
1104 for (; orig_auxv->a_type != AT_NULL; auxv++, orig_auxv++) {
1105 /* copy the entry... */
1106 *auxv = *orig_auxv;
1107
1108 /* ...and fix up the copy */
1109 switch(auxv->a_type) {
1110 case AT_PHDR:
1111 if (info->phdr == 0)
1112 auxv->a_type = AT_IGNORE;
1113 else
1114 auxv->u.a_val = info->phdr;
1115 break;
1116
1117 case AT_PHNUM:
1118 if (info->phdr == 0)
1119 auxv->a_type = AT_IGNORE;
1120 else
1121 auxv->u.a_val = info->phnum;
1122 break;
1123
1124 case AT_BASE:
1125 if (info->interp_base == 0)
1126 auxv->a_type = AT_IGNORE;
1127 else
1128 auxv->u.a_val = info->interp_base;
1129 break;
1130
1131 case AT_PLATFORM: /* points to a platform description string */
1132 auxv->u.a_ptr = copy_str(&strtab, orig_auxv->u.a_ptr);
1133 break;
1134
1135 case AT_ENTRY:
1136 auxv->u.a_val = info->entry;
1137 break;
1138
1139 case AT_IGNORE:
1140 case AT_EXECFD:
1141 case AT_PHENT:
1142 case AT_PAGESZ:
1143 case AT_FLAGS:
1144 case AT_NOTELF:
1145 case AT_UID:
1146 case AT_EUID:
1147 case AT_GID:
1148 case AT_EGID:
1149 case AT_CLKTCK:
1150 case AT_HWCAP:
1151 case AT_FPUCW:
1152 case AT_DCACHEBSIZE:
1153 case AT_ICACHEBSIZE:
1154 case AT_UCACHEBSIZE:
1155 /* All these are pointerless, so we don't need to do anything
1156 about them. */
1157 break;
1158
1159 case AT_SECURE:
1160 /* If this is 1, then it means that this program is running
1161 suid, and therefore the dynamic linker should be careful
1162 about LD_PRELOAD, etc. However, since stage1 (the thing
1163 the kernel actually execve's) should never be SUID, and we
1164 need LD_PRELOAD/LD_LIBRARY_PATH to work for the client, we
1165 set AT_SECURE to 0. */
1166 auxv->u.a_val = 0;
1167 break;
1168
1169 case AT_SYSINFO:
1170 /* Leave this unmolested for now, but we'll update it later
1171 when we set up the client trampoline code page */
1172 break;
1173
1174 case AT_SYSINFO_EHDR:
1175 /* Trash this, because we don't reproduce it */
1176 auxv->a_type = AT_IGNORE;
1177 break;
1178
1179 default:
1180 /* stomp out anything we don't know about */
1181 if (0)
1182 printf("stomping auxv entry %d\n", auxv->a_type);
1183 auxv->a_type = AT_IGNORE;
1184 break;
1185
1186 }
1187 }
1188 *auxv = *orig_auxv;
1189 vg_assert(auxv->a_type == AT_NULL);
1190
1191 vg_assert((strtab-stringbase) == stringsize);
1192
1193 return cl_esp;
1194}
1195
1196/*====================================================================*/
1197/*=== Find executable ===*/
1198/*====================================================================*/
1199
1200static const char* find_executable(const char* exec)
1201{
1202 vg_assert(NULL != exec);
1203 if (strchr(exec, '/') == NULL) {
1204 /* no '/' - we need to search the path */
1205 char *path = getenv("PATH");
1206 int pathlen = path ? strlen(path) : 0;
1207
1208 int match_exe(const char *entry) {
1209 char buf[pathlen + strlen(entry) + 3];
1210
1211 /* empty PATH element means . */
1212 if (*entry == '\0')
1213 entry = ".";
1214
1215 snprintf(buf, sizeof(buf), "%s/%s", entry, exec);
1216
1217 if (access(buf, R_OK|X_OK) == 0) {
1218 exec = strdup(buf);
1219 vg_assert(NULL != exec);
1220 return 1;
1221 }
1222 return 0;
1223 }
1224 scan_colsep(path, match_exe);
1225 }
1226 return exec;
1227}
1228
1229
1230/*====================================================================*/
1231/*=== Loading tools ===*/
1232/*====================================================================*/
1233
1234static void list_tools(void)
1235{
1236 DIR *dir = opendir(VG_(libdir));
1237 struct dirent *de;
1238 int first = 1;
1239
1240 if (dir == NULL) {
1241 fprintf(stderr, "Can't open %s: %s (installation problem?)\n",
nethercotef4928da2004-06-15 10:54:40 +00001242 VG_(libdir), strerror(errno));
nethercote71980f02004-01-24 18:18:54 +00001243 return;
1244 }
1245
nethercotef4928da2004-06-15 10:54:40 +00001246 while ((de = readdir(dir)) != NULL) {
nethercote71980f02004-01-24 18:18:54 +00001247 int len = strlen(de->d_name);
1248
1249 /* look for vgskin_TOOL.so names */
1250 if (len > (7+1+3) && /* "vgskin_" + at least 1-char toolname + ".so" */
nethercotef4928da2004-06-15 10:54:40 +00001251 strncmp(de->d_name, "vgskin_", 7) == 0 &&
1252 VG_STREQ(de->d_name + len - 3, ".so")) {
1253 if (first) {
1254 fprintf(stderr, "Available tools:\n");
1255 first = 0;
1256 }
1257 de->d_name[len-3] = '\0';
1258 fprintf(stderr, "\t%s\n", de->d_name+7);
nethercote71980f02004-01-24 18:18:54 +00001259 }
1260 }
1261
1262 closedir(dir);
1263
1264 if (first)
nethercotef4928da2004-06-15 10:54:40 +00001265 fprintf(stderr, "No tools available in \"%s\" (installation problem?)\n",
1266 VG_(libdir));
nethercote71980f02004-01-24 18:18:54 +00001267}
1268
1269
1270/* Find and load a tool, and check it looks ok. Also looks to see if there's
1271 * a matching vgpreload_*.so file, and returns its name in *preloadpath. */
1272static void load_tool( const char *toolname, void** handle_out,
1273 ToolInfo** toolinfo_out, char **preloadpath_out )
1274{
1275 Bool ok;
1276 int len = strlen(VG_(libdir)) + strlen(toolname)*2 + 16;
1277 char buf[len];
1278 void* handle;
1279 ToolInfo* toolinfo;
1280 char* preloadpath = NULL;
1281 Int* vg_malloc_redzonep;
1282
1283 // XXX: allowing full paths for --tool option -- does it make sense?
1284 // Doesn't allow for vgpreload_<tool>.so.
1285
1286 if (strchr(toolname, '/') != 0) {
1287 /* toolname contains '/', and so must be a pathname */
1288 handle = dlopen(toolname, RTLD_NOW);
1289 } else {
1290 /* just try in the libdir */
1291 snprintf(buf, len, "%s/vgskin_%s.so", VG_(libdir), toolname);
1292 handle = dlopen(buf, RTLD_NOW);
1293
1294 if (handle != NULL) {
1295 snprintf(buf, len, "%s/vgpreload_%s.so", VG_(libdir), toolname);
1296 if (access(buf, R_OK) == 0) {
1297 preloadpath = strdup(buf);
1298 vg_assert(NULL != preloadpath);
1299 }
1300 }
1301 }
1302
1303 ok = (NULL != handle);
1304 if (!ok) {
1305 fprintf(stderr, "Can't open tool \"%s\": %s\n", toolname, dlerror());
1306 goto bad_load;
1307 }
1308
1309 toolinfo = dlsym(handle, "vgSkin_tool_info");
1310 ok = (NULL != toolinfo);
1311 if (!ok) {
1312 fprintf(stderr, "Tool \"%s\" doesn't define SK_(tool_info) - "
1313 "add VG_DETERMINE_INTERFACE_VERSION?\n", toolname);
1314 goto bad_load;
1315 }
1316
1317 ok = (toolinfo->sizeof_ToolInfo == sizeof(*toolinfo) &&
1318 toolinfo->interface_major_version == VG_CORE_INTERFACE_MAJOR_VERSION &&
1319 toolinfo->sk_pre_clo_init != NULL);
1320 if (!ok) {
1321 fprintf(stderr, "Error:\n"
1322 " Tool and core interface versions do not match.\n"
1323 " Interface version used by core is: %d.%d (size %d)\n"
1324 " Interface version used by tool is: %d.%d (size %d)\n"
1325 " The major version numbers must match.\n",
1326 VG_CORE_INTERFACE_MAJOR_VERSION,
1327 VG_CORE_INTERFACE_MINOR_VERSION,
1328 sizeof(*toolinfo),
1329 toolinfo->interface_major_version,
1330 toolinfo->interface_minor_version,
1331 toolinfo->sizeof_ToolInfo);
1332 fprintf(stderr, " You need to at least recompile, and possibly update,\n");
1333 if (VG_CORE_INTERFACE_MAJOR_VERSION > toolinfo->interface_major_version)
1334 fprintf(stderr, " your skin to work with this version of Valgrind.\n");
1335 else
1336 fprintf(stderr, " your version of Valgrind to work with this skin.\n");
1337 goto bad_load;
1338 }
1339
1340 // Set redzone size for V's allocator
1341 vg_malloc_redzonep = dlsym(handle, STR(VG_(vg_malloc_redzone_szB)));
1342 if ( NULL != vg_malloc_redzonep ) {
1343 VG_(vg_malloc_redzone_szB) = *vg_malloc_redzonep;
1344 }
1345
1346 vg_assert(NULL != handle && NULL != toolinfo);
1347 *handle_out = handle;
1348 *toolinfo_out = toolinfo;
1349 *preloadpath_out = preloadpath;
1350 return;
1351
1352
1353 bad_load:
1354 if (handle != NULL)
1355 dlclose(handle);
1356
nethercotef4928da2004-06-15 10:54:40 +00001357 fprintf(stderr, "valgrind: couldn't load tool\n");
nethercote71980f02004-01-24 18:18:54 +00001358 list_tools();
1359 exit(127);
1360}
1361
nethercotef4928da2004-06-15 10:54:40 +00001362
1363/*====================================================================*/
1364/*=== Command line errors ===*/
1365/*====================================================================*/
1366
1367static void abort_msg ( void )
1368{
1369 VG_(clo_log_to) = VgLogTo_Fd;
1370 VG_(clo_logfile_fd) = 2; /* stderr */
1371}
1372
1373void VG_(bad_option) ( Char* opt )
1374{
1375 abort_msg();
1376 VG_(printf)("valgrind: Bad option `%s'; aborting.\n", opt);
1377 VG_(printf)("valgrind: Use --help for more information.\n");
1378 VG_(exit)(1);
1379}
1380
1381static void missing_tool_option ( void )
1382{
1383 abort_msg();
1384 VG_(printf)("valgrind: Missing --tool option\n");
1385 list_tools();
1386 VG_(printf)("valgrind: Use --help for more information.\n");
1387 VG_(exit)(1);
1388}
1389
1390static void missing_prog ( void )
1391{
1392 abort_msg();
1393 VG_(printf)("valgrind: no program specified\n");
1394 VG_(printf)("valgrind: Use --help for more information.\n");
1395 VG_(exit)(1);
1396}
1397
1398static void config_error ( Char* msg )
1399{
1400 abort_msg();
1401 VG_(printf)("valgrind: Startup or configuration error:\n %s\n", msg);
1402 VG_(printf)("valgrind: Unable to start up properly. Giving up.\n");
1403 VG_(exit)(1);
1404}
1405
1406
nethercote71980f02004-01-24 18:18:54 +00001407/*====================================================================*/
1408/*=== Loading the client ===*/
1409/*====================================================================*/
1410
nethercotef4928da2004-06-15 10:54:40 +00001411static void load_client(char* cl_argv[], const char* exec, Int need_help,
nethercote71980f02004-01-24 18:18:54 +00001412 /*out*/struct exeinfo* info, /*out*/Addr* client_eip)
1413{
1414 // If they didn't specify an executable with --exec, and didn't specify
1415 // --help, then use client argv[0] (searching $PATH if necessary).
nethercotef4928da2004-06-15 10:54:40 +00001416 if (NULL == exec && !need_help) {
nethercote71980f02004-01-24 18:18:54 +00001417 if (cl_argv[0] == NULL ||
1418 ( NULL == (exec = find_executable(cl_argv[0])) ) )
1419 {
nethercotef4928da2004-06-15 10:54:40 +00001420 missing_prog();
nethercote71980f02004-01-24 18:18:54 +00001421 }
1422 }
1423
1424 info->map_base = VG_(client_mapbase);
nethercote71980f02004-01-24 18:18:54 +00001425
1426 info->exe_base = VG_(client_base);
1427 info->exe_end = VG_(client_end);
1428 info->argv = cl_argv;
1429
nethercotef4928da2004-06-15 10:54:40 +00001430 if (need_help) {
nethercote71980f02004-01-24 18:18:54 +00001431 VG_(clexecfd) = -1;
1432 info->argv0 = NULL;
1433 info->argv1 = NULL;
1434 } else {
1435 Int ret;
1436 VG_(clexecfd) = VG_(open)(exec, O_RDONLY, VKI_S_IRUSR);
1437 ret = do_exec(exec, info);
1438 if (ret != 0) {
nethercotef4928da2004-06-15 10:54:40 +00001439 fprintf(stderr, "valgrind: do_exec(%s) failed: %s\n", exec, strerror(ret));
nethercote71980f02004-01-24 18:18:54 +00001440 exit(127);
1441 }
1442 }
1443
1444 /* Copy necessary bits of 'info' that were filled in */
1445 *client_eip = info->init_eip;
1446 VG_(brk_base) = VG_(brk_limit) = info->brkbase;
1447}
1448
1449
1450/*====================================================================*/
1451/*=== Command-line: variables, processing ===*/
1452/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +00001453
njn25e49d8e72002-09-23 09:36:25 +00001454/* Define, and set defaults. */
1455Bool VG_(clo_error_limit) = True;
nethercote04d0fbc2004-01-26 16:48:06 +00001456Bool VG_(clo_db_attach) = False;
1457Char* VG_(clo_db_command) = VG_CLO_DEFAULT_DBCOMMAND;
njn43c799e2003-04-08 00:08:52 +00001458Bool VG_(clo_gen_suppressions) = False;
njn25e49d8e72002-09-23 09:36:25 +00001459Int VG_(sanity_level) = 1;
1460Int VG_(clo_verbosity) = 1;
1461Bool VG_(clo_demangle) = True;
njn25e49d8e72002-09-23 09:36:25 +00001462Bool VG_(clo_trace_children) = False;
sewardj4cf05692002-10-27 20:28:29 +00001463
nethercotee1730692003-11-20 10:38:07 +00001464/* See big comment in vg_include.h for meaning of these three.
1465 fd is initially stdout, for --help, but gets moved to stderr by default
1466 immediately afterwards. */
sewardj4cf05692002-10-27 20:28:29 +00001467VgLogTo VG_(clo_log_to) = VgLogTo_Fd;
nethercotee1730692003-11-20 10:38:07 +00001468Int VG_(clo_logfile_fd) = 1;
sewardj4cf05692002-10-27 20:28:29 +00001469Char* VG_(clo_logfile_name) = NULL;
1470
sewardj6024b212003-07-13 10:54:33 +00001471Int VG_(clo_input_fd) = 0; /* stdin */
njn25e49d8e72002-09-23 09:36:25 +00001472Int VG_(clo_n_suppressions) = 0;
sewardjde4a1d02002-03-22 01:27:54 +00001473Char* VG_(clo_suppressions)[VG_CLO_MAX_SFILES];
njn25e49d8e72002-09-23 09:36:25 +00001474Bool VG_(clo_profile) = False;
1475Bool VG_(clo_single_step) = False;
1476Bool VG_(clo_optimise) = True;
1477UChar VG_(clo_trace_codegen) = 0; // 00000000b
1478Bool VG_(clo_trace_syscalls) = False;
1479Bool VG_(clo_trace_signals) = False;
1480Bool VG_(clo_trace_symtab) = False;
njn25e49d8e72002-09-23 09:36:25 +00001481Bool VG_(clo_trace_sched) = False;
1482Int VG_(clo_trace_pthread_level) = 0;
njn25e49d8e72002-09-23 09:36:25 +00001483Int VG_(clo_dump_error) = 0;
1484Int VG_(clo_backtrace_size) = 4;
1485Char* VG_(clo_weird_hacks) = NULL;
sewardj858964b2002-10-05 14:15:43 +00001486Bool VG_(clo_run_libc_freeres) = True;
rjwalshf5f536f2003-11-17 17:45:00 +00001487Bool VG_(clo_track_fds) = False;
sewardj22854b92002-11-30 14:00:47 +00001488Bool VG_(clo_chain_bb) = True;
nethercote77eba602003-11-13 17:35:04 +00001489Bool VG_(clo_show_below_main) = False;
fitzhardinge98abfc72003-12-16 02:05:15 +00001490Bool VG_(clo_pointercheck) = True;
fitzhardinge462f4f92003-12-18 02:10:54 +00001491Bool VG_(clo_branchpred) = False;
sewardj2370f3b2002-11-30 15:01:01 +00001492
jsgf855d93d2003-10-13 22:26:55 +00001493static Bool VG_(clo_wait_for_gdb) = False;
1494
1495/* If we're doing signal routing, poll for signals every 50mS by
1496 default. */
1497Int VG_(clo_signal_polltime) = 50;
1498
1499/* These flags reduce thread wakeup latency on syscall completion and
1500 signal delivery, respectively. The downside is possible unfairness. */
1501Bool VG_(clo_lowlat_syscalls) = False; /* low-latency syscalls */
1502Bool VG_(clo_lowlat_signals) = False; /* low-latency signals */
1503
sewardjde4a1d02002-03-22 01:27:54 +00001504
nethercote6c999f22004-01-31 22:55:15 +00001505void usage ( Bool debug_help )
njn7cf0bd32002-06-08 13:36:03 +00001506{
njn25e49d8e72002-09-23 09:36:25 +00001507 Char* usage1 =
nethercote71980f02004-01-24 18:18:54 +00001508"usage: valgrind --tool=<toolname> [options] prog-and-args\n"
njn25e49d8e72002-09-23 09:36:25 +00001509"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001510" common user options for all Valgrind tools, with defaults in [ ]:\n"
nethercote71980f02004-01-24 18:18:54 +00001511" --tool=<name> Use the Valgrind tool named <name>\n"
njn25e49d8e72002-09-23 09:36:25 +00001512" --help show this message\n"
nethercote6c999f22004-01-31 22:55:15 +00001513" --help-debug show this message, plus debugging options\n"
njn25e49d8e72002-09-23 09:36:25 +00001514" --version show version\n"
njn25e49d8e72002-09-23 09:36:25 +00001515" -q --quiet run silently; only print error msgs\n"
1516" -v --verbose be more verbose, incl counts of errors\n"
nethercote77eba602003-11-13 17:35:04 +00001517" --trace-children=no|yes Valgrind-ise child processes? [no]\n"
rjwalshf5f536f2003-11-17 17:45:00 +00001518" --track-fds=no|yes Track open file descriptors? [no]\n"
nethercote2b0793f2003-12-02 10:41:18 +00001519"\n"
1520" uncommon user options for all Valgrind tools:\n"
nethercote77eba602003-11-13 17:35:04 +00001521" --run-libc-freeres=no|yes Free up glibc memory at exit? [yes]\n"
1522" --weird-hacks=hack1,hack2,... [none]\n"
sewardj3d652a32002-10-20 18:11:49 +00001523" recognised hacks are: ioctl-VTIME truncate-writes lax-ioctls\n"
jsgf855d93d2003-10-13 22:26:55 +00001524" --signal-polltime=<time> time, in mS, we should poll for signals.\n"
1525" Only applies for older kernels which need\n"
1526" signal routing [50]\n"
1527" --lowlat-signals=no|yes improve wake-up latency when a thread receives\n"
1528" a signal [no]\n"
1529" --lowlat-syscalls=no|yes improve wake-up latency when a thread's\n"
1530" syscall completes [no]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001531" --pointercheck=no|yes enforce client address space limits [yes]\n"
njn25e49d8e72002-09-23 09:36:25 +00001532"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001533" user options for Valgrind tools that report errors:\n"
1534" --logfile-fd=<number> file descriptor for messages [2=stderr]\n"
1535" --logfile=<file> log messages to <file>.pid<pid>\n"
1536" --logsocket=ipaddr:port log messages to socket ipaddr:port\n"
1537" --demangle=no|yes automatically demangle C++ names? [yes]\n"
1538" --num-callers=<number> show <num> callers in stack traces [4]\n"
1539" --error-limit=no|yes stop showing new errors if too many? [yes]\n"
1540" --show-below-main=no|yes continue stack traces below main() [no]\n"
1541" --suppressions=<filename> suppress errors described in <filename>\n"
1542" --gen-suppressions=no|yes print suppressions for errors detected [no]\n"
njn7cf0bd32002-06-08 13:36:03 +00001543
nethercote04d0fbc2004-01-26 16:48:06 +00001544" --db-attach=no|yes start debugger when errors detected? [no]\n"
1545" --db-command=<command> command to start debugger [gdb -nw %%f %%p]\n"
1546" --input-fd=<number> file descriptor for input [0=stdin]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001547"\n";
njn7cf0bd32002-06-08 13:36:03 +00001548
njn25e49d8e72002-09-23 09:36:25 +00001549 Char* usage2 =
1550"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001551" debugging options for all Valgrind tools:\n"
njn25e49d8e72002-09-23 09:36:25 +00001552" --sanity-level=<number> level of sanity checking to do [1]\n"
1553" --single-step=no|yes translate each instr separately? [no]\n"
1554" --optimise=no|yes improve intermediate code? [yes]\n"
nethercote137bc552003-11-14 17:47:54 +00001555" --profile=no|yes profile? (tool must be built for it) [no]\n"
sewardj22854b92002-11-30 14:00:47 +00001556" --chain-bb=no|yes do basic-block chaining? [yes]\n"
fitzhardinge462f4f92003-12-18 02:10:54 +00001557" --branchpred=yes|no generate branch prediction hints [no]\n"
njn25e49d8e72002-09-23 09:36:25 +00001558" --trace-codegen=<XXXXX> show generated code? (X = 0|1) [00000]\n"
1559" --trace-syscalls=no|yes show all system calls? [no]\n"
1560" --trace-signals=no|yes show signal handling details? [no]\n"
1561" --trace-symtab=no|yes show symbol table details? [no]\n"
njn25e49d8e72002-09-23 09:36:25 +00001562" --trace-sched=no|yes show thread scheduler details? [no]\n"
njn3e884182003-04-15 13:03:23 +00001563" --trace-pthread=none|some|all show pthread event details? [none]\n"
jsgf855d93d2003-10-13 22:26:55 +00001564" --wait-for-gdb=yes|no pause on startup to wait for gdb attach\n"
njn25e49d8e72002-09-23 09:36:25 +00001565"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001566" debugging options for Valgrind tools that report errors\n"
1567" --dump-error=<number> show translation for basic block associated\n"
1568" with <number>'th error context [0=show none]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001569"\n";
njn3e884182003-04-15 13:03:23 +00001570
1571 Char* usage3 =
1572"\n"
nethercote71980f02004-01-24 18:18:54 +00001573" Extra options read from ~/.valgrindrc, $VALGRIND_OPTS, ./.valgrindrc\n"
njn25e49d8e72002-09-23 09:36:25 +00001574"\n"
nethercotebb1c9912004-01-04 16:43:23 +00001575" Valgrind is Copyright (C) 2000-2004 Julian Seward\n"
njn25e49d8e72002-09-23 09:36:25 +00001576" and licensed under the GNU General Public License, version 2.\n"
1577" Bug reports, feedback, admiration, abuse, etc, to: %s.\n"
njnd04b7c62002-10-03 14:05:52 +00001578"\n"
nethercote137bc552003-11-14 17:47:54 +00001579" Tools are copyright and licensed by their authors. See each\n"
1580" tool's start-up message for more information.\n"
njn25e49d8e72002-09-23 09:36:25 +00001581"\n";
njn7cf0bd32002-06-08 13:36:03 +00001582
fitzhardinge98abfc72003-12-16 02:05:15 +00001583 VG_(printf)(usage1);
1584 if (VG_(details).name) {
1585 VG_(printf)(" user options for %s:\n", VG_(details).name);
fitzhardinge98abfc72003-12-16 02:05:15 +00001586 if (VG_(needs).command_line_options)
1587 SK_(print_usage)();
1588 else
1589 VG_(printf)(" (none)\n");
1590 }
nethercote6c999f22004-01-31 22:55:15 +00001591 if (debug_help) {
1592 VG_(printf)(usage2);
fitzhardinge98abfc72003-12-16 02:05:15 +00001593
nethercote6c999f22004-01-31 22:55:15 +00001594 if (VG_(details).name) {
1595 VG_(printf)(" debugging options for %s:\n", VG_(details).name);
1596
1597 if (VG_(needs).command_line_options)
1598 SK_(print_debug_usage)();
1599 else
1600 VG_(printf)(" (none)\n");
1601 }
fitzhardinge98abfc72003-12-16 02:05:15 +00001602 }
nethercote421281e2003-11-20 16:20:55 +00001603 VG_(printf)(usage3, VG_BUGS_TO);
nethercotef4928da2004-06-15 10:54:40 +00001604 VG_(exit)(0);
njn7cf0bd32002-06-08 13:36:03 +00001605}
sewardjde4a1d02002-03-22 01:27:54 +00001606
nethercote71980f02004-01-24 18:18:54 +00001607static void pre_process_cmd_line_options
nethercote6c999f22004-01-31 22:55:15 +00001608 ( Int* need_help, const char** tool, const char** exec )
sewardj1c1b1162003-02-23 01:25:51 +00001609{
nethercote71980f02004-01-24 18:18:54 +00001610 UInt i;
sewardjde4a1d02002-03-22 01:27:54 +00001611
nethercote71980f02004-01-24 18:18:54 +00001612 /* parse the options we have (only the options we care about now) */
1613 for (i = 1; i < VG_(vg_argc); i++) {
1614
1615 if (strcmp(VG_(vg_argv)[i], "--version") == 0) {
1616 printf("valgrind-" VERSION "\n");
nethercotef4928da2004-06-15 10:54:40 +00001617 exit(0);
nethercote71980f02004-01-24 18:18:54 +00001618
nethercotef4928da2004-06-15 10:54:40 +00001619 } else if (VG_CLO_STREQ(VG_(vg_argv)[i], "--help")) {
nethercote6c999f22004-01-31 22:55:15 +00001620 *need_help = 1;
1621
nethercotef4928da2004-06-15 10:54:40 +00001622 } else if (VG_CLO_STREQ(VG_(vg_argv)[i], "--help-debug")) {
nethercote6c999f22004-01-31 22:55:15 +00001623 *need_help = 2;
nethercote71980f02004-01-24 18:18:54 +00001624
nethercotef4928da2004-06-15 10:54:40 +00001625 } else if (VG_CLO_STREQN(7, VG_(vg_argv)[i], "--tool=") ||
1626 VG_CLO_STREQN(7, VG_(vg_argv)[i], "--skin=")) {
nethercote71980f02004-01-24 18:18:54 +00001627 *tool = &VG_(vg_argv)[i][7];
1628
nethercotef4928da2004-06-15 10:54:40 +00001629 } else if (VG_CLO_STREQN(7, VG_(vg_argv)[i], "--exec=")) {
nethercote71980f02004-01-24 18:18:54 +00001630 *exec = &VG_(vg_argv)[i][7];
1631 }
1632 }
1633
nethercotef4928da2004-06-15 10:54:40 +00001634 /* If no tool specified, can act appropriately without loading tool */
nethercote71980f02004-01-24 18:18:54 +00001635 if (*tool == NULL) {
nethercotef4928da2004-06-15 10:54:40 +00001636 if (0 == *need_help) {
1637 // neither --tool nor --help/--help-debug specified
1638 missing_tool_option();
1639 } else {
1640 // Give help message, without any tool-specific help
1641 usage(/*help-debug?*/2 == *need_help);
1642 }
nethercote71980f02004-01-24 18:18:54 +00001643 }
1644}
1645
nethercotef4928da2004-06-15 10:54:40 +00001646static void process_cmd_line_options
1647 ( UInt* client_auxv, Addr esp_at_startup, const char* toolname )
nethercote71980f02004-01-24 18:18:54 +00001648{
1649 Int i, eventually_logfile_fd;
1650 Int *auxp;
1651 Int toolname_len = VG_(strlen)(toolname);
sewardjde4a1d02002-03-22 01:27:54 +00001652
nethercotee1730692003-11-20 10:38:07 +00001653 /* log to stderr by default, but usage message goes to stdout */
1654 eventually_logfile_fd = 2;
sewardjde4a1d02002-03-22 01:27:54 +00001655
sewardj19d81412002-06-03 01:10:40 +00001656 /* Check for sane path in ./configure --prefix=... */
fitzhardinge98abfc72003-12-16 02:05:15 +00001657 if (VG_LIBDIR[0] != '/')
sewardj19d81412002-06-03 01:10:40 +00001658 config_error("Please use absolute paths in "
1659 "./configure --prefix=... or --libdir=...");
sewardj38170912002-05-10 21:07:22 +00001660
nethercote71980f02004-01-24 18:18:54 +00001661 for (auxp = client_auxv; auxp[0] != VKI_AT_NULL; auxp += 2) {
fitzhardinge98abfc72003-12-16 02:05:15 +00001662 switch(auxp[0]) {
1663 case VKI_AT_SYSINFO:
1664 VG_(sysinfo_page_exists) = True;
fitzhardinge92360792003-12-24 10:11:11 +00001665 auxp[1] = (Int)(VG_(client_trampoline_code) + VG_(tramp_syscall_offset));
fitzhardinge98abfc72003-12-16 02:05:15 +00001666 VG_(sysinfo_page_addr) = auxp[1];
1667 break;
sewardjde4a1d02002-03-22 01:27:54 +00001668 }
fitzhardinge98abfc72003-12-16 02:05:15 +00001669 }
sewardjde4a1d02002-03-22 01:27:54 +00001670
fitzhardinge98abfc72003-12-16 02:05:15 +00001671 /* We know the initial ESP is pointing at argc/argv */
nethercote71980f02004-01-24 18:18:54 +00001672 VG_(client_argc) = *(Int *)esp_at_startup;
1673 VG_(client_argv) = (Char **)(esp_at_startup + sizeof(Int));
fitzhardinge98abfc72003-12-16 02:05:15 +00001674
nethercote71980f02004-01-24 18:18:54 +00001675 for (i = 1; i < VG_(vg_argc); i++) {
1676
1677 Char* arg = VG_(vg_argv)[i];
1678
1679 // XXX: allow colons in options, for Josef
1680
1681 /* Look for matching "--toolname:foo" */
1682 if (VG_(strstr)(arg, ":")) {
1683 if (VG_CLO_STREQN(2, arg, "--") &&
1684 VG_CLO_STREQN(toolname_len, arg+2, toolname) &&
1685 VG_CLO_STREQN(1, arg+2+toolname_len, ":"))
1686 {
1687 // prefix matches, convert "--toolname:foo" to "--foo"
1688 if (0)
1689 VG_(printf)("tool-specific arg: %s\n", arg);
1690 arg += toolname_len + 1;
1691 arg[0] = '-';
1692 arg[1] = '-';
1693
1694 } else {
1695 // prefix doesn't match, skip to next arg
1696 continue;
1697 }
1698 }
1699
fitzhardinge98abfc72003-12-16 02:05:15 +00001700 /* Ignore these options - they've already been handled */
nethercote71980f02004-01-24 18:18:54 +00001701 if (VG_CLO_STREQN(7, arg, "--tool=") ||
1702 VG_CLO_STREQN(7, arg, "--skin="))
fitzhardinge98abfc72003-12-16 02:05:15 +00001703 continue;
nethercote71980f02004-01-24 18:18:54 +00001704 if (VG_CLO_STREQN(7, arg, "--exec="))
fitzhardinge98abfc72003-12-16 02:05:15 +00001705 continue;
1706
nethercote71980f02004-01-24 18:18:54 +00001707 if ( VG_CLO_STREQ(arg, "--"))
fitzhardinge98abfc72003-12-16 02:05:15 +00001708 continue;
nethercote71980f02004-01-24 18:18:54 +00001709 else if (VG_CLO_STREQ(arg, "-v") ||
1710 VG_CLO_STREQ(arg, "--verbose"))
sewardjde4a1d02002-03-22 01:27:54 +00001711 VG_(clo_verbosity)++;
nethercote71980f02004-01-24 18:18:54 +00001712 else if (VG_CLO_STREQ(arg, "-q") ||
1713 VG_CLO_STREQ(arg, "--quiet"))
sewardjde4a1d02002-03-22 01:27:54 +00001714 VG_(clo_verbosity)--;
1715
nethercote71980f02004-01-24 18:18:54 +00001716 else if (VG_CLO_STREQ(arg, "--error-limit=yes"))
sewardj2e432902002-06-13 20:44:00 +00001717 VG_(clo_error_limit) = True;
nethercote71980f02004-01-24 18:18:54 +00001718 else if (VG_CLO_STREQ(arg, "--error-limit=no"))
sewardj2e432902002-06-13 20:44:00 +00001719 VG_(clo_error_limit) = False;
sewardj72f98ff2002-06-13 17:23:38 +00001720
nethercote04d0fbc2004-01-26 16:48:06 +00001721 else if (VG_CLO_STREQ(arg, "--db-attach=yes"))
1722 VG_(clo_db_attach) = True;
1723 else if (VG_CLO_STREQ(arg, "--db-attach=no"))
1724 VG_(clo_db_attach) = False;
sewardjde4a1d02002-03-22 01:27:54 +00001725
nethercote04d0fbc2004-01-26 16:48:06 +00001726 else if (VG_CLO_STREQN(13,arg, "--db-command="))
1727 VG_(clo_db_command) = &arg[13];
sewardj6024b212003-07-13 10:54:33 +00001728
nethercote71980f02004-01-24 18:18:54 +00001729 else if (VG_CLO_STREQ(arg, "--gen-suppressions=yes"))
njn43c799e2003-04-08 00:08:52 +00001730 VG_(clo_gen_suppressions) = True;
nethercote71980f02004-01-24 18:18:54 +00001731 else if (VG_CLO_STREQ(arg, "--gen-suppressions=no"))
njn43c799e2003-04-08 00:08:52 +00001732 VG_(clo_gen_suppressions) = False;
1733
nethercote71980f02004-01-24 18:18:54 +00001734 else if (VG_CLO_STREQ(arg, "--show-below-main=yes"))
nethercote77eba602003-11-13 17:35:04 +00001735 VG_(clo_show_below_main) = True;
nethercote71980f02004-01-24 18:18:54 +00001736 else if (VG_CLO_STREQ(arg, "--show-below-main=no"))
nethercote77eba602003-11-13 17:35:04 +00001737 VG_(clo_show_below_main) = False;
1738
nethercote71980f02004-01-24 18:18:54 +00001739 else if (VG_CLO_STREQ(arg, "--pointercheck=yes"))
fitzhardinge98abfc72003-12-16 02:05:15 +00001740 VG_(clo_pointercheck) = True;
nethercote71980f02004-01-24 18:18:54 +00001741 else if (VG_CLO_STREQ(arg, "--pointercheck=no"))
fitzhardinge98abfc72003-12-16 02:05:15 +00001742 VG_(clo_pointercheck) = False;
1743
nethercote71980f02004-01-24 18:18:54 +00001744 else if (VG_CLO_STREQ(arg, "--demangle=yes"))
sewardjde4a1d02002-03-22 01:27:54 +00001745 VG_(clo_demangle) = True;
nethercote71980f02004-01-24 18:18:54 +00001746 else if (VG_CLO_STREQ(arg, "--demangle=no"))
sewardjde4a1d02002-03-22 01:27:54 +00001747 VG_(clo_demangle) = False;
1748
nethercote71980f02004-01-24 18:18:54 +00001749 else if (VG_CLO_STREQ(arg, "--trace-children=yes"))
sewardjde4a1d02002-03-22 01:27:54 +00001750 VG_(clo_trace_children) = True;
nethercote71980f02004-01-24 18:18:54 +00001751 else if (VG_CLO_STREQ(arg, "--trace-children=no"))
sewardjde4a1d02002-03-22 01:27:54 +00001752 VG_(clo_trace_children) = False;
1753
nethercote71980f02004-01-24 18:18:54 +00001754 else if (VG_CLO_STREQ(arg, "--run-libc-freeres=yes"))
sewardj858964b2002-10-05 14:15:43 +00001755 VG_(clo_run_libc_freeres) = True;
nethercote71980f02004-01-24 18:18:54 +00001756 else if (VG_CLO_STREQ(arg, "--run-libc-freeres=no"))
sewardj858964b2002-10-05 14:15:43 +00001757 VG_(clo_run_libc_freeres) = False;
1758
nethercote71980f02004-01-24 18:18:54 +00001759 else if (VG_CLO_STREQ(arg, "--track-fds=yes"))
rjwalshf5f536f2003-11-17 17:45:00 +00001760 VG_(clo_track_fds) = True;
nethercote71980f02004-01-24 18:18:54 +00001761 else if (VG_CLO_STREQ(arg, "--track-fds=no"))
rjwalshf5f536f2003-11-17 17:45:00 +00001762 VG_(clo_track_fds) = False;
1763
nethercote71980f02004-01-24 18:18:54 +00001764 else if (VG_CLO_STREQN(15, arg, "--sanity-level="))
1765 VG_(sanity_level) = (Int)VG_(atoll)(&arg[15]);
sewardjde4a1d02002-03-22 01:27:54 +00001766
nethercote71980f02004-01-24 18:18:54 +00001767 else if (VG_CLO_STREQN(13, arg, "--logfile-fd=")) {
sewardj4cf05692002-10-27 20:28:29 +00001768 VG_(clo_log_to) = VgLogTo_Fd;
1769 VG_(clo_logfile_name) = NULL;
nethercote71980f02004-01-24 18:18:54 +00001770 eventually_logfile_fd = (Int)VG_(atoll)(&arg[13]);
sewardj4cf05692002-10-27 20:28:29 +00001771 }
1772
nethercote71980f02004-01-24 18:18:54 +00001773 else if (VG_CLO_STREQN(10, arg, "--logfile=")) {
sewardj4cf05692002-10-27 20:28:29 +00001774 VG_(clo_log_to) = VgLogTo_File;
nethercote71980f02004-01-24 18:18:54 +00001775 VG_(clo_logfile_name) = &arg[10];
sewardj4cf05692002-10-27 20:28:29 +00001776 }
sewardjde4a1d02002-03-22 01:27:54 +00001777
nethercote71980f02004-01-24 18:18:54 +00001778 else if (VG_CLO_STREQN(12, arg, "--logsocket=")) {
sewardj73cf3bc2002-11-03 03:20:15 +00001779 VG_(clo_log_to) = VgLogTo_Socket;
nethercote71980f02004-01-24 18:18:54 +00001780 VG_(clo_logfile_name) = &arg[12];
sewardj73cf3bc2002-11-03 03:20:15 +00001781 }
1782
nethercote71980f02004-01-24 18:18:54 +00001783 else if (VG_CLO_STREQN(11, arg, "--input-fd="))
1784 VG_(clo_input_fd) = (Int)VG_(atoll)(&arg[11]);
sewardj6024b212003-07-13 10:54:33 +00001785
nethercote71980f02004-01-24 18:18:54 +00001786 else if (VG_CLO_STREQN(15, arg, "--suppressions=")) {
sewardjde4a1d02002-03-22 01:27:54 +00001787 if (VG_(clo_n_suppressions) >= VG_CLO_MAX_SFILES) {
njn25e49d8e72002-09-23 09:36:25 +00001788 VG_(message)(Vg_UserMsg, "Too many suppression files specified.");
sewardjde4a1d02002-03-22 01:27:54 +00001789 VG_(message)(Vg_UserMsg,
1790 "Increase VG_CLO_MAX_SFILES and recompile.");
nethercote71980f02004-01-24 18:18:54 +00001791 VG_(bad_option)(arg);
sewardjde4a1d02002-03-22 01:27:54 +00001792 }
nethercote71980f02004-01-24 18:18:54 +00001793 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = &arg[15];
sewardjde4a1d02002-03-22 01:27:54 +00001794 VG_(clo_n_suppressions)++;
1795 }
nethercote71980f02004-01-24 18:18:54 +00001796 else if (VG_CLO_STREQ(arg, "--profile=yes"))
njn25e49d8e72002-09-23 09:36:25 +00001797 VG_(clo_profile) = True;
nethercote71980f02004-01-24 18:18:54 +00001798 else if (VG_CLO_STREQ(arg, "--profile=no"))
njn25e49d8e72002-09-23 09:36:25 +00001799 VG_(clo_profile) = False;
1800
nethercote71980f02004-01-24 18:18:54 +00001801 else if (VG_CLO_STREQ(arg, "--chain-bb=yes"))
sewardj22854b92002-11-30 14:00:47 +00001802 VG_(clo_chain_bb) = True;
nethercote71980f02004-01-24 18:18:54 +00001803 else if (VG_CLO_STREQ(arg, "--chain-bb=no"))
sewardj22854b92002-11-30 14:00:47 +00001804 VG_(clo_chain_bb) = False;
1805
nethercote71980f02004-01-24 18:18:54 +00001806 else if (VG_CLO_STREQ(arg, "--branchpred=yes"))
fitzhardinge462f4f92003-12-18 02:10:54 +00001807 VG_(clo_branchpred) = True;
nethercote71980f02004-01-24 18:18:54 +00001808 else if (VG_CLO_STREQ(arg, "--branchpred=no"))
fitzhardinge462f4f92003-12-18 02:10:54 +00001809 VG_(clo_branchpred) = False;
1810
nethercote71980f02004-01-24 18:18:54 +00001811 else if (VG_CLO_STREQ(arg, "--single-step=yes"))
sewardjde4a1d02002-03-22 01:27:54 +00001812 VG_(clo_single_step) = True;
nethercote71980f02004-01-24 18:18:54 +00001813 else if (VG_CLO_STREQ(arg, "--single-step=no"))
sewardjde4a1d02002-03-22 01:27:54 +00001814 VG_(clo_single_step) = False;
1815
nethercote71980f02004-01-24 18:18:54 +00001816 else if (VG_CLO_STREQ(arg, "--optimise=yes"))
sewardjde4a1d02002-03-22 01:27:54 +00001817 VG_(clo_optimise) = True;
nethercote71980f02004-01-24 18:18:54 +00001818 else if (VG_CLO_STREQ(arg, "--optimise=no"))
sewardjde4a1d02002-03-22 01:27:54 +00001819 VG_(clo_optimise) = False;
1820
njn25e49d8e72002-09-23 09:36:25 +00001821 /* "vwxyz" --> 000zyxwv (binary) */
nethercote71980f02004-01-24 18:18:54 +00001822 else if (VG_CLO_STREQN(16, arg, "--trace-codegen=")) {
njn25e49d8e72002-09-23 09:36:25 +00001823 Int j;
nethercote71980f02004-01-24 18:18:54 +00001824 char* opt = & arg[16];
njn25e49d8e72002-09-23 09:36:25 +00001825
1826 if (5 != VG_(strlen)(opt)) {
1827 VG_(message)(Vg_UserMsg,
1828 "--trace-codegen argument must have 5 digits");
nethercote71980f02004-01-24 18:18:54 +00001829 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001830 }
1831 for (j = 0; j < 5; j++) {
1832 if ('0' == opt[j]) { /* do nothing */ }
1833 else if ('1' == opt[j]) VG_(clo_trace_codegen) |= (1 << j);
1834 else {
1835 VG_(message)(Vg_UserMsg, "--trace-codegen argument can only "
1836 "contain 0s and 1s");
nethercote71980f02004-01-24 18:18:54 +00001837 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001838 }
1839 }
1840 }
sewardjde4a1d02002-03-22 01:27:54 +00001841
nethercote71980f02004-01-24 18:18:54 +00001842 else if (VG_CLO_STREQ(arg, "--trace-syscalls=yes"))
sewardjde4a1d02002-03-22 01:27:54 +00001843 VG_(clo_trace_syscalls) = True;
nethercote71980f02004-01-24 18:18:54 +00001844 else if (VG_CLO_STREQ(arg, "--trace-syscalls=no"))
sewardjde4a1d02002-03-22 01:27:54 +00001845 VG_(clo_trace_syscalls) = False;
1846
nethercote71980f02004-01-24 18:18:54 +00001847 else if (VG_CLO_STREQ(arg, "--trace-signals=yes"))
sewardjde4a1d02002-03-22 01:27:54 +00001848 VG_(clo_trace_signals) = True;
nethercote71980f02004-01-24 18:18:54 +00001849 else if (VG_CLO_STREQ(arg, "--trace-signals=no"))
sewardjde4a1d02002-03-22 01:27:54 +00001850 VG_(clo_trace_signals) = False;
1851
nethercote71980f02004-01-24 18:18:54 +00001852 else if (VG_CLO_STREQ(arg, "--trace-symtab=yes"))
sewardjde4a1d02002-03-22 01:27:54 +00001853 VG_(clo_trace_symtab) = True;
nethercote71980f02004-01-24 18:18:54 +00001854 else if (VG_CLO_STREQ(arg, "--trace-symtab=no"))
sewardjde4a1d02002-03-22 01:27:54 +00001855 VG_(clo_trace_symtab) = False;
1856
nethercote71980f02004-01-24 18:18:54 +00001857 else if (VG_CLO_STREQ(arg, "--trace-sched=yes"))
sewardj8937c812002-04-12 20:12:20 +00001858 VG_(clo_trace_sched) = True;
nethercote71980f02004-01-24 18:18:54 +00001859 else if (VG_CLO_STREQ(arg, "--trace-sched=no"))
sewardj8937c812002-04-12 20:12:20 +00001860 VG_(clo_trace_sched) = False;
1861
nethercote71980f02004-01-24 18:18:54 +00001862 else if (VG_CLO_STREQ(arg, "--trace-pthread=none"))
sewardj45b4b372002-04-16 22:50:32 +00001863 VG_(clo_trace_pthread_level) = 0;
nethercote71980f02004-01-24 18:18:54 +00001864 else if (VG_CLO_STREQ(arg, "--trace-pthread=some"))
sewardj45b4b372002-04-16 22:50:32 +00001865 VG_(clo_trace_pthread_level) = 1;
nethercote71980f02004-01-24 18:18:54 +00001866 else if (VG_CLO_STREQ(arg, "--trace-pthread=all"))
sewardj45b4b372002-04-16 22:50:32 +00001867 VG_(clo_trace_pthread_level) = 2;
sewardj8937c812002-04-12 20:12:20 +00001868
nethercote71980f02004-01-24 18:18:54 +00001869 else if (VG_CLO_STREQN(14, arg, "--weird-hacks="))
1870 VG_(clo_weird_hacks) = &arg[14];
sewardj3984b852002-05-12 03:00:17 +00001871
nethercote71980f02004-01-24 18:18:54 +00001872 else if (VG_CLO_STREQN(17, arg, "--signal-polltime="))
1873 VG_(clo_signal_polltime) = VG_(atoll)(&arg[17]);
jsgf855d93d2003-10-13 22:26:55 +00001874
nethercote71980f02004-01-24 18:18:54 +00001875 else if (VG_CLO_STREQ(arg, "--lowlat-signals=yes"))
jsgf855d93d2003-10-13 22:26:55 +00001876 VG_(clo_lowlat_signals) = True;
nethercote71980f02004-01-24 18:18:54 +00001877 else if (VG_CLO_STREQ(arg, "--lowlat-signals=no"))
jsgf855d93d2003-10-13 22:26:55 +00001878 VG_(clo_lowlat_signals) = False;
1879
nethercote71980f02004-01-24 18:18:54 +00001880 else if (VG_CLO_STREQ(arg, "--lowlat-syscalls=yes"))
jsgf855d93d2003-10-13 22:26:55 +00001881 VG_(clo_lowlat_syscalls) = True;
nethercote71980f02004-01-24 18:18:54 +00001882 else if (VG_CLO_STREQ(arg, "--lowlat-syscalls=no"))
jsgf855d93d2003-10-13 22:26:55 +00001883 VG_(clo_lowlat_syscalls) = False;
1884
nethercote71980f02004-01-24 18:18:54 +00001885 else if (VG_CLO_STREQN(13, arg, "--dump-error="))
1886 VG_(clo_dump_error) = (Int)VG_(atoll)(&arg[13]);
sewardjde4a1d02002-03-22 01:27:54 +00001887
nethercote71980f02004-01-24 18:18:54 +00001888 else if (VG_CLO_STREQ(arg, "--wait-for-gdb=yes"))
jsgf855d93d2003-10-13 22:26:55 +00001889 VG_(clo_wait_for_gdb) = True;
nethercote71980f02004-01-24 18:18:54 +00001890 else if (VG_CLO_STREQ(arg, "--wait-for-gdb=no"))
jsgf855d93d2003-10-13 22:26:55 +00001891 VG_(clo_wait_for_gdb) = False;
1892
nethercote71980f02004-01-24 18:18:54 +00001893 else if (VG_CLO_STREQN(14, arg, "--num-callers=")) {
sewardjde4a1d02002-03-22 01:27:54 +00001894 /* Make sure it's sane. */
nethercote71980f02004-01-24 18:18:54 +00001895 VG_(clo_backtrace_size) = (Int)VG_(atoll)(&arg[14]);
njn6c846552003-09-16 07:41:43 +00001896 if (VG_(clo_backtrace_size) < 1)
1897 VG_(clo_backtrace_size) = 1;
sewardjde4a1d02002-03-22 01:27:54 +00001898 if (VG_(clo_backtrace_size) >= VG_DEEPEST_BACKTRACE)
1899 VG_(clo_backtrace_size) = VG_DEEPEST_BACKTRACE;
1900 }
1901
nethercote71980f02004-01-24 18:18:54 +00001902 else if ( ! VG_(needs).command_line_options
1903 || ! SK_(process_cmd_line_option)(arg) ) {
nethercotef4928da2004-06-15 10:54:40 +00001904 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001905 }
sewardjde4a1d02002-03-22 01:27:54 +00001906 }
1907
njnf9ebf672003-05-12 21:41:30 +00001908 if (VG_(clo_verbosity) < 0)
sewardjde4a1d02002-03-22 01:27:54 +00001909 VG_(clo_verbosity) = 0;
1910
nethercote04d0fbc2004-01-26 16:48:06 +00001911 if (VG_(clo_db_attach) && VG_(clo_trace_children)) {
sewardjde4a1d02002-03-22 01:27:54 +00001912 VG_(message)(Vg_UserMsg, "");
1913 VG_(message)(Vg_UserMsg,
nethercote04d0fbc2004-01-26 16:48:06 +00001914 "--db-attach=yes conflicts with --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001915 VG_(message)(Vg_UserMsg,
1916 "Please choose one or the other, but not both.");
nethercote04d0fbc2004-01-26 16:48:06 +00001917 VG_(bad_option)("--db-attach=yes and --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001918 }
1919
sewardj4cf05692002-10-27 20:28:29 +00001920 /* Set up logging now. After this is done, VG_(clo_logfile_fd)
1921 should be connected to whatever sink has been selected, and we
1922 indiscriminately chuck stuff into it without worrying what the
1923 nature of it is. Oh the wonder of Unix streams. */
1924
nethercotee1730692003-11-20 10:38:07 +00001925 /* So far we should be still attached to stdout, so we can show on
sewardj4cf05692002-10-27 20:28:29 +00001926 the terminal any problems to do with processing command line
1927 opts. */
nethercotee1730692003-11-20 10:38:07 +00001928 vg_assert(VG_(clo_logfile_fd) == 1 /* stdout */);
sewardj73cf3bc2002-11-03 03:20:15 +00001929 vg_assert(VG_(logging_to_filedes) == True);
sewardj4cf05692002-10-27 20:28:29 +00001930
1931 switch (VG_(clo_log_to)) {
sewardj73cf3bc2002-11-03 03:20:15 +00001932
sewardj4cf05692002-10-27 20:28:29 +00001933 case VgLogTo_Fd:
1934 vg_assert(VG_(clo_logfile_name) == NULL);
1935 VG_(clo_logfile_fd) = eventually_logfile_fd;
1936 break;
sewardj73cf3bc2002-11-03 03:20:15 +00001937
sewardj4cf05692002-10-27 20:28:29 +00001938 case VgLogTo_File: {
1939 Char logfilename[1000];
jsgff3c3f1a2003-10-14 22:13:28 +00001940 Int seq = 0;
1941 Int pid = VG_(getpid)();
1942
sewardj4cf05692002-10-27 20:28:29 +00001943 vg_assert(VG_(clo_logfile_name) != NULL);
1944 vg_assert(VG_(strlen)(VG_(clo_logfile_name)) <= 900); /* paranoia */
jsgff3c3f1a2003-10-14 22:13:28 +00001945
nethercote71980f02004-01-24 18:18:54 +00001946 for (;;) {
jsgff3c3f1a2003-10-14 22:13:28 +00001947 if (seq == 0)
1948 VG_(sprintf)(logfilename, "%s.pid%d",
1949 VG_(clo_logfile_name), pid );
1950 else
1951 VG_(sprintf)(logfilename, "%s.pid%d.%d",
1952 VG_(clo_logfile_name), pid, seq );
1953 seq++;
1954
1955 eventually_logfile_fd
1956 = VG_(open)(logfilename,
1957 VKI_O_CREAT|VKI_O_WRONLY|VKI_O_EXCL|VKI_O_TRUNC,
1958 VKI_S_IRUSR|VKI_S_IWUSR);
1959 if (eventually_logfile_fd >= 0) {
fitzhardinge9b8c2f32004-01-06 00:15:26 +00001960 VG_(clo_logfile_fd) = VG_(safe_fd)(eventually_logfile_fd);
jsgff3c3f1a2003-10-14 22:13:28 +00001961 break;
1962 } else {
1963 if (eventually_logfile_fd != -VKI_EEXIST) {
1964 VG_(message)(Vg_UserMsg,
1965 "Can't create/open log file `%s.pid%d'; giving up!",
1966 VG_(clo_logfile_name), pid);
1967 VG_(bad_option)(
1968 "--logfile=<file> didn't work out for some reason.");
1969 break;
1970 }
1971 }
1972 }
sewardj4cf05692002-10-27 20:28:29 +00001973 break;
sewardj73cf3bc2002-11-03 03:20:15 +00001974 }
1975
1976 case VgLogTo_Socket: {
1977 vg_assert(VG_(clo_logfile_name) != NULL);
1978 vg_assert(VG_(strlen)(VG_(clo_logfile_name)) <= 900); /* paranoia */
1979 eventually_logfile_fd
1980 = VG_(connect_via_socket)( VG_(clo_logfile_name) );
1981 if (eventually_logfile_fd == -1) {
1982 VG_(message)(Vg_UserMsg,
1983 "Invalid --logsocket=ipaddr or --logsocket=ipaddr:port spec");
1984 VG_(message)(Vg_UserMsg,
1985 "of `%s'; giving up!", VG_(clo_logfile_name) );
1986 VG_(bad_option)(
1987 "--logsocket=");
sewardj4cf05692002-10-27 20:28:29 +00001988 }
sewardj73cf3bc2002-11-03 03:20:15 +00001989 if (eventually_logfile_fd == -2) {
1990 VG_(message)(Vg_UserMsg,
sewardj570f8902002-11-03 11:44:36 +00001991 "valgrind: failed to connect to logging server `%s'.",
sewardj73cf3bc2002-11-03 03:20:15 +00001992 VG_(clo_logfile_name) );
sewardj570f8902002-11-03 11:44:36 +00001993 VG_(message)(Vg_UserMsg,
1994 "Log messages will sent to stderr instead." );
1995 VG_(message)(Vg_UserMsg,
1996 "" );
1997 /* We don't change anything here. */
1998 } else {
1999 vg_assert(eventually_logfile_fd > 0);
2000 VG_(clo_logfile_fd) = eventually_logfile_fd;
2001 VG_(logging_to_filedes) = False;
2002 }
sewardj73cf3bc2002-11-03 03:20:15 +00002003 break;
2004 }
2005
sewardj4cf05692002-10-27 20:28:29 +00002006 }
2007
jsgf855d93d2003-10-13 22:26:55 +00002008 /* Move logfile_fd into the safe range, so it doesn't conflict with any app fds */
fitzhardingef0046f22003-12-18 02:39:22 +00002009 eventually_logfile_fd = VG_(fcntl)(VG_(clo_logfile_fd), VKI_F_DUPFD, VG_(max_fd)+1);
jsgf855d93d2003-10-13 22:26:55 +00002010 if (eventually_logfile_fd < 0)
2011 VG_(message)(Vg_UserMsg, "valgrind: failed to move logfile fd into safe range");
2012 else {
2013 VG_(clo_logfile_fd) = eventually_logfile_fd;
2014 VG_(fcntl)(VG_(clo_logfile_fd), VKI_F_SETFD, VKI_FD_CLOEXEC);
2015 }
2016
sewardj4cf05692002-10-27 20:28:29 +00002017 /* Ok, the logging sink is running now. Print a suitable preamble.
2018 If logging to file or a socket, write details of parent PID and
2019 command line args, to help people trying to interpret the
2020 results of a run which encompasses multiple processes. */
sewardjde4a1d02002-03-22 01:27:54 +00002021
sewardj83adf412002-05-01 01:25:45 +00002022 if (VG_(clo_verbosity > 0)) {
njnd04b7c62002-10-03 14:05:52 +00002023 /* Skin details */
2024 VG_(message)(Vg_UserMsg, "%s%s%s, %s for x86-linux.",
2025 VG_(details).name,
2026 NULL == VG_(details).version ? "" : "-",
2027 NULL == VG_(details).version
2028 ? (Char*)"" : VG_(details).version,
2029 VG_(details).description);
2030 VG_(message)(Vg_UserMsg, "%s", VG_(details).copyright_author);
sewardj3b2736a2002-03-24 12:18:35 +00002031
njnd04b7c62002-10-03 14:05:52 +00002032 /* Core details */
2033 VG_(message)(Vg_UserMsg,
njn3e884182003-04-15 13:03:23 +00002034 "Using valgrind-%s, a program supervision framework for x86-linux.",
sewardj4aa62ba2002-10-05 15:49:27 +00002035 VERSION);
sewardjde4a1d02002-03-22 01:27:54 +00002036 VG_(message)(Vg_UserMsg,
nethercotebb1c9912004-01-04 16:43:23 +00002037 "Copyright (C) 2000-2004, and GNU GPL'd, by Julian Seward.");
njnd04b7c62002-10-03 14:05:52 +00002038 }
2039
nethercotec1e395d2003-11-10 13:26:49 +00002040 if (VG_(clo_verbosity) > 0 && VG_(clo_log_to) != VgLogTo_Fd) {
sewardj4cf05692002-10-27 20:28:29 +00002041 VG_(message)(Vg_UserMsg, "");
2042 VG_(message)(Vg_UserMsg,
2043 "My PID = %d, parent PID = %d. Prog and args are:",
2044 VG_(getpid)(), VG_(getppid)() );
2045 for (i = 0; i < VG_(client_argc); i++)
2046 VG_(message)(Vg_UserMsg, " %s", VG_(client_argv)[i]);
2047 }
2048
sewardjde4a1d02002-03-22 01:27:54 +00002049 if (VG_(clo_verbosity) > 1) {
nethercotea70f7352004-04-18 12:08:46 +00002050 Int fd;
sewardj4cf05692002-10-27 20:28:29 +00002051 if (VG_(clo_log_to) != VgLogTo_Fd)
2052 VG_(message)(Vg_UserMsg, "");
fitzhardinge98abfc72003-12-16 02:05:15 +00002053 VG_(message)(Vg_UserMsg, "Valgrind library directory: %s", VG_(libdir));
njn86dc2bc2003-09-09 07:26:21 +00002054 VG_(message)(Vg_UserMsg, "Command line");
2055 for (i = 0; i < VG_(client_argc); i++)
2056 VG_(message)(Vg_UserMsg, " %s", VG_(client_argv)[i]);
2057
sewardjde4a1d02002-03-22 01:27:54 +00002058 VG_(message)(Vg_UserMsg, "Startup, with flags:");
nethercote71980f02004-01-24 18:18:54 +00002059 for (i = 1; i < VG_(vg_argc); i++) {
2060 VG_(message)(Vg_UserMsg, " %s", VG_(vg_argv)[i]);
sewardjde4a1d02002-03-22 01:27:54 +00002061 }
nethercotea70f7352004-04-18 12:08:46 +00002062
2063 VG_(message)(Vg_UserMsg, "Contents of /proc/version:");
2064 fd = VG_(open) ( "/proc/version", VKI_O_RDONLY, 0 );
2065 if (fd < 0) {
2066 VG_(message)(Vg_UserMsg, " can't open /proc/version");
2067 } else {
2068 #define BUF_LEN 256
2069 Char version_buf[BUF_LEN];
2070 Int n = VG_(read) ( fd, version_buf, BUF_LEN );
2071 vg_assert(n <= 256);
2072 if (n > 0) {
2073 version_buf[n-1] = '\0';
2074 VG_(message)(Vg_UserMsg, " %s", version_buf);
2075 } else {
2076 VG_(message)(Vg_UserMsg, " (empty?)");
2077 }
2078 VG_(close)(fd);
2079 #undef BUF_LEN
2080 }
sewardjde4a1d02002-03-22 01:27:54 +00002081 }
2082
fitzhardinge98abfc72003-12-16 02:05:15 +00002083 if (VG_(clo_n_suppressions) < VG_CLO_MAX_SFILES-1 &&
njn25e49d8e72002-09-23 09:36:25 +00002084 (VG_(needs).core_errors || VG_(needs).skin_errors)) {
fitzhardinge98abfc72003-12-16 02:05:15 +00002085 /* If there are no suppression files specified and the skin
2086 needs one, load the default */
2087 static const Char default_supp[] = "default.supp";
2088 Int len = VG_(strlen)(VG_(libdir)) + 1 + sizeof(default_supp);
2089 Char *buf = VG_(arena_malloc)(VG_AR_CORE, len);
2090 VG_(sprintf)(buf, "%s/%s", VG_(libdir), default_supp);
2091 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = buf;
2092 VG_(clo_n_suppressions)++;
sewardjde4a1d02002-03-22 01:27:54 +00002093 }
sewardj4cf05692002-10-27 20:28:29 +00002094
njn6a230532003-07-21 10:38:23 +00002095 if (VG_(clo_gen_suppressions) &&
2096 !VG_(needs).core_errors && !VG_(needs).skin_errors) {
nethercotef4928da2004-06-15 10:54:40 +00002097 VG_(message)(Vg_UserMsg,
2098 "Can't use --gen-suppressions=yes with this tool,");
2099 VG_(message)(Vg_UserMsg,
2100 "as it doesn't generate errors.");
2101 VG_(bad_option)("--gen-suppressions=yes");
njn6a230532003-07-21 10:38:23 +00002102 }
sewardjde4a1d02002-03-22 01:27:54 +00002103}
2104
sewardjde4a1d02002-03-22 01:27:54 +00002105
nethercote71980f02004-01-24 18:18:54 +00002106/*====================================================================*/
2107/*=== File descriptor setup ===*/
2108/*====================================================================*/
2109
2110static void setup_file_descriptors(void)
2111{
2112 struct vki_rlimit rl;
2113
2114 /* Get the current file descriptor limits. */
2115 if (VG_(getrlimit)(VKI_RLIMIT_NOFILE, &rl) < 0) {
2116 rl.rlim_cur = 1024;
2117 rl.rlim_max = 1024;
2118 }
2119
2120 /* Work out where to move the soft limit to. */
2121 if (rl.rlim_cur + VG_N_RESERVED_FDS <= rl.rlim_max) {
2122 rl.rlim_cur = rl.rlim_cur + VG_N_RESERVED_FDS;
2123 } else {
2124 rl.rlim_cur = rl.rlim_max;
2125 }
2126
2127 /* Reserve some file descriptors for our use. */
2128 VG_(max_fd) = rl.rlim_cur - VG_N_RESERVED_FDS;
2129
2130 /* Update the soft limit. */
2131 VG_(setrlimit)(VKI_RLIMIT_NOFILE, &rl);
2132
2133 if (VG_(vgexecfd) != -1)
2134 VG_(vgexecfd) = VG_(safe_fd)( VG_(vgexecfd) );
2135 if (VG_(clexecfd) != -1)
2136 VG_(clexecfd) = VG_(safe_fd)( VG_(clexecfd) );
2137}
2138
2139
2140/*====================================================================*/
nethercote1d447092004-02-01 17:29:59 +00002141/*=== baseBlock: definition + setup ===*/
nethercote71980f02004-01-24 18:18:54 +00002142/*====================================================================*/
2143
2144/* The variables storing offsets. */
2145
2146#define INVALID_OFFSET (-1)
2147
2148Int VGOFF_(m_eax) = INVALID_OFFSET;
2149Int VGOFF_(m_ecx) = INVALID_OFFSET;
2150Int VGOFF_(m_edx) = INVALID_OFFSET;
2151Int VGOFF_(m_ebx) = INVALID_OFFSET;
2152Int VGOFF_(m_esp) = INVALID_OFFSET;
2153Int VGOFF_(m_ebp) = INVALID_OFFSET;
2154Int VGOFF_(m_esi) = INVALID_OFFSET;
2155Int VGOFF_(m_edi) = INVALID_OFFSET;
2156Int VGOFF_(m_eflags) = INVALID_OFFSET;
2157Int VGOFF_(m_dflag) = INVALID_OFFSET;
2158Int VGOFF_(m_ssestate) = INVALID_OFFSET;
2159Int VGOFF_(ldt) = INVALID_OFFSET;
2160Int VGOFF_(tls) = INVALID_OFFSET;
2161Int VGOFF_(m_cs) = INVALID_OFFSET;
2162Int VGOFF_(m_ss) = INVALID_OFFSET;
2163Int VGOFF_(m_ds) = INVALID_OFFSET;
2164Int VGOFF_(m_es) = INVALID_OFFSET;
2165Int VGOFF_(m_fs) = INVALID_OFFSET;
2166Int VGOFF_(m_gs) = INVALID_OFFSET;
2167Int VGOFF_(m_eip) = INVALID_OFFSET;
2168Int VGOFF_(spillslots) = INVALID_OFFSET;
2169Int VGOFF_(sh_eax) = INVALID_OFFSET;
2170Int VGOFF_(sh_ecx) = INVALID_OFFSET;
2171Int VGOFF_(sh_edx) = INVALID_OFFSET;
2172Int VGOFF_(sh_ebx) = INVALID_OFFSET;
2173Int VGOFF_(sh_esp) = INVALID_OFFSET;
2174Int VGOFF_(sh_ebp) = INVALID_OFFSET;
2175Int VGOFF_(sh_esi) = INVALID_OFFSET;
2176Int VGOFF_(sh_edi) = INVALID_OFFSET;
2177Int VGOFF_(sh_eflags) = INVALID_OFFSET;
2178
2179Int VGOFF_(helper_idiv_64_32) = INVALID_OFFSET;
2180Int VGOFF_(helper_div_64_32) = INVALID_OFFSET;
2181Int VGOFF_(helper_idiv_32_16) = INVALID_OFFSET;
2182Int VGOFF_(helper_div_32_16) = INVALID_OFFSET;
2183Int VGOFF_(helper_idiv_16_8) = INVALID_OFFSET;
2184Int VGOFF_(helper_div_16_8) = INVALID_OFFSET;
2185Int VGOFF_(helper_imul_32_64) = INVALID_OFFSET;
2186Int VGOFF_(helper_mul_32_64) = INVALID_OFFSET;
2187Int VGOFF_(helper_imul_16_32) = INVALID_OFFSET;
2188Int VGOFF_(helper_mul_16_32) = INVALID_OFFSET;
2189Int VGOFF_(helper_imul_8_16) = INVALID_OFFSET;
2190Int VGOFF_(helper_mul_8_16) = INVALID_OFFSET;
2191Int VGOFF_(helper_CLD) = INVALID_OFFSET;
2192Int VGOFF_(helper_STD) = INVALID_OFFSET;
2193Int VGOFF_(helper_get_dirflag) = INVALID_OFFSET;
2194Int VGOFF_(helper_CLC) = INVALID_OFFSET;
2195Int VGOFF_(helper_STC) = INVALID_OFFSET;
nethercote1018bdd2004-02-11 23:33:29 +00002196Int VGOFF_(helper_CMC) = INVALID_OFFSET;
nethercote71980f02004-01-24 18:18:54 +00002197Int VGOFF_(helper_shldl) = INVALID_OFFSET;
2198Int VGOFF_(helper_shldw) = INVALID_OFFSET;
2199Int VGOFF_(helper_shrdl) = INVALID_OFFSET;
2200Int VGOFF_(helper_shrdw) = INVALID_OFFSET;
2201Int VGOFF_(helper_IN) = INVALID_OFFSET;
2202Int VGOFF_(helper_OUT) = INVALID_OFFSET;
2203Int VGOFF_(helper_RDTSC) = INVALID_OFFSET;
2204Int VGOFF_(helper_CPUID) = INVALID_OFFSET;
2205Int VGOFF_(helper_BSWAP) = INVALID_OFFSET;
nethercote1018bdd2004-02-11 23:33:29 +00002206Int VGOFF_(helper_bsfw) = INVALID_OFFSET;
2207Int VGOFF_(helper_bsfl) = INVALID_OFFSET;
2208Int VGOFF_(helper_bsrw) = INVALID_OFFSET;
2209Int VGOFF_(helper_bsrl) = INVALID_OFFSET;
nethercote71980f02004-01-24 18:18:54 +00002210Int VGOFF_(helper_fstsw_AX) = INVALID_OFFSET;
2211Int VGOFF_(helper_SAHF) = INVALID_OFFSET;
2212Int VGOFF_(helper_LAHF) = INVALID_OFFSET;
2213Int VGOFF_(helper_DAS) = INVALID_OFFSET;
2214Int VGOFF_(helper_DAA) = INVALID_OFFSET;
nethercote1018bdd2004-02-11 23:33:29 +00002215Int VGOFF_(helper_AAS) = INVALID_OFFSET;
2216Int VGOFF_(helper_AAA) = INVALID_OFFSET;
2217Int VGOFF_(helper_AAD) = INVALID_OFFSET;
2218Int VGOFF_(helper_AAM) = INVALID_OFFSET;
nethercote71980f02004-01-24 18:18:54 +00002219Int VGOFF_(helper_cmpxchg8b) = INVALID_OFFSET;
2220Int VGOFF_(helper_undefined_instruction) = INVALID_OFFSET;
2221
2222/* MAX_NONCOMPACT_HELPERS can be increased easily. If MAX_COMPACT_HELPERS is
2223 * increased too much, they won't really be compact any more... */
2224#define MAX_COMPACT_HELPERS 8
2225#define MAX_NONCOMPACT_HELPERS 50
2226
2227UInt VG_(n_compact_helpers) = 0;
2228UInt VG_(n_noncompact_helpers) = 0;
2229
2230Addr VG_(compact_helper_addrs) [MAX_COMPACT_HELPERS];
2231Int VG_(compact_helper_offsets)[MAX_COMPACT_HELPERS];
2232Addr VG_(noncompact_helper_addrs) [MAX_NONCOMPACT_HELPERS];
2233Int VG_(noncompact_helper_offsets)[MAX_NONCOMPACT_HELPERS];
2234
2235/* This is the actual defn of baseblock. */
2236UInt VG_(baseBlock)[VG_BASEBLOCK_WORDS];
2237
nethercote71980f02004-01-24 18:18:54 +00002238/* Words. */
2239static Int baB_off = 0;
2240
2241
sewardjfa492d42002-12-08 18:20:01 +00002242UInt VG_(insertDflag)(UInt eflags, Int d)
2243{
2244 vg_assert(d == 1 || d == -1);
2245 eflags &= ~EFlagD;
2246
2247 if (d < 0)
2248 eflags |= EFlagD;
2249
2250 return eflags;
2251}
2252
2253Int VG_(extractDflag)(UInt eflags)
2254{
2255 Int ret;
2256
2257 if (eflags & EFlagD)
2258 ret = -1;
2259 else
2260 ret = 1;
2261
2262 return ret;
2263}
2264
nethercote71980f02004-01-24 18:18:54 +00002265/* Returns the offset, in words. */
2266static Int alloc_BaB ( Int words )
sewardjde4a1d02002-03-22 01:27:54 +00002267{
nethercote71980f02004-01-24 18:18:54 +00002268 Int off = baB_off;
2269 baB_off += words;
2270 if (baB_off >= VG_BASEBLOCK_WORDS)
2271 VG_(core_panic)( "alloc_BaB: baseBlock is too small");
sewardjde4a1d02002-03-22 01:27:54 +00002272
nethercote71980f02004-01-24 18:18:54 +00002273 return off;
sewardjde4a1d02002-03-22 01:27:54 +00002274}
2275
nethercote71980f02004-01-24 18:18:54 +00002276/* Align offset, in *bytes* */
2277static void align_BaB ( UInt align )
njn25e49d8e72002-09-23 09:36:25 +00002278{
nethercote71980f02004-01-24 18:18:54 +00002279 vg_assert(2 == align || 4 == align || 8 == align || 16 == align);
2280 baB_off += (align-1);
2281 baB_off &= ~(align-1);
njn25e49d8e72002-09-23 09:36:25 +00002282}
2283
nethercote71980f02004-01-24 18:18:54 +00002284/* Allocate 1 word in baseBlock and set it to the given value. */
2285static Int alloc_BaB_1_set ( Addr a )
njn25e49d8e72002-09-23 09:36:25 +00002286{
nethercote71980f02004-01-24 18:18:54 +00002287 Int off = alloc_BaB(1);
2288 VG_(baseBlock)[off] = (UInt)a;
2289 return off;
njn25e49d8e72002-09-23 09:36:25 +00002290}
2291
nethercote71980f02004-01-24 18:18:54 +00002292/* Registers a function in compact_helper_addrs; compact_helper_offsets is
2293 filled in later. */
2294void VG_(register_compact_helper)(Addr a)
sewardjde4a1d02002-03-22 01:27:54 +00002295{
nethercote71980f02004-01-24 18:18:54 +00002296 if (MAX_COMPACT_HELPERS <= VG_(n_compact_helpers)) {
2297 VG_(printf)("Can only register %d compact helpers\n",
2298 MAX_COMPACT_HELPERS);
2299 VG_(core_panic)("Too many compact helpers registered");
2300 }
2301 VG_(compact_helper_addrs)[VG_(n_compact_helpers)] = a;
2302 VG_(n_compact_helpers)++;
2303}
2304
2305/* Registers a function in noncompact_helper_addrs; noncompact_helper_offsets
2306 * is filled in later.
2307 */
2308void VG_(register_noncompact_helper)(Addr a)
2309{
2310 if (MAX_NONCOMPACT_HELPERS <= VG_(n_noncompact_helpers)) {
2311 VG_(printf)("Can only register %d non-compact helpers\n",
2312 MAX_NONCOMPACT_HELPERS);
2313 VG_(printf)("Try increasing MAX_NON_COMPACT_HELPERS\n");
2314 VG_(core_panic)("Too many non-compact helpers registered");
2315 }
2316 VG_(noncompact_helper_addrs)[VG_(n_noncompact_helpers)] = a;
2317 VG_(n_noncompact_helpers)++;
2318}
2319
2320/* Allocate offsets in baseBlock for the skin helpers */
2321static
2322void assign_helpers_in_baseBlock(UInt n, Int offsets[], Addr addrs[])
2323{
2324 UInt i;
2325 for (i = 0; i < n; i++)
2326 offsets[i] = alloc_BaB_1_set( addrs[i] );
2327}
2328
2329Bool VG_(need_to_handle_esp_assignment)(void)
2330{
2331 return ( VG_(defined_new_mem_stack_4)() ||
2332 VG_(defined_die_mem_stack_4)() ||
2333 VG_(defined_new_mem_stack_8)() ||
2334 VG_(defined_die_mem_stack_8)() ||
2335 VG_(defined_new_mem_stack_12)() ||
2336 VG_(defined_die_mem_stack_12)() ||
2337 VG_(defined_new_mem_stack_16)() ||
2338 VG_(defined_die_mem_stack_16)() ||
2339 VG_(defined_new_mem_stack_32)() ||
2340 VG_(defined_die_mem_stack_32)() ||
2341 VG_(defined_new_mem_stack)() ||
2342 VG_(defined_die_mem_stack)()
2343 );
2344}
2345
2346/* Here we assign actual offsets. It's important to get the most
2347 popular referents within 128 bytes of the start, so we can take
2348 advantage of short addressing modes relative to %ebp. Popularity
2349 of offsets was measured on 22 Feb 02 running a KDE application, and
2350 the slots rearranged accordingly, with a 1.5% reduction in total
2351 size of translations. */
2352static void init_baseBlock ( Addr client_eip, Addr esp_at_startup )
2353{
2354 /* Those with offsets under 128 are carefully chosen. */
2355
2356 /* WORD offsets in this column */
2357 /* 0 */ VGOFF_(m_eax) = alloc_BaB_1_set(0);
2358 /* 1 */ VGOFF_(m_ecx) = alloc_BaB_1_set(0);
2359 /* 2 */ VGOFF_(m_edx) = alloc_BaB_1_set(0);
2360 /* 3 */ VGOFF_(m_ebx) = alloc_BaB_1_set(0);
2361 /* 4 */ VGOFF_(m_esp) = alloc_BaB_1_set(esp_at_startup);
2362 /* 5 */ VGOFF_(m_ebp) = alloc_BaB_1_set(0);
2363 /* 6 */ VGOFF_(m_esi) = alloc_BaB_1_set(0);
2364 /* 7 */ VGOFF_(m_edi) = alloc_BaB_1_set(0);
2365 /* 8 */ VGOFF_(m_eflags) = alloc_BaB_1_set(0);
2366
2367 if (VG_(needs).shadow_regs) {
2368 /* 9 */ VGOFF_(sh_eax) = alloc_BaB_1_set(0);
2369 /* 10 */ VGOFF_(sh_ecx) = alloc_BaB_1_set(0);
2370 /* 11 */ VGOFF_(sh_edx) = alloc_BaB_1_set(0);
2371 /* 12 */ VGOFF_(sh_ebx) = alloc_BaB_1_set(0);
2372 /* 13 */ VGOFF_(sh_esp) = alloc_BaB_1_set(0);
2373 /* 14 */ VGOFF_(sh_ebp) = alloc_BaB_1_set(0);
2374 /* 15 */ VGOFF_(sh_esi) = alloc_BaB_1_set(0);
2375 /* 16 */ VGOFF_(sh_edi) = alloc_BaB_1_set(0);
2376 /* 17 */ VGOFF_(sh_eflags) = alloc_BaB_1_set(0);
2377 VG_TRACK( post_regs_write_init );
2378 }
2379
2380 /* 9,10,11 or 18,19,20... depends on number whether shadow regs are used
2381 * and on compact helpers registered */
2382
2383 /* Make these most-frequently-called specialised ones compact, if they
2384 are used. */
2385 if (VG_(defined_new_mem_stack_4)())
2386 VG_(register_compact_helper)( (Addr) VG_(tool_interface).track_new_mem_stack_4);
2387
2388 if (VG_(defined_die_mem_stack_4)())
2389 VG_(register_compact_helper)( (Addr) VG_(tool_interface).track_die_mem_stack_4);
2390
2391 /* (9 or 18) + n_compact_helpers */
2392 /* Allocate slots for compact helpers */
2393 assign_helpers_in_baseBlock(VG_(n_compact_helpers),
2394 VG_(compact_helper_offsets),
2395 VG_(compact_helper_addrs));
2396
2397 /* (9/10 or 18/19) + n_compact_helpers */
2398 VGOFF_(m_eip) = alloc_BaB_1_set(client_eip);
2399
2400 /* There are currently 24 spill slots */
2401 /* (11+/20+ .. 32+/43+) + n_compact_helpers. This can overlap the magic
2402 * boundary at >= 32 words, but most spills are to low numbered spill
2403 * slots, so the ones above the boundary don't see much action. */
2404 VGOFF_(spillslots) = alloc_BaB(VG_MAX_SPILLSLOTS);
2405
2406 /* I gave up counting at this point. Since they're above the
2407 short-amode-boundary, there's no point. */
2408
2409 VGOFF_(m_dflag) = alloc_BaB_1_set(1); // 1 == forward D-flag
2410
2411 /* The FPU/SSE state. This _must_ be 16-byte aligned. Initial
2412 state doesn't matter much, as long as it's not totally borked. */
2413 align_BaB(16);
2414 VGOFF_(m_ssestate) = alloc_BaB(VG_SIZE_OF_SSESTATE_W);
2415 vg_assert(
2416 0 == ( ((UInt)(& VG_(baseBlock)[VGOFF_(m_ssestate)])) % 16 )
sewardj22854b92002-11-30 14:00:47 +00002417 );
2418
fitzhardingec2dbbac2004-01-23 23:09:01 +00002419 /* I assume that if we have SSE2 we also have SSE */
2420 VG_(have_ssestate) =
2421 VG_(cpu_has_feature)(VG_X86_FEAT_FXSR) &&
2422 VG_(cpu_has_feature)(VG_X86_FEAT_SSE);
2423
fitzhardinge98abfc72003-12-16 02:05:15 +00002424 /* set up an initial FPU state (doesn't really matter what it is,
2425 so long as it's somewhat valid) */
2426 if (!VG_(have_ssestate))
nethercote71980f02004-01-24 18:18:54 +00002427 asm volatile("fwait; fnsave %0; fwait; frstor %0; fwait"
2428 :
2429 : "m" (VG_(baseBlock)[VGOFF_(m_ssestate)])
2430 : "cc", "memory");
fitzhardinge98abfc72003-12-16 02:05:15 +00002431 else
nethercote71980f02004-01-24 18:18:54 +00002432 asm volatile("fwait; fxsave %0; fwait; andl $0xffbf, %1;"
2433 "fxrstor %0; fwait"
2434 :
2435 : "m" (VG_(baseBlock)[VGOFF_(m_ssestate)]),
2436 "m" (VG_(baseBlock)[VGOFF_(m_ssestate)+(24/4)])
2437 : "cc", "memory");
fitzhardinge98abfc72003-12-16 02:05:15 +00002438
njn0c7a5b52003-04-30 09:00:33 +00002439 if (0) {
2440 if (VG_(have_ssestate))
2441 VG_(printf)("Looks like a SSE-capable CPU\n");
2442 else
2443 VG_(printf)("Looks like a MMX-only CPU\n");
2444 }
sewardjb91ae7f2003-04-29 23:50:00 +00002445
nethercote71980f02004-01-24 18:18:54 +00002446 /* LDT pointer: pretend the root thread has an empty LDT to start with. */
2447 VGOFF_(ldt) = alloc_BaB_1_set((UInt)NULL);
jsgf855d93d2003-10-13 22:26:55 +00002448
nethercote71980f02004-01-24 18:18:54 +00002449 /* TLS pointer: pretend the root thread has no TLS array for now. */
2450 VGOFF_(tls) = alloc_BaB_1_set((UInt)NULL);
fitzhardingef0046f22003-12-18 02:39:22 +00002451
nethercote71980f02004-01-24 18:18:54 +00002452 /* segment registers */
2453 VGOFF_(m_cs) = alloc_BaB_1_set(0);
2454 VGOFF_(m_ss) = alloc_BaB_1_set(0);
2455 VGOFF_(m_ds) = alloc_BaB_1_set(0);
2456 VGOFF_(m_es) = alloc_BaB_1_set(0);
2457 VGOFF_(m_fs) = alloc_BaB_1_set(0);
2458 VGOFF_(m_gs) = alloc_BaB_1_set(0);
fitzhardingef0046f22003-12-18 02:39:22 +00002459
thughes35cec982004-04-21 15:16:43 +00002460 /* initialise %cs, %ds and %ss to point at the operating systems
2461 default code, data and stack segments */
2462 asm volatile("movw %%cs, %0"
2463 :
2464 : "m" (VG_(baseBlock)[VGOFF_(m_cs)]));
2465 asm volatile("movw %%ds, %0"
2466 :
2467 : "m" (VG_(baseBlock)[VGOFF_(m_ds)]));
2468 asm volatile("movw %%ss, %0"
2469 :
2470 : "m" (VG_(baseBlock)[VGOFF_(m_ss)]));
2471
nethercote71980f02004-01-24 18:18:54 +00002472 VG_(register_noncompact_helper)( (Addr) & VG_(do_useseg) );
fitzhardingef0046f22003-12-18 02:39:22 +00002473
nethercote71980f02004-01-24 18:18:54 +00002474#define REG(kind, size) \
2475 if (VG_(defined_##kind##_mem_stack##size)()) \
2476 VG_(register_noncompact_helper)( \
2477 (Addr) VG_(tool_interface).track_##kind##_mem_stack##size );
2478 REG(new, _8);
2479 REG(new, _12);
2480 REG(new, _16);
2481 REG(new, _32);
2482 REG(new, );
2483 REG(die, _8);
2484 REG(die, _12);
2485 REG(die, _16);
2486 REG(die, _32);
2487 REG(die, );
2488#undef REG
fitzhardingef0046f22003-12-18 02:39:22 +00002489
nethercote71980f02004-01-24 18:18:54 +00002490 if (VG_(need_to_handle_esp_assignment)())
2491 VG_(register_noncompact_helper)((Addr) VG_(unknown_esp_update));
fitzhardingeb791a192003-12-18 07:22:44 +00002492
nethercote71980f02004-01-24 18:18:54 +00002493# define HELPER(name) \
2494 VGOFF_(helper_##name) = alloc_BaB_1_set( (Addr) & VG_(helper_##name))
njn3e884182003-04-15 13:03:23 +00002495
nethercote71980f02004-01-24 18:18:54 +00002496 /* Helper functions. */
2497 HELPER(idiv_64_32); HELPER(div_64_32);
2498 HELPER(idiv_32_16); HELPER(div_32_16);
2499 HELPER(idiv_16_8); HELPER(div_16_8);
fitzhardinge98abfc72003-12-16 02:05:15 +00002500
nethercote71980f02004-01-24 18:18:54 +00002501 HELPER(imul_32_64); HELPER(mul_32_64);
2502 HELPER(imul_16_32); HELPER(mul_16_32);
2503 HELPER(imul_8_16); HELPER(mul_8_16);
njn25e49d8e72002-09-23 09:36:25 +00002504
nethercote71980f02004-01-24 18:18:54 +00002505 HELPER(CLD); HELPER(STD);
2506 HELPER(get_dirflag);
sewardjde4a1d02002-03-22 01:27:54 +00002507
nethercote71980f02004-01-24 18:18:54 +00002508 HELPER(CLC); HELPER(STC);
nethercote1018bdd2004-02-11 23:33:29 +00002509 HELPER(CMC);
jsgf855d93d2003-10-13 22:26:55 +00002510
nethercote71980f02004-01-24 18:18:54 +00002511 HELPER(shldl); HELPER(shldw);
2512 HELPER(shrdl); HELPER(shrdw);
njncc7bb472002-10-14 09:25:19 +00002513
nethercote71980f02004-01-24 18:18:54 +00002514 HELPER(RDTSC); HELPER(CPUID);
njncc7bb472002-10-14 09:25:19 +00002515
nethercote1018bdd2004-02-11 23:33:29 +00002516 HELPER(bsfw); HELPER(bsfl);
2517 HELPER(bsrw); HELPER(bsrl);
rjwalshf5f536f2003-11-17 17:45:00 +00002518
nethercote71980f02004-01-24 18:18:54 +00002519 HELPER(fstsw_AX);
2520 HELPER(SAHF); HELPER(LAHF);
2521 HELPER(DAS); HELPER(DAA);
nethercote1018bdd2004-02-11 23:33:29 +00002522 HELPER(AAS); HELPER(AAA);
2523 HELPER(AAD); HELPER(AAM);
nethercote71980f02004-01-24 18:18:54 +00002524 HELPER(IN); HELPER(OUT);
2525 HELPER(cmpxchg8b);
sewardj018f7622002-05-15 21:13:39 +00002526
nethercote71980f02004-01-24 18:18:54 +00002527 HELPER(undefined_instruction);
jsgf855d93d2003-10-13 22:26:55 +00002528
nethercote71980f02004-01-24 18:18:54 +00002529# undef HELPER
sewardjde4a1d02002-03-22 01:27:54 +00002530
nethercote71980f02004-01-24 18:18:54 +00002531 /* Allocate slots for noncompact helpers */
2532 assign_helpers_in_baseBlock(VG_(n_noncompact_helpers),
2533 VG_(noncompact_helper_offsets),
2534 VG_(noncompact_helper_addrs));
2535}
sewardjde4a1d02002-03-22 01:27:54 +00002536
sewardj5f07b662002-04-23 16:52:51 +00002537
nethercote71980f02004-01-24 18:18:54 +00002538/*====================================================================*/
2539/*=== Setup pointercheck ===*/
2540/*====================================================================*/
njn25e49d8e72002-09-23 09:36:25 +00002541
nethercote71980f02004-01-24 18:18:54 +00002542static void setup_pointercheck(void)
2543{
2544 int ret;
sewardj2e93c502002-04-12 11:12:52 +00002545
fitzhardinge98abfc72003-12-16 02:05:15 +00002546 if (VG_(clo_pointercheck)) {
nethercote71980f02004-01-24 18:18:54 +00002547 vki_modify_ldt_t ldt = {
2548 VG_POINTERCHECK_SEGIDX, // entry_number
2549 VG_(client_base), // base_addr
2550 (VG_(client_end)-VG_(client_base)) / VKI_BYTES_PER_PAGE, // limit
2551 1, // seg_32bit
2552 0, // contents: data, RW, non-expanding
2553 0, // ! read_exec_only
2554 1, // limit_in_pages
2555 0, // ! seg not present
2556 1, // useable
fitzhardinge98abfc72003-12-16 02:05:15 +00002557 };
nethercote71980f02004-01-24 18:18:54 +00002558 ret = VG_(do_syscall)(__NR_modify_ldt, 1, &ldt, sizeof(ldt));
fitzhardinge98abfc72003-12-16 02:05:15 +00002559 if (ret < 0) {
2560 VG_(message)(Vg_UserMsg,
2561 "Warning: ignoring --pointercheck=yes, "
2562 "because modify_ldt failed (errno=%d)", -ret);
2563 VG_(clo_pointercheck) = False;
2564 }
2565 }
sewardjde4a1d02002-03-22 01:27:54 +00002566}
2567
nethercote71980f02004-01-24 18:18:54 +00002568/*====================================================================*/
2569/*=== Initialise program data/text, etc. ===*/
2570/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +00002571
nethercote71980f02004-01-24 18:18:54 +00002572static void build_valgrind_map_callback
2573 ( Addr start, UInt size, Char rr, Char ww, Char xx,
2574 UInt dev, UInt ino, ULong foffset, const UChar* filename )
sewardjde4a1d02002-03-22 01:27:54 +00002575{
nethercote71980f02004-01-24 18:18:54 +00002576 UInt prot = 0;
2577 UInt flags = SF_MMAP|SF_NOSYMS;
2578 Bool is_stack_segment;
2579
2580 is_stack_segment =
2581 (start == VG_(clstk_base) && (start+size) == VG_(clstk_end));
2582
2583 /* Only record valgrind mappings for now, without loading any
2584 symbols. This is so we know where the free space is before we
2585 start allocating more memory (note: heap is OK, it's just mmap
2586 which is the problem here). */
2587 if (start >= VG_(valgrind_base) && (start+size) <= VG_(valgrind_end)) {
2588 flags |= SF_VALGRIND;
2589 VG_(map_file_segment)(start, size, prot, flags, dev, ino, foffset, filename);
2590 }
sewardjde4a1d02002-03-22 01:27:54 +00002591}
2592
nethercote71980f02004-01-24 18:18:54 +00002593// Global var used to pass local data to callback
2594Addr esp_at_startup___global_arg = 0;
sewardjde4a1d02002-03-22 01:27:54 +00002595
nethercote71980f02004-01-24 18:18:54 +00002596static void build_segment_map_callback
2597 ( Addr start, UInt size, Char rr, Char ww, Char xx,
2598 UInt dev, UInt ino, ULong foffset, const UChar* filename )
sewardj45b672d2003-07-25 19:58:11 +00002599{
nethercote71980f02004-01-24 18:18:54 +00002600 UInt prot = 0;
2601 UInt flags;
2602 Bool is_stack_segment;
2603 Addr r_esp;
sewardj45b672d2003-07-25 19:58:11 +00002604
nethercote71980f02004-01-24 18:18:54 +00002605 is_stack_segment
2606 = (start == VG_(clstk_base) && (start+size) == VG_(clstk_end));
fitzhardinge98abfc72003-12-16 02:05:15 +00002607
nethercote71980f02004-01-24 18:18:54 +00002608 if (rr == 'r') prot |= VKI_PROT_READ;
2609 if (ww == 'w') prot |= VKI_PROT_WRITE;
2610 if (xx == 'x') prot |= VKI_PROT_EXEC;
fitzhardinge98abfc72003-12-16 02:05:15 +00002611
nethercote71980f02004-01-24 18:18:54 +00002612 if (is_stack_segment)
2613 flags = SF_STACK | SF_GROWDOWN;
2614 else
2615 flags = SF_EXEC|SF_MMAP;
fitzhardinge98abfc72003-12-16 02:05:15 +00002616
nethercote71980f02004-01-24 18:18:54 +00002617 if (filename != NULL)
2618 flags |= SF_FILE;
fitzhardinge98abfc72003-12-16 02:05:15 +00002619
nethercote71980f02004-01-24 18:18:54 +00002620 if (start >= VG_(valgrind_base) && (start+size) <= VG_(valgrind_end))
2621 flags |= SF_VALGRIND;
fitzhardinge98abfc72003-12-16 02:05:15 +00002622
nethercote71980f02004-01-24 18:18:54 +00002623 VG_(map_file_segment)(start, size, prot, flags, dev, ino, foffset, filename);
fitzhardinge98abfc72003-12-16 02:05:15 +00002624
nethercote71980f02004-01-24 18:18:54 +00002625 if (VG_(is_client_addr)(start) && VG_(is_client_addr)(start+size-1))
2626 VG_TRACK( new_mem_startup, start, size, rr=='r', ww=='w', xx=='x' );
sewardj3e1eb1f2002-05-18 13:14:17 +00002627
nethercote71980f02004-01-24 18:18:54 +00002628 /* If this is the stack segment mark all below %esp as noaccess. */
2629 r_esp = esp_at_startup___global_arg;
2630 vg_assert(0 != r_esp);
2631 if (is_stack_segment) {
2632 if (0)
2633 VG_(message)(Vg_DebugMsg, "invalidating stack area: %x .. %x",
2634 start,r_esp);
2635 VG_TRACK( die_mem_stack, start, r_esp-start );
sewardjde4a1d02002-03-22 01:27:54 +00002636 }
sewardjde4a1d02002-03-22 01:27:54 +00002637}
2638
2639
nethercote71980f02004-01-24 18:18:54 +00002640/*====================================================================*/
2641/*=== Sanity check machinery (permanently engaged) ===*/
2642/*====================================================================*/
njn25e49d8e72002-09-23 09:36:25 +00002643
2644/* A fast sanity check -- suitable for calling circa once per
2645 millisecond. */
2646
2647void VG_(do_sanity_checks) ( Bool force_expensive )
2648{
njn37cea302002-09-30 11:24:00 +00002649 VGP_PUSHCC(VgpCoreCheapSanity);
2650
njn25e49d8e72002-09-23 09:36:25 +00002651 if (VG_(sanity_level) < 1) return;
2652
2653 /* --- First do all the tests that we can do quickly. ---*/
2654
2655 VG_(sanity_fast_count)++;
2656
njn25e49d8e72002-09-23 09:36:25 +00002657 /* Check stuff pertaining to the memory check system. */
2658
2659 /* Check that nobody has spuriously claimed that the first or
2660 last 16 pages of memory have become accessible [...] */
njn37cea302002-09-30 11:24:00 +00002661 if (VG_(needs).sanity_checks) {
2662 VGP_PUSHCC(VgpSkinCheapSanity);
njn25e49d8e72002-09-23 09:36:25 +00002663 vg_assert(SK_(cheap_sanity_check)());
njn37cea302002-09-30 11:24:00 +00002664 VGP_POPCC(VgpSkinCheapSanity);
2665 }
njn25e49d8e72002-09-23 09:36:25 +00002666
2667 /* --- Now some more expensive checks. ---*/
2668
2669 /* Once every 25 times, check some more expensive stuff. */
2670 if ( force_expensive
2671 || VG_(sanity_level) > 1
2672 || (VG_(sanity_level) == 1 && (VG_(sanity_fast_count) % 25) == 0)) {
2673
njn37cea302002-09-30 11:24:00 +00002674 VGP_PUSHCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002675 VG_(sanity_slow_count)++;
2676
jsgf855d93d2003-10-13 22:26:55 +00002677 VG_(proxy_sanity)();
2678
njn25e49d8e72002-09-23 09:36:25 +00002679# if 0
2680 { void zzzmemscan(void); zzzmemscan(); }
2681# endif
2682
2683 if ((VG_(sanity_fast_count) % 250) == 0)
2684 VG_(sanity_check_tc_tt)();
2685
2686 if (VG_(needs).sanity_checks) {
njn37cea302002-09-30 11:24:00 +00002687 VGP_PUSHCC(VgpSkinExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002688 vg_assert(SK_(expensive_sanity_check)());
njn37cea302002-09-30 11:24:00 +00002689 VGP_POPCC(VgpSkinExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002690 }
2691 /*
2692 if ((VG_(sanity_fast_count) % 500) == 0) VG_(mallocSanityCheckAll)();
2693 */
njn37cea302002-09-30 11:24:00 +00002694 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002695 }
2696
2697 if (VG_(sanity_level) > 1) {
njn37cea302002-09-30 11:24:00 +00002698 VGP_PUSHCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002699 /* Check sanity of the low-level memory manager. Note that bugs
2700 in the client's code can cause this to fail, so we don't do
2701 this check unless specially asked for. And because it's
2702 potentially very expensive. */
2703 VG_(mallocSanityCheckAll)();
njn37cea302002-09-30 11:24:00 +00002704 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002705 }
njn37cea302002-09-30 11:24:00 +00002706 VGP_POPCC(VgpCoreCheapSanity);
njn25e49d8e72002-09-23 09:36:25 +00002707}
nethercote71980f02004-01-24 18:18:54 +00002708
2709
2710/*====================================================================*/
2711/*=== main() ===*/
2712/*====================================================================*/
2713
2714int main(int argc, char **argv)
2715{
2716 char **cl_argv;
2717 const char *tool = NULL;
2718 const char *exec = NULL;
2719 char *preload; /* tool-specific LD_PRELOAD .so */
2720 char **env;
nethercote6c999f22004-01-31 22:55:15 +00002721 Int need_help = 0; // 0 = no, 1 = --help, 2 = --help-debug
nethercote71980f02004-01-24 18:18:54 +00002722 struct exeinfo info;
2723 ToolInfo *toolinfo = NULL;
2724 void *tool_dlhandle;
2725 Addr client_eip;
2726 Addr esp_at_startup; /* client's %esp at the point we gained control. */
2727 UInt * client_auxv;
2728 VgSchedReturnCode src;
fitzhardingeb50068f2004-02-24 23:42:55 +00002729 vki_rlimit zero = { 0, 0 };
nethercote71980f02004-01-24 18:18:54 +00002730
2731 //============================================================
2732 // Nb: startup is complex. Prerequisites are shown at every step.
2733 //
2734 // *** Be very careful when messing with the order ***
2735 //============================================================
2736
nethercotef4928da2004-06-15 10:54:40 +00002737 //============================================================
2738 // Command line argument handling order:
2739 // * If --help/--help-debug are present, show usage message
2740 // (if --tool is also present, that includes the tool-specific usage)
2741 // * Then, if --tool is missing, abort with error msg
2742 // * Then, if client is missing, abort with error msg
2743 // * Then, if any cmdline args are bad, abort with error msg
2744 //============================================================
2745
fitzhardingeb50068f2004-02-24 23:42:55 +00002746 // Get the current process datasize rlimit, and set it to zero.
2747 // This prevents any internal uses of brk() from having any effect.
2748 // We remember the old value so we can restore it on exec, so that
2749 // child processes will have a reasonable brk value.
2750 VG_(getrlimit)(VKI_RLIMIT_DATA, &VG_(client_rlimit_data));
2751 zero.rlim_max = VG_(client_rlimit_data).rlim_max;
2752 VG_(setrlimit)(VKI_RLIMIT_DATA, &zero);
2753
nethercote71980f02004-01-24 18:18:54 +00002754 //--------------------------------------------------------------
2755 // Check we were launched by stage1
2756 // p: n/a [must be first step]
2757 //--------------------------------------------------------------
2758 scan_auxv();
2759
2760 if (0) {
2761 int prmap(void *start, void *end, const char *perm, off_t off,
2762 int maj, int min, int ino) {
2763 printf("mapping %10p-%10p %s %02x:%02x %d\n",
2764 start, end, perm, maj, min, ino);
2765 return True;
2766 }
2767 printf("========== main() ==========\n");
2768 foreach_map(prmap);
2769 }
2770
2771 //--------------------------------------------------------------
2772 // Look for alternative libdir
2773 // p: n/a
2774 //--------------------------------------------------------------
2775 { char *cp = getenv(VALGRINDLIB);
2776 if (cp != NULL)
2777 VG_(libdir) = cp;
2778 }
2779
2780 //--------------------------------------------------------------
2781 // Begin working out address space layout
2782 // p: n/a
2783 //--------------------------------------------------------------
2784 layout_client_space( (Addr) & argc );
2785
2786 //--------------------------------------------------------------
2787 // Get valgrind args + client args (inc. from VALGRIND_OPTS/.valgrindrc).
2788 // Pre-process the command line.
2789 // p: n/a
2790 //--------------------------------------------------------------
2791 get_command_line(argc, argv, &VG_(vg_argc), &VG_(vg_argv), &cl_argv);
2792 pre_process_cmd_line_options(&need_help, &tool, &exec);
2793
2794 //==============================================================
2795 // Nb: once a tool is specified, the tool.so must be loaded even if
2796 // they specified --help or didn't specify a client program.
2797 //==============================================================
2798
2799 //--------------------------------------------------------------
2800 // With client padded out, map in tool
2801 // p: layout_client_space() [for padding]
2802 // p: set-libdir [for VG_(libdir)]
2803 // p: pre_process_cmd_line_options() [for 'tool']
2804 //--------------------------------------------------------------
2805 load_tool(tool, &tool_dlhandle, &toolinfo, &preload);
2806
2807 //==============================================================
2808 // Can use VG_(malloc)() and VG_(arena_malloc)() only after load_tool()
2809 // -- redzone size is now set.
2810 //==============================================================
2811
2812 //--------------------------------------------------------------
2813 // Finalise address space layout
2814 // p: layout_client_space(), load_tool() [for 'toolinfo']
2815 //--------------------------------------------------------------
2816 layout_remaining_space( toolinfo->shadow_ratio );
2817
2818 //--------------------------------------------------------------
2819 // Load client executable, finding in $PATH if necessary
2820 // p: layout_client_space() [so there's space]
2821 // p: pre_process_cmd_line_options() [for 'exec', 'need_help']
2822 // p: layout_remaining_space [so there's space]
2823 //--------------------------------------------------------------
nethercotef4928da2004-06-15 10:54:40 +00002824 load_client(cl_argv, exec, need_help, &info, &client_eip);
nethercote71980f02004-01-24 18:18:54 +00002825
2826 //--------------------------------------------------------------
2827 // Everything in place, unpad us
2828 // p: layout_remaining_space() [everything must be mapped in before now]
2829 // p: load_client() [ditto]
2830 //--------------------------------------------------------------
2831 as_unpad((void *)VG_(shadow_end), (void *)~0);
2832 as_closepadfile(); /* no more padding */
2833
2834 //--------------------------------------------------------------
2835 // Set up client's environment
2836 // p: set-libdir [for VG_(libdir)]
2837 // p: load_tool() [for 'preload']
2838 //--------------------------------------------------------------
2839 env = fix_environment(environ, preload);
2840
2841 //--------------------------------------------------------------
2842 // Setup client stack and eip
2843 // p: load_client() [for 'info']
2844 // p: fix_environment() [for 'env']
2845 //--------------------------------------------------------------
2846 esp_at_startup = setup_client_stack(cl_argv, env, &info, &client_auxv);
2847
2848 if (0)
2849 printf("entry=%x client esp=%x vg_argc=%d brkbase=%x\n",
2850 client_eip, esp_at_startup, VG_(vg_argc), VG_(brk_base));
2851
2852 //==============================================================
2853 // Finished setting up operating environment. Now initialise
2854 // Valgrind. (This is where the old VG_(main)() started.)
2855 //==============================================================
2856
2857 //--------------------------------------------------------------
2858 // Read /proc/self/maps into a buffer
2859 // p: all memory layout, environment setup [so memory maps are right]
2860 //--------------------------------------------------------------
2861 VG_(read_procselfmaps)();
2862
2863 //--------------------------------------------------------------
2864 // atfork
2865 // p: n/a
2866 //--------------------------------------------------------------
2867 VG_(atfork)(NULL, NULL, newpid);
2868 newpid(VG_INVALID_THREADID);
2869
2870 //--------------------------------------------------------------
2871 // setup file descriptors
2872 // p: n/a
2873 //--------------------------------------------------------------
2874 setup_file_descriptors();
2875
2876 //--------------------------------------------------------------
2877 // Setup tool
2878 // p: VG_(read_procselfmaps)() [so if sk_pre_clo_init calls
2879 // VG_(malloc), any mmap'd superblocks aren't erroneously
2880 // identified later as being owned by the client]
2881 // XXX: is that necessary, now that we look for V's segments separately?
2882 // XXX: alternatively, if sk_pre_clo_init does use VG_(malloc)(), is it
2883 // wrong to ignore any segments that might add in parse_procselfmaps?
2884 //--------------------------------------------------------------
2885 (*toolinfo->sk_pre_clo_init)();
2886 VG_(tool_init_dlsym)(tool_dlhandle);
2887 VG_(sanity_check_needs)();
2888
2889 //--------------------------------------------------------------
nethercotef4928da2004-06-15 10:54:40 +00002890 // If --tool and --help/--help-debug was given, now give the core+tool
2891 // help message
2892 // p: pre_clo_init()
2893 //--------------------------------------------------------------
2894 if (need_help) {
2895 usage(/*--help-debug?*/2 == need_help);
2896 }
2897
2898 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002899 // Process Valgrind's + tool's command-line options
2900 // p: load_tool() [for 'tool']
nethercote71980f02004-01-24 18:18:54 +00002901 // p: setup_file_descriptors() [for 'VG_(max_fd)']
2902 // p: sk_pre_clo_init [to set 'command_line_options' need]
2903 //--------------------------------------------------------------
nethercotef4928da2004-06-15 10:54:40 +00002904 process_cmd_line_options(client_auxv, esp_at_startup, tool);
nethercote71980f02004-01-24 18:18:54 +00002905
2906 //--------------------------------------------------------------
2907 // Allow GDB attach
2908 // p: process_cmd_line_options() [for VG_(clo_wait_for_gdb)]
2909 //--------------------------------------------------------------
2910 /* Hook to delay things long enough so we can get the pid and
2911 attach GDB in another shell. */
2912 if (VG_(clo_wait_for_gdb)) {
2913 VG_(printf)("pid=%d\n", VG_(getpid)());
2914 /* do "jump *$eip" to skip this in gdb */
2915 VG_(do_syscall)(__NR_pause);
2916 }
2917
2918 //--------------------------------------------------------------
2919 // Setup tool, post command-line processing
2920 // p: process_cmd_line_options [tool assumes it]
2921 //--------------------------------------------------------------
2922 SK_(post_clo_init)();
2923
2924 //--------------------------------------------------------------
nethercote1d447092004-02-01 17:29:59 +00002925 // Set up baseBlock
nethercote71980f02004-01-24 18:18:54 +00002926 // p: {pre,post}_clo_init() [for tool helper registration]
2927 // load_client() [for 'client_eip']
2928 // setup_client_stack() [for 'esp_at_startup']
2929 //--------------------------------------------------------------
2930 init_baseBlock(client_eip, esp_at_startup);
2931
2932 //--------------------------------------------------------------
2933 // Search for file descriptors that are inherited from our parent
2934 // p: process_cmd_line_options [for VG_(clo_track_fds)]
2935 //--------------------------------------------------------------
2936 if (VG_(clo_track_fds))
2937 VG_(init_preopened_fds)();
2938
2939 //--------------------------------------------------------------
2940 // Initialise the scheduler
2941 // p: init_baseBlock() [baseBlock regs copied into VG_(threads)[1]]
2942 // p: setup_file_descriptors() [else VG_(safe_fd)() breaks]
2943 //--------------------------------------------------------------
2944 VG_(scheduler_init)();
2945
2946 //--------------------------------------------------------------
2947 // Set up the ProxyLWP machinery
2948 // p: VG_(scheduler_init)()? [XXX: subtle dependency?]
2949 // - subs: VG_(sigstartup_actions)()?
2950 //--------------------------------------------------------------
2951 VG_(proxy_init)();
2952
2953 //--------------------------------------------------------------
2954 // Initialise the signal handling subsystem
2955 // p: VG_(atfork)(NULL, NULL, newpid) [else problems with sigmasks]
2956 // p: VG_(proxy_init)() [else breaks...]
2957 //--------------------------------------------------------------
2958 // Nb: temporarily parks the saved blocking-mask in saved_sigmask.
2959 VG_(sigstartup_actions)();
2960
2961 //--------------------------------------------------------------
2962 // Perhaps we're profiling Valgrind?
2963 // p: process_cmd_line_options() [for VG_(clo_profile)]
2964 // p: others?
2965 //
2966 // XXX: this seems to be broken? It always says the tool wasn't built
2967 // for profiling; vg_profile.c's functions don't seem to be overriding
2968 // vg_dummy_profile.c's?
2969 //
2970 // XXX: want this as early as possible. Looking for --profile
2971 // in pre_process_cmd_line_options() could get it earlier.
2972 //--------------------------------------------------------------
2973 if (VG_(clo_profile))
2974 VGP_(init_profiling)();
2975
2976 VGP_PUSHCC(VgpStartup);
2977
2978 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002979 // Reserve Valgrind's kickstart, heap and stack
2980 // p: XXX ???
2981 //--------------------------------------------------------------
2982 VG_(map_segment)(VG_(valgrind_mmap_end),
2983 VG_(valgrind_end)-VG_(valgrind_mmap_end),
2984 VKI_PROT_NONE, SF_VALGRIND|SF_FIXED);
2985
2986 //--------------------------------------------------------------
2987 // Identify Valgrind's segments
2988 // p: read proc/self/maps
2989 // p: VG_(map_segment) [XXX ???]
2990 // p: sk_pre_clo_init() [to setup new_mem_startup tracker]
2991 //--------------------------------------------------------------
2992 VG_(parse_procselfmaps) ( build_valgrind_map_callback );
2993
2994 // XXX: I can't see why these two need to be separate; could they be
2995 // folded together? If not, need a comment explaining why.
2996 //
2997 // XXX: can we merge reading and parsing of /proc/self/maps?
2998 //
2999 // XXX: can we dynamically allocate the /proc/self/maps buffer? (or mmap
3000 // it?) Or does that disturb its contents...
3001
3002 //--------------------------------------------------------------
3003 // Build segment map (all segments)
3004 // p: setup_client_stack() [for 'esp_at_startup']
3005 //--------------------------------------------------------------
3006 esp_at_startup___global_arg = esp_at_startup;
3007 VG_(parse_procselfmaps) ( build_segment_map_callback ); /* everything */
3008 esp_at_startup___global_arg = 0;
3009
3010 //==============================================================
3011 // Can only use VG_(map)() after VG_(map_segment)() [XXX ???]
3012 //==============================================================
3013
3014 //--------------------------------------------------------------
3015 // Build segment map (all segments)
3016 // p: setup_client_stack() [for 'esp_at_startup']
3017 //--------------------------------------------------------------
3018 /* Initialize our trampoline page (which is also sysinfo stuff) */
3019 VG_(memcpy)( (void *)VG_(client_trampoline_code),
3020 &VG_(trampoline_code_start), VG_(trampoline_code_length) );
3021 VG_(mprotect)( (void *)VG_(client_trampoline_code),
3022 VG_(trampoline_code_length), VKI_PROT_READ|VKI_PROT_EXEC );
3023
3024 //--------------------------------------------------------------
3025 // Read suppression file
3026 // p: process_cmd_line_options() [for VG_(clo_suppressions)]
3027 //--------------------------------------------------------------
3028 if (VG_(needs).core_errors || VG_(needs).skin_errors)
3029 VG_(load_suppressions)();
3030
3031 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00003032 // Initialise translation table and translation cache
3033 // p: read_procselfmaps [so the anonymous mmaps for the TT/TC
3034 // aren't identified as part of the client, which would waste
3035 // > 20M of virtual address space.]
3036 //--------------------------------------------------------------
3037 VG_(init_tt_tc)();
3038
3039 //--------------------------------------------------------------
3040 // Read debug info to find glibc entry points to intercept
3041 // p: parse_procselfmaps? [XXX for debug info?]
3042 // p: init_tt_tc? [XXX ???]
3043 //--------------------------------------------------------------
3044 VG_(setup_code_redirect_table)();
3045
3046 //--------------------------------------------------------------
3047 // Verbosity message
3048 // p: end_rdtsc_calibration [so startup message is printed first]
3049 //--------------------------------------------------------------
3050 if (VG_(clo_verbosity) == 1)
3051 VG_(message)(Vg_UserMsg, "For more details, rerun with: -v");
3052 if (VG_(clo_verbosity) > 0)
3053 VG_(message)(Vg_UserMsg, "");
3054
3055 //--------------------------------------------------------------
3056 // Setup pointercheck
3057 // p: process_cmd_line_options() [for VG_(clo_pointercheck)]
3058 //--------------------------------------------------------------
3059 setup_pointercheck();
3060
3061
3062
3063 //--------------------------------------------------------------
3064 // Run!
3065 //--------------------------------------------------------------
3066 VG_(running_on_simd_CPU) = True;
3067 VGP_POPCC(VgpStartup);
3068 VGP_PUSHCC(VgpSched);
3069
3070 if (__builtin_setjmp(&VG_(fatal_signal_jmpbuf)) == 0) {
3071 VG_(fatal_signal_set) = True;
3072 src = VG_(scheduler)();
3073 } else
3074 src = VgSrc_FatalSig;
3075
3076 VGP_POPCC(VgpSched);
3077 VG_(running_on_simd_CPU) = False;
3078
3079
3080
3081 //--------------------------------------------------------------
3082 // Finalisation: cleanup, messages, etc. Order no so important, only
3083 // affects what order the messages come.
3084 //--------------------------------------------------------------
3085 if (VG_(clo_verbosity) > 0)
3086 VG_(message)(Vg_UserMsg, "");
3087
3088 if (src == VgSrc_Deadlock) {
3089 VG_(message)(Vg_UserMsg,
3090 "Warning: pthread scheduler exited due to deadlock");
3091 }
3092
3093 /* Print out file descriptor summary and stats. */
3094 if (VG_(clo_track_fds))
3095 VG_(fd_stats)();
3096
3097 if (VG_(needs).core_errors || VG_(needs).skin_errors)
3098 VG_(show_all_errors)();
3099
3100 SK_(fini)( VG_(exitcode) );
3101
3102 VG_(do_sanity_checks)( True /*include expensive checks*/ );
3103
3104 if (VG_(clo_verbosity) > 1)
3105 show_counts();
3106
3107 if (VG_(clo_verbosity) > 3)
3108 VG_(print_UInstr_histogram)();
3109
3110 if (0) {
3111 VG_(message)(Vg_DebugMsg, "");
3112 VG_(message)(Vg_DebugMsg,
3113 "------ Valgrind's internal memory use stats follow ------" );
3114 VG_(mallocSanityCheckAll)();
3115 VG_(show_all_arena_stats)();
3116 VG_(message)(Vg_DebugMsg,
3117 "------ Valgrind's ExeContext management stats follow ------" );
3118 VG_(show_ExeContext_stats)();
3119 }
3120
3121 if (VG_(clo_profile))
3122 VGP_(done_profiling)();
3123
nethercote71980f02004-01-24 18:18:54 +00003124 /* We're exiting, so nuke all the threads and clean up the proxy LWPs */
3125 vg_assert(src == VgSrc_FatalSig ||
3126 VG_(threads)[VG_(last_run_tid)].status == VgTs_Runnable ||
3127 VG_(threads)[VG_(last_run_tid)].status == VgTs_WaitJoiner);
3128 VG_(nuke_all_threads_except)(VG_INVALID_THREADID);
3129
3130 //--------------------------------------------------------------
3131 // Exit, according to the scheduler's return code
3132 //--------------------------------------------------------------
3133 switch (src) {
3134 case VgSrc_ExitSyscall: /* the normal way out */
3135 vg_assert(VG_(last_run_tid) > 0
3136 && VG_(last_run_tid) < VG_N_THREADS);
3137 VG_(proxy_shutdown)();
3138
3139 /* The thread's %EBX at the time it did __NR_exit() will hold
3140 the arg to __NR_exit(), so we just do __NR_exit() with
3141 that arg. */
3142 VG_(exit)( VG_(exitcode) );
3143 /* NOT ALIVE HERE! */
3144 VG_(core_panic)("entered the afterlife in main() -- ExitSyscall");
3145 break; /* what the hell :) */
3146
3147 case VgSrc_Deadlock:
3148 /* Just exit now. No point in continuing. */
3149 VG_(proxy_shutdown)();
3150 VG_(exit)(0);
3151 VG_(core_panic)("entered the afterlife in main() -- Deadlock");
3152 break;
3153
nethercote71980f02004-01-24 18:18:54 +00003154 case VgSrc_FatalSig:
3155 /* We were killed by a fatal signal, so replicate the effect */
3156 vg_assert(VG_(fatal_sigNo) != -1);
3157 VG_(kill_self)(VG_(fatal_sigNo));
3158 VG_(core_panic)("main(): signal was supposed to be fatal");
3159 break;
3160
3161 default:
3162 VG_(core_panic)("main(): unexpected scheduler return code");
3163 }
3164
3165 abort();
3166}
3167
3168
sewardjde4a1d02002-03-22 01:27:54 +00003169/*--------------------------------------------------------------------*/
3170/*--- end vg_main.c ---*/
3171/*--------------------------------------------------------------------*/