blob: 4b187f055423e0a67169185e4164939e09c0c6fe [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
thughes74b8de22004-04-22 18:12:31 +000053#ifndef AT_DCACHEBSIZE
54#define AT_DCACHEBSIZE 19
55#endif /* AT_DCACHEBSIZE */
56
57#ifndef AT_ICACHEBSIZE
58#define AT_ICACHEBSIZE 20
59#endif /* AT_ICACHEBSIZE */
60
61#ifndef AT_UCACHEBSIZE
62#define AT_UCACHEBSIZE 21
63#endif /* AT_UCACHEBSIZE */
64
nethercote71980f02004-01-24 18:18:54 +000065#ifndef AT_SYSINFO
66#define AT_SYSINFO 32
67#endif /* AT_SYSINFO */
68
69#ifndef AT_SYSINFO_EHDR
70#define AT_SYSINFO_EHDR 33
71#endif /* AT_SYSINFO_EHDR */
72
73#ifndef AT_SECURE
74#define AT_SECURE 23 /* secure mode boolean */
75#endif /* AT_SECURE */
76
nethercote71980f02004-01-24 18:18:54 +000077/* Amount to reserve for Valgrind's internal mappings */
78#define VALGRIND_MAPSIZE (128*1024*1024)
79
80/* redzone gap between client address space and shadow */
81#define REDZONE_SIZE (1 * 1024*1024)
82
83/* size multiple for client address space */
nethercotee94b2de2004-06-23 16:15:06 +000084#define CLIENT_SIZE_MULTIPLE (1 * 1024*1024)
nethercote71980f02004-01-24 18:18:54 +000085
nethercotee2097312004-06-27 12:29:56 +000086/* Proportion of client space for its heap (rest is for mmaps + stack) */
87#define CLIENT_HEAP_PROPORTION 0.333
nethercote71980f02004-01-24 18:18:54 +000088
89/*====================================================================*/
90/*=== Global entities not referenced from generated code ===*/
91/*====================================================================*/
92
sewardjde4a1d02002-03-22 01:27:54 +000093/* ---------------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +000094 Startup stuff
sewardjde4a1d02002-03-22 01:27:54 +000095 ------------------------------------------------------------------ */
nethercote71980f02004-01-24 18:18:54 +000096/* linker-defined base address */
97extern char kickstart_base;
sewardjde4a1d02002-03-22 01:27:54 +000098
nethercote71980f02004-01-24 18:18:54 +000099/* Client address space, lowest to highest (see top of ume.c) */
100Addr VG_(client_base); /* client address space limits */
fitzhardinge98abfc72003-12-16 02:05:15 +0000101Addr VG_(client_end);
102Addr VG_(client_mapbase);
fitzhardinge92360792003-12-24 10:11:11 +0000103Addr VG_(client_trampoline_code);
fitzhardinge98abfc72003-12-16 02:05:15 +0000104Addr VG_(clstk_base);
105Addr VG_(clstk_end);
nethercote71980f02004-01-24 18:18:54 +0000106
107Addr VG_(brk_base); /* start of brk */
108Addr VG_(brk_limit); /* current brk */
109
110Addr VG_(shadow_base); /* skin's shadow memory */
fitzhardinge98abfc72003-12-16 02:05:15 +0000111Addr VG_(shadow_end);
nethercote71980f02004-01-24 18:18:54 +0000112
113Addr VG_(valgrind_base); /* valgrind's address range */
114Addr VG_(valgrind_mmap_end); /* valgrind's mmaps are between valgrind_base and here */
fitzhardinge98abfc72003-12-16 02:05:15 +0000115Addr VG_(valgrind_end);
116
fitzhardingeb50068f2004-02-24 23:42:55 +0000117vki_rlimit VG_(client_rlimit_data);
118
nethercote71980f02004-01-24 18:18:54 +0000119/* This is set early to indicate whether this CPU has the
120 SSE/fxsave/fxrestor features. */
121Bool VG_(have_ssestate);
122
123/* Indicates presence, and holds address of client's sysinfo page, a
124 feature of some modern kernels used to provide vsyscalls, etc. */
125Bool VG_(sysinfo_page_exists) = False;
126Addr VG_(sysinfo_page_addr) = 0;
127
fitzhardinge98abfc72003-12-16 02:05:15 +0000128/* stage1 (main) executable */
fitzhardingea49f9b52003-12-16 22:26:45 +0000129Int VG_(vgexecfd) = -1;
130
131/* client executable */
132Int VG_(clexecfd) = -1;
fitzhardinge98abfc72003-12-16 02:05:15 +0000133
134/* Path to library directory */
135const Char *VG_(libdir) = VG_LIBDIR;
136
137/* our argc/argv */
138Int VG_(vg_argc);
139Char **VG_(vg_argv);
140
jsgf855d93d2003-10-13 22:26:55 +0000141/* PID of the main thread */
142Int VG_(main_pid);
143
144/* PGRP of process */
145Int VG_(main_pgrp);
njn25e49d8e72002-09-23 09:36:25 +0000146
thughesad1c9562004-06-26 11:27:52 +0000147/* Application-visible file descriptor limits */
148Int VG_(fd_soft_limit) = -1;
149Int VG_(fd_hard_limit) = -1;
fitzhardingef0046f22003-12-18 02:39:22 +0000150
nethercote71980f02004-01-24 18:18:54 +0000151/* As deduced from esp_at_startup, the client's argc, argv[] and
152 envp[] as extracted from the client's stack at startup-time. */
153Int VG_(client_argc);
154Char** VG_(client_argv);
155Char** VG_(client_envp);
sewardjde4a1d02002-03-22 01:27:54 +0000156
157/* ---------------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +0000158 Running stuff
sewardjde4a1d02002-03-22 01:27:54 +0000159 ------------------------------------------------------------------ */
nethercote71980f02004-01-24 18:18:54 +0000160/* Our signal delivery stack. */
njn6eba4ef2003-05-01 08:06:41 +0000161UInt VG_(sigstack)[VG_SIGSTACK_SIZE_W];
sewardjde4a1d02002-03-22 01:27:54 +0000162
nethercote71980f02004-01-24 18:18:54 +0000163/* jmp_buf for fatal signals */
164Int VG_(fatal_sigNo) = -1;
165Bool VG_(fatal_signal_set) = False;
166jmp_buf VG_(fatal_signal_jmpbuf);
sewardjde4a1d02002-03-22 01:27:54 +0000167
nethercote71980f02004-01-24 18:18:54 +0000168/* Counts downwards in VG_(run_innerloop). */
169UInt VG_(dispatch_ctr);
sewardjde4a1d02002-03-22 01:27:54 +0000170
171/* 64-bit counter for the number of basic blocks done. */
172ULong VG_(bbs_done);
sewardjde4a1d02002-03-22 01:27:54 +0000173
sewardj7e87e382002-05-03 19:09:05 +0000174/* This is the ThreadId of the last thread the scheduler ran. */
175ThreadId VG_(last_run_tid) = 0;
176
nethercote71980f02004-01-24 18:18:54 +0000177/* Tell the logging mechanism whether we are logging to a file
178 descriptor or a socket descriptor. */
179Bool VG_(logging_to_filedes) = True;
180
sewardj73cf3bc2002-11-03 03:20:15 +0000181
nethercote71980f02004-01-24 18:18:54 +0000182/*====================================================================*/
183/*=== Counters, for profiling purposes only ===*/
184/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +0000185
186/* Number of lookups which miss the fast tt helper. */
187UInt VG_(tt_fast_misses) = 0;
188
189
sewardjc0d8f682002-11-30 00:49:43 +0000190/* Counts for TT/TC informational messages. */
sewardjde4a1d02002-03-22 01:27:54 +0000191
sewardjde4a1d02002-03-22 01:27:54 +0000192/* Number and total o/t size of translations overall. */
193UInt VG_(overall_in_count) = 0;
194UInt VG_(overall_in_osize) = 0;
195UInt VG_(overall_in_tsize) = 0;
196/* Number and total o/t size of discards overall. */
197UInt VG_(overall_out_count) = 0;
198UInt VG_(overall_out_osize) = 0;
199UInt VG_(overall_out_tsize) = 0;
sewardjc0d8f682002-11-30 00:49:43 +0000200/* The number of discards of TT/TC. */
201UInt VG_(number_of_tc_discards) = 0;
sewardj22854b92002-11-30 14:00:47 +0000202/* Counts of chain and unchain operations done. */
203UInt VG_(bb_enchain_count) = 0;
204UInt VG_(bb_dechain_count) = 0;
205/* Number of unchained jumps performed. */
206UInt VG_(unchained_jumps_done) = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000207
208
209/* Counts pertaining to the register allocator. */
210
211/* total number of uinstrs input to reg-alloc */
212UInt VG_(uinstrs_prealloc) = 0;
213
214/* total number of uinstrs added due to spill code */
215UInt VG_(uinstrs_spill) = 0;
216
217/* number of bbs requiring spill code */
218UInt VG_(translations_needing_spill) = 0;
219
220/* total of register ranks over all translations */
221UInt VG_(total_reg_rank) = 0;
222
223
sewardjde4a1d02002-03-22 01:27:54 +0000224/* Counts pertaining to internal sanity checking. */
sewardjde4a1d02002-03-22 01:27:54 +0000225UInt VG_(sanity_fast_count) = 0;
226UInt VG_(sanity_slow_count) = 0;
227
sewardj2e93c502002-04-12 11:12:52 +0000228/* Counts pertaining to the scheduler. */
229UInt VG_(num_scheduling_events_MINOR) = 0;
230UInt VG_(num_scheduling_events_MAJOR) = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000231
232
nethercote71980f02004-01-24 18:18:54 +0000233static __inline__ Int safe_idiv(Int a, Int b)
234{
235 return (b == 0 ? 0 : a / b);
236}
237
238static void show_counts ( void )
239{
240 VG_(message)(Vg_DebugMsg,
241 " TT/TC: %d tc sectors discarded.",
242 VG_(number_of_tc_discards) );
243 VG_(message)(Vg_DebugMsg,
244 " %d chainings, %d unchainings.",
245 VG_(bb_enchain_count), VG_(bb_dechain_count) );
246 VG_(message)(Vg_DebugMsg,
247 "translate: new %d (%d -> %d; ratio %d:10)",
248 VG_(overall_in_count),
249 VG_(overall_in_osize),
250 VG_(overall_in_tsize),
251 safe_idiv(10*VG_(overall_in_tsize), VG_(overall_in_osize)));
252 VG_(message)(Vg_DebugMsg,
253 " discard %d (%d -> %d; ratio %d:10).",
254 VG_(overall_out_count),
255 VG_(overall_out_osize),
256 VG_(overall_out_tsize),
257 safe_idiv(10*VG_(overall_out_tsize), VG_(overall_out_osize)));
258 VG_(message)(Vg_DebugMsg,
259 " dispatch: %llu jumps (bb entries), of which %u (%lu%%) were unchained.",
260 VG_(bbs_done),
261 VG_(unchained_jumps_done),
262 ((ULong)(100) * (ULong)(VG_(unchained_jumps_done)))
263 / ( VG_(bbs_done)==0 ? 1 : VG_(bbs_done) )
264 );
265
266 VG_(message)(Vg_DebugMsg,
267 " %d/%d major/minor sched events. %d tt_fast misses.",
268 VG_(num_scheduling_events_MAJOR),
269 VG_(num_scheduling_events_MINOR),
270 VG_(tt_fast_misses));
271
272 VG_(message)(Vg_DebugMsg,
273 "reg-alloc: %d t-req-spill, "
274 "%d+%d orig+spill uis, %d total-reg-r.",
275 VG_(translations_needing_spill),
276 VG_(uinstrs_prealloc),
277 VG_(uinstrs_spill),
278 VG_(total_reg_rank) );
279 VG_(message)(Vg_DebugMsg,
280 " sanity: %d cheap, %d expensive checks.",
281 VG_(sanity_fast_count),
282 VG_(sanity_slow_count) );
283 VG_(print_ccall_stats)();
284}
285
286
287/*====================================================================*/
288/*=== Miscellaneous global functions ===*/
289/*====================================================================*/
290
nethercote04d0fbc2004-01-26 16:48:06 +0000291/* Start debugger and get it to attach to this process. Called if the
292 user requests this service after an error has been shown, so she can
nethercote71980f02004-01-24 18:18:54 +0000293 poke around and look at parameters, memory, etc. You can't
nethercote04d0fbc2004-01-26 16:48:06 +0000294 meaningfully get the debugger to continue the program, though; to
295 continue, quit the debugger. */
296void VG_(start_debugger) ( Int tid )
nethercote71980f02004-01-24 18:18:54 +0000297{
298 Int pid;
299
300 if ((pid = fork()) == 0) {
301 ptrace(PTRACE_TRACEME, 0, NULL, NULL);
302 VG_(kkill)(VG_(getpid)(), VKI_SIGSTOP);
303
304 } else if (pid > 0) {
305 struct user_regs_struct regs;
306 Int status;
307 Int res;
308
309 if (VG_(is_running_thread)( tid )) {
fitzhardinged65dcad2004-03-13 02:06:58 +0000310 regs.cs = VG_(baseBlock)[VGOFF_(m_cs)];
311 regs.ss = VG_(baseBlock)[VGOFF_(m_ss)];
312 regs.ds = VG_(baseBlock)[VGOFF_(m_ds)];
313 regs.es = VG_(baseBlock)[VGOFF_(m_es)];
314 regs.fs = VG_(baseBlock)[VGOFF_(m_fs)];
315 regs.gs = VG_(baseBlock)[VGOFF_(m_gs)];
nethercote71980f02004-01-24 18:18:54 +0000316 regs.eax = VG_(baseBlock)[VGOFF_(m_eax)];
317 regs.ebx = VG_(baseBlock)[VGOFF_(m_ebx)];
318 regs.ecx = VG_(baseBlock)[VGOFF_(m_ecx)];
319 regs.edx = VG_(baseBlock)[VGOFF_(m_edx)];
320 regs.esi = VG_(baseBlock)[VGOFF_(m_esi)];
321 regs.edi = VG_(baseBlock)[VGOFF_(m_edi)];
322 regs.ebp = VG_(baseBlock)[VGOFF_(m_ebp)];
323 regs.esp = VG_(baseBlock)[VGOFF_(m_esp)];
324 regs.eflags = VG_(baseBlock)[VGOFF_(m_eflags)];
325 regs.eip = VG_(baseBlock)[VGOFF_(m_eip)];
326 } else {
327 ThreadState* tst = & VG_(threads)[ tid ];
328
fitzhardinged65dcad2004-03-13 02:06:58 +0000329 regs.cs = tst->m_cs;
330 regs.ss = tst->m_ss;
331 regs.ds = tst->m_ds;
332 regs.es = tst->m_es;
333 regs.fs = tst->m_fs;
334 regs.gs = tst->m_gs;
nethercote71980f02004-01-24 18:18:54 +0000335 regs.eax = tst->m_eax;
336 regs.ebx = tst->m_ebx;
337 regs.ecx = tst->m_ecx;
338 regs.edx = tst->m_edx;
339 regs.esi = tst->m_esi;
340 regs.edi = tst->m_edi;
341 regs.ebp = tst->m_ebp;
342 regs.esp = tst->m_esp;
343 regs.eflags = tst->m_eflags;
344 regs.eip = tst->m_eip;
345 }
346
347 if ((res = VG_(waitpid)(pid, &status, 0)) == pid &&
348 WIFSTOPPED(status) && WSTOPSIG(status) == SIGSTOP &&
349 ptrace(PTRACE_SETREGS, pid, NULL, &regs) == 0 &&
thughes1d160052004-04-21 15:39:57 +0000350 kill(pid, SIGSTOP) == 0 &&
351 ptrace(PTRACE_DETACH, pid, NULL, 0) == 0) {
nethercote04d0fbc2004-01-26 16:48:06 +0000352 Char pidbuf[15];
353 Char file[30];
354 Char buf[100];
355 Char *bufptr;
356 Char *cmdptr;
357
358 VG_(sprintf)(pidbuf, "%d", pid);
359 VG_(sprintf)(file, "/proc/%d/fd/%d", pid, VG_(clexecfd));
360
361 bufptr = buf;
362 cmdptr = VG_(clo_db_command);
363
364 while (*cmdptr) {
365 switch (*cmdptr) {
366 case '%':
367 switch (*++cmdptr) {
368 case 'f':
369 VG_(memcpy)(bufptr, file, VG_(strlen)(file));
370 bufptr += VG_(strlen)(file);
371 cmdptr++;
372 break;
373 case 'p':
374 VG_(memcpy)(bufptr, pidbuf, VG_(strlen)(pidbuf));
375 bufptr += VG_(strlen)(pidbuf);
376 cmdptr++;
377 break;
378 default:
379 *bufptr++ = *cmdptr++;
380 break;
381 }
382 break;
383 default:
384 *bufptr++ = *cmdptr++;
385 break;
386 }
387 }
388
389 *bufptr++ = '\0';
390
391 VG_(message)(Vg_UserMsg, "starting debugger with cmd: %s", buf);
nethercote71980f02004-01-24 18:18:54 +0000392 res = VG_(system)(buf);
393 if (res == 0) {
394 VG_(message)(Vg_UserMsg, "");
395 VG_(message)(Vg_UserMsg,
nethercote04d0fbc2004-01-26 16:48:06 +0000396 "Debugger has detached. Valgrind regains control. We continue.");
nethercote71980f02004-01-24 18:18:54 +0000397 } else {
398 VG_(message)(Vg_UserMsg, "Apparently failed!");
399 VG_(message)(Vg_UserMsg, "");
400 }
401 }
402
403 VG_(kkill)(pid, VKI_SIGKILL);
404 VG_(waitpid)(pid, &status, 0);
405 }
406}
407
408
409/* Print some helpful-ish text about unimplemented things, and give
410 up. */
411void VG_(unimplemented) ( Char* msg )
412{
413 VG_(message)(Vg_UserMsg, "");
414 VG_(message)(Vg_UserMsg,
415 "Valgrind detected that your program requires");
416 VG_(message)(Vg_UserMsg,
417 "the following unimplemented functionality:");
418 VG_(message)(Vg_UserMsg, " %s", msg);
419 VG_(message)(Vg_UserMsg,
420 "This may be because the functionality is hard to implement,");
421 VG_(message)(Vg_UserMsg,
422 "or because no reasonable program would behave this way,");
423 VG_(message)(Vg_UserMsg,
424 "or because nobody has yet needed it. In any case, let us know at");
425 VG_(message)(Vg_UserMsg,
426 "%s and/or try to work around the problem, if you can.", VG_BUGS_TO);
427 VG_(message)(Vg_UserMsg,
428 "");
429 VG_(message)(Vg_UserMsg,
430 "Valgrind has to exit now. Sorry. Bye!");
431 VG_(message)(Vg_UserMsg,
432 "");
433 VG_(pp_sched_status)();
434 VG_(exit)(1);
435}
436
437Addr VG_(get_stack_pointer) ( void )
438{
439 return VG_(baseBlock)[VGOFF_(m_esp)];
440}
441
442/* Debugging thing .. can be called from assembly with OYNK macro. */
443void VG_(oynk) ( Int n )
444{
445 OINK(n);
446}
447
448/* Initialize the PID and PGRP of scheduler LWP; this is also called
449 in any new children after fork. */
450static void newpid(ThreadId unused)
451{
452 /* PID of scheduler LWP */
453 VG_(main_pid) = VG_(getpid)();
454 VG_(main_pgrp) = VG_(getpgrp)();
455}
456
457/*====================================================================*/
458/*=== Check we were launched by stage 1 ===*/
459/*====================================================================*/
460
461/* Look for our AUXV table */
462static void scan_auxv(void)
463{
464 const struct ume_auxv *auxv = find_auxv((int *)ume_exec_esp);
465 int found = 0;
466
467 for (; auxv->a_type != AT_NULL; auxv++)
468 switch(auxv->a_type) {
469 case AT_UME_PADFD:
470 as_setpadfd(auxv->u.a_val);
471 found |= 1;
472 break;
473
474 case AT_UME_EXECFD:
475 VG_(vgexecfd) = auxv->u.a_val;
476 found |= 2;
477 break;
478 }
479
480 if ( ! (1|2) ) {
481 fprintf(stderr, "stage2 must be launched by stage1\n");
482 exit(127);
483 }
484}
485
486
487/*====================================================================*/
488/*=== Address space determination ===*/
489/*====================================================================*/
490
491/* Pad client space so it doesn't get filled in before the right time */
492static void layout_client_space(Addr argc_addr)
493{
494 VG_(client_base) = CLIENT_BASE;
495 VG_(valgrind_mmap_end) = (addr_t)&kickstart_base; /* end of V's mmaps */
496 VG_(valgrind_base) = VG_(valgrind_mmap_end) - VALGRIND_MAPSIZE;
497 VG_(valgrind_end) = ROUNDUP(argc_addr, 0x10000); /* stack */
498
nethercote71980f02004-01-24 18:18:54 +0000499 as_pad((void *)VG_(client_base), (void *)VG_(valgrind_base));
500}
501
502static void layout_remaining_space(float ratio)
503{
504 /* This tries to give the client as large as possible address space while
505 * taking into account the tool's shadow needs. */
506 addr_t client_size = ROUNDDN((VG_(valgrind_base) - REDZONE_SIZE) / (1. + ratio),
507 CLIENT_SIZE_MULTIPLE);
508 addr_t shadow_size = PGROUNDUP(client_size * ratio);
509
510 VG_(client_end) = VG_(client_base) + client_size;
511 VG_(client_mapbase) = PGROUNDDN((client_size/4)*3); /* where !FIXED mmap goes */
nethercotee2097312004-06-27 12:29:56 +0000512
513 /* where !FIXED mmap goes */
514 VG_(client_mapbase) = PGROUNDDN((addr_t)(client_size * CLIENT_HEAP_PROPORTION));
nethercote71980f02004-01-24 18:18:54 +0000515 VG_(client_trampoline_code) = VG_(client_end) - VKI_BYTES_PER_PAGE;
516
517 VG_(shadow_base) = VG_(client_end) + REDZONE_SIZE;
518 VG_(shadow_end) = VG_(shadow_base) + shadow_size;
519
nethercotee2097312004-06-27 12:29:56 +0000520#define SEGSIZE(a,b) ((VG_(b) - VG_(a))/(1024*1024))
521
nethercote71980f02004-01-24 18:18:54 +0000522 if (0)
nethercotee2097312004-06-27 12:29:56 +0000523 VG_(printf)(
524 "client_base %8x (%dMB)\n"
525 "client_mapbase %8x (%dMB)\n"
526 "client_end %8x (%dMB)\n"
527 "shadow_base %8x (%dMB)\n"
528 "shadow_end %8x (%dMB)\n"
529 "valgrind_base %8x (%dMB)\n"
530 "valgrind_mmap_end %8x (%dMB)\n"
531 "valgrind_end %8x\n",
532 VG_(client_base), SEGSIZE(client_base, client_mapbase),
533 VG_(client_mapbase), SEGSIZE(client_mapbase, client_end),
534 VG_(client_end), SEGSIZE(client_end, shadow_base),
535 VG_(shadow_base), SEGSIZE(shadow_base, shadow_end),
536 VG_(shadow_end), SEGSIZE(shadow_end, valgrind_base),
537 VG_(valgrind_base), SEGSIZE(valgrind_base, valgrind_mmap_end),
538 VG_(valgrind_mmap_end), SEGSIZE(valgrind_mmap_end, valgrind_end),
539 VG_(valgrind_end)
540 );
541
542#undef SEGSIZE
nethercote71980f02004-01-24 18:18:54 +0000543
544 // Ban redzone
545 mmap((void *)VG_(client_end), REDZONE_SIZE, PROT_NONE,
546 MAP_FIXED|MAP_ANON|MAP_PRIVATE, -1, 0);
547
548 // Make client hole
549 munmap((void*)VG_(client_base), client_size);
550
551 // Map shadow memory.
552 // Initially all inaccessible, incrementally initialized as it is used
553 if (shadow_size != 0)
554 mmap((char *)VG_(shadow_base), shadow_size, PROT_NONE,
555 MAP_PRIVATE|MAP_ANON|MAP_FIXED, -1, 0);
556}
557
558/*====================================================================*/
559/*=== Command line setup ===*/
560/*====================================================================*/
561
562/* Nb: malloc'd memory never freed -- kept throughout like argv, envp */
563static char* get_file_clo(char* dir)
564{
565# define FLEN 512
566 Int fd, n;
567 struct stat s1;
568 char* f_clo = NULL;
569 char filename[FLEN];
570
571 snprintf(filename, FLEN, "%s/.valgrindrc", ( NULL == dir ? "" : dir ) );
572 fd = VG_(open)(filename, 0, VKI_S_IRUSR);
573 if ( fd > 0 ) {
574 if ( 0 == fstat(fd, &s1) ) {
575 f_clo = malloc(s1.st_size+1);
576 vg_assert(f_clo);
577 n = read(fd, f_clo, s1.st_size);
578 if (n == -1) n = 0;
579 f_clo[n] = '\0';
580 }
581 close(fd);
582 }
583 return f_clo;
584# undef FLEN
585}
586
nethercotee2097312004-06-27 12:29:56 +0000587#define ISSPACE(cc) ((cc) == ' ' || (cc) == '\t' || (cc) == '\n')
588
nethercote71980f02004-01-24 18:18:54 +0000589static Int count_args(char* s)
590{
591 Int n = 0;
592 if (s) {
593 char* cp = s;
594 while (True) {
595 // We have alternating sequences: blanks, non-blanks, blanks...
596 // count the non-blanks sequences.
597 while ( ISSPACE(*cp) ) cp++;
598 if ( !*cp ) break;
599 n++;
600 while ( !ISSPACE(*cp) && *cp ) cp++;
601 }
602 }
603 return n;
604}
605
606/* add args out of environment, skipping multiple spaces and -- args */
607static char** copy_args( char* s, char** to )
608{
609 if (s) {
610 char* cp = s;
611 while (True) {
612 // We have alternating sequences: blanks, non-blanks, blanks...
613 // copy the non-blanks sequences, and add terminating '\0'
614 while ( ISSPACE(*cp) ) cp++;
615 if ( !*cp ) break;
616 *to++ = cp;
617 while ( !ISSPACE(*cp) && *cp ) cp++;
618 if ( *cp ) *cp++ = '\0'; // terminate if necessary
619 if (VG_STREQ(to[-1], "--")) to--; // undo any '--' arg
620 }
621 }
622 return to;
623}
624
nethercotee2097312004-06-27 12:29:56 +0000625#undef ISSPACE
626
nethercote71980f02004-01-24 18:18:54 +0000627// Augment command line with arguments from environment and .valgrindrc
628// files.
629static void augment_command_line(Int* vg_argc_inout, char*** vg_argv_inout)
630{
631 int vg_argc = *vg_argc_inout;
632 char** vg_argv = *vg_argv_inout;
633
634 char* env_clo = getenv(VALGRINDOPTS);
635 char* f1_clo = get_file_clo( getenv("HOME") );
636 char* f2_clo = get_file_clo(".");
637
638 /* copy any extra args from file or environment, if present */
639 if ( (env_clo && *env_clo) || (f1_clo && *f1_clo) || (f2_clo && *f2_clo) ) {
640 /* ' ' separated extra options */
641 char **from;
642 char **to;
643 int env_arg_count, f1_arg_count, f2_arg_count;
644
645 env_arg_count = count_args(env_clo);
646 f1_arg_count = count_args(f1_clo);
647 f2_arg_count = count_args(f2_clo);
648
649 if (0)
650 printf("extra-argc=%d %d %d\n",
651 env_arg_count, f1_arg_count, f2_arg_count);
652
653 /* +2: +1 for null-termination, +1 for added '--' */
654 from = vg_argv;
655 vg_argv = malloc( (vg_argc + env_arg_count + f1_arg_count
656 + f2_arg_count + 2) * sizeof(char **));
657 to = vg_argv;
658
659 /* copy argv[0] */
660 *to++ = *from++;
661
662 /* Copy extra args from env var and file, in the order: ~/.valgrindrc,
663 * $VALGRIND_OPTS, ./.valgrindrc -- more local options are put later
664 * to override less local ones. */
665 to = copy_args(f1_clo, to);
666 to = copy_args(env_clo, to);
667 to = copy_args(f2_clo, to);
668
669 /* copy original arguments, stopping at command or -- */
670 while (*from) {
671 if (**from != '-')
672 break;
673 if (VG_STREQ(*from, "--")) {
674 from++; /* skip -- */
675 break;
676 }
677 *to++ = *from++;
678 }
679
680 /* add -- */
681 *to++ = "--";
682
683 vg_argc = to - vg_argv;
684
685 /* copy rest of original command line, then NULL */
686 while (*from) *to++ = *from++;
687 *to = NULL;
688 }
689
690 *vg_argc_inout = vg_argc;
691 *vg_argv_inout = vg_argv;
692}
693
694static void get_command_line( int argc, char** argv,
695 Int* vg_argc_out, Char*** vg_argv_out,
696 char*** cl_argv_out )
697{
698 int vg_argc;
699 char** vg_argv;
700 char** cl_argv;
701 char* env_clo = getenv(VALGRINDCLO);
702
703 if (env_clo != NULL && *env_clo != '\0') {
704 char *cp;
705 char **cpp;
706
707 /* OK, we're getting all our arguments from the environment - the
708 entire command line belongs to the client (including argv[0]) */
709 vg_argc = 1; /* argv[0] */
710 for (cp = env_clo; *cp; cp++)
711 if (*cp == '\01')
712 vg_argc++;
713
714 vg_argv = malloc(sizeof(char **) * (vg_argc + 1));
715
716 cpp = vg_argv;
717
718 *cpp++ = "valgrind"; /* nominal argv[0] */
719 *cpp++ = env_clo;
720
721 for (cp = env_clo; *cp; cp++) {
722 if (*cp == '\01') {
723 *cp++ = '\0'; /* chop it up in place */
724 *cpp++ = cp;
725 }
726 }
727 *cpp = NULL;
728 cl_argv = argv;
729
730 } else {
731 /* Count the arguments on the command line. */
732 vg_argv = argv;
733
734 for (vg_argc = 1; vg_argc < argc; vg_argc++) {
735 if (argv[vg_argc][0] != '-') /* exe name */
736 break;
737 if (VG_STREQ(argv[vg_argc], "--")) { /* dummy arg */
738 vg_argc++;
739 break;
740 }
741 }
742 cl_argv = &argv[vg_argc];
743
744 /* Get extra args from VALGRIND_OPTS and .valgrindrc files.
745 * Note we don't do this if getting args from VALGRINDCLO. */
746 augment_command_line(&vg_argc, &vg_argv);
747 }
748
749 if (0) {
750 Int i;
751 for (i = 0; i < vg_argc; i++)
752 printf("vg_argv[%d]=\"%s\"\n", i, vg_argv[i]);
753 }
754
755 *vg_argc_out = vg_argc;
756 *vg_argv_out = (Char**)vg_argv;
757 *cl_argv_out = cl_argv;
758}
759
760
761/*====================================================================*/
762/*=== Environment and stack setup ===*/
763/*====================================================================*/
764
765/* Scan a colon-separated list, and call a function on each element.
766 The string must be mutable, because we insert a temporary '\0', but
767 the string will end up unmodified. (*func) should return 1 if it
768 doesn't need to see any more.
769*/
770static void scan_colsep(char *colsep, int (*func)(const char *))
771{
772 char *cp, *entry;
773 int end;
774
775 if (colsep == NULL ||
776 *colsep == '\0')
777 return;
778
779 entry = cp = colsep;
780
781 do {
782 end = (*cp == '\0');
783
784 if (*cp == ':' || *cp == '\0') {
785 char save = *cp;
786
787 *cp = '\0';
788 if ((*func)(entry))
789 end = 1;
790 *cp = save;
791 entry = cp+1;
792 }
793 cp++;
794 } while(!end);
795}
796
797/* Prepare the client's environment. This is basically a copy of our
798 environment, except:
799 1. LD_LIBRARY_PATH=$VALGRINDLIB:$LD_LIBRARY_PATH
800 2. LD_PRELOAD=$VALGRINDLIB/vg_inject.so:($VALGRINDLIB/vgpreload_TOOL.so:)?$LD_PRELOAD
801
802 If any of these is missing, then it is added.
803
804 Yummy. String hacking in C.
805
806 If this needs to handle any more variables it should be hacked
807 into something table driven.
808 */
809static char **fix_environment(char **origenv, const char *preload)
810{
811 static const char inject_so[] = "vg_inject.so";
812 static const char ld_library_path[] = "LD_LIBRARY_PATH=";
813 static const char ld_preload[] = "LD_PRELOAD=";
814 static const char valgrind_clo[] = VALGRINDCLO "=";
815 static const int ld_library_path_len = sizeof(ld_library_path)-1;
816 static const int ld_preload_len = sizeof(ld_preload)-1;
817 static const int valgrind_clo_len = sizeof(valgrind_clo)-1;
818 int ld_preload_done = 0;
819 int ld_library_path_done = 0;
820 char *inject_path;
821 int inject_path_len;
822 int vgliblen = strlen(VG_(libdir));
823 char **cpp;
824 char **ret;
825 int envc;
826 const int preloadlen = (preload == NULL) ? 0 : strlen(preload);
827
828 /* Find the vg_inject.so; also make room for the tool preload
829 library */
830 inject_path_len = sizeof(inject_so) + vgliblen + preloadlen + 16;
831 inject_path = malloc(inject_path_len);
832
833 if (preload)
834 snprintf(inject_path, inject_path_len, "%s/%s:%s",
835 VG_(libdir), inject_so, preload);
836 else
837 snprintf(inject_path, inject_path_len, "%s/%s",
838 VG_(libdir), inject_so);
839
840 /* Count the original size of the env */
841 envc = 0; /* trailing NULL */
842 for (cpp = origenv; cpp && *cpp; cpp++)
843 envc++;
844
845 /* Allocate a new space */
846 ret = malloc(sizeof(char *) * (envc+3+1)); /* 3 new entries + NULL */
847
848 /* copy it over */
849 for (cpp = ret; *origenv; )
850 *cpp++ = *origenv++;
851 *cpp = NULL;
852
853 vg_assert(envc == (cpp - ret));
854
855 /* Walk over the new environment, mashing as we go */
856 for (cpp = ret; cpp && *cpp; cpp++) {
857 if (memcmp(*cpp, ld_library_path, ld_library_path_len) == 0) {
858 int done = 0;
859 int contains(const char *p) {
860 if (VG_STREQ(p, VG_(libdir))) {
861 done = 1;
862 return 1;
863 }
864 return 0;
865 }
866
867 /* If the LD_LIBRARY_PATH already contains libdir, then don't
868 bother adding it again, even if it isn't the first (it
869 seems that the Java runtime will keep reexecing itself
870 unless its paths are at the front of LD_LIBRARY_PATH) */
871 scan_colsep(*cpp + ld_library_path_len, contains);
872
873 if (!done) {
874 int len = strlen(*cpp) + vgliblen*2 + 16;
875 char *cp = malloc(len);
876
877 snprintf(cp, len, "%s%s:%s",
878 ld_library_path, VG_(libdir),
879 (*cpp)+ld_library_path_len);
880
881 *cpp = cp;
882 }
883
884 ld_library_path_done = 1;
885 } else if (memcmp(*cpp, ld_preload, ld_preload_len) == 0) {
886 int len = strlen(*cpp) + inject_path_len;
887 char *cp = malloc(len);
888
889 snprintf(cp, len, "%s%s:%s",
890 ld_preload, inject_path, (*cpp)+ld_preload_len);
891
892 *cpp = cp;
893
894 ld_preload_done = 1;
895 } else if (memcmp(*cpp, valgrind_clo, valgrind_clo_len) == 0) {
896 *cpp = "";
897 }
898 }
899
900 /* Add the missing bits */
901
902 if (!ld_library_path_done) {
903 int len = ld_library_path_len + vgliblen*2 + 16;
904 char *cp = malloc(len);
905
906 snprintf(cp, len, "%s%s", ld_library_path, VG_(libdir));
907
908 ret[envc++] = cp;
909 }
910
911 if (!ld_preload_done) {
912 int len = ld_preload_len + inject_path_len;
913 char *cp = malloc(len);
914
915 snprintf(cp, len, "%s%s",
916 ld_preload, inject_path);
917
918 ret[envc++] = cp;
919 }
920
921 ret[envc] = NULL;
922
923 return ret;
924}
925
926extern char **environ; /* our environment */
927//#include <error.h>
928
929/* Add a string onto the string table, and return its address */
930static char *copy_str(char **tab, const char *str)
931{
932 char *cp = *tab;
933 char *orig = cp;
934
935 while(*str)
936 *cp++ = *str++;
937 *cp++ = '\0';
938
939 if (0)
940 printf("copied %p \"%s\" len %d\n",
941 orig, orig, cp-orig);
942
943 *tab = cp;
944
945 return orig;
946}
947
948/*
949 This sets up the client's initial stack, containing the args,
950 environment and aux vector.
951
952 The format of the stack is:
953
954 higher address +-----------------+
955 | Trampoline code |
956 +-----------------+
957 | |
958 : string table :
959 | |
960 +-----------------+
961 | AT_NULL |
962 - -
963 | auxv |
964 +-----------------+
965 | NULL |
966 - -
967 | envp |
968 +-----------------+
969 | NULL |
970 - -
971 | argv |
972 +-----------------+
973 | argc |
974 lower address +-----------------+ <- esp
975 | undefined |
976 : :
977 */
978static Addr setup_client_stack(char **orig_argv, char **orig_envp,
979 const struct exeinfo *info,
980 UInt** client_auxv)
981{
982 char **cpp;
983 char *strtab; /* string table */
984 char *stringbase;
985 addr_t *ptr;
986 struct ume_auxv *auxv;
987 const struct ume_auxv *orig_auxv;
988 const struct ume_auxv *cauxv;
989 unsigned stringsize; /* total size of strings in bytes */
990 unsigned auxsize; /* total size of auxv in bytes */
991 int argc; /* total argc */
992 int envc; /* total number of env vars */
993 unsigned stacksize; /* total client stack size */
994 addr_t cl_esp; /* client stack base (initial esp) */
995
996 /* use our own auxv as a prototype */
997 orig_auxv = find_auxv(ume_exec_esp);
998
999 /* ==================== compute sizes ==================== */
1000
1001 /* first of all, work out how big the client stack will be */
1002 stringsize = 0;
1003
1004 /* paste on the extra args if the loader needs them (ie, the #!
1005 interpreter and its argument) */
1006 argc = 0;
1007 if (info->argv0 != NULL) {
1008 argc++;
1009 stringsize += strlen(info->argv0) + 1;
1010 }
1011 if (info->argv1 != NULL) {
1012 argc++;
1013 stringsize += strlen(info->argv1) + 1;
1014 }
1015
1016 /* now scan the args we're given... */
1017 for (cpp = orig_argv; *cpp; cpp++) {
1018 argc++;
1019 stringsize += strlen(*cpp) + 1;
1020 }
1021
1022 /* ...and the environment */
1023 envc = 0;
1024 for (cpp = orig_envp; cpp && *cpp; cpp++) {
1025 envc++;
1026 stringsize += strlen(*cpp) + 1;
1027 }
1028
1029 /* now, how big is the auxv? */
1030 auxsize = sizeof(*auxv); /* there's always at least one entry: AT_NULL */
1031 for (cauxv = orig_auxv; cauxv->a_type != AT_NULL; cauxv++) {
1032 if (cauxv->a_type == AT_PLATFORM)
1033 stringsize += strlen(cauxv->u.a_ptr) + 1;
1034 auxsize += sizeof(*cauxv);
1035 }
1036
1037 /* OK, now we know how big the client stack is */
1038 stacksize =
1039 sizeof(int) + /* argc */
1040 sizeof(char **)*argc + /* argv */
1041 sizeof(char **) + /* terminal NULL */
1042 sizeof(char **)*envc + /* envp */
1043 sizeof(char **) + /* terminal NULL */
1044 auxsize + /* auxv */
1045 ROUNDUP(stringsize, sizeof(int)) +/* strings (aligned) */
1046 VKI_BYTES_PER_PAGE; /* page for trampoline code */
1047
1048 /* cl_esp is the client's stack pointer */
1049 cl_esp = VG_(client_end) - stacksize;
1050 cl_esp = ROUNDDN(cl_esp, 16); /* make stack 16 byte aligned */
1051
nethercote71980f02004-01-24 18:18:54 +00001052 /* base of the string table (aligned) */
1053 stringbase = strtab = (char *)(VG_(client_trampoline_code) - ROUNDUP(stringsize, sizeof(int)));
1054
1055 VG_(clstk_base) = PGROUNDDN(cl_esp);
1056 VG_(clstk_end) = VG_(client_end);
1057
nethercote5ee67ca2004-06-22 14:00:09 +00001058 if (0)
1059 printf("stringsize=%d auxsize=%d stacksize=%d\n"
1060 "clstk_base %x\n"
1061 "clstk_end %x\n",
1062 stringsize, auxsize, stacksize, VG_(clstk_base), VG_(clstk_end));
1063
1064
nethercote71980f02004-01-24 18:18:54 +00001065 /* ==================== allocate space ==================== */
1066
1067 /* allocate a stack - mmap enough space for the stack */
1068 mmap((void *)PGROUNDDN(cl_esp),
1069 VG_(client_end) - PGROUNDDN(cl_esp),
1070 PROT_READ | PROT_WRITE | PROT_EXEC,
1071 MAP_PRIVATE | MAP_ANON | MAP_FIXED, -1, 0);
1072
1073
1074 /* ==================== copy client stack ==================== */
1075
1076 ptr = (addr_t *)cl_esp;
1077
1078 /* --- argc --- */
1079 *ptr++ = argc; /* client argc */
1080
1081 /* --- argv --- */
1082 if (info->argv0) {
1083 *ptr++ = (addr_t)copy_str(&strtab, info->argv0);
1084 free(info->argv0);
1085 }
1086 if (info->argv1) {
1087 *ptr++ = (addr_t)copy_str(&strtab, info->argv1);
1088 free(info->argv1);
1089 }
1090 for (cpp = orig_argv; *cpp; ptr++, cpp++) {
1091 *ptr = (addr_t)copy_str(&strtab, *cpp);
1092 }
1093 *ptr++ = 0;
1094
1095 /* --- envp --- */
1096 VG_(client_envp) = (Char **)ptr;
1097 for (cpp = orig_envp; cpp && *cpp; ptr++, cpp++)
1098 *ptr = (addr_t)copy_str(&strtab, *cpp);
1099 *ptr++ = 0;
1100
1101 /* --- auxv --- */
1102 auxv = (struct ume_auxv *)ptr;
1103 *client_auxv = (UInt *)auxv;
1104
1105 for (; orig_auxv->a_type != AT_NULL; auxv++, orig_auxv++) {
1106 /* copy the entry... */
1107 *auxv = *orig_auxv;
1108
1109 /* ...and fix up the copy */
1110 switch(auxv->a_type) {
1111 case AT_PHDR:
1112 if (info->phdr == 0)
1113 auxv->a_type = AT_IGNORE;
1114 else
1115 auxv->u.a_val = info->phdr;
1116 break;
1117
1118 case AT_PHNUM:
1119 if (info->phdr == 0)
1120 auxv->a_type = AT_IGNORE;
1121 else
1122 auxv->u.a_val = info->phnum;
1123 break;
1124
1125 case AT_BASE:
1126 if (info->interp_base == 0)
1127 auxv->a_type = AT_IGNORE;
1128 else
1129 auxv->u.a_val = info->interp_base;
1130 break;
1131
1132 case AT_PLATFORM: /* points to a platform description string */
1133 auxv->u.a_ptr = copy_str(&strtab, orig_auxv->u.a_ptr);
1134 break;
1135
1136 case AT_ENTRY:
1137 auxv->u.a_val = info->entry;
1138 break;
1139
1140 case AT_IGNORE:
1141 case AT_EXECFD:
1142 case AT_PHENT:
1143 case AT_PAGESZ:
1144 case AT_FLAGS:
1145 case AT_NOTELF:
1146 case AT_UID:
1147 case AT_EUID:
1148 case AT_GID:
1149 case AT_EGID:
1150 case AT_CLKTCK:
1151 case AT_HWCAP:
1152 case AT_FPUCW:
1153 case AT_DCACHEBSIZE:
1154 case AT_ICACHEBSIZE:
1155 case AT_UCACHEBSIZE:
1156 /* All these are pointerless, so we don't need to do anything
1157 about them. */
1158 break;
1159
1160 case AT_SECURE:
1161 /* If this is 1, then it means that this program is running
1162 suid, and therefore the dynamic linker should be careful
1163 about LD_PRELOAD, etc. However, since stage1 (the thing
1164 the kernel actually execve's) should never be SUID, and we
1165 need LD_PRELOAD/LD_LIBRARY_PATH to work for the client, we
1166 set AT_SECURE to 0. */
1167 auxv->u.a_val = 0;
1168 break;
1169
1170 case AT_SYSINFO:
1171 /* Leave this unmolested for now, but we'll update it later
1172 when we set up the client trampoline code page */
1173 break;
1174
1175 case AT_SYSINFO_EHDR:
1176 /* Trash this, because we don't reproduce it */
1177 auxv->a_type = AT_IGNORE;
1178 break;
1179
1180 default:
1181 /* stomp out anything we don't know about */
1182 if (0)
1183 printf("stomping auxv entry %d\n", auxv->a_type);
1184 auxv->a_type = AT_IGNORE;
1185 break;
1186
1187 }
1188 }
1189 *auxv = *orig_auxv;
1190 vg_assert(auxv->a_type == AT_NULL);
1191
1192 vg_assert((strtab-stringbase) == stringsize);
1193
nethercote5ee67ca2004-06-22 14:00:09 +00001194 /* We know the initial ESP is pointing at argc/argv */
1195 VG_(client_argc) = *(Int*)cl_esp;
1196 VG_(client_argv) = (Char**)(cl_esp + sizeof(Int));
1197
nethercote71980f02004-01-24 18:18:54 +00001198 return cl_esp;
1199}
1200
1201/*====================================================================*/
1202/*=== Find executable ===*/
1203/*====================================================================*/
1204
1205static const char* find_executable(const char* exec)
1206{
1207 vg_assert(NULL != exec);
1208 if (strchr(exec, '/') == NULL) {
1209 /* no '/' - we need to search the path */
1210 char *path = getenv("PATH");
1211 int pathlen = path ? strlen(path) : 0;
1212
1213 int match_exe(const char *entry) {
1214 char buf[pathlen + strlen(entry) + 3];
1215
1216 /* empty PATH element means . */
1217 if (*entry == '\0')
1218 entry = ".";
1219
1220 snprintf(buf, sizeof(buf), "%s/%s", entry, exec);
1221
1222 if (access(buf, R_OK|X_OK) == 0) {
1223 exec = strdup(buf);
1224 vg_assert(NULL != exec);
1225 return 1;
1226 }
1227 return 0;
1228 }
1229 scan_colsep(path, match_exe);
1230 }
1231 return exec;
1232}
1233
1234
1235/*====================================================================*/
1236/*=== Loading tools ===*/
1237/*====================================================================*/
1238
1239static void list_tools(void)
1240{
1241 DIR *dir = opendir(VG_(libdir));
1242 struct dirent *de;
1243 int first = 1;
1244
1245 if (dir == NULL) {
1246 fprintf(stderr, "Can't open %s: %s (installation problem?)\n",
nethercotef4928da2004-06-15 10:54:40 +00001247 VG_(libdir), strerror(errno));
nethercote71980f02004-01-24 18:18:54 +00001248 return;
1249 }
1250
nethercotef4928da2004-06-15 10:54:40 +00001251 while ((de = readdir(dir)) != NULL) {
nethercote71980f02004-01-24 18:18:54 +00001252 int len = strlen(de->d_name);
1253
1254 /* look for vgskin_TOOL.so names */
1255 if (len > (7+1+3) && /* "vgskin_" + at least 1-char toolname + ".so" */
nethercotef4928da2004-06-15 10:54:40 +00001256 strncmp(de->d_name, "vgskin_", 7) == 0 &&
1257 VG_STREQ(de->d_name + len - 3, ".so")) {
1258 if (first) {
1259 fprintf(stderr, "Available tools:\n");
1260 first = 0;
1261 }
1262 de->d_name[len-3] = '\0';
1263 fprintf(stderr, "\t%s\n", de->d_name+7);
nethercote71980f02004-01-24 18:18:54 +00001264 }
1265 }
1266
1267 closedir(dir);
1268
1269 if (first)
nethercotef4928da2004-06-15 10:54:40 +00001270 fprintf(stderr, "No tools available in \"%s\" (installation problem?)\n",
1271 VG_(libdir));
nethercote71980f02004-01-24 18:18:54 +00001272}
1273
1274
1275/* Find and load a tool, and check it looks ok. Also looks to see if there's
1276 * a matching vgpreload_*.so file, and returns its name in *preloadpath. */
1277static void load_tool( const char *toolname, void** handle_out,
1278 ToolInfo** toolinfo_out, char **preloadpath_out )
1279{
1280 Bool ok;
1281 int len = strlen(VG_(libdir)) + strlen(toolname)*2 + 16;
1282 char buf[len];
1283 void* handle;
1284 ToolInfo* toolinfo;
1285 char* preloadpath = NULL;
1286 Int* vg_malloc_redzonep;
1287
1288 // XXX: allowing full paths for --tool option -- does it make sense?
1289 // Doesn't allow for vgpreload_<tool>.so.
1290
1291 if (strchr(toolname, '/') != 0) {
1292 /* toolname contains '/', and so must be a pathname */
1293 handle = dlopen(toolname, RTLD_NOW);
1294 } else {
1295 /* just try in the libdir */
1296 snprintf(buf, len, "%s/vgskin_%s.so", VG_(libdir), toolname);
1297 handle = dlopen(buf, RTLD_NOW);
1298
1299 if (handle != NULL) {
1300 snprintf(buf, len, "%s/vgpreload_%s.so", VG_(libdir), toolname);
1301 if (access(buf, R_OK) == 0) {
1302 preloadpath = strdup(buf);
1303 vg_assert(NULL != preloadpath);
1304 }
1305 }
1306 }
1307
1308 ok = (NULL != handle);
1309 if (!ok) {
1310 fprintf(stderr, "Can't open tool \"%s\": %s\n", toolname, dlerror());
1311 goto bad_load;
1312 }
1313
1314 toolinfo = dlsym(handle, "vgSkin_tool_info");
1315 ok = (NULL != toolinfo);
1316 if (!ok) {
1317 fprintf(stderr, "Tool \"%s\" doesn't define SK_(tool_info) - "
1318 "add VG_DETERMINE_INTERFACE_VERSION?\n", toolname);
1319 goto bad_load;
1320 }
1321
1322 ok = (toolinfo->sizeof_ToolInfo == sizeof(*toolinfo) &&
1323 toolinfo->interface_major_version == VG_CORE_INTERFACE_MAJOR_VERSION &&
1324 toolinfo->sk_pre_clo_init != NULL);
1325 if (!ok) {
1326 fprintf(stderr, "Error:\n"
1327 " Tool and core interface versions do not match.\n"
1328 " Interface version used by core is: %d.%d (size %d)\n"
1329 " Interface version used by tool is: %d.%d (size %d)\n"
1330 " The major version numbers must match.\n",
1331 VG_CORE_INTERFACE_MAJOR_VERSION,
1332 VG_CORE_INTERFACE_MINOR_VERSION,
1333 sizeof(*toolinfo),
1334 toolinfo->interface_major_version,
1335 toolinfo->interface_minor_version,
1336 toolinfo->sizeof_ToolInfo);
1337 fprintf(stderr, " You need to at least recompile, and possibly update,\n");
1338 if (VG_CORE_INTERFACE_MAJOR_VERSION > toolinfo->interface_major_version)
1339 fprintf(stderr, " your skin to work with this version of Valgrind.\n");
1340 else
1341 fprintf(stderr, " your version of Valgrind to work with this skin.\n");
1342 goto bad_load;
1343 }
1344
1345 // Set redzone size for V's allocator
1346 vg_malloc_redzonep = dlsym(handle, STR(VG_(vg_malloc_redzone_szB)));
1347 if ( NULL != vg_malloc_redzonep ) {
1348 VG_(vg_malloc_redzone_szB) = *vg_malloc_redzonep;
1349 }
1350
1351 vg_assert(NULL != handle && NULL != toolinfo);
1352 *handle_out = handle;
1353 *toolinfo_out = toolinfo;
1354 *preloadpath_out = preloadpath;
1355 return;
1356
1357
1358 bad_load:
1359 if (handle != NULL)
1360 dlclose(handle);
1361
nethercotef4928da2004-06-15 10:54:40 +00001362 fprintf(stderr, "valgrind: couldn't load tool\n");
nethercote71980f02004-01-24 18:18:54 +00001363 list_tools();
1364 exit(127);
1365}
1366
nethercotef4928da2004-06-15 10:54:40 +00001367
1368/*====================================================================*/
1369/*=== Command line errors ===*/
1370/*====================================================================*/
1371
1372static void abort_msg ( void )
1373{
nethercotef8548672004-06-21 12:42:35 +00001374 VG_(clo_log_to) = VgLogTo_Fd;
1375 VG_(clo_log_fd) = 2; /* stderr */
nethercotef4928da2004-06-15 10:54:40 +00001376}
1377
1378void VG_(bad_option) ( Char* opt )
1379{
1380 abort_msg();
1381 VG_(printf)("valgrind: Bad option `%s'; aborting.\n", opt);
1382 VG_(printf)("valgrind: Use --help for more information.\n");
1383 VG_(exit)(1);
1384}
1385
1386static void missing_tool_option ( void )
1387{
1388 abort_msg();
1389 VG_(printf)("valgrind: Missing --tool option\n");
1390 list_tools();
1391 VG_(printf)("valgrind: Use --help for more information.\n");
1392 VG_(exit)(1);
1393}
1394
1395static void missing_prog ( void )
1396{
1397 abort_msg();
1398 VG_(printf)("valgrind: no program specified\n");
1399 VG_(printf)("valgrind: Use --help for more information.\n");
1400 VG_(exit)(1);
1401}
1402
1403static void config_error ( Char* msg )
1404{
1405 abort_msg();
1406 VG_(printf)("valgrind: Startup or configuration error:\n %s\n", msg);
1407 VG_(printf)("valgrind: Unable to start up properly. Giving up.\n");
1408 VG_(exit)(1);
1409}
1410
1411
nethercote71980f02004-01-24 18:18:54 +00001412/*====================================================================*/
1413/*=== Loading the client ===*/
1414/*====================================================================*/
1415
nethercotef4928da2004-06-15 10:54:40 +00001416static void load_client(char* cl_argv[], const char* exec, Int need_help,
nethercote71980f02004-01-24 18:18:54 +00001417 /*out*/struct exeinfo* info, /*out*/Addr* client_eip)
1418{
1419 // If they didn't specify an executable with --exec, and didn't specify
1420 // --help, then use client argv[0] (searching $PATH if necessary).
nethercotef4928da2004-06-15 10:54:40 +00001421 if (NULL == exec && !need_help) {
nethercote71980f02004-01-24 18:18:54 +00001422 if (cl_argv[0] == NULL ||
1423 ( NULL == (exec = find_executable(cl_argv[0])) ) )
1424 {
nethercotef4928da2004-06-15 10:54:40 +00001425 missing_prog();
nethercote71980f02004-01-24 18:18:54 +00001426 }
1427 }
1428
1429 info->map_base = VG_(client_mapbase);
nethercote71980f02004-01-24 18:18:54 +00001430
1431 info->exe_base = VG_(client_base);
1432 info->exe_end = VG_(client_end);
1433 info->argv = cl_argv;
1434
nethercotef4928da2004-06-15 10:54:40 +00001435 if (need_help) {
nethercote71980f02004-01-24 18:18:54 +00001436 VG_(clexecfd) = -1;
1437 info->argv0 = NULL;
1438 info->argv1 = NULL;
1439 } else {
1440 Int ret;
1441 VG_(clexecfd) = VG_(open)(exec, O_RDONLY, VKI_S_IRUSR);
1442 ret = do_exec(exec, info);
1443 if (ret != 0) {
nethercotef4928da2004-06-15 10:54:40 +00001444 fprintf(stderr, "valgrind: do_exec(%s) failed: %s\n", exec, strerror(ret));
nethercote71980f02004-01-24 18:18:54 +00001445 exit(127);
1446 }
1447 }
1448
1449 /* Copy necessary bits of 'info' that were filled in */
1450 *client_eip = info->init_eip;
1451 VG_(brk_base) = VG_(brk_limit) = info->brkbase;
1452}
1453
1454
1455/*====================================================================*/
1456/*=== Command-line: variables, processing ===*/
1457/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +00001458
njn25e49d8e72002-09-23 09:36:25 +00001459/* Define, and set defaults. */
1460Bool VG_(clo_error_limit) = True;
nethercote04d0fbc2004-01-26 16:48:06 +00001461Bool VG_(clo_db_attach) = False;
1462Char* VG_(clo_db_command) = VG_CLO_DEFAULT_DBCOMMAND;
njn43c799e2003-04-08 00:08:52 +00001463Bool VG_(clo_gen_suppressions) = False;
nethercote27fec902004-06-16 21:26:32 +00001464Int VG_(clo_sanity_level) = 1;
njn25e49d8e72002-09-23 09:36:25 +00001465Int VG_(clo_verbosity) = 1;
1466Bool VG_(clo_demangle) = True;
njn25e49d8e72002-09-23 09:36:25 +00001467Bool VG_(clo_trace_children) = False;
sewardj4cf05692002-10-27 20:28:29 +00001468
nethercotee1730692003-11-20 10:38:07 +00001469/* See big comment in vg_include.h for meaning of these three.
1470 fd is initially stdout, for --help, but gets moved to stderr by default
1471 immediately afterwards. */
sewardj4cf05692002-10-27 20:28:29 +00001472VgLogTo VG_(clo_log_to) = VgLogTo_Fd;
nethercotef8548672004-06-21 12:42:35 +00001473Int VG_(clo_log_fd) = 1;
1474Char* VG_(clo_log_name) = NULL;
sewardj4cf05692002-10-27 20:28:29 +00001475
sewardj6024b212003-07-13 10:54:33 +00001476Int VG_(clo_input_fd) = 0; /* stdin */
njn25e49d8e72002-09-23 09:36:25 +00001477Int VG_(clo_n_suppressions) = 0;
sewardjde4a1d02002-03-22 01:27:54 +00001478Char* VG_(clo_suppressions)[VG_CLO_MAX_SFILES];
njn25e49d8e72002-09-23 09:36:25 +00001479Bool VG_(clo_profile) = False;
1480Bool VG_(clo_single_step) = False;
1481Bool VG_(clo_optimise) = True;
1482UChar VG_(clo_trace_codegen) = 0; // 00000000b
1483Bool VG_(clo_trace_syscalls) = False;
1484Bool VG_(clo_trace_signals) = False;
1485Bool VG_(clo_trace_symtab) = False;
njn25e49d8e72002-09-23 09:36:25 +00001486Bool VG_(clo_trace_sched) = False;
1487Int VG_(clo_trace_pthread_level) = 0;
njn25e49d8e72002-09-23 09:36:25 +00001488Int VG_(clo_dump_error) = 0;
1489Int VG_(clo_backtrace_size) = 4;
1490Char* VG_(clo_weird_hacks) = NULL;
sewardj858964b2002-10-05 14:15:43 +00001491Bool VG_(clo_run_libc_freeres) = True;
rjwalshf5f536f2003-11-17 17:45:00 +00001492Bool VG_(clo_track_fds) = False;
sewardj22854b92002-11-30 14:00:47 +00001493Bool VG_(clo_chain_bb) = True;
nethercote77eba602003-11-13 17:35:04 +00001494Bool VG_(clo_show_below_main) = False;
fitzhardinge98abfc72003-12-16 02:05:15 +00001495Bool VG_(clo_pointercheck) = True;
fitzhardinge462f4f92003-12-18 02:10:54 +00001496Bool VG_(clo_branchpred) = False;
sewardj2370f3b2002-11-30 15:01:01 +00001497
jsgf855d93d2003-10-13 22:26:55 +00001498static Bool VG_(clo_wait_for_gdb) = False;
1499
1500/* If we're doing signal routing, poll for signals every 50mS by
1501 default. */
1502Int VG_(clo_signal_polltime) = 50;
1503
1504/* These flags reduce thread wakeup latency on syscall completion and
1505 signal delivery, respectively. The downside is possible unfairness. */
1506Bool VG_(clo_lowlat_syscalls) = False; /* low-latency syscalls */
1507Bool VG_(clo_lowlat_signals) = False; /* low-latency signals */
1508
sewardjde4a1d02002-03-22 01:27:54 +00001509
nethercote6c999f22004-01-31 22:55:15 +00001510void usage ( Bool debug_help )
njn7cf0bd32002-06-08 13:36:03 +00001511{
njn25e49d8e72002-09-23 09:36:25 +00001512 Char* usage1 =
nethercote71980f02004-01-24 18:18:54 +00001513"usage: valgrind --tool=<toolname> [options] prog-and-args\n"
njn25e49d8e72002-09-23 09:36:25 +00001514"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001515" common user options for all Valgrind tools, with defaults in [ ]:\n"
nethercote0d588502004-06-21 13:27:11 +00001516" --tool=<name> use the Valgrind tool named <name>\n"
nethercotea76368b2004-06-16 11:56:29 +00001517" -h --help show this message\n"
nethercote6c999f22004-01-31 22:55:15 +00001518" --help-debug show this message, plus debugging options\n"
njn25e49d8e72002-09-23 09:36:25 +00001519" --version show version\n"
njn25e49d8e72002-09-23 09:36:25 +00001520" -q --quiet run silently; only print error msgs\n"
1521" -v --verbose be more verbose, incl counts of errors\n"
nethercote77eba602003-11-13 17:35:04 +00001522" --trace-children=no|yes Valgrind-ise child processes? [no]\n"
nethercote0d588502004-06-21 13:27:11 +00001523" --track-fds=no|yes track open file descriptors? [no]\n"
nethercote2b0793f2003-12-02 10:41:18 +00001524"\n"
1525" uncommon user options for all Valgrind tools:\n"
nethercote0d588502004-06-21 13:27:11 +00001526" --run-libc-freeres=no|yes free up glibc memory at exit? [yes]\n"
1527" --weird-hacks=hack1,hack2,... recognised hacks: lax-ioctls [none]\n"
1528" --signal-polltime=<time> signal poll period (mS) for older kernels [50]\n"
1529" --lowlat-signals=no|yes improve thread signal wake-up latency [no]\n"
1530" --lowlat-syscalls=no|yes improve thread syscall wake-up latency [no]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001531" --pointercheck=no|yes enforce client address space limits [yes]\n"
njn25e49d8e72002-09-23 09:36:25 +00001532"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001533" user options for Valgrind tools that report errors:\n"
nethercotef8548672004-06-21 12:42:35 +00001534" --log-fd=<number> log messages to file descriptor [2=stderr]\n"
1535" --log-file=<file> log messages to <file>.pid<pid>\n"
1536" --log-socket=ipaddr:port log messages to socket ipaddr:port\n"
nethercote2b0793f2003-12-02 10:41:18 +00001537" --demangle=no|yes automatically demangle C++ names? [yes]\n"
1538" --num-callers=<number> show <num> callers in stack traces [4]\n"
1539" --error-limit=no|yes stop showing new errors if too many? [yes]\n"
1540" --show-below-main=no|yes continue stack traces below main() [no]\n"
1541" --suppressions=<filename> suppress errors described in <filename>\n"
1542" --gen-suppressions=no|yes print suppressions for errors detected [no]\n"
nethercote04d0fbc2004-01-26 16:48:06 +00001543" --db-attach=no|yes start debugger when errors detected? [no]\n"
1544" --db-command=<command> command to start debugger [gdb -nw %%f %%p]\n"
1545" --input-fd=<number> file descriptor for input [0=stdin]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001546"\n";
njn7cf0bd32002-06-08 13:36:03 +00001547
njn25e49d8e72002-09-23 09:36:25 +00001548 Char* usage2 =
1549"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001550" debugging options for all Valgrind tools:\n"
njn25e49d8e72002-09-23 09:36:25 +00001551" --sanity-level=<number> level of sanity checking to do [1]\n"
1552" --single-step=no|yes translate each instr separately? [no]\n"
1553" --optimise=no|yes improve intermediate code? [yes]\n"
nethercote137bc552003-11-14 17:47:54 +00001554" --profile=no|yes profile? (tool must be built for it) [no]\n"
sewardj22854b92002-11-30 14:00:47 +00001555" --chain-bb=no|yes do basic-block chaining? [yes]\n"
fitzhardinge462f4f92003-12-18 02:10:54 +00001556" --branchpred=yes|no generate branch prediction hints [no]\n"
njn25e49d8e72002-09-23 09:36:25 +00001557" --trace-codegen=<XXXXX> show generated code? (X = 0|1) [00000]\n"
1558" --trace-syscalls=no|yes show all system calls? [no]\n"
1559" --trace-signals=no|yes show signal handling details? [no]\n"
1560" --trace-symtab=no|yes show symbol table details? [no]\n"
njn25e49d8e72002-09-23 09:36:25 +00001561" --trace-sched=no|yes show thread scheduler details? [no]\n"
njn3e884182003-04-15 13:03:23 +00001562" --trace-pthread=none|some|all show pthread event details? [none]\n"
jsgf855d93d2003-10-13 22:26:55 +00001563" --wait-for-gdb=yes|no pause on startup to wait for gdb attach\n"
njn25e49d8e72002-09-23 09:36:25 +00001564"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001565" debugging options for Valgrind tools that report errors\n"
1566" --dump-error=<number> show translation for basic block associated\n"
1567" with <number>'th error context [0=show none]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001568"\n";
njn3e884182003-04-15 13:03:23 +00001569
1570 Char* usage3 =
1571"\n"
nethercote71980f02004-01-24 18:18:54 +00001572" Extra options read from ~/.valgrindrc, $VALGRIND_OPTS, ./.valgrindrc\n"
njn25e49d8e72002-09-23 09:36:25 +00001573"\n"
nethercotebb1c9912004-01-04 16:43:23 +00001574" Valgrind is Copyright (C) 2000-2004 Julian Seward\n"
njn25e49d8e72002-09-23 09:36:25 +00001575" and licensed under the GNU General Public License, version 2.\n"
1576" Bug reports, feedback, admiration, abuse, etc, to: %s.\n"
njnd04b7c62002-10-03 14:05:52 +00001577"\n"
nethercote137bc552003-11-14 17:47:54 +00001578" Tools are copyright and licensed by their authors. See each\n"
1579" tool's start-up message for more information.\n"
njn25e49d8e72002-09-23 09:36:25 +00001580"\n";
njn7cf0bd32002-06-08 13:36:03 +00001581
fitzhardinge98abfc72003-12-16 02:05:15 +00001582 VG_(printf)(usage1);
1583 if (VG_(details).name) {
1584 VG_(printf)(" user options for %s:\n", VG_(details).name);
fitzhardinge98abfc72003-12-16 02:05:15 +00001585 if (VG_(needs).command_line_options)
1586 SK_(print_usage)();
1587 else
1588 VG_(printf)(" (none)\n");
1589 }
nethercote6c999f22004-01-31 22:55:15 +00001590 if (debug_help) {
1591 VG_(printf)(usage2);
fitzhardinge98abfc72003-12-16 02:05:15 +00001592
nethercote6c999f22004-01-31 22:55:15 +00001593 if (VG_(details).name) {
1594 VG_(printf)(" debugging options for %s:\n", VG_(details).name);
1595
1596 if (VG_(needs).command_line_options)
1597 SK_(print_debug_usage)();
1598 else
1599 VG_(printf)(" (none)\n");
1600 }
fitzhardinge98abfc72003-12-16 02:05:15 +00001601 }
nethercote421281e2003-11-20 16:20:55 +00001602 VG_(printf)(usage3, VG_BUGS_TO);
nethercotef4928da2004-06-15 10:54:40 +00001603 VG_(exit)(0);
njn7cf0bd32002-06-08 13:36:03 +00001604}
sewardjde4a1d02002-03-22 01:27:54 +00001605
nethercote71980f02004-01-24 18:18:54 +00001606static void pre_process_cmd_line_options
nethercote6c999f22004-01-31 22:55:15 +00001607 ( Int* need_help, const char** tool, const char** exec )
sewardj1c1b1162003-02-23 01:25:51 +00001608{
nethercote71980f02004-01-24 18:18:54 +00001609 UInt i;
sewardjde4a1d02002-03-22 01:27:54 +00001610
nethercote71980f02004-01-24 18:18:54 +00001611 /* parse the options we have (only the options we care about now) */
1612 for (i = 1; i < VG_(vg_argc); i++) {
1613
1614 if (strcmp(VG_(vg_argv)[i], "--version") == 0) {
1615 printf("valgrind-" VERSION "\n");
nethercotef4928da2004-06-15 10:54:40 +00001616 exit(0);
nethercote71980f02004-01-24 18:18:54 +00001617
nethercotea76368b2004-06-16 11:56:29 +00001618 } else if (VG_CLO_STREQ(VG_(vg_argv)[i], "--help") ||
1619 VG_CLO_STREQ(VG_(vg_argv)[i], "-h")) {
nethercote6c999f22004-01-31 22:55:15 +00001620 *need_help = 1;
1621
nethercotef4928da2004-06-15 10:54:40 +00001622 } else if (VG_CLO_STREQ(VG_(vg_argv)[i], "--help-debug")) {
nethercote6c999f22004-01-31 22:55:15 +00001623 *need_help = 2;
nethercote71980f02004-01-24 18:18:54 +00001624
nethercotef4928da2004-06-15 10:54:40 +00001625 } else if (VG_CLO_STREQN(7, VG_(vg_argv)[i], "--tool=") ||
1626 VG_CLO_STREQN(7, VG_(vg_argv)[i], "--skin=")) {
nethercote71980f02004-01-24 18:18:54 +00001627 *tool = &VG_(vg_argv)[i][7];
1628
nethercotef4928da2004-06-15 10:54:40 +00001629 } else if (VG_CLO_STREQN(7, VG_(vg_argv)[i], "--exec=")) {
nethercote71980f02004-01-24 18:18:54 +00001630 *exec = &VG_(vg_argv)[i][7];
1631 }
1632 }
1633
nethercotef4928da2004-06-15 10:54:40 +00001634 /* If no tool specified, can act appropriately without loading tool */
nethercote71980f02004-01-24 18:18:54 +00001635 if (*tool == NULL) {
nethercotef4928da2004-06-15 10:54:40 +00001636 if (0 == *need_help) {
1637 // neither --tool nor --help/--help-debug specified
1638 missing_tool_option();
1639 } else {
1640 // Give help message, without any tool-specific help
1641 usage(/*help-debug?*/2 == *need_help);
1642 }
nethercote71980f02004-01-24 18:18:54 +00001643 }
1644}
1645
nethercote5ee67ca2004-06-22 14:00:09 +00001646static void process_cmd_line_options( UInt* client_auxv, const char* toolname )
nethercote71980f02004-01-24 18:18:54 +00001647{
nethercotef8548672004-06-21 12:42:35 +00001648 Int i, eventually_log_fd;
nethercote71980f02004-01-24 18:18:54 +00001649 Int *auxp;
1650 Int toolname_len = VG_(strlen)(toolname);
sewardjde4a1d02002-03-22 01:27:54 +00001651
nethercotee1730692003-11-20 10:38:07 +00001652 /* log to stderr by default, but usage message goes to stdout */
nethercotef8548672004-06-21 12:42:35 +00001653 eventually_log_fd = 2;
sewardjde4a1d02002-03-22 01:27:54 +00001654
sewardj19d81412002-06-03 01:10:40 +00001655 /* Check for sane path in ./configure --prefix=... */
fitzhardinge98abfc72003-12-16 02:05:15 +00001656 if (VG_LIBDIR[0] != '/')
sewardj19d81412002-06-03 01:10:40 +00001657 config_error("Please use absolute paths in "
1658 "./configure --prefix=... or --libdir=...");
sewardj38170912002-05-10 21:07:22 +00001659
nethercote71980f02004-01-24 18:18:54 +00001660 for (auxp = client_auxv; auxp[0] != VKI_AT_NULL; auxp += 2) {
fitzhardinge98abfc72003-12-16 02:05:15 +00001661 switch(auxp[0]) {
1662 case VKI_AT_SYSINFO:
1663 VG_(sysinfo_page_exists) = True;
fitzhardinge92360792003-12-24 10:11:11 +00001664 auxp[1] = (Int)(VG_(client_trampoline_code) + VG_(tramp_syscall_offset));
fitzhardinge98abfc72003-12-16 02:05:15 +00001665 VG_(sysinfo_page_addr) = auxp[1];
1666 break;
sewardjde4a1d02002-03-22 01:27:54 +00001667 }
fitzhardinge98abfc72003-12-16 02:05:15 +00001668 }
sewardjde4a1d02002-03-22 01:27:54 +00001669
nethercote71980f02004-01-24 18:18:54 +00001670 for (i = 1; i < VG_(vg_argc); i++) {
1671
1672 Char* arg = VG_(vg_argv)[i];
1673
1674 // XXX: allow colons in options, for Josef
1675
1676 /* Look for matching "--toolname:foo" */
1677 if (VG_(strstr)(arg, ":")) {
1678 if (VG_CLO_STREQN(2, arg, "--") &&
1679 VG_CLO_STREQN(toolname_len, arg+2, toolname) &&
1680 VG_CLO_STREQN(1, arg+2+toolname_len, ":"))
1681 {
1682 // prefix matches, convert "--toolname:foo" to "--foo"
1683 if (0)
1684 VG_(printf)("tool-specific arg: %s\n", arg);
1685 arg += toolname_len + 1;
1686 arg[0] = '-';
1687 arg[1] = '-';
1688
1689 } else {
1690 // prefix doesn't match, skip to next arg
1691 continue;
1692 }
1693 }
1694
fitzhardinge98abfc72003-12-16 02:05:15 +00001695 /* Ignore these options - they've already been handled */
nethercote71980f02004-01-24 18:18:54 +00001696 if (VG_CLO_STREQN(7, arg, "--tool=") ||
1697 VG_CLO_STREQN(7, arg, "--skin="))
fitzhardinge98abfc72003-12-16 02:05:15 +00001698 continue;
nethercote71980f02004-01-24 18:18:54 +00001699 if (VG_CLO_STREQN(7, arg, "--exec="))
fitzhardinge98abfc72003-12-16 02:05:15 +00001700 continue;
1701
nethercote71980f02004-01-24 18:18:54 +00001702 if ( VG_CLO_STREQ(arg, "--"))
fitzhardinge98abfc72003-12-16 02:05:15 +00001703 continue;
nethercote27fec902004-06-16 21:26:32 +00001704
nethercote71980f02004-01-24 18:18:54 +00001705 else if (VG_CLO_STREQ(arg, "-v") ||
1706 VG_CLO_STREQ(arg, "--verbose"))
sewardjde4a1d02002-03-22 01:27:54 +00001707 VG_(clo_verbosity)++;
nethercote27fec902004-06-16 21:26:32 +00001708
nethercote71980f02004-01-24 18:18:54 +00001709 else if (VG_CLO_STREQ(arg, "-q") ||
1710 VG_CLO_STREQ(arg, "--quiet"))
sewardjde4a1d02002-03-22 01:27:54 +00001711 VG_(clo_verbosity)--;
1712
nethercote27fec902004-06-16 21:26:32 +00001713 else VG_BOOL_CLO("--branchpred", VG_(clo_branchpred))
1714 else VG_BOOL_CLO("--chain-bb", VG_(clo_chain_bb))
1715 else VG_BOOL_CLO("--db-attach", VG_(clo_db_attach))
1716 else VG_BOOL_CLO("--demangle", VG_(clo_demangle))
1717 else VG_BOOL_CLO("--error-limit", VG_(clo_error_limit))
1718 else VG_BOOL_CLO("--gen-suppressions", VG_(clo_gen_suppressions))
1719 else VG_BOOL_CLO("--lowlat-signals", VG_(clo_lowlat_signals))
1720 else VG_BOOL_CLO("--lowlat-syscalls", VG_(clo_lowlat_syscalls))
1721 else VG_BOOL_CLO("--optimise", VG_(clo_optimise))
1722 else VG_BOOL_CLO("--pointercheck", VG_(clo_pointercheck))
1723 else VG_BOOL_CLO("--profile", VG_(clo_profile))
1724 else VG_BOOL_CLO("--run-libc-freeres", VG_(clo_run_libc_freeres))
1725 else VG_BOOL_CLO("--show-below-main", VG_(clo_show_below_main))
1726 else VG_BOOL_CLO("--single-step", VG_(clo_single_step))
1727 else VG_BOOL_CLO("--track-fds", VG_(clo_track_fds))
1728 else VG_BOOL_CLO("--trace-children", VG_(clo_trace_children))
1729 else VG_BOOL_CLO("--trace-sched", VG_(clo_trace_sched))
1730 else VG_BOOL_CLO("--trace-signals", VG_(clo_trace_signals))
1731 else VG_BOOL_CLO("--trace-symtab", VG_(clo_trace_symtab))
1732 else VG_BOOL_CLO("--trace-syscalls", VG_(clo_trace_syscalls))
1733 else VG_BOOL_CLO("--wait-for-gdb", VG_(clo_wait_for_gdb))
sewardj72f98ff2002-06-13 17:23:38 +00001734
nethercote27fec902004-06-16 21:26:32 +00001735 else VG_STR_CLO ("--db-command", VG_(clo_db_command))
1736 else VG_STR_CLO ("--weird-hacks", VG_(clo_weird_hacks))
sewardjde4a1d02002-03-22 01:27:54 +00001737
nethercote27fec902004-06-16 21:26:32 +00001738 else VG_NUM_CLO ("--dump-error", VG_(clo_dump_error))
1739 else VG_NUM_CLO ("--input-fd", VG_(clo_input_fd))
1740 else VG_NUM_CLO ("--sanity-level", VG_(clo_sanity_level))
1741 else VG_NUM_CLO ("--signal­polltime", VG_(clo_signal_polltime))
1742 else VG_BNUM_CLO("--num-callers", VG_(clo_backtrace_size), 1,
1743 VG_DEEPEST_BACKTRACE)
sewardjde4a1d02002-03-22 01:27:54 +00001744
nethercotef8548672004-06-21 12:42:35 +00001745 // for backwards compatibility, replaced by --log-fd
nethercote71980f02004-01-24 18:18:54 +00001746 else if (VG_CLO_STREQN(13, arg, "--logfile-fd=")) {
nethercotef8548672004-06-21 12:42:35 +00001747 VG_(clo_log_to) = VgLogTo_Fd;
1748 VG_(clo_log_name) = NULL;
1749 eventually_log_fd = (Int)VG_(atoll)(&arg[13]);
1750 }
1751 else if (VG_CLO_STREQN(9, arg, "--log-fd=")) {
1752 VG_(clo_log_to) = VgLogTo_Fd;
1753 VG_(clo_log_name) = NULL;
1754 eventually_log_fd = (Int)VG_(atoll)(&arg[9]);
sewardj4cf05692002-10-27 20:28:29 +00001755 }
1756
nethercotef8548672004-06-21 12:42:35 +00001757 // for backwards compatibility, replaced by --log-file
nethercote71980f02004-01-24 18:18:54 +00001758 else if (VG_CLO_STREQN(10, arg, "--logfile=")) {
nethercotef8548672004-06-21 12:42:35 +00001759 VG_(clo_log_to) = VgLogTo_File;
1760 VG_(clo_log_name) = &arg[10];
1761 }
1762 else if (VG_CLO_STREQN(11, arg, "--log-file=")) {
1763 VG_(clo_log_to) = VgLogTo_File;
1764 VG_(clo_log_name) = &arg[11];
sewardj4cf05692002-10-27 20:28:29 +00001765 }
sewardjde4a1d02002-03-22 01:27:54 +00001766
nethercotef8548672004-06-21 12:42:35 +00001767 // for backwards compatibility, replaced by --log-socket
nethercote71980f02004-01-24 18:18:54 +00001768 else if (VG_CLO_STREQN(12, arg, "--logsocket=")) {
nethercotef8548672004-06-21 12:42:35 +00001769 VG_(clo_log_to) = VgLogTo_Socket;
1770 VG_(clo_log_name) = &arg[12];
1771 }
1772 else if (VG_CLO_STREQN(13, arg, "--log-socket=")) {
1773 VG_(clo_log_to) = VgLogTo_Socket;
1774 VG_(clo_log_name) = &arg[13];
sewardj73cf3bc2002-11-03 03:20:15 +00001775 }
1776
nethercote71980f02004-01-24 18:18:54 +00001777 else if (VG_CLO_STREQN(15, arg, "--suppressions=")) {
sewardjde4a1d02002-03-22 01:27:54 +00001778 if (VG_(clo_n_suppressions) >= VG_CLO_MAX_SFILES) {
njn25e49d8e72002-09-23 09:36:25 +00001779 VG_(message)(Vg_UserMsg, "Too many suppression files specified.");
sewardjde4a1d02002-03-22 01:27:54 +00001780 VG_(message)(Vg_UserMsg,
1781 "Increase VG_CLO_MAX_SFILES and recompile.");
nethercote71980f02004-01-24 18:18:54 +00001782 VG_(bad_option)(arg);
sewardjde4a1d02002-03-22 01:27:54 +00001783 }
nethercote71980f02004-01-24 18:18:54 +00001784 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = &arg[15];
sewardjde4a1d02002-03-22 01:27:54 +00001785 VG_(clo_n_suppressions)++;
1786 }
sewardjde4a1d02002-03-22 01:27:54 +00001787
njn25e49d8e72002-09-23 09:36:25 +00001788 /* "vwxyz" --> 000zyxwv (binary) */
nethercote71980f02004-01-24 18:18:54 +00001789 else if (VG_CLO_STREQN(16, arg, "--trace-codegen=")) {
njn25e49d8e72002-09-23 09:36:25 +00001790 Int j;
nethercote71980f02004-01-24 18:18:54 +00001791 char* opt = & arg[16];
njn25e49d8e72002-09-23 09:36:25 +00001792
1793 if (5 != VG_(strlen)(opt)) {
1794 VG_(message)(Vg_UserMsg,
1795 "--trace-codegen argument must have 5 digits");
nethercote71980f02004-01-24 18:18:54 +00001796 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001797 }
1798 for (j = 0; j < 5; j++) {
1799 if ('0' == opt[j]) { /* do nothing */ }
1800 else if ('1' == opt[j]) VG_(clo_trace_codegen) |= (1 << j);
1801 else {
1802 VG_(message)(Vg_UserMsg, "--trace-codegen argument can only "
1803 "contain 0s and 1s");
nethercote71980f02004-01-24 18:18:54 +00001804 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001805 }
1806 }
1807 }
sewardjde4a1d02002-03-22 01:27:54 +00001808
nethercote71980f02004-01-24 18:18:54 +00001809 else if (VG_CLO_STREQ(arg, "--trace-pthread=none"))
sewardj45b4b372002-04-16 22:50:32 +00001810 VG_(clo_trace_pthread_level) = 0;
nethercote71980f02004-01-24 18:18:54 +00001811 else if (VG_CLO_STREQ(arg, "--trace-pthread=some"))
sewardj45b4b372002-04-16 22:50:32 +00001812 VG_(clo_trace_pthread_level) = 1;
nethercote71980f02004-01-24 18:18:54 +00001813 else if (VG_CLO_STREQ(arg, "--trace-pthread=all"))
sewardj45b4b372002-04-16 22:50:32 +00001814 VG_(clo_trace_pthread_level) = 2;
sewardj8937c812002-04-12 20:12:20 +00001815
nethercote71980f02004-01-24 18:18:54 +00001816 else if ( ! VG_(needs).command_line_options
1817 || ! SK_(process_cmd_line_option)(arg) ) {
nethercotef4928da2004-06-15 10:54:40 +00001818 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001819 }
sewardjde4a1d02002-03-22 01:27:54 +00001820 }
1821
nethercote27fec902004-06-16 21:26:32 +00001822 // Check various option values
1823
njnf9ebf672003-05-12 21:41:30 +00001824 if (VG_(clo_verbosity) < 0)
sewardjde4a1d02002-03-22 01:27:54 +00001825 VG_(clo_verbosity) = 0;
1826
nethercote04d0fbc2004-01-26 16:48:06 +00001827 if (VG_(clo_db_attach) && VG_(clo_trace_children)) {
sewardjde4a1d02002-03-22 01:27:54 +00001828 VG_(message)(Vg_UserMsg, "");
1829 VG_(message)(Vg_UserMsg,
nethercote04d0fbc2004-01-26 16:48:06 +00001830 "--db-attach=yes conflicts with --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001831 VG_(message)(Vg_UserMsg,
1832 "Please choose one or the other, but not both.");
nethercote04d0fbc2004-01-26 16:48:06 +00001833 VG_(bad_option)("--db-attach=yes and --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001834 }
1835
nethercotef8548672004-06-21 12:42:35 +00001836 /* Set up logging now. After this is done, VG_(clo_log_fd)
sewardj4cf05692002-10-27 20:28:29 +00001837 should be connected to whatever sink has been selected, and we
1838 indiscriminately chuck stuff into it without worrying what the
1839 nature of it is. Oh the wonder of Unix streams. */
1840
nethercotee1730692003-11-20 10:38:07 +00001841 /* So far we should be still attached to stdout, so we can show on
sewardj4cf05692002-10-27 20:28:29 +00001842 the terminal any problems to do with processing command line
1843 opts. */
nethercotef8548672004-06-21 12:42:35 +00001844 vg_assert(VG_(clo_log_fd) == 1 /* stdout */);
sewardj73cf3bc2002-11-03 03:20:15 +00001845 vg_assert(VG_(logging_to_filedes) == True);
sewardj4cf05692002-10-27 20:28:29 +00001846
1847 switch (VG_(clo_log_to)) {
sewardj73cf3bc2002-11-03 03:20:15 +00001848
sewardj4cf05692002-10-27 20:28:29 +00001849 case VgLogTo_Fd:
nethercotef8548672004-06-21 12:42:35 +00001850 vg_assert(VG_(clo_log_name) == NULL);
1851 VG_(clo_log_fd) = eventually_log_fd;
sewardj4cf05692002-10-27 20:28:29 +00001852 break;
sewardj73cf3bc2002-11-03 03:20:15 +00001853
sewardj4cf05692002-10-27 20:28:29 +00001854 case VgLogTo_File: {
1855 Char logfilename[1000];
jsgff3c3f1a2003-10-14 22:13:28 +00001856 Int seq = 0;
1857 Int pid = VG_(getpid)();
1858
nethercotef8548672004-06-21 12:42:35 +00001859 vg_assert(VG_(clo_log_name) != NULL);
1860 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
jsgff3c3f1a2003-10-14 22:13:28 +00001861
nethercote71980f02004-01-24 18:18:54 +00001862 for (;;) {
jsgff3c3f1a2003-10-14 22:13:28 +00001863 if (seq == 0)
1864 VG_(sprintf)(logfilename, "%s.pid%d",
nethercotef8548672004-06-21 12:42:35 +00001865 VG_(clo_log_name), pid );
jsgff3c3f1a2003-10-14 22:13:28 +00001866 else
1867 VG_(sprintf)(logfilename, "%s.pid%d.%d",
nethercotef8548672004-06-21 12:42:35 +00001868 VG_(clo_log_name), pid, seq );
jsgff3c3f1a2003-10-14 22:13:28 +00001869 seq++;
1870
nethercotef8548672004-06-21 12:42:35 +00001871 eventually_log_fd
jsgff3c3f1a2003-10-14 22:13:28 +00001872 = VG_(open)(logfilename,
1873 VKI_O_CREAT|VKI_O_WRONLY|VKI_O_EXCL|VKI_O_TRUNC,
1874 VKI_S_IRUSR|VKI_S_IWUSR);
nethercotef8548672004-06-21 12:42:35 +00001875 if (eventually_log_fd >= 0) {
1876 VG_(clo_log_fd) = VG_(safe_fd)(eventually_log_fd);
jsgff3c3f1a2003-10-14 22:13:28 +00001877 break;
1878 } else {
nethercotef8548672004-06-21 12:42:35 +00001879 if (eventually_log_fd != -VKI_EEXIST) {
jsgff3c3f1a2003-10-14 22:13:28 +00001880 VG_(message)(Vg_UserMsg,
1881 "Can't create/open log file `%s.pid%d'; giving up!",
nethercotef8548672004-06-21 12:42:35 +00001882 VG_(clo_log_name), pid);
jsgff3c3f1a2003-10-14 22:13:28 +00001883 VG_(bad_option)(
nethercotef8548672004-06-21 12:42:35 +00001884 "--log-file=<file> didn't work out for some reason.");
jsgff3c3f1a2003-10-14 22:13:28 +00001885 break;
1886 }
1887 }
1888 }
sewardj4cf05692002-10-27 20:28:29 +00001889 break;
sewardj73cf3bc2002-11-03 03:20:15 +00001890 }
1891
1892 case VgLogTo_Socket: {
nethercotef8548672004-06-21 12:42:35 +00001893 vg_assert(VG_(clo_log_name) != NULL);
1894 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
1895 eventually_log_fd = VG_(connect_via_socket)( VG_(clo_log_name) );
1896 if (eventually_log_fd == -1) {
sewardj73cf3bc2002-11-03 03:20:15 +00001897 VG_(message)(Vg_UserMsg,
nethercotef8548672004-06-21 12:42:35 +00001898 "Invalid --log-socket=ipaddr or --log-socket=ipaddr:port spec");
sewardj73cf3bc2002-11-03 03:20:15 +00001899 VG_(message)(Vg_UserMsg,
nethercotef8548672004-06-21 12:42:35 +00001900 "of `%s'; giving up!", VG_(clo_log_name) );
sewardj73cf3bc2002-11-03 03:20:15 +00001901 VG_(bad_option)(
nethercotef8548672004-06-21 12:42:35 +00001902 "--log-socket=");
sewardj4cf05692002-10-27 20:28:29 +00001903 }
nethercotef8548672004-06-21 12:42:35 +00001904 if (eventually_log_fd == -2) {
sewardj73cf3bc2002-11-03 03:20:15 +00001905 VG_(message)(Vg_UserMsg,
sewardj570f8902002-11-03 11:44:36 +00001906 "valgrind: failed to connect to logging server `%s'.",
nethercotef8548672004-06-21 12:42:35 +00001907 VG_(clo_log_name) );
sewardj570f8902002-11-03 11:44:36 +00001908 VG_(message)(Vg_UserMsg,
1909 "Log messages will sent to stderr instead." );
1910 VG_(message)(Vg_UserMsg,
1911 "" );
1912 /* We don't change anything here. */
1913 } else {
nethercotef8548672004-06-21 12:42:35 +00001914 vg_assert(eventually_log_fd > 0);
1915 VG_(clo_log_fd) = eventually_log_fd;
sewardj570f8902002-11-03 11:44:36 +00001916 VG_(logging_to_filedes) = False;
1917 }
sewardj73cf3bc2002-11-03 03:20:15 +00001918 break;
1919 }
1920
sewardj4cf05692002-10-27 20:28:29 +00001921 }
1922
nethercotef8548672004-06-21 12:42:35 +00001923 /* Move log_fd into the safe range, so it doesn't conflict with any app fds */
thughesad1c9562004-06-26 11:27:52 +00001924 eventually_log_fd = VG_(fcntl)(VG_(clo_log_fd), VKI_F_DUPFD, VG_(fd_hard_limit));
nethercotef8548672004-06-21 12:42:35 +00001925 if (eventually_log_fd < 0)
jsgf855d93d2003-10-13 22:26:55 +00001926 VG_(message)(Vg_UserMsg, "valgrind: failed to move logfile fd into safe range");
1927 else {
nethercotef8548672004-06-21 12:42:35 +00001928 VG_(clo_log_fd) = eventually_log_fd;
1929 VG_(fcntl)(VG_(clo_log_fd), VKI_F_SETFD, VKI_FD_CLOEXEC);
jsgf855d93d2003-10-13 22:26:55 +00001930 }
1931
sewardj4cf05692002-10-27 20:28:29 +00001932 /* Ok, the logging sink is running now. Print a suitable preamble.
1933 If logging to file or a socket, write details of parent PID and
1934 command line args, to help people trying to interpret the
1935 results of a run which encompasses multiple processes. */
sewardjde4a1d02002-03-22 01:27:54 +00001936
sewardj83adf412002-05-01 01:25:45 +00001937 if (VG_(clo_verbosity > 0)) {
njnd04b7c62002-10-03 14:05:52 +00001938 /* Skin details */
1939 VG_(message)(Vg_UserMsg, "%s%s%s, %s for x86-linux.",
1940 VG_(details).name,
1941 NULL == VG_(details).version ? "" : "-",
1942 NULL == VG_(details).version
1943 ? (Char*)"" : VG_(details).version,
1944 VG_(details).description);
1945 VG_(message)(Vg_UserMsg, "%s", VG_(details).copyright_author);
sewardj3b2736a2002-03-24 12:18:35 +00001946
njnd04b7c62002-10-03 14:05:52 +00001947 /* Core details */
1948 VG_(message)(Vg_UserMsg,
njn3e884182003-04-15 13:03:23 +00001949 "Using valgrind-%s, a program supervision framework for x86-linux.",
sewardj4aa62ba2002-10-05 15:49:27 +00001950 VERSION);
sewardjde4a1d02002-03-22 01:27:54 +00001951 VG_(message)(Vg_UserMsg,
nethercotebb1c9912004-01-04 16:43:23 +00001952 "Copyright (C) 2000-2004, and GNU GPL'd, by Julian Seward.");
njnd04b7c62002-10-03 14:05:52 +00001953 }
1954
nethercotec1e395d2003-11-10 13:26:49 +00001955 if (VG_(clo_verbosity) > 0 && VG_(clo_log_to) != VgLogTo_Fd) {
sewardj4cf05692002-10-27 20:28:29 +00001956 VG_(message)(Vg_UserMsg, "");
1957 VG_(message)(Vg_UserMsg,
1958 "My PID = %d, parent PID = %d. Prog and args are:",
1959 VG_(getpid)(), VG_(getppid)() );
1960 for (i = 0; i < VG_(client_argc); i++)
1961 VG_(message)(Vg_UserMsg, " %s", VG_(client_argv)[i]);
1962 }
1963
sewardjde4a1d02002-03-22 01:27:54 +00001964 if (VG_(clo_verbosity) > 1) {
nethercotea70f7352004-04-18 12:08:46 +00001965 Int fd;
sewardj4cf05692002-10-27 20:28:29 +00001966 if (VG_(clo_log_to) != VgLogTo_Fd)
1967 VG_(message)(Vg_UserMsg, "");
fitzhardinge98abfc72003-12-16 02:05:15 +00001968 VG_(message)(Vg_UserMsg, "Valgrind library directory: %s", VG_(libdir));
njn86dc2bc2003-09-09 07:26:21 +00001969 VG_(message)(Vg_UserMsg, "Command line");
1970 for (i = 0; i < VG_(client_argc); i++)
1971 VG_(message)(Vg_UserMsg, " %s", VG_(client_argv)[i]);
1972
sewardjde4a1d02002-03-22 01:27:54 +00001973 VG_(message)(Vg_UserMsg, "Startup, with flags:");
nethercote71980f02004-01-24 18:18:54 +00001974 for (i = 1; i < VG_(vg_argc); i++) {
1975 VG_(message)(Vg_UserMsg, " %s", VG_(vg_argv)[i]);
sewardjde4a1d02002-03-22 01:27:54 +00001976 }
nethercotea70f7352004-04-18 12:08:46 +00001977
1978 VG_(message)(Vg_UserMsg, "Contents of /proc/version:");
1979 fd = VG_(open) ( "/proc/version", VKI_O_RDONLY, 0 );
1980 if (fd < 0) {
1981 VG_(message)(Vg_UserMsg, " can't open /proc/version");
1982 } else {
1983 #define BUF_LEN 256
1984 Char version_buf[BUF_LEN];
1985 Int n = VG_(read) ( fd, version_buf, BUF_LEN );
1986 vg_assert(n <= 256);
1987 if (n > 0) {
1988 version_buf[n-1] = '\0';
1989 VG_(message)(Vg_UserMsg, " %s", version_buf);
1990 } else {
1991 VG_(message)(Vg_UserMsg, " (empty?)");
1992 }
1993 VG_(close)(fd);
1994 #undef BUF_LEN
1995 }
sewardjde4a1d02002-03-22 01:27:54 +00001996 }
1997
fitzhardinge98abfc72003-12-16 02:05:15 +00001998 if (VG_(clo_n_suppressions) < VG_CLO_MAX_SFILES-1 &&
njn25e49d8e72002-09-23 09:36:25 +00001999 (VG_(needs).core_errors || VG_(needs).skin_errors)) {
fitzhardinge98abfc72003-12-16 02:05:15 +00002000 /* If there are no suppression files specified and the skin
2001 needs one, load the default */
2002 static const Char default_supp[] = "default.supp";
2003 Int len = VG_(strlen)(VG_(libdir)) + 1 + sizeof(default_supp);
2004 Char *buf = VG_(arena_malloc)(VG_AR_CORE, len);
2005 VG_(sprintf)(buf, "%s/%s", VG_(libdir), default_supp);
2006 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = buf;
2007 VG_(clo_n_suppressions)++;
sewardjde4a1d02002-03-22 01:27:54 +00002008 }
sewardj4cf05692002-10-27 20:28:29 +00002009
njn6a230532003-07-21 10:38:23 +00002010 if (VG_(clo_gen_suppressions) &&
2011 !VG_(needs).core_errors && !VG_(needs).skin_errors) {
nethercotef4928da2004-06-15 10:54:40 +00002012 VG_(message)(Vg_UserMsg,
2013 "Can't use --gen-suppressions=yes with this tool,");
2014 VG_(message)(Vg_UserMsg,
2015 "as it doesn't generate errors.");
2016 VG_(bad_option)("--gen-suppressions=yes");
njn6a230532003-07-21 10:38:23 +00002017 }
sewardjde4a1d02002-03-22 01:27:54 +00002018}
2019
sewardjde4a1d02002-03-22 01:27:54 +00002020
nethercote71980f02004-01-24 18:18:54 +00002021/*====================================================================*/
2022/*=== File descriptor setup ===*/
2023/*====================================================================*/
2024
2025static void setup_file_descriptors(void)
2026{
2027 struct vki_rlimit rl;
2028
2029 /* Get the current file descriptor limits. */
2030 if (VG_(getrlimit)(VKI_RLIMIT_NOFILE, &rl) < 0) {
2031 rl.rlim_cur = 1024;
2032 rl.rlim_max = 1024;
2033 }
2034
2035 /* Work out where to move the soft limit to. */
2036 if (rl.rlim_cur + VG_N_RESERVED_FDS <= rl.rlim_max) {
2037 rl.rlim_cur = rl.rlim_cur + VG_N_RESERVED_FDS;
2038 } else {
2039 rl.rlim_cur = rl.rlim_max;
2040 }
2041
2042 /* Reserve some file descriptors for our use. */
thughesad1c9562004-06-26 11:27:52 +00002043 VG_(fd_soft_limit) = rl.rlim_cur - VG_N_RESERVED_FDS;
2044 VG_(fd_hard_limit) = rl.rlim_cur - VG_N_RESERVED_FDS;
nethercote71980f02004-01-24 18:18:54 +00002045
2046 /* Update the soft limit. */
2047 VG_(setrlimit)(VKI_RLIMIT_NOFILE, &rl);
2048
2049 if (VG_(vgexecfd) != -1)
2050 VG_(vgexecfd) = VG_(safe_fd)( VG_(vgexecfd) );
2051 if (VG_(clexecfd) != -1)
2052 VG_(clexecfd) = VG_(safe_fd)( VG_(clexecfd) );
2053}
2054
2055
2056/*====================================================================*/
nethercote1d447092004-02-01 17:29:59 +00002057/*=== baseBlock: definition + setup ===*/
nethercote71980f02004-01-24 18:18:54 +00002058/*====================================================================*/
2059
2060/* The variables storing offsets. */
2061
2062#define INVALID_OFFSET (-1)
2063
2064Int VGOFF_(m_eax) = INVALID_OFFSET;
2065Int VGOFF_(m_ecx) = INVALID_OFFSET;
2066Int VGOFF_(m_edx) = INVALID_OFFSET;
2067Int VGOFF_(m_ebx) = INVALID_OFFSET;
2068Int VGOFF_(m_esp) = INVALID_OFFSET;
2069Int VGOFF_(m_ebp) = INVALID_OFFSET;
2070Int VGOFF_(m_esi) = INVALID_OFFSET;
2071Int VGOFF_(m_edi) = INVALID_OFFSET;
2072Int VGOFF_(m_eflags) = INVALID_OFFSET;
2073Int VGOFF_(m_dflag) = INVALID_OFFSET;
2074Int VGOFF_(m_ssestate) = INVALID_OFFSET;
2075Int VGOFF_(ldt) = INVALID_OFFSET;
2076Int VGOFF_(tls) = INVALID_OFFSET;
2077Int VGOFF_(m_cs) = INVALID_OFFSET;
2078Int VGOFF_(m_ss) = INVALID_OFFSET;
2079Int VGOFF_(m_ds) = INVALID_OFFSET;
2080Int VGOFF_(m_es) = INVALID_OFFSET;
2081Int VGOFF_(m_fs) = INVALID_OFFSET;
2082Int VGOFF_(m_gs) = INVALID_OFFSET;
2083Int VGOFF_(m_eip) = INVALID_OFFSET;
2084Int VGOFF_(spillslots) = INVALID_OFFSET;
2085Int VGOFF_(sh_eax) = INVALID_OFFSET;
2086Int VGOFF_(sh_ecx) = INVALID_OFFSET;
2087Int VGOFF_(sh_edx) = INVALID_OFFSET;
2088Int VGOFF_(sh_ebx) = INVALID_OFFSET;
2089Int VGOFF_(sh_esp) = INVALID_OFFSET;
2090Int VGOFF_(sh_ebp) = INVALID_OFFSET;
2091Int VGOFF_(sh_esi) = INVALID_OFFSET;
2092Int VGOFF_(sh_edi) = INVALID_OFFSET;
2093Int VGOFF_(sh_eflags) = INVALID_OFFSET;
2094
2095Int VGOFF_(helper_idiv_64_32) = INVALID_OFFSET;
2096Int VGOFF_(helper_div_64_32) = INVALID_OFFSET;
2097Int VGOFF_(helper_idiv_32_16) = INVALID_OFFSET;
2098Int VGOFF_(helper_div_32_16) = INVALID_OFFSET;
2099Int VGOFF_(helper_idiv_16_8) = INVALID_OFFSET;
2100Int VGOFF_(helper_div_16_8) = INVALID_OFFSET;
2101Int VGOFF_(helper_imul_32_64) = INVALID_OFFSET;
2102Int VGOFF_(helper_mul_32_64) = INVALID_OFFSET;
2103Int VGOFF_(helper_imul_16_32) = INVALID_OFFSET;
2104Int VGOFF_(helper_mul_16_32) = INVALID_OFFSET;
2105Int VGOFF_(helper_imul_8_16) = INVALID_OFFSET;
2106Int VGOFF_(helper_mul_8_16) = INVALID_OFFSET;
2107Int VGOFF_(helper_CLD) = INVALID_OFFSET;
2108Int VGOFF_(helper_STD) = INVALID_OFFSET;
2109Int VGOFF_(helper_get_dirflag) = INVALID_OFFSET;
2110Int VGOFF_(helper_CLC) = INVALID_OFFSET;
2111Int VGOFF_(helper_STC) = INVALID_OFFSET;
nethercote1018bdd2004-02-11 23:33:29 +00002112Int VGOFF_(helper_CMC) = INVALID_OFFSET;
nethercote71980f02004-01-24 18:18:54 +00002113Int VGOFF_(helper_shldl) = INVALID_OFFSET;
2114Int VGOFF_(helper_shldw) = INVALID_OFFSET;
2115Int VGOFF_(helper_shrdl) = INVALID_OFFSET;
2116Int VGOFF_(helper_shrdw) = INVALID_OFFSET;
2117Int VGOFF_(helper_IN) = INVALID_OFFSET;
2118Int VGOFF_(helper_OUT) = INVALID_OFFSET;
2119Int VGOFF_(helper_RDTSC) = INVALID_OFFSET;
2120Int VGOFF_(helper_CPUID) = INVALID_OFFSET;
2121Int VGOFF_(helper_BSWAP) = INVALID_OFFSET;
nethercote1018bdd2004-02-11 23:33:29 +00002122Int VGOFF_(helper_bsfw) = INVALID_OFFSET;
2123Int VGOFF_(helper_bsfl) = INVALID_OFFSET;
2124Int VGOFF_(helper_bsrw) = INVALID_OFFSET;
2125Int VGOFF_(helper_bsrl) = INVALID_OFFSET;
nethercote71980f02004-01-24 18:18:54 +00002126Int VGOFF_(helper_fstsw_AX) = INVALID_OFFSET;
2127Int VGOFF_(helper_SAHF) = INVALID_OFFSET;
2128Int VGOFF_(helper_LAHF) = INVALID_OFFSET;
2129Int VGOFF_(helper_DAS) = INVALID_OFFSET;
2130Int VGOFF_(helper_DAA) = INVALID_OFFSET;
nethercote1018bdd2004-02-11 23:33:29 +00002131Int VGOFF_(helper_AAS) = INVALID_OFFSET;
2132Int VGOFF_(helper_AAA) = INVALID_OFFSET;
2133Int VGOFF_(helper_AAD) = INVALID_OFFSET;
2134Int VGOFF_(helper_AAM) = INVALID_OFFSET;
nethercote71980f02004-01-24 18:18:54 +00002135Int VGOFF_(helper_cmpxchg8b) = INVALID_OFFSET;
2136Int VGOFF_(helper_undefined_instruction) = INVALID_OFFSET;
2137
2138/* MAX_NONCOMPACT_HELPERS can be increased easily. If MAX_COMPACT_HELPERS is
2139 * increased too much, they won't really be compact any more... */
2140#define MAX_COMPACT_HELPERS 8
2141#define MAX_NONCOMPACT_HELPERS 50
2142
2143UInt VG_(n_compact_helpers) = 0;
2144UInt VG_(n_noncompact_helpers) = 0;
2145
2146Addr VG_(compact_helper_addrs) [MAX_COMPACT_HELPERS];
2147Int VG_(compact_helper_offsets)[MAX_COMPACT_HELPERS];
2148Addr VG_(noncompact_helper_addrs) [MAX_NONCOMPACT_HELPERS];
2149Int VG_(noncompact_helper_offsets)[MAX_NONCOMPACT_HELPERS];
2150
2151/* This is the actual defn of baseblock. */
2152UInt VG_(baseBlock)[VG_BASEBLOCK_WORDS];
2153
nethercote71980f02004-01-24 18:18:54 +00002154/* Words. */
2155static Int baB_off = 0;
2156
2157
sewardjfa492d42002-12-08 18:20:01 +00002158UInt VG_(insertDflag)(UInt eflags, Int d)
2159{
2160 vg_assert(d == 1 || d == -1);
2161 eflags &= ~EFlagD;
2162
2163 if (d < 0)
2164 eflags |= EFlagD;
2165
2166 return eflags;
2167}
2168
2169Int VG_(extractDflag)(UInt eflags)
2170{
2171 Int ret;
2172
2173 if (eflags & EFlagD)
2174 ret = -1;
2175 else
2176 ret = 1;
2177
2178 return ret;
2179}
2180
nethercote71980f02004-01-24 18:18:54 +00002181/* Returns the offset, in words. */
2182static Int alloc_BaB ( Int words )
sewardjde4a1d02002-03-22 01:27:54 +00002183{
nethercote71980f02004-01-24 18:18:54 +00002184 Int off = baB_off;
2185 baB_off += words;
2186 if (baB_off >= VG_BASEBLOCK_WORDS)
2187 VG_(core_panic)( "alloc_BaB: baseBlock is too small");
sewardjde4a1d02002-03-22 01:27:54 +00002188
nethercote71980f02004-01-24 18:18:54 +00002189 return off;
sewardjde4a1d02002-03-22 01:27:54 +00002190}
2191
nethercote71980f02004-01-24 18:18:54 +00002192/* Align offset, in *bytes* */
2193static void align_BaB ( UInt align )
njn25e49d8e72002-09-23 09:36:25 +00002194{
nethercote71980f02004-01-24 18:18:54 +00002195 vg_assert(2 == align || 4 == align || 8 == align || 16 == align);
2196 baB_off += (align-1);
2197 baB_off &= ~(align-1);
njn25e49d8e72002-09-23 09:36:25 +00002198}
2199
nethercote71980f02004-01-24 18:18:54 +00002200/* Allocate 1 word in baseBlock and set it to the given value. */
2201static Int alloc_BaB_1_set ( Addr a )
njn25e49d8e72002-09-23 09:36:25 +00002202{
nethercote71980f02004-01-24 18:18:54 +00002203 Int off = alloc_BaB(1);
2204 VG_(baseBlock)[off] = (UInt)a;
2205 return off;
njn25e49d8e72002-09-23 09:36:25 +00002206}
2207
nethercote71980f02004-01-24 18:18:54 +00002208/* Registers a function in compact_helper_addrs; compact_helper_offsets is
2209 filled in later. */
2210void VG_(register_compact_helper)(Addr a)
sewardjde4a1d02002-03-22 01:27:54 +00002211{
nethercote71980f02004-01-24 18:18:54 +00002212 if (MAX_COMPACT_HELPERS <= VG_(n_compact_helpers)) {
2213 VG_(printf)("Can only register %d compact helpers\n",
2214 MAX_COMPACT_HELPERS);
2215 VG_(core_panic)("Too many compact helpers registered");
2216 }
2217 VG_(compact_helper_addrs)[VG_(n_compact_helpers)] = a;
2218 VG_(n_compact_helpers)++;
2219}
2220
2221/* Registers a function in noncompact_helper_addrs; noncompact_helper_offsets
2222 * is filled in later.
2223 */
2224void VG_(register_noncompact_helper)(Addr a)
2225{
2226 if (MAX_NONCOMPACT_HELPERS <= VG_(n_noncompact_helpers)) {
2227 VG_(printf)("Can only register %d non-compact helpers\n",
2228 MAX_NONCOMPACT_HELPERS);
2229 VG_(printf)("Try increasing MAX_NON_COMPACT_HELPERS\n");
2230 VG_(core_panic)("Too many non-compact helpers registered");
2231 }
2232 VG_(noncompact_helper_addrs)[VG_(n_noncompact_helpers)] = a;
2233 VG_(n_noncompact_helpers)++;
2234}
2235
2236/* Allocate offsets in baseBlock for the skin helpers */
2237static
2238void assign_helpers_in_baseBlock(UInt n, Int offsets[], Addr addrs[])
2239{
2240 UInt i;
2241 for (i = 0; i < n; i++)
2242 offsets[i] = alloc_BaB_1_set( addrs[i] );
2243}
2244
2245Bool VG_(need_to_handle_esp_assignment)(void)
2246{
2247 return ( VG_(defined_new_mem_stack_4)() ||
2248 VG_(defined_die_mem_stack_4)() ||
2249 VG_(defined_new_mem_stack_8)() ||
2250 VG_(defined_die_mem_stack_8)() ||
2251 VG_(defined_new_mem_stack_12)() ||
2252 VG_(defined_die_mem_stack_12)() ||
2253 VG_(defined_new_mem_stack_16)() ||
2254 VG_(defined_die_mem_stack_16)() ||
2255 VG_(defined_new_mem_stack_32)() ||
2256 VG_(defined_die_mem_stack_32)() ||
2257 VG_(defined_new_mem_stack)() ||
2258 VG_(defined_die_mem_stack)()
2259 );
2260}
2261
2262/* Here we assign actual offsets. It's important to get the most
2263 popular referents within 128 bytes of the start, so we can take
2264 advantage of short addressing modes relative to %ebp. Popularity
2265 of offsets was measured on 22 Feb 02 running a KDE application, and
2266 the slots rearranged accordingly, with a 1.5% reduction in total
2267 size of translations. */
2268static void init_baseBlock ( Addr client_eip, Addr esp_at_startup )
2269{
2270 /* Those with offsets under 128 are carefully chosen. */
2271
2272 /* WORD offsets in this column */
2273 /* 0 */ VGOFF_(m_eax) = alloc_BaB_1_set(0);
2274 /* 1 */ VGOFF_(m_ecx) = alloc_BaB_1_set(0);
2275 /* 2 */ VGOFF_(m_edx) = alloc_BaB_1_set(0);
2276 /* 3 */ VGOFF_(m_ebx) = alloc_BaB_1_set(0);
2277 /* 4 */ VGOFF_(m_esp) = alloc_BaB_1_set(esp_at_startup);
2278 /* 5 */ VGOFF_(m_ebp) = alloc_BaB_1_set(0);
2279 /* 6 */ VGOFF_(m_esi) = alloc_BaB_1_set(0);
2280 /* 7 */ VGOFF_(m_edi) = alloc_BaB_1_set(0);
2281 /* 8 */ VGOFF_(m_eflags) = alloc_BaB_1_set(0);
2282
2283 if (VG_(needs).shadow_regs) {
2284 /* 9 */ VGOFF_(sh_eax) = alloc_BaB_1_set(0);
2285 /* 10 */ VGOFF_(sh_ecx) = alloc_BaB_1_set(0);
2286 /* 11 */ VGOFF_(sh_edx) = alloc_BaB_1_set(0);
2287 /* 12 */ VGOFF_(sh_ebx) = alloc_BaB_1_set(0);
2288 /* 13 */ VGOFF_(sh_esp) = alloc_BaB_1_set(0);
2289 /* 14 */ VGOFF_(sh_ebp) = alloc_BaB_1_set(0);
2290 /* 15 */ VGOFF_(sh_esi) = alloc_BaB_1_set(0);
2291 /* 16 */ VGOFF_(sh_edi) = alloc_BaB_1_set(0);
2292 /* 17 */ VGOFF_(sh_eflags) = alloc_BaB_1_set(0);
2293 VG_TRACK( post_regs_write_init );
2294 }
2295
2296 /* 9,10,11 or 18,19,20... depends on number whether shadow regs are used
2297 * and on compact helpers registered */
2298
2299 /* Make these most-frequently-called specialised ones compact, if they
2300 are used. */
2301 if (VG_(defined_new_mem_stack_4)())
2302 VG_(register_compact_helper)( (Addr) VG_(tool_interface).track_new_mem_stack_4);
2303
2304 if (VG_(defined_die_mem_stack_4)())
2305 VG_(register_compact_helper)( (Addr) VG_(tool_interface).track_die_mem_stack_4);
2306
2307 /* (9 or 18) + n_compact_helpers */
2308 /* Allocate slots for compact helpers */
2309 assign_helpers_in_baseBlock(VG_(n_compact_helpers),
2310 VG_(compact_helper_offsets),
2311 VG_(compact_helper_addrs));
2312
2313 /* (9/10 or 18/19) + n_compact_helpers */
2314 VGOFF_(m_eip) = alloc_BaB_1_set(client_eip);
2315
2316 /* There are currently 24 spill slots */
2317 /* (11+/20+ .. 32+/43+) + n_compact_helpers. This can overlap the magic
2318 * boundary at >= 32 words, but most spills are to low numbered spill
2319 * slots, so the ones above the boundary don't see much action. */
2320 VGOFF_(spillslots) = alloc_BaB(VG_MAX_SPILLSLOTS);
2321
2322 /* I gave up counting at this point. Since they're above the
2323 short-amode-boundary, there's no point. */
2324
2325 VGOFF_(m_dflag) = alloc_BaB_1_set(1); // 1 == forward D-flag
2326
2327 /* The FPU/SSE state. This _must_ be 16-byte aligned. Initial
2328 state doesn't matter much, as long as it's not totally borked. */
2329 align_BaB(16);
2330 VGOFF_(m_ssestate) = alloc_BaB(VG_SIZE_OF_SSESTATE_W);
2331 vg_assert(
2332 0 == ( ((UInt)(& VG_(baseBlock)[VGOFF_(m_ssestate)])) % 16 )
sewardj22854b92002-11-30 14:00:47 +00002333 );
2334
fitzhardingec2dbbac2004-01-23 23:09:01 +00002335 /* I assume that if we have SSE2 we also have SSE */
2336 VG_(have_ssestate) =
2337 VG_(cpu_has_feature)(VG_X86_FEAT_FXSR) &&
2338 VG_(cpu_has_feature)(VG_X86_FEAT_SSE);
2339
fitzhardinge98abfc72003-12-16 02:05:15 +00002340 /* set up an initial FPU state (doesn't really matter what it is,
2341 so long as it's somewhat valid) */
2342 if (!VG_(have_ssestate))
nethercote71980f02004-01-24 18:18:54 +00002343 asm volatile("fwait; fnsave %0; fwait; frstor %0; fwait"
2344 :
2345 : "m" (VG_(baseBlock)[VGOFF_(m_ssestate)])
2346 : "cc", "memory");
fitzhardinge98abfc72003-12-16 02:05:15 +00002347 else
nethercote71980f02004-01-24 18:18:54 +00002348 asm volatile("fwait; fxsave %0; fwait; andl $0xffbf, %1;"
2349 "fxrstor %0; fwait"
2350 :
2351 : "m" (VG_(baseBlock)[VGOFF_(m_ssestate)]),
2352 "m" (VG_(baseBlock)[VGOFF_(m_ssestate)+(24/4)])
2353 : "cc", "memory");
fitzhardinge98abfc72003-12-16 02:05:15 +00002354
njn0c7a5b52003-04-30 09:00:33 +00002355 if (0) {
2356 if (VG_(have_ssestate))
2357 VG_(printf)("Looks like a SSE-capable CPU\n");
2358 else
2359 VG_(printf)("Looks like a MMX-only CPU\n");
2360 }
sewardjb91ae7f2003-04-29 23:50:00 +00002361
nethercote71980f02004-01-24 18:18:54 +00002362 /* LDT pointer: pretend the root thread has an empty LDT to start with. */
2363 VGOFF_(ldt) = alloc_BaB_1_set((UInt)NULL);
jsgf855d93d2003-10-13 22:26:55 +00002364
nethercote71980f02004-01-24 18:18:54 +00002365 /* TLS pointer: pretend the root thread has no TLS array for now. */
2366 VGOFF_(tls) = alloc_BaB_1_set((UInt)NULL);
fitzhardingef0046f22003-12-18 02:39:22 +00002367
nethercote71980f02004-01-24 18:18:54 +00002368 /* segment registers */
2369 VGOFF_(m_cs) = alloc_BaB_1_set(0);
2370 VGOFF_(m_ss) = alloc_BaB_1_set(0);
2371 VGOFF_(m_ds) = alloc_BaB_1_set(0);
2372 VGOFF_(m_es) = alloc_BaB_1_set(0);
2373 VGOFF_(m_fs) = alloc_BaB_1_set(0);
2374 VGOFF_(m_gs) = alloc_BaB_1_set(0);
fitzhardingef0046f22003-12-18 02:39:22 +00002375
thughes35cec982004-04-21 15:16:43 +00002376 /* initialise %cs, %ds and %ss to point at the operating systems
2377 default code, data and stack segments */
2378 asm volatile("movw %%cs, %0"
2379 :
2380 : "m" (VG_(baseBlock)[VGOFF_(m_cs)]));
2381 asm volatile("movw %%ds, %0"
2382 :
2383 : "m" (VG_(baseBlock)[VGOFF_(m_ds)]));
2384 asm volatile("movw %%ss, %0"
2385 :
2386 : "m" (VG_(baseBlock)[VGOFF_(m_ss)]));
2387
nethercote71980f02004-01-24 18:18:54 +00002388 VG_(register_noncompact_helper)( (Addr) & VG_(do_useseg) );
fitzhardingef0046f22003-12-18 02:39:22 +00002389
nethercote71980f02004-01-24 18:18:54 +00002390#define REG(kind, size) \
2391 if (VG_(defined_##kind##_mem_stack##size)()) \
2392 VG_(register_noncompact_helper)( \
2393 (Addr) VG_(tool_interface).track_##kind##_mem_stack##size );
2394 REG(new, _8);
2395 REG(new, _12);
2396 REG(new, _16);
2397 REG(new, _32);
2398 REG(new, );
2399 REG(die, _8);
2400 REG(die, _12);
2401 REG(die, _16);
2402 REG(die, _32);
2403 REG(die, );
2404#undef REG
fitzhardingef0046f22003-12-18 02:39:22 +00002405
nethercote71980f02004-01-24 18:18:54 +00002406 if (VG_(need_to_handle_esp_assignment)())
2407 VG_(register_noncompact_helper)((Addr) VG_(unknown_esp_update));
fitzhardingeb791a192003-12-18 07:22:44 +00002408
nethercote71980f02004-01-24 18:18:54 +00002409# define HELPER(name) \
2410 VGOFF_(helper_##name) = alloc_BaB_1_set( (Addr) & VG_(helper_##name))
njn3e884182003-04-15 13:03:23 +00002411
nethercote71980f02004-01-24 18:18:54 +00002412 /* Helper functions. */
2413 HELPER(idiv_64_32); HELPER(div_64_32);
2414 HELPER(idiv_32_16); HELPER(div_32_16);
2415 HELPER(idiv_16_8); HELPER(div_16_8);
fitzhardinge98abfc72003-12-16 02:05:15 +00002416
nethercote71980f02004-01-24 18:18:54 +00002417 HELPER(imul_32_64); HELPER(mul_32_64);
2418 HELPER(imul_16_32); HELPER(mul_16_32);
2419 HELPER(imul_8_16); HELPER(mul_8_16);
njn25e49d8e72002-09-23 09:36:25 +00002420
nethercote71980f02004-01-24 18:18:54 +00002421 HELPER(CLD); HELPER(STD);
2422 HELPER(get_dirflag);
sewardjde4a1d02002-03-22 01:27:54 +00002423
nethercote71980f02004-01-24 18:18:54 +00002424 HELPER(CLC); HELPER(STC);
nethercote1018bdd2004-02-11 23:33:29 +00002425 HELPER(CMC);
jsgf855d93d2003-10-13 22:26:55 +00002426
nethercote71980f02004-01-24 18:18:54 +00002427 HELPER(shldl); HELPER(shldw);
2428 HELPER(shrdl); HELPER(shrdw);
njncc7bb472002-10-14 09:25:19 +00002429
nethercote71980f02004-01-24 18:18:54 +00002430 HELPER(RDTSC); HELPER(CPUID);
njncc7bb472002-10-14 09:25:19 +00002431
nethercote1018bdd2004-02-11 23:33:29 +00002432 HELPER(bsfw); HELPER(bsfl);
2433 HELPER(bsrw); HELPER(bsrl);
rjwalshf5f536f2003-11-17 17:45:00 +00002434
nethercote71980f02004-01-24 18:18:54 +00002435 HELPER(fstsw_AX);
2436 HELPER(SAHF); HELPER(LAHF);
2437 HELPER(DAS); HELPER(DAA);
nethercote1018bdd2004-02-11 23:33:29 +00002438 HELPER(AAS); HELPER(AAA);
2439 HELPER(AAD); HELPER(AAM);
nethercote71980f02004-01-24 18:18:54 +00002440 HELPER(IN); HELPER(OUT);
2441 HELPER(cmpxchg8b);
sewardj018f7622002-05-15 21:13:39 +00002442
nethercote71980f02004-01-24 18:18:54 +00002443 HELPER(undefined_instruction);
jsgf855d93d2003-10-13 22:26:55 +00002444
nethercote71980f02004-01-24 18:18:54 +00002445# undef HELPER
sewardjde4a1d02002-03-22 01:27:54 +00002446
nethercote71980f02004-01-24 18:18:54 +00002447 /* Allocate slots for noncompact helpers */
2448 assign_helpers_in_baseBlock(VG_(n_noncompact_helpers),
2449 VG_(noncompact_helper_offsets),
2450 VG_(noncompact_helper_addrs));
2451}
sewardjde4a1d02002-03-22 01:27:54 +00002452
sewardj5f07b662002-04-23 16:52:51 +00002453
nethercote71980f02004-01-24 18:18:54 +00002454/*====================================================================*/
2455/*=== Setup pointercheck ===*/
2456/*====================================================================*/
njn25e49d8e72002-09-23 09:36:25 +00002457
nethercote71980f02004-01-24 18:18:54 +00002458static void setup_pointercheck(void)
2459{
2460 int ret;
sewardj2e93c502002-04-12 11:12:52 +00002461
fitzhardinge98abfc72003-12-16 02:05:15 +00002462 if (VG_(clo_pointercheck)) {
nethercote71980f02004-01-24 18:18:54 +00002463 vki_modify_ldt_t ldt = {
2464 VG_POINTERCHECK_SEGIDX, // entry_number
2465 VG_(client_base), // base_addr
2466 (VG_(client_end)-VG_(client_base)) / VKI_BYTES_PER_PAGE, // limit
2467 1, // seg_32bit
2468 0, // contents: data, RW, non-expanding
2469 0, // ! read_exec_only
2470 1, // limit_in_pages
2471 0, // ! seg not present
2472 1, // useable
fitzhardinge98abfc72003-12-16 02:05:15 +00002473 };
nethercote71980f02004-01-24 18:18:54 +00002474 ret = VG_(do_syscall)(__NR_modify_ldt, 1, &ldt, sizeof(ldt));
fitzhardinge98abfc72003-12-16 02:05:15 +00002475 if (ret < 0) {
2476 VG_(message)(Vg_UserMsg,
2477 "Warning: ignoring --pointercheck=yes, "
2478 "because modify_ldt failed (errno=%d)", -ret);
2479 VG_(clo_pointercheck) = False;
2480 }
2481 }
sewardjde4a1d02002-03-22 01:27:54 +00002482}
2483
nethercote71980f02004-01-24 18:18:54 +00002484/*====================================================================*/
2485/*=== Initialise program data/text, etc. ===*/
2486/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +00002487
nethercote71980f02004-01-24 18:18:54 +00002488static void build_valgrind_map_callback
2489 ( Addr start, UInt size, Char rr, Char ww, Char xx,
2490 UInt dev, UInt ino, ULong foffset, const UChar* filename )
sewardjde4a1d02002-03-22 01:27:54 +00002491{
nethercote71980f02004-01-24 18:18:54 +00002492 UInt prot = 0;
2493 UInt flags = SF_MMAP|SF_NOSYMS;
2494 Bool is_stack_segment;
2495
2496 is_stack_segment =
2497 (start == VG_(clstk_base) && (start+size) == VG_(clstk_end));
2498
2499 /* Only record valgrind mappings for now, without loading any
2500 symbols. This is so we know where the free space is before we
2501 start allocating more memory (note: heap is OK, it's just mmap
2502 which is the problem here). */
2503 if (start >= VG_(valgrind_base) && (start+size) <= VG_(valgrind_end)) {
2504 flags |= SF_VALGRIND;
2505 VG_(map_file_segment)(start, size, prot, flags, dev, ino, foffset, filename);
2506 }
sewardjde4a1d02002-03-22 01:27:54 +00002507}
2508
nethercote71980f02004-01-24 18:18:54 +00002509// Global var used to pass local data to callback
2510Addr esp_at_startup___global_arg = 0;
sewardjde4a1d02002-03-22 01:27:54 +00002511
nethercote71980f02004-01-24 18:18:54 +00002512static void build_segment_map_callback
2513 ( Addr start, UInt size, Char rr, Char ww, Char xx,
2514 UInt dev, UInt ino, ULong foffset, const UChar* filename )
sewardj45b672d2003-07-25 19:58:11 +00002515{
nethercote71980f02004-01-24 18:18:54 +00002516 UInt prot = 0;
2517 UInt flags;
2518 Bool is_stack_segment;
2519 Addr r_esp;
sewardj45b672d2003-07-25 19:58:11 +00002520
nethercote71980f02004-01-24 18:18:54 +00002521 is_stack_segment
2522 = (start == VG_(clstk_base) && (start+size) == VG_(clstk_end));
fitzhardinge98abfc72003-12-16 02:05:15 +00002523
nethercote71980f02004-01-24 18:18:54 +00002524 if (rr == 'r') prot |= VKI_PROT_READ;
2525 if (ww == 'w') prot |= VKI_PROT_WRITE;
2526 if (xx == 'x') prot |= VKI_PROT_EXEC;
fitzhardinge98abfc72003-12-16 02:05:15 +00002527
nethercote71980f02004-01-24 18:18:54 +00002528 if (is_stack_segment)
2529 flags = SF_STACK | SF_GROWDOWN;
2530 else
2531 flags = SF_EXEC|SF_MMAP;
fitzhardinge98abfc72003-12-16 02:05:15 +00002532
nethercote71980f02004-01-24 18:18:54 +00002533 if (filename != NULL)
2534 flags |= SF_FILE;
fitzhardinge98abfc72003-12-16 02:05:15 +00002535
nethercote71980f02004-01-24 18:18:54 +00002536 if (start >= VG_(valgrind_base) && (start+size) <= VG_(valgrind_end))
2537 flags |= SF_VALGRIND;
fitzhardinge98abfc72003-12-16 02:05:15 +00002538
nethercote71980f02004-01-24 18:18:54 +00002539 VG_(map_file_segment)(start, size, prot, flags, dev, ino, foffset, filename);
fitzhardinge98abfc72003-12-16 02:05:15 +00002540
nethercote71980f02004-01-24 18:18:54 +00002541 if (VG_(is_client_addr)(start) && VG_(is_client_addr)(start+size-1))
2542 VG_TRACK( new_mem_startup, start, size, rr=='r', ww=='w', xx=='x' );
sewardj3e1eb1f2002-05-18 13:14:17 +00002543
nethercote71980f02004-01-24 18:18:54 +00002544 /* If this is the stack segment mark all below %esp as noaccess. */
2545 r_esp = esp_at_startup___global_arg;
2546 vg_assert(0 != r_esp);
2547 if (is_stack_segment) {
2548 if (0)
2549 VG_(message)(Vg_DebugMsg, "invalidating stack area: %x .. %x",
2550 start,r_esp);
2551 VG_TRACK( die_mem_stack, start, r_esp-start );
sewardjde4a1d02002-03-22 01:27:54 +00002552 }
sewardjde4a1d02002-03-22 01:27:54 +00002553}
2554
2555
nethercote71980f02004-01-24 18:18:54 +00002556/*====================================================================*/
2557/*=== Sanity check machinery (permanently engaged) ===*/
2558/*====================================================================*/
njn25e49d8e72002-09-23 09:36:25 +00002559
2560/* A fast sanity check -- suitable for calling circa once per
2561 millisecond. */
2562
2563void VG_(do_sanity_checks) ( Bool force_expensive )
2564{
njn37cea302002-09-30 11:24:00 +00002565 VGP_PUSHCC(VgpCoreCheapSanity);
2566
nethercote27fec902004-06-16 21:26:32 +00002567 if (VG_(clo_sanity_level) < 1) return;
njn25e49d8e72002-09-23 09:36:25 +00002568
2569 /* --- First do all the tests that we can do quickly. ---*/
2570
2571 VG_(sanity_fast_count)++;
2572
njn25e49d8e72002-09-23 09:36:25 +00002573 /* Check stuff pertaining to the memory check system. */
2574
2575 /* Check that nobody has spuriously claimed that the first or
2576 last 16 pages of memory have become accessible [...] */
njn37cea302002-09-30 11:24:00 +00002577 if (VG_(needs).sanity_checks) {
2578 VGP_PUSHCC(VgpSkinCheapSanity);
njn25e49d8e72002-09-23 09:36:25 +00002579 vg_assert(SK_(cheap_sanity_check)());
njn37cea302002-09-30 11:24:00 +00002580 VGP_POPCC(VgpSkinCheapSanity);
2581 }
njn25e49d8e72002-09-23 09:36:25 +00002582
2583 /* --- Now some more expensive checks. ---*/
2584
2585 /* Once every 25 times, check some more expensive stuff. */
2586 if ( force_expensive
nethercote27fec902004-06-16 21:26:32 +00002587 || VG_(clo_sanity_level) > 1
2588 || (VG_(clo_sanity_level) == 1 && (VG_(sanity_fast_count) % 25) == 0)) {
njn25e49d8e72002-09-23 09:36:25 +00002589
njn37cea302002-09-30 11:24:00 +00002590 VGP_PUSHCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002591 VG_(sanity_slow_count)++;
2592
jsgf855d93d2003-10-13 22:26:55 +00002593 VG_(proxy_sanity)();
2594
njn25e49d8e72002-09-23 09:36:25 +00002595# if 0
2596 { void zzzmemscan(void); zzzmemscan(); }
2597# endif
2598
2599 if ((VG_(sanity_fast_count) % 250) == 0)
2600 VG_(sanity_check_tc_tt)();
2601
2602 if (VG_(needs).sanity_checks) {
njn37cea302002-09-30 11:24:00 +00002603 VGP_PUSHCC(VgpSkinExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002604 vg_assert(SK_(expensive_sanity_check)());
njn37cea302002-09-30 11:24:00 +00002605 VGP_POPCC(VgpSkinExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002606 }
2607 /*
2608 if ((VG_(sanity_fast_count) % 500) == 0) VG_(mallocSanityCheckAll)();
2609 */
njn37cea302002-09-30 11:24:00 +00002610 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002611 }
2612
nethercote27fec902004-06-16 21:26:32 +00002613 if (VG_(clo_sanity_level) > 1) {
njn37cea302002-09-30 11:24:00 +00002614 VGP_PUSHCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002615 /* Check sanity of the low-level memory manager. Note that bugs
2616 in the client's code can cause this to fail, so we don't do
2617 this check unless specially asked for. And because it's
2618 potentially very expensive. */
2619 VG_(mallocSanityCheckAll)();
njn37cea302002-09-30 11:24:00 +00002620 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002621 }
njn37cea302002-09-30 11:24:00 +00002622 VGP_POPCC(VgpCoreCheapSanity);
njn25e49d8e72002-09-23 09:36:25 +00002623}
nethercote71980f02004-01-24 18:18:54 +00002624
2625
2626/*====================================================================*/
2627/*=== main() ===*/
2628/*====================================================================*/
2629
2630int main(int argc, char **argv)
2631{
2632 char **cl_argv;
2633 const char *tool = NULL;
2634 const char *exec = NULL;
2635 char *preload; /* tool-specific LD_PRELOAD .so */
2636 char **env;
nethercote6c999f22004-01-31 22:55:15 +00002637 Int need_help = 0; // 0 = no, 1 = --help, 2 = --help-debug
nethercote71980f02004-01-24 18:18:54 +00002638 struct exeinfo info;
2639 ToolInfo *toolinfo = NULL;
2640 void *tool_dlhandle;
2641 Addr client_eip;
2642 Addr esp_at_startup; /* client's %esp at the point we gained control. */
2643 UInt * client_auxv;
2644 VgSchedReturnCode src;
nethercote47dd12c2004-06-22 14:18:42 +00002645 Int exitcode = 0;
fitzhardingeb50068f2004-02-24 23:42:55 +00002646 vki_rlimit zero = { 0, 0 };
nethercote71980f02004-01-24 18:18:54 +00002647
2648 //============================================================
2649 // Nb: startup is complex. Prerequisites are shown at every step.
2650 //
2651 // *** Be very careful when messing with the order ***
2652 //============================================================
2653
nethercotef4928da2004-06-15 10:54:40 +00002654 //============================================================
2655 // Command line argument handling order:
2656 // * If --help/--help-debug are present, show usage message
2657 // (if --tool is also present, that includes the tool-specific usage)
2658 // * Then, if --tool is missing, abort with error msg
2659 // * Then, if client is missing, abort with error msg
2660 // * Then, if any cmdline args are bad, abort with error msg
2661 //============================================================
2662
fitzhardingeb50068f2004-02-24 23:42:55 +00002663 // Get the current process datasize rlimit, and set it to zero.
2664 // This prevents any internal uses of brk() from having any effect.
2665 // We remember the old value so we can restore it on exec, so that
2666 // child processes will have a reasonable brk value.
2667 VG_(getrlimit)(VKI_RLIMIT_DATA, &VG_(client_rlimit_data));
2668 zero.rlim_max = VG_(client_rlimit_data).rlim_max;
2669 VG_(setrlimit)(VKI_RLIMIT_DATA, &zero);
2670
nethercote71980f02004-01-24 18:18:54 +00002671 //--------------------------------------------------------------
2672 // Check we were launched by stage1
2673 // p: n/a [must be first step]
2674 //--------------------------------------------------------------
2675 scan_auxv();
2676
2677 if (0) {
2678 int prmap(void *start, void *end, const char *perm, off_t off,
2679 int maj, int min, int ino) {
2680 printf("mapping %10p-%10p %s %02x:%02x %d\n",
2681 start, end, perm, maj, min, ino);
2682 return True;
2683 }
2684 printf("========== main() ==========\n");
2685 foreach_map(prmap);
2686 }
2687
2688 //--------------------------------------------------------------
2689 // Look for alternative libdir
2690 // p: n/a
2691 //--------------------------------------------------------------
2692 { char *cp = getenv(VALGRINDLIB);
2693 if (cp != NULL)
2694 VG_(libdir) = cp;
2695 }
2696
2697 //--------------------------------------------------------------
2698 // Begin working out address space layout
2699 // p: n/a
2700 //--------------------------------------------------------------
2701 layout_client_space( (Addr) & argc );
2702
2703 //--------------------------------------------------------------
2704 // Get valgrind args + client args (inc. from VALGRIND_OPTS/.valgrindrc).
2705 // Pre-process the command line.
2706 // p: n/a
2707 //--------------------------------------------------------------
2708 get_command_line(argc, argv, &VG_(vg_argc), &VG_(vg_argv), &cl_argv);
2709 pre_process_cmd_line_options(&need_help, &tool, &exec);
2710
2711 //==============================================================
2712 // Nb: once a tool is specified, the tool.so must be loaded even if
2713 // they specified --help or didn't specify a client program.
2714 //==============================================================
2715
2716 //--------------------------------------------------------------
2717 // With client padded out, map in tool
2718 // p: layout_client_space() [for padding]
2719 // p: set-libdir [for VG_(libdir)]
2720 // p: pre_process_cmd_line_options() [for 'tool']
2721 //--------------------------------------------------------------
2722 load_tool(tool, &tool_dlhandle, &toolinfo, &preload);
2723
2724 //==============================================================
2725 // Can use VG_(malloc)() and VG_(arena_malloc)() only after load_tool()
2726 // -- redzone size is now set.
2727 //==============================================================
2728
2729 //--------------------------------------------------------------
2730 // Finalise address space layout
2731 // p: layout_client_space(), load_tool() [for 'toolinfo']
2732 //--------------------------------------------------------------
2733 layout_remaining_space( toolinfo->shadow_ratio );
2734
2735 //--------------------------------------------------------------
2736 // Load client executable, finding in $PATH if necessary
2737 // p: layout_client_space() [so there's space]
2738 // p: pre_process_cmd_line_options() [for 'exec', 'need_help']
2739 // p: layout_remaining_space [so there's space]
2740 //--------------------------------------------------------------
nethercotef4928da2004-06-15 10:54:40 +00002741 load_client(cl_argv, exec, need_help, &info, &client_eip);
nethercote71980f02004-01-24 18:18:54 +00002742
2743 //--------------------------------------------------------------
2744 // Everything in place, unpad us
2745 // p: layout_remaining_space() [everything must be mapped in before now]
2746 // p: load_client() [ditto]
2747 //--------------------------------------------------------------
2748 as_unpad((void *)VG_(shadow_end), (void *)~0);
2749 as_closepadfile(); /* no more padding */
2750
2751 //--------------------------------------------------------------
2752 // Set up client's environment
2753 // p: set-libdir [for VG_(libdir)]
2754 // p: load_tool() [for 'preload']
2755 //--------------------------------------------------------------
2756 env = fix_environment(environ, preload);
2757
2758 //--------------------------------------------------------------
nethercote5ee67ca2004-06-22 14:00:09 +00002759 // Setup client stack, eip, and VG_(client_arg[cv])
nethercote71980f02004-01-24 18:18:54 +00002760 // p: load_client() [for 'info']
2761 // p: fix_environment() [for 'env']
2762 //--------------------------------------------------------------
2763 esp_at_startup = setup_client_stack(cl_argv, env, &info, &client_auxv);
2764
2765 if (0)
2766 printf("entry=%x client esp=%x vg_argc=%d brkbase=%x\n",
2767 client_eip, esp_at_startup, VG_(vg_argc), VG_(brk_base));
2768
2769 //==============================================================
2770 // Finished setting up operating environment. Now initialise
2771 // Valgrind. (This is where the old VG_(main)() started.)
2772 //==============================================================
2773
2774 //--------------------------------------------------------------
2775 // Read /proc/self/maps into a buffer
2776 // p: all memory layout, environment setup [so memory maps are right]
2777 //--------------------------------------------------------------
2778 VG_(read_procselfmaps)();
2779
2780 //--------------------------------------------------------------
2781 // atfork
2782 // p: n/a
2783 //--------------------------------------------------------------
2784 VG_(atfork)(NULL, NULL, newpid);
2785 newpid(VG_INVALID_THREADID);
2786
2787 //--------------------------------------------------------------
2788 // setup file descriptors
2789 // p: n/a
2790 //--------------------------------------------------------------
2791 setup_file_descriptors();
2792
2793 //--------------------------------------------------------------
2794 // Setup tool
2795 // p: VG_(read_procselfmaps)() [so if sk_pre_clo_init calls
2796 // VG_(malloc), any mmap'd superblocks aren't erroneously
2797 // identified later as being owned by the client]
2798 // XXX: is that necessary, now that we look for V's segments separately?
2799 // XXX: alternatively, if sk_pre_clo_init does use VG_(malloc)(), is it
2800 // wrong to ignore any segments that might add in parse_procselfmaps?
nethercote5ee67ca2004-06-22 14:00:09 +00002801 // p: setup_client_stack() [for 'VG_(client_arg[cv]']
nethercote71980f02004-01-24 18:18:54 +00002802 //--------------------------------------------------------------
2803 (*toolinfo->sk_pre_clo_init)();
2804 VG_(tool_init_dlsym)(tool_dlhandle);
2805 VG_(sanity_check_needs)();
2806
2807 //--------------------------------------------------------------
nethercotef4928da2004-06-15 10:54:40 +00002808 // If --tool and --help/--help-debug was given, now give the core+tool
2809 // help message
2810 // p: pre_clo_init()
2811 //--------------------------------------------------------------
2812 if (need_help) {
2813 usage(/*--help-debug?*/2 == need_help);
2814 }
2815
2816 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002817 // Process Valgrind's + tool's command-line options
2818 // p: load_tool() [for 'tool']
thughesad1c9562004-06-26 11:27:52 +00002819 // p: setup_file_descriptors() [for 'VG_(fd_xxx_limit)']
nethercote71980f02004-01-24 18:18:54 +00002820 // p: sk_pre_clo_init [to set 'command_line_options' need]
2821 //--------------------------------------------------------------
nethercote5ee67ca2004-06-22 14:00:09 +00002822 process_cmd_line_options(client_auxv, tool);
nethercote71980f02004-01-24 18:18:54 +00002823
2824 //--------------------------------------------------------------
2825 // Allow GDB attach
2826 // p: process_cmd_line_options() [for VG_(clo_wait_for_gdb)]
2827 //--------------------------------------------------------------
2828 /* Hook to delay things long enough so we can get the pid and
2829 attach GDB in another shell. */
2830 if (VG_(clo_wait_for_gdb)) {
2831 VG_(printf)("pid=%d\n", VG_(getpid)());
2832 /* do "jump *$eip" to skip this in gdb */
2833 VG_(do_syscall)(__NR_pause);
2834 }
2835
2836 //--------------------------------------------------------------
2837 // Setup tool, post command-line processing
2838 // p: process_cmd_line_options [tool assumes it]
2839 //--------------------------------------------------------------
2840 SK_(post_clo_init)();
2841
2842 //--------------------------------------------------------------
nethercote1d447092004-02-01 17:29:59 +00002843 // Set up baseBlock
nethercote71980f02004-01-24 18:18:54 +00002844 // p: {pre,post}_clo_init() [for tool helper registration]
2845 // load_client() [for 'client_eip']
2846 // setup_client_stack() [for 'esp_at_startup']
2847 //--------------------------------------------------------------
2848 init_baseBlock(client_eip, esp_at_startup);
2849
2850 //--------------------------------------------------------------
2851 // Search for file descriptors that are inherited from our parent
2852 // p: process_cmd_line_options [for VG_(clo_track_fds)]
2853 //--------------------------------------------------------------
2854 if (VG_(clo_track_fds))
2855 VG_(init_preopened_fds)();
2856
2857 //--------------------------------------------------------------
2858 // Initialise the scheduler
2859 // p: init_baseBlock() [baseBlock regs copied into VG_(threads)[1]]
2860 // p: setup_file_descriptors() [else VG_(safe_fd)() breaks]
2861 //--------------------------------------------------------------
2862 VG_(scheduler_init)();
2863
2864 //--------------------------------------------------------------
2865 // Set up the ProxyLWP machinery
2866 // p: VG_(scheduler_init)()? [XXX: subtle dependency?]
2867 // - subs: VG_(sigstartup_actions)()?
2868 //--------------------------------------------------------------
2869 VG_(proxy_init)();
2870
2871 //--------------------------------------------------------------
2872 // Initialise the signal handling subsystem
2873 // p: VG_(atfork)(NULL, NULL, newpid) [else problems with sigmasks]
2874 // p: VG_(proxy_init)() [else breaks...]
2875 //--------------------------------------------------------------
2876 // Nb: temporarily parks the saved blocking-mask in saved_sigmask.
2877 VG_(sigstartup_actions)();
2878
2879 //--------------------------------------------------------------
2880 // Perhaps we're profiling Valgrind?
2881 // p: process_cmd_line_options() [for VG_(clo_profile)]
2882 // p: others?
2883 //
2884 // XXX: this seems to be broken? It always says the tool wasn't built
2885 // for profiling; vg_profile.c's functions don't seem to be overriding
2886 // vg_dummy_profile.c's?
2887 //
2888 // XXX: want this as early as possible. Looking for --profile
2889 // in pre_process_cmd_line_options() could get it earlier.
2890 //--------------------------------------------------------------
2891 if (VG_(clo_profile))
2892 VGP_(init_profiling)();
2893
2894 VGP_PUSHCC(VgpStartup);
2895
2896 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002897 // Reserve Valgrind's kickstart, heap and stack
2898 // p: XXX ???
2899 //--------------------------------------------------------------
2900 VG_(map_segment)(VG_(valgrind_mmap_end),
2901 VG_(valgrind_end)-VG_(valgrind_mmap_end),
2902 VKI_PROT_NONE, SF_VALGRIND|SF_FIXED);
2903
2904 //--------------------------------------------------------------
2905 // Identify Valgrind's segments
2906 // p: read proc/self/maps
2907 // p: VG_(map_segment) [XXX ???]
2908 // p: sk_pre_clo_init() [to setup new_mem_startup tracker]
2909 //--------------------------------------------------------------
2910 VG_(parse_procselfmaps) ( build_valgrind_map_callback );
2911
2912 // XXX: I can't see why these two need to be separate; could they be
2913 // folded together? If not, need a comment explaining why.
2914 //
2915 // XXX: can we merge reading and parsing of /proc/self/maps?
2916 //
2917 // XXX: can we dynamically allocate the /proc/self/maps buffer? (or mmap
2918 // it?) Or does that disturb its contents...
2919
2920 //--------------------------------------------------------------
2921 // Build segment map (all segments)
2922 // p: setup_client_stack() [for 'esp_at_startup']
2923 //--------------------------------------------------------------
2924 esp_at_startup___global_arg = esp_at_startup;
2925 VG_(parse_procselfmaps) ( build_segment_map_callback ); /* everything */
2926 esp_at_startup___global_arg = 0;
2927
2928 //==============================================================
2929 // Can only use VG_(map)() after VG_(map_segment)() [XXX ???]
2930 //==============================================================
2931
2932 //--------------------------------------------------------------
2933 // Build segment map (all segments)
2934 // p: setup_client_stack() [for 'esp_at_startup']
2935 //--------------------------------------------------------------
2936 /* Initialize our trampoline page (which is also sysinfo stuff) */
2937 VG_(memcpy)( (void *)VG_(client_trampoline_code),
2938 &VG_(trampoline_code_start), VG_(trampoline_code_length) );
2939 VG_(mprotect)( (void *)VG_(client_trampoline_code),
2940 VG_(trampoline_code_length), VKI_PROT_READ|VKI_PROT_EXEC );
2941
2942 //--------------------------------------------------------------
2943 // Read suppression file
2944 // p: process_cmd_line_options() [for VG_(clo_suppressions)]
2945 //--------------------------------------------------------------
2946 if (VG_(needs).core_errors || VG_(needs).skin_errors)
2947 VG_(load_suppressions)();
2948
2949 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002950 // Initialise translation table and translation cache
2951 // p: read_procselfmaps [so the anonymous mmaps for the TT/TC
2952 // aren't identified as part of the client, which would waste
2953 // > 20M of virtual address space.]
2954 //--------------------------------------------------------------
2955 VG_(init_tt_tc)();
2956
2957 //--------------------------------------------------------------
2958 // Read debug info to find glibc entry points to intercept
2959 // p: parse_procselfmaps? [XXX for debug info?]
2960 // p: init_tt_tc? [XXX ???]
2961 //--------------------------------------------------------------
2962 VG_(setup_code_redirect_table)();
2963
2964 //--------------------------------------------------------------
2965 // Verbosity message
2966 // p: end_rdtsc_calibration [so startup message is printed first]
2967 //--------------------------------------------------------------
2968 if (VG_(clo_verbosity) == 1)
2969 VG_(message)(Vg_UserMsg, "For more details, rerun with: -v");
2970 if (VG_(clo_verbosity) > 0)
2971 VG_(message)(Vg_UserMsg, "");
2972
2973 //--------------------------------------------------------------
2974 // Setup pointercheck
2975 // p: process_cmd_line_options() [for VG_(clo_pointercheck)]
2976 //--------------------------------------------------------------
2977 setup_pointercheck();
2978
2979
2980
2981 //--------------------------------------------------------------
2982 // Run!
2983 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002984 VGP_POPCC(VgpStartup);
2985 VGP_PUSHCC(VgpSched);
2986
2987 if (__builtin_setjmp(&VG_(fatal_signal_jmpbuf)) == 0) {
2988 VG_(fatal_signal_set) = True;
nethercote47dd12c2004-06-22 14:18:42 +00002989 src = VG_(scheduler)( &exitcode );
nethercote71980f02004-01-24 18:18:54 +00002990 } else
2991 src = VgSrc_FatalSig;
2992
2993 VGP_POPCC(VgpSched);
nethercote71980f02004-01-24 18:18:54 +00002994
2995
2996
2997 //--------------------------------------------------------------
2998 // Finalisation: cleanup, messages, etc. Order no so important, only
2999 // affects what order the messages come.
3000 //--------------------------------------------------------------
3001 if (VG_(clo_verbosity) > 0)
3002 VG_(message)(Vg_UserMsg, "");
3003
3004 if (src == VgSrc_Deadlock) {
3005 VG_(message)(Vg_UserMsg,
3006 "Warning: pthread scheduler exited due to deadlock");
3007 }
3008
3009 /* Print out file descriptor summary and stats. */
3010 if (VG_(clo_track_fds))
3011 VG_(fd_stats)();
3012
3013 if (VG_(needs).core_errors || VG_(needs).skin_errors)
3014 VG_(show_all_errors)();
3015
nethercote47dd12c2004-06-22 14:18:42 +00003016 SK_(fini)( exitcode );
nethercote71980f02004-01-24 18:18:54 +00003017
3018 VG_(do_sanity_checks)( True /*include expensive checks*/ );
3019
3020 if (VG_(clo_verbosity) > 1)
3021 show_counts();
3022
3023 if (VG_(clo_verbosity) > 3)
3024 VG_(print_UInstr_histogram)();
3025
3026 if (0) {
3027 VG_(message)(Vg_DebugMsg, "");
3028 VG_(message)(Vg_DebugMsg,
3029 "------ Valgrind's internal memory use stats follow ------" );
3030 VG_(mallocSanityCheckAll)();
3031 VG_(show_all_arena_stats)();
3032 VG_(message)(Vg_DebugMsg,
3033 "------ Valgrind's ExeContext management stats follow ------" );
3034 VG_(show_ExeContext_stats)();
3035 }
3036
3037 if (VG_(clo_profile))
3038 VGP_(done_profiling)();
3039
nethercote71980f02004-01-24 18:18:54 +00003040 /* We're exiting, so nuke all the threads and clean up the proxy LWPs */
3041 vg_assert(src == VgSrc_FatalSig ||
3042 VG_(threads)[VG_(last_run_tid)].status == VgTs_Runnable ||
3043 VG_(threads)[VG_(last_run_tid)].status == VgTs_WaitJoiner);
3044 VG_(nuke_all_threads_except)(VG_INVALID_THREADID);
3045
3046 //--------------------------------------------------------------
3047 // Exit, according to the scheduler's return code
3048 //--------------------------------------------------------------
3049 switch (src) {
3050 case VgSrc_ExitSyscall: /* the normal way out */
3051 vg_assert(VG_(last_run_tid) > 0
3052 && VG_(last_run_tid) < VG_N_THREADS);
3053 VG_(proxy_shutdown)();
3054
3055 /* The thread's %EBX at the time it did __NR_exit() will hold
3056 the arg to __NR_exit(), so we just do __NR_exit() with
3057 that arg. */
nethercote47dd12c2004-06-22 14:18:42 +00003058 VG_(exit)( exitcode );
nethercote71980f02004-01-24 18:18:54 +00003059 /* NOT ALIVE HERE! */
3060 VG_(core_panic)("entered the afterlife in main() -- ExitSyscall");
3061 break; /* what the hell :) */
3062
3063 case VgSrc_Deadlock:
3064 /* Just exit now. No point in continuing. */
3065 VG_(proxy_shutdown)();
3066 VG_(exit)(0);
3067 VG_(core_panic)("entered the afterlife in main() -- Deadlock");
3068 break;
3069
nethercote71980f02004-01-24 18:18:54 +00003070 case VgSrc_FatalSig:
3071 /* We were killed by a fatal signal, so replicate the effect */
3072 vg_assert(VG_(fatal_sigNo) != -1);
3073 VG_(kill_self)(VG_(fatal_sigNo));
3074 VG_(core_panic)("main(): signal was supposed to be fatal");
3075 break;
3076
3077 default:
3078 VG_(core_panic)("main(): unexpected scheduler return code");
3079 }
3080
3081 abort();
3082}
3083
3084
sewardjde4a1d02002-03-22 01:27:54 +00003085/*--------------------------------------------------------------------*/
3086/*--- end vg_main.c ---*/
3087/*--------------------------------------------------------------------*/