blob: e2a15e4836b7be97b96487e1b1344e2274be6a0f [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/* redzone gap between client address space and shadow */
78#define REDZONE_SIZE (1 * 1024*1024)
79
80/* size multiple for client address space */
nethercotee94b2de2004-06-23 16:15:06 +000081#define CLIENT_SIZE_MULTIPLE (1 * 1024*1024)
nethercote71980f02004-01-24 18:18:54 +000082
nethercotee2097312004-06-27 12:29:56 +000083/* Proportion of client space for its heap (rest is for mmaps + stack) */
84#define CLIENT_HEAP_PROPORTION 0.333
nethercote71980f02004-01-24 18:18:54 +000085
86/*====================================================================*/
87/*=== Global entities not referenced from generated code ===*/
88/*====================================================================*/
89
sewardjde4a1d02002-03-22 01:27:54 +000090/* ---------------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +000091 Startup stuff
sewardjde4a1d02002-03-22 01:27:54 +000092 ------------------------------------------------------------------ */
nethercote71980f02004-01-24 18:18:54 +000093/* linker-defined base address */
94extern char kickstart_base;
sewardjde4a1d02002-03-22 01:27:54 +000095
nethercote71980f02004-01-24 18:18:54 +000096/* Client address space, lowest to highest (see top of ume.c) */
97Addr VG_(client_base); /* client address space limits */
fitzhardinge98abfc72003-12-16 02:05:15 +000098Addr VG_(client_end);
99Addr VG_(client_mapbase);
fitzhardinge92360792003-12-24 10:11:11 +0000100Addr VG_(client_trampoline_code);
fitzhardinge98abfc72003-12-16 02:05:15 +0000101Addr VG_(clstk_base);
102Addr VG_(clstk_end);
nethercote71980f02004-01-24 18:18:54 +0000103
104Addr VG_(brk_base); /* start of brk */
105Addr VG_(brk_limit); /* current brk */
106
107Addr VG_(shadow_base); /* skin's shadow memory */
fitzhardinge98abfc72003-12-16 02:05:15 +0000108Addr VG_(shadow_end);
nethercote71980f02004-01-24 18:18:54 +0000109
110Addr VG_(valgrind_base); /* valgrind's address range */
fitzhardinge98abfc72003-12-16 02:05:15 +0000111Addr VG_(valgrind_end);
112
fitzhardingeb50068f2004-02-24 23:42:55 +0000113vki_rlimit VG_(client_rlimit_data);
114
nethercote71980f02004-01-24 18:18:54 +0000115/* This is set early to indicate whether this CPU has the
116 SSE/fxsave/fxrestor features. */
117Bool VG_(have_ssestate);
118
119/* Indicates presence, and holds address of client's sysinfo page, a
120 feature of some modern kernels used to provide vsyscalls, etc. */
121Bool VG_(sysinfo_page_exists) = False;
122Addr VG_(sysinfo_page_addr) = 0;
123
fitzhardinge98abfc72003-12-16 02:05:15 +0000124/* stage1 (main) executable */
fitzhardingea49f9b52003-12-16 22:26:45 +0000125Int VG_(vgexecfd) = -1;
126
127/* client executable */
128Int VG_(clexecfd) = -1;
fitzhardinge98abfc72003-12-16 02:05:15 +0000129
130/* Path to library directory */
131const Char *VG_(libdir) = VG_LIBDIR;
132
133/* our argc/argv */
134Int VG_(vg_argc);
135Char **VG_(vg_argv);
136
jsgf855d93d2003-10-13 22:26:55 +0000137/* PID of the main thread */
138Int VG_(main_pid);
139
140/* PGRP of process */
141Int VG_(main_pgrp);
njn25e49d8e72002-09-23 09:36:25 +0000142
thughesad1c9562004-06-26 11:27:52 +0000143/* Application-visible file descriptor limits */
144Int VG_(fd_soft_limit) = -1;
145Int VG_(fd_hard_limit) = -1;
fitzhardingef0046f22003-12-18 02:39:22 +0000146
nethercote71980f02004-01-24 18:18:54 +0000147/* As deduced from esp_at_startup, the client's argc, argv[] and
148 envp[] as extracted from the client's stack at startup-time. */
149Int VG_(client_argc);
150Char** VG_(client_argv);
151Char** VG_(client_envp);
sewardjde4a1d02002-03-22 01:27:54 +0000152
153/* ---------------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +0000154 Running stuff
sewardjde4a1d02002-03-22 01:27:54 +0000155 ------------------------------------------------------------------ */
nethercote71980f02004-01-24 18:18:54 +0000156/* Our signal delivery stack. */
njn6eba4ef2003-05-01 08:06:41 +0000157UInt VG_(sigstack)[VG_SIGSTACK_SIZE_W];
sewardjde4a1d02002-03-22 01:27:54 +0000158
nethercote71980f02004-01-24 18:18:54 +0000159/* jmp_buf for fatal signals */
160Int VG_(fatal_sigNo) = -1;
161Bool VG_(fatal_signal_set) = False;
162jmp_buf VG_(fatal_signal_jmpbuf);
sewardjde4a1d02002-03-22 01:27:54 +0000163
nethercote71980f02004-01-24 18:18:54 +0000164/* Counts downwards in VG_(run_innerloop). */
165UInt VG_(dispatch_ctr);
sewardjde4a1d02002-03-22 01:27:54 +0000166
167/* 64-bit counter for the number of basic blocks done. */
168ULong VG_(bbs_done);
sewardjde4a1d02002-03-22 01:27:54 +0000169
sewardj7e87e382002-05-03 19:09:05 +0000170/* This is the ThreadId of the last thread the scheduler ran. */
171ThreadId VG_(last_run_tid) = 0;
172
nethercote71980f02004-01-24 18:18:54 +0000173/* Tell the logging mechanism whether we are logging to a file
174 descriptor or a socket descriptor. */
175Bool VG_(logging_to_filedes) = True;
176
sewardj73cf3bc2002-11-03 03:20:15 +0000177
nethercote71980f02004-01-24 18:18:54 +0000178/*====================================================================*/
179/*=== Counters, for profiling purposes only ===*/
180/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +0000181
182/* Number of lookups which miss the fast tt helper. */
183UInt VG_(tt_fast_misses) = 0;
184
185
sewardjc0d8f682002-11-30 00:49:43 +0000186/* Counts for TT/TC informational messages. */
sewardjde4a1d02002-03-22 01:27:54 +0000187
sewardjde4a1d02002-03-22 01:27:54 +0000188/* Number and total o/t size of translations overall. */
189UInt VG_(overall_in_count) = 0;
190UInt VG_(overall_in_osize) = 0;
191UInt VG_(overall_in_tsize) = 0;
192/* Number and total o/t size of discards overall. */
193UInt VG_(overall_out_count) = 0;
194UInt VG_(overall_out_osize) = 0;
195UInt VG_(overall_out_tsize) = 0;
sewardjc0d8f682002-11-30 00:49:43 +0000196/* The number of discards of TT/TC. */
197UInt VG_(number_of_tc_discards) = 0;
sewardj22854b92002-11-30 14:00:47 +0000198/* Counts of chain and unchain operations done. */
199UInt VG_(bb_enchain_count) = 0;
200UInt VG_(bb_dechain_count) = 0;
201/* Number of unchained jumps performed. */
202UInt VG_(unchained_jumps_done) = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000203
204
205/* Counts pertaining to the register allocator. */
206
207/* total number of uinstrs input to reg-alloc */
208UInt VG_(uinstrs_prealloc) = 0;
209
210/* total number of uinstrs added due to spill code */
211UInt VG_(uinstrs_spill) = 0;
212
213/* number of bbs requiring spill code */
214UInt VG_(translations_needing_spill) = 0;
215
216/* total of register ranks over all translations */
217UInt VG_(total_reg_rank) = 0;
218
219
sewardjde4a1d02002-03-22 01:27:54 +0000220/* Counts pertaining to internal sanity checking. */
sewardjde4a1d02002-03-22 01:27:54 +0000221UInt VG_(sanity_fast_count) = 0;
222UInt VG_(sanity_slow_count) = 0;
223
sewardj2e93c502002-04-12 11:12:52 +0000224/* Counts pertaining to the scheduler. */
225UInt VG_(num_scheduling_events_MINOR) = 0;
226UInt VG_(num_scheduling_events_MAJOR) = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000227
228
nethercote71980f02004-01-24 18:18:54 +0000229static __inline__ Int safe_idiv(Int a, Int b)
230{
231 return (b == 0 ? 0 : a / b);
232}
233
234static void show_counts ( void )
235{
236 VG_(message)(Vg_DebugMsg,
237 " TT/TC: %d tc sectors discarded.",
238 VG_(number_of_tc_discards) );
239 VG_(message)(Vg_DebugMsg,
240 " %d chainings, %d unchainings.",
241 VG_(bb_enchain_count), VG_(bb_dechain_count) );
242 VG_(message)(Vg_DebugMsg,
243 "translate: new %d (%d -> %d; ratio %d:10)",
244 VG_(overall_in_count),
245 VG_(overall_in_osize),
246 VG_(overall_in_tsize),
247 safe_idiv(10*VG_(overall_in_tsize), VG_(overall_in_osize)));
248 VG_(message)(Vg_DebugMsg,
249 " discard %d (%d -> %d; ratio %d:10).",
250 VG_(overall_out_count),
251 VG_(overall_out_osize),
252 VG_(overall_out_tsize),
253 safe_idiv(10*VG_(overall_out_tsize), VG_(overall_out_osize)));
254 VG_(message)(Vg_DebugMsg,
255 " dispatch: %llu jumps (bb entries), of which %u (%lu%%) were unchained.",
256 VG_(bbs_done),
257 VG_(unchained_jumps_done),
258 ((ULong)(100) * (ULong)(VG_(unchained_jumps_done)))
259 / ( VG_(bbs_done)==0 ? 1 : VG_(bbs_done) )
260 );
261
262 VG_(message)(Vg_DebugMsg,
263 " %d/%d major/minor sched events. %d tt_fast misses.",
264 VG_(num_scheduling_events_MAJOR),
265 VG_(num_scheduling_events_MINOR),
266 VG_(tt_fast_misses));
267
268 VG_(message)(Vg_DebugMsg,
269 "reg-alloc: %d t-req-spill, "
270 "%d+%d orig+spill uis, %d total-reg-r.",
271 VG_(translations_needing_spill),
272 VG_(uinstrs_prealloc),
273 VG_(uinstrs_spill),
274 VG_(total_reg_rank) );
275 VG_(message)(Vg_DebugMsg,
276 " sanity: %d cheap, %d expensive checks.",
277 VG_(sanity_fast_count),
278 VG_(sanity_slow_count) );
279 VG_(print_ccall_stats)();
280}
281
282
283/*====================================================================*/
284/*=== Miscellaneous global functions ===*/
285/*====================================================================*/
286
nethercote04d0fbc2004-01-26 16:48:06 +0000287/* Start debugger and get it to attach to this process. Called if the
288 user requests this service after an error has been shown, so she can
nethercote71980f02004-01-24 18:18:54 +0000289 poke around and look at parameters, memory, etc. You can't
nethercote04d0fbc2004-01-26 16:48:06 +0000290 meaningfully get the debugger to continue the program, though; to
291 continue, quit the debugger. */
292void VG_(start_debugger) ( Int tid )
nethercote71980f02004-01-24 18:18:54 +0000293{
294 Int pid;
295
296 if ((pid = fork()) == 0) {
297 ptrace(PTRACE_TRACEME, 0, NULL, NULL);
298 VG_(kkill)(VG_(getpid)(), VKI_SIGSTOP);
299
300 } else if (pid > 0) {
301 struct user_regs_struct regs;
302 Int status;
303 Int res;
304
305 if (VG_(is_running_thread)( tid )) {
fitzhardinged65dcad2004-03-13 02:06:58 +0000306 regs.cs = VG_(baseBlock)[VGOFF_(m_cs)];
307 regs.ss = VG_(baseBlock)[VGOFF_(m_ss)];
308 regs.ds = VG_(baseBlock)[VGOFF_(m_ds)];
309 regs.es = VG_(baseBlock)[VGOFF_(m_es)];
310 regs.fs = VG_(baseBlock)[VGOFF_(m_fs)];
311 regs.gs = VG_(baseBlock)[VGOFF_(m_gs)];
nethercote71980f02004-01-24 18:18:54 +0000312 regs.eax = VG_(baseBlock)[VGOFF_(m_eax)];
313 regs.ebx = VG_(baseBlock)[VGOFF_(m_ebx)];
314 regs.ecx = VG_(baseBlock)[VGOFF_(m_ecx)];
315 regs.edx = VG_(baseBlock)[VGOFF_(m_edx)];
316 regs.esi = VG_(baseBlock)[VGOFF_(m_esi)];
317 regs.edi = VG_(baseBlock)[VGOFF_(m_edi)];
318 regs.ebp = VG_(baseBlock)[VGOFF_(m_ebp)];
319 regs.esp = VG_(baseBlock)[VGOFF_(m_esp)];
320 regs.eflags = VG_(baseBlock)[VGOFF_(m_eflags)];
321 regs.eip = VG_(baseBlock)[VGOFF_(m_eip)];
322 } else {
323 ThreadState* tst = & VG_(threads)[ tid ];
324
fitzhardinged65dcad2004-03-13 02:06:58 +0000325 regs.cs = tst->m_cs;
326 regs.ss = tst->m_ss;
327 regs.ds = tst->m_ds;
328 regs.es = tst->m_es;
329 regs.fs = tst->m_fs;
330 regs.gs = tst->m_gs;
nethercote71980f02004-01-24 18:18:54 +0000331 regs.eax = tst->m_eax;
332 regs.ebx = tst->m_ebx;
333 regs.ecx = tst->m_ecx;
334 regs.edx = tst->m_edx;
335 regs.esi = tst->m_esi;
336 regs.edi = tst->m_edi;
337 regs.ebp = tst->m_ebp;
338 regs.esp = tst->m_esp;
339 regs.eflags = tst->m_eflags;
340 regs.eip = tst->m_eip;
341 }
342
343 if ((res = VG_(waitpid)(pid, &status, 0)) == pid &&
344 WIFSTOPPED(status) && WSTOPSIG(status) == SIGSTOP &&
345 ptrace(PTRACE_SETREGS, pid, NULL, &regs) == 0 &&
thughes1d160052004-04-21 15:39:57 +0000346 kill(pid, SIGSTOP) == 0 &&
347 ptrace(PTRACE_DETACH, pid, NULL, 0) == 0) {
nethercote04d0fbc2004-01-26 16:48:06 +0000348 Char pidbuf[15];
349 Char file[30];
350 Char buf[100];
351 Char *bufptr;
352 Char *cmdptr;
353
354 VG_(sprintf)(pidbuf, "%d", pid);
355 VG_(sprintf)(file, "/proc/%d/fd/%d", pid, VG_(clexecfd));
356
357 bufptr = buf;
358 cmdptr = VG_(clo_db_command);
359
360 while (*cmdptr) {
361 switch (*cmdptr) {
362 case '%':
363 switch (*++cmdptr) {
364 case 'f':
365 VG_(memcpy)(bufptr, file, VG_(strlen)(file));
366 bufptr += VG_(strlen)(file);
367 cmdptr++;
368 break;
369 case 'p':
370 VG_(memcpy)(bufptr, pidbuf, VG_(strlen)(pidbuf));
371 bufptr += VG_(strlen)(pidbuf);
372 cmdptr++;
373 break;
374 default:
375 *bufptr++ = *cmdptr++;
376 break;
377 }
378 break;
379 default:
380 *bufptr++ = *cmdptr++;
381 break;
382 }
383 }
384
385 *bufptr++ = '\0';
386
387 VG_(message)(Vg_UserMsg, "starting debugger with cmd: %s", buf);
nethercote71980f02004-01-24 18:18:54 +0000388 res = VG_(system)(buf);
389 if (res == 0) {
390 VG_(message)(Vg_UserMsg, "");
391 VG_(message)(Vg_UserMsg,
nethercote04d0fbc2004-01-26 16:48:06 +0000392 "Debugger has detached. Valgrind regains control. We continue.");
nethercote71980f02004-01-24 18:18:54 +0000393 } else {
394 VG_(message)(Vg_UserMsg, "Apparently failed!");
395 VG_(message)(Vg_UserMsg, "");
396 }
397 }
398
399 VG_(kkill)(pid, VKI_SIGKILL);
400 VG_(waitpid)(pid, &status, 0);
401 }
402}
403
404
405/* Print some helpful-ish text about unimplemented things, and give
406 up. */
407void VG_(unimplemented) ( Char* msg )
408{
409 VG_(message)(Vg_UserMsg, "");
410 VG_(message)(Vg_UserMsg,
411 "Valgrind detected that your program requires");
412 VG_(message)(Vg_UserMsg,
413 "the following unimplemented functionality:");
414 VG_(message)(Vg_UserMsg, " %s", msg);
415 VG_(message)(Vg_UserMsg,
416 "This may be because the functionality is hard to implement,");
417 VG_(message)(Vg_UserMsg,
418 "or because no reasonable program would behave this way,");
419 VG_(message)(Vg_UserMsg,
420 "or because nobody has yet needed it. In any case, let us know at");
421 VG_(message)(Vg_UserMsg,
422 "%s and/or try to work around the problem, if you can.", VG_BUGS_TO);
423 VG_(message)(Vg_UserMsg,
424 "");
425 VG_(message)(Vg_UserMsg,
426 "Valgrind has to exit now. Sorry. Bye!");
427 VG_(message)(Vg_UserMsg,
428 "");
429 VG_(pp_sched_status)();
430 VG_(exit)(1);
431}
432
433Addr VG_(get_stack_pointer) ( void )
434{
435 return VG_(baseBlock)[VGOFF_(m_esp)];
436}
437
438/* Debugging thing .. can be called from assembly with OYNK macro. */
439void VG_(oynk) ( Int n )
440{
441 OINK(n);
442}
443
444/* Initialize the PID and PGRP of scheduler LWP; this is also called
445 in any new children after fork. */
446static void newpid(ThreadId unused)
447{
448 /* PID of scheduler LWP */
449 VG_(main_pid) = VG_(getpid)();
450 VG_(main_pgrp) = VG_(getpgrp)();
451}
452
453/*====================================================================*/
454/*=== Check we were launched by stage 1 ===*/
455/*====================================================================*/
456
457/* Look for our AUXV table */
458static void scan_auxv(void)
459{
460 const struct ume_auxv *auxv = find_auxv((int *)ume_exec_esp);
461 int found = 0;
462
463 for (; auxv->a_type != AT_NULL; auxv++)
464 switch(auxv->a_type) {
465 case AT_UME_PADFD:
466 as_setpadfd(auxv->u.a_val);
467 found |= 1;
468 break;
469
470 case AT_UME_EXECFD:
471 VG_(vgexecfd) = auxv->u.a_val;
472 found |= 2;
473 break;
474 }
475
476 if ( ! (1|2) ) {
477 fprintf(stderr, "stage2 must be launched by stage1\n");
478 exit(127);
479 }
480}
481
482
483/*====================================================================*/
484/*=== Address space determination ===*/
485/*====================================================================*/
486
487/* Pad client space so it doesn't get filled in before the right time */
488static void layout_client_space(Addr argc_addr)
489{
490 VG_(client_base) = CLIENT_BASE;
nethercotec314eba2004-07-15 12:59:41 +0000491 VG_(valgrind_base) = (addr_t)&kickstart_base;
nethercote71980f02004-01-24 18:18:54 +0000492 VG_(valgrind_end) = ROUNDUP(argc_addr, 0x10000); /* stack */
493
nethercote71980f02004-01-24 18:18:54 +0000494 as_pad((void *)VG_(client_base), (void *)VG_(valgrind_base));
495}
496
497static void layout_remaining_space(float ratio)
498{
nethercotee567e702004-07-10 17:49:17 +0000499 Int ires;
500 void* vres;
501
nethercote71980f02004-01-24 18:18:54 +0000502 /* This tries to give the client as large as possible address space while
503 * taking into account the tool's shadow needs. */
504 addr_t client_size = ROUNDDN((VG_(valgrind_base) - REDZONE_SIZE) / (1. + ratio),
505 CLIENT_SIZE_MULTIPLE);
506 addr_t shadow_size = PGROUNDUP(client_size * ratio);
507
508 VG_(client_end) = VG_(client_base) + client_size;
509 VG_(client_mapbase) = PGROUNDDN((client_size/4)*3); /* where !FIXED mmap goes */
nethercotee2097312004-06-27 12:29:56 +0000510
511 /* where !FIXED mmap goes */
512 VG_(client_mapbase) = PGROUNDDN((addr_t)(client_size * CLIENT_HEAP_PROPORTION));
nethercote71980f02004-01-24 18:18:54 +0000513
514 VG_(shadow_base) = VG_(client_end) + REDZONE_SIZE;
515 VG_(shadow_end) = VG_(shadow_base) + shadow_size;
516
nethercotee2097312004-06-27 12:29:56 +0000517#define SEGSIZE(a,b) ((VG_(b) - VG_(a))/(1024*1024))
518
nethercote71980f02004-01-24 18:18:54 +0000519 if (0)
nethercotee2097312004-06-27 12:29:56 +0000520 VG_(printf)(
521 "client_base %8x (%dMB)\n"
522 "client_mapbase %8x (%dMB)\n"
523 "client_end %8x (%dMB)\n"
524 "shadow_base %8x (%dMB)\n"
525 "shadow_end %8x (%dMB)\n"
526 "valgrind_base %8x (%dMB)\n"
nethercotee2097312004-06-27 12:29:56 +0000527 "valgrind_end %8x\n",
528 VG_(client_base), SEGSIZE(client_base, client_mapbase),
529 VG_(client_mapbase), SEGSIZE(client_mapbase, client_end),
530 VG_(client_end), SEGSIZE(client_end, shadow_base),
531 VG_(shadow_base), SEGSIZE(shadow_base, shadow_end),
532 VG_(shadow_end), SEGSIZE(shadow_end, valgrind_base),
nethercotec314eba2004-07-15 12:59:41 +0000533 VG_(valgrind_base), SEGSIZE(valgrind_base, valgrind_end),
nethercotee2097312004-06-27 12:29:56 +0000534 VG_(valgrind_end)
535 );
536
537#undef SEGSIZE
nethercote71980f02004-01-24 18:18:54 +0000538
539 // Ban redzone
nethercotee567e702004-07-10 17:49:17 +0000540 vres = mmap((void *)VG_(client_end), REDZONE_SIZE, PROT_NONE,
541 MAP_FIXED|MAP_ANON|MAP_PRIVATE, -1, 0);
542 vg_assert((void*)-1 != vres);
nethercote71980f02004-01-24 18:18:54 +0000543
544 // Make client hole
nethercotee567e702004-07-10 17:49:17 +0000545 ires = munmap((void*)VG_(client_base), client_size);
546 vg_assert(0 == ires);
nethercote71980f02004-01-24 18:18:54 +0000547
548 // Map shadow memory.
549 // Initially all inaccessible, incrementally initialized as it is used
nethercotee567e702004-07-10 17:49:17 +0000550 if (shadow_size != 0) {
551 vres = mmap((char *)VG_(shadow_base), shadow_size, PROT_NONE,
552 MAP_PRIVATE|MAP_ANON|MAP_FIXED, -1, 0);
553 vg_assert((void*)-1 != vres);
554 }
nethercote71980f02004-01-24 18:18:54 +0000555}
556
557/*====================================================================*/
558/*=== Command line setup ===*/
559/*====================================================================*/
560
561/* Nb: malloc'd memory never freed -- kept throughout like argv, envp */
562static char* get_file_clo(char* dir)
563{
564# define FLEN 512
565 Int fd, n;
566 struct stat s1;
567 char* f_clo = NULL;
568 char filename[FLEN];
569
570 snprintf(filename, FLEN, "%s/.valgrindrc", ( NULL == dir ? "" : dir ) );
571 fd = VG_(open)(filename, 0, VKI_S_IRUSR);
572 if ( fd > 0 ) {
573 if ( 0 == fstat(fd, &s1) ) {
574 f_clo = malloc(s1.st_size+1);
575 vg_assert(f_clo);
576 n = read(fd, f_clo, s1.st_size);
577 if (n == -1) n = 0;
578 f_clo[n] = '\0';
579 }
580 close(fd);
581 }
582 return f_clo;
583# undef FLEN
584}
585
nethercotee2097312004-06-27 12:29:56 +0000586#define ISSPACE(cc) ((cc) == ' ' || (cc) == '\t' || (cc) == '\n')
587
nethercote71980f02004-01-24 18:18:54 +0000588static Int count_args(char* s)
589{
590 Int n = 0;
591 if (s) {
592 char* cp = s;
593 while (True) {
594 // We have alternating sequences: blanks, non-blanks, blanks...
595 // count the non-blanks sequences.
596 while ( ISSPACE(*cp) ) cp++;
597 if ( !*cp ) break;
598 n++;
599 while ( !ISSPACE(*cp) && *cp ) cp++;
600 }
601 }
602 return n;
603}
604
605/* add args out of environment, skipping multiple spaces and -- args */
606static char** copy_args( char* s, char** to )
607{
608 if (s) {
609 char* cp = s;
610 while (True) {
611 // We have alternating sequences: blanks, non-blanks, blanks...
612 // copy the non-blanks sequences, and add terminating '\0'
613 while ( ISSPACE(*cp) ) cp++;
614 if ( !*cp ) break;
615 *to++ = cp;
616 while ( !ISSPACE(*cp) && *cp ) cp++;
617 if ( *cp ) *cp++ = '\0'; // terminate if necessary
618 if (VG_STREQ(to[-1], "--")) to--; // undo any '--' arg
619 }
620 }
621 return to;
622}
623
nethercotee2097312004-06-27 12:29:56 +0000624#undef ISSPACE
625
nethercote71980f02004-01-24 18:18:54 +0000626// Augment command line with arguments from environment and .valgrindrc
627// files.
628static void augment_command_line(Int* vg_argc_inout, char*** vg_argv_inout)
629{
630 int vg_argc = *vg_argc_inout;
631 char** vg_argv = *vg_argv_inout;
632
633 char* env_clo = getenv(VALGRINDOPTS);
634 char* f1_clo = get_file_clo( getenv("HOME") );
635 char* f2_clo = get_file_clo(".");
636
637 /* copy any extra args from file or environment, if present */
638 if ( (env_clo && *env_clo) || (f1_clo && *f1_clo) || (f2_clo && *f2_clo) ) {
639 /* ' ' separated extra options */
640 char **from;
641 char **to;
642 int env_arg_count, f1_arg_count, f2_arg_count;
643
644 env_arg_count = count_args(env_clo);
645 f1_arg_count = count_args(f1_clo);
646 f2_arg_count = count_args(f2_clo);
647
648 if (0)
649 printf("extra-argc=%d %d %d\n",
650 env_arg_count, f1_arg_count, f2_arg_count);
651
652 /* +2: +1 for null-termination, +1 for added '--' */
653 from = vg_argv;
654 vg_argv = malloc( (vg_argc + env_arg_count + f1_arg_count
655 + f2_arg_count + 2) * sizeof(char **));
nethercote7c018f42004-07-17 16:40:50 +0000656 vg_assert(vg_argv);
nethercote71980f02004-01-24 18:18:54 +0000657 to = vg_argv;
658
659 /* copy argv[0] */
660 *to++ = *from++;
661
662 /* Copy extra args from env var and file, in the order: ~/.valgrindrc,
663 * $VALGRIND_OPTS, ./.valgrindrc -- more local options are put later
664 * to override less local ones. */
665 to = copy_args(f1_clo, to);
666 to = copy_args(env_clo, to);
667 to = copy_args(f2_clo, to);
668
669 /* copy original arguments, stopping at command or -- */
670 while (*from) {
671 if (**from != '-')
672 break;
673 if (VG_STREQ(*from, "--")) {
674 from++; /* skip -- */
675 break;
676 }
677 *to++ = *from++;
678 }
679
680 /* add -- */
681 *to++ = "--";
682
683 vg_argc = to - vg_argv;
684
685 /* copy rest of original command line, then NULL */
686 while (*from) *to++ = *from++;
687 *to = NULL;
688 }
689
690 *vg_argc_inout = vg_argc;
691 *vg_argv_inout = vg_argv;
692}
693
694static void get_command_line( int argc, char** argv,
695 Int* vg_argc_out, Char*** vg_argv_out,
696 char*** cl_argv_out )
697{
698 int vg_argc;
699 char** vg_argv;
700 char** cl_argv;
701 char* env_clo = getenv(VALGRINDCLO);
702
703 if (env_clo != NULL && *env_clo != '\0') {
704 char *cp;
705 char **cpp;
706
707 /* OK, we're getting all our arguments from the environment - the
708 entire command line belongs to the client (including argv[0]) */
709 vg_argc = 1; /* argv[0] */
710 for (cp = env_clo; *cp; cp++)
711 if (*cp == '\01')
712 vg_argc++;
713
714 vg_argv = malloc(sizeof(char **) * (vg_argc + 1));
nethercote7c018f42004-07-17 16:40:50 +0000715 vg_assert(vg_argv);
nethercote71980f02004-01-24 18:18:54 +0000716
717 cpp = vg_argv;
718
719 *cpp++ = "valgrind"; /* nominal argv[0] */
720 *cpp++ = env_clo;
721
722 for (cp = env_clo; *cp; cp++) {
723 if (*cp == '\01') {
724 *cp++ = '\0'; /* chop it up in place */
725 *cpp++ = cp;
726 }
727 }
728 *cpp = NULL;
729 cl_argv = argv;
730
731 } else {
732 /* Count the arguments on the command line. */
733 vg_argv = argv;
734
735 for (vg_argc = 1; vg_argc < argc; vg_argc++) {
736 if (argv[vg_argc][0] != '-') /* exe name */
737 break;
738 if (VG_STREQ(argv[vg_argc], "--")) { /* dummy arg */
739 vg_argc++;
740 break;
741 }
742 }
743 cl_argv = &argv[vg_argc];
744
745 /* Get extra args from VALGRIND_OPTS and .valgrindrc files.
746 * Note we don't do this if getting args from VALGRINDCLO. */
747 augment_command_line(&vg_argc, &vg_argv);
748 }
749
750 if (0) {
751 Int i;
752 for (i = 0; i < vg_argc; i++)
753 printf("vg_argv[%d]=\"%s\"\n", i, vg_argv[i]);
754 }
755
756 *vg_argc_out = vg_argc;
757 *vg_argv_out = (Char**)vg_argv;
758 *cl_argv_out = cl_argv;
759}
760
761
762/*====================================================================*/
763/*=== Environment and stack setup ===*/
764/*====================================================================*/
765
766/* Scan a colon-separated list, and call a function on each element.
767 The string must be mutable, because we insert a temporary '\0', but
thughes4ad52d02004-06-27 17:37:21 +0000768 the string will end up unmodified. (*func) should return True if it
nethercote71980f02004-01-24 18:18:54 +0000769 doesn't need to see any more.
thughes4ad52d02004-06-27 17:37:21 +0000770
771 This routine will return True if (*func) returns True and False if
772 it reaches the end of the list without that happening.
nethercote71980f02004-01-24 18:18:54 +0000773*/
thughes4ad52d02004-06-27 17:37:21 +0000774static Bool scan_colsep(char *colsep, Bool (*func)(const char *))
nethercote71980f02004-01-24 18:18:54 +0000775{
776 char *cp, *entry;
777 int end;
778
779 if (colsep == NULL ||
780 *colsep == '\0')
thughes4ad52d02004-06-27 17:37:21 +0000781 return False;
nethercote71980f02004-01-24 18:18:54 +0000782
783 entry = cp = colsep;
784
785 do {
786 end = (*cp == '\0');
787
788 if (*cp == ':' || *cp == '\0') {
789 char save = *cp;
790
791 *cp = '\0';
thughes21942d92004-07-12 09:35:37 +0000792 if ((*func)(entry)) {
793 *cp = save;
thughes4ad52d02004-06-27 17:37:21 +0000794 return True;
thughes21942d92004-07-12 09:35:37 +0000795 }
nethercote71980f02004-01-24 18:18:54 +0000796 *cp = save;
797 entry = cp+1;
798 }
799 cp++;
800 } while(!end);
thughes4ad52d02004-06-27 17:37:21 +0000801
802 return False;
803}
804
805static Bool contains(const char *p) {
806 if (VG_STREQ(p, VG_(libdir))) {
807 return True;
808 }
809 return False;
nethercote71980f02004-01-24 18:18:54 +0000810}
811
812/* Prepare the client's environment. This is basically a copy of our
813 environment, except:
814 1. LD_LIBRARY_PATH=$VALGRINDLIB:$LD_LIBRARY_PATH
815 2. LD_PRELOAD=$VALGRINDLIB/vg_inject.so:($VALGRINDLIB/vgpreload_TOOL.so:)?$LD_PRELOAD
816
817 If any of these is missing, then it is added.
818
819 Yummy. String hacking in C.
820
821 If this needs to handle any more variables it should be hacked
822 into something table driven.
823 */
824static char **fix_environment(char **origenv, const char *preload)
825{
826 static const char inject_so[] = "vg_inject.so";
827 static const char ld_library_path[] = "LD_LIBRARY_PATH=";
828 static const char ld_preload[] = "LD_PRELOAD=";
829 static const char valgrind_clo[] = VALGRINDCLO "=";
830 static const int ld_library_path_len = sizeof(ld_library_path)-1;
831 static const int ld_preload_len = sizeof(ld_preload)-1;
832 static const int valgrind_clo_len = sizeof(valgrind_clo)-1;
833 int ld_preload_done = 0;
834 int ld_library_path_done = 0;
835 char *inject_path;
836 int inject_path_len;
837 int vgliblen = strlen(VG_(libdir));
838 char **cpp;
839 char **ret;
840 int envc;
841 const int preloadlen = (preload == NULL) ? 0 : strlen(preload);
842
843 /* Find the vg_inject.so; also make room for the tool preload
844 library */
845 inject_path_len = sizeof(inject_so) + vgliblen + preloadlen + 16;
846 inject_path = malloc(inject_path_len);
nethercote7c018f42004-07-17 16:40:50 +0000847 vg_assert(inject_path);
nethercote71980f02004-01-24 18:18:54 +0000848
849 if (preload)
850 snprintf(inject_path, inject_path_len, "%s/%s:%s",
851 VG_(libdir), inject_so, preload);
852 else
853 snprintf(inject_path, inject_path_len, "%s/%s",
854 VG_(libdir), inject_so);
855
856 /* Count the original size of the env */
857 envc = 0; /* trailing NULL */
858 for (cpp = origenv; cpp && *cpp; cpp++)
859 envc++;
860
861 /* Allocate a new space */
862 ret = malloc(sizeof(char *) * (envc+3+1)); /* 3 new entries + NULL */
nethercote7c018f42004-07-17 16:40:50 +0000863 vg_assert(ret);
nethercote71980f02004-01-24 18:18:54 +0000864
865 /* copy it over */
866 for (cpp = ret; *origenv; )
867 *cpp++ = *origenv++;
868 *cpp = NULL;
869
870 vg_assert(envc == (cpp - ret));
871
872 /* Walk over the new environment, mashing as we go */
873 for (cpp = ret; cpp && *cpp; cpp++) {
874 if (memcmp(*cpp, ld_library_path, ld_library_path_len) == 0) {
nethercote71980f02004-01-24 18:18:54 +0000875 /* If the LD_LIBRARY_PATH already contains libdir, then don't
876 bother adding it again, even if it isn't the first (it
877 seems that the Java runtime will keep reexecing itself
878 unless its paths are at the front of LD_LIBRARY_PATH) */
thughes4ad52d02004-06-27 17:37:21 +0000879 if (!scan_colsep(*cpp + ld_library_path_len, contains)) {
nethercote71980f02004-01-24 18:18:54 +0000880 int len = strlen(*cpp) + vgliblen*2 + 16;
881 char *cp = malloc(len);
nethercote7c018f42004-07-17 16:40:50 +0000882 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000883
884 snprintf(cp, len, "%s%s:%s",
885 ld_library_path, VG_(libdir),
886 (*cpp)+ld_library_path_len);
887
888 *cpp = cp;
889 }
890
891 ld_library_path_done = 1;
892 } else if (memcmp(*cpp, ld_preload, ld_preload_len) == 0) {
893 int len = strlen(*cpp) + inject_path_len;
894 char *cp = malloc(len);
nethercote7c018f42004-07-17 16:40:50 +0000895 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000896
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);
nethercote7c018f42004-07-17 16:40:50 +0000913 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000914
915 snprintf(cp, len, "%s%s", ld_library_path, VG_(libdir));
916
917 ret[envc++] = cp;
918 }
919
920 if (!ld_preload_done) {
921 int len = ld_preload_len + inject_path_len;
922 char *cp = malloc(len);
nethercote7c018f42004-07-17 16:40:50 +0000923 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000924
925 snprintf(cp, len, "%s%s",
926 ld_preload, inject_path);
927
928 ret[envc++] = cp;
929 }
930
931 ret[envc] = NULL;
932
933 return ret;
934}
935
936extern char **environ; /* our environment */
937//#include <error.h>
938
939/* Add a string onto the string table, and return its address */
940static char *copy_str(char **tab, const char *str)
941{
942 char *cp = *tab;
943 char *orig = cp;
944
945 while(*str)
946 *cp++ = *str++;
947 *cp++ = '\0';
948
949 if (0)
nethercotef84f6952004-07-15 14:58:33 +0000950 printf("copied %p \"%s\" len %d\n", orig, orig, cp-orig);
nethercote71980f02004-01-24 18:18:54 +0000951
952 *tab = cp;
953
954 return orig;
955}
956
957/*
958 This sets up the client's initial stack, containing the args,
959 environment and aux vector.
960
961 The format of the stack is:
962
963 higher address +-----------------+
964 | Trampoline code |
965 +-----------------+
966 | |
967 : string table :
968 | |
969 +-----------------+
970 | AT_NULL |
971 - -
972 | auxv |
973 +-----------------+
974 | NULL |
975 - -
976 | envp |
977 +-----------------+
978 | NULL |
979 - -
980 | argv |
981 +-----------------+
982 | argc |
983 lower address +-----------------+ <- esp
984 | undefined |
985 : :
986 */
987static Addr setup_client_stack(char **orig_argv, char **orig_envp,
988 const struct exeinfo *info,
989 UInt** client_auxv)
990{
nethercotee567e702004-07-10 17:49:17 +0000991 void* res;
nethercote71980f02004-01-24 18:18:54 +0000992 char **cpp;
993 char *strtab; /* string table */
994 char *stringbase;
995 addr_t *ptr;
996 struct ume_auxv *auxv;
997 const struct ume_auxv *orig_auxv;
998 const struct ume_auxv *cauxv;
999 unsigned stringsize; /* total size of strings in bytes */
1000 unsigned auxsize; /* total size of auxv in bytes */
1001 int argc; /* total argc */
1002 int envc; /* total number of env vars */
1003 unsigned stacksize; /* total client stack size */
1004 addr_t cl_esp; /* client stack base (initial esp) */
1005
1006 /* use our own auxv as a prototype */
1007 orig_auxv = find_auxv(ume_exec_esp);
1008
1009 /* ==================== compute sizes ==================== */
1010
1011 /* first of all, work out how big the client stack will be */
1012 stringsize = 0;
1013
1014 /* paste on the extra args if the loader needs them (ie, the #!
1015 interpreter and its argument) */
1016 argc = 0;
1017 if (info->argv0 != NULL) {
1018 argc++;
1019 stringsize += strlen(info->argv0) + 1;
1020 }
1021 if (info->argv1 != NULL) {
1022 argc++;
1023 stringsize += strlen(info->argv1) + 1;
1024 }
1025
1026 /* now scan the args we're given... */
1027 for (cpp = orig_argv; *cpp; cpp++) {
1028 argc++;
1029 stringsize += strlen(*cpp) + 1;
1030 }
1031
1032 /* ...and the environment */
1033 envc = 0;
1034 for (cpp = orig_envp; cpp && *cpp; cpp++) {
1035 envc++;
1036 stringsize += strlen(*cpp) + 1;
1037 }
1038
1039 /* now, how big is the auxv? */
1040 auxsize = sizeof(*auxv); /* there's always at least one entry: AT_NULL */
1041 for (cauxv = orig_auxv; cauxv->a_type != AT_NULL; cauxv++) {
1042 if (cauxv->a_type == AT_PLATFORM)
1043 stringsize += strlen(cauxv->u.a_ptr) + 1;
1044 auxsize += sizeof(*cauxv);
1045 }
1046
1047 /* OK, now we know how big the client stack is */
1048 stacksize =
1049 sizeof(int) + /* argc */
1050 sizeof(char **)*argc + /* argv */
1051 sizeof(char **) + /* terminal NULL */
1052 sizeof(char **)*envc + /* envp */
1053 sizeof(char **) + /* terminal NULL */
1054 auxsize + /* auxv */
1055 ROUNDUP(stringsize, sizeof(int)) +/* strings (aligned) */
1056 VKI_BYTES_PER_PAGE; /* page for trampoline code */
1057
nethercotef84f6952004-07-15 14:58:33 +00001058 // decide where stack goes!
1059 VG_(clstk_end) = VG_(client_end);
1060
1061 VG_(client_trampoline_code) = VG_(clstk_end) - VKI_BYTES_PER_PAGE;
1062
nethercote71980f02004-01-24 18:18:54 +00001063 /* cl_esp is the client's stack pointer */
nethercotef84f6952004-07-15 14:58:33 +00001064 cl_esp = VG_(clstk_end) - stacksize;
nethercote71980f02004-01-24 18:18:54 +00001065 cl_esp = ROUNDDN(cl_esp, 16); /* make stack 16 byte aligned */
1066
nethercote71980f02004-01-24 18:18:54 +00001067 /* base of the string table (aligned) */
1068 stringbase = strtab = (char *)(VG_(client_trampoline_code) - ROUNDUP(stringsize, sizeof(int)));
1069
1070 VG_(clstk_base) = PGROUNDDN(cl_esp);
nethercote71980f02004-01-24 18:18:54 +00001071
nethercote5ee67ca2004-06-22 14:00:09 +00001072 if (0)
1073 printf("stringsize=%d auxsize=%d stacksize=%d\n"
1074 "clstk_base %x\n"
1075 "clstk_end %x\n",
1076 stringsize, auxsize, stacksize, VG_(clstk_base), VG_(clstk_end));
1077
1078
nethercote71980f02004-01-24 18:18:54 +00001079 /* ==================== allocate space ==================== */
1080
1081 /* allocate a stack - mmap enough space for the stack */
nethercotef84f6952004-07-15 14:58:33 +00001082 res = mmap((void *)PGROUNDDN(cl_esp), VG_(clstk_end) - PGROUNDDN(cl_esp),
nethercotee567e702004-07-10 17:49:17 +00001083 PROT_READ | PROT_WRITE | PROT_EXEC,
1084 MAP_PRIVATE | MAP_ANON | MAP_FIXED, -1, 0);
1085 vg_assert((void*)-1 != res);
nethercote71980f02004-01-24 18:18:54 +00001086
1087 /* ==================== copy client stack ==================== */
1088
1089 ptr = (addr_t *)cl_esp;
1090
1091 /* --- argc --- */
1092 *ptr++ = argc; /* client argc */
1093
1094 /* --- argv --- */
1095 if (info->argv0) {
1096 *ptr++ = (addr_t)copy_str(&strtab, info->argv0);
1097 free(info->argv0);
1098 }
1099 if (info->argv1) {
1100 *ptr++ = (addr_t)copy_str(&strtab, info->argv1);
1101 free(info->argv1);
1102 }
1103 for (cpp = orig_argv; *cpp; ptr++, cpp++) {
1104 *ptr = (addr_t)copy_str(&strtab, *cpp);
1105 }
1106 *ptr++ = 0;
1107
1108 /* --- envp --- */
1109 VG_(client_envp) = (Char **)ptr;
1110 for (cpp = orig_envp; cpp && *cpp; ptr++, cpp++)
1111 *ptr = (addr_t)copy_str(&strtab, *cpp);
1112 *ptr++ = 0;
1113
1114 /* --- auxv --- */
1115 auxv = (struct ume_auxv *)ptr;
1116 *client_auxv = (UInt *)auxv;
1117
1118 for (; orig_auxv->a_type != AT_NULL; auxv++, orig_auxv++) {
1119 /* copy the entry... */
1120 *auxv = *orig_auxv;
1121
1122 /* ...and fix up the copy */
1123 switch(auxv->a_type) {
1124 case AT_PHDR:
1125 if (info->phdr == 0)
1126 auxv->a_type = AT_IGNORE;
1127 else
1128 auxv->u.a_val = info->phdr;
1129 break;
1130
1131 case AT_PHNUM:
1132 if (info->phdr == 0)
1133 auxv->a_type = AT_IGNORE;
1134 else
1135 auxv->u.a_val = info->phnum;
1136 break;
1137
1138 case AT_BASE:
1139 if (info->interp_base == 0)
1140 auxv->a_type = AT_IGNORE;
1141 else
1142 auxv->u.a_val = info->interp_base;
1143 break;
1144
1145 case AT_PLATFORM: /* points to a platform description string */
1146 auxv->u.a_ptr = copy_str(&strtab, orig_auxv->u.a_ptr);
1147 break;
1148
1149 case AT_ENTRY:
1150 auxv->u.a_val = info->entry;
1151 break;
1152
1153 case AT_IGNORE:
1154 case AT_EXECFD:
1155 case AT_PHENT:
1156 case AT_PAGESZ:
1157 case AT_FLAGS:
1158 case AT_NOTELF:
1159 case AT_UID:
1160 case AT_EUID:
1161 case AT_GID:
1162 case AT_EGID:
1163 case AT_CLKTCK:
1164 case AT_HWCAP:
1165 case AT_FPUCW:
1166 case AT_DCACHEBSIZE:
1167 case AT_ICACHEBSIZE:
1168 case AT_UCACHEBSIZE:
1169 /* All these are pointerless, so we don't need to do anything
1170 about them. */
1171 break;
1172
1173 case AT_SECURE:
1174 /* If this is 1, then it means that this program is running
1175 suid, and therefore the dynamic linker should be careful
1176 about LD_PRELOAD, etc. However, since stage1 (the thing
1177 the kernel actually execve's) should never be SUID, and we
1178 need LD_PRELOAD/LD_LIBRARY_PATH to work for the client, we
1179 set AT_SECURE to 0. */
1180 auxv->u.a_val = 0;
1181 break;
1182
1183 case AT_SYSINFO:
1184 /* Leave this unmolested for now, but we'll update it later
1185 when we set up the client trampoline code page */
1186 break;
1187
1188 case AT_SYSINFO_EHDR:
1189 /* Trash this, because we don't reproduce it */
1190 auxv->a_type = AT_IGNORE;
1191 break;
1192
1193 default:
1194 /* stomp out anything we don't know about */
1195 if (0)
1196 printf("stomping auxv entry %d\n", auxv->a_type);
1197 auxv->a_type = AT_IGNORE;
1198 break;
1199
1200 }
1201 }
1202 *auxv = *orig_auxv;
1203 vg_assert(auxv->a_type == AT_NULL);
1204
nethercotef84f6952004-07-15 14:58:33 +00001205 /* --- trampoline page --- */
1206 VG_(memcpy)( (void *)VG_(client_trampoline_code),
1207 &VG_(trampoline_code_start), VG_(trampoline_code_length) );
1208
nethercote71980f02004-01-24 18:18:54 +00001209 vg_assert((strtab-stringbase) == stringsize);
1210
nethercote5ee67ca2004-06-22 14:00:09 +00001211 /* We know the initial ESP is pointing at argc/argv */
1212 VG_(client_argc) = *(Int*)cl_esp;
1213 VG_(client_argv) = (Char**)(cl_esp + sizeof(Int));
1214
nethercote71980f02004-01-24 18:18:54 +00001215 return cl_esp;
1216}
1217
1218/*====================================================================*/
1219/*=== Find executable ===*/
1220/*====================================================================*/
1221
thughes4ad52d02004-06-27 17:37:21 +00001222static const char* executable_name;
1223
1224static Bool match_executable(const char *entry) {
1225 char buf[strlen(entry) + strlen(executable_name) + 2];
1226
1227 /* empty PATH element means . */
1228 if (*entry == '\0')
1229 entry = ".";
1230
1231 snprintf(buf, sizeof(buf), "%s/%s", entry, executable_name);
1232
1233 if (access(buf, R_OK|X_OK) == 0) {
1234 executable_name = strdup(buf);
1235 vg_assert(NULL != executable_name);
1236 return True;
1237 }
1238 return False;
1239}
1240
nethercote71980f02004-01-24 18:18:54 +00001241static const char* find_executable(const char* exec)
1242{
1243 vg_assert(NULL != exec);
thughes4ad52d02004-06-27 17:37:21 +00001244 executable_name = exec;
1245 if (strchr(executable_name, '/') == NULL) {
nethercote71980f02004-01-24 18:18:54 +00001246 /* no '/' - we need to search the path */
1247 char *path = getenv("PATH");
thughes4ad52d02004-06-27 17:37:21 +00001248 scan_colsep(path, match_executable);
nethercote71980f02004-01-24 18:18:54 +00001249 }
thughes4ad52d02004-06-27 17:37:21 +00001250 return executable_name;
nethercote71980f02004-01-24 18:18:54 +00001251}
1252
1253
1254/*====================================================================*/
1255/*=== Loading tools ===*/
1256/*====================================================================*/
1257
1258static void list_tools(void)
1259{
1260 DIR *dir = opendir(VG_(libdir));
1261 struct dirent *de;
1262 int first = 1;
1263
1264 if (dir == NULL) {
1265 fprintf(stderr, "Can't open %s: %s (installation problem?)\n",
nethercotef4928da2004-06-15 10:54:40 +00001266 VG_(libdir), strerror(errno));
nethercote71980f02004-01-24 18:18:54 +00001267 return;
1268 }
1269
nethercotef4928da2004-06-15 10:54:40 +00001270 while ((de = readdir(dir)) != NULL) {
nethercote71980f02004-01-24 18:18:54 +00001271 int len = strlen(de->d_name);
1272
1273 /* look for vgskin_TOOL.so names */
1274 if (len > (7+1+3) && /* "vgskin_" + at least 1-char toolname + ".so" */
nethercotef4928da2004-06-15 10:54:40 +00001275 strncmp(de->d_name, "vgskin_", 7) == 0 &&
1276 VG_STREQ(de->d_name + len - 3, ".so")) {
1277 if (first) {
1278 fprintf(stderr, "Available tools:\n");
1279 first = 0;
1280 }
1281 de->d_name[len-3] = '\0';
1282 fprintf(stderr, "\t%s\n", de->d_name+7);
nethercote71980f02004-01-24 18:18:54 +00001283 }
1284 }
1285
1286 closedir(dir);
1287
1288 if (first)
nethercotef4928da2004-06-15 10:54:40 +00001289 fprintf(stderr, "No tools available in \"%s\" (installation problem?)\n",
1290 VG_(libdir));
nethercote71980f02004-01-24 18:18:54 +00001291}
1292
1293
1294/* Find and load a tool, and check it looks ok. Also looks to see if there's
1295 * a matching vgpreload_*.so file, and returns its name in *preloadpath. */
1296static void load_tool( const char *toolname, void** handle_out,
1297 ToolInfo** toolinfo_out, char **preloadpath_out )
1298{
1299 Bool ok;
1300 int len = strlen(VG_(libdir)) + strlen(toolname)*2 + 16;
1301 char buf[len];
1302 void* handle;
1303 ToolInfo* toolinfo;
1304 char* preloadpath = NULL;
1305 Int* vg_malloc_redzonep;
1306
1307 // XXX: allowing full paths for --tool option -- does it make sense?
1308 // Doesn't allow for vgpreload_<tool>.so.
1309
1310 if (strchr(toolname, '/') != 0) {
1311 /* toolname contains '/', and so must be a pathname */
1312 handle = dlopen(toolname, RTLD_NOW);
1313 } else {
1314 /* just try in the libdir */
1315 snprintf(buf, len, "%s/vgskin_%s.so", VG_(libdir), toolname);
1316 handle = dlopen(buf, RTLD_NOW);
1317
1318 if (handle != NULL) {
1319 snprintf(buf, len, "%s/vgpreload_%s.so", VG_(libdir), toolname);
1320 if (access(buf, R_OK) == 0) {
1321 preloadpath = strdup(buf);
1322 vg_assert(NULL != preloadpath);
1323 }
1324 }
1325 }
1326
1327 ok = (NULL != handle);
1328 if (!ok) {
1329 fprintf(stderr, "Can't open tool \"%s\": %s\n", toolname, dlerror());
1330 goto bad_load;
1331 }
1332
1333 toolinfo = dlsym(handle, "vgSkin_tool_info");
1334 ok = (NULL != toolinfo);
1335 if (!ok) {
1336 fprintf(stderr, "Tool \"%s\" doesn't define SK_(tool_info) - "
1337 "add VG_DETERMINE_INTERFACE_VERSION?\n", toolname);
1338 goto bad_load;
1339 }
1340
1341 ok = (toolinfo->sizeof_ToolInfo == sizeof(*toolinfo) &&
1342 toolinfo->interface_major_version == VG_CORE_INTERFACE_MAJOR_VERSION &&
1343 toolinfo->sk_pre_clo_init != NULL);
1344 if (!ok) {
1345 fprintf(stderr, "Error:\n"
1346 " Tool and core interface versions do not match.\n"
1347 " Interface version used by core is: %d.%d (size %d)\n"
1348 " Interface version used by tool is: %d.%d (size %d)\n"
1349 " The major version numbers must match.\n",
1350 VG_CORE_INTERFACE_MAJOR_VERSION,
1351 VG_CORE_INTERFACE_MINOR_VERSION,
1352 sizeof(*toolinfo),
1353 toolinfo->interface_major_version,
1354 toolinfo->interface_minor_version,
1355 toolinfo->sizeof_ToolInfo);
1356 fprintf(stderr, " You need to at least recompile, and possibly update,\n");
1357 if (VG_CORE_INTERFACE_MAJOR_VERSION > toolinfo->interface_major_version)
1358 fprintf(stderr, " your skin to work with this version of Valgrind.\n");
1359 else
1360 fprintf(stderr, " your version of Valgrind to work with this skin.\n");
1361 goto bad_load;
1362 }
1363
1364 // Set redzone size for V's allocator
1365 vg_malloc_redzonep = dlsym(handle, STR(VG_(vg_malloc_redzone_szB)));
1366 if ( NULL != vg_malloc_redzonep ) {
1367 VG_(vg_malloc_redzone_szB) = *vg_malloc_redzonep;
1368 }
1369
1370 vg_assert(NULL != handle && NULL != toolinfo);
1371 *handle_out = handle;
1372 *toolinfo_out = toolinfo;
1373 *preloadpath_out = preloadpath;
1374 return;
1375
1376
1377 bad_load:
1378 if (handle != NULL)
1379 dlclose(handle);
1380
nethercotef4928da2004-06-15 10:54:40 +00001381 fprintf(stderr, "valgrind: couldn't load tool\n");
nethercote71980f02004-01-24 18:18:54 +00001382 list_tools();
1383 exit(127);
1384}
1385
nethercotef4928da2004-06-15 10:54:40 +00001386
1387/*====================================================================*/
1388/*=== Command line errors ===*/
1389/*====================================================================*/
1390
1391static void abort_msg ( void )
1392{
nethercotef8548672004-06-21 12:42:35 +00001393 VG_(clo_log_to) = VgLogTo_Fd;
1394 VG_(clo_log_fd) = 2; /* stderr */
nethercotef4928da2004-06-15 10:54:40 +00001395}
1396
1397void VG_(bad_option) ( Char* opt )
1398{
1399 abort_msg();
1400 VG_(printf)("valgrind: Bad option `%s'; aborting.\n", opt);
1401 VG_(printf)("valgrind: Use --help for more information.\n");
1402 VG_(exit)(1);
1403}
1404
1405static void missing_tool_option ( void )
1406{
1407 abort_msg();
1408 VG_(printf)("valgrind: Missing --tool option\n");
1409 list_tools();
1410 VG_(printf)("valgrind: Use --help for more information.\n");
1411 VG_(exit)(1);
1412}
1413
1414static void missing_prog ( void )
1415{
1416 abort_msg();
1417 VG_(printf)("valgrind: no program specified\n");
1418 VG_(printf)("valgrind: Use --help for more information.\n");
1419 VG_(exit)(1);
1420}
1421
1422static void config_error ( Char* msg )
1423{
1424 abort_msg();
1425 VG_(printf)("valgrind: Startup or configuration error:\n %s\n", msg);
1426 VG_(printf)("valgrind: Unable to start up properly. Giving up.\n");
1427 VG_(exit)(1);
1428}
1429
1430
nethercote71980f02004-01-24 18:18:54 +00001431/*====================================================================*/
1432/*=== Loading the client ===*/
1433/*====================================================================*/
1434
nethercotef4928da2004-06-15 10:54:40 +00001435static void load_client(char* cl_argv[], const char* exec, Int need_help,
nethercote71980f02004-01-24 18:18:54 +00001436 /*out*/struct exeinfo* info, /*out*/Addr* client_eip)
1437{
1438 // If they didn't specify an executable with --exec, and didn't specify
1439 // --help, then use client argv[0] (searching $PATH if necessary).
nethercotef4928da2004-06-15 10:54:40 +00001440 if (NULL == exec && !need_help) {
nethercote71980f02004-01-24 18:18:54 +00001441 if (cl_argv[0] == NULL ||
1442 ( NULL == (exec = find_executable(cl_argv[0])) ) )
1443 {
nethercotef4928da2004-06-15 10:54:40 +00001444 missing_prog();
nethercote71980f02004-01-24 18:18:54 +00001445 }
1446 }
1447
1448 info->map_base = VG_(client_mapbase);
nethercote71980f02004-01-24 18:18:54 +00001449
1450 info->exe_base = VG_(client_base);
1451 info->exe_end = VG_(client_end);
1452 info->argv = cl_argv;
1453
nethercotef4928da2004-06-15 10:54:40 +00001454 if (need_help) {
nethercote71980f02004-01-24 18:18:54 +00001455 VG_(clexecfd) = -1;
1456 info->argv0 = NULL;
1457 info->argv1 = NULL;
1458 } else {
1459 Int ret;
1460 VG_(clexecfd) = VG_(open)(exec, O_RDONLY, VKI_S_IRUSR);
1461 ret = do_exec(exec, info);
1462 if (ret != 0) {
nethercotef4928da2004-06-15 10:54:40 +00001463 fprintf(stderr, "valgrind: do_exec(%s) failed: %s\n", exec, strerror(ret));
nethercote71980f02004-01-24 18:18:54 +00001464 exit(127);
1465 }
1466 }
1467
1468 /* Copy necessary bits of 'info' that were filled in */
1469 *client_eip = info->init_eip;
1470 VG_(brk_base) = VG_(brk_limit) = info->brkbase;
1471}
1472
1473
1474/*====================================================================*/
1475/*=== Command-line: variables, processing ===*/
1476/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +00001477
njn25e49d8e72002-09-23 09:36:25 +00001478/* Define, and set defaults. */
1479Bool VG_(clo_error_limit) = True;
nethercote04d0fbc2004-01-26 16:48:06 +00001480Bool VG_(clo_db_attach) = False;
1481Char* VG_(clo_db_command) = VG_CLO_DEFAULT_DBCOMMAND;
njn43c799e2003-04-08 00:08:52 +00001482Bool VG_(clo_gen_suppressions) = False;
nethercote27fec902004-06-16 21:26:32 +00001483Int VG_(clo_sanity_level) = 1;
njn25e49d8e72002-09-23 09:36:25 +00001484Int VG_(clo_verbosity) = 1;
1485Bool VG_(clo_demangle) = True;
njn25e49d8e72002-09-23 09:36:25 +00001486Bool VG_(clo_trace_children) = False;
sewardj4cf05692002-10-27 20:28:29 +00001487
nethercotee1730692003-11-20 10:38:07 +00001488/* See big comment in vg_include.h for meaning of these three.
1489 fd is initially stdout, for --help, but gets moved to stderr by default
1490 immediately afterwards. */
sewardj4cf05692002-10-27 20:28:29 +00001491VgLogTo VG_(clo_log_to) = VgLogTo_Fd;
nethercotef8548672004-06-21 12:42:35 +00001492Int VG_(clo_log_fd) = 1;
1493Char* VG_(clo_log_name) = NULL;
sewardj4cf05692002-10-27 20:28:29 +00001494
sewardj6024b212003-07-13 10:54:33 +00001495Int VG_(clo_input_fd) = 0; /* stdin */
njn25e49d8e72002-09-23 09:36:25 +00001496Int VG_(clo_n_suppressions) = 0;
sewardjde4a1d02002-03-22 01:27:54 +00001497Char* VG_(clo_suppressions)[VG_CLO_MAX_SFILES];
njn25e49d8e72002-09-23 09:36:25 +00001498Bool VG_(clo_profile) = False;
1499Bool VG_(clo_single_step) = False;
1500Bool VG_(clo_optimise) = True;
1501UChar VG_(clo_trace_codegen) = 0; // 00000000b
1502Bool VG_(clo_trace_syscalls) = False;
1503Bool VG_(clo_trace_signals) = False;
1504Bool VG_(clo_trace_symtab) = False;
njn25e49d8e72002-09-23 09:36:25 +00001505Bool VG_(clo_trace_sched) = False;
1506Int VG_(clo_trace_pthread_level) = 0;
njn25e49d8e72002-09-23 09:36:25 +00001507Int VG_(clo_dump_error) = 0;
1508Int VG_(clo_backtrace_size) = 4;
1509Char* VG_(clo_weird_hacks) = NULL;
sewardj858964b2002-10-05 14:15:43 +00001510Bool VG_(clo_run_libc_freeres) = True;
rjwalshf5f536f2003-11-17 17:45:00 +00001511Bool VG_(clo_track_fds) = False;
sewardj22854b92002-11-30 14:00:47 +00001512Bool VG_(clo_chain_bb) = True;
nethercote77eba602003-11-13 17:35:04 +00001513Bool VG_(clo_show_below_main) = False;
fitzhardinge98abfc72003-12-16 02:05:15 +00001514Bool VG_(clo_pointercheck) = True;
fitzhardinge462f4f92003-12-18 02:10:54 +00001515Bool VG_(clo_branchpred) = False;
sewardj2370f3b2002-11-30 15:01:01 +00001516
jsgf855d93d2003-10-13 22:26:55 +00001517static Bool VG_(clo_wait_for_gdb) = False;
1518
1519/* If we're doing signal routing, poll for signals every 50mS by
1520 default. */
1521Int VG_(clo_signal_polltime) = 50;
1522
1523/* These flags reduce thread wakeup latency on syscall completion and
1524 signal delivery, respectively. The downside is possible unfairness. */
1525Bool VG_(clo_lowlat_syscalls) = False; /* low-latency syscalls */
1526Bool VG_(clo_lowlat_signals) = False; /* low-latency signals */
1527
sewardjde4a1d02002-03-22 01:27:54 +00001528
nethercote6c999f22004-01-31 22:55:15 +00001529void usage ( Bool debug_help )
njn7cf0bd32002-06-08 13:36:03 +00001530{
njn25e49d8e72002-09-23 09:36:25 +00001531 Char* usage1 =
nethercote71980f02004-01-24 18:18:54 +00001532"usage: valgrind --tool=<toolname> [options] prog-and-args\n"
njn25e49d8e72002-09-23 09:36:25 +00001533"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001534" common user options for all Valgrind tools, with defaults in [ ]:\n"
nethercote0d588502004-06-21 13:27:11 +00001535" --tool=<name> use the Valgrind tool named <name>\n"
nethercotea76368b2004-06-16 11:56:29 +00001536" -h --help show this message\n"
nethercote6c999f22004-01-31 22:55:15 +00001537" --help-debug show this message, plus debugging options\n"
njn25e49d8e72002-09-23 09:36:25 +00001538" --version show version\n"
njn25e49d8e72002-09-23 09:36:25 +00001539" -q --quiet run silently; only print error msgs\n"
1540" -v --verbose be more verbose, incl counts of errors\n"
nethercote77eba602003-11-13 17:35:04 +00001541" --trace-children=no|yes Valgrind-ise child processes? [no]\n"
nethercote0d588502004-06-21 13:27:11 +00001542" --track-fds=no|yes track open file descriptors? [no]\n"
nethercote2b0793f2003-12-02 10:41:18 +00001543"\n"
1544" uncommon user options for all Valgrind tools:\n"
nethercote0d588502004-06-21 13:27:11 +00001545" --run-libc-freeres=no|yes free up glibc memory at exit? [yes]\n"
1546" --weird-hacks=hack1,hack2,... recognised hacks: lax-ioctls [none]\n"
1547" --signal-polltime=<time> signal poll period (mS) for older kernels [50]\n"
1548" --lowlat-signals=no|yes improve thread signal wake-up latency [no]\n"
1549" --lowlat-syscalls=no|yes improve thread syscall wake-up latency [no]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001550" --pointercheck=no|yes enforce client address space limits [yes]\n"
njn25e49d8e72002-09-23 09:36:25 +00001551"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001552" user options for Valgrind tools that report errors:\n"
nethercotef8548672004-06-21 12:42:35 +00001553" --log-fd=<number> log messages to file descriptor [2=stderr]\n"
1554" --log-file=<file> log messages to <file>.pid<pid>\n"
1555" --log-socket=ipaddr:port log messages to socket ipaddr:port\n"
nethercote2b0793f2003-12-02 10:41:18 +00001556" --demangle=no|yes automatically demangle C++ names? [yes]\n"
1557" --num-callers=<number> show <num> callers in stack traces [4]\n"
1558" --error-limit=no|yes stop showing new errors if too many? [yes]\n"
1559" --show-below-main=no|yes continue stack traces below main() [no]\n"
1560" --suppressions=<filename> suppress errors described in <filename>\n"
1561" --gen-suppressions=no|yes print suppressions for errors detected [no]\n"
nethercote04d0fbc2004-01-26 16:48:06 +00001562" --db-attach=no|yes start debugger when errors detected? [no]\n"
1563" --db-command=<command> command to start debugger [gdb -nw %%f %%p]\n"
1564" --input-fd=<number> file descriptor for input [0=stdin]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001565"\n";
njn7cf0bd32002-06-08 13:36:03 +00001566
njn25e49d8e72002-09-23 09:36:25 +00001567 Char* usage2 =
1568"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001569" debugging options for all Valgrind tools:\n"
njn25e49d8e72002-09-23 09:36:25 +00001570" --sanity-level=<number> level of sanity checking to do [1]\n"
1571" --single-step=no|yes translate each instr separately? [no]\n"
1572" --optimise=no|yes improve intermediate code? [yes]\n"
nethercote137bc552003-11-14 17:47:54 +00001573" --profile=no|yes profile? (tool must be built for it) [no]\n"
sewardj22854b92002-11-30 14:00:47 +00001574" --chain-bb=no|yes do basic-block chaining? [yes]\n"
fitzhardinge462f4f92003-12-18 02:10:54 +00001575" --branchpred=yes|no generate branch prediction hints [no]\n"
njn25e49d8e72002-09-23 09:36:25 +00001576" --trace-codegen=<XXXXX> show generated code? (X = 0|1) [00000]\n"
1577" --trace-syscalls=no|yes show all system calls? [no]\n"
1578" --trace-signals=no|yes show signal handling details? [no]\n"
1579" --trace-symtab=no|yes show symbol table details? [no]\n"
njn25e49d8e72002-09-23 09:36:25 +00001580" --trace-sched=no|yes show thread scheduler details? [no]\n"
njn3e884182003-04-15 13:03:23 +00001581" --trace-pthread=none|some|all show pthread event details? [none]\n"
jsgf855d93d2003-10-13 22:26:55 +00001582" --wait-for-gdb=yes|no pause on startup to wait for gdb attach\n"
njn25e49d8e72002-09-23 09:36:25 +00001583"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001584" debugging options for Valgrind tools that report errors\n"
1585" --dump-error=<number> show translation for basic block associated\n"
1586" with <number>'th error context [0=show none]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001587"\n";
njn3e884182003-04-15 13:03:23 +00001588
1589 Char* usage3 =
1590"\n"
nethercote71980f02004-01-24 18:18:54 +00001591" Extra options read from ~/.valgrindrc, $VALGRIND_OPTS, ./.valgrindrc\n"
njn25e49d8e72002-09-23 09:36:25 +00001592"\n"
nethercote08fa9a72004-07-16 17:44:00 +00001593" Valgrind is Copyright (C) 2000-2004 Julian Seward et al.\n"
njn25e49d8e72002-09-23 09:36:25 +00001594" and licensed under the GNU General Public License, version 2.\n"
1595" Bug reports, feedback, admiration, abuse, etc, to: %s.\n"
njnd04b7c62002-10-03 14:05:52 +00001596"\n"
nethercote137bc552003-11-14 17:47:54 +00001597" Tools are copyright and licensed by their authors. See each\n"
1598" tool's start-up message for more information.\n"
njn25e49d8e72002-09-23 09:36:25 +00001599"\n";
njn7cf0bd32002-06-08 13:36:03 +00001600
fitzhardinge98abfc72003-12-16 02:05:15 +00001601 VG_(printf)(usage1);
1602 if (VG_(details).name) {
1603 VG_(printf)(" user options for %s:\n", VG_(details).name);
fitzhardinge98abfc72003-12-16 02:05:15 +00001604 if (VG_(needs).command_line_options)
1605 SK_(print_usage)();
1606 else
1607 VG_(printf)(" (none)\n");
1608 }
nethercote6c999f22004-01-31 22:55:15 +00001609 if (debug_help) {
1610 VG_(printf)(usage2);
fitzhardinge98abfc72003-12-16 02:05:15 +00001611
nethercote6c999f22004-01-31 22:55:15 +00001612 if (VG_(details).name) {
1613 VG_(printf)(" debugging options for %s:\n", VG_(details).name);
1614
1615 if (VG_(needs).command_line_options)
1616 SK_(print_debug_usage)();
1617 else
1618 VG_(printf)(" (none)\n");
1619 }
fitzhardinge98abfc72003-12-16 02:05:15 +00001620 }
nethercote421281e2003-11-20 16:20:55 +00001621 VG_(printf)(usage3, VG_BUGS_TO);
nethercotef4928da2004-06-15 10:54:40 +00001622 VG_(exit)(0);
njn7cf0bd32002-06-08 13:36:03 +00001623}
sewardjde4a1d02002-03-22 01:27:54 +00001624
nethercote71980f02004-01-24 18:18:54 +00001625static void pre_process_cmd_line_options
nethercote6c999f22004-01-31 22:55:15 +00001626 ( Int* need_help, const char** tool, const char** exec )
sewardj1c1b1162003-02-23 01:25:51 +00001627{
nethercote71980f02004-01-24 18:18:54 +00001628 UInt i;
sewardjde4a1d02002-03-22 01:27:54 +00001629
nethercote71980f02004-01-24 18:18:54 +00001630 /* parse the options we have (only the options we care about now) */
1631 for (i = 1; i < VG_(vg_argc); i++) {
1632
1633 if (strcmp(VG_(vg_argv)[i], "--version") == 0) {
1634 printf("valgrind-" VERSION "\n");
nethercotef4928da2004-06-15 10:54:40 +00001635 exit(0);
nethercote71980f02004-01-24 18:18:54 +00001636
nethercotea76368b2004-06-16 11:56:29 +00001637 } else if (VG_CLO_STREQ(VG_(vg_argv)[i], "--help") ||
1638 VG_CLO_STREQ(VG_(vg_argv)[i], "-h")) {
nethercote6c999f22004-01-31 22:55:15 +00001639 *need_help = 1;
1640
nethercotef4928da2004-06-15 10:54:40 +00001641 } else if (VG_CLO_STREQ(VG_(vg_argv)[i], "--help-debug")) {
nethercote6c999f22004-01-31 22:55:15 +00001642 *need_help = 2;
nethercote71980f02004-01-24 18:18:54 +00001643
nethercotef4928da2004-06-15 10:54:40 +00001644 } else if (VG_CLO_STREQN(7, VG_(vg_argv)[i], "--tool=") ||
1645 VG_CLO_STREQN(7, VG_(vg_argv)[i], "--skin=")) {
nethercote71980f02004-01-24 18:18:54 +00001646 *tool = &VG_(vg_argv)[i][7];
1647
nethercotef4928da2004-06-15 10:54:40 +00001648 } else if (VG_CLO_STREQN(7, VG_(vg_argv)[i], "--exec=")) {
nethercote71980f02004-01-24 18:18:54 +00001649 *exec = &VG_(vg_argv)[i][7];
1650 }
1651 }
1652
nethercotef4928da2004-06-15 10:54:40 +00001653 /* If no tool specified, can act appropriately without loading tool */
nethercote71980f02004-01-24 18:18:54 +00001654 if (*tool == NULL) {
nethercotef4928da2004-06-15 10:54:40 +00001655 if (0 == *need_help) {
1656 // neither --tool nor --help/--help-debug specified
1657 missing_tool_option();
1658 } else {
1659 // Give help message, without any tool-specific help
1660 usage(/*help-debug?*/2 == *need_help);
1661 }
nethercote71980f02004-01-24 18:18:54 +00001662 }
1663}
1664
nethercote5ee67ca2004-06-22 14:00:09 +00001665static void process_cmd_line_options( UInt* client_auxv, const char* toolname )
nethercote71980f02004-01-24 18:18:54 +00001666{
nethercotef8548672004-06-21 12:42:35 +00001667 Int i, eventually_log_fd;
nethercote71980f02004-01-24 18:18:54 +00001668 Int *auxp;
1669 Int toolname_len = VG_(strlen)(toolname);
sewardjde4a1d02002-03-22 01:27:54 +00001670
nethercotee1730692003-11-20 10:38:07 +00001671 /* log to stderr by default, but usage message goes to stdout */
nethercotef8548672004-06-21 12:42:35 +00001672 eventually_log_fd = 2;
sewardjde4a1d02002-03-22 01:27:54 +00001673
sewardj19d81412002-06-03 01:10:40 +00001674 /* Check for sane path in ./configure --prefix=... */
fitzhardinge98abfc72003-12-16 02:05:15 +00001675 if (VG_LIBDIR[0] != '/')
sewardj19d81412002-06-03 01:10:40 +00001676 config_error("Please use absolute paths in "
1677 "./configure --prefix=... or --libdir=...");
sewardj38170912002-05-10 21:07:22 +00001678
nethercote71980f02004-01-24 18:18:54 +00001679 for (auxp = client_auxv; auxp[0] != VKI_AT_NULL; auxp += 2) {
fitzhardinge98abfc72003-12-16 02:05:15 +00001680 switch(auxp[0]) {
1681 case VKI_AT_SYSINFO:
1682 VG_(sysinfo_page_exists) = True;
fitzhardinge92360792003-12-24 10:11:11 +00001683 auxp[1] = (Int)(VG_(client_trampoline_code) + VG_(tramp_syscall_offset));
fitzhardinge98abfc72003-12-16 02:05:15 +00001684 VG_(sysinfo_page_addr) = auxp[1];
1685 break;
sewardjde4a1d02002-03-22 01:27:54 +00001686 }
fitzhardinge98abfc72003-12-16 02:05:15 +00001687 }
sewardjde4a1d02002-03-22 01:27:54 +00001688
nethercote71980f02004-01-24 18:18:54 +00001689 for (i = 1; i < VG_(vg_argc); i++) {
1690
1691 Char* arg = VG_(vg_argv)[i];
1692
1693 // XXX: allow colons in options, for Josef
1694
1695 /* Look for matching "--toolname:foo" */
1696 if (VG_(strstr)(arg, ":")) {
1697 if (VG_CLO_STREQN(2, arg, "--") &&
1698 VG_CLO_STREQN(toolname_len, arg+2, toolname) &&
1699 VG_CLO_STREQN(1, arg+2+toolname_len, ":"))
1700 {
1701 // prefix matches, convert "--toolname:foo" to "--foo"
1702 if (0)
1703 VG_(printf)("tool-specific arg: %s\n", arg);
1704 arg += toolname_len + 1;
1705 arg[0] = '-';
1706 arg[1] = '-';
1707
1708 } else {
1709 // prefix doesn't match, skip to next arg
1710 continue;
1711 }
1712 }
1713
fitzhardinge98abfc72003-12-16 02:05:15 +00001714 /* Ignore these options - they've already been handled */
nethercote71980f02004-01-24 18:18:54 +00001715 if (VG_CLO_STREQN(7, arg, "--tool=") ||
1716 VG_CLO_STREQN(7, arg, "--skin="))
fitzhardinge98abfc72003-12-16 02:05:15 +00001717 continue;
nethercote71980f02004-01-24 18:18:54 +00001718 if (VG_CLO_STREQN(7, arg, "--exec="))
fitzhardinge98abfc72003-12-16 02:05:15 +00001719 continue;
1720
nethercote71980f02004-01-24 18:18:54 +00001721 if ( VG_CLO_STREQ(arg, "--"))
fitzhardinge98abfc72003-12-16 02:05:15 +00001722 continue;
nethercote27fec902004-06-16 21:26:32 +00001723
nethercote71980f02004-01-24 18:18:54 +00001724 else if (VG_CLO_STREQ(arg, "-v") ||
1725 VG_CLO_STREQ(arg, "--verbose"))
sewardjde4a1d02002-03-22 01:27:54 +00001726 VG_(clo_verbosity)++;
nethercote27fec902004-06-16 21:26:32 +00001727
nethercote71980f02004-01-24 18:18:54 +00001728 else if (VG_CLO_STREQ(arg, "-q") ||
1729 VG_CLO_STREQ(arg, "--quiet"))
sewardjde4a1d02002-03-22 01:27:54 +00001730 VG_(clo_verbosity)--;
1731
nethercote27fec902004-06-16 21:26:32 +00001732 else VG_BOOL_CLO("--branchpred", VG_(clo_branchpred))
1733 else VG_BOOL_CLO("--chain-bb", VG_(clo_chain_bb))
1734 else VG_BOOL_CLO("--db-attach", VG_(clo_db_attach))
1735 else VG_BOOL_CLO("--demangle", VG_(clo_demangle))
1736 else VG_BOOL_CLO("--error-limit", VG_(clo_error_limit))
1737 else VG_BOOL_CLO("--gen-suppressions", VG_(clo_gen_suppressions))
1738 else VG_BOOL_CLO("--lowlat-signals", VG_(clo_lowlat_signals))
1739 else VG_BOOL_CLO("--lowlat-syscalls", VG_(clo_lowlat_syscalls))
1740 else VG_BOOL_CLO("--optimise", VG_(clo_optimise))
1741 else VG_BOOL_CLO("--pointercheck", VG_(clo_pointercheck))
1742 else VG_BOOL_CLO("--profile", VG_(clo_profile))
1743 else VG_BOOL_CLO("--run-libc-freeres", VG_(clo_run_libc_freeres))
1744 else VG_BOOL_CLO("--show-below-main", VG_(clo_show_below_main))
1745 else VG_BOOL_CLO("--single-step", VG_(clo_single_step))
1746 else VG_BOOL_CLO("--track-fds", VG_(clo_track_fds))
1747 else VG_BOOL_CLO("--trace-children", VG_(clo_trace_children))
1748 else VG_BOOL_CLO("--trace-sched", VG_(clo_trace_sched))
1749 else VG_BOOL_CLO("--trace-signals", VG_(clo_trace_signals))
1750 else VG_BOOL_CLO("--trace-symtab", VG_(clo_trace_symtab))
1751 else VG_BOOL_CLO("--trace-syscalls", VG_(clo_trace_syscalls))
1752 else VG_BOOL_CLO("--wait-for-gdb", VG_(clo_wait_for_gdb))
sewardj72f98ff2002-06-13 17:23:38 +00001753
nethercote27fec902004-06-16 21:26:32 +00001754 else VG_STR_CLO ("--db-command", VG_(clo_db_command))
1755 else VG_STR_CLO ("--weird-hacks", VG_(clo_weird_hacks))
sewardjde4a1d02002-03-22 01:27:54 +00001756
nethercote27fec902004-06-16 21:26:32 +00001757 else VG_NUM_CLO ("--dump-error", VG_(clo_dump_error))
1758 else VG_NUM_CLO ("--input-fd", VG_(clo_input_fd))
1759 else VG_NUM_CLO ("--sanity-level", VG_(clo_sanity_level))
1760 else VG_NUM_CLO ("--signal­polltime", VG_(clo_signal_polltime))
1761 else VG_BNUM_CLO("--num-callers", VG_(clo_backtrace_size), 1,
1762 VG_DEEPEST_BACKTRACE)
sewardjde4a1d02002-03-22 01:27:54 +00001763
nethercotef8548672004-06-21 12:42:35 +00001764 // for backwards compatibility, replaced by --log-fd
nethercote71980f02004-01-24 18:18:54 +00001765 else if (VG_CLO_STREQN(13, arg, "--logfile-fd=")) {
nethercotef8548672004-06-21 12:42:35 +00001766 VG_(clo_log_to) = VgLogTo_Fd;
1767 VG_(clo_log_name) = NULL;
1768 eventually_log_fd = (Int)VG_(atoll)(&arg[13]);
1769 }
1770 else if (VG_CLO_STREQN(9, arg, "--log-fd=")) {
1771 VG_(clo_log_to) = VgLogTo_Fd;
1772 VG_(clo_log_name) = NULL;
1773 eventually_log_fd = (Int)VG_(atoll)(&arg[9]);
sewardj4cf05692002-10-27 20:28:29 +00001774 }
1775
nethercotef8548672004-06-21 12:42:35 +00001776 // for backwards compatibility, replaced by --log-file
nethercote71980f02004-01-24 18:18:54 +00001777 else if (VG_CLO_STREQN(10, arg, "--logfile=")) {
nethercotef8548672004-06-21 12:42:35 +00001778 VG_(clo_log_to) = VgLogTo_File;
1779 VG_(clo_log_name) = &arg[10];
1780 }
1781 else if (VG_CLO_STREQN(11, arg, "--log-file=")) {
1782 VG_(clo_log_to) = VgLogTo_File;
1783 VG_(clo_log_name) = &arg[11];
sewardj4cf05692002-10-27 20:28:29 +00001784 }
sewardjde4a1d02002-03-22 01:27:54 +00001785
nethercotef8548672004-06-21 12:42:35 +00001786 // for backwards compatibility, replaced by --log-socket
nethercote71980f02004-01-24 18:18:54 +00001787 else if (VG_CLO_STREQN(12, arg, "--logsocket=")) {
nethercotef8548672004-06-21 12:42:35 +00001788 VG_(clo_log_to) = VgLogTo_Socket;
1789 VG_(clo_log_name) = &arg[12];
1790 }
1791 else if (VG_CLO_STREQN(13, arg, "--log-socket=")) {
1792 VG_(clo_log_to) = VgLogTo_Socket;
1793 VG_(clo_log_name) = &arg[13];
sewardj73cf3bc2002-11-03 03:20:15 +00001794 }
1795
nethercote71980f02004-01-24 18:18:54 +00001796 else if (VG_CLO_STREQN(15, arg, "--suppressions=")) {
sewardjde4a1d02002-03-22 01:27:54 +00001797 if (VG_(clo_n_suppressions) >= VG_CLO_MAX_SFILES) {
njn25e49d8e72002-09-23 09:36:25 +00001798 VG_(message)(Vg_UserMsg, "Too many suppression files specified.");
sewardjde4a1d02002-03-22 01:27:54 +00001799 VG_(message)(Vg_UserMsg,
1800 "Increase VG_CLO_MAX_SFILES and recompile.");
nethercote71980f02004-01-24 18:18:54 +00001801 VG_(bad_option)(arg);
sewardjde4a1d02002-03-22 01:27:54 +00001802 }
nethercote71980f02004-01-24 18:18:54 +00001803 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = &arg[15];
sewardjde4a1d02002-03-22 01:27:54 +00001804 VG_(clo_n_suppressions)++;
1805 }
sewardjde4a1d02002-03-22 01:27:54 +00001806
njn25e49d8e72002-09-23 09:36:25 +00001807 /* "vwxyz" --> 000zyxwv (binary) */
nethercote71980f02004-01-24 18:18:54 +00001808 else if (VG_CLO_STREQN(16, arg, "--trace-codegen=")) {
njn25e49d8e72002-09-23 09:36:25 +00001809 Int j;
nethercote71980f02004-01-24 18:18:54 +00001810 char* opt = & arg[16];
njn25e49d8e72002-09-23 09:36:25 +00001811
1812 if (5 != VG_(strlen)(opt)) {
1813 VG_(message)(Vg_UserMsg,
1814 "--trace-codegen argument must have 5 digits");
nethercote71980f02004-01-24 18:18:54 +00001815 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001816 }
1817 for (j = 0; j < 5; j++) {
1818 if ('0' == opt[j]) { /* do nothing */ }
1819 else if ('1' == opt[j]) VG_(clo_trace_codegen) |= (1 << j);
1820 else {
1821 VG_(message)(Vg_UserMsg, "--trace-codegen argument can only "
1822 "contain 0s and 1s");
nethercote71980f02004-01-24 18:18:54 +00001823 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001824 }
1825 }
1826 }
sewardjde4a1d02002-03-22 01:27:54 +00001827
nethercote71980f02004-01-24 18:18:54 +00001828 else if (VG_CLO_STREQ(arg, "--trace-pthread=none"))
sewardj45b4b372002-04-16 22:50:32 +00001829 VG_(clo_trace_pthread_level) = 0;
nethercote71980f02004-01-24 18:18:54 +00001830 else if (VG_CLO_STREQ(arg, "--trace-pthread=some"))
sewardj45b4b372002-04-16 22:50:32 +00001831 VG_(clo_trace_pthread_level) = 1;
nethercote71980f02004-01-24 18:18:54 +00001832 else if (VG_CLO_STREQ(arg, "--trace-pthread=all"))
sewardj45b4b372002-04-16 22:50:32 +00001833 VG_(clo_trace_pthread_level) = 2;
sewardj8937c812002-04-12 20:12:20 +00001834
nethercote71980f02004-01-24 18:18:54 +00001835 else if ( ! VG_(needs).command_line_options
1836 || ! SK_(process_cmd_line_option)(arg) ) {
nethercotef4928da2004-06-15 10:54:40 +00001837 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001838 }
sewardjde4a1d02002-03-22 01:27:54 +00001839 }
1840
nethercote27fec902004-06-16 21:26:32 +00001841 // Check various option values
1842
njnf9ebf672003-05-12 21:41:30 +00001843 if (VG_(clo_verbosity) < 0)
sewardjde4a1d02002-03-22 01:27:54 +00001844 VG_(clo_verbosity) = 0;
1845
nethercote04d0fbc2004-01-26 16:48:06 +00001846 if (VG_(clo_db_attach) && VG_(clo_trace_children)) {
sewardjde4a1d02002-03-22 01:27:54 +00001847 VG_(message)(Vg_UserMsg, "");
1848 VG_(message)(Vg_UserMsg,
nethercote04d0fbc2004-01-26 16:48:06 +00001849 "--db-attach=yes conflicts with --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001850 VG_(message)(Vg_UserMsg,
1851 "Please choose one or the other, but not both.");
nethercote04d0fbc2004-01-26 16:48:06 +00001852 VG_(bad_option)("--db-attach=yes and --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001853 }
1854
nethercotef8548672004-06-21 12:42:35 +00001855 /* Set up logging now. After this is done, VG_(clo_log_fd)
sewardj4cf05692002-10-27 20:28:29 +00001856 should be connected to whatever sink has been selected, and we
1857 indiscriminately chuck stuff into it without worrying what the
1858 nature of it is. Oh the wonder of Unix streams. */
1859
nethercotee1730692003-11-20 10:38:07 +00001860 /* So far we should be still attached to stdout, so we can show on
sewardj4cf05692002-10-27 20:28:29 +00001861 the terminal any problems to do with processing command line
1862 opts. */
nethercotef8548672004-06-21 12:42:35 +00001863 vg_assert(VG_(clo_log_fd) == 1 /* stdout */);
sewardj73cf3bc2002-11-03 03:20:15 +00001864 vg_assert(VG_(logging_to_filedes) == True);
sewardj4cf05692002-10-27 20:28:29 +00001865
1866 switch (VG_(clo_log_to)) {
sewardj73cf3bc2002-11-03 03:20:15 +00001867
sewardj4cf05692002-10-27 20:28:29 +00001868 case VgLogTo_Fd:
nethercotef8548672004-06-21 12:42:35 +00001869 vg_assert(VG_(clo_log_name) == NULL);
1870 VG_(clo_log_fd) = eventually_log_fd;
sewardj4cf05692002-10-27 20:28:29 +00001871 break;
sewardj73cf3bc2002-11-03 03:20:15 +00001872
sewardj4cf05692002-10-27 20:28:29 +00001873 case VgLogTo_File: {
1874 Char logfilename[1000];
jsgff3c3f1a2003-10-14 22:13:28 +00001875 Int seq = 0;
1876 Int pid = VG_(getpid)();
1877
nethercotef8548672004-06-21 12:42:35 +00001878 vg_assert(VG_(clo_log_name) != NULL);
1879 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
jsgff3c3f1a2003-10-14 22:13:28 +00001880
nethercote71980f02004-01-24 18:18:54 +00001881 for (;;) {
jsgff3c3f1a2003-10-14 22:13:28 +00001882 if (seq == 0)
1883 VG_(sprintf)(logfilename, "%s.pid%d",
nethercotef8548672004-06-21 12:42:35 +00001884 VG_(clo_log_name), pid );
jsgff3c3f1a2003-10-14 22:13:28 +00001885 else
1886 VG_(sprintf)(logfilename, "%s.pid%d.%d",
nethercotef8548672004-06-21 12:42:35 +00001887 VG_(clo_log_name), pid, seq );
jsgff3c3f1a2003-10-14 22:13:28 +00001888 seq++;
1889
nethercotef8548672004-06-21 12:42:35 +00001890 eventually_log_fd
jsgff3c3f1a2003-10-14 22:13:28 +00001891 = VG_(open)(logfilename,
1892 VKI_O_CREAT|VKI_O_WRONLY|VKI_O_EXCL|VKI_O_TRUNC,
1893 VKI_S_IRUSR|VKI_S_IWUSR);
nethercotef8548672004-06-21 12:42:35 +00001894 if (eventually_log_fd >= 0) {
1895 VG_(clo_log_fd) = VG_(safe_fd)(eventually_log_fd);
jsgff3c3f1a2003-10-14 22:13:28 +00001896 break;
1897 } else {
nethercotef8548672004-06-21 12:42:35 +00001898 if (eventually_log_fd != -VKI_EEXIST) {
jsgff3c3f1a2003-10-14 22:13:28 +00001899 VG_(message)(Vg_UserMsg,
1900 "Can't create/open log file `%s.pid%d'; giving up!",
nethercotef8548672004-06-21 12:42:35 +00001901 VG_(clo_log_name), pid);
jsgff3c3f1a2003-10-14 22:13:28 +00001902 VG_(bad_option)(
nethercotef8548672004-06-21 12:42:35 +00001903 "--log-file=<file> didn't work out for some reason.");
jsgff3c3f1a2003-10-14 22:13:28 +00001904 break;
1905 }
1906 }
1907 }
sewardj4cf05692002-10-27 20:28:29 +00001908 break;
sewardj73cf3bc2002-11-03 03:20:15 +00001909 }
1910
1911 case VgLogTo_Socket: {
nethercotef8548672004-06-21 12:42:35 +00001912 vg_assert(VG_(clo_log_name) != NULL);
1913 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
1914 eventually_log_fd = VG_(connect_via_socket)( VG_(clo_log_name) );
1915 if (eventually_log_fd == -1) {
sewardj73cf3bc2002-11-03 03:20:15 +00001916 VG_(message)(Vg_UserMsg,
nethercotef8548672004-06-21 12:42:35 +00001917 "Invalid --log-socket=ipaddr or --log-socket=ipaddr:port spec");
sewardj73cf3bc2002-11-03 03:20:15 +00001918 VG_(message)(Vg_UserMsg,
nethercotef8548672004-06-21 12:42:35 +00001919 "of `%s'; giving up!", VG_(clo_log_name) );
sewardj73cf3bc2002-11-03 03:20:15 +00001920 VG_(bad_option)(
nethercotef8548672004-06-21 12:42:35 +00001921 "--log-socket=");
sewardj4cf05692002-10-27 20:28:29 +00001922 }
nethercotef8548672004-06-21 12:42:35 +00001923 if (eventually_log_fd == -2) {
sewardj73cf3bc2002-11-03 03:20:15 +00001924 VG_(message)(Vg_UserMsg,
sewardj570f8902002-11-03 11:44:36 +00001925 "valgrind: failed to connect to logging server `%s'.",
nethercotef8548672004-06-21 12:42:35 +00001926 VG_(clo_log_name) );
sewardj570f8902002-11-03 11:44:36 +00001927 VG_(message)(Vg_UserMsg,
1928 "Log messages will sent to stderr instead." );
1929 VG_(message)(Vg_UserMsg,
1930 "" );
1931 /* We don't change anything here. */
1932 } else {
nethercotef8548672004-06-21 12:42:35 +00001933 vg_assert(eventually_log_fd > 0);
1934 VG_(clo_log_fd) = eventually_log_fd;
sewardj570f8902002-11-03 11:44:36 +00001935 VG_(logging_to_filedes) = False;
1936 }
sewardj73cf3bc2002-11-03 03:20:15 +00001937 break;
1938 }
1939
sewardj4cf05692002-10-27 20:28:29 +00001940 }
1941
nethercotef8548672004-06-21 12:42:35 +00001942 /* Move log_fd into the safe range, so it doesn't conflict with any app fds */
thughesad1c9562004-06-26 11:27:52 +00001943 eventually_log_fd = VG_(fcntl)(VG_(clo_log_fd), VKI_F_DUPFD, VG_(fd_hard_limit));
nethercotef8548672004-06-21 12:42:35 +00001944 if (eventually_log_fd < 0)
jsgf855d93d2003-10-13 22:26:55 +00001945 VG_(message)(Vg_UserMsg, "valgrind: failed to move logfile fd into safe range");
1946 else {
nethercotef8548672004-06-21 12:42:35 +00001947 VG_(clo_log_fd) = eventually_log_fd;
1948 VG_(fcntl)(VG_(clo_log_fd), VKI_F_SETFD, VKI_FD_CLOEXEC);
jsgf855d93d2003-10-13 22:26:55 +00001949 }
1950
sewardj4cf05692002-10-27 20:28:29 +00001951 /* Ok, the logging sink is running now. Print a suitable preamble.
1952 If logging to file or a socket, write details of parent PID and
1953 command line args, to help people trying to interpret the
1954 results of a run which encompasses multiple processes. */
sewardjde4a1d02002-03-22 01:27:54 +00001955
sewardj83adf412002-05-01 01:25:45 +00001956 if (VG_(clo_verbosity > 0)) {
njnd04b7c62002-10-03 14:05:52 +00001957 /* Skin details */
1958 VG_(message)(Vg_UserMsg, "%s%s%s, %s for x86-linux.",
1959 VG_(details).name,
1960 NULL == VG_(details).version ? "" : "-",
1961 NULL == VG_(details).version
1962 ? (Char*)"" : VG_(details).version,
1963 VG_(details).description);
1964 VG_(message)(Vg_UserMsg, "%s", VG_(details).copyright_author);
sewardj3b2736a2002-03-24 12:18:35 +00001965
njnd04b7c62002-10-03 14:05:52 +00001966 /* Core details */
1967 VG_(message)(Vg_UserMsg,
njn3e884182003-04-15 13:03:23 +00001968 "Using valgrind-%s, a program supervision framework for x86-linux.",
sewardj4aa62ba2002-10-05 15:49:27 +00001969 VERSION);
sewardjde4a1d02002-03-22 01:27:54 +00001970 VG_(message)(Vg_UserMsg,
nethercote08fa9a72004-07-16 17:44:00 +00001971 "Copyright (C) 2000-2004, and GNU GPL'd, by Julian Seward et al.");
njnd04b7c62002-10-03 14:05:52 +00001972 }
1973
nethercotec1e395d2003-11-10 13:26:49 +00001974 if (VG_(clo_verbosity) > 0 && VG_(clo_log_to) != VgLogTo_Fd) {
sewardj4cf05692002-10-27 20:28:29 +00001975 VG_(message)(Vg_UserMsg, "");
1976 VG_(message)(Vg_UserMsg,
1977 "My PID = %d, parent PID = %d. Prog and args are:",
1978 VG_(getpid)(), VG_(getppid)() );
1979 for (i = 0; i < VG_(client_argc); i++)
1980 VG_(message)(Vg_UserMsg, " %s", VG_(client_argv)[i]);
1981 }
1982
sewardjde4a1d02002-03-22 01:27:54 +00001983 if (VG_(clo_verbosity) > 1) {
nethercotea70f7352004-04-18 12:08:46 +00001984 Int fd;
sewardj4cf05692002-10-27 20:28:29 +00001985 if (VG_(clo_log_to) != VgLogTo_Fd)
1986 VG_(message)(Vg_UserMsg, "");
fitzhardinge98abfc72003-12-16 02:05:15 +00001987 VG_(message)(Vg_UserMsg, "Valgrind library directory: %s", VG_(libdir));
njn86dc2bc2003-09-09 07:26:21 +00001988 VG_(message)(Vg_UserMsg, "Command line");
1989 for (i = 0; i < VG_(client_argc); i++)
1990 VG_(message)(Vg_UserMsg, " %s", VG_(client_argv)[i]);
1991
sewardjde4a1d02002-03-22 01:27:54 +00001992 VG_(message)(Vg_UserMsg, "Startup, with flags:");
nethercote71980f02004-01-24 18:18:54 +00001993 for (i = 1; i < VG_(vg_argc); i++) {
1994 VG_(message)(Vg_UserMsg, " %s", VG_(vg_argv)[i]);
sewardjde4a1d02002-03-22 01:27:54 +00001995 }
nethercotea70f7352004-04-18 12:08:46 +00001996
1997 VG_(message)(Vg_UserMsg, "Contents of /proc/version:");
1998 fd = VG_(open) ( "/proc/version", VKI_O_RDONLY, 0 );
1999 if (fd < 0) {
2000 VG_(message)(Vg_UserMsg, " can't open /proc/version");
2001 } else {
2002 #define BUF_LEN 256
2003 Char version_buf[BUF_LEN];
2004 Int n = VG_(read) ( fd, version_buf, BUF_LEN );
2005 vg_assert(n <= 256);
2006 if (n > 0) {
2007 version_buf[n-1] = '\0';
2008 VG_(message)(Vg_UserMsg, " %s", version_buf);
2009 } else {
2010 VG_(message)(Vg_UserMsg, " (empty?)");
2011 }
2012 VG_(close)(fd);
2013 #undef BUF_LEN
2014 }
sewardjde4a1d02002-03-22 01:27:54 +00002015 }
2016
fitzhardinge98abfc72003-12-16 02:05:15 +00002017 if (VG_(clo_n_suppressions) < VG_CLO_MAX_SFILES-1 &&
njn25e49d8e72002-09-23 09:36:25 +00002018 (VG_(needs).core_errors || VG_(needs).skin_errors)) {
fitzhardinge98abfc72003-12-16 02:05:15 +00002019 /* If there are no suppression files specified and the skin
2020 needs one, load the default */
2021 static const Char default_supp[] = "default.supp";
2022 Int len = VG_(strlen)(VG_(libdir)) + 1 + sizeof(default_supp);
2023 Char *buf = VG_(arena_malloc)(VG_AR_CORE, len);
2024 VG_(sprintf)(buf, "%s/%s", VG_(libdir), default_supp);
2025 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = buf;
2026 VG_(clo_n_suppressions)++;
sewardjde4a1d02002-03-22 01:27:54 +00002027 }
sewardj4cf05692002-10-27 20:28:29 +00002028
njn6a230532003-07-21 10:38:23 +00002029 if (VG_(clo_gen_suppressions) &&
2030 !VG_(needs).core_errors && !VG_(needs).skin_errors) {
nethercotef4928da2004-06-15 10:54:40 +00002031 VG_(message)(Vg_UserMsg,
2032 "Can't use --gen-suppressions=yes with this tool,");
2033 VG_(message)(Vg_UserMsg,
2034 "as it doesn't generate errors.");
2035 VG_(bad_option)("--gen-suppressions=yes");
njn6a230532003-07-21 10:38:23 +00002036 }
sewardjde4a1d02002-03-22 01:27:54 +00002037}
2038
sewardjde4a1d02002-03-22 01:27:54 +00002039
nethercote71980f02004-01-24 18:18:54 +00002040/*====================================================================*/
2041/*=== File descriptor setup ===*/
2042/*====================================================================*/
2043
2044static void setup_file_descriptors(void)
2045{
2046 struct vki_rlimit rl;
2047
2048 /* Get the current file descriptor limits. */
2049 if (VG_(getrlimit)(VKI_RLIMIT_NOFILE, &rl) < 0) {
2050 rl.rlim_cur = 1024;
2051 rl.rlim_max = 1024;
2052 }
2053
2054 /* Work out where to move the soft limit to. */
2055 if (rl.rlim_cur + VG_N_RESERVED_FDS <= rl.rlim_max) {
2056 rl.rlim_cur = rl.rlim_cur + VG_N_RESERVED_FDS;
2057 } else {
2058 rl.rlim_cur = rl.rlim_max;
2059 }
2060
2061 /* Reserve some file descriptors for our use. */
thughesad1c9562004-06-26 11:27:52 +00002062 VG_(fd_soft_limit) = rl.rlim_cur - VG_N_RESERVED_FDS;
2063 VG_(fd_hard_limit) = rl.rlim_cur - VG_N_RESERVED_FDS;
nethercote71980f02004-01-24 18:18:54 +00002064
2065 /* Update the soft limit. */
2066 VG_(setrlimit)(VKI_RLIMIT_NOFILE, &rl);
2067
2068 if (VG_(vgexecfd) != -1)
2069 VG_(vgexecfd) = VG_(safe_fd)( VG_(vgexecfd) );
2070 if (VG_(clexecfd) != -1)
2071 VG_(clexecfd) = VG_(safe_fd)( VG_(clexecfd) );
2072}
2073
2074
2075/*====================================================================*/
nethercote1d447092004-02-01 17:29:59 +00002076/*=== baseBlock: definition + setup ===*/
nethercote71980f02004-01-24 18:18:54 +00002077/*====================================================================*/
2078
2079/* The variables storing offsets. */
2080
2081#define INVALID_OFFSET (-1)
2082
2083Int VGOFF_(m_eax) = INVALID_OFFSET;
2084Int VGOFF_(m_ecx) = INVALID_OFFSET;
2085Int VGOFF_(m_edx) = INVALID_OFFSET;
2086Int VGOFF_(m_ebx) = INVALID_OFFSET;
2087Int VGOFF_(m_esp) = INVALID_OFFSET;
2088Int VGOFF_(m_ebp) = INVALID_OFFSET;
2089Int VGOFF_(m_esi) = INVALID_OFFSET;
2090Int VGOFF_(m_edi) = INVALID_OFFSET;
2091Int VGOFF_(m_eflags) = INVALID_OFFSET;
2092Int VGOFF_(m_dflag) = INVALID_OFFSET;
2093Int VGOFF_(m_ssestate) = INVALID_OFFSET;
2094Int VGOFF_(ldt) = INVALID_OFFSET;
2095Int VGOFF_(tls) = INVALID_OFFSET;
2096Int VGOFF_(m_cs) = INVALID_OFFSET;
2097Int VGOFF_(m_ss) = INVALID_OFFSET;
2098Int VGOFF_(m_ds) = INVALID_OFFSET;
2099Int VGOFF_(m_es) = INVALID_OFFSET;
2100Int VGOFF_(m_fs) = INVALID_OFFSET;
2101Int VGOFF_(m_gs) = INVALID_OFFSET;
2102Int VGOFF_(m_eip) = INVALID_OFFSET;
2103Int VGOFF_(spillslots) = INVALID_OFFSET;
2104Int VGOFF_(sh_eax) = INVALID_OFFSET;
2105Int VGOFF_(sh_ecx) = INVALID_OFFSET;
2106Int VGOFF_(sh_edx) = INVALID_OFFSET;
2107Int VGOFF_(sh_ebx) = INVALID_OFFSET;
2108Int VGOFF_(sh_esp) = INVALID_OFFSET;
2109Int VGOFF_(sh_ebp) = INVALID_OFFSET;
2110Int VGOFF_(sh_esi) = INVALID_OFFSET;
2111Int VGOFF_(sh_edi) = INVALID_OFFSET;
2112Int VGOFF_(sh_eflags) = INVALID_OFFSET;
2113
2114Int VGOFF_(helper_idiv_64_32) = INVALID_OFFSET;
2115Int VGOFF_(helper_div_64_32) = INVALID_OFFSET;
2116Int VGOFF_(helper_idiv_32_16) = INVALID_OFFSET;
2117Int VGOFF_(helper_div_32_16) = INVALID_OFFSET;
2118Int VGOFF_(helper_idiv_16_8) = INVALID_OFFSET;
2119Int VGOFF_(helper_div_16_8) = INVALID_OFFSET;
2120Int VGOFF_(helper_imul_32_64) = INVALID_OFFSET;
2121Int VGOFF_(helper_mul_32_64) = INVALID_OFFSET;
2122Int VGOFF_(helper_imul_16_32) = INVALID_OFFSET;
2123Int VGOFF_(helper_mul_16_32) = INVALID_OFFSET;
2124Int VGOFF_(helper_imul_8_16) = INVALID_OFFSET;
2125Int VGOFF_(helper_mul_8_16) = INVALID_OFFSET;
2126Int VGOFF_(helper_CLD) = INVALID_OFFSET;
2127Int VGOFF_(helper_STD) = INVALID_OFFSET;
2128Int VGOFF_(helper_get_dirflag) = INVALID_OFFSET;
2129Int VGOFF_(helper_CLC) = INVALID_OFFSET;
2130Int VGOFF_(helper_STC) = INVALID_OFFSET;
nethercote1018bdd2004-02-11 23:33:29 +00002131Int VGOFF_(helper_CMC) = INVALID_OFFSET;
nethercote71980f02004-01-24 18:18:54 +00002132Int VGOFF_(helper_shldl) = INVALID_OFFSET;
2133Int VGOFF_(helper_shldw) = INVALID_OFFSET;
2134Int VGOFF_(helper_shrdl) = INVALID_OFFSET;
2135Int VGOFF_(helper_shrdw) = INVALID_OFFSET;
2136Int VGOFF_(helper_IN) = INVALID_OFFSET;
2137Int VGOFF_(helper_OUT) = INVALID_OFFSET;
2138Int VGOFF_(helper_RDTSC) = INVALID_OFFSET;
2139Int VGOFF_(helper_CPUID) = INVALID_OFFSET;
2140Int VGOFF_(helper_BSWAP) = INVALID_OFFSET;
nethercote1018bdd2004-02-11 23:33:29 +00002141Int VGOFF_(helper_bsfw) = INVALID_OFFSET;
2142Int VGOFF_(helper_bsfl) = INVALID_OFFSET;
2143Int VGOFF_(helper_bsrw) = INVALID_OFFSET;
2144Int VGOFF_(helper_bsrl) = INVALID_OFFSET;
nethercote71980f02004-01-24 18:18:54 +00002145Int VGOFF_(helper_fstsw_AX) = INVALID_OFFSET;
2146Int VGOFF_(helper_SAHF) = INVALID_OFFSET;
2147Int VGOFF_(helper_LAHF) = INVALID_OFFSET;
2148Int VGOFF_(helper_DAS) = INVALID_OFFSET;
2149Int VGOFF_(helper_DAA) = INVALID_OFFSET;
nethercote1018bdd2004-02-11 23:33:29 +00002150Int VGOFF_(helper_AAS) = INVALID_OFFSET;
2151Int VGOFF_(helper_AAA) = INVALID_OFFSET;
2152Int VGOFF_(helper_AAD) = INVALID_OFFSET;
2153Int VGOFF_(helper_AAM) = INVALID_OFFSET;
nethercote71980f02004-01-24 18:18:54 +00002154Int VGOFF_(helper_cmpxchg8b) = INVALID_OFFSET;
2155Int VGOFF_(helper_undefined_instruction) = INVALID_OFFSET;
2156
2157/* MAX_NONCOMPACT_HELPERS can be increased easily. If MAX_COMPACT_HELPERS is
2158 * increased too much, they won't really be compact any more... */
2159#define MAX_COMPACT_HELPERS 8
2160#define MAX_NONCOMPACT_HELPERS 50
2161
2162UInt VG_(n_compact_helpers) = 0;
2163UInt VG_(n_noncompact_helpers) = 0;
2164
2165Addr VG_(compact_helper_addrs) [MAX_COMPACT_HELPERS];
2166Int VG_(compact_helper_offsets)[MAX_COMPACT_HELPERS];
2167Addr VG_(noncompact_helper_addrs) [MAX_NONCOMPACT_HELPERS];
2168Int VG_(noncompact_helper_offsets)[MAX_NONCOMPACT_HELPERS];
2169
2170/* This is the actual defn of baseblock. */
2171UInt VG_(baseBlock)[VG_BASEBLOCK_WORDS];
2172
nethercote71980f02004-01-24 18:18:54 +00002173/* Words. */
2174static Int baB_off = 0;
2175
2176
sewardjfa492d42002-12-08 18:20:01 +00002177UInt VG_(insertDflag)(UInt eflags, Int d)
2178{
2179 vg_assert(d == 1 || d == -1);
2180 eflags &= ~EFlagD;
2181
2182 if (d < 0)
2183 eflags |= EFlagD;
2184
2185 return eflags;
2186}
2187
2188Int VG_(extractDflag)(UInt eflags)
2189{
2190 Int ret;
2191
2192 if (eflags & EFlagD)
2193 ret = -1;
2194 else
2195 ret = 1;
2196
2197 return ret;
2198}
2199
nethercote71980f02004-01-24 18:18:54 +00002200/* Returns the offset, in words. */
2201static Int alloc_BaB ( Int words )
sewardjde4a1d02002-03-22 01:27:54 +00002202{
nethercote71980f02004-01-24 18:18:54 +00002203 Int off = baB_off;
2204 baB_off += words;
2205 if (baB_off >= VG_BASEBLOCK_WORDS)
2206 VG_(core_panic)( "alloc_BaB: baseBlock is too small");
sewardjde4a1d02002-03-22 01:27:54 +00002207
nethercote71980f02004-01-24 18:18:54 +00002208 return off;
sewardjde4a1d02002-03-22 01:27:54 +00002209}
2210
nethercote71980f02004-01-24 18:18:54 +00002211/* Align offset, in *bytes* */
2212static void align_BaB ( UInt align )
njn25e49d8e72002-09-23 09:36:25 +00002213{
nethercote71980f02004-01-24 18:18:54 +00002214 vg_assert(2 == align || 4 == align || 8 == align || 16 == align);
2215 baB_off += (align-1);
2216 baB_off &= ~(align-1);
njn25e49d8e72002-09-23 09:36:25 +00002217}
2218
nethercote71980f02004-01-24 18:18:54 +00002219/* Allocate 1 word in baseBlock and set it to the given value. */
2220static Int alloc_BaB_1_set ( Addr a )
njn25e49d8e72002-09-23 09:36:25 +00002221{
nethercote71980f02004-01-24 18:18:54 +00002222 Int off = alloc_BaB(1);
2223 VG_(baseBlock)[off] = (UInt)a;
2224 return off;
njn25e49d8e72002-09-23 09:36:25 +00002225}
2226
nethercote71980f02004-01-24 18:18:54 +00002227/* Registers a function in compact_helper_addrs; compact_helper_offsets is
2228 filled in later. */
2229void VG_(register_compact_helper)(Addr a)
sewardjde4a1d02002-03-22 01:27:54 +00002230{
nethercote71980f02004-01-24 18:18:54 +00002231 if (MAX_COMPACT_HELPERS <= VG_(n_compact_helpers)) {
2232 VG_(printf)("Can only register %d compact helpers\n",
2233 MAX_COMPACT_HELPERS);
2234 VG_(core_panic)("Too many compact helpers registered");
2235 }
2236 VG_(compact_helper_addrs)[VG_(n_compact_helpers)] = a;
2237 VG_(n_compact_helpers)++;
2238}
2239
2240/* Registers a function in noncompact_helper_addrs; noncompact_helper_offsets
2241 * is filled in later.
2242 */
2243void VG_(register_noncompact_helper)(Addr a)
2244{
2245 if (MAX_NONCOMPACT_HELPERS <= VG_(n_noncompact_helpers)) {
2246 VG_(printf)("Can only register %d non-compact helpers\n",
2247 MAX_NONCOMPACT_HELPERS);
2248 VG_(printf)("Try increasing MAX_NON_COMPACT_HELPERS\n");
2249 VG_(core_panic)("Too many non-compact helpers registered");
2250 }
2251 VG_(noncompact_helper_addrs)[VG_(n_noncompact_helpers)] = a;
2252 VG_(n_noncompact_helpers)++;
2253}
2254
2255/* Allocate offsets in baseBlock for the skin helpers */
2256static
2257void assign_helpers_in_baseBlock(UInt n, Int offsets[], Addr addrs[])
2258{
2259 UInt i;
2260 for (i = 0; i < n; i++)
2261 offsets[i] = alloc_BaB_1_set( addrs[i] );
2262}
2263
2264Bool VG_(need_to_handle_esp_assignment)(void)
2265{
2266 return ( VG_(defined_new_mem_stack_4)() ||
2267 VG_(defined_die_mem_stack_4)() ||
2268 VG_(defined_new_mem_stack_8)() ||
2269 VG_(defined_die_mem_stack_8)() ||
2270 VG_(defined_new_mem_stack_12)() ||
2271 VG_(defined_die_mem_stack_12)() ||
2272 VG_(defined_new_mem_stack_16)() ||
2273 VG_(defined_die_mem_stack_16)() ||
2274 VG_(defined_new_mem_stack_32)() ||
2275 VG_(defined_die_mem_stack_32)() ||
2276 VG_(defined_new_mem_stack)() ||
2277 VG_(defined_die_mem_stack)()
2278 );
2279}
2280
2281/* Here we assign actual offsets. It's important to get the most
2282 popular referents within 128 bytes of the start, so we can take
2283 advantage of short addressing modes relative to %ebp. Popularity
2284 of offsets was measured on 22 Feb 02 running a KDE application, and
2285 the slots rearranged accordingly, with a 1.5% reduction in total
2286 size of translations. */
2287static void init_baseBlock ( Addr client_eip, Addr esp_at_startup )
2288{
2289 /* Those with offsets under 128 are carefully chosen. */
2290
2291 /* WORD offsets in this column */
2292 /* 0 */ VGOFF_(m_eax) = alloc_BaB_1_set(0);
2293 /* 1 */ VGOFF_(m_ecx) = alloc_BaB_1_set(0);
2294 /* 2 */ VGOFF_(m_edx) = alloc_BaB_1_set(0);
2295 /* 3 */ VGOFF_(m_ebx) = alloc_BaB_1_set(0);
2296 /* 4 */ VGOFF_(m_esp) = alloc_BaB_1_set(esp_at_startup);
2297 /* 5 */ VGOFF_(m_ebp) = alloc_BaB_1_set(0);
2298 /* 6 */ VGOFF_(m_esi) = alloc_BaB_1_set(0);
2299 /* 7 */ VGOFF_(m_edi) = alloc_BaB_1_set(0);
2300 /* 8 */ VGOFF_(m_eflags) = alloc_BaB_1_set(0);
2301
2302 if (VG_(needs).shadow_regs) {
2303 /* 9 */ VGOFF_(sh_eax) = alloc_BaB_1_set(0);
2304 /* 10 */ VGOFF_(sh_ecx) = alloc_BaB_1_set(0);
2305 /* 11 */ VGOFF_(sh_edx) = alloc_BaB_1_set(0);
2306 /* 12 */ VGOFF_(sh_ebx) = alloc_BaB_1_set(0);
2307 /* 13 */ VGOFF_(sh_esp) = alloc_BaB_1_set(0);
2308 /* 14 */ VGOFF_(sh_ebp) = alloc_BaB_1_set(0);
2309 /* 15 */ VGOFF_(sh_esi) = alloc_BaB_1_set(0);
2310 /* 16 */ VGOFF_(sh_edi) = alloc_BaB_1_set(0);
2311 /* 17 */ VGOFF_(sh_eflags) = alloc_BaB_1_set(0);
2312 VG_TRACK( post_regs_write_init );
2313 }
2314
2315 /* 9,10,11 or 18,19,20... depends on number whether shadow regs are used
2316 * and on compact helpers registered */
2317
2318 /* Make these most-frequently-called specialised ones compact, if they
2319 are used. */
2320 if (VG_(defined_new_mem_stack_4)())
2321 VG_(register_compact_helper)( (Addr) VG_(tool_interface).track_new_mem_stack_4);
2322
2323 if (VG_(defined_die_mem_stack_4)())
2324 VG_(register_compact_helper)( (Addr) VG_(tool_interface).track_die_mem_stack_4);
2325
2326 /* (9 or 18) + n_compact_helpers */
2327 /* Allocate slots for compact helpers */
2328 assign_helpers_in_baseBlock(VG_(n_compact_helpers),
2329 VG_(compact_helper_offsets),
2330 VG_(compact_helper_addrs));
2331
2332 /* (9/10 or 18/19) + n_compact_helpers */
2333 VGOFF_(m_eip) = alloc_BaB_1_set(client_eip);
2334
2335 /* There are currently 24 spill slots */
2336 /* (11+/20+ .. 32+/43+) + n_compact_helpers. This can overlap the magic
2337 * boundary at >= 32 words, but most spills are to low numbered spill
2338 * slots, so the ones above the boundary don't see much action. */
2339 VGOFF_(spillslots) = alloc_BaB(VG_MAX_SPILLSLOTS);
2340
2341 /* I gave up counting at this point. Since they're above the
2342 short-amode-boundary, there's no point. */
2343
2344 VGOFF_(m_dflag) = alloc_BaB_1_set(1); // 1 == forward D-flag
2345
2346 /* The FPU/SSE state. This _must_ be 16-byte aligned. Initial
2347 state doesn't matter much, as long as it's not totally borked. */
2348 align_BaB(16);
2349 VGOFF_(m_ssestate) = alloc_BaB(VG_SIZE_OF_SSESTATE_W);
2350 vg_assert(
2351 0 == ( ((UInt)(& VG_(baseBlock)[VGOFF_(m_ssestate)])) % 16 )
sewardj22854b92002-11-30 14:00:47 +00002352 );
2353
fitzhardingec2dbbac2004-01-23 23:09:01 +00002354 /* I assume that if we have SSE2 we also have SSE */
2355 VG_(have_ssestate) =
2356 VG_(cpu_has_feature)(VG_X86_FEAT_FXSR) &&
2357 VG_(cpu_has_feature)(VG_X86_FEAT_SSE);
2358
fitzhardinge98abfc72003-12-16 02:05:15 +00002359 /* set up an initial FPU state (doesn't really matter what it is,
2360 so long as it's somewhat valid) */
2361 if (!VG_(have_ssestate))
nethercote71980f02004-01-24 18:18:54 +00002362 asm volatile("fwait; fnsave %0; fwait; frstor %0; fwait"
2363 :
2364 : "m" (VG_(baseBlock)[VGOFF_(m_ssestate)])
2365 : "cc", "memory");
fitzhardinge98abfc72003-12-16 02:05:15 +00002366 else
nethercote71980f02004-01-24 18:18:54 +00002367 asm volatile("fwait; fxsave %0; fwait; andl $0xffbf, %1;"
2368 "fxrstor %0; fwait"
2369 :
2370 : "m" (VG_(baseBlock)[VGOFF_(m_ssestate)]),
2371 "m" (VG_(baseBlock)[VGOFF_(m_ssestate)+(24/4)])
2372 : "cc", "memory");
fitzhardinge98abfc72003-12-16 02:05:15 +00002373
njn0c7a5b52003-04-30 09:00:33 +00002374 if (0) {
2375 if (VG_(have_ssestate))
2376 VG_(printf)("Looks like a SSE-capable CPU\n");
2377 else
2378 VG_(printf)("Looks like a MMX-only CPU\n");
2379 }
sewardjb91ae7f2003-04-29 23:50:00 +00002380
nethercote71980f02004-01-24 18:18:54 +00002381 /* LDT pointer: pretend the root thread has an empty LDT to start with. */
2382 VGOFF_(ldt) = alloc_BaB_1_set((UInt)NULL);
jsgf855d93d2003-10-13 22:26:55 +00002383
nethercote71980f02004-01-24 18:18:54 +00002384 /* TLS pointer: pretend the root thread has no TLS array for now. */
2385 VGOFF_(tls) = alloc_BaB_1_set((UInt)NULL);
fitzhardingef0046f22003-12-18 02:39:22 +00002386
nethercote71980f02004-01-24 18:18:54 +00002387 /* segment registers */
2388 VGOFF_(m_cs) = alloc_BaB_1_set(0);
2389 VGOFF_(m_ss) = alloc_BaB_1_set(0);
2390 VGOFF_(m_ds) = alloc_BaB_1_set(0);
2391 VGOFF_(m_es) = alloc_BaB_1_set(0);
2392 VGOFF_(m_fs) = alloc_BaB_1_set(0);
2393 VGOFF_(m_gs) = alloc_BaB_1_set(0);
fitzhardingef0046f22003-12-18 02:39:22 +00002394
thughes35cec982004-04-21 15:16:43 +00002395 /* initialise %cs, %ds and %ss to point at the operating systems
2396 default code, data and stack segments */
2397 asm volatile("movw %%cs, %0"
2398 :
2399 : "m" (VG_(baseBlock)[VGOFF_(m_cs)]));
2400 asm volatile("movw %%ds, %0"
2401 :
2402 : "m" (VG_(baseBlock)[VGOFF_(m_ds)]));
2403 asm volatile("movw %%ss, %0"
2404 :
2405 : "m" (VG_(baseBlock)[VGOFF_(m_ss)]));
2406
nethercote71980f02004-01-24 18:18:54 +00002407 VG_(register_noncompact_helper)( (Addr) & VG_(do_useseg) );
fitzhardingef0046f22003-12-18 02:39:22 +00002408
nethercote71980f02004-01-24 18:18:54 +00002409#define REG(kind, size) \
2410 if (VG_(defined_##kind##_mem_stack##size)()) \
2411 VG_(register_noncompact_helper)( \
2412 (Addr) VG_(tool_interface).track_##kind##_mem_stack##size );
2413 REG(new, _8);
2414 REG(new, _12);
2415 REG(new, _16);
2416 REG(new, _32);
2417 REG(new, );
2418 REG(die, _8);
2419 REG(die, _12);
2420 REG(die, _16);
2421 REG(die, _32);
2422 REG(die, );
2423#undef REG
fitzhardingef0046f22003-12-18 02:39:22 +00002424
nethercote71980f02004-01-24 18:18:54 +00002425 if (VG_(need_to_handle_esp_assignment)())
2426 VG_(register_noncompact_helper)((Addr) VG_(unknown_esp_update));
fitzhardingeb791a192003-12-18 07:22:44 +00002427
nethercote71980f02004-01-24 18:18:54 +00002428# define HELPER(name) \
2429 VGOFF_(helper_##name) = alloc_BaB_1_set( (Addr) & VG_(helper_##name))
njn3e884182003-04-15 13:03:23 +00002430
nethercote71980f02004-01-24 18:18:54 +00002431 /* Helper functions. */
2432 HELPER(idiv_64_32); HELPER(div_64_32);
2433 HELPER(idiv_32_16); HELPER(div_32_16);
2434 HELPER(idiv_16_8); HELPER(div_16_8);
fitzhardinge98abfc72003-12-16 02:05:15 +00002435
nethercote71980f02004-01-24 18:18:54 +00002436 HELPER(imul_32_64); HELPER(mul_32_64);
2437 HELPER(imul_16_32); HELPER(mul_16_32);
2438 HELPER(imul_8_16); HELPER(mul_8_16);
njn25e49d8e72002-09-23 09:36:25 +00002439
nethercote71980f02004-01-24 18:18:54 +00002440 HELPER(CLD); HELPER(STD);
2441 HELPER(get_dirflag);
sewardjde4a1d02002-03-22 01:27:54 +00002442
nethercote71980f02004-01-24 18:18:54 +00002443 HELPER(CLC); HELPER(STC);
nethercote1018bdd2004-02-11 23:33:29 +00002444 HELPER(CMC);
jsgf855d93d2003-10-13 22:26:55 +00002445
nethercote71980f02004-01-24 18:18:54 +00002446 HELPER(shldl); HELPER(shldw);
2447 HELPER(shrdl); HELPER(shrdw);
njncc7bb472002-10-14 09:25:19 +00002448
nethercote71980f02004-01-24 18:18:54 +00002449 HELPER(RDTSC); HELPER(CPUID);
njncc7bb472002-10-14 09:25:19 +00002450
nethercote1018bdd2004-02-11 23:33:29 +00002451 HELPER(bsfw); HELPER(bsfl);
2452 HELPER(bsrw); HELPER(bsrl);
rjwalshf5f536f2003-11-17 17:45:00 +00002453
nethercote71980f02004-01-24 18:18:54 +00002454 HELPER(fstsw_AX);
2455 HELPER(SAHF); HELPER(LAHF);
2456 HELPER(DAS); HELPER(DAA);
nethercote1018bdd2004-02-11 23:33:29 +00002457 HELPER(AAS); HELPER(AAA);
2458 HELPER(AAD); HELPER(AAM);
nethercote71980f02004-01-24 18:18:54 +00002459 HELPER(IN); HELPER(OUT);
2460 HELPER(cmpxchg8b);
sewardj018f7622002-05-15 21:13:39 +00002461
nethercote71980f02004-01-24 18:18:54 +00002462 HELPER(undefined_instruction);
jsgf855d93d2003-10-13 22:26:55 +00002463
nethercote71980f02004-01-24 18:18:54 +00002464# undef HELPER
sewardjde4a1d02002-03-22 01:27:54 +00002465
nethercote71980f02004-01-24 18:18:54 +00002466 /* Allocate slots for noncompact helpers */
2467 assign_helpers_in_baseBlock(VG_(n_noncompact_helpers),
2468 VG_(noncompact_helper_offsets),
2469 VG_(noncompact_helper_addrs));
2470}
sewardjde4a1d02002-03-22 01:27:54 +00002471
sewardj5f07b662002-04-23 16:52:51 +00002472
nethercote71980f02004-01-24 18:18:54 +00002473/*====================================================================*/
2474/*=== Setup pointercheck ===*/
2475/*====================================================================*/
njn25e49d8e72002-09-23 09:36:25 +00002476
nethercote71980f02004-01-24 18:18:54 +00002477static void setup_pointercheck(void)
2478{
2479 int ret;
sewardj2e93c502002-04-12 11:12:52 +00002480
fitzhardinge98abfc72003-12-16 02:05:15 +00002481 if (VG_(clo_pointercheck)) {
nethercote71980f02004-01-24 18:18:54 +00002482 vki_modify_ldt_t ldt = {
2483 VG_POINTERCHECK_SEGIDX, // entry_number
2484 VG_(client_base), // base_addr
2485 (VG_(client_end)-VG_(client_base)) / VKI_BYTES_PER_PAGE, // limit
2486 1, // seg_32bit
2487 0, // contents: data, RW, non-expanding
2488 0, // ! read_exec_only
2489 1, // limit_in_pages
2490 0, // ! seg not present
2491 1, // useable
fitzhardinge98abfc72003-12-16 02:05:15 +00002492 };
nethercote71980f02004-01-24 18:18:54 +00002493 ret = VG_(do_syscall)(__NR_modify_ldt, 1, &ldt, sizeof(ldt));
fitzhardinge98abfc72003-12-16 02:05:15 +00002494 if (ret < 0) {
2495 VG_(message)(Vg_UserMsg,
2496 "Warning: ignoring --pointercheck=yes, "
2497 "because modify_ldt failed (errno=%d)", -ret);
2498 VG_(clo_pointercheck) = False;
2499 }
2500 }
sewardjde4a1d02002-03-22 01:27:54 +00002501}
2502
nethercote71980f02004-01-24 18:18:54 +00002503/*====================================================================*/
2504/*=== Initialise program data/text, etc. ===*/
2505/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +00002506
nethercote71980f02004-01-24 18:18:54 +00002507static void build_valgrind_map_callback
2508 ( Addr start, UInt size, Char rr, Char ww, Char xx,
2509 UInt dev, UInt ino, ULong foffset, const UChar* filename )
sewardjde4a1d02002-03-22 01:27:54 +00002510{
nethercote71980f02004-01-24 18:18:54 +00002511 UInt prot = 0;
2512 UInt flags = SF_MMAP|SF_NOSYMS;
2513 Bool is_stack_segment;
2514
2515 is_stack_segment =
2516 (start == VG_(clstk_base) && (start+size) == VG_(clstk_end));
2517
2518 /* Only record valgrind mappings for now, without loading any
2519 symbols. This is so we know where the free space is before we
2520 start allocating more memory (note: heap is OK, it's just mmap
2521 which is the problem here). */
2522 if (start >= VG_(valgrind_base) && (start+size) <= VG_(valgrind_end)) {
2523 flags |= SF_VALGRIND;
2524 VG_(map_file_segment)(start, size, prot, flags, dev, ino, foffset, filename);
2525 }
sewardjde4a1d02002-03-22 01:27:54 +00002526}
2527
nethercote71980f02004-01-24 18:18:54 +00002528// Global var used to pass local data to callback
2529Addr esp_at_startup___global_arg = 0;
sewardjde4a1d02002-03-22 01:27:54 +00002530
nethercote71980f02004-01-24 18:18:54 +00002531static void build_segment_map_callback
2532 ( Addr start, UInt size, Char rr, Char ww, Char xx,
2533 UInt dev, UInt ino, ULong foffset, const UChar* filename )
sewardj45b672d2003-07-25 19:58:11 +00002534{
nethercote71980f02004-01-24 18:18:54 +00002535 UInt prot = 0;
2536 UInt flags;
2537 Bool is_stack_segment;
2538 Addr r_esp;
sewardj45b672d2003-07-25 19:58:11 +00002539
nethercote71980f02004-01-24 18:18:54 +00002540 is_stack_segment
2541 = (start == VG_(clstk_base) && (start+size) == VG_(clstk_end));
fitzhardinge98abfc72003-12-16 02:05:15 +00002542
nethercote71980f02004-01-24 18:18:54 +00002543 if (rr == 'r') prot |= VKI_PROT_READ;
2544 if (ww == 'w') prot |= VKI_PROT_WRITE;
2545 if (xx == 'x') prot |= VKI_PROT_EXEC;
fitzhardinge98abfc72003-12-16 02:05:15 +00002546
nethercote71980f02004-01-24 18:18:54 +00002547 if (is_stack_segment)
2548 flags = SF_STACK | SF_GROWDOWN;
2549 else
2550 flags = SF_EXEC|SF_MMAP;
fitzhardinge98abfc72003-12-16 02:05:15 +00002551
nethercote71980f02004-01-24 18:18:54 +00002552 if (filename != NULL)
2553 flags |= SF_FILE;
fitzhardinge98abfc72003-12-16 02:05:15 +00002554
nethercote71980f02004-01-24 18:18:54 +00002555 if (start >= VG_(valgrind_base) && (start+size) <= VG_(valgrind_end))
2556 flags |= SF_VALGRIND;
fitzhardinge98abfc72003-12-16 02:05:15 +00002557
nethercote71980f02004-01-24 18:18:54 +00002558 VG_(map_file_segment)(start, size, prot, flags, dev, ino, foffset, filename);
fitzhardinge98abfc72003-12-16 02:05:15 +00002559
nethercote71980f02004-01-24 18:18:54 +00002560 if (VG_(is_client_addr)(start) && VG_(is_client_addr)(start+size-1))
2561 VG_TRACK( new_mem_startup, start, size, rr=='r', ww=='w', xx=='x' );
sewardj3e1eb1f2002-05-18 13:14:17 +00002562
nethercote71980f02004-01-24 18:18:54 +00002563 /* If this is the stack segment mark all below %esp as noaccess. */
2564 r_esp = esp_at_startup___global_arg;
2565 vg_assert(0 != r_esp);
2566 if (is_stack_segment) {
2567 if (0)
2568 VG_(message)(Vg_DebugMsg, "invalidating stack area: %x .. %x",
2569 start,r_esp);
2570 VG_TRACK( die_mem_stack, start, r_esp-start );
sewardjde4a1d02002-03-22 01:27:54 +00002571 }
sewardjde4a1d02002-03-22 01:27:54 +00002572}
2573
2574
nethercote71980f02004-01-24 18:18:54 +00002575/*====================================================================*/
2576/*=== Sanity check machinery (permanently engaged) ===*/
2577/*====================================================================*/
njn25e49d8e72002-09-23 09:36:25 +00002578
2579/* A fast sanity check -- suitable for calling circa once per
2580 millisecond. */
2581
2582void VG_(do_sanity_checks) ( Bool force_expensive )
2583{
njn37cea302002-09-30 11:24:00 +00002584 VGP_PUSHCC(VgpCoreCheapSanity);
2585
nethercote27fec902004-06-16 21:26:32 +00002586 if (VG_(clo_sanity_level) < 1) return;
njn25e49d8e72002-09-23 09:36:25 +00002587
2588 /* --- First do all the tests that we can do quickly. ---*/
2589
2590 VG_(sanity_fast_count)++;
2591
njn25e49d8e72002-09-23 09:36:25 +00002592 /* Check stuff pertaining to the memory check system. */
2593
2594 /* Check that nobody has spuriously claimed that the first or
2595 last 16 pages of memory have become accessible [...] */
njn37cea302002-09-30 11:24:00 +00002596 if (VG_(needs).sanity_checks) {
2597 VGP_PUSHCC(VgpSkinCheapSanity);
njn25e49d8e72002-09-23 09:36:25 +00002598 vg_assert(SK_(cheap_sanity_check)());
njn37cea302002-09-30 11:24:00 +00002599 VGP_POPCC(VgpSkinCheapSanity);
2600 }
njn25e49d8e72002-09-23 09:36:25 +00002601
2602 /* --- Now some more expensive checks. ---*/
2603
2604 /* Once every 25 times, check some more expensive stuff. */
2605 if ( force_expensive
nethercote27fec902004-06-16 21:26:32 +00002606 || VG_(clo_sanity_level) > 1
2607 || (VG_(clo_sanity_level) == 1 && (VG_(sanity_fast_count) % 25) == 0)) {
njn25e49d8e72002-09-23 09:36:25 +00002608
njn37cea302002-09-30 11:24:00 +00002609 VGP_PUSHCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002610 VG_(sanity_slow_count)++;
2611
jsgf855d93d2003-10-13 22:26:55 +00002612 VG_(proxy_sanity)();
2613
njn25e49d8e72002-09-23 09:36:25 +00002614# if 0
2615 { void zzzmemscan(void); zzzmemscan(); }
2616# endif
2617
2618 if ((VG_(sanity_fast_count) % 250) == 0)
2619 VG_(sanity_check_tc_tt)();
2620
2621 if (VG_(needs).sanity_checks) {
njn37cea302002-09-30 11:24:00 +00002622 VGP_PUSHCC(VgpSkinExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002623 vg_assert(SK_(expensive_sanity_check)());
njn37cea302002-09-30 11:24:00 +00002624 VGP_POPCC(VgpSkinExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002625 }
2626 /*
2627 if ((VG_(sanity_fast_count) % 500) == 0) VG_(mallocSanityCheckAll)();
2628 */
njn37cea302002-09-30 11:24:00 +00002629 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002630 }
2631
nethercote27fec902004-06-16 21:26:32 +00002632 if (VG_(clo_sanity_level) > 1) {
njn37cea302002-09-30 11:24:00 +00002633 VGP_PUSHCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002634 /* Check sanity of the low-level memory manager. Note that bugs
2635 in the client's code can cause this to fail, so we don't do
2636 this check unless specially asked for. And because it's
2637 potentially very expensive. */
2638 VG_(mallocSanityCheckAll)();
njn37cea302002-09-30 11:24:00 +00002639 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002640 }
njn37cea302002-09-30 11:24:00 +00002641 VGP_POPCC(VgpCoreCheapSanity);
njn25e49d8e72002-09-23 09:36:25 +00002642}
nethercote71980f02004-01-24 18:18:54 +00002643
2644
2645/*====================================================================*/
2646/*=== main() ===*/
2647/*====================================================================*/
2648
nethercotec314eba2004-07-15 12:59:41 +00002649/*
2650 This code decides on the layout of the client and Valgrind address
2651 spaces, loads valgrind.so and the skin.so into the valgrind part,
2652 loads the client executable (and the dynamic linker, if necessary)
2653 into the client part, and calls into Valgrind proper.
2654
2655 The code is careful not to allow spurious mappings to appear in the
2656 wrong parts of the address space. In particular, to make sure
2657 dlopen puts things in the right place, it will pad out the forbidden
2658 chunks of address space so that dlopen is forced to put things where
2659 we want them.
2660
2661 The memory map it creates is:
2662
2663 CLIENT_BASE +-------------------------+
2664 | client address space |
2665 : :
2666 : :
2667 | client stack |
2668 client_end +-------------------------+
2669 | redzone |
2670 shadow_base +-------------------------+
2671 | |
2672 : shadow memory for skins :
2673 | (may be 0 sized) |
2674 shadow_end +-------------------------+
2675 : gap (may be 0 sized) :
2676 valgrind_base +-------------------------+
2677 | kickstart executable |
2678 | valgrind heap vvvvvvvvv| (barely used)
2679 - -
2680 | valgrind .so files |
2681 | and mappings |
2682 - -
2683 | valgrind stack ^^^^^^^^^|
2684 valgrind_end +-------------------------+
2685 : kernel :
2686
2687 Nb: Before we can do general allocations with VG_(arena_malloc)() and
2688 VG_(mmap)(), we need to build the segment skip-list, so we know where
2689 we can put things. However, building that structure requires
2690 allocating memory. So we need to a bootstrapping process. It's done
2691 by making VG_(arena_malloc)() have a special static superblock that's
2692 used for the first 1MB's worth of allocations. This is enough to
2693 build the segment skip-list.
2694*/
2695
thughes4ad52d02004-06-27 17:37:21 +00002696static int prmap(void *start, void *end, const char *perm, off_t off,
2697 int maj, int min, int ino) {
2698 printf("mapping %10p-%10p %s %02x:%02x %d\n",
2699 start, end, perm, maj, min, ino);
2700 return True;
2701}
2702
nethercote71980f02004-01-24 18:18:54 +00002703int main(int argc, char **argv)
2704{
2705 char **cl_argv;
2706 const char *tool = NULL;
2707 const char *exec = NULL;
2708 char *preload; /* tool-specific LD_PRELOAD .so */
2709 char **env;
nethercote6c999f22004-01-31 22:55:15 +00002710 Int need_help = 0; // 0 = no, 1 = --help, 2 = --help-debug
nethercote71980f02004-01-24 18:18:54 +00002711 struct exeinfo info;
2712 ToolInfo *toolinfo = NULL;
2713 void *tool_dlhandle;
2714 Addr client_eip;
2715 Addr esp_at_startup; /* client's %esp at the point we gained control. */
2716 UInt * client_auxv;
2717 VgSchedReturnCode src;
nethercote47dd12c2004-06-22 14:18:42 +00002718 Int exitcode = 0;
fitzhardingeb50068f2004-02-24 23:42:55 +00002719 vki_rlimit zero = { 0, 0 };
nethercote71980f02004-01-24 18:18:54 +00002720
2721 //============================================================
2722 // Nb: startup is complex. Prerequisites are shown at every step.
2723 //
2724 // *** Be very careful when messing with the order ***
2725 //============================================================
2726
nethercotef4928da2004-06-15 10:54:40 +00002727 //============================================================
2728 // Command line argument handling order:
2729 // * If --help/--help-debug are present, show usage message
2730 // (if --tool is also present, that includes the tool-specific usage)
2731 // * Then, if --tool is missing, abort with error msg
2732 // * Then, if client is missing, abort with error msg
2733 // * Then, if any cmdline args are bad, abort with error msg
2734 //============================================================
2735
fitzhardingeb50068f2004-02-24 23:42:55 +00002736 // Get the current process datasize rlimit, and set it to zero.
2737 // This prevents any internal uses of brk() from having any effect.
2738 // We remember the old value so we can restore it on exec, so that
2739 // child processes will have a reasonable brk value.
2740 VG_(getrlimit)(VKI_RLIMIT_DATA, &VG_(client_rlimit_data));
2741 zero.rlim_max = VG_(client_rlimit_data).rlim_max;
2742 VG_(setrlimit)(VKI_RLIMIT_DATA, &zero);
2743
nethercote71980f02004-01-24 18:18:54 +00002744 //--------------------------------------------------------------
2745 // Check we were launched by stage1
nethercotec314eba2004-07-15 12:59:41 +00002746 // p: n/a
nethercote71980f02004-01-24 18:18:54 +00002747 //--------------------------------------------------------------
2748 scan_auxv();
2749
2750 if (0) {
nethercote71980f02004-01-24 18:18:54 +00002751 printf("========== main() ==========\n");
2752 foreach_map(prmap);
2753 }
2754
2755 //--------------------------------------------------------------
2756 // Look for alternative libdir
2757 // p: n/a
2758 //--------------------------------------------------------------
2759 { char *cp = getenv(VALGRINDLIB);
2760 if (cp != NULL)
2761 VG_(libdir) = cp;
2762 }
2763
2764 //--------------------------------------------------------------
2765 // Begin working out address space layout
2766 // p: n/a
2767 //--------------------------------------------------------------
2768 layout_client_space( (Addr) & argc );
2769
2770 //--------------------------------------------------------------
2771 // Get valgrind args + client args (inc. from VALGRIND_OPTS/.valgrindrc).
2772 // Pre-process the command line.
2773 // p: n/a
2774 //--------------------------------------------------------------
2775 get_command_line(argc, argv, &VG_(vg_argc), &VG_(vg_argv), &cl_argv);
2776 pre_process_cmd_line_options(&need_help, &tool, &exec);
2777
2778 //==============================================================
2779 // Nb: once a tool is specified, the tool.so must be loaded even if
2780 // they specified --help or didn't specify a client program.
2781 //==============================================================
2782
2783 //--------------------------------------------------------------
2784 // With client padded out, map in tool
2785 // p: layout_client_space() [for padding]
2786 // p: set-libdir [for VG_(libdir)]
2787 // p: pre_process_cmd_line_options() [for 'tool']
2788 //--------------------------------------------------------------
2789 load_tool(tool, &tool_dlhandle, &toolinfo, &preload);
2790
2791 //==============================================================
2792 // Can use VG_(malloc)() and VG_(arena_malloc)() only after load_tool()
nethercotec314eba2004-07-15 12:59:41 +00002793 // -- redzone size is now set. This is checked by vg_malloc2.c.
nethercote71980f02004-01-24 18:18:54 +00002794 //==============================================================
2795
2796 //--------------------------------------------------------------
2797 // Finalise address space layout
nethercotec314eba2004-07-15 12:59:41 +00002798 // p: layout_client_space(), load_tool() [for 'toolinfo']
nethercote71980f02004-01-24 18:18:54 +00002799 //--------------------------------------------------------------
2800 layout_remaining_space( toolinfo->shadow_ratio );
2801
2802 //--------------------------------------------------------------
2803 // Load client executable, finding in $PATH if necessary
2804 // p: layout_client_space() [so there's space]
2805 // p: pre_process_cmd_line_options() [for 'exec', 'need_help']
2806 // p: layout_remaining_space [so there's space]
2807 //--------------------------------------------------------------
nethercotef4928da2004-06-15 10:54:40 +00002808 load_client(cl_argv, exec, need_help, &info, &client_eip);
nethercote71980f02004-01-24 18:18:54 +00002809
2810 //--------------------------------------------------------------
2811 // Everything in place, unpad us
2812 // p: layout_remaining_space() [everything must be mapped in before now]
2813 // p: load_client() [ditto]
2814 //--------------------------------------------------------------
2815 as_unpad((void *)VG_(shadow_end), (void *)~0);
2816 as_closepadfile(); /* no more padding */
2817
2818 //--------------------------------------------------------------
2819 // Set up client's environment
2820 // p: set-libdir [for VG_(libdir)]
2821 // p: load_tool() [for 'preload']
2822 //--------------------------------------------------------------
2823 env = fix_environment(environ, preload);
2824
2825 //--------------------------------------------------------------
nethercote5ee67ca2004-06-22 14:00:09 +00002826 // Setup client stack, eip, and VG_(client_arg[cv])
nethercote71980f02004-01-24 18:18:54 +00002827 // p: load_client() [for 'info']
2828 // p: fix_environment() [for 'env']
2829 //--------------------------------------------------------------
2830 esp_at_startup = setup_client_stack(cl_argv, env, &info, &client_auxv);
2831
2832 if (0)
2833 printf("entry=%x client esp=%x vg_argc=%d brkbase=%x\n",
2834 client_eip, esp_at_startup, VG_(vg_argc), VG_(brk_base));
2835
2836 //==============================================================
2837 // Finished setting up operating environment. Now initialise
2838 // Valgrind. (This is where the old VG_(main)() started.)
2839 //==============================================================
2840
2841 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002842 // atfork
2843 // p: n/a
2844 //--------------------------------------------------------------
2845 VG_(atfork)(NULL, NULL, newpid);
2846 newpid(VG_INVALID_THREADID);
2847
2848 //--------------------------------------------------------------
2849 // setup file descriptors
2850 // p: n/a
2851 //--------------------------------------------------------------
2852 setup_file_descriptors();
2853
2854 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002855 // Read /proc/self/maps into a buffer
2856 // p: all memory layout, environment setup [so memory maps are right]
2857 //--------------------------------------------------------------
2858 VG_(read_procselfmaps)();
2859
2860 //--------------------------------------------------------------
2861 // Build segment map (Valgrind segments only)
2862 // p: read proc/self/maps
2863 // p: sk_pre_clo_init() [to setup new_mem_startup tracker]
2864 //--------------------------------------------------------------
2865 VG_(parse_procselfmaps) ( build_valgrind_map_callback );
2866
2867 //==============================================================
2868 // Can use VG_(arena_malloc)() with non-CORE arena after segments set up
2869 //==============================================================
2870
2871 //--------------------------------------------------------------
2872 // Init tool: pre_clo_init, process cmd line, post_clo_init
2873 // p: setup_client_stack() [for 'VG_(client_arg[cv]']
2874 // p: load_tool() [for 'tool']
2875 // p: setup_file_descriptors() [for 'VG_(fd_xxx_limit)']
2876 // p: parse_procselfmaps [so VG segments are setup so tool can
2877 // call VG_(malloc)]
nethercote71980f02004-01-24 18:18:54 +00002878 //--------------------------------------------------------------
2879 (*toolinfo->sk_pre_clo_init)();
2880 VG_(tool_init_dlsym)(tool_dlhandle);
2881 VG_(sanity_check_needs)();
2882
nethercotef4928da2004-06-15 10:54:40 +00002883 // If --tool and --help/--help-debug was given, now give the core+tool
2884 // help message
nethercotef4928da2004-06-15 10:54:40 +00002885 if (need_help) {
2886 usage(/*--help-debug?*/2 == need_help);
2887 }
nethercotec314eba2004-07-15 12:59:41 +00002888 process_cmd_line_options(client_auxv, tool);
2889
2890 SK_(post_clo_init)();
nethercotef4928da2004-06-15 10:54:40 +00002891
2892 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002893 // Build segment map (all segments)
2894 // p: setup_client_stack() [for 'esp_at_startup']
2895 // p: init tool [for 'new_mem_startup']
nethercote71980f02004-01-24 18:18:54 +00002896 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002897 esp_at_startup___global_arg = esp_at_startup;
2898 VG_(parse_procselfmaps) ( build_segment_map_callback ); /* everything */
2899 esp_at_startup___global_arg = 0;
2900
2901 //--------------------------------------------------------------
nethercotef84f6952004-07-15 14:58:33 +00002902 // Protect client trampoline page (which is also sysinfo stuff)
2903 // p: segment stuff [otherwise get seg faults...]
nethercotec314eba2004-07-15 12:59:41 +00002904 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002905 VG_(mprotect)( (void *)VG_(client_trampoline_code),
2906 VG_(trampoline_code_length), VKI_PROT_READ|VKI_PROT_EXEC );
2907
2908 //==============================================================
2909 // Can use VG_(map)() after segments set up
2910 //==============================================================
nethercote71980f02004-01-24 18:18:54 +00002911
2912 //--------------------------------------------------------------
2913 // Allow GDB attach
2914 // p: process_cmd_line_options() [for VG_(clo_wait_for_gdb)]
2915 //--------------------------------------------------------------
2916 /* Hook to delay things long enough so we can get the pid and
2917 attach GDB in another shell. */
2918 if (VG_(clo_wait_for_gdb)) {
2919 VG_(printf)("pid=%d\n", VG_(getpid)());
2920 /* do "jump *$eip" to skip this in gdb */
2921 VG_(do_syscall)(__NR_pause);
2922 }
2923
2924 //--------------------------------------------------------------
nethercote1d447092004-02-01 17:29:59 +00002925 // Set up baseBlock
nethercote71980f02004-01-24 18:18:54 +00002926 // p: {pre,post}_clo_init() [for tool helper registration]
2927 // load_client() [for 'client_eip']
2928 // setup_client_stack() [for 'esp_at_startup']
2929 //--------------------------------------------------------------
2930 init_baseBlock(client_eip, esp_at_startup);
2931
2932 //--------------------------------------------------------------
2933 // Search for file descriptors that are inherited from our parent
2934 // p: process_cmd_line_options [for VG_(clo_track_fds)]
2935 //--------------------------------------------------------------
2936 if (VG_(clo_track_fds))
2937 VG_(init_preopened_fds)();
2938
2939 //--------------------------------------------------------------
2940 // Initialise the scheduler
2941 // p: init_baseBlock() [baseBlock regs copied into VG_(threads)[1]]
2942 // p: setup_file_descriptors() [else VG_(safe_fd)() breaks]
2943 //--------------------------------------------------------------
2944 VG_(scheduler_init)();
2945
2946 //--------------------------------------------------------------
2947 // Set up the ProxyLWP machinery
2948 // p: VG_(scheduler_init)()? [XXX: subtle dependency?]
2949 // - subs: VG_(sigstartup_actions)()?
2950 //--------------------------------------------------------------
2951 VG_(proxy_init)();
2952
2953 //--------------------------------------------------------------
2954 // Initialise the signal handling subsystem
2955 // p: VG_(atfork)(NULL, NULL, newpid) [else problems with sigmasks]
2956 // p: VG_(proxy_init)() [else breaks...]
2957 //--------------------------------------------------------------
2958 // Nb: temporarily parks the saved blocking-mask in saved_sigmask.
2959 VG_(sigstartup_actions)();
2960
2961 //--------------------------------------------------------------
2962 // Perhaps we're profiling Valgrind?
2963 // p: process_cmd_line_options() [for VG_(clo_profile)]
2964 // p: others?
2965 //
2966 // XXX: this seems to be broken? It always says the tool wasn't built
2967 // for profiling; vg_profile.c's functions don't seem to be overriding
2968 // vg_dummy_profile.c's?
2969 //
2970 // XXX: want this as early as possible. Looking for --profile
2971 // in pre_process_cmd_line_options() could get it earlier.
2972 //--------------------------------------------------------------
2973 if (VG_(clo_profile))
2974 VGP_(init_profiling)();
2975
2976 VGP_PUSHCC(VgpStartup);
2977
2978 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002979 // Read suppression file
2980 // p: process_cmd_line_options() [for VG_(clo_suppressions)]
2981 //--------------------------------------------------------------
2982 if (VG_(needs).core_errors || VG_(needs).skin_errors)
2983 VG_(load_suppressions)();
2984
2985 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002986 // Initialise translation table and translation cache
2987 // p: read_procselfmaps [so the anonymous mmaps for the TT/TC
2988 // aren't identified as part of the client, which would waste
2989 // > 20M of virtual address space.]
2990 //--------------------------------------------------------------
2991 VG_(init_tt_tc)();
2992
2993 //--------------------------------------------------------------
2994 // Read debug info to find glibc entry points to intercept
2995 // p: parse_procselfmaps? [XXX for debug info?]
2996 // p: init_tt_tc? [XXX ???]
2997 //--------------------------------------------------------------
2998 VG_(setup_code_redirect_table)();
2999
3000 //--------------------------------------------------------------
3001 // Verbosity message
3002 // p: end_rdtsc_calibration [so startup message is printed first]
3003 //--------------------------------------------------------------
3004 if (VG_(clo_verbosity) == 1)
3005 VG_(message)(Vg_UserMsg, "For more details, rerun with: -v");
3006 if (VG_(clo_verbosity) > 0)
3007 VG_(message)(Vg_UserMsg, "");
3008
3009 //--------------------------------------------------------------
3010 // Setup pointercheck
3011 // p: process_cmd_line_options() [for VG_(clo_pointercheck)]
3012 //--------------------------------------------------------------
3013 setup_pointercheck();
3014
nethercote71980f02004-01-24 18:18:54 +00003015 //--------------------------------------------------------------
3016 // Run!
3017 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00003018 VGP_POPCC(VgpStartup);
3019 VGP_PUSHCC(VgpSched);
3020
3021 if (__builtin_setjmp(&VG_(fatal_signal_jmpbuf)) == 0) {
3022 VG_(fatal_signal_set) = True;
nethercote47dd12c2004-06-22 14:18:42 +00003023 src = VG_(scheduler)( &exitcode );
nethercote71980f02004-01-24 18:18:54 +00003024 } else
3025 src = VgSrc_FatalSig;
3026
3027 VGP_POPCC(VgpSched);
nethercote71980f02004-01-24 18:18:54 +00003028
3029
3030
3031 //--------------------------------------------------------------
3032 // Finalisation: cleanup, messages, etc. Order no so important, only
3033 // affects what order the messages come.
3034 //--------------------------------------------------------------
3035 if (VG_(clo_verbosity) > 0)
3036 VG_(message)(Vg_UserMsg, "");
3037
3038 if (src == VgSrc_Deadlock) {
3039 VG_(message)(Vg_UserMsg,
3040 "Warning: pthread scheduler exited due to deadlock");
3041 }
3042
3043 /* Print out file descriptor summary and stats. */
3044 if (VG_(clo_track_fds))
3045 VG_(fd_stats)();
3046
3047 if (VG_(needs).core_errors || VG_(needs).skin_errors)
3048 VG_(show_all_errors)();
3049
nethercote47dd12c2004-06-22 14:18:42 +00003050 SK_(fini)( exitcode );
nethercote71980f02004-01-24 18:18:54 +00003051
3052 VG_(do_sanity_checks)( True /*include expensive checks*/ );
3053
3054 if (VG_(clo_verbosity) > 1)
3055 show_counts();
3056
3057 if (VG_(clo_verbosity) > 3)
3058 VG_(print_UInstr_histogram)();
3059
3060 if (0) {
3061 VG_(message)(Vg_DebugMsg, "");
3062 VG_(message)(Vg_DebugMsg,
3063 "------ Valgrind's internal memory use stats follow ------" );
3064 VG_(mallocSanityCheckAll)();
3065 VG_(show_all_arena_stats)();
3066 VG_(message)(Vg_DebugMsg,
3067 "------ Valgrind's ExeContext management stats follow ------" );
3068 VG_(show_ExeContext_stats)();
3069 }
3070
3071 if (VG_(clo_profile))
3072 VGP_(done_profiling)();
3073
nethercote71980f02004-01-24 18:18:54 +00003074 /* We're exiting, so nuke all the threads and clean up the proxy LWPs */
3075 vg_assert(src == VgSrc_FatalSig ||
3076 VG_(threads)[VG_(last_run_tid)].status == VgTs_Runnable ||
3077 VG_(threads)[VG_(last_run_tid)].status == VgTs_WaitJoiner);
3078 VG_(nuke_all_threads_except)(VG_INVALID_THREADID);
3079
3080 //--------------------------------------------------------------
3081 // Exit, according to the scheduler's return code
3082 //--------------------------------------------------------------
3083 switch (src) {
3084 case VgSrc_ExitSyscall: /* the normal way out */
3085 vg_assert(VG_(last_run_tid) > 0
3086 && VG_(last_run_tid) < VG_N_THREADS);
3087 VG_(proxy_shutdown)();
3088
3089 /* The thread's %EBX at the time it did __NR_exit() will hold
3090 the arg to __NR_exit(), so we just do __NR_exit() with
3091 that arg. */
nethercote47dd12c2004-06-22 14:18:42 +00003092 VG_(exit)( exitcode );
nethercote71980f02004-01-24 18:18:54 +00003093 /* NOT ALIVE HERE! */
3094 VG_(core_panic)("entered the afterlife in main() -- ExitSyscall");
3095 break; /* what the hell :) */
3096
3097 case VgSrc_Deadlock:
3098 /* Just exit now. No point in continuing. */
3099 VG_(proxy_shutdown)();
3100 VG_(exit)(0);
3101 VG_(core_panic)("entered the afterlife in main() -- Deadlock");
3102 break;
3103
nethercote71980f02004-01-24 18:18:54 +00003104 case VgSrc_FatalSig:
3105 /* We were killed by a fatal signal, so replicate the effect */
3106 vg_assert(VG_(fatal_sigNo) != -1);
3107 VG_(kill_self)(VG_(fatal_sigNo));
3108 VG_(core_panic)("main(): signal was supposed to be fatal");
3109 break;
3110
3111 default:
3112 VG_(core_panic)("main(): unexpected scheduler return code");
3113 }
3114
3115 abort();
3116}
3117
3118
sewardjde4a1d02002-03-22 01:27:54 +00003119/*--------------------------------------------------------------------*/
3120/*--- end vg_main.c ---*/
3121/*--------------------------------------------------------------------*/