blob: 59637ee9f2d612fc25d4cc0b5cba0d213318b442 [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,
1355 /*inout*/Bool* need_help,
1356 /*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 {
1364 *need_help = True;
1365 }
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
nethercote71980f02004-01-24 18:18:54 +00001472void usage ( void )
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"
1480" --version show version\n"
njn25e49d8e72002-09-23 09:36:25 +00001481" -q --quiet run silently; only print error msgs\n"
1482" -v --verbose be more verbose, incl counts of errors\n"
nethercote77eba602003-11-13 17:35:04 +00001483" --trace-children=no|yes Valgrind-ise child processes? [no]\n"
rjwalshf5f536f2003-11-17 17:45:00 +00001484" --track-fds=no|yes Track open file descriptors? [no]\n"
nethercote2b0793f2003-12-02 10:41:18 +00001485"\n"
1486" uncommon user options for all Valgrind tools:\n"
nethercote77eba602003-11-13 17:35:04 +00001487" --run-libc-freeres=no|yes Free up glibc memory at exit? [yes]\n"
1488" --weird-hacks=hack1,hack2,... [none]\n"
sewardj3d652a32002-10-20 18:11:49 +00001489" recognised hacks are: ioctl-VTIME truncate-writes lax-ioctls\n"
jsgf855d93d2003-10-13 22:26:55 +00001490" --signal-polltime=<time> time, in mS, we should poll for signals.\n"
1491" Only applies for older kernels which need\n"
1492" signal routing [50]\n"
1493" --lowlat-signals=no|yes improve wake-up latency when a thread receives\n"
1494" a signal [no]\n"
1495" --lowlat-syscalls=no|yes improve wake-up latency when a thread's\n"
1496" syscall completes [no]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001497" --pointercheck=no|yes enforce client address space limits [yes]\n"
njn25e49d8e72002-09-23 09:36:25 +00001498"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001499" user options for Valgrind tools that report errors:\n"
1500" --logfile-fd=<number> file descriptor for messages [2=stderr]\n"
1501" --logfile=<file> log messages to <file>.pid<pid>\n"
1502" --logsocket=ipaddr:port log messages to socket ipaddr:port\n"
1503" --demangle=no|yes automatically demangle C++ names? [yes]\n"
1504" --num-callers=<number> show <num> callers in stack traces [4]\n"
1505" --error-limit=no|yes stop showing new errors if too many? [yes]\n"
1506" --show-below-main=no|yes continue stack traces below main() [no]\n"
1507" --suppressions=<filename> suppress errors described in <filename>\n"
1508" --gen-suppressions=no|yes print suppressions for errors detected [no]\n"
njn7cf0bd32002-06-08 13:36:03 +00001509
nethercote04d0fbc2004-01-26 16:48:06 +00001510" --db-attach=no|yes start debugger when errors detected? [no]\n"
1511" --db-command=<command> command to start debugger [gdb -nw %%f %%p]\n"
1512" --input-fd=<number> file descriptor for input [0=stdin]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001513"\n";
njn7cf0bd32002-06-08 13:36:03 +00001514
njn25e49d8e72002-09-23 09:36:25 +00001515 Char* usage2 =
1516"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001517" debugging options for all Valgrind tools:\n"
njn25e49d8e72002-09-23 09:36:25 +00001518" --sanity-level=<number> level of sanity checking to do [1]\n"
1519" --single-step=no|yes translate each instr separately? [no]\n"
1520" --optimise=no|yes improve intermediate code? [yes]\n"
nethercote137bc552003-11-14 17:47:54 +00001521" --profile=no|yes profile? (tool must be built for it) [no]\n"
sewardj22854b92002-11-30 14:00:47 +00001522" --chain-bb=no|yes do basic-block chaining? [yes]\n"
fitzhardinge462f4f92003-12-18 02:10:54 +00001523" --branchpred=yes|no generate branch prediction hints [no]\n"
njn25e49d8e72002-09-23 09:36:25 +00001524" --trace-codegen=<XXXXX> show generated code? (X = 0|1) [00000]\n"
1525" --trace-syscalls=no|yes show all system calls? [no]\n"
1526" --trace-signals=no|yes show signal handling details? [no]\n"
1527" --trace-symtab=no|yes show symbol table details? [no]\n"
njn25e49d8e72002-09-23 09:36:25 +00001528" --trace-sched=no|yes show thread scheduler details? [no]\n"
njn3e884182003-04-15 13:03:23 +00001529" --trace-pthread=none|some|all show pthread event details? [none]\n"
njn25e49d8e72002-09-23 09:36:25 +00001530" --stop-after=<number> switch to real CPU after executing\n"
1531" <number> basic blocks [infinity]\n"
jsgf855d93d2003-10-13 22:26:55 +00001532" --wait-for-gdb=yes|no pause on startup to wait for gdb attach\n"
njn25e49d8e72002-09-23 09:36:25 +00001533"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001534" debugging options for Valgrind tools that report errors\n"
1535" --dump-error=<number> show translation for basic block associated\n"
1536" with <number>'th error context [0=show none]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001537"\n";
njn3e884182003-04-15 13:03:23 +00001538
1539 Char* usage3 =
1540"\n"
nethercote71980f02004-01-24 18:18:54 +00001541" Extra options read from ~/.valgrindrc, $VALGRIND_OPTS, ./.valgrindrc\n"
njn25e49d8e72002-09-23 09:36:25 +00001542"\n"
nethercotebb1c9912004-01-04 16:43:23 +00001543" Valgrind is Copyright (C) 2000-2004 Julian Seward\n"
njn25e49d8e72002-09-23 09:36:25 +00001544" and licensed under the GNU General Public License, version 2.\n"
1545" Bug reports, feedback, admiration, abuse, etc, to: %s.\n"
njnd04b7c62002-10-03 14:05:52 +00001546"\n"
nethercote137bc552003-11-14 17:47:54 +00001547" Tools are copyright and licensed by their authors. See each\n"
1548" tool's start-up message for more information.\n"
njn25e49d8e72002-09-23 09:36:25 +00001549"\n";
njn7cf0bd32002-06-08 13:36:03 +00001550
fitzhardinge98abfc72003-12-16 02:05:15 +00001551 VG_(printf)(usage1);
1552 if (VG_(details).name) {
1553 VG_(printf)(" user options for %s:\n", VG_(details).name);
1554 /* Don't print skin string directly for security, ha! */
1555 if (VG_(needs).command_line_options)
1556 SK_(print_usage)();
1557 else
1558 VG_(printf)(" (none)\n");
1559 }
1560 VG_(printf)(usage2);
1561
1562 if (VG_(details).name) {
1563 VG_(printf)(" debugging options for %s:\n", VG_(details).name);
1564
1565 if (VG_(needs).command_line_options)
1566 SK_(print_debug_usage)();
1567 else
1568 VG_(printf)(" (none)\n");
1569 }
nethercote421281e2003-11-20 16:20:55 +00001570 VG_(printf)(usage3, VG_BUGS_TO);
njn7cf0bd32002-06-08 13:36:03 +00001571
njn25e49d8e72002-09-23 09:36:25 +00001572 VG_(shutdown_logging)();
sewardj4cf05692002-10-27 20:28:29 +00001573 VG_(clo_log_to) = VgLogTo_Fd;
njn25e49d8e72002-09-23 09:36:25 +00001574 VG_(clo_logfile_fd) = 2; /* stderr */
1575 VG_(exit)(1);
njn7cf0bd32002-06-08 13:36:03 +00001576}
sewardjde4a1d02002-03-22 01:27:54 +00001577
nethercote71980f02004-01-24 18:18:54 +00001578static void pre_process_cmd_line_options
1579 ( Bool* need_help, const char** tool, const char** exec )
sewardj1c1b1162003-02-23 01:25:51 +00001580{
nethercote71980f02004-01-24 18:18:54 +00001581 UInt i;
sewardjde4a1d02002-03-22 01:27:54 +00001582
nethercote71980f02004-01-24 18:18:54 +00001583 /* parse the options we have (only the options we care about now) */
1584 for (i = 1; i < VG_(vg_argc); i++) {
1585
1586 if (strcmp(VG_(vg_argv)[i], "--version") == 0) {
1587 printf("valgrind-" VERSION "\n");
1588 exit(1);
1589
1590 } else if (strcmp(VG_(vg_argv)[i], "--help") == 0) {
1591 *need_help = True;
1592
1593 } else if (strncmp(VG_(vg_argv)[i], "--tool=", 7) == 0 ||
1594 strncmp(VG_(vg_argv)[i], "--skin=", 7) == 0) {
1595 *tool = &VG_(vg_argv)[i][7];
1596
1597 } else if (strncmp(VG_(vg_argv)[i], "--exec=", 7) == 0) {
1598 *exec = &VG_(vg_argv)[i][7];
1599 }
1600 }
1601
1602 /* If no tool specified, can give usage message without loading tool */
1603 if (*tool == NULL) {
1604 if (!need_help)
1605 list_tools();
1606 usage();
1607 }
1608}
1609
1610static void process_cmd_line_options
1611 ( UInt* client_auxv, Addr esp_at_startup,
1612 const char* toolname, Bool need_help )
1613{
1614 Int i, eventually_logfile_fd;
1615 Int *auxp;
1616 Int toolname_len = VG_(strlen)(toolname);
sewardjde4a1d02002-03-22 01:27:54 +00001617
nethercotee1730692003-11-20 10:38:07 +00001618 /* log to stderr by default, but usage message goes to stdout */
1619 eventually_logfile_fd = 2;
sewardjde4a1d02002-03-22 01:27:54 +00001620
1621 /* Once logging is started, we can safely send messages pertaining
1622 to failures in initialisation. */
1623 VG_(startup_logging)();
1624
sewardj19d81412002-06-03 01:10:40 +00001625 /* Check for sane path in ./configure --prefix=... */
fitzhardinge98abfc72003-12-16 02:05:15 +00001626 if (VG_LIBDIR[0] != '/')
sewardj19d81412002-06-03 01:10:40 +00001627 config_error("Please use absolute paths in "
1628 "./configure --prefix=... or --libdir=...");
sewardj38170912002-05-10 21:07:22 +00001629
nethercote71980f02004-01-24 18:18:54 +00001630 for (auxp = client_auxv; auxp[0] != VKI_AT_NULL; auxp += 2) {
fitzhardinge98abfc72003-12-16 02:05:15 +00001631 switch(auxp[0]) {
1632 case VKI_AT_SYSINFO:
1633 VG_(sysinfo_page_exists) = True;
fitzhardinge92360792003-12-24 10:11:11 +00001634 auxp[1] = (Int)(VG_(client_trampoline_code) + VG_(tramp_syscall_offset));
fitzhardinge98abfc72003-12-16 02:05:15 +00001635 VG_(sysinfo_page_addr) = auxp[1];
1636 break;
sewardjde4a1d02002-03-22 01:27:54 +00001637 }
fitzhardinge98abfc72003-12-16 02:05:15 +00001638 }
sewardjde4a1d02002-03-22 01:27:54 +00001639
nethercote71980f02004-01-24 18:18:54 +00001640 if (need_help)
1641 usage();
fitzhardinge98abfc72003-12-16 02:05:15 +00001642
1643 /* We know the initial ESP is pointing at argc/argv */
nethercote71980f02004-01-24 18:18:54 +00001644 VG_(client_argc) = *(Int *)esp_at_startup;
1645 VG_(client_argv) = (Char **)(esp_at_startup + sizeof(Int));
fitzhardinge98abfc72003-12-16 02:05:15 +00001646
nethercote71980f02004-01-24 18:18:54 +00001647 for (i = 1; i < VG_(vg_argc); i++) {
1648
1649 Char* arg = VG_(vg_argv)[i];
1650
1651 // XXX: allow colons in options, for Josef
1652
1653 /* Look for matching "--toolname:foo" */
1654 if (VG_(strstr)(arg, ":")) {
1655 if (VG_CLO_STREQN(2, arg, "--") &&
1656 VG_CLO_STREQN(toolname_len, arg+2, toolname) &&
1657 VG_CLO_STREQN(1, arg+2+toolname_len, ":"))
1658 {
1659 // prefix matches, convert "--toolname:foo" to "--foo"
1660 if (0)
1661 VG_(printf)("tool-specific arg: %s\n", arg);
1662 arg += toolname_len + 1;
1663 arg[0] = '-';
1664 arg[1] = '-';
1665
1666 } else {
1667 // prefix doesn't match, skip to next arg
1668 continue;
1669 }
1670 }
1671
fitzhardinge98abfc72003-12-16 02:05:15 +00001672 /* Ignore these options - they've already been handled */
nethercote71980f02004-01-24 18:18:54 +00001673 if (VG_CLO_STREQN(7, arg, "--tool=") ||
1674 VG_CLO_STREQN(7, arg, "--skin="))
fitzhardinge98abfc72003-12-16 02:05:15 +00001675 continue;
nethercote71980f02004-01-24 18:18:54 +00001676 if (VG_CLO_STREQN(7, arg, "--exec="))
fitzhardinge98abfc72003-12-16 02:05:15 +00001677 continue;
1678
nethercote71980f02004-01-24 18:18:54 +00001679 if ( VG_CLO_STREQ(arg, "--"))
fitzhardinge98abfc72003-12-16 02:05:15 +00001680 continue;
nethercote71980f02004-01-24 18:18:54 +00001681 else if (VG_CLO_STREQ(arg, "-v") ||
1682 VG_CLO_STREQ(arg, "--verbose"))
sewardjde4a1d02002-03-22 01:27:54 +00001683 VG_(clo_verbosity)++;
nethercote71980f02004-01-24 18:18:54 +00001684 else if (VG_CLO_STREQ(arg, "-q") ||
1685 VG_CLO_STREQ(arg, "--quiet"))
sewardjde4a1d02002-03-22 01:27:54 +00001686 VG_(clo_verbosity)--;
1687
nethercote71980f02004-01-24 18:18:54 +00001688 else if (VG_CLO_STREQ(arg, "--error-limit=yes"))
sewardj2e432902002-06-13 20:44:00 +00001689 VG_(clo_error_limit) = True;
nethercote71980f02004-01-24 18:18:54 +00001690 else if (VG_CLO_STREQ(arg, "--error-limit=no"))
sewardj2e432902002-06-13 20:44:00 +00001691 VG_(clo_error_limit) = False;
sewardj72f98ff2002-06-13 17:23:38 +00001692
nethercote04d0fbc2004-01-26 16:48:06 +00001693 else if (VG_CLO_STREQ(arg, "--db-attach=yes"))
1694 VG_(clo_db_attach) = True;
1695 else if (VG_CLO_STREQ(arg, "--db-attach=no"))
1696 VG_(clo_db_attach) = False;
sewardjde4a1d02002-03-22 01:27:54 +00001697
nethercote04d0fbc2004-01-26 16:48:06 +00001698 else if (VG_CLO_STREQN(13,arg, "--db-command="))
1699 VG_(clo_db_command) = &arg[13];
sewardj6024b212003-07-13 10:54:33 +00001700
nethercote71980f02004-01-24 18:18:54 +00001701 else if (VG_CLO_STREQ(arg, "--gen-suppressions=yes"))
njn43c799e2003-04-08 00:08:52 +00001702 VG_(clo_gen_suppressions) = True;
nethercote71980f02004-01-24 18:18:54 +00001703 else if (VG_CLO_STREQ(arg, "--gen-suppressions=no"))
njn43c799e2003-04-08 00:08:52 +00001704 VG_(clo_gen_suppressions) = False;
1705
nethercote71980f02004-01-24 18:18:54 +00001706 else if (VG_CLO_STREQ(arg, "--show-below-main=yes"))
nethercote77eba602003-11-13 17:35:04 +00001707 VG_(clo_show_below_main) = True;
nethercote71980f02004-01-24 18:18:54 +00001708 else if (VG_CLO_STREQ(arg, "--show-below-main=no"))
nethercote77eba602003-11-13 17:35:04 +00001709 VG_(clo_show_below_main) = False;
1710
nethercote71980f02004-01-24 18:18:54 +00001711 else if (VG_CLO_STREQ(arg, "--pointercheck=yes"))
fitzhardinge98abfc72003-12-16 02:05:15 +00001712 VG_(clo_pointercheck) = True;
nethercote71980f02004-01-24 18:18:54 +00001713 else if (VG_CLO_STREQ(arg, "--pointercheck=no"))
fitzhardinge98abfc72003-12-16 02:05:15 +00001714 VG_(clo_pointercheck) = False;
1715
nethercote71980f02004-01-24 18:18:54 +00001716 else if (VG_CLO_STREQ(arg, "--demangle=yes"))
sewardjde4a1d02002-03-22 01:27:54 +00001717 VG_(clo_demangle) = True;
nethercote71980f02004-01-24 18:18:54 +00001718 else if (VG_CLO_STREQ(arg, "--demangle=no"))
sewardjde4a1d02002-03-22 01:27:54 +00001719 VG_(clo_demangle) = False;
1720
nethercote71980f02004-01-24 18:18:54 +00001721 else if (VG_CLO_STREQ(arg, "--trace-children=yes"))
sewardjde4a1d02002-03-22 01:27:54 +00001722 VG_(clo_trace_children) = True;
nethercote71980f02004-01-24 18:18:54 +00001723 else if (VG_CLO_STREQ(arg, "--trace-children=no"))
sewardjde4a1d02002-03-22 01:27:54 +00001724 VG_(clo_trace_children) = False;
1725
nethercote71980f02004-01-24 18:18:54 +00001726 else if (VG_CLO_STREQ(arg, "--run-libc-freeres=yes"))
sewardj858964b2002-10-05 14:15:43 +00001727 VG_(clo_run_libc_freeres) = True;
nethercote71980f02004-01-24 18:18:54 +00001728 else if (VG_CLO_STREQ(arg, "--run-libc-freeres=no"))
sewardj858964b2002-10-05 14:15:43 +00001729 VG_(clo_run_libc_freeres) = False;
1730
nethercote71980f02004-01-24 18:18:54 +00001731 else if (VG_CLO_STREQ(arg, "--track-fds=yes"))
rjwalshf5f536f2003-11-17 17:45:00 +00001732 VG_(clo_track_fds) = True;
nethercote71980f02004-01-24 18:18:54 +00001733 else if (VG_CLO_STREQ(arg, "--track-fds=no"))
rjwalshf5f536f2003-11-17 17:45:00 +00001734 VG_(clo_track_fds) = False;
1735
nethercote71980f02004-01-24 18:18:54 +00001736 else if (VG_CLO_STREQN(15, arg, "--sanity-level="))
1737 VG_(sanity_level) = (Int)VG_(atoll)(&arg[15]);
sewardjde4a1d02002-03-22 01:27:54 +00001738
nethercote71980f02004-01-24 18:18:54 +00001739 else if (VG_CLO_STREQN(13, arg, "--logfile-fd=")) {
sewardj4cf05692002-10-27 20:28:29 +00001740 VG_(clo_log_to) = VgLogTo_Fd;
1741 VG_(clo_logfile_name) = NULL;
nethercote71980f02004-01-24 18:18:54 +00001742 eventually_logfile_fd = (Int)VG_(atoll)(&arg[13]);
sewardj4cf05692002-10-27 20:28:29 +00001743 }
1744
nethercote71980f02004-01-24 18:18:54 +00001745 else if (VG_CLO_STREQN(10, arg, "--logfile=")) {
sewardj4cf05692002-10-27 20:28:29 +00001746 VG_(clo_log_to) = VgLogTo_File;
nethercote71980f02004-01-24 18:18:54 +00001747 VG_(clo_logfile_name) = &arg[10];
sewardj4cf05692002-10-27 20:28:29 +00001748 }
sewardjde4a1d02002-03-22 01:27:54 +00001749
nethercote71980f02004-01-24 18:18:54 +00001750 else if (VG_CLO_STREQN(12, arg, "--logsocket=")) {
sewardj73cf3bc2002-11-03 03:20:15 +00001751 VG_(clo_log_to) = VgLogTo_Socket;
nethercote71980f02004-01-24 18:18:54 +00001752 VG_(clo_logfile_name) = &arg[12];
sewardj73cf3bc2002-11-03 03:20:15 +00001753 }
1754
nethercote71980f02004-01-24 18:18:54 +00001755 else if (VG_CLO_STREQN(11, arg, "--input-fd="))
1756 VG_(clo_input_fd) = (Int)VG_(atoll)(&arg[11]);
sewardj6024b212003-07-13 10:54:33 +00001757
nethercote71980f02004-01-24 18:18:54 +00001758 else if (VG_CLO_STREQN(15, arg, "--suppressions=")) {
sewardjde4a1d02002-03-22 01:27:54 +00001759 if (VG_(clo_n_suppressions) >= VG_CLO_MAX_SFILES) {
njn25e49d8e72002-09-23 09:36:25 +00001760 VG_(message)(Vg_UserMsg, "Too many suppression files specified.");
sewardjde4a1d02002-03-22 01:27:54 +00001761 VG_(message)(Vg_UserMsg,
1762 "Increase VG_CLO_MAX_SFILES and recompile.");
nethercote71980f02004-01-24 18:18:54 +00001763 VG_(bad_option)(arg);
sewardjde4a1d02002-03-22 01:27:54 +00001764 }
nethercote71980f02004-01-24 18:18:54 +00001765 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = &arg[15];
sewardjde4a1d02002-03-22 01:27:54 +00001766 VG_(clo_n_suppressions)++;
1767 }
nethercote71980f02004-01-24 18:18:54 +00001768 else if (VG_CLO_STREQ(arg, "--profile=yes"))
njn25e49d8e72002-09-23 09:36:25 +00001769 VG_(clo_profile) = True;
nethercote71980f02004-01-24 18:18:54 +00001770 else if (VG_CLO_STREQ(arg, "--profile=no"))
njn25e49d8e72002-09-23 09:36:25 +00001771 VG_(clo_profile) = False;
1772
nethercote71980f02004-01-24 18:18:54 +00001773 else if (VG_CLO_STREQ(arg, "--chain-bb=yes"))
sewardj22854b92002-11-30 14:00:47 +00001774 VG_(clo_chain_bb) = True;
nethercote71980f02004-01-24 18:18:54 +00001775 else if (VG_CLO_STREQ(arg, "--chain-bb=no"))
sewardj22854b92002-11-30 14:00:47 +00001776 VG_(clo_chain_bb) = False;
1777
nethercote71980f02004-01-24 18:18:54 +00001778 else if (VG_CLO_STREQ(arg, "--branchpred=yes"))
fitzhardinge462f4f92003-12-18 02:10:54 +00001779 VG_(clo_branchpred) = True;
nethercote71980f02004-01-24 18:18:54 +00001780 else if (VG_CLO_STREQ(arg, "--branchpred=no"))
fitzhardinge462f4f92003-12-18 02:10:54 +00001781 VG_(clo_branchpred) = False;
1782
nethercote71980f02004-01-24 18:18:54 +00001783 else if (VG_CLO_STREQ(arg, "--single-step=yes"))
sewardjde4a1d02002-03-22 01:27:54 +00001784 VG_(clo_single_step) = True;
nethercote71980f02004-01-24 18:18:54 +00001785 else if (VG_CLO_STREQ(arg, "--single-step=no"))
sewardjde4a1d02002-03-22 01:27:54 +00001786 VG_(clo_single_step) = False;
1787
nethercote71980f02004-01-24 18:18:54 +00001788 else if (VG_CLO_STREQ(arg, "--optimise=yes"))
sewardjde4a1d02002-03-22 01:27:54 +00001789 VG_(clo_optimise) = True;
nethercote71980f02004-01-24 18:18:54 +00001790 else if (VG_CLO_STREQ(arg, "--optimise=no"))
sewardjde4a1d02002-03-22 01:27:54 +00001791 VG_(clo_optimise) = False;
1792
njn25e49d8e72002-09-23 09:36:25 +00001793 /* "vwxyz" --> 000zyxwv (binary) */
nethercote71980f02004-01-24 18:18:54 +00001794 else if (VG_CLO_STREQN(16, arg, "--trace-codegen=")) {
njn25e49d8e72002-09-23 09:36:25 +00001795 Int j;
nethercote71980f02004-01-24 18:18:54 +00001796 char* opt = & arg[16];
njn25e49d8e72002-09-23 09:36:25 +00001797
1798 if (5 != VG_(strlen)(opt)) {
1799 VG_(message)(Vg_UserMsg,
1800 "--trace-codegen argument must have 5 digits");
nethercote71980f02004-01-24 18:18:54 +00001801 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001802 }
1803 for (j = 0; j < 5; j++) {
1804 if ('0' == opt[j]) { /* do nothing */ }
1805 else if ('1' == opt[j]) VG_(clo_trace_codegen) |= (1 << j);
1806 else {
1807 VG_(message)(Vg_UserMsg, "--trace-codegen argument can only "
1808 "contain 0s and 1s");
nethercote71980f02004-01-24 18:18:54 +00001809 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001810 }
1811 }
1812 }
sewardjde4a1d02002-03-22 01:27:54 +00001813
nethercote71980f02004-01-24 18:18:54 +00001814 else if (VG_CLO_STREQ(arg, "--trace-syscalls=yes"))
sewardjde4a1d02002-03-22 01:27:54 +00001815 VG_(clo_trace_syscalls) = True;
nethercote71980f02004-01-24 18:18:54 +00001816 else if (VG_CLO_STREQ(arg, "--trace-syscalls=no"))
sewardjde4a1d02002-03-22 01:27:54 +00001817 VG_(clo_trace_syscalls) = False;
1818
nethercote71980f02004-01-24 18:18:54 +00001819 else if (VG_CLO_STREQ(arg, "--trace-signals=yes"))
sewardjde4a1d02002-03-22 01:27:54 +00001820 VG_(clo_trace_signals) = True;
nethercote71980f02004-01-24 18:18:54 +00001821 else if (VG_CLO_STREQ(arg, "--trace-signals=no"))
sewardjde4a1d02002-03-22 01:27:54 +00001822 VG_(clo_trace_signals) = False;
1823
nethercote71980f02004-01-24 18:18:54 +00001824 else if (VG_CLO_STREQ(arg, "--trace-symtab=yes"))
sewardjde4a1d02002-03-22 01:27:54 +00001825 VG_(clo_trace_symtab) = True;
nethercote71980f02004-01-24 18:18:54 +00001826 else if (VG_CLO_STREQ(arg, "--trace-symtab=no"))
sewardjde4a1d02002-03-22 01:27:54 +00001827 VG_(clo_trace_symtab) = False;
1828
nethercote71980f02004-01-24 18:18:54 +00001829 else if (VG_CLO_STREQ(arg, "--trace-sched=yes"))
sewardj8937c812002-04-12 20:12:20 +00001830 VG_(clo_trace_sched) = True;
nethercote71980f02004-01-24 18:18:54 +00001831 else if (VG_CLO_STREQ(arg, "--trace-sched=no"))
sewardj8937c812002-04-12 20:12:20 +00001832 VG_(clo_trace_sched) = False;
1833
nethercote71980f02004-01-24 18:18:54 +00001834 else if (VG_CLO_STREQ(arg, "--trace-pthread=none"))
sewardj45b4b372002-04-16 22:50:32 +00001835 VG_(clo_trace_pthread_level) = 0;
nethercote71980f02004-01-24 18:18:54 +00001836 else if (VG_CLO_STREQ(arg, "--trace-pthread=some"))
sewardj45b4b372002-04-16 22:50:32 +00001837 VG_(clo_trace_pthread_level) = 1;
nethercote71980f02004-01-24 18:18:54 +00001838 else if (VG_CLO_STREQ(arg, "--trace-pthread=all"))
sewardj45b4b372002-04-16 22:50:32 +00001839 VG_(clo_trace_pthread_level) = 2;
sewardj8937c812002-04-12 20:12:20 +00001840
nethercote71980f02004-01-24 18:18:54 +00001841 else if (VG_CLO_STREQN(14, arg, "--weird-hacks="))
1842 VG_(clo_weird_hacks) = &arg[14];
sewardj3984b852002-05-12 03:00:17 +00001843
nethercote71980f02004-01-24 18:18:54 +00001844 else if (VG_CLO_STREQN(17, arg, "--signal-polltime="))
1845 VG_(clo_signal_polltime) = VG_(atoll)(&arg[17]);
jsgf855d93d2003-10-13 22:26:55 +00001846
nethercote71980f02004-01-24 18:18:54 +00001847 else if (VG_CLO_STREQ(arg, "--lowlat-signals=yes"))
jsgf855d93d2003-10-13 22:26:55 +00001848 VG_(clo_lowlat_signals) = True;
nethercote71980f02004-01-24 18:18:54 +00001849 else if (VG_CLO_STREQ(arg, "--lowlat-signals=no"))
jsgf855d93d2003-10-13 22:26:55 +00001850 VG_(clo_lowlat_signals) = False;
1851
nethercote71980f02004-01-24 18:18:54 +00001852 else if (VG_CLO_STREQ(arg, "--lowlat-syscalls=yes"))
jsgf855d93d2003-10-13 22:26:55 +00001853 VG_(clo_lowlat_syscalls) = True;
nethercote71980f02004-01-24 18:18:54 +00001854 else if (VG_CLO_STREQ(arg, "--lowlat-syscalls=no"))
jsgf855d93d2003-10-13 22:26:55 +00001855 VG_(clo_lowlat_syscalls) = False;
1856
nethercote71980f02004-01-24 18:18:54 +00001857 else if (VG_CLO_STREQN(13, arg, "--stop-after="))
1858 VG_(clo_stop_after) = VG_(atoll)(&arg[13]);
sewardjde4a1d02002-03-22 01:27:54 +00001859
nethercote71980f02004-01-24 18:18:54 +00001860 else if (VG_CLO_STREQN(13, arg, "--dump-error="))
1861 VG_(clo_dump_error) = (Int)VG_(atoll)(&arg[13]);
sewardjde4a1d02002-03-22 01:27:54 +00001862
nethercote71980f02004-01-24 18:18:54 +00001863 else if (VG_CLO_STREQ(arg, "--wait-for-gdb=yes"))
jsgf855d93d2003-10-13 22:26:55 +00001864 VG_(clo_wait_for_gdb) = True;
nethercote71980f02004-01-24 18:18:54 +00001865 else if (VG_CLO_STREQ(arg, "--wait-for-gdb=no"))
jsgf855d93d2003-10-13 22:26:55 +00001866 VG_(clo_wait_for_gdb) = False;
1867
nethercote71980f02004-01-24 18:18:54 +00001868 else if (VG_CLO_STREQN(14, arg, "--num-callers=")) {
sewardjde4a1d02002-03-22 01:27:54 +00001869 /* Make sure it's sane. */
nethercote71980f02004-01-24 18:18:54 +00001870 VG_(clo_backtrace_size) = (Int)VG_(atoll)(&arg[14]);
njn6c846552003-09-16 07:41:43 +00001871 if (VG_(clo_backtrace_size) < 1)
1872 VG_(clo_backtrace_size) = 1;
sewardjde4a1d02002-03-22 01:27:54 +00001873 if (VG_(clo_backtrace_size) >= VG_DEEPEST_BACKTRACE)
1874 VG_(clo_backtrace_size) = VG_DEEPEST_BACKTRACE;
1875 }
1876
nethercote71980f02004-01-24 18:18:54 +00001877 else if ( ! VG_(needs).command_line_options
1878 || ! SK_(process_cmd_line_option)(arg) ) {
1879 usage();
njn25e49d8e72002-09-23 09:36:25 +00001880 }
sewardjde4a1d02002-03-22 01:27:54 +00001881 }
1882
njnf9ebf672003-05-12 21:41:30 +00001883 if (VG_(clo_verbosity) < 0)
sewardjde4a1d02002-03-22 01:27:54 +00001884 VG_(clo_verbosity) = 0;
1885
nethercote04d0fbc2004-01-26 16:48:06 +00001886 if (VG_(clo_db_attach) && VG_(clo_trace_children)) {
sewardjde4a1d02002-03-22 01:27:54 +00001887 VG_(message)(Vg_UserMsg, "");
1888 VG_(message)(Vg_UserMsg,
nethercote04d0fbc2004-01-26 16:48:06 +00001889 "--db-attach=yes conflicts with --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001890 VG_(message)(Vg_UserMsg,
1891 "Please choose one or the other, but not both.");
nethercote04d0fbc2004-01-26 16:48:06 +00001892 VG_(bad_option)("--db-attach=yes and --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001893 }
1894
sewardj4cf05692002-10-27 20:28:29 +00001895 /* Set up logging now. After this is done, VG_(clo_logfile_fd)
1896 should be connected to whatever sink has been selected, and we
1897 indiscriminately chuck stuff into it without worrying what the
1898 nature of it is. Oh the wonder of Unix streams. */
1899
nethercotee1730692003-11-20 10:38:07 +00001900 /* So far we should be still attached to stdout, so we can show on
sewardj4cf05692002-10-27 20:28:29 +00001901 the terminal any problems to do with processing command line
1902 opts. */
nethercotee1730692003-11-20 10:38:07 +00001903 vg_assert(VG_(clo_logfile_fd) == 1 /* stdout */);
sewardj73cf3bc2002-11-03 03:20:15 +00001904 vg_assert(VG_(logging_to_filedes) == True);
sewardj4cf05692002-10-27 20:28:29 +00001905
1906 switch (VG_(clo_log_to)) {
sewardj73cf3bc2002-11-03 03:20:15 +00001907
sewardj4cf05692002-10-27 20:28:29 +00001908 case VgLogTo_Fd:
1909 vg_assert(VG_(clo_logfile_name) == NULL);
1910 VG_(clo_logfile_fd) = eventually_logfile_fd;
1911 break;
sewardj73cf3bc2002-11-03 03:20:15 +00001912
sewardj4cf05692002-10-27 20:28:29 +00001913 case VgLogTo_File: {
1914 Char logfilename[1000];
jsgff3c3f1a2003-10-14 22:13:28 +00001915 Int seq = 0;
1916 Int pid = VG_(getpid)();
1917
sewardj4cf05692002-10-27 20:28:29 +00001918 vg_assert(VG_(clo_logfile_name) != NULL);
1919 vg_assert(VG_(strlen)(VG_(clo_logfile_name)) <= 900); /* paranoia */
jsgff3c3f1a2003-10-14 22:13:28 +00001920
nethercote71980f02004-01-24 18:18:54 +00001921 for (;;) {
jsgff3c3f1a2003-10-14 22:13:28 +00001922 if (seq == 0)
1923 VG_(sprintf)(logfilename, "%s.pid%d",
1924 VG_(clo_logfile_name), pid );
1925 else
1926 VG_(sprintf)(logfilename, "%s.pid%d.%d",
1927 VG_(clo_logfile_name), pid, seq );
1928 seq++;
1929
1930 eventually_logfile_fd
1931 = VG_(open)(logfilename,
1932 VKI_O_CREAT|VKI_O_WRONLY|VKI_O_EXCL|VKI_O_TRUNC,
1933 VKI_S_IRUSR|VKI_S_IWUSR);
1934 if (eventually_logfile_fd >= 0) {
fitzhardinge9b8c2f32004-01-06 00:15:26 +00001935 VG_(clo_logfile_fd) = VG_(safe_fd)(eventually_logfile_fd);
jsgff3c3f1a2003-10-14 22:13:28 +00001936 break;
1937 } else {
1938 if (eventually_logfile_fd != -VKI_EEXIST) {
1939 VG_(message)(Vg_UserMsg,
1940 "Can't create/open log file `%s.pid%d'; giving up!",
1941 VG_(clo_logfile_name), pid);
1942 VG_(bad_option)(
1943 "--logfile=<file> didn't work out for some reason.");
1944 break;
1945 }
1946 }
1947 }
sewardj4cf05692002-10-27 20:28:29 +00001948 break;
sewardj73cf3bc2002-11-03 03:20:15 +00001949 }
1950
1951 case VgLogTo_Socket: {
1952 vg_assert(VG_(clo_logfile_name) != NULL);
1953 vg_assert(VG_(strlen)(VG_(clo_logfile_name)) <= 900); /* paranoia */
1954 eventually_logfile_fd
1955 = VG_(connect_via_socket)( VG_(clo_logfile_name) );
1956 if (eventually_logfile_fd == -1) {
1957 VG_(message)(Vg_UserMsg,
1958 "Invalid --logsocket=ipaddr or --logsocket=ipaddr:port spec");
1959 VG_(message)(Vg_UserMsg,
1960 "of `%s'; giving up!", VG_(clo_logfile_name) );
1961 VG_(bad_option)(
1962 "--logsocket=");
sewardj4cf05692002-10-27 20:28:29 +00001963 }
sewardj73cf3bc2002-11-03 03:20:15 +00001964 if (eventually_logfile_fd == -2) {
1965 VG_(message)(Vg_UserMsg,
sewardj570f8902002-11-03 11:44:36 +00001966 "valgrind: failed to connect to logging server `%s'.",
sewardj73cf3bc2002-11-03 03:20:15 +00001967 VG_(clo_logfile_name) );
sewardj570f8902002-11-03 11:44:36 +00001968 VG_(message)(Vg_UserMsg,
1969 "Log messages will sent to stderr instead." );
1970 VG_(message)(Vg_UserMsg,
1971 "" );
1972 /* We don't change anything here. */
1973 } else {
1974 vg_assert(eventually_logfile_fd > 0);
1975 VG_(clo_logfile_fd) = eventually_logfile_fd;
1976 VG_(logging_to_filedes) = False;
1977 }
sewardj73cf3bc2002-11-03 03:20:15 +00001978 break;
1979 }
1980
sewardj4cf05692002-10-27 20:28:29 +00001981 }
1982
jsgf855d93d2003-10-13 22:26:55 +00001983 /* Move logfile_fd into the safe range, so it doesn't conflict with any app fds */
fitzhardingef0046f22003-12-18 02:39:22 +00001984 eventually_logfile_fd = VG_(fcntl)(VG_(clo_logfile_fd), VKI_F_DUPFD, VG_(max_fd)+1);
jsgf855d93d2003-10-13 22:26:55 +00001985 if (eventually_logfile_fd < 0)
1986 VG_(message)(Vg_UserMsg, "valgrind: failed to move logfile fd into safe range");
1987 else {
1988 VG_(clo_logfile_fd) = eventually_logfile_fd;
1989 VG_(fcntl)(VG_(clo_logfile_fd), VKI_F_SETFD, VKI_FD_CLOEXEC);
1990 }
1991
sewardj4cf05692002-10-27 20:28:29 +00001992 /* Ok, the logging sink is running now. Print a suitable preamble.
1993 If logging to file or a socket, write details of parent PID and
1994 command line args, to help people trying to interpret the
1995 results of a run which encompasses multiple processes. */
sewardjde4a1d02002-03-22 01:27:54 +00001996
sewardj83adf412002-05-01 01:25:45 +00001997 if (VG_(clo_verbosity > 0)) {
njnd04b7c62002-10-03 14:05:52 +00001998 /* Skin details */
1999 VG_(message)(Vg_UserMsg, "%s%s%s, %s for x86-linux.",
2000 VG_(details).name,
2001 NULL == VG_(details).version ? "" : "-",
2002 NULL == VG_(details).version
2003 ? (Char*)"" : VG_(details).version,
2004 VG_(details).description);
2005 VG_(message)(Vg_UserMsg, "%s", VG_(details).copyright_author);
sewardj3b2736a2002-03-24 12:18:35 +00002006
njnd04b7c62002-10-03 14:05:52 +00002007 /* Core details */
2008 VG_(message)(Vg_UserMsg,
njn3e884182003-04-15 13:03:23 +00002009 "Using valgrind-%s, a program supervision framework for x86-linux.",
sewardj4aa62ba2002-10-05 15:49:27 +00002010 VERSION);
sewardjde4a1d02002-03-22 01:27:54 +00002011 VG_(message)(Vg_UserMsg,
nethercotebb1c9912004-01-04 16:43:23 +00002012 "Copyright (C) 2000-2004, and GNU GPL'd, by Julian Seward.");
njnd04b7c62002-10-03 14:05:52 +00002013 }
2014
nethercotec1e395d2003-11-10 13:26:49 +00002015 if (VG_(clo_verbosity) > 0 && VG_(clo_log_to) != VgLogTo_Fd) {
sewardj4cf05692002-10-27 20:28:29 +00002016 VG_(message)(Vg_UserMsg, "");
2017 VG_(message)(Vg_UserMsg,
2018 "My PID = %d, parent PID = %d. Prog and args are:",
2019 VG_(getpid)(), VG_(getppid)() );
2020 for (i = 0; i < VG_(client_argc); i++)
2021 VG_(message)(Vg_UserMsg, " %s", VG_(client_argv)[i]);
2022 }
2023
sewardjde4a1d02002-03-22 01:27:54 +00002024 if (VG_(clo_verbosity) > 1) {
sewardj4cf05692002-10-27 20:28:29 +00002025 if (VG_(clo_log_to) != VgLogTo_Fd)
2026 VG_(message)(Vg_UserMsg, "");
fitzhardinge98abfc72003-12-16 02:05:15 +00002027 VG_(message)(Vg_UserMsg, "Valgrind library directory: %s", VG_(libdir));
njn86dc2bc2003-09-09 07:26:21 +00002028 VG_(message)(Vg_UserMsg, "Command line");
2029 for (i = 0; i < VG_(client_argc); i++)
2030 VG_(message)(Vg_UserMsg, " %s", VG_(client_argv)[i]);
2031
sewardjde4a1d02002-03-22 01:27:54 +00002032 VG_(message)(Vg_UserMsg, "Startup, with flags:");
nethercote71980f02004-01-24 18:18:54 +00002033 for (i = 1; i < VG_(vg_argc); i++) {
2034 VG_(message)(Vg_UserMsg, " %s", VG_(vg_argv)[i]);
sewardjde4a1d02002-03-22 01:27:54 +00002035 }
2036 }
2037
fitzhardinge98abfc72003-12-16 02:05:15 +00002038 if (VG_(clo_n_suppressions) < VG_CLO_MAX_SFILES-1 &&
njn25e49d8e72002-09-23 09:36:25 +00002039 (VG_(needs).core_errors || VG_(needs).skin_errors)) {
fitzhardinge98abfc72003-12-16 02:05:15 +00002040 /* If there are no suppression files specified and the skin
2041 needs one, load the default */
2042 static const Char default_supp[] = "default.supp";
2043 Int len = VG_(strlen)(VG_(libdir)) + 1 + sizeof(default_supp);
2044 Char *buf = VG_(arena_malloc)(VG_AR_CORE, len);
2045 VG_(sprintf)(buf, "%s/%s", VG_(libdir), default_supp);
2046 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = buf;
2047 VG_(clo_n_suppressions)++;
sewardjde4a1d02002-03-22 01:27:54 +00002048 }
sewardj4cf05692002-10-27 20:28:29 +00002049
njn6a230532003-07-21 10:38:23 +00002050 if (VG_(clo_gen_suppressions) &&
2051 !VG_(needs).core_errors && !VG_(needs).skin_errors) {
2052 config_error("Can't use --gen-suppressions=yes with this skin,\n"
2053 " as it doesn't generate errors.");
2054 }
2055
nethercote71980f02004-01-24 18:18:54 +00002056 VG_(bbs_to_go) = VG_(clo_stop_after);
sewardjde4a1d02002-03-22 01:27:54 +00002057}
2058
sewardjde4a1d02002-03-22 01:27:54 +00002059
nethercote71980f02004-01-24 18:18:54 +00002060/*====================================================================*/
2061/*=== File descriptor setup ===*/
2062/*====================================================================*/
2063
2064static void setup_file_descriptors(void)
2065{
2066 struct vki_rlimit rl;
2067
2068 /* Get the current file descriptor limits. */
2069 if (VG_(getrlimit)(VKI_RLIMIT_NOFILE, &rl) < 0) {
2070 rl.rlim_cur = 1024;
2071 rl.rlim_max = 1024;
2072 }
2073
2074 /* Work out where to move the soft limit to. */
2075 if (rl.rlim_cur + VG_N_RESERVED_FDS <= rl.rlim_max) {
2076 rl.rlim_cur = rl.rlim_cur + VG_N_RESERVED_FDS;
2077 } else {
2078 rl.rlim_cur = rl.rlim_max;
2079 }
2080
2081 /* Reserve some file descriptors for our use. */
2082 VG_(max_fd) = rl.rlim_cur - VG_N_RESERVED_FDS;
2083
2084 /* Update the soft limit. */
2085 VG_(setrlimit)(VKI_RLIMIT_NOFILE, &rl);
2086
2087 if (VG_(vgexecfd) != -1)
2088 VG_(vgexecfd) = VG_(safe_fd)( VG_(vgexecfd) );
2089 if (VG_(clexecfd) != -1)
2090 VG_(clexecfd) = VG_(safe_fd)( VG_(clexecfd) );
2091}
2092
2093
2094/*====================================================================*/
2095/*=== m_state_static + baseBlock: definition, setup, copying ===*/
2096/*====================================================================*/
2097
2098/* The variables storing offsets. */
2099
2100#define INVALID_OFFSET (-1)
2101
2102Int VGOFF_(m_eax) = INVALID_OFFSET;
2103Int VGOFF_(m_ecx) = INVALID_OFFSET;
2104Int VGOFF_(m_edx) = INVALID_OFFSET;
2105Int VGOFF_(m_ebx) = INVALID_OFFSET;
2106Int VGOFF_(m_esp) = INVALID_OFFSET;
2107Int VGOFF_(m_ebp) = INVALID_OFFSET;
2108Int VGOFF_(m_esi) = INVALID_OFFSET;
2109Int VGOFF_(m_edi) = INVALID_OFFSET;
2110Int VGOFF_(m_eflags) = INVALID_OFFSET;
2111Int VGOFF_(m_dflag) = INVALID_OFFSET;
2112Int VGOFF_(m_ssestate) = INVALID_OFFSET;
2113Int VGOFF_(ldt) = INVALID_OFFSET;
2114Int VGOFF_(tls) = INVALID_OFFSET;
2115Int VGOFF_(m_cs) = INVALID_OFFSET;
2116Int VGOFF_(m_ss) = INVALID_OFFSET;
2117Int VGOFF_(m_ds) = INVALID_OFFSET;
2118Int VGOFF_(m_es) = INVALID_OFFSET;
2119Int VGOFF_(m_fs) = INVALID_OFFSET;
2120Int VGOFF_(m_gs) = INVALID_OFFSET;
2121Int VGOFF_(m_eip) = INVALID_OFFSET;
2122Int VGOFF_(spillslots) = INVALID_OFFSET;
2123Int VGOFF_(sh_eax) = INVALID_OFFSET;
2124Int VGOFF_(sh_ecx) = INVALID_OFFSET;
2125Int VGOFF_(sh_edx) = INVALID_OFFSET;
2126Int VGOFF_(sh_ebx) = INVALID_OFFSET;
2127Int VGOFF_(sh_esp) = INVALID_OFFSET;
2128Int VGOFF_(sh_ebp) = INVALID_OFFSET;
2129Int VGOFF_(sh_esi) = INVALID_OFFSET;
2130Int VGOFF_(sh_edi) = INVALID_OFFSET;
2131Int VGOFF_(sh_eflags) = INVALID_OFFSET;
2132
2133Int VGOFF_(helper_idiv_64_32) = INVALID_OFFSET;
2134Int VGOFF_(helper_div_64_32) = INVALID_OFFSET;
2135Int VGOFF_(helper_idiv_32_16) = INVALID_OFFSET;
2136Int VGOFF_(helper_div_32_16) = INVALID_OFFSET;
2137Int VGOFF_(helper_idiv_16_8) = INVALID_OFFSET;
2138Int VGOFF_(helper_div_16_8) = INVALID_OFFSET;
2139Int VGOFF_(helper_imul_32_64) = INVALID_OFFSET;
2140Int VGOFF_(helper_mul_32_64) = INVALID_OFFSET;
2141Int VGOFF_(helper_imul_16_32) = INVALID_OFFSET;
2142Int VGOFF_(helper_mul_16_32) = INVALID_OFFSET;
2143Int VGOFF_(helper_imul_8_16) = INVALID_OFFSET;
2144Int VGOFF_(helper_mul_8_16) = INVALID_OFFSET;
2145Int VGOFF_(helper_CLD) = INVALID_OFFSET;
2146Int VGOFF_(helper_STD) = INVALID_OFFSET;
2147Int VGOFF_(helper_get_dirflag) = INVALID_OFFSET;
2148Int VGOFF_(helper_CLC) = INVALID_OFFSET;
2149Int VGOFF_(helper_STC) = INVALID_OFFSET;
2150Int VGOFF_(helper_shldl) = INVALID_OFFSET;
2151Int VGOFF_(helper_shldw) = INVALID_OFFSET;
2152Int VGOFF_(helper_shrdl) = INVALID_OFFSET;
2153Int VGOFF_(helper_shrdw) = INVALID_OFFSET;
2154Int VGOFF_(helper_IN) = INVALID_OFFSET;
2155Int VGOFF_(helper_OUT) = INVALID_OFFSET;
2156Int VGOFF_(helper_RDTSC) = INVALID_OFFSET;
2157Int VGOFF_(helper_CPUID) = INVALID_OFFSET;
2158Int VGOFF_(helper_BSWAP) = INVALID_OFFSET;
2159Int VGOFF_(helper_bsf) = INVALID_OFFSET;
2160Int VGOFF_(helper_bsr) = INVALID_OFFSET;
2161Int VGOFF_(helper_fstsw_AX) = INVALID_OFFSET;
2162Int VGOFF_(helper_SAHF) = INVALID_OFFSET;
2163Int VGOFF_(helper_LAHF) = INVALID_OFFSET;
2164Int VGOFF_(helper_DAS) = INVALID_OFFSET;
2165Int VGOFF_(helper_DAA) = INVALID_OFFSET;
2166Int VGOFF_(helper_cmpxchg8b) = INVALID_OFFSET;
2167Int VGOFF_(helper_undefined_instruction) = INVALID_OFFSET;
2168
2169/* MAX_NONCOMPACT_HELPERS can be increased easily. If MAX_COMPACT_HELPERS is
2170 * increased too much, they won't really be compact any more... */
2171#define MAX_COMPACT_HELPERS 8
2172#define MAX_NONCOMPACT_HELPERS 50
2173
2174UInt VG_(n_compact_helpers) = 0;
2175UInt VG_(n_noncompact_helpers) = 0;
2176
2177Addr VG_(compact_helper_addrs) [MAX_COMPACT_HELPERS];
2178Int VG_(compact_helper_offsets)[MAX_COMPACT_HELPERS];
2179Addr VG_(noncompact_helper_addrs) [MAX_NONCOMPACT_HELPERS];
2180Int VG_(noncompact_helper_offsets)[MAX_NONCOMPACT_HELPERS];
2181
2182/* This is the actual defn of baseblock. */
2183UInt VG_(baseBlock)[VG_BASEBLOCK_WORDS];
2184
2185/* See comment about this in vg_include.h. Change only with great care. */
sewardjb91ae7f2003-04-29 23:50:00 +00002186__attribute__ ((aligned (16)))
sewardj92a59562002-09-30 00:53:10 +00002187UInt VG_(m_state_static) [6 /* segment regs, Intel order */
2188 + 8 /* int regs, in Intel order */
sewardjde4a1d02002-03-22 01:27:54 +00002189 + 1 /* %eflags */
2190 + 1 /* %eip */
sewardjb91ae7f2003-04-29 23:50:00 +00002191 + VG_SIZE_OF_SSESTATE_W /* FPU state */
sewardjde4a1d02002-03-22 01:27:54 +00002192 ];
2193
nethercote71980f02004-01-24 18:18:54 +00002194/* Words. */
2195static Int baB_off = 0;
2196
2197
sewardjfa492d42002-12-08 18:20:01 +00002198UInt VG_(insertDflag)(UInt eflags, Int d)
2199{
2200 vg_assert(d == 1 || d == -1);
2201 eflags &= ~EFlagD;
2202
2203 if (d < 0)
2204 eflags |= EFlagD;
2205
2206 return eflags;
2207}
2208
2209Int VG_(extractDflag)(UInt eflags)
2210{
2211 Int ret;
2212
2213 if (eflags & EFlagD)
2214 ret = -1;
2215 else
2216 ret = 1;
2217
2218 return ret;
2219}
2220
nethercote71980f02004-01-24 18:18:54 +00002221static void copy_baseBlock_to_m_state_static( void )
sewardjde4a1d02002-03-22 01:27:54 +00002222{
2223 Int i;
sewardj92a59562002-09-30 00:53:10 +00002224 VG_(m_state_static)[ 0/4] = VG_(baseBlock)[VGOFF_(m_cs)];
2225 VG_(m_state_static)[ 4/4] = VG_(baseBlock)[VGOFF_(m_ss)];
2226 VG_(m_state_static)[ 8/4] = VG_(baseBlock)[VGOFF_(m_ds)];
2227 VG_(m_state_static)[12/4] = VG_(baseBlock)[VGOFF_(m_es)];
2228 VG_(m_state_static)[16/4] = VG_(baseBlock)[VGOFF_(m_fs)];
2229 VG_(m_state_static)[20/4] = VG_(baseBlock)[VGOFF_(m_gs)];
sewardjde4a1d02002-03-22 01:27:54 +00002230
sewardj92a59562002-09-30 00:53:10 +00002231 VG_(m_state_static)[24/4] = VG_(baseBlock)[VGOFF_(m_eax)];
2232 VG_(m_state_static)[28/4] = VG_(baseBlock)[VGOFF_(m_ecx)];
2233 VG_(m_state_static)[32/4] = VG_(baseBlock)[VGOFF_(m_edx)];
2234 VG_(m_state_static)[36/4] = VG_(baseBlock)[VGOFF_(m_ebx)];
2235 VG_(m_state_static)[40/4] = VG_(baseBlock)[VGOFF_(m_esp)];
2236 VG_(m_state_static)[44/4] = VG_(baseBlock)[VGOFF_(m_ebp)];
2237 VG_(m_state_static)[48/4] = VG_(baseBlock)[VGOFF_(m_esi)];
2238 VG_(m_state_static)[52/4] = VG_(baseBlock)[VGOFF_(m_edi)];
2239
sewardjb91ae7f2003-04-29 23:50:00 +00002240 VG_(m_state_static)[56/4]
2241 = VG_(insertDflag)(VG_(baseBlock)[VGOFF_(m_eflags)],
2242 VG_(baseBlock)[VGOFF_(m_dflag)]);
sewardj92a59562002-09-30 00:53:10 +00002243 VG_(m_state_static)[60/4] = VG_(baseBlock)[VGOFF_(m_eip)];
sewardjde4a1d02002-03-22 01:27:54 +00002244
sewardjb91ae7f2003-04-29 23:50:00 +00002245 for (i = 0; i < VG_SIZE_OF_SSESTATE_W; i++)
sewardj92a59562002-09-30 00:53:10 +00002246 VG_(m_state_static)[64/4 + i]
sewardjb91ae7f2003-04-29 23:50:00 +00002247 = VG_(baseBlock)[VGOFF_(m_ssestate) + i];
sewardjde4a1d02002-03-22 01:27:54 +00002248}
2249
2250
nethercote71980f02004-01-24 18:18:54 +00002251/* Returns the offset, in words. */
2252static Int alloc_BaB ( Int words )
sewardjde4a1d02002-03-22 01:27:54 +00002253{
nethercote71980f02004-01-24 18:18:54 +00002254 Int off = baB_off;
2255 baB_off += words;
2256 if (baB_off >= VG_BASEBLOCK_WORDS)
2257 VG_(core_panic)( "alloc_BaB: baseBlock is too small");
sewardjde4a1d02002-03-22 01:27:54 +00002258
nethercote71980f02004-01-24 18:18:54 +00002259 return off;
sewardjde4a1d02002-03-22 01:27:54 +00002260}
2261
nethercote71980f02004-01-24 18:18:54 +00002262/* Align offset, in *bytes* */
2263static void align_BaB ( UInt align )
njn25e49d8e72002-09-23 09:36:25 +00002264{
nethercote71980f02004-01-24 18:18:54 +00002265 vg_assert(2 == align || 4 == align || 8 == align || 16 == align);
2266 baB_off += (align-1);
2267 baB_off &= ~(align-1);
njn25e49d8e72002-09-23 09:36:25 +00002268}
2269
nethercote71980f02004-01-24 18:18:54 +00002270/* Allocate 1 word in baseBlock and set it to the given value. */
2271static Int alloc_BaB_1_set ( Addr a )
njn25e49d8e72002-09-23 09:36:25 +00002272{
nethercote71980f02004-01-24 18:18:54 +00002273 Int off = alloc_BaB(1);
2274 VG_(baseBlock)[off] = (UInt)a;
2275 return off;
njn25e49d8e72002-09-23 09:36:25 +00002276}
2277
nethercote71980f02004-01-24 18:18:54 +00002278/* Registers a function in compact_helper_addrs; compact_helper_offsets is
2279 filled in later. */
2280void VG_(register_compact_helper)(Addr a)
sewardjde4a1d02002-03-22 01:27:54 +00002281{
nethercote71980f02004-01-24 18:18:54 +00002282 if (MAX_COMPACT_HELPERS <= VG_(n_compact_helpers)) {
2283 VG_(printf)("Can only register %d compact helpers\n",
2284 MAX_COMPACT_HELPERS);
2285 VG_(core_panic)("Too many compact helpers registered");
2286 }
2287 VG_(compact_helper_addrs)[VG_(n_compact_helpers)] = a;
2288 VG_(n_compact_helpers)++;
2289}
2290
2291/* Registers a function in noncompact_helper_addrs; noncompact_helper_offsets
2292 * is filled in later.
2293 */
2294void VG_(register_noncompact_helper)(Addr a)
2295{
2296 if (MAX_NONCOMPACT_HELPERS <= VG_(n_noncompact_helpers)) {
2297 VG_(printf)("Can only register %d non-compact helpers\n",
2298 MAX_NONCOMPACT_HELPERS);
2299 VG_(printf)("Try increasing MAX_NON_COMPACT_HELPERS\n");
2300 VG_(core_panic)("Too many non-compact helpers registered");
2301 }
2302 VG_(noncompact_helper_addrs)[VG_(n_noncompact_helpers)] = a;
2303 VG_(n_noncompact_helpers)++;
2304}
2305
2306/* Allocate offsets in baseBlock for the skin helpers */
2307static
2308void assign_helpers_in_baseBlock(UInt n, Int offsets[], Addr addrs[])
2309{
2310 UInt i;
2311 for (i = 0; i < n; i++)
2312 offsets[i] = alloc_BaB_1_set( addrs[i] );
2313}
2314
2315Bool VG_(need_to_handle_esp_assignment)(void)
2316{
2317 return ( VG_(defined_new_mem_stack_4)() ||
2318 VG_(defined_die_mem_stack_4)() ||
2319 VG_(defined_new_mem_stack_8)() ||
2320 VG_(defined_die_mem_stack_8)() ||
2321 VG_(defined_new_mem_stack_12)() ||
2322 VG_(defined_die_mem_stack_12)() ||
2323 VG_(defined_new_mem_stack_16)() ||
2324 VG_(defined_die_mem_stack_16)() ||
2325 VG_(defined_new_mem_stack_32)() ||
2326 VG_(defined_die_mem_stack_32)() ||
2327 VG_(defined_new_mem_stack)() ||
2328 VG_(defined_die_mem_stack)()
2329 );
2330}
2331
2332/* Here we assign actual offsets. It's important to get the most
2333 popular referents within 128 bytes of the start, so we can take
2334 advantage of short addressing modes relative to %ebp. Popularity
2335 of offsets was measured on 22 Feb 02 running a KDE application, and
2336 the slots rearranged accordingly, with a 1.5% reduction in total
2337 size of translations. */
2338static void init_baseBlock ( Addr client_eip, Addr esp_at_startup )
2339{
2340 /* Those with offsets under 128 are carefully chosen. */
2341
2342 /* WORD offsets in this column */
2343 /* 0 */ VGOFF_(m_eax) = alloc_BaB_1_set(0);
2344 /* 1 */ VGOFF_(m_ecx) = alloc_BaB_1_set(0);
2345 /* 2 */ VGOFF_(m_edx) = alloc_BaB_1_set(0);
2346 /* 3 */ VGOFF_(m_ebx) = alloc_BaB_1_set(0);
2347 /* 4 */ VGOFF_(m_esp) = alloc_BaB_1_set(esp_at_startup);
2348 /* 5 */ VGOFF_(m_ebp) = alloc_BaB_1_set(0);
2349 /* 6 */ VGOFF_(m_esi) = alloc_BaB_1_set(0);
2350 /* 7 */ VGOFF_(m_edi) = alloc_BaB_1_set(0);
2351 /* 8 */ VGOFF_(m_eflags) = alloc_BaB_1_set(0);
2352
2353 if (VG_(needs).shadow_regs) {
2354 /* 9 */ VGOFF_(sh_eax) = alloc_BaB_1_set(0);
2355 /* 10 */ VGOFF_(sh_ecx) = alloc_BaB_1_set(0);
2356 /* 11 */ VGOFF_(sh_edx) = alloc_BaB_1_set(0);
2357 /* 12 */ VGOFF_(sh_ebx) = alloc_BaB_1_set(0);
2358 /* 13 */ VGOFF_(sh_esp) = alloc_BaB_1_set(0);
2359 /* 14 */ VGOFF_(sh_ebp) = alloc_BaB_1_set(0);
2360 /* 15 */ VGOFF_(sh_esi) = alloc_BaB_1_set(0);
2361 /* 16 */ VGOFF_(sh_edi) = alloc_BaB_1_set(0);
2362 /* 17 */ VGOFF_(sh_eflags) = alloc_BaB_1_set(0);
2363 VG_TRACK( post_regs_write_init );
2364 }
2365
2366 /* 9,10,11 or 18,19,20... depends on number whether shadow regs are used
2367 * and on compact helpers registered */
2368
2369 /* Make these most-frequently-called specialised ones compact, if they
2370 are used. */
2371 if (VG_(defined_new_mem_stack_4)())
2372 VG_(register_compact_helper)( (Addr) VG_(tool_interface).track_new_mem_stack_4);
2373
2374 if (VG_(defined_die_mem_stack_4)())
2375 VG_(register_compact_helper)( (Addr) VG_(tool_interface).track_die_mem_stack_4);
2376
2377 /* (9 or 18) + n_compact_helpers */
2378 /* Allocate slots for compact helpers */
2379 assign_helpers_in_baseBlock(VG_(n_compact_helpers),
2380 VG_(compact_helper_offsets),
2381 VG_(compact_helper_addrs));
2382
2383 /* (9/10 or 18/19) + n_compact_helpers */
2384 VGOFF_(m_eip) = alloc_BaB_1_set(client_eip);
2385
2386 /* There are currently 24 spill slots */
2387 /* (11+/20+ .. 32+/43+) + n_compact_helpers. This can overlap the magic
2388 * boundary at >= 32 words, but most spills are to low numbered spill
2389 * slots, so the ones above the boundary don't see much action. */
2390 VGOFF_(spillslots) = alloc_BaB(VG_MAX_SPILLSLOTS);
2391
2392 /* I gave up counting at this point. Since they're above the
2393 short-amode-boundary, there's no point. */
2394
2395 VGOFF_(m_dflag) = alloc_BaB_1_set(1); // 1 == forward D-flag
2396
2397 /* The FPU/SSE state. This _must_ be 16-byte aligned. Initial
2398 state doesn't matter much, as long as it's not totally borked. */
2399 align_BaB(16);
2400 VGOFF_(m_ssestate) = alloc_BaB(VG_SIZE_OF_SSESTATE_W);
2401 vg_assert(
2402 0 == ( ((UInt)(& VG_(baseBlock)[VGOFF_(m_ssestate)])) % 16 )
sewardj22854b92002-11-30 14:00:47 +00002403 );
2404
fitzhardingec2dbbac2004-01-23 23:09:01 +00002405 /* I assume that if we have SSE2 we also have SSE */
2406 VG_(have_ssestate) =
2407 VG_(cpu_has_feature)(VG_X86_FEAT_FXSR) &&
2408 VG_(cpu_has_feature)(VG_X86_FEAT_SSE);
2409
fitzhardinge98abfc72003-12-16 02:05:15 +00002410 /* set up an initial FPU state (doesn't really matter what it is,
2411 so long as it's somewhat valid) */
2412 if (!VG_(have_ssestate))
nethercote71980f02004-01-24 18:18:54 +00002413 asm volatile("fwait; fnsave %0; fwait; frstor %0; fwait"
2414 :
2415 : "m" (VG_(baseBlock)[VGOFF_(m_ssestate)])
2416 : "cc", "memory");
fitzhardinge98abfc72003-12-16 02:05:15 +00002417 else
nethercote71980f02004-01-24 18:18:54 +00002418 asm volatile("fwait; fxsave %0; fwait; andl $0xffbf, %1;"
2419 "fxrstor %0; fwait"
2420 :
2421 : "m" (VG_(baseBlock)[VGOFF_(m_ssestate)]),
2422 "m" (VG_(baseBlock)[VGOFF_(m_ssestate)+(24/4)])
2423 : "cc", "memory");
fitzhardinge98abfc72003-12-16 02:05:15 +00002424
njn0c7a5b52003-04-30 09:00:33 +00002425 if (0) {
2426 if (VG_(have_ssestate))
2427 VG_(printf)("Looks like a SSE-capable CPU\n");
2428 else
2429 VG_(printf)("Looks like a MMX-only CPU\n");
2430 }
sewardjb91ae7f2003-04-29 23:50:00 +00002431
nethercote71980f02004-01-24 18:18:54 +00002432 /* LDT pointer: pretend the root thread has an empty LDT to start with. */
2433 VGOFF_(ldt) = alloc_BaB_1_set((UInt)NULL);
jsgf855d93d2003-10-13 22:26:55 +00002434
nethercote71980f02004-01-24 18:18:54 +00002435 /* TLS pointer: pretend the root thread has no TLS array for now. */
2436 VGOFF_(tls) = alloc_BaB_1_set((UInt)NULL);
fitzhardingef0046f22003-12-18 02:39:22 +00002437
nethercote71980f02004-01-24 18:18:54 +00002438 /* segment registers */
2439 VGOFF_(m_cs) = alloc_BaB_1_set(0);
2440 VGOFF_(m_ss) = alloc_BaB_1_set(0);
2441 VGOFF_(m_ds) = alloc_BaB_1_set(0);
2442 VGOFF_(m_es) = alloc_BaB_1_set(0);
2443 VGOFF_(m_fs) = alloc_BaB_1_set(0);
2444 VGOFF_(m_gs) = alloc_BaB_1_set(0);
fitzhardingef0046f22003-12-18 02:39:22 +00002445
nethercote71980f02004-01-24 18:18:54 +00002446 VG_(register_noncompact_helper)( (Addr) & VG_(do_useseg) );
fitzhardingef0046f22003-12-18 02:39:22 +00002447
nethercote71980f02004-01-24 18:18:54 +00002448#define REG(kind, size) \
2449 if (VG_(defined_##kind##_mem_stack##size)()) \
2450 VG_(register_noncompact_helper)( \
2451 (Addr) VG_(tool_interface).track_##kind##_mem_stack##size );
2452 REG(new, _8);
2453 REG(new, _12);
2454 REG(new, _16);
2455 REG(new, _32);
2456 REG(new, );
2457 REG(die, _8);
2458 REG(die, _12);
2459 REG(die, _16);
2460 REG(die, _32);
2461 REG(die, );
2462#undef REG
fitzhardingef0046f22003-12-18 02:39:22 +00002463
nethercote71980f02004-01-24 18:18:54 +00002464 if (VG_(need_to_handle_esp_assignment)())
2465 VG_(register_noncompact_helper)((Addr) VG_(unknown_esp_update));
fitzhardingeb791a192003-12-18 07:22:44 +00002466
nethercote71980f02004-01-24 18:18:54 +00002467# define HELPER(name) \
2468 VGOFF_(helper_##name) = alloc_BaB_1_set( (Addr) & VG_(helper_##name))
njn3e884182003-04-15 13:03:23 +00002469
nethercote71980f02004-01-24 18:18:54 +00002470 /* Helper functions. */
2471 HELPER(idiv_64_32); HELPER(div_64_32);
2472 HELPER(idiv_32_16); HELPER(div_32_16);
2473 HELPER(idiv_16_8); HELPER(div_16_8);
fitzhardinge98abfc72003-12-16 02:05:15 +00002474
nethercote71980f02004-01-24 18:18:54 +00002475 HELPER(imul_32_64); HELPER(mul_32_64);
2476 HELPER(imul_16_32); HELPER(mul_16_32);
2477 HELPER(imul_8_16); HELPER(mul_8_16);
njn25e49d8e72002-09-23 09:36:25 +00002478
nethercote71980f02004-01-24 18:18:54 +00002479 HELPER(CLD); HELPER(STD);
2480 HELPER(get_dirflag);
sewardjde4a1d02002-03-22 01:27:54 +00002481
nethercote71980f02004-01-24 18:18:54 +00002482 HELPER(CLC); HELPER(STC);
jsgf855d93d2003-10-13 22:26:55 +00002483
nethercote71980f02004-01-24 18:18:54 +00002484 HELPER(shldl); HELPER(shldw);
2485 HELPER(shrdl); HELPER(shrdw);
njncc7bb472002-10-14 09:25:19 +00002486
nethercote71980f02004-01-24 18:18:54 +00002487 HELPER(RDTSC); HELPER(CPUID);
njncc7bb472002-10-14 09:25:19 +00002488
nethercote71980f02004-01-24 18:18:54 +00002489 HELPER(bsf); HELPER(bsr);
rjwalshf5f536f2003-11-17 17:45:00 +00002490
nethercote71980f02004-01-24 18:18:54 +00002491 HELPER(fstsw_AX);
2492 HELPER(SAHF); HELPER(LAHF);
2493 HELPER(DAS); HELPER(DAA);
2494 HELPER(IN); HELPER(OUT);
2495 HELPER(cmpxchg8b);
sewardj018f7622002-05-15 21:13:39 +00002496
nethercote71980f02004-01-24 18:18:54 +00002497 HELPER(undefined_instruction);
jsgf855d93d2003-10-13 22:26:55 +00002498
nethercote71980f02004-01-24 18:18:54 +00002499# undef HELPER
sewardjde4a1d02002-03-22 01:27:54 +00002500
nethercote71980f02004-01-24 18:18:54 +00002501 /* Allocate slots for noncompact helpers */
2502 assign_helpers_in_baseBlock(VG_(n_noncompact_helpers),
2503 VG_(noncompact_helper_offsets),
2504 VG_(noncompact_helper_addrs));
2505}
sewardjde4a1d02002-03-22 01:27:54 +00002506
sewardj5f07b662002-04-23 16:52:51 +00002507
nethercote71980f02004-01-24 18:18:54 +00002508/*====================================================================*/
2509/*=== Setup pointercheck ===*/
2510/*====================================================================*/
njn25e49d8e72002-09-23 09:36:25 +00002511
nethercote71980f02004-01-24 18:18:54 +00002512static void setup_pointercheck(void)
2513{
2514 int ret;
sewardj2e93c502002-04-12 11:12:52 +00002515
fitzhardinge98abfc72003-12-16 02:05:15 +00002516 if (VG_(clo_pointercheck)) {
nethercote71980f02004-01-24 18:18:54 +00002517 vki_modify_ldt_t ldt = {
2518 VG_POINTERCHECK_SEGIDX, // entry_number
2519 VG_(client_base), // base_addr
2520 (VG_(client_end)-VG_(client_base)) / VKI_BYTES_PER_PAGE, // limit
2521 1, // seg_32bit
2522 0, // contents: data, RW, non-expanding
2523 0, // ! read_exec_only
2524 1, // limit_in_pages
2525 0, // ! seg not present
2526 1, // useable
fitzhardinge98abfc72003-12-16 02:05:15 +00002527 };
nethercote71980f02004-01-24 18:18:54 +00002528 ret = VG_(do_syscall)(__NR_modify_ldt, 1, &ldt, sizeof(ldt));
fitzhardinge98abfc72003-12-16 02:05:15 +00002529 if (ret < 0) {
2530 VG_(message)(Vg_UserMsg,
2531 "Warning: ignoring --pointercheck=yes, "
2532 "because modify_ldt failed (errno=%d)", -ret);
2533 VG_(clo_pointercheck) = False;
2534 }
2535 }
sewardjde4a1d02002-03-22 01:27:54 +00002536}
2537
nethercote71980f02004-01-24 18:18:54 +00002538/*====================================================================*/
2539/*=== Initialise program data/text, etc. ===*/
2540/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +00002541
nethercote71980f02004-01-24 18:18:54 +00002542static void build_valgrind_map_callback
2543 ( Addr start, UInt size, Char rr, Char ww, Char xx,
2544 UInt dev, UInt ino, ULong foffset, const UChar* filename )
sewardjde4a1d02002-03-22 01:27:54 +00002545{
nethercote71980f02004-01-24 18:18:54 +00002546 UInt prot = 0;
2547 UInt flags = SF_MMAP|SF_NOSYMS;
2548 Bool is_stack_segment;
2549
2550 is_stack_segment =
2551 (start == VG_(clstk_base) && (start+size) == VG_(clstk_end));
2552
2553 /* Only record valgrind mappings for now, without loading any
2554 symbols. This is so we know where the free space is before we
2555 start allocating more memory (note: heap is OK, it's just mmap
2556 which is the problem here). */
2557 if (start >= VG_(valgrind_base) && (start+size) <= VG_(valgrind_end)) {
2558 flags |= SF_VALGRIND;
2559 VG_(map_file_segment)(start, size, prot, flags, dev, ino, foffset, filename);
2560 }
sewardjde4a1d02002-03-22 01:27:54 +00002561}
2562
nethercote71980f02004-01-24 18:18:54 +00002563// Global var used to pass local data to callback
2564Addr esp_at_startup___global_arg = 0;
sewardjde4a1d02002-03-22 01:27:54 +00002565
nethercote71980f02004-01-24 18:18:54 +00002566static void build_segment_map_callback
2567 ( Addr start, UInt size, Char rr, Char ww, Char xx,
2568 UInt dev, UInt ino, ULong foffset, const UChar* filename )
sewardj45b672d2003-07-25 19:58:11 +00002569{
nethercote71980f02004-01-24 18:18:54 +00002570 UInt prot = 0;
2571 UInt flags;
2572 Bool is_stack_segment;
2573 Addr r_esp;
sewardj45b672d2003-07-25 19:58:11 +00002574
nethercote71980f02004-01-24 18:18:54 +00002575 is_stack_segment
2576 = (start == VG_(clstk_base) && (start+size) == VG_(clstk_end));
fitzhardinge98abfc72003-12-16 02:05:15 +00002577
nethercote71980f02004-01-24 18:18:54 +00002578 if (rr == 'r') prot |= VKI_PROT_READ;
2579 if (ww == 'w') prot |= VKI_PROT_WRITE;
2580 if (xx == 'x') prot |= VKI_PROT_EXEC;
fitzhardinge98abfc72003-12-16 02:05:15 +00002581
nethercote71980f02004-01-24 18:18:54 +00002582 if (is_stack_segment)
2583 flags = SF_STACK | SF_GROWDOWN;
2584 else
2585 flags = SF_EXEC|SF_MMAP;
fitzhardinge98abfc72003-12-16 02:05:15 +00002586
nethercote71980f02004-01-24 18:18:54 +00002587 if (filename != NULL)
2588 flags |= SF_FILE;
fitzhardinge98abfc72003-12-16 02:05:15 +00002589
nethercote71980f02004-01-24 18:18:54 +00002590 if (start >= VG_(valgrind_base) && (start+size) <= VG_(valgrind_end))
2591 flags |= SF_VALGRIND;
fitzhardinge98abfc72003-12-16 02:05:15 +00002592
nethercote71980f02004-01-24 18:18:54 +00002593 VG_(map_file_segment)(start, size, prot, flags, dev, ino, foffset, filename);
fitzhardinge98abfc72003-12-16 02:05:15 +00002594
nethercote71980f02004-01-24 18:18:54 +00002595 if (VG_(is_client_addr)(start) && VG_(is_client_addr)(start+size-1))
2596 VG_TRACK( new_mem_startup, start, size, rr=='r', ww=='w', xx=='x' );
sewardj3e1eb1f2002-05-18 13:14:17 +00002597
nethercote71980f02004-01-24 18:18:54 +00002598 /* If this is the stack segment mark all below %esp as noaccess. */
2599 r_esp = esp_at_startup___global_arg;
2600 vg_assert(0 != r_esp);
2601 if (is_stack_segment) {
2602 if (0)
2603 VG_(message)(Vg_DebugMsg, "invalidating stack area: %x .. %x",
2604 start,r_esp);
2605 VG_TRACK( die_mem_stack, start, r_esp-start );
sewardjde4a1d02002-03-22 01:27:54 +00002606 }
sewardjde4a1d02002-03-22 01:27:54 +00002607}
2608
2609
nethercote71980f02004-01-24 18:18:54 +00002610/*====================================================================*/
2611/*=== Sanity check machinery (permanently engaged) ===*/
2612/*====================================================================*/
njn25e49d8e72002-09-23 09:36:25 +00002613
2614/* A fast sanity check -- suitable for calling circa once per
2615 millisecond. */
2616
2617void VG_(do_sanity_checks) ( Bool force_expensive )
2618{
njn37cea302002-09-30 11:24:00 +00002619 VGP_PUSHCC(VgpCoreCheapSanity);
2620
njn25e49d8e72002-09-23 09:36:25 +00002621 if (VG_(sanity_level) < 1) return;
2622
2623 /* --- First do all the tests that we can do quickly. ---*/
2624
2625 VG_(sanity_fast_count)++;
2626
njn25e49d8e72002-09-23 09:36:25 +00002627 /* Check stuff pertaining to the memory check system. */
2628
2629 /* Check that nobody has spuriously claimed that the first or
2630 last 16 pages of memory have become accessible [...] */
njn37cea302002-09-30 11:24:00 +00002631 if (VG_(needs).sanity_checks) {
2632 VGP_PUSHCC(VgpSkinCheapSanity);
njn25e49d8e72002-09-23 09:36:25 +00002633 vg_assert(SK_(cheap_sanity_check)());
njn37cea302002-09-30 11:24:00 +00002634 VGP_POPCC(VgpSkinCheapSanity);
2635 }
njn25e49d8e72002-09-23 09:36:25 +00002636
2637 /* --- Now some more expensive checks. ---*/
2638
2639 /* Once every 25 times, check some more expensive stuff. */
2640 if ( force_expensive
2641 || VG_(sanity_level) > 1
2642 || (VG_(sanity_level) == 1 && (VG_(sanity_fast_count) % 25) == 0)) {
2643
njn37cea302002-09-30 11:24:00 +00002644 VGP_PUSHCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002645 VG_(sanity_slow_count)++;
2646
jsgf855d93d2003-10-13 22:26:55 +00002647 VG_(proxy_sanity)();
2648
njn25e49d8e72002-09-23 09:36:25 +00002649# if 0
2650 { void zzzmemscan(void); zzzmemscan(); }
2651# endif
2652
2653 if ((VG_(sanity_fast_count) % 250) == 0)
2654 VG_(sanity_check_tc_tt)();
2655
2656 if (VG_(needs).sanity_checks) {
njn37cea302002-09-30 11:24:00 +00002657 VGP_PUSHCC(VgpSkinExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002658 vg_assert(SK_(expensive_sanity_check)());
njn37cea302002-09-30 11:24:00 +00002659 VGP_POPCC(VgpSkinExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002660 }
2661 /*
2662 if ((VG_(sanity_fast_count) % 500) == 0) VG_(mallocSanityCheckAll)();
2663 */
njn37cea302002-09-30 11:24:00 +00002664 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002665 }
2666
2667 if (VG_(sanity_level) > 1) {
njn37cea302002-09-30 11:24:00 +00002668 VGP_PUSHCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002669 /* Check sanity of the low-level memory manager. Note that bugs
2670 in the client's code can cause this to fail, so we don't do
2671 this check unless specially asked for. And because it's
2672 potentially very expensive. */
2673 VG_(mallocSanityCheckAll)();
njn37cea302002-09-30 11:24:00 +00002674 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002675 }
njn37cea302002-09-30 11:24:00 +00002676 VGP_POPCC(VgpCoreCheapSanity);
njn25e49d8e72002-09-23 09:36:25 +00002677}
nethercote71980f02004-01-24 18:18:54 +00002678
2679
2680/*====================================================================*/
2681/*=== main() ===*/
2682/*====================================================================*/
2683
2684int main(int argc, char **argv)
2685{
2686 char **cl_argv;
2687 const char *tool = NULL;
2688 const char *exec = NULL;
2689 char *preload; /* tool-specific LD_PRELOAD .so */
2690 char **env;
2691 Bool need_help = False;
2692 struct exeinfo info;
2693 ToolInfo *toolinfo = NULL;
2694 void *tool_dlhandle;
2695 Addr client_eip;
2696 Addr esp_at_startup; /* client's %esp at the point we gained control. */
2697 UInt * client_auxv;
2698 VgSchedReturnCode src;
2699
2700 //============================================================
2701 // Nb: startup is complex. Prerequisites are shown at every step.
2702 //
2703 // *** Be very careful when messing with the order ***
2704 //============================================================
2705
2706 //--------------------------------------------------------------
2707 // Check we were launched by stage1
2708 // p: n/a [must be first step]
2709 //--------------------------------------------------------------
2710 scan_auxv();
2711
2712 if (0) {
2713 int prmap(void *start, void *end, const char *perm, off_t off,
2714 int maj, int min, int ino) {
2715 printf("mapping %10p-%10p %s %02x:%02x %d\n",
2716 start, end, perm, maj, min, ino);
2717 return True;
2718 }
2719 printf("========== main() ==========\n");
2720 foreach_map(prmap);
2721 }
2722
2723 //--------------------------------------------------------------
2724 // Look for alternative libdir
2725 // p: n/a
2726 //--------------------------------------------------------------
2727 { char *cp = getenv(VALGRINDLIB);
2728 if (cp != NULL)
2729 VG_(libdir) = cp;
2730 }
2731
2732 //--------------------------------------------------------------
2733 // Begin working out address space layout
2734 // p: n/a
2735 //--------------------------------------------------------------
2736 layout_client_space( (Addr) & argc );
2737
2738 //--------------------------------------------------------------
2739 // Get valgrind args + client args (inc. from VALGRIND_OPTS/.valgrindrc).
2740 // Pre-process the command line.
2741 // p: n/a
2742 //--------------------------------------------------------------
2743 get_command_line(argc, argv, &VG_(vg_argc), &VG_(vg_argv), &cl_argv);
2744 pre_process_cmd_line_options(&need_help, &tool, &exec);
2745
2746 //==============================================================
2747 // Nb: once a tool is specified, the tool.so must be loaded even if
2748 // they specified --help or didn't specify a client program.
2749 //==============================================================
2750
2751 //--------------------------------------------------------------
2752 // With client padded out, map in tool
2753 // p: layout_client_space() [for padding]
2754 // p: set-libdir [for VG_(libdir)]
2755 // p: pre_process_cmd_line_options() [for 'tool']
2756 //--------------------------------------------------------------
2757 load_tool(tool, &tool_dlhandle, &toolinfo, &preload);
2758
2759 //==============================================================
2760 // Can use VG_(malloc)() and VG_(arena_malloc)() only after load_tool()
2761 // -- redzone size is now set.
2762 //==============================================================
2763
2764 //--------------------------------------------------------------
2765 // Finalise address space layout
2766 // p: layout_client_space(), load_tool() [for 'toolinfo']
2767 //--------------------------------------------------------------
2768 layout_remaining_space( toolinfo->shadow_ratio );
2769
2770 //--------------------------------------------------------------
2771 // Load client executable, finding in $PATH if necessary
2772 // p: layout_client_space() [so there's space]
2773 // p: pre_process_cmd_line_options() [for 'exec', 'need_help']
2774 // p: layout_remaining_space [so there's space]
2775 //--------------------------------------------------------------
2776 load_client(cl_argv, exec, /*inout*/&need_help, &info, &client_eip);
2777
2778 //--------------------------------------------------------------
2779 // Everything in place, unpad us
2780 // p: layout_remaining_space() [everything must be mapped in before now]
2781 // p: load_client() [ditto]
2782 //--------------------------------------------------------------
2783 as_unpad((void *)VG_(shadow_end), (void *)~0);
2784 as_closepadfile(); /* no more padding */
2785
2786 //--------------------------------------------------------------
2787 // Set up client's environment
2788 // p: set-libdir [for VG_(libdir)]
2789 // p: load_tool() [for 'preload']
2790 //--------------------------------------------------------------
2791 env = fix_environment(environ, preload);
2792
2793 //--------------------------------------------------------------
2794 // Setup client stack and eip
2795 // p: load_client() [for 'info']
2796 // p: fix_environment() [for 'env']
2797 //--------------------------------------------------------------
2798 esp_at_startup = setup_client_stack(cl_argv, env, &info, &client_auxv);
2799
2800 if (0)
2801 printf("entry=%x client esp=%x vg_argc=%d brkbase=%x\n",
2802 client_eip, esp_at_startup, VG_(vg_argc), VG_(brk_base));
2803
2804 //==============================================================
2805 // Finished setting up operating environment. Now initialise
2806 // Valgrind. (This is where the old VG_(main)() started.)
2807 //==============================================================
2808
2809 //--------------------------------------------------------------
2810 // Read /proc/self/maps into a buffer
2811 // p: all memory layout, environment setup [so memory maps are right]
2812 //--------------------------------------------------------------
2813 VG_(read_procselfmaps)();
2814
2815 //--------------------------------------------------------------
2816 // atfork
2817 // p: n/a
2818 //--------------------------------------------------------------
2819 VG_(atfork)(NULL, NULL, newpid);
2820 newpid(VG_INVALID_THREADID);
2821
2822 //--------------------------------------------------------------
2823 // setup file descriptors
2824 // p: n/a
2825 //--------------------------------------------------------------
2826 setup_file_descriptors();
2827
2828 //--------------------------------------------------------------
2829 // Setup tool
2830 // p: VG_(read_procselfmaps)() [so if sk_pre_clo_init calls
2831 // VG_(malloc), any mmap'd superblocks aren't erroneously
2832 // identified later as being owned by the client]
2833 // XXX: is that necessary, now that we look for V's segments separately?
2834 // XXX: alternatively, if sk_pre_clo_init does use VG_(malloc)(), is it
2835 // wrong to ignore any segments that might add in parse_procselfmaps?
2836 //--------------------------------------------------------------
2837 (*toolinfo->sk_pre_clo_init)();
2838 VG_(tool_init_dlsym)(tool_dlhandle);
2839 VG_(sanity_check_needs)();
2840
2841 //--------------------------------------------------------------
2842 // Process Valgrind's + tool's command-line options
2843 // p: load_tool() [for 'tool']
2844 // p: load_client() [for 'need_help']
2845 // p: setup_file_descriptors() [for 'VG_(max_fd)']
2846 // p: sk_pre_clo_init [to set 'command_line_options' need]
2847 //--------------------------------------------------------------
2848 process_cmd_line_options(client_auxv, esp_at_startup, tool, need_help);
2849
2850 //--------------------------------------------------------------
2851 // Allow GDB attach
2852 // p: process_cmd_line_options() [for VG_(clo_wait_for_gdb)]
2853 //--------------------------------------------------------------
2854 /* Hook to delay things long enough so we can get the pid and
2855 attach GDB in another shell. */
2856 if (VG_(clo_wait_for_gdb)) {
2857 VG_(printf)("pid=%d\n", VG_(getpid)());
2858 /* do "jump *$eip" to skip this in gdb */
2859 VG_(do_syscall)(__NR_pause);
2860 }
2861
2862 //--------------------------------------------------------------
2863 // Setup tool, post command-line processing
2864 // p: process_cmd_line_options [tool assumes it]
2865 //--------------------------------------------------------------
2866 SK_(post_clo_init)();
2867
2868 //--------------------------------------------------------------
2869 // Set up baseBlock, copy machine state (m_state_static)
2870 // p: {pre,post}_clo_init() [for tool helper registration]
2871 // load_client() [for 'client_eip']
2872 // setup_client_stack() [for 'esp_at_startup']
2873 //--------------------------------------------------------------
2874 init_baseBlock(client_eip, esp_at_startup);
2875
2876 //--------------------------------------------------------------
2877 // Search for file descriptors that are inherited from our parent
2878 // p: process_cmd_line_options [for VG_(clo_track_fds)]
2879 //--------------------------------------------------------------
2880 if (VG_(clo_track_fds))
2881 VG_(init_preopened_fds)();
2882
2883 //--------------------------------------------------------------
2884 // Initialise the scheduler
2885 // p: init_baseBlock() [baseBlock regs copied into VG_(threads)[1]]
2886 // p: setup_file_descriptors() [else VG_(safe_fd)() breaks]
2887 //--------------------------------------------------------------
2888 VG_(scheduler_init)();
2889
2890 //--------------------------------------------------------------
2891 // Set up the ProxyLWP machinery
2892 // p: VG_(scheduler_init)()? [XXX: subtle dependency?]
2893 // - subs: VG_(sigstartup_actions)()?
2894 //--------------------------------------------------------------
2895 VG_(proxy_init)();
2896
2897 //--------------------------------------------------------------
2898 // Initialise the signal handling subsystem
2899 // p: VG_(atfork)(NULL, NULL, newpid) [else problems with sigmasks]
2900 // p: VG_(proxy_init)() [else breaks...]
2901 //--------------------------------------------------------------
2902 // Nb: temporarily parks the saved blocking-mask in saved_sigmask.
2903 VG_(sigstartup_actions)();
2904
2905 //--------------------------------------------------------------
2906 // Perhaps we're profiling Valgrind?
2907 // p: process_cmd_line_options() [for VG_(clo_profile)]
2908 // p: others?
2909 //
2910 // XXX: this seems to be broken? It always says the tool wasn't built
2911 // for profiling; vg_profile.c's functions don't seem to be overriding
2912 // vg_dummy_profile.c's?
2913 //
2914 // XXX: want this as early as possible. Looking for --profile
2915 // in pre_process_cmd_line_options() could get it earlier.
2916 //--------------------------------------------------------------
2917 if (VG_(clo_profile))
2918 VGP_(init_profiling)();
2919
2920 VGP_PUSHCC(VgpStartup);
2921
2922 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002923 // Reserve Valgrind's kickstart, heap and stack
2924 // p: XXX ???
2925 //--------------------------------------------------------------
2926 VG_(map_segment)(VG_(valgrind_mmap_end),
2927 VG_(valgrind_end)-VG_(valgrind_mmap_end),
2928 VKI_PROT_NONE, SF_VALGRIND|SF_FIXED);
2929
2930 //--------------------------------------------------------------
2931 // Identify Valgrind's segments
2932 // p: read proc/self/maps
2933 // p: VG_(map_segment) [XXX ???]
2934 // p: sk_pre_clo_init() [to setup new_mem_startup tracker]
2935 //--------------------------------------------------------------
2936 VG_(parse_procselfmaps) ( build_valgrind_map_callback );
2937
2938 // XXX: I can't see why these two need to be separate; could they be
2939 // folded together? If not, need a comment explaining why.
2940 //
2941 // XXX: can we merge reading and parsing of /proc/self/maps?
2942 //
2943 // XXX: can we dynamically allocate the /proc/self/maps buffer? (or mmap
2944 // it?) Or does that disturb its contents...
2945
2946 //--------------------------------------------------------------
2947 // Build segment map (all segments)
2948 // p: setup_client_stack() [for 'esp_at_startup']
2949 //--------------------------------------------------------------
2950 esp_at_startup___global_arg = esp_at_startup;
2951 VG_(parse_procselfmaps) ( build_segment_map_callback ); /* everything */
2952 esp_at_startup___global_arg = 0;
2953
2954 //==============================================================
2955 // Can only use VG_(map)() after VG_(map_segment)() [XXX ???]
2956 //==============================================================
2957
2958 //--------------------------------------------------------------
2959 // Build segment map (all segments)
2960 // p: setup_client_stack() [for 'esp_at_startup']
2961 //--------------------------------------------------------------
2962 /* Initialize our trampoline page (which is also sysinfo stuff) */
2963 VG_(memcpy)( (void *)VG_(client_trampoline_code),
2964 &VG_(trampoline_code_start), VG_(trampoline_code_length) );
2965 VG_(mprotect)( (void *)VG_(client_trampoline_code),
2966 VG_(trampoline_code_length), VKI_PROT_READ|VKI_PROT_EXEC );
2967
2968 //--------------------------------------------------------------
2969 // Read suppression file
2970 // p: process_cmd_line_options() [for VG_(clo_suppressions)]
2971 //--------------------------------------------------------------
2972 if (VG_(needs).core_errors || VG_(needs).skin_errors)
2973 VG_(load_suppressions)();
2974
2975 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002976 // Initialise translation table and translation cache
2977 // p: read_procselfmaps [so the anonymous mmaps for the TT/TC
2978 // aren't identified as part of the client, which would waste
2979 // > 20M of virtual address space.]
2980 //--------------------------------------------------------------
2981 VG_(init_tt_tc)();
2982
2983 //--------------------------------------------------------------
2984 // Read debug info to find glibc entry points to intercept
2985 // p: parse_procselfmaps? [XXX for debug info?]
2986 // p: init_tt_tc? [XXX ???]
2987 //--------------------------------------------------------------
2988 VG_(setup_code_redirect_table)();
2989
2990 //--------------------------------------------------------------
2991 // Verbosity message
2992 // p: end_rdtsc_calibration [so startup message is printed first]
2993 //--------------------------------------------------------------
2994 if (VG_(clo_verbosity) == 1)
2995 VG_(message)(Vg_UserMsg, "For more details, rerun with: -v");
2996 if (VG_(clo_verbosity) > 0)
2997 VG_(message)(Vg_UserMsg, "");
2998
2999 //--------------------------------------------------------------
3000 // Setup pointercheck
3001 // p: process_cmd_line_options() [for VG_(clo_pointercheck)]
3002 //--------------------------------------------------------------
3003 setup_pointercheck();
3004
3005
3006
3007 //--------------------------------------------------------------
3008 // Run!
3009 //--------------------------------------------------------------
3010 VG_(running_on_simd_CPU) = True;
3011 VGP_POPCC(VgpStartup);
3012 VGP_PUSHCC(VgpSched);
3013
3014 if (__builtin_setjmp(&VG_(fatal_signal_jmpbuf)) == 0) {
3015 VG_(fatal_signal_set) = True;
3016 src = VG_(scheduler)();
3017 } else
3018 src = VgSrc_FatalSig;
3019
3020 VGP_POPCC(VgpSched);
3021 VG_(running_on_simd_CPU) = False;
3022
3023
3024
3025 //--------------------------------------------------------------
3026 // Finalisation: cleanup, messages, etc. Order no so important, only
3027 // affects what order the messages come.
3028 //--------------------------------------------------------------
3029 if (VG_(clo_verbosity) > 0)
3030 VG_(message)(Vg_UserMsg, "");
3031
3032 if (src == VgSrc_Deadlock) {
3033 VG_(message)(Vg_UserMsg,
3034 "Warning: pthread scheduler exited due to deadlock");
3035 }
3036
3037 /* Print out file descriptor summary and stats. */
3038 if (VG_(clo_track_fds))
3039 VG_(fd_stats)();
3040
3041 if (VG_(needs).core_errors || VG_(needs).skin_errors)
3042 VG_(show_all_errors)();
3043
3044 SK_(fini)( VG_(exitcode) );
3045
3046 VG_(do_sanity_checks)( True /*include expensive checks*/ );
3047
3048 if (VG_(clo_verbosity) > 1)
3049 show_counts();
3050
3051 if (VG_(clo_verbosity) > 3)
3052 VG_(print_UInstr_histogram)();
3053
3054 if (0) {
3055 VG_(message)(Vg_DebugMsg, "");
3056 VG_(message)(Vg_DebugMsg,
3057 "------ Valgrind's internal memory use stats follow ------" );
3058 VG_(mallocSanityCheckAll)();
3059 VG_(show_all_arena_stats)();
3060 VG_(message)(Vg_DebugMsg,
3061 "------ Valgrind's ExeContext management stats follow ------" );
3062 VG_(show_ExeContext_stats)();
3063 }
3064
3065 if (VG_(clo_profile))
3066 VGP_(done_profiling)();
3067
3068 /* Must be after all messages are done */
3069 VG_(shutdown_logging)();
3070
3071 /* We're exiting, so nuke all the threads and clean up the proxy LWPs */
3072 vg_assert(src == VgSrc_FatalSig ||
3073 VG_(threads)[VG_(last_run_tid)].status == VgTs_Runnable ||
3074 VG_(threads)[VG_(last_run_tid)].status == VgTs_WaitJoiner);
3075 VG_(nuke_all_threads_except)(VG_INVALID_THREADID);
3076
3077 //--------------------------------------------------------------
3078 // Exit, according to the scheduler's return code
3079 //--------------------------------------------------------------
3080 switch (src) {
3081 case VgSrc_ExitSyscall: /* the normal way out */
3082 vg_assert(VG_(last_run_tid) > 0
3083 && VG_(last_run_tid) < VG_N_THREADS);
3084 VG_(proxy_shutdown)();
3085
3086 /* The thread's %EBX at the time it did __NR_exit() will hold
3087 the arg to __NR_exit(), so we just do __NR_exit() with
3088 that arg. */
3089 VG_(exit)( VG_(exitcode) );
3090 /* NOT ALIVE HERE! */
3091 VG_(core_panic)("entered the afterlife in main() -- ExitSyscall");
3092 break; /* what the hell :) */
3093
3094 case VgSrc_Deadlock:
3095 /* Just exit now. No point in continuing. */
3096 VG_(proxy_shutdown)();
3097 VG_(exit)(0);
3098 VG_(core_panic)("entered the afterlife in main() -- Deadlock");
3099 break;
3100
3101 case VgSrc_BbsDone:
3102 /* Tricky; we have to try and switch back to the real CPU.
3103 This is all very dodgy and won't work at all in the
3104 presence of threads, or if the client happened to be
3105 running a signal handler. */
3106 /* Prepare to restore state to the real CPU. */
3107 VG_(sigshutdown_actions)();
3108 VG_(load_thread_state)(1 /* root thread */ );
3109 copy_baseBlock_to_m_state_static();
3110
3111 VG_(proxy_shutdown)();
3112
3113 /* This pushes a return address on the simulator's stack,
3114 which is abandoned. We call vg_sigshutdown_actions() at
3115 the end of vg_switch_to_real_CPU(), so as to ensure that
3116 the original stack and machine state is restored before
3117 the real signal mechanism is restored. */
3118 VG_(switch_to_real_CPU)();
3119
3120 case VgSrc_FatalSig:
3121 /* We were killed by a fatal signal, so replicate the effect */
3122 vg_assert(VG_(fatal_sigNo) != -1);
3123 VG_(kill_self)(VG_(fatal_sigNo));
3124 VG_(core_panic)("main(): signal was supposed to be fatal");
3125 break;
3126
3127 default:
3128 VG_(core_panic)("main(): unexpected scheduler return code");
3129 }
3130
3131 abort();
3132}
3133
3134
sewardjde4a1d02002-03-22 01:27:54 +00003135/*--------------------------------------------------------------------*/
3136/*--- end vg_main.c ---*/
3137/*--------------------------------------------------------------------*/