blob: 11b80d4848a1f85039adbb98915025a50b4f4e36 [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
295/* Start GDB and get it to attach to this process. Called if the user
296 requests this service after an error has been shown, so she can
297 poke around and look at parameters, memory, etc. You can't
298 meaningfully get GDB to continue the program, though; to continue,
299 quit GDB. */
300void VG_(start_GDB) ( Int tid )
301{
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) {
355 UChar buf[VG_(strlen)(VG_(clo_GDB_path)) + 100];
356
357 VG_(sprintf)(buf, "%s -nw /proc/%d/fd/%d %d",
358 VG_(clo_GDB_path), VG_(main_pid), VG_(clexecfd), pid);
359 VG_(message)(Vg_UserMsg, "starting GDB with cmd: %s", buf);
360 res = VG_(system)(buf);
361 if (res == 0) {
362 VG_(message)(Vg_UserMsg, "");
363 VG_(message)(Vg_UserMsg,
364 "GDB has detached. Valgrind regains control. We continue.");
365 } else {
366 VG_(message)(Vg_UserMsg, "Apparently failed!");
367 VG_(message)(Vg_UserMsg, "");
368 }
369 }
370
371 VG_(kkill)(pid, VKI_SIGKILL);
372 VG_(waitpid)(pid, &status, 0);
373 }
374}
375
376
377/* Print some helpful-ish text about unimplemented things, and give
378 up. */
379void VG_(unimplemented) ( Char* msg )
380{
381 VG_(message)(Vg_UserMsg, "");
382 VG_(message)(Vg_UserMsg,
383 "Valgrind detected that your program requires");
384 VG_(message)(Vg_UserMsg,
385 "the following unimplemented functionality:");
386 VG_(message)(Vg_UserMsg, " %s", msg);
387 VG_(message)(Vg_UserMsg,
388 "This may be because the functionality is hard to implement,");
389 VG_(message)(Vg_UserMsg,
390 "or because no reasonable program would behave this way,");
391 VG_(message)(Vg_UserMsg,
392 "or because nobody has yet needed it. In any case, let us know at");
393 VG_(message)(Vg_UserMsg,
394 "%s and/or try to work around the problem, if you can.", VG_BUGS_TO);
395 VG_(message)(Vg_UserMsg,
396 "");
397 VG_(message)(Vg_UserMsg,
398 "Valgrind has to exit now. Sorry. Bye!");
399 VG_(message)(Vg_UserMsg,
400 "");
401 VG_(pp_sched_status)();
402 VG_(exit)(1);
403}
404
405Addr VG_(get_stack_pointer) ( void )
406{
407 return VG_(baseBlock)[VGOFF_(m_esp)];
408}
409
410/* Debugging thing .. can be called from assembly with OYNK macro. */
411void VG_(oynk) ( Int n )
412{
413 OINK(n);
414}
415
416/* Initialize the PID and PGRP of scheduler LWP; this is also called
417 in any new children after fork. */
418static void newpid(ThreadId unused)
419{
420 /* PID of scheduler LWP */
421 VG_(main_pid) = VG_(getpid)();
422 VG_(main_pgrp) = VG_(getpgrp)();
423}
424
425/*====================================================================*/
426/*=== Check we were launched by stage 1 ===*/
427/*====================================================================*/
428
429/* Look for our AUXV table */
430static void scan_auxv(void)
431{
432 const struct ume_auxv *auxv = find_auxv((int *)ume_exec_esp);
433 int found = 0;
434
435 for (; auxv->a_type != AT_NULL; auxv++)
436 switch(auxv->a_type) {
437 case AT_UME_PADFD:
438 as_setpadfd(auxv->u.a_val);
439 found |= 1;
440 break;
441
442 case AT_UME_EXECFD:
443 VG_(vgexecfd) = auxv->u.a_val;
444 found |= 2;
445 break;
446 }
447
448 if ( ! (1|2) ) {
449 fprintf(stderr, "stage2 must be launched by stage1\n");
450 exit(127);
451 }
452}
453
454
455/*====================================================================*/
456/*=== Address space determination ===*/
457/*====================================================================*/
458
459/* Pad client space so it doesn't get filled in before the right time */
460static void layout_client_space(Addr argc_addr)
461{
462 VG_(client_base) = CLIENT_BASE;
463 VG_(valgrind_mmap_end) = (addr_t)&kickstart_base; /* end of V's mmaps */
464 VG_(valgrind_base) = VG_(valgrind_mmap_end) - VALGRIND_MAPSIZE;
465 VG_(valgrind_end) = ROUNDUP(argc_addr, 0x10000); /* stack */
466
467 if (0)
468 printf("client base: %x\n"
469 "valgrind base--end: %x--%x (%x)\n"
470 "valgrind mmap end: %x\n\n",
471 VG_(client_base),
472 VG_(valgrind_base), VG_(valgrind_end),
473 VG_(valgrind_end) - VG_(valgrind_base),
474 VG_(valgrind_mmap_end));
475
476 as_pad((void *)VG_(client_base), (void *)VG_(valgrind_base));
477}
478
479static void layout_remaining_space(float ratio)
480{
481 /* This tries to give the client as large as possible address space while
482 * taking into account the tool's shadow needs. */
483 addr_t client_size = ROUNDDN((VG_(valgrind_base) - REDZONE_SIZE) / (1. + ratio),
484 CLIENT_SIZE_MULTIPLE);
485 addr_t shadow_size = PGROUNDUP(client_size * ratio);
486
487 VG_(client_end) = VG_(client_base) + client_size;
488 VG_(client_mapbase) = PGROUNDDN((client_size/4)*3); /* where !FIXED mmap goes */
489 VG_(client_trampoline_code) = VG_(client_end) - VKI_BYTES_PER_PAGE;
490
491 VG_(shadow_base) = VG_(client_end) + REDZONE_SIZE;
492 VG_(shadow_end) = VG_(shadow_base) + shadow_size;
493
494 if (0)
495 printf("client base--end: %x--%x (%x)\n"
496 "client mapbase: %x\n"
497 "shadow base--end: %x--%x (%x)\n\n",
498 VG_(client_base), VG_(client_end), client_size,
499 VG_(client_mapbase),
500 VG_(shadow_base), VG_(shadow_end), shadow_size);
501
502 // Ban redzone
503 mmap((void *)VG_(client_end), REDZONE_SIZE, PROT_NONE,
504 MAP_FIXED|MAP_ANON|MAP_PRIVATE, -1, 0);
505
506 // Make client hole
507 munmap((void*)VG_(client_base), client_size);
508
509 // Map shadow memory.
510 // Initially all inaccessible, incrementally initialized as it is used
511 if (shadow_size != 0)
512 mmap((char *)VG_(shadow_base), shadow_size, PROT_NONE,
513 MAP_PRIVATE|MAP_ANON|MAP_FIXED, -1, 0);
514}
515
516/*====================================================================*/
517/*=== Command line setup ===*/
518/*====================================================================*/
519
520/* Nb: malloc'd memory never freed -- kept throughout like argv, envp */
521static char* get_file_clo(char* dir)
522{
523# define FLEN 512
524 Int fd, n;
525 struct stat s1;
526 char* f_clo = NULL;
527 char filename[FLEN];
528
529 snprintf(filename, FLEN, "%s/.valgrindrc", ( NULL == dir ? "" : dir ) );
530 fd = VG_(open)(filename, 0, VKI_S_IRUSR);
531 if ( fd > 0 ) {
532 if ( 0 == fstat(fd, &s1) ) {
533 f_clo = malloc(s1.st_size+1);
534 vg_assert(f_clo);
535 n = read(fd, f_clo, s1.st_size);
536 if (n == -1) n = 0;
537 f_clo[n] = '\0';
538 }
539 close(fd);
540 }
541 return f_clo;
542# undef FLEN
543}
544
545static Int count_args(char* s)
546{
547 Int n = 0;
548 if (s) {
549 char* cp = s;
550 while (True) {
551 // We have alternating sequences: blanks, non-blanks, blanks...
552 // count the non-blanks sequences.
553 while ( ISSPACE(*cp) ) cp++;
554 if ( !*cp ) break;
555 n++;
556 while ( !ISSPACE(*cp) && *cp ) cp++;
557 }
558 }
559 return n;
560}
561
562/* add args out of environment, skipping multiple spaces and -- args */
563static char** copy_args( char* s, char** to )
564{
565 if (s) {
566 char* cp = s;
567 while (True) {
568 // We have alternating sequences: blanks, non-blanks, blanks...
569 // copy the non-blanks sequences, and add terminating '\0'
570 while ( ISSPACE(*cp) ) cp++;
571 if ( !*cp ) break;
572 *to++ = cp;
573 while ( !ISSPACE(*cp) && *cp ) cp++;
574 if ( *cp ) *cp++ = '\0'; // terminate if necessary
575 if (VG_STREQ(to[-1], "--")) to--; // undo any '--' arg
576 }
577 }
578 return to;
579}
580
581// Augment command line with arguments from environment and .valgrindrc
582// files.
583static void augment_command_line(Int* vg_argc_inout, char*** vg_argv_inout)
584{
585 int vg_argc = *vg_argc_inout;
586 char** vg_argv = *vg_argv_inout;
587
588 char* env_clo = getenv(VALGRINDOPTS);
589 char* f1_clo = get_file_clo( getenv("HOME") );
590 char* f2_clo = get_file_clo(".");
591
592 /* copy any extra args from file or environment, if present */
593 if ( (env_clo && *env_clo) || (f1_clo && *f1_clo) || (f2_clo && *f2_clo) ) {
594 /* ' ' separated extra options */
595 char **from;
596 char **to;
597 int env_arg_count, f1_arg_count, f2_arg_count;
598
599 env_arg_count = count_args(env_clo);
600 f1_arg_count = count_args(f1_clo);
601 f2_arg_count = count_args(f2_clo);
602
603 if (0)
604 printf("extra-argc=%d %d %d\n",
605 env_arg_count, f1_arg_count, f2_arg_count);
606
607 /* +2: +1 for null-termination, +1 for added '--' */
608 from = vg_argv;
609 vg_argv = malloc( (vg_argc + env_arg_count + f1_arg_count
610 + f2_arg_count + 2) * sizeof(char **));
611 to = vg_argv;
612
613 /* copy argv[0] */
614 *to++ = *from++;
615
616 /* Copy extra args from env var and file, in the order: ~/.valgrindrc,
617 * $VALGRIND_OPTS, ./.valgrindrc -- more local options are put later
618 * to override less local ones. */
619 to = copy_args(f1_clo, to);
620 to = copy_args(env_clo, to);
621 to = copy_args(f2_clo, to);
622
623 /* copy original arguments, stopping at command or -- */
624 while (*from) {
625 if (**from != '-')
626 break;
627 if (VG_STREQ(*from, "--")) {
628 from++; /* skip -- */
629 break;
630 }
631 *to++ = *from++;
632 }
633
634 /* add -- */
635 *to++ = "--";
636
637 vg_argc = to - vg_argv;
638
639 /* copy rest of original command line, then NULL */
640 while (*from) *to++ = *from++;
641 *to = NULL;
642 }
643
644 *vg_argc_inout = vg_argc;
645 *vg_argv_inout = vg_argv;
646}
647
648static void get_command_line( int argc, char** argv,
649 Int* vg_argc_out, Char*** vg_argv_out,
650 char*** cl_argv_out )
651{
652 int vg_argc;
653 char** vg_argv;
654 char** cl_argv;
655 char* env_clo = getenv(VALGRINDCLO);
656
657 if (env_clo != NULL && *env_clo != '\0') {
658 char *cp;
659 char **cpp;
660
661 /* OK, we're getting all our arguments from the environment - the
662 entire command line belongs to the client (including argv[0]) */
663 vg_argc = 1; /* argv[0] */
664 for (cp = env_clo; *cp; cp++)
665 if (*cp == '\01')
666 vg_argc++;
667
668 vg_argv = malloc(sizeof(char **) * (vg_argc + 1));
669
670 cpp = vg_argv;
671
672 *cpp++ = "valgrind"; /* nominal argv[0] */
673 *cpp++ = env_clo;
674
675 for (cp = env_clo; *cp; cp++) {
676 if (*cp == '\01') {
677 *cp++ = '\0'; /* chop it up in place */
678 *cpp++ = cp;
679 }
680 }
681 *cpp = NULL;
682 cl_argv = argv;
683
684 } else {
685 /* Count the arguments on the command line. */
686 vg_argv = argv;
687
688 for (vg_argc = 1; vg_argc < argc; vg_argc++) {
689 if (argv[vg_argc][0] != '-') /* exe name */
690 break;
691 if (VG_STREQ(argv[vg_argc], "--")) { /* dummy arg */
692 vg_argc++;
693 break;
694 }
695 }
696 cl_argv = &argv[vg_argc];
697
698 /* Get extra args from VALGRIND_OPTS and .valgrindrc files.
699 * Note we don't do this if getting args from VALGRINDCLO. */
700 augment_command_line(&vg_argc, &vg_argv);
701 }
702
703 if (0) {
704 Int i;
705 for (i = 0; i < vg_argc; i++)
706 printf("vg_argv[%d]=\"%s\"\n", i, vg_argv[i]);
707 }
708
709 *vg_argc_out = vg_argc;
710 *vg_argv_out = (Char**)vg_argv;
711 *cl_argv_out = cl_argv;
712}
713
714
715/*====================================================================*/
716/*=== Environment and stack setup ===*/
717/*====================================================================*/
718
719/* Scan a colon-separated list, and call a function on each element.
720 The string must be mutable, because we insert a temporary '\0', but
721 the string will end up unmodified. (*func) should return 1 if it
722 doesn't need to see any more.
723*/
724static void scan_colsep(char *colsep, int (*func)(const char *))
725{
726 char *cp, *entry;
727 int end;
728
729 if (colsep == NULL ||
730 *colsep == '\0')
731 return;
732
733 entry = cp = colsep;
734
735 do {
736 end = (*cp == '\0');
737
738 if (*cp == ':' || *cp == '\0') {
739 char save = *cp;
740
741 *cp = '\0';
742 if ((*func)(entry))
743 end = 1;
744 *cp = save;
745 entry = cp+1;
746 }
747 cp++;
748 } while(!end);
749}
750
751/* Prepare the client's environment. This is basically a copy of our
752 environment, except:
753 1. LD_LIBRARY_PATH=$VALGRINDLIB:$LD_LIBRARY_PATH
754 2. LD_PRELOAD=$VALGRINDLIB/vg_inject.so:($VALGRINDLIB/vgpreload_TOOL.so:)?$LD_PRELOAD
755
756 If any of these is missing, then it is added.
757
758 Yummy. String hacking in C.
759
760 If this needs to handle any more variables it should be hacked
761 into something table driven.
762 */
763static char **fix_environment(char **origenv, const char *preload)
764{
765 static const char inject_so[] = "vg_inject.so";
766 static const char ld_library_path[] = "LD_LIBRARY_PATH=";
767 static const char ld_preload[] = "LD_PRELOAD=";
768 static const char valgrind_clo[] = VALGRINDCLO "=";
769 static const int ld_library_path_len = sizeof(ld_library_path)-1;
770 static const int ld_preload_len = sizeof(ld_preload)-1;
771 static const int valgrind_clo_len = sizeof(valgrind_clo)-1;
772 int ld_preload_done = 0;
773 int ld_library_path_done = 0;
774 char *inject_path;
775 int inject_path_len;
776 int vgliblen = strlen(VG_(libdir));
777 char **cpp;
778 char **ret;
779 int envc;
780 const int preloadlen = (preload == NULL) ? 0 : strlen(preload);
781
782 /* Find the vg_inject.so; also make room for the tool preload
783 library */
784 inject_path_len = sizeof(inject_so) + vgliblen + preloadlen + 16;
785 inject_path = malloc(inject_path_len);
786
787 if (preload)
788 snprintf(inject_path, inject_path_len, "%s/%s:%s",
789 VG_(libdir), inject_so, preload);
790 else
791 snprintf(inject_path, inject_path_len, "%s/%s",
792 VG_(libdir), inject_so);
793
794 /* Count the original size of the env */
795 envc = 0; /* trailing NULL */
796 for (cpp = origenv; cpp && *cpp; cpp++)
797 envc++;
798
799 /* Allocate a new space */
800 ret = malloc(sizeof(char *) * (envc+3+1)); /* 3 new entries + NULL */
801
802 /* copy it over */
803 for (cpp = ret; *origenv; )
804 *cpp++ = *origenv++;
805 *cpp = NULL;
806
807 vg_assert(envc == (cpp - ret));
808
809 /* Walk over the new environment, mashing as we go */
810 for (cpp = ret; cpp && *cpp; cpp++) {
811 if (memcmp(*cpp, ld_library_path, ld_library_path_len) == 0) {
812 int done = 0;
813 int contains(const char *p) {
814 if (VG_STREQ(p, VG_(libdir))) {
815 done = 1;
816 return 1;
817 }
818 return 0;
819 }
820
821 /* If the LD_LIBRARY_PATH already contains libdir, then don't
822 bother adding it again, even if it isn't the first (it
823 seems that the Java runtime will keep reexecing itself
824 unless its paths are at the front of LD_LIBRARY_PATH) */
825 scan_colsep(*cpp + ld_library_path_len, contains);
826
827 if (!done) {
828 int len = strlen(*cpp) + vgliblen*2 + 16;
829 char *cp = malloc(len);
830
831 snprintf(cp, len, "%s%s:%s",
832 ld_library_path, VG_(libdir),
833 (*cpp)+ld_library_path_len);
834
835 *cpp = cp;
836 }
837
838 ld_library_path_done = 1;
839 } else if (memcmp(*cpp, ld_preload, ld_preload_len) == 0) {
840 int len = strlen(*cpp) + inject_path_len;
841 char *cp = malloc(len);
842
843 snprintf(cp, len, "%s%s:%s",
844 ld_preload, inject_path, (*cpp)+ld_preload_len);
845
846 *cpp = cp;
847
848 ld_preload_done = 1;
849 } else if (memcmp(*cpp, valgrind_clo, valgrind_clo_len) == 0) {
850 *cpp = "";
851 }
852 }
853
854 /* Add the missing bits */
855
856 if (!ld_library_path_done) {
857 int len = ld_library_path_len + vgliblen*2 + 16;
858 char *cp = malloc(len);
859
860 snprintf(cp, len, "%s%s", ld_library_path, VG_(libdir));
861
862 ret[envc++] = cp;
863 }
864
865 if (!ld_preload_done) {
866 int len = ld_preload_len + inject_path_len;
867 char *cp = malloc(len);
868
869 snprintf(cp, len, "%s%s",
870 ld_preload, inject_path);
871
872 ret[envc++] = cp;
873 }
874
875 ret[envc] = NULL;
876
877 return ret;
878}
879
880extern char **environ; /* our environment */
881//#include <error.h>
882
883/* Add a string onto the string table, and return its address */
884static char *copy_str(char **tab, const char *str)
885{
886 char *cp = *tab;
887 char *orig = cp;
888
889 while(*str)
890 *cp++ = *str++;
891 *cp++ = '\0';
892
893 if (0)
894 printf("copied %p \"%s\" len %d\n",
895 orig, orig, cp-orig);
896
897 *tab = cp;
898
899 return orig;
900}
901
902/*
903 This sets up the client's initial stack, containing the args,
904 environment and aux vector.
905
906 The format of the stack is:
907
908 higher address +-----------------+
909 | Trampoline code |
910 +-----------------+
911 | |
912 : string table :
913 | |
914 +-----------------+
915 | AT_NULL |
916 - -
917 | auxv |
918 +-----------------+
919 | NULL |
920 - -
921 | envp |
922 +-----------------+
923 | NULL |
924 - -
925 | argv |
926 +-----------------+
927 | argc |
928 lower address +-----------------+ <- esp
929 | undefined |
930 : :
931 */
932static Addr setup_client_stack(char **orig_argv, char **orig_envp,
933 const struct exeinfo *info,
934 UInt** client_auxv)
935{
936 char **cpp;
937 char *strtab; /* string table */
938 char *stringbase;
939 addr_t *ptr;
940 struct ume_auxv *auxv;
941 const struct ume_auxv *orig_auxv;
942 const struct ume_auxv *cauxv;
943 unsigned stringsize; /* total size of strings in bytes */
944 unsigned auxsize; /* total size of auxv in bytes */
945 int argc; /* total argc */
946 int envc; /* total number of env vars */
947 unsigned stacksize; /* total client stack size */
948 addr_t cl_esp; /* client stack base (initial esp) */
949
950 /* use our own auxv as a prototype */
951 orig_auxv = find_auxv(ume_exec_esp);
952
953 /* ==================== compute sizes ==================== */
954
955 /* first of all, work out how big the client stack will be */
956 stringsize = 0;
957
958 /* paste on the extra args if the loader needs them (ie, the #!
959 interpreter and its argument) */
960 argc = 0;
961 if (info->argv0 != NULL) {
962 argc++;
963 stringsize += strlen(info->argv0) + 1;
964 }
965 if (info->argv1 != NULL) {
966 argc++;
967 stringsize += strlen(info->argv1) + 1;
968 }
969
970 /* now scan the args we're given... */
971 for (cpp = orig_argv; *cpp; cpp++) {
972 argc++;
973 stringsize += strlen(*cpp) + 1;
974 }
975
976 /* ...and the environment */
977 envc = 0;
978 for (cpp = orig_envp; cpp && *cpp; cpp++) {
979 envc++;
980 stringsize += strlen(*cpp) + 1;
981 }
982
983 /* now, how big is the auxv? */
984 auxsize = sizeof(*auxv); /* there's always at least one entry: AT_NULL */
985 for (cauxv = orig_auxv; cauxv->a_type != AT_NULL; cauxv++) {
986 if (cauxv->a_type == AT_PLATFORM)
987 stringsize += strlen(cauxv->u.a_ptr) + 1;
988 auxsize += sizeof(*cauxv);
989 }
990
991 /* OK, now we know how big the client stack is */
992 stacksize =
993 sizeof(int) + /* argc */
994 sizeof(char **)*argc + /* argv */
995 sizeof(char **) + /* terminal NULL */
996 sizeof(char **)*envc + /* envp */
997 sizeof(char **) + /* terminal NULL */
998 auxsize + /* auxv */
999 ROUNDUP(stringsize, sizeof(int)) +/* strings (aligned) */
1000 VKI_BYTES_PER_PAGE; /* page for trampoline code */
1001
1002 /* cl_esp is the client's stack pointer */
1003 cl_esp = VG_(client_end) - stacksize;
1004 cl_esp = ROUNDDN(cl_esp, 16); /* make stack 16 byte aligned */
1005
1006 if (0)
1007 printf("stringsize=%d auxsize=%d stacksize=%d\n",
1008 stringsize, auxsize, stacksize);
1009
1010
1011 /* base of the string table (aligned) */
1012 stringbase = strtab = (char *)(VG_(client_trampoline_code) - ROUNDUP(stringsize, sizeof(int)));
1013
1014 VG_(clstk_base) = PGROUNDDN(cl_esp);
1015 VG_(clstk_end) = VG_(client_end);
1016
1017 /* ==================== allocate space ==================== */
1018
1019 /* allocate a stack - mmap enough space for the stack */
1020 mmap((void *)PGROUNDDN(cl_esp),
1021 VG_(client_end) - PGROUNDDN(cl_esp),
1022 PROT_READ | PROT_WRITE | PROT_EXEC,
1023 MAP_PRIVATE | MAP_ANON | MAP_FIXED, -1, 0);
1024
1025
1026 /* ==================== copy client stack ==================== */
1027
1028 ptr = (addr_t *)cl_esp;
1029
1030 /* --- argc --- */
1031 *ptr++ = argc; /* client argc */
1032
1033 /* --- argv --- */
1034 if (info->argv0) {
1035 *ptr++ = (addr_t)copy_str(&strtab, info->argv0);
1036 free(info->argv0);
1037 }
1038 if (info->argv1) {
1039 *ptr++ = (addr_t)copy_str(&strtab, info->argv1);
1040 free(info->argv1);
1041 }
1042 for (cpp = orig_argv; *cpp; ptr++, cpp++) {
1043 *ptr = (addr_t)copy_str(&strtab, *cpp);
1044 }
1045 *ptr++ = 0;
1046
1047 /* --- envp --- */
1048 VG_(client_envp) = (Char **)ptr;
1049 for (cpp = orig_envp; cpp && *cpp; ptr++, cpp++)
1050 *ptr = (addr_t)copy_str(&strtab, *cpp);
1051 *ptr++ = 0;
1052
1053 /* --- auxv --- */
1054 auxv = (struct ume_auxv *)ptr;
1055 *client_auxv = (UInt *)auxv;
1056
1057 for (; orig_auxv->a_type != AT_NULL; auxv++, orig_auxv++) {
1058 /* copy the entry... */
1059 *auxv = *orig_auxv;
1060
1061 /* ...and fix up the copy */
1062 switch(auxv->a_type) {
1063 case AT_PHDR:
1064 if (info->phdr == 0)
1065 auxv->a_type = AT_IGNORE;
1066 else
1067 auxv->u.a_val = info->phdr;
1068 break;
1069
1070 case AT_PHNUM:
1071 if (info->phdr == 0)
1072 auxv->a_type = AT_IGNORE;
1073 else
1074 auxv->u.a_val = info->phnum;
1075 break;
1076
1077 case AT_BASE:
1078 if (info->interp_base == 0)
1079 auxv->a_type = AT_IGNORE;
1080 else
1081 auxv->u.a_val = info->interp_base;
1082 break;
1083
1084 case AT_PLATFORM: /* points to a platform description string */
1085 auxv->u.a_ptr = copy_str(&strtab, orig_auxv->u.a_ptr);
1086 break;
1087
1088 case AT_ENTRY:
1089 auxv->u.a_val = info->entry;
1090 break;
1091
1092 case AT_IGNORE:
1093 case AT_EXECFD:
1094 case AT_PHENT:
1095 case AT_PAGESZ:
1096 case AT_FLAGS:
1097 case AT_NOTELF:
1098 case AT_UID:
1099 case AT_EUID:
1100 case AT_GID:
1101 case AT_EGID:
1102 case AT_CLKTCK:
1103 case AT_HWCAP:
1104 case AT_FPUCW:
1105 case AT_DCACHEBSIZE:
1106 case AT_ICACHEBSIZE:
1107 case AT_UCACHEBSIZE:
1108 /* All these are pointerless, so we don't need to do anything
1109 about them. */
1110 break;
1111
1112 case AT_SECURE:
1113 /* If this is 1, then it means that this program is running
1114 suid, and therefore the dynamic linker should be careful
1115 about LD_PRELOAD, etc. However, since stage1 (the thing
1116 the kernel actually execve's) should never be SUID, and we
1117 need LD_PRELOAD/LD_LIBRARY_PATH to work for the client, we
1118 set AT_SECURE to 0. */
1119 auxv->u.a_val = 0;
1120 break;
1121
1122 case AT_SYSINFO:
1123 /* Leave this unmolested for now, but we'll update it later
1124 when we set up the client trampoline code page */
1125 break;
1126
1127 case AT_SYSINFO_EHDR:
1128 /* Trash this, because we don't reproduce it */
1129 auxv->a_type = AT_IGNORE;
1130 break;
1131
1132 default:
1133 /* stomp out anything we don't know about */
1134 if (0)
1135 printf("stomping auxv entry %d\n", auxv->a_type);
1136 auxv->a_type = AT_IGNORE;
1137 break;
1138
1139 }
1140 }
1141 *auxv = *orig_auxv;
1142 vg_assert(auxv->a_type == AT_NULL);
1143
1144 vg_assert((strtab-stringbase) == stringsize);
1145
1146 return cl_esp;
1147}
1148
1149/*====================================================================*/
1150/*=== Find executable ===*/
1151/*====================================================================*/
1152
1153static const char* find_executable(const char* exec)
1154{
1155 vg_assert(NULL != exec);
1156 if (strchr(exec, '/') == NULL) {
1157 /* no '/' - we need to search the path */
1158 char *path = getenv("PATH");
1159 int pathlen = path ? strlen(path) : 0;
1160
1161 int match_exe(const char *entry) {
1162 char buf[pathlen + strlen(entry) + 3];
1163
1164 /* empty PATH element means . */
1165 if (*entry == '\0')
1166 entry = ".";
1167
1168 snprintf(buf, sizeof(buf), "%s/%s", entry, exec);
1169
1170 if (access(buf, R_OK|X_OK) == 0) {
1171 exec = strdup(buf);
1172 vg_assert(NULL != exec);
1173 return 1;
1174 }
1175 return 0;
1176 }
1177 scan_colsep(path, match_exe);
1178 }
1179 return exec;
1180}
1181
1182
1183/*====================================================================*/
1184/*=== Loading tools ===*/
1185/*====================================================================*/
1186
1187static void list_tools(void)
1188{
1189 DIR *dir = opendir(VG_(libdir));
1190 struct dirent *de;
1191 int first = 1;
1192
1193 if (dir == NULL) {
1194 fprintf(stderr, "Can't open %s: %s (installation problem?)\n",
1195 VG_(libdir), strerror(errno));
1196 return;
1197 }
1198
1199 while((de = readdir(dir)) != NULL) {
1200 int len = strlen(de->d_name);
1201
1202 /* look for vgskin_TOOL.so names */
1203 if (len > (7+1+3) && /* "vgskin_" + at least 1-char toolname + ".so" */
1204 strncmp(de->d_name, "vgskin_", 7) == 0 &&
1205 VG_STREQ(de->d_name + len - 3, ".so")) {
1206 if (first) {
1207 printf("Available tools:\n");
1208 first = 0;
1209 }
1210 de->d_name[len-3] = '\0';
1211 printf("\t%s\n", de->d_name+7);
1212 }
1213 }
1214
1215 closedir(dir);
1216
1217 if (first)
1218 printf("No tools available in \"%s\" (installation problem?)\n",
1219 VG_(libdir));
1220}
1221
1222
1223/* Find and load a tool, and check it looks ok. Also looks to see if there's
1224 * a matching vgpreload_*.so file, and returns its name in *preloadpath. */
1225static void load_tool( const char *toolname, void** handle_out,
1226 ToolInfo** toolinfo_out, char **preloadpath_out )
1227{
1228 Bool ok;
1229 int len = strlen(VG_(libdir)) + strlen(toolname)*2 + 16;
1230 char buf[len];
1231 void* handle;
1232 ToolInfo* toolinfo;
1233 char* preloadpath = NULL;
1234 Int* vg_malloc_redzonep;
1235
1236 // XXX: allowing full paths for --tool option -- does it make sense?
1237 // Doesn't allow for vgpreload_<tool>.so.
1238
1239 if (strchr(toolname, '/') != 0) {
1240 /* toolname contains '/', and so must be a pathname */
1241 handle = dlopen(toolname, RTLD_NOW);
1242 } else {
1243 /* just try in the libdir */
1244 snprintf(buf, len, "%s/vgskin_%s.so", VG_(libdir), toolname);
1245 handle = dlopen(buf, RTLD_NOW);
1246
1247 if (handle != NULL) {
1248 snprintf(buf, len, "%s/vgpreload_%s.so", VG_(libdir), toolname);
1249 if (access(buf, R_OK) == 0) {
1250 preloadpath = strdup(buf);
1251 vg_assert(NULL != preloadpath);
1252 }
1253 }
1254 }
1255
1256 ok = (NULL != handle);
1257 if (!ok) {
1258 fprintf(stderr, "Can't open tool \"%s\": %s\n", toolname, dlerror());
1259 goto bad_load;
1260 }
1261
1262 toolinfo = dlsym(handle, "vgSkin_tool_info");
1263 ok = (NULL != toolinfo);
1264 if (!ok) {
1265 fprintf(stderr, "Tool \"%s\" doesn't define SK_(tool_info) - "
1266 "add VG_DETERMINE_INTERFACE_VERSION?\n", toolname);
1267 goto bad_load;
1268 }
1269
1270 ok = (toolinfo->sizeof_ToolInfo == sizeof(*toolinfo) &&
1271 toolinfo->interface_major_version == VG_CORE_INTERFACE_MAJOR_VERSION &&
1272 toolinfo->sk_pre_clo_init != NULL);
1273 if (!ok) {
1274 fprintf(stderr, "Error:\n"
1275 " Tool and core interface versions do not match.\n"
1276 " Interface version used by core is: %d.%d (size %d)\n"
1277 " Interface version used by tool is: %d.%d (size %d)\n"
1278 " The major version numbers must match.\n",
1279 VG_CORE_INTERFACE_MAJOR_VERSION,
1280 VG_CORE_INTERFACE_MINOR_VERSION,
1281 sizeof(*toolinfo),
1282 toolinfo->interface_major_version,
1283 toolinfo->interface_minor_version,
1284 toolinfo->sizeof_ToolInfo);
1285 fprintf(stderr, " You need to at least recompile, and possibly update,\n");
1286 if (VG_CORE_INTERFACE_MAJOR_VERSION > toolinfo->interface_major_version)
1287 fprintf(stderr, " your skin to work with this version of Valgrind.\n");
1288 else
1289 fprintf(stderr, " your version of Valgrind to work with this skin.\n");
1290 goto bad_load;
1291 }
1292
1293 // Set redzone size for V's allocator
1294 vg_malloc_redzonep = dlsym(handle, STR(VG_(vg_malloc_redzone_szB)));
1295 if ( NULL != vg_malloc_redzonep ) {
1296 VG_(vg_malloc_redzone_szB) = *vg_malloc_redzonep;
1297 }
1298
1299 vg_assert(NULL != handle && NULL != toolinfo);
1300 *handle_out = handle;
1301 *toolinfo_out = toolinfo;
1302 *preloadpath_out = preloadpath;
1303 return;
1304
1305
1306 bad_load:
1307 if (handle != NULL)
1308 dlclose(handle);
1309
1310 fprintf(stderr, "Aborting: couldn't load tool\n");
1311 list_tools();
1312 exit(127);
1313}
1314
1315/*====================================================================*/
1316/*=== Loading the client ===*/
1317/*====================================================================*/
1318
1319static void load_client(char* cl_argv[], const char* exec,
1320 /*inout*/Bool* need_help,
1321 /*out*/struct exeinfo* info, /*out*/Addr* client_eip)
1322{
1323 // If they didn't specify an executable with --exec, and didn't specify
1324 // --help, then use client argv[0] (searching $PATH if necessary).
1325 if (NULL == exec && !*need_help) {
1326 if (cl_argv[0] == NULL ||
1327 ( NULL == (exec = find_executable(cl_argv[0])) ) )
1328 {
1329 *need_help = True;
1330 }
1331 }
1332
1333 info->map_base = VG_(client_mapbase);
1334 info->setbrk = False;
1335
1336 info->exe_base = VG_(client_base);
1337 info->exe_end = VG_(client_end);
1338 info->argv = cl_argv;
1339
1340 if (*need_help) {
1341 VG_(clexecfd) = -1;
1342 info->argv0 = NULL;
1343 info->argv1 = NULL;
1344 } else {
1345 Int ret;
1346 VG_(clexecfd) = VG_(open)(exec, O_RDONLY, VKI_S_IRUSR);
1347 ret = do_exec(exec, info);
1348 if (ret != 0) {
1349 fprintf(stderr, "do_exec(%s) failed: %s\n", exec, strerror(ret));
1350 exit(127);
1351 }
1352 }
1353
1354 /* Copy necessary bits of 'info' that were filled in */
1355 *client_eip = info->init_eip;
1356 VG_(brk_base) = VG_(brk_limit) = info->brkbase;
1357}
1358
1359
1360/*====================================================================*/
1361/*=== Command-line: variables, processing ===*/
1362/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +00001363
njn25e49d8e72002-09-23 09:36:25 +00001364/* Define, and set defaults. */
1365Bool VG_(clo_error_limit) = True;
1366Bool VG_(clo_GDB_attach) = False;
sewardj6024b212003-07-13 10:54:33 +00001367Char* VG_(clo_GDB_path) = GDB_PATH;
njn43c799e2003-04-08 00:08:52 +00001368Bool VG_(clo_gen_suppressions) = False;
njn25e49d8e72002-09-23 09:36:25 +00001369Int VG_(sanity_level) = 1;
1370Int VG_(clo_verbosity) = 1;
1371Bool VG_(clo_demangle) = True;
njn25e49d8e72002-09-23 09:36:25 +00001372Bool VG_(clo_trace_children) = False;
sewardj4cf05692002-10-27 20:28:29 +00001373
nethercotee1730692003-11-20 10:38:07 +00001374/* See big comment in vg_include.h for meaning of these three.
1375 fd is initially stdout, for --help, but gets moved to stderr by default
1376 immediately afterwards. */
sewardj4cf05692002-10-27 20:28:29 +00001377VgLogTo VG_(clo_log_to) = VgLogTo_Fd;
nethercotee1730692003-11-20 10:38:07 +00001378Int VG_(clo_logfile_fd) = 1;
sewardj4cf05692002-10-27 20:28:29 +00001379Char* VG_(clo_logfile_name) = NULL;
1380
sewardj6024b212003-07-13 10:54:33 +00001381Int VG_(clo_input_fd) = 0; /* stdin */
njn25e49d8e72002-09-23 09:36:25 +00001382Int VG_(clo_n_suppressions) = 0;
sewardjde4a1d02002-03-22 01:27:54 +00001383Char* VG_(clo_suppressions)[VG_CLO_MAX_SFILES];
njn25e49d8e72002-09-23 09:36:25 +00001384Bool VG_(clo_profile) = False;
1385Bool VG_(clo_single_step) = False;
1386Bool VG_(clo_optimise) = True;
1387UChar VG_(clo_trace_codegen) = 0; // 00000000b
1388Bool VG_(clo_trace_syscalls) = False;
1389Bool VG_(clo_trace_signals) = False;
1390Bool VG_(clo_trace_symtab) = False;
njn25e49d8e72002-09-23 09:36:25 +00001391Bool VG_(clo_trace_sched) = False;
1392Int VG_(clo_trace_pthread_level) = 0;
sewardj59438c02003-01-05 12:16:30 +00001393ULong VG_(clo_stop_after) = 1000000000000000LL;
njn25e49d8e72002-09-23 09:36:25 +00001394Int VG_(clo_dump_error) = 0;
1395Int VG_(clo_backtrace_size) = 4;
1396Char* VG_(clo_weird_hacks) = NULL;
sewardj858964b2002-10-05 14:15:43 +00001397Bool VG_(clo_run_libc_freeres) = True;
rjwalshf5f536f2003-11-17 17:45:00 +00001398Bool VG_(clo_track_fds) = False;
sewardj22854b92002-11-30 14:00:47 +00001399Bool VG_(clo_chain_bb) = True;
nethercote77eba602003-11-13 17:35:04 +00001400Bool VG_(clo_show_below_main) = False;
fitzhardinge98abfc72003-12-16 02:05:15 +00001401Bool VG_(clo_pointercheck) = True;
fitzhardinge462f4f92003-12-18 02:10:54 +00001402Bool VG_(clo_branchpred) = False;
sewardj2370f3b2002-11-30 15:01:01 +00001403
jsgf855d93d2003-10-13 22:26:55 +00001404static Bool VG_(clo_wait_for_gdb) = False;
1405
1406/* If we're doing signal routing, poll for signals every 50mS by
1407 default. */
1408Int VG_(clo_signal_polltime) = 50;
1409
1410/* These flags reduce thread wakeup latency on syscall completion and
1411 signal delivery, respectively. The downside is possible unfairness. */
1412Bool VG_(clo_lowlat_syscalls) = False; /* low-latency syscalls */
1413Bool VG_(clo_lowlat_signals) = False; /* low-latency signals */
1414
sewardjde4a1d02002-03-22 01:27:54 +00001415
njn25e49d8e72002-09-23 09:36:25 +00001416void VG_(bad_option) ( Char* opt )
sewardjde4a1d02002-03-22 01:27:54 +00001417{
1418 VG_(shutdown_logging)();
sewardj4cf05692002-10-27 20:28:29 +00001419 VG_(clo_log_to) = VgLogTo_Fd;
sewardjde4a1d02002-03-22 01:27:54 +00001420 VG_(clo_logfile_fd) = 2; /* stderr */
1421 VG_(printf)("valgrind.so: Bad option `%s'; aborting.\n", opt);
1422 VG_(exit)(1);
1423}
1424
1425static void config_error ( Char* msg )
1426{
1427 VG_(shutdown_logging)();
sewardj4cf05692002-10-27 20:28:29 +00001428 VG_(clo_log_to) = VgLogTo_Fd;
sewardjde4a1d02002-03-22 01:27:54 +00001429 VG_(clo_logfile_fd) = 2; /* stderr */
sewardj19d81412002-06-03 01:10:40 +00001430 VG_(printf)(
fitzhardinge98abfc72003-12-16 02:05:15 +00001431 "valgrind: Startup or configuration error:\n %s\n", msg);
sewardj19d81412002-06-03 01:10:40 +00001432 VG_(printf)(
fitzhardinge98abfc72003-12-16 02:05:15 +00001433 "valgrind: Unable to start up properly. Giving up.\n");
sewardjde4a1d02002-03-22 01:27:54 +00001434 VG_(exit)(1);
1435}
1436
nethercote71980f02004-01-24 18:18:54 +00001437void usage ( void )
njn7cf0bd32002-06-08 13:36:03 +00001438{
njn25e49d8e72002-09-23 09:36:25 +00001439 Char* usage1 =
nethercote71980f02004-01-24 18:18:54 +00001440"usage: valgrind --tool=<toolname> [options] prog-and-args\n"
njn25e49d8e72002-09-23 09:36:25 +00001441"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001442" common user options for all Valgrind tools, with defaults in [ ]:\n"
nethercote71980f02004-01-24 18:18:54 +00001443" --tool=<name> Use the Valgrind tool named <name>\n"
njn25e49d8e72002-09-23 09:36:25 +00001444" --help show this message\n"
1445" --version show version\n"
njn25e49d8e72002-09-23 09:36:25 +00001446" -q --quiet run silently; only print error msgs\n"
1447" -v --verbose be more verbose, incl counts of errors\n"
nethercote77eba602003-11-13 17:35:04 +00001448" --trace-children=no|yes Valgrind-ise child processes? [no]\n"
rjwalshf5f536f2003-11-17 17:45:00 +00001449" --track-fds=no|yes Track open file descriptors? [no]\n"
nethercote2b0793f2003-12-02 10:41:18 +00001450"\n"
1451" uncommon user options for all Valgrind tools:\n"
nethercote77eba602003-11-13 17:35:04 +00001452" --run-libc-freeres=no|yes Free up glibc memory at exit? [yes]\n"
1453" --weird-hacks=hack1,hack2,... [none]\n"
sewardj3d652a32002-10-20 18:11:49 +00001454" recognised hacks are: ioctl-VTIME truncate-writes lax-ioctls\n"
jsgf855d93d2003-10-13 22:26:55 +00001455" --signal-polltime=<time> time, in mS, we should poll for signals.\n"
1456" Only applies for older kernels which need\n"
1457" signal routing [50]\n"
1458" --lowlat-signals=no|yes improve wake-up latency when a thread receives\n"
1459" a signal [no]\n"
1460" --lowlat-syscalls=no|yes improve wake-up latency when a thread's\n"
1461" syscall completes [no]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001462" --pointercheck=no|yes enforce client address space limits [yes]\n"
njn25e49d8e72002-09-23 09:36:25 +00001463"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001464" user options for Valgrind tools that report errors:\n"
1465" --logfile-fd=<number> file descriptor for messages [2=stderr]\n"
1466" --logfile=<file> log messages to <file>.pid<pid>\n"
1467" --logsocket=ipaddr:port log messages to socket ipaddr:port\n"
1468" --demangle=no|yes automatically demangle C++ names? [yes]\n"
1469" --num-callers=<number> show <num> callers in stack traces [4]\n"
1470" --error-limit=no|yes stop showing new errors if too many? [yes]\n"
1471" --show-below-main=no|yes continue stack traces below main() [no]\n"
1472" --suppressions=<filename> suppress errors described in <filename>\n"
1473" --gen-suppressions=no|yes print suppressions for errors detected [no]\n"
njn7cf0bd32002-06-08 13:36:03 +00001474
nethercote2b0793f2003-12-02 10:41:18 +00001475" --gdb-attach=no|yes start GDB when errors detected? [no]\n"
1476" --gdb-path=/path/to/gdb path to the GDB to use [/usr/bin/gdb]\n"
1477" --input-fd=<number> file descriptor for (gdb) input [0=stdin]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001478"\n";
njn7cf0bd32002-06-08 13:36:03 +00001479
njn25e49d8e72002-09-23 09:36:25 +00001480 Char* usage2 =
1481"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001482" debugging options for all Valgrind tools:\n"
njn25e49d8e72002-09-23 09:36:25 +00001483" --sanity-level=<number> level of sanity checking to do [1]\n"
1484" --single-step=no|yes translate each instr separately? [no]\n"
1485" --optimise=no|yes improve intermediate code? [yes]\n"
nethercote137bc552003-11-14 17:47:54 +00001486" --profile=no|yes profile? (tool must be built for it) [no]\n"
sewardj22854b92002-11-30 14:00:47 +00001487" --chain-bb=no|yes do basic-block chaining? [yes]\n"
fitzhardinge462f4f92003-12-18 02:10:54 +00001488" --branchpred=yes|no generate branch prediction hints [no]\n"
njn25e49d8e72002-09-23 09:36:25 +00001489" --trace-codegen=<XXXXX> show generated code? (X = 0|1) [00000]\n"
1490" --trace-syscalls=no|yes show all system calls? [no]\n"
1491" --trace-signals=no|yes show signal handling details? [no]\n"
1492" --trace-symtab=no|yes show symbol table details? [no]\n"
njn25e49d8e72002-09-23 09:36:25 +00001493" --trace-sched=no|yes show thread scheduler details? [no]\n"
njn3e884182003-04-15 13:03:23 +00001494" --trace-pthread=none|some|all show pthread event details? [none]\n"
njn25e49d8e72002-09-23 09:36:25 +00001495" --stop-after=<number> switch to real CPU after executing\n"
1496" <number> basic blocks [infinity]\n"
jsgf855d93d2003-10-13 22:26:55 +00001497" --wait-for-gdb=yes|no pause on startup to wait for gdb attach\n"
njn25e49d8e72002-09-23 09:36:25 +00001498"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001499" debugging options for Valgrind tools that report errors\n"
1500" --dump-error=<number> show translation for basic block associated\n"
1501" with <number>'th error context [0=show none]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001502"\n";
njn3e884182003-04-15 13:03:23 +00001503
1504 Char* usage3 =
1505"\n"
nethercote71980f02004-01-24 18:18:54 +00001506" Extra options read from ~/.valgrindrc, $VALGRIND_OPTS, ./.valgrindrc\n"
njn25e49d8e72002-09-23 09:36:25 +00001507"\n"
nethercotebb1c9912004-01-04 16:43:23 +00001508" Valgrind is Copyright (C) 2000-2004 Julian Seward\n"
njn25e49d8e72002-09-23 09:36:25 +00001509" and licensed under the GNU General Public License, version 2.\n"
1510" Bug reports, feedback, admiration, abuse, etc, to: %s.\n"
njnd04b7c62002-10-03 14:05:52 +00001511"\n"
nethercote137bc552003-11-14 17:47:54 +00001512" Tools are copyright and licensed by their authors. See each\n"
1513" tool's start-up message for more information.\n"
njn25e49d8e72002-09-23 09:36:25 +00001514"\n";
njn7cf0bd32002-06-08 13:36:03 +00001515
fitzhardinge98abfc72003-12-16 02:05:15 +00001516 VG_(printf)(usage1);
1517 if (VG_(details).name) {
1518 VG_(printf)(" user options for %s:\n", VG_(details).name);
1519 /* Don't print skin string directly for security, ha! */
1520 if (VG_(needs).command_line_options)
1521 SK_(print_usage)();
1522 else
1523 VG_(printf)(" (none)\n");
1524 }
1525 VG_(printf)(usage2);
1526
1527 if (VG_(details).name) {
1528 VG_(printf)(" debugging options for %s:\n", VG_(details).name);
1529
1530 if (VG_(needs).command_line_options)
1531 SK_(print_debug_usage)();
1532 else
1533 VG_(printf)(" (none)\n");
1534 }
nethercote421281e2003-11-20 16:20:55 +00001535 VG_(printf)(usage3, VG_BUGS_TO);
njn7cf0bd32002-06-08 13:36:03 +00001536
njn25e49d8e72002-09-23 09:36:25 +00001537 VG_(shutdown_logging)();
sewardj4cf05692002-10-27 20:28:29 +00001538 VG_(clo_log_to) = VgLogTo_Fd;
njn25e49d8e72002-09-23 09:36:25 +00001539 VG_(clo_logfile_fd) = 2; /* stderr */
1540 VG_(exit)(1);
njn7cf0bd32002-06-08 13:36:03 +00001541}
sewardjde4a1d02002-03-22 01:27:54 +00001542
nethercote71980f02004-01-24 18:18:54 +00001543static void pre_process_cmd_line_options
1544 ( Bool* need_help, const char** tool, const char** exec )
sewardj1c1b1162003-02-23 01:25:51 +00001545{
nethercote71980f02004-01-24 18:18:54 +00001546 UInt i;
sewardjde4a1d02002-03-22 01:27:54 +00001547
nethercote71980f02004-01-24 18:18:54 +00001548 /* parse the options we have (only the options we care about now) */
1549 for (i = 1; i < VG_(vg_argc); i++) {
1550
1551 if (strcmp(VG_(vg_argv)[i], "--version") == 0) {
1552 printf("valgrind-" VERSION "\n");
1553 exit(1);
1554
1555 } else if (strcmp(VG_(vg_argv)[i], "--help") == 0) {
1556 *need_help = True;
1557
1558 } else if (strncmp(VG_(vg_argv)[i], "--tool=", 7) == 0 ||
1559 strncmp(VG_(vg_argv)[i], "--skin=", 7) == 0) {
1560 *tool = &VG_(vg_argv)[i][7];
1561
1562 } else if (strncmp(VG_(vg_argv)[i], "--exec=", 7) == 0) {
1563 *exec = &VG_(vg_argv)[i][7];
1564 }
1565 }
1566
1567 /* If no tool specified, can give usage message without loading tool */
1568 if (*tool == NULL) {
1569 if (!need_help)
1570 list_tools();
1571 usage();
1572 }
1573}
1574
1575static void process_cmd_line_options
1576 ( UInt* client_auxv, Addr esp_at_startup,
1577 const char* toolname, Bool need_help )
1578{
1579 Int i, eventually_logfile_fd;
1580 Int *auxp;
1581 Int toolname_len = VG_(strlen)(toolname);
sewardjde4a1d02002-03-22 01:27:54 +00001582
nethercotee1730692003-11-20 10:38:07 +00001583 /* log to stderr by default, but usage message goes to stdout */
1584 eventually_logfile_fd = 2;
sewardjde4a1d02002-03-22 01:27:54 +00001585
1586 /* Once logging is started, we can safely send messages pertaining
1587 to failures in initialisation. */
1588 VG_(startup_logging)();
1589
sewardj19d81412002-06-03 01:10:40 +00001590 /* Check for sane path in ./configure --prefix=... */
fitzhardinge98abfc72003-12-16 02:05:15 +00001591 if (VG_LIBDIR[0] != '/')
sewardj19d81412002-06-03 01:10:40 +00001592 config_error("Please use absolute paths in "
1593 "./configure --prefix=... or --libdir=...");
sewardj38170912002-05-10 21:07:22 +00001594
nethercote71980f02004-01-24 18:18:54 +00001595 for (auxp = client_auxv; auxp[0] != VKI_AT_NULL; auxp += 2) {
fitzhardinge98abfc72003-12-16 02:05:15 +00001596 switch(auxp[0]) {
1597 case VKI_AT_SYSINFO:
1598 VG_(sysinfo_page_exists) = True;
fitzhardinge92360792003-12-24 10:11:11 +00001599 auxp[1] = (Int)(VG_(client_trampoline_code) + VG_(tramp_syscall_offset));
fitzhardinge98abfc72003-12-16 02:05:15 +00001600 VG_(sysinfo_page_addr) = auxp[1];
1601 break;
sewardjde4a1d02002-03-22 01:27:54 +00001602 }
fitzhardinge98abfc72003-12-16 02:05:15 +00001603 }
sewardjde4a1d02002-03-22 01:27:54 +00001604
nethercote71980f02004-01-24 18:18:54 +00001605 if (need_help)
1606 usage();
fitzhardinge98abfc72003-12-16 02:05:15 +00001607
1608 /* We know the initial ESP is pointing at argc/argv */
nethercote71980f02004-01-24 18:18:54 +00001609 VG_(client_argc) = *(Int *)esp_at_startup;
1610 VG_(client_argv) = (Char **)(esp_at_startup + sizeof(Int));
fitzhardinge98abfc72003-12-16 02:05:15 +00001611
nethercote71980f02004-01-24 18:18:54 +00001612 for (i = 1; i < VG_(vg_argc); i++) {
1613
1614 Char* arg = VG_(vg_argv)[i];
1615
1616 // XXX: allow colons in options, for Josef
1617
1618 /* Look for matching "--toolname:foo" */
1619 if (VG_(strstr)(arg, ":")) {
1620 if (VG_CLO_STREQN(2, arg, "--") &&
1621 VG_CLO_STREQN(toolname_len, arg+2, toolname) &&
1622 VG_CLO_STREQN(1, arg+2+toolname_len, ":"))
1623 {
1624 // prefix matches, convert "--toolname:foo" to "--foo"
1625 if (0)
1626 VG_(printf)("tool-specific arg: %s\n", arg);
1627 arg += toolname_len + 1;
1628 arg[0] = '-';
1629 arg[1] = '-';
1630
1631 } else {
1632 // prefix doesn't match, skip to next arg
1633 continue;
1634 }
1635 }
1636
fitzhardinge98abfc72003-12-16 02:05:15 +00001637 /* Ignore these options - they've already been handled */
nethercote71980f02004-01-24 18:18:54 +00001638 if (VG_CLO_STREQN(7, arg, "--tool=") ||
1639 VG_CLO_STREQN(7, arg, "--skin="))
fitzhardinge98abfc72003-12-16 02:05:15 +00001640 continue;
nethercote71980f02004-01-24 18:18:54 +00001641 if (VG_CLO_STREQN(7, arg, "--exec="))
fitzhardinge98abfc72003-12-16 02:05:15 +00001642 continue;
1643
nethercote71980f02004-01-24 18:18:54 +00001644 if ( VG_CLO_STREQ(arg, "--"))
fitzhardinge98abfc72003-12-16 02:05:15 +00001645 continue;
nethercote71980f02004-01-24 18:18:54 +00001646 else if (VG_CLO_STREQ(arg, "-v") ||
1647 VG_CLO_STREQ(arg, "--verbose"))
sewardjde4a1d02002-03-22 01:27:54 +00001648 VG_(clo_verbosity)++;
nethercote71980f02004-01-24 18:18:54 +00001649 else if (VG_CLO_STREQ(arg, "-q") ||
1650 VG_CLO_STREQ(arg, "--quiet"))
sewardjde4a1d02002-03-22 01:27:54 +00001651 VG_(clo_verbosity)--;
1652
nethercote71980f02004-01-24 18:18:54 +00001653 else if (VG_CLO_STREQ(arg, "--error-limit=yes"))
sewardj2e432902002-06-13 20:44:00 +00001654 VG_(clo_error_limit) = True;
nethercote71980f02004-01-24 18:18:54 +00001655 else if (VG_CLO_STREQ(arg, "--error-limit=no"))
sewardj2e432902002-06-13 20:44:00 +00001656 VG_(clo_error_limit) = False;
sewardj72f98ff2002-06-13 17:23:38 +00001657
nethercote71980f02004-01-24 18:18:54 +00001658 else if (VG_CLO_STREQ(arg, "--gdb-attach=yes"))
sewardjde4a1d02002-03-22 01:27:54 +00001659 VG_(clo_GDB_attach) = True;
nethercote71980f02004-01-24 18:18:54 +00001660 else if (VG_CLO_STREQ(arg, "--gdb-attach=no"))
sewardjde4a1d02002-03-22 01:27:54 +00001661 VG_(clo_GDB_attach) = False;
1662
nethercote71980f02004-01-24 18:18:54 +00001663 else if (VG_CLO_STREQN(11,arg, "--gdb-path="))
1664 VG_(clo_GDB_path) = &arg[11];
sewardj6024b212003-07-13 10:54:33 +00001665
nethercote71980f02004-01-24 18:18:54 +00001666 else if (VG_CLO_STREQ(arg, "--gen-suppressions=yes"))
njn43c799e2003-04-08 00:08:52 +00001667 VG_(clo_gen_suppressions) = True;
nethercote71980f02004-01-24 18:18:54 +00001668 else if (VG_CLO_STREQ(arg, "--gen-suppressions=no"))
njn43c799e2003-04-08 00:08:52 +00001669 VG_(clo_gen_suppressions) = False;
1670
nethercote71980f02004-01-24 18:18:54 +00001671 else if (VG_CLO_STREQ(arg, "--show-below-main=yes"))
nethercote77eba602003-11-13 17:35:04 +00001672 VG_(clo_show_below_main) = True;
nethercote71980f02004-01-24 18:18:54 +00001673 else if (VG_CLO_STREQ(arg, "--show-below-main=no"))
nethercote77eba602003-11-13 17:35:04 +00001674 VG_(clo_show_below_main) = False;
1675
nethercote71980f02004-01-24 18:18:54 +00001676 else if (VG_CLO_STREQ(arg, "--pointercheck=yes"))
fitzhardinge98abfc72003-12-16 02:05:15 +00001677 VG_(clo_pointercheck) = True;
nethercote71980f02004-01-24 18:18:54 +00001678 else if (VG_CLO_STREQ(arg, "--pointercheck=no"))
fitzhardinge98abfc72003-12-16 02:05:15 +00001679 VG_(clo_pointercheck) = False;
1680
nethercote71980f02004-01-24 18:18:54 +00001681 else if (VG_CLO_STREQ(arg, "--demangle=yes"))
sewardjde4a1d02002-03-22 01:27:54 +00001682 VG_(clo_demangle) = True;
nethercote71980f02004-01-24 18:18:54 +00001683 else if (VG_CLO_STREQ(arg, "--demangle=no"))
sewardjde4a1d02002-03-22 01:27:54 +00001684 VG_(clo_demangle) = False;
1685
nethercote71980f02004-01-24 18:18:54 +00001686 else if (VG_CLO_STREQ(arg, "--trace-children=yes"))
sewardjde4a1d02002-03-22 01:27:54 +00001687 VG_(clo_trace_children) = True;
nethercote71980f02004-01-24 18:18:54 +00001688 else if (VG_CLO_STREQ(arg, "--trace-children=no"))
sewardjde4a1d02002-03-22 01:27:54 +00001689 VG_(clo_trace_children) = False;
1690
nethercote71980f02004-01-24 18:18:54 +00001691 else if (VG_CLO_STREQ(arg, "--run-libc-freeres=yes"))
sewardj858964b2002-10-05 14:15:43 +00001692 VG_(clo_run_libc_freeres) = True;
nethercote71980f02004-01-24 18:18:54 +00001693 else if (VG_CLO_STREQ(arg, "--run-libc-freeres=no"))
sewardj858964b2002-10-05 14:15:43 +00001694 VG_(clo_run_libc_freeres) = False;
1695
nethercote71980f02004-01-24 18:18:54 +00001696 else if (VG_CLO_STREQ(arg, "--track-fds=yes"))
rjwalshf5f536f2003-11-17 17:45:00 +00001697 VG_(clo_track_fds) = True;
nethercote71980f02004-01-24 18:18:54 +00001698 else if (VG_CLO_STREQ(arg, "--track-fds=no"))
rjwalshf5f536f2003-11-17 17:45:00 +00001699 VG_(clo_track_fds) = False;
1700
nethercote71980f02004-01-24 18:18:54 +00001701 else if (VG_CLO_STREQN(15, arg, "--sanity-level="))
1702 VG_(sanity_level) = (Int)VG_(atoll)(&arg[15]);
sewardjde4a1d02002-03-22 01:27:54 +00001703
nethercote71980f02004-01-24 18:18:54 +00001704 else if (VG_CLO_STREQN(13, arg, "--logfile-fd=")) {
sewardj4cf05692002-10-27 20:28:29 +00001705 VG_(clo_log_to) = VgLogTo_Fd;
1706 VG_(clo_logfile_name) = NULL;
nethercote71980f02004-01-24 18:18:54 +00001707 eventually_logfile_fd = (Int)VG_(atoll)(&arg[13]);
sewardj4cf05692002-10-27 20:28:29 +00001708 }
1709
nethercote71980f02004-01-24 18:18:54 +00001710 else if (VG_CLO_STREQN(10, arg, "--logfile=")) {
sewardj4cf05692002-10-27 20:28:29 +00001711 VG_(clo_log_to) = VgLogTo_File;
nethercote71980f02004-01-24 18:18:54 +00001712 VG_(clo_logfile_name) = &arg[10];
sewardj4cf05692002-10-27 20:28:29 +00001713 }
sewardjde4a1d02002-03-22 01:27:54 +00001714
nethercote71980f02004-01-24 18:18:54 +00001715 else if (VG_CLO_STREQN(12, arg, "--logsocket=")) {
sewardj73cf3bc2002-11-03 03:20:15 +00001716 VG_(clo_log_to) = VgLogTo_Socket;
nethercote71980f02004-01-24 18:18:54 +00001717 VG_(clo_logfile_name) = &arg[12];
sewardj73cf3bc2002-11-03 03:20:15 +00001718 }
1719
nethercote71980f02004-01-24 18:18:54 +00001720 else if (VG_CLO_STREQN(11, arg, "--input-fd="))
1721 VG_(clo_input_fd) = (Int)VG_(atoll)(&arg[11]);
sewardj6024b212003-07-13 10:54:33 +00001722
nethercote71980f02004-01-24 18:18:54 +00001723 else if (VG_CLO_STREQN(15, arg, "--suppressions=")) {
sewardjde4a1d02002-03-22 01:27:54 +00001724 if (VG_(clo_n_suppressions) >= VG_CLO_MAX_SFILES) {
njn25e49d8e72002-09-23 09:36:25 +00001725 VG_(message)(Vg_UserMsg, "Too many suppression files specified.");
sewardjde4a1d02002-03-22 01:27:54 +00001726 VG_(message)(Vg_UserMsg,
1727 "Increase VG_CLO_MAX_SFILES and recompile.");
nethercote71980f02004-01-24 18:18:54 +00001728 VG_(bad_option)(arg);
sewardjde4a1d02002-03-22 01:27:54 +00001729 }
nethercote71980f02004-01-24 18:18:54 +00001730 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = &arg[15];
sewardjde4a1d02002-03-22 01:27:54 +00001731 VG_(clo_n_suppressions)++;
1732 }
nethercote71980f02004-01-24 18:18:54 +00001733 else if (VG_CLO_STREQ(arg, "--profile=yes"))
njn25e49d8e72002-09-23 09:36:25 +00001734 VG_(clo_profile) = True;
nethercote71980f02004-01-24 18:18:54 +00001735 else if (VG_CLO_STREQ(arg, "--profile=no"))
njn25e49d8e72002-09-23 09:36:25 +00001736 VG_(clo_profile) = False;
1737
nethercote71980f02004-01-24 18:18:54 +00001738 else if (VG_CLO_STREQ(arg, "--chain-bb=yes"))
sewardj22854b92002-11-30 14:00:47 +00001739 VG_(clo_chain_bb) = True;
nethercote71980f02004-01-24 18:18:54 +00001740 else if (VG_CLO_STREQ(arg, "--chain-bb=no"))
sewardj22854b92002-11-30 14:00:47 +00001741 VG_(clo_chain_bb) = False;
1742
nethercote71980f02004-01-24 18:18:54 +00001743 else if (VG_CLO_STREQ(arg, "--branchpred=yes"))
fitzhardinge462f4f92003-12-18 02:10:54 +00001744 VG_(clo_branchpred) = True;
nethercote71980f02004-01-24 18:18:54 +00001745 else if (VG_CLO_STREQ(arg, "--branchpred=no"))
fitzhardinge462f4f92003-12-18 02:10:54 +00001746 VG_(clo_branchpred) = False;
1747
nethercote71980f02004-01-24 18:18:54 +00001748 else if (VG_CLO_STREQ(arg, "--single-step=yes"))
sewardjde4a1d02002-03-22 01:27:54 +00001749 VG_(clo_single_step) = True;
nethercote71980f02004-01-24 18:18:54 +00001750 else if (VG_CLO_STREQ(arg, "--single-step=no"))
sewardjde4a1d02002-03-22 01:27:54 +00001751 VG_(clo_single_step) = False;
1752
nethercote71980f02004-01-24 18:18:54 +00001753 else if (VG_CLO_STREQ(arg, "--optimise=yes"))
sewardjde4a1d02002-03-22 01:27:54 +00001754 VG_(clo_optimise) = True;
nethercote71980f02004-01-24 18:18:54 +00001755 else if (VG_CLO_STREQ(arg, "--optimise=no"))
sewardjde4a1d02002-03-22 01:27:54 +00001756 VG_(clo_optimise) = False;
1757
njn25e49d8e72002-09-23 09:36:25 +00001758 /* "vwxyz" --> 000zyxwv (binary) */
nethercote71980f02004-01-24 18:18:54 +00001759 else if (VG_CLO_STREQN(16, arg, "--trace-codegen=")) {
njn25e49d8e72002-09-23 09:36:25 +00001760 Int j;
nethercote71980f02004-01-24 18:18:54 +00001761 char* opt = & arg[16];
njn25e49d8e72002-09-23 09:36:25 +00001762
1763 if (5 != VG_(strlen)(opt)) {
1764 VG_(message)(Vg_UserMsg,
1765 "--trace-codegen argument must have 5 digits");
nethercote71980f02004-01-24 18:18:54 +00001766 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001767 }
1768 for (j = 0; j < 5; j++) {
1769 if ('0' == opt[j]) { /* do nothing */ }
1770 else if ('1' == opt[j]) VG_(clo_trace_codegen) |= (1 << j);
1771 else {
1772 VG_(message)(Vg_UserMsg, "--trace-codegen argument can only "
1773 "contain 0s and 1s");
nethercote71980f02004-01-24 18:18:54 +00001774 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001775 }
1776 }
1777 }
sewardjde4a1d02002-03-22 01:27:54 +00001778
nethercote71980f02004-01-24 18:18:54 +00001779 else if (VG_CLO_STREQ(arg, "--trace-syscalls=yes"))
sewardjde4a1d02002-03-22 01:27:54 +00001780 VG_(clo_trace_syscalls) = True;
nethercote71980f02004-01-24 18:18:54 +00001781 else if (VG_CLO_STREQ(arg, "--trace-syscalls=no"))
sewardjde4a1d02002-03-22 01:27:54 +00001782 VG_(clo_trace_syscalls) = False;
1783
nethercote71980f02004-01-24 18:18:54 +00001784 else if (VG_CLO_STREQ(arg, "--trace-signals=yes"))
sewardjde4a1d02002-03-22 01:27:54 +00001785 VG_(clo_trace_signals) = True;
nethercote71980f02004-01-24 18:18:54 +00001786 else if (VG_CLO_STREQ(arg, "--trace-signals=no"))
sewardjde4a1d02002-03-22 01:27:54 +00001787 VG_(clo_trace_signals) = False;
1788
nethercote71980f02004-01-24 18:18:54 +00001789 else if (VG_CLO_STREQ(arg, "--trace-symtab=yes"))
sewardjde4a1d02002-03-22 01:27:54 +00001790 VG_(clo_trace_symtab) = True;
nethercote71980f02004-01-24 18:18:54 +00001791 else if (VG_CLO_STREQ(arg, "--trace-symtab=no"))
sewardjde4a1d02002-03-22 01:27:54 +00001792 VG_(clo_trace_symtab) = False;
1793
nethercote71980f02004-01-24 18:18:54 +00001794 else if (VG_CLO_STREQ(arg, "--trace-sched=yes"))
sewardj8937c812002-04-12 20:12:20 +00001795 VG_(clo_trace_sched) = True;
nethercote71980f02004-01-24 18:18:54 +00001796 else if (VG_CLO_STREQ(arg, "--trace-sched=no"))
sewardj8937c812002-04-12 20:12:20 +00001797 VG_(clo_trace_sched) = False;
1798
nethercote71980f02004-01-24 18:18:54 +00001799 else if (VG_CLO_STREQ(arg, "--trace-pthread=none"))
sewardj45b4b372002-04-16 22:50:32 +00001800 VG_(clo_trace_pthread_level) = 0;
nethercote71980f02004-01-24 18:18:54 +00001801 else if (VG_CLO_STREQ(arg, "--trace-pthread=some"))
sewardj45b4b372002-04-16 22:50:32 +00001802 VG_(clo_trace_pthread_level) = 1;
nethercote71980f02004-01-24 18:18:54 +00001803 else if (VG_CLO_STREQ(arg, "--trace-pthread=all"))
sewardj45b4b372002-04-16 22:50:32 +00001804 VG_(clo_trace_pthread_level) = 2;
sewardj8937c812002-04-12 20:12:20 +00001805
nethercote71980f02004-01-24 18:18:54 +00001806 else if (VG_CLO_STREQN(14, arg, "--weird-hacks="))
1807 VG_(clo_weird_hacks) = &arg[14];
sewardj3984b852002-05-12 03:00:17 +00001808
nethercote71980f02004-01-24 18:18:54 +00001809 else if (VG_CLO_STREQN(17, arg, "--signal-polltime="))
1810 VG_(clo_signal_polltime) = VG_(atoll)(&arg[17]);
jsgf855d93d2003-10-13 22:26:55 +00001811
nethercote71980f02004-01-24 18:18:54 +00001812 else if (VG_CLO_STREQ(arg, "--lowlat-signals=yes"))
jsgf855d93d2003-10-13 22:26:55 +00001813 VG_(clo_lowlat_signals) = True;
nethercote71980f02004-01-24 18:18:54 +00001814 else if (VG_CLO_STREQ(arg, "--lowlat-signals=no"))
jsgf855d93d2003-10-13 22:26:55 +00001815 VG_(clo_lowlat_signals) = False;
1816
nethercote71980f02004-01-24 18:18:54 +00001817 else if (VG_CLO_STREQ(arg, "--lowlat-syscalls=yes"))
jsgf855d93d2003-10-13 22:26:55 +00001818 VG_(clo_lowlat_syscalls) = True;
nethercote71980f02004-01-24 18:18:54 +00001819 else if (VG_CLO_STREQ(arg, "--lowlat-syscalls=no"))
jsgf855d93d2003-10-13 22:26:55 +00001820 VG_(clo_lowlat_syscalls) = False;
1821
nethercote71980f02004-01-24 18:18:54 +00001822 else if (VG_CLO_STREQN(13, arg, "--stop-after="))
1823 VG_(clo_stop_after) = VG_(atoll)(&arg[13]);
sewardjde4a1d02002-03-22 01:27:54 +00001824
nethercote71980f02004-01-24 18:18:54 +00001825 else if (VG_CLO_STREQN(13, arg, "--dump-error="))
1826 VG_(clo_dump_error) = (Int)VG_(atoll)(&arg[13]);
sewardjde4a1d02002-03-22 01:27:54 +00001827
nethercote71980f02004-01-24 18:18:54 +00001828 else if (VG_CLO_STREQ(arg, "--wait-for-gdb=yes"))
jsgf855d93d2003-10-13 22:26:55 +00001829 VG_(clo_wait_for_gdb) = True;
nethercote71980f02004-01-24 18:18:54 +00001830 else if (VG_CLO_STREQ(arg, "--wait-for-gdb=no"))
jsgf855d93d2003-10-13 22:26:55 +00001831 VG_(clo_wait_for_gdb) = False;
1832
nethercote71980f02004-01-24 18:18:54 +00001833 else if (VG_CLO_STREQN(14, arg, "--num-callers=")) {
sewardjde4a1d02002-03-22 01:27:54 +00001834 /* Make sure it's sane. */
nethercote71980f02004-01-24 18:18:54 +00001835 VG_(clo_backtrace_size) = (Int)VG_(atoll)(&arg[14]);
njn6c846552003-09-16 07:41:43 +00001836 if (VG_(clo_backtrace_size) < 1)
1837 VG_(clo_backtrace_size) = 1;
sewardjde4a1d02002-03-22 01:27:54 +00001838 if (VG_(clo_backtrace_size) >= VG_DEEPEST_BACKTRACE)
1839 VG_(clo_backtrace_size) = VG_DEEPEST_BACKTRACE;
1840 }
1841
nethercote71980f02004-01-24 18:18:54 +00001842 else if ( ! VG_(needs).command_line_options
1843 || ! SK_(process_cmd_line_option)(arg) ) {
1844 usage();
njn25e49d8e72002-09-23 09:36:25 +00001845 }
sewardjde4a1d02002-03-22 01:27:54 +00001846 }
1847
njnf9ebf672003-05-12 21:41:30 +00001848 if (VG_(clo_verbosity) < 0)
sewardjde4a1d02002-03-22 01:27:54 +00001849 VG_(clo_verbosity) = 0;
1850
1851 if (VG_(clo_GDB_attach) && VG_(clo_trace_children)) {
1852 VG_(message)(Vg_UserMsg, "");
1853 VG_(message)(Vg_UserMsg,
1854 "--gdb-attach=yes conflicts with --trace-children=yes");
1855 VG_(message)(Vg_UserMsg,
1856 "Please choose one or the other, but not both.");
njn25e49d8e72002-09-23 09:36:25 +00001857 VG_(bad_option)("--gdb-attach=yes and --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001858 }
1859
sewardj4cf05692002-10-27 20:28:29 +00001860 /* Set up logging now. After this is done, VG_(clo_logfile_fd)
1861 should be connected to whatever sink has been selected, and we
1862 indiscriminately chuck stuff into it without worrying what the
1863 nature of it is. Oh the wonder of Unix streams. */
1864
nethercotee1730692003-11-20 10:38:07 +00001865 /* So far we should be still attached to stdout, so we can show on
sewardj4cf05692002-10-27 20:28:29 +00001866 the terminal any problems to do with processing command line
1867 opts. */
nethercotee1730692003-11-20 10:38:07 +00001868 vg_assert(VG_(clo_logfile_fd) == 1 /* stdout */);
sewardj73cf3bc2002-11-03 03:20:15 +00001869 vg_assert(VG_(logging_to_filedes) == True);
sewardj4cf05692002-10-27 20:28:29 +00001870
1871 switch (VG_(clo_log_to)) {
sewardj73cf3bc2002-11-03 03:20:15 +00001872
sewardj4cf05692002-10-27 20:28:29 +00001873 case VgLogTo_Fd:
1874 vg_assert(VG_(clo_logfile_name) == NULL);
1875 VG_(clo_logfile_fd) = eventually_logfile_fd;
1876 break;
sewardj73cf3bc2002-11-03 03:20:15 +00001877
sewardj4cf05692002-10-27 20:28:29 +00001878 case VgLogTo_File: {
1879 Char logfilename[1000];
jsgff3c3f1a2003-10-14 22:13:28 +00001880 Int seq = 0;
1881 Int pid = VG_(getpid)();
1882
sewardj4cf05692002-10-27 20:28:29 +00001883 vg_assert(VG_(clo_logfile_name) != NULL);
1884 vg_assert(VG_(strlen)(VG_(clo_logfile_name)) <= 900); /* paranoia */
jsgff3c3f1a2003-10-14 22:13:28 +00001885
nethercote71980f02004-01-24 18:18:54 +00001886 for (;;) {
jsgff3c3f1a2003-10-14 22:13:28 +00001887 if (seq == 0)
1888 VG_(sprintf)(logfilename, "%s.pid%d",
1889 VG_(clo_logfile_name), pid );
1890 else
1891 VG_(sprintf)(logfilename, "%s.pid%d.%d",
1892 VG_(clo_logfile_name), pid, seq );
1893 seq++;
1894
1895 eventually_logfile_fd
1896 = VG_(open)(logfilename,
1897 VKI_O_CREAT|VKI_O_WRONLY|VKI_O_EXCL|VKI_O_TRUNC,
1898 VKI_S_IRUSR|VKI_S_IWUSR);
1899 if (eventually_logfile_fd >= 0) {
fitzhardinge9b8c2f32004-01-06 00:15:26 +00001900 VG_(clo_logfile_fd) = VG_(safe_fd)(eventually_logfile_fd);
jsgff3c3f1a2003-10-14 22:13:28 +00001901 break;
1902 } else {
1903 if (eventually_logfile_fd != -VKI_EEXIST) {
1904 VG_(message)(Vg_UserMsg,
1905 "Can't create/open log file `%s.pid%d'; giving up!",
1906 VG_(clo_logfile_name), pid);
1907 VG_(bad_option)(
1908 "--logfile=<file> didn't work out for some reason.");
1909 break;
1910 }
1911 }
1912 }
sewardj4cf05692002-10-27 20:28:29 +00001913 break;
sewardj73cf3bc2002-11-03 03:20:15 +00001914 }
1915
1916 case VgLogTo_Socket: {
1917 vg_assert(VG_(clo_logfile_name) != NULL);
1918 vg_assert(VG_(strlen)(VG_(clo_logfile_name)) <= 900); /* paranoia */
1919 eventually_logfile_fd
1920 = VG_(connect_via_socket)( VG_(clo_logfile_name) );
1921 if (eventually_logfile_fd == -1) {
1922 VG_(message)(Vg_UserMsg,
1923 "Invalid --logsocket=ipaddr or --logsocket=ipaddr:port spec");
1924 VG_(message)(Vg_UserMsg,
1925 "of `%s'; giving up!", VG_(clo_logfile_name) );
1926 VG_(bad_option)(
1927 "--logsocket=");
sewardj4cf05692002-10-27 20:28:29 +00001928 }
sewardj73cf3bc2002-11-03 03:20:15 +00001929 if (eventually_logfile_fd == -2) {
1930 VG_(message)(Vg_UserMsg,
sewardj570f8902002-11-03 11:44:36 +00001931 "valgrind: failed to connect to logging server `%s'.",
sewardj73cf3bc2002-11-03 03:20:15 +00001932 VG_(clo_logfile_name) );
sewardj570f8902002-11-03 11:44:36 +00001933 VG_(message)(Vg_UserMsg,
1934 "Log messages will sent to stderr instead." );
1935 VG_(message)(Vg_UserMsg,
1936 "" );
1937 /* We don't change anything here. */
1938 } else {
1939 vg_assert(eventually_logfile_fd > 0);
1940 VG_(clo_logfile_fd) = eventually_logfile_fd;
1941 VG_(logging_to_filedes) = False;
1942 }
sewardj73cf3bc2002-11-03 03:20:15 +00001943 break;
1944 }
1945
sewardj4cf05692002-10-27 20:28:29 +00001946 }
1947
jsgf855d93d2003-10-13 22:26:55 +00001948 /* Move logfile_fd into the safe range, so it doesn't conflict with any app fds */
fitzhardingef0046f22003-12-18 02:39:22 +00001949 eventually_logfile_fd = VG_(fcntl)(VG_(clo_logfile_fd), VKI_F_DUPFD, VG_(max_fd)+1);
jsgf855d93d2003-10-13 22:26:55 +00001950 if (eventually_logfile_fd < 0)
1951 VG_(message)(Vg_UserMsg, "valgrind: failed to move logfile fd into safe range");
1952 else {
1953 VG_(clo_logfile_fd) = eventually_logfile_fd;
1954 VG_(fcntl)(VG_(clo_logfile_fd), VKI_F_SETFD, VKI_FD_CLOEXEC);
1955 }
1956
sewardj4cf05692002-10-27 20:28:29 +00001957 /* Ok, the logging sink is running now. Print a suitable preamble.
1958 If logging to file or a socket, write details of parent PID and
1959 command line args, to help people trying to interpret the
1960 results of a run which encompasses multiple processes. */
sewardjde4a1d02002-03-22 01:27:54 +00001961
sewardj83adf412002-05-01 01:25:45 +00001962 if (VG_(clo_verbosity > 0)) {
njnd04b7c62002-10-03 14:05:52 +00001963 /* Skin details */
1964 VG_(message)(Vg_UserMsg, "%s%s%s, %s for x86-linux.",
1965 VG_(details).name,
1966 NULL == VG_(details).version ? "" : "-",
1967 NULL == VG_(details).version
1968 ? (Char*)"" : VG_(details).version,
1969 VG_(details).description);
1970 VG_(message)(Vg_UserMsg, "%s", VG_(details).copyright_author);
sewardj3b2736a2002-03-24 12:18:35 +00001971
njnd04b7c62002-10-03 14:05:52 +00001972 /* Core details */
1973 VG_(message)(Vg_UserMsg,
njn3e884182003-04-15 13:03:23 +00001974 "Using valgrind-%s, a program supervision framework for x86-linux.",
sewardj4aa62ba2002-10-05 15:49:27 +00001975 VERSION);
sewardjde4a1d02002-03-22 01:27:54 +00001976 VG_(message)(Vg_UserMsg,
nethercotebb1c9912004-01-04 16:43:23 +00001977 "Copyright (C) 2000-2004, and GNU GPL'd, by Julian Seward.");
njnd04b7c62002-10-03 14:05:52 +00001978 }
1979
nethercotec1e395d2003-11-10 13:26:49 +00001980 if (VG_(clo_verbosity) > 0 && VG_(clo_log_to) != VgLogTo_Fd) {
sewardj4cf05692002-10-27 20:28:29 +00001981 VG_(message)(Vg_UserMsg, "");
1982 VG_(message)(Vg_UserMsg,
1983 "My PID = %d, parent PID = %d. Prog and args are:",
1984 VG_(getpid)(), VG_(getppid)() );
1985 for (i = 0; i < VG_(client_argc); i++)
1986 VG_(message)(Vg_UserMsg, " %s", VG_(client_argv)[i]);
1987 }
1988
sewardjde4a1d02002-03-22 01:27:54 +00001989 if (VG_(clo_verbosity) > 1) {
sewardj4cf05692002-10-27 20:28:29 +00001990 if (VG_(clo_log_to) != VgLogTo_Fd)
1991 VG_(message)(Vg_UserMsg, "");
fitzhardinge98abfc72003-12-16 02:05:15 +00001992 VG_(message)(Vg_UserMsg, "Valgrind library directory: %s", VG_(libdir));
njn86dc2bc2003-09-09 07:26:21 +00001993 VG_(message)(Vg_UserMsg, "Command line");
1994 for (i = 0; i < VG_(client_argc); i++)
1995 VG_(message)(Vg_UserMsg, " %s", VG_(client_argv)[i]);
1996
sewardjde4a1d02002-03-22 01:27:54 +00001997 VG_(message)(Vg_UserMsg, "Startup, with flags:");
nethercote71980f02004-01-24 18:18:54 +00001998 for (i = 1; i < VG_(vg_argc); i++) {
1999 VG_(message)(Vg_UserMsg, " %s", VG_(vg_argv)[i]);
sewardjde4a1d02002-03-22 01:27:54 +00002000 }
2001 }
2002
fitzhardinge98abfc72003-12-16 02:05:15 +00002003 if (VG_(clo_n_suppressions) < VG_CLO_MAX_SFILES-1 &&
njn25e49d8e72002-09-23 09:36:25 +00002004 (VG_(needs).core_errors || VG_(needs).skin_errors)) {
fitzhardinge98abfc72003-12-16 02:05:15 +00002005 /* If there are no suppression files specified and the skin
2006 needs one, load the default */
2007 static const Char default_supp[] = "default.supp";
2008 Int len = VG_(strlen)(VG_(libdir)) + 1 + sizeof(default_supp);
2009 Char *buf = VG_(arena_malloc)(VG_AR_CORE, len);
2010 VG_(sprintf)(buf, "%s/%s", VG_(libdir), default_supp);
2011 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = buf;
2012 VG_(clo_n_suppressions)++;
sewardjde4a1d02002-03-22 01:27:54 +00002013 }
sewardj4cf05692002-10-27 20:28:29 +00002014
njn6a230532003-07-21 10:38:23 +00002015 if (VG_(clo_gen_suppressions) &&
2016 !VG_(needs).core_errors && !VG_(needs).skin_errors) {
2017 config_error("Can't use --gen-suppressions=yes with this skin,\n"
2018 " as it doesn't generate errors.");
2019 }
2020
nethercote71980f02004-01-24 18:18:54 +00002021 VG_(bbs_to_go) = VG_(clo_stop_after);
sewardjde4a1d02002-03-22 01:27:54 +00002022}
2023
sewardjde4a1d02002-03-22 01:27:54 +00002024
nethercote71980f02004-01-24 18:18:54 +00002025/*====================================================================*/
2026/*=== File descriptor setup ===*/
2027/*====================================================================*/
2028
2029static void setup_file_descriptors(void)
2030{
2031 struct vki_rlimit rl;
2032
2033 /* Get the current file descriptor limits. */
2034 if (VG_(getrlimit)(VKI_RLIMIT_NOFILE, &rl) < 0) {
2035 rl.rlim_cur = 1024;
2036 rl.rlim_max = 1024;
2037 }
2038
2039 /* Work out where to move the soft limit to. */
2040 if (rl.rlim_cur + VG_N_RESERVED_FDS <= rl.rlim_max) {
2041 rl.rlim_cur = rl.rlim_cur + VG_N_RESERVED_FDS;
2042 } else {
2043 rl.rlim_cur = rl.rlim_max;
2044 }
2045
2046 /* Reserve some file descriptors for our use. */
2047 VG_(max_fd) = rl.rlim_cur - VG_N_RESERVED_FDS;
2048
2049 /* Update the soft limit. */
2050 VG_(setrlimit)(VKI_RLIMIT_NOFILE, &rl);
2051
2052 if (VG_(vgexecfd) != -1)
2053 VG_(vgexecfd) = VG_(safe_fd)( VG_(vgexecfd) );
2054 if (VG_(clexecfd) != -1)
2055 VG_(clexecfd) = VG_(safe_fd)( VG_(clexecfd) );
2056}
2057
2058
2059/*====================================================================*/
2060/*=== m_state_static + baseBlock: definition, setup, copying ===*/
2061/*====================================================================*/
2062
2063/* The variables storing offsets. */
2064
2065#define INVALID_OFFSET (-1)
2066
2067Int VGOFF_(m_eax) = INVALID_OFFSET;
2068Int VGOFF_(m_ecx) = INVALID_OFFSET;
2069Int VGOFF_(m_edx) = INVALID_OFFSET;
2070Int VGOFF_(m_ebx) = INVALID_OFFSET;
2071Int VGOFF_(m_esp) = INVALID_OFFSET;
2072Int VGOFF_(m_ebp) = INVALID_OFFSET;
2073Int VGOFF_(m_esi) = INVALID_OFFSET;
2074Int VGOFF_(m_edi) = INVALID_OFFSET;
2075Int VGOFF_(m_eflags) = INVALID_OFFSET;
2076Int VGOFF_(m_dflag) = INVALID_OFFSET;
2077Int VGOFF_(m_ssestate) = INVALID_OFFSET;
2078Int VGOFF_(ldt) = INVALID_OFFSET;
2079Int VGOFF_(tls) = INVALID_OFFSET;
2080Int VGOFF_(m_cs) = INVALID_OFFSET;
2081Int VGOFF_(m_ss) = INVALID_OFFSET;
2082Int VGOFF_(m_ds) = INVALID_OFFSET;
2083Int VGOFF_(m_es) = INVALID_OFFSET;
2084Int VGOFF_(m_fs) = INVALID_OFFSET;
2085Int VGOFF_(m_gs) = INVALID_OFFSET;
2086Int VGOFF_(m_eip) = INVALID_OFFSET;
2087Int VGOFF_(spillslots) = INVALID_OFFSET;
2088Int VGOFF_(sh_eax) = INVALID_OFFSET;
2089Int VGOFF_(sh_ecx) = INVALID_OFFSET;
2090Int VGOFF_(sh_edx) = INVALID_OFFSET;
2091Int VGOFF_(sh_ebx) = INVALID_OFFSET;
2092Int VGOFF_(sh_esp) = INVALID_OFFSET;
2093Int VGOFF_(sh_ebp) = INVALID_OFFSET;
2094Int VGOFF_(sh_esi) = INVALID_OFFSET;
2095Int VGOFF_(sh_edi) = INVALID_OFFSET;
2096Int VGOFF_(sh_eflags) = INVALID_OFFSET;
2097
2098Int VGOFF_(helper_idiv_64_32) = INVALID_OFFSET;
2099Int VGOFF_(helper_div_64_32) = INVALID_OFFSET;
2100Int VGOFF_(helper_idiv_32_16) = INVALID_OFFSET;
2101Int VGOFF_(helper_div_32_16) = INVALID_OFFSET;
2102Int VGOFF_(helper_idiv_16_8) = INVALID_OFFSET;
2103Int VGOFF_(helper_div_16_8) = INVALID_OFFSET;
2104Int VGOFF_(helper_imul_32_64) = INVALID_OFFSET;
2105Int VGOFF_(helper_mul_32_64) = INVALID_OFFSET;
2106Int VGOFF_(helper_imul_16_32) = INVALID_OFFSET;
2107Int VGOFF_(helper_mul_16_32) = INVALID_OFFSET;
2108Int VGOFF_(helper_imul_8_16) = INVALID_OFFSET;
2109Int VGOFF_(helper_mul_8_16) = INVALID_OFFSET;
2110Int VGOFF_(helper_CLD) = INVALID_OFFSET;
2111Int VGOFF_(helper_STD) = INVALID_OFFSET;
2112Int VGOFF_(helper_get_dirflag) = INVALID_OFFSET;
2113Int VGOFF_(helper_CLC) = INVALID_OFFSET;
2114Int VGOFF_(helper_STC) = INVALID_OFFSET;
2115Int VGOFF_(helper_shldl) = INVALID_OFFSET;
2116Int VGOFF_(helper_shldw) = INVALID_OFFSET;
2117Int VGOFF_(helper_shrdl) = INVALID_OFFSET;
2118Int VGOFF_(helper_shrdw) = INVALID_OFFSET;
2119Int VGOFF_(helper_IN) = INVALID_OFFSET;
2120Int VGOFF_(helper_OUT) = INVALID_OFFSET;
2121Int VGOFF_(helper_RDTSC) = INVALID_OFFSET;
2122Int VGOFF_(helper_CPUID) = INVALID_OFFSET;
2123Int VGOFF_(helper_BSWAP) = INVALID_OFFSET;
2124Int VGOFF_(helper_bsf) = INVALID_OFFSET;
2125Int VGOFF_(helper_bsr) = INVALID_OFFSET;
2126Int VGOFF_(helper_fstsw_AX) = INVALID_OFFSET;
2127Int VGOFF_(helper_SAHF) = INVALID_OFFSET;
2128Int VGOFF_(helper_LAHF) = INVALID_OFFSET;
2129Int VGOFF_(helper_DAS) = INVALID_OFFSET;
2130Int VGOFF_(helper_DAA) = INVALID_OFFSET;
2131Int VGOFF_(helper_cmpxchg8b) = INVALID_OFFSET;
2132Int VGOFF_(helper_undefined_instruction) = INVALID_OFFSET;
2133
2134/* MAX_NONCOMPACT_HELPERS can be increased easily. If MAX_COMPACT_HELPERS is
2135 * increased too much, they won't really be compact any more... */
2136#define MAX_COMPACT_HELPERS 8
2137#define MAX_NONCOMPACT_HELPERS 50
2138
2139UInt VG_(n_compact_helpers) = 0;
2140UInt VG_(n_noncompact_helpers) = 0;
2141
2142Addr VG_(compact_helper_addrs) [MAX_COMPACT_HELPERS];
2143Int VG_(compact_helper_offsets)[MAX_COMPACT_HELPERS];
2144Addr VG_(noncompact_helper_addrs) [MAX_NONCOMPACT_HELPERS];
2145Int VG_(noncompact_helper_offsets)[MAX_NONCOMPACT_HELPERS];
2146
2147/* This is the actual defn of baseblock. */
2148UInt VG_(baseBlock)[VG_BASEBLOCK_WORDS];
2149
2150/* See comment about this in vg_include.h. Change only with great care. */
sewardjb91ae7f2003-04-29 23:50:00 +00002151__attribute__ ((aligned (16)))
sewardj92a59562002-09-30 00:53:10 +00002152UInt VG_(m_state_static) [6 /* segment regs, Intel order */
2153 + 8 /* int regs, in Intel order */
sewardjde4a1d02002-03-22 01:27:54 +00002154 + 1 /* %eflags */
2155 + 1 /* %eip */
sewardjb91ae7f2003-04-29 23:50:00 +00002156 + VG_SIZE_OF_SSESTATE_W /* FPU state */
sewardjde4a1d02002-03-22 01:27:54 +00002157 ];
2158
nethercote71980f02004-01-24 18:18:54 +00002159/* Words. */
2160static Int baB_off = 0;
2161
2162
sewardjfa492d42002-12-08 18:20:01 +00002163UInt VG_(insertDflag)(UInt eflags, Int d)
2164{
2165 vg_assert(d == 1 || d == -1);
2166 eflags &= ~EFlagD;
2167
2168 if (d < 0)
2169 eflags |= EFlagD;
2170
2171 return eflags;
2172}
2173
2174Int VG_(extractDflag)(UInt eflags)
2175{
2176 Int ret;
2177
2178 if (eflags & EFlagD)
2179 ret = -1;
2180 else
2181 ret = 1;
2182
2183 return ret;
2184}
2185
nethercote71980f02004-01-24 18:18:54 +00002186static void copy_baseBlock_to_m_state_static( void )
sewardjde4a1d02002-03-22 01:27:54 +00002187{
2188 Int i;
sewardj92a59562002-09-30 00:53:10 +00002189 VG_(m_state_static)[ 0/4] = VG_(baseBlock)[VGOFF_(m_cs)];
2190 VG_(m_state_static)[ 4/4] = VG_(baseBlock)[VGOFF_(m_ss)];
2191 VG_(m_state_static)[ 8/4] = VG_(baseBlock)[VGOFF_(m_ds)];
2192 VG_(m_state_static)[12/4] = VG_(baseBlock)[VGOFF_(m_es)];
2193 VG_(m_state_static)[16/4] = VG_(baseBlock)[VGOFF_(m_fs)];
2194 VG_(m_state_static)[20/4] = VG_(baseBlock)[VGOFF_(m_gs)];
sewardjde4a1d02002-03-22 01:27:54 +00002195
sewardj92a59562002-09-30 00:53:10 +00002196 VG_(m_state_static)[24/4] = VG_(baseBlock)[VGOFF_(m_eax)];
2197 VG_(m_state_static)[28/4] = VG_(baseBlock)[VGOFF_(m_ecx)];
2198 VG_(m_state_static)[32/4] = VG_(baseBlock)[VGOFF_(m_edx)];
2199 VG_(m_state_static)[36/4] = VG_(baseBlock)[VGOFF_(m_ebx)];
2200 VG_(m_state_static)[40/4] = VG_(baseBlock)[VGOFF_(m_esp)];
2201 VG_(m_state_static)[44/4] = VG_(baseBlock)[VGOFF_(m_ebp)];
2202 VG_(m_state_static)[48/4] = VG_(baseBlock)[VGOFF_(m_esi)];
2203 VG_(m_state_static)[52/4] = VG_(baseBlock)[VGOFF_(m_edi)];
2204
sewardjb91ae7f2003-04-29 23:50:00 +00002205 VG_(m_state_static)[56/4]
2206 = VG_(insertDflag)(VG_(baseBlock)[VGOFF_(m_eflags)],
2207 VG_(baseBlock)[VGOFF_(m_dflag)]);
sewardj92a59562002-09-30 00:53:10 +00002208 VG_(m_state_static)[60/4] = VG_(baseBlock)[VGOFF_(m_eip)];
sewardjde4a1d02002-03-22 01:27:54 +00002209
sewardjb91ae7f2003-04-29 23:50:00 +00002210 for (i = 0; i < VG_SIZE_OF_SSESTATE_W; i++)
sewardj92a59562002-09-30 00:53:10 +00002211 VG_(m_state_static)[64/4 + i]
sewardjb91ae7f2003-04-29 23:50:00 +00002212 = VG_(baseBlock)[VGOFF_(m_ssestate) + i];
sewardjde4a1d02002-03-22 01:27:54 +00002213}
2214
2215
nethercote71980f02004-01-24 18:18:54 +00002216/* Returns the offset, in words. */
2217static Int alloc_BaB ( Int words )
sewardjde4a1d02002-03-22 01:27:54 +00002218{
nethercote71980f02004-01-24 18:18:54 +00002219 Int off = baB_off;
2220 baB_off += words;
2221 if (baB_off >= VG_BASEBLOCK_WORDS)
2222 VG_(core_panic)( "alloc_BaB: baseBlock is too small");
sewardjde4a1d02002-03-22 01:27:54 +00002223
nethercote71980f02004-01-24 18:18:54 +00002224 return off;
sewardjde4a1d02002-03-22 01:27:54 +00002225}
2226
nethercote71980f02004-01-24 18:18:54 +00002227/* Align offset, in *bytes* */
2228static void align_BaB ( UInt align )
njn25e49d8e72002-09-23 09:36:25 +00002229{
nethercote71980f02004-01-24 18:18:54 +00002230 vg_assert(2 == align || 4 == align || 8 == align || 16 == align);
2231 baB_off += (align-1);
2232 baB_off &= ~(align-1);
njn25e49d8e72002-09-23 09:36:25 +00002233}
2234
nethercote71980f02004-01-24 18:18:54 +00002235/* Allocate 1 word in baseBlock and set it to the given value. */
2236static Int alloc_BaB_1_set ( Addr a )
njn25e49d8e72002-09-23 09:36:25 +00002237{
nethercote71980f02004-01-24 18:18:54 +00002238 Int off = alloc_BaB(1);
2239 VG_(baseBlock)[off] = (UInt)a;
2240 return off;
njn25e49d8e72002-09-23 09:36:25 +00002241}
2242
nethercote71980f02004-01-24 18:18:54 +00002243/* Registers a function in compact_helper_addrs; compact_helper_offsets is
2244 filled in later. */
2245void VG_(register_compact_helper)(Addr a)
sewardjde4a1d02002-03-22 01:27:54 +00002246{
nethercote71980f02004-01-24 18:18:54 +00002247 if (MAX_COMPACT_HELPERS <= VG_(n_compact_helpers)) {
2248 VG_(printf)("Can only register %d compact helpers\n",
2249 MAX_COMPACT_HELPERS);
2250 VG_(core_panic)("Too many compact helpers registered");
2251 }
2252 VG_(compact_helper_addrs)[VG_(n_compact_helpers)] = a;
2253 VG_(n_compact_helpers)++;
2254}
2255
2256/* Registers a function in noncompact_helper_addrs; noncompact_helper_offsets
2257 * is filled in later.
2258 */
2259void VG_(register_noncompact_helper)(Addr a)
2260{
2261 if (MAX_NONCOMPACT_HELPERS <= VG_(n_noncompact_helpers)) {
2262 VG_(printf)("Can only register %d non-compact helpers\n",
2263 MAX_NONCOMPACT_HELPERS);
2264 VG_(printf)("Try increasing MAX_NON_COMPACT_HELPERS\n");
2265 VG_(core_panic)("Too many non-compact helpers registered");
2266 }
2267 VG_(noncompact_helper_addrs)[VG_(n_noncompact_helpers)] = a;
2268 VG_(n_noncompact_helpers)++;
2269}
2270
2271/* Allocate offsets in baseBlock for the skin helpers */
2272static
2273void assign_helpers_in_baseBlock(UInt n, Int offsets[], Addr addrs[])
2274{
2275 UInt i;
2276 for (i = 0; i < n; i++)
2277 offsets[i] = alloc_BaB_1_set( addrs[i] );
2278}
2279
2280Bool VG_(need_to_handle_esp_assignment)(void)
2281{
2282 return ( VG_(defined_new_mem_stack_4)() ||
2283 VG_(defined_die_mem_stack_4)() ||
2284 VG_(defined_new_mem_stack_8)() ||
2285 VG_(defined_die_mem_stack_8)() ||
2286 VG_(defined_new_mem_stack_12)() ||
2287 VG_(defined_die_mem_stack_12)() ||
2288 VG_(defined_new_mem_stack_16)() ||
2289 VG_(defined_die_mem_stack_16)() ||
2290 VG_(defined_new_mem_stack_32)() ||
2291 VG_(defined_die_mem_stack_32)() ||
2292 VG_(defined_new_mem_stack)() ||
2293 VG_(defined_die_mem_stack)()
2294 );
2295}
2296
2297/* Here we assign actual offsets. It's important to get the most
2298 popular referents within 128 bytes of the start, so we can take
2299 advantage of short addressing modes relative to %ebp. Popularity
2300 of offsets was measured on 22 Feb 02 running a KDE application, and
2301 the slots rearranged accordingly, with a 1.5% reduction in total
2302 size of translations. */
2303static void init_baseBlock ( Addr client_eip, Addr esp_at_startup )
2304{
2305 /* Those with offsets under 128 are carefully chosen. */
2306
2307 /* WORD offsets in this column */
2308 /* 0 */ VGOFF_(m_eax) = alloc_BaB_1_set(0);
2309 /* 1 */ VGOFF_(m_ecx) = alloc_BaB_1_set(0);
2310 /* 2 */ VGOFF_(m_edx) = alloc_BaB_1_set(0);
2311 /* 3 */ VGOFF_(m_ebx) = alloc_BaB_1_set(0);
2312 /* 4 */ VGOFF_(m_esp) = alloc_BaB_1_set(esp_at_startup);
2313 /* 5 */ VGOFF_(m_ebp) = alloc_BaB_1_set(0);
2314 /* 6 */ VGOFF_(m_esi) = alloc_BaB_1_set(0);
2315 /* 7 */ VGOFF_(m_edi) = alloc_BaB_1_set(0);
2316 /* 8 */ VGOFF_(m_eflags) = alloc_BaB_1_set(0);
2317
2318 if (VG_(needs).shadow_regs) {
2319 /* 9 */ VGOFF_(sh_eax) = alloc_BaB_1_set(0);
2320 /* 10 */ VGOFF_(sh_ecx) = alloc_BaB_1_set(0);
2321 /* 11 */ VGOFF_(sh_edx) = alloc_BaB_1_set(0);
2322 /* 12 */ VGOFF_(sh_ebx) = alloc_BaB_1_set(0);
2323 /* 13 */ VGOFF_(sh_esp) = alloc_BaB_1_set(0);
2324 /* 14 */ VGOFF_(sh_ebp) = alloc_BaB_1_set(0);
2325 /* 15 */ VGOFF_(sh_esi) = alloc_BaB_1_set(0);
2326 /* 16 */ VGOFF_(sh_edi) = alloc_BaB_1_set(0);
2327 /* 17 */ VGOFF_(sh_eflags) = alloc_BaB_1_set(0);
2328 VG_TRACK( post_regs_write_init );
2329 }
2330
2331 /* 9,10,11 or 18,19,20... depends on number whether shadow regs are used
2332 * and on compact helpers registered */
2333
2334 /* Make these most-frequently-called specialised ones compact, if they
2335 are used. */
2336 if (VG_(defined_new_mem_stack_4)())
2337 VG_(register_compact_helper)( (Addr) VG_(tool_interface).track_new_mem_stack_4);
2338
2339 if (VG_(defined_die_mem_stack_4)())
2340 VG_(register_compact_helper)( (Addr) VG_(tool_interface).track_die_mem_stack_4);
2341
2342 /* (9 or 18) + n_compact_helpers */
2343 /* Allocate slots for compact helpers */
2344 assign_helpers_in_baseBlock(VG_(n_compact_helpers),
2345 VG_(compact_helper_offsets),
2346 VG_(compact_helper_addrs));
2347
2348 /* (9/10 or 18/19) + n_compact_helpers */
2349 VGOFF_(m_eip) = alloc_BaB_1_set(client_eip);
2350
2351 /* There are currently 24 spill slots */
2352 /* (11+/20+ .. 32+/43+) + n_compact_helpers. This can overlap the magic
2353 * boundary at >= 32 words, but most spills are to low numbered spill
2354 * slots, so the ones above the boundary don't see much action. */
2355 VGOFF_(spillslots) = alloc_BaB(VG_MAX_SPILLSLOTS);
2356
2357 /* I gave up counting at this point. Since they're above the
2358 short-amode-boundary, there's no point. */
2359
2360 VGOFF_(m_dflag) = alloc_BaB_1_set(1); // 1 == forward D-flag
2361
2362 /* The FPU/SSE state. This _must_ be 16-byte aligned. Initial
2363 state doesn't matter much, as long as it's not totally borked. */
2364 align_BaB(16);
2365 VGOFF_(m_ssestate) = alloc_BaB(VG_SIZE_OF_SSESTATE_W);
2366 vg_assert(
2367 0 == ( ((UInt)(& VG_(baseBlock)[VGOFF_(m_ssestate)])) % 16 )
sewardj22854b92002-11-30 14:00:47 +00002368 );
2369
fitzhardingec2dbbac2004-01-23 23:09:01 +00002370 /* I assume that if we have SSE2 we also have SSE */
2371 VG_(have_ssestate) =
2372 VG_(cpu_has_feature)(VG_X86_FEAT_FXSR) &&
2373 VG_(cpu_has_feature)(VG_X86_FEAT_SSE);
2374
fitzhardinge98abfc72003-12-16 02:05:15 +00002375 /* set up an initial FPU state (doesn't really matter what it is,
2376 so long as it's somewhat valid) */
2377 if (!VG_(have_ssestate))
nethercote71980f02004-01-24 18:18:54 +00002378 asm volatile("fwait; fnsave %0; fwait; frstor %0; fwait"
2379 :
2380 : "m" (VG_(baseBlock)[VGOFF_(m_ssestate)])
2381 : "cc", "memory");
fitzhardinge98abfc72003-12-16 02:05:15 +00002382 else
nethercote71980f02004-01-24 18:18:54 +00002383 asm volatile("fwait; fxsave %0; fwait; andl $0xffbf, %1;"
2384 "fxrstor %0; fwait"
2385 :
2386 : "m" (VG_(baseBlock)[VGOFF_(m_ssestate)]),
2387 "m" (VG_(baseBlock)[VGOFF_(m_ssestate)+(24/4)])
2388 : "cc", "memory");
fitzhardinge98abfc72003-12-16 02:05:15 +00002389
njn0c7a5b52003-04-30 09:00:33 +00002390 if (0) {
2391 if (VG_(have_ssestate))
2392 VG_(printf)("Looks like a SSE-capable CPU\n");
2393 else
2394 VG_(printf)("Looks like a MMX-only CPU\n");
2395 }
sewardjb91ae7f2003-04-29 23:50:00 +00002396
nethercote71980f02004-01-24 18:18:54 +00002397 /* LDT pointer: pretend the root thread has an empty LDT to start with. */
2398 VGOFF_(ldt) = alloc_BaB_1_set((UInt)NULL);
jsgf855d93d2003-10-13 22:26:55 +00002399
nethercote71980f02004-01-24 18:18:54 +00002400 /* TLS pointer: pretend the root thread has no TLS array for now. */
2401 VGOFF_(tls) = alloc_BaB_1_set((UInt)NULL);
fitzhardingef0046f22003-12-18 02:39:22 +00002402
nethercote71980f02004-01-24 18:18:54 +00002403 /* segment registers */
2404 VGOFF_(m_cs) = alloc_BaB_1_set(0);
2405 VGOFF_(m_ss) = alloc_BaB_1_set(0);
2406 VGOFF_(m_ds) = alloc_BaB_1_set(0);
2407 VGOFF_(m_es) = alloc_BaB_1_set(0);
2408 VGOFF_(m_fs) = alloc_BaB_1_set(0);
2409 VGOFF_(m_gs) = alloc_BaB_1_set(0);
fitzhardingef0046f22003-12-18 02:39:22 +00002410
nethercote71980f02004-01-24 18:18:54 +00002411 VG_(register_noncompact_helper)( (Addr) & VG_(do_useseg) );
fitzhardingef0046f22003-12-18 02:39:22 +00002412
nethercote71980f02004-01-24 18:18:54 +00002413#define REG(kind, size) \
2414 if (VG_(defined_##kind##_mem_stack##size)()) \
2415 VG_(register_noncompact_helper)( \
2416 (Addr) VG_(tool_interface).track_##kind##_mem_stack##size );
2417 REG(new, _8);
2418 REG(new, _12);
2419 REG(new, _16);
2420 REG(new, _32);
2421 REG(new, );
2422 REG(die, _8);
2423 REG(die, _12);
2424 REG(die, _16);
2425 REG(die, _32);
2426 REG(die, );
2427#undef REG
fitzhardingef0046f22003-12-18 02:39:22 +00002428
nethercote71980f02004-01-24 18:18:54 +00002429 if (VG_(need_to_handle_esp_assignment)())
2430 VG_(register_noncompact_helper)((Addr) VG_(unknown_esp_update));
fitzhardingeb791a192003-12-18 07:22:44 +00002431
nethercote71980f02004-01-24 18:18:54 +00002432# define HELPER(name) \
2433 VGOFF_(helper_##name) = alloc_BaB_1_set( (Addr) & VG_(helper_##name))
njn3e884182003-04-15 13:03:23 +00002434
nethercote71980f02004-01-24 18:18:54 +00002435 /* Helper functions. */
2436 HELPER(idiv_64_32); HELPER(div_64_32);
2437 HELPER(idiv_32_16); HELPER(div_32_16);
2438 HELPER(idiv_16_8); HELPER(div_16_8);
fitzhardinge98abfc72003-12-16 02:05:15 +00002439
nethercote71980f02004-01-24 18:18:54 +00002440 HELPER(imul_32_64); HELPER(mul_32_64);
2441 HELPER(imul_16_32); HELPER(mul_16_32);
2442 HELPER(imul_8_16); HELPER(mul_8_16);
njn25e49d8e72002-09-23 09:36:25 +00002443
nethercote71980f02004-01-24 18:18:54 +00002444 HELPER(CLD); HELPER(STD);
2445 HELPER(get_dirflag);
sewardjde4a1d02002-03-22 01:27:54 +00002446
nethercote71980f02004-01-24 18:18:54 +00002447 HELPER(CLC); HELPER(STC);
jsgf855d93d2003-10-13 22:26:55 +00002448
nethercote71980f02004-01-24 18:18:54 +00002449 HELPER(shldl); HELPER(shldw);
2450 HELPER(shrdl); HELPER(shrdw);
njncc7bb472002-10-14 09:25:19 +00002451
nethercote71980f02004-01-24 18:18:54 +00002452 HELPER(RDTSC); HELPER(CPUID);
njncc7bb472002-10-14 09:25:19 +00002453
nethercote71980f02004-01-24 18:18:54 +00002454 HELPER(bsf); HELPER(bsr);
rjwalshf5f536f2003-11-17 17:45:00 +00002455
nethercote71980f02004-01-24 18:18:54 +00002456 HELPER(fstsw_AX);
2457 HELPER(SAHF); HELPER(LAHF);
2458 HELPER(DAS); HELPER(DAA);
2459 HELPER(IN); HELPER(OUT);
2460 HELPER(cmpxchg8b);
sewardj018f7622002-05-15 21:13:39 +00002461
nethercote71980f02004-01-24 18:18:54 +00002462 HELPER(undefined_instruction);
jsgf855d93d2003-10-13 22:26:55 +00002463
nethercote71980f02004-01-24 18:18:54 +00002464# undef HELPER
sewardjde4a1d02002-03-22 01:27:54 +00002465
nethercote71980f02004-01-24 18:18:54 +00002466 /* Allocate slots for noncompact helpers */
2467 assign_helpers_in_baseBlock(VG_(n_noncompact_helpers),
2468 VG_(noncompact_helper_offsets),
2469 VG_(noncompact_helper_addrs));
2470}
sewardjde4a1d02002-03-22 01:27:54 +00002471
sewardj5f07b662002-04-23 16:52:51 +00002472
nethercote71980f02004-01-24 18:18:54 +00002473/*====================================================================*/
2474/*=== Setup pointercheck ===*/
2475/*====================================================================*/
njn25e49d8e72002-09-23 09:36:25 +00002476
nethercote71980f02004-01-24 18:18:54 +00002477static void setup_pointercheck(void)
2478{
2479 int ret;
sewardj2e93c502002-04-12 11:12:52 +00002480
fitzhardinge98abfc72003-12-16 02:05:15 +00002481 if (VG_(clo_pointercheck)) {
nethercote71980f02004-01-24 18:18:54 +00002482 vki_modify_ldt_t ldt = {
2483 VG_POINTERCHECK_SEGIDX, // entry_number
2484 VG_(client_base), // base_addr
2485 (VG_(client_end)-VG_(client_base)) / VKI_BYTES_PER_PAGE, // limit
2486 1, // seg_32bit
2487 0, // contents: data, RW, non-expanding
2488 0, // ! read_exec_only
2489 1, // limit_in_pages
2490 0, // ! seg not present
2491 1, // useable
fitzhardinge98abfc72003-12-16 02:05:15 +00002492 };
nethercote71980f02004-01-24 18:18:54 +00002493 ret = VG_(do_syscall)(__NR_modify_ldt, 1, &ldt, sizeof(ldt));
fitzhardinge98abfc72003-12-16 02:05:15 +00002494 if (ret < 0) {
2495 VG_(message)(Vg_UserMsg,
2496 "Warning: ignoring --pointercheck=yes, "
2497 "because modify_ldt failed (errno=%d)", -ret);
2498 VG_(clo_pointercheck) = False;
2499 }
2500 }
sewardjde4a1d02002-03-22 01:27:54 +00002501}
2502
nethercote71980f02004-01-24 18:18:54 +00002503/*====================================================================*/
2504/*=== Initialise program data/text, etc. ===*/
2505/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +00002506
nethercote71980f02004-01-24 18:18:54 +00002507static void build_valgrind_map_callback
2508 ( Addr start, UInt size, Char rr, Char ww, Char xx,
2509 UInt dev, UInt ino, ULong foffset, const UChar* filename )
sewardjde4a1d02002-03-22 01:27:54 +00002510{
nethercote71980f02004-01-24 18:18:54 +00002511 UInt prot = 0;
2512 UInt flags = SF_MMAP|SF_NOSYMS;
2513 Bool is_stack_segment;
2514
2515 is_stack_segment =
2516 (start == VG_(clstk_base) && (start+size) == VG_(clstk_end));
2517
2518 /* Only record valgrind mappings for now, without loading any
2519 symbols. This is so we know where the free space is before we
2520 start allocating more memory (note: heap is OK, it's just mmap
2521 which is the problem here). */
2522 if (start >= VG_(valgrind_base) && (start+size) <= VG_(valgrind_end)) {
2523 flags |= SF_VALGRIND;
2524 VG_(map_file_segment)(start, size, prot, flags, dev, ino, foffset, filename);
2525 }
sewardjde4a1d02002-03-22 01:27:54 +00002526}
2527
nethercote71980f02004-01-24 18:18:54 +00002528// Global var used to pass local data to callback
2529Addr esp_at_startup___global_arg = 0;
sewardjde4a1d02002-03-22 01:27:54 +00002530
nethercote71980f02004-01-24 18:18:54 +00002531static void build_segment_map_callback
2532 ( Addr start, UInt size, Char rr, Char ww, Char xx,
2533 UInt dev, UInt ino, ULong foffset, const UChar* filename )
sewardj45b672d2003-07-25 19:58:11 +00002534{
nethercote71980f02004-01-24 18:18:54 +00002535 UInt prot = 0;
2536 UInt flags;
2537 Bool is_stack_segment;
2538 Addr r_esp;
sewardj45b672d2003-07-25 19:58:11 +00002539
nethercote71980f02004-01-24 18:18:54 +00002540 is_stack_segment
2541 = (start == VG_(clstk_base) && (start+size) == VG_(clstk_end));
fitzhardinge98abfc72003-12-16 02:05:15 +00002542
nethercote71980f02004-01-24 18:18:54 +00002543 if (rr == 'r') prot |= VKI_PROT_READ;
2544 if (ww == 'w') prot |= VKI_PROT_WRITE;
2545 if (xx == 'x') prot |= VKI_PROT_EXEC;
fitzhardinge98abfc72003-12-16 02:05:15 +00002546
nethercote71980f02004-01-24 18:18:54 +00002547 if (is_stack_segment)
2548 flags = SF_STACK | SF_GROWDOWN;
2549 else
2550 flags = SF_EXEC|SF_MMAP;
fitzhardinge98abfc72003-12-16 02:05:15 +00002551
nethercote71980f02004-01-24 18:18:54 +00002552 if (filename != NULL)
2553 flags |= SF_FILE;
fitzhardinge98abfc72003-12-16 02:05:15 +00002554
nethercote71980f02004-01-24 18:18:54 +00002555 if (start >= VG_(valgrind_base) && (start+size) <= VG_(valgrind_end))
2556 flags |= SF_VALGRIND;
fitzhardinge98abfc72003-12-16 02:05:15 +00002557
nethercote71980f02004-01-24 18:18:54 +00002558 VG_(map_file_segment)(start, size, prot, flags, dev, ino, foffset, filename);
fitzhardinge98abfc72003-12-16 02:05:15 +00002559
nethercote71980f02004-01-24 18:18:54 +00002560 if (VG_(is_client_addr)(start) && VG_(is_client_addr)(start+size-1))
2561 VG_TRACK( new_mem_startup, start, size, rr=='r', ww=='w', xx=='x' );
sewardj3e1eb1f2002-05-18 13:14:17 +00002562
nethercote71980f02004-01-24 18:18:54 +00002563 /* If this is the stack segment mark all below %esp as noaccess. */
2564 r_esp = esp_at_startup___global_arg;
2565 vg_assert(0 != r_esp);
2566 if (is_stack_segment) {
2567 if (0)
2568 VG_(message)(Vg_DebugMsg, "invalidating stack area: %x .. %x",
2569 start,r_esp);
2570 VG_TRACK( die_mem_stack, start, r_esp-start );
sewardjde4a1d02002-03-22 01:27:54 +00002571 }
sewardjde4a1d02002-03-22 01:27:54 +00002572}
2573
2574
nethercote71980f02004-01-24 18:18:54 +00002575/*====================================================================*/
2576/*=== Sanity check machinery (permanently engaged) ===*/
2577/*====================================================================*/
njn25e49d8e72002-09-23 09:36:25 +00002578
2579/* A fast sanity check -- suitable for calling circa once per
2580 millisecond. */
2581
2582void VG_(do_sanity_checks) ( Bool force_expensive )
2583{
njn37cea302002-09-30 11:24:00 +00002584 VGP_PUSHCC(VgpCoreCheapSanity);
2585
njn25e49d8e72002-09-23 09:36:25 +00002586 if (VG_(sanity_level) < 1) return;
2587
2588 /* --- First do all the tests that we can do quickly. ---*/
2589
2590 VG_(sanity_fast_count)++;
2591
njn25e49d8e72002-09-23 09:36:25 +00002592 /* Check stuff pertaining to the memory check system. */
2593
2594 /* Check that nobody has spuriously claimed that the first or
2595 last 16 pages of memory have become accessible [...] */
njn37cea302002-09-30 11:24:00 +00002596 if (VG_(needs).sanity_checks) {
2597 VGP_PUSHCC(VgpSkinCheapSanity);
njn25e49d8e72002-09-23 09:36:25 +00002598 vg_assert(SK_(cheap_sanity_check)());
njn37cea302002-09-30 11:24:00 +00002599 VGP_POPCC(VgpSkinCheapSanity);
2600 }
njn25e49d8e72002-09-23 09:36:25 +00002601
2602 /* --- Now some more expensive checks. ---*/
2603
2604 /* Once every 25 times, check some more expensive stuff. */
2605 if ( force_expensive
2606 || VG_(sanity_level) > 1
2607 || (VG_(sanity_level) == 1 && (VG_(sanity_fast_count) % 25) == 0)) {
2608
njn37cea302002-09-30 11:24:00 +00002609 VGP_PUSHCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002610 VG_(sanity_slow_count)++;
2611
jsgf855d93d2003-10-13 22:26:55 +00002612 VG_(proxy_sanity)();
2613
njn25e49d8e72002-09-23 09:36:25 +00002614# if 0
2615 { void zzzmemscan(void); zzzmemscan(); }
2616# endif
2617
2618 if ((VG_(sanity_fast_count) % 250) == 0)
2619 VG_(sanity_check_tc_tt)();
2620
2621 if (VG_(needs).sanity_checks) {
njn37cea302002-09-30 11:24:00 +00002622 VGP_PUSHCC(VgpSkinExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002623 vg_assert(SK_(expensive_sanity_check)());
njn37cea302002-09-30 11:24:00 +00002624 VGP_POPCC(VgpSkinExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002625 }
2626 /*
2627 if ((VG_(sanity_fast_count) % 500) == 0) VG_(mallocSanityCheckAll)();
2628 */
njn37cea302002-09-30 11:24:00 +00002629 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002630 }
2631
2632 if (VG_(sanity_level) > 1) {
njn37cea302002-09-30 11:24:00 +00002633 VGP_PUSHCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002634 /* Check sanity of the low-level memory manager. Note that bugs
2635 in the client's code can cause this to fail, so we don't do
2636 this check unless specially asked for. And because it's
2637 potentially very expensive. */
2638 VG_(mallocSanityCheckAll)();
njn37cea302002-09-30 11:24:00 +00002639 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002640 }
njn37cea302002-09-30 11:24:00 +00002641 VGP_POPCC(VgpCoreCheapSanity);
njn25e49d8e72002-09-23 09:36:25 +00002642}
nethercote71980f02004-01-24 18:18:54 +00002643
2644
2645/*====================================================================*/
2646/*=== main() ===*/
2647/*====================================================================*/
2648
2649int main(int argc, char **argv)
2650{
2651 char **cl_argv;
2652 const char *tool = NULL;
2653 const char *exec = NULL;
2654 char *preload; /* tool-specific LD_PRELOAD .so */
2655 char **env;
2656 Bool need_help = False;
2657 struct exeinfo info;
2658 ToolInfo *toolinfo = NULL;
2659 void *tool_dlhandle;
2660 Addr client_eip;
2661 Addr esp_at_startup; /* client's %esp at the point we gained control. */
2662 UInt * client_auxv;
2663 VgSchedReturnCode src;
2664
2665 //============================================================
2666 // Nb: startup is complex. Prerequisites are shown at every step.
2667 //
2668 // *** Be very careful when messing with the order ***
2669 //============================================================
2670
2671 //--------------------------------------------------------------
2672 // Check we were launched by stage1
2673 // p: n/a [must be first step]
2674 //--------------------------------------------------------------
2675 scan_auxv();
2676
2677 if (0) {
2678 int prmap(void *start, void *end, const char *perm, off_t off,
2679 int maj, int min, int ino) {
2680 printf("mapping %10p-%10p %s %02x:%02x %d\n",
2681 start, end, perm, maj, min, ino);
2682 return True;
2683 }
2684 printf("========== main() ==========\n");
2685 foreach_map(prmap);
2686 }
2687
2688 //--------------------------------------------------------------
2689 // Look for alternative libdir
2690 // p: n/a
2691 //--------------------------------------------------------------
2692 { char *cp = getenv(VALGRINDLIB);
2693 if (cp != NULL)
2694 VG_(libdir) = cp;
2695 }
2696
2697 //--------------------------------------------------------------
2698 // Begin working out address space layout
2699 // p: n/a
2700 //--------------------------------------------------------------
2701 layout_client_space( (Addr) & argc );
2702
2703 //--------------------------------------------------------------
2704 // Get valgrind args + client args (inc. from VALGRIND_OPTS/.valgrindrc).
2705 // Pre-process the command line.
2706 // p: n/a
2707 //--------------------------------------------------------------
2708 get_command_line(argc, argv, &VG_(vg_argc), &VG_(vg_argv), &cl_argv);
2709 pre_process_cmd_line_options(&need_help, &tool, &exec);
2710
2711 //==============================================================
2712 // Nb: once a tool is specified, the tool.so must be loaded even if
2713 // they specified --help or didn't specify a client program.
2714 //==============================================================
2715
2716 //--------------------------------------------------------------
2717 // With client padded out, map in tool
2718 // p: layout_client_space() [for padding]
2719 // p: set-libdir [for VG_(libdir)]
2720 // p: pre_process_cmd_line_options() [for 'tool']
2721 //--------------------------------------------------------------
2722 load_tool(tool, &tool_dlhandle, &toolinfo, &preload);
2723
2724 //==============================================================
2725 // Can use VG_(malloc)() and VG_(arena_malloc)() only after load_tool()
2726 // -- redzone size is now set.
2727 //==============================================================
2728
2729 //--------------------------------------------------------------
2730 // Finalise address space layout
2731 // p: layout_client_space(), load_tool() [for 'toolinfo']
2732 //--------------------------------------------------------------
2733 layout_remaining_space( toolinfo->shadow_ratio );
2734
2735 //--------------------------------------------------------------
2736 // Load client executable, finding in $PATH if necessary
2737 // p: layout_client_space() [so there's space]
2738 // p: pre_process_cmd_line_options() [for 'exec', 'need_help']
2739 // p: layout_remaining_space [so there's space]
2740 //--------------------------------------------------------------
2741 load_client(cl_argv, exec, /*inout*/&need_help, &info, &client_eip);
2742
2743 //--------------------------------------------------------------
2744 // Everything in place, unpad us
2745 // p: layout_remaining_space() [everything must be mapped in before now]
2746 // p: load_client() [ditto]
2747 //--------------------------------------------------------------
2748 as_unpad((void *)VG_(shadow_end), (void *)~0);
2749 as_closepadfile(); /* no more padding */
2750
2751 //--------------------------------------------------------------
2752 // Set up client's environment
2753 // p: set-libdir [for VG_(libdir)]
2754 // p: load_tool() [for 'preload']
2755 //--------------------------------------------------------------
2756 env = fix_environment(environ, preload);
2757
2758 //--------------------------------------------------------------
2759 // Setup client stack and eip
2760 // p: load_client() [for 'info']
2761 // p: fix_environment() [for 'env']
2762 //--------------------------------------------------------------
2763 esp_at_startup = setup_client_stack(cl_argv, env, &info, &client_auxv);
2764
2765 if (0)
2766 printf("entry=%x client esp=%x vg_argc=%d brkbase=%x\n",
2767 client_eip, esp_at_startup, VG_(vg_argc), VG_(brk_base));
2768
2769 //==============================================================
2770 // Finished setting up operating environment. Now initialise
2771 // Valgrind. (This is where the old VG_(main)() started.)
2772 //==============================================================
2773
2774 //--------------------------------------------------------------
2775 // Read /proc/self/maps into a buffer
2776 // p: all memory layout, environment setup [so memory maps are right]
2777 //--------------------------------------------------------------
2778 VG_(read_procselfmaps)();
2779
2780 //--------------------------------------------------------------
2781 // atfork
2782 // p: n/a
2783 //--------------------------------------------------------------
2784 VG_(atfork)(NULL, NULL, newpid);
2785 newpid(VG_INVALID_THREADID);
2786
2787 //--------------------------------------------------------------
2788 // setup file descriptors
2789 // p: n/a
2790 //--------------------------------------------------------------
2791 setup_file_descriptors();
2792
2793 //--------------------------------------------------------------
2794 // Setup tool
2795 // p: VG_(read_procselfmaps)() [so if sk_pre_clo_init calls
2796 // VG_(malloc), any mmap'd superblocks aren't erroneously
2797 // identified later as being owned by the client]
2798 // XXX: is that necessary, now that we look for V's segments separately?
2799 // XXX: alternatively, if sk_pre_clo_init does use VG_(malloc)(), is it
2800 // wrong to ignore any segments that might add in parse_procselfmaps?
2801 //--------------------------------------------------------------
2802 (*toolinfo->sk_pre_clo_init)();
2803 VG_(tool_init_dlsym)(tool_dlhandle);
2804 VG_(sanity_check_needs)();
2805
2806 //--------------------------------------------------------------
2807 // Process Valgrind's + tool's command-line options
2808 // p: load_tool() [for 'tool']
2809 // p: load_client() [for 'need_help']
2810 // p: setup_file_descriptors() [for 'VG_(max_fd)']
2811 // p: sk_pre_clo_init [to set 'command_line_options' need]
2812 //--------------------------------------------------------------
2813 process_cmd_line_options(client_auxv, esp_at_startup, tool, need_help);
2814
2815 //--------------------------------------------------------------
2816 // Allow GDB attach
2817 // p: process_cmd_line_options() [for VG_(clo_wait_for_gdb)]
2818 //--------------------------------------------------------------
2819 /* Hook to delay things long enough so we can get the pid and
2820 attach GDB in another shell. */
2821 if (VG_(clo_wait_for_gdb)) {
2822 VG_(printf)("pid=%d\n", VG_(getpid)());
2823 /* do "jump *$eip" to skip this in gdb */
2824 VG_(do_syscall)(__NR_pause);
2825 }
2826
2827 //--------------------------------------------------------------
2828 // Setup tool, post command-line processing
2829 // p: process_cmd_line_options [tool assumes it]
2830 //--------------------------------------------------------------
2831 SK_(post_clo_init)();
2832
2833 //--------------------------------------------------------------
2834 // Set up baseBlock, copy machine state (m_state_static)
2835 // p: {pre,post}_clo_init() [for tool helper registration]
2836 // load_client() [for 'client_eip']
2837 // setup_client_stack() [for 'esp_at_startup']
2838 //--------------------------------------------------------------
2839 init_baseBlock(client_eip, esp_at_startup);
2840
2841 //--------------------------------------------------------------
2842 // Search for file descriptors that are inherited from our parent
2843 // p: process_cmd_line_options [for VG_(clo_track_fds)]
2844 //--------------------------------------------------------------
2845 if (VG_(clo_track_fds))
2846 VG_(init_preopened_fds)();
2847
2848 //--------------------------------------------------------------
2849 // Initialise the scheduler
2850 // p: init_baseBlock() [baseBlock regs copied into VG_(threads)[1]]
2851 // p: setup_file_descriptors() [else VG_(safe_fd)() breaks]
2852 //--------------------------------------------------------------
2853 VG_(scheduler_init)();
2854
2855 //--------------------------------------------------------------
2856 // Set up the ProxyLWP machinery
2857 // p: VG_(scheduler_init)()? [XXX: subtle dependency?]
2858 // - subs: VG_(sigstartup_actions)()?
2859 //--------------------------------------------------------------
2860 VG_(proxy_init)();
2861
2862 //--------------------------------------------------------------
2863 // Initialise the signal handling subsystem
2864 // p: VG_(atfork)(NULL, NULL, newpid) [else problems with sigmasks]
2865 // p: VG_(proxy_init)() [else breaks...]
2866 //--------------------------------------------------------------
2867 // Nb: temporarily parks the saved blocking-mask in saved_sigmask.
2868 VG_(sigstartup_actions)();
2869
2870 //--------------------------------------------------------------
2871 // Perhaps we're profiling Valgrind?
2872 // p: process_cmd_line_options() [for VG_(clo_profile)]
2873 // p: others?
2874 //
2875 // XXX: this seems to be broken? It always says the tool wasn't built
2876 // for profiling; vg_profile.c's functions don't seem to be overriding
2877 // vg_dummy_profile.c's?
2878 //
2879 // XXX: want this as early as possible. Looking for --profile
2880 // in pre_process_cmd_line_options() could get it earlier.
2881 //--------------------------------------------------------------
2882 if (VG_(clo_profile))
2883 VGP_(init_profiling)();
2884
2885 VGP_PUSHCC(VgpStartup);
2886
2887 //--------------------------------------------------------------
2888 // Start calibration of our RDTSC-based clock
2889 // p: n/a
2890 //--------------------------------------------------------------
2891 VG_(start_rdtsc_calibration)();
2892
2893 //--------------------------------------------------------------
2894 // Reserve Valgrind's kickstart, heap and stack
2895 // p: XXX ???
2896 //--------------------------------------------------------------
2897 VG_(map_segment)(VG_(valgrind_mmap_end),
2898 VG_(valgrind_end)-VG_(valgrind_mmap_end),
2899 VKI_PROT_NONE, SF_VALGRIND|SF_FIXED);
2900
2901 //--------------------------------------------------------------
2902 // Identify Valgrind's segments
2903 // p: read proc/self/maps
2904 // p: VG_(map_segment) [XXX ???]
2905 // p: sk_pre_clo_init() [to setup new_mem_startup tracker]
2906 //--------------------------------------------------------------
2907 VG_(parse_procselfmaps) ( build_valgrind_map_callback );
2908
2909 // XXX: I can't see why these two need to be separate; could they be
2910 // folded together? If not, need a comment explaining why.
2911 //
2912 // XXX: can we merge reading and parsing of /proc/self/maps?
2913 //
2914 // XXX: can we dynamically allocate the /proc/self/maps buffer? (or mmap
2915 // it?) Or does that disturb its contents...
2916
2917 //--------------------------------------------------------------
2918 // Build segment map (all segments)
2919 // p: setup_client_stack() [for 'esp_at_startup']
2920 //--------------------------------------------------------------
2921 esp_at_startup___global_arg = esp_at_startup;
2922 VG_(parse_procselfmaps) ( build_segment_map_callback ); /* everything */
2923 esp_at_startup___global_arg = 0;
2924
2925 //==============================================================
2926 // Can only use VG_(map)() after VG_(map_segment)() [XXX ???]
2927 //==============================================================
2928
2929 //--------------------------------------------------------------
2930 // Build segment map (all segments)
2931 // p: setup_client_stack() [for 'esp_at_startup']
2932 //--------------------------------------------------------------
2933 /* Initialize our trampoline page (which is also sysinfo stuff) */
2934 VG_(memcpy)( (void *)VG_(client_trampoline_code),
2935 &VG_(trampoline_code_start), VG_(trampoline_code_length) );
2936 VG_(mprotect)( (void *)VG_(client_trampoline_code),
2937 VG_(trampoline_code_length), VKI_PROT_READ|VKI_PROT_EXEC );
2938
2939 //--------------------------------------------------------------
2940 // Read suppression file
2941 // p: process_cmd_line_options() [for VG_(clo_suppressions)]
2942 //--------------------------------------------------------------
2943 if (VG_(needs).core_errors || VG_(needs).skin_errors)
2944 VG_(load_suppressions)();
2945
2946 //--------------------------------------------------------------
2947 // End calibrating our RDTSC-based clock, having waited a while.
2948 // p: VG_(start_rdtsc_calibration)() [obviously]
2949 //--------------------------------------------------------------
2950 // Nb: Don't have to wait very long; it does pretty well even if
2951 // start_rdtsc_calibration() is immediately before this.
2952 VG_(end_rdtsc_calibration)();
2953
2954 //--------------------------------------------------------------
2955 // Initialise translation table and translation cache
2956 // p: read_procselfmaps [so the anonymous mmaps for the TT/TC
2957 // aren't identified as part of the client, which would waste
2958 // > 20M of virtual address space.]
2959 //--------------------------------------------------------------
2960 VG_(init_tt_tc)();
2961
2962 //--------------------------------------------------------------
2963 // Read debug info to find glibc entry points to intercept
2964 // p: parse_procselfmaps? [XXX for debug info?]
2965 // p: init_tt_tc? [XXX ???]
2966 //--------------------------------------------------------------
2967 VG_(setup_code_redirect_table)();
2968
2969 //--------------------------------------------------------------
2970 // Verbosity message
2971 // p: end_rdtsc_calibration [so startup message is printed first]
2972 //--------------------------------------------------------------
2973 if (VG_(clo_verbosity) == 1)
2974 VG_(message)(Vg_UserMsg, "For more details, rerun with: -v");
2975 if (VG_(clo_verbosity) > 0)
2976 VG_(message)(Vg_UserMsg, "");
2977
2978 //--------------------------------------------------------------
2979 // Setup pointercheck
2980 // p: process_cmd_line_options() [for VG_(clo_pointercheck)]
2981 //--------------------------------------------------------------
2982 setup_pointercheck();
2983
2984
2985
2986 //--------------------------------------------------------------
2987 // Run!
2988 //--------------------------------------------------------------
2989 VG_(running_on_simd_CPU) = True;
2990 VGP_POPCC(VgpStartup);
2991 VGP_PUSHCC(VgpSched);
2992
2993 if (__builtin_setjmp(&VG_(fatal_signal_jmpbuf)) == 0) {
2994 VG_(fatal_signal_set) = True;
2995 src = VG_(scheduler)();
2996 } else
2997 src = VgSrc_FatalSig;
2998
2999 VGP_POPCC(VgpSched);
3000 VG_(running_on_simd_CPU) = False;
3001
3002
3003
3004 //--------------------------------------------------------------
3005 // Finalisation: cleanup, messages, etc. Order no so important, only
3006 // affects what order the messages come.
3007 //--------------------------------------------------------------
3008 if (VG_(clo_verbosity) > 0)
3009 VG_(message)(Vg_UserMsg, "");
3010
3011 if (src == VgSrc_Deadlock) {
3012 VG_(message)(Vg_UserMsg,
3013 "Warning: pthread scheduler exited due to deadlock");
3014 }
3015
3016 /* Print out file descriptor summary and stats. */
3017 if (VG_(clo_track_fds))
3018 VG_(fd_stats)();
3019
3020 if (VG_(needs).core_errors || VG_(needs).skin_errors)
3021 VG_(show_all_errors)();
3022
3023 SK_(fini)( VG_(exitcode) );
3024
3025 VG_(do_sanity_checks)( True /*include expensive checks*/ );
3026
3027 if (VG_(clo_verbosity) > 1)
3028 show_counts();
3029
3030 if (VG_(clo_verbosity) > 3)
3031 VG_(print_UInstr_histogram)();
3032
3033 if (0) {
3034 VG_(message)(Vg_DebugMsg, "");
3035 VG_(message)(Vg_DebugMsg,
3036 "------ Valgrind's internal memory use stats follow ------" );
3037 VG_(mallocSanityCheckAll)();
3038 VG_(show_all_arena_stats)();
3039 VG_(message)(Vg_DebugMsg,
3040 "------ Valgrind's ExeContext management stats follow ------" );
3041 VG_(show_ExeContext_stats)();
3042 }
3043
3044 if (VG_(clo_profile))
3045 VGP_(done_profiling)();
3046
3047 /* Must be after all messages are done */
3048 VG_(shutdown_logging)();
3049
3050 /* We're exiting, so nuke all the threads and clean up the proxy LWPs */
3051 vg_assert(src == VgSrc_FatalSig ||
3052 VG_(threads)[VG_(last_run_tid)].status == VgTs_Runnable ||
3053 VG_(threads)[VG_(last_run_tid)].status == VgTs_WaitJoiner);
3054 VG_(nuke_all_threads_except)(VG_INVALID_THREADID);
3055
3056 //--------------------------------------------------------------
3057 // Exit, according to the scheduler's return code
3058 //--------------------------------------------------------------
3059 switch (src) {
3060 case VgSrc_ExitSyscall: /* the normal way out */
3061 vg_assert(VG_(last_run_tid) > 0
3062 && VG_(last_run_tid) < VG_N_THREADS);
3063 VG_(proxy_shutdown)();
3064
3065 /* The thread's %EBX at the time it did __NR_exit() will hold
3066 the arg to __NR_exit(), so we just do __NR_exit() with
3067 that arg. */
3068 VG_(exit)( VG_(exitcode) );
3069 /* NOT ALIVE HERE! */
3070 VG_(core_panic)("entered the afterlife in main() -- ExitSyscall");
3071 break; /* what the hell :) */
3072
3073 case VgSrc_Deadlock:
3074 /* Just exit now. No point in continuing. */
3075 VG_(proxy_shutdown)();
3076 VG_(exit)(0);
3077 VG_(core_panic)("entered the afterlife in main() -- Deadlock");
3078 break;
3079
3080 case VgSrc_BbsDone:
3081 /* Tricky; we have to try and switch back to the real CPU.
3082 This is all very dodgy and won't work at all in the
3083 presence of threads, or if the client happened to be
3084 running a signal handler. */
3085 /* Prepare to restore state to the real CPU. */
3086 VG_(sigshutdown_actions)();
3087 VG_(load_thread_state)(1 /* root thread */ );
3088 copy_baseBlock_to_m_state_static();
3089
3090 VG_(proxy_shutdown)();
3091
3092 /* This pushes a return address on the simulator's stack,
3093 which is abandoned. We call vg_sigshutdown_actions() at
3094 the end of vg_switch_to_real_CPU(), so as to ensure that
3095 the original stack and machine state is restored before
3096 the real signal mechanism is restored. */
3097 VG_(switch_to_real_CPU)();
3098
3099 case VgSrc_FatalSig:
3100 /* We were killed by a fatal signal, so replicate the effect */
3101 vg_assert(VG_(fatal_sigNo) != -1);
3102 VG_(kill_self)(VG_(fatal_sigNo));
3103 VG_(core_panic)("main(): signal was supposed to be fatal");
3104 break;
3105
3106 default:
3107 VG_(core_panic)("main(): unexpected scheduler return code");
3108 }
3109
3110 abort();
3111}
3112
3113
sewardjde4a1d02002-03-22 01:27:54 +00003114/*--------------------------------------------------------------------*/
3115/*--- end vg_main.c ---*/
3116/*--------------------------------------------------------------------*/