blob: 14c302b78725e76026c8fe5890876a8754a16f81 [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{
nethercotee567e702004-07-10 17:49:17 +0000504 Int ires;
505 void* vres;
506
nethercote71980f02004-01-24 18:18:54 +0000507 /* This tries to give the client as large as possible address space while
508 * taking into account the tool's shadow needs. */
509 addr_t client_size = ROUNDDN((VG_(valgrind_base) - REDZONE_SIZE) / (1. + ratio),
510 CLIENT_SIZE_MULTIPLE);
511 addr_t shadow_size = PGROUNDUP(client_size * ratio);
512
513 VG_(client_end) = VG_(client_base) + client_size;
514 VG_(client_mapbase) = PGROUNDDN((client_size/4)*3); /* where !FIXED mmap goes */
nethercotee2097312004-06-27 12:29:56 +0000515
516 /* where !FIXED mmap goes */
517 VG_(client_mapbase) = PGROUNDDN((addr_t)(client_size * CLIENT_HEAP_PROPORTION));
nethercote71980f02004-01-24 18:18:54 +0000518 VG_(client_trampoline_code) = VG_(client_end) - VKI_BYTES_PER_PAGE;
519
520 VG_(shadow_base) = VG_(client_end) + REDZONE_SIZE;
521 VG_(shadow_end) = VG_(shadow_base) + shadow_size;
522
nethercotee2097312004-06-27 12:29:56 +0000523#define SEGSIZE(a,b) ((VG_(b) - VG_(a))/(1024*1024))
524
nethercote71980f02004-01-24 18:18:54 +0000525 if (0)
nethercotee2097312004-06-27 12:29:56 +0000526 VG_(printf)(
527 "client_base %8x (%dMB)\n"
528 "client_mapbase %8x (%dMB)\n"
529 "client_end %8x (%dMB)\n"
530 "shadow_base %8x (%dMB)\n"
531 "shadow_end %8x (%dMB)\n"
532 "valgrind_base %8x (%dMB)\n"
533 "valgrind_mmap_end %8x (%dMB)\n"
534 "valgrind_end %8x\n",
535 VG_(client_base), SEGSIZE(client_base, client_mapbase),
536 VG_(client_mapbase), SEGSIZE(client_mapbase, client_end),
537 VG_(client_end), SEGSIZE(client_end, shadow_base),
538 VG_(shadow_base), SEGSIZE(shadow_base, shadow_end),
539 VG_(shadow_end), SEGSIZE(shadow_end, valgrind_base),
540 VG_(valgrind_base), SEGSIZE(valgrind_base, valgrind_mmap_end),
541 VG_(valgrind_mmap_end), SEGSIZE(valgrind_mmap_end, valgrind_end),
542 VG_(valgrind_end)
543 );
544
545#undef SEGSIZE
nethercote71980f02004-01-24 18:18:54 +0000546
547 // Ban redzone
nethercotee567e702004-07-10 17:49:17 +0000548 vres = mmap((void *)VG_(client_end), REDZONE_SIZE, PROT_NONE,
549 MAP_FIXED|MAP_ANON|MAP_PRIVATE, -1, 0);
550 vg_assert((void*)-1 != vres);
nethercote71980f02004-01-24 18:18:54 +0000551
552 // Make client hole
nethercotee567e702004-07-10 17:49:17 +0000553 ires = munmap((void*)VG_(client_base), client_size);
554 vg_assert(0 == ires);
nethercote71980f02004-01-24 18:18:54 +0000555
556 // Map shadow memory.
557 // Initially all inaccessible, incrementally initialized as it is used
nethercotee567e702004-07-10 17:49:17 +0000558 if (shadow_size != 0) {
559 vres = mmap((char *)VG_(shadow_base), shadow_size, PROT_NONE,
560 MAP_PRIVATE|MAP_ANON|MAP_FIXED, -1, 0);
561 vg_assert((void*)-1 != vres);
562 }
nethercote71980f02004-01-24 18:18:54 +0000563}
564
565/*====================================================================*/
566/*=== Command line setup ===*/
567/*====================================================================*/
568
569/* Nb: malloc'd memory never freed -- kept throughout like argv, envp */
570static char* get_file_clo(char* dir)
571{
572# define FLEN 512
573 Int fd, n;
574 struct stat s1;
575 char* f_clo = NULL;
576 char filename[FLEN];
577
578 snprintf(filename, FLEN, "%s/.valgrindrc", ( NULL == dir ? "" : dir ) );
579 fd = VG_(open)(filename, 0, VKI_S_IRUSR);
580 if ( fd > 0 ) {
581 if ( 0 == fstat(fd, &s1) ) {
582 f_clo = malloc(s1.st_size+1);
583 vg_assert(f_clo);
584 n = read(fd, f_clo, s1.st_size);
585 if (n == -1) n = 0;
586 f_clo[n] = '\0';
587 }
588 close(fd);
589 }
590 return f_clo;
591# undef FLEN
592}
593
nethercotee2097312004-06-27 12:29:56 +0000594#define ISSPACE(cc) ((cc) == ' ' || (cc) == '\t' || (cc) == '\n')
595
nethercote71980f02004-01-24 18:18:54 +0000596static Int count_args(char* s)
597{
598 Int n = 0;
599 if (s) {
600 char* cp = s;
601 while (True) {
602 // We have alternating sequences: blanks, non-blanks, blanks...
603 // count the non-blanks sequences.
604 while ( ISSPACE(*cp) ) cp++;
605 if ( !*cp ) break;
606 n++;
607 while ( !ISSPACE(*cp) && *cp ) cp++;
608 }
609 }
610 return n;
611}
612
613/* add args out of environment, skipping multiple spaces and -- args */
614static char** copy_args( char* s, char** to )
615{
616 if (s) {
617 char* cp = s;
618 while (True) {
619 // We have alternating sequences: blanks, non-blanks, blanks...
620 // copy the non-blanks sequences, and add terminating '\0'
621 while ( ISSPACE(*cp) ) cp++;
622 if ( !*cp ) break;
623 *to++ = cp;
624 while ( !ISSPACE(*cp) && *cp ) cp++;
625 if ( *cp ) *cp++ = '\0'; // terminate if necessary
626 if (VG_STREQ(to[-1], "--")) to--; // undo any '--' arg
627 }
628 }
629 return to;
630}
631
nethercotee2097312004-06-27 12:29:56 +0000632#undef ISSPACE
633
nethercote71980f02004-01-24 18:18:54 +0000634// Augment command line with arguments from environment and .valgrindrc
635// files.
636static void augment_command_line(Int* vg_argc_inout, char*** vg_argv_inout)
637{
638 int vg_argc = *vg_argc_inout;
639 char** vg_argv = *vg_argv_inout;
640
641 char* env_clo = getenv(VALGRINDOPTS);
642 char* f1_clo = get_file_clo( getenv("HOME") );
643 char* f2_clo = get_file_clo(".");
644
645 /* copy any extra args from file or environment, if present */
646 if ( (env_clo && *env_clo) || (f1_clo && *f1_clo) || (f2_clo && *f2_clo) ) {
647 /* ' ' separated extra options */
648 char **from;
649 char **to;
650 int env_arg_count, f1_arg_count, f2_arg_count;
651
652 env_arg_count = count_args(env_clo);
653 f1_arg_count = count_args(f1_clo);
654 f2_arg_count = count_args(f2_clo);
655
656 if (0)
657 printf("extra-argc=%d %d %d\n",
658 env_arg_count, f1_arg_count, f2_arg_count);
659
660 /* +2: +1 for null-termination, +1 for added '--' */
661 from = vg_argv;
662 vg_argv = malloc( (vg_argc + env_arg_count + f1_arg_count
663 + f2_arg_count + 2) * sizeof(char **));
664 to = vg_argv;
665
666 /* copy argv[0] */
667 *to++ = *from++;
668
669 /* Copy extra args from env var and file, in the order: ~/.valgrindrc,
670 * $VALGRIND_OPTS, ./.valgrindrc -- more local options are put later
671 * to override less local ones. */
672 to = copy_args(f1_clo, to);
673 to = copy_args(env_clo, to);
674 to = copy_args(f2_clo, to);
675
676 /* copy original arguments, stopping at command or -- */
677 while (*from) {
678 if (**from != '-')
679 break;
680 if (VG_STREQ(*from, "--")) {
681 from++; /* skip -- */
682 break;
683 }
684 *to++ = *from++;
685 }
686
687 /* add -- */
688 *to++ = "--";
689
690 vg_argc = to - vg_argv;
691
692 /* copy rest of original command line, then NULL */
693 while (*from) *to++ = *from++;
694 *to = NULL;
695 }
696
697 *vg_argc_inout = vg_argc;
698 *vg_argv_inout = vg_argv;
699}
700
701static void get_command_line( int argc, char** argv,
702 Int* vg_argc_out, Char*** vg_argv_out,
703 char*** cl_argv_out )
704{
705 int vg_argc;
706 char** vg_argv;
707 char** cl_argv;
708 char* env_clo = getenv(VALGRINDCLO);
709
710 if (env_clo != NULL && *env_clo != '\0') {
711 char *cp;
712 char **cpp;
713
714 /* OK, we're getting all our arguments from the environment - the
715 entire command line belongs to the client (including argv[0]) */
716 vg_argc = 1; /* argv[0] */
717 for (cp = env_clo; *cp; cp++)
718 if (*cp == '\01')
719 vg_argc++;
720
721 vg_argv = malloc(sizeof(char **) * (vg_argc + 1));
722
723 cpp = vg_argv;
724
725 *cpp++ = "valgrind"; /* nominal argv[0] */
726 *cpp++ = env_clo;
727
728 for (cp = env_clo; *cp; cp++) {
729 if (*cp == '\01') {
730 *cp++ = '\0'; /* chop it up in place */
731 *cpp++ = cp;
732 }
733 }
734 *cpp = NULL;
735 cl_argv = argv;
736
737 } else {
738 /* Count the arguments on the command line. */
739 vg_argv = argv;
740
741 for (vg_argc = 1; vg_argc < argc; vg_argc++) {
742 if (argv[vg_argc][0] != '-') /* exe name */
743 break;
744 if (VG_STREQ(argv[vg_argc], "--")) { /* dummy arg */
745 vg_argc++;
746 break;
747 }
748 }
749 cl_argv = &argv[vg_argc];
750
751 /* Get extra args from VALGRIND_OPTS and .valgrindrc files.
752 * Note we don't do this if getting args from VALGRINDCLO. */
753 augment_command_line(&vg_argc, &vg_argv);
754 }
755
756 if (0) {
757 Int i;
758 for (i = 0; i < vg_argc; i++)
759 printf("vg_argv[%d]=\"%s\"\n", i, vg_argv[i]);
760 }
761
762 *vg_argc_out = vg_argc;
763 *vg_argv_out = (Char**)vg_argv;
764 *cl_argv_out = cl_argv;
765}
766
767
768/*====================================================================*/
769/*=== Environment and stack setup ===*/
770/*====================================================================*/
771
772/* Scan a colon-separated list, and call a function on each element.
773 The string must be mutable, because we insert a temporary '\0', but
thughes4ad52d02004-06-27 17:37:21 +0000774 the string will end up unmodified. (*func) should return True if it
nethercote71980f02004-01-24 18:18:54 +0000775 doesn't need to see any more.
thughes4ad52d02004-06-27 17:37:21 +0000776
777 This routine will return True if (*func) returns True and False if
778 it reaches the end of the list without that happening.
nethercote71980f02004-01-24 18:18:54 +0000779*/
thughes4ad52d02004-06-27 17:37:21 +0000780static Bool scan_colsep(char *colsep, Bool (*func)(const char *))
nethercote71980f02004-01-24 18:18:54 +0000781{
782 char *cp, *entry;
783 int end;
784
785 if (colsep == NULL ||
786 *colsep == '\0')
thughes4ad52d02004-06-27 17:37:21 +0000787 return False;
nethercote71980f02004-01-24 18:18:54 +0000788
789 entry = cp = colsep;
790
791 do {
792 end = (*cp == '\0');
793
794 if (*cp == ':' || *cp == '\0') {
795 char save = *cp;
796
797 *cp = '\0';
798 if ((*func)(entry))
thughes4ad52d02004-06-27 17:37:21 +0000799 return True;
nethercote71980f02004-01-24 18:18:54 +0000800 *cp = save;
801 entry = cp+1;
802 }
803 cp++;
804 } while(!end);
thughes4ad52d02004-06-27 17:37:21 +0000805
806 return False;
807}
808
809static Bool contains(const char *p) {
810 if (VG_STREQ(p, VG_(libdir))) {
811 return True;
812 }
813 return False;
nethercote71980f02004-01-24 18:18:54 +0000814}
815
816/* Prepare the client's environment. This is basically a copy of our
817 environment, except:
818 1. LD_LIBRARY_PATH=$VALGRINDLIB:$LD_LIBRARY_PATH
819 2. LD_PRELOAD=$VALGRINDLIB/vg_inject.so:($VALGRINDLIB/vgpreload_TOOL.so:)?$LD_PRELOAD
820
821 If any of these is missing, then it is added.
822
823 Yummy. String hacking in C.
824
825 If this needs to handle any more variables it should be hacked
826 into something table driven.
827 */
828static char **fix_environment(char **origenv, const char *preload)
829{
830 static const char inject_so[] = "vg_inject.so";
831 static const char ld_library_path[] = "LD_LIBRARY_PATH=";
832 static const char ld_preload[] = "LD_PRELOAD=";
833 static const char valgrind_clo[] = VALGRINDCLO "=";
834 static const int ld_library_path_len = sizeof(ld_library_path)-1;
835 static const int ld_preload_len = sizeof(ld_preload)-1;
836 static const int valgrind_clo_len = sizeof(valgrind_clo)-1;
837 int ld_preload_done = 0;
838 int ld_library_path_done = 0;
839 char *inject_path;
840 int inject_path_len;
841 int vgliblen = strlen(VG_(libdir));
842 char **cpp;
843 char **ret;
844 int envc;
845 const int preloadlen = (preload == NULL) ? 0 : strlen(preload);
846
847 /* Find the vg_inject.so; also make room for the tool preload
848 library */
849 inject_path_len = sizeof(inject_so) + vgliblen + preloadlen + 16;
850 inject_path = malloc(inject_path_len);
851
852 if (preload)
853 snprintf(inject_path, inject_path_len, "%s/%s:%s",
854 VG_(libdir), inject_so, preload);
855 else
856 snprintf(inject_path, inject_path_len, "%s/%s",
857 VG_(libdir), inject_so);
858
859 /* Count the original size of the env */
860 envc = 0; /* trailing NULL */
861 for (cpp = origenv; cpp && *cpp; cpp++)
862 envc++;
863
864 /* Allocate a new space */
865 ret = malloc(sizeof(char *) * (envc+3+1)); /* 3 new entries + NULL */
866
867 /* copy it over */
868 for (cpp = ret; *origenv; )
869 *cpp++ = *origenv++;
870 *cpp = NULL;
871
872 vg_assert(envc == (cpp - ret));
873
874 /* Walk over the new environment, mashing as we go */
875 for (cpp = ret; cpp && *cpp; cpp++) {
876 if (memcmp(*cpp, ld_library_path, ld_library_path_len) == 0) {
nethercote71980f02004-01-24 18:18:54 +0000877 /* If the LD_LIBRARY_PATH already contains libdir, then don't
878 bother adding it again, even if it isn't the first (it
879 seems that the Java runtime will keep reexecing itself
880 unless its paths are at the front of LD_LIBRARY_PATH) */
thughes4ad52d02004-06-27 17:37:21 +0000881 if (!scan_colsep(*cpp + ld_library_path_len, contains)) {
nethercote71980f02004-01-24 18:18:54 +0000882 int len = strlen(*cpp) + vgliblen*2 + 16;
883 char *cp = malloc(len);
884
885 snprintf(cp, len, "%s%s:%s",
886 ld_library_path, VG_(libdir),
887 (*cpp)+ld_library_path_len);
888
889 *cpp = cp;
890 }
891
892 ld_library_path_done = 1;
893 } else if (memcmp(*cpp, ld_preload, ld_preload_len) == 0) {
894 int len = strlen(*cpp) + inject_path_len;
895 char *cp = malloc(len);
896
897 snprintf(cp, len, "%s%s:%s",
898 ld_preload, inject_path, (*cpp)+ld_preload_len);
899
900 *cpp = cp;
901
902 ld_preload_done = 1;
903 } else if (memcmp(*cpp, valgrind_clo, valgrind_clo_len) == 0) {
904 *cpp = "";
905 }
906 }
907
908 /* Add the missing bits */
909
910 if (!ld_library_path_done) {
911 int len = ld_library_path_len + vgliblen*2 + 16;
912 char *cp = malloc(len);
913
914 snprintf(cp, len, "%s%s", ld_library_path, VG_(libdir));
915
916 ret[envc++] = cp;
917 }
918
919 if (!ld_preload_done) {
920 int len = ld_preload_len + inject_path_len;
921 char *cp = malloc(len);
922
923 snprintf(cp, len, "%s%s",
924 ld_preload, inject_path);
925
926 ret[envc++] = cp;
927 }
928
929 ret[envc] = NULL;
930
931 return ret;
932}
933
934extern char **environ; /* our environment */
935//#include <error.h>
936
937/* Add a string onto the string table, and return its address */
938static char *copy_str(char **tab, const char *str)
939{
940 char *cp = *tab;
941 char *orig = cp;
942
943 while(*str)
944 *cp++ = *str++;
945 *cp++ = '\0';
946
947 if (0)
948 printf("copied %p \"%s\" len %d\n",
949 orig, orig, cp-orig);
950
951 *tab = cp;
952
953 return orig;
954}
955
956/*
957 This sets up the client's initial stack, containing the args,
958 environment and aux vector.
959
960 The format of the stack is:
961
962 higher address +-----------------+
963 | Trampoline code |
964 +-----------------+
965 | |
966 : string table :
967 | |
968 +-----------------+
969 | AT_NULL |
970 - -
971 | auxv |
972 +-----------------+
973 | NULL |
974 - -
975 | envp |
976 +-----------------+
977 | NULL |
978 - -
979 | argv |
980 +-----------------+
981 | argc |
982 lower address +-----------------+ <- esp
983 | undefined |
984 : :
985 */
986static Addr setup_client_stack(char **orig_argv, char **orig_envp,
987 const struct exeinfo *info,
988 UInt** client_auxv)
989{
nethercotee567e702004-07-10 17:49:17 +0000990 void* res;
nethercote71980f02004-01-24 18:18:54 +0000991 char **cpp;
992 char *strtab; /* string table */
993 char *stringbase;
994 addr_t *ptr;
995 struct ume_auxv *auxv;
996 const struct ume_auxv *orig_auxv;
997 const struct ume_auxv *cauxv;
998 unsigned stringsize; /* total size of strings in bytes */
999 unsigned auxsize; /* total size of auxv in bytes */
1000 int argc; /* total argc */
1001 int envc; /* total number of env vars */
1002 unsigned stacksize; /* total client stack size */
1003 addr_t cl_esp; /* client stack base (initial esp) */
1004
1005 /* use our own auxv as a prototype */
1006 orig_auxv = find_auxv(ume_exec_esp);
1007
1008 /* ==================== compute sizes ==================== */
1009
1010 /* first of all, work out how big the client stack will be */
1011 stringsize = 0;
1012
1013 /* paste on the extra args if the loader needs them (ie, the #!
1014 interpreter and its argument) */
1015 argc = 0;
1016 if (info->argv0 != NULL) {
1017 argc++;
1018 stringsize += strlen(info->argv0) + 1;
1019 }
1020 if (info->argv1 != NULL) {
1021 argc++;
1022 stringsize += strlen(info->argv1) + 1;
1023 }
1024
1025 /* now scan the args we're given... */
1026 for (cpp = orig_argv; *cpp; cpp++) {
1027 argc++;
1028 stringsize += strlen(*cpp) + 1;
1029 }
1030
1031 /* ...and the environment */
1032 envc = 0;
1033 for (cpp = orig_envp; cpp && *cpp; cpp++) {
1034 envc++;
1035 stringsize += strlen(*cpp) + 1;
1036 }
1037
1038 /* now, how big is the auxv? */
1039 auxsize = sizeof(*auxv); /* there's always at least one entry: AT_NULL */
1040 for (cauxv = orig_auxv; cauxv->a_type != AT_NULL; cauxv++) {
1041 if (cauxv->a_type == AT_PLATFORM)
1042 stringsize += strlen(cauxv->u.a_ptr) + 1;
1043 auxsize += sizeof(*cauxv);
1044 }
1045
1046 /* OK, now we know how big the client stack is */
1047 stacksize =
1048 sizeof(int) + /* argc */
1049 sizeof(char **)*argc + /* argv */
1050 sizeof(char **) + /* terminal NULL */
1051 sizeof(char **)*envc + /* envp */
1052 sizeof(char **) + /* terminal NULL */
1053 auxsize + /* auxv */
1054 ROUNDUP(stringsize, sizeof(int)) +/* strings (aligned) */
1055 VKI_BYTES_PER_PAGE; /* page for trampoline code */
1056
1057 /* cl_esp is the client's stack pointer */
1058 cl_esp = VG_(client_end) - stacksize;
1059 cl_esp = ROUNDDN(cl_esp, 16); /* make stack 16 byte aligned */
1060
nethercote71980f02004-01-24 18:18:54 +00001061 /* base of the string table (aligned) */
1062 stringbase = strtab = (char *)(VG_(client_trampoline_code) - ROUNDUP(stringsize, sizeof(int)));
1063
1064 VG_(clstk_base) = PGROUNDDN(cl_esp);
1065 VG_(clstk_end) = VG_(client_end);
1066
nethercote5ee67ca2004-06-22 14:00:09 +00001067 if (0)
1068 printf("stringsize=%d auxsize=%d stacksize=%d\n"
1069 "clstk_base %x\n"
1070 "clstk_end %x\n",
1071 stringsize, auxsize, stacksize, VG_(clstk_base), VG_(clstk_end));
1072
1073
nethercote71980f02004-01-24 18:18:54 +00001074 /* ==================== allocate space ==================== */
1075
1076 /* allocate a stack - mmap enough space for the stack */
nethercotee567e702004-07-10 17:49:17 +00001077 res = mmap((void *)PGROUNDDN(cl_esp), VG_(client_end) - PGROUNDDN(cl_esp),
1078 PROT_READ | PROT_WRITE | PROT_EXEC,
1079 MAP_PRIVATE | MAP_ANON | MAP_FIXED, -1, 0);
1080 vg_assert((void*)-1 != res);
nethercote71980f02004-01-24 18:18:54 +00001081
1082 /* ==================== copy client stack ==================== */
1083
1084 ptr = (addr_t *)cl_esp;
1085
1086 /* --- argc --- */
1087 *ptr++ = argc; /* client argc */
1088
1089 /* --- argv --- */
1090 if (info->argv0) {
1091 *ptr++ = (addr_t)copy_str(&strtab, info->argv0);
1092 free(info->argv0);
1093 }
1094 if (info->argv1) {
1095 *ptr++ = (addr_t)copy_str(&strtab, info->argv1);
1096 free(info->argv1);
1097 }
1098 for (cpp = orig_argv; *cpp; ptr++, cpp++) {
1099 *ptr = (addr_t)copy_str(&strtab, *cpp);
1100 }
1101 *ptr++ = 0;
1102
1103 /* --- envp --- */
1104 VG_(client_envp) = (Char **)ptr;
1105 for (cpp = orig_envp; cpp && *cpp; ptr++, cpp++)
1106 *ptr = (addr_t)copy_str(&strtab, *cpp);
1107 *ptr++ = 0;
1108
1109 /* --- auxv --- */
1110 auxv = (struct ume_auxv *)ptr;
1111 *client_auxv = (UInt *)auxv;
1112
1113 for (; orig_auxv->a_type != AT_NULL; auxv++, orig_auxv++) {
1114 /* copy the entry... */
1115 *auxv = *orig_auxv;
1116
1117 /* ...and fix up the copy */
1118 switch(auxv->a_type) {
1119 case AT_PHDR:
1120 if (info->phdr == 0)
1121 auxv->a_type = AT_IGNORE;
1122 else
1123 auxv->u.a_val = info->phdr;
1124 break;
1125
1126 case AT_PHNUM:
1127 if (info->phdr == 0)
1128 auxv->a_type = AT_IGNORE;
1129 else
1130 auxv->u.a_val = info->phnum;
1131 break;
1132
1133 case AT_BASE:
1134 if (info->interp_base == 0)
1135 auxv->a_type = AT_IGNORE;
1136 else
1137 auxv->u.a_val = info->interp_base;
1138 break;
1139
1140 case AT_PLATFORM: /* points to a platform description string */
1141 auxv->u.a_ptr = copy_str(&strtab, orig_auxv->u.a_ptr);
1142 break;
1143
1144 case AT_ENTRY:
1145 auxv->u.a_val = info->entry;
1146 break;
1147
1148 case AT_IGNORE:
1149 case AT_EXECFD:
1150 case AT_PHENT:
1151 case AT_PAGESZ:
1152 case AT_FLAGS:
1153 case AT_NOTELF:
1154 case AT_UID:
1155 case AT_EUID:
1156 case AT_GID:
1157 case AT_EGID:
1158 case AT_CLKTCK:
1159 case AT_HWCAP:
1160 case AT_FPUCW:
1161 case AT_DCACHEBSIZE:
1162 case AT_ICACHEBSIZE:
1163 case AT_UCACHEBSIZE:
1164 /* All these are pointerless, so we don't need to do anything
1165 about them. */
1166 break;
1167
1168 case AT_SECURE:
1169 /* If this is 1, then it means that this program is running
1170 suid, and therefore the dynamic linker should be careful
1171 about LD_PRELOAD, etc. However, since stage1 (the thing
1172 the kernel actually execve's) should never be SUID, and we
1173 need LD_PRELOAD/LD_LIBRARY_PATH to work for the client, we
1174 set AT_SECURE to 0. */
1175 auxv->u.a_val = 0;
1176 break;
1177
1178 case AT_SYSINFO:
1179 /* Leave this unmolested for now, but we'll update it later
1180 when we set up the client trampoline code page */
1181 break;
1182
1183 case AT_SYSINFO_EHDR:
1184 /* Trash this, because we don't reproduce it */
1185 auxv->a_type = AT_IGNORE;
1186 break;
1187
1188 default:
1189 /* stomp out anything we don't know about */
1190 if (0)
1191 printf("stomping auxv entry %d\n", auxv->a_type);
1192 auxv->a_type = AT_IGNORE;
1193 break;
1194
1195 }
1196 }
1197 *auxv = *orig_auxv;
1198 vg_assert(auxv->a_type == AT_NULL);
1199
1200 vg_assert((strtab-stringbase) == stringsize);
1201
nethercote5ee67ca2004-06-22 14:00:09 +00001202 /* We know the initial ESP is pointing at argc/argv */
1203 VG_(client_argc) = *(Int*)cl_esp;
1204 VG_(client_argv) = (Char**)(cl_esp + sizeof(Int));
1205
nethercote71980f02004-01-24 18:18:54 +00001206 return cl_esp;
1207}
1208
1209/*====================================================================*/
1210/*=== Find executable ===*/
1211/*====================================================================*/
1212
thughes4ad52d02004-06-27 17:37:21 +00001213static const char* executable_name;
1214
1215static Bool match_executable(const char *entry) {
1216 char buf[strlen(entry) + strlen(executable_name) + 2];
1217
1218 /* empty PATH element means . */
1219 if (*entry == '\0')
1220 entry = ".";
1221
1222 snprintf(buf, sizeof(buf), "%s/%s", entry, executable_name);
1223
1224 if (access(buf, R_OK|X_OK) == 0) {
1225 executable_name = strdup(buf);
1226 vg_assert(NULL != executable_name);
1227 return True;
1228 }
1229 return False;
1230}
1231
nethercote71980f02004-01-24 18:18:54 +00001232static const char* find_executable(const char* exec)
1233{
1234 vg_assert(NULL != exec);
thughes4ad52d02004-06-27 17:37:21 +00001235 executable_name = exec;
1236 if (strchr(executable_name, '/') == NULL) {
nethercote71980f02004-01-24 18:18:54 +00001237 /* no '/' - we need to search the path */
1238 char *path = getenv("PATH");
thughes4ad52d02004-06-27 17:37:21 +00001239 scan_colsep(path, match_executable);
nethercote71980f02004-01-24 18:18:54 +00001240 }
thughes4ad52d02004-06-27 17:37:21 +00001241 return executable_name;
nethercote71980f02004-01-24 18:18:54 +00001242}
1243
1244
1245/*====================================================================*/
1246/*=== Loading tools ===*/
1247/*====================================================================*/
1248
1249static void list_tools(void)
1250{
1251 DIR *dir = opendir(VG_(libdir));
1252 struct dirent *de;
1253 int first = 1;
1254
1255 if (dir == NULL) {
1256 fprintf(stderr, "Can't open %s: %s (installation problem?)\n",
nethercotef4928da2004-06-15 10:54:40 +00001257 VG_(libdir), strerror(errno));
nethercote71980f02004-01-24 18:18:54 +00001258 return;
1259 }
1260
nethercotef4928da2004-06-15 10:54:40 +00001261 while ((de = readdir(dir)) != NULL) {
nethercote71980f02004-01-24 18:18:54 +00001262 int len = strlen(de->d_name);
1263
1264 /* look for vgskin_TOOL.so names */
1265 if (len > (7+1+3) && /* "vgskin_" + at least 1-char toolname + ".so" */
nethercotef4928da2004-06-15 10:54:40 +00001266 strncmp(de->d_name, "vgskin_", 7) == 0 &&
1267 VG_STREQ(de->d_name + len - 3, ".so")) {
1268 if (first) {
1269 fprintf(stderr, "Available tools:\n");
1270 first = 0;
1271 }
1272 de->d_name[len-3] = '\0';
1273 fprintf(stderr, "\t%s\n", de->d_name+7);
nethercote71980f02004-01-24 18:18:54 +00001274 }
1275 }
1276
1277 closedir(dir);
1278
1279 if (first)
nethercotef4928da2004-06-15 10:54:40 +00001280 fprintf(stderr, "No tools available in \"%s\" (installation problem?)\n",
1281 VG_(libdir));
nethercote71980f02004-01-24 18:18:54 +00001282}
1283
1284
1285/* Find and load a tool, and check it looks ok. Also looks to see if there's
1286 * a matching vgpreload_*.so file, and returns its name in *preloadpath. */
1287static void load_tool( const char *toolname, void** handle_out,
1288 ToolInfo** toolinfo_out, char **preloadpath_out )
1289{
1290 Bool ok;
1291 int len = strlen(VG_(libdir)) + strlen(toolname)*2 + 16;
1292 char buf[len];
1293 void* handle;
1294 ToolInfo* toolinfo;
1295 char* preloadpath = NULL;
1296 Int* vg_malloc_redzonep;
1297
1298 // XXX: allowing full paths for --tool option -- does it make sense?
1299 // Doesn't allow for vgpreload_<tool>.so.
1300
1301 if (strchr(toolname, '/') != 0) {
1302 /* toolname contains '/', and so must be a pathname */
1303 handle = dlopen(toolname, RTLD_NOW);
1304 } else {
1305 /* just try in the libdir */
1306 snprintf(buf, len, "%s/vgskin_%s.so", VG_(libdir), toolname);
1307 handle = dlopen(buf, RTLD_NOW);
1308
1309 if (handle != NULL) {
1310 snprintf(buf, len, "%s/vgpreload_%s.so", VG_(libdir), toolname);
1311 if (access(buf, R_OK) == 0) {
1312 preloadpath = strdup(buf);
1313 vg_assert(NULL != preloadpath);
1314 }
1315 }
1316 }
1317
1318 ok = (NULL != handle);
1319 if (!ok) {
1320 fprintf(stderr, "Can't open tool \"%s\": %s\n", toolname, dlerror());
1321 goto bad_load;
1322 }
1323
1324 toolinfo = dlsym(handle, "vgSkin_tool_info");
1325 ok = (NULL != toolinfo);
1326 if (!ok) {
1327 fprintf(stderr, "Tool \"%s\" doesn't define SK_(tool_info) - "
1328 "add VG_DETERMINE_INTERFACE_VERSION?\n", toolname);
1329 goto bad_load;
1330 }
1331
1332 ok = (toolinfo->sizeof_ToolInfo == sizeof(*toolinfo) &&
1333 toolinfo->interface_major_version == VG_CORE_INTERFACE_MAJOR_VERSION &&
1334 toolinfo->sk_pre_clo_init != NULL);
1335 if (!ok) {
1336 fprintf(stderr, "Error:\n"
1337 " Tool and core interface versions do not match.\n"
1338 " Interface version used by core is: %d.%d (size %d)\n"
1339 " Interface version used by tool is: %d.%d (size %d)\n"
1340 " The major version numbers must match.\n",
1341 VG_CORE_INTERFACE_MAJOR_VERSION,
1342 VG_CORE_INTERFACE_MINOR_VERSION,
1343 sizeof(*toolinfo),
1344 toolinfo->interface_major_version,
1345 toolinfo->interface_minor_version,
1346 toolinfo->sizeof_ToolInfo);
1347 fprintf(stderr, " You need to at least recompile, and possibly update,\n");
1348 if (VG_CORE_INTERFACE_MAJOR_VERSION > toolinfo->interface_major_version)
1349 fprintf(stderr, " your skin to work with this version of Valgrind.\n");
1350 else
1351 fprintf(stderr, " your version of Valgrind to work with this skin.\n");
1352 goto bad_load;
1353 }
1354
1355 // Set redzone size for V's allocator
1356 vg_malloc_redzonep = dlsym(handle, STR(VG_(vg_malloc_redzone_szB)));
1357 if ( NULL != vg_malloc_redzonep ) {
1358 VG_(vg_malloc_redzone_szB) = *vg_malloc_redzonep;
1359 }
1360
1361 vg_assert(NULL != handle && NULL != toolinfo);
1362 *handle_out = handle;
1363 *toolinfo_out = toolinfo;
1364 *preloadpath_out = preloadpath;
1365 return;
1366
1367
1368 bad_load:
1369 if (handle != NULL)
1370 dlclose(handle);
1371
nethercotef4928da2004-06-15 10:54:40 +00001372 fprintf(stderr, "valgrind: couldn't load tool\n");
nethercote71980f02004-01-24 18:18:54 +00001373 list_tools();
1374 exit(127);
1375}
1376
nethercotef4928da2004-06-15 10:54:40 +00001377
1378/*====================================================================*/
1379/*=== Command line errors ===*/
1380/*====================================================================*/
1381
1382static void abort_msg ( void )
1383{
nethercotef8548672004-06-21 12:42:35 +00001384 VG_(clo_log_to) = VgLogTo_Fd;
1385 VG_(clo_log_fd) = 2; /* stderr */
nethercotef4928da2004-06-15 10:54:40 +00001386}
1387
1388void VG_(bad_option) ( Char* opt )
1389{
1390 abort_msg();
1391 VG_(printf)("valgrind: Bad option `%s'; aborting.\n", opt);
1392 VG_(printf)("valgrind: Use --help for more information.\n");
1393 VG_(exit)(1);
1394}
1395
1396static void missing_tool_option ( void )
1397{
1398 abort_msg();
1399 VG_(printf)("valgrind: Missing --tool option\n");
1400 list_tools();
1401 VG_(printf)("valgrind: Use --help for more information.\n");
1402 VG_(exit)(1);
1403}
1404
1405static void missing_prog ( void )
1406{
1407 abort_msg();
1408 VG_(printf)("valgrind: no program specified\n");
1409 VG_(printf)("valgrind: Use --help for more information.\n");
1410 VG_(exit)(1);
1411}
1412
1413static void config_error ( Char* msg )
1414{
1415 abort_msg();
1416 VG_(printf)("valgrind: Startup or configuration error:\n %s\n", msg);
1417 VG_(printf)("valgrind: Unable to start up properly. Giving up.\n");
1418 VG_(exit)(1);
1419}
1420
1421
nethercote71980f02004-01-24 18:18:54 +00001422/*====================================================================*/
1423/*=== Loading the client ===*/
1424/*====================================================================*/
1425
nethercotef4928da2004-06-15 10:54:40 +00001426static void load_client(char* cl_argv[], const char* exec, Int need_help,
nethercote71980f02004-01-24 18:18:54 +00001427 /*out*/struct exeinfo* info, /*out*/Addr* client_eip)
1428{
1429 // If they didn't specify an executable with --exec, and didn't specify
1430 // --help, then use client argv[0] (searching $PATH if necessary).
nethercotef4928da2004-06-15 10:54:40 +00001431 if (NULL == exec && !need_help) {
nethercote71980f02004-01-24 18:18:54 +00001432 if (cl_argv[0] == NULL ||
1433 ( NULL == (exec = find_executable(cl_argv[0])) ) )
1434 {
nethercotef4928da2004-06-15 10:54:40 +00001435 missing_prog();
nethercote71980f02004-01-24 18:18:54 +00001436 }
1437 }
1438
1439 info->map_base = VG_(client_mapbase);
nethercote71980f02004-01-24 18:18:54 +00001440
1441 info->exe_base = VG_(client_base);
1442 info->exe_end = VG_(client_end);
1443 info->argv = cl_argv;
1444
nethercotef4928da2004-06-15 10:54:40 +00001445 if (need_help) {
nethercote71980f02004-01-24 18:18:54 +00001446 VG_(clexecfd) = -1;
1447 info->argv0 = NULL;
1448 info->argv1 = NULL;
1449 } else {
1450 Int ret;
1451 VG_(clexecfd) = VG_(open)(exec, O_RDONLY, VKI_S_IRUSR);
1452 ret = do_exec(exec, info);
1453 if (ret != 0) {
nethercotef4928da2004-06-15 10:54:40 +00001454 fprintf(stderr, "valgrind: do_exec(%s) failed: %s\n", exec, strerror(ret));
nethercote71980f02004-01-24 18:18:54 +00001455 exit(127);
1456 }
1457 }
1458
1459 /* Copy necessary bits of 'info' that were filled in */
1460 *client_eip = info->init_eip;
1461 VG_(brk_base) = VG_(brk_limit) = info->brkbase;
1462}
1463
1464
1465/*====================================================================*/
1466/*=== Command-line: variables, processing ===*/
1467/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +00001468
njn25e49d8e72002-09-23 09:36:25 +00001469/* Define, and set defaults. */
1470Bool VG_(clo_error_limit) = True;
nethercote04d0fbc2004-01-26 16:48:06 +00001471Bool VG_(clo_db_attach) = False;
1472Char* VG_(clo_db_command) = VG_CLO_DEFAULT_DBCOMMAND;
njn43c799e2003-04-08 00:08:52 +00001473Bool VG_(clo_gen_suppressions) = False;
nethercote27fec902004-06-16 21:26:32 +00001474Int VG_(clo_sanity_level) = 1;
njn25e49d8e72002-09-23 09:36:25 +00001475Int VG_(clo_verbosity) = 1;
1476Bool VG_(clo_demangle) = True;
njn25e49d8e72002-09-23 09:36:25 +00001477Bool VG_(clo_trace_children) = False;
sewardj4cf05692002-10-27 20:28:29 +00001478
nethercotee1730692003-11-20 10:38:07 +00001479/* See big comment in vg_include.h for meaning of these three.
1480 fd is initially stdout, for --help, but gets moved to stderr by default
1481 immediately afterwards. */
sewardj4cf05692002-10-27 20:28:29 +00001482VgLogTo VG_(clo_log_to) = VgLogTo_Fd;
nethercotef8548672004-06-21 12:42:35 +00001483Int VG_(clo_log_fd) = 1;
1484Char* VG_(clo_log_name) = NULL;
sewardj4cf05692002-10-27 20:28:29 +00001485
sewardj6024b212003-07-13 10:54:33 +00001486Int VG_(clo_input_fd) = 0; /* stdin */
njn25e49d8e72002-09-23 09:36:25 +00001487Int VG_(clo_n_suppressions) = 0;
sewardjde4a1d02002-03-22 01:27:54 +00001488Char* VG_(clo_suppressions)[VG_CLO_MAX_SFILES];
njn25e49d8e72002-09-23 09:36:25 +00001489Bool VG_(clo_profile) = False;
1490Bool VG_(clo_single_step) = False;
1491Bool VG_(clo_optimise) = True;
1492UChar VG_(clo_trace_codegen) = 0; // 00000000b
1493Bool VG_(clo_trace_syscalls) = False;
1494Bool VG_(clo_trace_signals) = False;
1495Bool VG_(clo_trace_symtab) = False;
njn25e49d8e72002-09-23 09:36:25 +00001496Bool VG_(clo_trace_sched) = False;
1497Int VG_(clo_trace_pthread_level) = 0;
njn25e49d8e72002-09-23 09:36:25 +00001498Int VG_(clo_dump_error) = 0;
1499Int VG_(clo_backtrace_size) = 4;
1500Char* VG_(clo_weird_hacks) = NULL;
sewardj858964b2002-10-05 14:15:43 +00001501Bool VG_(clo_run_libc_freeres) = True;
rjwalshf5f536f2003-11-17 17:45:00 +00001502Bool VG_(clo_track_fds) = False;
sewardj22854b92002-11-30 14:00:47 +00001503Bool VG_(clo_chain_bb) = True;
nethercote77eba602003-11-13 17:35:04 +00001504Bool VG_(clo_show_below_main) = False;
fitzhardinge98abfc72003-12-16 02:05:15 +00001505Bool VG_(clo_pointercheck) = True;
fitzhardinge462f4f92003-12-18 02:10:54 +00001506Bool VG_(clo_branchpred) = False;
sewardj2370f3b2002-11-30 15:01:01 +00001507
jsgf855d93d2003-10-13 22:26:55 +00001508static Bool VG_(clo_wait_for_gdb) = False;
1509
1510/* If we're doing signal routing, poll for signals every 50mS by
1511 default. */
1512Int VG_(clo_signal_polltime) = 50;
1513
1514/* These flags reduce thread wakeup latency on syscall completion and
1515 signal delivery, respectively. The downside is possible unfairness. */
1516Bool VG_(clo_lowlat_syscalls) = False; /* low-latency syscalls */
1517Bool VG_(clo_lowlat_signals) = False; /* low-latency signals */
1518
sewardjde4a1d02002-03-22 01:27:54 +00001519
nethercote6c999f22004-01-31 22:55:15 +00001520void usage ( Bool debug_help )
njn7cf0bd32002-06-08 13:36:03 +00001521{
njn25e49d8e72002-09-23 09:36:25 +00001522 Char* usage1 =
nethercote71980f02004-01-24 18:18:54 +00001523"usage: valgrind --tool=<toolname> [options] prog-and-args\n"
njn25e49d8e72002-09-23 09:36:25 +00001524"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001525" common user options for all Valgrind tools, with defaults in [ ]:\n"
nethercote0d588502004-06-21 13:27:11 +00001526" --tool=<name> use the Valgrind tool named <name>\n"
nethercotea76368b2004-06-16 11:56:29 +00001527" -h --help show this message\n"
nethercote6c999f22004-01-31 22:55:15 +00001528" --help-debug show this message, plus debugging options\n"
njn25e49d8e72002-09-23 09:36:25 +00001529" --version show version\n"
njn25e49d8e72002-09-23 09:36:25 +00001530" -q --quiet run silently; only print error msgs\n"
1531" -v --verbose be more verbose, incl counts of errors\n"
nethercote77eba602003-11-13 17:35:04 +00001532" --trace-children=no|yes Valgrind-ise child processes? [no]\n"
nethercote0d588502004-06-21 13:27:11 +00001533" --track-fds=no|yes track open file descriptors? [no]\n"
nethercote2b0793f2003-12-02 10:41:18 +00001534"\n"
1535" uncommon user options for all Valgrind tools:\n"
nethercote0d588502004-06-21 13:27:11 +00001536" --run-libc-freeres=no|yes free up glibc memory at exit? [yes]\n"
1537" --weird-hacks=hack1,hack2,... recognised hacks: lax-ioctls [none]\n"
1538" --signal-polltime=<time> signal poll period (mS) for older kernels [50]\n"
1539" --lowlat-signals=no|yes improve thread signal wake-up latency [no]\n"
1540" --lowlat-syscalls=no|yes improve thread syscall wake-up latency [no]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001541" --pointercheck=no|yes enforce client address space limits [yes]\n"
njn25e49d8e72002-09-23 09:36:25 +00001542"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001543" user options for Valgrind tools that report errors:\n"
nethercotef8548672004-06-21 12:42:35 +00001544" --log-fd=<number> log messages to file descriptor [2=stderr]\n"
1545" --log-file=<file> log messages to <file>.pid<pid>\n"
1546" --log-socket=ipaddr:port log messages to socket ipaddr:port\n"
nethercote2b0793f2003-12-02 10:41:18 +00001547" --demangle=no|yes automatically demangle C++ names? [yes]\n"
1548" --num-callers=<number> show <num> callers in stack traces [4]\n"
1549" --error-limit=no|yes stop showing new errors if too many? [yes]\n"
1550" --show-below-main=no|yes continue stack traces below main() [no]\n"
1551" --suppressions=<filename> suppress errors described in <filename>\n"
1552" --gen-suppressions=no|yes print suppressions for errors detected [no]\n"
nethercote04d0fbc2004-01-26 16:48:06 +00001553" --db-attach=no|yes start debugger when errors detected? [no]\n"
1554" --db-command=<command> command to start debugger [gdb -nw %%f %%p]\n"
1555" --input-fd=<number> file descriptor for input [0=stdin]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001556"\n";
njn7cf0bd32002-06-08 13:36:03 +00001557
njn25e49d8e72002-09-23 09:36:25 +00001558 Char* usage2 =
1559"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001560" debugging options for all Valgrind tools:\n"
njn25e49d8e72002-09-23 09:36:25 +00001561" --sanity-level=<number> level of sanity checking to do [1]\n"
1562" --single-step=no|yes translate each instr separately? [no]\n"
1563" --optimise=no|yes improve intermediate code? [yes]\n"
nethercote137bc552003-11-14 17:47:54 +00001564" --profile=no|yes profile? (tool must be built for it) [no]\n"
sewardj22854b92002-11-30 14:00:47 +00001565" --chain-bb=no|yes do basic-block chaining? [yes]\n"
fitzhardinge462f4f92003-12-18 02:10:54 +00001566" --branchpred=yes|no generate branch prediction hints [no]\n"
njn25e49d8e72002-09-23 09:36:25 +00001567" --trace-codegen=<XXXXX> show generated code? (X = 0|1) [00000]\n"
1568" --trace-syscalls=no|yes show all system calls? [no]\n"
1569" --trace-signals=no|yes show signal handling details? [no]\n"
1570" --trace-symtab=no|yes show symbol table details? [no]\n"
njn25e49d8e72002-09-23 09:36:25 +00001571" --trace-sched=no|yes show thread scheduler details? [no]\n"
njn3e884182003-04-15 13:03:23 +00001572" --trace-pthread=none|some|all show pthread event details? [none]\n"
jsgf855d93d2003-10-13 22:26:55 +00001573" --wait-for-gdb=yes|no pause on startup to wait for gdb attach\n"
njn25e49d8e72002-09-23 09:36:25 +00001574"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001575" debugging options for Valgrind tools that report errors\n"
1576" --dump-error=<number> show translation for basic block associated\n"
1577" with <number>'th error context [0=show none]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001578"\n";
njn3e884182003-04-15 13:03:23 +00001579
1580 Char* usage3 =
1581"\n"
nethercote71980f02004-01-24 18:18:54 +00001582" Extra options read from ~/.valgrindrc, $VALGRIND_OPTS, ./.valgrindrc\n"
njn25e49d8e72002-09-23 09:36:25 +00001583"\n"
nethercotebb1c9912004-01-04 16:43:23 +00001584" Valgrind is Copyright (C) 2000-2004 Julian Seward\n"
njn25e49d8e72002-09-23 09:36:25 +00001585" and licensed under the GNU General Public License, version 2.\n"
1586" Bug reports, feedback, admiration, abuse, etc, to: %s.\n"
njnd04b7c62002-10-03 14:05:52 +00001587"\n"
nethercote137bc552003-11-14 17:47:54 +00001588" Tools are copyright and licensed by their authors. See each\n"
1589" tool's start-up message for more information.\n"
njn25e49d8e72002-09-23 09:36:25 +00001590"\n";
njn7cf0bd32002-06-08 13:36:03 +00001591
fitzhardinge98abfc72003-12-16 02:05:15 +00001592 VG_(printf)(usage1);
1593 if (VG_(details).name) {
1594 VG_(printf)(" user options for %s:\n", VG_(details).name);
fitzhardinge98abfc72003-12-16 02:05:15 +00001595 if (VG_(needs).command_line_options)
1596 SK_(print_usage)();
1597 else
1598 VG_(printf)(" (none)\n");
1599 }
nethercote6c999f22004-01-31 22:55:15 +00001600 if (debug_help) {
1601 VG_(printf)(usage2);
fitzhardinge98abfc72003-12-16 02:05:15 +00001602
nethercote6c999f22004-01-31 22:55:15 +00001603 if (VG_(details).name) {
1604 VG_(printf)(" debugging options for %s:\n", VG_(details).name);
1605
1606 if (VG_(needs).command_line_options)
1607 SK_(print_debug_usage)();
1608 else
1609 VG_(printf)(" (none)\n");
1610 }
fitzhardinge98abfc72003-12-16 02:05:15 +00001611 }
nethercote421281e2003-11-20 16:20:55 +00001612 VG_(printf)(usage3, VG_BUGS_TO);
nethercotef4928da2004-06-15 10:54:40 +00001613 VG_(exit)(0);
njn7cf0bd32002-06-08 13:36:03 +00001614}
sewardjde4a1d02002-03-22 01:27:54 +00001615
nethercote71980f02004-01-24 18:18:54 +00001616static void pre_process_cmd_line_options
nethercote6c999f22004-01-31 22:55:15 +00001617 ( Int* need_help, const char** tool, const char** exec )
sewardj1c1b1162003-02-23 01:25:51 +00001618{
nethercote71980f02004-01-24 18:18:54 +00001619 UInt i;
sewardjde4a1d02002-03-22 01:27:54 +00001620
nethercote71980f02004-01-24 18:18:54 +00001621 /* parse the options we have (only the options we care about now) */
1622 for (i = 1; i < VG_(vg_argc); i++) {
1623
1624 if (strcmp(VG_(vg_argv)[i], "--version") == 0) {
1625 printf("valgrind-" VERSION "\n");
nethercotef4928da2004-06-15 10:54:40 +00001626 exit(0);
nethercote71980f02004-01-24 18:18:54 +00001627
nethercotea76368b2004-06-16 11:56:29 +00001628 } else if (VG_CLO_STREQ(VG_(vg_argv)[i], "--help") ||
1629 VG_CLO_STREQ(VG_(vg_argv)[i], "-h")) {
nethercote6c999f22004-01-31 22:55:15 +00001630 *need_help = 1;
1631
nethercotef4928da2004-06-15 10:54:40 +00001632 } else if (VG_CLO_STREQ(VG_(vg_argv)[i], "--help-debug")) {
nethercote6c999f22004-01-31 22:55:15 +00001633 *need_help = 2;
nethercote71980f02004-01-24 18:18:54 +00001634
nethercotef4928da2004-06-15 10:54:40 +00001635 } else if (VG_CLO_STREQN(7, VG_(vg_argv)[i], "--tool=") ||
1636 VG_CLO_STREQN(7, VG_(vg_argv)[i], "--skin=")) {
nethercote71980f02004-01-24 18:18:54 +00001637 *tool = &VG_(vg_argv)[i][7];
1638
nethercotef4928da2004-06-15 10:54:40 +00001639 } else if (VG_CLO_STREQN(7, VG_(vg_argv)[i], "--exec=")) {
nethercote71980f02004-01-24 18:18:54 +00001640 *exec = &VG_(vg_argv)[i][7];
1641 }
1642 }
1643
nethercotef4928da2004-06-15 10:54:40 +00001644 /* If no tool specified, can act appropriately without loading tool */
nethercote71980f02004-01-24 18:18:54 +00001645 if (*tool == NULL) {
nethercotef4928da2004-06-15 10:54:40 +00001646 if (0 == *need_help) {
1647 // neither --tool nor --help/--help-debug specified
1648 missing_tool_option();
1649 } else {
1650 // Give help message, without any tool-specific help
1651 usage(/*help-debug?*/2 == *need_help);
1652 }
nethercote71980f02004-01-24 18:18:54 +00001653 }
1654}
1655
nethercote5ee67ca2004-06-22 14:00:09 +00001656static void process_cmd_line_options( UInt* client_auxv, const char* toolname )
nethercote71980f02004-01-24 18:18:54 +00001657{
nethercotef8548672004-06-21 12:42:35 +00001658 Int i, eventually_log_fd;
nethercote71980f02004-01-24 18:18:54 +00001659 Int *auxp;
1660 Int toolname_len = VG_(strlen)(toolname);
sewardjde4a1d02002-03-22 01:27:54 +00001661
nethercotee1730692003-11-20 10:38:07 +00001662 /* log to stderr by default, but usage message goes to stdout */
nethercotef8548672004-06-21 12:42:35 +00001663 eventually_log_fd = 2;
sewardjde4a1d02002-03-22 01:27:54 +00001664
sewardj19d81412002-06-03 01:10:40 +00001665 /* Check for sane path in ./configure --prefix=... */
fitzhardinge98abfc72003-12-16 02:05:15 +00001666 if (VG_LIBDIR[0] != '/')
sewardj19d81412002-06-03 01:10:40 +00001667 config_error("Please use absolute paths in "
1668 "./configure --prefix=... or --libdir=...");
sewardj38170912002-05-10 21:07:22 +00001669
nethercote71980f02004-01-24 18:18:54 +00001670 for (auxp = client_auxv; auxp[0] != VKI_AT_NULL; auxp += 2) {
fitzhardinge98abfc72003-12-16 02:05:15 +00001671 switch(auxp[0]) {
1672 case VKI_AT_SYSINFO:
1673 VG_(sysinfo_page_exists) = True;
fitzhardinge92360792003-12-24 10:11:11 +00001674 auxp[1] = (Int)(VG_(client_trampoline_code) + VG_(tramp_syscall_offset));
fitzhardinge98abfc72003-12-16 02:05:15 +00001675 VG_(sysinfo_page_addr) = auxp[1];
1676 break;
sewardjde4a1d02002-03-22 01:27:54 +00001677 }
fitzhardinge98abfc72003-12-16 02:05:15 +00001678 }
sewardjde4a1d02002-03-22 01:27:54 +00001679
nethercote71980f02004-01-24 18:18:54 +00001680 for (i = 1; i < VG_(vg_argc); i++) {
1681
1682 Char* arg = VG_(vg_argv)[i];
1683
1684 // XXX: allow colons in options, for Josef
1685
1686 /* Look for matching "--toolname:foo" */
1687 if (VG_(strstr)(arg, ":")) {
1688 if (VG_CLO_STREQN(2, arg, "--") &&
1689 VG_CLO_STREQN(toolname_len, arg+2, toolname) &&
1690 VG_CLO_STREQN(1, arg+2+toolname_len, ":"))
1691 {
1692 // prefix matches, convert "--toolname:foo" to "--foo"
1693 if (0)
1694 VG_(printf)("tool-specific arg: %s\n", arg);
1695 arg += toolname_len + 1;
1696 arg[0] = '-';
1697 arg[1] = '-';
1698
1699 } else {
1700 // prefix doesn't match, skip to next arg
1701 continue;
1702 }
1703 }
1704
fitzhardinge98abfc72003-12-16 02:05:15 +00001705 /* Ignore these options - they've already been handled */
nethercote71980f02004-01-24 18:18:54 +00001706 if (VG_CLO_STREQN(7, arg, "--tool=") ||
1707 VG_CLO_STREQN(7, arg, "--skin="))
fitzhardinge98abfc72003-12-16 02:05:15 +00001708 continue;
nethercote71980f02004-01-24 18:18:54 +00001709 if (VG_CLO_STREQN(7, arg, "--exec="))
fitzhardinge98abfc72003-12-16 02:05:15 +00001710 continue;
1711
nethercote71980f02004-01-24 18:18:54 +00001712 if ( VG_CLO_STREQ(arg, "--"))
fitzhardinge98abfc72003-12-16 02:05:15 +00001713 continue;
nethercote27fec902004-06-16 21:26:32 +00001714
nethercote71980f02004-01-24 18:18:54 +00001715 else if (VG_CLO_STREQ(arg, "-v") ||
1716 VG_CLO_STREQ(arg, "--verbose"))
sewardjde4a1d02002-03-22 01:27:54 +00001717 VG_(clo_verbosity)++;
nethercote27fec902004-06-16 21:26:32 +00001718
nethercote71980f02004-01-24 18:18:54 +00001719 else if (VG_CLO_STREQ(arg, "-q") ||
1720 VG_CLO_STREQ(arg, "--quiet"))
sewardjde4a1d02002-03-22 01:27:54 +00001721 VG_(clo_verbosity)--;
1722
nethercote27fec902004-06-16 21:26:32 +00001723 else VG_BOOL_CLO("--branchpred", VG_(clo_branchpred))
1724 else VG_BOOL_CLO("--chain-bb", VG_(clo_chain_bb))
1725 else VG_BOOL_CLO("--db-attach", VG_(clo_db_attach))
1726 else VG_BOOL_CLO("--demangle", VG_(clo_demangle))
1727 else VG_BOOL_CLO("--error-limit", VG_(clo_error_limit))
1728 else VG_BOOL_CLO("--gen-suppressions", VG_(clo_gen_suppressions))
1729 else VG_BOOL_CLO("--lowlat-signals", VG_(clo_lowlat_signals))
1730 else VG_BOOL_CLO("--lowlat-syscalls", VG_(clo_lowlat_syscalls))
1731 else VG_BOOL_CLO("--optimise", VG_(clo_optimise))
1732 else VG_BOOL_CLO("--pointercheck", VG_(clo_pointercheck))
1733 else VG_BOOL_CLO("--profile", VG_(clo_profile))
1734 else VG_BOOL_CLO("--run-libc-freeres", VG_(clo_run_libc_freeres))
1735 else VG_BOOL_CLO("--show-below-main", VG_(clo_show_below_main))
1736 else VG_BOOL_CLO("--single-step", VG_(clo_single_step))
1737 else VG_BOOL_CLO("--track-fds", VG_(clo_track_fds))
1738 else VG_BOOL_CLO("--trace-children", VG_(clo_trace_children))
1739 else VG_BOOL_CLO("--trace-sched", VG_(clo_trace_sched))
1740 else VG_BOOL_CLO("--trace-signals", VG_(clo_trace_signals))
1741 else VG_BOOL_CLO("--trace-symtab", VG_(clo_trace_symtab))
1742 else VG_BOOL_CLO("--trace-syscalls", VG_(clo_trace_syscalls))
1743 else VG_BOOL_CLO("--wait-for-gdb", VG_(clo_wait_for_gdb))
sewardj72f98ff2002-06-13 17:23:38 +00001744
nethercote27fec902004-06-16 21:26:32 +00001745 else VG_STR_CLO ("--db-command", VG_(clo_db_command))
1746 else VG_STR_CLO ("--weird-hacks", VG_(clo_weird_hacks))
sewardjde4a1d02002-03-22 01:27:54 +00001747
nethercote27fec902004-06-16 21:26:32 +00001748 else VG_NUM_CLO ("--dump-error", VG_(clo_dump_error))
1749 else VG_NUM_CLO ("--input-fd", VG_(clo_input_fd))
1750 else VG_NUM_CLO ("--sanity-level", VG_(clo_sanity_level))
1751 else VG_NUM_CLO ("--signal­polltime", VG_(clo_signal_polltime))
1752 else VG_BNUM_CLO("--num-callers", VG_(clo_backtrace_size), 1,
1753 VG_DEEPEST_BACKTRACE)
sewardjde4a1d02002-03-22 01:27:54 +00001754
nethercotef8548672004-06-21 12:42:35 +00001755 // for backwards compatibility, replaced by --log-fd
nethercote71980f02004-01-24 18:18:54 +00001756 else if (VG_CLO_STREQN(13, arg, "--logfile-fd=")) {
nethercotef8548672004-06-21 12:42:35 +00001757 VG_(clo_log_to) = VgLogTo_Fd;
1758 VG_(clo_log_name) = NULL;
1759 eventually_log_fd = (Int)VG_(atoll)(&arg[13]);
1760 }
1761 else if (VG_CLO_STREQN(9, arg, "--log-fd=")) {
1762 VG_(clo_log_to) = VgLogTo_Fd;
1763 VG_(clo_log_name) = NULL;
1764 eventually_log_fd = (Int)VG_(atoll)(&arg[9]);
sewardj4cf05692002-10-27 20:28:29 +00001765 }
1766
nethercotef8548672004-06-21 12:42:35 +00001767 // for backwards compatibility, replaced by --log-file
nethercote71980f02004-01-24 18:18:54 +00001768 else if (VG_CLO_STREQN(10, arg, "--logfile=")) {
nethercotef8548672004-06-21 12:42:35 +00001769 VG_(clo_log_to) = VgLogTo_File;
1770 VG_(clo_log_name) = &arg[10];
1771 }
1772 else if (VG_CLO_STREQN(11, arg, "--log-file=")) {
1773 VG_(clo_log_to) = VgLogTo_File;
1774 VG_(clo_log_name) = &arg[11];
sewardj4cf05692002-10-27 20:28:29 +00001775 }
sewardjde4a1d02002-03-22 01:27:54 +00001776
nethercotef8548672004-06-21 12:42:35 +00001777 // for backwards compatibility, replaced by --log-socket
nethercote71980f02004-01-24 18:18:54 +00001778 else if (VG_CLO_STREQN(12, arg, "--logsocket=")) {
nethercotef8548672004-06-21 12:42:35 +00001779 VG_(clo_log_to) = VgLogTo_Socket;
1780 VG_(clo_log_name) = &arg[12];
1781 }
1782 else if (VG_CLO_STREQN(13, arg, "--log-socket=")) {
1783 VG_(clo_log_to) = VgLogTo_Socket;
1784 VG_(clo_log_name) = &arg[13];
sewardj73cf3bc2002-11-03 03:20:15 +00001785 }
1786
nethercote71980f02004-01-24 18:18:54 +00001787 else if (VG_CLO_STREQN(15, arg, "--suppressions=")) {
sewardjde4a1d02002-03-22 01:27:54 +00001788 if (VG_(clo_n_suppressions) >= VG_CLO_MAX_SFILES) {
njn25e49d8e72002-09-23 09:36:25 +00001789 VG_(message)(Vg_UserMsg, "Too many suppression files specified.");
sewardjde4a1d02002-03-22 01:27:54 +00001790 VG_(message)(Vg_UserMsg,
1791 "Increase VG_CLO_MAX_SFILES and recompile.");
nethercote71980f02004-01-24 18:18:54 +00001792 VG_(bad_option)(arg);
sewardjde4a1d02002-03-22 01:27:54 +00001793 }
nethercote71980f02004-01-24 18:18:54 +00001794 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = &arg[15];
sewardjde4a1d02002-03-22 01:27:54 +00001795 VG_(clo_n_suppressions)++;
1796 }
sewardjde4a1d02002-03-22 01:27:54 +00001797
njn25e49d8e72002-09-23 09:36:25 +00001798 /* "vwxyz" --> 000zyxwv (binary) */
nethercote71980f02004-01-24 18:18:54 +00001799 else if (VG_CLO_STREQN(16, arg, "--trace-codegen=")) {
njn25e49d8e72002-09-23 09:36:25 +00001800 Int j;
nethercote71980f02004-01-24 18:18:54 +00001801 char* opt = & arg[16];
njn25e49d8e72002-09-23 09:36:25 +00001802
1803 if (5 != VG_(strlen)(opt)) {
1804 VG_(message)(Vg_UserMsg,
1805 "--trace-codegen argument must have 5 digits");
nethercote71980f02004-01-24 18:18:54 +00001806 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001807 }
1808 for (j = 0; j < 5; j++) {
1809 if ('0' == opt[j]) { /* do nothing */ }
1810 else if ('1' == opt[j]) VG_(clo_trace_codegen) |= (1 << j);
1811 else {
1812 VG_(message)(Vg_UserMsg, "--trace-codegen argument can only "
1813 "contain 0s and 1s");
nethercote71980f02004-01-24 18:18:54 +00001814 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001815 }
1816 }
1817 }
sewardjde4a1d02002-03-22 01:27:54 +00001818
nethercote71980f02004-01-24 18:18:54 +00001819 else if (VG_CLO_STREQ(arg, "--trace-pthread=none"))
sewardj45b4b372002-04-16 22:50:32 +00001820 VG_(clo_trace_pthread_level) = 0;
nethercote71980f02004-01-24 18:18:54 +00001821 else if (VG_CLO_STREQ(arg, "--trace-pthread=some"))
sewardj45b4b372002-04-16 22:50:32 +00001822 VG_(clo_trace_pthread_level) = 1;
nethercote71980f02004-01-24 18:18:54 +00001823 else if (VG_CLO_STREQ(arg, "--trace-pthread=all"))
sewardj45b4b372002-04-16 22:50:32 +00001824 VG_(clo_trace_pthread_level) = 2;
sewardj8937c812002-04-12 20:12:20 +00001825
nethercote71980f02004-01-24 18:18:54 +00001826 else if ( ! VG_(needs).command_line_options
1827 || ! SK_(process_cmd_line_option)(arg) ) {
nethercotef4928da2004-06-15 10:54:40 +00001828 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001829 }
sewardjde4a1d02002-03-22 01:27:54 +00001830 }
1831
nethercote27fec902004-06-16 21:26:32 +00001832 // Check various option values
1833
njnf9ebf672003-05-12 21:41:30 +00001834 if (VG_(clo_verbosity) < 0)
sewardjde4a1d02002-03-22 01:27:54 +00001835 VG_(clo_verbosity) = 0;
1836
nethercote04d0fbc2004-01-26 16:48:06 +00001837 if (VG_(clo_db_attach) && VG_(clo_trace_children)) {
sewardjde4a1d02002-03-22 01:27:54 +00001838 VG_(message)(Vg_UserMsg, "");
1839 VG_(message)(Vg_UserMsg,
nethercote04d0fbc2004-01-26 16:48:06 +00001840 "--db-attach=yes conflicts with --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001841 VG_(message)(Vg_UserMsg,
1842 "Please choose one or the other, but not both.");
nethercote04d0fbc2004-01-26 16:48:06 +00001843 VG_(bad_option)("--db-attach=yes and --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001844 }
1845
nethercotef8548672004-06-21 12:42:35 +00001846 /* Set up logging now. After this is done, VG_(clo_log_fd)
sewardj4cf05692002-10-27 20:28:29 +00001847 should be connected to whatever sink has been selected, and we
1848 indiscriminately chuck stuff into it without worrying what the
1849 nature of it is. Oh the wonder of Unix streams. */
1850
nethercotee1730692003-11-20 10:38:07 +00001851 /* So far we should be still attached to stdout, so we can show on
sewardj4cf05692002-10-27 20:28:29 +00001852 the terminal any problems to do with processing command line
1853 opts. */
nethercotef8548672004-06-21 12:42:35 +00001854 vg_assert(VG_(clo_log_fd) == 1 /* stdout */);
sewardj73cf3bc2002-11-03 03:20:15 +00001855 vg_assert(VG_(logging_to_filedes) == True);
sewardj4cf05692002-10-27 20:28:29 +00001856
1857 switch (VG_(clo_log_to)) {
sewardj73cf3bc2002-11-03 03:20:15 +00001858
sewardj4cf05692002-10-27 20:28:29 +00001859 case VgLogTo_Fd:
nethercotef8548672004-06-21 12:42:35 +00001860 vg_assert(VG_(clo_log_name) == NULL);
1861 VG_(clo_log_fd) = eventually_log_fd;
sewardj4cf05692002-10-27 20:28:29 +00001862 break;
sewardj73cf3bc2002-11-03 03:20:15 +00001863
sewardj4cf05692002-10-27 20:28:29 +00001864 case VgLogTo_File: {
1865 Char logfilename[1000];
jsgff3c3f1a2003-10-14 22:13:28 +00001866 Int seq = 0;
1867 Int pid = VG_(getpid)();
1868
nethercotef8548672004-06-21 12:42:35 +00001869 vg_assert(VG_(clo_log_name) != NULL);
1870 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
jsgff3c3f1a2003-10-14 22:13:28 +00001871
nethercote71980f02004-01-24 18:18:54 +00001872 for (;;) {
jsgff3c3f1a2003-10-14 22:13:28 +00001873 if (seq == 0)
1874 VG_(sprintf)(logfilename, "%s.pid%d",
nethercotef8548672004-06-21 12:42:35 +00001875 VG_(clo_log_name), pid );
jsgff3c3f1a2003-10-14 22:13:28 +00001876 else
1877 VG_(sprintf)(logfilename, "%s.pid%d.%d",
nethercotef8548672004-06-21 12:42:35 +00001878 VG_(clo_log_name), pid, seq );
jsgff3c3f1a2003-10-14 22:13:28 +00001879 seq++;
1880
nethercotef8548672004-06-21 12:42:35 +00001881 eventually_log_fd
jsgff3c3f1a2003-10-14 22:13:28 +00001882 = VG_(open)(logfilename,
1883 VKI_O_CREAT|VKI_O_WRONLY|VKI_O_EXCL|VKI_O_TRUNC,
1884 VKI_S_IRUSR|VKI_S_IWUSR);
nethercotef8548672004-06-21 12:42:35 +00001885 if (eventually_log_fd >= 0) {
1886 VG_(clo_log_fd) = VG_(safe_fd)(eventually_log_fd);
jsgff3c3f1a2003-10-14 22:13:28 +00001887 break;
1888 } else {
nethercotef8548672004-06-21 12:42:35 +00001889 if (eventually_log_fd != -VKI_EEXIST) {
jsgff3c3f1a2003-10-14 22:13:28 +00001890 VG_(message)(Vg_UserMsg,
1891 "Can't create/open log file `%s.pid%d'; giving up!",
nethercotef8548672004-06-21 12:42:35 +00001892 VG_(clo_log_name), pid);
jsgff3c3f1a2003-10-14 22:13:28 +00001893 VG_(bad_option)(
nethercotef8548672004-06-21 12:42:35 +00001894 "--log-file=<file> didn't work out for some reason.");
jsgff3c3f1a2003-10-14 22:13:28 +00001895 break;
1896 }
1897 }
1898 }
sewardj4cf05692002-10-27 20:28:29 +00001899 break;
sewardj73cf3bc2002-11-03 03:20:15 +00001900 }
1901
1902 case VgLogTo_Socket: {
nethercotef8548672004-06-21 12:42:35 +00001903 vg_assert(VG_(clo_log_name) != NULL);
1904 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
1905 eventually_log_fd = VG_(connect_via_socket)( VG_(clo_log_name) );
1906 if (eventually_log_fd == -1) {
sewardj73cf3bc2002-11-03 03:20:15 +00001907 VG_(message)(Vg_UserMsg,
nethercotef8548672004-06-21 12:42:35 +00001908 "Invalid --log-socket=ipaddr or --log-socket=ipaddr:port spec");
sewardj73cf3bc2002-11-03 03:20:15 +00001909 VG_(message)(Vg_UserMsg,
nethercotef8548672004-06-21 12:42:35 +00001910 "of `%s'; giving up!", VG_(clo_log_name) );
sewardj73cf3bc2002-11-03 03:20:15 +00001911 VG_(bad_option)(
nethercotef8548672004-06-21 12:42:35 +00001912 "--log-socket=");
sewardj4cf05692002-10-27 20:28:29 +00001913 }
nethercotef8548672004-06-21 12:42:35 +00001914 if (eventually_log_fd == -2) {
sewardj73cf3bc2002-11-03 03:20:15 +00001915 VG_(message)(Vg_UserMsg,
sewardj570f8902002-11-03 11:44:36 +00001916 "valgrind: failed to connect to logging server `%s'.",
nethercotef8548672004-06-21 12:42:35 +00001917 VG_(clo_log_name) );
sewardj570f8902002-11-03 11:44:36 +00001918 VG_(message)(Vg_UserMsg,
1919 "Log messages will sent to stderr instead." );
1920 VG_(message)(Vg_UserMsg,
1921 "" );
1922 /* We don't change anything here. */
1923 } else {
nethercotef8548672004-06-21 12:42:35 +00001924 vg_assert(eventually_log_fd > 0);
1925 VG_(clo_log_fd) = eventually_log_fd;
sewardj570f8902002-11-03 11:44:36 +00001926 VG_(logging_to_filedes) = False;
1927 }
sewardj73cf3bc2002-11-03 03:20:15 +00001928 break;
1929 }
1930
sewardj4cf05692002-10-27 20:28:29 +00001931 }
1932
nethercotef8548672004-06-21 12:42:35 +00001933 /* Move log_fd into the safe range, so it doesn't conflict with any app fds */
thughesad1c9562004-06-26 11:27:52 +00001934 eventually_log_fd = VG_(fcntl)(VG_(clo_log_fd), VKI_F_DUPFD, VG_(fd_hard_limit));
nethercotef8548672004-06-21 12:42:35 +00001935 if (eventually_log_fd < 0)
jsgf855d93d2003-10-13 22:26:55 +00001936 VG_(message)(Vg_UserMsg, "valgrind: failed to move logfile fd into safe range");
1937 else {
nethercotef8548672004-06-21 12:42:35 +00001938 VG_(clo_log_fd) = eventually_log_fd;
1939 VG_(fcntl)(VG_(clo_log_fd), VKI_F_SETFD, VKI_FD_CLOEXEC);
jsgf855d93d2003-10-13 22:26:55 +00001940 }
1941
sewardj4cf05692002-10-27 20:28:29 +00001942 /* Ok, the logging sink is running now. Print a suitable preamble.
1943 If logging to file or a socket, write details of parent PID and
1944 command line args, to help people trying to interpret the
1945 results of a run which encompasses multiple processes. */
sewardjde4a1d02002-03-22 01:27:54 +00001946
sewardj83adf412002-05-01 01:25:45 +00001947 if (VG_(clo_verbosity > 0)) {
njnd04b7c62002-10-03 14:05:52 +00001948 /* Skin details */
1949 VG_(message)(Vg_UserMsg, "%s%s%s, %s for x86-linux.",
1950 VG_(details).name,
1951 NULL == VG_(details).version ? "" : "-",
1952 NULL == VG_(details).version
1953 ? (Char*)"" : VG_(details).version,
1954 VG_(details).description);
1955 VG_(message)(Vg_UserMsg, "%s", VG_(details).copyright_author);
sewardj3b2736a2002-03-24 12:18:35 +00001956
njnd04b7c62002-10-03 14:05:52 +00001957 /* Core details */
1958 VG_(message)(Vg_UserMsg,
njn3e884182003-04-15 13:03:23 +00001959 "Using valgrind-%s, a program supervision framework for x86-linux.",
sewardj4aa62ba2002-10-05 15:49:27 +00001960 VERSION);
sewardjde4a1d02002-03-22 01:27:54 +00001961 VG_(message)(Vg_UserMsg,
nethercotebb1c9912004-01-04 16:43:23 +00001962 "Copyright (C) 2000-2004, and GNU GPL'd, by Julian Seward.");
njnd04b7c62002-10-03 14:05:52 +00001963 }
1964
nethercotec1e395d2003-11-10 13:26:49 +00001965 if (VG_(clo_verbosity) > 0 && VG_(clo_log_to) != VgLogTo_Fd) {
sewardj4cf05692002-10-27 20:28:29 +00001966 VG_(message)(Vg_UserMsg, "");
1967 VG_(message)(Vg_UserMsg,
1968 "My PID = %d, parent PID = %d. Prog and args are:",
1969 VG_(getpid)(), VG_(getppid)() );
1970 for (i = 0; i < VG_(client_argc); i++)
1971 VG_(message)(Vg_UserMsg, " %s", VG_(client_argv)[i]);
1972 }
1973
sewardjde4a1d02002-03-22 01:27:54 +00001974 if (VG_(clo_verbosity) > 1) {
nethercotea70f7352004-04-18 12:08:46 +00001975 Int fd;
sewardj4cf05692002-10-27 20:28:29 +00001976 if (VG_(clo_log_to) != VgLogTo_Fd)
1977 VG_(message)(Vg_UserMsg, "");
fitzhardinge98abfc72003-12-16 02:05:15 +00001978 VG_(message)(Vg_UserMsg, "Valgrind library directory: %s", VG_(libdir));
njn86dc2bc2003-09-09 07:26:21 +00001979 VG_(message)(Vg_UserMsg, "Command line");
1980 for (i = 0; i < VG_(client_argc); i++)
1981 VG_(message)(Vg_UserMsg, " %s", VG_(client_argv)[i]);
1982
sewardjde4a1d02002-03-22 01:27:54 +00001983 VG_(message)(Vg_UserMsg, "Startup, with flags:");
nethercote71980f02004-01-24 18:18:54 +00001984 for (i = 1; i < VG_(vg_argc); i++) {
1985 VG_(message)(Vg_UserMsg, " %s", VG_(vg_argv)[i]);
sewardjde4a1d02002-03-22 01:27:54 +00001986 }
nethercotea70f7352004-04-18 12:08:46 +00001987
1988 VG_(message)(Vg_UserMsg, "Contents of /proc/version:");
1989 fd = VG_(open) ( "/proc/version", VKI_O_RDONLY, 0 );
1990 if (fd < 0) {
1991 VG_(message)(Vg_UserMsg, " can't open /proc/version");
1992 } else {
1993 #define BUF_LEN 256
1994 Char version_buf[BUF_LEN];
1995 Int n = VG_(read) ( fd, version_buf, BUF_LEN );
1996 vg_assert(n <= 256);
1997 if (n > 0) {
1998 version_buf[n-1] = '\0';
1999 VG_(message)(Vg_UserMsg, " %s", version_buf);
2000 } else {
2001 VG_(message)(Vg_UserMsg, " (empty?)");
2002 }
2003 VG_(close)(fd);
2004 #undef BUF_LEN
2005 }
sewardjde4a1d02002-03-22 01:27:54 +00002006 }
2007
fitzhardinge98abfc72003-12-16 02:05:15 +00002008 if (VG_(clo_n_suppressions) < VG_CLO_MAX_SFILES-1 &&
njn25e49d8e72002-09-23 09:36:25 +00002009 (VG_(needs).core_errors || VG_(needs).skin_errors)) {
fitzhardinge98abfc72003-12-16 02:05:15 +00002010 /* If there are no suppression files specified and the skin
2011 needs one, load the default */
2012 static const Char default_supp[] = "default.supp";
2013 Int len = VG_(strlen)(VG_(libdir)) + 1 + sizeof(default_supp);
2014 Char *buf = VG_(arena_malloc)(VG_AR_CORE, len);
2015 VG_(sprintf)(buf, "%s/%s", VG_(libdir), default_supp);
2016 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = buf;
2017 VG_(clo_n_suppressions)++;
sewardjde4a1d02002-03-22 01:27:54 +00002018 }
sewardj4cf05692002-10-27 20:28:29 +00002019
njn6a230532003-07-21 10:38:23 +00002020 if (VG_(clo_gen_suppressions) &&
2021 !VG_(needs).core_errors && !VG_(needs).skin_errors) {
nethercotef4928da2004-06-15 10:54:40 +00002022 VG_(message)(Vg_UserMsg,
2023 "Can't use --gen-suppressions=yes with this tool,");
2024 VG_(message)(Vg_UserMsg,
2025 "as it doesn't generate errors.");
2026 VG_(bad_option)("--gen-suppressions=yes");
njn6a230532003-07-21 10:38:23 +00002027 }
sewardjde4a1d02002-03-22 01:27:54 +00002028}
2029
sewardjde4a1d02002-03-22 01:27:54 +00002030
nethercote71980f02004-01-24 18:18:54 +00002031/*====================================================================*/
2032/*=== File descriptor setup ===*/
2033/*====================================================================*/
2034
2035static void setup_file_descriptors(void)
2036{
2037 struct vki_rlimit rl;
2038
2039 /* Get the current file descriptor limits. */
2040 if (VG_(getrlimit)(VKI_RLIMIT_NOFILE, &rl) < 0) {
2041 rl.rlim_cur = 1024;
2042 rl.rlim_max = 1024;
2043 }
2044
2045 /* Work out where to move the soft limit to. */
2046 if (rl.rlim_cur + VG_N_RESERVED_FDS <= rl.rlim_max) {
2047 rl.rlim_cur = rl.rlim_cur + VG_N_RESERVED_FDS;
2048 } else {
2049 rl.rlim_cur = rl.rlim_max;
2050 }
2051
2052 /* Reserve some file descriptors for our use. */
thughesad1c9562004-06-26 11:27:52 +00002053 VG_(fd_soft_limit) = rl.rlim_cur - VG_N_RESERVED_FDS;
2054 VG_(fd_hard_limit) = rl.rlim_cur - VG_N_RESERVED_FDS;
nethercote71980f02004-01-24 18:18:54 +00002055
2056 /* Update the soft limit. */
2057 VG_(setrlimit)(VKI_RLIMIT_NOFILE, &rl);
2058
2059 if (VG_(vgexecfd) != -1)
2060 VG_(vgexecfd) = VG_(safe_fd)( VG_(vgexecfd) );
2061 if (VG_(clexecfd) != -1)
2062 VG_(clexecfd) = VG_(safe_fd)( VG_(clexecfd) );
2063}
2064
2065
2066/*====================================================================*/
nethercote1d447092004-02-01 17:29:59 +00002067/*=== baseBlock: definition + setup ===*/
nethercote71980f02004-01-24 18:18:54 +00002068/*====================================================================*/
2069
2070/* The variables storing offsets. */
2071
2072#define INVALID_OFFSET (-1)
2073
2074Int VGOFF_(m_eax) = INVALID_OFFSET;
2075Int VGOFF_(m_ecx) = INVALID_OFFSET;
2076Int VGOFF_(m_edx) = INVALID_OFFSET;
2077Int VGOFF_(m_ebx) = INVALID_OFFSET;
2078Int VGOFF_(m_esp) = INVALID_OFFSET;
2079Int VGOFF_(m_ebp) = INVALID_OFFSET;
2080Int VGOFF_(m_esi) = INVALID_OFFSET;
2081Int VGOFF_(m_edi) = INVALID_OFFSET;
2082Int VGOFF_(m_eflags) = INVALID_OFFSET;
2083Int VGOFF_(m_dflag) = INVALID_OFFSET;
2084Int VGOFF_(m_ssestate) = INVALID_OFFSET;
2085Int VGOFF_(ldt) = INVALID_OFFSET;
2086Int VGOFF_(tls) = INVALID_OFFSET;
2087Int VGOFF_(m_cs) = INVALID_OFFSET;
2088Int VGOFF_(m_ss) = INVALID_OFFSET;
2089Int VGOFF_(m_ds) = INVALID_OFFSET;
2090Int VGOFF_(m_es) = INVALID_OFFSET;
2091Int VGOFF_(m_fs) = INVALID_OFFSET;
2092Int VGOFF_(m_gs) = INVALID_OFFSET;
2093Int VGOFF_(m_eip) = INVALID_OFFSET;
2094Int VGOFF_(spillslots) = INVALID_OFFSET;
2095Int VGOFF_(sh_eax) = INVALID_OFFSET;
2096Int VGOFF_(sh_ecx) = INVALID_OFFSET;
2097Int VGOFF_(sh_edx) = INVALID_OFFSET;
2098Int VGOFF_(sh_ebx) = INVALID_OFFSET;
2099Int VGOFF_(sh_esp) = INVALID_OFFSET;
2100Int VGOFF_(sh_ebp) = INVALID_OFFSET;
2101Int VGOFF_(sh_esi) = INVALID_OFFSET;
2102Int VGOFF_(sh_edi) = INVALID_OFFSET;
2103Int VGOFF_(sh_eflags) = INVALID_OFFSET;
2104
2105Int VGOFF_(helper_idiv_64_32) = INVALID_OFFSET;
2106Int VGOFF_(helper_div_64_32) = INVALID_OFFSET;
2107Int VGOFF_(helper_idiv_32_16) = INVALID_OFFSET;
2108Int VGOFF_(helper_div_32_16) = INVALID_OFFSET;
2109Int VGOFF_(helper_idiv_16_8) = INVALID_OFFSET;
2110Int VGOFF_(helper_div_16_8) = INVALID_OFFSET;
2111Int VGOFF_(helper_imul_32_64) = INVALID_OFFSET;
2112Int VGOFF_(helper_mul_32_64) = INVALID_OFFSET;
2113Int VGOFF_(helper_imul_16_32) = INVALID_OFFSET;
2114Int VGOFF_(helper_mul_16_32) = INVALID_OFFSET;
2115Int VGOFF_(helper_imul_8_16) = INVALID_OFFSET;
2116Int VGOFF_(helper_mul_8_16) = INVALID_OFFSET;
2117Int VGOFF_(helper_CLD) = INVALID_OFFSET;
2118Int VGOFF_(helper_STD) = INVALID_OFFSET;
2119Int VGOFF_(helper_get_dirflag) = INVALID_OFFSET;
2120Int VGOFF_(helper_CLC) = INVALID_OFFSET;
2121Int VGOFF_(helper_STC) = INVALID_OFFSET;
nethercote1018bdd2004-02-11 23:33:29 +00002122Int VGOFF_(helper_CMC) = INVALID_OFFSET;
nethercote71980f02004-01-24 18:18:54 +00002123Int VGOFF_(helper_shldl) = INVALID_OFFSET;
2124Int VGOFF_(helper_shldw) = INVALID_OFFSET;
2125Int VGOFF_(helper_shrdl) = INVALID_OFFSET;
2126Int VGOFF_(helper_shrdw) = INVALID_OFFSET;
2127Int VGOFF_(helper_IN) = INVALID_OFFSET;
2128Int VGOFF_(helper_OUT) = INVALID_OFFSET;
2129Int VGOFF_(helper_RDTSC) = INVALID_OFFSET;
2130Int VGOFF_(helper_CPUID) = INVALID_OFFSET;
2131Int VGOFF_(helper_BSWAP) = INVALID_OFFSET;
nethercote1018bdd2004-02-11 23:33:29 +00002132Int VGOFF_(helper_bsfw) = INVALID_OFFSET;
2133Int VGOFF_(helper_bsfl) = INVALID_OFFSET;
2134Int VGOFF_(helper_bsrw) = INVALID_OFFSET;
2135Int VGOFF_(helper_bsrl) = INVALID_OFFSET;
nethercote71980f02004-01-24 18:18:54 +00002136Int VGOFF_(helper_fstsw_AX) = INVALID_OFFSET;
2137Int VGOFF_(helper_SAHF) = INVALID_OFFSET;
2138Int VGOFF_(helper_LAHF) = INVALID_OFFSET;
2139Int VGOFF_(helper_DAS) = INVALID_OFFSET;
2140Int VGOFF_(helper_DAA) = INVALID_OFFSET;
nethercote1018bdd2004-02-11 23:33:29 +00002141Int VGOFF_(helper_AAS) = INVALID_OFFSET;
2142Int VGOFF_(helper_AAA) = INVALID_OFFSET;
2143Int VGOFF_(helper_AAD) = INVALID_OFFSET;
2144Int VGOFF_(helper_AAM) = INVALID_OFFSET;
nethercote71980f02004-01-24 18:18:54 +00002145Int VGOFF_(helper_cmpxchg8b) = INVALID_OFFSET;
2146Int VGOFF_(helper_undefined_instruction) = INVALID_OFFSET;
2147
2148/* MAX_NONCOMPACT_HELPERS can be increased easily. If MAX_COMPACT_HELPERS is
2149 * increased too much, they won't really be compact any more... */
2150#define MAX_COMPACT_HELPERS 8
2151#define MAX_NONCOMPACT_HELPERS 50
2152
2153UInt VG_(n_compact_helpers) = 0;
2154UInt VG_(n_noncompact_helpers) = 0;
2155
2156Addr VG_(compact_helper_addrs) [MAX_COMPACT_HELPERS];
2157Int VG_(compact_helper_offsets)[MAX_COMPACT_HELPERS];
2158Addr VG_(noncompact_helper_addrs) [MAX_NONCOMPACT_HELPERS];
2159Int VG_(noncompact_helper_offsets)[MAX_NONCOMPACT_HELPERS];
2160
2161/* This is the actual defn of baseblock. */
2162UInt VG_(baseBlock)[VG_BASEBLOCK_WORDS];
2163
nethercote71980f02004-01-24 18:18:54 +00002164/* Words. */
2165static Int baB_off = 0;
2166
2167
sewardjfa492d42002-12-08 18:20:01 +00002168UInt VG_(insertDflag)(UInt eflags, Int d)
2169{
2170 vg_assert(d == 1 || d == -1);
2171 eflags &= ~EFlagD;
2172
2173 if (d < 0)
2174 eflags |= EFlagD;
2175
2176 return eflags;
2177}
2178
2179Int VG_(extractDflag)(UInt eflags)
2180{
2181 Int ret;
2182
2183 if (eflags & EFlagD)
2184 ret = -1;
2185 else
2186 ret = 1;
2187
2188 return ret;
2189}
2190
nethercote71980f02004-01-24 18:18:54 +00002191/* Returns the offset, in words. */
2192static Int alloc_BaB ( Int words )
sewardjde4a1d02002-03-22 01:27:54 +00002193{
nethercote71980f02004-01-24 18:18:54 +00002194 Int off = baB_off;
2195 baB_off += words;
2196 if (baB_off >= VG_BASEBLOCK_WORDS)
2197 VG_(core_panic)( "alloc_BaB: baseBlock is too small");
sewardjde4a1d02002-03-22 01:27:54 +00002198
nethercote71980f02004-01-24 18:18:54 +00002199 return off;
sewardjde4a1d02002-03-22 01:27:54 +00002200}
2201
nethercote71980f02004-01-24 18:18:54 +00002202/* Align offset, in *bytes* */
2203static void align_BaB ( UInt align )
njn25e49d8e72002-09-23 09:36:25 +00002204{
nethercote71980f02004-01-24 18:18:54 +00002205 vg_assert(2 == align || 4 == align || 8 == align || 16 == align);
2206 baB_off += (align-1);
2207 baB_off &= ~(align-1);
njn25e49d8e72002-09-23 09:36:25 +00002208}
2209
nethercote71980f02004-01-24 18:18:54 +00002210/* Allocate 1 word in baseBlock and set it to the given value. */
2211static Int alloc_BaB_1_set ( Addr a )
njn25e49d8e72002-09-23 09:36:25 +00002212{
nethercote71980f02004-01-24 18:18:54 +00002213 Int off = alloc_BaB(1);
2214 VG_(baseBlock)[off] = (UInt)a;
2215 return off;
njn25e49d8e72002-09-23 09:36:25 +00002216}
2217
nethercote71980f02004-01-24 18:18:54 +00002218/* Registers a function in compact_helper_addrs; compact_helper_offsets is
2219 filled in later. */
2220void VG_(register_compact_helper)(Addr a)
sewardjde4a1d02002-03-22 01:27:54 +00002221{
nethercote71980f02004-01-24 18:18:54 +00002222 if (MAX_COMPACT_HELPERS <= VG_(n_compact_helpers)) {
2223 VG_(printf)("Can only register %d compact helpers\n",
2224 MAX_COMPACT_HELPERS);
2225 VG_(core_panic)("Too many compact helpers registered");
2226 }
2227 VG_(compact_helper_addrs)[VG_(n_compact_helpers)] = a;
2228 VG_(n_compact_helpers)++;
2229}
2230
2231/* Registers a function in noncompact_helper_addrs; noncompact_helper_offsets
2232 * is filled in later.
2233 */
2234void VG_(register_noncompact_helper)(Addr a)
2235{
2236 if (MAX_NONCOMPACT_HELPERS <= VG_(n_noncompact_helpers)) {
2237 VG_(printf)("Can only register %d non-compact helpers\n",
2238 MAX_NONCOMPACT_HELPERS);
2239 VG_(printf)("Try increasing MAX_NON_COMPACT_HELPERS\n");
2240 VG_(core_panic)("Too many non-compact helpers registered");
2241 }
2242 VG_(noncompact_helper_addrs)[VG_(n_noncompact_helpers)] = a;
2243 VG_(n_noncompact_helpers)++;
2244}
2245
2246/* Allocate offsets in baseBlock for the skin helpers */
2247static
2248void assign_helpers_in_baseBlock(UInt n, Int offsets[], Addr addrs[])
2249{
2250 UInt i;
2251 for (i = 0; i < n; i++)
2252 offsets[i] = alloc_BaB_1_set( addrs[i] );
2253}
2254
2255Bool VG_(need_to_handle_esp_assignment)(void)
2256{
2257 return ( VG_(defined_new_mem_stack_4)() ||
2258 VG_(defined_die_mem_stack_4)() ||
2259 VG_(defined_new_mem_stack_8)() ||
2260 VG_(defined_die_mem_stack_8)() ||
2261 VG_(defined_new_mem_stack_12)() ||
2262 VG_(defined_die_mem_stack_12)() ||
2263 VG_(defined_new_mem_stack_16)() ||
2264 VG_(defined_die_mem_stack_16)() ||
2265 VG_(defined_new_mem_stack_32)() ||
2266 VG_(defined_die_mem_stack_32)() ||
2267 VG_(defined_new_mem_stack)() ||
2268 VG_(defined_die_mem_stack)()
2269 );
2270}
2271
2272/* Here we assign actual offsets. It's important to get the most
2273 popular referents within 128 bytes of the start, so we can take
2274 advantage of short addressing modes relative to %ebp. Popularity
2275 of offsets was measured on 22 Feb 02 running a KDE application, and
2276 the slots rearranged accordingly, with a 1.5% reduction in total
2277 size of translations. */
2278static void init_baseBlock ( Addr client_eip, Addr esp_at_startup )
2279{
2280 /* Those with offsets under 128 are carefully chosen. */
2281
2282 /* WORD offsets in this column */
2283 /* 0 */ VGOFF_(m_eax) = alloc_BaB_1_set(0);
2284 /* 1 */ VGOFF_(m_ecx) = alloc_BaB_1_set(0);
2285 /* 2 */ VGOFF_(m_edx) = alloc_BaB_1_set(0);
2286 /* 3 */ VGOFF_(m_ebx) = alloc_BaB_1_set(0);
2287 /* 4 */ VGOFF_(m_esp) = alloc_BaB_1_set(esp_at_startup);
2288 /* 5 */ VGOFF_(m_ebp) = alloc_BaB_1_set(0);
2289 /* 6 */ VGOFF_(m_esi) = alloc_BaB_1_set(0);
2290 /* 7 */ VGOFF_(m_edi) = alloc_BaB_1_set(0);
2291 /* 8 */ VGOFF_(m_eflags) = alloc_BaB_1_set(0);
2292
2293 if (VG_(needs).shadow_regs) {
2294 /* 9 */ VGOFF_(sh_eax) = alloc_BaB_1_set(0);
2295 /* 10 */ VGOFF_(sh_ecx) = alloc_BaB_1_set(0);
2296 /* 11 */ VGOFF_(sh_edx) = alloc_BaB_1_set(0);
2297 /* 12 */ VGOFF_(sh_ebx) = alloc_BaB_1_set(0);
2298 /* 13 */ VGOFF_(sh_esp) = alloc_BaB_1_set(0);
2299 /* 14 */ VGOFF_(sh_ebp) = alloc_BaB_1_set(0);
2300 /* 15 */ VGOFF_(sh_esi) = alloc_BaB_1_set(0);
2301 /* 16 */ VGOFF_(sh_edi) = alloc_BaB_1_set(0);
2302 /* 17 */ VGOFF_(sh_eflags) = alloc_BaB_1_set(0);
2303 VG_TRACK( post_regs_write_init );
2304 }
2305
2306 /* 9,10,11 or 18,19,20... depends on number whether shadow regs are used
2307 * and on compact helpers registered */
2308
2309 /* Make these most-frequently-called specialised ones compact, if they
2310 are used. */
2311 if (VG_(defined_new_mem_stack_4)())
2312 VG_(register_compact_helper)( (Addr) VG_(tool_interface).track_new_mem_stack_4);
2313
2314 if (VG_(defined_die_mem_stack_4)())
2315 VG_(register_compact_helper)( (Addr) VG_(tool_interface).track_die_mem_stack_4);
2316
2317 /* (9 or 18) + n_compact_helpers */
2318 /* Allocate slots for compact helpers */
2319 assign_helpers_in_baseBlock(VG_(n_compact_helpers),
2320 VG_(compact_helper_offsets),
2321 VG_(compact_helper_addrs));
2322
2323 /* (9/10 or 18/19) + n_compact_helpers */
2324 VGOFF_(m_eip) = alloc_BaB_1_set(client_eip);
2325
2326 /* There are currently 24 spill slots */
2327 /* (11+/20+ .. 32+/43+) + n_compact_helpers. This can overlap the magic
2328 * boundary at >= 32 words, but most spills are to low numbered spill
2329 * slots, so the ones above the boundary don't see much action. */
2330 VGOFF_(spillslots) = alloc_BaB(VG_MAX_SPILLSLOTS);
2331
2332 /* I gave up counting at this point. Since they're above the
2333 short-amode-boundary, there's no point. */
2334
2335 VGOFF_(m_dflag) = alloc_BaB_1_set(1); // 1 == forward D-flag
2336
2337 /* The FPU/SSE state. This _must_ be 16-byte aligned. Initial
2338 state doesn't matter much, as long as it's not totally borked. */
2339 align_BaB(16);
2340 VGOFF_(m_ssestate) = alloc_BaB(VG_SIZE_OF_SSESTATE_W);
2341 vg_assert(
2342 0 == ( ((UInt)(& VG_(baseBlock)[VGOFF_(m_ssestate)])) % 16 )
sewardj22854b92002-11-30 14:00:47 +00002343 );
2344
fitzhardingec2dbbac2004-01-23 23:09:01 +00002345 /* I assume that if we have SSE2 we also have SSE */
2346 VG_(have_ssestate) =
2347 VG_(cpu_has_feature)(VG_X86_FEAT_FXSR) &&
2348 VG_(cpu_has_feature)(VG_X86_FEAT_SSE);
2349
fitzhardinge98abfc72003-12-16 02:05:15 +00002350 /* set up an initial FPU state (doesn't really matter what it is,
2351 so long as it's somewhat valid) */
2352 if (!VG_(have_ssestate))
nethercote71980f02004-01-24 18:18:54 +00002353 asm volatile("fwait; fnsave %0; fwait; frstor %0; fwait"
2354 :
2355 : "m" (VG_(baseBlock)[VGOFF_(m_ssestate)])
2356 : "cc", "memory");
fitzhardinge98abfc72003-12-16 02:05:15 +00002357 else
nethercote71980f02004-01-24 18:18:54 +00002358 asm volatile("fwait; fxsave %0; fwait; andl $0xffbf, %1;"
2359 "fxrstor %0; fwait"
2360 :
2361 : "m" (VG_(baseBlock)[VGOFF_(m_ssestate)]),
2362 "m" (VG_(baseBlock)[VGOFF_(m_ssestate)+(24/4)])
2363 : "cc", "memory");
fitzhardinge98abfc72003-12-16 02:05:15 +00002364
njn0c7a5b52003-04-30 09:00:33 +00002365 if (0) {
2366 if (VG_(have_ssestate))
2367 VG_(printf)("Looks like a SSE-capable CPU\n");
2368 else
2369 VG_(printf)("Looks like a MMX-only CPU\n");
2370 }
sewardjb91ae7f2003-04-29 23:50:00 +00002371
nethercote71980f02004-01-24 18:18:54 +00002372 /* LDT pointer: pretend the root thread has an empty LDT to start with. */
2373 VGOFF_(ldt) = alloc_BaB_1_set((UInt)NULL);
jsgf855d93d2003-10-13 22:26:55 +00002374
nethercote71980f02004-01-24 18:18:54 +00002375 /* TLS pointer: pretend the root thread has no TLS array for now. */
2376 VGOFF_(tls) = alloc_BaB_1_set((UInt)NULL);
fitzhardingef0046f22003-12-18 02:39:22 +00002377
nethercote71980f02004-01-24 18:18:54 +00002378 /* segment registers */
2379 VGOFF_(m_cs) = alloc_BaB_1_set(0);
2380 VGOFF_(m_ss) = alloc_BaB_1_set(0);
2381 VGOFF_(m_ds) = alloc_BaB_1_set(0);
2382 VGOFF_(m_es) = alloc_BaB_1_set(0);
2383 VGOFF_(m_fs) = alloc_BaB_1_set(0);
2384 VGOFF_(m_gs) = alloc_BaB_1_set(0);
fitzhardingef0046f22003-12-18 02:39:22 +00002385
thughes35cec982004-04-21 15:16:43 +00002386 /* initialise %cs, %ds and %ss to point at the operating systems
2387 default code, data and stack segments */
2388 asm volatile("movw %%cs, %0"
2389 :
2390 : "m" (VG_(baseBlock)[VGOFF_(m_cs)]));
2391 asm volatile("movw %%ds, %0"
2392 :
2393 : "m" (VG_(baseBlock)[VGOFF_(m_ds)]));
2394 asm volatile("movw %%ss, %0"
2395 :
2396 : "m" (VG_(baseBlock)[VGOFF_(m_ss)]));
2397
nethercote71980f02004-01-24 18:18:54 +00002398 VG_(register_noncompact_helper)( (Addr) & VG_(do_useseg) );
fitzhardingef0046f22003-12-18 02:39:22 +00002399
nethercote71980f02004-01-24 18:18:54 +00002400#define REG(kind, size) \
2401 if (VG_(defined_##kind##_mem_stack##size)()) \
2402 VG_(register_noncompact_helper)( \
2403 (Addr) VG_(tool_interface).track_##kind##_mem_stack##size );
2404 REG(new, _8);
2405 REG(new, _12);
2406 REG(new, _16);
2407 REG(new, _32);
2408 REG(new, );
2409 REG(die, _8);
2410 REG(die, _12);
2411 REG(die, _16);
2412 REG(die, _32);
2413 REG(die, );
2414#undef REG
fitzhardingef0046f22003-12-18 02:39:22 +00002415
nethercote71980f02004-01-24 18:18:54 +00002416 if (VG_(need_to_handle_esp_assignment)())
2417 VG_(register_noncompact_helper)((Addr) VG_(unknown_esp_update));
fitzhardingeb791a192003-12-18 07:22:44 +00002418
nethercote71980f02004-01-24 18:18:54 +00002419# define HELPER(name) \
2420 VGOFF_(helper_##name) = alloc_BaB_1_set( (Addr) & VG_(helper_##name))
njn3e884182003-04-15 13:03:23 +00002421
nethercote71980f02004-01-24 18:18:54 +00002422 /* Helper functions. */
2423 HELPER(idiv_64_32); HELPER(div_64_32);
2424 HELPER(idiv_32_16); HELPER(div_32_16);
2425 HELPER(idiv_16_8); HELPER(div_16_8);
fitzhardinge98abfc72003-12-16 02:05:15 +00002426
nethercote71980f02004-01-24 18:18:54 +00002427 HELPER(imul_32_64); HELPER(mul_32_64);
2428 HELPER(imul_16_32); HELPER(mul_16_32);
2429 HELPER(imul_8_16); HELPER(mul_8_16);
njn25e49d8e72002-09-23 09:36:25 +00002430
nethercote71980f02004-01-24 18:18:54 +00002431 HELPER(CLD); HELPER(STD);
2432 HELPER(get_dirflag);
sewardjde4a1d02002-03-22 01:27:54 +00002433
nethercote71980f02004-01-24 18:18:54 +00002434 HELPER(CLC); HELPER(STC);
nethercote1018bdd2004-02-11 23:33:29 +00002435 HELPER(CMC);
jsgf855d93d2003-10-13 22:26:55 +00002436
nethercote71980f02004-01-24 18:18:54 +00002437 HELPER(shldl); HELPER(shldw);
2438 HELPER(shrdl); HELPER(shrdw);
njncc7bb472002-10-14 09:25:19 +00002439
nethercote71980f02004-01-24 18:18:54 +00002440 HELPER(RDTSC); HELPER(CPUID);
njncc7bb472002-10-14 09:25:19 +00002441
nethercote1018bdd2004-02-11 23:33:29 +00002442 HELPER(bsfw); HELPER(bsfl);
2443 HELPER(bsrw); HELPER(bsrl);
rjwalshf5f536f2003-11-17 17:45:00 +00002444
nethercote71980f02004-01-24 18:18:54 +00002445 HELPER(fstsw_AX);
2446 HELPER(SAHF); HELPER(LAHF);
2447 HELPER(DAS); HELPER(DAA);
nethercote1018bdd2004-02-11 23:33:29 +00002448 HELPER(AAS); HELPER(AAA);
2449 HELPER(AAD); HELPER(AAM);
nethercote71980f02004-01-24 18:18:54 +00002450 HELPER(IN); HELPER(OUT);
2451 HELPER(cmpxchg8b);
sewardj018f7622002-05-15 21:13:39 +00002452
nethercote71980f02004-01-24 18:18:54 +00002453 HELPER(undefined_instruction);
jsgf855d93d2003-10-13 22:26:55 +00002454
nethercote71980f02004-01-24 18:18:54 +00002455# undef HELPER
sewardjde4a1d02002-03-22 01:27:54 +00002456
nethercote71980f02004-01-24 18:18:54 +00002457 /* Allocate slots for noncompact helpers */
2458 assign_helpers_in_baseBlock(VG_(n_noncompact_helpers),
2459 VG_(noncompact_helper_offsets),
2460 VG_(noncompact_helper_addrs));
2461}
sewardjde4a1d02002-03-22 01:27:54 +00002462
sewardj5f07b662002-04-23 16:52:51 +00002463
nethercote71980f02004-01-24 18:18:54 +00002464/*====================================================================*/
2465/*=== Setup pointercheck ===*/
2466/*====================================================================*/
njn25e49d8e72002-09-23 09:36:25 +00002467
nethercote71980f02004-01-24 18:18:54 +00002468static void setup_pointercheck(void)
2469{
2470 int ret;
sewardj2e93c502002-04-12 11:12:52 +00002471
fitzhardinge98abfc72003-12-16 02:05:15 +00002472 if (VG_(clo_pointercheck)) {
nethercote71980f02004-01-24 18:18:54 +00002473 vki_modify_ldt_t ldt = {
2474 VG_POINTERCHECK_SEGIDX, // entry_number
2475 VG_(client_base), // base_addr
2476 (VG_(client_end)-VG_(client_base)) / VKI_BYTES_PER_PAGE, // limit
2477 1, // seg_32bit
2478 0, // contents: data, RW, non-expanding
2479 0, // ! read_exec_only
2480 1, // limit_in_pages
2481 0, // ! seg not present
2482 1, // useable
fitzhardinge98abfc72003-12-16 02:05:15 +00002483 };
nethercote71980f02004-01-24 18:18:54 +00002484 ret = VG_(do_syscall)(__NR_modify_ldt, 1, &ldt, sizeof(ldt));
fitzhardinge98abfc72003-12-16 02:05:15 +00002485 if (ret < 0) {
2486 VG_(message)(Vg_UserMsg,
2487 "Warning: ignoring --pointercheck=yes, "
2488 "because modify_ldt failed (errno=%d)", -ret);
2489 VG_(clo_pointercheck) = False;
2490 }
2491 }
sewardjde4a1d02002-03-22 01:27:54 +00002492}
2493
nethercote71980f02004-01-24 18:18:54 +00002494/*====================================================================*/
2495/*=== Initialise program data/text, etc. ===*/
2496/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +00002497
nethercote71980f02004-01-24 18:18:54 +00002498static void build_valgrind_map_callback
2499 ( Addr start, UInt size, Char rr, Char ww, Char xx,
2500 UInt dev, UInt ino, ULong foffset, const UChar* filename )
sewardjde4a1d02002-03-22 01:27:54 +00002501{
nethercote71980f02004-01-24 18:18:54 +00002502 UInt prot = 0;
2503 UInt flags = SF_MMAP|SF_NOSYMS;
2504 Bool is_stack_segment;
2505
2506 is_stack_segment =
2507 (start == VG_(clstk_base) && (start+size) == VG_(clstk_end));
2508
2509 /* Only record valgrind mappings for now, without loading any
2510 symbols. This is so we know where the free space is before we
2511 start allocating more memory (note: heap is OK, it's just mmap
2512 which is the problem here). */
2513 if (start >= VG_(valgrind_base) && (start+size) <= VG_(valgrind_end)) {
2514 flags |= SF_VALGRIND;
2515 VG_(map_file_segment)(start, size, prot, flags, dev, ino, foffset, filename);
2516 }
sewardjde4a1d02002-03-22 01:27:54 +00002517}
2518
nethercote71980f02004-01-24 18:18:54 +00002519// Global var used to pass local data to callback
2520Addr esp_at_startup___global_arg = 0;
sewardjde4a1d02002-03-22 01:27:54 +00002521
nethercote71980f02004-01-24 18:18:54 +00002522static void build_segment_map_callback
2523 ( Addr start, UInt size, Char rr, Char ww, Char xx,
2524 UInt dev, UInt ino, ULong foffset, const UChar* filename )
sewardj45b672d2003-07-25 19:58:11 +00002525{
nethercote71980f02004-01-24 18:18:54 +00002526 UInt prot = 0;
2527 UInt flags;
2528 Bool is_stack_segment;
2529 Addr r_esp;
sewardj45b672d2003-07-25 19:58:11 +00002530
nethercote71980f02004-01-24 18:18:54 +00002531 is_stack_segment
2532 = (start == VG_(clstk_base) && (start+size) == VG_(clstk_end));
fitzhardinge98abfc72003-12-16 02:05:15 +00002533
nethercote71980f02004-01-24 18:18:54 +00002534 if (rr == 'r') prot |= VKI_PROT_READ;
2535 if (ww == 'w') prot |= VKI_PROT_WRITE;
2536 if (xx == 'x') prot |= VKI_PROT_EXEC;
fitzhardinge98abfc72003-12-16 02:05:15 +00002537
nethercote71980f02004-01-24 18:18:54 +00002538 if (is_stack_segment)
2539 flags = SF_STACK | SF_GROWDOWN;
2540 else
2541 flags = SF_EXEC|SF_MMAP;
fitzhardinge98abfc72003-12-16 02:05:15 +00002542
nethercote71980f02004-01-24 18:18:54 +00002543 if (filename != NULL)
2544 flags |= SF_FILE;
fitzhardinge98abfc72003-12-16 02:05:15 +00002545
nethercote71980f02004-01-24 18:18:54 +00002546 if (start >= VG_(valgrind_base) && (start+size) <= VG_(valgrind_end))
2547 flags |= SF_VALGRIND;
fitzhardinge98abfc72003-12-16 02:05:15 +00002548
nethercote71980f02004-01-24 18:18:54 +00002549 VG_(map_file_segment)(start, size, prot, flags, dev, ino, foffset, filename);
fitzhardinge98abfc72003-12-16 02:05:15 +00002550
nethercote71980f02004-01-24 18:18:54 +00002551 if (VG_(is_client_addr)(start) && VG_(is_client_addr)(start+size-1))
2552 VG_TRACK( new_mem_startup, start, size, rr=='r', ww=='w', xx=='x' );
sewardj3e1eb1f2002-05-18 13:14:17 +00002553
nethercote71980f02004-01-24 18:18:54 +00002554 /* If this is the stack segment mark all below %esp as noaccess. */
2555 r_esp = esp_at_startup___global_arg;
2556 vg_assert(0 != r_esp);
2557 if (is_stack_segment) {
2558 if (0)
2559 VG_(message)(Vg_DebugMsg, "invalidating stack area: %x .. %x",
2560 start,r_esp);
2561 VG_TRACK( die_mem_stack, start, r_esp-start );
sewardjde4a1d02002-03-22 01:27:54 +00002562 }
sewardjde4a1d02002-03-22 01:27:54 +00002563}
2564
2565
nethercote71980f02004-01-24 18:18:54 +00002566/*====================================================================*/
2567/*=== Sanity check machinery (permanently engaged) ===*/
2568/*====================================================================*/
njn25e49d8e72002-09-23 09:36:25 +00002569
2570/* A fast sanity check -- suitable for calling circa once per
2571 millisecond. */
2572
2573void VG_(do_sanity_checks) ( Bool force_expensive )
2574{
njn37cea302002-09-30 11:24:00 +00002575 VGP_PUSHCC(VgpCoreCheapSanity);
2576
nethercote27fec902004-06-16 21:26:32 +00002577 if (VG_(clo_sanity_level) < 1) return;
njn25e49d8e72002-09-23 09:36:25 +00002578
2579 /* --- First do all the tests that we can do quickly. ---*/
2580
2581 VG_(sanity_fast_count)++;
2582
njn25e49d8e72002-09-23 09:36:25 +00002583 /* Check stuff pertaining to the memory check system. */
2584
2585 /* Check that nobody has spuriously claimed that the first or
2586 last 16 pages of memory have become accessible [...] */
njn37cea302002-09-30 11:24:00 +00002587 if (VG_(needs).sanity_checks) {
2588 VGP_PUSHCC(VgpSkinCheapSanity);
njn25e49d8e72002-09-23 09:36:25 +00002589 vg_assert(SK_(cheap_sanity_check)());
njn37cea302002-09-30 11:24:00 +00002590 VGP_POPCC(VgpSkinCheapSanity);
2591 }
njn25e49d8e72002-09-23 09:36:25 +00002592
2593 /* --- Now some more expensive checks. ---*/
2594
2595 /* Once every 25 times, check some more expensive stuff. */
2596 if ( force_expensive
nethercote27fec902004-06-16 21:26:32 +00002597 || VG_(clo_sanity_level) > 1
2598 || (VG_(clo_sanity_level) == 1 && (VG_(sanity_fast_count) % 25) == 0)) {
njn25e49d8e72002-09-23 09:36:25 +00002599
njn37cea302002-09-30 11:24:00 +00002600 VGP_PUSHCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002601 VG_(sanity_slow_count)++;
2602
jsgf855d93d2003-10-13 22:26:55 +00002603 VG_(proxy_sanity)();
2604
njn25e49d8e72002-09-23 09:36:25 +00002605# if 0
2606 { void zzzmemscan(void); zzzmemscan(); }
2607# endif
2608
2609 if ((VG_(sanity_fast_count) % 250) == 0)
2610 VG_(sanity_check_tc_tt)();
2611
2612 if (VG_(needs).sanity_checks) {
njn37cea302002-09-30 11:24:00 +00002613 VGP_PUSHCC(VgpSkinExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002614 vg_assert(SK_(expensive_sanity_check)());
njn37cea302002-09-30 11:24:00 +00002615 VGP_POPCC(VgpSkinExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002616 }
2617 /*
2618 if ((VG_(sanity_fast_count) % 500) == 0) VG_(mallocSanityCheckAll)();
2619 */
njn37cea302002-09-30 11:24:00 +00002620 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002621 }
2622
nethercote27fec902004-06-16 21:26:32 +00002623 if (VG_(clo_sanity_level) > 1) {
njn37cea302002-09-30 11:24:00 +00002624 VGP_PUSHCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002625 /* Check sanity of the low-level memory manager. Note that bugs
2626 in the client's code can cause this to fail, so we don't do
2627 this check unless specially asked for. And because it's
2628 potentially very expensive. */
2629 VG_(mallocSanityCheckAll)();
njn37cea302002-09-30 11:24:00 +00002630 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002631 }
njn37cea302002-09-30 11:24:00 +00002632 VGP_POPCC(VgpCoreCheapSanity);
njn25e49d8e72002-09-23 09:36:25 +00002633}
nethercote71980f02004-01-24 18:18:54 +00002634
2635
2636/*====================================================================*/
2637/*=== main() ===*/
2638/*====================================================================*/
2639
thughes4ad52d02004-06-27 17:37:21 +00002640static int prmap(void *start, void *end, const char *perm, off_t off,
2641 int maj, int min, int ino) {
2642 printf("mapping %10p-%10p %s %02x:%02x %d\n",
2643 start, end, perm, maj, min, ino);
2644 return True;
2645}
2646
nethercote71980f02004-01-24 18:18:54 +00002647int main(int argc, char **argv)
2648{
2649 char **cl_argv;
2650 const char *tool = NULL;
2651 const char *exec = NULL;
2652 char *preload; /* tool-specific LD_PRELOAD .so */
2653 char **env;
nethercote6c999f22004-01-31 22:55:15 +00002654 Int need_help = 0; // 0 = no, 1 = --help, 2 = --help-debug
nethercote71980f02004-01-24 18:18:54 +00002655 struct exeinfo info;
2656 ToolInfo *toolinfo = NULL;
2657 void *tool_dlhandle;
2658 Addr client_eip;
2659 Addr esp_at_startup; /* client's %esp at the point we gained control. */
2660 UInt * client_auxv;
2661 VgSchedReturnCode src;
nethercote47dd12c2004-06-22 14:18:42 +00002662 Int exitcode = 0;
fitzhardingeb50068f2004-02-24 23:42:55 +00002663 vki_rlimit zero = { 0, 0 };
nethercote71980f02004-01-24 18:18:54 +00002664
2665 //============================================================
2666 // Nb: startup is complex. Prerequisites are shown at every step.
2667 //
2668 // *** Be very careful when messing with the order ***
2669 //============================================================
2670
nethercotef4928da2004-06-15 10:54:40 +00002671 //============================================================
2672 // Command line argument handling order:
2673 // * If --help/--help-debug are present, show usage message
2674 // (if --tool is also present, that includes the tool-specific usage)
2675 // * Then, if --tool is missing, abort with error msg
2676 // * Then, if client is missing, abort with error msg
2677 // * Then, if any cmdline args are bad, abort with error msg
2678 //============================================================
2679
fitzhardingeb50068f2004-02-24 23:42:55 +00002680 // Get the current process datasize rlimit, and set it to zero.
2681 // This prevents any internal uses of brk() from having any effect.
2682 // We remember the old value so we can restore it on exec, so that
2683 // child processes will have a reasonable brk value.
2684 VG_(getrlimit)(VKI_RLIMIT_DATA, &VG_(client_rlimit_data));
2685 zero.rlim_max = VG_(client_rlimit_data).rlim_max;
2686 VG_(setrlimit)(VKI_RLIMIT_DATA, &zero);
2687
nethercote71980f02004-01-24 18:18:54 +00002688 //--------------------------------------------------------------
2689 // Check we were launched by stage1
2690 // p: n/a [must be first step]
2691 //--------------------------------------------------------------
2692 scan_auxv();
2693
2694 if (0) {
nethercote71980f02004-01-24 18:18:54 +00002695 printf("========== main() ==========\n");
2696 foreach_map(prmap);
2697 }
2698
2699 //--------------------------------------------------------------
2700 // Look for alternative libdir
2701 // p: n/a
2702 //--------------------------------------------------------------
2703 { char *cp = getenv(VALGRINDLIB);
2704 if (cp != NULL)
2705 VG_(libdir) = cp;
2706 }
2707
2708 //--------------------------------------------------------------
2709 // Begin working out address space layout
2710 // p: n/a
2711 //--------------------------------------------------------------
2712 layout_client_space( (Addr) & argc );
2713
2714 //--------------------------------------------------------------
2715 // Get valgrind args + client args (inc. from VALGRIND_OPTS/.valgrindrc).
2716 // Pre-process the command line.
2717 // p: n/a
2718 //--------------------------------------------------------------
2719 get_command_line(argc, argv, &VG_(vg_argc), &VG_(vg_argv), &cl_argv);
2720 pre_process_cmd_line_options(&need_help, &tool, &exec);
2721
2722 //==============================================================
2723 // Nb: once a tool is specified, the tool.so must be loaded even if
2724 // they specified --help or didn't specify a client program.
2725 //==============================================================
2726
2727 //--------------------------------------------------------------
2728 // With client padded out, map in tool
2729 // p: layout_client_space() [for padding]
2730 // p: set-libdir [for VG_(libdir)]
2731 // p: pre_process_cmd_line_options() [for 'tool']
2732 //--------------------------------------------------------------
2733 load_tool(tool, &tool_dlhandle, &toolinfo, &preload);
2734
2735 //==============================================================
2736 // Can use VG_(malloc)() and VG_(arena_malloc)() only after load_tool()
2737 // -- redzone size is now set.
2738 //==============================================================
2739
2740 //--------------------------------------------------------------
2741 // Finalise address space layout
2742 // p: layout_client_space(), load_tool() [for 'toolinfo']
2743 //--------------------------------------------------------------
2744 layout_remaining_space( toolinfo->shadow_ratio );
2745
2746 //--------------------------------------------------------------
2747 // Load client executable, finding in $PATH if necessary
2748 // p: layout_client_space() [so there's space]
2749 // p: pre_process_cmd_line_options() [for 'exec', 'need_help']
2750 // p: layout_remaining_space [so there's space]
2751 //--------------------------------------------------------------
nethercotef4928da2004-06-15 10:54:40 +00002752 load_client(cl_argv, exec, need_help, &info, &client_eip);
nethercote71980f02004-01-24 18:18:54 +00002753
2754 //--------------------------------------------------------------
2755 // Everything in place, unpad us
2756 // p: layout_remaining_space() [everything must be mapped in before now]
2757 // p: load_client() [ditto]
2758 //--------------------------------------------------------------
2759 as_unpad((void *)VG_(shadow_end), (void *)~0);
2760 as_closepadfile(); /* no more padding */
2761
2762 //--------------------------------------------------------------
2763 // Set up client's environment
2764 // p: set-libdir [for VG_(libdir)]
2765 // p: load_tool() [for 'preload']
2766 //--------------------------------------------------------------
2767 env = fix_environment(environ, preload);
2768
2769 //--------------------------------------------------------------
nethercote5ee67ca2004-06-22 14:00:09 +00002770 // Setup client stack, eip, and VG_(client_arg[cv])
nethercote71980f02004-01-24 18:18:54 +00002771 // p: load_client() [for 'info']
2772 // p: fix_environment() [for 'env']
2773 //--------------------------------------------------------------
2774 esp_at_startup = setup_client_stack(cl_argv, env, &info, &client_auxv);
2775
2776 if (0)
2777 printf("entry=%x client esp=%x vg_argc=%d brkbase=%x\n",
2778 client_eip, esp_at_startup, VG_(vg_argc), VG_(brk_base));
2779
2780 //==============================================================
2781 // Finished setting up operating environment. Now initialise
2782 // Valgrind. (This is where the old VG_(main)() started.)
2783 //==============================================================
2784
2785 //--------------------------------------------------------------
2786 // Read /proc/self/maps into a buffer
2787 // p: all memory layout, environment setup [so memory maps are right]
2788 //--------------------------------------------------------------
2789 VG_(read_procselfmaps)();
2790
2791 //--------------------------------------------------------------
2792 // atfork
2793 // p: n/a
2794 //--------------------------------------------------------------
2795 VG_(atfork)(NULL, NULL, newpid);
2796 newpid(VG_INVALID_THREADID);
2797
2798 //--------------------------------------------------------------
2799 // setup file descriptors
2800 // p: n/a
2801 //--------------------------------------------------------------
2802 setup_file_descriptors();
2803
2804 //--------------------------------------------------------------
2805 // Setup tool
2806 // p: VG_(read_procselfmaps)() [so if sk_pre_clo_init calls
2807 // VG_(malloc), any mmap'd superblocks aren't erroneously
2808 // identified later as being owned by the client]
2809 // XXX: is that necessary, now that we look for V's segments separately?
2810 // XXX: alternatively, if sk_pre_clo_init does use VG_(malloc)(), is it
2811 // wrong to ignore any segments that might add in parse_procselfmaps?
nethercote5ee67ca2004-06-22 14:00:09 +00002812 // p: setup_client_stack() [for 'VG_(client_arg[cv]']
nethercote71980f02004-01-24 18:18:54 +00002813 //--------------------------------------------------------------
2814 (*toolinfo->sk_pre_clo_init)();
2815 VG_(tool_init_dlsym)(tool_dlhandle);
2816 VG_(sanity_check_needs)();
2817
2818 //--------------------------------------------------------------
nethercotef4928da2004-06-15 10:54:40 +00002819 // If --tool and --help/--help-debug was given, now give the core+tool
2820 // help message
2821 // p: pre_clo_init()
2822 //--------------------------------------------------------------
2823 if (need_help) {
2824 usage(/*--help-debug?*/2 == need_help);
2825 }
2826
2827 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002828 // Process Valgrind's + tool's command-line options
2829 // p: load_tool() [for 'tool']
thughesad1c9562004-06-26 11:27:52 +00002830 // p: setup_file_descriptors() [for 'VG_(fd_xxx_limit)']
nethercote71980f02004-01-24 18:18:54 +00002831 // p: sk_pre_clo_init [to set 'command_line_options' need]
2832 //--------------------------------------------------------------
nethercote5ee67ca2004-06-22 14:00:09 +00002833 process_cmd_line_options(client_auxv, tool);
nethercote71980f02004-01-24 18:18:54 +00002834
2835 //--------------------------------------------------------------
2836 // Allow GDB attach
2837 // p: process_cmd_line_options() [for VG_(clo_wait_for_gdb)]
2838 //--------------------------------------------------------------
2839 /* Hook to delay things long enough so we can get the pid and
2840 attach GDB in another shell. */
2841 if (VG_(clo_wait_for_gdb)) {
2842 VG_(printf)("pid=%d\n", VG_(getpid)());
2843 /* do "jump *$eip" to skip this in gdb */
2844 VG_(do_syscall)(__NR_pause);
2845 }
2846
2847 //--------------------------------------------------------------
2848 // Setup tool, post command-line processing
2849 // p: process_cmd_line_options [tool assumes it]
2850 //--------------------------------------------------------------
2851 SK_(post_clo_init)();
2852
2853 //--------------------------------------------------------------
nethercote1d447092004-02-01 17:29:59 +00002854 // Set up baseBlock
nethercote71980f02004-01-24 18:18:54 +00002855 // p: {pre,post}_clo_init() [for tool helper registration]
2856 // load_client() [for 'client_eip']
2857 // setup_client_stack() [for 'esp_at_startup']
2858 //--------------------------------------------------------------
2859 init_baseBlock(client_eip, esp_at_startup);
2860
2861 //--------------------------------------------------------------
2862 // Search for file descriptors that are inherited from our parent
2863 // p: process_cmd_line_options [for VG_(clo_track_fds)]
2864 //--------------------------------------------------------------
2865 if (VG_(clo_track_fds))
2866 VG_(init_preopened_fds)();
2867
2868 //--------------------------------------------------------------
2869 // Initialise the scheduler
2870 // p: init_baseBlock() [baseBlock regs copied into VG_(threads)[1]]
2871 // p: setup_file_descriptors() [else VG_(safe_fd)() breaks]
2872 //--------------------------------------------------------------
2873 VG_(scheduler_init)();
2874
2875 //--------------------------------------------------------------
2876 // Set up the ProxyLWP machinery
2877 // p: VG_(scheduler_init)()? [XXX: subtle dependency?]
2878 // - subs: VG_(sigstartup_actions)()?
2879 //--------------------------------------------------------------
2880 VG_(proxy_init)();
2881
2882 //--------------------------------------------------------------
2883 // Initialise the signal handling subsystem
2884 // p: VG_(atfork)(NULL, NULL, newpid) [else problems with sigmasks]
2885 // p: VG_(proxy_init)() [else breaks...]
2886 //--------------------------------------------------------------
2887 // Nb: temporarily parks the saved blocking-mask in saved_sigmask.
2888 VG_(sigstartup_actions)();
2889
2890 //--------------------------------------------------------------
2891 // Perhaps we're profiling Valgrind?
2892 // p: process_cmd_line_options() [for VG_(clo_profile)]
2893 // p: others?
2894 //
2895 // XXX: this seems to be broken? It always says the tool wasn't built
2896 // for profiling; vg_profile.c's functions don't seem to be overriding
2897 // vg_dummy_profile.c's?
2898 //
2899 // XXX: want this as early as possible. Looking for --profile
2900 // in pre_process_cmd_line_options() could get it earlier.
2901 //--------------------------------------------------------------
2902 if (VG_(clo_profile))
2903 VGP_(init_profiling)();
2904
2905 VGP_PUSHCC(VgpStartup);
2906
2907 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002908 // Reserve Valgrind's kickstart, heap and stack
2909 // p: XXX ???
2910 //--------------------------------------------------------------
2911 VG_(map_segment)(VG_(valgrind_mmap_end),
2912 VG_(valgrind_end)-VG_(valgrind_mmap_end),
2913 VKI_PROT_NONE, SF_VALGRIND|SF_FIXED);
2914
2915 //--------------------------------------------------------------
2916 // Identify Valgrind's segments
2917 // p: read proc/self/maps
2918 // p: VG_(map_segment) [XXX ???]
2919 // p: sk_pre_clo_init() [to setup new_mem_startup tracker]
2920 //--------------------------------------------------------------
2921 VG_(parse_procselfmaps) ( build_valgrind_map_callback );
2922
2923 // XXX: I can't see why these two need to be separate; could they be
2924 // folded together? If not, need a comment explaining why.
2925 //
2926 // XXX: can we merge reading and parsing of /proc/self/maps?
2927 //
2928 // XXX: can we dynamically allocate the /proc/self/maps buffer? (or mmap
2929 // it?) Or does that disturb its contents...
2930
2931 //--------------------------------------------------------------
2932 // Build segment map (all segments)
2933 // p: setup_client_stack() [for 'esp_at_startup']
2934 //--------------------------------------------------------------
2935 esp_at_startup___global_arg = esp_at_startup;
2936 VG_(parse_procselfmaps) ( build_segment_map_callback ); /* everything */
2937 esp_at_startup___global_arg = 0;
2938
2939 //==============================================================
2940 // Can only use VG_(map)() after VG_(map_segment)() [XXX ???]
2941 //==============================================================
2942
2943 //--------------------------------------------------------------
2944 // Build segment map (all segments)
2945 // p: setup_client_stack() [for 'esp_at_startup']
2946 //--------------------------------------------------------------
2947 /* Initialize our trampoline page (which is also sysinfo stuff) */
2948 VG_(memcpy)( (void *)VG_(client_trampoline_code),
2949 &VG_(trampoline_code_start), VG_(trampoline_code_length) );
2950 VG_(mprotect)( (void *)VG_(client_trampoline_code),
2951 VG_(trampoline_code_length), VKI_PROT_READ|VKI_PROT_EXEC );
2952
2953 //--------------------------------------------------------------
2954 // Read suppression file
2955 // p: process_cmd_line_options() [for VG_(clo_suppressions)]
2956 //--------------------------------------------------------------
2957 if (VG_(needs).core_errors || VG_(needs).skin_errors)
2958 VG_(load_suppressions)();
2959
2960 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002961 // Initialise translation table and translation cache
2962 // p: read_procselfmaps [so the anonymous mmaps for the TT/TC
2963 // aren't identified as part of the client, which would waste
2964 // > 20M of virtual address space.]
2965 //--------------------------------------------------------------
2966 VG_(init_tt_tc)();
2967
2968 //--------------------------------------------------------------
2969 // Read debug info to find glibc entry points to intercept
2970 // p: parse_procselfmaps? [XXX for debug info?]
2971 // p: init_tt_tc? [XXX ???]
2972 //--------------------------------------------------------------
2973 VG_(setup_code_redirect_table)();
2974
2975 //--------------------------------------------------------------
2976 // Verbosity message
2977 // p: end_rdtsc_calibration [so startup message is printed first]
2978 //--------------------------------------------------------------
2979 if (VG_(clo_verbosity) == 1)
2980 VG_(message)(Vg_UserMsg, "For more details, rerun with: -v");
2981 if (VG_(clo_verbosity) > 0)
2982 VG_(message)(Vg_UserMsg, "");
2983
2984 //--------------------------------------------------------------
2985 // Setup pointercheck
2986 // p: process_cmd_line_options() [for VG_(clo_pointercheck)]
2987 //--------------------------------------------------------------
2988 setup_pointercheck();
2989
2990
2991
2992 //--------------------------------------------------------------
2993 // Run!
2994 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002995 VGP_POPCC(VgpStartup);
2996 VGP_PUSHCC(VgpSched);
2997
2998 if (__builtin_setjmp(&VG_(fatal_signal_jmpbuf)) == 0) {
2999 VG_(fatal_signal_set) = True;
nethercote47dd12c2004-06-22 14:18:42 +00003000 src = VG_(scheduler)( &exitcode );
nethercote71980f02004-01-24 18:18:54 +00003001 } else
3002 src = VgSrc_FatalSig;
3003
3004 VGP_POPCC(VgpSched);
nethercote71980f02004-01-24 18:18:54 +00003005
3006
3007
3008 //--------------------------------------------------------------
3009 // Finalisation: cleanup, messages, etc. Order no so important, only
3010 // affects what order the messages come.
3011 //--------------------------------------------------------------
3012 if (VG_(clo_verbosity) > 0)
3013 VG_(message)(Vg_UserMsg, "");
3014
3015 if (src == VgSrc_Deadlock) {
3016 VG_(message)(Vg_UserMsg,
3017 "Warning: pthread scheduler exited due to deadlock");
3018 }
3019
3020 /* Print out file descriptor summary and stats. */
3021 if (VG_(clo_track_fds))
3022 VG_(fd_stats)();
3023
3024 if (VG_(needs).core_errors || VG_(needs).skin_errors)
3025 VG_(show_all_errors)();
3026
nethercote47dd12c2004-06-22 14:18:42 +00003027 SK_(fini)( exitcode );
nethercote71980f02004-01-24 18:18:54 +00003028
3029 VG_(do_sanity_checks)( True /*include expensive checks*/ );
3030
3031 if (VG_(clo_verbosity) > 1)
3032 show_counts();
3033
3034 if (VG_(clo_verbosity) > 3)
3035 VG_(print_UInstr_histogram)();
3036
3037 if (0) {
3038 VG_(message)(Vg_DebugMsg, "");
3039 VG_(message)(Vg_DebugMsg,
3040 "------ Valgrind's internal memory use stats follow ------" );
3041 VG_(mallocSanityCheckAll)();
3042 VG_(show_all_arena_stats)();
3043 VG_(message)(Vg_DebugMsg,
3044 "------ Valgrind's ExeContext management stats follow ------" );
3045 VG_(show_ExeContext_stats)();
3046 }
3047
3048 if (VG_(clo_profile))
3049 VGP_(done_profiling)();
3050
nethercote71980f02004-01-24 18:18:54 +00003051 /* We're exiting, so nuke all the threads and clean up the proxy LWPs */
3052 vg_assert(src == VgSrc_FatalSig ||
3053 VG_(threads)[VG_(last_run_tid)].status == VgTs_Runnable ||
3054 VG_(threads)[VG_(last_run_tid)].status == VgTs_WaitJoiner);
3055 VG_(nuke_all_threads_except)(VG_INVALID_THREADID);
3056
3057 //--------------------------------------------------------------
3058 // Exit, according to the scheduler's return code
3059 //--------------------------------------------------------------
3060 switch (src) {
3061 case VgSrc_ExitSyscall: /* the normal way out */
3062 vg_assert(VG_(last_run_tid) > 0
3063 && VG_(last_run_tid) < VG_N_THREADS);
3064 VG_(proxy_shutdown)();
3065
3066 /* The thread's %EBX at the time it did __NR_exit() will hold
3067 the arg to __NR_exit(), so we just do __NR_exit() with
3068 that arg. */
nethercote47dd12c2004-06-22 14:18:42 +00003069 VG_(exit)( exitcode );
nethercote71980f02004-01-24 18:18:54 +00003070 /* NOT ALIVE HERE! */
3071 VG_(core_panic)("entered the afterlife in main() -- ExitSyscall");
3072 break; /* what the hell :) */
3073
3074 case VgSrc_Deadlock:
3075 /* Just exit now. No point in continuing. */
3076 VG_(proxy_shutdown)();
3077 VG_(exit)(0);
3078 VG_(core_panic)("entered the afterlife in main() -- Deadlock");
3079 break;
3080
nethercote71980f02004-01-24 18:18:54 +00003081 case VgSrc_FatalSig:
3082 /* We were killed by a fatal signal, so replicate the effect */
3083 vg_assert(VG_(fatal_sigNo) != -1);
3084 VG_(kill_self)(VG_(fatal_sigNo));
3085 VG_(core_panic)("main(): signal was supposed to be fatal");
3086 break;
3087
3088 default:
3089 VG_(core_panic)("main(): unexpected scheduler return code");
3090 }
3091
3092 abort();
3093}
3094
3095
sewardjde4a1d02002-03-22 01:27:54 +00003096/*--------------------------------------------------------------------*/
3097/*--- end vg_main.c ---*/
3098/*--------------------------------------------------------------------*/