blob: 6653dcdc95c1398e3fe7118cf22334163dc64457 [file] [log] [blame]
sewardjde4a1d02002-03-22 01:27:54 +00001
2/*--------------------------------------------------------------------*/
nethercote71980f02004-01-24 18:18:54 +00003/*--- Startup: the real stuff vg_main.c ---*/
sewardjde4a1d02002-03-22 01:27:54 +00004/*--------------------------------------------------------------------*/
5
6/*
njnc9539842002-10-02 13:26:35 +00007 This file is part of Valgrind, an extensible x86 protected-mode
8 emulator for monitoring program execution on x86-Unixes.
sewardjde4a1d02002-03-22 01:27:54 +00009
nethercotebb1c9912004-01-04 16:43:23 +000010 Copyright (C) 2000-2004 Julian Seward
sewardjde4a1d02002-03-22 01:27:54 +000011 jseward@acm.org
sewardjde4a1d02002-03-22 01:27:54 +000012
13 This program is free software; you can redistribute it and/or
14 modify it under the terms of the GNU General Public License as
15 published by the Free Software Foundation; either version 2 of the
16 License, or (at your option) any later version.
17
18 This program is distributed in the hope that it will be useful, but
19 WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 General Public License for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software
25 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
26 02111-1307, USA.
27
njn25e49d8e72002-09-23 09:36:25 +000028 The GNU General Public License is contained in the file COPYING.
sewardjde4a1d02002-03-22 01:27:54 +000029*/
30
nethercote71980f02004-01-24 18:18:54 +000031#define _FILE_OFFSET_BITS 64
sewardjde4a1d02002-03-22 01:27:54 +000032
nethercote71980f02004-01-24 18:18:54 +000033#include "vg_include.h"
34#include "ume.h"
35#include "ume_arch.h"
36#include "ume_archdefs.h"
37
38#include <dirent.h>
39#include <dlfcn.h>
40#include <errno.h>
41#include <fcntl.h>
42#include <stdio.h>
fitzhardingeb727d042004-01-06 00:18:21 +000043#include <stdlib.h>
nethercote71980f02004-01-24 18:18:54 +000044#include <string.h>
45#include <sys/mman.h>
46#include <sys/types.h>
47#include <sys/stat.h>
fitzhardingeb727d042004-01-06 00:18:21 +000048#include <sys/ptrace.h>
49#include <sys/signal.h>
fitzhardingeb727d042004-01-06 00:18:21 +000050#include <sys/wait.h>
51#include <unistd.h>
52
nethercote71980f02004-01-24 18:18:54 +000053#ifndef AT_SYSINFO
54#define AT_SYSINFO 32
55#endif /* AT_SYSINFO */
56
57#ifndef AT_SYSINFO_EHDR
58#define AT_SYSINFO_EHDR 33
59#endif /* AT_SYSINFO_EHDR */
60
61#ifndef AT_SECURE
62#define AT_SECURE 23 /* secure mode boolean */
63#endif /* AT_SECURE */
64
65/* Amount to reserve for Valgrind's internal heap */
66#define VALGRIND_HEAPSIZE (128*1024*1024)
67
68/* Amount to reserve for Valgrind's internal mappings */
69#define VALGRIND_MAPSIZE (128*1024*1024)
70
71/* redzone gap between client address space and shadow */
72#define REDZONE_SIZE (1 * 1024*1024)
73
74/* size multiple for client address space */
75#define CLIENT_SIZE_MULTIPLE (64 * 1024*1024)
76
77#define ISSPACE(cc) ((cc) == ' ' || (cc) == '\t' || (cc) == '\n')
78
79/*====================================================================*/
80/*=== Global entities not referenced from generated code ===*/
81/*====================================================================*/
82
sewardjde4a1d02002-03-22 01:27:54 +000083/* ---------------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +000084 Startup stuff
sewardjde4a1d02002-03-22 01:27:54 +000085 ------------------------------------------------------------------ */
nethercote71980f02004-01-24 18:18:54 +000086/* linker-defined base address */
87extern char kickstart_base;
sewardjde4a1d02002-03-22 01:27:54 +000088
nethercote71980f02004-01-24 18:18:54 +000089/* Client address space, lowest to highest (see top of ume.c) */
90Addr VG_(client_base); /* client address space limits */
fitzhardinge98abfc72003-12-16 02:05:15 +000091Addr VG_(client_end);
92Addr VG_(client_mapbase);
fitzhardinge92360792003-12-24 10:11:11 +000093Addr VG_(client_trampoline_code);
fitzhardinge98abfc72003-12-16 02:05:15 +000094Addr VG_(clstk_base);
95Addr VG_(clstk_end);
nethercote71980f02004-01-24 18:18:54 +000096
97Addr VG_(brk_base); /* start of brk */
98Addr VG_(brk_limit); /* current brk */
99
100Addr VG_(shadow_base); /* skin's shadow memory */
fitzhardinge98abfc72003-12-16 02:05:15 +0000101Addr VG_(shadow_end);
nethercote71980f02004-01-24 18:18:54 +0000102
103Addr VG_(valgrind_base); /* valgrind's address range */
104Addr VG_(valgrind_mmap_end); /* valgrind's mmaps are between valgrind_base and here */
fitzhardinge98abfc72003-12-16 02:05:15 +0000105Addr VG_(valgrind_end);
106
fitzhardingeb50068f2004-02-24 23:42:55 +0000107vki_rlimit VG_(client_rlimit_data);
108
nethercote71980f02004-01-24 18:18:54 +0000109/* This is set early to indicate whether this CPU has the
110 SSE/fxsave/fxrestor features. */
111Bool VG_(have_ssestate);
112
113/* Indicates presence, and holds address of client's sysinfo page, a
114 feature of some modern kernels used to provide vsyscalls, etc. */
115Bool VG_(sysinfo_page_exists) = False;
116Addr VG_(sysinfo_page_addr) = 0;
117
fitzhardinge98abfc72003-12-16 02:05:15 +0000118/* stage1 (main) executable */
fitzhardingea49f9b52003-12-16 22:26:45 +0000119Int VG_(vgexecfd) = -1;
120
121/* client executable */
122Int VG_(clexecfd) = -1;
fitzhardinge98abfc72003-12-16 02:05:15 +0000123
124/* Path to library directory */
125const Char *VG_(libdir) = VG_LIBDIR;
126
127/* our argc/argv */
128Int VG_(vg_argc);
129Char **VG_(vg_argv);
130
jsgf855d93d2003-10-13 22:26:55 +0000131/* PID of the main thread */
132Int VG_(main_pid);
133
134/* PGRP of process */
135Int VG_(main_pgrp);
njn25e49d8e72002-09-23 09:36:25 +0000136
fitzhardingef0046f22003-12-18 02:39:22 +0000137/* Maximum allowed application-visible file descriptor */
fitzhardingeb791a192003-12-18 07:22:44 +0000138Int VG_(max_fd) = -1;
fitzhardingef0046f22003-12-18 02:39:22 +0000139
nethercote71980f02004-01-24 18:18:54 +0000140/* As deduced from esp_at_startup, the client's argc, argv[] and
141 envp[] as extracted from the client's stack at startup-time. */
142Int VG_(client_argc);
143Char** VG_(client_argv);
144Char** VG_(client_envp);
sewardjde4a1d02002-03-22 01:27:54 +0000145
146/* ---------------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +0000147 Running stuff
sewardjde4a1d02002-03-22 01:27:54 +0000148 ------------------------------------------------------------------ */
nethercote71980f02004-01-24 18:18:54 +0000149/* Our signal delivery stack. */
njn6eba4ef2003-05-01 08:06:41 +0000150UInt VG_(sigstack)[VG_SIGSTACK_SIZE_W];
sewardjde4a1d02002-03-22 01:27:54 +0000151
152/* Saving stuff across system calls. */
sewardjb91ae7f2003-04-29 23:50:00 +0000153__attribute__ ((aligned (16)))
154UInt VG_(real_sse_state_saved_over_syscall)[VG_SIZE_OF_SSESTATE_W];
sewardj43c356f2002-06-02 00:21:08 +0000155Addr VG_(esp_saved_over_syscall);
sewardjde4a1d02002-03-22 01:27:54 +0000156
nethercote71980f02004-01-24 18:18:54 +0000157/* jmp_buf for fatal signals */
158Int VG_(fatal_sigNo) = -1;
159Bool VG_(fatal_signal_set) = False;
160jmp_buf VG_(fatal_signal_jmpbuf);
sewardjde4a1d02002-03-22 01:27:54 +0000161
nethercote71980f02004-01-24 18:18:54 +0000162/* Counts downwards in VG_(run_innerloop). */
163UInt VG_(dispatch_ctr);
sewardjde4a1d02002-03-22 01:27:54 +0000164
165/* 64-bit counter for the number of basic blocks done. */
166ULong VG_(bbs_done);
sewardjde4a1d02002-03-22 01:27:54 +0000167
sewardj7e87e382002-05-03 19:09:05 +0000168/* This is the ThreadId of the last thread the scheduler ran. */
169ThreadId VG_(last_run_tid) = 0;
170
nethercote71980f02004-01-24 18:18:54 +0000171/* Tell the logging mechanism whether we are logging to a file
172 descriptor or a socket descriptor. */
173Bool VG_(logging_to_filedes) = True;
174
175/* This Bool is needed by wrappers in vg_clientmalloc.c to decide how
176 to behave. Initially we say False. */
177Bool VG_(running_on_simd_CPU) = False;
178
njn25e49d8e72002-09-23 09:36:25 +0000179/* This is the argument to __NR_exit() supplied by the first thread to
180 call that syscall. We eventually pass that to __NR_exit() for
181 real. */
njn633de322003-05-12 20:40:13 +0000182Int VG_(exitcode) = 0;
njn25e49d8e72002-09-23 09:36:25 +0000183
sewardj73cf3bc2002-11-03 03:20:15 +0000184
nethercote71980f02004-01-24 18:18:54 +0000185/*====================================================================*/
186/*=== Counters, for profiling purposes only ===*/
187/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +0000188
189/* Number of lookups which miss the fast tt helper. */
190UInt VG_(tt_fast_misses) = 0;
191
192
sewardjc0d8f682002-11-30 00:49:43 +0000193/* Counts for TT/TC informational messages. */
sewardjde4a1d02002-03-22 01:27:54 +0000194
sewardjde4a1d02002-03-22 01:27:54 +0000195/* Number and total o/t size of translations overall. */
196UInt VG_(overall_in_count) = 0;
197UInt VG_(overall_in_osize) = 0;
198UInt VG_(overall_in_tsize) = 0;
199/* Number and total o/t size of discards overall. */
200UInt VG_(overall_out_count) = 0;
201UInt VG_(overall_out_osize) = 0;
202UInt VG_(overall_out_tsize) = 0;
sewardjc0d8f682002-11-30 00:49:43 +0000203/* The number of discards of TT/TC. */
204UInt VG_(number_of_tc_discards) = 0;
sewardj22854b92002-11-30 14:00:47 +0000205/* Counts of chain and unchain operations done. */
206UInt VG_(bb_enchain_count) = 0;
207UInt VG_(bb_dechain_count) = 0;
208/* Number of unchained jumps performed. */
209UInt VG_(unchained_jumps_done) = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000210
211
212/* Counts pertaining to the register allocator. */
213
214/* total number of uinstrs input to reg-alloc */
215UInt VG_(uinstrs_prealloc) = 0;
216
217/* total number of uinstrs added due to spill code */
218UInt VG_(uinstrs_spill) = 0;
219
220/* number of bbs requiring spill code */
221UInt VG_(translations_needing_spill) = 0;
222
223/* total of register ranks over all translations */
224UInt VG_(total_reg_rank) = 0;
225
226
sewardjde4a1d02002-03-22 01:27:54 +0000227/* Counts pertaining to internal sanity checking. */
sewardjde4a1d02002-03-22 01:27:54 +0000228UInt VG_(sanity_fast_count) = 0;
229UInt VG_(sanity_slow_count) = 0;
230
sewardj2e93c502002-04-12 11:12:52 +0000231/* Counts pertaining to the scheduler. */
232UInt VG_(num_scheduling_events_MINOR) = 0;
233UInt VG_(num_scheduling_events_MAJOR) = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000234
235
nethercote71980f02004-01-24 18:18:54 +0000236static __inline__ Int safe_idiv(Int a, Int b)
237{
238 return (b == 0 ? 0 : a / b);
239}
240
241static void show_counts ( void )
242{
243 VG_(message)(Vg_DebugMsg,
244 " TT/TC: %d tc sectors discarded.",
245 VG_(number_of_tc_discards) );
246 VG_(message)(Vg_DebugMsg,
247 " %d chainings, %d unchainings.",
248 VG_(bb_enchain_count), VG_(bb_dechain_count) );
249 VG_(message)(Vg_DebugMsg,
250 "translate: new %d (%d -> %d; ratio %d:10)",
251 VG_(overall_in_count),
252 VG_(overall_in_osize),
253 VG_(overall_in_tsize),
254 safe_idiv(10*VG_(overall_in_tsize), VG_(overall_in_osize)));
255 VG_(message)(Vg_DebugMsg,
256 " discard %d (%d -> %d; ratio %d:10).",
257 VG_(overall_out_count),
258 VG_(overall_out_osize),
259 VG_(overall_out_tsize),
260 safe_idiv(10*VG_(overall_out_tsize), VG_(overall_out_osize)));
261 VG_(message)(Vg_DebugMsg,
262 " dispatch: %llu jumps (bb entries), of which %u (%lu%%) were unchained.",
263 VG_(bbs_done),
264 VG_(unchained_jumps_done),
265 ((ULong)(100) * (ULong)(VG_(unchained_jumps_done)))
266 / ( VG_(bbs_done)==0 ? 1 : VG_(bbs_done) )
267 );
268
269 VG_(message)(Vg_DebugMsg,
270 " %d/%d major/minor sched events. %d tt_fast misses.",
271 VG_(num_scheduling_events_MAJOR),
272 VG_(num_scheduling_events_MINOR),
273 VG_(tt_fast_misses));
274
275 VG_(message)(Vg_DebugMsg,
276 "reg-alloc: %d t-req-spill, "
277 "%d+%d orig+spill uis, %d total-reg-r.",
278 VG_(translations_needing_spill),
279 VG_(uinstrs_prealloc),
280 VG_(uinstrs_spill),
281 VG_(total_reg_rank) );
282 VG_(message)(Vg_DebugMsg,
283 " sanity: %d cheap, %d expensive checks.",
284 VG_(sanity_fast_count),
285 VG_(sanity_slow_count) );
286 VG_(print_ccall_stats)();
287}
288
289
290/*====================================================================*/
291/*=== Miscellaneous global functions ===*/
292/*====================================================================*/
293
nethercote04d0fbc2004-01-26 16:48:06 +0000294/* Start debugger and get it to attach to this process. Called if the
295 user requests this service after an error has been shown, so she can
nethercote71980f02004-01-24 18:18:54 +0000296 poke around and look at parameters, memory, etc. You can't
nethercote04d0fbc2004-01-26 16:48:06 +0000297 meaningfully get the debugger to continue the program, though; to
298 continue, quit the debugger. */
299void VG_(start_debugger) ( Int tid )
nethercote71980f02004-01-24 18:18:54 +0000300{
301 Int pid;
302
303 if ((pid = fork()) == 0) {
304 ptrace(PTRACE_TRACEME, 0, NULL, NULL);
305 VG_(kkill)(VG_(getpid)(), VKI_SIGSTOP);
306
307 } else if (pid > 0) {
308 struct user_regs_struct regs;
309 Int status;
310 Int res;
311
312 if (VG_(is_running_thread)( tid )) {
fitzhardinged65dcad2004-03-13 02:06:58 +0000313 regs.cs = VG_(baseBlock)[VGOFF_(m_cs)];
314 regs.ss = VG_(baseBlock)[VGOFF_(m_ss)];
315 regs.ds = VG_(baseBlock)[VGOFF_(m_ds)];
316 regs.es = VG_(baseBlock)[VGOFF_(m_es)];
317 regs.fs = VG_(baseBlock)[VGOFF_(m_fs)];
318 regs.gs = VG_(baseBlock)[VGOFF_(m_gs)];
nethercote71980f02004-01-24 18:18:54 +0000319 regs.eax = VG_(baseBlock)[VGOFF_(m_eax)];
320 regs.ebx = VG_(baseBlock)[VGOFF_(m_ebx)];
321 regs.ecx = VG_(baseBlock)[VGOFF_(m_ecx)];
322 regs.edx = VG_(baseBlock)[VGOFF_(m_edx)];
323 regs.esi = VG_(baseBlock)[VGOFF_(m_esi)];
324 regs.edi = VG_(baseBlock)[VGOFF_(m_edi)];
325 regs.ebp = VG_(baseBlock)[VGOFF_(m_ebp)];
326 regs.esp = VG_(baseBlock)[VGOFF_(m_esp)];
327 regs.eflags = VG_(baseBlock)[VGOFF_(m_eflags)];
328 regs.eip = VG_(baseBlock)[VGOFF_(m_eip)];
329 } else {
330 ThreadState* tst = & VG_(threads)[ tid ];
331
fitzhardinged65dcad2004-03-13 02:06:58 +0000332 regs.cs = tst->m_cs;
333 regs.ss = tst->m_ss;
334 regs.ds = tst->m_ds;
335 regs.es = tst->m_es;
336 regs.fs = tst->m_fs;
337 regs.gs = tst->m_gs;
nethercote71980f02004-01-24 18:18:54 +0000338 regs.eax = tst->m_eax;
339 regs.ebx = tst->m_ebx;
340 regs.ecx = tst->m_ecx;
341 regs.edx = tst->m_edx;
342 regs.esi = tst->m_esi;
343 regs.edi = tst->m_edi;
344 regs.ebp = tst->m_ebp;
345 regs.esp = tst->m_esp;
346 regs.eflags = tst->m_eflags;
347 regs.eip = tst->m_eip;
348 }
349
350 if ((res = VG_(waitpid)(pid, &status, 0)) == pid &&
351 WIFSTOPPED(status) && WSTOPSIG(status) == SIGSTOP &&
352 ptrace(PTRACE_SETREGS, pid, NULL, &regs) == 0 &&
353 ptrace(PTRACE_DETACH, pid, NULL, SIGSTOP) == 0) {
nethercote04d0fbc2004-01-26 16:48:06 +0000354 Char pidbuf[15];
355 Char file[30];
356 Char buf[100];
357 Char *bufptr;
358 Char *cmdptr;
359
360 VG_(sprintf)(pidbuf, "%d", pid);
361 VG_(sprintf)(file, "/proc/%d/fd/%d", pid, VG_(clexecfd));
362
363 bufptr = buf;
364 cmdptr = VG_(clo_db_command);
365
366 while (*cmdptr) {
367 switch (*cmdptr) {
368 case '%':
369 switch (*++cmdptr) {
370 case 'f':
371 VG_(memcpy)(bufptr, file, VG_(strlen)(file));
372 bufptr += VG_(strlen)(file);
373 cmdptr++;
374 break;
375 case 'p':
376 VG_(memcpy)(bufptr, pidbuf, VG_(strlen)(pidbuf));
377 bufptr += VG_(strlen)(pidbuf);
378 cmdptr++;
379 break;
380 default:
381 *bufptr++ = *cmdptr++;
382 break;
383 }
384 break;
385 default:
386 *bufptr++ = *cmdptr++;
387 break;
388 }
389 }
390
391 *bufptr++ = '\0';
392
393 VG_(message)(Vg_UserMsg, "starting debugger with cmd: %s", buf);
nethercote71980f02004-01-24 18:18:54 +0000394 res = VG_(system)(buf);
395 if (res == 0) {
396 VG_(message)(Vg_UserMsg, "");
397 VG_(message)(Vg_UserMsg,
nethercote04d0fbc2004-01-26 16:48:06 +0000398 "Debugger has detached. Valgrind regains control. We continue.");
nethercote71980f02004-01-24 18:18:54 +0000399 } else {
400 VG_(message)(Vg_UserMsg, "Apparently failed!");
401 VG_(message)(Vg_UserMsg, "");
402 }
403 }
404
405 VG_(kkill)(pid, VKI_SIGKILL);
406 VG_(waitpid)(pid, &status, 0);
407 }
408}
409
410
411/* Print some helpful-ish text about unimplemented things, and give
412 up. */
413void VG_(unimplemented) ( Char* msg )
414{
415 VG_(message)(Vg_UserMsg, "");
416 VG_(message)(Vg_UserMsg,
417 "Valgrind detected that your program requires");
418 VG_(message)(Vg_UserMsg,
419 "the following unimplemented functionality:");
420 VG_(message)(Vg_UserMsg, " %s", msg);
421 VG_(message)(Vg_UserMsg,
422 "This may be because the functionality is hard to implement,");
423 VG_(message)(Vg_UserMsg,
424 "or because no reasonable program would behave this way,");
425 VG_(message)(Vg_UserMsg,
426 "or because nobody has yet needed it. In any case, let us know at");
427 VG_(message)(Vg_UserMsg,
428 "%s and/or try to work around the problem, if you can.", VG_BUGS_TO);
429 VG_(message)(Vg_UserMsg,
430 "");
431 VG_(message)(Vg_UserMsg,
432 "Valgrind has to exit now. Sorry. Bye!");
433 VG_(message)(Vg_UserMsg,
434 "");
435 VG_(pp_sched_status)();
436 VG_(exit)(1);
437}
438
439Addr VG_(get_stack_pointer) ( void )
440{
441 return VG_(baseBlock)[VGOFF_(m_esp)];
442}
443
444/* Debugging thing .. can be called from assembly with OYNK macro. */
445void VG_(oynk) ( Int n )
446{
447 OINK(n);
448}
449
450/* Initialize the PID and PGRP of scheduler LWP; this is also called
451 in any new children after fork. */
452static void newpid(ThreadId unused)
453{
454 /* PID of scheduler LWP */
455 VG_(main_pid) = VG_(getpid)();
456 VG_(main_pgrp) = VG_(getpgrp)();
457}
458
459/*====================================================================*/
460/*=== Check we were launched by stage 1 ===*/
461/*====================================================================*/
462
463/* Look for our AUXV table */
464static void scan_auxv(void)
465{
466 const struct ume_auxv *auxv = find_auxv((int *)ume_exec_esp);
467 int found = 0;
468
469 for (; auxv->a_type != AT_NULL; auxv++)
470 switch(auxv->a_type) {
471 case AT_UME_PADFD:
472 as_setpadfd(auxv->u.a_val);
473 found |= 1;
474 break;
475
476 case AT_UME_EXECFD:
477 VG_(vgexecfd) = auxv->u.a_val;
478 found |= 2;
479 break;
480 }
481
482 if ( ! (1|2) ) {
483 fprintf(stderr, "stage2 must be launched by stage1\n");
484 exit(127);
485 }
486}
487
488
489/*====================================================================*/
490/*=== Address space determination ===*/
491/*====================================================================*/
492
493/* Pad client space so it doesn't get filled in before the right time */
494static void layout_client_space(Addr argc_addr)
495{
496 VG_(client_base) = CLIENT_BASE;
497 VG_(valgrind_mmap_end) = (addr_t)&kickstart_base; /* end of V's mmaps */
498 VG_(valgrind_base) = VG_(valgrind_mmap_end) - VALGRIND_MAPSIZE;
499 VG_(valgrind_end) = ROUNDUP(argc_addr, 0x10000); /* stack */
500
501 if (0)
502 printf("client base: %x\n"
503 "valgrind base--end: %x--%x (%x)\n"
504 "valgrind mmap end: %x\n\n",
505 VG_(client_base),
506 VG_(valgrind_base), VG_(valgrind_end),
507 VG_(valgrind_end) - VG_(valgrind_base),
508 VG_(valgrind_mmap_end));
509
510 as_pad((void *)VG_(client_base), (void *)VG_(valgrind_base));
511}
512
513static void layout_remaining_space(float ratio)
514{
515 /* This tries to give the client as large as possible address space while
516 * taking into account the tool's shadow needs. */
517 addr_t client_size = ROUNDDN((VG_(valgrind_base) - REDZONE_SIZE) / (1. + ratio),
518 CLIENT_SIZE_MULTIPLE);
519 addr_t shadow_size = PGROUNDUP(client_size * ratio);
520
521 VG_(client_end) = VG_(client_base) + client_size;
522 VG_(client_mapbase) = PGROUNDDN((client_size/4)*3); /* where !FIXED mmap goes */
523 VG_(client_trampoline_code) = VG_(client_end) - VKI_BYTES_PER_PAGE;
524
525 VG_(shadow_base) = VG_(client_end) + REDZONE_SIZE;
526 VG_(shadow_end) = VG_(shadow_base) + shadow_size;
527
528 if (0)
529 printf("client base--end: %x--%x (%x)\n"
530 "client mapbase: %x\n"
531 "shadow base--end: %x--%x (%x)\n\n",
532 VG_(client_base), VG_(client_end), client_size,
533 VG_(client_mapbase),
534 VG_(shadow_base), VG_(shadow_end), shadow_size);
535
536 // Ban redzone
537 mmap((void *)VG_(client_end), REDZONE_SIZE, PROT_NONE,
538 MAP_FIXED|MAP_ANON|MAP_PRIVATE, -1, 0);
539
540 // Make client hole
541 munmap((void*)VG_(client_base), client_size);
542
543 // Map shadow memory.
544 // Initially all inaccessible, incrementally initialized as it is used
545 if (shadow_size != 0)
546 mmap((char *)VG_(shadow_base), shadow_size, PROT_NONE,
547 MAP_PRIVATE|MAP_ANON|MAP_FIXED, -1, 0);
548}
549
550/*====================================================================*/
551/*=== Command line setup ===*/
552/*====================================================================*/
553
554/* Nb: malloc'd memory never freed -- kept throughout like argv, envp */
555static char* get_file_clo(char* dir)
556{
557# define FLEN 512
558 Int fd, n;
559 struct stat s1;
560 char* f_clo = NULL;
561 char filename[FLEN];
562
563 snprintf(filename, FLEN, "%s/.valgrindrc", ( NULL == dir ? "" : dir ) );
564 fd = VG_(open)(filename, 0, VKI_S_IRUSR);
565 if ( fd > 0 ) {
566 if ( 0 == fstat(fd, &s1) ) {
567 f_clo = malloc(s1.st_size+1);
568 vg_assert(f_clo);
569 n = read(fd, f_clo, s1.st_size);
570 if (n == -1) n = 0;
571 f_clo[n] = '\0';
572 }
573 close(fd);
574 }
575 return f_clo;
576# undef FLEN
577}
578
579static Int count_args(char* s)
580{
581 Int n = 0;
582 if (s) {
583 char* cp = s;
584 while (True) {
585 // We have alternating sequences: blanks, non-blanks, blanks...
586 // count the non-blanks sequences.
587 while ( ISSPACE(*cp) ) cp++;
588 if ( !*cp ) break;
589 n++;
590 while ( !ISSPACE(*cp) && *cp ) cp++;
591 }
592 }
593 return n;
594}
595
596/* add args out of environment, skipping multiple spaces and -- args */
597static char** copy_args( char* s, char** to )
598{
599 if (s) {
600 char* cp = s;
601 while (True) {
602 // We have alternating sequences: blanks, non-blanks, blanks...
603 // copy the non-blanks sequences, and add terminating '\0'
604 while ( ISSPACE(*cp) ) cp++;
605 if ( !*cp ) break;
606 *to++ = cp;
607 while ( !ISSPACE(*cp) && *cp ) cp++;
608 if ( *cp ) *cp++ = '\0'; // terminate if necessary
609 if (VG_STREQ(to[-1], "--")) to--; // undo any '--' arg
610 }
611 }
612 return to;
613}
614
615// Augment command line with arguments from environment and .valgrindrc
616// files.
617static void augment_command_line(Int* vg_argc_inout, char*** vg_argv_inout)
618{
619 int vg_argc = *vg_argc_inout;
620 char** vg_argv = *vg_argv_inout;
621
622 char* env_clo = getenv(VALGRINDOPTS);
623 char* f1_clo = get_file_clo( getenv("HOME") );
624 char* f2_clo = get_file_clo(".");
625
626 /* copy any extra args from file or environment, if present */
627 if ( (env_clo && *env_clo) || (f1_clo && *f1_clo) || (f2_clo && *f2_clo) ) {
628 /* ' ' separated extra options */
629 char **from;
630 char **to;
631 int env_arg_count, f1_arg_count, f2_arg_count;
632
633 env_arg_count = count_args(env_clo);
634 f1_arg_count = count_args(f1_clo);
635 f2_arg_count = count_args(f2_clo);
636
637 if (0)
638 printf("extra-argc=%d %d %d\n",
639 env_arg_count, f1_arg_count, f2_arg_count);
640
641 /* +2: +1 for null-termination, +1 for added '--' */
642 from = vg_argv;
643 vg_argv = malloc( (vg_argc + env_arg_count + f1_arg_count
644 + f2_arg_count + 2) * sizeof(char **));
645 to = vg_argv;
646
647 /* copy argv[0] */
648 *to++ = *from++;
649
650 /* Copy extra args from env var and file, in the order: ~/.valgrindrc,
651 * $VALGRIND_OPTS, ./.valgrindrc -- more local options are put later
652 * to override less local ones. */
653 to = copy_args(f1_clo, to);
654 to = copy_args(env_clo, to);
655 to = copy_args(f2_clo, to);
656
657 /* copy original arguments, stopping at command or -- */
658 while (*from) {
659 if (**from != '-')
660 break;
661 if (VG_STREQ(*from, "--")) {
662 from++; /* skip -- */
663 break;
664 }
665 *to++ = *from++;
666 }
667
668 /* add -- */
669 *to++ = "--";
670
671 vg_argc = to - vg_argv;
672
673 /* copy rest of original command line, then NULL */
674 while (*from) *to++ = *from++;
675 *to = NULL;
676 }
677
678 *vg_argc_inout = vg_argc;
679 *vg_argv_inout = vg_argv;
680}
681
682static void get_command_line( int argc, char** argv,
683 Int* vg_argc_out, Char*** vg_argv_out,
684 char*** cl_argv_out )
685{
686 int vg_argc;
687 char** vg_argv;
688 char** cl_argv;
689 char* env_clo = getenv(VALGRINDCLO);
690
691 if (env_clo != NULL && *env_clo != '\0') {
692 char *cp;
693 char **cpp;
694
695 /* OK, we're getting all our arguments from the environment - the
696 entire command line belongs to the client (including argv[0]) */
697 vg_argc = 1; /* argv[0] */
698 for (cp = env_clo; *cp; cp++)
699 if (*cp == '\01')
700 vg_argc++;
701
702 vg_argv = malloc(sizeof(char **) * (vg_argc + 1));
703
704 cpp = vg_argv;
705
706 *cpp++ = "valgrind"; /* nominal argv[0] */
707 *cpp++ = env_clo;
708
709 for (cp = env_clo; *cp; cp++) {
710 if (*cp == '\01') {
711 *cp++ = '\0'; /* chop it up in place */
712 *cpp++ = cp;
713 }
714 }
715 *cpp = NULL;
716 cl_argv = argv;
717
718 } else {
719 /* Count the arguments on the command line. */
720 vg_argv = argv;
721
722 for (vg_argc = 1; vg_argc < argc; vg_argc++) {
723 if (argv[vg_argc][0] != '-') /* exe name */
724 break;
725 if (VG_STREQ(argv[vg_argc], "--")) { /* dummy arg */
726 vg_argc++;
727 break;
728 }
729 }
730 cl_argv = &argv[vg_argc];
731
732 /* Get extra args from VALGRIND_OPTS and .valgrindrc files.
733 * Note we don't do this if getting args from VALGRINDCLO. */
734 augment_command_line(&vg_argc, &vg_argv);
735 }
736
737 if (0) {
738 Int i;
739 for (i = 0; i < vg_argc; i++)
740 printf("vg_argv[%d]=\"%s\"\n", i, vg_argv[i]);
741 }
742
743 *vg_argc_out = vg_argc;
744 *vg_argv_out = (Char**)vg_argv;
745 *cl_argv_out = cl_argv;
746}
747
748
749/*====================================================================*/
750/*=== Environment and stack setup ===*/
751/*====================================================================*/
752
753/* Scan a colon-separated list, and call a function on each element.
754 The string must be mutable, because we insert a temporary '\0', but
755 the string will end up unmodified. (*func) should return 1 if it
756 doesn't need to see any more.
757*/
758static void scan_colsep(char *colsep, int (*func)(const char *))
759{
760 char *cp, *entry;
761 int end;
762
763 if (colsep == NULL ||
764 *colsep == '\0')
765 return;
766
767 entry = cp = colsep;
768
769 do {
770 end = (*cp == '\0');
771
772 if (*cp == ':' || *cp == '\0') {
773 char save = *cp;
774
775 *cp = '\0';
776 if ((*func)(entry))
777 end = 1;
778 *cp = save;
779 entry = cp+1;
780 }
781 cp++;
782 } while(!end);
783}
784
785/* Prepare the client's environment. This is basically a copy of our
786 environment, except:
787 1. LD_LIBRARY_PATH=$VALGRINDLIB:$LD_LIBRARY_PATH
788 2. LD_PRELOAD=$VALGRINDLIB/vg_inject.so:($VALGRINDLIB/vgpreload_TOOL.so:)?$LD_PRELOAD
789
790 If any of these is missing, then it is added.
791
792 Yummy. String hacking in C.
793
794 If this needs to handle any more variables it should be hacked
795 into something table driven.
796 */
797static char **fix_environment(char **origenv, const char *preload)
798{
799 static const char inject_so[] = "vg_inject.so";
800 static const char ld_library_path[] = "LD_LIBRARY_PATH=";
801 static const char ld_preload[] = "LD_PRELOAD=";
802 static const char valgrind_clo[] = VALGRINDCLO "=";
803 static const int ld_library_path_len = sizeof(ld_library_path)-1;
804 static const int ld_preload_len = sizeof(ld_preload)-1;
805 static const int valgrind_clo_len = sizeof(valgrind_clo)-1;
806 int ld_preload_done = 0;
807 int ld_library_path_done = 0;
808 char *inject_path;
809 int inject_path_len;
810 int vgliblen = strlen(VG_(libdir));
811 char **cpp;
812 char **ret;
813 int envc;
814 const int preloadlen = (preload == NULL) ? 0 : strlen(preload);
815
816 /* Find the vg_inject.so; also make room for the tool preload
817 library */
818 inject_path_len = sizeof(inject_so) + vgliblen + preloadlen + 16;
819 inject_path = malloc(inject_path_len);
820
821 if (preload)
822 snprintf(inject_path, inject_path_len, "%s/%s:%s",
823 VG_(libdir), inject_so, preload);
824 else
825 snprintf(inject_path, inject_path_len, "%s/%s",
826 VG_(libdir), inject_so);
827
828 /* Count the original size of the env */
829 envc = 0; /* trailing NULL */
830 for (cpp = origenv; cpp && *cpp; cpp++)
831 envc++;
832
833 /* Allocate a new space */
834 ret = malloc(sizeof(char *) * (envc+3+1)); /* 3 new entries + NULL */
835
836 /* copy it over */
837 for (cpp = ret; *origenv; )
838 *cpp++ = *origenv++;
839 *cpp = NULL;
840
841 vg_assert(envc == (cpp - ret));
842
843 /* Walk over the new environment, mashing as we go */
844 for (cpp = ret; cpp && *cpp; cpp++) {
845 if (memcmp(*cpp, ld_library_path, ld_library_path_len) == 0) {
846 int done = 0;
847 int contains(const char *p) {
848 if (VG_STREQ(p, VG_(libdir))) {
849 done = 1;
850 return 1;
851 }
852 return 0;
853 }
854
855 /* If the LD_LIBRARY_PATH already contains libdir, then don't
856 bother adding it again, even if it isn't the first (it
857 seems that the Java runtime will keep reexecing itself
858 unless its paths are at the front of LD_LIBRARY_PATH) */
859 scan_colsep(*cpp + ld_library_path_len, contains);
860
861 if (!done) {
862 int len = strlen(*cpp) + vgliblen*2 + 16;
863 char *cp = malloc(len);
864
865 snprintf(cp, len, "%s%s:%s",
866 ld_library_path, VG_(libdir),
867 (*cpp)+ld_library_path_len);
868
869 *cpp = cp;
870 }
871
872 ld_library_path_done = 1;
873 } else if (memcmp(*cpp, ld_preload, ld_preload_len) == 0) {
874 int len = strlen(*cpp) + inject_path_len;
875 char *cp = malloc(len);
876
877 snprintf(cp, len, "%s%s:%s",
878 ld_preload, inject_path, (*cpp)+ld_preload_len);
879
880 *cpp = cp;
881
882 ld_preload_done = 1;
883 } else if (memcmp(*cpp, valgrind_clo, valgrind_clo_len) == 0) {
884 *cpp = "";
885 }
886 }
887
888 /* Add the missing bits */
889
890 if (!ld_library_path_done) {
891 int len = ld_library_path_len + vgliblen*2 + 16;
892 char *cp = malloc(len);
893
894 snprintf(cp, len, "%s%s", ld_library_path, VG_(libdir));
895
896 ret[envc++] = cp;
897 }
898
899 if (!ld_preload_done) {
900 int len = ld_preload_len + inject_path_len;
901 char *cp = malloc(len);
902
903 snprintf(cp, len, "%s%s",
904 ld_preload, inject_path);
905
906 ret[envc++] = cp;
907 }
908
909 ret[envc] = NULL;
910
911 return ret;
912}
913
914extern char **environ; /* our environment */
915//#include <error.h>
916
917/* Add a string onto the string table, and return its address */
918static char *copy_str(char **tab, const char *str)
919{
920 char *cp = *tab;
921 char *orig = cp;
922
923 while(*str)
924 *cp++ = *str++;
925 *cp++ = '\0';
926
927 if (0)
928 printf("copied %p \"%s\" len %d\n",
929 orig, orig, cp-orig);
930
931 *tab = cp;
932
933 return orig;
934}
935
936/*
937 This sets up the client's initial stack, containing the args,
938 environment and aux vector.
939
940 The format of the stack is:
941
942 higher address +-----------------+
943 | Trampoline code |
944 +-----------------+
945 | |
946 : string table :
947 | |
948 +-----------------+
949 | AT_NULL |
950 - -
951 | auxv |
952 +-----------------+
953 | NULL |
954 - -
955 | envp |
956 +-----------------+
957 | NULL |
958 - -
959 | argv |
960 +-----------------+
961 | argc |
962 lower address +-----------------+ <- esp
963 | undefined |
964 : :
965 */
966static Addr setup_client_stack(char **orig_argv, char **orig_envp,
967 const struct exeinfo *info,
968 UInt** client_auxv)
969{
970 char **cpp;
971 char *strtab; /* string table */
972 char *stringbase;
973 addr_t *ptr;
974 struct ume_auxv *auxv;
975 const struct ume_auxv *orig_auxv;
976 const struct ume_auxv *cauxv;
977 unsigned stringsize; /* total size of strings in bytes */
978 unsigned auxsize; /* total size of auxv in bytes */
979 int argc; /* total argc */
980 int envc; /* total number of env vars */
981 unsigned stacksize; /* total client stack size */
982 addr_t cl_esp; /* client stack base (initial esp) */
983
984 /* use our own auxv as a prototype */
985 orig_auxv = find_auxv(ume_exec_esp);
986
987 /* ==================== compute sizes ==================== */
988
989 /* first of all, work out how big the client stack will be */
990 stringsize = 0;
991
992 /* paste on the extra args if the loader needs them (ie, the #!
993 interpreter and its argument) */
994 argc = 0;
995 if (info->argv0 != NULL) {
996 argc++;
997 stringsize += strlen(info->argv0) + 1;
998 }
999 if (info->argv1 != NULL) {
1000 argc++;
1001 stringsize += strlen(info->argv1) + 1;
1002 }
1003
1004 /* now scan the args we're given... */
1005 for (cpp = orig_argv; *cpp; cpp++) {
1006 argc++;
1007 stringsize += strlen(*cpp) + 1;
1008 }
1009
1010 /* ...and the environment */
1011 envc = 0;
1012 for (cpp = orig_envp; cpp && *cpp; cpp++) {
1013 envc++;
1014 stringsize += strlen(*cpp) + 1;
1015 }
1016
1017 /* now, how big is the auxv? */
1018 auxsize = sizeof(*auxv); /* there's always at least one entry: AT_NULL */
1019 for (cauxv = orig_auxv; cauxv->a_type != AT_NULL; cauxv++) {
1020 if (cauxv->a_type == AT_PLATFORM)
1021 stringsize += strlen(cauxv->u.a_ptr) + 1;
1022 auxsize += sizeof(*cauxv);
1023 }
1024
1025 /* OK, now we know how big the client stack is */
1026 stacksize =
1027 sizeof(int) + /* argc */
1028 sizeof(char **)*argc + /* argv */
1029 sizeof(char **) + /* terminal NULL */
1030 sizeof(char **)*envc + /* envp */
1031 sizeof(char **) + /* terminal NULL */
1032 auxsize + /* auxv */
1033 ROUNDUP(stringsize, sizeof(int)) +/* strings (aligned) */
1034 VKI_BYTES_PER_PAGE; /* page for trampoline code */
1035
1036 /* cl_esp is the client's stack pointer */
1037 cl_esp = VG_(client_end) - stacksize;
1038 cl_esp = ROUNDDN(cl_esp, 16); /* make stack 16 byte aligned */
1039
1040 if (0)
1041 printf("stringsize=%d auxsize=%d stacksize=%d\n",
1042 stringsize, auxsize, stacksize);
1043
1044
1045 /* base of the string table (aligned) */
1046 stringbase = strtab = (char *)(VG_(client_trampoline_code) - ROUNDUP(stringsize, sizeof(int)));
1047
1048 VG_(clstk_base) = PGROUNDDN(cl_esp);
1049 VG_(clstk_end) = VG_(client_end);
1050
1051 /* ==================== allocate space ==================== */
1052
1053 /* allocate a stack - mmap enough space for the stack */
1054 mmap((void *)PGROUNDDN(cl_esp),
1055 VG_(client_end) - PGROUNDDN(cl_esp),
1056 PROT_READ | PROT_WRITE | PROT_EXEC,
1057 MAP_PRIVATE | MAP_ANON | MAP_FIXED, -1, 0);
1058
1059
1060 /* ==================== copy client stack ==================== */
1061
1062 ptr = (addr_t *)cl_esp;
1063
1064 /* --- argc --- */
1065 *ptr++ = argc; /* client argc */
1066
1067 /* --- argv --- */
1068 if (info->argv0) {
1069 *ptr++ = (addr_t)copy_str(&strtab, info->argv0);
1070 free(info->argv0);
1071 }
1072 if (info->argv1) {
1073 *ptr++ = (addr_t)copy_str(&strtab, info->argv1);
1074 free(info->argv1);
1075 }
1076 for (cpp = orig_argv; *cpp; ptr++, cpp++) {
1077 *ptr = (addr_t)copy_str(&strtab, *cpp);
1078 }
1079 *ptr++ = 0;
1080
1081 /* --- envp --- */
1082 VG_(client_envp) = (Char **)ptr;
1083 for (cpp = orig_envp; cpp && *cpp; ptr++, cpp++)
1084 *ptr = (addr_t)copy_str(&strtab, *cpp);
1085 *ptr++ = 0;
1086
1087 /* --- auxv --- */
1088 auxv = (struct ume_auxv *)ptr;
1089 *client_auxv = (UInt *)auxv;
1090
1091 for (; orig_auxv->a_type != AT_NULL; auxv++, orig_auxv++) {
1092 /* copy the entry... */
1093 *auxv = *orig_auxv;
1094
1095 /* ...and fix up the copy */
1096 switch(auxv->a_type) {
1097 case AT_PHDR:
1098 if (info->phdr == 0)
1099 auxv->a_type = AT_IGNORE;
1100 else
1101 auxv->u.a_val = info->phdr;
1102 break;
1103
1104 case AT_PHNUM:
1105 if (info->phdr == 0)
1106 auxv->a_type = AT_IGNORE;
1107 else
1108 auxv->u.a_val = info->phnum;
1109 break;
1110
1111 case AT_BASE:
1112 if (info->interp_base == 0)
1113 auxv->a_type = AT_IGNORE;
1114 else
1115 auxv->u.a_val = info->interp_base;
1116 break;
1117
1118 case AT_PLATFORM: /* points to a platform description string */
1119 auxv->u.a_ptr = copy_str(&strtab, orig_auxv->u.a_ptr);
1120 break;
1121
1122 case AT_ENTRY:
1123 auxv->u.a_val = info->entry;
1124 break;
1125
1126 case AT_IGNORE:
1127 case AT_EXECFD:
1128 case AT_PHENT:
1129 case AT_PAGESZ:
1130 case AT_FLAGS:
1131 case AT_NOTELF:
1132 case AT_UID:
1133 case AT_EUID:
1134 case AT_GID:
1135 case AT_EGID:
1136 case AT_CLKTCK:
1137 case AT_HWCAP:
1138 case AT_FPUCW:
1139 case AT_DCACHEBSIZE:
1140 case AT_ICACHEBSIZE:
1141 case AT_UCACHEBSIZE:
1142 /* All these are pointerless, so we don't need to do anything
1143 about them. */
1144 break;
1145
1146 case AT_SECURE:
1147 /* If this is 1, then it means that this program is running
1148 suid, and therefore the dynamic linker should be careful
1149 about LD_PRELOAD, etc. However, since stage1 (the thing
1150 the kernel actually execve's) should never be SUID, and we
1151 need LD_PRELOAD/LD_LIBRARY_PATH to work for the client, we
1152 set AT_SECURE to 0. */
1153 auxv->u.a_val = 0;
1154 break;
1155
1156 case AT_SYSINFO:
1157 /* Leave this unmolested for now, but we'll update it later
1158 when we set up the client trampoline code page */
1159 break;
1160
1161 case AT_SYSINFO_EHDR:
1162 /* Trash this, because we don't reproduce it */
1163 auxv->a_type = AT_IGNORE;
1164 break;
1165
1166 default:
1167 /* stomp out anything we don't know about */
1168 if (0)
1169 printf("stomping auxv entry %d\n", auxv->a_type);
1170 auxv->a_type = AT_IGNORE;
1171 break;
1172
1173 }
1174 }
1175 *auxv = *orig_auxv;
1176 vg_assert(auxv->a_type == AT_NULL);
1177
1178 vg_assert((strtab-stringbase) == stringsize);
1179
1180 return cl_esp;
1181}
1182
1183/*====================================================================*/
1184/*=== Find executable ===*/
1185/*====================================================================*/
1186
1187static const char* find_executable(const char* exec)
1188{
1189 vg_assert(NULL != exec);
1190 if (strchr(exec, '/') == NULL) {
1191 /* no '/' - we need to search the path */
1192 char *path = getenv("PATH");
1193 int pathlen = path ? strlen(path) : 0;
1194
1195 int match_exe(const char *entry) {
1196 char buf[pathlen + strlen(entry) + 3];
1197
1198 /* empty PATH element means . */
1199 if (*entry == '\0')
1200 entry = ".";
1201
1202 snprintf(buf, sizeof(buf), "%s/%s", entry, exec);
1203
1204 if (access(buf, R_OK|X_OK) == 0) {
1205 exec = strdup(buf);
1206 vg_assert(NULL != exec);
1207 return 1;
1208 }
1209 return 0;
1210 }
1211 scan_colsep(path, match_exe);
1212 }
1213 return exec;
1214}
1215
1216
1217/*====================================================================*/
1218/*=== Loading tools ===*/
1219/*====================================================================*/
1220
1221static void list_tools(void)
1222{
1223 DIR *dir = opendir(VG_(libdir));
1224 struct dirent *de;
1225 int first = 1;
1226
1227 if (dir == NULL) {
1228 fprintf(stderr, "Can't open %s: %s (installation problem?)\n",
1229 VG_(libdir), strerror(errno));
1230 return;
1231 }
1232
1233 while((de = readdir(dir)) != NULL) {
1234 int len = strlen(de->d_name);
1235
1236 /* look for vgskin_TOOL.so names */
1237 if (len > (7+1+3) && /* "vgskin_" + at least 1-char toolname + ".so" */
1238 strncmp(de->d_name, "vgskin_", 7) == 0 &&
1239 VG_STREQ(de->d_name + len - 3, ".so")) {
1240 if (first) {
1241 printf("Available tools:\n");
1242 first = 0;
1243 }
1244 de->d_name[len-3] = '\0';
1245 printf("\t%s\n", de->d_name+7);
1246 }
1247 }
1248
1249 closedir(dir);
1250
1251 if (first)
1252 printf("No tools available in \"%s\" (installation problem?)\n",
1253 VG_(libdir));
1254}
1255
1256
1257/* Find and load a tool, and check it looks ok. Also looks to see if there's
1258 * a matching vgpreload_*.so file, and returns its name in *preloadpath. */
1259static void load_tool( const char *toolname, void** handle_out,
1260 ToolInfo** toolinfo_out, char **preloadpath_out )
1261{
1262 Bool ok;
1263 int len = strlen(VG_(libdir)) + strlen(toolname)*2 + 16;
1264 char buf[len];
1265 void* handle;
1266 ToolInfo* toolinfo;
1267 char* preloadpath = NULL;
1268 Int* vg_malloc_redzonep;
1269
1270 // XXX: allowing full paths for --tool option -- does it make sense?
1271 // Doesn't allow for vgpreload_<tool>.so.
1272
1273 if (strchr(toolname, '/') != 0) {
1274 /* toolname contains '/', and so must be a pathname */
1275 handle = dlopen(toolname, RTLD_NOW);
1276 } else {
1277 /* just try in the libdir */
1278 snprintf(buf, len, "%s/vgskin_%s.so", VG_(libdir), toolname);
1279 handle = dlopen(buf, RTLD_NOW);
1280
1281 if (handle != NULL) {
1282 snprintf(buf, len, "%s/vgpreload_%s.so", VG_(libdir), toolname);
1283 if (access(buf, R_OK) == 0) {
1284 preloadpath = strdup(buf);
1285 vg_assert(NULL != preloadpath);
1286 }
1287 }
1288 }
1289
1290 ok = (NULL != handle);
1291 if (!ok) {
1292 fprintf(stderr, "Can't open tool \"%s\": %s\n", toolname, dlerror());
1293 goto bad_load;
1294 }
1295
1296 toolinfo = dlsym(handle, "vgSkin_tool_info");
1297 ok = (NULL != toolinfo);
1298 if (!ok) {
1299 fprintf(stderr, "Tool \"%s\" doesn't define SK_(tool_info) - "
1300 "add VG_DETERMINE_INTERFACE_VERSION?\n", toolname);
1301 goto bad_load;
1302 }
1303
1304 ok = (toolinfo->sizeof_ToolInfo == sizeof(*toolinfo) &&
1305 toolinfo->interface_major_version == VG_CORE_INTERFACE_MAJOR_VERSION &&
1306 toolinfo->sk_pre_clo_init != NULL);
1307 if (!ok) {
1308 fprintf(stderr, "Error:\n"
1309 " Tool and core interface versions do not match.\n"
1310 " Interface version used by core is: %d.%d (size %d)\n"
1311 " Interface version used by tool is: %d.%d (size %d)\n"
1312 " The major version numbers must match.\n",
1313 VG_CORE_INTERFACE_MAJOR_VERSION,
1314 VG_CORE_INTERFACE_MINOR_VERSION,
1315 sizeof(*toolinfo),
1316 toolinfo->interface_major_version,
1317 toolinfo->interface_minor_version,
1318 toolinfo->sizeof_ToolInfo);
1319 fprintf(stderr, " You need to at least recompile, and possibly update,\n");
1320 if (VG_CORE_INTERFACE_MAJOR_VERSION > toolinfo->interface_major_version)
1321 fprintf(stderr, " your skin to work with this version of Valgrind.\n");
1322 else
1323 fprintf(stderr, " your version of Valgrind to work with this skin.\n");
1324 goto bad_load;
1325 }
1326
1327 // Set redzone size for V's allocator
1328 vg_malloc_redzonep = dlsym(handle, STR(VG_(vg_malloc_redzone_szB)));
1329 if ( NULL != vg_malloc_redzonep ) {
1330 VG_(vg_malloc_redzone_szB) = *vg_malloc_redzonep;
1331 }
1332
1333 vg_assert(NULL != handle && NULL != toolinfo);
1334 *handle_out = handle;
1335 *toolinfo_out = toolinfo;
1336 *preloadpath_out = preloadpath;
1337 return;
1338
1339
1340 bad_load:
1341 if (handle != NULL)
1342 dlclose(handle);
1343
1344 fprintf(stderr, "Aborting: couldn't load tool\n");
1345 list_tools();
1346 exit(127);
1347}
1348
1349/*====================================================================*/
1350/*=== Loading the client ===*/
1351/*====================================================================*/
1352
1353static void load_client(char* cl_argv[], const char* exec,
nethercote6c999f22004-01-31 22:55:15 +00001354 /*inout*/Int* need_help,
nethercote71980f02004-01-24 18:18:54 +00001355 /*out*/struct exeinfo* info, /*out*/Addr* client_eip)
1356{
1357 // If they didn't specify an executable with --exec, and didn't specify
1358 // --help, then use client argv[0] (searching $PATH if necessary).
1359 if (NULL == exec && !*need_help) {
1360 if (cl_argv[0] == NULL ||
1361 ( NULL == (exec = find_executable(cl_argv[0])) ) )
1362 {
nethercote6c999f22004-01-31 22:55:15 +00001363 *need_help = 1;
nethercote71980f02004-01-24 18:18:54 +00001364 }
1365 }
1366
1367 info->map_base = VG_(client_mapbase);
nethercote71980f02004-01-24 18:18:54 +00001368
1369 info->exe_base = VG_(client_base);
1370 info->exe_end = VG_(client_end);
1371 info->argv = cl_argv;
1372
1373 if (*need_help) {
1374 VG_(clexecfd) = -1;
1375 info->argv0 = NULL;
1376 info->argv1 = NULL;
1377 } else {
1378 Int ret;
1379 VG_(clexecfd) = VG_(open)(exec, O_RDONLY, VKI_S_IRUSR);
1380 ret = do_exec(exec, info);
1381 if (ret != 0) {
1382 fprintf(stderr, "do_exec(%s) failed: %s\n", exec, strerror(ret));
1383 exit(127);
1384 }
1385 }
1386
1387 /* Copy necessary bits of 'info' that were filled in */
1388 *client_eip = info->init_eip;
1389 VG_(brk_base) = VG_(brk_limit) = info->brkbase;
1390}
1391
1392
1393/*====================================================================*/
1394/*=== Command-line: variables, processing ===*/
1395/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +00001396
njn25e49d8e72002-09-23 09:36:25 +00001397/* Define, and set defaults. */
1398Bool VG_(clo_error_limit) = True;
nethercote04d0fbc2004-01-26 16:48:06 +00001399Bool VG_(clo_db_attach) = False;
1400Char* VG_(clo_db_command) = VG_CLO_DEFAULT_DBCOMMAND;
njn43c799e2003-04-08 00:08:52 +00001401Bool VG_(clo_gen_suppressions) = False;
njn25e49d8e72002-09-23 09:36:25 +00001402Int VG_(sanity_level) = 1;
1403Int VG_(clo_verbosity) = 1;
1404Bool VG_(clo_demangle) = True;
njn25e49d8e72002-09-23 09:36:25 +00001405Bool VG_(clo_trace_children) = False;
sewardj4cf05692002-10-27 20:28:29 +00001406
nethercotee1730692003-11-20 10:38:07 +00001407/* See big comment in vg_include.h for meaning of these three.
1408 fd is initially stdout, for --help, but gets moved to stderr by default
1409 immediately afterwards. */
sewardj4cf05692002-10-27 20:28:29 +00001410VgLogTo VG_(clo_log_to) = VgLogTo_Fd;
nethercotee1730692003-11-20 10:38:07 +00001411Int VG_(clo_logfile_fd) = 1;
sewardj4cf05692002-10-27 20:28:29 +00001412Char* VG_(clo_logfile_name) = NULL;
1413
sewardj6024b212003-07-13 10:54:33 +00001414Int VG_(clo_input_fd) = 0; /* stdin */
njn25e49d8e72002-09-23 09:36:25 +00001415Int VG_(clo_n_suppressions) = 0;
sewardjde4a1d02002-03-22 01:27:54 +00001416Char* VG_(clo_suppressions)[VG_CLO_MAX_SFILES];
njn25e49d8e72002-09-23 09:36:25 +00001417Bool VG_(clo_profile) = False;
1418Bool VG_(clo_single_step) = False;
1419Bool VG_(clo_optimise) = True;
1420UChar VG_(clo_trace_codegen) = 0; // 00000000b
1421Bool VG_(clo_trace_syscalls) = False;
1422Bool VG_(clo_trace_signals) = False;
1423Bool VG_(clo_trace_symtab) = False;
njn25e49d8e72002-09-23 09:36:25 +00001424Bool VG_(clo_trace_sched) = False;
1425Int VG_(clo_trace_pthread_level) = 0;
njn25e49d8e72002-09-23 09:36:25 +00001426Int VG_(clo_dump_error) = 0;
1427Int VG_(clo_backtrace_size) = 4;
1428Char* VG_(clo_weird_hacks) = NULL;
sewardj858964b2002-10-05 14:15:43 +00001429Bool VG_(clo_run_libc_freeres) = True;
rjwalshf5f536f2003-11-17 17:45:00 +00001430Bool VG_(clo_track_fds) = False;
sewardj22854b92002-11-30 14:00:47 +00001431Bool VG_(clo_chain_bb) = True;
nethercote77eba602003-11-13 17:35:04 +00001432Bool VG_(clo_show_below_main) = False;
fitzhardinge98abfc72003-12-16 02:05:15 +00001433Bool VG_(clo_pointercheck) = True;
fitzhardinge462f4f92003-12-18 02:10:54 +00001434Bool VG_(clo_branchpred) = False;
sewardj2370f3b2002-11-30 15:01:01 +00001435
jsgf855d93d2003-10-13 22:26:55 +00001436static Bool VG_(clo_wait_for_gdb) = False;
1437
1438/* If we're doing signal routing, poll for signals every 50mS by
1439 default. */
1440Int VG_(clo_signal_polltime) = 50;
1441
1442/* These flags reduce thread wakeup latency on syscall completion and
1443 signal delivery, respectively. The downside is possible unfairness. */
1444Bool VG_(clo_lowlat_syscalls) = False; /* low-latency syscalls */
1445Bool VG_(clo_lowlat_signals) = False; /* low-latency signals */
1446
sewardjde4a1d02002-03-22 01:27:54 +00001447
njn25e49d8e72002-09-23 09:36:25 +00001448void VG_(bad_option) ( Char* opt )
sewardjde4a1d02002-03-22 01:27:54 +00001449{
1450 VG_(shutdown_logging)();
sewardj4cf05692002-10-27 20:28:29 +00001451 VG_(clo_log_to) = VgLogTo_Fd;
sewardjde4a1d02002-03-22 01:27:54 +00001452 VG_(clo_logfile_fd) = 2; /* stderr */
1453 VG_(printf)("valgrind.so: Bad option `%s'; aborting.\n", opt);
1454 VG_(exit)(1);
1455}
1456
1457static void config_error ( Char* msg )
1458{
1459 VG_(shutdown_logging)();
sewardj4cf05692002-10-27 20:28:29 +00001460 VG_(clo_log_to) = VgLogTo_Fd;
sewardjde4a1d02002-03-22 01:27:54 +00001461 VG_(clo_logfile_fd) = 2; /* stderr */
sewardj19d81412002-06-03 01:10:40 +00001462 VG_(printf)(
fitzhardinge98abfc72003-12-16 02:05:15 +00001463 "valgrind: Startup or configuration error:\n %s\n", msg);
sewardj19d81412002-06-03 01:10:40 +00001464 VG_(printf)(
fitzhardinge98abfc72003-12-16 02:05:15 +00001465 "valgrind: Unable to start up properly. Giving up.\n");
sewardjde4a1d02002-03-22 01:27:54 +00001466 VG_(exit)(1);
1467}
1468
nethercote6c999f22004-01-31 22:55:15 +00001469void usage ( Bool debug_help )
njn7cf0bd32002-06-08 13:36:03 +00001470{
njn25e49d8e72002-09-23 09:36:25 +00001471 Char* usage1 =
nethercote71980f02004-01-24 18:18:54 +00001472"usage: valgrind --tool=<toolname> [options] prog-and-args\n"
njn25e49d8e72002-09-23 09:36:25 +00001473"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001474" common user options for all Valgrind tools, with defaults in [ ]:\n"
nethercote71980f02004-01-24 18:18:54 +00001475" --tool=<name> Use the Valgrind tool named <name>\n"
njn25e49d8e72002-09-23 09:36:25 +00001476" --help show this message\n"
nethercote6c999f22004-01-31 22:55:15 +00001477" --help-debug show this message, plus debugging options\n"
njn25e49d8e72002-09-23 09:36:25 +00001478" --version show version\n"
njn25e49d8e72002-09-23 09:36:25 +00001479" -q --quiet run silently; only print error msgs\n"
1480" -v --verbose be more verbose, incl counts of errors\n"
nethercote77eba602003-11-13 17:35:04 +00001481" --trace-children=no|yes Valgrind-ise child processes? [no]\n"
rjwalshf5f536f2003-11-17 17:45:00 +00001482" --track-fds=no|yes Track open file descriptors? [no]\n"
nethercote2b0793f2003-12-02 10:41:18 +00001483"\n"
1484" uncommon user options for all Valgrind tools:\n"
nethercote77eba602003-11-13 17:35:04 +00001485" --run-libc-freeres=no|yes Free up glibc memory at exit? [yes]\n"
1486" --weird-hacks=hack1,hack2,... [none]\n"
sewardj3d652a32002-10-20 18:11:49 +00001487" recognised hacks are: ioctl-VTIME truncate-writes lax-ioctls\n"
jsgf855d93d2003-10-13 22:26:55 +00001488" --signal-polltime=<time> time, in mS, we should poll for signals.\n"
1489" Only applies for older kernels which need\n"
1490" signal routing [50]\n"
1491" --lowlat-signals=no|yes improve wake-up latency when a thread receives\n"
1492" a signal [no]\n"
1493" --lowlat-syscalls=no|yes improve wake-up latency when a thread's\n"
1494" syscall completes [no]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001495" --pointercheck=no|yes enforce client address space limits [yes]\n"
njn25e49d8e72002-09-23 09:36:25 +00001496"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001497" user options for Valgrind tools that report errors:\n"
1498" --logfile-fd=<number> file descriptor for messages [2=stderr]\n"
1499" --logfile=<file> log messages to <file>.pid<pid>\n"
1500" --logsocket=ipaddr:port log messages to socket ipaddr:port\n"
1501" --demangle=no|yes automatically demangle C++ names? [yes]\n"
1502" --num-callers=<number> show <num> callers in stack traces [4]\n"
1503" --error-limit=no|yes stop showing new errors if too many? [yes]\n"
1504" --show-below-main=no|yes continue stack traces below main() [no]\n"
1505" --suppressions=<filename> suppress errors described in <filename>\n"
1506" --gen-suppressions=no|yes print suppressions for errors detected [no]\n"
njn7cf0bd32002-06-08 13:36:03 +00001507
nethercote04d0fbc2004-01-26 16:48:06 +00001508" --db-attach=no|yes start debugger when errors detected? [no]\n"
1509" --db-command=<command> command to start debugger [gdb -nw %%f %%p]\n"
1510" --input-fd=<number> file descriptor for input [0=stdin]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001511"\n";
njn7cf0bd32002-06-08 13:36:03 +00001512
njn25e49d8e72002-09-23 09:36:25 +00001513 Char* usage2 =
1514"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001515" debugging options for all Valgrind tools:\n"
njn25e49d8e72002-09-23 09:36:25 +00001516" --sanity-level=<number> level of sanity checking to do [1]\n"
1517" --single-step=no|yes translate each instr separately? [no]\n"
1518" --optimise=no|yes improve intermediate code? [yes]\n"
nethercote137bc552003-11-14 17:47:54 +00001519" --profile=no|yes profile? (tool must be built for it) [no]\n"
sewardj22854b92002-11-30 14:00:47 +00001520" --chain-bb=no|yes do basic-block chaining? [yes]\n"
fitzhardinge462f4f92003-12-18 02:10:54 +00001521" --branchpred=yes|no generate branch prediction hints [no]\n"
njn25e49d8e72002-09-23 09:36:25 +00001522" --trace-codegen=<XXXXX> show generated code? (X = 0|1) [00000]\n"
1523" --trace-syscalls=no|yes show all system calls? [no]\n"
1524" --trace-signals=no|yes show signal handling details? [no]\n"
1525" --trace-symtab=no|yes show symbol table details? [no]\n"
njn25e49d8e72002-09-23 09:36:25 +00001526" --trace-sched=no|yes show thread scheduler details? [no]\n"
njn3e884182003-04-15 13:03:23 +00001527" --trace-pthread=none|some|all show pthread event details? [none]\n"
jsgf855d93d2003-10-13 22:26:55 +00001528" --wait-for-gdb=yes|no pause on startup to wait for gdb attach\n"
njn25e49d8e72002-09-23 09:36:25 +00001529"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001530" debugging options for Valgrind tools that report errors\n"
1531" --dump-error=<number> show translation for basic block associated\n"
1532" with <number>'th error context [0=show none]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001533"\n";
njn3e884182003-04-15 13:03:23 +00001534
1535 Char* usage3 =
1536"\n"
nethercote71980f02004-01-24 18:18:54 +00001537" Extra options read from ~/.valgrindrc, $VALGRIND_OPTS, ./.valgrindrc\n"
njn25e49d8e72002-09-23 09:36:25 +00001538"\n"
nethercotebb1c9912004-01-04 16:43:23 +00001539" Valgrind is Copyright (C) 2000-2004 Julian Seward\n"
njn25e49d8e72002-09-23 09:36:25 +00001540" and licensed under the GNU General Public License, version 2.\n"
1541" Bug reports, feedback, admiration, abuse, etc, to: %s.\n"
njnd04b7c62002-10-03 14:05:52 +00001542"\n"
nethercote137bc552003-11-14 17:47:54 +00001543" Tools are copyright and licensed by their authors. See each\n"
1544" tool's start-up message for more information.\n"
njn25e49d8e72002-09-23 09:36:25 +00001545"\n";
njn7cf0bd32002-06-08 13:36:03 +00001546
fitzhardinge98abfc72003-12-16 02:05:15 +00001547 VG_(printf)(usage1);
1548 if (VG_(details).name) {
1549 VG_(printf)(" user options for %s:\n", VG_(details).name);
1550 /* Don't print skin string directly for security, ha! */
1551 if (VG_(needs).command_line_options)
1552 SK_(print_usage)();
1553 else
1554 VG_(printf)(" (none)\n");
1555 }
nethercote6c999f22004-01-31 22:55:15 +00001556 if (debug_help) {
1557 VG_(printf)(usage2);
fitzhardinge98abfc72003-12-16 02:05:15 +00001558
nethercote6c999f22004-01-31 22:55:15 +00001559 if (VG_(details).name) {
1560 VG_(printf)(" debugging options for %s:\n", VG_(details).name);
1561
1562 if (VG_(needs).command_line_options)
1563 SK_(print_debug_usage)();
1564 else
1565 VG_(printf)(" (none)\n");
1566 }
fitzhardinge98abfc72003-12-16 02:05:15 +00001567 }
nethercote421281e2003-11-20 16:20:55 +00001568 VG_(printf)(usage3, VG_BUGS_TO);
njn7cf0bd32002-06-08 13:36:03 +00001569
njn25e49d8e72002-09-23 09:36:25 +00001570 VG_(shutdown_logging)();
sewardj4cf05692002-10-27 20:28:29 +00001571 VG_(clo_log_to) = VgLogTo_Fd;
njn25e49d8e72002-09-23 09:36:25 +00001572 VG_(clo_logfile_fd) = 2; /* stderr */
1573 VG_(exit)(1);
njn7cf0bd32002-06-08 13:36:03 +00001574}
sewardjde4a1d02002-03-22 01:27:54 +00001575
nethercote71980f02004-01-24 18:18:54 +00001576static void pre_process_cmd_line_options
nethercote6c999f22004-01-31 22:55:15 +00001577 ( Int* need_help, const char** tool, const char** exec )
sewardj1c1b1162003-02-23 01:25:51 +00001578{
nethercote71980f02004-01-24 18:18:54 +00001579 UInt i;
sewardjde4a1d02002-03-22 01:27:54 +00001580
nethercote71980f02004-01-24 18:18:54 +00001581 /* parse the options we have (only the options we care about now) */
1582 for (i = 1; i < VG_(vg_argc); i++) {
1583
1584 if (strcmp(VG_(vg_argv)[i], "--version") == 0) {
1585 printf("valgrind-" VERSION "\n");
1586 exit(1);
1587
1588 } else if (strcmp(VG_(vg_argv)[i], "--help") == 0) {
nethercote6c999f22004-01-31 22:55:15 +00001589 *need_help = 1;
1590
1591 } else if (strcmp(VG_(vg_argv)[i], "--help-debug") == 0) {
1592 *need_help = 2;
nethercote71980f02004-01-24 18:18:54 +00001593
1594 } else if (strncmp(VG_(vg_argv)[i], "--tool=", 7) == 0 ||
1595 strncmp(VG_(vg_argv)[i], "--skin=", 7) == 0) {
1596 *tool = &VG_(vg_argv)[i][7];
1597
1598 } else if (strncmp(VG_(vg_argv)[i], "--exec=", 7) == 0) {
1599 *exec = &VG_(vg_argv)[i][7];
1600 }
1601 }
1602
1603 /* If no tool specified, can give usage message without loading tool */
1604 if (*tool == NULL) {
1605 if (!need_help)
1606 list_tools();
nethercote6c999f22004-01-31 22:55:15 +00001607 usage(/*help-debug?*/False);
nethercote71980f02004-01-24 18:18:54 +00001608 }
1609}
1610
1611static void process_cmd_line_options
1612 ( UInt* client_auxv, Addr esp_at_startup,
nethercote6c999f22004-01-31 22:55:15 +00001613 const char* toolname, Int need_help )
nethercote71980f02004-01-24 18:18:54 +00001614{
1615 Int i, eventually_logfile_fd;
1616 Int *auxp;
1617 Int toolname_len = VG_(strlen)(toolname);
sewardjde4a1d02002-03-22 01:27:54 +00001618
nethercotee1730692003-11-20 10:38:07 +00001619 /* log to stderr by default, but usage message goes to stdout */
1620 eventually_logfile_fd = 2;
sewardjde4a1d02002-03-22 01:27:54 +00001621
1622 /* Once logging is started, we can safely send messages pertaining
1623 to failures in initialisation. */
1624 VG_(startup_logging)();
1625
sewardj19d81412002-06-03 01:10:40 +00001626 /* Check for sane path in ./configure --prefix=... */
fitzhardinge98abfc72003-12-16 02:05:15 +00001627 if (VG_LIBDIR[0] != '/')
sewardj19d81412002-06-03 01:10:40 +00001628 config_error("Please use absolute paths in "
1629 "./configure --prefix=... or --libdir=...");
sewardj38170912002-05-10 21:07:22 +00001630
nethercote71980f02004-01-24 18:18:54 +00001631 for (auxp = client_auxv; auxp[0] != VKI_AT_NULL; auxp += 2) {
fitzhardinge98abfc72003-12-16 02:05:15 +00001632 switch(auxp[0]) {
1633 case VKI_AT_SYSINFO:
1634 VG_(sysinfo_page_exists) = True;
fitzhardinge92360792003-12-24 10:11:11 +00001635 auxp[1] = (Int)(VG_(client_trampoline_code) + VG_(tramp_syscall_offset));
fitzhardinge98abfc72003-12-16 02:05:15 +00001636 VG_(sysinfo_page_addr) = auxp[1];
1637 break;
sewardjde4a1d02002-03-22 01:27:54 +00001638 }
fitzhardinge98abfc72003-12-16 02:05:15 +00001639 }
sewardjde4a1d02002-03-22 01:27:54 +00001640
nethercote71980f02004-01-24 18:18:54 +00001641 if (need_help)
nethercote6c999f22004-01-31 22:55:15 +00001642 usage(/*--help-debug?*/need_help == 2);
fitzhardinge98abfc72003-12-16 02:05:15 +00001643
1644 /* We know the initial ESP is pointing at argc/argv */
nethercote71980f02004-01-24 18:18:54 +00001645 VG_(client_argc) = *(Int *)esp_at_startup;
1646 VG_(client_argv) = (Char **)(esp_at_startup + sizeof(Int));
fitzhardinge98abfc72003-12-16 02:05:15 +00001647
nethercote71980f02004-01-24 18:18:54 +00001648 for (i = 1; i < VG_(vg_argc); i++) {
1649
1650 Char* arg = VG_(vg_argv)[i];
1651
1652 // XXX: allow colons in options, for Josef
1653
1654 /* Look for matching "--toolname:foo" */
1655 if (VG_(strstr)(arg, ":")) {
1656 if (VG_CLO_STREQN(2, arg, "--") &&
1657 VG_CLO_STREQN(toolname_len, arg+2, toolname) &&
1658 VG_CLO_STREQN(1, arg+2+toolname_len, ":"))
1659 {
1660 // prefix matches, convert "--toolname:foo" to "--foo"
1661 if (0)
1662 VG_(printf)("tool-specific arg: %s\n", arg);
1663 arg += toolname_len + 1;
1664 arg[0] = '-';
1665 arg[1] = '-';
1666
1667 } else {
1668 // prefix doesn't match, skip to next arg
1669 continue;
1670 }
1671 }
1672
fitzhardinge98abfc72003-12-16 02:05:15 +00001673 /* Ignore these options - they've already been handled */
nethercote71980f02004-01-24 18:18:54 +00001674 if (VG_CLO_STREQN(7, arg, "--tool=") ||
1675 VG_CLO_STREQN(7, arg, "--skin="))
fitzhardinge98abfc72003-12-16 02:05:15 +00001676 continue;
nethercote71980f02004-01-24 18:18:54 +00001677 if (VG_CLO_STREQN(7, arg, "--exec="))
fitzhardinge98abfc72003-12-16 02:05:15 +00001678 continue;
1679
nethercote71980f02004-01-24 18:18:54 +00001680 if ( VG_CLO_STREQ(arg, "--"))
fitzhardinge98abfc72003-12-16 02:05:15 +00001681 continue;
nethercote71980f02004-01-24 18:18:54 +00001682 else if (VG_CLO_STREQ(arg, "-v") ||
1683 VG_CLO_STREQ(arg, "--verbose"))
sewardjde4a1d02002-03-22 01:27:54 +00001684 VG_(clo_verbosity)++;
nethercote71980f02004-01-24 18:18:54 +00001685 else if (VG_CLO_STREQ(arg, "-q") ||
1686 VG_CLO_STREQ(arg, "--quiet"))
sewardjde4a1d02002-03-22 01:27:54 +00001687 VG_(clo_verbosity)--;
1688
nethercote71980f02004-01-24 18:18:54 +00001689 else if (VG_CLO_STREQ(arg, "--error-limit=yes"))
sewardj2e432902002-06-13 20:44:00 +00001690 VG_(clo_error_limit) = True;
nethercote71980f02004-01-24 18:18:54 +00001691 else if (VG_CLO_STREQ(arg, "--error-limit=no"))
sewardj2e432902002-06-13 20:44:00 +00001692 VG_(clo_error_limit) = False;
sewardj72f98ff2002-06-13 17:23:38 +00001693
nethercote04d0fbc2004-01-26 16:48:06 +00001694 else if (VG_CLO_STREQ(arg, "--db-attach=yes"))
1695 VG_(clo_db_attach) = True;
1696 else if (VG_CLO_STREQ(arg, "--db-attach=no"))
1697 VG_(clo_db_attach) = False;
sewardjde4a1d02002-03-22 01:27:54 +00001698
nethercote04d0fbc2004-01-26 16:48:06 +00001699 else if (VG_CLO_STREQN(13,arg, "--db-command="))
1700 VG_(clo_db_command) = &arg[13];
sewardj6024b212003-07-13 10:54:33 +00001701
nethercote71980f02004-01-24 18:18:54 +00001702 else if (VG_CLO_STREQ(arg, "--gen-suppressions=yes"))
njn43c799e2003-04-08 00:08:52 +00001703 VG_(clo_gen_suppressions) = True;
nethercote71980f02004-01-24 18:18:54 +00001704 else if (VG_CLO_STREQ(arg, "--gen-suppressions=no"))
njn43c799e2003-04-08 00:08:52 +00001705 VG_(clo_gen_suppressions) = False;
1706
nethercote71980f02004-01-24 18:18:54 +00001707 else if (VG_CLO_STREQ(arg, "--show-below-main=yes"))
nethercote77eba602003-11-13 17:35:04 +00001708 VG_(clo_show_below_main) = True;
nethercote71980f02004-01-24 18:18:54 +00001709 else if (VG_CLO_STREQ(arg, "--show-below-main=no"))
nethercote77eba602003-11-13 17:35:04 +00001710 VG_(clo_show_below_main) = False;
1711
nethercote71980f02004-01-24 18:18:54 +00001712 else if (VG_CLO_STREQ(arg, "--pointercheck=yes"))
fitzhardinge98abfc72003-12-16 02:05:15 +00001713 VG_(clo_pointercheck) = True;
nethercote71980f02004-01-24 18:18:54 +00001714 else if (VG_CLO_STREQ(arg, "--pointercheck=no"))
fitzhardinge98abfc72003-12-16 02:05:15 +00001715 VG_(clo_pointercheck) = False;
1716
nethercote71980f02004-01-24 18:18:54 +00001717 else if (VG_CLO_STREQ(arg, "--demangle=yes"))
sewardjde4a1d02002-03-22 01:27:54 +00001718 VG_(clo_demangle) = True;
nethercote71980f02004-01-24 18:18:54 +00001719 else if (VG_CLO_STREQ(arg, "--demangle=no"))
sewardjde4a1d02002-03-22 01:27:54 +00001720 VG_(clo_demangle) = False;
1721
nethercote71980f02004-01-24 18:18:54 +00001722 else if (VG_CLO_STREQ(arg, "--trace-children=yes"))
sewardjde4a1d02002-03-22 01:27:54 +00001723 VG_(clo_trace_children) = True;
nethercote71980f02004-01-24 18:18:54 +00001724 else if (VG_CLO_STREQ(arg, "--trace-children=no"))
sewardjde4a1d02002-03-22 01:27:54 +00001725 VG_(clo_trace_children) = False;
1726
nethercote71980f02004-01-24 18:18:54 +00001727 else if (VG_CLO_STREQ(arg, "--run-libc-freeres=yes"))
sewardj858964b2002-10-05 14:15:43 +00001728 VG_(clo_run_libc_freeres) = True;
nethercote71980f02004-01-24 18:18:54 +00001729 else if (VG_CLO_STREQ(arg, "--run-libc-freeres=no"))
sewardj858964b2002-10-05 14:15:43 +00001730 VG_(clo_run_libc_freeres) = False;
1731
nethercote71980f02004-01-24 18:18:54 +00001732 else if (VG_CLO_STREQ(arg, "--track-fds=yes"))
rjwalshf5f536f2003-11-17 17:45:00 +00001733 VG_(clo_track_fds) = True;
nethercote71980f02004-01-24 18:18:54 +00001734 else if (VG_CLO_STREQ(arg, "--track-fds=no"))
rjwalshf5f536f2003-11-17 17:45:00 +00001735 VG_(clo_track_fds) = False;
1736
nethercote71980f02004-01-24 18:18:54 +00001737 else if (VG_CLO_STREQN(15, arg, "--sanity-level="))
1738 VG_(sanity_level) = (Int)VG_(atoll)(&arg[15]);
sewardjde4a1d02002-03-22 01:27:54 +00001739
nethercote71980f02004-01-24 18:18:54 +00001740 else if (VG_CLO_STREQN(13, arg, "--logfile-fd=")) {
sewardj4cf05692002-10-27 20:28:29 +00001741 VG_(clo_log_to) = VgLogTo_Fd;
1742 VG_(clo_logfile_name) = NULL;
nethercote71980f02004-01-24 18:18:54 +00001743 eventually_logfile_fd = (Int)VG_(atoll)(&arg[13]);
sewardj4cf05692002-10-27 20:28:29 +00001744 }
1745
nethercote71980f02004-01-24 18:18:54 +00001746 else if (VG_CLO_STREQN(10, arg, "--logfile=")) {
sewardj4cf05692002-10-27 20:28:29 +00001747 VG_(clo_log_to) = VgLogTo_File;
nethercote71980f02004-01-24 18:18:54 +00001748 VG_(clo_logfile_name) = &arg[10];
sewardj4cf05692002-10-27 20:28:29 +00001749 }
sewardjde4a1d02002-03-22 01:27:54 +00001750
nethercote71980f02004-01-24 18:18:54 +00001751 else if (VG_CLO_STREQN(12, arg, "--logsocket=")) {
sewardj73cf3bc2002-11-03 03:20:15 +00001752 VG_(clo_log_to) = VgLogTo_Socket;
nethercote71980f02004-01-24 18:18:54 +00001753 VG_(clo_logfile_name) = &arg[12];
sewardj73cf3bc2002-11-03 03:20:15 +00001754 }
1755
nethercote71980f02004-01-24 18:18:54 +00001756 else if (VG_CLO_STREQN(11, arg, "--input-fd="))
1757 VG_(clo_input_fd) = (Int)VG_(atoll)(&arg[11]);
sewardj6024b212003-07-13 10:54:33 +00001758
nethercote71980f02004-01-24 18:18:54 +00001759 else if (VG_CLO_STREQN(15, arg, "--suppressions=")) {
sewardjde4a1d02002-03-22 01:27:54 +00001760 if (VG_(clo_n_suppressions) >= VG_CLO_MAX_SFILES) {
njn25e49d8e72002-09-23 09:36:25 +00001761 VG_(message)(Vg_UserMsg, "Too many suppression files specified.");
sewardjde4a1d02002-03-22 01:27:54 +00001762 VG_(message)(Vg_UserMsg,
1763 "Increase VG_CLO_MAX_SFILES and recompile.");
nethercote71980f02004-01-24 18:18:54 +00001764 VG_(bad_option)(arg);
sewardjde4a1d02002-03-22 01:27:54 +00001765 }
nethercote71980f02004-01-24 18:18:54 +00001766 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = &arg[15];
sewardjde4a1d02002-03-22 01:27:54 +00001767 VG_(clo_n_suppressions)++;
1768 }
nethercote71980f02004-01-24 18:18:54 +00001769 else if (VG_CLO_STREQ(arg, "--profile=yes"))
njn25e49d8e72002-09-23 09:36:25 +00001770 VG_(clo_profile) = True;
nethercote71980f02004-01-24 18:18:54 +00001771 else if (VG_CLO_STREQ(arg, "--profile=no"))
njn25e49d8e72002-09-23 09:36:25 +00001772 VG_(clo_profile) = False;
1773
nethercote71980f02004-01-24 18:18:54 +00001774 else if (VG_CLO_STREQ(arg, "--chain-bb=yes"))
sewardj22854b92002-11-30 14:00:47 +00001775 VG_(clo_chain_bb) = True;
nethercote71980f02004-01-24 18:18:54 +00001776 else if (VG_CLO_STREQ(arg, "--chain-bb=no"))
sewardj22854b92002-11-30 14:00:47 +00001777 VG_(clo_chain_bb) = False;
1778
nethercote71980f02004-01-24 18:18:54 +00001779 else if (VG_CLO_STREQ(arg, "--branchpred=yes"))
fitzhardinge462f4f92003-12-18 02:10:54 +00001780 VG_(clo_branchpred) = True;
nethercote71980f02004-01-24 18:18:54 +00001781 else if (VG_CLO_STREQ(arg, "--branchpred=no"))
fitzhardinge462f4f92003-12-18 02:10:54 +00001782 VG_(clo_branchpred) = False;
1783
nethercote71980f02004-01-24 18:18:54 +00001784 else if (VG_CLO_STREQ(arg, "--single-step=yes"))
sewardjde4a1d02002-03-22 01:27:54 +00001785 VG_(clo_single_step) = True;
nethercote71980f02004-01-24 18:18:54 +00001786 else if (VG_CLO_STREQ(arg, "--single-step=no"))
sewardjde4a1d02002-03-22 01:27:54 +00001787 VG_(clo_single_step) = False;
1788
nethercote71980f02004-01-24 18:18:54 +00001789 else if (VG_CLO_STREQ(arg, "--optimise=yes"))
sewardjde4a1d02002-03-22 01:27:54 +00001790 VG_(clo_optimise) = True;
nethercote71980f02004-01-24 18:18:54 +00001791 else if (VG_CLO_STREQ(arg, "--optimise=no"))
sewardjde4a1d02002-03-22 01:27:54 +00001792 VG_(clo_optimise) = False;
1793
njn25e49d8e72002-09-23 09:36:25 +00001794 /* "vwxyz" --> 000zyxwv (binary) */
nethercote71980f02004-01-24 18:18:54 +00001795 else if (VG_CLO_STREQN(16, arg, "--trace-codegen=")) {
njn25e49d8e72002-09-23 09:36:25 +00001796 Int j;
nethercote71980f02004-01-24 18:18:54 +00001797 char* opt = & arg[16];
njn25e49d8e72002-09-23 09:36:25 +00001798
1799 if (5 != VG_(strlen)(opt)) {
1800 VG_(message)(Vg_UserMsg,
1801 "--trace-codegen argument must have 5 digits");
nethercote71980f02004-01-24 18:18:54 +00001802 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001803 }
1804 for (j = 0; j < 5; j++) {
1805 if ('0' == opt[j]) { /* do nothing */ }
1806 else if ('1' == opt[j]) VG_(clo_trace_codegen) |= (1 << j);
1807 else {
1808 VG_(message)(Vg_UserMsg, "--trace-codegen argument can only "
1809 "contain 0s and 1s");
nethercote71980f02004-01-24 18:18:54 +00001810 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001811 }
1812 }
1813 }
sewardjde4a1d02002-03-22 01:27:54 +00001814
nethercote71980f02004-01-24 18:18:54 +00001815 else if (VG_CLO_STREQ(arg, "--trace-syscalls=yes"))
sewardjde4a1d02002-03-22 01:27:54 +00001816 VG_(clo_trace_syscalls) = True;
nethercote71980f02004-01-24 18:18:54 +00001817 else if (VG_CLO_STREQ(arg, "--trace-syscalls=no"))
sewardjde4a1d02002-03-22 01:27:54 +00001818 VG_(clo_trace_syscalls) = False;
1819
nethercote71980f02004-01-24 18:18:54 +00001820 else if (VG_CLO_STREQ(arg, "--trace-signals=yes"))
sewardjde4a1d02002-03-22 01:27:54 +00001821 VG_(clo_trace_signals) = True;
nethercote71980f02004-01-24 18:18:54 +00001822 else if (VG_CLO_STREQ(arg, "--trace-signals=no"))
sewardjde4a1d02002-03-22 01:27:54 +00001823 VG_(clo_trace_signals) = False;
1824
nethercote71980f02004-01-24 18:18:54 +00001825 else if (VG_CLO_STREQ(arg, "--trace-symtab=yes"))
sewardjde4a1d02002-03-22 01:27:54 +00001826 VG_(clo_trace_symtab) = True;
nethercote71980f02004-01-24 18:18:54 +00001827 else if (VG_CLO_STREQ(arg, "--trace-symtab=no"))
sewardjde4a1d02002-03-22 01:27:54 +00001828 VG_(clo_trace_symtab) = False;
1829
nethercote71980f02004-01-24 18:18:54 +00001830 else if (VG_CLO_STREQ(arg, "--trace-sched=yes"))
sewardj8937c812002-04-12 20:12:20 +00001831 VG_(clo_trace_sched) = True;
nethercote71980f02004-01-24 18:18:54 +00001832 else if (VG_CLO_STREQ(arg, "--trace-sched=no"))
sewardj8937c812002-04-12 20:12:20 +00001833 VG_(clo_trace_sched) = False;
1834
nethercote71980f02004-01-24 18:18:54 +00001835 else if (VG_CLO_STREQ(arg, "--trace-pthread=none"))
sewardj45b4b372002-04-16 22:50:32 +00001836 VG_(clo_trace_pthread_level) = 0;
nethercote71980f02004-01-24 18:18:54 +00001837 else if (VG_CLO_STREQ(arg, "--trace-pthread=some"))
sewardj45b4b372002-04-16 22:50:32 +00001838 VG_(clo_trace_pthread_level) = 1;
nethercote71980f02004-01-24 18:18:54 +00001839 else if (VG_CLO_STREQ(arg, "--trace-pthread=all"))
sewardj45b4b372002-04-16 22:50:32 +00001840 VG_(clo_trace_pthread_level) = 2;
sewardj8937c812002-04-12 20:12:20 +00001841
nethercote71980f02004-01-24 18:18:54 +00001842 else if (VG_CLO_STREQN(14, arg, "--weird-hacks="))
1843 VG_(clo_weird_hacks) = &arg[14];
sewardj3984b852002-05-12 03:00:17 +00001844
nethercote71980f02004-01-24 18:18:54 +00001845 else if (VG_CLO_STREQN(17, arg, "--signal-polltime="))
1846 VG_(clo_signal_polltime) = VG_(atoll)(&arg[17]);
jsgf855d93d2003-10-13 22:26:55 +00001847
nethercote71980f02004-01-24 18:18:54 +00001848 else if (VG_CLO_STREQ(arg, "--lowlat-signals=yes"))
jsgf855d93d2003-10-13 22:26:55 +00001849 VG_(clo_lowlat_signals) = True;
nethercote71980f02004-01-24 18:18:54 +00001850 else if (VG_CLO_STREQ(arg, "--lowlat-signals=no"))
jsgf855d93d2003-10-13 22:26:55 +00001851 VG_(clo_lowlat_signals) = False;
1852
nethercote71980f02004-01-24 18:18:54 +00001853 else if (VG_CLO_STREQ(arg, "--lowlat-syscalls=yes"))
jsgf855d93d2003-10-13 22:26:55 +00001854 VG_(clo_lowlat_syscalls) = True;
nethercote71980f02004-01-24 18:18:54 +00001855 else if (VG_CLO_STREQ(arg, "--lowlat-syscalls=no"))
jsgf855d93d2003-10-13 22:26:55 +00001856 VG_(clo_lowlat_syscalls) = False;
1857
nethercote71980f02004-01-24 18:18:54 +00001858 else if (VG_CLO_STREQN(13, arg, "--dump-error="))
1859 VG_(clo_dump_error) = (Int)VG_(atoll)(&arg[13]);
sewardjde4a1d02002-03-22 01:27:54 +00001860
nethercote71980f02004-01-24 18:18:54 +00001861 else if (VG_CLO_STREQ(arg, "--wait-for-gdb=yes"))
jsgf855d93d2003-10-13 22:26:55 +00001862 VG_(clo_wait_for_gdb) = True;
nethercote71980f02004-01-24 18:18:54 +00001863 else if (VG_CLO_STREQ(arg, "--wait-for-gdb=no"))
jsgf855d93d2003-10-13 22:26:55 +00001864 VG_(clo_wait_for_gdb) = False;
1865
nethercote71980f02004-01-24 18:18:54 +00001866 else if (VG_CLO_STREQN(14, arg, "--num-callers=")) {
sewardjde4a1d02002-03-22 01:27:54 +00001867 /* Make sure it's sane. */
nethercote71980f02004-01-24 18:18:54 +00001868 VG_(clo_backtrace_size) = (Int)VG_(atoll)(&arg[14]);
njn6c846552003-09-16 07:41:43 +00001869 if (VG_(clo_backtrace_size) < 1)
1870 VG_(clo_backtrace_size) = 1;
sewardjde4a1d02002-03-22 01:27:54 +00001871 if (VG_(clo_backtrace_size) >= VG_DEEPEST_BACKTRACE)
1872 VG_(clo_backtrace_size) = VG_DEEPEST_BACKTRACE;
1873 }
1874
nethercote71980f02004-01-24 18:18:54 +00001875 else if ( ! VG_(needs).command_line_options
1876 || ! SK_(process_cmd_line_option)(arg) ) {
nethercote6c999f22004-01-31 22:55:15 +00001877 usage(/*--help-debug?*/need_help == 2);
njn25e49d8e72002-09-23 09:36:25 +00001878 }
sewardjde4a1d02002-03-22 01:27:54 +00001879 }
1880
njnf9ebf672003-05-12 21:41:30 +00001881 if (VG_(clo_verbosity) < 0)
sewardjde4a1d02002-03-22 01:27:54 +00001882 VG_(clo_verbosity) = 0;
1883
nethercote04d0fbc2004-01-26 16:48:06 +00001884 if (VG_(clo_db_attach) && VG_(clo_trace_children)) {
sewardjde4a1d02002-03-22 01:27:54 +00001885 VG_(message)(Vg_UserMsg, "");
1886 VG_(message)(Vg_UserMsg,
nethercote04d0fbc2004-01-26 16:48:06 +00001887 "--db-attach=yes conflicts with --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001888 VG_(message)(Vg_UserMsg,
1889 "Please choose one or the other, but not both.");
nethercote04d0fbc2004-01-26 16:48:06 +00001890 VG_(bad_option)("--db-attach=yes and --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001891 }
1892
sewardj4cf05692002-10-27 20:28:29 +00001893 /* Set up logging now. After this is done, VG_(clo_logfile_fd)
1894 should be connected to whatever sink has been selected, and we
1895 indiscriminately chuck stuff into it without worrying what the
1896 nature of it is. Oh the wonder of Unix streams. */
1897
nethercotee1730692003-11-20 10:38:07 +00001898 /* So far we should be still attached to stdout, so we can show on
sewardj4cf05692002-10-27 20:28:29 +00001899 the terminal any problems to do with processing command line
1900 opts. */
nethercotee1730692003-11-20 10:38:07 +00001901 vg_assert(VG_(clo_logfile_fd) == 1 /* stdout */);
sewardj73cf3bc2002-11-03 03:20:15 +00001902 vg_assert(VG_(logging_to_filedes) == True);
sewardj4cf05692002-10-27 20:28:29 +00001903
1904 switch (VG_(clo_log_to)) {
sewardj73cf3bc2002-11-03 03:20:15 +00001905
sewardj4cf05692002-10-27 20:28:29 +00001906 case VgLogTo_Fd:
1907 vg_assert(VG_(clo_logfile_name) == NULL);
1908 VG_(clo_logfile_fd) = eventually_logfile_fd;
1909 break;
sewardj73cf3bc2002-11-03 03:20:15 +00001910
sewardj4cf05692002-10-27 20:28:29 +00001911 case VgLogTo_File: {
1912 Char logfilename[1000];
jsgff3c3f1a2003-10-14 22:13:28 +00001913 Int seq = 0;
1914 Int pid = VG_(getpid)();
1915
sewardj4cf05692002-10-27 20:28:29 +00001916 vg_assert(VG_(clo_logfile_name) != NULL);
1917 vg_assert(VG_(strlen)(VG_(clo_logfile_name)) <= 900); /* paranoia */
jsgff3c3f1a2003-10-14 22:13:28 +00001918
nethercote71980f02004-01-24 18:18:54 +00001919 for (;;) {
jsgff3c3f1a2003-10-14 22:13:28 +00001920 if (seq == 0)
1921 VG_(sprintf)(logfilename, "%s.pid%d",
1922 VG_(clo_logfile_name), pid );
1923 else
1924 VG_(sprintf)(logfilename, "%s.pid%d.%d",
1925 VG_(clo_logfile_name), pid, seq );
1926 seq++;
1927
1928 eventually_logfile_fd
1929 = VG_(open)(logfilename,
1930 VKI_O_CREAT|VKI_O_WRONLY|VKI_O_EXCL|VKI_O_TRUNC,
1931 VKI_S_IRUSR|VKI_S_IWUSR);
1932 if (eventually_logfile_fd >= 0) {
fitzhardinge9b8c2f32004-01-06 00:15:26 +00001933 VG_(clo_logfile_fd) = VG_(safe_fd)(eventually_logfile_fd);
jsgff3c3f1a2003-10-14 22:13:28 +00001934 break;
1935 } else {
1936 if (eventually_logfile_fd != -VKI_EEXIST) {
1937 VG_(message)(Vg_UserMsg,
1938 "Can't create/open log file `%s.pid%d'; giving up!",
1939 VG_(clo_logfile_name), pid);
1940 VG_(bad_option)(
1941 "--logfile=<file> didn't work out for some reason.");
1942 break;
1943 }
1944 }
1945 }
sewardj4cf05692002-10-27 20:28:29 +00001946 break;
sewardj73cf3bc2002-11-03 03:20:15 +00001947 }
1948
1949 case VgLogTo_Socket: {
1950 vg_assert(VG_(clo_logfile_name) != NULL);
1951 vg_assert(VG_(strlen)(VG_(clo_logfile_name)) <= 900); /* paranoia */
1952 eventually_logfile_fd
1953 = VG_(connect_via_socket)( VG_(clo_logfile_name) );
1954 if (eventually_logfile_fd == -1) {
1955 VG_(message)(Vg_UserMsg,
1956 "Invalid --logsocket=ipaddr or --logsocket=ipaddr:port spec");
1957 VG_(message)(Vg_UserMsg,
1958 "of `%s'; giving up!", VG_(clo_logfile_name) );
1959 VG_(bad_option)(
1960 "--logsocket=");
sewardj4cf05692002-10-27 20:28:29 +00001961 }
sewardj73cf3bc2002-11-03 03:20:15 +00001962 if (eventually_logfile_fd == -2) {
1963 VG_(message)(Vg_UserMsg,
sewardj570f8902002-11-03 11:44:36 +00001964 "valgrind: failed to connect to logging server `%s'.",
sewardj73cf3bc2002-11-03 03:20:15 +00001965 VG_(clo_logfile_name) );
sewardj570f8902002-11-03 11:44:36 +00001966 VG_(message)(Vg_UserMsg,
1967 "Log messages will sent to stderr instead." );
1968 VG_(message)(Vg_UserMsg,
1969 "" );
1970 /* We don't change anything here. */
1971 } else {
1972 vg_assert(eventually_logfile_fd > 0);
1973 VG_(clo_logfile_fd) = eventually_logfile_fd;
1974 VG_(logging_to_filedes) = False;
1975 }
sewardj73cf3bc2002-11-03 03:20:15 +00001976 break;
1977 }
1978
sewardj4cf05692002-10-27 20:28:29 +00001979 }
1980
jsgf855d93d2003-10-13 22:26:55 +00001981 /* Move logfile_fd into the safe range, so it doesn't conflict with any app fds */
fitzhardingef0046f22003-12-18 02:39:22 +00001982 eventually_logfile_fd = VG_(fcntl)(VG_(clo_logfile_fd), VKI_F_DUPFD, VG_(max_fd)+1);
jsgf855d93d2003-10-13 22:26:55 +00001983 if (eventually_logfile_fd < 0)
1984 VG_(message)(Vg_UserMsg, "valgrind: failed to move logfile fd into safe range");
1985 else {
1986 VG_(clo_logfile_fd) = eventually_logfile_fd;
1987 VG_(fcntl)(VG_(clo_logfile_fd), VKI_F_SETFD, VKI_FD_CLOEXEC);
1988 }
1989
sewardj4cf05692002-10-27 20:28:29 +00001990 /* Ok, the logging sink is running now. Print a suitable preamble.
1991 If logging to file or a socket, write details of parent PID and
1992 command line args, to help people trying to interpret the
1993 results of a run which encompasses multiple processes. */
sewardjde4a1d02002-03-22 01:27:54 +00001994
sewardj83adf412002-05-01 01:25:45 +00001995 if (VG_(clo_verbosity > 0)) {
njnd04b7c62002-10-03 14:05:52 +00001996 /* Skin details */
1997 VG_(message)(Vg_UserMsg, "%s%s%s, %s for x86-linux.",
1998 VG_(details).name,
1999 NULL == VG_(details).version ? "" : "-",
2000 NULL == VG_(details).version
2001 ? (Char*)"" : VG_(details).version,
2002 VG_(details).description);
2003 VG_(message)(Vg_UserMsg, "%s", VG_(details).copyright_author);
sewardj3b2736a2002-03-24 12:18:35 +00002004
njnd04b7c62002-10-03 14:05:52 +00002005 /* Core details */
2006 VG_(message)(Vg_UserMsg,
njn3e884182003-04-15 13:03:23 +00002007 "Using valgrind-%s, a program supervision framework for x86-linux.",
sewardj4aa62ba2002-10-05 15:49:27 +00002008 VERSION);
sewardjde4a1d02002-03-22 01:27:54 +00002009 VG_(message)(Vg_UserMsg,
nethercotebb1c9912004-01-04 16:43:23 +00002010 "Copyright (C) 2000-2004, and GNU GPL'd, by Julian Seward.");
njnd04b7c62002-10-03 14:05:52 +00002011 }
2012
nethercotec1e395d2003-11-10 13:26:49 +00002013 if (VG_(clo_verbosity) > 0 && VG_(clo_log_to) != VgLogTo_Fd) {
sewardj4cf05692002-10-27 20:28:29 +00002014 VG_(message)(Vg_UserMsg, "");
2015 VG_(message)(Vg_UserMsg,
2016 "My PID = %d, parent PID = %d. Prog and args are:",
2017 VG_(getpid)(), VG_(getppid)() );
2018 for (i = 0; i < VG_(client_argc); i++)
2019 VG_(message)(Vg_UserMsg, " %s", VG_(client_argv)[i]);
2020 }
2021
sewardjde4a1d02002-03-22 01:27:54 +00002022 if (VG_(clo_verbosity) > 1) {
nethercotea70f7352004-04-18 12:08:46 +00002023 Int fd;
sewardj4cf05692002-10-27 20:28:29 +00002024 if (VG_(clo_log_to) != VgLogTo_Fd)
2025 VG_(message)(Vg_UserMsg, "");
fitzhardinge98abfc72003-12-16 02:05:15 +00002026 VG_(message)(Vg_UserMsg, "Valgrind library directory: %s", VG_(libdir));
njn86dc2bc2003-09-09 07:26:21 +00002027 VG_(message)(Vg_UserMsg, "Command line");
2028 for (i = 0; i < VG_(client_argc); i++)
2029 VG_(message)(Vg_UserMsg, " %s", VG_(client_argv)[i]);
2030
sewardjde4a1d02002-03-22 01:27:54 +00002031 VG_(message)(Vg_UserMsg, "Startup, with flags:");
nethercote71980f02004-01-24 18:18:54 +00002032 for (i = 1; i < VG_(vg_argc); i++) {
2033 VG_(message)(Vg_UserMsg, " %s", VG_(vg_argv)[i]);
sewardjde4a1d02002-03-22 01:27:54 +00002034 }
nethercotea70f7352004-04-18 12:08:46 +00002035
2036 VG_(message)(Vg_UserMsg, "Contents of /proc/version:");
2037 fd = VG_(open) ( "/proc/version", VKI_O_RDONLY, 0 );
2038 if (fd < 0) {
2039 VG_(message)(Vg_UserMsg, " can't open /proc/version");
2040 } else {
2041 #define BUF_LEN 256
2042 Char version_buf[BUF_LEN];
2043 Int n = VG_(read) ( fd, version_buf, BUF_LEN );
2044 vg_assert(n <= 256);
2045 if (n > 0) {
2046 version_buf[n-1] = '\0';
2047 VG_(message)(Vg_UserMsg, " %s", version_buf);
2048 } else {
2049 VG_(message)(Vg_UserMsg, " (empty?)");
2050 }
2051 VG_(close)(fd);
2052 #undef BUF_LEN
2053 }
sewardjde4a1d02002-03-22 01:27:54 +00002054 }
2055
fitzhardinge98abfc72003-12-16 02:05:15 +00002056 if (VG_(clo_n_suppressions) < VG_CLO_MAX_SFILES-1 &&
njn25e49d8e72002-09-23 09:36:25 +00002057 (VG_(needs).core_errors || VG_(needs).skin_errors)) {
fitzhardinge98abfc72003-12-16 02:05:15 +00002058 /* If there are no suppression files specified and the skin
2059 needs one, load the default */
2060 static const Char default_supp[] = "default.supp";
2061 Int len = VG_(strlen)(VG_(libdir)) + 1 + sizeof(default_supp);
2062 Char *buf = VG_(arena_malloc)(VG_AR_CORE, len);
2063 VG_(sprintf)(buf, "%s/%s", VG_(libdir), default_supp);
2064 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = buf;
2065 VG_(clo_n_suppressions)++;
sewardjde4a1d02002-03-22 01:27:54 +00002066 }
sewardj4cf05692002-10-27 20:28:29 +00002067
njn6a230532003-07-21 10:38:23 +00002068 if (VG_(clo_gen_suppressions) &&
2069 !VG_(needs).core_errors && !VG_(needs).skin_errors) {
2070 config_error("Can't use --gen-suppressions=yes with this skin,\n"
2071 " as it doesn't generate errors.");
2072 }
sewardjde4a1d02002-03-22 01:27:54 +00002073}
2074
sewardjde4a1d02002-03-22 01:27:54 +00002075
nethercote71980f02004-01-24 18:18:54 +00002076/*====================================================================*/
2077/*=== File descriptor setup ===*/
2078/*====================================================================*/
2079
2080static void setup_file_descriptors(void)
2081{
2082 struct vki_rlimit rl;
2083
2084 /* Get the current file descriptor limits. */
2085 if (VG_(getrlimit)(VKI_RLIMIT_NOFILE, &rl) < 0) {
2086 rl.rlim_cur = 1024;
2087 rl.rlim_max = 1024;
2088 }
2089
2090 /* Work out where to move the soft limit to. */
2091 if (rl.rlim_cur + VG_N_RESERVED_FDS <= rl.rlim_max) {
2092 rl.rlim_cur = rl.rlim_cur + VG_N_RESERVED_FDS;
2093 } else {
2094 rl.rlim_cur = rl.rlim_max;
2095 }
2096
2097 /* Reserve some file descriptors for our use. */
2098 VG_(max_fd) = rl.rlim_cur - VG_N_RESERVED_FDS;
2099
2100 /* Update the soft limit. */
2101 VG_(setrlimit)(VKI_RLIMIT_NOFILE, &rl);
2102
2103 if (VG_(vgexecfd) != -1)
2104 VG_(vgexecfd) = VG_(safe_fd)( VG_(vgexecfd) );
2105 if (VG_(clexecfd) != -1)
2106 VG_(clexecfd) = VG_(safe_fd)( VG_(clexecfd) );
2107}
2108
2109
2110/*====================================================================*/
nethercote1d447092004-02-01 17:29:59 +00002111/*=== baseBlock: definition + setup ===*/
nethercote71980f02004-01-24 18:18:54 +00002112/*====================================================================*/
2113
2114/* The variables storing offsets. */
2115
2116#define INVALID_OFFSET (-1)
2117
2118Int VGOFF_(m_eax) = INVALID_OFFSET;
2119Int VGOFF_(m_ecx) = INVALID_OFFSET;
2120Int VGOFF_(m_edx) = INVALID_OFFSET;
2121Int VGOFF_(m_ebx) = INVALID_OFFSET;
2122Int VGOFF_(m_esp) = INVALID_OFFSET;
2123Int VGOFF_(m_ebp) = INVALID_OFFSET;
2124Int VGOFF_(m_esi) = INVALID_OFFSET;
2125Int VGOFF_(m_edi) = INVALID_OFFSET;
2126Int VGOFF_(m_eflags) = INVALID_OFFSET;
2127Int VGOFF_(m_dflag) = INVALID_OFFSET;
2128Int VGOFF_(m_ssestate) = INVALID_OFFSET;
2129Int VGOFF_(ldt) = INVALID_OFFSET;
2130Int VGOFF_(tls) = INVALID_OFFSET;
2131Int VGOFF_(m_cs) = INVALID_OFFSET;
2132Int VGOFF_(m_ss) = INVALID_OFFSET;
2133Int VGOFF_(m_ds) = INVALID_OFFSET;
2134Int VGOFF_(m_es) = INVALID_OFFSET;
2135Int VGOFF_(m_fs) = INVALID_OFFSET;
2136Int VGOFF_(m_gs) = INVALID_OFFSET;
2137Int VGOFF_(m_eip) = INVALID_OFFSET;
2138Int VGOFF_(spillslots) = INVALID_OFFSET;
2139Int VGOFF_(sh_eax) = INVALID_OFFSET;
2140Int VGOFF_(sh_ecx) = INVALID_OFFSET;
2141Int VGOFF_(sh_edx) = INVALID_OFFSET;
2142Int VGOFF_(sh_ebx) = INVALID_OFFSET;
2143Int VGOFF_(sh_esp) = INVALID_OFFSET;
2144Int VGOFF_(sh_ebp) = INVALID_OFFSET;
2145Int VGOFF_(sh_esi) = INVALID_OFFSET;
2146Int VGOFF_(sh_edi) = INVALID_OFFSET;
2147Int VGOFF_(sh_eflags) = INVALID_OFFSET;
2148
2149Int VGOFF_(helper_idiv_64_32) = INVALID_OFFSET;
2150Int VGOFF_(helper_div_64_32) = INVALID_OFFSET;
2151Int VGOFF_(helper_idiv_32_16) = INVALID_OFFSET;
2152Int VGOFF_(helper_div_32_16) = INVALID_OFFSET;
2153Int VGOFF_(helper_idiv_16_8) = INVALID_OFFSET;
2154Int VGOFF_(helper_div_16_8) = INVALID_OFFSET;
2155Int VGOFF_(helper_imul_32_64) = INVALID_OFFSET;
2156Int VGOFF_(helper_mul_32_64) = INVALID_OFFSET;
2157Int VGOFF_(helper_imul_16_32) = INVALID_OFFSET;
2158Int VGOFF_(helper_mul_16_32) = INVALID_OFFSET;
2159Int VGOFF_(helper_imul_8_16) = INVALID_OFFSET;
2160Int VGOFF_(helper_mul_8_16) = INVALID_OFFSET;
2161Int VGOFF_(helper_CLD) = INVALID_OFFSET;
2162Int VGOFF_(helper_STD) = INVALID_OFFSET;
2163Int VGOFF_(helper_get_dirflag) = INVALID_OFFSET;
2164Int VGOFF_(helper_CLC) = INVALID_OFFSET;
2165Int VGOFF_(helper_STC) = INVALID_OFFSET;
nethercote1018bdd2004-02-11 23:33:29 +00002166Int VGOFF_(helper_CMC) = INVALID_OFFSET;
nethercote71980f02004-01-24 18:18:54 +00002167Int VGOFF_(helper_shldl) = INVALID_OFFSET;
2168Int VGOFF_(helper_shldw) = INVALID_OFFSET;
2169Int VGOFF_(helper_shrdl) = INVALID_OFFSET;
2170Int VGOFF_(helper_shrdw) = INVALID_OFFSET;
2171Int VGOFF_(helper_IN) = INVALID_OFFSET;
2172Int VGOFF_(helper_OUT) = INVALID_OFFSET;
2173Int VGOFF_(helper_RDTSC) = INVALID_OFFSET;
2174Int VGOFF_(helper_CPUID) = INVALID_OFFSET;
2175Int VGOFF_(helper_BSWAP) = INVALID_OFFSET;
nethercote1018bdd2004-02-11 23:33:29 +00002176Int VGOFF_(helper_bsfw) = INVALID_OFFSET;
2177Int VGOFF_(helper_bsfl) = INVALID_OFFSET;
2178Int VGOFF_(helper_bsrw) = INVALID_OFFSET;
2179Int VGOFF_(helper_bsrl) = INVALID_OFFSET;
nethercote71980f02004-01-24 18:18:54 +00002180Int VGOFF_(helper_fstsw_AX) = INVALID_OFFSET;
2181Int VGOFF_(helper_SAHF) = INVALID_OFFSET;
2182Int VGOFF_(helper_LAHF) = INVALID_OFFSET;
2183Int VGOFF_(helper_DAS) = INVALID_OFFSET;
2184Int VGOFF_(helper_DAA) = INVALID_OFFSET;
nethercote1018bdd2004-02-11 23:33:29 +00002185Int VGOFF_(helper_AAS) = INVALID_OFFSET;
2186Int VGOFF_(helper_AAA) = INVALID_OFFSET;
2187Int VGOFF_(helper_AAD) = INVALID_OFFSET;
2188Int VGOFF_(helper_AAM) = INVALID_OFFSET;
nethercote71980f02004-01-24 18:18:54 +00002189Int VGOFF_(helper_cmpxchg8b) = INVALID_OFFSET;
2190Int VGOFF_(helper_undefined_instruction) = INVALID_OFFSET;
2191
2192/* MAX_NONCOMPACT_HELPERS can be increased easily. If MAX_COMPACT_HELPERS is
2193 * increased too much, they won't really be compact any more... */
2194#define MAX_COMPACT_HELPERS 8
2195#define MAX_NONCOMPACT_HELPERS 50
2196
2197UInt VG_(n_compact_helpers) = 0;
2198UInt VG_(n_noncompact_helpers) = 0;
2199
2200Addr VG_(compact_helper_addrs) [MAX_COMPACT_HELPERS];
2201Int VG_(compact_helper_offsets)[MAX_COMPACT_HELPERS];
2202Addr VG_(noncompact_helper_addrs) [MAX_NONCOMPACT_HELPERS];
2203Int VG_(noncompact_helper_offsets)[MAX_NONCOMPACT_HELPERS];
2204
2205/* This is the actual defn of baseblock. */
2206UInt VG_(baseBlock)[VG_BASEBLOCK_WORDS];
2207
nethercote71980f02004-01-24 18:18:54 +00002208/* Words. */
2209static Int baB_off = 0;
2210
2211
sewardjfa492d42002-12-08 18:20:01 +00002212UInt VG_(insertDflag)(UInt eflags, Int d)
2213{
2214 vg_assert(d == 1 || d == -1);
2215 eflags &= ~EFlagD;
2216
2217 if (d < 0)
2218 eflags |= EFlagD;
2219
2220 return eflags;
2221}
2222
2223Int VG_(extractDflag)(UInt eflags)
2224{
2225 Int ret;
2226
2227 if (eflags & EFlagD)
2228 ret = -1;
2229 else
2230 ret = 1;
2231
2232 return ret;
2233}
2234
nethercote71980f02004-01-24 18:18:54 +00002235/* Returns the offset, in words. */
2236static Int alloc_BaB ( Int words )
sewardjde4a1d02002-03-22 01:27:54 +00002237{
nethercote71980f02004-01-24 18:18:54 +00002238 Int off = baB_off;
2239 baB_off += words;
2240 if (baB_off >= VG_BASEBLOCK_WORDS)
2241 VG_(core_panic)( "alloc_BaB: baseBlock is too small");
sewardjde4a1d02002-03-22 01:27:54 +00002242
nethercote71980f02004-01-24 18:18:54 +00002243 return off;
sewardjde4a1d02002-03-22 01:27:54 +00002244}
2245
nethercote71980f02004-01-24 18:18:54 +00002246/* Align offset, in *bytes* */
2247static void align_BaB ( UInt align )
njn25e49d8e72002-09-23 09:36:25 +00002248{
nethercote71980f02004-01-24 18:18:54 +00002249 vg_assert(2 == align || 4 == align || 8 == align || 16 == align);
2250 baB_off += (align-1);
2251 baB_off &= ~(align-1);
njn25e49d8e72002-09-23 09:36:25 +00002252}
2253
nethercote71980f02004-01-24 18:18:54 +00002254/* Allocate 1 word in baseBlock and set it to the given value. */
2255static Int alloc_BaB_1_set ( Addr a )
njn25e49d8e72002-09-23 09:36:25 +00002256{
nethercote71980f02004-01-24 18:18:54 +00002257 Int off = alloc_BaB(1);
2258 VG_(baseBlock)[off] = (UInt)a;
2259 return off;
njn25e49d8e72002-09-23 09:36:25 +00002260}
2261
nethercote71980f02004-01-24 18:18:54 +00002262/* Registers a function in compact_helper_addrs; compact_helper_offsets is
2263 filled in later. */
2264void VG_(register_compact_helper)(Addr a)
sewardjde4a1d02002-03-22 01:27:54 +00002265{
nethercote71980f02004-01-24 18:18:54 +00002266 if (MAX_COMPACT_HELPERS <= VG_(n_compact_helpers)) {
2267 VG_(printf)("Can only register %d compact helpers\n",
2268 MAX_COMPACT_HELPERS);
2269 VG_(core_panic)("Too many compact helpers registered");
2270 }
2271 VG_(compact_helper_addrs)[VG_(n_compact_helpers)] = a;
2272 VG_(n_compact_helpers)++;
2273}
2274
2275/* Registers a function in noncompact_helper_addrs; noncompact_helper_offsets
2276 * is filled in later.
2277 */
2278void VG_(register_noncompact_helper)(Addr a)
2279{
2280 if (MAX_NONCOMPACT_HELPERS <= VG_(n_noncompact_helpers)) {
2281 VG_(printf)("Can only register %d non-compact helpers\n",
2282 MAX_NONCOMPACT_HELPERS);
2283 VG_(printf)("Try increasing MAX_NON_COMPACT_HELPERS\n");
2284 VG_(core_panic)("Too many non-compact helpers registered");
2285 }
2286 VG_(noncompact_helper_addrs)[VG_(n_noncompact_helpers)] = a;
2287 VG_(n_noncompact_helpers)++;
2288}
2289
2290/* Allocate offsets in baseBlock for the skin helpers */
2291static
2292void assign_helpers_in_baseBlock(UInt n, Int offsets[], Addr addrs[])
2293{
2294 UInt i;
2295 for (i = 0; i < n; i++)
2296 offsets[i] = alloc_BaB_1_set( addrs[i] );
2297}
2298
2299Bool VG_(need_to_handle_esp_assignment)(void)
2300{
2301 return ( VG_(defined_new_mem_stack_4)() ||
2302 VG_(defined_die_mem_stack_4)() ||
2303 VG_(defined_new_mem_stack_8)() ||
2304 VG_(defined_die_mem_stack_8)() ||
2305 VG_(defined_new_mem_stack_12)() ||
2306 VG_(defined_die_mem_stack_12)() ||
2307 VG_(defined_new_mem_stack_16)() ||
2308 VG_(defined_die_mem_stack_16)() ||
2309 VG_(defined_new_mem_stack_32)() ||
2310 VG_(defined_die_mem_stack_32)() ||
2311 VG_(defined_new_mem_stack)() ||
2312 VG_(defined_die_mem_stack)()
2313 );
2314}
2315
2316/* Here we assign actual offsets. It's important to get the most
2317 popular referents within 128 bytes of the start, so we can take
2318 advantage of short addressing modes relative to %ebp. Popularity
2319 of offsets was measured on 22 Feb 02 running a KDE application, and
2320 the slots rearranged accordingly, with a 1.5% reduction in total
2321 size of translations. */
2322static void init_baseBlock ( Addr client_eip, Addr esp_at_startup )
2323{
2324 /* Those with offsets under 128 are carefully chosen. */
2325
2326 /* WORD offsets in this column */
2327 /* 0 */ VGOFF_(m_eax) = alloc_BaB_1_set(0);
2328 /* 1 */ VGOFF_(m_ecx) = alloc_BaB_1_set(0);
2329 /* 2 */ VGOFF_(m_edx) = alloc_BaB_1_set(0);
2330 /* 3 */ VGOFF_(m_ebx) = alloc_BaB_1_set(0);
2331 /* 4 */ VGOFF_(m_esp) = alloc_BaB_1_set(esp_at_startup);
2332 /* 5 */ VGOFF_(m_ebp) = alloc_BaB_1_set(0);
2333 /* 6 */ VGOFF_(m_esi) = alloc_BaB_1_set(0);
2334 /* 7 */ VGOFF_(m_edi) = alloc_BaB_1_set(0);
2335 /* 8 */ VGOFF_(m_eflags) = alloc_BaB_1_set(0);
2336
2337 if (VG_(needs).shadow_regs) {
2338 /* 9 */ VGOFF_(sh_eax) = alloc_BaB_1_set(0);
2339 /* 10 */ VGOFF_(sh_ecx) = alloc_BaB_1_set(0);
2340 /* 11 */ VGOFF_(sh_edx) = alloc_BaB_1_set(0);
2341 /* 12 */ VGOFF_(sh_ebx) = alloc_BaB_1_set(0);
2342 /* 13 */ VGOFF_(sh_esp) = alloc_BaB_1_set(0);
2343 /* 14 */ VGOFF_(sh_ebp) = alloc_BaB_1_set(0);
2344 /* 15 */ VGOFF_(sh_esi) = alloc_BaB_1_set(0);
2345 /* 16 */ VGOFF_(sh_edi) = alloc_BaB_1_set(0);
2346 /* 17 */ VGOFF_(sh_eflags) = alloc_BaB_1_set(0);
2347 VG_TRACK( post_regs_write_init );
2348 }
2349
2350 /* 9,10,11 or 18,19,20... depends on number whether shadow regs are used
2351 * and on compact helpers registered */
2352
2353 /* Make these most-frequently-called specialised ones compact, if they
2354 are used. */
2355 if (VG_(defined_new_mem_stack_4)())
2356 VG_(register_compact_helper)( (Addr) VG_(tool_interface).track_new_mem_stack_4);
2357
2358 if (VG_(defined_die_mem_stack_4)())
2359 VG_(register_compact_helper)( (Addr) VG_(tool_interface).track_die_mem_stack_4);
2360
2361 /* (9 or 18) + n_compact_helpers */
2362 /* Allocate slots for compact helpers */
2363 assign_helpers_in_baseBlock(VG_(n_compact_helpers),
2364 VG_(compact_helper_offsets),
2365 VG_(compact_helper_addrs));
2366
2367 /* (9/10 or 18/19) + n_compact_helpers */
2368 VGOFF_(m_eip) = alloc_BaB_1_set(client_eip);
2369
2370 /* There are currently 24 spill slots */
2371 /* (11+/20+ .. 32+/43+) + n_compact_helpers. This can overlap the magic
2372 * boundary at >= 32 words, but most spills are to low numbered spill
2373 * slots, so the ones above the boundary don't see much action. */
2374 VGOFF_(spillslots) = alloc_BaB(VG_MAX_SPILLSLOTS);
2375
2376 /* I gave up counting at this point. Since they're above the
2377 short-amode-boundary, there's no point. */
2378
2379 VGOFF_(m_dflag) = alloc_BaB_1_set(1); // 1 == forward D-flag
2380
2381 /* The FPU/SSE state. This _must_ be 16-byte aligned. Initial
2382 state doesn't matter much, as long as it's not totally borked. */
2383 align_BaB(16);
2384 VGOFF_(m_ssestate) = alloc_BaB(VG_SIZE_OF_SSESTATE_W);
2385 vg_assert(
2386 0 == ( ((UInt)(& VG_(baseBlock)[VGOFF_(m_ssestate)])) % 16 )
sewardj22854b92002-11-30 14:00:47 +00002387 );
2388
fitzhardingec2dbbac2004-01-23 23:09:01 +00002389 /* I assume that if we have SSE2 we also have SSE */
2390 VG_(have_ssestate) =
2391 VG_(cpu_has_feature)(VG_X86_FEAT_FXSR) &&
2392 VG_(cpu_has_feature)(VG_X86_FEAT_SSE);
2393
fitzhardinge98abfc72003-12-16 02:05:15 +00002394 /* set up an initial FPU state (doesn't really matter what it is,
2395 so long as it's somewhat valid) */
2396 if (!VG_(have_ssestate))
nethercote71980f02004-01-24 18:18:54 +00002397 asm volatile("fwait; fnsave %0; fwait; frstor %0; fwait"
2398 :
2399 : "m" (VG_(baseBlock)[VGOFF_(m_ssestate)])
2400 : "cc", "memory");
fitzhardinge98abfc72003-12-16 02:05:15 +00002401 else
nethercote71980f02004-01-24 18:18:54 +00002402 asm volatile("fwait; fxsave %0; fwait; andl $0xffbf, %1;"
2403 "fxrstor %0; fwait"
2404 :
2405 : "m" (VG_(baseBlock)[VGOFF_(m_ssestate)]),
2406 "m" (VG_(baseBlock)[VGOFF_(m_ssestate)+(24/4)])
2407 : "cc", "memory");
fitzhardinge98abfc72003-12-16 02:05:15 +00002408
njn0c7a5b52003-04-30 09:00:33 +00002409 if (0) {
2410 if (VG_(have_ssestate))
2411 VG_(printf)("Looks like a SSE-capable CPU\n");
2412 else
2413 VG_(printf)("Looks like a MMX-only CPU\n");
2414 }
sewardjb91ae7f2003-04-29 23:50:00 +00002415
nethercote71980f02004-01-24 18:18:54 +00002416 /* LDT pointer: pretend the root thread has an empty LDT to start with. */
2417 VGOFF_(ldt) = alloc_BaB_1_set((UInt)NULL);
jsgf855d93d2003-10-13 22:26:55 +00002418
nethercote71980f02004-01-24 18:18:54 +00002419 /* TLS pointer: pretend the root thread has no TLS array for now. */
2420 VGOFF_(tls) = alloc_BaB_1_set((UInt)NULL);
fitzhardingef0046f22003-12-18 02:39:22 +00002421
nethercote71980f02004-01-24 18:18:54 +00002422 /* segment registers */
2423 VGOFF_(m_cs) = alloc_BaB_1_set(0);
2424 VGOFF_(m_ss) = alloc_BaB_1_set(0);
2425 VGOFF_(m_ds) = alloc_BaB_1_set(0);
2426 VGOFF_(m_es) = alloc_BaB_1_set(0);
2427 VGOFF_(m_fs) = alloc_BaB_1_set(0);
2428 VGOFF_(m_gs) = alloc_BaB_1_set(0);
fitzhardingef0046f22003-12-18 02:39:22 +00002429
nethercote71980f02004-01-24 18:18:54 +00002430 VG_(register_noncompact_helper)( (Addr) & VG_(do_useseg) );
fitzhardingef0046f22003-12-18 02:39:22 +00002431
nethercote71980f02004-01-24 18:18:54 +00002432#define REG(kind, size) \
2433 if (VG_(defined_##kind##_mem_stack##size)()) \
2434 VG_(register_noncompact_helper)( \
2435 (Addr) VG_(tool_interface).track_##kind##_mem_stack##size );
2436 REG(new, _8);
2437 REG(new, _12);
2438 REG(new, _16);
2439 REG(new, _32);
2440 REG(new, );
2441 REG(die, _8);
2442 REG(die, _12);
2443 REG(die, _16);
2444 REG(die, _32);
2445 REG(die, );
2446#undef REG
fitzhardingef0046f22003-12-18 02:39:22 +00002447
nethercote71980f02004-01-24 18:18:54 +00002448 if (VG_(need_to_handle_esp_assignment)())
2449 VG_(register_noncompact_helper)((Addr) VG_(unknown_esp_update));
fitzhardingeb791a192003-12-18 07:22:44 +00002450
nethercote71980f02004-01-24 18:18:54 +00002451# define HELPER(name) \
2452 VGOFF_(helper_##name) = alloc_BaB_1_set( (Addr) & VG_(helper_##name))
njn3e884182003-04-15 13:03:23 +00002453
nethercote71980f02004-01-24 18:18:54 +00002454 /* Helper functions. */
2455 HELPER(idiv_64_32); HELPER(div_64_32);
2456 HELPER(idiv_32_16); HELPER(div_32_16);
2457 HELPER(idiv_16_8); HELPER(div_16_8);
fitzhardinge98abfc72003-12-16 02:05:15 +00002458
nethercote71980f02004-01-24 18:18:54 +00002459 HELPER(imul_32_64); HELPER(mul_32_64);
2460 HELPER(imul_16_32); HELPER(mul_16_32);
2461 HELPER(imul_8_16); HELPER(mul_8_16);
njn25e49d8e72002-09-23 09:36:25 +00002462
nethercote71980f02004-01-24 18:18:54 +00002463 HELPER(CLD); HELPER(STD);
2464 HELPER(get_dirflag);
sewardjde4a1d02002-03-22 01:27:54 +00002465
nethercote71980f02004-01-24 18:18:54 +00002466 HELPER(CLC); HELPER(STC);
nethercote1018bdd2004-02-11 23:33:29 +00002467 HELPER(CMC);
jsgf855d93d2003-10-13 22:26:55 +00002468
nethercote71980f02004-01-24 18:18:54 +00002469 HELPER(shldl); HELPER(shldw);
2470 HELPER(shrdl); HELPER(shrdw);
njncc7bb472002-10-14 09:25:19 +00002471
nethercote71980f02004-01-24 18:18:54 +00002472 HELPER(RDTSC); HELPER(CPUID);
njncc7bb472002-10-14 09:25:19 +00002473
nethercote1018bdd2004-02-11 23:33:29 +00002474 HELPER(bsfw); HELPER(bsfl);
2475 HELPER(bsrw); HELPER(bsrl);
rjwalshf5f536f2003-11-17 17:45:00 +00002476
nethercote71980f02004-01-24 18:18:54 +00002477 HELPER(fstsw_AX);
2478 HELPER(SAHF); HELPER(LAHF);
2479 HELPER(DAS); HELPER(DAA);
nethercote1018bdd2004-02-11 23:33:29 +00002480 HELPER(AAS); HELPER(AAA);
2481 HELPER(AAD); HELPER(AAM);
nethercote71980f02004-01-24 18:18:54 +00002482 HELPER(IN); HELPER(OUT);
2483 HELPER(cmpxchg8b);
sewardj018f7622002-05-15 21:13:39 +00002484
nethercote71980f02004-01-24 18:18:54 +00002485 HELPER(undefined_instruction);
jsgf855d93d2003-10-13 22:26:55 +00002486
nethercote71980f02004-01-24 18:18:54 +00002487# undef HELPER
sewardjde4a1d02002-03-22 01:27:54 +00002488
nethercote71980f02004-01-24 18:18:54 +00002489 /* Allocate slots for noncompact helpers */
2490 assign_helpers_in_baseBlock(VG_(n_noncompact_helpers),
2491 VG_(noncompact_helper_offsets),
2492 VG_(noncompact_helper_addrs));
2493}
sewardjde4a1d02002-03-22 01:27:54 +00002494
sewardj5f07b662002-04-23 16:52:51 +00002495
nethercote71980f02004-01-24 18:18:54 +00002496/*====================================================================*/
2497/*=== Setup pointercheck ===*/
2498/*====================================================================*/
njn25e49d8e72002-09-23 09:36:25 +00002499
nethercote71980f02004-01-24 18:18:54 +00002500static void setup_pointercheck(void)
2501{
2502 int ret;
sewardj2e93c502002-04-12 11:12:52 +00002503
fitzhardinge98abfc72003-12-16 02:05:15 +00002504 if (VG_(clo_pointercheck)) {
nethercote71980f02004-01-24 18:18:54 +00002505 vki_modify_ldt_t ldt = {
2506 VG_POINTERCHECK_SEGIDX, // entry_number
2507 VG_(client_base), // base_addr
2508 (VG_(client_end)-VG_(client_base)) / VKI_BYTES_PER_PAGE, // limit
2509 1, // seg_32bit
2510 0, // contents: data, RW, non-expanding
2511 0, // ! read_exec_only
2512 1, // limit_in_pages
2513 0, // ! seg not present
2514 1, // useable
fitzhardinge98abfc72003-12-16 02:05:15 +00002515 };
nethercote71980f02004-01-24 18:18:54 +00002516 ret = VG_(do_syscall)(__NR_modify_ldt, 1, &ldt, sizeof(ldt));
fitzhardinge98abfc72003-12-16 02:05:15 +00002517 if (ret < 0) {
2518 VG_(message)(Vg_UserMsg,
2519 "Warning: ignoring --pointercheck=yes, "
2520 "because modify_ldt failed (errno=%d)", -ret);
2521 VG_(clo_pointercheck) = False;
2522 }
2523 }
sewardjde4a1d02002-03-22 01:27:54 +00002524}
2525
nethercote71980f02004-01-24 18:18:54 +00002526/*====================================================================*/
2527/*=== Initialise program data/text, etc. ===*/
2528/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +00002529
nethercote71980f02004-01-24 18:18:54 +00002530static void build_valgrind_map_callback
2531 ( Addr start, UInt size, Char rr, Char ww, Char xx,
2532 UInt dev, UInt ino, ULong foffset, const UChar* filename )
sewardjde4a1d02002-03-22 01:27:54 +00002533{
nethercote71980f02004-01-24 18:18:54 +00002534 UInt prot = 0;
2535 UInt flags = SF_MMAP|SF_NOSYMS;
2536 Bool is_stack_segment;
2537
2538 is_stack_segment =
2539 (start == VG_(clstk_base) && (start+size) == VG_(clstk_end));
2540
2541 /* Only record valgrind mappings for now, without loading any
2542 symbols. This is so we know where the free space is before we
2543 start allocating more memory (note: heap is OK, it's just mmap
2544 which is the problem here). */
2545 if (start >= VG_(valgrind_base) && (start+size) <= VG_(valgrind_end)) {
2546 flags |= SF_VALGRIND;
2547 VG_(map_file_segment)(start, size, prot, flags, dev, ino, foffset, filename);
2548 }
sewardjde4a1d02002-03-22 01:27:54 +00002549}
2550
nethercote71980f02004-01-24 18:18:54 +00002551// Global var used to pass local data to callback
2552Addr esp_at_startup___global_arg = 0;
sewardjde4a1d02002-03-22 01:27:54 +00002553
nethercote71980f02004-01-24 18:18:54 +00002554static void build_segment_map_callback
2555 ( Addr start, UInt size, Char rr, Char ww, Char xx,
2556 UInt dev, UInt ino, ULong foffset, const UChar* filename )
sewardj45b672d2003-07-25 19:58:11 +00002557{
nethercote71980f02004-01-24 18:18:54 +00002558 UInt prot = 0;
2559 UInt flags;
2560 Bool is_stack_segment;
2561 Addr r_esp;
sewardj45b672d2003-07-25 19:58:11 +00002562
nethercote71980f02004-01-24 18:18:54 +00002563 is_stack_segment
2564 = (start == VG_(clstk_base) && (start+size) == VG_(clstk_end));
fitzhardinge98abfc72003-12-16 02:05:15 +00002565
nethercote71980f02004-01-24 18:18:54 +00002566 if (rr == 'r') prot |= VKI_PROT_READ;
2567 if (ww == 'w') prot |= VKI_PROT_WRITE;
2568 if (xx == 'x') prot |= VKI_PROT_EXEC;
fitzhardinge98abfc72003-12-16 02:05:15 +00002569
nethercote71980f02004-01-24 18:18:54 +00002570 if (is_stack_segment)
2571 flags = SF_STACK | SF_GROWDOWN;
2572 else
2573 flags = SF_EXEC|SF_MMAP;
fitzhardinge98abfc72003-12-16 02:05:15 +00002574
nethercote71980f02004-01-24 18:18:54 +00002575 if (filename != NULL)
2576 flags |= SF_FILE;
fitzhardinge98abfc72003-12-16 02:05:15 +00002577
nethercote71980f02004-01-24 18:18:54 +00002578 if (start >= VG_(valgrind_base) && (start+size) <= VG_(valgrind_end))
2579 flags |= SF_VALGRIND;
fitzhardinge98abfc72003-12-16 02:05:15 +00002580
nethercote71980f02004-01-24 18:18:54 +00002581 VG_(map_file_segment)(start, size, prot, flags, dev, ino, foffset, filename);
fitzhardinge98abfc72003-12-16 02:05:15 +00002582
nethercote71980f02004-01-24 18:18:54 +00002583 if (VG_(is_client_addr)(start) && VG_(is_client_addr)(start+size-1))
2584 VG_TRACK( new_mem_startup, start, size, rr=='r', ww=='w', xx=='x' );
sewardj3e1eb1f2002-05-18 13:14:17 +00002585
nethercote71980f02004-01-24 18:18:54 +00002586 /* If this is the stack segment mark all below %esp as noaccess. */
2587 r_esp = esp_at_startup___global_arg;
2588 vg_assert(0 != r_esp);
2589 if (is_stack_segment) {
2590 if (0)
2591 VG_(message)(Vg_DebugMsg, "invalidating stack area: %x .. %x",
2592 start,r_esp);
2593 VG_TRACK( die_mem_stack, start, r_esp-start );
sewardjde4a1d02002-03-22 01:27:54 +00002594 }
sewardjde4a1d02002-03-22 01:27:54 +00002595}
2596
2597
nethercote71980f02004-01-24 18:18:54 +00002598/*====================================================================*/
2599/*=== Sanity check machinery (permanently engaged) ===*/
2600/*====================================================================*/
njn25e49d8e72002-09-23 09:36:25 +00002601
2602/* A fast sanity check -- suitable for calling circa once per
2603 millisecond. */
2604
2605void VG_(do_sanity_checks) ( Bool force_expensive )
2606{
njn37cea302002-09-30 11:24:00 +00002607 VGP_PUSHCC(VgpCoreCheapSanity);
2608
njn25e49d8e72002-09-23 09:36:25 +00002609 if (VG_(sanity_level) < 1) return;
2610
2611 /* --- First do all the tests that we can do quickly. ---*/
2612
2613 VG_(sanity_fast_count)++;
2614
njn25e49d8e72002-09-23 09:36:25 +00002615 /* Check stuff pertaining to the memory check system. */
2616
2617 /* Check that nobody has spuriously claimed that the first or
2618 last 16 pages of memory have become accessible [...] */
njn37cea302002-09-30 11:24:00 +00002619 if (VG_(needs).sanity_checks) {
2620 VGP_PUSHCC(VgpSkinCheapSanity);
njn25e49d8e72002-09-23 09:36:25 +00002621 vg_assert(SK_(cheap_sanity_check)());
njn37cea302002-09-30 11:24:00 +00002622 VGP_POPCC(VgpSkinCheapSanity);
2623 }
njn25e49d8e72002-09-23 09:36:25 +00002624
2625 /* --- Now some more expensive checks. ---*/
2626
2627 /* Once every 25 times, check some more expensive stuff. */
2628 if ( force_expensive
2629 || VG_(sanity_level) > 1
2630 || (VG_(sanity_level) == 1 && (VG_(sanity_fast_count) % 25) == 0)) {
2631
njn37cea302002-09-30 11:24:00 +00002632 VGP_PUSHCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002633 VG_(sanity_slow_count)++;
2634
jsgf855d93d2003-10-13 22:26:55 +00002635 VG_(proxy_sanity)();
2636
njn25e49d8e72002-09-23 09:36:25 +00002637# if 0
2638 { void zzzmemscan(void); zzzmemscan(); }
2639# endif
2640
2641 if ((VG_(sanity_fast_count) % 250) == 0)
2642 VG_(sanity_check_tc_tt)();
2643
2644 if (VG_(needs).sanity_checks) {
njn37cea302002-09-30 11:24:00 +00002645 VGP_PUSHCC(VgpSkinExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002646 vg_assert(SK_(expensive_sanity_check)());
njn37cea302002-09-30 11:24:00 +00002647 VGP_POPCC(VgpSkinExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002648 }
2649 /*
2650 if ((VG_(sanity_fast_count) % 500) == 0) VG_(mallocSanityCheckAll)();
2651 */
njn37cea302002-09-30 11:24:00 +00002652 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002653 }
2654
2655 if (VG_(sanity_level) > 1) {
njn37cea302002-09-30 11:24:00 +00002656 VGP_PUSHCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002657 /* Check sanity of the low-level memory manager. Note that bugs
2658 in the client's code can cause this to fail, so we don't do
2659 this check unless specially asked for. And because it's
2660 potentially very expensive. */
2661 VG_(mallocSanityCheckAll)();
njn37cea302002-09-30 11:24:00 +00002662 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002663 }
njn37cea302002-09-30 11:24:00 +00002664 VGP_POPCC(VgpCoreCheapSanity);
njn25e49d8e72002-09-23 09:36:25 +00002665}
nethercote71980f02004-01-24 18:18:54 +00002666
2667
2668/*====================================================================*/
2669/*=== main() ===*/
2670/*====================================================================*/
2671
2672int main(int argc, char **argv)
2673{
2674 char **cl_argv;
2675 const char *tool = NULL;
2676 const char *exec = NULL;
2677 char *preload; /* tool-specific LD_PRELOAD .so */
2678 char **env;
nethercote6c999f22004-01-31 22:55:15 +00002679 Int need_help = 0; // 0 = no, 1 = --help, 2 = --help-debug
nethercote71980f02004-01-24 18:18:54 +00002680 struct exeinfo info;
2681 ToolInfo *toolinfo = NULL;
2682 void *tool_dlhandle;
2683 Addr client_eip;
2684 Addr esp_at_startup; /* client's %esp at the point we gained control. */
2685 UInt * client_auxv;
2686 VgSchedReturnCode src;
fitzhardingeb50068f2004-02-24 23:42:55 +00002687 vki_rlimit zero = { 0, 0 };
nethercote71980f02004-01-24 18:18:54 +00002688
2689 //============================================================
2690 // Nb: startup is complex. Prerequisites are shown at every step.
2691 //
2692 // *** Be very careful when messing with the order ***
2693 //============================================================
2694
fitzhardingeb50068f2004-02-24 23:42:55 +00002695 // Get the current process datasize rlimit, and set it to zero.
2696 // This prevents any internal uses of brk() from having any effect.
2697 // We remember the old value so we can restore it on exec, so that
2698 // child processes will have a reasonable brk value.
2699 VG_(getrlimit)(VKI_RLIMIT_DATA, &VG_(client_rlimit_data));
2700 zero.rlim_max = VG_(client_rlimit_data).rlim_max;
2701 VG_(setrlimit)(VKI_RLIMIT_DATA, &zero);
2702
nethercote71980f02004-01-24 18:18:54 +00002703 //--------------------------------------------------------------
2704 // Check we were launched by stage1
2705 // p: n/a [must be first step]
2706 //--------------------------------------------------------------
2707 scan_auxv();
2708
2709 if (0) {
2710 int prmap(void *start, void *end, const char *perm, off_t off,
2711 int maj, int min, int ino) {
2712 printf("mapping %10p-%10p %s %02x:%02x %d\n",
2713 start, end, perm, maj, min, ino);
2714 return True;
2715 }
2716 printf("========== main() ==========\n");
2717 foreach_map(prmap);
2718 }
2719
2720 //--------------------------------------------------------------
2721 // Look for alternative libdir
2722 // p: n/a
2723 //--------------------------------------------------------------
2724 { char *cp = getenv(VALGRINDLIB);
2725 if (cp != NULL)
2726 VG_(libdir) = cp;
2727 }
2728
2729 //--------------------------------------------------------------
2730 // Begin working out address space layout
2731 // p: n/a
2732 //--------------------------------------------------------------
2733 layout_client_space( (Addr) & argc );
2734
2735 //--------------------------------------------------------------
2736 // Get valgrind args + client args (inc. from VALGRIND_OPTS/.valgrindrc).
2737 // Pre-process the command line.
2738 // p: n/a
2739 //--------------------------------------------------------------
2740 get_command_line(argc, argv, &VG_(vg_argc), &VG_(vg_argv), &cl_argv);
2741 pre_process_cmd_line_options(&need_help, &tool, &exec);
2742
2743 //==============================================================
2744 // Nb: once a tool is specified, the tool.so must be loaded even if
2745 // they specified --help or didn't specify a client program.
2746 //==============================================================
2747
2748 //--------------------------------------------------------------
2749 // With client padded out, map in tool
2750 // p: layout_client_space() [for padding]
2751 // p: set-libdir [for VG_(libdir)]
2752 // p: pre_process_cmd_line_options() [for 'tool']
2753 //--------------------------------------------------------------
2754 load_tool(tool, &tool_dlhandle, &toolinfo, &preload);
2755
2756 //==============================================================
2757 // Can use VG_(malloc)() and VG_(arena_malloc)() only after load_tool()
2758 // -- redzone size is now set.
2759 //==============================================================
2760
2761 //--------------------------------------------------------------
2762 // Finalise address space layout
2763 // p: layout_client_space(), load_tool() [for 'toolinfo']
2764 //--------------------------------------------------------------
2765 layout_remaining_space( toolinfo->shadow_ratio );
2766
2767 //--------------------------------------------------------------
2768 // Load client executable, finding in $PATH if necessary
2769 // p: layout_client_space() [so there's space]
2770 // p: pre_process_cmd_line_options() [for 'exec', 'need_help']
2771 // p: layout_remaining_space [so there's space]
2772 //--------------------------------------------------------------
2773 load_client(cl_argv, exec, /*inout*/&need_help, &info, &client_eip);
2774
2775 //--------------------------------------------------------------
2776 // Everything in place, unpad us
2777 // p: layout_remaining_space() [everything must be mapped in before now]
2778 // p: load_client() [ditto]
2779 //--------------------------------------------------------------
2780 as_unpad((void *)VG_(shadow_end), (void *)~0);
2781 as_closepadfile(); /* no more padding */
2782
2783 //--------------------------------------------------------------
2784 // Set up client's environment
2785 // p: set-libdir [for VG_(libdir)]
2786 // p: load_tool() [for 'preload']
2787 //--------------------------------------------------------------
2788 env = fix_environment(environ, preload);
2789
2790 //--------------------------------------------------------------
2791 // Setup client stack and eip
2792 // p: load_client() [for 'info']
2793 // p: fix_environment() [for 'env']
2794 //--------------------------------------------------------------
2795 esp_at_startup = setup_client_stack(cl_argv, env, &info, &client_auxv);
2796
2797 if (0)
2798 printf("entry=%x client esp=%x vg_argc=%d brkbase=%x\n",
2799 client_eip, esp_at_startup, VG_(vg_argc), VG_(brk_base));
2800
2801 //==============================================================
2802 // Finished setting up operating environment. Now initialise
2803 // Valgrind. (This is where the old VG_(main)() started.)
2804 //==============================================================
2805
2806 //--------------------------------------------------------------
2807 // Read /proc/self/maps into a buffer
2808 // p: all memory layout, environment setup [so memory maps are right]
2809 //--------------------------------------------------------------
2810 VG_(read_procselfmaps)();
2811
2812 //--------------------------------------------------------------
2813 // atfork
2814 // p: n/a
2815 //--------------------------------------------------------------
2816 VG_(atfork)(NULL, NULL, newpid);
2817 newpid(VG_INVALID_THREADID);
2818
2819 //--------------------------------------------------------------
2820 // setup file descriptors
2821 // p: n/a
2822 //--------------------------------------------------------------
2823 setup_file_descriptors();
2824
2825 //--------------------------------------------------------------
2826 // Setup tool
2827 // p: VG_(read_procselfmaps)() [so if sk_pre_clo_init calls
2828 // VG_(malloc), any mmap'd superblocks aren't erroneously
2829 // identified later as being owned by the client]
2830 // XXX: is that necessary, now that we look for V's segments separately?
2831 // XXX: alternatively, if sk_pre_clo_init does use VG_(malloc)(), is it
2832 // wrong to ignore any segments that might add in parse_procselfmaps?
2833 //--------------------------------------------------------------
2834 (*toolinfo->sk_pre_clo_init)();
2835 VG_(tool_init_dlsym)(tool_dlhandle);
2836 VG_(sanity_check_needs)();
2837
2838 //--------------------------------------------------------------
2839 // Process Valgrind's + tool's command-line options
2840 // p: load_tool() [for 'tool']
2841 // p: load_client() [for 'need_help']
2842 // p: setup_file_descriptors() [for 'VG_(max_fd)']
2843 // p: sk_pre_clo_init [to set 'command_line_options' need]
2844 //--------------------------------------------------------------
2845 process_cmd_line_options(client_auxv, esp_at_startup, tool, need_help);
2846
2847 //--------------------------------------------------------------
2848 // Allow GDB attach
2849 // p: process_cmd_line_options() [for VG_(clo_wait_for_gdb)]
2850 //--------------------------------------------------------------
2851 /* Hook to delay things long enough so we can get the pid and
2852 attach GDB in another shell. */
2853 if (VG_(clo_wait_for_gdb)) {
2854 VG_(printf)("pid=%d\n", VG_(getpid)());
2855 /* do "jump *$eip" to skip this in gdb */
2856 VG_(do_syscall)(__NR_pause);
2857 }
2858
2859 //--------------------------------------------------------------
2860 // Setup tool, post command-line processing
2861 // p: process_cmd_line_options [tool assumes it]
2862 //--------------------------------------------------------------
2863 SK_(post_clo_init)();
2864
2865 //--------------------------------------------------------------
nethercote1d447092004-02-01 17:29:59 +00002866 // Set up baseBlock
nethercote71980f02004-01-24 18:18:54 +00002867 // p: {pre,post}_clo_init() [for tool helper registration]
2868 // load_client() [for 'client_eip']
2869 // setup_client_stack() [for 'esp_at_startup']
2870 //--------------------------------------------------------------
2871 init_baseBlock(client_eip, esp_at_startup);
2872
2873 //--------------------------------------------------------------
2874 // Search for file descriptors that are inherited from our parent
2875 // p: process_cmd_line_options [for VG_(clo_track_fds)]
2876 //--------------------------------------------------------------
2877 if (VG_(clo_track_fds))
2878 VG_(init_preopened_fds)();
2879
2880 //--------------------------------------------------------------
2881 // Initialise the scheduler
2882 // p: init_baseBlock() [baseBlock regs copied into VG_(threads)[1]]
2883 // p: setup_file_descriptors() [else VG_(safe_fd)() breaks]
2884 //--------------------------------------------------------------
2885 VG_(scheduler_init)();
2886
2887 //--------------------------------------------------------------
2888 // Set up the ProxyLWP machinery
2889 // p: VG_(scheduler_init)()? [XXX: subtle dependency?]
2890 // - subs: VG_(sigstartup_actions)()?
2891 //--------------------------------------------------------------
2892 VG_(proxy_init)();
2893
2894 //--------------------------------------------------------------
2895 // Initialise the signal handling subsystem
2896 // p: VG_(atfork)(NULL, NULL, newpid) [else problems with sigmasks]
2897 // p: VG_(proxy_init)() [else breaks...]
2898 //--------------------------------------------------------------
2899 // Nb: temporarily parks the saved blocking-mask in saved_sigmask.
2900 VG_(sigstartup_actions)();
2901
2902 //--------------------------------------------------------------
2903 // Perhaps we're profiling Valgrind?
2904 // p: process_cmd_line_options() [for VG_(clo_profile)]
2905 // p: others?
2906 //
2907 // XXX: this seems to be broken? It always says the tool wasn't built
2908 // for profiling; vg_profile.c's functions don't seem to be overriding
2909 // vg_dummy_profile.c's?
2910 //
2911 // XXX: want this as early as possible. Looking for --profile
2912 // in pre_process_cmd_line_options() could get it earlier.
2913 //--------------------------------------------------------------
2914 if (VG_(clo_profile))
2915 VGP_(init_profiling)();
2916
2917 VGP_PUSHCC(VgpStartup);
2918
2919 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002920 // Reserve Valgrind's kickstart, heap and stack
2921 // p: XXX ???
2922 //--------------------------------------------------------------
2923 VG_(map_segment)(VG_(valgrind_mmap_end),
2924 VG_(valgrind_end)-VG_(valgrind_mmap_end),
2925 VKI_PROT_NONE, SF_VALGRIND|SF_FIXED);
2926
2927 //--------------------------------------------------------------
2928 // Identify Valgrind's segments
2929 // p: read proc/self/maps
2930 // p: VG_(map_segment) [XXX ???]
2931 // p: sk_pre_clo_init() [to setup new_mem_startup tracker]
2932 //--------------------------------------------------------------
2933 VG_(parse_procselfmaps) ( build_valgrind_map_callback );
2934
2935 // XXX: I can't see why these two need to be separate; could they be
2936 // folded together? If not, need a comment explaining why.
2937 //
2938 // XXX: can we merge reading and parsing of /proc/self/maps?
2939 //
2940 // XXX: can we dynamically allocate the /proc/self/maps buffer? (or mmap
2941 // it?) Or does that disturb its contents...
2942
2943 //--------------------------------------------------------------
2944 // Build segment map (all segments)
2945 // p: setup_client_stack() [for 'esp_at_startup']
2946 //--------------------------------------------------------------
2947 esp_at_startup___global_arg = esp_at_startup;
2948 VG_(parse_procselfmaps) ( build_segment_map_callback ); /* everything */
2949 esp_at_startup___global_arg = 0;
2950
2951 //==============================================================
2952 // Can only use VG_(map)() after VG_(map_segment)() [XXX ???]
2953 //==============================================================
2954
2955 //--------------------------------------------------------------
2956 // Build segment map (all segments)
2957 // p: setup_client_stack() [for 'esp_at_startup']
2958 //--------------------------------------------------------------
2959 /* Initialize our trampoline page (which is also sysinfo stuff) */
2960 VG_(memcpy)( (void *)VG_(client_trampoline_code),
2961 &VG_(trampoline_code_start), VG_(trampoline_code_length) );
2962 VG_(mprotect)( (void *)VG_(client_trampoline_code),
2963 VG_(trampoline_code_length), VKI_PROT_READ|VKI_PROT_EXEC );
2964
2965 //--------------------------------------------------------------
2966 // Read suppression file
2967 // p: process_cmd_line_options() [for VG_(clo_suppressions)]
2968 //--------------------------------------------------------------
2969 if (VG_(needs).core_errors || VG_(needs).skin_errors)
2970 VG_(load_suppressions)();
2971
2972 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002973 // Initialise translation table and translation cache
2974 // p: read_procselfmaps [so the anonymous mmaps for the TT/TC
2975 // aren't identified as part of the client, which would waste
2976 // > 20M of virtual address space.]
2977 //--------------------------------------------------------------
2978 VG_(init_tt_tc)();
2979
2980 //--------------------------------------------------------------
2981 // Read debug info to find glibc entry points to intercept
2982 // p: parse_procselfmaps? [XXX for debug info?]
2983 // p: init_tt_tc? [XXX ???]
2984 //--------------------------------------------------------------
2985 VG_(setup_code_redirect_table)();
2986
2987 //--------------------------------------------------------------
2988 // Verbosity message
2989 // p: end_rdtsc_calibration [so startup message is printed first]
2990 //--------------------------------------------------------------
2991 if (VG_(clo_verbosity) == 1)
2992 VG_(message)(Vg_UserMsg, "For more details, rerun with: -v");
2993 if (VG_(clo_verbosity) > 0)
2994 VG_(message)(Vg_UserMsg, "");
2995
2996 //--------------------------------------------------------------
2997 // Setup pointercheck
2998 // p: process_cmd_line_options() [for VG_(clo_pointercheck)]
2999 //--------------------------------------------------------------
3000 setup_pointercheck();
3001
3002
3003
3004 //--------------------------------------------------------------
3005 // Run!
3006 //--------------------------------------------------------------
3007 VG_(running_on_simd_CPU) = True;
3008 VGP_POPCC(VgpStartup);
3009 VGP_PUSHCC(VgpSched);
3010
3011 if (__builtin_setjmp(&VG_(fatal_signal_jmpbuf)) == 0) {
3012 VG_(fatal_signal_set) = True;
3013 src = VG_(scheduler)();
3014 } else
3015 src = VgSrc_FatalSig;
3016
3017 VGP_POPCC(VgpSched);
3018 VG_(running_on_simd_CPU) = False;
3019
3020
3021
3022 //--------------------------------------------------------------
3023 // Finalisation: cleanup, messages, etc. Order no so important, only
3024 // affects what order the messages come.
3025 //--------------------------------------------------------------
3026 if (VG_(clo_verbosity) > 0)
3027 VG_(message)(Vg_UserMsg, "");
3028
3029 if (src == VgSrc_Deadlock) {
3030 VG_(message)(Vg_UserMsg,
3031 "Warning: pthread scheduler exited due to deadlock");
3032 }
3033
3034 /* Print out file descriptor summary and stats. */
3035 if (VG_(clo_track_fds))
3036 VG_(fd_stats)();
3037
3038 if (VG_(needs).core_errors || VG_(needs).skin_errors)
3039 VG_(show_all_errors)();
3040
3041 SK_(fini)( VG_(exitcode) );
3042
3043 VG_(do_sanity_checks)( True /*include expensive checks*/ );
3044
3045 if (VG_(clo_verbosity) > 1)
3046 show_counts();
3047
3048 if (VG_(clo_verbosity) > 3)
3049 VG_(print_UInstr_histogram)();
3050
3051 if (0) {
3052 VG_(message)(Vg_DebugMsg, "");
3053 VG_(message)(Vg_DebugMsg,
3054 "------ Valgrind's internal memory use stats follow ------" );
3055 VG_(mallocSanityCheckAll)();
3056 VG_(show_all_arena_stats)();
3057 VG_(message)(Vg_DebugMsg,
3058 "------ Valgrind's ExeContext management stats follow ------" );
3059 VG_(show_ExeContext_stats)();
3060 }
3061
3062 if (VG_(clo_profile))
3063 VGP_(done_profiling)();
3064
3065 /* Must be after all messages are done */
3066 VG_(shutdown_logging)();
3067
3068 /* We're exiting, so nuke all the threads and clean up the proxy LWPs */
3069 vg_assert(src == VgSrc_FatalSig ||
3070 VG_(threads)[VG_(last_run_tid)].status == VgTs_Runnable ||
3071 VG_(threads)[VG_(last_run_tid)].status == VgTs_WaitJoiner);
3072 VG_(nuke_all_threads_except)(VG_INVALID_THREADID);
3073
3074 //--------------------------------------------------------------
3075 // Exit, according to the scheduler's return code
3076 //--------------------------------------------------------------
3077 switch (src) {
3078 case VgSrc_ExitSyscall: /* the normal way out */
3079 vg_assert(VG_(last_run_tid) > 0
3080 && VG_(last_run_tid) < VG_N_THREADS);
3081 VG_(proxy_shutdown)();
3082
3083 /* The thread's %EBX at the time it did __NR_exit() will hold
3084 the arg to __NR_exit(), so we just do __NR_exit() with
3085 that arg. */
3086 VG_(exit)( VG_(exitcode) );
3087 /* NOT ALIVE HERE! */
3088 VG_(core_panic)("entered the afterlife in main() -- ExitSyscall");
3089 break; /* what the hell :) */
3090
3091 case VgSrc_Deadlock:
3092 /* Just exit now. No point in continuing. */
3093 VG_(proxy_shutdown)();
3094 VG_(exit)(0);
3095 VG_(core_panic)("entered the afterlife in main() -- Deadlock");
3096 break;
3097
nethercote71980f02004-01-24 18:18:54 +00003098 case VgSrc_FatalSig:
3099 /* We were killed by a fatal signal, so replicate the effect */
3100 vg_assert(VG_(fatal_sigNo) != -1);
3101 VG_(kill_self)(VG_(fatal_sigNo));
3102 VG_(core_panic)("main(): signal was supposed to be fatal");
3103 break;
3104
3105 default:
3106 VG_(core_panic)("main(): unexpected scheduler return code");
3107 }
3108
3109 abort();
3110}
3111
3112
sewardjde4a1d02002-03-22 01:27:54 +00003113/*--------------------------------------------------------------------*/
3114/*--- end vg_main.c ---*/
3115/*--------------------------------------------------------------------*/