blob: 9da5b98d279109955ea5e582b58aa5824959b54d [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 &&
thughes1d160052004-04-21 15:39:57 +0000353 kill(pid, SIGSTOP) == 0 &&
354 ptrace(PTRACE_DETACH, pid, NULL, 0) == 0) {
nethercote04d0fbc2004-01-26 16:48:06 +0000355 Char pidbuf[15];
356 Char file[30];
357 Char buf[100];
358 Char *bufptr;
359 Char *cmdptr;
360
361 VG_(sprintf)(pidbuf, "%d", pid);
362 VG_(sprintf)(file, "/proc/%d/fd/%d", pid, VG_(clexecfd));
363
364 bufptr = buf;
365 cmdptr = VG_(clo_db_command);
366
367 while (*cmdptr) {
368 switch (*cmdptr) {
369 case '%':
370 switch (*++cmdptr) {
371 case 'f':
372 VG_(memcpy)(bufptr, file, VG_(strlen)(file));
373 bufptr += VG_(strlen)(file);
374 cmdptr++;
375 break;
376 case 'p':
377 VG_(memcpy)(bufptr, pidbuf, VG_(strlen)(pidbuf));
378 bufptr += VG_(strlen)(pidbuf);
379 cmdptr++;
380 break;
381 default:
382 *bufptr++ = *cmdptr++;
383 break;
384 }
385 break;
386 default:
387 *bufptr++ = *cmdptr++;
388 break;
389 }
390 }
391
392 *bufptr++ = '\0';
393
394 VG_(message)(Vg_UserMsg, "starting debugger with cmd: %s", buf);
nethercote71980f02004-01-24 18:18:54 +0000395 res = VG_(system)(buf);
396 if (res == 0) {
397 VG_(message)(Vg_UserMsg, "");
398 VG_(message)(Vg_UserMsg,
nethercote04d0fbc2004-01-26 16:48:06 +0000399 "Debugger has detached. Valgrind regains control. We continue.");
nethercote71980f02004-01-24 18:18:54 +0000400 } else {
401 VG_(message)(Vg_UserMsg, "Apparently failed!");
402 VG_(message)(Vg_UserMsg, "");
403 }
404 }
405
406 VG_(kkill)(pid, VKI_SIGKILL);
407 VG_(waitpid)(pid, &status, 0);
408 }
409}
410
411
412/* Print some helpful-ish text about unimplemented things, and give
413 up. */
414void VG_(unimplemented) ( Char* msg )
415{
416 VG_(message)(Vg_UserMsg, "");
417 VG_(message)(Vg_UserMsg,
418 "Valgrind detected that your program requires");
419 VG_(message)(Vg_UserMsg,
420 "the following unimplemented functionality:");
421 VG_(message)(Vg_UserMsg, " %s", msg);
422 VG_(message)(Vg_UserMsg,
423 "This may be because the functionality is hard to implement,");
424 VG_(message)(Vg_UserMsg,
425 "or because no reasonable program would behave this way,");
426 VG_(message)(Vg_UserMsg,
427 "or because nobody has yet needed it. In any case, let us know at");
428 VG_(message)(Vg_UserMsg,
429 "%s and/or try to work around the problem, if you can.", VG_BUGS_TO);
430 VG_(message)(Vg_UserMsg,
431 "");
432 VG_(message)(Vg_UserMsg,
433 "Valgrind has to exit now. Sorry. Bye!");
434 VG_(message)(Vg_UserMsg,
435 "");
436 VG_(pp_sched_status)();
437 VG_(exit)(1);
438}
439
440Addr VG_(get_stack_pointer) ( void )
441{
442 return VG_(baseBlock)[VGOFF_(m_esp)];
443}
444
445/* Debugging thing .. can be called from assembly with OYNK macro. */
446void VG_(oynk) ( Int n )
447{
448 OINK(n);
449}
450
451/* Initialize the PID and PGRP of scheduler LWP; this is also called
452 in any new children after fork. */
453static void newpid(ThreadId unused)
454{
455 /* PID of scheduler LWP */
456 VG_(main_pid) = VG_(getpid)();
457 VG_(main_pgrp) = VG_(getpgrp)();
458}
459
460/*====================================================================*/
461/*=== Check we were launched by stage 1 ===*/
462/*====================================================================*/
463
464/* Look for our AUXV table */
465static void scan_auxv(void)
466{
467 const struct ume_auxv *auxv = find_auxv((int *)ume_exec_esp);
468 int found = 0;
469
470 for (; auxv->a_type != AT_NULL; auxv++)
471 switch(auxv->a_type) {
472 case AT_UME_PADFD:
473 as_setpadfd(auxv->u.a_val);
474 found |= 1;
475 break;
476
477 case AT_UME_EXECFD:
478 VG_(vgexecfd) = auxv->u.a_val;
479 found |= 2;
480 break;
481 }
482
483 if ( ! (1|2) ) {
484 fprintf(stderr, "stage2 must be launched by stage1\n");
485 exit(127);
486 }
487}
488
489
490/*====================================================================*/
491/*=== Address space determination ===*/
492/*====================================================================*/
493
494/* Pad client space so it doesn't get filled in before the right time */
495static void layout_client_space(Addr argc_addr)
496{
497 VG_(client_base) = CLIENT_BASE;
498 VG_(valgrind_mmap_end) = (addr_t)&kickstart_base; /* end of V's mmaps */
499 VG_(valgrind_base) = VG_(valgrind_mmap_end) - VALGRIND_MAPSIZE;
500 VG_(valgrind_end) = ROUNDUP(argc_addr, 0x10000); /* stack */
501
502 if (0)
503 printf("client base: %x\n"
504 "valgrind base--end: %x--%x (%x)\n"
505 "valgrind mmap end: %x\n\n",
506 VG_(client_base),
507 VG_(valgrind_base), VG_(valgrind_end),
508 VG_(valgrind_end) - VG_(valgrind_base),
509 VG_(valgrind_mmap_end));
510
511 as_pad((void *)VG_(client_base), (void *)VG_(valgrind_base));
512}
513
514static void layout_remaining_space(float ratio)
515{
516 /* This tries to give the client as large as possible address space while
517 * taking into account the tool's shadow needs. */
518 addr_t client_size = ROUNDDN((VG_(valgrind_base) - REDZONE_SIZE) / (1. + ratio),
519 CLIENT_SIZE_MULTIPLE);
520 addr_t shadow_size = PGROUNDUP(client_size * ratio);
521
522 VG_(client_end) = VG_(client_base) + client_size;
523 VG_(client_mapbase) = PGROUNDDN((client_size/4)*3); /* where !FIXED mmap goes */
524 VG_(client_trampoline_code) = VG_(client_end) - VKI_BYTES_PER_PAGE;
525
526 VG_(shadow_base) = VG_(client_end) + REDZONE_SIZE;
527 VG_(shadow_end) = VG_(shadow_base) + shadow_size;
528
529 if (0)
530 printf("client base--end: %x--%x (%x)\n"
531 "client mapbase: %x\n"
532 "shadow base--end: %x--%x (%x)\n\n",
533 VG_(client_base), VG_(client_end), client_size,
534 VG_(client_mapbase),
535 VG_(shadow_base), VG_(shadow_end), shadow_size);
536
537 // Ban redzone
538 mmap((void *)VG_(client_end), REDZONE_SIZE, PROT_NONE,
539 MAP_FIXED|MAP_ANON|MAP_PRIVATE, -1, 0);
540
541 // Make client hole
542 munmap((void*)VG_(client_base), client_size);
543
544 // Map shadow memory.
545 // Initially all inaccessible, incrementally initialized as it is used
546 if (shadow_size != 0)
547 mmap((char *)VG_(shadow_base), shadow_size, PROT_NONE,
548 MAP_PRIVATE|MAP_ANON|MAP_FIXED, -1, 0);
549}
550
551/*====================================================================*/
552/*=== Command line setup ===*/
553/*====================================================================*/
554
555/* Nb: malloc'd memory never freed -- kept throughout like argv, envp */
556static char* get_file_clo(char* dir)
557{
558# define FLEN 512
559 Int fd, n;
560 struct stat s1;
561 char* f_clo = NULL;
562 char filename[FLEN];
563
564 snprintf(filename, FLEN, "%s/.valgrindrc", ( NULL == dir ? "" : dir ) );
565 fd = VG_(open)(filename, 0, VKI_S_IRUSR);
566 if ( fd > 0 ) {
567 if ( 0 == fstat(fd, &s1) ) {
568 f_clo = malloc(s1.st_size+1);
569 vg_assert(f_clo);
570 n = read(fd, f_clo, s1.st_size);
571 if (n == -1) n = 0;
572 f_clo[n] = '\0';
573 }
574 close(fd);
575 }
576 return f_clo;
577# undef FLEN
578}
579
580static Int count_args(char* s)
581{
582 Int n = 0;
583 if (s) {
584 char* cp = s;
585 while (True) {
586 // We have alternating sequences: blanks, non-blanks, blanks...
587 // count the non-blanks sequences.
588 while ( ISSPACE(*cp) ) cp++;
589 if ( !*cp ) break;
590 n++;
591 while ( !ISSPACE(*cp) && *cp ) cp++;
592 }
593 }
594 return n;
595}
596
597/* add args out of environment, skipping multiple spaces and -- args */
598static char** copy_args( char* s, char** to )
599{
600 if (s) {
601 char* cp = s;
602 while (True) {
603 // We have alternating sequences: blanks, non-blanks, blanks...
604 // copy the non-blanks sequences, and add terminating '\0'
605 while ( ISSPACE(*cp) ) cp++;
606 if ( !*cp ) break;
607 *to++ = cp;
608 while ( !ISSPACE(*cp) && *cp ) cp++;
609 if ( *cp ) *cp++ = '\0'; // terminate if necessary
610 if (VG_STREQ(to[-1], "--")) to--; // undo any '--' arg
611 }
612 }
613 return to;
614}
615
616// Augment command line with arguments from environment and .valgrindrc
617// files.
618static void augment_command_line(Int* vg_argc_inout, char*** vg_argv_inout)
619{
620 int vg_argc = *vg_argc_inout;
621 char** vg_argv = *vg_argv_inout;
622
623 char* env_clo = getenv(VALGRINDOPTS);
624 char* f1_clo = get_file_clo( getenv("HOME") );
625 char* f2_clo = get_file_clo(".");
626
627 /* copy any extra args from file or environment, if present */
628 if ( (env_clo && *env_clo) || (f1_clo && *f1_clo) || (f2_clo && *f2_clo) ) {
629 /* ' ' separated extra options */
630 char **from;
631 char **to;
632 int env_arg_count, f1_arg_count, f2_arg_count;
633
634 env_arg_count = count_args(env_clo);
635 f1_arg_count = count_args(f1_clo);
636 f2_arg_count = count_args(f2_clo);
637
638 if (0)
639 printf("extra-argc=%d %d %d\n",
640 env_arg_count, f1_arg_count, f2_arg_count);
641
642 /* +2: +1 for null-termination, +1 for added '--' */
643 from = vg_argv;
644 vg_argv = malloc( (vg_argc + env_arg_count + f1_arg_count
645 + f2_arg_count + 2) * sizeof(char **));
646 to = vg_argv;
647
648 /* copy argv[0] */
649 *to++ = *from++;
650
651 /* Copy extra args from env var and file, in the order: ~/.valgrindrc,
652 * $VALGRIND_OPTS, ./.valgrindrc -- more local options are put later
653 * to override less local ones. */
654 to = copy_args(f1_clo, to);
655 to = copy_args(env_clo, to);
656 to = copy_args(f2_clo, to);
657
658 /* copy original arguments, stopping at command or -- */
659 while (*from) {
660 if (**from != '-')
661 break;
662 if (VG_STREQ(*from, "--")) {
663 from++; /* skip -- */
664 break;
665 }
666 *to++ = *from++;
667 }
668
669 /* add -- */
670 *to++ = "--";
671
672 vg_argc = to - vg_argv;
673
674 /* copy rest of original command line, then NULL */
675 while (*from) *to++ = *from++;
676 *to = NULL;
677 }
678
679 *vg_argc_inout = vg_argc;
680 *vg_argv_inout = vg_argv;
681}
682
683static void get_command_line( int argc, char** argv,
684 Int* vg_argc_out, Char*** vg_argv_out,
685 char*** cl_argv_out )
686{
687 int vg_argc;
688 char** vg_argv;
689 char** cl_argv;
690 char* env_clo = getenv(VALGRINDCLO);
691
692 if (env_clo != NULL && *env_clo != '\0') {
693 char *cp;
694 char **cpp;
695
696 /* OK, we're getting all our arguments from the environment - the
697 entire command line belongs to the client (including argv[0]) */
698 vg_argc = 1; /* argv[0] */
699 for (cp = env_clo; *cp; cp++)
700 if (*cp == '\01')
701 vg_argc++;
702
703 vg_argv = malloc(sizeof(char **) * (vg_argc + 1));
704
705 cpp = vg_argv;
706
707 *cpp++ = "valgrind"; /* nominal argv[0] */
708 *cpp++ = env_clo;
709
710 for (cp = env_clo; *cp; cp++) {
711 if (*cp == '\01') {
712 *cp++ = '\0'; /* chop it up in place */
713 *cpp++ = cp;
714 }
715 }
716 *cpp = NULL;
717 cl_argv = argv;
718
719 } else {
720 /* Count the arguments on the command line. */
721 vg_argv = argv;
722
723 for (vg_argc = 1; vg_argc < argc; vg_argc++) {
724 if (argv[vg_argc][0] != '-') /* exe name */
725 break;
726 if (VG_STREQ(argv[vg_argc], "--")) { /* dummy arg */
727 vg_argc++;
728 break;
729 }
730 }
731 cl_argv = &argv[vg_argc];
732
733 /* Get extra args from VALGRIND_OPTS and .valgrindrc files.
734 * Note we don't do this if getting args from VALGRINDCLO. */
735 augment_command_line(&vg_argc, &vg_argv);
736 }
737
738 if (0) {
739 Int i;
740 for (i = 0; i < vg_argc; i++)
741 printf("vg_argv[%d]=\"%s\"\n", i, vg_argv[i]);
742 }
743
744 *vg_argc_out = vg_argc;
745 *vg_argv_out = (Char**)vg_argv;
746 *cl_argv_out = cl_argv;
747}
748
749
750/*====================================================================*/
751/*=== Environment and stack setup ===*/
752/*====================================================================*/
753
754/* Scan a colon-separated list, and call a function on each element.
755 The string must be mutable, because we insert a temporary '\0', but
756 the string will end up unmodified. (*func) should return 1 if it
757 doesn't need to see any more.
758*/
759static void scan_colsep(char *colsep, int (*func)(const char *))
760{
761 char *cp, *entry;
762 int end;
763
764 if (colsep == NULL ||
765 *colsep == '\0')
766 return;
767
768 entry = cp = colsep;
769
770 do {
771 end = (*cp == '\0');
772
773 if (*cp == ':' || *cp == '\0') {
774 char save = *cp;
775
776 *cp = '\0';
777 if ((*func)(entry))
778 end = 1;
779 *cp = save;
780 entry = cp+1;
781 }
782 cp++;
783 } while(!end);
784}
785
786/* Prepare the client's environment. This is basically a copy of our
787 environment, except:
788 1. LD_LIBRARY_PATH=$VALGRINDLIB:$LD_LIBRARY_PATH
789 2. LD_PRELOAD=$VALGRINDLIB/vg_inject.so:($VALGRINDLIB/vgpreload_TOOL.so:)?$LD_PRELOAD
790
791 If any of these is missing, then it is added.
792
793 Yummy. String hacking in C.
794
795 If this needs to handle any more variables it should be hacked
796 into something table driven.
797 */
798static char **fix_environment(char **origenv, const char *preload)
799{
800 static const char inject_so[] = "vg_inject.so";
801 static const char ld_library_path[] = "LD_LIBRARY_PATH=";
802 static const char ld_preload[] = "LD_PRELOAD=";
803 static const char valgrind_clo[] = VALGRINDCLO "=";
804 static const int ld_library_path_len = sizeof(ld_library_path)-1;
805 static const int ld_preload_len = sizeof(ld_preload)-1;
806 static const int valgrind_clo_len = sizeof(valgrind_clo)-1;
807 int ld_preload_done = 0;
808 int ld_library_path_done = 0;
809 char *inject_path;
810 int inject_path_len;
811 int vgliblen = strlen(VG_(libdir));
812 char **cpp;
813 char **ret;
814 int envc;
815 const int preloadlen = (preload == NULL) ? 0 : strlen(preload);
816
817 /* Find the vg_inject.so; also make room for the tool preload
818 library */
819 inject_path_len = sizeof(inject_so) + vgliblen + preloadlen + 16;
820 inject_path = malloc(inject_path_len);
821
822 if (preload)
823 snprintf(inject_path, inject_path_len, "%s/%s:%s",
824 VG_(libdir), inject_so, preload);
825 else
826 snprintf(inject_path, inject_path_len, "%s/%s",
827 VG_(libdir), inject_so);
828
829 /* Count the original size of the env */
830 envc = 0; /* trailing NULL */
831 for (cpp = origenv; cpp && *cpp; cpp++)
832 envc++;
833
834 /* Allocate a new space */
835 ret = malloc(sizeof(char *) * (envc+3+1)); /* 3 new entries + NULL */
836
837 /* copy it over */
838 for (cpp = ret; *origenv; )
839 *cpp++ = *origenv++;
840 *cpp = NULL;
841
842 vg_assert(envc == (cpp - ret));
843
844 /* Walk over the new environment, mashing as we go */
845 for (cpp = ret; cpp && *cpp; cpp++) {
846 if (memcmp(*cpp, ld_library_path, ld_library_path_len) == 0) {
847 int done = 0;
848 int contains(const char *p) {
849 if (VG_STREQ(p, VG_(libdir))) {
850 done = 1;
851 return 1;
852 }
853 return 0;
854 }
855
856 /* If the LD_LIBRARY_PATH already contains libdir, then don't
857 bother adding it again, even if it isn't the first (it
858 seems that the Java runtime will keep reexecing itself
859 unless its paths are at the front of LD_LIBRARY_PATH) */
860 scan_colsep(*cpp + ld_library_path_len, contains);
861
862 if (!done) {
863 int len = strlen(*cpp) + vgliblen*2 + 16;
864 char *cp = malloc(len);
865
866 snprintf(cp, len, "%s%s:%s",
867 ld_library_path, VG_(libdir),
868 (*cpp)+ld_library_path_len);
869
870 *cpp = cp;
871 }
872
873 ld_library_path_done = 1;
874 } else if (memcmp(*cpp, ld_preload, ld_preload_len) == 0) {
875 int len = strlen(*cpp) + inject_path_len;
876 char *cp = malloc(len);
877
878 snprintf(cp, len, "%s%s:%s",
879 ld_preload, inject_path, (*cpp)+ld_preload_len);
880
881 *cpp = cp;
882
883 ld_preload_done = 1;
884 } else if (memcmp(*cpp, valgrind_clo, valgrind_clo_len) == 0) {
885 *cpp = "";
886 }
887 }
888
889 /* Add the missing bits */
890
891 if (!ld_library_path_done) {
892 int len = ld_library_path_len + vgliblen*2 + 16;
893 char *cp = malloc(len);
894
895 snprintf(cp, len, "%s%s", ld_library_path, VG_(libdir));
896
897 ret[envc++] = cp;
898 }
899
900 if (!ld_preload_done) {
901 int len = ld_preload_len + inject_path_len;
902 char *cp = malloc(len);
903
904 snprintf(cp, len, "%s%s",
905 ld_preload, inject_path);
906
907 ret[envc++] = cp;
908 }
909
910 ret[envc] = NULL;
911
912 return ret;
913}
914
915extern char **environ; /* our environment */
916//#include <error.h>
917
918/* Add a string onto the string table, and return its address */
919static char *copy_str(char **tab, const char *str)
920{
921 char *cp = *tab;
922 char *orig = cp;
923
924 while(*str)
925 *cp++ = *str++;
926 *cp++ = '\0';
927
928 if (0)
929 printf("copied %p \"%s\" len %d\n",
930 orig, orig, cp-orig);
931
932 *tab = cp;
933
934 return orig;
935}
936
937/*
938 This sets up the client's initial stack, containing the args,
939 environment and aux vector.
940
941 The format of the stack is:
942
943 higher address +-----------------+
944 | Trampoline code |
945 +-----------------+
946 | |
947 : string table :
948 | |
949 +-----------------+
950 | AT_NULL |
951 - -
952 | auxv |
953 +-----------------+
954 | NULL |
955 - -
956 | envp |
957 +-----------------+
958 | NULL |
959 - -
960 | argv |
961 +-----------------+
962 | argc |
963 lower address +-----------------+ <- esp
964 | undefined |
965 : :
966 */
967static Addr setup_client_stack(char **orig_argv, char **orig_envp,
968 const struct exeinfo *info,
969 UInt** client_auxv)
970{
971 char **cpp;
972 char *strtab; /* string table */
973 char *stringbase;
974 addr_t *ptr;
975 struct ume_auxv *auxv;
976 const struct ume_auxv *orig_auxv;
977 const struct ume_auxv *cauxv;
978 unsigned stringsize; /* total size of strings in bytes */
979 unsigned auxsize; /* total size of auxv in bytes */
980 int argc; /* total argc */
981 int envc; /* total number of env vars */
982 unsigned stacksize; /* total client stack size */
983 addr_t cl_esp; /* client stack base (initial esp) */
984
985 /* use our own auxv as a prototype */
986 orig_auxv = find_auxv(ume_exec_esp);
987
988 /* ==================== compute sizes ==================== */
989
990 /* first of all, work out how big the client stack will be */
991 stringsize = 0;
992
993 /* paste on the extra args if the loader needs them (ie, the #!
994 interpreter and its argument) */
995 argc = 0;
996 if (info->argv0 != NULL) {
997 argc++;
998 stringsize += strlen(info->argv0) + 1;
999 }
1000 if (info->argv1 != NULL) {
1001 argc++;
1002 stringsize += strlen(info->argv1) + 1;
1003 }
1004
1005 /* now scan the args we're given... */
1006 for (cpp = orig_argv; *cpp; cpp++) {
1007 argc++;
1008 stringsize += strlen(*cpp) + 1;
1009 }
1010
1011 /* ...and the environment */
1012 envc = 0;
1013 for (cpp = orig_envp; cpp && *cpp; cpp++) {
1014 envc++;
1015 stringsize += strlen(*cpp) + 1;
1016 }
1017
1018 /* now, how big is the auxv? */
1019 auxsize = sizeof(*auxv); /* there's always at least one entry: AT_NULL */
1020 for (cauxv = orig_auxv; cauxv->a_type != AT_NULL; cauxv++) {
1021 if (cauxv->a_type == AT_PLATFORM)
1022 stringsize += strlen(cauxv->u.a_ptr) + 1;
1023 auxsize += sizeof(*cauxv);
1024 }
1025
1026 /* OK, now we know how big the client stack is */
1027 stacksize =
1028 sizeof(int) + /* argc */
1029 sizeof(char **)*argc + /* argv */
1030 sizeof(char **) + /* terminal NULL */
1031 sizeof(char **)*envc + /* envp */
1032 sizeof(char **) + /* terminal NULL */
1033 auxsize + /* auxv */
1034 ROUNDUP(stringsize, sizeof(int)) +/* strings (aligned) */
1035 VKI_BYTES_PER_PAGE; /* page for trampoline code */
1036
1037 /* cl_esp is the client's stack pointer */
1038 cl_esp = VG_(client_end) - stacksize;
1039 cl_esp = ROUNDDN(cl_esp, 16); /* make stack 16 byte aligned */
1040
1041 if (0)
1042 printf("stringsize=%d auxsize=%d stacksize=%d\n",
1043 stringsize, auxsize, stacksize);
1044
1045
1046 /* base of the string table (aligned) */
1047 stringbase = strtab = (char *)(VG_(client_trampoline_code) - ROUNDUP(stringsize, sizeof(int)));
1048
1049 VG_(clstk_base) = PGROUNDDN(cl_esp);
1050 VG_(clstk_end) = VG_(client_end);
1051
1052 /* ==================== allocate space ==================== */
1053
1054 /* allocate a stack - mmap enough space for the stack */
1055 mmap((void *)PGROUNDDN(cl_esp),
1056 VG_(client_end) - PGROUNDDN(cl_esp),
1057 PROT_READ | PROT_WRITE | PROT_EXEC,
1058 MAP_PRIVATE | MAP_ANON | MAP_FIXED, -1, 0);
1059
1060
1061 /* ==================== copy client stack ==================== */
1062
1063 ptr = (addr_t *)cl_esp;
1064
1065 /* --- argc --- */
1066 *ptr++ = argc; /* client argc */
1067
1068 /* --- argv --- */
1069 if (info->argv0) {
1070 *ptr++ = (addr_t)copy_str(&strtab, info->argv0);
1071 free(info->argv0);
1072 }
1073 if (info->argv1) {
1074 *ptr++ = (addr_t)copy_str(&strtab, info->argv1);
1075 free(info->argv1);
1076 }
1077 for (cpp = orig_argv; *cpp; ptr++, cpp++) {
1078 *ptr = (addr_t)copy_str(&strtab, *cpp);
1079 }
1080 *ptr++ = 0;
1081
1082 /* --- envp --- */
1083 VG_(client_envp) = (Char **)ptr;
1084 for (cpp = orig_envp; cpp && *cpp; ptr++, cpp++)
1085 *ptr = (addr_t)copy_str(&strtab, *cpp);
1086 *ptr++ = 0;
1087
1088 /* --- auxv --- */
1089 auxv = (struct ume_auxv *)ptr;
1090 *client_auxv = (UInt *)auxv;
1091
1092 for (; orig_auxv->a_type != AT_NULL; auxv++, orig_auxv++) {
1093 /* copy the entry... */
1094 *auxv = *orig_auxv;
1095
1096 /* ...and fix up the copy */
1097 switch(auxv->a_type) {
1098 case AT_PHDR:
1099 if (info->phdr == 0)
1100 auxv->a_type = AT_IGNORE;
1101 else
1102 auxv->u.a_val = info->phdr;
1103 break;
1104
1105 case AT_PHNUM:
1106 if (info->phdr == 0)
1107 auxv->a_type = AT_IGNORE;
1108 else
1109 auxv->u.a_val = info->phnum;
1110 break;
1111
1112 case AT_BASE:
1113 if (info->interp_base == 0)
1114 auxv->a_type = AT_IGNORE;
1115 else
1116 auxv->u.a_val = info->interp_base;
1117 break;
1118
1119 case AT_PLATFORM: /* points to a platform description string */
1120 auxv->u.a_ptr = copy_str(&strtab, orig_auxv->u.a_ptr);
1121 break;
1122
1123 case AT_ENTRY:
1124 auxv->u.a_val = info->entry;
1125 break;
1126
1127 case AT_IGNORE:
1128 case AT_EXECFD:
1129 case AT_PHENT:
1130 case AT_PAGESZ:
1131 case AT_FLAGS:
1132 case AT_NOTELF:
1133 case AT_UID:
1134 case AT_EUID:
1135 case AT_GID:
1136 case AT_EGID:
1137 case AT_CLKTCK:
1138 case AT_HWCAP:
1139 case AT_FPUCW:
1140 case AT_DCACHEBSIZE:
1141 case AT_ICACHEBSIZE:
1142 case AT_UCACHEBSIZE:
1143 /* All these are pointerless, so we don't need to do anything
1144 about them. */
1145 break;
1146
1147 case AT_SECURE:
1148 /* If this is 1, then it means that this program is running
1149 suid, and therefore the dynamic linker should be careful
1150 about LD_PRELOAD, etc. However, since stage1 (the thing
1151 the kernel actually execve's) should never be SUID, and we
1152 need LD_PRELOAD/LD_LIBRARY_PATH to work for the client, we
1153 set AT_SECURE to 0. */
1154 auxv->u.a_val = 0;
1155 break;
1156
1157 case AT_SYSINFO:
1158 /* Leave this unmolested for now, but we'll update it later
1159 when we set up the client trampoline code page */
1160 break;
1161
1162 case AT_SYSINFO_EHDR:
1163 /* Trash this, because we don't reproduce it */
1164 auxv->a_type = AT_IGNORE;
1165 break;
1166
1167 default:
1168 /* stomp out anything we don't know about */
1169 if (0)
1170 printf("stomping auxv entry %d\n", auxv->a_type);
1171 auxv->a_type = AT_IGNORE;
1172 break;
1173
1174 }
1175 }
1176 *auxv = *orig_auxv;
1177 vg_assert(auxv->a_type == AT_NULL);
1178
1179 vg_assert((strtab-stringbase) == stringsize);
1180
1181 return cl_esp;
1182}
1183
1184/*====================================================================*/
1185/*=== Find executable ===*/
1186/*====================================================================*/
1187
1188static const char* find_executable(const char* exec)
1189{
1190 vg_assert(NULL != exec);
1191 if (strchr(exec, '/') == NULL) {
1192 /* no '/' - we need to search the path */
1193 char *path = getenv("PATH");
1194 int pathlen = path ? strlen(path) : 0;
1195
1196 int match_exe(const char *entry) {
1197 char buf[pathlen + strlen(entry) + 3];
1198
1199 /* empty PATH element means . */
1200 if (*entry == '\0')
1201 entry = ".";
1202
1203 snprintf(buf, sizeof(buf), "%s/%s", entry, exec);
1204
1205 if (access(buf, R_OK|X_OK) == 0) {
1206 exec = strdup(buf);
1207 vg_assert(NULL != exec);
1208 return 1;
1209 }
1210 return 0;
1211 }
1212 scan_colsep(path, match_exe);
1213 }
1214 return exec;
1215}
1216
1217
1218/*====================================================================*/
1219/*=== Loading tools ===*/
1220/*====================================================================*/
1221
1222static void list_tools(void)
1223{
1224 DIR *dir = opendir(VG_(libdir));
1225 struct dirent *de;
1226 int first = 1;
1227
1228 if (dir == NULL) {
1229 fprintf(stderr, "Can't open %s: %s (installation problem?)\n",
1230 VG_(libdir), strerror(errno));
1231 return;
1232 }
1233
1234 while((de = readdir(dir)) != NULL) {
1235 int len = strlen(de->d_name);
1236
1237 /* look for vgskin_TOOL.so names */
1238 if (len > (7+1+3) && /* "vgskin_" + at least 1-char toolname + ".so" */
1239 strncmp(de->d_name, "vgskin_", 7) == 0 &&
1240 VG_STREQ(de->d_name + len - 3, ".so")) {
1241 if (first) {
1242 printf("Available tools:\n");
1243 first = 0;
1244 }
1245 de->d_name[len-3] = '\0';
1246 printf("\t%s\n", de->d_name+7);
1247 }
1248 }
1249
1250 closedir(dir);
1251
1252 if (first)
1253 printf("No tools available in \"%s\" (installation problem?)\n",
1254 VG_(libdir));
1255}
1256
1257
1258/* Find and load a tool, and check it looks ok. Also looks to see if there's
1259 * a matching vgpreload_*.so file, and returns its name in *preloadpath. */
1260static void load_tool( const char *toolname, void** handle_out,
1261 ToolInfo** toolinfo_out, char **preloadpath_out )
1262{
1263 Bool ok;
1264 int len = strlen(VG_(libdir)) + strlen(toolname)*2 + 16;
1265 char buf[len];
1266 void* handle;
1267 ToolInfo* toolinfo;
1268 char* preloadpath = NULL;
1269 Int* vg_malloc_redzonep;
1270
1271 // XXX: allowing full paths for --tool option -- does it make sense?
1272 // Doesn't allow for vgpreload_<tool>.so.
1273
1274 if (strchr(toolname, '/') != 0) {
1275 /* toolname contains '/', and so must be a pathname */
1276 handle = dlopen(toolname, RTLD_NOW);
1277 } else {
1278 /* just try in the libdir */
1279 snprintf(buf, len, "%s/vgskin_%s.so", VG_(libdir), toolname);
1280 handle = dlopen(buf, RTLD_NOW);
1281
1282 if (handle != NULL) {
1283 snprintf(buf, len, "%s/vgpreload_%s.so", VG_(libdir), toolname);
1284 if (access(buf, R_OK) == 0) {
1285 preloadpath = strdup(buf);
1286 vg_assert(NULL != preloadpath);
1287 }
1288 }
1289 }
1290
1291 ok = (NULL != handle);
1292 if (!ok) {
1293 fprintf(stderr, "Can't open tool \"%s\": %s\n", toolname, dlerror());
1294 goto bad_load;
1295 }
1296
1297 toolinfo = dlsym(handle, "vgSkin_tool_info");
1298 ok = (NULL != toolinfo);
1299 if (!ok) {
1300 fprintf(stderr, "Tool \"%s\" doesn't define SK_(tool_info) - "
1301 "add VG_DETERMINE_INTERFACE_VERSION?\n", toolname);
1302 goto bad_load;
1303 }
1304
1305 ok = (toolinfo->sizeof_ToolInfo == sizeof(*toolinfo) &&
1306 toolinfo->interface_major_version == VG_CORE_INTERFACE_MAJOR_VERSION &&
1307 toolinfo->sk_pre_clo_init != NULL);
1308 if (!ok) {
1309 fprintf(stderr, "Error:\n"
1310 " Tool and core interface versions do not match.\n"
1311 " Interface version used by core is: %d.%d (size %d)\n"
1312 " Interface version used by tool is: %d.%d (size %d)\n"
1313 " The major version numbers must match.\n",
1314 VG_CORE_INTERFACE_MAJOR_VERSION,
1315 VG_CORE_INTERFACE_MINOR_VERSION,
1316 sizeof(*toolinfo),
1317 toolinfo->interface_major_version,
1318 toolinfo->interface_minor_version,
1319 toolinfo->sizeof_ToolInfo);
1320 fprintf(stderr, " You need to at least recompile, and possibly update,\n");
1321 if (VG_CORE_INTERFACE_MAJOR_VERSION > toolinfo->interface_major_version)
1322 fprintf(stderr, " your skin to work with this version of Valgrind.\n");
1323 else
1324 fprintf(stderr, " your version of Valgrind to work with this skin.\n");
1325 goto bad_load;
1326 }
1327
1328 // Set redzone size for V's allocator
1329 vg_malloc_redzonep = dlsym(handle, STR(VG_(vg_malloc_redzone_szB)));
1330 if ( NULL != vg_malloc_redzonep ) {
1331 VG_(vg_malloc_redzone_szB) = *vg_malloc_redzonep;
1332 }
1333
1334 vg_assert(NULL != handle && NULL != toolinfo);
1335 *handle_out = handle;
1336 *toolinfo_out = toolinfo;
1337 *preloadpath_out = preloadpath;
1338 return;
1339
1340
1341 bad_load:
1342 if (handle != NULL)
1343 dlclose(handle);
1344
1345 fprintf(stderr, "Aborting: couldn't load tool\n");
1346 list_tools();
1347 exit(127);
1348}
1349
1350/*====================================================================*/
1351/*=== Loading the client ===*/
1352/*====================================================================*/
1353
1354static void load_client(char* cl_argv[], const char* exec,
nethercote6c999f22004-01-31 22:55:15 +00001355 /*inout*/Int* need_help,
nethercote71980f02004-01-24 18:18:54 +00001356 /*out*/struct exeinfo* info, /*out*/Addr* client_eip)
1357{
1358 // If they didn't specify an executable with --exec, and didn't specify
1359 // --help, then use client argv[0] (searching $PATH if necessary).
1360 if (NULL == exec && !*need_help) {
1361 if (cl_argv[0] == NULL ||
1362 ( NULL == (exec = find_executable(cl_argv[0])) ) )
1363 {
nethercote6c999f22004-01-31 22:55:15 +00001364 *need_help = 1;
nethercote71980f02004-01-24 18:18:54 +00001365 }
1366 }
1367
1368 info->map_base = VG_(client_mapbase);
nethercote71980f02004-01-24 18:18:54 +00001369
1370 info->exe_base = VG_(client_base);
1371 info->exe_end = VG_(client_end);
1372 info->argv = cl_argv;
1373
1374 if (*need_help) {
1375 VG_(clexecfd) = -1;
1376 info->argv0 = NULL;
1377 info->argv1 = NULL;
1378 } else {
1379 Int ret;
1380 VG_(clexecfd) = VG_(open)(exec, O_RDONLY, VKI_S_IRUSR);
1381 ret = do_exec(exec, info);
1382 if (ret != 0) {
1383 fprintf(stderr, "do_exec(%s) failed: %s\n", exec, strerror(ret));
1384 exit(127);
1385 }
1386 }
1387
1388 /* Copy necessary bits of 'info' that were filled in */
1389 *client_eip = info->init_eip;
1390 VG_(brk_base) = VG_(brk_limit) = info->brkbase;
1391}
1392
1393
1394/*====================================================================*/
1395/*=== Command-line: variables, processing ===*/
1396/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +00001397
njn25e49d8e72002-09-23 09:36:25 +00001398/* Define, and set defaults. */
1399Bool VG_(clo_error_limit) = True;
nethercote04d0fbc2004-01-26 16:48:06 +00001400Bool VG_(clo_db_attach) = False;
1401Char* VG_(clo_db_command) = VG_CLO_DEFAULT_DBCOMMAND;
njn43c799e2003-04-08 00:08:52 +00001402Bool VG_(clo_gen_suppressions) = False;
njn25e49d8e72002-09-23 09:36:25 +00001403Int VG_(sanity_level) = 1;
1404Int VG_(clo_verbosity) = 1;
1405Bool VG_(clo_demangle) = True;
njn25e49d8e72002-09-23 09:36:25 +00001406Bool VG_(clo_trace_children) = False;
sewardj4cf05692002-10-27 20:28:29 +00001407
nethercotee1730692003-11-20 10:38:07 +00001408/* See big comment in vg_include.h for meaning of these three.
1409 fd is initially stdout, for --help, but gets moved to stderr by default
1410 immediately afterwards. */
sewardj4cf05692002-10-27 20:28:29 +00001411VgLogTo VG_(clo_log_to) = VgLogTo_Fd;
nethercotee1730692003-11-20 10:38:07 +00001412Int VG_(clo_logfile_fd) = 1;
sewardj4cf05692002-10-27 20:28:29 +00001413Char* VG_(clo_logfile_name) = NULL;
1414
sewardj6024b212003-07-13 10:54:33 +00001415Int VG_(clo_input_fd) = 0; /* stdin */
njn25e49d8e72002-09-23 09:36:25 +00001416Int VG_(clo_n_suppressions) = 0;
sewardjde4a1d02002-03-22 01:27:54 +00001417Char* VG_(clo_suppressions)[VG_CLO_MAX_SFILES];
njn25e49d8e72002-09-23 09:36:25 +00001418Bool VG_(clo_profile) = False;
1419Bool VG_(clo_single_step) = False;
1420Bool VG_(clo_optimise) = True;
1421UChar VG_(clo_trace_codegen) = 0; // 00000000b
1422Bool VG_(clo_trace_syscalls) = False;
1423Bool VG_(clo_trace_signals) = False;
1424Bool VG_(clo_trace_symtab) = False;
njn25e49d8e72002-09-23 09:36:25 +00001425Bool VG_(clo_trace_sched) = False;
1426Int VG_(clo_trace_pthread_level) = 0;
njn25e49d8e72002-09-23 09:36:25 +00001427Int VG_(clo_dump_error) = 0;
1428Int VG_(clo_backtrace_size) = 4;
1429Char* VG_(clo_weird_hacks) = NULL;
sewardj858964b2002-10-05 14:15:43 +00001430Bool VG_(clo_run_libc_freeres) = True;
rjwalshf5f536f2003-11-17 17:45:00 +00001431Bool VG_(clo_track_fds) = False;
sewardj22854b92002-11-30 14:00:47 +00001432Bool VG_(clo_chain_bb) = True;
nethercote77eba602003-11-13 17:35:04 +00001433Bool VG_(clo_show_below_main) = False;
fitzhardinge98abfc72003-12-16 02:05:15 +00001434Bool VG_(clo_pointercheck) = True;
fitzhardinge462f4f92003-12-18 02:10:54 +00001435Bool VG_(clo_branchpred) = False;
sewardj2370f3b2002-11-30 15:01:01 +00001436
jsgf855d93d2003-10-13 22:26:55 +00001437static Bool VG_(clo_wait_for_gdb) = False;
1438
1439/* If we're doing signal routing, poll for signals every 50mS by
1440 default. */
1441Int VG_(clo_signal_polltime) = 50;
1442
1443/* These flags reduce thread wakeup latency on syscall completion and
1444 signal delivery, respectively. The downside is possible unfairness. */
1445Bool VG_(clo_lowlat_syscalls) = False; /* low-latency syscalls */
1446Bool VG_(clo_lowlat_signals) = False; /* low-latency signals */
1447
sewardjde4a1d02002-03-22 01:27:54 +00001448
njn25e49d8e72002-09-23 09:36:25 +00001449void VG_(bad_option) ( Char* opt )
sewardjde4a1d02002-03-22 01:27:54 +00001450{
1451 VG_(shutdown_logging)();
sewardj4cf05692002-10-27 20:28:29 +00001452 VG_(clo_log_to) = VgLogTo_Fd;
sewardjde4a1d02002-03-22 01:27:54 +00001453 VG_(clo_logfile_fd) = 2; /* stderr */
1454 VG_(printf)("valgrind.so: Bad option `%s'; aborting.\n", opt);
1455 VG_(exit)(1);
1456}
1457
1458static void config_error ( Char* msg )
1459{
1460 VG_(shutdown_logging)();
sewardj4cf05692002-10-27 20:28:29 +00001461 VG_(clo_log_to) = VgLogTo_Fd;
sewardjde4a1d02002-03-22 01:27:54 +00001462 VG_(clo_logfile_fd) = 2; /* stderr */
sewardj19d81412002-06-03 01:10:40 +00001463 VG_(printf)(
fitzhardinge98abfc72003-12-16 02:05:15 +00001464 "valgrind: Startup or configuration error:\n %s\n", msg);
sewardj19d81412002-06-03 01:10:40 +00001465 VG_(printf)(
fitzhardinge98abfc72003-12-16 02:05:15 +00001466 "valgrind: Unable to start up properly. Giving up.\n");
sewardjde4a1d02002-03-22 01:27:54 +00001467 VG_(exit)(1);
1468}
1469
nethercote6c999f22004-01-31 22:55:15 +00001470void usage ( Bool debug_help )
njn7cf0bd32002-06-08 13:36:03 +00001471{
njn25e49d8e72002-09-23 09:36:25 +00001472 Char* usage1 =
nethercote71980f02004-01-24 18:18:54 +00001473"usage: valgrind --tool=<toolname> [options] prog-and-args\n"
njn25e49d8e72002-09-23 09:36:25 +00001474"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001475" common user options for all Valgrind tools, with defaults in [ ]:\n"
nethercote71980f02004-01-24 18:18:54 +00001476" --tool=<name> Use the Valgrind tool named <name>\n"
njn25e49d8e72002-09-23 09:36:25 +00001477" --help show this message\n"
nethercote6c999f22004-01-31 22:55:15 +00001478" --help-debug show this message, plus debugging options\n"
njn25e49d8e72002-09-23 09:36:25 +00001479" --version show version\n"
njn25e49d8e72002-09-23 09:36:25 +00001480" -q --quiet run silently; only print error msgs\n"
1481" -v --verbose be more verbose, incl counts of errors\n"
nethercote77eba602003-11-13 17:35:04 +00001482" --trace-children=no|yes Valgrind-ise child processes? [no]\n"
rjwalshf5f536f2003-11-17 17:45:00 +00001483" --track-fds=no|yes Track open file descriptors? [no]\n"
nethercote2b0793f2003-12-02 10:41:18 +00001484"\n"
1485" uncommon user options for all Valgrind tools:\n"
nethercote77eba602003-11-13 17:35:04 +00001486" --run-libc-freeres=no|yes Free up glibc memory at exit? [yes]\n"
1487" --weird-hacks=hack1,hack2,... [none]\n"
sewardj3d652a32002-10-20 18:11:49 +00001488" recognised hacks are: ioctl-VTIME truncate-writes lax-ioctls\n"
jsgf855d93d2003-10-13 22:26:55 +00001489" --signal-polltime=<time> time, in mS, we should poll for signals.\n"
1490" Only applies for older kernels which need\n"
1491" signal routing [50]\n"
1492" --lowlat-signals=no|yes improve wake-up latency when a thread receives\n"
1493" a signal [no]\n"
1494" --lowlat-syscalls=no|yes improve wake-up latency when a thread's\n"
1495" syscall completes [no]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001496" --pointercheck=no|yes enforce client address space limits [yes]\n"
njn25e49d8e72002-09-23 09:36:25 +00001497"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001498" user options for Valgrind tools that report errors:\n"
1499" --logfile-fd=<number> file descriptor for messages [2=stderr]\n"
1500" --logfile=<file> log messages to <file>.pid<pid>\n"
1501" --logsocket=ipaddr:port log messages to socket ipaddr:port\n"
1502" --demangle=no|yes automatically demangle C++ names? [yes]\n"
1503" --num-callers=<number> show <num> callers in stack traces [4]\n"
1504" --error-limit=no|yes stop showing new errors if too many? [yes]\n"
1505" --show-below-main=no|yes continue stack traces below main() [no]\n"
1506" --suppressions=<filename> suppress errors described in <filename>\n"
1507" --gen-suppressions=no|yes print suppressions for errors detected [no]\n"
njn7cf0bd32002-06-08 13:36:03 +00001508
nethercote04d0fbc2004-01-26 16:48:06 +00001509" --db-attach=no|yes start debugger when errors detected? [no]\n"
1510" --db-command=<command> command to start debugger [gdb -nw %%f %%p]\n"
1511" --input-fd=<number> file descriptor for input [0=stdin]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001512"\n";
njn7cf0bd32002-06-08 13:36:03 +00001513
njn25e49d8e72002-09-23 09:36:25 +00001514 Char* usage2 =
1515"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001516" debugging options for all Valgrind tools:\n"
njn25e49d8e72002-09-23 09:36:25 +00001517" --sanity-level=<number> level of sanity checking to do [1]\n"
1518" --single-step=no|yes translate each instr separately? [no]\n"
1519" --optimise=no|yes improve intermediate code? [yes]\n"
nethercote137bc552003-11-14 17:47:54 +00001520" --profile=no|yes profile? (tool must be built for it) [no]\n"
sewardj22854b92002-11-30 14:00:47 +00001521" --chain-bb=no|yes do basic-block chaining? [yes]\n"
fitzhardinge462f4f92003-12-18 02:10:54 +00001522" --branchpred=yes|no generate branch prediction hints [no]\n"
njn25e49d8e72002-09-23 09:36:25 +00001523" --trace-codegen=<XXXXX> show generated code? (X = 0|1) [00000]\n"
1524" --trace-syscalls=no|yes show all system calls? [no]\n"
1525" --trace-signals=no|yes show signal handling details? [no]\n"
1526" --trace-symtab=no|yes show symbol table details? [no]\n"
njn25e49d8e72002-09-23 09:36:25 +00001527" --trace-sched=no|yes show thread scheduler details? [no]\n"
njn3e884182003-04-15 13:03:23 +00001528" --trace-pthread=none|some|all show pthread event details? [none]\n"
jsgf855d93d2003-10-13 22:26:55 +00001529" --wait-for-gdb=yes|no pause on startup to wait for gdb attach\n"
njn25e49d8e72002-09-23 09:36:25 +00001530"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001531" debugging options for Valgrind tools that report errors\n"
1532" --dump-error=<number> show translation for basic block associated\n"
1533" with <number>'th error context [0=show none]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001534"\n";
njn3e884182003-04-15 13:03:23 +00001535
1536 Char* usage3 =
1537"\n"
nethercote71980f02004-01-24 18:18:54 +00001538" Extra options read from ~/.valgrindrc, $VALGRIND_OPTS, ./.valgrindrc\n"
njn25e49d8e72002-09-23 09:36:25 +00001539"\n"
nethercotebb1c9912004-01-04 16:43:23 +00001540" Valgrind is Copyright (C) 2000-2004 Julian Seward\n"
njn25e49d8e72002-09-23 09:36:25 +00001541" and licensed under the GNU General Public License, version 2.\n"
1542" Bug reports, feedback, admiration, abuse, etc, to: %s.\n"
njnd04b7c62002-10-03 14:05:52 +00001543"\n"
nethercote137bc552003-11-14 17:47:54 +00001544" Tools are copyright and licensed by their authors. See each\n"
1545" tool's start-up message for more information.\n"
njn25e49d8e72002-09-23 09:36:25 +00001546"\n";
njn7cf0bd32002-06-08 13:36:03 +00001547
fitzhardinge98abfc72003-12-16 02:05:15 +00001548 VG_(printf)(usage1);
1549 if (VG_(details).name) {
1550 VG_(printf)(" user options for %s:\n", VG_(details).name);
1551 /* Don't print skin string directly for security, ha! */
1552 if (VG_(needs).command_line_options)
1553 SK_(print_usage)();
1554 else
1555 VG_(printf)(" (none)\n");
1556 }
nethercote6c999f22004-01-31 22:55:15 +00001557 if (debug_help) {
1558 VG_(printf)(usage2);
fitzhardinge98abfc72003-12-16 02:05:15 +00001559
nethercote6c999f22004-01-31 22:55:15 +00001560 if (VG_(details).name) {
1561 VG_(printf)(" debugging options for %s:\n", VG_(details).name);
1562
1563 if (VG_(needs).command_line_options)
1564 SK_(print_debug_usage)();
1565 else
1566 VG_(printf)(" (none)\n");
1567 }
fitzhardinge98abfc72003-12-16 02:05:15 +00001568 }
nethercote421281e2003-11-20 16:20:55 +00001569 VG_(printf)(usage3, VG_BUGS_TO);
njn7cf0bd32002-06-08 13:36:03 +00001570
njn25e49d8e72002-09-23 09:36:25 +00001571 VG_(shutdown_logging)();
sewardj4cf05692002-10-27 20:28:29 +00001572 VG_(clo_log_to) = VgLogTo_Fd;
njn25e49d8e72002-09-23 09:36:25 +00001573 VG_(clo_logfile_fd) = 2; /* stderr */
1574 VG_(exit)(1);
njn7cf0bd32002-06-08 13:36:03 +00001575}
sewardjde4a1d02002-03-22 01:27:54 +00001576
nethercote71980f02004-01-24 18:18:54 +00001577static void pre_process_cmd_line_options
nethercote6c999f22004-01-31 22:55:15 +00001578 ( Int* need_help, const char** tool, const char** exec )
sewardj1c1b1162003-02-23 01:25:51 +00001579{
nethercote71980f02004-01-24 18:18:54 +00001580 UInt i;
sewardjde4a1d02002-03-22 01:27:54 +00001581
nethercote71980f02004-01-24 18:18:54 +00001582 /* parse the options we have (only the options we care about now) */
1583 for (i = 1; i < VG_(vg_argc); i++) {
1584
1585 if (strcmp(VG_(vg_argv)[i], "--version") == 0) {
1586 printf("valgrind-" VERSION "\n");
1587 exit(1);
1588
1589 } else if (strcmp(VG_(vg_argv)[i], "--help") == 0) {
nethercote6c999f22004-01-31 22:55:15 +00001590 *need_help = 1;
1591
1592 } else if (strcmp(VG_(vg_argv)[i], "--help-debug") == 0) {
1593 *need_help = 2;
nethercote71980f02004-01-24 18:18:54 +00001594
1595 } else if (strncmp(VG_(vg_argv)[i], "--tool=", 7) == 0 ||
1596 strncmp(VG_(vg_argv)[i], "--skin=", 7) == 0) {
1597 *tool = &VG_(vg_argv)[i][7];
1598
1599 } else if (strncmp(VG_(vg_argv)[i], "--exec=", 7) == 0) {
1600 *exec = &VG_(vg_argv)[i][7];
1601 }
1602 }
1603
1604 /* If no tool specified, can give usage message without loading tool */
1605 if (*tool == NULL) {
1606 if (!need_help)
1607 list_tools();
nethercote6c999f22004-01-31 22:55:15 +00001608 usage(/*help-debug?*/False);
nethercote71980f02004-01-24 18:18:54 +00001609 }
1610}
1611
1612static void process_cmd_line_options
1613 ( UInt* client_auxv, Addr esp_at_startup,
nethercote6c999f22004-01-31 22:55:15 +00001614 const char* toolname, Int need_help )
nethercote71980f02004-01-24 18:18:54 +00001615{
1616 Int i, eventually_logfile_fd;
1617 Int *auxp;
1618 Int toolname_len = VG_(strlen)(toolname);
sewardjde4a1d02002-03-22 01:27:54 +00001619
nethercotee1730692003-11-20 10:38:07 +00001620 /* log to stderr by default, but usage message goes to stdout */
1621 eventually_logfile_fd = 2;
sewardjde4a1d02002-03-22 01:27:54 +00001622
1623 /* Once logging is started, we can safely send messages pertaining
1624 to failures in initialisation. */
1625 VG_(startup_logging)();
1626
sewardj19d81412002-06-03 01:10:40 +00001627 /* Check for sane path in ./configure --prefix=... */
fitzhardinge98abfc72003-12-16 02:05:15 +00001628 if (VG_LIBDIR[0] != '/')
sewardj19d81412002-06-03 01:10:40 +00001629 config_error("Please use absolute paths in "
1630 "./configure --prefix=... or --libdir=...");
sewardj38170912002-05-10 21:07:22 +00001631
nethercote71980f02004-01-24 18:18:54 +00001632 for (auxp = client_auxv; auxp[0] != VKI_AT_NULL; auxp += 2) {
fitzhardinge98abfc72003-12-16 02:05:15 +00001633 switch(auxp[0]) {
1634 case VKI_AT_SYSINFO:
1635 VG_(sysinfo_page_exists) = True;
fitzhardinge92360792003-12-24 10:11:11 +00001636 auxp[1] = (Int)(VG_(client_trampoline_code) + VG_(tramp_syscall_offset));
fitzhardinge98abfc72003-12-16 02:05:15 +00001637 VG_(sysinfo_page_addr) = auxp[1];
1638 break;
sewardjde4a1d02002-03-22 01:27:54 +00001639 }
fitzhardinge98abfc72003-12-16 02:05:15 +00001640 }
sewardjde4a1d02002-03-22 01:27:54 +00001641
nethercote71980f02004-01-24 18:18:54 +00001642 if (need_help)
nethercote6c999f22004-01-31 22:55:15 +00001643 usage(/*--help-debug?*/need_help == 2);
fitzhardinge98abfc72003-12-16 02:05:15 +00001644
1645 /* We know the initial ESP is pointing at argc/argv */
nethercote71980f02004-01-24 18:18:54 +00001646 VG_(client_argc) = *(Int *)esp_at_startup;
1647 VG_(client_argv) = (Char **)(esp_at_startup + sizeof(Int));
fitzhardinge98abfc72003-12-16 02:05:15 +00001648
nethercote71980f02004-01-24 18:18:54 +00001649 for (i = 1; i < VG_(vg_argc); i++) {
1650
1651 Char* arg = VG_(vg_argv)[i];
1652
1653 // XXX: allow colons in options, for Josef
1654
1655 /* Look for matching "--toolname:foo" */
1656 if (VG_(strstr)(arg, ":")) {
1657 if (VG_CLO_STREQN(2, arg, "--") &&
1658 VG_CLO_STREQN(toolname_len, arg+2, toolname) &&
1659 VG_CLO_STREQN(1, arg+2+toolname_len, ":"))
1660 {
1661 // prefix matches, convert "--toolname:foo" to "--foo"
1662 if (0)
1663 VG_(printf)("tool-specific arg: %s\n", arg);
1664 arg += toolname_len + 1;
1665 arg[0] = '-';
1666 arg[1] = '-';
1667
1668 } else {
1669 // prefix doesn't match, skip to next arg
1670 continue;
1671 }
1672 }
1673
fitzhardinge98abfc72003-12-16 02:05:15 +00001674 /* Ignore these options - they've already been handled */
nethercote71980f02004-01-24 18:18:54 +00001675 if (VG_CLO_STREQN(7, arg, "--tool=") ||
1676 VG_CLO_STREQN(7, arg, "--skin="))
fitzhardinge98abfc72003-12-16 02:05:15 +00001677 continue;
nethercote71980f02004-01-24 18:18:54 +00001678 if (VG_CLO_STREQN(7, arg, "--exec="))
fitzhardinge98abfc72003-12-16 02:05:15 +00001679 continue;
1680
nethercote71980f02004-01-24 18:18:54 +00001681 if ( VG_CLO_STREQ(arg, "--"))
fitzhardinge98abfc72003-12-16 02:05:15 +00001682 continue;
nethercote71980f02004-01-24 18:18:54 +00001683 else if (VG_CLO_STREQ(arg, "-v") ||
1684 VG_CLO_STREQ(arg, "--verbose"))
sewardjde4a1d02002-03-22 01:27:54 +00001685 VG_(clo_verbosity)++;
nethercote71980f02004-01-24 18:18:54 +00001686 else if (VG_CLO_STREQ(arg, "-q") ||
1687 VG_CLO_STREQ(arg, "--quiet"))
sewardjde4a1d02002-03-22 01:27:54 +00001688 VG_(clo_verbosity)--;
1689
nethercote71980f02004-01-24 18:18:54 +00001690 else if (VG_CLO_STREQ(arg, "--error-limit=yes"))
sewardj2e432902002-06-13 20:44:00 +00001691 VG_(clo_error_limit) = True;
nethercote71980f02004-01-24 18:18:54 +00001692 else if (VG_CLO_STREQ(arg, "--error-limit=no"))
sewardj2e432902002-06-13 20:44:00 +00001693 VG_(clo_error_limit) = False;
sewardj72f98ff2002-06-13 17:23:38 +00001694
nethercote04d0fbc2004-01-26 16:48:06 +00001695 else if (VG_CLO_STREQ(arg, "--db-attach=yes"))
1696 VG_(clo_db_attach) = True;
1697 else if (VG_CLO_STREQ(arg, "--db-attach=no"))
1698 VG_(clo_db_attach) = False;
sewardjde4a1d02002-03-22 01:27:54 +00001699
nethercote04d0fbc2004-01-26 16:48:06 +00001700 else if (VG_CLO_STREQN(13,arg, "--db-command="))
1701 VG_(clo_db_command) = &arg[13];
sewardj6024b212003-07-13 10:54:33 +00001702
nethercote71980f02004-01-24 18:18:54 +00001703 else if (VG_CLO_STREQ(arg, "--gen-suppressions=yes"))
njn43c799e2003-04-08 00:08:52 +00001704 VG_(clo_gen_suppressions) = True;
nethercote71980f02004-01-24 18:18:54 +00001705 else if (VG_CLO_STREQ(arg, "--gen-suppressions=no"))
njn43c799e2003-04-08 00:08:52 +00001706 VG_(clo_gen_suppressions) = False;
1707
nethercote71980f02004-01-24 18:18:54 +00001708 else if (VG_CLO_STREQ(arg, "--show-below-main=yes"))
nethercote77eba602003-11-13 17:35:04 +00001709 VG_(clo_show_below_main) = True;
nethercote71980f02004-01-24 18:18:54 +00001710 else if (VG_CLO_STREQ(arg, "--show-below-main=no"))
nethercote77eba602003-11-13 17:35:04 +00001711 VG_(clo_show_below_main) = False;
1712
nethercote71980f02004-01-24 18:18:54 +00001713 else if (VG_CLO_STREQ(arg, "--pointercheck=yes"))
fitzhardinge98abfc72003-12-16 02:05:15 +00001714 VG_(clo_pointercheck) = True;
nethercote71980f02004-01-24 18:18:54 +00001715 else if (VG_CLO_STREQ(arg, "--pointercheck=no"))
fitzhardinge98abfc72003-12-16 02:05:15 +00001716 VG_(clo_pointercheck) = False;
1717
nethercote71980f02004-01-24 18:18:54 +00001718 else if (VG_CLO_STREQ(arg, "--demangle=yes"))
sewardjde4a1d02002-03-22 01:27:54 +00001719 VG_(clo_demangle) = True;
nethercote71980f02004-01-24 18:18:54 +00001720 else if (VG_CLO_STREQ(arg, "--demangle=no"))
sewardjde4a1d02002-03-22 01:27:54 +00001721 VG_(clo_demangle) = False;
1722
nethercote71980f02004-01-24 18:18:54 +00001723 else if (VG_CLO_STREQ(arg, "--trace-children=yes"))
sewardjde4a1d02002-03-22 01:27:54 +00001724 VG_(clo_trace_children) = True;
nethercote71980f02004-01-24 18:18:54 +00001725 else if (VG_CLO_STREQ(arg, "--trace-children=no"))
sewardjde4a1d02002-03-22 01:27:54 +00001726 VG_(clo_trace_children) = False;
1727
nethercote71980f02004-01-24 18:18:54 +00001728 else if (VG_CLO_STREQ(arg, "--run-libc-freeres=yes"))
sewardj858964b2002-10-05 14:15:43 +00001729 VG_(clo_run_libc_freeres) = True;
nethercote71980f02004-01-24 18:18:54 +00001730 else if (VG_CLO_STREQ(arg, "--run-libc-freeres=no"))
sewardj858964b2002-10-05 14:15:43 +00001731 VG_(clo_run_libc_freeres) = False;
1732
nethercote71980f02004-01-24 18:18:54 +00001733 else if (VG_CLO_STREQ(arg, "--track-fds=yes"))
rjwalshf5f536f2003-11-17 17:45:00 +00001734 VG_(clo_track_fds) = True;
nethercote71980f02004-01-24 18:18:54 +00001735 else if (VG_CLO_STREQ(arg, "--track-fds=no"))
rjwalshf5f536f2003-11-17 17:45:00 +00001736 VG_(clo_track_fds) = False;
1737
nethercote71980f02004-01-24 18:18:54 +00001738 else if (VG_CLO_STREQN(15, arg, "--sanity-level="))
1739 VG_(sanity_level) = (Int)VG_(atoll)(&arg[15]);
sewardjde4a1d02002-03-22 01:27:54 +00001740
nethercote71980f02004-01-24 18:18:54 +00001741 else if (VG_CLO_STREQN(13, arg, "--logfile-fd=")) {
sewardj4cf05692002-10-27 20:28:29 +00001742 VG_(clo_log_to) = VgLogTo_Fd;
1743 VG_(clo_logfile_name) = NULL;
nethercote71980f02004-01-24 18:18:54 +00001744 eventually_logfile_fd = (Int)VG_(atoll)(&arg[13]);
sewardj4cf05692002-10-27 20:28:29 +00001745 }
1746
nethercote71980f02004-01-24 18:18:54 +00001747 else if (VG_CLO_STREQN(10, arg, "--logfile=")) {
sewardj4cf05692002-10-27 20:28:29 +00001748 VG_(clo_log_to) = VgLogTo_File;
nethercote71980f02004-01-24 18:18:54 +00001749 VG_(clo_logfile_name) = &arg[10];
sewardj4cf05692002-10-27 20:28:29 +00001750 }
sewardjde4a1d02002-03-22 01:27:54 +00001751
nethercote71980f02004-01-24 18:18:54 +00001752 else if (VG_CLO_STREQN(12, arg, "--logsocket=")) {
sewardj73cf3bc2002-11-03 03:20:15 +00001753 VG_(clo_log_to) = VgLogTo_Socket;
nethercote71980f02004-01-24 18:18:54 +00001754 VG_(clo_logfile_name) = &arg[12];
sewardj73cf3bc2002-11-03 03:20:15 +00001755 }
1756
nethercote71980f02004-01-24 18:18:54 +00001757 else if (VG_CLO_STREQN(11, arg, "--input-fd="))
1758 VG_(clo_input_fd) = (Int)VG_(atoll)(&arg[11]);
sewardj6024b212003-07-13 10:54:33 +00001759
nethercote71980f02004-01-24 18:18:54 +00001760 else if (VG_CLO_STREQN(15, arg, "--suppressions=")) {
sewardjde4a1d02002-03-22 01:27:54 +00001761 if (VG_(clo_n_suppressions) >= VG_CLO_MAX_SFILES) {
njn25e49d8e72002-09-23 09:36:25 +00001762 VG_(message)(Vg_UserMsg, "Too many suppression files specified.");
sewardjde4a1d02002-03-22 01:27:54 +00001763 VG_(message)(Vg_UserMsg,
1764 "Increase VG_CLO_MAX_SFILES and recompile.");
nethercote71980f02004-01-24 18:18:54 +00001765 VG_(bad_option)(arg);
sewardjde4a1d02002-03-22 01:27:54 +00001766 }
nethercote71980f02004-01-24 18:18:54 +00001767 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = &arg[15];
sewardjde4a1d02002-03-22 01:27:54 +00001768 VG_(clo_n_suppressions)++;
1769 }
nethercote71980f02004-01-24 18:18:54 +00001770 else if (VG_CLO_STREQ(arg, "--profile=yes"))
njn25e49d8e72002-09-23 09:36:25 +00001771 VG_(clo_profile) = True;
nethercote71980f02004-01-24 18:18:54 +00001772 else if (VG_CLO_STREQ(arg, "--profile=no"))
njn25e49d8e72002-09-23 09:36:25 +00001773 VG_(clo_profile) = False;
1774
nethercote71980f02004-01-24 18:18:54 +00001775 else if (VG_CLO_STREQ(arg, "--chain-bb=yes"))
sewardj22854b92002-11-30 14:00:47 +00001776 VG_(clo_chain_bb) = True;
nethercote71980f02004-01-24 18:18:54 +00001777 else if (VG_CLO_STREQ(arg, "--chain-bb=no"))
sewardj22854b92002-11-30 14:00:47 +00001778 VG_(clo_chain_bb) = False;
1779
nethercote71980f02004-01-24 18:18:54 +00001780 else if (VG_CLO_STREQ(arg, "--branchpred=yes"))
fitzhardinge462f4f92003-12-18 02:10:54 +00001781 VG_(clo_branchpred) = True;
nethercote71980f02004-01-24 18:18:54 +00001782 else if (VG_CLO_STREQ(arg, "--branchpred=no"))
fitzhardinge462f4f92003-12-18 02:10:54 +00001783 VG_(clo_branchpred) = False;
1784
nethercote71980f02004-01-24 18:18:54 +00001785 else if (VG_CLO_STREQ(arg, "--single-step=yes"))
sewardjde4a1d02002-03-22 01:27:54 +00001786 VG_(clo_single_step) = True;
nethercote71980f02004-01-24 18:18:54 +00001787 else if (VG_CLO_STREQ(arg, "--single-step=no"))
sewardjde4a1d02002-03-22 01:27:54 +00001788 VG_(clo_single_step) = False;
1789
nethercote71980f02004-01-24 18:18:54 +00001790 else if (VG_CLO_STREQ(arg, "--optimise=yes"))
sewardjde4a1d02002-03-22 01:27:54 +00001791 VG_(clo_optimise) = True;
nethercote71980f02004-01-24 18:18:54 +00001792 else if (VG_CLO_STREQ(arg, "--optimise=no"))
sewardjde4a1d02002-03-22 01:27:54 +00001793 VG_(clo_optimise) = False;
1794
njn25e49d8e72002-09-23 09:36:25 +00001795 /* "vwxyz" --> 000zyxwv (binary) */
nethercote71980f02004-01-24 18:18:54 +00001796 else if (VG_CLO_STREQN(16, arg, "--trace-codegen=")) {
njn25e49d8e72002-09-23 09:36:25 +00001797 Int j;
nethercote71980f02004-01-24 18:18:54 +00001798 char* opt = & arg[16];
njn25e49d8e72002-09-23 09:36:25 +00001799
1800 if (5 != VG_(strlen)(opt)) {
1801 VG_(message)(Vg_UserMsg,
1802 "--trace-codegen argument must have 5 digits");
nethercote71980f02004-01-24 18:18:54 +00001803 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001804 }
1805 for (j = 0; j < 5; j++) {
1806 if ('0' == opt[j]) { /* do nothing */ }
1807 else if ('1' == opt[j]) VG_(clo_trace_codegen) |= (1 << j);
1808 else {
1809 VG_(message)(Vg_UserMsg, "--trace-codegen argument can only "
1810 "contain 0s and 1s");
nethercote71980f02004-01-24 18:18:54 +00001811 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001812 }
1813 }
1814 }
sewardjde4a1d02002-03-22 01:27:54 +00001815
nethercote71980f02004-01-24 18:18:54 +00001816 else if (VG_CLO_STREQ(arg, "--trace-syscalls=yes"))
sewardjde4a1d02002-03-22 01:27:54 +00001817 VG_(clo_trace_syscalls) = True;
nethercote71980f02004-01-24 18:18:54 +00001818 else if (VG_CLO_STREQ(arg, "--trace-syscalls=no"))
sewardjde4a1d02002-03-22 01:27:54 +00001819 VG_(clo_trace_syscalls) = False;
1820
nethercote71980f02004-01-24 18:18:54 +00001821 else if (VG_CLO_STREQ(arg, "--trace-signals=yes"))
sewardjde4a1d02002-03-22 01:27:54 +00001822 VG_(clo_trace_signals) = True;
nethercote71980f02004-01-24 18:18:54 +00001823 else if (VG_CLO_STREQ(arg, "--trace-signals=no"))
sewardjde4a1d02002-03-22 01:27:54 +00001824 VG_(clo_trace_signals) = False;
1825
nethercote71980f02004-01-24 18:18:54 +00001826 else if (VG_CLO_STREQ(arg, "--trace-symtab=yes"))
sewardjde4a1d02002-03-22 01:27:54 +00001827 VG_(clo_trace_symtab) = True;
nethercote71980f02004-01-24 18:18:54 +00001828 else if (VG_CLO_STREQ(arg, "--trace-symtab=no"))
sewardjde4a1d02002-03-22 01:27:54 +00001829 VG_(clo_trace_symtab) = False;
1830
nethercote71980f02004-01-24 18:18:54 +00001831 else if (VG_CLO_STREQ(arg, "--trace-sched=yes"))
sewardj8937c812002-04-12 20:12:20 +00001832 VG_(clo_trace_sched) = True;
nethercote71980f02004-01-24 18:18:54 +00001833 else if (VG_CLO_STREQ(arg, "--trace-sched=no"))
sewardj8937c812002-04-12 20:12:20 +00001834 VG_(clo_trace_sched) = False;
1835
nethercote71980f02004-01-24 18:18:54 +00001836 else if (VG_CLO_STREQ(arg, "--trace-pthread=none"))
sewardj45b4b372002-04-16 22:50:32 +00001837 VG_(clo_trace_pthread_level) = 0;
nethercote71980f02004-01-24 18:18:54 +00001838 else if (VG_CLO_STREQ(arg, "--trace-pthread=some"))
sewardj45b4b372002-04-16 22:50:32 +00001839 VG_(clo_trace_pthread_level) = 1;
nethercote71980f02004-01-24 18:18:54 +00001840 else if (VG_CLO_STREQ(arg, "--trace-pthread=all"))
sewardj45b4b372002-04-16 22:50:32 +00001841 VG_(clo_trace_pthread_level) = 2;
sewardj8937c812002-04-12 20:12:20 +00001842
nethercote71980f02004-01-24 18:18:54 +00001843 else if (VG_CLO_STREQN(14, arg, "--weird-hacks="))
1844 VG_(clo_weird_hacks) = &arg[14];
sewardj3984b852002-05-12 03:00:17 +00001845
nethercote71980f02004-01-24 18:18:54 +00001846 else if (VG_CLO_STREQN(17, arg, "--signal-polltime="))
1847 VG_(clo_signal_polltime) = VG_(atoll)(&arg[17]);
jsgf855d93d2003-10-13 22:26:55 +00001848
nethercote71980f02004-01-24 18:18:54 +00001849 else if (VG_CLO_STREQ(arg, "--lowlat-signals=yes"))
jsgf855d93d2003-10-13 22:26:55 +00001850 VG_(clo_lowlat_signals) = True;
nethercote71980f02004-01-24 18:18:54 +00001851 else if (VG_CLO_STREQ(arg, "--lowlat-signals=no"))
jsgf855d93d2003-10-13 22:26:55 +00001852 VG_(clo_lowlat_signals) = False;
1853
nethercote71980f02004-01-24 18:18:54 +00001854 else if (VG_CLO_STREQ(arg, "--lowlat-syscalls=yes"))
jsgf855d93d2003-10-13 22:26:55 +00001855 VG_(clo_lowlat_syscalls) = True;
nethercote71980f02004-01-24 18:18:54 +00001856 else if (VG_CLO_STREQ(arg, "--lowlat-syscalls=no"))
jsgf855d93d2003-10-13 22:26:55 +00001857 VG_(clo_lowlat_syscalls) = False;
1858
nethercote71980f02004-01-24 18:18:54 +00001859 else if (VG_CLO_STREQN(13, arg, "--dump-error="))
1860 VG_(clo_dump_error) = (Int)VG_(atoll)(&arg[13]);
sewardjde4a1d02002-03-22 01:27:54 +00001861
nethercote71980f02004-01-24 18:18:54 +00001862 else if (VG_CLO_STREQ(arg, "--wait-for-gdb=yes"))
jsgf855d93d2003-10-13 22:26:55 +00001863 VG_(clo_wait_for_gdb) = True;
nethercote71980f02004-01-24 18:18:54 +00001864 else if (VG_CLO_STREQ(arg, "--wait-for-gdb=no"))
jsgf855d93d2003-10-13 22:26:55 +00001865 VG_(clo_wait_for_gdb) = False;
1866
nethercote71980f02004-01-24 18:18:54 +00001867 else if (VG_CLO_STREQN(14, arg, "--num-callers=")) {
sewardjde4a1d02002-03-22 01:27:54 +00001868 /* Make sure it's sane. */
nethercote71980f02004-01-24 18:18:54 +00001869 VG_(clo_backtrace_size) = (Int)VG_(atoll)(&arg[14]);
njn6c846552003-09-16 07:41:43 +00001870 if (VG_(clo_backtrace_size) < 1)
1871 VG_(clo_backtrace_size) = 1;
sewardjde4a1d02002-03-22 01:27:54 +00001872 if (VG_(clo_backtrace_size) >= VG_DEEPEST_BACKTRACE)
1873 VG_(clo_backtrace_size) = VG_DEEPEST_BACKTRACE;
1874 }
1875
nethercote71980f02004-01-24 18:18:54 +00001876 else if ( ! VG_(needs).command_line_options
1877 || ! SK_(process_cmd_line_option)(arg) ) {
nethercote6c999f22004-01-31 22:55:15 +00001878 usage(/*--help-debug?*/need_help == 2);
njn25e49d8e72002-09-23 09:36:25 +00001879 }
sewardjde4a1d02002-03-22 01:27:54 +00001880 }
1881
njnf9ebf672003-05-12 21:41:30 +00001882 if (VG_(clo_verbosity) < 0)
sewardjde4a1d02002-03-22 01:27:54 +00001883 VG_(clo_verbosity) = 0;
1884
nethercote04d0fbc2004-01-26 16:48:06 +00001885 if (VG_(clo_db_attach) && VG_(clo_trace_children)) {
sewardjde4a1d02002-03-22 01:27:54 +00001886 VG_(message)(Vg_UserMsg, "");
1887 VG_(message)(Vg_UserMsg,
nethercote04d0fbc2004-01-26 16:48:06 +00001888 "--db-attach=yes conflicts with --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001889 VG_(message)(Vg_UserMsg,
1890 "Please choose one or the other, but not both.");
nethercote04d0fbc2004-01-26 16:48:06 +00001891 VG_(bad_option)("--db-attach=yes and --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001892 }
1893
sewardj4cf05692002-10-27 20:28:29 +00001894 /* Set up logging now. After this is done, VG_(clo_logfile_fd)
1895 should be connected to whatever sink has been selected, and we
1896 indiscriminately chuck stuff into it without worrying what the
1897 nature of it is. Oh the wonder of Unix streams. */
1898
nethercotee1730692003-11-20 10:38:07 +00001899 /* So far we should be still attached to stdout, so we can show on
sewardj4cf05692002-10-27 20:28:29 +00001900 the terminal any problems to do with processing command line
1901 opts. */
nethercotee1730692003-11-20 10:38:07 +00001902 vg_assert(VG_(clo_logfile_fd) == 1 /* stdout */);
sewardj73cf3bc2002-11-03 03:20:15 +00001903 vg_assert(VG_(logging_to_filedes) == True);
sewardj4cf05692002-10-27 20:28:29 +00001904
1905 switch (VG_(clo_log_to)) {
sewardj73cf3bc2002-11-03 03:20:15 +00001906
sewardj4cf05692002-10-27 20:28:29 +00001907 case VgLogTo_Fd:
1908 vg_assert(VG_(clo_logfile_name) == NULL);
1909 VG_(clo_logfile_fd) = eventually_logfile_fd;
1910 break;
sewardj73cf3bc2002-11-03 03:20:15 +00001911
sewardj4cf05692002-10-27 20:28:29 +00001912 case VgLogTo_File: {
1913 Char logfilename[1000];
jsgff3c3f1a2003-10-14 22:13:28 +00001914 Int seq = 0;
1915 Int pid = VG_(getpid)();
1916
sewardj4cf05692002-10-27 20:28:29 +00001917 vg_assert(VG_(clo_logfile_name) != NULL);
1918 vg_assert(VG_(strlen)(VG_(clo_logfile_name)) <= 900); /* paranoia */
jsgff3c3f1a2003-10-14 22:13:28 +00001919
nethercote71980f02004-01-24 18:18:54 +00001920 for (;;) {
jsgff3c3f1a2003-10-14 22:13:28 +00001921 if (seq == 0)
1922 VG_(sprintf)(logfilename, "%s.pid%d",
1923 VG_(clo_logfile_name), pid );
1924 else
1925 VG_(sprintf)(logfilename, "%s.pid%d.%d",
1926 VG_(clo_logfile_name), pid, seq );
1927 seq++;
1928
1929 eventually_logfile_fd
1930 = VG_(open)(logfilename,
1931 VKI_O_CREAT|VKI_O_WRONLY|VKI_O_EXCL|VKI_O_TRUNC,
1932 VKI_S_IRUSR|VKI_S_IWUSR);
1933 if (eventually_logfile_fd >= 0) {
fitzhardinge9b8c2f32004-01-06 00:15:26 +00001934 VG_(clo_logfile_fd) = VG_(safe_fd)(eventually_logfile_fd);
jsgff3c3f1a2003-10-14 22:13:28 +00001935 break;
1936 } else {
1937 if (eventually_logfile_fd != -VKI_EEXIST) {
1938 VG_(message)(Vg_UserMsg,
1939 "Can't create/open log file `%s.pid%d'; giving up!",
1940 VG_(clo_logfile_name), pid);
1941 VG_(bad_option)(
1942 "--logfile=<file> didn't work out for some reason.");
1943 break;
1944 }
1945 }
1946 }
sewardj4cf05692002-10-27 20:28:29 +00001947 break;
sewardj73cf3bc2002-11-03 03:20:15 +00001948 }
1949
1950 case VgLogTo_Socket: {
1951 vg_assert(VG_(clo_logfile_name) != NULL);
1952 vg_assert(VG_(strlen)(VG_(clo_logfile_name)) <= 900); /* paranoia */
1953 eventually_logfile_fd
1954 = VG_(connect_via_socket)( VG_(clo_logfile_name) );
1955 if (eventually_logfile_fd == -1) {
1956 VG_(message)(Vg_UserMsg,
1957 "Invalid --logsocket=ipaddr or --logsocket=ipaddr:port spec");
1958 VG_(message)(Vg_UserMsg,
1959 "of `%s'; giving up!", VG_(clo_logfile_name) );
1960 VG_(bad_option)(
1961 "--logsocket=");
sewardj4cf05692002-10-27 20:28:29 +00001962 }
sewardj73cf3bc2002-11-03 03:20:15 +00001963 if (eventually_logfile_fd == -2) {
1964 VG_(message)(Vg_UserMsg,
sewardj570f8902002-11-03 11:44:36 +00001965 "valgrind: failed to connect to logging server `%s'.",
sewardj73cf3bc2002-11-03 03:20:15 +00001966 VG_(clo_logfile_name) );
sewardj570f8902002-11-03 11:44:36 +00001967 VG_(message)(Vg_UserMsg,
1968 "Log messages will sent to stderr instead." );
1969 VG_(message)(Vg_UserMsg,
1970 "" );
1971 /* We don't change anything here. */
1972 } else {
1973 vg_assert(eventually_logfile_fd > 0);
1974 VG_(clo_logfile_fd) = eventually_logfile_fd;
1975 VG_(logging_to_filedes) = False;
1976 }
sewardj73cf3bc2002-11-03 03:20:15 +00001977 break;
1978 }
1979
sewardj4cf05692002-10-27 20:28:29 +00001980 }
1981
jsgf855d93d2003-10-13 22:26:55 +00001982 /* Move logfile_fd into the safe range, so it doesn't conflict with any app fds */
fitzhardingef0046f22003-12-18 02:39:22 +00001983 eventually_logfile_fd = VG_(fcntl)(VG_(clo_logfile_fd), VKI_F_DUPFD, VG_(max_fd)+1);
jsgf855d93d2003-10-13 22:26:55 +00001984 if (eventually_logfile_fd < 0)
1985 VG_(message)(Vg_UserMsg, "valgrind: failed to move logfile fd into safe range");
1986 else {
1987 VG_(clo_logfile_fd) = eventually_logfile_fd;
1988 VG_(fcntl)(VG_(clo_logfile_fd), VKI_F_SETFD, VKI_FD_CLOEXEC);
1989 }
1990
sewardj4cf05692002-10-27 20:28:29 +00001991 /* Ok, the logging sink is running now. Print a suitable preamble.
1992 If logging to file or a socket, write details of parent PID and
1993 command line args, to help people trying to interpret the
1994 results of a run which encompasses multiple processes. */
sewardjde4a1d02002-03-22 01:27:54 +00001995
sewardj83adf412002-05-01 01:25:45 +00001996 if (VG_(clo_verbosity > 0)) {
njnd04b7c62002-10-03 14:05:52 +00001997 /* Skin details */
1998 VG_(message)(Vg_UserMsg, "%s%s%s, %s for x86-linux.",
1999 VG_(details).name,
2000 NULL == VG_(details).version ? "" : "-",
2001 NULL == VG_(details).version
2002 ? (Char*)"" : VG_(details).version,
2003 VG_(details).description);
2004 VG_(message)(Vg_UserMsg, "%s", VG_(details).copyright_author);
sewardj3b2736a2002-03-24 12:18:35 +00002005
njnd04b7c62002-10-03 14:05:52 +00002006 /* Core details */
2007 VG_(message)(Vg_UserMsg,
njn3e884182003-04-15 13:03:23 +00002008 "Using valgrind-%s, a program supervision framework for x86-linux.",
sewardj4aa62ba2002-10-05 15:49:27 +00002009 VERSION);
sewardjde4a1d02002-03-22 01:27:54 +00002010 VG_(message)(Vg_UserMsg,
nethercotebb1c9912004-01-04 16:43:23 +00002011 "Copyright (C) 2000-2004, and GNU GPL'd, by Julian Seward.");
njnd04b7c62002-10-03 14:05:52 +00002012 }
2013
nethercotec1e395d2003-11-10 13:26:49 +00002014 if (VG_(clo_verbosity) > 0 && VG_(clo_log_to) != VgLogTo_Fd) {
sewardj4cf05692002-10-27 20:28:29 +00002015 VG_(message)(Vg_UserMsg, "");
2016 VG_(message)(Vg_UserMsg,
2017 "My PID = %d, parent PID = %d. Prog and args are:",
2018 VG_(getpid)(), VG_(getppid)() );
2019 for (i = 0; i < VG_(client_argc); i++)
2020 VG_(message)(Vg_UserMsg, " %s", VG_(client_argv)[i]);
2021 }
2022
sewardjde4a1d02002-03-22 01:27:54 +00002023 if (VG_(clo_verbosity) > 1) {
nethercotea70f7352004-04-18 12:08:46 +00002024 Int fd;
sewardj4cf05692002-10-27 20:28:29 +00002025 if (VG_(clo_log_to) != VgLogTo_Fd)
2026 VG_(message)(Vg_UserMsg, "");
fitzhardinge98abfc72003-12-16 02:05:15 +00002027 VG_(message)(Vg_UserMsg, "Valgrind library directory: %s", VG_(libdir));
njn86dc2bc2003-09-09 07:26:21 +00002028 VG_(message)(Vg_UserMsg, "Command line");
2029 for (i = 0; i < VG_(client_argc); i++)
2030 VG_(message)(Vg_UserMsg, " %s", VG_(client_argv)[i]);
2031
sewardjde4a1d02002-03-22 01:27:54 +00002032 VG_(message)(Vg_UserMsg, "Startup, with flags:");
nethercote71980f02004-01-24 18:18:54 +00002033 for (i = 1; i < VG_(vg_argc); i++) {
2034 VG_(message)(Vg_UserMsg, " %s", VG_(vg_argv)[i]);
sewardjde4a1d02002-03-22 01:27:54 +00002035 }
nethercotea70f7352004-04-18 12:08:46 +00002036
2037 VG_(message)(Vg_UserMsg, "Contents of /proc/version:");
2038 fd = VG_(open) ( "/proc/version", VKI_O_RDONLY, 0 );
2039 if (fd < 0) {
2040 VG_(message)(Vg_UserMsg, " can't open /proc/version");
2041 } else {
2042 #define BUF_LEN 256
2043 Char version_buf[BUF_LEN];
2044 Int n = VG_(read) ( fd, version_buf, BUF_LEN );
2045 vg_assert(n <= 256);
2046 if (n > 0) {
2047 version_buf[n-1] = '\0';
2048 VG_(message)(Vg_UserMsg, " %s", version_buf);
2049 } else {
2050 VG_(message)(Vg_UserMsg, " (empty?)");
2051 }
2052 VG_(close)(fd);
2053 #undef BUF_LEN
2054 }
sewardjde4a1d02002-03-22 01:27:54 +00002055 }
2056
fitzhardinge98abfc72003-12-16 02:05:15 +00002057 if (VG_(clo_n_suppressions) < VG_CLO_MAX_SFILES-1 &&
njn25e49d8e72002-09-23 09:36:25 +00002058 (VG_(needs).core_errors || VG_(needs).skin_errors)) {
fitzhardinge98abfc72003-12-16 02:05:15 +00002059 /* If there are no suppression files specified and the skin
2060 needs one, load the default */
2061 static const Char default_supp[] = "default.supp";
2062 Int len = VG_(strlen)(VG_(libdir)) + 1 + sizeof(default_supp);
2063 Char *buf = VG_(arena_malloc)(VG_AR_CORE, len);
2064 VG_(sprintf)(buf, "%s/%s", VG_(libdir), default_supp);
2065 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = buf;
2066 VG_(clo_n_suppressions)++;
sewardjde4a1d02002-03-22 01:27:54 +00002067 }
sewardj4cf05692002-10-27 20:28:29 +00002068
njn6a230532003-07-21 10:38:23 +00002069 if (VG_(clo_gen_suppressions) &&
2070 !VG_(needs).core_errors && !VG_(needs).skin_errors) {
2071 config_error("Can't use --gen-suppressions=yes with this skin,\n"
2072 " as it doesn't generate errors.");
2073 }
sewardjde4a1d02002-03-22 01:27:54 +00002074}
2075
sewardjde4a1d02002-03-22 01:27:54 +00002076
nethercote71980f02004-01-24 18:18:54 +00002077/*====================================================================*/
2078/*=== File descriptor setup ===*/
2079/*====================================================================*/
2080
2081static void setup_file_descriptors(void)
2082{
2083 struct vki_rlimit rl;
2084
2085 /* Get the current file descriptor limits. */
2086 if (VG_(getrlimit)(VKI_RLIMIT_NOFILE, &rl) < 0) {
2087 rl.rlim_cur = 1024;
2088 rl.rlim_max = 1024;
2089 }
2090
2091 /* Work out where to move the soft limit to. */
2092 if (rl.rlim_cur + VG_N_RESERVED_FDS <= rl.rlim_max) {
2093 rl.rlim_cur = rl.rlim_cur + VG_N_RESERVED_FDS;
2094 } else {
2095 rl.rlim_cur = rl.rlim_max;
2096 }
2097
2098 /* Reserve some file descriptors for our use. */
2099 VG_(max_fd) = rl.rlim_cur - VG_N_RESERVED_FDS;
2100
2101 /* Update the soft limit. */
2102 VG_(setrlimit)(VKI_RLIMIT_NOFILE, &rl);
2103
2104 if (VG_(vgexecfd) != -1)
2105 VG_(vgexecfd) = VG_(safe_fd)( VG_(vgexecfd) );
2106 if (VG_(clexecfd) != -1)
2107 VG_(clexecfd) = VG_(safe_fd)( VG_(clexecfd) );
2108}
2109
2110
2111/*====================================================================*/
nethercote1d447092004-02-01 17:29:59 +00002112/*=== baseBlock: definition + setup ===*/
nethercote71980f02004-01-24 18:18:54 +00002113/*====================================================================*/
2114
2115/* The variables storing offsets. */
2116
2117#define INVALID_OFFSET (-1)
2118
2119Int VGOFF_(m_eax) = INVALID_OFFSET;
2120Int VGOFF_(m_ecx) = INVALID_OFFSET;
2121Int VGOFF_(m_edx) = INVALID_OFFSET;
2122Int VGOFF_(m_ebx) = INVALID_OFFSET;
2123Int VGOFF_(m_esp) = INVALID_OFFSET;
2124Int VGOFF_(m_ebp) = INVALID_OFFSET;
2125Int VGOFF_(m_esi) = INVALID_OFFSET;
2126Int VGOFF_(m_edi) = INVALID_OFFSET;
2127Int VGOFF_(m_eflags) = INVALID_OFFSET;
2128Int VGOFF_(m_dflag) = INVALID_OFFSET;
2129Int VGOFF_(m_ssestate) = INVALID_OFFSET;
2130Int VGOFF_(ldt) = INVALID_OFFSET;
2131Int VGOFF_(tls) = INVALID_OFFSET;
2132Int VGOFF_(m_cs) = INVALID_OFFSET;
2133Int VGOFF_(m_ss) = INVALID_OFFSET;
2134Int VGOFF_(m_ds) = INVALID_OFFSET;
2135Int VGOFF_(m_es) = INVALID_OFFSET;
2136Int VGOFF_(m_fs) = INVALID_OFFSET;
2137Int VGOFF_(m_gs) = INVALID_OFFSET;
2138Int VGOFF_(m_eip) = INVALID_OFFSET;
2139Int VGOFF_(spillslots) = INVALID_OFFSET;
2140Int VGOFF_(sh_eax) = INVALID_OFFSET;
2141Int VGOFF_(sh_ecx) = INVALID_OFFSET;
2142Int VGOFF_(sh_edx) = INVALID_OFFSET;
2143Int VGOFF_(sh_ebx) = INVALID_OFFSET;
2144Int VGOFF_(sh_esp) = INVALID_OFFSET;
2145Int VGOFF_(sh_ebp) = INVALID_OFFSET;
2146Int VGOFF_(sh_esi) = INVALID_OFFSET;
2147Int VGOFF_(sh_edi) = INVALID_OFFSET;
2148Int VGOFF_(sh_eflags) = INVALID_OFFSET;
2149
2150Int VGOFF_(helper_idiv_64_32) = INVALID_OFFSET;
2151Int VGOFF_(helper_div_64_32) = INVALID_OFFSET;
2152Int VGOFF_(helper_idiv_32_16) = INVALID_OFFSET;
2153Int VGOFF_(helper_div_32_16) = INVALID_OFFSET;
2154Int VGOFF_(helper_idiv_16_8) = INVALID_OFFSET;
2155Int VGOFF_(helper_div_16_8) = INVALID_OFFSET;
2156Int VGOFF_(helper_imul_32_64) = INVALID_OFFSET;
2157Int VGOFF_(helper_mul_32_64) = INVALID_OFFSET;
2158Int VGOFF_(helper_imul_16_32) = INVALID_OFFSET;
2159Int VGOFF_(helper_mul_16_32) = INVALID_OFFSET;
2160Int VGOFF_(helper_imul_8_16) = INVALID_OFFSET;
2161Int VGOFF_(helper_mul_8_16) = INVALID_OFFSET;
2162Int VGOFF_(helper_CLD) = INVALID_OFFSET;
2163Int VGOFF_(helper_STD) = INVALID_OFFSET;
2164Int VGOFF_(helper_get_dirflag) = INVALID_OFFSET;
2165Int VGOFF_(helper_CLC) = INVALID_OFFSET;
2166Int VGOFF_(helper_STC) = INVALID_OFFSET;
nethercote1018bdd2004-02-11 23:33:29 +00002167Int VGOFF_(helper_CMC) = INVALID_OFFSET;
nethercote71980f02004-01-24 18:18:54 +00002168Int VGOFF_(helper_shldl) = INVALID_OFFSET;
2169Int VGOFF_(helper_shldw) = INVALID_OFFSET;
2170Int VGOFF_(helper_shrdl) = INVALID_OFFSET;
2171Int VGOFF_(helper_shrdw) = INVALID_OFFSET;
2172Int VGOFF_(helper_IN) = INVALID_OFFSET;
2173Int VGOFF_(helper_OUT) = INVALID_OFFSET;
2174Int VGOFF_(helper_RDTSC) = INVALID_OFFSET;
2175Int VGOFF_(helper_CPUID) = INVALID_OFFSET;
2176Int VGOFF_(helper_BSWAP) = INVALID_OFFSET;
nethercote1018bdd2004-02-11 23:33:29 +00002177Int VGOFF_(helper_bsfw) = INVALID_OFFSET;
2178Int VGOFF_(helper_bsfl) = INVALID_OFFSET;
2179Int VGOFF_(helper_bsrw) = INVALID_OFFSET;
2180Int VGOFF_(helper_bsrl) = INVALID_OFFSET;
nethercote71980f02004-01-24 18:18:54 +00002181Int VGOFF_(helper_fstsw_AX) = INVALID_OFFSET;
2182Int VGOFF_(helper_SAHF) = INVALID_OFFSET;
2183Int VGOFF_(helper_LAHF) = INVALID_OFFSET;
2184Int VGOFF_(helper_DAS) = INVALID_OFFSET;
2185Int VGOFF_(helper_DAA) = INVALID_OFFSET;
nethercote1018bdd2004-02-11 23:33:29 +00002186Int VGOFF_(helper_AAS) = INVALID_OFFSET;
2187Int VGOFF_(helper_AAA) = INVALID_OFFSET;
2188Int VGOFF_(helper_AAD) = INVALID_OFFSET;
2189Int VGOFF_(helper_AAM) = INVALID_OFFSET;
nethercote71980f02004-01-24 18:18:54 +00002190Int VGOFF_(helper_cmpxchg8b) = INVALID_OFFSET;
2191Int VGOFF_(helper_undefined_instruction) = INVALID_OFFSET;
2192
2193/* MAX_NONCOMPACT_HELPERS can be increased easily. If MAX_COMPACT_HELPERS is
2194 * increased too much, they won't really be compact any more... */
2195#define MAX_COMPACT_HELPERS 8
2196#define MAX_NONCOMPACT_HELPERS 50
2197
2198UInt VG_(n_compact_helpers) = 0;
2199UInt VG_(n_noncompact_helpers) = 0;
2200
2201Addr VG_(compact_helper_addrs) [MAX_COMPACT_HELPERS];
2202Int VG_(compact_helper_offsets)[MAX_COMPACT_HELPERS];
2203Addr VG_(noncompact_helper_addrs) [MAX_NONCOMPACT_HELPERS];
2204Int VG_(noncompact_helper_offsets)[MAX_NONCOMPACT_HELPERS];
2205
2206/* This is the actual defn of baseblock. */
2207UInt VG_(baseBlock)[VG_BASEBLOCK_WORDS];
2208
nethercote71980f02004-01-24 18:18:54 +00002209/* Words. */
2210static Int baB_off = 0;
2211
2212
sewardjfa492d42002-12-08 18:20:01 +00002213UInt VG_(insertDflag)(UInt eflags, Int d)
2214{
2215 vg_assert(d == 1 || d == -1);
2216 eflags &= ~EFlagD;
2217
2218 if (d < 0)
2219 eflags |= EFlagD;
2220
2221 return eflags;
2222}
2223
2224Int VG_(extractDflag)(UInt eflags)
2225{
2226 Int ret;
2227
2228 if (eflags & EFlagD)
2229 ret = -1;
2230 else
2231 ret = 1;
2232
2233 return ret;
2234}
2235
nethercote71980f02004-01-24 18:18:54 +00002236/* Returns the offset, in words. */
2237static Int alloc_BaB ( Int words )
sewardjde4a1d02002-03-22 01:27:54 +00002238{
nethercote71980f02004-01-24 18:18:54 +00002239 Int off = baB_off;
2240 baB_off += words;
2241 if (baB_off >= VG_BASEBLOCK_WORDS)
2242 VG_(core_panic)( "alloc_BaB: baseBlock is too small");
sewardjde4a1d02002-03-22 01:27:54 +00002243
nethercote71980f02004-01-24 18:18:54 +00002244 return off;
sewardjde4a1d02002-03-22 01:27:54 +00002245}
2246
nethercote71980f02004-01-24 18:18:54 +00002247/* Align offset, in *bytes* */
2248static void align_BaB ( UInt align )
njn25e49d8e72002-09-23 09:36:25 +00002249{
nethercote71980f02004-01-24 18:18:54 +00002250 vg_assert(2 == align || 4 == align || 8 == align || 16 == align);
2251 baB_off += (align-1);
2252 baB_off &= ~(align-1);
njn25e49d8e72002-09-23 09:36:25 +00002253}
2254
nethercote71980f02004-01-24 18:18:54 +00002255/* Allocate 1 word in baseBlock and set it to the given value. */
2256static Int alloc_BaB_1_set ( Addr a )
njn25e49d8e72002-09-23 09:36:25 +00002257{
nethercote71980f02004-01-24 18:18:54 +00002258 Int off = alloc_BaB(1);
2259 VG_(baseBlock)[off] = (UInt)a;
2260 return off;
njn25e49d8e72002-09-23 09:36:25 +00002261}
2262
nethercote71980f02004-01-24 18:18:54 +00002263/* Registers a function in compact_helper_addrs; compact_helper_offsets is
2264 filled in later. */
2265void VG_(register_compact_helper)(Addr a)
sewardjde4a1d02002-03-22 01:27:54 +00002266{
nethercote71980f02004-01-24 18:18:54 +00002267 if (MAX_COMPACT_HELPERS <= VG_(n_compact_helpers)) {
2268 VG_(printf)("Can only register %d compact helpers\n",
2269 MAX_COMPACT_HELPERS);
2270 VG_(core_panic)("Too many compact helpers registered");
2271 }
2272 VG_(compact_helper_addrs)[VG_(n_compact_helpers)] = a;
2273 VG_(n_compact_helpers)++;
2274}
2275
2276/* Registers a function in noncompact_helper_addrs; noncompact_helper_offsets
2277 * is filled in later.
2278 */
2279void VG_(register_noncompact_helper)(Addr a)
2280{
2281 if (MAX_NONCOMPACT_HELPERS <= VG_(n_noncompact_helpers)) {
2282 VG_(printf)("Can only register %d non-compact helpers\n",
2283 MAX_NONCOMPACT_HELPERS);
2284 VG_(printf)("Try increasing MAX_NON_COMPACT_HELPERS\n");
2285 VG_(core_panic)("Too many non-compact helpers registered");
2286 }
2287 VG_(noncompact_helper_addrs)[VG_(n_noncompact_helpers)] = a;
2288 VG_(n_noncompact_helpers)++;
2289}
2290
2291/* Allocate offsets in baseBlock for the skin helpers */
2292static
2293void assign_helpers_in_baseBlock(UInt n, Int offsets[], Addr addrs[])
2294{
2295 UInt i;
2296 for (i = 0; i < n; i++)
2297 offsets[i] = alloc_BaB_1_set( addrs[i] );
2298}
2299
2300Bool VG_(need_to_handle_esp_assignment)(void)
2301{
2302 return ( VG_(defined_new_mem_stack_4)() ||
2303 VG_(defined_die_mem_stack_4)() ||
2304 VG_(defined_new_mem_stack_8)() ||
2305 VG_(defined_die_mem_stack_8)() ||
2306 VG_(defined_new_mem_stack_12)() ||
2307 VG_(defined_die_mem_stack_12)() ||
2308 VG_(defined_new_mem_stack_16)() ||
2309 VG_(defined_die_mem_stack_16)() ||
2310 VG_(defined_new_mem_stack_32)() ||
2311 VG_(defined_die_mem_stack_32)() ||
2312 VG_(defined_new_mem_stack)() ||
2313 VG_(defined_die_mem_stack)()
2314 );
2315}
2316
2317/* Here we assign actual offsets. It's important to get the most
2318 popular referents within 128 bytes of the start, so we can take
2319 advantage of short addressing modes relative to %ebp. Popularity
2320 of offsets was measured on 22 Feb 02 running a KDE application, and
2321 the slots rearranged accordingly, with a 1.5% reduction in total
2322 size of translations. */
2323static void init_baseBlock ( Addr client_eip, Addr esp_at_startup )
2324{
2325 /* Those with offsets under 128 are carefully chosen. */
2326
2327 /* WORD offsets in this column */
2328 /* 0 */ VGOFF_(m_eax) = alloc_BaB_1_set(0);
2329 /* 1 */ VGOFF_(m_ecx) = alloc_BaB_1_set(0);
2330 /* 2 */ VGOFF_(m_edx) = alloc_BaB_1_set(0);
2331 /* 3 */ VGOFF_(m_ebx) = alloc_BaB_1_set(0);
2332 /* 4 */ VGOFF_(m_esp) = alloc_BaB_1_set(esp_at_startup);
2333 /* 5 */ VGOFF_(m_ebp) = alloc_BaB_1_set(0);
2334 /* 6 */ VGOFF_(m_esi) = alloc_BaB_1_set(0);
2335 /* 7 */ VGOFF_(m_edi) = alloc_BaB_1_set(0);
2336 /* 8 */ VGOFF_(m_eflags) = alloc_BaB_1_set(0);
2337
2338 if (VG_(needs).shadow_regs) {
2339 /* 9 */ VGOFF_(sh_eax) = alloc_BaB_1_set(0);
2340 /* 10 */ VGOFF_(sh_ecx) = alloc_BaB_1_set(0);
2341 /* 11 */ VGOFF_(sh_edx) = alloc_BaB_1_set(0);
2342 /* 12 */ VGOFF_(sh_ebx) = alloc_BaB_1_set(0);
2343 /* 13 */ VGOFF_(sh_esp) = alloc_BaB_1_set(0);
2344 /* 14 */ VGOFF_(sh_ebp) = alloc_BaB_1_set(0);
2345 /* 15 */ VGOFF_(sh_esi) = alloc_BaB_1_set(0);
2346 /* 16 */ VGOFF_(sh_edi) = alloc_BaB_1_set(0);
2347 /* 17 */ VGOFF_(sh_eflags) = alloc_BaB_1_set(0);
2348 VG_TRACK( post_regs_write_init );
2349 }
2350
2351 /* 9,10,11 or 18,19,20... depends on number whether shadow regs are used
2352 * and on compact helpers registered */
2353
2354 /* Make these most-frequently-called specialised ones compact, if they
2355 are used. */
2356 if (VG_(defined_new_mem_stack_4)())
2357 VG_(register_compact_helper)( (Addr) VG_(tool_interface).track_new_mem_stack_4);
2358
2359 if (VG_(defined_die_mem_stack_4)())
2360 VG_(register_compact_helper)( (Addr) VG_(tool_interface).track_die_mem_stack_4);
2361
2362 /* (9 or 18) + n_compact_helpers */
2363 /* Allocate slots for compact helpers */
2364 assign_helpers_in_baseBlock(VG_(n_compact_helpers),
2365 VG_(compact_helper_offsets),
2366 VG_(compact_helper_addrs));
2367
2368 /* (9/10 or 18/19) + n_compact_helpers */
2369 VGOFF_(m_eip) = alloc_BaB_1_set(client_eip);
2370
2371 /* There are currently 24 spill slots */
2372 /* (11+/20+ .. 32+/43+) + n_compact_helpers. This can overlap the magic
2373 * boundary at >= 32 words, but most spills are to low numbered spill
2374 * slots, so the ones above the boundary don't see much action. */
2375 VGOFF_(spillslots) = alloc_BaB(VG_MAX_SPILLSLOTS);
2376
2377 /* I gave up counting at this point. Since they're above the
2378 short-amode-boundary, there's no point. */
2379
2380 VGOFF_(m_dflag) = alloc_BaB_1_set(1); // 1 == forward D-flag
2381
2382 /* The FPU/SSE state. This _must_ be 16-byte aligned. Initial
2383 state doesn't matter much, as long as it's not totally borked. */
2384 align_BaB(16);
2385 VGOFF_(m_ssestate) = alloc_BaB(VG_SIZE_OF_SSESTATE_W);
2386 vg_assert(
2387 0 == ( ((UInt)(& VG_(baseBlock)[VGOFF_(m_ssestate)])) % 16 )
sewardj22854b92002-11-30 14:00:47 +00002388 );
2389
fitzhardingec2dbbac2004-01-23 23:09:01 +00002390 /* I assume that if we have SSE2 we also have SSE */
2391 VG_(have_ssestate) =
2392 VG_(cpu_has_feature)(VG_X86_FEAT_FXSR) &&
2393 VG_(cpu_has_feature)(VG_X86_FEAT_SSE);
2394
fitzhardinge98abfc72003-12-16 02:05:15 +00002395 /* set up an initial FPU state (doesn't really matter what it is,
2396 so long as it's somewhat valid) */
2397 if (!VG_(have_ssestate))
nethercote71980f02004-01-24 18:18:54 +00002398 asm volatile("fwait; fnsave %0; fwait; frstor %0; fwait"
2399 :
2400 : "m" (VG_(baseBlock)[VGOFF_(m_ssestate)])
2401 : "cc", "memory");
fitzhardinge98abfc72003-12-16 02:05:15 +00002402 else
nethercote71980f02004-01-24 18:18:54 +00002403 asm volatile("fwait; fxsave %0; fwait; andl $0xffbf, %1;"
2404 "fxrstor %0; fwait"
2405 :
2406 : "m" (VG_(baseBlock)[VGOFF_(m_ssestate)]),
2407 "m" (VG_(baseBlock)[VGOFF_(m_ssestate)+(24/4)])
2408 : "cc", "memory");
fitzhardinge98abfc72003-12-16 02:05:15 +00002409
njn0c7a5b52003-04-30 09:00:33 +00002410 if (0) {
2411 if (VG_(have_ssestate))
2412 VG_(printf)("Looks like a SSE-capable CPU\n");
2413 else
2414 VG_(printf)("Looks like a MMX-only CPU\n");
2415 }
sewardjb91ae7f2003-04-29 23:50:00 +00002416
nethercote71980f02004-01-24 18:18:54 +00002417 /* LDT pointer: pretend the root thread has an empty LDT to start with. */
2418 VGOFF_(ldt) = alloc_BaB_1_set((UInt)NULL);
jsgf855d93d2003-10-13 22:26:55 +00002419
nethercote71980f02004-01-24 18:18:54 +00002420 /* TLS pointer: pretend the root thread has no TLS array for now. */
2421 VGOFF_(tls) = alloc_BaB_1_set((UInt)NULL);
fitzhardingef0046f22003-12-18 02:39:22 +00002422
nethercote71980f02004-01-24 18:18:54 +00002423 /* segment registers */
2424 VGOFF_(m_cs) = alloc_BaB_1_set(0);
2425 VGOFF_(m_ss) = alloc_BaB_1_set(0);
2426 VGOFF_(m_ds) = alloc_BaB_1_set(0);
2427 VGOFF_(m_es) = alloc_BaB_1_set(0);
2428 VGOFF_(m_fs) = alloc_BaB_1_set(0);
2429 VGOFF_(m_gs) = alloc_BaB_1_set(0);
fitzhardingef0046f22003-12-18 02:39:22 +00002430
thughes35cec982004-04-21 15:16:43 +00002431 /* initialise %cs, %ds and %ss to point at the operating systems
2432 default code, data and stack segments */
2433 asm volatile("movw %%cs, %0"
2434 :
2435 : "m" (VG_(baseBlock)[VGOFF_(m_cs)]));
2436 asm volatile("movw %%ds, %0"
2437 :
2438 : "m" (VG_(baseBlock)[VGOFF_(m_ds)]));
2439 asm volatile("movw %%ss, %0"
2440 :
2441 : "m" (VG_(baseBlock)[VGOFF_(m_ss)]));
2442
nethercote71980f02004-01-24 18:18:54 +00002443 VG_(register_noncompact_helper)( (Addr) & VG_(do_useseg) );
fitzhardingef0046f22003-12-18 02:39:22 +00002444
nethercote71980f02004-01-24 18:18:54 +00002445#define REG(kind, size) \
2446 if (VG_(defined_##kind##_mem_stack##size)()) \
2447 VG_(register_noncompact_helper)( \
2448 (Addr) VG_(tool_interface).track_##kind##_mem_stack##size );
2449 REG(new, _8);
2450 REG(new, _12);
2451 REG(new, _16);
2452 REG(new, _32);
2453 REG(new, );
2454 REG(die, _8);
2455 REG(die, _12);
2456 REG(die, _16);
2457 REG(die, _32);
2458 REG(die, );
2459#undef REG
fitzhardingef0046f22003-12-18 02:39:22 +00002460
nethercote71980f02004-01-24 18:18:54 +00002461 if (VG_(need_to_handle_esp_assignment)())
2462 VG_(register_noncompact_helper)((Addr) VG_(unknown_esp_update));
fitzhardingeb791a192003-12-18 07:22:44 +00002463
nethercote71980f02004-01-24 18:18:54 +00002464# define HELPER(name) \
2465 VGOFF_(helper_##name) = alloc_BaB_1_set( (Addr) & VG_(helper_##name))
njn3e884182003-04-15 13:03:23 +00002466
nethercote71980f02004-01-24 18:18:54 +00002467 /* Helper functions. */
2468 HELPER(idiv_64_32); HELPER(div_64_32);
2469 HELPER(idiv_32_16); HELPER(div_32_16);
2470 HELPER(idiv_16_8); HELPER(div_16_8);
fitzhardinge98abfc72003-12-16 02:05:15 +00002471
nethercote71980f02004-01-24 18:18:54 +00002472 HELPER(imul_32_64); HELPER(mul_32_64);
2473 HELPER(imul_16_32); HELPER(mul_16_32);
2474 HELPER(imul_8_16); HELPER(mul_8_16);
njn25e49d8e72002-09-23 09:36:25 +00002475
nethercote71980f02004-01-24 18:18:54 +00002476 HELPER(CLD); HELPER(STD);
2477 HELPER(get_dirflag);
sewardjde4a1d02002-03-22 01:27:54 +00002478
nethercote71980f02004-01-24 18:18:54 +00002479 HELPER(CLC); HELPER(STC);
nethercote1018bdd2004-02-11 23:33:29 +00002480 HELPER(CMC);
jsgf855d93d2003-10-13 22:26:55 +00002481
nethercote71980f02004-01-24 18:18:54 +00002482 HELPER(shldl); HELPER(shldw);
2483 HELPER(shrdl); HELPER(shrdw);
njncc7bb472002-10-14 09:25:19 +00002484
nethercote71980f02004-01-24 18:18:54 +00002485 HELPER(RDTSC); HELPER(CPUID);
njncc7bb472002-10-14 09:25:19 +00002486
nethercote1018bdd2004-02-11 23:33:29 +00002487 HELPER(bsfw); HELPER(bsfl);
2488 HELPER(bsrw); HELPER(bsrl);
rjwalshf5f536f2003-11-17 17:45:00 +00002489
nethercote71980f02004-01-24 18:18:54 +00002490 HELPER(fstsw_AX);
2491 HELPER(SAHF); HELPER(LAHF);
2492 HELPER(DAS); HELPER(DAA);
nethercote1018bdd2004-02-11 23:33:29 +00002493 HELPER(AAS); HELPER(AAA);
2494 HELPER(AAD); HELPER(AAM);
nethercote71980f02004-01-24 18:18:54 +00002495 HELPER(IN); HELPER(OUT);
2496 HELPER(cmpxchg8b);
sewardj018f7622002-05-15 21:13:39 +00002497
nethercote71980f02004-01-24 18:18:54 +00002498 HELPER(undefined_instruction);
jsgf855d93d2003-10-13 22:26:55 +00002499
nethercote71980f02004-01-24 18:18:54 +00002500# undef HELPER
sewardjde4a1d02002-03-22 01:27:54 +00002501
nethercote71980f02004-01-24 18:18:54 +00002502 /* Allocate slots for noncompact helpers */
2503 assign_helpers_in_baseBlock(VG_(n_noncompact_helpers),
2504 VG_(noncompact_helper_offsets),
2505 VG_(noncompact_helper_addrs));
2506}
sewardjde4a1d02002-03-22 01:27:54 +00002507
sewardj5f07b662002-04-23 16:52:51 +00002508
nethercote71980f02004-01-24 18:18:54 +00002509/*====================================================================*/
2510/*=== Setup pointercheck ===*/
2511/*====================================================================*/
njn25e49d8e72002-09-23 09:36:25 +00002512
nethercote71980f02004-01-24 18:18:54 +00002513static void setup_pointercheck(void)
2514{
2515 int ret;
sewardj2e93c502002-04-12 11:12:52 +00002516
fitzhardinge98abfc72003-12-16 02:05:15 +00002517 if (VG_(clo_pointercheck)) {
nethercote71980f02004-01-24 18:18:54 +00002518 vki_modify_ldt_t ldt = {
2519 VG_POINTERCHECK_SEGIDX, // entry_number
2520 VG_(client_base), // base_addr
2521 (VG_(client_end)-VG_(client_base)) / VKI_BYTES_PER_PAGE, // limit
2522 1, // seg_32bit
2523 0, // contents: data, RW, non-expanding
2524 0, // ! read_exec_only
2525 1, // limit_in_pages
2526 0, // ! seg not present
2527 1, // useable
fitzhardinge98abfc72003-12-16 02:05:15 +00002528 };
nethercote71980f02004-01-24 18:18:54 +00002529 ret = VG_(do_syscall)(__NR_modify_ldt, 1, &ldt, sizeof(ldt));
fitzhardinge98abfc72003-12-16 02:05:15 +00002530 if (ret < 0) {
2531 VG_(message)(Vg_UserMsg,
2532 "Warning: ignoring --pointercheck=yes, "
2533 "because modify_ldt failed (errno=%d)", -ret);
2534 VG_(clo_pointercheck) = False;
2535 }
2536 }
sewardjde4a1d02002-03-22 01:27:54 +00002537}
2538
nethercote71980f02004-01-24 18:18:54 +00002539/*====================================================================*/
2540/*=== Initialise program data/text, etc. ===*/
2541/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +00002542
nethercote71980f02004-01-24 18:18:54 +00002543static void build_valgrind_map_callback
2544 ( Addr start, UInt size, Char rr, Char ww, Char xx,
2545 UInt dev, UInt ino, ULong foffset, const UChar* filename )
sewardjde4a1d02002-03-22 01:27:54 +00002546{
nethercote71980f02004-01-24 18:18:54 +00002547 UInt prot = 0;
2548 UInt flags = SF_MMAP|SF_NOSYMS;
2549 Bool is_stack_segment;
2550
2551 is_stack_segment =
2552 (start == VG_(clstk_base) && (start+size) == VG_(clstk_end));
2553
2554 /* Only record valgrind mappings for now, without loading any
2555 symbols. This is so we know where the free space is before we
2556 start allocating more memory (note: heap is OK, it's just mmap
2557 which is the problem here). */
2558 if (start >= VG_(valgrind_base) && (start+size) <= VG_(valgrind_end)) {
2559 flags |= SF_VALGRIND;
2560 VG_(map_file_segment)(start, size, prot, flags, dev, ino, foffset, filename);
2561 }
sewardjde4a1d02002-03-22 01:27:54 +00002562}
2563
nethercote71980f02004-01-24 18:18:54 +00002564// Global var used to pass local data to callback
2565Addr esp_at_startup___global_arg = 0;
sewardjde4a1d02002-03-22 01:27:54 +00002566
nethercote71980f02004-01-24 18:18:54 +00002567static void build_segment_map_callback
2568 ( Addr start, UInt size, Char rr, Char ww, Char xx,
2569 UInt dev, UInt ino, ULong foffset, const UChar* filename )
sewardj45b672d2003-07-25 19:58:11 +00002570{
nethercote71980f02004-01-24 18:18:54 +00002571 UInt prot = 0;
2572 UInt flags;
2573 Bool is_stack_segment;
2574 Addr r_esp;
sewardj45b672d2003-07-25 19:58:11 +00002575
nethercote71980f02004-01-24 18:18:54 +00002576 is_stack_segment
2577 = (start == VG_(clstk_base) && (start+size) == VG_(clstk_end));
fitzhardinge98abfc72003-12-16 02:05:15 +00002578
nethercote71980f02004-01-24 18:18:54 +00002579 if (rr == 'r') prot |= VKI_PROT_READ;
2580 if (ww == 'w') prot |= VKI_PROT_WRITE;
2581 if (xx == 'x') prot |= VKI_PROT_EXEC;
fitzhardinge98abfc72003-12-16 02:05:15 +00002582
nethercote71980f02004-01-24 18:18:54 +00002583 if (is_stack_segment)
2584 flags = SF_STACK | SF_GROWDOWN;
2585 else
2586 flags = SF_EXEC|SF_MMAP;
fitzhardinge98abfc72003-12-16 02:05:15 +00002587
nethercote71980f02004-01-24 18:18:54 +00002588 if (filename != NULL)
2589 flags |= SF_FILE;
fitzhardinge98abfc72003-12-16 02:05:15 +00002590
nethercote71980f02004-01-24 18:18:54 +00002591 if (start >= VG_(valgrind_base) && (start+size) <= VG_(valgrind_end))
2592 flags |= SF_VALGRIND;
fitzhardinge98abfc72003-12-16 02:05:15 +00002593
nethercote71980f02004-01-24 18:18:54 +00002594 VG_(map_file_segment)(start, size, prot, flags, dev, ino, foffset, filename);
fitzhardinge98abfc72003-12-16 02:05:15 +00002595
nethercote71980f02004-01-24 18:18:54 +00002596 if (VG_(is_client_addr)(start) && VG_(is_client_addr)(start+size-1))
2597 VG_TRACK( new_mem_startup, start, size, rr=='r', ww=='w', xx=='x' );
sewardj3e1eb1f2002-05-18 13:14:17 +00002598
nethercote71980f02004-01-24 18:18:54 +00002599 /* If this is the stack segment mark all below %esp as noaccess. */
2600 r_esp = esp_at_startup___global_arg;
2601 vg_assert(0 != r_esp);
2602 if (is_stack_segment) {
2603 if (0)
2604 VG_(message)(Vg_DebugMsg, "invalidating stack area: %x .. %x",
2605 start,r_esp);
2606 VG_TRACK( die_mem_stack, start, r_esp-start );
sewardjde4a1d02002-03-22 01:27:54 +00002607 }
sewardjde4a1d02002-03-22 01:27:54 +00002608}
2609
2610
nethercote71980f02004-01-24 18:18:54 +00002611/*====================================================================*/
2612/*=== Sanity check machinery (permanently engaged) ===*/
2613/*====================================================================*/
njn25e49d8e72002-09-23 09:36:25 +00002614
2615/* A fast sanity check -- suitable for calling circa once per
2616 millisecond. */
2617
2618void VG_(do_sanity_checks) ( Bool force_expensive )
2619{
njn37cea302002-09-30 11:24:00 +00002620 VGP_PUSHCC(VgpCoreCheapSanity);
2621
njn25e49d8e72002-09-23 09:36:25 +00002622 if (VG_(sanity_level) < 1) return;
2623
2624 /* --- First do all the tests that we can do quickly. ---*/
2625
2626 VG_(sanity_fast_count)++;
2627
njn25e49d8e72002-09-23 09:36:25 +00002628 /* Check stuff pertaining to the memory check system. */
2629
2630 /* Check that nobody has spuriously claimed that the first or
2631 last 16 pages of memory have become accessible [...] */
njn37cea302002-09-30 11:24:00 +00002632 if (VG_(needs).sanity_checks) {
2633 VGP_PUSHCC(VgpSkinCheapSanity);
njn25e49d8e72002-09-23 09:36:25 +00002634 vg_assert(SK_(cheap_sanity_check)());
njn37cea302002-09-30 11:24:00 +00002635 VGP_POPCC(VgpSkinCheapSanity);
2636 }
njn25e49d8e72002-09-23 09:36:25 +00002637
2638 /* --- Now some more expensive checks. ---*/
2639
2640 /* Once every 25 times, check some more expensive stuff. */
2641 if ( force_expensive
2642 || VG_(sanity_level) > 1
2643 || (VG_(sanity_level) == 1 && (VG_(sanity_fast_count) % 25) == 0)) {
2644
njn37cea302002-09-30 11:24:00 +00002645 VGP_PUSHCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002646 VG_(sanity_slow_count)++;
2647
jsgf855d93d2003-10-13 22:26:55 +00002648 VG_(proxy_sanity)();
2649
njn25e49d8e72002-09-23 09:36:25 +00002650# if 0
2651 { void zzzmemscan(void); zzzmemscan(); }
2652# endif
2653
2654 if ((VG_(sanity_fast_count) % 250) == 0)
2655 VG_(sanity_check_tc_tt)();
2656
2657 if (VG_(needs).sanity_checks) {
njn37cea302002-09-30 11:24:00 +00002658 VGP_PUSHCC(VgpSkinExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002659 vg_assert(SK_(expensive_sanity_check)());
njn37cea302002-09-30 11:24:00 +00002660 VGP_POPCC(VgpSkinExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002661 }
2662 /*
2663 if ((VG_(sanity_fast_count) % 500) == 0) VG_(mallocSanityCheckAll)();
2664 */
njn37cea302002-09-30 11:24:00 +00002665 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002666 }
2667
2668 if (VG_(sanity_level) > 1) {
njn37cea302002-09-30 11:24:00 +00002669 VGP_PUSHCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002670 /* Check sanity of the low-level memory manager. Note that bugs
2671 in the client's code can cause this to fail, so we don't do
2672 this check unless specially asked for. And because it's
2673 potentially very expensive. */
2674 VG_(mallocSanityCheckAll)();
njn37cea302002-09-30 11:24:00 +00002675 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002676 }
njn37cea302002-09-30 11:24:00 +00002677 VGP_POPCC(VgpCoreCheapSanity);
njn25e49d8e72002-09-23 09:36:25 +00002678}
nethercote71980f02004-01-24 18:18:54 +00002679
2680
2681/*====================================================================*/
2682/*=== main() ===*/
2683/*====================================================================*/
2684
2685int main(int argc, char **argv)
2686{
2687 char **cl_argv;
2688 const char *tool = NULL;
2689 const char *exec = NULL;
2690 char *preload; /* tool-specific LD_PRELOAD .so */
2691 char **env;
nethercote6c999f22004-01-31 22:55:15 +00002692 Int need_help = 0; // 0 = no, 1 = --help, 2 = --help-debug
nethercote71980f02004-01-24 18:18:54 +00002693 struct exeinfo info;
2694 ToolInfo *toolinfo = NULL;
2695 void *tool_dlhandle;
2696 Addr client_eip;
2697 Addr esp_at_startup; /* client's %esp at the point we gained control. */
2698 UInt * client_auxv;
2699 VgSchedReturnCode src;
fitzhardingeb50068f2004-02-24 23:42:55 +00002700 vki_rlimit zero = { 0, 0 };
nethercote71980f02004-01-24 18:18:54 +00002701
2702 //============================================================
2703 // Nb: startup is complex. Prerequisites are shown at every step.
2704 //
2705 // *** Be very careful when messing with the order ***
2706 //============================================================
2707
fitzhardingeb50068f2004-02-24 23:42:55 +00002708 // Get the current process datasize rlimit, and set it to zero.
2709 // This prevents any internal uses of brk() from having any effect.
2710 // We remember the old value so we can restore it on exec, so that
2711 // child processes will have a reasonable brk value.
2712 VG_(getrlimit)(VKI_RLIMIT_DATA, &VG_(client_rlimit_data));
2713 zero.rlim_max = VG_(client_rlimit_data).rlim_max;
2714 VG_(setrlimit)(VKI_RLIMIT_DATA, &zero);
2715
nethercote71980f02004-01-24 18:18:54 +00002716 //--------------------------------------------------------------
2717 // Check we were launched by stage1
2718 // p: n/a [must be first step]
2719 //--------------------------------------------------------------
2720 scan_auxv();
2721
2722 if (0) {
2723 int prmap(void *start, void *end, const char *perm, off_t off,
2724 int maj, int min, int ino) {
2725 printf("mapping %10p-%10p %s %02x:%02x %d\n",
2726 start, end, perm, maj, min, ino);
2727 return True;
2728 }
2729 printf("========== main() ==========\n");
2730 foreach_map(prmap);
2731 }
2732
2733 //--------------------------------------------------------------
2734 // Look for alternative libdir
2735 // p: n/a
2736 //--------------------------------------------------------------
2737 { char *cp = getenv(VALGRINDLIB);
2738 if (cp != NULL)
2739 VG_(libdir) = cp;
2740 }
2741
2742 //--------------------------------------------------------------
2743 // Begin working out address space layout
2744 // p: n/a
2745 //--------------------------------------------------------------
2746 layout_client_space( (Addr) & argc );
2747
2748 //--------------------------------------------------------------
2749 // Get valgrind args + client args (inc. from VALGRIND_OPTS/.valgrindrc).
2750 // Pre-process the command line.
2751 // p: n/a
2752 //--------------------------------------------------------------
2753 get_command_line(argc, argv, &VG_(vg_argc), &VG_(vg_argv), &cl_argv);
2754 pre_process_cmd_line_options(&need_help, &tool, &exec);
2755
2756 //==============================================================
2757 // Nb: once a tool is specified, the tool.so must be loaded even if
2758 // they specified --help or didn't specify a client program.
2759 //==============================================================
2760
2761 //--------------------------------------------------------------
2762 // With client padded out, map in tool
2763 // p: layout_client_space() [for padding]
2764 // p: set-libdir [for VG_(libdir)]
2765 // p: pre_process_cmd_line_options() [for 'tool']
2766 //--------------------------------------------------------------
2767 load_tool(tool, &tool_dlhandle, &toolinfo, &preload);
2768
2769 //==============================================================
2770 // Can use VG_(malloc)() and VG_(arena_malloc)() only after load_tool()
2771 // -- redzone size is now set.
2772 //==============================================================
2773
2774 //--------------------------------------------------------------
2775 // Finalise address space layout
2776 // p: layout_client_space(), load_tool() [for 'toolinfo']
2777 //--------------------------------------------------------------
2778 layout_remaining_space( toolinfo->shadow_ratio );
2779
2780 //--------------------------------------------------------------
2781 // Load client executable, finding in $PATH if necessary
2782 // p: layout_client_space() [so there's space]
2783 // p: pre_process_cmd_line_options() [for 'exec', 'need_help']
2784 // p: layout_remaining_space [so there's space]
2785 //--------------------------------------------------------------
2786 load_client(cl_argv, exec, /*inout*/&need_help, &info, &client_eip);
2787
2788 //--------------------------------------------------------------
2789 // Everything in place, unpad us
2790 // p: layout_remaining_space() [everything must be mapped in before now]
2791 // p: load_client() [ditto]
2792 //--------------------------------------------------------------
2793 as_unpad((void *)VG_(shadow_end), (void *)~0);
2794 as_closepadfile(); /* no more padding */
2795
2796 //--------------------------------------------------------------
2797 // Set up client's environment
2798 // p: set-libdir [for VG_(libdir)]
2799 // p: load_tool() [for 'preload']
2800 //--------------------------------------------------------------
2801 env = fix_environment(environ, preload);
2802
2803 //--------------------------------------------------------------
2804 // Setup client stack and eip
2805 // p: load_client() [for 'info']
2806 // p: fix_environment() [for 'env']
2807 //--------------------------------------------------------------
2808 esp_at_startup = setup_client_stack(cl_argv, env, &info, &client_auxv);
2809
2810 if (0)
2811 printf("entry=%x client esp=%x vg_argc=%d brkbase=%x\n",
2812 client_eip, esp_at_startup, VG_(vg_argc), VG_(brk_base));
2813
2814 //==============================================================
2815 // Finished setting up operating environment. Now initialise
2816 // Valgrind. (This is where the old VG_(main)() started.)
2817 //==============================================================
2818
2819 //--------------------------------------------------------------
2820 // Read /proc/self/maps into a buffer
2821 // p: all memory layout, environment setup [so memory maps are right]
2822 //--------------------------------------------------------------
2823 VG_(read_procselfmaps)();
2824
2825 //--------------------------------------------------------------
2826 // atfork
2827 // p: n/a
2828 //--------------------------------------------------------------
2829 VG_(atfork)(NULL, NULL, newpid);
2830 newpid(VG_INVALID_THREADID);
2831
2832 //--------------------------------------------------------------
2833 // setup file descriptors
2834 // p: n/a
2835 //--------------------------------------------------------------
2836 setup_file_descriptors();
2837
2838 //--------------------------------------------------------------
2839 // Setup tool
2840 // p: VG_(read_procselfmaps)() [so if sk_pre_clo_init calls
2841 // VG_(malloc), any mmap'd superblocks aren't erroneously
2842 // identified later as being owned by the client]
2843 // XXX: is that necessary, now that we look for V's segments separately?
2844 // XXX: alternatively, if sk_pre_clo_init does use VG_(malloc)(), is it
2845 // wrong to ignore any segments that might add in parse_procselfmaps?
2846 //--------------------------------------------------------------
2847 (*toolinfo->sk_pre_clo_init)();
2848 VG_(tool_init_dlsym)(tool_dlhandle);
2849 VG_(sanity_check_needs)();
2850
2851 //--------------------------------------------------------------
2852 // Process Valgrind's + tool's command-line options
2853 // p: load_tool() [for 'tool']
2854 // p: load_client() [for 'need_help']
2855 // p: setup_file_descriptors() [for 'VG_(max_fd)']
2856 // p: sk_pre_clo_init [to set 'command_line_options' need]
2857 //--------------------------------------------------------------
2858 process_cmd_line_options(client_auxv, esp_at_startup, tool, need_help);
2859
2860 //--------------------------------------------------------------
2861 // Allow GDB attach
2862 // p: process_cmd_line_options() [for VG_(clo_wait_for_gdb)]
2863 //--------------------------------------------------------------
2864 /* Hook to delay things long enough so we can get the pid and
2865 attach GDB in another shell. */
2866 if (VG_(clo_wait_for_gdb)) {
2867 VG_(printf)("pid=%d\n", VG_(getpid)());
2868 /* do "jump *$eip" to skip this in gdb */
2869 VG_(do_syscall)(__NR_pause);
2870 }
2871
2872 //--------------------------------------------------------------
2873 // Setup tool, post command-line processing
2874 // p: process_cmd_line_options [tool assumes it]
2875 //--------------------------------------------------------------
2876 SK_(post_clo_init)();
2877
2878 //--------------------------------------------------------------
nethercote1d447092004-02-01 17:29:59 +00002879 // Set up baseBlock
nethercote71980f02004-01-24 18:18:54 +00002880 // p: {pre,post}_clo_init() [for tool helper registration]
2881 // load_client() [for 'client_eip']
2882 // setup_client_stack() [for 'esp_at_startup']
2883 //--------------------------------------------------------------
2884 init_baseBlock(client_eip, esp_at_startup);
2885
2886 //--------------------------------------------------------------
2887 // Search for file descriptors that are inherited from our parent
2888 // p: process_cmd_line_options [for VG_(clo_track_fds)]
2889 //--------------------------------------------------------------
2890 if (VG_(clo_track_fds))
2891 VG_(init_preopened_fds)();
2892
2893 //--------------------------------------------------------------
2894 // Initialise the scheduler
2895 // p: init_baseBlock() [baseBlock regs copied into VG_(threads)[1]]
2896 // p: setup_file_descriptors() [else VG_(safe_fd)() breaks]
2897 //--------------------------------------------------------------
2898 VG_(scheduler_init)();
2899
2900 //--------------------------------------------------------------
2901 // Set up the ProxyLWP machinery
2902 // p: VG_(scheduler_init)()? [XXX: subtle dependency?]
2903 // - subs: VG_(sigstartup_actions)()?
2904 //--------------------------------------------------------------
2905 VG_(proxy_init)();
2906
2907 //--------------------------------------------------------------
2908 // Initialise the signal handling subsystem
2909 // p: VG_(atfork)(NULL, NULL, newpid) [else problems with sigmasks]
2910 // p: VG_(proxy_init)() [else breaks...]
2911 //--------------------------------------------------------------
2912 // Nb: temporarily parks the saved blocking-mask in saved_sigmask.
2913 VG_(sigstartup_actions)();
2914
2915 //--------------------------------------------------------------
2916 // Perhaps we're profiling Valgrind?
2917 // p: process_cmd_line_options() [for VG_(clo_profile)]
2918 // p: others?
2919 //
2920 // XXX: this seems to be broken? It always says the tool wasn't built
2921 // for profiling; vg_profile.c's functions don't seem to be overriding
2922 // vg_dummy_profile.c's?
2923 //
2924 // XXX: want this as early as possible. Looking for --profile
2925 // in pre_process_cmd_line_options() could get it earlier.
2926 //--------------------------------------------------------------
2927 if (VG_(clo_profile))
2928 VGP_(init_profiling)();
2929
2930 VGP_PUSHCC(VgpStartup);
2931
2932 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002933 // Reserve Valgrind's kickstart, heap and stack
2934 // p: XXX ???
2935 //--------------------------------------------------------------
2936 VG_(map_segment)(VG_(valgrind_mmap_end),
2937 VG_(valgrind_end)-VG_(valgrind_mmap_end),
2938 VKI_PROT_NONE, SF_VALGRIND|SF_FIXED);
2939
2940 //--------------------------------------------------------------
2941 // Identify Valgrind's segments
2942 // p: read proc/self/maps
2943 // p: VG_(map_segment) [XXX ???]
2944 // p: sk_pre_clo_init() [to setup new_mem_startup tracker]
2945 //--------------------------------------------------------------
2946 VG_(parse_procselfmaps) ( build_valgrind_map_callback );
2947
2948 // XXX: I can't see why these two need to be separate; could they be
2949 // folded together? If not, need a comment explaining why.
2950 //
2951 // XXX: can we merge reading and parsing of /proc/self/maps?
2952 //
2953 // XXX: can we dynamically allocate the /proc/self/maps buffer? (or mmap
2954 // it?) Or does that disturb its contents...
2955
2956 //--------------------------------------------------------------
2957 // Build segment map (all segments)
2958 // p: setup_client_stack() [for 'esp_at_startup']
2959 //--------------------------------------------------------------
2960 esp_at_startup___global_arg = esp_at_startup;
2961 VG_(parse_procselfmaps) ( build_segment_map_callback ); /* everything */
2962 esp_at_startup___global_arg = 0;
2963
2964 //==============================================================
2965 // Can only use VG_(map)() after VG_(map_segment)() [XXX ???]
2966 //==============================================================
2967
2968 //--------------------------------------------------------------
2969 // Build segment map (all segments)
2970 // p: setup_client_stack() [for 'esp_at_startup']
2971 //--------------------------------------------------------------
2972 /* Initialize our trampoline page (which is also sysinfo stuff) */
2973 VG_(memcpy)( (void *)VG_(client_trampoline_code),
2974 &VG_(trampoline_code_start), VG_(trampoline_code_length) );
2975 VG_(mprotect)( (void *)VG_(client_trampoline_code),
2976 VG_(trampoline_code_length), VKI_PROT_READ|VKI_PROT_EXEC );
2977
2978 //--------------------------------------------------------------
2979 // Read suppression file
2980 // p: process_cmd_line_options() [for VG_(clo_suppressions)]
2981 //--------------------------------------------------------------
2982 if (VG_(needs).core_errors || VG_(needs).skin_errors)
2983 VG_(load_suppressions)();
2984
2985 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002986 // Initialise translation table and translation cache
2987 // p: read_procselfmaps [so the anonymous mmaps for the TT/TC
2988 // aren't identified as part of the client, which would waste
2989 // > 20M of virtual address space.]
2990 //--------------------------------------------------------------
2991 VG_(init_tt_tc)();
2992
2993 //--------------------------------------------------------------
2994 // Read debug info to find glibc entry points to intercept
2995 // p: parse_procselfmaps? [XXX for debug info?]
2996 // p: init_tt_tc? [XXX ???]
2997 //--------------------------------------------------------------
2998 VG_(setup_code_redirect_table)();
2999
3000 //--------------------------------------------------------------
3001 // Verbosity message
3002 // p: end_rdtsc_calibration [so startup message is printed first]
3003 //--------------------------------------------------------------
3004 if (VG_(clo_verbosity) == 1)
3005 VG_(message)(Vg_UserMsg, "For more details, rerun with: -v");
3006 if (VG_(clo_verbosity) > 0)
3007 VG_(message)(Vg_UserMsg, "");
3008
3009 //--------------------------------------------------------------
3010 // Setup pointercheck
3011 // p: process_cmd_line_options() [for VG_(clo_pointercheck)]
3012 //--------------------------------------------------------------
3013 setup_pointercheck();
3014
3015
3016
3017 //--------------------------------------------------------------
3018 // Run!
3019 //--------------------------------------------------------------
3020 VG_(running_on_simd_CPU) = True;
3021 VGP_POPCC(VgpStartup);
3022 VGP_PUSHCC(VgpSched);
3023
3024 if (__builtin_setjmp(&VG_(fatal_signal_jmpbuf)) == 0) {
3025 VG_(fatal_signal_set) = True;
3026 src = VG_(scheduler)();
3027 } else
3028 src = VgSrc_FatalSig;
3029
3030 VGP_POPCC(VgpSched);
3031 VG_(running_on_simd_CPU) = False;
3032
3033
3034
3035 //--------------------------------------------------------------
3036 // Finalisation: cleanup, messages, etc. Order no so important, only
3037 // affects what order the messages come.
3038 //--------------------------------------------------------------
3039 if (VG_(clo_verbosity) > 0)
3040 VG_(message)(Vg_UserMsg, "");
3041
3042 if (src == VgSrc_Deadlock) {
3043 VG_(message)(Vg_UserMsg,
3044 "Warning: pthread scheduler exited due to deadlock");
3045 }
3046
3047 /* Print out file descriptor summary and stats. */
3048 if (VG_(clo_track_fds))
3049 VG_(fd_stats)();
3050
3051 if (VG_(needs).core_errors || VG_(needs).skin_errors)
3052 VG_(show_all_errors)();
3053
3054 SK_(fini)( VG_(exitcode) );
3055
3056 VG_(do_sanity_checks)( True /*include expensive checks*/ );
3057
3058 if (VG_(clo_verbosity) > 1)
3059 show_counts();
3060
3061 if (VG_(clo_verbosity) > 3)
3062 VG_(print_UInstr_histogram)();
3063
3064 if (0) {
3065 VG_(message)(Vg_DebugMsg, "");
3066 VG_(message)(Vg_DebugMsg,
3067 "------ Valgrind's internal memory use stats follow ------" );
3068 VG_(mallocSanityCheckAll)();
3069 VG_(show_all_arena_stats)();
3070 VG_(message)(Vg_DebugMsg,
3071 "------ Valgrind's ExeContext management stats follow ------" );
3072 VG_(show_ExeContext_stats)();
3073 }
3074
3075 if (VG_(clo_profile))
3076 VGP_(done_profiling)();
3077
3078 /* Must be after all messages are done */
3079 VG_(shutdown_logging)();
3080
3081 /* We're exiting, so nuke all the threads and clean up the proxy LWPs */
3082 vg_assert(src == VgSrc_FatalSig ||
3083 VG_(threads)[VG_(last_run_tid)].status == VgTs_Runnable ||
3084 VG_(threads)[VG_(last_run_tid)].status == VgTs_WaitJoiner);
3085 VG_(nuke_all_threads_except)(VG_INVALID_THREADID);
3086
3087 //--------------------------------------------------------------
3088 // Exit, according to the scheduler's return code
3089 //--------------------------------------------------------------
3090 switch (src) {
3091 case VgSrc_ExitSyscall: /* the normal way out */
3092 vg_assert(VG_(last_run_tid) > 0
3093 && VG_(last_run_tid) < VG_N_THREADS);
3094 VG_(proxy_shutdown)();
3095
3096 /* The thread's %EBX at the time it did __NR_exit() will hold
3097 the arg to __NR_exit(), so we just do __NR_exit() with
3098 that arg. */
3099 VG_(exit)( VG_(exitcode) );
3100 /* NOT ALIVE HERE! */
3101 VG_(core_panic)("entered the afterlife in main() -- ExitSyscall");
3102 break; /* what the hell :) */
3103
3104 case VgSrc_Deadlock:
3105 /* Just exit now. No point in continuing. */
3106 VG_(proxy_shutdown)();
3107 VG_(exit)(0);
3108 VG_(core_panic)("entered the afterlife in main() -- Deadlock");
3109 break;
3110
nethercote71980f02004-01-24 18:18:54 +00003111 case VgSrc_FatalSig:
3112 /* We were killed by a fatal signal, so replicate the effect */
3113 vg_assert(VG_(fatal_sigNo) != -1);
3114 VG_(kill_self)(VG_(fatal_sigNo));
3115 VG_(core_panic)("main(): signal was supposed to be fatal");
3116 break;
3117
3118 default:
3119 VG_(core_panic)("main(): unexpected scheduler return code");
3120 }
3121
3122 abort();
3123}
3124
3125
sewardjde4a1d02002-03-22 01:27:54 +00003126/*--------------------------------------------------------------------*/
3127/*--- end vg_main.c ---*/
3128/*--------------------------------------------------------------------*/