blob: ebbb33a0e8d2db30f0ccac8a525e3f6c69c8876d [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>
50#include <sys/user.h>
51#include <sys/wait.h>
52#include <unistd.h>
53
nethercote71980f02004-01-24 18:18:54 +000054#ifndef AT_SYSINFO
55#define AT_SYSINFO 32
56#endif /* AT_SYSINFO */
57
58#ifndef AT_SYSINFO_EHDR
59#define AT_SYSINFO_EHDR 33
60#endif /* AT_SYSINFO_EHDR */
61
62#ifndef AT_SECURE
63#define AT_SECURE 23 /* secure mode boolean */
64#endif /* AT_SECURE */
65
66/* Amount to reserve for Valgrind's internal heap */
67#define VALGRIND_HEAPSIZE (128*1024*1024)
68
69/* Amount to reserve for Valgrind's internal mappings */
70#define VALGRIND_MAPSIZE (128*1024*1024)
71
72/* redzone gap between client address space and shadow */
73#define REDZONE_SIZE (1 * 1024*1024)
74
75/* size multiple for client address space */
76#define CLIENT_SIZE_MULTIPLE (64 * 1024*1024)
77
78#define ISSPACE(cc) ((cc) == ' ' || (cc) == '\t' || (cc) == '\n')
79
80/*====================================================================*/
81/*=== Global entities not referenced from generated code ===*/
82/*====================================================================*/
83
sewardjde4a1d02002-03-22 01:27:54 +000084/* ---------------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +000085 Startup stuff
sewardjde4a1d02002-03-22 01:27:54 +000086 ------------------------------------------------------------------ */
nethercote71980f02004-01-24 18:18:54 +000087/* linker-defined base address */
88extern char kickstart_base;
sewardjde4a1d02002-03-22 01:27:54 +000089
nethercote71980f02004-01-24 18:18:54 +000090/* Client address space, lowest to highest (see top of ume.c) */
91Addr VG_(client_base); /* client address space limits */
fitzhardinge98abfc72003-12-16 02:05:15 +000092Addr VG_(client_end);
93Addr VG_(client_mapbase);
fitzhardinge92360792003-12-24 10:11:11 +000094Addr VG_(client_trampoline_code);
fitzhardinge98abfc72003-12-16 02:05:15 +000095Addr VG_(clstk_base);
96Addr VG_(clstk_end);
nethercote71980f02004-01-24 18:18:54 +000097
98Addr VG_(brk_base); /* start of brk */
99Addr VG_(brk_limit); /* current brk */
100
101Addr VG_(shadow_base); /* skin's shadow memory */
fitzhardinge98abfc72003-12-16 02:05:15 +0000102Addr VG_(shadow_end);
nethercote71980f02004-01-24 18:18:54 +0000103
104Addr VG_(valgrind_base); /* valgrind's address range */
105Addr VG_(valgrind_mmap_end); /* valgrind's mmaps are between valgrind_base and here */
fitzhardinge98abfc72003-12-16 02:05:15 +0000106Addr VG_(valgrind_end);
107
nethercote71980f02004-01-24 18:18:54 +0000108/* This is set early to indicate whether this CPU has the
109 SSE/fxsave/fxrestor features. */
110Bool VG_(have_ssestate);
111
112/* Indicates presence, and holds address of client's sysinfo page, a
113 feature of some modern kernels used to provide vsyscalls, etc. */
114Bool VG_(sysinfo_page_exists) = False;
115Addr VG_(sysinfo_page_addr) = 0;
116
fitzhardinge98abfc72003-12-16 02:05:15 +0000117/* stage1 (main) executable */
fitzhardingea49f9b52003-12-16 22:26:45 +0000118Int VG_(vgexecfd) = -1;
119
120/* client executable */
121Int VG_(clexecfd) = -1;
fitzhardinge98abfc72003-12-16 02:05:15 +0000122
123/* Path to library directory */
124const Char *VG_(libdir) = VG_LIBDIR;
125
126/* our argc/argv */
127Int VG_(vg_argc);
128Char **VG_(vg_argv);
129
jsgf855d93d2003-10-13 22:26:55 +0000130/* PID of the main thread */
131Int VG_(main_pid);
132
133/* PGRP of process */
134Int VG_(main_pgrp);
njn25e49d8e72002-09-23 09:36:25 +0000135
fitzhardingef0046f22003-12-18 02:39:22 +0000136/* Maximum allowed application-visible file descriptor */
fitzhardingeb791a192003-12-18 07:22:44 +0000137Int VG_(max_fd) = -1;
fitzhardingef0046f22003-12-18 02:39:22 +0000138
nethercote71980f02004-01-24 18:18:54 +0000139/* As deduced from esp_at_startup, the client's argc, argv[] and
140 envp[] as extracted from the client's stack at startup-time. */
141Int VG_(client_argc);
142Char** VG_(client_argv);
143Char** VG_(client_envp);
sewardjde4a1d02002-03-22 01:27:54 +0000144
145/* ---------------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +0000146 Running stuff
sewardjde4a1d02002-03-22 01:27:54 +0000147 ------------------------------------------------------------------ */
nethercote71980f02004-01-24 18:18:54 +0000148/* Our signal delivery stack. */
njn6eba4ef2003-05-01 08:06:41 +0000149UInt VG_(sigstack)[VG_SIGSTACK_SIZE_W];
sewardjde4a1d02002-03-22 01:27:54 +0000150
151/* Saving stuff across system calls. */
sewardjb91ae7f2003-04-29 23:50:00 +0000152__attribute__ ((aligned (16)))
153UInt VG_(real_sse_state_saved_over_syscall)[VG_SIZE_OF_SSESTATE_W];
sewardj43c356f2002-06-02 00:21:08 +0000154Addr VG_(esp_saved_over_syscall);
sewardjde4a1d02002-03-22 01:27:54 +0000155
nethercote71980f02004-01-24 18:18:54 +0000156/* jmp_buf for fatal signals */
157Int VG_(fatal_sigNo) = -1;
158Bool VG_(fatal_signal_set) = False;
159jmp_buf VG_(fatal_signal_jmpbuf);
sewardjde4a1d02002-03-22 01:27:54 +0000160
nethercote71980f02004-01-24 18:18:54 +0000161/* Counts downwards in VG_(run_innerloop). */
162UInt VG_(dispatch_ctr);
sewardjde4a1d02002-03-22 01:27:54 +0000163
164/* 64-bit counter for the number of basic blocks done. */
165ULong VG_(bbs_done);
166/* 64-bit counter for the number of bbs to go before a debug exit. */
167ULong VG_(bbs_to_go);
168
sewardj7e87e382002-05-03 19:09:05 +0000169/* This is the ThreadId of the last thread the scheduler ran. */
170ThreadId VG_(last_run_tid) = 0;
171
nethercote71980f02004-01-24 18:18:54 +0000172/* Tell the logging mechanism whether we are logging to a file
173 descriptor or a socket descriptor. */
174Bool VG_(logging_to_filedes) = True;
175
176/* This Bool is needed by wrappers in vg_clientmalloc.c to decide how
177 to behave. Initially we say False. */
178Bool VG_(running_on_simd_CPU) = False;
179
njn25e49d8e72002-09-23 09:36:25 +0000180/* This is the argument to __NR_exit() supplied by the first thread to
181 call that syscall. We eventually pass that to __NR_exit() for
182 real. */
njn633de322003-05-12 20:40:13 +0000183Int VG_(exitcode) = 0;
njn25e49d8e72002-09-23 09:36:25 +0000184
sewardj73cf3bc2002-11-03 03:20:15 +0000185
nethercote71980f02004-01-24 18:18:54 +0000186/*====================================================================*/
187/*=== Counters, for profiling purposes only ===*/
188/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +0000189
190/* Number of lookups which miss the fast tt helper. */
191UInt VG_(tt_fast_misses) = 0;
192
193
sewardjc0d8f682002-11-30 00:49:43 +0000194/* Counts for TT/TC informational messages. */
sewardjde4a1d02002-03-22 01:27:54 +0000195
sewardjde4a1d02002-03-22 01:27:54 +0000196/* Number and total o/t size of translations overall. */
197UInt VG_(overall_in_count) = 0;
198UInt VG_(overall_in_osize) = 0;
199UInt VG_(overall_in_tsize) = 0;
200/* Number and total o/t size of discards overall. */
201UInt VG_(overall_out_count) = 0;
202UInt VG_(overall_out_osize) = 0;
203UInt VG_(overall_out_tsize) = 0;
sewardjc0d8f682002-11-30 00:49:43 +0000204/* The number of discards of TT/TC. */
205UInt VG_(number_of_tc_discards) = 0;
sewardj22854b92002-11-30 14:00:47 +0000206/* Counts of chain and unchain operations done. */
207UInt VG_(bb_enchain_count) = 0;
208UInt VG_(bb_dechain_count) = 0;
209/* Number of unchained jumps performed. */
210UInt VG_(unchained_jumps_done) = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000211
212
213/* Counts pertaining to the register allocator. */
214
215/* total number of uinstrs input to reg-alloc */
216UInt VG_(uinstrs_prealloc) = 0;
217
218/* total number of uinstrs added due to spill code */
219UInt VG_(uinstrs_spill) = 0;
220
221/* number of bbs requiring spill code */
222UInt VG_(translations_needing_spill) = 0;
223
224/* total of register ranks over all translations */
225UInt VG_(total_reg_rank) = 0;
226
227
sewardjde4a1d02002-03-22 01:27:54 +0000228/* Counts pertaining to internal sanity checking. */
sewardjde4a1d02002-03-22 01:27:54 +0000229UInt VG_(sanity_fast_count) = 0;
230UInt VG_(sanity_slow_count) = 0;
231
sewardj2e93c502002-04-12 11:12:52 +0000232/* Counts pertaining to the scheduler. */
233UInt VG_(num_scheduling_events_MINOR) = 0;
234UInt VG_(num_scheduling_events_MAJOR) = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000235
236
nethercote71980f02004-01-24 18:18:54 +0000237static __inline__ Int safe_idiv(Int a, Int b)
238{
239 return (b == 0 ? 0 : a / b);
240}
241
242static void show_counts ( void )
243{
244 VG_(message)(Vg_DebugMsg,
245 " TT/TC: %d tc sectors discarded.",
246 VG_(number_of_tc_discards) );
247 VG_(message)(Vg_DebugMsg,
248 " %d chainings, %d unchainings.",
249 VG_(bb_enchain_count), VG_(bb_dechain_count) );
250 VG_(message)(Vg_DebugMsg,
251 "translate: new %d (%d -> %d; ratio %d:10)",
252 VG_(overall_in_count),
253 VG_(overall_in_osize),
254 VG_(overall_in_tsize),
255 safe_idiv(10*VG_(overall_in_tsize), VG_(overall_in_osize)));
256 VG_(message)(Vg_DebugMsg,
257 " discard %d (%d -> %d; ratio %d:10).",
258 VG_(overall_out_count),
259 VG_(overall_out_osize),
260 VG_(overall_out_tsize),
261 safe_idiv(10*VG_(overall_out_tsize), VG_(overall_out_osize)));
262 VG_(message)(Vg_DebugMsg,
263 " dispatch: %llu jumps (bb entries), of which %u (%lu%%) were unchained.",
264 VG_(bbs_done),
265 VG_(unchained_jumps_done),
266 ((ULong)(100) * (ULong)(VG_(unchained_jumps_done)))
267 / ( VG_(bbs_done)==0 ? 1 : VG_(bbs_done) )
268 );
269
270 VG_(message)(Vg_DebugMsg,
271 " %d/%d major/minor sched events. %d tt_fast misses.",
272 VG_(num_scheduling_events_MAJOR),
273 VG_(num_scheduling_events_MINOR),
274 VG_(tt_fast_misses));
275
276 VG_(message)(Vg_DebugMsg,
277 "reg-alloc: %d t-req-spill, "
278 "%d+%d orig+spill uis, %d total-reg-r.",
279 VG_(translations_needing_spill),
280 VG_(uinstrs_prealloc),
281 VG_(uinstrs_spill),
282 VG_(total_reg_rank) );
283 VG_(message)(Vg_DebugMsg,
284 " sanity: %d cheap, %d expensive checks.",
285 VG_(sanity_fast_count),
286 VG_(sanity_slow_count) );
287 VG_(print_ccall_stats)();
288}
289
290
291/*====================================================================*/
292/*=== Miscellaneous global functions ===*/
293/*====================================================================*/
294
nethercote04d0fbc2004-01-26 16:48:06 +0000295/* Start debugger and get it to attach to this process. Called if the
296 user requests this service after an error has been shown, so she can
nethercote71980f02004-01-24 18:18:54 +0000297 poke around and look at parameters, memory, etc. You can't
nethercote04d0fbc2004-01-26 16:48:06 +0000298 meaningfully get the debugger to continue the program, though; to
299 continue, quit the debugger. */
300void VG_(start_debugger) ( Int tid )
nethercote71980f02004-01-24 18:18:54 +0000301{
302 Int pid;
303
304 if ((pid = fork()) == 0) {
305 ptrace(PTRACE_TRACEME, 0, NULL, NULL);
306 VG_(kkill)(VG_(getpid)(), VKI_SIGSTOP);
307
308 } else if (pid > 0) {
309 struct user_regs_struct regs;
310 Int status;
311 Int res;
312
313 if (VG_(is_running_thread)( tid )) {
314 regs.xcs = VG_(baseBlock)[VGOFF_(m_cs)];
315 regs.xss = VG_(baseBlock)[VGOFF_(m_ss)];
316 regs.xds = VG_(baseBlock)[VGOFF_(m_ds)];
317 regs.xes = VG_(baseBlock)[VGOFF_(m_es)];
318 regs.xfs = VG_(baseBlock)[VGOFF_(m_fs)];
319 regs.xgs = VG_(baseBlock)[VGOFF_(m_gs)];
320 regs.eax = VG_(baseBlock)[VGOFF_(m_eax)];
321 regs.ebx = VG_(baseBlock)[VGOFF_(m_ebx)];
322 regs.ecx = VG_(baseBlock)[VGOFF_(m_ecx)];
323 regs.edx = VG_(baseBlock)[VGOFF_(m_edx)];
324 regs.esi = VG_(baseBlock)[VGOFF_(m_esi)];
325 regs.edi = VG_(baseBlock)[VGOFF_(m_edi)];
326 regs.ebp = VG_(baseBlock)[VGOFF_(m_ebp)];
327 regs.esp = VG_(baseBlock)[VGOFF_(m_esp)];
328 regs.eflags = VG_(baseBlock)[VGOFF_(m_eflags)];
329 regs.eip = VG_(baseBlock)[VGOFF_(m_eip)];
330 } else {
331 ThreadState* tst = & VG_(threads)[ tid ];
332
333 regs.xcs = tst->m_cs;
334 regs.xss = tst->m_ss;
335 regs.xds = tst->m_ds;
336 regs.xes = tst->m_es;
337 regs.xfs = tst->m_fs;
338 regs.xgs = tst->m_gs;
339 regs.eax = tst->m_eax;
340 regs.ebx = tst->m_ebx;
341 regs.ecx = tst->m_ecx;
342 regs.edx = tst->m_edx;
343 regs.esi = tst->m_esi;
344 regs.edi = tst->m_edi;
345 regs.ebp = tst->m_ebp;
346 regs.esp = tst->m_esp;
347 regs.eflags = tst->m_eflags;
348 regs.eip = tst->m_eip;
349 }
350
351 if ((res = VG_(waitpid)(pid, &status, 0)) == pid &&
352 WIFSTOPPED(status) && WSTOPSIG(status) == SIGSTOP &&
353 ptrace(PTRACE_SETREGS, pid, NULL, &regs) == 0 &&
354 ptrace(PTRACE_DETACH, pid, NULL, SIGSTOP) == 0) {
nethercote04d0fbc2004-01-26 16:48:06 +0000355 Char pidbuf[15];
356 Char file[30];
357 Char buf[100];
358 Char *bufptr;
359 Char *cmdptr;
360
361 VG_(sprintf)(pidbuf, "%d", pid);
362 VG_(sprintf)(file, "/proc/%d/fd/%d", pid, VG_(clexecfd));
363
364 bufptr = buf;
365 cmdptr = VG_(clo_db_command);
366
367 while (*cmdptr) {
368 switch (*cmdptr) {
369 case '%':
370 switch (*++cmdptr) {
371 case 'f':
372 VG_(memcpy)(bufptr, file, VG_(strlen)(file));
373 bufptr += VG_(strlen)(file);
374 cmdptr++;
375 break;
376 case 'p':
377 VG_(memcpy)(bufptr, pidbuf, VG_(strlen)(pidbuf));
378 bufptr += VG_(strlen)(pidbuf);
379 cmdptr++;
380 break;
381 default:
382 *bufptr++ = *cmdptr++;
383 break;
384 }
385 break;
386 default:
387 *bufptr++ = *cmdptr++;
388 break;
389 }
390 }
391
392 *bufptr++ = '\0';
393
394 VG_(message)(Vg_UserMsg, "starting debugger with cmd: %s", buf);
nethercote71980f02004-01-24 18:18:54 +0000395 res = VG_(system)(buf);
396 if (res == 0) {
397 VG_(message)(Vg_UserMsg, "");
398 VG_(message)(Vg_UserMsg,
nethercote04d0fbc2004-01-26 16:48:06 +0000399 "Debugger has detached. Valgrind regains control. We continue.");
nethercote71980f02004-01-24 18:18:54 +0000400 } else {
401 VG_(message)(Vg_UserMsg, "Apparently failed!");
402 VG_(message)(Vg_UserMsg, "");
403 }
404 }
405
406 VG_(kkill)(pid, VKI_SIGKILL);
407 VG_(waitpid)(pid, &status, 0);
408 }
409}
410
411
412/* Print some helpful-ish text about unimplemented things, and give
413 up. */
414void VG_(unimplemented) ( Char* msg )
415{
416 VG_(message)(Vg_UserMsg, "");
417 VG_(message)(Vg_UserMsg,
418 "Valgrind detected that your program requires");
419 VG_(message)(Vg_UserMsg,
420 "the following unimplemented functionality:");
421 VG_(message)(Vg_UserMsg, " %s", msg);
422 VG_(message)(Vg_UserMsg,
423 "This may be because the functionality is hard to implement,");
424 VG_(message)(Vg_UserMsg,
425 "or because no reasonable program would behave this way,");
426 VG_(message)(Vg_UserMsg,
427 "or because nobody has yet needed it. In any case, let us know at");
428 VG_(message)(Vg_UserMsg,
429 "%s and/or try to work around the problem, if you can.", VG_BUGS_TO);
430 VG_(message)(Vg_UserMsg,
431 "");
432 VG_(message)(Vg_UserMsg,
433 "Valgrind has to exit now. Sorry. Bye!");
434 VG_(message)(Vg_UserMsg,
435 "");
436 VG_(pp_sched_status)();
437 VG_(exit)(1);
438}
439
440Addr VG_(get_stack_pointer) ( void )
441{
442 return VG_(baseBlock)[VGOFF_(m_esp)];
443}
444
445/* Debugging thing .. can be called from assembly with OYNK macro. */
446void VG_(oynk) ( Int n )
447{
448 OINK(n);
449}
450
451/* Initialize the PID and PGRP of scheduler LWP; this is also called
452 in any new children after fork. */
453static void newpid(ThreadId unused)
454{
455 /* PID of scheduler LWP */
456 VG_(main_pid) = VG_(getpid)();
457 VG_(main_pgrp) = VG_(getpgrp)();
458}
459
460/*====================================================================*/
461/*=== Check we were launched by stage 1 ===*/
462/*====================================================================*/
463
464/* Look for our AUXV table */
465static void scan_auxv(void)
466{
467 const struct ume_auxv *auxv = find_auxv((int *)ume_exec_esp);
468 int found = 0;
469
470 for (; auxv->a_type != AT_NULL; auxv++)
471 switch(auxv->a_type) {
472 case AT_UME_PADFD:
473 as_setpadfd(auxv->u.a_val);
474 found |= 1;
475 break;
476
477 case AT_UME_EXECFD:
478 VG_(vgexecfd) = auxv->u.a_val;
479 found |= 2;
480 break;
481 }
482
483 if ( ! (1|2) ) {
484 fprintf(stderr, "stage2 must be launched by stage1\n");
485 exit(127);
486 }
487}
488
489
490/*====================================================================*/
491/*=== Address space determination ===*/
492/*====================================================================*/
493
494/* Pad client space so it doesn't get filled in before the right time */
495static void layout_client_space(Addr argc_addr)
496{
497 VG_(client_base) = CLIENT_BASE;
498 VG_(valgrind_mmap_end) = (addr_t)&kickstart_base; /* end of V's mmaps */
499 VG_(valgrind_base) = VG_(valgrind_mmap_end) - VALGRIND_MAPSIZE;
500 VG_(valgrind_end) = ROUNDUP(argc_addr, 0x10000); /* stack */
501
502 if (0)
503 printf("client base: %x\n"
504 "valgrind base--end: %x--%x (%x)\n"
505 "valgrind mmap end: %x\n\n",
506 VG_(client_base),
507 VG_(valgrind_base), VG_(valgrind_end),
508 VG_(valgrind_end) - VG_(valgrind_base),
509 VG_(valgrind_mmap_end));
510
511 as_pad((void *)VG_(client_base), (void *)VG_(valgrind_base));
512}
513
514static void layout_remaining_space(float ratio)
515{
516 /* This tries to give the client as large as possible address space while
517 * taking into account the tool's shadow needs. */
518 addr_t client_size = ROUNDDN((VG_(valgrind_base) - REDZONE_SIZE) / (1. + ratio),
519 CLIENT_SIZE_MULTIPLE);
520 addr_t shadow_size = PGROUNDUP(client_size * ratio);
521
522 VG_(client_end) = VG_(client_base) + client_size;
523 VG_(client_mapbase) = PGROUNDDN((client_size/4)*3); /* where !FIXED mmap goes */
524 VG_(client_trampoline_code) = VG_(client_end) - VKI_BYTES_PER_PAGE;
525
526 VG_(shadow_base) = VG_(client_end) + REDZONE_SIZE;
527 VG_(shadow_end) = VG_(shadow_base) + shadow_size;
528
529 if (0)
530 printf("client base--end: %x--%x (%x)\n"
531 "client mapbase: %x\n"
532 "shadow base--end: %x--%x (%x)\n\n",
533 VG_(client_base), VG_(client_end), client_size,
534 VG_(client_mapbase),
535 VG_(shadow_base), VG_(shadow_end), shadow_size);
536
537 // Ban redzone
538 mmap((void *)VG_(client_end), REDZONE_SIZE, PROT_NONE,
539 MAP_FIXED|MAP_ANON|MAP_PRIVATE, -1, 0);
540
541 // Make client hole
542 munmap((void*)VG_(client_base), client_size);
543
544 // Map shadow memory.
545 // Initially all inaccessible, incrementally initialized as it is used
546 if (shadow_size != 0)
547 mmap((char *)VG_(shadow_base), shadow_size, PROT_NONE,
548 MAP_PRIVATE|MAP_ANON|MAP_FIXED, -1, 0);
549}
550
551/*====================================================================*/
552/*=== Command line setup ===*/
553/*====================================================================*/
554
555/* Nb: malloc'd memory never freed -- kept throughout like argv, envp */
556static char* get_file_clo(char* dir)
557{
558# define FLEN 512
559 Int fd, n;
560 struct stat s1;
561 char* f_clo = NULL;
562 char filename[FLEN];
563
564 snprintf(filename, FLEN, "%s/.valgrindrc", ( NULL == dir ? "" : dir ) );
565 fd = VG_(open)(filename, 0, VKI_S_IRUSR);
566 if ( fd > 0 ) {
567 if ( 0 == fstat(fd, &s1) ) {
568 f_clo = malloc(s1.st_size+1);
569 vg_assert(f_clo);
570 n = read(fd, f_clo, s1.st_size);
571 if (n == -1) n = 0;
572 f_clo[n] = '\0';
573 }
574 close(fd);
575 }
576 return f_clo;
577# undef FLEN
578}
579
580static Int count_args(char* s)
581{
582 Int n = 0;
583 if (s) {
584 char* cp = s;
585 while (True) {
586 // We have alternating sequences: blanks, non-blanks, blanks...
587 // count the non-blanks sequences.
588 while ( ISSPACE(*cp) ) cp++;
589 if ( !*cp ) break;
590 n++;
591 while ( !ISSPACE(*cp) && *cp ) cp++;
592 }
593 }
594 return n;
595}
596
597/* add args out of environment, skipping multiple spaces and -- args */
598static char** copy_args( char* s, char** to )
599{
600 if (s) {
601 char* cp = s;
602 while (True) {
603 // We have alternating sequences: blanks, non-blanks, blanks...
604 // copy the non-blanks sequences, and add terminating '\0'
605 while ( ISSPACE(*cp) ) cp++;
606 if ( !*cp ) break;
607 *to++ = cp;
608 while ( !ISSPACE(*cp) && *cp ) cp++;
609 if ( *cp ) *cp++ = '\0'; // terminate if necessary
610 if (VG_STREQ(to[-1], "--")) to--; // undo any '--' arg
611 }
612 }
613 return to;
614}
615
616// Augment command line with arguments from environment and .valgrindrc
617// files.
618static void augment_command_line(Int* vg_argc_inout, char*** vg_argv_inout)
619{
620 int vg_argc = *vg_argc_inout;
621 char** vg_argv = *vg_argv_inout;
622
623 char* env_clo = getenv(VALGRINDOPTS);
624 char* f1_clo = get_file_clo( getenv("HOME") );
625 char* f2_clo = get_file_clo(".");
626
627 /* copy any extra args from file or environment, if present */
628 if ( (env_clo && *env_clo) || (f1_clo && *f1_clo) || (f2_clo && *f2_clo) ) {
629 /* ' ' separated extra options */
630 char **from;
631 char **to;
632 int env_arg_count, f1_arg_count, f2_arg_count;
633
634 env_arg_count = count_args(env_clo);
635 f1_arg_count = count_args(f1_clo);
636 f2_arg_count = count_args(f2_clo);
637
638 if (0)
639 printf("extra-argc=%d %d %d\n",
640 env_arg_count, f1_arg_count, f2_arg_count);
641
642 /* +2: +1 for null-termination, +1 for added '--' */
643 from = vg_argv;
644 vg_argv = malloc( (vg_argc + env_arg_count + f1_arg_count
645 + f2_arg_count + 2) * sizeof(char **));
646 to = vg_argv;
647
648 /* copy argv[0] */
649 *to++ = *from++;
650
651 /* Copy extra args from env var and file, in the order: ~/.valgrindrc,
652 * $VALGRIND_OPTS, ./.valgrindrc -- more local options are put later
653 * to override less local ones. */
654 to = copy_args(f1_clo, to);
655 to = copy_args(env_clo, to);
656 to = copy_args(f2_clo, to);
657
658 /* copy original arguments, stopping at command or -- */
659 while (*from) {
660 if (**from != '-')
661 break;
662 if (VG_STREQ(*from, "--")) {
663 from++; /* skip -- */
664 break;
665 }
666 *to++ = *from++;
667 }
668
669 /* add -- */
670 *to++ = "--";
671
672 vg_argc = to - vg_argv;
673
674 /* copy rest of original command line, then NULL */
675 while (*from) *to++ = *from++;
676 *to = NULL;
677 }
678
679 *vg_argc_inout = vg_argc;
680 *vg_argv_inout = vg_argv;
681}
682
683static void get_command_line( int argc, char** argv,
684 Int* vg_argc_out, Char*** vg_argv_out,
685 char*** cl_argv_out )
686{
687 int vg_argc;
688 char** vg_argv;
689 char** cl_argv;
690 char* env_clo = getenv(VALGRINDCLO);
691
692 if (env_clo != NULL && *env_clo != '\0') {
693 char *cp;
694 char **cpp;
695
696 /* OK, we're getting all our arguments from the environment - the
697 entire command line belongs to the client (including argv[0]) */
698 vg_argc = 1; /* argv[0] */
699 for (cp = env_clo; *cp; cp++)
700 if (*cp == '\01')
701 vg_argc++;
702
703 vg_argv = malloc(sizeof(char **) * (vg_argc + 1));
704
705 cpp = vg_argv;
706
707 *cpp++ = "valgrind"; /* nominal argv[0] */
708 *cpp++ = env_clo;
709
710 for (cp = env_clo; *cp; cp++) {
711 if (*cp == '\01') {
712 *cp++ = '\0'; /* chop it up in place */
713 *cpp++ = cp;
714 }
715 }
716 *cpp = NULL;
717 cl_argv = argv;
718
719 } else {
720 /* Count the arguments on the command line. */
721 vg_argv = argv;
722
723 for (vg_argc = 1; vg_argc < argc; vg_argc++) {
724 if (argv[vg_argc][0] != '-') /* exe name */
725 break;
726 if (VG_STREQ(argv[vg_argc], "--")) { /* dummy arg */
727 vg_argc++;
728 break;
729 }
730 }
731 cl_argv = &argv[vg_argc];
732
733 /* Get extra args from VALGRIND_OPTS and .valgrindrc files.
734 * Note we don't do this if getting args from VALGRINDCLO. */
735 augment_command_line(&vg_argc, &vg_argv);
736 }
737
738 if (0) {
739 Int i;
740 for (i = 0; i < vg_argc; i++)
741 printf("vg_argv[%d]=\"%s\"\n", i, vg_argv[i]);
742 }
743
744 *vg_argc_out = vg_argc;
745 *vg_argv_out = (Char**)vg_argv;
746 *cl_argv_out = cl_argv;
747}
748
749
750/*====================================================================*/
751/*=== Environment and stack setup ===*/
752/*====================================================================*/
753
754/* Scan a colon-separated list, and call a function on each element.
755 The string must be mutable, because we insert a temporary '\0', but
756 the string will end up unmodified. (*func) should return 1 if it
757 doesn't need to see any more.
758*/
759static void scan_colsep(char *colsep, int (*func)(const char *))
760{
761 char *cp, *entry;
762 int end;
763
764 if (colsep == NULL ||
765 *colsep == '\0')
766 return;
767
768 entry = cp = colsep;
769
770 do {
771 end = (*cp == '\0');
772
773 if (*cp == ':' || *cp == '\0') {
774 char save = *cp;
775
776 *cp = '\0';
777 if ((*func)(entry))
778 end = 1;
779 *cp = save;
780 entry = cp+1;
781 }
782 cp++;
783 } while(!end);
784}
785
786/* Prepare the client's environment. This is basically a copy of our
787 environment, except:
788 1. LD_LIBRARY_PATH=$VALGRINDLIB:$LD_LIBRARY_PATH
789 2. LD_PRELOAD=$VALGRINDLIB/vg_inject.so:($VALGRINDLIB/vgpreload_TOOL.so:)?$LD_PRELOAD
790
791 If any of these is missing, then it is added.
792
793 Yummy. String hacking in C.
794
795 If this needs to handle any more variables it should be hacked
796 into something table driven.
797 */
798static char **fix_environment(char **origenv, const char *preload)
799{
800 static const char inject_so[] = "vg_inject.so";
801 static const char ld_library_path[] = "LD_LIBRARY_PATH=";
802 static const char ld_preload[] = "LD_PRELOAD=";
803 static const char valgrind_clo[] = VALGRINDCLO "=";
804 static const int ld_library_path_len = sizeof(ld_library_path)-1;
805 static const int ld_preload_len = sizeof(ld_preload)-1;
806 static const int valgrind_clo_len = sizeof(valgrind_clo)-1;
807 int ld_preload_done = 0;
808 int ld_library_path_done = 0;
809 char *inject_path;
810 int inject_path_len;
811 int vgliblen = strlen(VG_(libdir));
812 char **cpp;
813 char **ret;
814 int envc;
815 const int preloadlen = (preload == NULL) ? 0 : strlen(preload);
816
817 /* Find the vg_inject.so; also make room for the tool preload
818 library */
819 inject_path_len = sizeof(inject_so) + vgliblen + preloadlen + 16;
820 inject_path = malloc(inject_path_len);
821
822 if (preload)
823 snprintf(inject_path, inject_path_len, "%s/%s:%s",
824 VG_(libdir), inject_so, preload);
825 else
826 snprintf(inject_path, inject_path_len, "%s/%s",
827 VG_(libdir), inject_so);
828
829 /* Count the original size of the env */
830 envc = 0; /* trailing NULL */
831 for (cpp = origenv; cpp && *cpp; cpp++)
832 envc++;
833
834 /* Allocate a new space */
835 ret = malloc(sizeof(char *) * (envc+3+1)); /* 3 new entries + NULL */
836
837 /* copy it over */
838 for (cpp = ret; *origenv; )
839 *cpp++ = *origenv++;
840 *cpp = NULL;
841
842 vg_assert(envc == (cpp - ret));
843
844 /* Walk over the new environment, mashing as we go */
845 for (cpp = ret; cpp && *cpp; cpp++) {
846 if (memcmp(*cpp, ld_library_path, ld_library_path_len) == 0) {
847 int done = 0;
848 int contains(const char *p) {
849 if (VG_STREQ(p, VG_(libdir))) {
850 done = 1;
851 return 1;
852 }
853 return 0;
854 }
855
856 /* If the LD_LIBRARY_PATH already contains libdir, then don't
857 bother adding it again, even if it isn't the first (it
858 seems that the Java runtime will keep reexecing itself
859 unless its paths are at the front of LD_LIBRARY_PATH) */
860 scan_colsep(*cpp + ld_library_path_len, contains);
861
862 if (!done) {
863 int len = strlen(*cpp) + vgliblen*2 + 16;
864 char *cp = malloc(len);
865
866 snprintf(cp, len, "%s%s:%s",
867 ld_library_path, VG_(libdir),
868 (*cpp)+ld_library_path_len);
869
870 *cpp = cp;
871 }
872
873 ld_library_path_done = 1;
874 } else if (memcmp(*cpp, ld_preload, ld_preload_len) == 0) {
875 int len = strlen(*cpp) + inject_path_len;
876 char *cp = malloc(len);
877
878 snprintf(cp, len, "%s%s:%s",
879 ld_preload, inject_path, (*cpp)+ld_preload_len);
880
881 *cpp = cp;
882
883 ld_preload_done = 1;
884 } else if (memcmp(*cpp, valgrind_clo, valgrind_clo_len) == 0) {
885 *cpp = "";
886 }
887 }
888
889 /* Add the missing bits */
890
891 if (!ld_library_path_done) {
892 int len = ld_library_path_len + vgliblen*2 + 16;
893 char *cp = malloc(len);
894
895 snprintf(cp, len, "%s%s", ld_library_path, VG_(libdir));
896
897 ret[envc++] = cp;
898 }
899
900 if (!ld_preload_done) {
901 int len = ld_preload_len + inject_path_len;
902 char *cp = malloc(len);
903
904 snprintf(cp, len, "%s%s",
905 ld_preload, inject_path);
906
907 ret[envc++] = cp;
908 }
909
910 ret[envc] = NULL;
911
912 return ret;
913}
914
915extern char **environ; /* our environment */
916//#include <error.h>
917
918/* Add a string onto the string table, and return its address */
919static char *copy_str(char **tab, const char *str)
920{
921 char *cp = *tab;
922 char *orig = cp;
923
924 while(*str)
925 *cp++ = *str++;
926 *cp++ = '\0';
927
928 if (0)
929 printf("copied %p \"%s\" len %d\n",
930 orig, orig, cp-orig);
931
932 *tab = cp;
933
934 return orig;
935}
936
937/*
938 This sets up the client's initial stack, containing the args,
939 environment and aux vector.
940
941 The format of the stack is:
942
943 higher address +-----------------+
944 | Trampoline code |
945 +-----------------+
946 | |
947 : string table :
948 | |
949 +-----------------+
950 | AT_NULL |
951 - -
952 | auxv |
953 +-----------------+
954 | NULL |
955 - -
956 | envp |
957 +-----------------+
958 | NULL |
959 - -
960 | argv |
961 +-----------------+
962 | argc |
963 lower address +-----------------+ <- esp
964 | undefined |
965 : :
966 */
967static Addr setup_client_stack(char **orig_argv, char **orig_envp,
968 const struct exeinfo *info,
969 UInt** client_auxv)
970{
971 char **cpp;
972 char *strtab; /* string table */
973 char *stringbase;
974 addr_t *ptr;
975 struct ume_auxv *auxv;
976 const struct ume_auxv *orig_auxv;
977 const struct ume_auxv *cauxv;
978 unsigned stringsize; /* total size of strings in bytes */
979 unsigned auxsize; /* total size of auxv in bytes */
980 int argc; /* total argc */
981 int envc; /* total number of env vars */
982 unsigned stacksize; /* total client stack size */
983 addr_t cl_esp; /* client stack base (initial esp) */
984
985 /* use our own auxv as a prototype */
986 orig_auxv = find_auxv(ume_exec_esp);
987
988 /* ==================== compute sizes ==================== */
989
990 /* first of all, work out how big the client stack will be */
991 stringsize = 0;
992
993 /* paste on the extra args if the loader needs them (ie, the #!
994 interpreter and its argument) */
995 argc = 0;
996 if (info->argv0 != NULL) {
997 argc++;
998 stringsize += strlen(info->argv0) + 1;
999 }
1000 if (info->argv1 != NULL) {
1001 argc++;
1002 stringsize += strlen(info->argv1) + 1;
1003 }
1004
1005 /* now scan the args we're given... */
1006 for (cpp = orig_argv; *cpp; cpp++) {
1007 argc++;
1008 stringsize += strlen(*cpp) + 1;
1009 }
1010
1011 /* ...and the environment */
1012 envc = 0;
1013 for (cpp = orig_envp; cpp && *cpp; cpp++) {
1014 envc++;
1015 stringsize += strlen(*cpp) + 1;
1016 }
1017
1018 /* now, how big is the auxv? */
1019 auxsize = sizeof(*auxv); /* there's always at least one entry: AT_NULL */
1020 for (cauxv = orig_auxv; cauxv->a_type != AT_NULL; cauxv++) {
1021 if (cauxv->a_type == AT_PLATFORM)
1022 stringsize += strlen(cauxv->u.a_ptr) + 1;
1023 auxsize += sizeof(*cauxv);
1024 }
1025
1026 /* OK, now we know how big the client stack is */
1027 stacksize =
1028 sizeof(int) + /* argc */
1029 sizeof(char **)*argc + /* argv */
1030 sizeof(char **) + /* terminal NULL */
1031 sizeof(char **)*envc + /* envp */
1032 sizeof(char **) + /* terminal NULL */
1033 auxsize + /* auxv */
1034 ROUNDUP(stringsize, sizeof(int)) +/* strings (aligned) */
1035 VKI_BYTES_PER_PAGE; /* page for trampoline code */
1036
1037 /* cl_esp is the client's stack pointer */
1038 cl_esp = VG_(client_end) - stacksize;
1039 cl_esp = ROUNDDN(cl_esp, 16); /* make stack 16 byte aligned */
1040
1041 if (0)
1042 printf("stringsize=%d auxsize=%d stacksize=%d\n",
1043 stringsize, auxsize, stacksize);
1044
1045
1046 /* base of the string table (aligned) */
1047 stringbase = strtab = (char *)(VG_(client_trampoline_code) - ROUNDUP(stringsize, sizeof(int)));
1048
1049 VG_(clstk_base) = PGROUNDDN(cl_esp);
1050 VG_(clstk_end) = VG_(client_end);
1051
1052 /* ==================== allocate space ==================== */
1053
1054 /* allocate a stack - mmap enough space for the stack */
1055 mmap((void *)PGROUNDDN(cl_esp),
1056 VG_(client_end) - PGROUNDDN(cl_esp),
1057 PROT_READ | PROT_WRITE | PROT_EXEC,
1058 MAP_PRIVATE | MAP_ANON | MAP_FIXED, -1, 0);
1059
1060
1061 /* ==================== copy client stack ==================== */
1062
1063 ptr = (addr_t *)cl_esp;
1064
1065 /* --- argc --- */
1066 *ptr++ = argc; /* client argc */
1067
1068 /* --- argv --- */
1069 if (info->argv0) {
1070 *ptr++ = (addr_t)copy_str(&strtab, info->argv0);
1071 free(info->argv0);
1072 }
1073 if (info->argv1) {
1074 *ptr++ = (addr_t)copy_str(&strtab, info->argv1);
1075 free(info->argv1);
1076 }
1077 for (cpp = orig_argv; *cpp; ptr++, cpp++) {
1078 *ptr = (addr_t)copy_str(&strtab, *cpp);
1079 }
1080 *ptr++ = 0;
1081
1082 /* --- envp --- */
1083 VG_(client_envp) = (Char **)ptr;
1084 for (cpp = orig_envp; cpp && *cpp; ptr++, cpp++)
1085 *ptr = (addr_t)copy_str(&strtab, *cpp);
1086 *ptr++ = 0;
1087
1088 /* --- auxv --- */
1089 auxv = (struct ume_auxv *)ptr;
1090 *client_auxv = (UInt *)auxv;
1091
1092 for (; orig_auxv->a_type != AT_NULL; auxv++, orig_auxv++) {
1093 /* copy the entry... */
1094 *auxv = *orig_auxv;
1095
1096 /* ...and fix up the copy */
1097 switch(auxv->a_type) {
1098 case AT_PHDR:
1099 if (info->phdr == 0)
1100 auxv->a_type = AT_IGNORE;
1101 else
1102 auxv->u.a_val = info->phdr;
1103 break;
1104
1105 case AT_PHNUM:
1106 if (info->phdr == 0)
1107 auxv->a_type = AT_IGNORE;
1108 else
1109 auxv->u.a_val = info->phnum;
1110 break;
1111
1112 case AT_BASE:
1113 if (info->interp_base == 0)
1114 auxv->a_type = AT_IGNORE;
1115 else
1116 auxv->u.a_val = info->interp_base;
1117 break;
1118
1119 case AT_PLATFORM: /* points to a platform description string */
1120 auxv->u.a_ptr = copy_str(&strtab, orig_auxv->u.a_ptr);
1121 break;
1122
1123 case AT_ENTRY:
1124 auxv->u.a_val = info->entry;
1125 break;
1126
1127 case AT_IGNORE:
1128 case AT_EXECFD:
1129 case AT_PHENT:
1130 case AT_PAGESZ:
1131 case AT_FLAGS:
1132 case AT_NOTELF:
1133 case AT_UID:
1134 case AT_EUID:
1135 case AT_GID:
1136 case AT_EGID:
1137 case AT_CLKTCK:
1138 case AT_HWCAP:
1139 case AT_FPUCW:
1140 case AT_DCACHEBSIZE:
1141 case AT_ICACHEBSIZE:
1142 case AT_UCACHEBSIZE:
1143 /* All these are pointerless, so we don't need to do anything
1144 about them. */
1145 break;
1146
1147 case AT_SECURE:
1148 /* If this is 1, then it means that this program is running
1149 suid, and therefore the dynamic linker should be careful
1150 about LD_PRELOAD, etc. However, since stage1 (the thing
1151 the kernel actually execve's) should never be SUID, and we
1152 need LD_PRELOAD/LD_LIBRARY_PATH to work for the client, we
1153 set AT_SECURE to 0. */
1154 auxv->u.a_val = 0;
1155 break;
1156
1157 case AT_SYSINFO:
1158 /* Leave this unmolested for now, but we'll update it later
1159 when we set up the client trampoline code page */
1160 break;
1161
1162 case AT_SYSINFO_EHDR:
1163 /* Trash this, because we don't reproduce it */
1164 auxv->a_type = AT_IGNORE;
1165 break;
1166
1167 default:
1168 /* stomp out anything we don't know about */
1169 if (0)
1170 printf("stomping auxv entry %d\n", auxv->a_type);
1171 auxv->a_type = AT_IGNORE;
1172 break;
1173
1174 }
1175 }
1176 *auxv = *orig_auxv;
1177 vg_assert(auxv->a_type == AT_NULL);
1178
1179 vg_assert((strtab-stringbase) == stringsize);
1180
1181 return cl_esp;
1182}
1183
1184/*====================================================================*/
1185/*=== Find executable ===*/
1186/*====================================================================*/
1187
1188static const char* find_executable(const char* exec)
1189{
1190 vg_assert(NULL != exec);
1191 if (strchr(exec, '/') == NULL) {
1192 /* no '/' - we need to search the path */
1193 char *path = getenv("PATH");
1194 int pathlen = path ? strlen(path) : 0;
1195
1196 int match_exe(const char *entry) {
1197 char buf[pathlen + strlen(entry) + 3];
1198
1199 /* empty PATH element means . */
1200 if (*entry == '\0')
1201 entry = ".";
1202
1203 snprintf(buf, sizeof(buf), "%s/%s", entry, exec);
1204
1205 if (access(buf, R_OK|X_OK) == 0) {
1206 exec = strdup(buf);
1207 vg_assert(NULL != exec);
1208 return 1;
1209 }
1210 return 0;
1211 }
1212 scan_colsep(path, match_exe);
1213 }
1214 return exec;
1215}
1216
1217
1218/*====================================================================*/
1219/*=== Loading tools ===*/
1220/*====================================================================*/
1221
1222static void list_tools(void)
1223{
1224 DIR *dir = opendir(VG_(libdir));
1225 struct dirent *de;
1226 int first = 1;
1227
1228 if (dir == NULL) {
1229 fprintf(stderr, "Can't open %s: %s (installation problem?)\n",
1230 VG_(libdir), strerror(errno));
1231 return;
1232 }
1233
1234 while((de = readdir(dir)) != NULL) {
1235 int len = strlen(de->d_name);
1236
1237 /* look for vgskin_TOOL.so names */
1238 if (len > (7+1+3) && /* "vgskin_" + at least 1-char toolname + ".so" */
1239 strncmp(de->d_name, "vgskin_", 7) == 0 &&
1240 VG_STREQ(de->d_name + len - 3, ".so")) {
1241 if (first) {
1242 printf("Available tools:\n");
1243 first = 0;
1244 }
1245 de->d_name[len-3] = '\0';
1246 printf("\t%s\n", de->d_name+7);
1247 }
1248 }
1249
1250 closedir(dir);
1251
1252 if (first)
1253 printf("No tools available in \"%s\" (installation problem?)\n",
1254 VG_(libdir));
1255}
1256
1257
1258/* Find and load a tool, and check it looks ok. Also looks to see if there's
1259 * a matching vgpreload_*.so file, and returns its name in *preloadpath. */
1260static void load_tool( const char *toolname, void** handle_out,
1261 ToolInfo** toolinfo_out, char **preloadpath_out )
1262{
1263 Bool ok;
1264 int len = strlen(VG_(libdir)) + strlen(toolname)*2 + 16;
1265 char buf[len];
1266 void* handle;
1267 ToolInfo* toolinfo;
1268 char* preloadpath = NULL;
1269 Int* vg_malloc_redzonep;
1270
1271 // XXX: allowing full paths for --tool option -- does it make sense?
1272 // Doesn't allow for vgpreload_<tool>.so.
1273
1274 if (strchr(toolname, '/') != 0) {
1275 /* toolname contains '/', and so must be a pathname */
1276 handle = dlopen(toolname, RTLD_NOW);
1277 } else {
1278 /* just try in the libdir */
1279 snprintf(buf, len, "%s/vgskin_%s.so", VG_(libdir), toolname);
1280 handle = dlopen(buf, RTLD_NOW);
1281
1282 if (handle != NULL) {
1283 snprintf(buf, len, "%s/vgpreload_%s.so", VG_(libdir), toolname);
1284 if (access(buf, R_OK) == 0) {
1285 preloadpath = strdup(buf);
1286 vg_assert(NULL != preloadpath);
1287 }
1288 }
1289 }
1290
1291 ok = (NULL != handle);
1292 if (!ok) {
1293 fprintf(stderr, "Can't open tool \"%s\": %s\n", toolname, dlerror());
1294 goto bad_load;
1295 }
1296
1297 toolinfo = dlsym(handle, "vgSkin_tool_info");
1298 ok = (NULL != toolinfo);
1299 if (!ok) {
1300 fprintf(stderr, "Tool \"%s\" doesn't define SK_(tool_info) - "
1301 "add VG_DETERMINE_INTERFACE_VERSION?\n", toolname);
1302 goto bad_load;
1303 }
1304
1305 ok = (toolinfo->sizeof_ToolInfo == sizeof(*toolinfo) &&
1306 toolinfo->interface_major_version == VG_CORE_INTERFACE_MAJOR_VERSION &&
1307 toolinfo->sk_pre_clo_init != NULL);
1308 if (!ok) {
1309 fprintf(stderr, "Error:\n"
1310 " Tool and core interface versions do not match.\n"
1311 " Interface version used by core is: %d.%d (size %d)\n"
1312 " Interface version used by tool is: %d.%d (size %d)\n"
1313 " The major version numbers must match.\n",
1314 VG_CORE_INTERFACE_MAJOR_VERSION,
1315 VG_CORE_INTERFACE_MINOR_VERSION,
1316 sizeof(*toolinfo),
1317 toolinfo->interface_major_version,
1318 toolinfo->interface_minor_version,
1319 toolinfo->sizeof_ToolInfo);
1320 fprintf(stderr, " You need to at least recompile, and possibly update,\n");
1321 if (VG_CORE_INTERFACE_MAJOR_VERSION > toolinfo->interface_major_version)
1322 fprintf(stderr, " your skin to work with this version of Valgrind.\n");
1323 else
1324 fprintf(stderr, " your version of Valgrind to work with this skin.\n");
1325 goto bad_load;
1326 }
1327
1328 // Set redzone size for V's allocator
1329 vg_malloc_redzonep = dlsym(handle, STR(VG_(vg_malloc_redzone_szB)));
1330 if ( NULL != vg_malloc_redzonep ) {
1331 VG_(vg_malloc_redzone_szB) = *vg_malloc_redzonep;
1332 }
1333
1334 vg_assert(NULL != handle && NULL != toolinfo);
1335 *handle_out = handle;
1336 *toolinfo_out = toolinfo;
1337 *preloadpath_out = preloadpath;
1338 return;
1339
1340
1341 bad_load:
1342 if (handle != NULL)
1343 dlclose(handle);
1344
1345 fprintf(stderr, "Aborting: couldn't load tool\n");
1346 list_tools();
1347 exit(127);
1348}
1349
1350/*====================================================================*/
1351/*=== Loading the client ===*/
1352/*====================================================================*/
1353
1354static void load_client(char* cl_argv[], const char* exec,
nethercote6c999f22004-01-31 22:55:15 +00001355 /*inout*/Int* need_help,
nethercote71980f02004-01-24 18:18:54 +00001356 /*out*/struct exeinfo* info, /*out*/Addr* client_eip)
1357{
1358 // If they didn't specify an executable with --exec, and didn't specify
1359 // --help, then use client argv[0] (searching $PATH if necessary).
1360 if (NULL == exec && !*need_help) {
1361 if (cl_argv[0] == NULL ||
1362 ( NULL == (exec = find_executable(cl_argv[0])) ) )
1363 {
nethercote6c999f22004-01-31 22:55:15 +00001364 *need_help = 1;
nethercote71980f02004-01-24 18:18:54 +00001365 }
1366 }
1367
1368 info->map_base = VG_(client_mapbase);
1369 info->setbrk = False;
1370
1371 info->exe_base = VG_(client_base);
1372 info->exe_end = VG_(client_end);
1373 info->argv = cl_argv;
1374
1375 if (*need_help) {
1376 VG_(clexecfd) = -1;
1377 info->argv0 = NULL;
1378 info->argv1 = NULL;
1379 } else {
1380 Int ret;
1381 VG_(clexecfd) = VG_(open)(exec, O_RDONLY, VKI_S_IRUSR);
1382 ret = do_exec(exec, info);
1383 if (ret != 0) {
1384 fprintf(stderr, "do_exec(%s) failed: %s\n", exec, strerror(ret));
1385 exit(127);
1386 }
1387 }
1388
1389 /* Copy necessary bits of 'info' that were filled in */
1390 *client_eip = info->init_eip;
1391 VG_(brk_base) = VG_(brk_limit) = info->brkbase;
1392}
1393
1394
1395/*====================================================================*/
1396/*=== Command-line: variables, processing ===*/
1397/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +00001398
njn25e49d8e72002-09-23 09:36:25 +00001399/* Define, and set defaults. */
1400Bool VG_(clo_error_limit) = True;
nethercote04d0fbc2004-01-26 16:48:06 +00001401Bool VG_(clo_db_attach) = False;
1402Char* VG_(clo_db_command) = VG_CLO_DEFAULT_DBCOMMAND;
njn43c799e2003-04-08 00:08:52 +00001403Bool VG_(clo_gen_suppressions) = False;
njn25e49d8e72002-09-23 09:36:25 +00001404Int VG_(sanity_level) = 1;
1405Int VG_(clo_verbosity) = 1;
1406Bool VG_(clo_demangle) = True;
njn25e49d8e72002-09-23 09:36:25 +00001407Bool VG_(clo_trace_children) = False;
sewardj4cf05692002-10-27 20:28:29 +00001408
nethercotee1730692003-11-20 10:38:07 +00001409/* See big comment in vg_include.h for meaning of these three.
1410 fd is initially stdout, for --help, but gets moved to stderr by default
1411 immediately afterwards. */
sewardj4cf05692002-10-27 20:28:29 +00001412VgLogTo VG_(clo_log_to) = VgLogTo_Fd;
nethercotee1730692003-11-20 10:38:07 +00001413Int VG_(clo_logfile_fd) = 1;
sewardj4cf05692002-10-27 20:28:29 +00001414Char* VG_(clo_logfile_name) = NULL;
1415
sewardj6024b212003-07-13 10:54:33 +00001416Int VG_(clo_input_fd) = 0; /* stdin */
njn25e49d8e72002-09-23 09:36:25 +00001417Int VG_(clo_n_suppressions) = 0;
sewardjde4a1d02002-03-22 01:27:54 +00001418Char* VG_(clo_suppressions)[VG_CLO_MAX_SFILES];
njn25e49d8e72002-09-23 09:36:25 +00001419Bool VG_(clo_profile) = False;
1420Bool VG_(clo_single_step) = False;
1421Bool VG_(clo_optimise) = True;
1422UChar VG_(clo_trace_codegen) = 0; // 00000000b
1423Bool VG_(clo_trace_syscalls) = False;
1424Bool VG_(clo_trace_signals) = False;
1425Bool VG_(clo_trace_symtab) = False;
njn25e49d8e72002-09-23 09:36:25 +00001426Bool VG_(clo_trace_sched) = False;
1427Int VG_(clo_trace_pthread_level) = 0;
sewardj59438c02003-01-05 12:16:30 +00001428ULong VG_(clo_stop_after) = 1000000000000000LL;
njn25e49d8e72002-09-23 09:36:25 +00001429Int VG_(clo_dump_error) = 0;
1430Int VG_(clo_backtrace_size) = 4;
1431Char* VG_(clo_weird_hacks) = NULL;
sewardj858964b2002-10-05 14:15:43 +00001432Bool VG_(clo_run_libc_freeres) = True;
rjwalshf5f536f2003-11-17 17:45:00 +00001433Bool VG_(clo_track_fds) = False;
sewardj22854b92002-11-30 14:00:47 +00001434Bool VG_(clo_chain_bb) = True;
nethercote77eba602003-11-13 17:35:04 +00001435Bool VG_(clo_show_below_main) = False;
fitzhardinge98abfc72003-12-16 02:05:15 +00001436Bool VG_(clo_pointercheck) = True;
fitzhardinge462f4f92003-12-18 02:10:54 +00001437Bool VG_(clo_branchpred) = False;
sewardj2370f3b2002-11-30 15:01:01 +00001438
jsgf855d93d2003-10-13 22:26:55 +00001439static Bool VG_(clo_wait_for_gdb) = False;
1440
1441/* If we're doing signal routing, poll for signals every 50mS by
1442 default. */
1443Int VG_(clo_signal_polltime) = 50;
1444
1445/* These flags reduce thread wakeup latency on syscall completion and
1446 signal delivery, respectively. The downside is possible unfairness. */
1447Bool VG_(clo_lowlat_syscalls) = False; /* low-latency syscalls */
1448Bool VG_(clo_lowlat_signals) = False; /* low-latency signals */
1449
sewardjde4a1d02002-03-22 01:27:54 +00001450
njn25e49d8e72002-09-23 09:36:25 +00001451void VG_(bad_option) ( Char* opt )
sewardjde4a1d02002-03-22 01:27:54 +00001452{
1453 VG_(shutdown_logging)();
sewardj4cf05692002-10-27 20:28:29 +00001454 VG_(clo_log_to) = VgLogTo_Fd;
sewardjde4a1d02002-03-22 01:27:54 +00001455 VG_(clo_logfile_fd) = 2; /* stderr */
1456 VG_(printf)("valgrind.so: Bad option `%s'; aborting.\n", opt);
1457 VG_(exit)(1);
1458}
1459
1460static void config_error ( Char* msg )
1461{
1462 VG_(shutdown_logging)();
sewardj4cf05692002-10-27 20:28:29 +00001463 VG_(clo_log_to) = VgLogTo_Fd;
sewardjde4a1d02002-03-22 01:27:54 +00001464 VG_(clo_logfile_fd) = 2; /* stderr */
sewardj19d81412002-06-03 01:10:40 +00001465 VG_(printf)(
fitzhardinge98abfc72003-12-16 02:05:15 +00001466 "valgrind: Startup or configuration error:\n %s\n", msg);
sewardj19d81412002-06-03 01:10:40 +00001467 VG_(printf)(
fitzhardinge98abfc72003-12-16 02:05:15 +00001468 "valgrind: Unable to start up properly. Giving up.\n");
sewardjde4a1d02002-03-22 01:27:54 +00001469 VG_(exit)(1);
1470}
1471
nethercote6c999f22004-01-31 22:55:15 +00001472void usage ( Bool debug_help )
njn7cf0bd32002-06-08 13:36:03 +00001473{
njn25e49d8e72002-09-23 09:36:25 +00001474 Char* usage1 =
nethercote71980f02004-01-24 18:18:54 +00001475"usage: valgrind --tool=<toolname> [options] prog-and-args\n"
njn25e49d8e72002-09-23 09:36:25 +00001476"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001477" common user options for all Valgrind tools, with defaults in [ ]:\n"
nethercote71980f02004-01-24 18:18:54 +00001478" --tool=<name> Use the Valgrind tool named <name>\n"
njn25e49d8e72002-09-23 09:36:25 +00001479" --help show this message\n"
nethercote6c999f22004-01-31 22:55:15 +00001480" --help-debug show this message, plus debugging options\n"
njn25e49d8e72002-09-23 09:36:25 +00001481" --version show version\n"
njn25e49d8e72002-09-23 09:36:25 +00001482" -q --quiet run silently; only print error msgs\n"
1483" -v --verbose be more verbose, incl counts of errors\n"
nethercote77eba602003-11-13 17:35:04 +00001484" --trace-children=no|yes Valgrind-ise child processes? [no]\n"
rjwalshf5f536f2003-11-17 17:45:00 +00001485" --track-fds=no|yes Track open file descriptors? [no]\n"
nethercote2b0793f2003-12-02 10:41:18 +00001486"\n"
1487" uncommon user options for all Valgrind tools:\n"
nethercote77eba602003-11-13 17:35:04 +00001488" --run-libc-freeres=no|yes Free up glibc memory at exit? [yes]\n"
1489" --weird-hacks=hack1,hack2,... [none]\n"
sewardj3d652a32002-10-20 18:11:49 +00001490" recognised hacks are: ioctl-VTIME truncate-writes lax-ioctls\n"
jsgf855d93d2003-10-13 22:26:55 +00001491" --signal-polltime=<time> time, in mS, we should poll for signals.\n"
1492" Only applies for older kernels which need\n"
1493" signal routing [50]\n"
1494" --lowlat-signals=no|yes improve wake-up latency when a thread receives\n"
1495" a signal [no]\n"
1496" --lowlat-syscalls=no|yes improve wake-up latency when a thread's\n"
1497" syscall completes [no]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001498" --pointercheck=no|yes enforce client address space limits [yes]\n"
njn25e49d8e72002-09-23 09:36:25 +00001499"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001500" user options for Valgrind tools that report errors:\n"
1501" --logfile-fd=<number> file descriptor for messages [2=stderr]\n"
1502" --logfile=<file> log messages to <file>.pid<pid>\n"
1503" --logsocket=ipaddr:port log messages to socket ipaddr:port\n"
1504" --demangle=no|yes automatically demangle C++ names? [yes]\n"
1505" --num-callers=<number> show <num> callers in stack traces [4]\n"
1506" --error-limit=no|yes stop showing new errors if too many? [yes]\n"
1507" --show-below-main=no|yes continue stack traces below main() [no]\n"
1508" --suppressions=<filename> suppress errors described in <filename>\n"
1509" --gen-suppressions=no|yes print suppressions for errors detected [no]\n"
njn7cf0bd32002-06-08 13:36:03 +00001510
nethercote04d0fbc2004-01-26 16:48:06 +00001511" --db-attach=no|yes start debugger when errors detected? [no]\n"
1512" --db-command=<command> command to start debugger [gdb -nw %%f %%p]\n"
1513" --input-fd=<number> file descriptor for input [0=stdin]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001514"\n";
njn7cf0bd32002-06-08 13:36:03 +00001515
njn25e49d8e72002-09-23 09:36:25 +00001516 Char* usage2 =
1517"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001518" debugging options for all Valgrind tools:\n"
njn25e49d8e72002-09-23 09:36:25 +00001519" --sanity-level=<number> level of sanity checking to do [1]\n"
1520" --single-step=no|yes translate each instr separately? [no]\n"
1521" --optimise=no|yes improve intermediate code? [yes]\n"
nethercote137bc552003-11-14 17:47:54 +00001522" --profile=no|yes profile? (tool must be built for it) [no]\n"
sewardj22854b92002-11-30 14:00:47 +00001523" --chain-bb=no|yes do basic-block chaining? [yes]\n"
fitzhardinge462f4f92003-12-18 02:10:54 +00001524" --branchpred=yes|no generate branch prediction hints [no]\n"
njn25e49d8e72002-09-23 09:36:25 +00001525" --trace-codegen=<XXXXX> show generated code? (X = 0|1) [00000]\n"
1526" --trace-syscalls=no|yes show all system calls? [no]\n"
1527" --trace-signals=no|yes show signal handling details? [no]\n"
1528" --trace-symtab=no|yes show symbol table details? [no]\n"
njn25e49d8e72002-09-23 09:36:25 +00001529" --trace-sched=no|yes show thread scheduler details? [no]\n"
njn3e884182003-04-15 13:03:23 +00001530" --trace-pthread=none|some|all show pthread event details? [none]\n"
njn25e49d8e72002-09-23 09:36:25 +00001531" --stop-after=<number> switch to real CPU after executing\n"
1532" <number> basic blocks [infinity]\n"
jsgf855d93d2003-10-13 22:26:55 +00001533" --wait-for-gdb=yes|no pause on startup to wait for gdb attach\n"
njn25e49d8e72002-09-23 09:36:25 +00001534"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001535" debugging options for Valgrind tools that report errors\n"
1536" --dump-error=<number> show translation for basic block associated\n"
1537" with <number>'th error context [0=show none]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001538"\n";
njn3e884182003-04-15 13:03:23 +00001539
1540 Char* usage3 =
1541"\n"
nethercote71980f02004-01-24 18:18:54 +00001542" Extra options read from ~/.valgrindrc, $VALGRIND_OPTS, ./.valgrindrc\n"
njn25e49d8e72002-09-23 09:36:25 +00001543"\n"
nethercotebb1c9912004-01-04 16:43:23 +00001544" Valgrind is Copyright (C) 2000-2004 Julian Seward\n"
njn25e49d8e72002-09-23 09:36:25 +00001545" and licensed under the GNU General Public License, version 2.\n"
1546" Bug reports, feedback, admiration, abuse, etc, to: %s.\n"
njnd04b7c62002-10-03 14:05:52 +00001547"\n"
nethercote137bc552003-11-14 17:47:54 +00001548" Tools are copyright and licensed by their authors. See each\n"
1549" tool's start-up message for more information.\n"
njn25e49d8e72002-09-23 09:36:25 +00001550"\n";
njn7cf0bd32002-06-08 13:36:03 +00001551
fitzhardinge98abfc72003-12-16 02:05:15 +00001552 VG_(printf)(usage1);
1553 if (VG_(details).name) {
1554 VG_(printf)(" user options for %s:\n", VG_(details).name);
1555 /* Don't print skin string directly for security, ha! */
1556 if (VG_(needs).command_line_options)
1557 SK_(print_usage)();
1558 else
1559 VG_(printf)(" (none)\n");
1560 }
nethercote6c999f22004-01-31 22:55:15 +00001561 if (debug_help) {
1562 VG_(printf)(usage2);
fitzhardinge98abfc72003-12-16 02:05:15 +00001563
nethercote6c999f22004-01-31 22:55:15 +00001564 if (VG_(details).name) {
1565 VG_(printf)(" debugging options for %s:\n", VG_(details).name);
1566
1567 if (VG_(needs).command_line_options)
1568 SK_(print_debug_usage)();
1569 else
1570 VG_(printf)(" (none)\n");
1571 }
fitzhardinge98abfc72003-12-16 02:05:15 +00001572 }
nethercote421281e2003-11-20 16:20:55 +00001573 VG_(printf)(usage3, VG_BUGS_TO);
njn7cf0bd32002-06-08 13:36:03 +00001574
njn25e49d8e72002-09-23 09:36:25 +00001575 VG_(shutdown_logging)();
sewardj4cf05692002-10-27 20:28:29 +00001576 VG_(clo_log_to) = VgLogTo_Fd;
njn25e49d8e72002-09-23 09:36:25 +00001577 VG_(clo_logfile_fd) = 2; /* stderr */
1578 VG_(exit)(1);
njn7cf0bd32002-06-08 13:36:03 +00001579}
sewardjde4a1d02002-03-22 01:27:54 +00001580
nethercote71980f02004-01-24 18:18:54 +00001581static void pre_process_cmd_line_options
nethercote6c999f22004-01-31 22:55:15 +00001582 ( Int* need_help, const char** tool, const char** exec )
sewardj1c1b1162003-02-23 01:25:51 +00001583{
nethercote71980f02004-01-24 18:18:54 +00001584 UInt i;
sewardjde4a1d02002-03-22 01:27:54 +00001585
nethercote71980f02004-01-24 18:18:54 +00001586 /* parse the options we have (only the options we care about now) */
1587 for (i = 1; i < VG_(vg_argc); i++) {
1588
1589 if (strcmp(VG_(vg_argv)[i], "--version") == 0) {
1590 printf("valgrind-" VERSION "\n");
1591 exit(1);
1592
1593 } else if (strcmp(VG_(vg_argv)[i], "--help") == 0) {
nethercote6c999f22004-01-31 22:55:15 +00001594 *need_help = 1;
1595
1596 } else if (strcmp(VG_(vg_argv)[i], "--help-debug") == 0) {
1597 *need_help = 2;
nethercote71980f02004-01-24 18:18:54 +00001598
1599 } else if (strncmp(VG_(vg_argv)[i], "--tool=", 7) == 0 ||
1600 strncmp(VG_(vg_argv)[i], "--skin=", 7) == 0) {
1601 *tool = &VG_(vg_argv)[i][7];
1602
1603 } else if (strncmp(VG_(vg_argv)[i], "--exec=", 7) == 0) {
1604 *exec = &VG_(vg_argv)[i][7];
1605 }
1606 }
1607
1608 /* If no tool specified, can give usage message without loading tool */
1609 if (*tool == NULL) {
1610 if (!need_help)
1611 list_tools();
nethercote6c999f22004-01-31 22:55:15 +00001612 usage(/*help-debug?*/False);
nethercote71980f02004-01-24 18:18:54 +00001613 }
1614}
1615
1616static void process_cmd_line_options
1617 ( UInt* client_auxv, Addr esp_at_startup,
nethercote6c999f22004-01-31 22:55:15 +00001618 const char* toolname, Int need_help )
nethercote71980f02004-01-24 18:18:54 +00001619{
1620 Int i, eventually_logfile_fd;
1621 Int *auxp;
1622 Int toolname_len = VG_(strlen)(toolname);
sewardjde4a1d02002-03-22 01:27:54 +00001623
nethercotee1730692003-11-20 10:38:07 +00001624 /* log to stderr by default, but usage message goes to stdout */
1625 eventually_logfile_fd = 2;
sewardjde4a1d02002-03-22 01:27:54 +00001626
1627 /* Once logging is started, we can safely send messages pertaining
1628 to failures in initialisation. */
1629 VG_(startup_logging)();
1630
sewardj19d81412002-06-03 01:10:40 +00001631 /* Check for sane path in ./configure --prefix=... */
fitzhardinge98abfc72003-12-16 02:05:15 +00001632 if (VG_LIBDIR[0] != '/')
sewardj19d81412002-06-03 01:10:40 +00001633 config_error("Please use absolute paths in "
1634 "./configure --prefix=... or --libdir=...");
sewardj38170912002-05-10 21:07:22 +00001635
nethercote71980f02004-01-24 18:18:54 +00001636 for (auxp = client_auxv; auxp[0] != VKI_AT_NULL; auxp += 2) {
fitzhardinge98abfc72003-12-16 02:05:15 +00001637 switch(auxp[0]) {
1638 case VKI_AT_SYSINFO:
1639 VG_(sysinfo_page_exists) = True;
fitzhardinge92360792003-12-24 10:11:11 +00001640 auxp[1] = (Int)(VG_(client_trampoline_code) + VG_(tramp_syscall_offset));
fitzhardinge98abfc72003-12-16 02:05:15 +00001641 VG_(sysinfo_page_addr) = auxp[1];
1642 break;
sewardjde4a1d02002-03-22 01:27:54 +00001643 }
fitzhardinge98abfc72003-12-16 02:05:15 +00001644 }
sewardjde4a1d02002-03-22 01:27:54 +00001645
nethercote71980f02004-01-24 18:18:54 +00001646 if (need_help)
nethercote6c999f22004-01-31 22:55:15 +00001647 usage(/*--help-debug?*/need_help == 2);
fitzhardinge98abfc72003-12-16 02:05:15 +00001648
1649 /* We know the initial ESP is pointing at argc/argv */
nethercote71980f02004-01-24 18:18:54 +00001650 VG_(client_argc) = *(Int *)esp_at_startup;
1651 VG_(client_argv) = (Char **)(esp_at_startup + sizeof(Int));
fitzhardinge98abfc72003-12-16 02:05:15 +00001652
nethercote71980f02004-01-24 18:18:54 +00001653 for (i = 1; i < VG_(vg_argc); i++) {
1654
1655 Char* arg = VG_(vg_argv)[i];
1656
1657 // XXX: allow colons in options, for Josef
1658
1659 /* Look for matching "--toolname:foo" */
1660 if (VG_(strstr)(arg, ":")) {
1661 if (VG_CLO_STREQN(2, arg, "--") &&
1662 VG_CLO_STREQN(toolname_len, arg+2, toolname) &&
1663 VG_CLO_STREQN(1, arg+2+toolname_len, ":"))
1664 {
1665 // prefix matches, convert "--toolname:foo" to "--foo"
1666 if (0)
1667 VG_(printf)("tool-specific arg: %s\n", arg);
1668 arg += toolname_len + 1;
1669 arg[0] = '-';
1670 arg[1] = '-';
1671
1672 } else {
1673 // prefix doesn't match, skip to next arg
1674 continue;
1675 }
1676 }
1677
fitzhardinge98abfc72003-12-16 02:05:15 +00001678 /* Ignore these options - they've already been handled */
nethercote71980f02004-01-24 18:18:54 +00001679 if (VG_CLO_STREQN(7, arg, "--tool=") ||
1680 VG_CLO_STREQN(7, arg, "--skin="))
fitzhardinge98abfc72003-12-16 02:05:15 +00001681 continue;
nethercote71980f02004-01-24 18:18:54 +00001682 if (VG_CLO_STREQN(7, arg, "--exec="))
fitzhardinge98abfc72003-12-16 02:05:15 +00001683 continue;
1684
nethercote71980f02004-01-24 18:18:54 +00001685 if ( VG_CLO_STREQ(arg, "--"))
fitzhardinge98abfc72003-12-16 02:05:15 +00001686 continue;
nethercote71980f02004-01-24 18:18:54 +00001687 else if (VG_CLO_STREQ(arg, "-v") ||
1688 VG_CLO_STREQ(arg, "--verbose"))
sewardjde4a1d02002-03-22 01:27:54 +00001689 VG_(clo_verbosity)++;
nethercote71980f02004-01-24 18:18:54 +00001690 else if (VG_CLO_STREQ(arg, "-q") ||
1691 VG_CLO_STREQ(arg, "--quiet"))
sewardjde4a1d02002-03-22 01:27:54 +00001692 VG_(clo_verbosity)--;
1693
nethercote71980f02004-01-24 18:18:54 +00001694 else if (VG_CLO_STREQ(arg, "--error-limit=yes"))
sewardj2e432902002-06-13 20:44:00 +00001695 VG_(clo_error_limit) = True;
nethercote71980f02004-01-24 18:18:54 +00001696 else if (VG_CLO_STREQ(arg, "--error-limit=no"))
sewardj2e432902002-06-13 20:44:00 +00001697 VG_(clo_error_limit) = False;
sewardj72f98ff2002-06-13 17:23:38 +00001698
nethercote04d0fbc2004-01-26 16:48:06 +00001699 else if (VG_CLO_STREQ(arg, "--db-attach=yes"))
1700 VG_(clo_db_attach) = True;
1701 else if (VG_CLO_STREQ(arg, "--db-attach=no"))
1702 VG_(clo_db_attach) = False;
sewardjde4a1d02002-03-22 01:27:54 +00001703
nethercote04d0fbc2004-01-26 16:48:06 +00001704 else if (VG_CLO_STREQN(13,arg, "--db-command="))
1705 VG_(clo_db_command) = &arg[13];
sewardj6024b212003-07-13 10:54:33 +00001706
nethercote71980f02004-01-24 18:18:54 +00001707 else if (VG_CLO_STREQ(arg, "--gen-suppressions=yes"))
njn43c799e2003-04-08 00:08:52 +00001708 VG_(clo_gen_suppressions) = True;
nethercote71980f02004-01-24 18:18:54 +00001709 else if (VG_CLO_STREQ(arg, "--gen-suppressions=no"))
njn43c799e2003-04-08 00:08:52 +00001710 VG_(clo_gen_suppressions) = False;
1711
nethercote71980f02004-01-24 18:18:54 +00001712 else if (VG_CLO_STREQ(arg, "--show-below-main=yes"))
nethercote77eba602003-11-13 17:35:04 +00001713 VG_(clo_show_below_main) = True;
nethercote71980f02004-01-24 18:18:54 +00001714 else if (VG_CLO_STREQ(arg, "--show-below-main=no"))
nethercote77eba602003-11-13 17:35:04 +00001715 VG_(clo_show_below_main) = False;
1716
nethercote71980f02004-01-24 18:18:54 +00001717 else if (VG_CLO_STREQ(arg, "--pointercheck=yes"))
fitzhardinge98abfc72003-12-16 02:05:15 +00001718 VG_(clo_pointercheck) = True;
nethercote71980f02004-01-24 18:18:54 +00001719 else if (VG_CLO_STREQ(arg, "--pointercheck=no"))
fitzhardinge98abfc72003-12-16 02:05:15 +00001720 VG_(clo_pointercheck) = False;
1721
nethercote71980f02004-01-24 18:18:54 +00001722 else if (VG_CLO_STREQ(arg, "--demangle=yes"))
sewardjde4a1d02002-03-22 01:27:54 +00001723 VG_(clo_demangle) = True;
nethercote71980f02004-01-24 18:18:54 +00001724 else if (VG_CLO_STREQ(arg, "--demangle=no"))
sewardjde4a1d02002-03-22 01:27:54 +00001725 VG_(clo_demangle) = False;
1726
nethercote71980f02004-01-24 18:18:54 +00001727 else if (VG_CLO_STREQ(arg, "--trace-children=yes"))
sewardjde4a1d02002-03-22 01:27:54 +00001728 VG_(clo_trace_children) = True;
nethercote71980f02004-01-24 18:18:54 +00001729 else if (VG_CLO_STREQ(arg, "--trace-children=no"))
sewardjde4a1d02002-03-22 01:27:54 +00001730 VG_(clo_trace_children) = False;
1731
nethercote71980f02004-01-24 18:18:54 +00001732 else if (VG_CLO_STREQ(arg, "--run-libc-freeres=yes"))
sewardj858964b2002-10-05 14:15:43 +00001733 VG_(clo_run_libc_freeres) = True;
nethercote71980f02004-01-24 18:18:54 +00001734 else if (VG_CLO_STREQ(arg, "--run-libc-freeres=no"))
sewardj858964b2002-10-05 14:15:43 +00001735 VG_(clo_run_libc_freeres) = False;
1736
nethercote71980f02004-01-24 18:18:54 +00001737 else if (VG_CLO_STREQ(arg, "--track-fds=yes"))
rjwalshf5f536f2003-11-17 17:45:00 +00001738 VG_(clo_track_fds) = True;
nethercote71980f02004-01-24 18:18:54 +00001739 else if (VG_CLO_STREQ(arg, "--track-fds=no"))
rjwalshf5f536f2003-11-17 17:45:00 +00001740 VG_(clo_track_fds) = False;
1741
nethercote71980f02004-01-24 18:18:54 +00001742 else if (VG_CLO_STREQN(15, arg, "--sanity-level="))
1743 VG_(sanity_level) = (Int)VG_(atoll)(&arg[15]);
sewardjde4a1d02002-03-22 01:27:54 +00001744
nethercote71980f02004-01-24 18:18:54 +00001745 else if (VG_CLO_STREQN(13, arg, "--logfile-fd=")) {
sewardj4cf05692002-10-27 20:28:29 +00001746 VG_(clo_log_to) = VgLogTo_Fd;
1747 VG_(clo_logfile_name) = NULL;
nethercote71980f02004-01-24 18:18:54 +00001748 eventually_logfile_fd = (Int)VG_(atoll)(&arg[13]);
sewardj4cf05692002-10-27 20:28:29 +00001749 }
1750
nethercote71980f02004-01-24 18:18:54 +00001751 else if (VG_CLO_STREQN(10, arg, "--logfile=")) {
sewardj4cf05692002-10-27 20:28:29 +00001752 VG_(clo_log_to) = VgLogTo_File;
nethercote71980f02004-01-24 18:18:54 +00001753 VG_(clo_logfile_name) = &arg[10];
sewardj4cf05692002-10-27 20:28:29 +00001754 }
sewardjde4a1d02002-03-22 01:27:54 +00001755
nethercote71980f02004-01-24 18:18:54 +00001756 else if (VG_CLO_STREQN(12, arg, "--logsocket=")) {
sewardj73cf3bc2002-11-03 03:20:15 +00001757 VG_(clo_log_to) = VgLogTo_Socket;
nethercote71980f02004-01-24 18:18:54 +00001758 VG_(clo_logfile_name) = &arg[12];
sewardj73cf3bc2002-11-03 03:20:15 +00001759 }
1760
nethercote71980f02004-01-24 18:18:54 +00001761 else if (VG_CLO_STREQN(11, arg, "--input-fd="))
1762 VG_(clo_input_fd) = (Int)VG_(atoll)(&arg[11]);
sewardj6024b212003-07-13 10:54:33 +00001763
nethercote71980f02004-01-24 18:18:54 +00001764 else if (VG_CLO_STREQN(15, arg, "--suppressions=")) {
sewardjde4a1d02002-03-22 01:27:54 +00001765 if (VG_(clo_n_suppressions) >= VG_CLO_MAX_SFILES) {
njn25e49d8e72002-09-23 09:36:25 +00001766 VG_(message)(Vg_UserMsg, "Too many suppression files specified.");
sewardjde4a1d02002-03-22 01:27:54 +00001767 VG_(message)(Vg_UserMsg,
1768 "Increase VG_CLO_MAX_SFILES and recompile.");
nethercote71980f02004-01-24 18:18:54 +00001769 VG_(bad_option)(arg);
sewardjde4a1d02002-03-22 01:27:54 +00001770 }
nethercote71980f02004-01-24 18:18:54 +00001771 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = &arg[15];
sewardjde4a1d02002-03-22 01:27:54 +00001772 VG_(clo_n_suppressions)++;
1773 }
nethercote71980f02004-01-24 18:18:54 +00001774 else if (VG_CLO_STREQ(arg, "--profile=yes"))
njn25e49d8e72002-09-23 09:36:25 +00001775 VG_(clo_profile) = True;
nethercote71980f02004-01-24 18:18:54 +00001776 else if (VG_CLO_STREQ(arg, "--profile=no"))
njn25e49d8e72002-09-23 09:36:25 +00001777 VG_(clo_profile) = False;
1778
nethercote71980f02004-01-24 18:18:54 +00001779 else if (VG_CLO_STREQ(arg, "--chain-bb=yes"))
sewardj22854b92002-11-30 14:00:47 +00001780 VG_(clo_chain_bb) = True;
nethercote71980f02004-01-24 18:18:54 +00001781 else if (VG_CLO_STREQ(arg, "--chain-bb=no"))
sewardj22854b92002-11-30 14:00:47 +00001782 VG_(clo_chain_bb) = False;
1783
nethercote71980f02004-01-24 18:18:54 +00001784 else if (VG_CLO_STREQ(arg, "--branchpred=yes"))
fitzhardinge462f4f92003-12-18 02:10:54 +00001785 VG_(clo_branchpred) = True;
nethercote71980f02004-01-24 18:18:54 +00001786 else if (VG_CLO_STREQ(arg, "--branchpred=no"))
fitzhardinge462f4f92003-12-18 02:10:54 +00001787 VG_(clo_branchpred) = False;
1788
nethercote71980f02004-01-24 18:18:54 +00001789 else if (VG_CLO_STREQ(arg, "--single-step=yes"))
sewardjde4a1d02002-03-22 01:27:54 +00001790 VG_(clo_single_step) = True;
nethercote71980f02004-01-24 18:18:54 +00001791 else if (VG_CLO_STREQ(arg, "--single-step=no"))
sewardjde4a1d02002-03-22 01:27:54 +00001792 VG_(clo_single_step) = False;
1793
nethercote71980f02004-01-24 18:18:54 +00001794 else if (VG_CLO_STREQ(arg, "--optimise=yes"))
sewardjde4a1d02002-03-22 01:27:54 +00001795 VG_(clo_optimise) = True;
nethercote71980f02004-01-24 18:18:54 +00001796 else if (VG_CLO_STREQ(arg, "--optimise=no"))
sewardjde4a1d02002-03-22 01:27:54 +00001797 VG_(clo_optimise) = False;
1798
njn25e49d8e72002-09-23 09:36:25 +00001799 /* "vwxyz" --> 000zyxwv (binary) */
nethercote71980f02004-01-24 18:18:54 +00001800 else if (VG_CLO_STREQN(16, arg, "--trace-codegen=")) {
njn25e49d8e72002-09-23 09:36:25 +00001801 Int j;
nethercote71980f02004-01-24 18:18:54 +00001802 char* opt = & arg[16];
njn25e49d8e72002-09-23 09:36:25 +00001803
1804 if (5 != VG_(strlen)(opt)) {
1805 VG_(message)(Vg_UserMsg,
1806 "--trace-codegen argument must have 5 digits");
nethercote71980f02004-01-24 18:18:54 +00001807 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001808 }
1809 for (j = 0; j < 5; j++) {
1810 if ('0' == opt[j]) { /* do nothing */ }
1811 else if ('1' == opt[j]) VG_(clo_trace_codegen) |= (1 << j);
1812 else {
1813 VG_(message)(Vg_UserMsg, "--trace-codegen argument can only "
1814 "contain 0s and 1s");
nethercote71980f02004-01-24 18:18:54 +00001815 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001816 }
1817 }
1818 }
sewardjde4a1d02002-03-22 01:27:54 +00001819
nethercote71980f02004-01-24 18:18:54 +00001820 else if (VG_CLO_STREQ(arg, "--trace-syscalls=yes"))
sewardjde4a1d02002-03-22 01:27:54 +00001821 VG_(clo_trace_syscalls) = True;
nethercote71980f02004-01-24 18:18:54 +00001822 else if (VG_CLO_STREQ(arg, "--trace-syscalls=no"))
sewardjde4a1d02002-03-22 01:27:54 +00001823 VG_(clo_trace_syscalls) = False;
1824
nethercote71980f02004-01-24 18:18:54 +00001825 else if (VG_CLO_STREQ(arg, "--trace-signals=yes"))
sewardjde4a1d02002-03-22 01:27:54 +00001826 VG_(clo_trace_signals) = True;
nethercote71980f02004-01-24 18:18:54 +00001827 else if (VG_CLO_STREQ(arg, "--trace-signals=no"))
sewardjde4a1d02002-03-22 01:27:54 +00001828 VG_(clo_trace_signals) = False;
1829
nethercote71980f02004-01-24 18:18:54 +00001830 else if (VG_CLO_STREQ(arg, "--trace-symtab=yes"))
sewardjde4a1d02002-03-22 01:27:54 +00001831 VG_(clo_trace_symtab) = True;
nethercote71980f02004-01-24 18:18:54 +00001832 else if (VG_CLO_STREQ(arg, "--trace-symtab=no"))
sewardjde4a1d02002-03-22 01:27:54 +00001833 VG_(clo_trace_symtab) = False;
1834
nethercote71980f02004-01-24 18:18:54 +00001835 else if (VG_CLO_STREQ(arg, "--trace-sched=yes"))
sewardj8937c812002-04-12 20:12:20 +00001836 VG_(clo_trace_sched) = True;
nethercote71980f02004-01-24 18:18:54 +00001837 else if (VG_CLO_STREQ(arg, "--trace-sched=no"))
sewardj8937c812002-04-12 20:12:20 +00001838 VG_(clo_trace_sched) = False;
1839
nethercote71980f02004-01-24 18:18:54 +00001840 else if (VG_CLO_STREQ(arg, "--trace-pthread=none"))
sewardj45b4b372002-04-16 22:50:32 +00001841 VG_(clo_trace_pthread_level) = 0;
nethercote71980f02004-01-24 18:18:54 +00001842 else if (VG_CLO_STREQ(arg, "--trace-pthread=some"))
sewardj45b4b372002-04-16 22:50:32 +00001843 VG_(clo_trace_pthread_level) = 1;
nethercote71980f02004-01-24 18:18:54 +00001844 else if (VG_CLO_STREQ(arg, "--trace-pthread=all"))
sewardj45b4b372002-04-16 22:50:32 +00001845 VG_(clo_trace_pthread_level) = 2;
sewardj8937c812002-04-12 20:12:20 +00001846
nethercote71980f02004-01-24 18:18:54 +00001847 else if (VG_CLO_STREQN(14, arg, "--weird-hacks="))
1848 VG_(clo_weird_hacks) = &arg[14];
sewardj3984b852002-05-12 03:00:17 +00001849
nethercote71980f02004-01-24 18:18:54 +00001850 else if (VG_CLO_STREQN(17, arg, "--signal-polltime="))
1851 VG_(clo_signal_polltime) = VG_(atoll)(&arg[17]);
jsgf855d93d2003-10-13 22:26:55 +00001852
nethercote71980f02004-01-24 18:18:54 +00001853 else if (VG_CLO_STREQ(arg, "--lowlat-signals=yes"))
jsgf855d93d2003-10-13 22:26:55 +00001854 VG_(clo_lowlat_signals) = True;
nethercote71980f02004-01-24 18:18:54 +00001855 else if (VG_CLO_STREQ(arg, "--lowlat-signals=no"))
jsgf855d93d2003-10-13 22:26:55 +00001856 VG_(clo_lowlat_signals) = False;
1857
nethercote71980f02004-01-24 18:18:54 +00001858 else if (VG_CLO_STREQ(arg, "--lowlat-syscalls=yes"))
jsgf855d93d2003-10-13 22:26:55 +00001859 VG_(clo_lowlat_syscalls) = True;
nethercote71980f02004-01-24 18:18:54 +00001860 else if (VG_CLO_STREQ(arg, "--lowlat-syscalls=no"))
jsgf855d93d2003-10-13 22:26:55 +00001861 VG_(clo_lowlat_syscalls) = False;
1862
nethercote71980f02004-01-24 18:18:54 +00001863 else if (VG_CLO_STREQN(13, arg, "--stop-after="))
1864 VG_(clo_stop_after) = VG_(atoll)(&arg[13]);
sewardjde4a1d02002-03-22 01:27:54 +00001865
nethercote71980f02004-01-24 18:18:54 +00001866 else if (VG_CLO_STREQN(13, arg, "--dump-error="))
1867 VG_(clo_dump_error) = (Int)VG_(atoll)(&arg[13]);
sewardjde4a1d02002-03-22 01:27:54 +00001868
nethercote71980f02004-01-24 18:18:54 +00001869 else if (VG_CLO_STREQ(arg, "--wait-for-gdb=yes"))
jsgf855d93d2003-10-13 22:26:55 +00001870 VG_(clo_wait_for_gdb) = True;
nethercote71980f02004-01-24 18:18:54 +00001871 else if (VG_CLO_STREQ(arg, "--wait-for-gdb=no"))
jsgf855d93d2003-10-13 22:26:55 +00001872 VG_(clo_wait_for_gdb) = False;
1873
nethercote71980f02004-01-24 18:18:54 +00001874 else if (VG_CLO_STREQN(14, arg, "--num-callers=")) {
sewardjde4a1d02002-03-22 01:27:54 +00001875 /* Make sure it's sane. */
nethercote71980f02004-01-24 18:18:54 +00001876 VG_(clo_backtrace_size) = (Int)VG_(atoll)(&arg[14]);
njn6c846552003-09-16 07:41:43 +00001877 if (VG_(clo_backtrace_size) < 1)
1878 VG_(clo_backtrace_size) = 1;
sewardjde4a1d02002-03-22 01:27:54 +00001879 if (VG_(clo_backtrace_size) >= VG_DEEPEST_BACKTRACE)
1880 VG_(clo_backtrace_size) = VG_DEEPEST_BACKTRACE;
1881 }
1882
nethercote71980f02004-01-24 18:18:54 +00001883 else if ( ! VG_(needs).command_line_options
1884 || ! SK_(process_cmd_line_option)(arg) ) {
nethercote6c999f22004-01-31 22:55:15 +00001885 usage(/*--help-debug?*/need_help == 2);
njn25e49d8e72002-09-23 09:36:25 +00001886 }
sewardjde4a1d02002-03-22 01:27:54 +00001887 }
1888
njnf9ebf672003-05-12 21:41:30 +00001889 if (VG_(clo_verbosity) < 0)
sewardjde4a1d02002-03-22 01:27:54 +00001890 VG_(clo_verbosity) = 0;
1891
nethercote04d0fbc2004-01-26 16:48:06 +00001892 if (VG_(clo_db_attach) && VG_(clo_trace_children)) {
sewardjde4a1d02002-03-22 01:27:54 +00001893 VG_(message)(Vg_UserMsg, "");
1894 VG_(message)(Vg_UserMsg,
nethercote04d0fbc2004-01-26 16:48:06 +00001895 "--db-attach=yes conflicts with --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001896 VG_(message)(Vg_UserMsg,
1897 "Please choose one or the other, but not both.");
nethercote04d0fbc2004-01-26 16:48:06 +00001898 VG_(bad_option)("--db-attach=yes and --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001899 }
1900
sewardj4cf05692002-10-27 20:28:29 +00001901 /* Set up logging now. After this is done, VG_(clo_logfile_fd)
1902 should be connected to whatever sink has been selected, and we
1903 indiscriminately chuck stuff into it without worrying what the
1904 nature of it is. Oh the wonder of Unix streams. */
1905
nethercotee1730692003-11-20 10:38:07 +00001906 /* So far we should be still attached to stdout, so we can show on
sewardj4cf05692002-10-27 20:28:29 +00001907 the terminal any problems to do with processing command line
1908 opts. */
nethercotee1730692003-11-20 10:38:07 +00001909 vg_assert(VG_(clo_logfile_fd) == 1 /* stdout */);
sewardj73cf3bc2002-11-03 03:20:15 +00001910 vg_assert(VG_(logging_to_filedes) == True);
sewardj4cf05692002-10-27 20:28:29 +00001911
1912 switch (VG_(clo_log_to)) {
sewardj73cf3bc2002-11-03 03:20:15 +00001913
sewardj4cf05692002-10-27 20:28:29 +00001914 case VgLogTo_Fd:
1915 vg_assert(VG_(clo_logfile_name) == NULL);
1916 VG_(clo_logfile_fd) = eventually_logfile_fd;
1917 break;
sewardj73cf3bc2002-11-03 03:20:15 +00001918
sewardj4cf05692002-10-27 20:28:29 +00001919 case VgLogTo_File: {
1920 Char logfilename[1000];
jsgff3c3f1a2003-10-14 22:13:28 +00001921 Int seq = 0;
1922 Int pid = VG_(getpid)();
1923
sewardj4cf05692002-10-27 20:28:29 +00001924 vg_assert(VG_(clo_logfile_name) != NULL);
1925 vg_assert(VG_(strlen)(VG_(clo_logfile_name)) <= 900); /* paranoia */
jsgff3c3f1a2003-10-14 22:13:28 +00001926
nethercote71980f02004-01-24 18:18:54 +00001927 for (;;) {
jsgff3c3f1a2003-10-14 22:13:28 +00001928 if (seq == 0)
1929 VG_(sprintf)(logfilename, "%s.pid%d",
1930 VG_(clo_logfile_name), pid );
1931 else
1932 VG_(sprintf)(logfilename, "%s.pid%d.%d",
1933 VG_(clo_logfile_name), pid, seq );
1934 seq++;
1935
1936 eventually_logfile_fd
1937 = VG_(open)(logfilename,
1938 VKI_O_CREAT|VKI_O_WRONLY|VKI_O_EXCL|VKI_O_TRUNC,
1939 VKI_S_IRUSR|VKI_S_IWUSR);
1940 if (eventually_logfile_fd >= 0) {
fitzhardinge9b8c2f32004-01-06 00:15:26 +00001941 VG_(clo_logfile_fd) = VG_(safe_fd)(eventually_logfile_fd);
jsgff3c3f1a2003-10-14 22:13:28 +00001942 break;
1943 } else {
1944 if (eventually_logfile_fd != -VKI_EEXIST) {
1945 VG_(message)(Vg_UserMsg,
1946 "Can't create/open log file `%s.pid%d'; giving up!",
1947 VG_(clo_logfile_name), pid);
1948 VG_(bad_option)(
1949 "--logfile=<file> didn't work out for some reason.");
1950 break;
1951 }
1952 }
1953 }
sewardj4cf05692002-10-27 20:28:29 +00001954 break;
sewardj73cf3bc2002-11-03 03:20:15 +00001955 }
1956
1957 case VgLogTo_Socket: {
1958 vg_assert(VG_(clo_logfile_name) != NULL);
1959 vg_assert(VG_(strlen)(VG_(clo_logfile_name)) <= 900); /* paranoia */
1960 eventually_logfile_fd
1961 = VG_(connect_via_socket)( VG_(clo_logfile_name) );
1962 if (eventually_logfile_fd == -1) {
1963 VG_(message)(Vg_UserMsg,
1964 "Invalid --logsocket=ipaddr or --logsocket=ipaddr:port spec");
1965 VG_(message)(Vg_UserMsg,
1966 "of `%s'; giving up!", VG_(clo_logfile_name) );
1967 VG_(bad_option)(
1968 "--logsocket=");
sewardj4cf05692002-10-27 20:28:29 +00001969 }
sewardj73cf3bc2002-11-03 03:20:15 +00001970 if (eventually_logfile_fd == -2) {
1971 VG_(message)(Vg_UserMsg,
sewardj570f8902002-11-03 11:44:36 +00001972 "valgrind: failed to connect to logging server `%s'.",
sewardj73cf3bc2002-11-03 03:20:15 +00001973 VG_(clo_logfile_name) );
sewardj570f8902002-11-03 11:44:36 +00001974 VG_(message)(Vg_UserMsg,
1975 "Log messages will sent to stderr instead." );
1976 VG_(message)(Vg_UserMsg,
1977 "" );
1978 /* We don't change anything here. */
1979 } else {
1980 vg_assert(eventually_logfile_fd > 0);
1981 VG_(clo_logfile_fd) = eventually_logfile_fd;
1982 VG_(logging_to_filedes) = False;
1983 }
sewardj73cf3bc2002-11-03 03:20:15 +00001984 break;
1985 }
1986
sewardj4cf05692002-10-27 20:28:29 +00001987 }
1988
jsgf855d93d2003-10-13 22:26:55 +00001989 /* Move logfile_fd into the safe range, so it doesn't conflict with any app fds */
fitzhardingef0046f22003-12-18 02:39:22 +00001990 eventually_logfile_fd = VG_(fcntl)(VG_(clo_logfile_fd), VKI_F_DUPFD, VG_(max_fd)+1);
jsgf855d93d2003-10-13 22:26:55 +00001991 if (eventually_logfile_fd < 0)
1992 VG_(message)(Vg_UserMsg, "valgrind: failed to move logfile fd into safe range");
1993 else {
1994 VG_(clo_logfile_fd) = eventually_logfile_fd;
1995 VG_(fcntl)(VG_(clo_logfile_fd), VKI_F_SETFD, VKI_FD_CLOEXEC);
1996 }
1997
sewardj4cf05692002-10-27 20:28:29 +00001998 /* Ok, the logging sink is running now. Print a suitable preamble.
1999 If logging to file or a socket, write details of parent PID and
2000 command line args, to help people trying to interpret the
2001 results of a run which encompasses multiple processes. */
sewardjde4a1d02002-03-22 01:27:54 +00002002
sewardj83adf412002-05-01 01:25:45 +00002003 if (VG_(clo_verbosity > 0)) {
njnd04b7c62002-10-03 14:05:52 +00002004 /* Skin details */
2005 VG_(message)(Vg_UserMsg, "%s%s%s, %s for x86-linux.",
2006 VG_(details).name,
2007 NULL == VG_(details).version ? "" : "-",
2008 NULL == VG_(details).version
2009 ? (Char*)"" : VG_(details).version,
2010 VG_(details).description);
2011 VG_(message)(Vg_UserMsg, "%s", VG_(details).copyright_author);
sewardj3b2736a2002-03-24 12:18:35 +00002012
njnd04b7c62002-10-03 14:05:52 +00002013 /* Core details */
2014 VG_(message)(Vg_UserMsg,
njn3e884182003-04-15 13:03:23 +00002015 "Using valgrind-%s, a program supervision framework for x86-linux.",
sewardj4aa62ba2002-10-05 15:49:27 +00002016 VERSION);
sewardjde4a1d02002-03-22 01:27:54 +00002017 VG_(message)(Vg_UserMsg,
nethercotebb1c9912004-01-04 16:43:23 +00002018 "Copyright (C) 2000-2004, and GNU GPL'd, by Julian Seward.");
njnd04b7c62002-10-03 14:05:52 +00002019 }
2020
nethercotec1e395d2003-11-10 13:26:49 +00002021 if (VG_(clo_verbosity) > 0 && VG_(clo_log_to) != VgLogTo_Fd) {
sewardj4cf05692002-10-27 20:28:29 +00002022 VG_(message)(Vg_UserMsg, "");
2023 VG_(message)(Vg_UserMsg,
2024 "My PID = %d, parent PID = %d. Prog and args are:",
2025 VG_(getpid)(), VG_(getppid)() );
2026 for (i = 0; i < VG_(client_argc); i++)
2027 VG_(message)(Vg_UserMsg, " %s", VG_(client_argv)[i]);
2028 }
2029
sewardjde4a1d02002-03-22 01:27:54 +00002030 if (VG_(clo_verbosity) > 1) {
sewardj4cf05692002-10-27 20:28:29 +00002031 if (VG_(clo_log_to) != VgLogTo_Fd)
2032 VG_(message)(Vg_UserMsg, "");
fitzhardinge98abfc72003-12-16 02:05:15 +00002033 VG_(message)(Vg_UserMsg, "Valgrind library directory: %s", VG_(libdir));
njn86dc2bc2003-09-09 07:26:21 +00002034 VG_(message)(Vg_UserMsg, "Command line");
2035 for (i = 0; i < VG_(client_argc); i++)
2036 VG_(message)(Vg_UserMsg, " %s", VG_(client_argv)[i]);
2037
sewardjde4a1d02002-03-22 01:27:54 +00002038 VG_(message)(Vg_UserMsg, "Startup, with flags:");
nethercote71980f02004-01-24 18:18:54 +00002039 for (i = 1; i < VG_(vg_argc); i++) {
2040 VG_(message)(Vg_UserMsg, " %s", VG_(vg_argv)[i]);
sewardjde4a1d02002-03-22 01:27:54 +00002041 }
2042 }
2043
fitzhardinge98abfc72003-12-16 02:05:15 +00002044 if (VG_(clo_n_suppressions) < VG_CLO_MAX_SFILES-1 &&
njn25e49d8e72002-09-23 09:36:25 +00002045 (VG_(needs).core_errors || VG_(needs).skin_errors)) {
fitzhardinge98abfc72003-12-16 02:05:15 +00002046 /* If there are no suppression files specified and the skin
2047 needs one, load the default */
2048 static const Char default_supp[] = "default.supp";
2049 Int len = VG_(strlen)(VG_(libdir)) + 1 + sizeof(default_supp);
2050 Char *buf = VG_(arena_malloc)(VG_AR_CORE, len);
2051 VG_(sprintf)(buf, "%s/%s", VG_(libdir), default_supp);
2052 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = buf;
2053 VG_(clo_n_suppressions)++;
sewardjde4a1d02002-03-22 01:27:54 +00002054 }
sewardj4cf05692002-10-27 20:28:29 +00002055
njn6a230532003-07-21 10:38:23 +00002056 if (VG_(clo_gen_suppressions) &&
2057 !VG_(needs).core_errors && !VG_(needs).skin_errors) {
2058 config_error("Can't use --gen-suppressions=yes with this skin,\n"
2059 " as it doesn't generate errors.");
2060 }
2061
nethercote71980f02004-01-24 18:18:54 +00002062 VG_(bbs_to_go) = VG_(clo_stop_after);
sewardjde4a1d02002-03-22 01:27:54 +00002063}
2064
sewardjde4a1d02002-03-22 01:27:54 +00002065
nethercote71980f02004-01-24 18:18:54 +00002066/*====================================================================*/
2067/*=== File descriptor setup ===*/
2068/*====================================================================*/
2069
2070static void setup_file_descriptors(void)
2071{
2072 struct vki_rlimit rl;
2073
2074 /* Get the current file descriptor limits. */
2075 if (VG_(getrlimit)(VKI_RLIMIT_NOFILE, &rl) < 0) {
2076 rl.rlim_cur = 1024;
2077 rl.rlim_max = 1024;
2078 }
2079
2080 /* Work out where to move the soft limit to. */
2081 if (rl.rlim_cur + VG_N_RESERVED_FDS <= rl.rlim_max) {
2082 rl.rlim_cur = rl.rlim_cur + VG_N_RESERVED_FDS;
2083 } else {
2084 rl.rlim_cur = rl.rlim_max;
2085 }
2086
2087 /* Reserve some file descriptors for our use. */
2088 VG_(max_fd) = rl.rlim_cur - VG_N_RESERVED_FDS;
2089
2090 /* Update the soft limit. */
2091 VG_(setrlimit)(VKI_RLIMIT_NOFILE, &rl);
2092
2093 if (VG_(vgexecfd) != -1)
2094 VG_(vgexecfd) = VG_(safe_fd)( VG_(vgexecfd) );
2095 if (VG_(clexecfd) != -1)
2096 VG_(clexecfd) = VG_(safe_fd)( VG_(clexecfd) );
2097}
2098
2099
2100/*====================================================================*/
2101/*=== m_state_static + baseBlock: definition, setup, copying ===*/
2102/*====================================================================*/
2103
2104/* The variables storing offsets. */
2105
2106#define INVALID_OFFSET (-1)
2107
2108Int VGOFF_(m_eax) = INVALID_OFFSET;
2109Int VGOFF_(m_ecx) = INVALID_OFFSET;
2110Int VGOFF_(m_edx) = INVALID_OFFSET;
2111Int VGOFF_(m_ebx) = INVALID_OFFSET;
2112Int VGOFF_(m_esp) = INVALID_OFFSET;
2113Int VGOFF_(m_ebp) = INVALID_OFFSET;
2114Int VGOFF_(m_esi) = INVALID_OFFSET;
2115Int VGOFF_(m_edi) = INVALID_OFFSET;
2116Int VGOFF_(m_eflags) = INVALID_OFFSET;
2117Int VGOFF_(m_dflag) = INVALID_OFFSET;
2118Int VGOFF_(m_ssestate) = INVALID_OFFSET;
2119Int VGOFF_(ldt) = INVALID_OFFSET;
2120Int VGOFF_(tls) = INVALID_OFFSET;
2121Int VGOFF_(m_cs) = INVALID_OFFSET;
2122Int VGOFF_(m_ss) = INVALID_OFFSET;
2123Int VGOFF_(m_ds) = INVALID_OFFSET;
2124Int VGOFF_(m_es) = INVALID_OFFSET;
2125Int VGOFF_(m_fs) = INVALID_OFFSET;
2126Int VGOFF_(m_gs) = INVALID_OFFSET;
2127Int VGOFF_(m_eip) = INVALID_OFFSET;
2128Int VGOFF_(spillslots) = INVALID_OFFSET;
2129Int VGOFF_(sh_eax) = INVALID_OFFSET;
2130Int VGOFF_(sh_ecx) = INVALID_OFFSET;
2131Int VGOFF_(sh_edx) = INVALID_OFFSET;
2132Int VGOFF_(sh_ebx) = INVALID_OFFSET;
2133Int VGOFF_(sh_esp) = INVALID_OFFSET;
2134Int VGOFF_(sh_ebp) = INVALID_OFFSET;
2135Int VGOFF_(sh_esi) = INVALID_OFFSET;
2136Int VGOFF_(sh_edi) = INVALID_OFFSET;
2137Int VGOFF_(sh_eflags) = INVALID_OFFSET;
2138
2139Int VGOFF_(helper_idiv_64_32) = INVALID_OFFSET;
2140Int VGOFF_(helper_div_64_32) = INVALID_OFFSET;
2141Int VGOFF_(helper_idiv_32_16) = INVALID_OFFSET;
2142Int VGOFF_(helper_div_32_16) = INVALID_OFFSET;
2143Int VGOFF_(helper_idiv_16_8) = INVALID_OFFSET;
2144Int VGOFF_(helper_div_16_8) = INVALID_OFFSET;
2145Int VGOFF_(helper_imul_32_64) = INVALID_OFFSET;
2146Int VGOFF_(helper_mul_32_64) = INVALID_OFFSET;
2147Int VGOFF_(helper_imul_16_32) = INVALID_OFFSET;
2148Int VGOFF_(helper_mul_16_32) = INVALID_OFFSET;
2149Int VGOFF_(helper_imul_8_16) = INVALID_OFFSET;
2150Int VGOFF_(helper_mul_8_16) = INVALID_OFFSET;
2151Int VGOFF_(helper_CLD) = INVALID_OFFSET;
2152Int VGOFF_(helper_STD) = INVALID_OFFSET;
2153Int VGOFF_(helper_get_dirflag) = INVALID_OFFSET;
2154Int VGOFF_(helper_CLC) = INVALID_OFFSET;
2155Int VGOFF_(helper_STC) = INVALID_OFFSET;
2156Int VGOFF_(helper_shldl) = INVALID_OFFSET;
2157Int VGOFF_(helper_shldw) = INVALID_OFFSET;
2158Int VGOFF_(helper_shrdl) = INVALID_OFFSET;
2159Int VGOFF_(helper_shrdw) = INVALID_OFFSET;
2160Int VGOFF_(helper_IN) = INVALID_OFFSET;
2161Int VGOFF_(helper_OUT) = INVALID_OFFSET;
2162Int VGOFF_(helper_RDTSC) = INVALID_OFFSET;
2163Int VGOFF_(helper_CPUID) = INVALID_OFFSET;
2164Int VGOFF_(helper_BSWAP) = INVALID_OFFSET;
2165Int VGOFF_(helper_bsf) = INVALID_OFFSET;
2166Int VGOFF_(helper_bsr) = INVALID_OFFSET;
2167Int VGOFF_(helper_fstsw_AX) = INVALID_OFFSET;
2168Int VGOFF_(helper_SAHF) = INVALID_OFFSET;
2169Int VGOFF_(helper_LAHF) = INVALID_OFFSET;
2170Int VGOFF_(helper_DAS) = INVALID_OFFSET;
2171Int VGOFF_(helper_DAA) = INVALID_OFFSET;
2172Int VGOFF_(helper_cmpxchg8b) = INVALID_OFFSET;
2173Int VGOFF_(helper_undefined_instruction) = INVALID_OFFSET;
2174
2175/* MAX_NONCOMPACT_HELPERS can be increased easily. If MAX_COMPACT_HELPERS is
2176 * increased too much, they won't really be compact any more... */
2177#define MAX_COMPACT_HELPERS 8
2178#define MAX_NONCOMPACT_HELPERS 50
2179
2180UInt VG_(n_compact_helpers) = 0;
2181UInt VG_(n_noncompact_helpers) = 0;
2182
2183Addr VG_(compact_helper_addrs) [MAX_COMPACT_HELPERS];
2184Int VG_(compact_helper_offsets)[MAX_COMPACT_HELPERS];
2185Addr VG_(noncompact_helper_addrs) [MAX_NONCOMPACT_HELPERS];
2186Int VG_(noncompact_helper_offsets)[MAX_NONCOMPACT_HELPERS];
2187
2188/* This is the actual defn of baseblock. */
2189UInt VG_(baseBlock)[VG_BASEBLOCK_WORDS];
2190
2191/* See comment about this in vg_include.h. Change only with great care. */
sewardjb91ae7f2003-04-29 23:50:00 +00002192__attribute__ ((aligned (16)))
sewardj92a59562002-09-30 00:53:10 +00002193UInt VG_(m_state_static) [6 /* segment regs, Intel order */
2194 + 8 /* int regs, in Intel order */
sewardjde4a1d02002-03-22 01:27:54 +00002195 + 1 /* %eflags */
2196 + 1 /* %eip */
sewardjb91ae7f2003-04-29 23:50:00 +00002197 + VG_SIZE_OF_SSESTATE_W /* FPU state */
sewardjde4a1d02002-03-22 01:27:54 +00002198 ];
2199
nethercote71980f02004-01-24 18:18:54 +00002200/* Words. */
2201static Int baB_off = 0;
2202
2203
sewardjfa492d42002-12-08 18:20:01 +00002204UInt VG_(insertDflag)(UInt eflags, Int d)
2205{
2206 vg_assert(d == 1 || d == -1);
2207 eflags &= ~EFlagD;
2208
2209 if (d < 0)
2210 eflags |= EFlagD;
2211
2212 return eflags;
2213}
2214
2215Int VG_(extractDflag)(UInt eflags)
2216{
2217 Int ret;
2218
2219 if (eflags & EFlagD)
2220 ret = -1;
2221 else
2222 ret = 1;
2223
2224 return ret;
2225}
2226
nethercote71980f02004-01-24 18:18:54 +00002227static void copy_baseBlock_to_m_state_static( void )
sewardjde4a1d02002-03-22 01:27:54 +00002228{
2229 Int i;
sewardj92a59562002-09-30 00:53:10 +00002230 VG_(m_state_static)[ 0/4] = VG_(baseBlock)[VGOFF_(m_cs)];
2231 VG_(m_state_static)[ 4/4] = VG_(baseBlock)[VGOFF_(m_ss)];
2232 VG_(m_state_static)[ 8/4] = VG_(baseBlock)[VGOFF_(m_ds)];
2233 VG_(m_state_static)[12/4] = VG_(baseBlock)[VGOFF_(m_es)];
2234 VG_(m_state_static)[16/4] = VG_(baseBlock)[VGOFF_(m_fs)];
2235 VG_(m_state_static)[20/4] = VG_(baseBlock)[VGOFF_(m_gs)];
sewardjde4a1d02002-03-22 01:27:54 +00002236
sewardj92a59562002-09-30 00:53:10 +00002237 VG_(m_state_static)[24/4] = VG_(baseBlock)[VGOFF_(m_eax)];
2238 VG_(m_state_static)[28/4] = VG_(baseBlock)[VGOFF_(m_ecx)];
2239 VG_(m_state_static)[32/4] = VG_(baseBlock)[VGOFF_(m_edx)];
2240 VG_(m_state_static)[36/4] = VG_(baseBlock)[VGOFF_(m_ebx)];
2241 VG_(m_state_static)[40/4] = VG_(baseBlock)[VGOFF_(m_esp)];
2242 VG_(m_state_static)[44/4] = VG_(baseBlock)[VGOFF_(m_ebp)];
2243 VG_(m_state_static)[48/4] = VG_(baseBlock)[VGOFF_(m_esi)];
2244 VG_(m_state_static)[52/4] = VG_(baseBlock)[VGOFF_(m_edi)];
2245
sewardjb91ae7f2003-04-29 23:50:00 +00002246 VG_(m_state_static)[56/4]
2247 = VG_(insertDflag)(VG_(baseBlock)[VGOFF_(m_eflags)],
2248 VG_(baseBlock)[VGOFF_(m_dflag)]);
sewardj92a59562002-09-30 00:53:10 +00002249 VG_(m_state_static)[60/4] = VG_(baseBlock)[VGOFF_(m_eip)];
sewardjde4a1d02002-03-22 01:27:54 +00002250
sewardjb91ae7f2003-04-29 23:50:00 +00002251 for (i = 0; i < VG_SIZE_OF_SSESTATE_W; i++)
sewardj92a59562002-09-30 00:53:10 +00002252 VG_(m_state_static)[64/4 + i]
sewardjb91ae7f2003-04-29 23:50:00 +00002253 = VG_(baseBlock)[VGOFF_(m_ssestate) + i];
sewardjde4a1d02002-03-22 01:27:54 +00002254}
2255
2256
nethercote71980f02004-01-24 18:18:54 +00002257/* Returns the offset, in words. */
2258static Int alloc_BaB ( Int words )
sewardjde4a1d02002-03-22 01:27:54 +00002259{
nethercote71980f02004-01-24 18:18:54 +00002260 Int off = baB_off;
2261 baB_off += words;
2262 if (baB_off >= VG_BASEBLOCK_WORDS)
2263 VG_(core_panic)( "alloc_BaB: baseBlock is too small");
sewardjde4a1d02002-03-22 01:27:54 +00002264
nethercote71980f02004-01-24 18:18:54 +00002265 return off;
sewardjde4a1d02002-03-22 01:27:54 +00002266}
2267
nethercote71980f02004-01-24 18:18:54 +00002268/* Align offset, in *bytes* */
2269static void align_BaB ( UInt align )
njn25e49d8e72002-09-23 09:36:25 +00002270{
nethercote71980f02004-01-24 18:18:54 +00002271 vg_assert(2 == align || 4 == align || 8 == align || 16 == align);
2272 baB_off += (align-1);
2273 baB_off &= ~(align-1);
njn25e49d8e72002-09-23 09:36:25 +00002274}
2275
nethercote71980f02004-01-24 18:18:54 +00002276/* Allocate 1 word in baseBlock and set it to the given value. */
2277static Int alloc_BaB_1_set ( Addr a )
njn25e49d8e72002-09-23 09:36:25 +00002278{
nethercote71980f02004-01-24 18:18:54 +00002279 Int off = alloc_BaB(1);
2280 VG_(baseBlock)[off] = (UInt)a;
2281 return off;
njn25e49d8e72002-09-23 09:36:25 +00002282}
2283
nethercote71980f02004-01-24 18:18:54 +00002284/* Registers a function in compact_helper_addrs; compact_helper_offsets is
2285 filled in later. */
2286void VG_(register_compact_helper)(Addr a)
sewardjde4a1d02002-03-22 01:27:54 +00002287{
nethercote71980f02004-01-24 18:18:54 +00002288 if (MAX_COMPACT_HELPERS <= VG_(n_compact_helpers)) {
2289 VG_(printf)("Can only register %d compact helpers\n",
2290 MAX_COMPACT_HELPERS);
2291 VG_(core_panic)("Too many compact helpers registered");
2292 }
2293 VG_(compact_helper_addrs)[VG_(n_compact_helpers)] = a;
2294 VG_(n_compact_helpers)++;
2295}
2296
2297/* Registers a function in noncompact_helper_addrs; noncompact_helper_offsets
2298 * is filled in later.
2299 */
2300void VG_(register_noncompact_helper)(Addr a)
2301{
2302 if (MAX_NONCOMPACT_HELPERS <= VG_(n_noncompact_helpers)) {
2303 VG_(printf)("Can only register %d non-compact helpers\n",
2304 MAX_NONCOMPACT_HELPERS);
2305 VG_(printf)("Try increasing MAX_NON_COMPACT_HELPERS\n");
2306 VG_(core_panic)("Too many non-compact helpers registered");
2307 }
2308 VG_(noncompact_helper_addrs)[VG_(n_noncompact_helpers)] = a;
2309 VG_(n_noncompact_helpers)++;
2310}
2311
2312/* Allocate offsets in baseBlock for the skin helpers */
2313static
2314void assign_helpers_in_baseBlock(UInt n, Int offsets[], Addr addrs[])
2315{
2316 UInt i;
2317 for (i = 0; i < n; i++)
2318 offsets[i] = alloc_BaB_1_set( addrs[i] );
2319}
2320
2321Bool VG_(need_to_handle_esp_assignment)(void)
2322{
2323 return ( VG_(defined_new_mem_stack_4)() ||
2324 VG_(defined_die_mem_stack_4)() ||
2325 VG_(defined_new_mem_stack_8)() ||
2326 VG_(defined_die_mem_stack_8)() ||
2327 VG_(defined_new_mem_stack_12)() ||
2328 VG_(defined_die_mem_stack_12)() ||
2329 VG_(defined_new_mem_stack_16)() ||
2330 VG_(defined_die_mem_stack_16)() ||
2331 VG_(defined_new_mem_stack_32)() ||
2332 VG_(defined_die_mem_stack_32)() ||
2333 VG_(defined_new_mem_stack)() ||
2334 VG_(defined_die_mem_stack)()
2335 );
2336}
2337
2338/* Here we assign actual offsets. It's important to get the most
2339 popular referents within 128 bytes of the start, so we can take
2340 advantage of short addressing modes relative to %ebp. Popularity
2341 of offsets was measured on 22 Feb 02 running a KDE application, and
2342 the slots rearranged accordingly, with a 1.5% reduction in total
2343 size of translations. */
2344static void init_baseBlock ( Addr client_eip, Addr esp_at_startup )
2345{
2346 /* Those with offsets under 128 are carefully chosen. */
2347
2348 /* WORD offsets in this column */
2349 /* 0 */ VGOFF_(m_eax) = alloc_BaB_1_set(0);
2350 /* 1 */ VGOFF_(m_ecx) = alloc_BaB_1_set(0);
2351 /* 2 */ VGOFF_(m_edx) = alloc_BaB_1_set(0);
2352 /* 3 */ VGOFF_(m_ebx) = alloc_BaB_1_set(0);
2353 /* 4 */ VGOFF_(m_esp) = alloc_BaB_1_set(esp_at_startup);
2354 /* 5 */ VGOFF_(m_ebp) = alloc_BaB_1_set(0);
2355 /* 6 */ VGOFF_(m_esi) = alloc_BaB_1_set(0);
2356 /* 7 */ VGOFF_(m_edi) = alloc_BaB_1_set(0);
2357 /* 8 */ VGOFF_(m_eflags) = alloc_BaB_1_set(0);
2358
2359 if (VG_(needs).shadow_regs) {
2360 /* 9 */ VGOFF_(sh_eax) = alloc_BaB_1_set(0);
2361 /* 10 */ VGOFF_(sh_ecx) = alloc_BaB_1_set(0);
2362 /* 11 */ VGOFF_(sh_edx) = alloc_BaB_1_set(0);
2363 /* 12 */ VGOFF_(sh_ebx) = alloc_BaB_1_set(0);
2364 /* 13 */ VGOFF_(sh_esp) = alloc_BaB_1_set(0);
2365 /* 14 */ VGOFF_(sh_ebp) = alloc_BaB_1_set(0);
2366 /* 15 */ VGOFF_(sh_esi) = alloc_BaB_1_set(0);
2367 /* 16 */ VGOFF_(sh_edi) = alloc_BaB_1_set(0);
2368 /* 17 */ VGOFF_(sh_eflags) = alloc_BaB_1_set(0);
2369 VG_TRACK( post_regs_write_init );
2370 }
2371
2372 /* 9,10,11 or 18,19,20... depends on number whether shadow regs are used
2373 * and on compact helpers registered */
2374
2375 /* Make these most-frequently-called specialised ones compact, if they
2376 are used. */
2377 if (VG_(defined_new_mem_stack_4)())
2378 VG_(register_compact_helper)( (Addr) VG_(tool_interface).track_new_mem_stack_4);
2379
2380 if (VG_(defined_die_mem_stack_4)())
2381 VG_(register_compact_helper)( (Addr) VG_(tool_interface).track_die_mem_stack_4);
2382
2383 /* (9 or 18) + n_compact_helpers */
2384 /* Allocate slots for compact helpers */
2385 assign_helpers_in_baseBlock(VG_(n_compact_helpers),
2386 VG_(compact_helper_offsets),
2387 VG_(compact_helper_addrs));
2388
2389 /* (9/10 or 18/19) + n_compact_helpers */
2390 VGOFF_(m_eip) = alloc_BaB_1_set(client_eip);
2391
2392 /* There are currently 24 spill slots */
2393 /* (11+/20+ .. 32+/43+) + n_compact_helpers. This can overlap the magic
2394 * boundary at >= 32 words, but most spills are to low numbered spill
2395 * slots, so the ones above the boundary don't see much action. */
2396 VGOFF_(spillslots) = alloc_BaB(VG_MAX_SPILLSLOTS);
2397
2398 /* I gave up counting at this point. Since they're above the
2399 short-amode-boundary, there's no point. */
2400
2401 VGOFF_(m_dflag) = alloc_BaB_1_set(1); // 1 == forward D-flag
2402
2403 /* The FPU/SSE state. This _must_ be 16-byte aligned. Initial
2404 state doesn't matter much, as long as it's not totally borked. */
2405 align_BaB(16);
2406 VGOFF_(m_ssestate) = alloc_BaB(VG_SIZE_OF_SSESTATE_W);
2407 vg_assert(
2408 0 == ( ((UInt)(& VG_(baseBlock)[VGOFF_(m_ssestate)])) % 16 )
sewardj22854b92002-11-30 14:00:47 +00002409 );
2410
fitzhardingec2dbbac2004-01-23 23:09:01 +00002411 /* I assume that if we have SSE2 we also have SSE */
2412 VG_(have_ssestate) =
2413 VG_(cpu_has_feature)(VG_X86_FEAT_FXSR) &&
2414 VG_(cpu_has_feature)(VG_X86_FEAT_SSE);
2415
fitzhardinge98abfc72003-12-16 02:05:15 +00002416 /* set up an initial FPU state (doesn't really matter what it is,
2417 so long as it's somewhat valid) */
2418 if (!VG_(have_ssestate))
nethercote71980f02004-01-24 18:18:54 +00002419 asm volatile("fwait; fnsave %0; fwait; frstor %0; fwait"
2420 :
2421 : "m" (VG_(baseBlock)[VGOFF_(m_ssestate)])
2422 : "cc", "memory");
fitzhardinge98abfc72003-12-16 02:05:15 +00002423 else
nethercote71980f02004-01-24 18:18:54 +00002424 asm volatile("fwait; fxsave %0; fwait; andl $0xffbf, %1;"
2425 "fxrstor %0; fwait"
2426 :
2427 : "m" (VG_(baseBlock)[VGOFF_(m_ssestate)]),
2428 "m" (VG_(baseBlock)[VGOFF_(m_ssestate)+(24/4)])
2429 : "cc", "memory");
fitzhardinge98abfc72003-12-16 02:05:15 +00002430
njn0c7a5b52003-04-30 09:00:33 +00002431 if (0) {
2432 if (VG_(have_ssestate))
2433 VG_(printf)("Looks like a SSE-capable CPU\n");
2434 else
2435 VG_(printf)("Looks like a MMX-only CPU\n");
2436 }
sewardjb91ae7f2003-04-29 23:50:00 +00002437
nethercote71980f02004-01-24 18:18:54 +00002438 /* LDT pointer: pretend the root thread has an empty LDT to start with. */
2439 VGOFF_(ldt) = alloc_BaB_1_set((UInt)NULL);
jsgf855d93d2003-10-13 22:26:55 +00002440
nethercote71980f02004-01-24 18:18:54 +00002441 /* TLS pointer: pretend the root thread has no TLS array for now. */
2442 VGOFF_(tls) = alloc_BaB_1_set((UInt)NULL);
fitzhardingef0046f22003-12-18 02:39:22 +00002443
nethercote71980f02004-01-24 18:18:54 +00002444 /* segment registers */
2445 VGOFF_(m_cs) = alloc_BaB_1_set(0);
2446 VGOFF_(m_ss) = alloc_BaB_1_set(0);
2447 VGOFF_(m_ds) = alloc_BaB_1_set(0);
2448 VGOFF_(m_es) = alloc_BaB_1_set(0);
2449 VGOFF_(m_fs) = alloc_BaB_1_set(0);
2450 VGOFF_(m_gs) = alloc_BaB_1_set(0);
fitzhardingef0046f22003-12-18 02:39:22 +00002451
nethercote71980f02004-01-24 18:18:54 +00002452 VG_(register_noncompact_helper)( (Addr) & VG_(do_useseg) );
fitzhardingef0046f22003-12-18 02:39:22 +00002453
nethercote71980f02004-01-24 18:18:54 +00002454#define REG(kind, size) \
2455 if (VG_(defined_##kind##_mem_stack##size)()) \
2456 VG_(register_noncompact_helper)( \
2457 (Addr) VG_(tool_interface).track_##kind##_mem_stack##size );
2458 REG(new, _8);
2459 REG(new, _12);
2460 REG(new, _16);
2461 REG(new, _32);
2462 REG(new, );
2463 REG(die, _8);
2464 REG(die, _12);
2465 REG(die, _16);
2466 REG(die, _32);
2467 REG(die, );
2468#undef REG
fitzhardingef0046f22003-12-18 02:39:22 +00002469
nethercote71980f02004-01-24 18:18:54 +00002470 if (VG_(need_to_handle_esp_assignment)())
2471 VG_(register_noncompact_helper)((Addr) VG_(unknown_esp_update));
fitzhardingeb791a192003-12-18 07:22:44 +00002472
nethercote71980f02004-01-24 18:18:54 +00002473# define HELPER(name) \
2474 VGOFF_(helper_##name) = alloc_BaB_1_set( (Addr) & VG_(helper_##name))
njn3e884182003-04-15 13:03:23 +00002475
nethercote71980f02004-01-24 18:18:54 +00002476 /* Helper functions. */
2477 HELPER(idiv_64_32); HELPER(div_64_32);
2478 HELPER(idiv_32_16); HELPER(div_32_16);
2479 HELPER(idiv_16_8); HELPER(div_16_8);
fitzhardinge98abfc72003-12-16 02:05:15 +00002480
nethercote71980f02004-01-24 18:18:54 +00002481 HELPER(imul_32_64); HELPER(mul_32_64);
2482 HELPER(imul_16_32); HELPER(mul_16_32);
2483 HELPER(imul_8_16); HELPER(mul_8_16);
njn25e49d8e72002-09-23 09:36:25 +00002484
nethercote71980f02004-01-24 18:18:54 +00002485 HELPER(CLD); HELPER(STD);
2486 HELPER(get_dirflag);
sewardjde4a1d02002-03-22 01:27:54 +00002487
nethercote71980f02004-01-24 18:18:54 +00002488 HELPER(CLC); HELPER(STC);
jsgf855d93d2003-10-13 22:26:55 +00002489
nethercote71980f02004-01-24 18:18:54 +00002490 HELPER(shldl); HELPER(shldw);
2491 HELPER(shrdl); HELPER(shrdw);
njncc7bb472002-10-14 09:25:19 +00002492
nethercote71980f02004-01-24 18:18:54 +00002493 HELPER(RDTSC); HELPER(CPUID);
njncc7bb472002-10-14 09:25:19 +00002494
nethercote71980f02004-01-24 18:18:54 +00002495 HELPER(bsf); HELPER(bsr);
rjwalshf5f536f2003-11-17 17:45:00 +00002496
nethercote71980f02004-01-24 18:18:54 +00002497 HELPER(fstsw_AX);
2498 HELPER(SAHF); HELPER(LAHF);
2499 HELPER(DAS); HELPER(DAA);
2500 HELPER(IN); HELPER(OUT);
2501 HELPER(cmpxchg8b);
sewardj018f7622002-05-15 21:13:39 +00002502
nethercote71980f02004-01-24 18:18:54 +00002503 HELPER(undefined_instruction);
jsgf855d93d2003-10-13 22:26:55 +00002504
nethercote71980f02004-01-24 18:18:54 +00002505# undef HELPER
sewardjde4a1d02002-03-22 01:27:54 +00002506
nethercote71980f02004-01-24 18:18:54 +00002507 /* Allocate slots for noncompact helpers */
2508 assign_helpers_in_baseBlock(VG_(n_noncompact_helpers),
2509 VG_(noncompact_helper_offsets),
2510 VG_(noncompact_helper_addrs));
2511}
sewardjde4a1d02002-03-22 01:27:54 +00002512
sewardj5f07b662002-04-23 16:52:51 +00002513
nethercote71980f02004-01-24 18:18:54 +00002514/*====================================================================*/
2515/*=== Setup pointercheck ===*/
2516/*====================================================================*/
njn25e49d8e72002-09-23 09:36:25 +00002517
nethercote71980f02004-01-24 18:18:54 +00002518static void setup_pointercheck(void)
2519{
2520 int ret;
sewardj2e93c502002-04-12 11:12:52 +00002521
fitzhardinge98abfc72003-12-16 02:05:15 +00002522 if (VG_(clo_pointercheck)) {
nethercote71980f02004-01-24 18:18:54 +00002523 vki_modify_ldt_t ldt = {
2524 VG_POINTERCHECK_SEGIDX, // entry_number
2525 VG_(client_base), // base_addr
2526 (VG_(client_end)-VG_(client_base)) / VKI_BYTES_PER_PAGE, // limit
2527 1, // seg_32bit
2528 0, // contents: data, RW, non-expanding
2529 0, // ! read_exec_only
2530 1, // limit_in_pages
2531 0, // ! seg not present
2532 1, // useable
fitzhardinge98abfc72003-12-16 02:05:15 +00002533 };
nethercote71980f02004-01-24 18:18:54 +00002534 ret = VG_(do_syscall)(__NR_modify_ldt, 1, &ldt, sizeof(ldt));
fitzhardinge98abfc72003-12-16 02:05:15 +00002535 if (ret < 0) {
2536 VG_(message)(Vg_UserMsg,
2537 "Warning: ignoring --pointercheck=yes, "
2538 "because modify_ldt failed (errno=%d)", -ret);
2539 VG_(clo_pointercheck) = False;
2540 }
2541 }
sewardjde4a1d02002-03-22 01:27:54 +00002542}
2543
nethercote71980f02004-01-24 18:18:54 +00002544/*====================================================================*/
2545/*=== Initialise program data/text, etc. ===*/
2546/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +00002547
nethercote71980f02004-01-24 18:18:54 +00002548static void build_valgrind_map_callback
2549 ( Addr start, UInt size, Char rr, Char ww, Char xx,
2550 UInt dev, UInt ino, ULong foffset, const UChar* filename )
sewardjde4a1d02002-03-22 01:27:54 +00002551{
nethercote71980f02004-01-24 18:18:54 +00002552 UInt prot = 0;
2553 UInt flags = SF_MMAP|SF_NOSYMS;
2554 Bool is_stack_segment;
2555
2556 is_stack_segment =
2557 (start == VG_(clstk_base) && (start+size) == VG_(clstk_end));
2558
2559 /* Only record valgrind mappings for now, without loading any
2560 symbols. This is so we know where the free space is before we
2561 start allocating more memory (note: heap is OK, it's just mmap
2562 which is the problem here). */
2563 if (start >= VG_(valgrind_base) && (start+size) <= VG_(valgrind_end)) {
2564 flags |= SF_VALGRIND;
2565 VG_(map_file_segment)(start, size, prot, flags, dev, ino, foffset, filename);
2566 }
sewardjde4a1d02002-03-22 01:27:54 +00002567}
2568
nethercote71980f02004-01-24 18:18:54 +00002569// Global var used to pass local data to callback
2570Addr esp_at_startup___global_arg = 0;
sewardjde4a1d02002-03-22 01:27:54 +00002571
nethercote71980f02004-01-24 18:18:54 +00002572static void build_segment_map_callback
2573 ( Addr start, UInt size, Char rr, Char ww, Char xx,
2574 UInt dev, UInt ino, ULong foffset, const UChar* filename )
sewardj45b672d2003-07-25 19:58:11 +00002575{
nethercote71980f02004-01-24 18:18:54 +00002576 UInt prot = 0;
2577 UInt flags;
2578 Bool is_stack_segment;
2579 Addr r_esp;
sewardj45b672d2003-07-25 19:58:11 +00002580
nethercote71980f02004-01-24 18:18:54 +00002581 is_stack_segment
2582 = (start == VG_(clstk_base) && (start+size) == VG_(clstk_end));
fitzhardinge98abfc72003-12-16 02:05:15 +00002583
nethercote71980f02004-01-24 18:18:54 +00002584 if (rr == 'r') prot |= VKI_PROT_READ;
2585 if (ww == 'w') prot |= VKI_PROT_WRITE;
2586 if (xx == 'x') prot |= VKI_PROT_EXEC;
fitzhardinge98abfc72003-12-16 02:05:15 +00002587
nethercote71980f02004-01-24 18:18:54 +00002588 if (is_stack_segment)
2589 flags = SF_STACK | SF_GROWDOWN;
2590 else
2591 flags = SF_EXEC|SF_MMAP;
fitzhardinge98abfc72003-12-16 02:05:15 +00002592
nethercote71980f02004-01-24 18:18:54 +00002593 if (filename != NULL)
2594 flags |= SF_FILE;
fitzhardinge98abfc72003-12-16 02:05:15 +00002595
nethercote71980f02004-01-24 18:18:54 +00002596 if (start >= VG_(valgrind_base) && (start+size) <= VG_(valgrind_end))
2597 flags |= SF_VALGRIND;
fitzhardinge98abfc72003-12-16 02:05:15 +00002598
nethercote71980f02004-01-24 18:18:54 +00002599 VG_(map_file_segment)(start, size, prot, flags, dev, ino, foffset, filename);
fitzhardinge98abfc72003-12-16 02:05:15 +00002600
nethercote71980f02004-01-24 18:18:54 +00002601 if (VG_(is_client_addr)(start) && VG_(is_client_addr)(start+size-1))
2602 VG_TRACK( new_mem_startup, start, size, rr=='r', ww=='w', xx=='x' );
sewardj3e1eb1f2002-05-18 13:14:17 +00002603
nethercote71980f02004-01-24 18:18:54 +00002604 /* If this is the stack segment mark all below %esp as noaccess. */
2605 r_esp = esp_at_startup___global_arg;
2606 vg_assert(0 != r_esp);
2607 if (is_stack_segment) {
2608 if (0)
2609 VG_(message)(Vg_DebugMsg, "invalidating stack area: %x .. %x",
2610 start,r_esp);
2611 VG_TRACK( die_mem_stack, start, r_esp-start );
sewardjde4a1d02002-03-22 01:27:54 +00002612 }
sewardjde4a1d02002-03-22 01:27:54 +00002613}
2614
2615
nethercote71980f02004-01-24 18:18:54 +00002616/*====================================================================*/
2617/*=== Sanity check machinery (permanently engaged) ===*/
2618/*====================================================================*/
njn25e49d8e72002-09-23 09:36:25 +00002619
2620/* A fast sanity check -- suitable for calling circa once per
2621 millisecond. */
2622
2623void VG_(do_sanity_checks) ( Bool force_expensive )
2624{
njn37cea302002-09-30 11:24:00 +00002625 VGP_PUSHCC(VgpCoreCheapSanity);
2626
njn25e49d8e72002-09-23 09:36:25 +00002627 if (VG_(sanity_level) < 1) return;
2628
2629 /* --- First do all the tests that we can do quickly. ---*/
2630
2631 VG_(sanity_fast_count)++;
2632
njn25e49d8e72002-09-23 09:36:25 +00002633 /* Check stuff pertaining to the memory check system. */
2634
2635 /* Check that nobody has spuriously claimed that the first or
2636 last 16 pages of memory have become accessible [...] */
njn37cea302002-09-30 11:24:00 +00002637 if (VG_(needs).sanity_checks) {
2638 VGP_PUSHCC(VgpSkinCheapSanity);
njn25e49d8e72002-09-23 09:36:25 +00002639 vg_assert(SK_(cheap_sanity_check)());
njn37cea302002-09-30 11:24:00 +00002640 VGP_POPCC(VgpSkinCheapSanity);
2641 }
njn25e49d8e72002-09-23 09:36:25 +00002642
2643 /* --- Now some more expensive checks. ---*/
2644
2645 /* Once every 25 times, check some more expensive stuff. */
2646 if ( force_expensive
2647 || VG_(sanity_level) > 1
2648 || (VG_(sanity_level) == 1 && (VG_(sanity_fast_count) % 25) == 0)) {
2649
njn37cea302002-09-30 11:24:00 +00002650 VGP_PUSHCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002651 VG_(sanity_slow_count)++;
2652
jsgf855d93d2003-10-13 22:26:55 +00002653 VG_(proxy_sanity)();
2654
njn25e49d8e72002-09-23 09:36:25 +00002655# if 0
2656 { void zzzmemscan(void); zzzmemscan(); }
2657# endif
2658
2659 if ((VG_(sanity_fast_count) % 250) == 0)
2660 VG_(sanity_check_tc_tt)();
2661
2662 if (VG_(needs).sanity_checks) {
njn37cea302002-09-30 11:24:00 +00002663 VGP_PUSHCC(VgpSkinExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002664 vg_assert(SK_(expensive_sanity_check)());
njn37cea302002-09-30 11:24:00 +00002665 VGP_POPCC(VgpSkinExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002666 }
2667 /*
2668 if ((VG_(sanity_fast_count) % 500) == 0) VG_(mallocSanityCheckAll)();
2669 */
njn37cea302002-09-30 11:24:00 +00002670 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002671 }
2672
2673 if (VG_(sanity_level) > 1) {
njn37cea302002-09-30 11:24:00 +00002674 VGP_PUSHCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002675 /* Check sanity of the low-level memory manager. Note that bugs
2676 in the client's code can cause this to fail, so we don't do
2677 this check unless specially asked for. And because it's
2678 potentially very expensive. */
2679 VG_(mallocSanityCheckAll)();
njn37cea302002-09-30 11:24:00 +00002680 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002681 }
njn37cea302002-09-30 11:24:00 +00002682 VGP_POPCC(VgpCoreCheapSanity);
njn25e49d8e72002-09-23 09:36:25 +00002683}
nethercote71980f02004-01-24 18:18:54 +00002684
2685
2686/*====================================================================*/
2687/*=== main() ===*/
2688/*====================================================================*/
2689
2690int main(int argc, char **argv)
2691{
2692 char **cl_argv;
2693 const char *tool = NULL;
2694 const char *exec = NULL;
2695 char *preload; /* tool-specific LD_PRELOAD .so */
2696 char **env;
nethercote6c999f22004-01-31 22:55:15 +00002697 Int need_help = 0; // 0 = no, 1 = --help, 2 = --help-debug
nethercote71980f02004-01-24 18:18:54 +00002698 struct exeinfo info;
2699 ToolInfo *toolinfo = NULL;
2700 void *tool_dlhandle;
2701 Addr client_eip;
2702 Addr esp_at_startup; /* client's %esp at the point we gained control. */
2703 UInt * client_auxv;
2704 VgSchedReturnCode src;
2705
2706 //============================================================
2707 // Nb: startup is complex. Prerequisites are shown at every step.
2708 //
2709 // *** Be very careful when messing with the order ***
2710 //============================================================
2711
2712 //--------------------------------------------------------------
2713 // Check we were launched by stage1
2714 // p: n/a [must be first step]
2715 //--------------------------------------------------------------
2716 scan_auxv();
2717
2718 if (0) {
2719 int prmap(void *start, void *end, const char *perm, off_t off,
2720 int maj, int min, int ino) {
2721 printf("mapping %10p-%10p %s %02x:%02x %d\n",
2722 start, end, perm, maj, min, ino);
2723 return True;
2724 }
2725 printf("========== main() ==========\n");
2726 foreach_map(prmap);
2727 }
2728
2729 //--------------------------------------------------------------
2730 // Look for alternative libdir
2731 // p: n/a
2732 //--------------------------------------------------------------
2733 { char *cp = getenv(VALGRINDLIB);
2734 if (cp != NULL)
2735 VG_(libdir) = cp;
2736 }
2737
2738 //--------------------------------------------------------------
2739 // Begin working out address space layout
2740 // p: n/a
2741 //--------------------------------------------------------------
2742 layout_client_space( (Addr) & argc );
2743
2744 //--------------------------------------------------------------
2745 // Get valgrind args + client args (inc. from VALGRIND_OPTS/.valgrindrc).
2746 // Pre-process the command line.
2747 // p: n/a
2748 //--------------------------------------------------------------
2749 get_command_line(argc, argv, &VG_(vg_argc), &VG_(vg_argv), &cl_argv);
2750 pre_process_cmd_line_options(&need_help, &tool, &exec);
2751
2752 //==============================================================
2753 // Nb: once a tool is specified, the tool.so must be loaded even if
2754 // they specified --help or didn't specify a client program.
2755 //==============================================================
2756
2757 //--------------------------------------------------------------
2758 // With client padded out, map in tool
2759 // p: layout_client_space() [for padding]
2760 // p: set-libdir [for VG_(libdir)]
2761 // p: pre_process_cmd_line_options() [for 'tool']
2762 //--------------------------------------------------------------
2763 load_tool(tool, &tool_dlhandle, &toolinfo, &preload);
2764
2765 //==============================================================
2766 // Can use VG_(malloc)() and VG_(arena_malloc)() only after load_tool()
2767 // -- redzone size is now set.
2768 //==============================================================
2769
2770 //--------------------------------------------------------------
2771 // Finalise address space layout
2772 // p: layout_client_space(), load_tool() [for 'toolinfo']
2773 //--------------------------------------------------------------
2774 layout_remaining_space( toolinfo->shadow_ratio );
2775
2776 //--------------------------------------------------------------
2777 // Load client executable, finding in $PATH if necessary
2778 // p: layout_client_space() [so there's space]
2779 // p: pre_process_cmd_line_options() [for 'exec', 'need_help']
2780 // p: layout_remaining_space [so there's space]
2781 //--------------------------------------------------------------
2782 load_client(cl_argv, exec, /*inout*/&need_help, &info, &client_eip);
2783
2784 //--------------------------------------------------------------
2785 // Everything in place, unpad us
2786 // p: layout_remaining_space() [everything must be mapped in before now]
2787 // p: load_client() [ditto]
2788 //--------------------------------------------------------------
2789 as_unpad((void *)VG_(shadow_end), (void *)~0);
2790 as_closepadfile(); /* no more padding */
2791
2792 //--------------------------------------------------------------
2793 // Set up client's environment
2794 // p: set-libdir [for VG_(libdir)]
2795 // p: load_tool() [for 'preload']
2796 //--------------------------------------------------------------
2797 env = fix_environment(environ, preload);
2798
2799 //--------------------------------------------------------------
2800 // Setup client stack and eip
2801 // p: load_client() [for 'info']
2802 // p: fix_environment() [for 'env']
2803 //--------------------------------------------------------------
2804 esp_at_startup = setup_client_stack(cl_argv, env, &info, &client_auxv);
2805
2806 if (0)
2807 printf("entry=%x client esp=%x vg_argc=%d brkbase=%x\n",
2808 client_eip, esp_at_startup, VG_(vg_argc), VG_(brk_base));
2809
2810 //==============================================================
2811 // Finished setting up operating environment. Now initialise
2812 // Valgrind. (This is where the old VG_(main)() started.)
2813 //==============================================================
2814
2815 //--------------------------------------------------------------
2816 // Read /proc/self/maps into a buffer
2817 // p: all memory layout, environment setup [so memory maps are right]
2818 //--------------------------------------------------------------
2819 VG_(read_procselfmaps)();
2820
2821 //--------------------------------------------------------------
2822 // atfork
2823 // p: n/a
2824 //--------------------------------------------------------------
2825 VG_(atfork)(NULL, NULL, newpid);
2826 newpid(VG_INVALID_THREADID);
2827
2828 //--------------------------------------------------------------
2829 // setup file descriptors
2830 // p: n/a
2831 //--------------------------------------------------------------
2832 setup_file_descriptors();
2833
2834 //--------------------------------------------------------------
2835 // Setup tool
2836 // p: VG_(read_procselfmaps)() [so if sk_pre_clo_init calls
2837 // VG_(malloc), any mmap'd superblocks aren't erroneously
2838 // identified later as being owned by the client]
2839 // XXX: is that necessary, now that we look for V's segments separately?
2840 // XXX: alternatively, if sk_pre_clo_init does use VG_(malloc)(), is it
2841 // wrong to ignore any segments that might add in parse_procselfmaps?
2842 //--------------------------------------------------------------
2843 (*toolinfo->sk_pre_clo_init)();
2844 VG_(tool_init_dlsym)(tool_dlhandle);
2845 VG_(sanity_check_needs)();
2846
2847 //--------------------------------------------------------------
2848 // Process Valgrind's + tool's command-line options
2849 // p: load_tool() [for 'tool']
2850 // p: load_client() [for 'need_help']
2851 // p: setup_file_descriptors() [for 'VG_(max_fd)']
2852 // p: sk_pre_clo_init [to set 'command_line_options' need]
2853 //--------------------------------------------------------------
2854 process_cmd_line_options(client_auxv, esp_at_startup, tool, need_help);
2855
2856 //--------------------------------------------------------------
2857 // Allow GDB attach
2858 // p: process_cmd_line_options() [for VG_(clo_wait_for_gdb)]
2859 //--------------------------------------------------------------
2860 /* Hook to delay things long enough so we can get the pid and
2861 attach GDB in another shell. */
2862 if (VG_(clo_wait_for_gdb)) {
2863 VG_(printf)("pid=%d\n", VG_(getpid)());
2864 /* do "jump *$eip" to skip this in gdb */
2865 VG_(do_syscall)(__NR_pause);
2866 }
2867
2868 //--------------------------------------------------------------
2869 // Setup tool, post command-line processing
2870 // p: process_cmd_line_options [tool assumes it]
2871 //--------------------------------------------------------------
2872 SK_(post_clo_init)();
2873
2874 //--------------------------------------------------------------
2875 // Set up baseBlock, copy machine state (m_state_static)
2876 // p: {pre,post}_clo_init() [for tool helper registration]
2877 // load_client() [for 'client_eip']
2878 // setup_client_stack() [for 'esp_at_startup']
2879 //--------------------------------------------------------------
2880 init_baseBlock(client_eip, esp_at_startup);
2881
2882 //--------------------------------------------------------------
2883 // Search for file descriptors that are inherited from our parent
2884 // p: process_cmd_line_options [for VG_(clo_track_fds)]
2885 //--------------------------------------------------------------
2886 if (VG_(clo_track_fds))
2887 VG_(init_preopened_fds)();
2888
2889 //--------------------------------------------------------------
2890 // Initialise the scheduler
2891 // p: init_baseBlock() [baseBlock regs copied into VG_(threads)[1]]
2892 // p: setup_file_descriptors() [else VG_(safe_fd)() breaks]
2893 //--------------------------------------------------------------
2894 VG_(scheduler_init)();
2895
2896 //--------------------------------------------------------------
2897 // Set up the ProxyLWP machinery
2898 // p: VG_(scheduler_init)()? [XXX: subtle dependency?]
2899 // - subs: VG_(sigstartup_actions)()?
2900 //--------------------------------------------------------------
2901 VG_(proxy_init)();
2902
2903 //--------------------------------------------------------------
2904 // Initialise the signal handling subsystem
2905 // p: VG_(atfork)(NULL, NULL, newpid) [else problems with sigmasks]
2906 // p: VG_(proxy_init)() [else breaks...]
2907 //--------------------------------------------------------------
2908 // Nb: temporarily parks the saved blocking-mask in saved_sigmask.
2909 VG_(sigstartup_actions)();
2910
2911 //--------------------------------------------------------------
2912 // Perhaps we're profiling Valgrind?
2913 // p: process_cmd_line_options() [for VG_(clo_profile)]
2914 // p: others?
2915 //
2916 // XXX: this seems to be broken? It always says the tool wasn't built
2917 // for profiling; vg_profile.c's functions don't seem to be overriding
2918 // vg_dummy_profile.c's?
2919 //
2920 // XXX: want this as early as possible. Looking for --profile
2921 // in pre_process_cmd_line_options() could get it earlier.
2922 //--------------------------------------------------------------
2923 if (VG_(clo_profile))
2924 VGP_(init_profiling)();
2925
2926 VGP_PUSHCC(VgpStartup);
2927
2928 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002929 // Reserve Valgrind's kickstart, heap and stack
2930 // p: XXX ???
2931 //--------------------------------------------------------------
2932 VG_(map_segment)(VG_(valgrind_mmap_end),
2933 VG_(valgrind_end)-VG_(valgrind_mmap_end),
2934 VKI_PROT_NONE, SF_VALGRIND|SF_FIXED);
2935
2936 //--------------------------------------------------------------
2937 // Identify Valgrind's segments
2938 // p: read proc/self/maps
2939 // p: VG_(map_segment) [XXX ???]
2940 // p: sk_pre_clo_init() [to setup new_mem_startup tracker]
2941 //--------------------------------------------------------------
2942 VG_(parse_procselfmaps) ( build_valgrind_map_callback );
2943
2944 // XXX: I can't see why these two need to be separate; could they be
2945 // folded together? If not, need a comment explaining why.
2946 //
2947 // XXX: can we merge reading and parsing of /proc/self/maps?
2948 //
2949 // XXX: can we dynamically allocate the /proc/self/maps buffer? (or mmap
2950 // it?) Or does that disturb its contents...
2951
2952 //--------------------------------------------------------------
2953 // Build segment map (all segments)
2954 // p: setup_client_stack() [for 'esp_at_startup']
2955 //--------------------------------------------------------------
2956 esp_at_startup___global_arg = esp_at_startup;
2957 VG_(parse_procselfmaps) ( build_segment_map_callback ); /* everything */
2958 esp_at_startup___global_arg = 0;
2959
2960 //==============================================================
2961 // Can only use VG_(map)() after VG_(map_segment)() [XXX ???]
2962 //==============================================================
2963
2964 //--------------------------------------------------------------
2965 // Build segment map (all segments)
2966 // p: setup_client_stack() [for 'esp_at_startup']
2967 //--------------------------------------------------------------
2968 /* Initialize our trampoline page (which is also sysinfo stuff) */
2969 VG_(memcpy)( (void *)VG_(client_trampoline_code),
2970 &VG_(trampoline_code_start), VG_(trampoline_code_length) );
2971 VG_(mprotect)( (void *)VG_(client_trampoline_code),
2972 VG_(trampoline_code_length), VKI_PROT_READ|VKI_PROT_EXEC );
2973
2974 //--------------------------------------------------------------
2975 // Read suppression file
2976 // p: process_cmd_line_options() [for VG_(clo_suppressions)]
2977 //--------------------------------------------------------------
2978 if (VG_(needs).core_errors || VG_(needs).skin_errors)
2979 VG_(load_suppressions)();
2980
2981 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002982 // Initialise translation table and translation cache
2983 // p: read_procselfmaps [so the anonymous mmaps for the TT/TC
2984 // aren't identified as part of the client, which would waste
2985 // > 20M of virtual address space.]
2986 //--------------------------------------------------------------
2987 VG_(init_tt_tc)();
2988
2989 //--------------------------------------------------------------
2990 // Read debug info to find glibc entry points to intercept
2991 // p: parse_procselfmaps? [XXX for debug info?]
2992 // p: init_tt_tc? [XXX ???]
2993 //--------------------------------------------------------------
2994 VG_(setup_code_redirect_table)();
2995
2996 //--------------------------------------------------------------
2997 // Verbosity message
2998 // p: end_rdtsc_calibration [so startup message is printed first]
2999 //--------------------------------------------------------------
3000 if (VG_(clo_verbosity) == 1)
3001 VG_(message)(Vg_UserMsg, "For more details, rerun with: -v");
3002 if (VG_(clo_verbosity) > 0)
3003 VG_(message)(Vg_UserMsg, "");
3004
3005 //--------------------------------------------------------------
3006 // Setup pointercheck
3007 // p: process_cmd_line_options() [for VG_(clo_pointercheck)]
3008 //--------------------------------------------------------------
3009 setup_pointercheck();
3010
3011
3012
3013 //--------------------------------------------------------------
3014 // Run!
3015 //--------------------------------------------------------------
3016 VG_(running_on_simd_CPU) = True;
3017 VGP_POPCC(VgpStartup);
3018 VGP_PUSHCC(VgpSched);
3019
3020 if (__builtin_setjmp(&VG_(fatal_signal_jmpbuf)) == 0) {
3021 VG_(fatal_signal_set) = True;
3022 src = VG_(scheduler)();
3023 } else
3024 src = VgSrc_FatalSig;
3025
3026 VGP_POPCC(VgpSched);
3027 VG_(running_on_simd_CPU) = False;
3028
3029
3030
3031 //--------------------------------------------------------------
3032 // Finalisation: cleanup, messages, etc. Order no so important, only
3033 // affects what order the messages come.
3034 //--------------------------------------------------------------
3035 if (VG_(clo_verbosity) > 0)
3036 VG_(message)(Vg_UserMsg, "");
3037
3038 if (src == VgSrc_Deadlock) {
3039 VG_(message)(Vg_UserMsg,
3040 "Warning: pthread scheduler exited due to deadlock");
3041 }
3042
3043 /* Print out file descriptor summary and stats. */
3044 if (VG_(clo_track_fds))
3045 VG_(fd_stats)();
3046
3047 if (VG_(needs).core_errors || VG_(needs).skin_errors)
3048 VG_(show_all_errors)();
3049
3050 SK_(fini)( VG_(exitcode) );
3051
3052 VG_(do_sanity_checks)( True /*include expensive checks*/ );
3053
3054 if (VG_(clo_verbosity) > 1)
3055 show_counts();
3056
3057 if (VG_(clo_verbosity) > 3)
3058 VG_(print_UInstr_histogram)();
3059
3060 if (0) {
3061 VG_(message)(Vg_DebugMsg, "");
3062 VG_(message)(Vg_DebugMsg,
3063 "------ Valgrind's internal memory use stats follow ------" );
3064 VG_(mallocSanityCheckAll)();
3065 VG_(show_all_arena_stats)();
3066 VG_(message)(Vg_DebugMsg,
3067 "------ Valgrind's ExeContext management stats follow ------" );
3068 VG_(show_ExeContext_stats)();
3069 }
3070
3071 if (VG_(clo_profile))
3072 VGP_(done_profiling)();
3073
3074 /* Must be after all messages are done */
3075 VG_(shutdown_logging)();
3076
3077 /* We're exiting, so nuke all the threads and clean up the proxy LWPs */
3078 vg_assert(src == VgSrc_FatalSig ||
3079 VG_(threads)[VG_(last_run_tid)].status == VgTs_Runnable ||
3080 VG_(threads)[VG_(last_run_tid)].status == VgTs_WaitJoiner);
3081 VG_(nuke_all_threads_except)(VG_INVALID_THREADID);
3082
3083 //--------------------------------------------------------------
3084 // Exit, according to the scheduler's return code
3085 //--------------------------------------------------------------
3086 switch (src) {
3087 case VgSrc_ExitSyscall: /* the normal way out */
3088 vg_assert(VG_(last_run_tid) > 0
3089 && VG_(last_run_tid) < VG_N_THREADS);
3090 VG_(proxy_shutdown)();
3091
3092 /* The thread's %EBX at the time it did __NR_exit() will hold
3093 the arg to __NR_exit(), so we just do __NR_exit() with
3094 that arg. */
3095 VG_(exit)( VG_(exitcode) );
3096 /* NOT ALIVE HERE! */
3097 VG_(core_panic)("entered the afterlife in main() -- ExitSyscall");
3098 break; /* what the hell :) */
3099
3100 case VgSrc_Deadlock:
3101 /* Just exit now. No point in continuing. */
3102 VG_(proxy_shutdown)();
3103 VG_(exit)(0);
3104 VG_(core_panic)("entered the afterlife in main() -- Deadlock");
3105 break;
3106
3107 case VgSrc_BbsDone:
3108 /* Tricky; we have to try and switch back to the real CPU.
3109 This is all very dodgy and won't work at all in the
3110 presence of threads, or if the client happened to be
3111 running a signal handler. */
3112 /* Prepare to restore state to the real CPU. */
3113 VG_(sigshutdown_actions)();
3114 VG_(load_thread_state)(1 /* root thread */ );
3115 copy_baseBlock_to_m_state_static();
3116
3117 VG_(proxy_shutdown)();
3118
3119 /* This pushes a return address on the simulator's stack,
3120 which is abandoned. We call vg_sigshutdown_actions() at
3121 the end of vg_switch_to_real_CPU(), so as to ensure that
3122 the original stack and machine state is restored before
3123 the real signal mechanism is restored. */
3124 VG_(switch_to_real_CPU)();
3125
3126 case VgSrc_FatalSig:
3127 /* We were killed by a fatal signal, so replicate the effect */
3128 vg_assert(VG_(fatal_sigNo) != -1);
3129 VG_(kill_self)(VG_(fatal_sigNo));
3130 VG_(core_panic)("main(): signal was supposed to be fatal");
3131 break;
3132
3133 default:
3134 VG_(core_panic)("main(): unexpected scheduler return code");
3135 }
3136
3137 abort();
3138}
3139
3140
sewardjde4a1d02002-03-22 01:27:54 +00003141/*--------------------------------------------------------------------*/
3142/*--- end vg_main.c ---*/
3143/*--------------------------------------------------------------------*/