blob: 53afa33a58d4e61b2b2dce68dfcf42e8f440d95b [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 **));
656 to = vg_argv;
657
658 /* copy argv[0] */
659 *to++ = *from++;
660
661 /* Copy extra args from env var and file, in the order: ~/.valgrindrc,
662 * $VALGRIND_OPTS, ./.valgrindrc -- more local options are put later
663 * to override less local ones. */
664 to = copy_args(f1_clo, to);
665 to = copy_args(env_clo, to);
666 to = copy_args(f2_clo, to);
667
668 /* copy original arguments, stopping at command or -- */
669 while (*from) {
670 if (**from != '-')
671 break;
672 if (VG_STREQ(*from, "--")) {
673 from++; /* skip -- */
674 break;
675 }
676 *to++ = *from++;
677 }
678
679 /* add -- */
680 *to++ = "--";
681
682 vg_argc = to - vg_argv;
683
684 /* copy rest of original command line, then NULL */
685 while (*from) *to++ = *from++;
686 *to = NULL;
687 }
688
689 *vg_argc_inout = vg_argc;
690 *vg_argv_inout = vg_argv;
691}
692
693static void get_command_line( int argc, char** argv,
694 Int* vg_argc_out, Char*** vg_argv_out,
695 char*** cl_argv_out )
696{
697 int vg_argc;
698 char** vg_argv;
699 char** cl_argv;
700 char* env_clo = getenv(VALGRINDCLO);
701
702 if (env_clo != NULL && *env_clo != '\0') {
703 char *cp;
704 char **cpp;
705
706 /* OK, we're getting all our arguments from the environment - the
707 entire command line belongs to the client (including argv[0]) */
708 vg_argc = 1; /* argv[0] */
709 for (cp = env_clo; *cp; cp++)
710 if (*cp == '\01')
711 vg_argc++;
712
713 vg_argv = malloc(sizeof(char **) * (vg_argc + 1));
714
715 cpp = vg_argv;
716
717 *cpp++ = "valgrind"; /* nominal argv[0] */
718 *cpp++ = env_clo;
719
720 for (cp = env_clo; *cp; cp++) {
721 if (*cp == '\01') {
722 *cp++ = '\0'; /* chop it up in place */
723 *cpp++ = cp;
724 }
725 }
726 *cpp = NULL;
727 cl_argv = argv;
728
729 } else {
730 /* Count the arguments on the command line. */
731 vg_argv = argv;
732
733 for (vg_argc = 1; vg_argc < argc; vg_argc++) {
734 if (argv[vg_argc][0] != '-') /* exe name */
735 break;
736 if (VG_STREQ(argv[vg_argc], "--")) { /* dummy arg */
737 vg_argc++;
738 break;
739 }
740 }
741 cl_argv = &argv[vg_argc];
742
743 /* Get extra args from VALGRIND_OPTS and .valgrindrc files.
744 * Note we don't do this if getting args from VALGRINDCLO. */
745 augment_command_line(&vg_argc, &vg_argv);
746 }
747
748 if (0) {
749 Int i;
750 for (i = 0; i < vg_argc; i++)
751 printf("vg_argv[%d]=\"%s\"\n", i, vg_argv[i]);
752 }
753
754 *vg_argc_out = vg_argc;
755 *vg_argv_out = (Char**)vg_argv;
756 *cl_argv_out = cl_argv;
757}
758
759
760/*====================================================================*/
761/*=== Environment and stack setup ===*/
762/*====================================================================*/
763
764/* Scan a colon-separated list, and call a function on each element.
765 The string must be mutable, because we insert a temporary '\0', but
thughes4ad52d02004-06-27 17:37:21 +0000766 the string will end up unmodified. (*func) should return True if it
nethercote71980f02004-01-24 18:18:54 +0000767 doesn't need to see any more.
thughes4ad52d02004-06-27 17:37:21 +0000768
769 This routine will return True if (*func) returns True and False if
770 it reaches the end of the list without that happening.
nethercote71980f02004-01-24 18:18:54 +0000771*/
thughes4ad52d02004-06-27 17:37:21 +0000772static Bool scan_colsep(char *colsep, Bool (*func)(const char *))
nethercote71980f02004-01-24 18:18:54 +0000773{
774 char *cp, *entry;
775 int end;
776
777 if (colsep == NULL ||
778 *colsep == '\0')
thughes4ad52d02004-06-27 17:37:21 +0000779 return False;
nethercote71980f02004-01-24 18:18:54 +0000780
781 entry = cp = colsep;
782
783 do {
784 end = (*cp == '\0');
785
786 if (*cp == ':' || *cp == '\0') {
787 char save = *cp;
788
789 *cp = '\0';
thughes21942d92004-07-12 09:35:37 +0000790 if ((*func)(entry)) {
791 *cp = save;
thughes4ad52d02004-06-27 17:37:21 +0000792 return True;
thughes21942d92004-07-12 09:35:37 +0000793 }
nethercote71980f02004-01-24 18:18:54 +0000794 *cp = save;
795 entry = cp+1;
796 }
797 cp++;
798 } while(!end);
thughes4ad52d02004-06-27 17:37:21 +0000799
800 return False;
801}
802
803static Bool contains(const char *p) {
804 if (VG_STREQ(p, VG_(libdir))) {
805 return True;
806 }
807 return False;
nethercote71980f02004-01-24 18:18:54 +0000808}
809
810/* Prepare the client's environment. This is basically a copy of our
811 environment, except:
812 1. LD_LIBRARY_PATH=$VALGRINDLIB:$LD_LIBRARY_PATH
813 2. LD_PRELOAD=$VALGRINDLIB/vg_inject.so:($VALGRINDLIB/vgpreload_TOOL.so:)?$LD_PRELOAD
814
815 If any of these is missing, then it is added.
816
817 Yummy. String hacking in C.
818
819 If this needs to handle any more variables it should be hacked
820 into something table driven.
821 */
822static char **fix_environment(char **origenv, const char *preload)
823{
824 static const char inject_so[] = "vg_inject.so";
825 static const char ld_library_path[] = "LD_LIBRARY_PATH=";
826 static const char ld_preload[] = "LD_PRELOAD=";
827 static const char valgrind_clo[] = VALGRINDCLO "=";
828 static const int ld_library_path_len = sizeof(ld_library_path)-1;
829 static const int ld_preload_len = sizeof(ld_preload)-1;
830 static const int valgrind_clo_len = sizeof(valgrind_clo)-1;
831 int ld_preload_done = 0;
832 int ld_library_path_done = 0;
833 char *inject_path;
834 int inject_path_len;
835 int vgliblen = strlen(VG_(libdir));
836 char **cpp;
837 char **ret;
838 int envc;
839 const int preloadlen = (preload == NULL) ? 0 : strlen(preload);
840
841 /* Find the vg_inject.so; also make room for the tool preload
842 library */
843 inject_path_len = sizeof(inject_so) + vgliblen + preloadlen + 16;
844 inject_path = malloc(inject_path_len);
845
846 if (preload)
847 snprintf(inject_path, inject_path_len, "%s/%s:%s",
848 VG_(libdir), inject_so, preload);
849 else
850 snprintf(inject_path, inject_path_len, "%s/%s",
851 VG_(libdir), inject_so);
852
853 /* Count the original size of the env */
854 envc = 0; /* trailing NULL */
855 for (cpp = origenv; cpp && *cpp; cpp++)
856 envc++;
857
858 /* Allocate a new space */
859 ret = malloc(sizeof(char *) * (envc+3+1)); /* 3 new entries + NULL */
860
861 /* copy it over */
862 for (cpp = ret; *origenv; )
863 *cpp++ = *origenv++;
864 *cpp = NULL;
865
866 vg_assert(envc == (cpp - ret));
867
868 /* Walk over the new environment, mashing as we go */
869 for (cpp = ret; cpp && *cpp; cpp++) {
870 if (memcmp(*cpp, ld_library_path, ld_library_path_len) == 0) {
nethercote71980f02004-01-24 18:18:54 +0000871 /* If the LD_LIBRARY_PATH already contains libdir, then don't
872 bother adding it again, even if it isn't the first (it
873 seems that the Java runtime will keep reexecing itself
874 unless its paths are at the front of LD_LIBRARY_PATH) */
thughes4ad52d02004-06-27 17:37:21 +0000875 if (!scan_colsep(*cpp + ld_library_path_len, contains)) {
nethercote71980f02004-01-24 18:18:54 +0000876 int len = strlen(*cpp) + vgliblen*2 + 16;
877 char *cp = malloc(len);
878
879 snprintf(cp, len, "%s%s:%s",
880 ld_library_path, VG_(libdir),
881 (*cpp)+ld_library_path_len);
882
883 *cpp = cp;
884 }
885
886 ld_library_path_done = 1;
887 } else if (memcmp(*cpp, ld_preload, ld_preload_len) == 0) {
888 int len = strlen(*cpp) + inject_path_len;
889 char *cp = malloc(len);
890
891 snprintf(cp, len, "%s%s:%s",
892 ld_preload, inject_path, (*cpp)+ld_preload_len);
893
894 *cpp = cp;
895
896 ld_preload_done = 1;
897 } else if (memcmp(*cpp, valgrind_clo, valgrind_clo_len) == 0) {
898 *cpp = "";
899 }
900 }
901
902 /* Add the missing bits */
903
904 if (!ld_library_path_done) {
905 int len = ld_library_path_len + vgliblen*2 + 16;
906 char *cp = malloc(len);
907
908 snprintf(cp, len, "%s%s", ld_library_path, VG_(libdir));
909
910 ret[envc++] = cp;
911 }
912
913 if (!ld_preload_done) {
914 int len = ld_preload_len + inject_path_len;
915 char *cp = malloc(len);
916
917 snprintf(cp, len, "%s%s",
918 ld_preload, inject_path);
919
920 ret[envc++] = cp;
921 }
922
923 ret[envc] = NULL;
924
925 return ret;
926}
927
928extern char **environ; /* our environment */
929//#include <error.h>
930
931/* Add a string onto the string table, and return its address */
932static char *copy_str(char **tab, const char *str)
933{
934 char *cp = *tab;
935 char *orig = cp;
936
937 while(*str)
938 *cp++ = *str++;
939 *cp++ = '\0';
940
941 if (0)
nethercotef84f6952004-07-15 14:58:33 +0000942 printf("copied %p \"%s\" len %d\n", orig, orig, cp-orig);
nethercote71980f02004-01-24 18:18:54 +0000943
944 *tab = cp;
945
946 return orig;
947}
948
949/*
950 This sets up the client's initial stack, containing the args,
951 environment and aux vector.
952
953 The format of the stack is:
954
955 higher address +-----------------+
956 | Trampoline code |
957 +-----------------+
958 | |
959 : string table :
960 | |
961 +-----------------+
962 | AT_NULL |
963 - -
964 | auxv |
965 +-----------------+
966 | NULL |
967 - -
968 | envp |
969 +-----------------+
970 | NULL |
971 - -
972 | argv |
973 +-----------------+
974 | argc |
975 lower address +-----------------+ <- esp
976 | undefined |
977 : :
978 */
979static Addr setup_client_stack(char **orig_argv, char **orig_envp,
980 const struct exeinfo *info,
981 UInt** client_auxv)
982{
nethercotee567e702004-07-10 17:49:17 +0000983 void* res;
nethercote71980f02004-01-24 18:18:54 +0000984 char **cpp;
985 char *strtab; /* string table */
986 char *stringbase;
987 addr_t *ptr;
988 struct ume_auxv *auxv;
989 const struct ume_auxv *orig_auxv;
990 const struct ume_auxv *cauxv;
991 unsigned stringsize; /* total size of strings in bytes */
992 unsigned auxsize; /* total size of auxv in bytes */
993 int argc; /* total argc */
994 int envc; /* total number of env vars */
995 unsigned stacksize; /* total client stack size */
996 addr_t cl_esp; /* client stack base (initial esp) */
997
998 /* use our own auxv as a prototype */
999 orig_auxv = find_auxv(ume_exec_esp);
1000
1001 /* ==================== compute sizes ==================== */
1002
1003 /* first of all, work out how big the client stack will be */
1004 stringsize = 0;
1005
1006 /* paste on the extra args if the loader needs them (ie, the #!
1007 interpreter and its argument) */
1008 argc = 0;
1009 if (info->argv0 != NULL) {
1010 argc++;
1011 stringsize += strlen(info->argv0) + 1;
1012 }
1013 if (info->argv1 != NULL) {
1014 argc++;
1015 stringsize += strlen(info->argv1) + 1;
1016 }
1017
1018 /* now scan the args we're given... */
1019 for (cpp = orig_argv; *cpp; cpp++) {
1020 argc++;
1021 stringsize += strlen(*cpp) + 1;
1022 }
1023
1024 /* ...and the environment */
1025 envc = 0;
1026 for (cpp = orig_envp; cpp && *cpp; cpp++) {
1027 envc++;
1028 stringsize += strlen(*cpp) + 1;
1029 }
1030
1031 /* now, how big is the auxv? */
1032 auxsize = sizeof(*auxv); /* there's always at least one entry: AT_NULL */
1033 for (cauxv = orig_auxv; cauxv->a_type != AT_NULL; cauxv++) {
1034 if (cauxv->a_type == AT_PLATFORM)
1035 stringsize += strlen(cauxv->u.a_ptr) + 1;
1036 auxsize += sizeof(*cauxv);
1037 }
1038
1039 /* OK, now we know how big the client stack is */
1040 stacksize =
1041 sizeof(int) + /* argc */
1042 sizeof(char **)*argc + /* argv */
1043 sizeof(char **) + /* terminal NULL */
1044 sizeof(char **)*envc + /* envp */
1045 sizeof(char **) + /* terminal NULL */
1046 auxsize + /* auxv */
1047 ROUNDUP(stringsize, sizeof(int)) +/* strings (aligned) */
1048 VKI_BYTES_PER_PAGE; /* page for trampoline code */
1049
nethercotef84f6952004-07-15 14:58:33 +00001050 // decide where stack goes!
1051 VG_(clstk_end) = VG_(client_end);
1052
1053 VG_(client_trampoline_code) = VG_(clstk_end) - VKI_BYTES_PER_PAGE;
1054
nethercote71980f02004-01-24 18:18:54 +00001055 /* cl_esp is the client's stack pointer */
nethercotef84f6952004-07-15 14:58:33 +00001056 cl_esp = VG_(clstk_end) - stacksize;
nethercote71980f02004-01-24 18:18:54 +00001057 cl_esp = ROUNDDN(cl_esp, 16); /* make stack 16 byte aligned */
1058
nethercote71980f02004-01-24 18:18:54 +00001059 /* base of the string table (aligned) */
1060 stringbase = strtab = (char *)(VG_(client_trampoline_code) - ROUNDUP(stringsize, sizeof(int)));
1061
1062 VG_(clstk_base) = PGROUNDDN(cl_esp);
nethercote71980f02004-01-24 18:18:54 +00001063
nethercote5ee67ca2004-06-22 14:00:09 +00001064 if (0)
1065 printf("stringsize=%d auxsize=%d stacksize=%d\n"
1066 "clstk_base %x\n"
1067 "clstk_end %x\n",
1068 stringsize, auxsize, stacksize, VG_(clstk_base), VG_(clstk_end));
1069
1070
nethercote71980f02004-01-24 18:18:54 +00001071 /* ==================== allocate space ==================== */
1072
1073 /* allocate a stack - mmap enough space for the stack */
nethercotef84f6952004-07-15 14:58:33 +00001074 res = mmap((void *)PGROUNDDN(cl_esp), VG_(clstk_end) - PGROUNDDN(cl_esp),
nethercotee567e702004-07-10 17:49:17 +00001075 PROT_READ | PROT_WRITE | PROT_EXEC,
1076 MAP_PRIVATE | MAP_ANON | MAP_FIXED, -1, 0);
1077 vg_assert((void*)-1 != res);
nethercote71980f02004-01-24 18:18:54 +00001078
1079 /* ==================== copy client stack ==================== */
1080
1081 ptr = (addr_t *)cl_esp;
1082
1083 /* --- argc --- */
1084 *ptr++ = argc; /* client argc */
1085
1086 /* --- argv --- */
1087 if (info->argv0) {
1088 *ptr++ = (addr_t)copy_str(&strtab, info->argv0);
1089 free(info->argv0);
1090 }
1091 if (info->argv1) {
1092 *ptr++ = (addr_t)copy_str(&strtab, info->argv1);
1093 free(info->argv1);
1094 }
1095 for (cpp = orig_argv; *cpp; ptr++, cpp++) {
1096 *ptr = (addr_t)copy_str(&strtab, *cpp);
1097 }
1098 *ptr++ = 0;
1099
1100 /* --- envp --- */
1101 VG_(client_envp) = (Char **)ptr;
1102 for (cpp = orig_envp; cpp && *cpp; ptr++, cpp++)
1103 *ptr = (addr_t)copy_str(&strtab, *cpp);
1104 *ptr++ = 0;
1105
1106 /* --- auxv --- */
1107 auxv = (struct ume_auxv *)ptr;
1108 *client_auxv = (UInt *)auxv;
1109
1110 for (; orig_auxv->a_type != AT_NULL; auxv++, orig_auxv++) {
1111 /* copy the entry... */
1112 *auxv = *orig_auxv;
1113
1114 /* ...and fix up the copy */
1115 switch(auxv->a_type) {
1116 case AT_PHDR:
1117 if (info->phdr == 0)
1118 auxv->a_type = AT_IGNORE;
1119 else
1120 auxv->u.a_val = info->phdr;
1121 break;
1122
1123 case AT_PHNUM:
1124 if (info->phdr == 0)
1125 auxv->a_type = AT_IGNORE;
1126 else
1127 auxv->u.a_val = info->phnum;
1128 break;
1129
1130 case AT_BASE:
1131 if (info->interp_base == 0)
1132 auxv->a_type = AT_IGNORE;
1133 else
1134 auxv->u.a_val = info->interp_base;
1135 break;
1136
1137 case AT_PLATFORM: /* points to a platform description string */
1138 auxv->u.a_ptr = copy_str(&strtab, orig_auxv->u.a_ptr);
1139 break;
1140
1141 case AT_ENTRY:
1142 auxv->u.a_val = info->entry;
1143 break;
1144
1145 case AT_IGNORE:
1146 case AT_EXECFD:
1147 case AT_PHENT:
1148 case AT_PAGESZ:
1149 case AT_FLAGS:
1150 case AT_NOTELF:
1151 case AT_UID:
1152 case AT_EUID:
1153 case AT_GID:
1154 case AT_EGID:
1155 case AT_CLKTCK:
1156 case AT_HWCAP:
1157 case AT_FPUCW:
1158 case AT_DCACHEBSIZE:
1159 case AT_ICACHEBSIZE:
1160 case AT_UCACHEBSIZE:
1161 /* All these are pointerless, so we don't need to do anything
1162 about them. */
1163 break;
1164
1165 case AT_SECURE:
1166 /* If this is 1, then it means that this program is running
1167 suid, and therefore the dynamic linker should be careful
1168 about LD_PRELOAD, etc. However, since stage1 (the thing
1169 the kernel actually execve's) should never be SUID, and we
1170 need LD_PRELOAD/LD_LIBRARY_PATH to work for the client, we
1171 set AT_SECURE to 0. */
1172 auxv->u.a_val = 0;
1173 break;
1174
1175 case AT_SYSINFO:
1176 /* Leave this unmolested for now, but we'll update it later
1177 when we set up the client trampoline code page */
1178 break;
1179
1180 case AT_SYSINFO_EHDR:
1181 /* Trash this, because we don't reproduce it */
1182 auxv->a_type = AT_IGNORE;
1183 break;
1184
1185 default:
1186 /* stomp out anything we don't know about */
1187 if (0)
1188 printf("stomping auxv entry %d\n", auxv->a_type);
1189 auxv->a_type = AT_IGNORE;
1190 break;
1191
1192 }
1193 }
1194 *auxv = *orig_auxv;
1195 vg_assert(auxv->a_type == AT_NULL);
1196
nethercotef84f6952004-07-15 14:58:33 +00001197 /* --- trampoline page --- */
1198 VG_(memcpy)( (void *)VG_(client_trampoline_code),
1199 &VG_(trampoline_code_start), VG_(trampoline_code_length) );
1200
nethercote71980f02004-01-24 18:18:54 +00001201 vg_assert((strtab-stringbase) == stringsize);
1202
nethercote5ee67ca2004-06-22 14:00:09 +00001203 /* We know the initial ESP is pointing at argc/argv */
1204 VG_(client_argc) = *(Int*)cl_esp;
1205 VG_(client_argv) = (Char**)(cl_esp + sizeof(Int));
1206
nethercote71980f02004-01-24 18:18:54 +00001207 return cl_esp;
1208}
1209
1210/*====================================================================*/
1211/*=== Find executable ===*/
1212/*====================================================================*/
1213
thughes4ad52d02004-06-27 17:37:21 +00001214static const char* executable_name;
1215
1216static Bool match_executable(const char *entry) {
1217 char buf[strlen(entry) + strlen(executable_name) + 2];
1218
1219 /* empty PATH element means . */
1220 if (*entry == '\0')
1221 entry = ".";
1222
1223 snprintf(buf, sizeof(buf), "%s/%s", entry, executable_name);
1224
1225 if (access(buf, R_OK|X_OK) == 0) {
1226 executable_name = strdup(buf);
1227 vg_assert(NULL != executable_name);
1228 return True;
1229 }
1230 return False;
1231}
1232
nethercote71980f02004-01-24 18:18:54 +00001233static const char* find_executable(const char* exec)
1234{
1235 vg_assert(NULL != exec);
thughes4ad52d02004-06-27 17:37:21 +00001236 executable_name = exec;
1237 if (strchr(executable_name, '/') == NULL) {
nethercote71980f02004-01-24 18:18:54 +00001238 /* no '/' - we need to search the path */
1239 char *path = getenv("PATH");
thughes4ad52d02004-06-27 17:37:21 +00001240 scan_colsep(path, match_executable);
nethercote71980f02004-01-24 18:18:54 +00001241 }
thughes4ad52d02004-06-27 17:37:21 +00001242 return executable_name;
nethercote71980f02004-01-24 18:18:54 +00001243}
1244
1245
1246/*====================================================================*/
1247/*=== Loading tools ===*/
1248/*====================================================================*/
1249
1250static void list_tools(void)
1251{
1252 DIR *dir = opendir(VG_(libdir));
1253 struct dirent *de;
1254 int first = 1;
1255
1256 if (dir == NULL) {
1257 fprintf(stderr, "Can't open %s: %s (installation problem?)\n",
nethercotef4928da2004-06-15 10:54:40 +00001258 VG_(libdir), strerror(errno));
nethercote71980f02004-01-24 18:18:54 +00001259 return;
1260 }
1261
nethercotef4928da2004-06-15 10:54:40 +00001262 while ((de = readdir(dir)) != NULL) {
nethercote71980f02004-01-24 18:18:54 +00001263 int len = strlen(de->d_name);
1264
1265 /* look for vgskin_TOOL.so names */
1266 if (len > (7+1+3) && /* "vgskin_" + at least 1-char toolname + ".so" */
nethercotef4928da2004-06-15 10:54:40 +00001267 strncmp(de->d_name, "vgskin_", 7) == 0 &&
1268 VG_STREQ(de->d_name + len - 3, ".so")) {
1269 if (first) {
1270 fprintf(stderr, "Available tools:\n");
1271 first = 0;
1272 }
1273 de->d_name[len-3] = '\0';
1274 fprintf(stderr, "\t%s\n", de->d_name+7);
nethercote71980f02004-01-24 18:18:54 +00001275 }
1276 }
1277
1278 closedir(dir);
1279
1280 if (first)
nethercotef4928da2004-06-15 10:54:40 +00001281 fprintf(stderr, "No tools available in \"%s\" (installation problem?)\n",
1282 VG_(libdir));
nethercote71980f02004-01-24 18:18:54 +00001283}
1284
1285
1286/* Find and load a tool, and check it looks ok. Also looks to see if there's
1287 * a matching vgpreload_*.so file, and returns its name in *preloadpath. */
1288static void load_tool( const char *toolname, void** handle_out,
1289 ToolInfo** toolinfo_out, char **preloadpath_out )
1290{
1291 Bool ok;
1292 int len = strlen(VG_(libdir)) + strlen(toolname)*2 + 16;
1293 char buf[len];
1294 void* handle;
1295 ToolInfo* toolinfo;
1296 char* preloadpath = NULL;
1297 Int* vg_malloc_redzonep;
1298
1299 // XXX: allowing full paths for --tool option -- does it make sense?
1300 // Doesn't allow for vgpreload_<tool>.so.
1301
1302 if (strchr(toolname, '/') != 0) {
1303 /* toolname contains '/', and so must be a pathname */
1304 handle = dlopen(toolname, RTLD_NOW);
1305 } else {
1306 /* just try in the libdir */
1307 snprintf(buf, len, "%s/vgskin_%s.so", VG_(libdir), toolname);
1308 handle = dlopen(buf, RTLD_NOW);
1309
1310 if (handle != NULL) {
1311 snprintf(buf, len, "%s/vgpreload_%s.so", VG_(libdir), toolname);
1312 if (access(buf, R_OK) == 0) {
1313 preloadpath = strdup(buf);
1314 vg_assert(NULL != preloadpath);
1315 }
1316 }
1317 }
1318
1319 ok = (NULL != handle);
1320 if (!ok) {
1321 fprintf(stderr, "Can't open tool \"%s\": %s\n", toolname, dlerror());
1322 goto bad_load;
1323 }
1324
1325 toolinfo = dlsym(handle, "vgSkin_tool_info");
1326 ok = (NULL != toolinfo);
1327 if (!ok) {
1328 fprintf(stderr, "Tool \"%s\" doesn't define SK_(tool_info) - "
1329 "add VG_DETERMINE_INTERFACE_VERSION?\n", toolname);
1330 goto bad_load;
1331 }
1332
1333 ok = (toolinfo->sizeof_ToolInfo == sizeof(*toolinfo) &&
1334 toolinfo->interface_major_version == VG_CORE_INTERFACE_MAJOR_VERSION &&
1335 toolinfo->sk_pre_clo_init != NULL);
1336 if (!ok) {
1337 fprintf(stderr, "Error:\n"
1338 " Tool and core interface versions do not match.\n"
1339 " Interface version used by core is: %d.%d (size %d)\n"
1340 " Interface version used by tool is: %d.%d (size %d)\n"
1341 " The major version numbers must match.\n",
1342 VG_CORE_INTERFACE_MAJOR_VERSION,
1343 VG_CORE_INTERFACE_MINOR_VERSION,
1344 sizeof(*toolinfo),
1345 toolinfo->interface_major_version,
1346 toolinfo->interface_minor_version,
1347 toolinfo->sizeof_ToolInfo);
1348 fprintf(stderr, " You need to at least recompile, and possibly update,\n");
1349 if (VG_CORE_INTERFACE_MAJOR_VERSION > toolinfo->interface_major_version)
1350 fprintf(stderr, " your skin to work with this version of Valgrind.\n");
1351 else
1352 fprintf(stderr, " your version of Valgrind to work with this skin.\n");
1353 goto bad_load;
1354 }
1355
1356 // Set redzone size for V's allocator
1357 vg_malloc_redzonep = dlsym(handle, STR(VG_(vg_malloc_redzone_szB)));
1358 if ( NULL != vg_malloc_redzonep ) {
1359 VG_(vg_malloc_redzone_szB) = *vg_malloc_redzonep;
1360 }
1361
1362 vg_assert(NULL != handle && NULL != toolinfo);
1363 *handle_out = handle;
1364 *toolinfo_out = toolinfo;
1365 *preloadpath_out = preloadpath;
1366 return;
1367
1368
1369 bad_load:
1370 if (handle != NULL)
1371 dlclose(handle);
1372
nethercotef4928da2004-06-15 10:54:40 +00001373 fprintf(stderr, "valgrind: couldn't load tool\n");
nethercote71980f02004-01-24 18:18:54 +00001374 list_tools();
1375 exit(127);
1376}
1377
nethercotef4928da2004-06-15 10:54:40 +00001378
1379/*====================================================================*/
1380/*=== Command line errors ===*/
1381/*====================================================================*/
1382
1383static void abort_msg ( void )
1384{
nethercotef8548672004-06-21 12:42:35 +00001385 VG_(clo_log_to) = VgLogTo_Fd;
1386 VG_(clo_log_fd) = 2; /* stderr */
nethercotef4928da2004-06-15 10:54:40 +00001387}
1388
1389void VG_(bad_option) ( Char* opt )
1390{
1391 abort_msg();
1392 VG_(printf)("valgrind: Bad option `%s'; aborting.\n", opt);
1393 VG_(printf)("valgrind: Use --help for more information.\n");
1394 VG_(exit)(1);
1395}
1396
1397static void missing_tool_option ( void )
1398{
1399 abort_msg();
1400 VG_(printf)("valgrind: Missing --tool option\n");
1401 list_tools();
1402 VG_(printf)("valgrind: Use --help for more information.\n");
1403 VG_(exit)(1);
1404}
1405
1406static void missing_prog ( void )
1407{
1408 abort_msg();
1409 VG_(printf)("valgrind: no program specified\n");
1410 VG_(printf)("valgrind: Use --help for more information.\n");
1411 VG_(exit)(1);
1412}
1413
1414static void config_error ( Char* msg )
1415{
1416 abort_msg();
1417 VG_(printf)("valgrind: Startup or configuration error:\n %s\n", msg);
1418 VG_(printf)("valgrind: Unable to start up properly. Giving up.\n");
1419 VG_(exit)(1);
1420}
1421
1422
nethercote71980f02004-01-24 18:18:54 +00001423/*====================================================================*/
1424/*=== Loading the client ===*/
1425/*====================================================================*/
1426
nethercotef4928da2004-06-15 10:54:40 +00001427static void load_client(char* cl_argv[], const char* exec, Int need_help,
nethercote71980f02004-01-24 18:18:54 +00001428 /*out*/struct exeinfo* info, /*out*/Addr* client_eip)
1429{
1430 // If they didn't specify an executable with --exec, and didn't specify
1431 // --help, then use client argv[0] (searching $PATH if necessary).
nethercotef4928da2004-06-15 10:54:40 +00001432 if (NULL == exec && !need_help) {
nethercote71980f02004-01-24 18:18:54 +00001433 if (cl_argv[0] == NULL ||
1434 ( NULL == (exec = find_executable(cl_argv[0])) ) )
1435 {
nethercotef4928da2004-06-15 10:54:40 +00001436 missing_prog();
nethercote71980f02004-01-24 18:18:54 +00001437 }
1438 }
1439
1440 info->map_base = VG_(client_mapbase);
nethercote71980f02004-01-24 18:18:54 +00001441
1442 info->exe_base = VG_(client_base);
1443 info->exe_end = VG_(client_end);
1444 info->argv = cl_argv;
1445
nethercotef4928da2004-06-15 10:54:40 +00001446 if (need_help) {
nethercote71980f02004-01-24 18:18:54 +00001447 VG_(clexecfd) = -1;
1448 info->argv0 = NULL;
1449 info->argv1 = NULL;
1450 } else {
1451 Int ret;
1452 VG_(clexecfd) = VG_(open)(exec, O_RDONLY, VKI_S_IRUSR);
1453 ret = do_exec(exec, info);
1454 if (ret != 0) {
nethercotef4928da2004-06-15 10:54:40 +00001455 fprintf(stderr, "valgrind: do_exec(%s) failed: %s\n", exec, strerror(ret));
nethercote71980f02004-01-24 18:18:54 +00001456 exit(127);
1457 }
1458 }
1459
1460 /* Copy necessary bits of 'info' that were filled in */
1461 *client_eip = info->init_eip;
1462 VG_(brk_base) = VG_(brk_limit) = info->brkbase;
1463}
1464
1465
1466/*====================================================================*/
1467/*=== Command-line: variables, processing ===*/
1468/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +00001469
njn25e49d8e72002-09-23 09:36:25 +00001470/* Define, and set defaults. */
1471Bool VG_(clo_error_limit) = True;
nethercote04d0fbc2004-01-26 16:48:06 +00001472Bool VG_(clo_db_attach) = False;
1473Char* VG_(clo_db_command) = VG_CLO_DEFAULT_DBCOMMAND;
njn43c799e2003-04-08 00:08:52 +00001474Bool VG_(clo_gen_suppressions) = False;
nethercote27fec902004-06-16 21:26:32 +00001475Int VG_(clo_sanity_level) = 1;
njn25e49d8e72002-09-23 09:36:25 +00001476Int VG_(clo_verbosity) = 1;
1477Bool VG_(clo_demangle) = True;
njn25e49d8e72002-09-23 09:36:25 +00001478Bool VG_(clo_trace_children) = False;
sewardj4cf05692002-10-27 20:28:29 +00001479
nethercotee1730692003-11-20 10:38:07 +00001480/* See big comment in vg_include.h for meaning of these three.
1481 fd is initially stdout, for --help, but gets moved to stderr by default
1482 immediately afterwards. */
sewardj4cf05692002-10-27 20:28:29 +00001483VgLogTo VG_(clo_log_to) = VgLogTo_Fd;
nethercotef8548672004-06-21 12:42:35 +00001484Int VG_(clo_log_fd) = 1;
1485Char* VG_(clo_log_name) = NULL;
sewardj4cf05692002-10-27 20:28:29 +00001486
sewardj6024b212003-07-13 10:54:33 +00001487Int VG_(clo_input_fd) = 0; /* stdin */
njn25e49d8e72002-09-23 09:36:25 +00001488Int VG_(clo_n_suppressions) = 0;
sewardjde4a1d02002-03-22 01:27:54 +00001489Char* VG_(clo_suppressions)[VG_CLO_MAX_SFILES];
njn25e49d8e72002-09-23 09:36:25 +00001490Bool VG_(clo_profile) = False;
1491Bool VG_(clo_single_step) = False;
1492Bool VG_(clo_optimise) = True;
1493UChar VG_(clo_trace_codegen) = 0; // 00000000b
1494Bool VG_(clo_trace_syscalls) = False;
1495Bool VG_(clo_trace_signals) = False;
1496Bool VG_(clo_trace_symtab) = False;
njn25e49d8e72002-09-23 09:36:25 +00001497Bool VG_(clo_trace_sched) = False;
1498Int VG_(clo_trace_pthread_level) = 0;
njn25e49d8e72002-09-23 09:36:25 +00001499Int VG_(clo_dump_error) = 0;
1500Int VG_(clo_backtrace_size) = 4;
1501Char* VG_(clo_weird_hacks) = NULL;
sewardj858964b2002-10-05 14:15:43 +00001502Bool VG_(clo_run_libc_freeres) = True;
rjwalshf5f536f2003-11-17 17:45:00 +00001503Bool VG_(clo_track_fds) = False;
sewardj22854b92002-11-30 14:00:47 +00001504Bool VG_(clo_chain_bb) = True;
nethercote77eba602003-11-13 17:35:04 +00001505Bool VG_(clo_show_below_main) = False;
fitzhardinge98abfc72003-12-16 02:05:15 +00001506Bool VG_(clo_pointercheck) = True;
fitzhardinge462f4f92003-12-18 02:10:54 +00001507Bool VG_(clo_branchpred) = False;
sewardj2370f3b2002-11-30 15:01:01 +00001508
jsgf855d93d2003-10-13 22:26:55 +00001509static Bool VG_(clo_wait_for_gdb) = False;
1510
1511/* If we're doing signal routing, poll for signals every 50mS by
1512 default. */
1513Int VG_(clo_signal_polltime) = 50;
1514
1515/* These flags reduce thread wakeup latency on syscall completion and
1516 signal delivery, respectively. The downside is possible unfairness. */
1517Bool VG_(clo_lowlat_syscalls) = False; /* low-latency syscalls */
1518Bool VG_(clo_lowlat_signals) = False; /* low-latency signals */
1519
sewardjde4a1d02002-03-22 01:27:54 +00001520
nethercote6c999f22004-01-31 22:55:15 +00001521void usage ( Bool debug_help )
njn7cf0bd32002-06-08 13:36:03 +00001522{
njn25e49d8e72002-09-23 09:36:25 +00001523 Char* usage1 =
nethercote71980f02004-01-24 18:18:54 +00001524"usage: valgrind --tool=<toolname> [options] prog-and-args\n"
njn25e49d8e72002-09-23 09:36:25 +00001525"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001526" common user options for all Valgrind tools, with defaults in [ ]:\n"
nethercote0d588502004-06-21 13:27:11 +00001527" --tool=<name> use the Valgrind tool named <name>\n"
nethercotea76368b2004-06-16 11:56:29 +00001528" -h --help show this message\n"
nethercote6c999f22004-01-31 22:55:15 +00001529" --help-debug show this message, plus debugging options\n"
njn25e49d8e72002-09-23 09:36:25 +00001530" --version show version\n"
njn25e49d8e72002-09-23 09:36:25 +00001531" -q --quiet run silently; only print error msgs\n"
1532" -v --verbose be more verbose, incl counts of errors\n"
nethercote77eba602003-11-13 17:35:04 +00001533" --trace-children=no|yes Valgrind-ise child processes? [no]\n"
nethercote0d588502004-06-21 13:27:11 +00001534" --track-fds=no|yes track open file descriptors? [no]\n"
nethercote2b0793f2003-12-02 10:41:18 +00001535"\n"
1536" uncommon user options for all Valgrind tools:\n"
nethercote0d588502004-06-21 13:27:11 +00001537" --run-libc-freeres=no|yes free up glibc memory at exit? [yes]\n"
1538" --weird-hacks=hack1,hack2,... recognised hacks: lax-ioctls [none]\n"
1539" --signal-polltime=<time> signal poll period (mS) for older kernels [50]\n"
1540" --lowlat-signals=no|yes improve thread signal wake-up latency [no]\n"
1541" --lowlat-syscalls=no|yes improve thread syscall wake-up latency [no]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001542" --pointercheck=no|yes enforce client address space limits [yes]\n"
njn25e49d8e72002-09-23 09:36:25 +00001543"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001544" user options for Valgrind tools that report errors:\n"
nethercotef8548672004-06-21 12:42:35 +00001545" --log-fd=<number> log messages to file descriptor [2=stderr]\n"
1546" --log-file=<file> log messages to <file>.pid<pid>\n"
1547" --log-socket=ipaddr:port log messages to socket ipaddr:port\n"
nethercote2b0793f2003-12-02 10:41:18 +00001548" --demangle=no|yes automatically demangle C++ names? [yes]\n"
1549" --num-callers=<number> show <num> callers in stack traces [4]\n"
1550" --error-limit=no|yes stop showing new errors if too many? [yes]\n"
1551" --show-below-main=no|yes continue stack traces below main() [no]\n"
1552" --suppressions=<filename> suppress errors described in <filename>\n"
1553" --gen-suppressions=no|yes print suppressions for errors detected [no]\n"
nethercote04d0fbc2004-01-26 16:48:06 +00001554" --db-attach=no|yes start debugger when errors detected? [no]\n"
1555" --db-command=<command> command to start debugger [gdb -nw %%f %%p]\n"
1556" --input-fd=<number> file descriptor for input [0=stdin]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001557"\n";
njn7cf0bd32002-06-08 13:36:03 +00001558
njn25e49d8e72002-09-23 09:36:25 +00001559 Char* usage2 =
1560"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001561" debugging options for all Valgrind tools:\n"
njn25e49d8e72002-09-23 09:36:25 +00001562" --sanity-level=<number> level of sanity checking to do [1]\n"
1563" --single-step=no|yes translate each instr separately? [no]\n"
1564" --optimise=no|yes improve intermediate code? [yes]\n"
nethercote137bc552003-11-14 17:47:54 +00001565" --profile=no|yes profile? (tool must be built for it) [no]\n"
sewardj22854b92002-11-30 14:00:47 +00001566" --chain-bb=no|yes do basic-block chaining? [yes]\n"
fitzhardinge462f4f92003-12-18 02:10:54 +00001567" --branchpred=yes|no generate branch prediction hints [no]\n"
njn25e49d8e72002-09-23 09:36:25 +00001568" --trace-codegen=<XXXXX> show generated code? (X = 0|1) [00000]\n"
1569" --trace-syscalls=no|yes show all system calls? [no]\n"
1570" --trace-signals=no|yes show signal handling details? [no]\n"
1571" --trace-symtab=no|yes show symbol table details? [no]\n"
njn25e49d8e72002-09-23 09:36:25 +00001572" --trace-sched=no|yes show thread scheduler details? [no]\n"
njn3e884182003-04-15 13:03:23 +00001573" --trace-pthread=none|some|all show pthread event details? [none]\n"
jsgf855d93d2003-10-13 22:26:55 +00001574" --wait-for-gdb=yes|no pause on startup to wait for gdb attach\n"
njn25e49d8e72002-09-23 09:36:25 +00001575"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001576" debugging options for Valgrind tools that report errors\n"
1577" --dump-error=<number> show translation for basic block associated\n"
1578" with <number>'th error context [0=show none]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001579"\n";
njn3e884182003-04-15 13:03:23 +00001580
1581 Char* usage3 =
1582"\n"
nethercote71980f02004-01-24 18:18:54 +00001583" Extra options read from ~/.valgrindrc, $VALGRIND_OPTS, ./.valgrindrc\n"
njn25e49d8e72002-09-23 09:36:25 +00001584"\n"
nethercote08fa9a72004-07-16 17:44:00 +00001585" Valgrind is Copyright (C) 2000-2004 Julian Seward et al.\n"
njn25e49d8e72002-09-23 09:36:25 +00001586" and licensed under the GNU General Public License, version 2.\n"
1587" Bug reports, feedback, admiration, abuse, etc, to: %s.\n"
njnd04b7c62002-10-03 14:05:52 +00001588"\n"
nethercote137bc552003-11-14 17:47:54 +00001589" Tools are copyright and licensed by their authors. See each\n"
1590" tool's start-up message for more information.\n"
njn25e49d8e72002-09-23 09:36:25 +00001591"\n";
njn7cf0bd32002-06-08 13:36:03 +00001592
fitzhardinge98abfc72003-12-16 02:05:15 +00001593 VG_(printf)(usage1);
1594 if (VG_(details).name) {
1595 VG_(printf)(" user options for %s:\n", VG_(details).name);
fitzhardinge98abfc72003-12-16 02:05:15 +00001596 if (VG_(needs).command_line_options)
1597 SK_(print_usage)();
1598 else
1599 VG_(printf)(" (none)\n");
1600 }
nethercote6c999f22004-01-31 22:55:15 +00001601 if (debug_help) {
1602 VG_(printf)(usage2);
fitzhardinge98abfc72003-12-16 02:05:15 +00001603
nethercote6c999f22004-01-31 22:55:15 +00001604 if (VG_(details).name) {
1605 VG_(printf)(" debugging options for %s:\n", VG_(details).name);
1606
1607 if (VG_(needs).command_line_options)
1608 SK_(print_debug_usage)();
1609 else
1610 VG_(printf)(" (none)\n");
1611 }
fitzhardinge98abfc72003-12-16 02:05:15 +00001612 }
nethercote421281e2003-11-20 16:20:55 +00001613 VG_(printf)(usage3, VG_BUGS_TO);
nethercotef4928da2004-06-15 10:54:40 +00001614 VG_(exit)(0);
njn7cf0bd32002-06-08 13:36:03 +00001615}
sewardjde4a1d02002-03-22 01:27:54 +00001616
nethercote71980f02004-01-24 18:18:54 +00001617static void pre_process_cmd_line_options
nethercote6c999f22004-01-31 22:55:15 +00001618 ( Int* need_help, const char** tool, const char** exec )
sewardj1c1b1162003-02-23 01:25:51 +00001619{
nethercote71980f02004-01-24 18:18:54 +00001620 UInt i;
sewardjde4a1d02002-03-22 01:27:54 +00001621
nethercote71980f02004-01-24 18:18:54 +00001622 /* parse the options we have (only the options we care about now) */
1623 for (i = 1; i < VG_(vg_argc); i++) {
1624
1625 if (strcmp(VG_(vg_argv)[i], "--version") == 0) {
1626 printf("valgrind-" VERSION "\n");
nethercotef4928da2004-06-15 10:54:40 +00001627 exit(0);
nethercote71980f02004-01-24 18:18:54 +00001628
nethercotea76368b2004-06-16 11:56:29 +00001629 } else if (VG_CLO_STREQ(VG_(vg_argv)[i], "--help") ||
1630 VG_CLO_STREQ(VG_(vg_argv)[i], "-h")) {
nethercote6c999f22004-01-31 22:55:15 +00001631 *need_help = 1;
1632
nethercotef4928da2004-06-15 10:54:40 +00001633 } else if (VG_CLO_STREQ(VG_(vg_argv)[i], "--help-debug")) {
nethercote6c999f22004-01-31 22:55:15 +00001634 *need_help = 2;
nethercote71980f02004-01-24 18:18:54 +00001635
nethercotef4928da2004-06-15 10:54:40 +00001636 } else if (VG_CLO_STREQN(7, VG_(vg_argv)[i], "--tool=") ||
1637 VG_CLO_STREQN(7, VG_(vg_argv)[i], "--skin=")) {
nethercote71980f02004-01-24 18:18:54 +00001638 *tool = &VG_(vg_argv)[i][7];
1639
nethercotef4928da2004-06-15 10:54:40 +00001640 } else if (VG_CLO_STREQN(7, VG_(vg_argv)[i], "--exec=")) {
nethercote71980f02004-01-24 18:18:54 +00001641 *exec = &VG_(vg_argv)[i][7];
1642 }
1643 }
1644
nethercotef4928da2004-06-15 10:54:40 +00001645 /* If no tool specified, can act appropriately without loading tool */
nethercote71980f02004-01-24 18:18:54 +00001646 if (*tool == NULL) {
nethercotef4928da2004-06-15 10:54:40 +00001647 if (0 == *need_help) {
1648 // neither --tool nor --help/--help-debug specified
1649 missing_tool_option();
1650 } else {
1651 // Give help message, without any tool-specific help
1652 usage(/*help-debug?*/2 == *need_help);
1653 }
nethercote71980f02004-01-24 18:18:54 +00001654 }
1655}
1656
nethercote5ee67ca2004-06-22 14:00:09 +00001657static void process_cmd_line_options( UInt* client_auxv, const char* toolname )
nethercote71980f02004-01-24 18:18:54 +00001658{
nethercotef8548672004-06-21 12:42:35 +00001659 Int i, eventually_log_fd;
nethercote71980f02004-01-24 18:18:54 +00001660 Int *auxp;
1661 Int toolname_len = VG_(strlen)(toolname);
sewardjde4a1d02002-03-22 01:27:54 +00001662
nethercotee1730692003-11-20 10:38:07 +00001663 /* log to stderr by default, but usage message goes to stdout */
nethercotef8548672004-06-21 12:42:35 +00001664 eventually_log_fd = 2;
sewardjde4a1d02002-03-22 01:27:54 +00001665
sewardj19d81412002-06-03 01:10:40 +00001666 /* Check for sane path in ./configure --prefix=... */
fitzhardinge98abfc72003-12-16 02:05:15 +00001667 if (VG_LIBDIR[0] != '/')
sewardj19d81412002-06-03 01:10:40 +00001668 config_error("Please use absolute paths in "
1669 "./configure --prefix=... or --libdir=...");
sewardj38170912002-05-10 21:07:22 +00001670
nethercote71980f02004-01-24 18:18:54 +00001671 for (auxp = client_auxv; auxp[0] != VKI_AT_NULL; auxp += 2) {
fitzhardinge98abfc72003-12-16 02:05:15 +00001672 switch(auxp[0]) {
1673 case VKI_AT_SYSINFO:
1674 VG_(sysinfo_page_exists) = True;
fitzhardinge92360792003-12-24 10:11:11 +00001675 auxp[1] = (Int)(VG_(client_trampoline_code) + VG_(tramp_syscall_offset));
fitzhardinge98abfc72003-12-16 02:05:15 +00001676 VG_(sysinfo_page_addr) = auxp[1];
1677 break;
sewardjde4a1d02002-03-22 01:27:54 +00001678 }
fitzhardinge98abfc72003-12-16 02:05:15 +00001679 }
sewardjde4a1d02002-03-22 01:27:54 +00001680
nethercote71980f02004-01-24 18:18:54 +00001681 for (i = 1; i < VG_(vg_argc); i++) {
1682
1683 Char* arg = VG_(vg_argv)[i];
1684
1685 // XXX: allow colons in options, for Josef
1686
1687 /* Look for matching "--toolname:foo" */
1688 if (VG_(strstr)(arg, ":")) {
1689 if (VG_CLO_STREQN(2, arg, "--") &&
1690 VG_CLO_STREQN(toolname_len, arg+2, toolname) &&
1691 VG_CLO_STREQN(1, arg+2+toolname_len, ":"))
1692 {
1693 // prefix matches, convert "--toolname:foo" to "--foo"
1694 if (0)
1695 VG_(printf)("tool-specific arg: %s\n", arg);
1696 arg += toolname_len + 1;
1697 arg[0] = '-';
1698 arg[1] = '-';
1699
1700 } else {
1701 // prefix doesn't match, skip to next arg
1702 continue;
1703 }
1704 }
1705
fitzhardinge98abfc72003-12-16 02:05:15 +00001706 /* Ignore these options - they've already been handled */
nethercote71980f02004-01-24 18:18:54 +00001707 if (VG_CLO_STREQN(7, arg, "--tool=") ||
1708 VG_CLO_STREQN(7, arg, "--skin="))
fitzhardinge98abfc72003-12-16 02:05:15 +00001709 continue;
nethercote71980f02004-01-24 18:18:54 +00001710 if (VG_CLO_STREQN(7, arg, "--exec="))
fitzhardinge98abfc72003-12-16 02:05:15 +00001711 continue;
1712
nethercote71980f02004-01-24 18:18:54 +00001713 if ( VG_CLO_STREQ(arg, "--"))
fitzhardinge98abfc72003-12-16 02:05:15 +00001714 continue;
nethercote27fec902004-06-16 21:26:32 +00001715
nethercote71980f02004-01-24 18:18:54 +00001716 else if (VG_CLO_STREQ(arg, "-v") ||
1717 VG_CLO_STREQ(arg, "--verbose"))
sewardjde4a1d02002-03-22 01:27:54 +00001718 VG_(clo_verbosity)++;
nethercote27fec902004-06-16 21:26:32 +00001719
nethercote71980f02004-01-24 18:18:54 +00001720 else if (VG_CLO_STREQ(arg, "-q") ||
1721 VG_CLO_STREQ(arg, "--quiet"))
sewardjde4a1d02002-03-22 01:27:54 +00001722 VG_(clo_verbosity)--;
1723
nethercote27fec902004-06-16 21:26:32 +00001724 else VG_BOOL_CLO("--branchpred", VG_(clo_branchpred))
1725 else VG_BOOL_CLO("--chain-bb", VG_(clo_chain_bb))
1726 else VG_BOOL_CLO("--db-attach", VG_(clo_db_attach))
1727 else VG_BOOL_CLO("--demangle", VG_(clo_demangle))
1728 else VG_BOOL_CLO("--error-limit", VG_(clo_error_limit))
1729 else VG_BOOL_CLO("--gen-suppressions", VG_(clo_gen_suppressions))
1730 else VG_BOOL_CLO("--lowlat-signals", VG_(clo_lowlat_signals))
1731 else VG_BOOL_CLO("--lowlat-syscalls", VG_(clo_lowlat_syscalls))
1732 else VG_BOOL_CLO("--optimise", VG_(clo_optimise))
1733 else VG_BOOL_CLO("--pointercheck", VG_(clo_pointercheck))
1734 else VG_BOOL_CLO("--profile", VG_(clo_profile))
1735 else VG_BOOL_CLO("--run-libc-freeres", VG_(clo_run_libc_freeres))
1736 else VG_BOOL_CLO("--show-below-main", VG_(clo_show_below_main))
1737 else VG_BOOL_CLO("--single-step", VG_(clo_single_step))
1738 else VG_BOOL_CLO("--track-fds", VG_(clo_track_fds))
1739 else VG_BOOL_CLO("--trace-children", VG_(clo_trace_children))
1740 else VG_BOOL_CLO("--trace-sched", VG_(clo_trace_sched))
1741 else VG_BOOL_CLO("--trace-signals", VG_(clo_trace_signals))
1742 else VG_BOOL_CLO("--trace-symtab", VG_(clo_trace_symtab))
1743 else VG_BOOL_CLO("--trace-syscalls", VG_(clo_trace_syscalls))
1744 else VG_BOOL_CLO("--wait-for-gdb", VG_(clo_wait_for_gdb))
sewardj72f98ff2002-06-13 17:23:38 +00001745
nethercote27fec902004-06-16 21:26:32 +00001746 else VG_STR_CLO ("--db-command", VG_(clo_db_command))
1747 else VG_STR_CLO ("--weird-hacks", VG_(clo_weird_hacks))
sewardjde4a1d02002-03-22 01:27:54 +00001748
nethercote27fec902004-06-16 21:26:32 +00001749 else VG_NUM_CLO ("--dump-error", VG_(clo_dump_error))
1750 else VG_NUM_CLO ("--input-fd", VG_(clo_input_fd))
1751 else VG_NUM_CLO ("--sanity-level", VG_(clo_sanity_level))
1752 else VG_NUM_CLO ("--signal­polltime", VG_(clo_signal_polltime))
1753 else VG_BNUM_CLO("--num-callers", VG_(clo_backtrace_size), 1,
1754 VG_DEEPEST_BACKTRACE)
sewardjde4a1d02002-03-22 01:27:54 +00001755
nethercotef8548672004-06-21 12:42:35 +00001756 // for backwards compatibility, replaced by --log-fd
nethercote71980f02004-01-24 18:18:54 +00001757 else if (VG_CLO_STREQN(13, arg, "--logfile-fd=")) {
nethercotef8548672004-06-21 12:42:35 +00001758 VG_(clo_log_to) = VgLogTo_Fd;
1759 VG_(clo_log_name) = NULL;
1760 eventually_log_fd = (Int)VG_(atoll)(&arg[13]);
1761 }
1762 else if (VG_CLO_STREQN(9, arg, "--log-fd=")) {
1763 VG_(clo_log_to) = VgLogTo_Fd;
1764 VG_(clo_log_name) = NULL;
1765 eventually_log_fd = (Int)VG_(atoll)(&arg[9]);
sewardj4cf05692002-10-27 20:28:29 +00001766 }
1767
nethercotef8548672004-06-21 12:42:35 +00001768 // for backwards compatibility, replaced by --log-file
nethercote71980f02004-01-24 18:18:54 +00001769 else if (VG_CLO_STREQN(10, arg, "--logfile=")) {
nethercotef8548672004-06-21 12:42:35 +00001770 VG_(clo_log_to) = VgLogTo_File;
1771 VG_(clo_log_name) = &arg[10];
1772 }
1773 else if (VG_CLO_STREQN(11, arg, "--log-file=")) {
1774 VG_(clo_log_to) = VgLogTo_File;
1775 VG_(clo_log_name) = &arg[11];
sewardj4cf05692002-10-27 20:28:29 +00001776 }
sewardjde4a1d02002-03-22 01:27:54 +00001777
nethercotef8548672004-06-21 12:42:35 +00001778 // for backwards compatibility, replaced by --log-socket
nethercote71980f02004-01-24 18:18:54 +00001779 else if (VG_CLO_STREQN(12, arg, "--logsocket=")) {
nethercotef8548672004-06-21 12:42:35 +00001780 VG_(clo_log_to) = VgLogTo_Socket;
1781 VG_(clo_log_name) = &arg[12];
1782 }
1783 else if (VG_CLO_STREQN(13, arg, "--log-socket=")) {
1784 VG_(clo_log_to) = VgLogTo_Socket;
1785 VG_(clo_log_name) = &arg[13];
sewardj73cf3bc2002-11-03 03:20:15 +00001786 }
1787
nethercote71980f02004-01-24 18:18:54 +00001788 else if (VG_CLO_STREQN(15, arg, "--suppressions=")) {
sewardjde4a1d02002-03-22 01:27:54 +00001789 if (VG_(clo_n_suppressions) >= VG_CLO_MAX_SFILES) {
njn25e49d8e72002-09-23 09:36:25 +00001790 VG_(message)(Vg_UserMsg, "Too many suppression files specified.");
sewardjde4a1d02002-03-22 01:27:54 +00001791 VG_(message)(Vg_UserMsg,
1792 "Increase VG_CLO_MAX_SFILES and recompile.");
nethercote71980f02004-01-24 18:18:54 +00001793 VG_(bad_option)(arg);
sewardjde4a1d02002-03-22 01:27:54 +00001794 }
nethercote71980f02004-01-24 18:18:54 +00001795 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = &arg[15];
sewardjde4a1d02002-03-22 01:27:54 +00001796 VG_(clo_n_suppressions)++;
1797 }
sewardjde4a1d02002-03-22 01:27:54 +00001798
njn25e49d8e72002-09-23 09:36:25 +00001799 /* "vwxyz" --> 000zyxwv (binary) */
nethercote71980f02004-01-24 18:18:54 +00001800 else if (VG_CLO_STREQN(16, arg, "--trace-codegen=")) {
njn25e49d8e72002-09-23 09:36:25 +00001801 Int j;
nethercote71980f02004-01-24 18:18:54 +00001802 char* opt = & arg[16];
njn25e49d8e72002-09-23 09:36:25 +00001803
1804 if (5 != VG_(strlen)(opt)) {
1805 VG_(message)(Vg_UserMsg,
1806 "--trace-codegen argument must have 5 digits");
nethercote71980f02004-01-24 18:18:54 +00001807 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001808 }
1809 for (j = 0; j < 5; j++) {
1810 if ('0' == opt[j]) { /* do nothing */ }
1811 else if ('1' == opt[j]) VG_(clo_trace_codegen) |= (1 << j);
1812 else {
1813 VG_(message)(Vg_UserMsg, "--trace-codegen argument can only "
1814 "contain 0s and 1s");
nethercote71980f02004-01-24 18:18:54 +00001815 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001816 }
1817 }
1818 }
sewardjde4a1d02002-03-22 01:27:54 +00001819
nethercote71980f02004-01-24 18:18:54 +00001820 else if (VG_CLO_STREQ(arg, "--trace-pthread=none"))
sewardj45b4b372002-04-16 22:50:32 +00001821 VG_(clo_trace_pthread_level) = 0;
nethercote71980f02004-01-24 18:18:54 +00001822 else if (VG_CLO_STREQ(arg, "--trace-pthread=some"))
sewardj45b4b372002-04-16 22:50:32 +00001823 VG_(clo_trace_pthread_level) = 1;
nethercote71980f02004-01-24 18:18:54 +00001824 else if (VG_CLO_STREQ(arg, "--trace-pthread=all"))
sewardj45b4b372002-04-16 22:50:32 +00001825 VG_(clo_trace_pthread_level) = 2;
sewardj8937c812002-04-12 20:12:20 +00001826
nethercote71980f02004-01-24 18:18:54 +00001827 else if ( ! VG_(needs).command_line_options
1828 || ! SK_(process_cmd_line_option)(arg) ) {
nethercotef4928da2004-06-15 10:54:40 +00001829 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001830 }
sewardjde4a1d02002-03-22 01:27:54 +00001831 }
1832
nethercote27fec902004-06-16 21:26:32 +00001833 // Check various option values
1834
njnf9ebf672003-05-12 21:41:30 +00001835 if (VG_(clo_verbosity) < 0)
sewardjde4a1d02002-03-22 01:27:54 +00001836 VG_(clo_verbosity) = 0;
1837
nethercote04d0fbc2004-01-26 16:48:06 +00001838 if (VG_(clo_db_attach) && VG_(clo_trace_children)) {
sewardjde4a1d02002-03-22 01:27:54 +00001839 VG_(message)(Vg_UserMsg, "");
1840 VG_(message)(Vg_UserMsg,
nethercote04d0fbc2004-01-26 16:48:06 +00001841 "--db-attach=yes conflicts with --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001842 VG_(message)(Vg_UserMsg,
1843 "Please choose one or the other, but not both.");
nethercote04d0fbc2004-01-26 16:48:06 +00001844 VG_(bad_option)("--db-attach=yes and --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001845 }
1846
nethercotef8548672004-06-21 12:42:35 +00001847 /* Set up logging now. After this is done, VG_(clo_log_fd)
sewardj4cf05692002-10-27 20:28:29 +00001848 should be connected to whatever sink has been selected, and we
1849 indiscriminately chuck stuff into it without worrying what the
1850 nature of it is. Oh the wonder of Unix streams. */
1851
nethercotee1730692003-11-20 10:38:07 +00001852 /* So far we should be still attached to stdout, so we can show on
sewardj4cf05692002-10-27 20:28:29 +00001853 the terminal any problems to do with processing command line
1854 opts. */
nethercotef8548672004-06-21 12:42:35 +00001855 vg_assert(VG_(clo_log_fd) == 1 /* stdout */);
sewardj73cf3bc2002-11-03 03:20:15 +00001856 vg_assert(VG_(logging_to_filedes) == True);
sewardj4cf05692002-10-27 20:28:29 +00001857
1858 switch (VG_(clo_log_to)) {
sewardj73cf3bc2002-11-03 03:20:15 +00001859
sewardj4cf05692002-10-27 20:28:29 +00001860 case VgLogTo_Fd:
nethercotef8548672004-06-21 12:42:35 +00001861 vg_assert(VG_(clo_log_name) == NULL);
1862 VG_(clo_log_fd) = eventually_log_fd;
sewardj4cf05692002-10-27 20:28:29 +00001863 break;
sewardj73cf3bc2002-11-03 03:20:15 +00001864
sewardj4cf05692002-10-27 20:28:29 +00001865 case VgLogTo_File: {
1866 Char logfilename[1000];
jsgff3c3f1a2003-10-14 22:13:28 +00001867 Int seq = 0;
1868 Int pid = VG_(getpid)();
1869
nethercotef8548672004-06-21 12:42:35 +00001870 vg_assert(VG_(clo_log_name) != NULL);
1871 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
jsgff3c3f1a2003-10-14 22:13:28 +00001872
nethercote71980f02004-01-24 18:18:54 +00001873 for (;;) {
jsgff3c3f1a2003-10-14 22:13:28 +00001874 if (seq == 0)
1875 VG_(sprintf)(logfilename, "%s.pid%d",
nethercotef8548672004-06-21 12:42:35 +00001876 VG_(clo_log_name), pid );
jsgff3c3f1a2003-10-14 22:13:28 +00001877 else
1878 VG_(sprintf)(logfilename, "%s.pid%d.%d",
nethercotef8548672004-06-21 12:42:35 +00001879 VG_(clo_log_name), pid, seq );
jsgff3c3f1a2003-10-14 22:13:28 +00001880 seq++;
1881
nethercotef8548672004-06-21 12:42:35 +00001882 eventually_log_fd
jsgff3c3f1a2003-10-14 22:13:28 +00001883 = VG_(open)(logfilename,
1884 VKI_O_CREAT|VKI_O_WRONLY|VKI_O_EXCL|VKI_O_TRUNC,
1885 VKI_S_IRUSR|VKI_S_IWUSR);
nethercotef8548672004-06-21 12:42:35 +00001886 if (eventually_log_fd >= 0) {
1887 VG_(clo_log_fd) = VG_(safe_fd)(eventually_log_fd);
jsgff3c3f1a2003-10-14 22:13:28 +00001888 break;
1889 } else {
nethercotef8548672004-06-21 12:42:35 +00001890 if (eventually_log_fd != -VKI_EEXIST) {
jsgff3c3f1a2003-10-14 22:13:28 +00001891 VG_(message)(Vg_UserMsg,
1892 "Can't create/open log file `%s.pid%d'; giving up!",
nethercotef8548672004-06-21 12:42:35 +00001893 VG_(clo_log_name), pid);
jsgff3c3f1a2003-10-14 22:13:28 +00001894 VG_(bad_option)(
nethercotef8548672004-06-21 12:42:35 +00001895 "--log-file=<file> didn't work out for some reason.");
jsgff3c3f1a2003-10-14 22:13:28 +00001896 break;
1897 }
1898 }
1899 }
sewardj4cf05692002-10-27 20:28:29 +00001900 break;
sewardj73cf3bc2002-11-03 03:20:15 +00001901 }
1902
1903 case VgLogTo_Socket: {
nethercotef8548672004-06-21 12:42:35 +00001904 vg_assert(VG_(clo_log_name) != NULL);
1905 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
1906 eventually_log_fd = VG_(connect_via_socket)( VG_(clo_log_name) );
1907 if (eventually_log_fd == -1) {
sewardj73cf3bc2002-11-03 03:20:15 +00001908 VG_(message)(Vg_UserMsg,
nethercotef8548672004-06-21 12:42:35 +00001909 "Invalid --log-socket=ipaddr or --log-socket=ipaddr:port spec");
sewardj73cf3bc2002-11-03 03:20:15 +00001910 VG_(message)(Vg_UserMsg,
nethercotef8548672004-06-21 12:42:35 +00001911 "of `%s'; giving up!", VG_(clo_log_name) );
sewardj73cf3bc2002-11-03 03:20:15 +00001912 VG_(bad_option)(
nethercotef8548672004-06-21 12:42:35 +00001913 "--log-socket=");
sewardj4cf05692002-10-27 20:28:29 +00001914 }
nethercotef8548672004-06-21 12:42:35 +00001915 if (eventually_log_fd == -2) {
sewardj73cf3bc2002-11-03 03:20:15 +00001916 VG_(message)(Vg_UserMsg,
sewardj570f8902002-11-03 11:44:36 +00001917 "valgrind: failed to connect to logging server `%s'.",
nethercotef8548672004-06-21 12:42:35 +00001918 VG_(clo_log_name) );
sewardj570f8902002-11-03 11:44:36 +00001919 VG_(message)(Vg_UserMsg,
1920 "Log messages will sent to stderr instead." );
1921 VG_(message)(Vg_UserMsg,
1922 "" );
1923 /* We don't change anything here. */
1924 } else {
nethercotef8548672004-06-21 12:42:35 +00001925 vg_assert(eventually_log_fd > 0);
1926 VG_(clo_log_fd) = eventually_log_fd;
sewardj570f8902002-11-03 11:44:36 +00001927 VG_(logging_to_filedes) = False;
1928 }
sewardj73cf3bc2002-11-03 03:20:15 +00001929 break;
1930 }
1931
sewardj4cf05692002-10-27 20:28:29 +00001932 }
1933
nethercotef8548672004-06-21 12:42:35 +00001934 /* Move log_fd into the safe range, so it doesn't conflict with any app fds */
thughesad1c9562004-06-26 11:27:52 +00001935 eventually_log_fd = VG_(fcntl)(VG_(clo_log_fd), VKI_F_DUPFD, VG_(fd_hard_limit));
nethercotef8548672004-06-21 12:42:35 +00001936 if (eventually_log_fd < 0)
jsgf855d93d2003-10-13 22:26:55 +00001937 VG_(message)(Vg_UserMsg, "valgrind: failed to move logfile fd into safe range");
1938 else {
nethercotef8548672004-06-21 12:42:35 +00001939 VG_(clo_log_fd) = eventually_log_fd;
1940 VG_(fcntl)(VG_(clo_log_fd), VKI_F_SETFD, VKI_FD_CLOEXEC);
jsgf855d93d2003-10-13 22:26:55 +00001941 }
1942
sewardj4cf05692002-10-27 20:28:29 +00001943 /* Ok, the logging sink is running now. Print a suitable preamble.
1944 If logging to file or a socket, write details of parent PID and
1945 command line args, to help people trying to interpret the
1946 results of a run which encompasses multiple processes. */
sewardjde4a1d02002-03-22 01:27:54 +00001947
sewardj83adf412002-05-01 01:25:45 +00001948 if (VG_(clo_verbosity > 0)) {
njnd04b7c62002-10-03 14:05:52 +00001949 /* Skin details */
1950 VG_(message)(Vg_UserMsg, "%s%s%s, %s for x86-linux.",
1951 VG_(details).name,
1952 NULL == VG_(details).version ? "" : "-",
1953 NULL == VG_(details).version
1954 ? (Char*)"" : VG_(details).version,
1955 VG_(details).description);
1956 VG_(message)(Vg_UserMsg, "%s", VG_(details).copyright_author);
sewardj3b2736a2002-03-24 12:18:35 +00001957
njnd04b7c62002-10-03 14:05:52 +00001958 /* Core details */
1959 VG_(message)(Vg_UserMsg,
njn3e884182003-04-15 13:03:23 +00001960 "Using valgrind-%s, a program supervision framework for x86-linux.",
sewardj4aa62ba2002-10-05 15:49:27 +00001961 VERSION);
sewardjde4a1d02002-03-22 01:27:54 +00001962 VG_(message)(Vg_UserMsg,
nethercote08fa9a72004-07-16 17:44:00 +00001963 "Copyright (C) 2000-2004, and GNU GPL'd, by Julian Seward et al.");
njnd04b7c62002-10-03 14:05:52 +00001964 }
1965
nethercotec1e395d2003-11-10 13:26:49 +00001966 if (VG_(clo_verbosity) > 0 && VG_(clo_log_to) != VgLogTo_Fd) {
sewardj4cf05692002-10-27 20:28:29 +00001967 VG_(message)(Vg_UserMsg, "");
1968 VG_(message)(Vg_UserMsg,
1969 "My PID = %d, parent PID = %d. Prog and args are:",
1970 VG_(getpid)(), VG_(getppid)() );
1971 for (i = 0; i < VG_(client_argc); i++)
1972 VG_(message)(Vg_UserMsg, " %s", VG_(client_argv)[i]);
1973 }
1974
sewardjde4a1d02002-03-22 01:27:54 +00001975 if (VG_(clo_verbosity) > 1) {
nethercotea70f7352004-04-18 12:08:46 +00001976 Int fd;
sewardj4cf05692002-10-27 20:28:29 +00001977 if (VG_(clo_log_to) != VgLogTo_Fd)
1978 VG_(message)(Vg_UserMsg, "");
fitzhardinge98abfc72003-12-16 02:05:15 +00001979 VG_(message)(Vg_UserMsg, "Valgrind library directory: %s", VG_(libdir));
njn86dc2bc2003-09-09 07:26:21 +00001980 VG_(message)(Vg_UserMsg, "Command line");
1981 for (i = 0; i < VG_(client_argc); i++)
1982 VG_(message)(Vg_UserMsg, " %s", VG_(client_argv)[i]);
1983
sewardjde4a1d02002-03-22 01:27:54 +00001984 VG_(message)(Vg_UserMsg, "Startup, with flags:");
nethercote71980f02004-01-24 18:18:54 +00001985 for (i = 1; i < VG_(vg_argc); i++) {
1986 VG_(message)(Vg_UserMsg, " %s", VG_(vg_argv)[i]);
sewardjde4a1d02002-03-22 01:27:54 +00001987 }
nethercotea70f7352004-04-18 12:08:46 +00001988
1989 VG_(message)(Vg_UserMsg, "Contents of /proc/version:");
1990 fd = VG_(open) ( "/proc/version", VKI_O_RDONLY, 0 );
1991 if (fd < 0) {
1992 VG_(message)(Vg_UserMsg, " can't open /proc/version");
1993 } else {
1994 #define BUF_LEN 256
1995 Char version_buf[BUF_LEN];
1996 Int n = VG_(read) ( fd, version_buf, BUF_LEN );
1997 vg_assert(n <= 256);
1998 if (n > 0) {
1999 version_buf[n-1] = '\0';
2000 VG_(message)(Vg_UserMsg, " %s", version_buf);
2001 } else {
2002 VG_(message)(Vg_UserMsg, " (empty?)");
2003 }
2004 VG_(close)(fd);
2005 #undef BUF_LEN
2006 }
sewardjde4a1d02002-03-22 01:27:54 +00002007 }
2008
fitzhardinge98abfc72003-12-16 02:05:15 +00002009 if (VG_(clo_n_suppressions) < VG_CLO_MAX_SFILES-1 &&
njn25e49d8e72002-09-23 09:36:25 +00002010 (VG_(needs).core_errors || VG_(needs).skin_errors)) {
fitzhardinge98abfc72003-12-16 02:05:15 +00002011 /* If there are no suppression files specified and the skin
2012 needs one, load the default */
2013 static const Char default_supp[] = "default.supp";
2014 Int len = VG_(strlen)(VG_(libdir)) + 1 + sizeof(default_supp);
2015 Char *buf = VG_(arena_malloc)(VG_AR_CORE, len);
2016 VG_(sprintf)(buf, "%s/%s", VG_(libdir), default_supp);
2017 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = buf;
2018 VG_(clo_n_suppressions)++;
sewardjde4a1d02002-03-22 01:27:54 +00002019 }
sewardj4cf05692002-10-27 20:28:29 +00002020
njn6a230532003-07-21 10:38:23 +00002021 if (VG_(clo_gen_suppressions) &&
2022 !VG_(needs).core_errors && !VG_(needs).skin_errors) {
nethercotef4928da2004-06-15 10:54:40 +00002023 VG_(message)(Vg_UserMsg,
2024 "Can't use --gen-suppressions=yes with this tool,");
2025 VG_(message)(Vg_UserMsg,
2026 "as it doesn't generate errors.");
2027 VG_(bad_option)("--gen-suppressions=yes");
njn6a230532003-07-21 10:38:23 +00002028 }
sewardjde4a1d02002-03-22 01:27:54 +00002029}
2030
sewardjde4a1d02002-03-22 01:27:54 +00002031
nethercote71980f02004-01-24 18:18:54 +00002032/*====================================================================*/
2033/*=== File descriptor setup ===*/
2034/*====================================================================*/
2035
2036static void setup_file_descriptors(void)
2037{
2038 struct vki_rlimit rl;
2039
2040 /* Get the current file descriptor limits. */
2041 if (VG_(getrlimit)(VKI_RLIMIT_NOFILE, &rl) < 0) {
2042 rl.rlim_cur = 1024;
2043 rl.rlim_max = 1024;
2044 }
2045
2046 /* Work out where to move the soft limit to. */
2047 if (rl.rlim_cur + VG_N_RESERVED_FDS <= rl.rlim_max) {
2048 rl.rlim_cur = rl.rlim_cur + VG_N_RESERVED_FDS;
2049 } else {
2050 rl.rlim_cur = rl.rlim_max;
2051 }
2052
2053 /* Reserve some file descriptors for our use. */
thughesad1c9562004-06-26 11:27:52 +00002054 VG_(fd_soft_limit) = rl.rlim_cur - VG_N_RESERVED_FDS;
2055 VG_(fd_hard_limit) = rl.rlim_cur - VG_N_RESERVED_FDS;
nethercote71980f02004-01-24 18:18:54 +00002056
2057 /* Update the soft limit. */
2058 VG_(setrlimit)(VKI_RLIMIT_NOFILE, &rl);
2059
2060 if (VG_(vgexecfd) != -1)
2061 VG_(vgexecfd) = VG_(safe_fd)( VG_(vgexecfd) );
2062 if (VG_(clexecfd) != -1)
2063 VG_(clexecfd) = VG_(safe_fd)( VG_(clexecfd) );
2064}
2065
2066
2067/*====================================================================*/
nethercote1d447092004-02-01 17:29:59 +00002068/*=== baseBlock: definition + setup ===*/
nethercote71980f02004-01-24 18:18:54 +00002069/*====================================================================*/
2070
2071/* The variables storing offsets. */
2072
2073#define INVALID_OFFSET (-1)
2074
2075Int VGOFF_(m_eax) = INVALID_OFFSET;
2076Int VGOFF_(m_ecx) = INVALID_OFFSET;
2077Int VGOFF_(m_edx) = INVALID_OFFSET;
2078Int VGOFF_(m_ebx) = INVALID_OFFSET;
2079Int VGOFF_(m_esp) = INVALID_OFFSET;
2080Int VGOFF_(m_ebp) = INVALID_OFFSET;
2081Int VGOFF_(m_esi) = INVALID_OFFSET;
2082Int VGOFF_(m_edi) = INVALID_OFFSET;
2083Int VGOFF_(m_eflags) = INVALID_OFFSET;
2084Int VGOFF_(m_dflag) = INVALID_OFFSET;
2085Int VGOFF_(m_ssestate) = INVALID_OFFSET;
2086Int VGOFF_(ldt) = INVALID_OFFSET;
2087Int VGOFF_(tls) = INVALID_OFFSET;
2088Int VGOFF_(m_cs) = INVALID_OFFSET;
2089Int VGOFF_(m_ss) = INVALID_OFFSET;
2090Int VGOFF_(m_ds) = INVALID_OFFSET;
2091Int VGOFF_(m_es) = INVALID_OFFSET;
2092Int VGOFF_(m_fs) = INVALID_OFFSET;
2093Int VGOFF_(m_gs) = INVALID_OFFSET;
2094Int VGOFF_(m_eip) = INVALID_OFFSET;
2095Int VGOFF_(spillslots) = INVALID_OFFSET;
2096Int VGOFF_(sh_eax) = INVALID_OFFSET;
2097Int VGOFF_(sh_ecx) = INVALID_OFFSET;
2098Int VGOFF_(sh_edx) = INVALID_OFFSET;
2099Int VGOFF_(sh_ebx) = INVALID_OFFSET;
2100Int VGOFF_(sh_esp) = INVALID_OFFSET;
2101Int VGOFF_(sh_ebp) = INVALID_OFFSET;
2102Int VGOFF_(sh_esi) = INVALID_OFFSET;
2103Int VGOFF_(sh_edi) = INVALID_OFFSET;
2104Int VGOFF_(sh_eflags) = INVALID_OFFSET;
2105
2106Int VGOFF_(helper_idiv_64_32) = INVALID_OFFSET;
2107Int VGOFF_(helper_div_64_32) = INVALID_OFFSET;
2108Int VGOFF_(helper_idiv_32_16) = INVALID_OFFSET;
2109Int VGOFF_(helper_div_32_16) = INVALID_OFFSET;
2110Int VGOFF_(helper_idiv_16_8) = INVALID_OFFSET;
2111Int VGOFF_(helper_div_16_8) = INVALID_OFFSET;
2112Int VGOFF_(helper_imul_32_64) = INVALID_OFFSET;
2113Int VGOFF_(helper_mul_32_64) = INVALID_OFFSET;
2114Int VGOFF_(helper_imul_16_32) = INVALID_OFFSET;
2115Int VGOFF_(helper_mul_16_32) = INVALID_OFFSET;
2116Int VGOFF_(helper_imul_8_16) = INVALID_OFFSET;
2117Int VGOFF_(helper_mul_8_16) = INVALID_OFFSET;
2118Int VGOFF_(helper_CLD) = INVALID_OFFSET;
2119Int VGOFF_(helper_STD) = INVALID_OFFSET;
2120Int VGOFF_(helper_get_dirflag) = INVALID_OFFSET;
2121Int VGOFF_(helper_CLC) = INVALID_OFFSET;
2122Int VGOFF_(helper_STC) = INVALID_OFFSET;
nethercote1018bdd2004-02-11 23:33:29 +00002123Int VGOFF_(helper_CMC) = INVALID_OFFSET;
nethercote71980f02004-01-24 18:18:54 +00002124Int VGOFF_(helper_shldl) = INVALID_OFFSET;
2125Int VGOFF_(helper_shldw) = INVALID_OFFSET;
2126Int VGOFF_(helper_shrdl) = INVALID_OFFSET;
2127Int VGOFF_(helper_shrdw) = INVALID_OFFSET;
2128Int VGOFF_(helper_IN) = INVALID_OFFSET;
2129Int VGOFF_(helper_OUT) = INVALID_OFFSET;
2130Int VGOFF_(helper_RDTSC) = INVALID_OFFSET;
2131Int VGOFF_(helper_CPUID) = INVALID_OFFSET;
2132Int VGOFF_(helper_BSWAP) = INVALID_OFFSET;
nethercote1018bdd2004-02-11 23:33:29 +00002133Int VGOFF_(helper_bsfw) = INVALID_OFFSET;
2134Int VGOFF_(helper_bsfl) = INVALID_OFFSET;
2135Int VGOFF_(helper_bsrw) = INVALID_OFFSET;
2136Int VGOFF_(helper_bsrl) = INVALID_OFFSET;
nethercote71980f02004-01-24 18:18:54 +00002137Int VGOFF_(helper_fstsw_AX) = INVALID_OFFSET;
2138Int VGOFF_(helper_SAHF) = INVALID_OFFSET;
2139Int VGOFF_(helper_LAHF) = INVALID_OFFSET;
2140Int VGOFF_(helper_DAS) = INVALID_OFFSET;
2141Int VGOFF_(helper_DAA) = INVALID_OFFSET;
nethercote1018bdd2004-02-11 23:33:29 +00002142Int VGOFF_(helper_AAS) = INVALID_OFFSET;
2143Int VGOFF_(helper_AAA) = INVALID_OFFSET;
2144Int VGOFF_(helper_AAD) = INVALID_OFFSET;
2145Int VGOFF_(helper_AAM) = INVALID_OFFSET;
nethercote71980f02004-01-24 18:18:54 +00002146Int VGOFF_(helper_cmpxchg8b) = INVALID_OFFSET;
2147Int VGOFF_(helper_undefined_instruction) = INVALID_OFFSET;
2148
2149/* MAX_NONCOMPACT_HELPERS can be increased easily. If MAX_COMPACT_HELPERS is
2150 * increased too much, they won't really be compact any more... */
2151#define MAX_COMPACT_HELPERS 8
2152#define MAX_NONCOMPACT_HELPERS 50
2153
2154UInt VG_(n_compact_helpers) = 0;
2155UInt VG_(n_noncompact_helpers) = 0;
2156
2157Addr VG_(compact_helper_addrs) [MAX_COMPACT_HELPERS];
2158Int VG_(compact_helper_offsets)[MAX_COMPACT_HELPERS];
2159Addr VG_(noncompact_helper_addrs) [MAX_NONCOMPACT_HELPERS];
2160Int VG_(noncompact_helper_offsets)[MAX_NONCOMPACT_HELPERS];
2161
2162/* This is the actual defn of baseblock. */
2163UInt VG_(baseBlock)[VG_BASEBLOCK_WORDS];
2164
nethercote71980f02004-01-24 18:18:54 +00002165/* Words. */
2166static Int baB_off = 0;
2167
2168
sewardjfa492d42002-12-08 18:20:01 +00002169UInt VG_(insertDflag)(UInt eflags, Int d)
2170{
2171 vg_assert(d == 1 || d == -1);
2172 eflags &= ~EFlagD;
2173
2174 if (d < 0)
2175 eflags |= EFlagD;
2176
2177 return eflags;
2178}
2179
2180Int VG_(extractDflag)(UInt eflags)
2181{
2182 Int ret;
2183
2184 if (eflags & EFlagD)
2185 ret = -1;
2186 else
2187 ret = 1;
2188
2189 return ret;
2190}
2191
nethercote71980f02004-01-24 18:18:54 +00002192/* Returns the offset, in words. */
2193static Int alloc_BaB ( Int words )
sewardjde4a1d02002-03-22 01:27:54 +00002194{
nethercote71980f02004-01-24 18:18:54 +00002195 Int off = baB_off;
2196 baB_off += words;
2197 if (baB_off >= VG_BASEBLOCK_WORDS)
2198 VG_(core_panic)( "alloc_BaB: baseBlock is too small");
sewardjde4a1d02002-03-22 01:27:54 +00002199
nethercote71980f02004-01-24 18:18:54 +00002200 return off;
sewardjde4a1d02002-03-22 01:27:54 +00002201}
2202
nethercote71980f02004-01-24 18:18:54 +00002203/* Align offset, in *bytes* */
2204static void align_BaB ( UInt align )
njn25e49d8e72002-09-23 09:36:25 +00002205{
nethercote71980f02004-01-24 18:18:54 +00002206 vg_assert(2 == align || 4 == align || 8 == align || 16 == align);
2207 baB_off += (align-1);
2208 baB_off &= ~(align-1);
njn25e49d8e72002-09-23 09:36:25 +00002209}
2210
nethercote71980f02004-01-24 18:18:54 +00002211/* Allocate 1 word in baseBlock and set it to the given value. */
2212static Int alloc_BaB_1_set ( Addr a )
njn25e49d8e72002-09-23 09:36:25 +00002213{
nethercote71980f02004-01-24 18:18:54 +00002214 Int off = alloc_BaB(1);
2215 VG_(baseBlock)[off] = (UInt)a;
2216 return off;
njn25e49d8e72002-09-23 09:36:25 +00002217}
2218
nethercote71980f02004-01-24 18:18:54 +00002219/* Registers a function in compact_helper_addrs; compact_helper_offsets is
2220 filled in later. */
2221void VG_(register_compact_helper)(Addr a)
sewardjde4a1d02002-03-22 01:27:54 +00002222{
nethercote71980f02004-01-24 18:18:54 +00002223 if (MAX_COMPACT_HELPERS <= VG_(n_compact_helpers)) {
2224 VG_(printf)("Can only register %d compact helpers\n",
2225 MAX_COMPACT_HELPERS);
2226 VG_(core_panic)("Too many compact helpers registered");
2227 }
2228 VG_(compact_helper_addrs)[VG_(n_compact_helpers)] = a;
2229 VG_(n_compact_helpers)++;
2230}
2231
2232/* Registers a function in noncompact_helper_addrs; noncompact_helper_offsets
2233 * is filled in later.
2234 */
2235void VG_(register_noncompact_helper)(Addr a)
2236{
2237 if (MAX_NONCOMPACT_HELPERS <= VG_(n_noncompact_helpers)) {
2238 VG_(printf)("Can only register %d non-compact helpers\n",
2239 MAX_NONCOMPACT_HELPERS);
2240 VG_(printf)("Try increasing MAX_NON_COMPACT_HELPERS\n");
2241 VG_(core_panic)("Too many non-compact helpers registered");
2242 }
2243 VG_(noncompact_helper_addrs)[VG_(n_noncompact_helpers)] = a;
2244 VG_(n_noncompact_helpers)++;
2245}
2246
2247/* Allocate offsets in baseBlock for the skin helpers */
2248static
2249void assign_helpers_in_baseBlock(UInt n, Int offsets[], Addr addrs[])
2250{
2251 UInt i;
2252 for (i = 0; i < n; i++)
2253 offsets[i] = alloc_BaB_1_set( addrs[i] );
2254}
2255
2256Bool VG_(need_to_handle_esp_assignment)(void)
2257{
2258 return ( VG_(defined_new_mem_stack_4)() ||
2259 VG_(defined_die_mem_stack_4)() ||
2260 VG_(defined_new_mem_stack_8)() ||
2261 VG_(defined_die_mem_stack_8)() ||
2262 VG_(defined_new_mem_stack_12)() ||
2263 VG_(defined_die_mem_stack_12)() ||
2264 VG_(defined_new_mem_stack_16)() ||
2265 VG_(defined_die_mem_stack_16)() ||
2266 VG_(defined_new_mem_stack_32)() ||
2267 VG_(defined_die_mem_stack_32)() ||
2268 VG_(defined_new_mem_stack)() ||
2269 VG_(defined_die_mem_stack)()
2270 );
2271}
2272
2273/* Here we assign actual offsets. It's important to get the most
2274 popular referents within 128 bytes of the start, so we can take
2275 advantage of short addressing modes relative to %ebp. Popularity
2276 of offsets was measured on 22 Feb 02 running a KDE application, and
2277 the slots rearranged accordingly, with a 1.5% reduction in total
2278 size of translations. */
2279static void init_baseBlock ( Addr client_eip, Addr esp_at_startup )
2280{
2281 /* Those with offsets under 128 are carefully chosen. */
2282
2283 /* WORD offsets in this column */
2284 /* 0 */ VGOFF_(m_eax) = alloc_BaB_1_set(0);
2285 /* 1 */ VGOFF_(m_ecx) = alloc_BaB_1_set(0);
2286 /* 2 */ VGOFF_(m_edx) = alloc_BaB_1_set(0);
2287 /* 3 */ VGOFF_(m_ebx) = alloc_BaB_1_set(0);
2288 /* 4 */ VGOFF_(m_esp) = alloc_BaB_1_set(esp_at_startup);
2289 /* 5 */ VGOFF_(m_ebp) = alloc_BaB_1_set(0);
2290 /* 6 */ VGOFF_(m_esi) = alloc_BaB_1_set(0);
2291 /* 7 */ VGOFF_(m_edi) = alloc_BaB_1_set(0);
2292 /* 8 */ VGOFF_(m_eflags) = alloc_BaB_1_set(0);
2293
2294 if (VG_(needs).shadow_regs) {
2295 /* 9 */ VGOFF_(sh_eax) = alloc_BaB_1_set(0);
2296 /* 10 */ VGOFF_(sh_ecx) = alloc_BaB_1_set(0);
2297 /* 11 */ VGOFF_(sh_edx) = alloc_BaB_1_set(0);
2298 /* 12 */ VGOFF_(sh_ebx) = alloc_BaB_1_set(0);
2299 /* 13 */ VGOFF_(sh_esp) = alloc_BaB_1_set(0);
2300 /* 14 */ VGOFF_(sh_ebp) = alloc_BaB_1_set(0);
2301 /* 15 */ VGOFF_(sh_esi) = alloc_BaB_1_set(0);
2302 /* 16 */ VGOFF_(sh_edi) = alloc_BaB_1_set(0);
2303 /* 17 */ VGOFF_(sh_eflags) = alloc_BaB_1_set(0);
2304 VG_TRACK( post_regs_write_init );
2305 }
2306
2307 /* 9,10,11 or 18,19,20... depends on number whether shadow regs are used
2308 * and on compact helpers registered */
2309
2310 /* Make these most-frequently-called specialised ones compact, if they
2311 are used. */
2312 if (VG_(defined_new_mem_stack_4)())
2313 VG_(register_compact_helper)( (Addr) VG_(tool_interface).track_new_mem_stack_4);
2314
2315 if (VG_(defined_die_mem_stack_4)())
2316 VG_(register_compact_helper)( (Addr) VG_(tool_interface).track_die_mem_stack_4);
2317
2318 /* (9 or 18) + n_compact_helpers */
2319 /* Allocate slots for compact helpers */
2320 assign_helpers_in_baseBlock(VG_(n_compact_helpers),
2321 VG_(compact_helper_offsets),
2322 VG_(compact_helper_addrs));
2323
2324 /* (9/10 or 18/19) + n_compact_helpers */
2325 VGOFF_(m_eip) = alloc_BaB_1_set(client_eip);
2326
2327 /* There are currently 24 spill slots */
2328 /* (11+/20+ .. 32+/43+) + n_compact_helpers. This can overlap the magic
2329 * boundary at >= 32 words, but most spills are to low numbered spill
2330 * slots, so the ones above the boundary don't see much action. */
2331 VGOFF_(spillslots) = alloc_BaB(VG_MAX_SPILLSLOTS);
2332
2333 /* I gave up counting at this point. Since they're above the
2334 short-amode-boundary, there's no point. */
2335
2336 VGOFF_(m_dflag) = alloc_BaB_1_set(1); // 1 == forward D-flag
2337
2338 /* The FPU/SSE state. This _must_ be 16-byte aligned. Initial
2339 state doesn't matter much, as long as it's not totally borked. */
2340 align_BaB(16);
2341 VGOFF_(m_ssestate) = alloc_BaB(VG_SIZE_OF_SSESTATE_W);
2342 vg_assert(
2343 0 == ( ((UInt)(& VG_(baseBlock)[VGOFF_(m_ssestate)])) % 16 )
sewardj22854b92002-11-30 14:00:47 +00002344 );
2345
fitzhardingec2dbbac2004-01-23 23:09:01 +00002346 /* I assume that if we have SSE2 we also have SSE */
2347 VG_(have_ssestate) =
2348 VG_(cpu_has_feature)(VG_X86_FEAT_FXSR) &&
2349 VG_(cpu_has_feature)(VG_X86_FEAT_SSE);
2350
fitzhardinge98abfc72003-12-16 02:05:15 +00002351 /* set up an initial FPU state (doesn't really matter what it is,
2352 so long as it's somewhat valid) */
2353 if (!VG_(have_ssestate))
nethercote71980f02004-01-24 18:18:54 +00002354 asm volatile("fwait; fnsave %0; fwait; frstor %0; fwait"
2355 :
2356 : "m" (VG_(baseBlock)[VGOFF_(m_ssestate)])
2357 : "cc", "memory");
fitzhardinge98abfc72003-12-16 02:05:15 +00002358 else
nethercote71980f02004-01-24 18:18:54 +00002359 asm volatile("fwait; fxsave %0; fwait; andl $0xffbf, %1;"
2360 "fxrstor %0; fwait"
2361 :
2362 : "m" (VG_(baseBlock)[VGOFF_(m_ssestate)]),
2363 "m" (VG_(baseBlock)[VGOFF_(m_ssestate)+(24/4)])
2364 : "cc", "memory");
fitzhardinge98abfc72003-12-16 02:05:15 +00002365
njn0c7a5b52003-04-30 09:00:33 +00002366 if (0) {
2367 if (VG_(have_ssestate))
2368 VG_(printf)("Looks like a SSE-capable CPU\n");
2369 else
2370 VG_(printf)("Looks like a MMX-only CPU\n");
2371 }
sewardjb91ae7f2003-04-29 23:50:00 +00002372
nethercote71980f02004-01-24 18:18:54 +00002373 /* LDT pointer: pretend the root thread has an empty LDT to start with. */
2374 VGOFF_(ldt) = alloc_BaB_1_set((UInt)NULL);
jsgf855d93d2003-10-13 22:26:55 +00002375
nethercote71980f02004-01-24 18:18:54 +00002376 /* TLS pointer: pretend the root thread has no TLS array for now. */
2377 VGOFF_(tls) = alloc_BaB_1_set((UInt)NULL);
fitzhardingef0046f22003-12-18 02:39:22 +00002378
nethercote71980f02004-01-24 18:18:54 +00002379 /* segment registers */
2380 VGOFF_(m_cs) = alloc_BaB_1_set(0);
2381 VGOFF_(m_ss) = alloc_BaB_1_set(0);
2382 VGOFF_(m_ds) = alloc_BaB_1_set(0);
2383 VGOFF_(m_es) = alloc_BaB_1_set(0);
2384 VGOFF_(m_fs) = alloc_BaB_1_set(0);
2385 VGOFF_(m_gs) = alloc_BaB_1_set(0);
fitzhardingef0046f22003-12-18 02:39:22 +00002386
thughes35cec982004-04-21 15:16:43 +00002387 /* initialise %cs, %ds and %ss to point at the operating systems
2388 default code, data and stack segments */
2389 asm volatile("movw %%cs, %0"
2390 :
2391 : "m" (VG_(baseBlock)[VGOFF_(m_cs)]));
2392 asm volatile("movw %%ds, %0"
2393 :
2394 : "m" (VG_(baseBlock)[VGOFF_(m_ds)]));
2395 asm volatile("movw %%ss, %0"
2396 :
2397 : "m" (VG_(baseBlock)[VGOFF_(m_ss)]));
2398
nethercote71980f02004-01-24 18:18:54 +00002399 VG_(register_noncompact_helper)( (Addr) & VG_(do_useseg) );
fitzhardingef0046f22003-12-18 02:39:22 +00002400
nethercote71980f02004-01-24 18:18:54 +00002401#define REG(kind, size) \
2402 if (VG_(defined_##kind##_mem_stack##size)()) \
2403 VG_(register_noncompact_helper)( \
2404 (Addr) VG_(tool_interface).track_##kind##_mem_stack##size );
2405 REG(new, _8);
2406 REG(new, _12);
2407 REG(new, _16);
2408 REG(new, _32);
2409 REG(new, );
2410 REG(die, _8);
2411 REG(die, _12);
2412 REG(die, _16);
2413 REG(die, _32);
2414 REG(die, );
2415#undef REG
fitzhardingef0046f22003-12-18 02:39:22 +00002416
nethercote71980f02004-01-24 18:18:54 +00002417 if (VG_(need_to_handle_esp_assignment)())
2418 VG_(register_noncompact_helper)((Addr) VG_(unknown_esp_update));
fitzhardingeb791a192003-12-18 07:22:44 +00002419
nethercote71980f02004-01-24 18:18:54 +00002420# define HELPER(name) \
2421 VGOFF_(helper_##name) = alloc_BaB_1_set( (Addr) & VG_(helper_##name))
njn3e884182003-04-15 13:03:23 +00002422
nethercote71980f02004-01-24 18:18:54 +00002423 /* Helper functions. */
2424 HELPER(idiv_64_32); HELPER(div_64_32);
2425 HELPER(idiv_32_16); HELPER(div_32_16);
2426 HELPER(idiv_16_8); HELPER(div_16_8);
fitzhardinge98abfc72003-12-16 02:05:15 +00002427
nethercote71980f02004-01-24 18:18:54 +00002428 HELPER(imul_32_64); HELPER(mul_32_64);
2429 HELPER(imul_16_32); HELPER(mul_16_32);
2430 HELPER(imul_8_16); HELPER(mul_8_16);
njn25e49d8e72002-09-23 09:36:25 +00002431
nethercote71980f02004-01-24 18:18:54 +00002432 HELPER(CLD); HELPER(STD);
2433 HELPER(get_dirflag);
sewardjde4a1d02002-03-22 01:27:54 +00002434
nethercote71980f02004-01-24 18:18:54 +00002435 HELPER(CLC); HELPER(STC);
nethercote1018bdd2004-02-11 23:33:29 +00002436 HELPER(CMC);
jsgf855d93d2003-10-13 22:26:55 +00002437
nethercote71980f02004-01-24 18:18:54 +00002438 HELPER(shldl); HELPER(shldw);
2439 HELPER(shrdl); HELPER(shrdw);
njncc7bb472002-10-14 09:25:19 +00002440
nethercote71980f02004-01-24 18:18:54 +00002441 HELPER(RDTSC); HELPER(CPUID);
njncc7bb472002-10-14 09:25:19 +00002442
nethercote1018bdd2004-02-11 23:33:29 +00002443 HELPER(bsfw); HELPER(bsfl);
2444 HELPER(bsrw); HELPER(bsrl);
rjwalshf5f536f2003-11-17 17:45:00 +00002445
nethercote71980f02004-01-24 18:18:54 +00002446 HELPER(fstsw_AX);
2447 HELPER(SAHF); HELPER(LAHF);
2448 HELPER(DAS); HELPER(DAA);
nethercote1018bdd2004-02-11 23:33:29 +00002449 HELPER(AAS); HELPER(AAA);
2450 HELPER(AAD); HELPER(AAM);
nethercote71980f02004-01-24 18:18:54 +00002451 HELPER(IN); HELPER(OUT);
2452 HELPER(cmpxchg8b);
sewardj018f7622002-05-15 21:13:39 +00002453
nethercote71980f02004-01-24 18:18:54 +00002454 HELPER(undefined_instruction);
jsgf855d93d2003-10-13 22:26:55 +00002455
nethercote71980f02004-01-24 18:18:54 +00002456# undef HELPER
sewardjde4a1d02002-03-22 01:27:54 +00002457
nethercote71980f02004-01-24 18:18:54 +00002458 /* Allocate slots for noncompact helpers */
2459 assign_helpers_in_baseBlock(VG_(n_noncompact_helpers),
2460 VG_(noncompact_helper_offsets),
2461 VG_(noncompact_helper_addrs));
2462}
sewardjde4a1d02002-03-22 01:27:54 +00002463
sewardj5f07b662002-04-23 16:52:51 +00002464
nethercote71980f02004-01-24 18:18:54 +00002465/*====================================================================*/
2466/*=== Setup pointercheck ===*/
2467/*====================================================================*/
njn25e49d8e72002-09-23 09:36:25 +00002468
nethercote71980f02004-01-24 18:18:54 +00002469static void setup_pointercheck(void)
2470{
2471 int ret;
sewardj2e93c502002-04-12 11:12:52 +00002472
fitzhardinge98abfc72003-12-16 02:05:15 +00002473 if (VG_(clo_pointercheck)) {
nethercote71980f02004-01-24 18:18:54 +00002474 vki_modify_ldt_t ldt = {
2475 VG_POINTERCHECK_SEGIDX, // entry_number
2476 VG_(client_base), // base_addr
2477 (VG_(client_end)-VG_(client_base)) / VKI_BYTES_PER_PAGE, // limit
2478 1, // seg_32bit
2479 0, // contents: data, RW, non-expanding
2480 0, // ! read_exec_only
2481 1, // limit_in_pages
2482 0, // ! seg not present
2483 1, // useable
fitzhardinge98abfc72003-12-16 02:05:15 +00002484 };
nethercote71980f02004-01-24 18:18:54 +00002485 ret = VG_(do_syscall)(__NR_modify_ldt, 1, &ldt, sizeof(ldt));
fitzhardinge98abfc72003-12-16 02:05:15 +00002486 if (ret < 0) {
2487 VG_(message)(Vg_UserMsg,
2488 "Warning: ignoring --pointercheck=yes, "
2489 "because modify_ldt failed (errno=%d)", -ret);
2490 VG_(clo_pointercheck) = False;
2491 }
2492 }
sewardjde4a1d02002-03-22 01:27:54 +00002493}
2494
nethercote71980f02004-01-24 18:18:54 +00002495/*====================================================================*/
2496/*=== Initialise program data/text, etc. ===*/
2497/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +00002498
nethercote71980f02004-01-24 18:18:54 +00002499static void build_valgrind_map_callback
2500 ( Addr start, UInt size, Char rr, Char ww, Char xx,
2501 UInt dev, UInt ino, ULong foffset, const UChar* filename )
sewardjde4a1d02002-03-22 01:27:54 +00002502{
nethercote71980f02004-01-24 18:18:54 +00002503 UInt prot = 0;
2504 UInt flags = SF_MMAP|SF_NOSYMS;
2505 Bool is_stack_segment;
2506
2507 is_stack_segment =
2508 (start == VG_(clstk_base) && (start+size) == VG_(clstk_end));
2509
2510 /* Only record valgrind mappings for now, without loading any
2511 symbols. This is so we know where the free space is before we
2512 start allocating more memory (note: heap is OK, it's just mmap
2513 which is the problem here). */
2514 if (start >= VG_(valgrind_base) && (start+size) <= VG_(valgrind_end)) {
2515 flags |= SF_VALGRIND;
2516 VG_(map_file_segment)(start, size, prot, flags, dev, ino, foffset, filename);
2517 }
sewardjde4a1d02002-03-22 01:27:54 +00002518}
2519
nethercote71980f02004-01-24 18:18:54 +00002520// Global var used to pass local data to callback
2521Addr esp_at_startup___global_arg = 0;
sewardjde4a1d02002-03-22 01:27:54 +00002522
nethercote71980f02004-01-24 18:18:54 +00002523static void build_segment_map_callback
2524 ( Addr start, UInt size, Char rr, Char ww, Char xx,
2525 UInt dev, UInt ino, ULong foffset, const UChar* filename )
sewardj45b672d2003-07-25 19:58:11 +00002526{
nethercote71980f02004-01-24 18:18:54 +00002527 UInt prot = 0;
2528 UInt flags;
2529 Bool is_stack_segment;
2530 Addr r_esp;
sewardj45b672d2003-07-25 19:58:11 +00002531
nethercote71980f02004-01-24 18:18:54 +00002532 is_stack_segment
2533 = (start == VG_(clstk_base) && (start+size) == VG_(clstk_end));
fitzhardinge98abfc72003-12-16 02:05:15 +00002534
nethercote71980f02004-01-24 18:18:54 +00002535 if (rr == 'r') prot |= VKI_PROT_READ;
2536 if (ww == 'w') prot |= VKI_PROT_WRITE;
2537 if (xx == 'x') prot |= VKI_PROT_EXEC;
fitzhardinge98abfc72003-12-16 02:05:15 +00002538
nethercote71980f02004-01-24 18:18:54 +00002539 if (is_stack_segment)
2540 flags = SF_STACK | SF_GROWDOWN;
2541 else
2542 flags = SF_EXEC|SF_MMAP;
fitzhardinge98abfc72003-12-16 02:05:15 +00002543
nethercote71980f02004-01-24 18:18:54 +00002544 if (filename != NULL)
2545 flags |= SF_FILE;
fitzhardinge98abfc72003-12-16 02:05:15 +00002546
nethercote71980f02004-01-24 18:18:54 +00002547 if (start >= VG_(valgrind_base) && (start+size) <= VG_(valgrind_end))
2548 flags |= SF_VALGRIND;
fitzhardinge98abfc72003-12-16 02:05:15 +00002549
nethercote71980f02004-01-24 18:18:54 +00002550 VG_(map_file_segment)(start, size, prot, flags, dev, ino, foffset, filename);
fitzhardinge98abfc72003-12-16 02:05:15 +00002551
nethercote71980f02004-01-24 18:18:54 +00002552 if (VG_(is_client_addr)(start) && VG_(is_client_addr)(start+size-1))
2553 VG_TRACK( new_mem_startup, start, size, rr=='r', ww=='w', xx=='x' );
sewardj3e1eb1f2002-05-18 13:14:17 +00002554
nethercote71980f02004-01-24 18:18:54 +00002555 /* If this is the stack segment mark all below %esp as noaccess. */
2556 r_esp = esp_at_startup___global_arg;
2557 vg_assert(0 != r_esp);
2558 if (is_stack_segment) {
2559 if (0)
2560 VG_(message)(Vg_DebugMsg, "invalidating stack area: %x .. %x",
2561 start,r_esp);
2562 VG_TRACK( die_mem_stack, start, r_esp-start );
sewardjde4a1d02002-03-22 01:27:54 +00002563 }
sewardjde4a1d02002-03-22 01:27:54 +00002564}
2565
2566
nethercote71980f02004-01-24 18:18:54 +00002567/*====================================================================*/
2568/*=== Sanity check machinery (permanently engaged) ===*/
2569/*====================================================================*/
njn25e49d8e72002-09-23 09:36:25 +00002570
2571/* A fast sanity check -- suitable for calling circa once per
2572 millisecond. */
2573
2574void VG_(do_sanity_checks) ( Bool force_expensive )
2575{
njn37cea302002-09-30 11:24:00 +00002576 VGP_PUSHCC(VgpCoreCheapSanity);
2577
nethercote27fec902004-06-16 21:26:32 +00002578 if (VG_(clo_sanity_level) < 1) return;
njn25e49d8e72002-09-23 09:36:25 +00002579
2580 /* --- First do all the tests that we can do quickly. ---*/
2581
2582 VG_(sanity_fast_count)++;
2583
njn25e49d8e72002-09-23 09:36:25 +00002584 /* Check stuff pertaining to the memory check system. */
2585
2586 /* Check that nobody has spuriously claimed that the first or
2587 last 16 pages of memory have become accessible [...] */
njn37cea302002-09-30 11:24:00 +00002588 if (VG_(needs).sanity_checks) {
2589 VGP_PUSHCC(VgpSkinCheapSanity);
njn25e49d8e72002-09-23 09:36:25 +00002590 vg_assert(SK_(cheap_sanity_check)());
njn37cea302002-09-30 11:24:00 +00002591 VGP_POPCC(VgpSkinCheapSanity);
2592 }
njn25e49d8e72002-09-23 09:36:25 +00002593
2594 /* --- Now some more expensive checks. ---*/
2595
2596 /* Once every 25 times, check some more expensive stuff. */
2597 if ( force_expensive
nethercote27fec902004-06-16 21:26:32 +00002598 || VG_(clo_sanity_level) > 1
2599 || (VG_(clo_sanity_level) == 1 && (VG_(sanity_fast_count) % 25) == 0)) {
njn25e49d8e72002-09-23 09:36:25 +00002600
njn37cea302002-09-30 11:24:00 +00002601 VGP_PUSHCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002602 VG_(sanity_slow_count)++;
2603
jsgf855d93d2003-10-13 22:26:55 +00002604 VG_(proxy_sanity)();
2605
njn25e49d8e72002-09-23 09:36:25 +00002606# if 0
2607 { void zzzmemscan(void); zzzmemscan(); }
2608# endif
2609
2610 if ((VG_(sanity_fast_count) % 250) == 0)
2611 VG_(sanity_check_tc_tt)();
2612
2613 if (VG_(needs).sanity_checks) {
njn37cea302002-09-30 11:24:00 +00002614 VGP_PUSHCC(VgpSkinExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002615 vg_assert(SK_(expensive_sanity_check)());
njn37cea302002-09-30 11:24:00 +00002616 VGP_POPCC(VgpSkinExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002617 }
2618 /*
2619 if ((VG_(sanity_fast_count) % 500) == 0) VG_(mallocSanityCheckAll)();
2620 */
njn37cea302002-09-30 11:24:00 +00002621 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002622 }
2623
nethercote27fec902004-06-16 21:26:32 +00002624 if (VG_(clo_sanity_level) > 1) {
njn37cea302002-09-30 11:24:00 +00002625 VGP_PUSHCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002626 /* Check sanity of the low-level memory manager. Note that bugs
2627 in the client's code can cause this to fail, so we don't do
2628 this check unless specially asked for. And because it's
2629 potentially very expensive. */
2630 VG_(mallocSanityCheckAll)();
njn37cea302002-09-30 11:24:00 +00002631 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002632 }
njn37cea302002-09-30 11:24:00 +00002633 VGP_POPCC(VgpCoreCheapSanity);
njn25e49d8e72002-09-23 09:36:25 +00002634}
nethercote71980f02004-01-24 18:18:54 +00002635
2636
2637/*====================================================================*/
2638/*=== main() ===*/
2639/*====================================================================*/
2640
nethercotec314eba2004-07-15 12:59:41 +00002641/*
2642 This code decides on the layout of the client and Valgrind address
2643 spaces, loads valgrind.so and the skin.so into the valgrind part,
2644 loads the client executable (and the dynamic linker, if necessary)
2645 into the client part, and calls into Valgrind proper.
2646
2647 The code is careful not to allow spurious mappings to appear in the
2648 wrong parts of the address space. In particular, to make sure
2649 dlopen puts things in the right place, it will pad out the forbidden
2650 chunks of address space so that dlopen is forced to put things where
2651 we want them.
2652
2653 The memory map it creates is:
2654
2655 CLIENT_BASE +-------------------------+
2656 | client address space |
2657 : :
2658 : :
2659 | client stack |
2660 client_end +-------------------------+
2661 | redzone |
2662 shadow_base +-------------------------+
2663 | |
2664 : shadow memory for skins :
2665 | (may be 0 sized) |
2666 shadow_end +-------------------------+
2667 : gap (may be 0 sized) :
2668 valgrind_base +-------------------------+
2669 | kickstart executable |
2670 | valgrind heap vvvvvvvvv| (barely used)
2671 - -
2672 | valgrind .so files |
2673 | and mappings |
2674 - -
2675 | valgrind stack ^^^^^^^^^|
2676 valgrind_end +-------------------------+
2677 : kernel :
2678
2679 Nb: Before we can do general allocations with VG_(arena_malloc)() and
2680 VG_(mmap)(), we need to build the segment skip-list, so we know where
2681 we can put things. However, building that structure requires
2682 allocating memory. So we need to a bootstrapping process. It's done
2683 by making VG_(arena_malloc)() have a special static superblock that's
2684 used for the first 1MB's worth of allocations. This is enough to
2685 build the segment skip-list.
2686*/
2687
thughes4ad52d02004-06-27 17:37:21 +00002688static int prmap(void *start, void *end, const char *perm, off_t off,
2689 int maj, int min, int ino) {
2690 printf("mapping %10p-%10p %s %02x:%02x %d\n",
2691 start, end, perm, maj, min, ino);
2692 return True;
2693}
2694
nethercote71980f02004-01-24 18:18:54 +00002695int main(int argc, char **argv)
2696{
2697 char **cl_argv;
2698 const char *tool = NULL;
2699 const char *exec = NULL;
2700 char *preload; /* tool-specific LD_PRELOAD .so */
2701 char **env;
nethercote6c999f22004-01-31 22:55:15 +00002702 Int need_help = 0; // 0 = no, 1 = --help, 2 = --help-debug
nethercote71980f02004-01-24 18:18:54 +00002703 struct exeinfo info;
2704 ToolInfo *toolinfo = NULL;
2705 void *tool_dlhandle;
2706 Addr client_eip;
2707 Addr esp_at_startup; /* client's %esp at the point we gained control. */
2708 UInt * client_auxv;
2709 VgSchedReturnCode src;
nethercote47dd12c2004-06-22 14:18:42 +00002710 Int exitcode = 0;
fitzhardingeb50068f2004-02-24 23:42:55 +00002711 vki_rlimit zero = { 0, 0 };
nethercote71980f02004-01-24 18:18:54 +00002712
2713 //============================================================
2714 // Nb: startup is complex. Prerequisites are shown at every step.
2715 //
2716 // *** Be very careful when messing with the order ***
2717 //============================================================
2718
nethercotef4928da2004-06-15 10:54:40 +00002719 //============================================================
2720 // Command line argument handling order:
2721 // * If --help/--help-debug are present, show usage message
2722 // (if --tool is also present, that includes the tool-specific usage)
2723 // * Then, if --tool is missing, abort with error msg
2724 // * Then, if client is missing, abort with error msg
2725 // * Then, if any cmdline args are bad, abort with error msg
2726 //============================================================
2727
fitzhardingeb50068f2004-02-24 23:42:55 +00002728 // Get the current process datasize rlimit, and set it to zero.
2729 // This prevents any internal uses of brk() from having any effect.
2730 // We remember the old value so we can restore it on exec, so that
2731 // child processes will have a reasonable brk value.
2732 VG_(getrlimit)(VKI_RLIMIT_DATA, &VG_(client_rlimit_data));
2733 zero.rlim_max = VG_(client_rlimit_data).rlim_max;
2734 VG_(setrlimit)(VKI_RLIMIT_DATA, &zero);
2735
nethercote71980f02004-01-24 18:18:54 +00002736 //--------------------------------------------------------------
2737 // Check we were launched by stage1
nethercotec314eba2004-07-15 12:59:41 +00002738 // p: n/a
nethercote71980f02004-01-24 18:18:54 +00002739 //--------------------------------------------------------------
2740 scan_auxv();
2741
2742 if (0) {
nethercote71980f02004-01-24 18:18:54 +00002743 printf("========== main() ==========\n");
2744 foreach_map(prmap);
2745 }
2746
2747 //--------------------------------------------------------------
2748 // Look for alternative libdir
2749 // p: n/a
2750 //--------------------------------------------------------------
2751 { char *cp = getenv(VALGRINDLIB);
2752 if (cp != NULL)
2753 VG_(libdir) = cp;
2754 }
2755
2756 //--------------------------------------------------------------
2757 // Begin working out address space layout
2758 // p: n/a
2759 //--------------------------------------------------------------
2760 layout_client_space( (Addr) & argc );
2761
2762 //--------------------------------------------------------------
2763 // Get valgrind args + client args (inc. from VALGRIND_OPTS/.valgrindrc).
2764 // Pre-process the command line.
2765 // p: n/a
2766 //--------------------------------------------------------------
2767 get_command_line(argc, argv, &VG_(vg_argc), &VG_(vg_argv), &cl_argv);
2768 pre_process_cmd_line_options(&need_help, &tool, &exec);
2769
2770 //==============================================================
2771 // Nb: once a tool is specified, the tool.so must be loaded even if
2772 // they specified --help or didn't specify a client program.
2773 //==============================================================
2774
2775 //--------------------------------------------------------------
2776 // With client padded out, map in tool
2777 // p: layout_client_space() [for padding]
2778 // p: set-libdir [for VG_(libdir)]
2779 // p: pre_process_cmd_line_options() [for 'tool']
2780 //--------------------------------------------------------------
2781 load_tool(tool, &tool_dlhandle, &toolinfo, &preload);
2782
2783 //==============================================================
2784 // Can use VG_(malloc)() and VG_(arena_malloc)() only after load_tool()
nethercotec314eba2004-07-15 12:59:41 +00002785 // -- redzone size is now set. This is checked by vg_malloc2.c.
nethercote71980f02004-01-24 18:18:54 +00002786 //==============================================================
2787
2788 //--------------------------------------------------------------
2789 // Finalise address space layout
nethercotec314eba2004-07-15 12:59:41 +00002790 // p: layout_client_space(), load_tool() [for 'toolinfo']
nethercote71980f02004-01-24 18:18:54 +00002791 //--------------------------------------------------------------
2792 layout_remaining_space( toolinfo->shadow_ratio );
2793
2794 //--------------------------------------------------------------
2795 // Load client executable, finding in $PATH if necessary
2796 // p: layout_client_space() [so there's space]
2797 // p: pre_process_cmd_line_options() [for 'exec', 'need_help']
2798 // p: layout_remaining_space [so there's space]
2799 //--------------------------------------------------------------
nethercotef4928da2004-06-15 10:54:40 +00002800 load_client(cl_argv, exec, need_help, &info, &client_eip);
nethercote71980f02004-01-24 18:18:54 +00002801
2802 //--------------------------------------------------------------
2803 // Everything in place, unpad us
2804 // p: layout_remaining_space() [everything must be mapped in before now]
2805 // p: load_client() [ditto]
2806 //--------------------------------------------------------------
2807 as_unpad((void *)VG_(shadow_end), (void *)~0);
2808 as_closepadfile(); /* no more padding */
2809
2810 //--------------------------------------------------------------
2811 // Set up client's environment
2812 // p: set-libdir [for VG_(libdir)]
2813 // p: load_tool() [for 'preload']
2814 //--------------------------------------------------------------
2815 env = fix_environment(environ, preload);
2816
2817 //--------------------------------------------------------------
nethercote5ee67ca2004-06-22 14:00:09 +00002818 // Setup client stack, eip, and VG_(client_arg[cv])
nethercote71980f02004-01-24 18:18:54 +00002819 // p: load_client() [for 'info']
2820 // p: fix_environment() [for 'env']
2821 //--------------------------------------------------------------
2822 esp_at_startup = setup_client_stack(cl_argv, env, &info, &client_auxv);
2823
2824 if (0)
2825 printf("entry=%x client esp=%x vg_argc=%d brkbase=%x\n",
2826 client_eip, esp_at_startup, VG_(vg_argc), VG_(brk_base));
2827
2828 //==============================================================
2829 // Finished setting up operating environment. Now initialise
2830 // Valgrind. (This is where the old VG_(main)() started.)
2831 //==============================================================
2832
2833 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002834 // atfork
2835 // p: n/a
2836 //--------------------------------------------------------------
2837 VG_(atfork)(NULL, NULL, newpid);
2838 newpid(VG_INVALID_THREADID);
2839
2840 //--------------------------------------------------------------
2841 // setup file descriptors
2842 // p: n/a
2843 //--------------------------------------------------------------
2844 setup_file_descriptors();
2845
2846 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002847 // Read /proc/self/maps into a buffer
2848 // p: all memory layout, environment setup [so memory maps are right]
2849 //--------------------------------------------------------------
2850 VG_(read_procselfmaps)();
2851
2852 //--------------------------------------------------------------
2853 // Build segment map (Valgrind segments only)
2854 // p: read proc/self/maps
2855 // p: sk_pre_clo_init() [to setup new_mem_startup tracker]
2856 //--------------------------------------------------------------
2857 VG_(parse_procselfmaps) ( build_valgrind_map_callback );
2858
2859 //==============================================================
2860 // Can use VG_(arena_malloc)() with non-CORE arena after segments set up
2861 //==============================================================
2862
2863 //--------------------------------------------------------------
2864 // Init tool: pre_clo_init, process cmd line, post_clo_init
2865 // p: setup_client_stack() [for 'VG_(client_arg[cv]']
2866 // p: load_tool() [for 'tool']
2867 // p: setup_file_descriptors() [for 'VG_(fd_xxx_limit)']
2868 // p: parse_procselfmaps [so VG segments are setup so tool can
2869 // call VG_(malloc)]
nethercote71980f02004-01-24 18:18:54 +00002870 //--------------------------------------------------------------
2871 (*toolinfo->sk_pre_clo_init)();
2872 VG_(tool_init_dlsym)(tool_dlhandle);
2873 VG_(sanity_check_needs)();
2874
nethercotef4928da2004-06-15 10:54:40 +00002875 // If --tool and --help/--help-debug was given, now give the core+tool
2876 // help message
nethercotef4928da2004-06-15 10:54:40 +00002877 if (need_help) {
2878 usage(/*--help-debug?*/2 == need_help);
2879 }
nethercotec314eba2004-07-15 12:59:41 +00002880 process_cmd_line_options(client_auxv, tool);
2881
2882 SK_(post_clo_init)();
nethercotef4928da2004-06-15 10:54:40 +00002883
2884 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002885 // Build segment map (all segments)
2886 // p: setup_client_stack() [for 'esp_at_startup']
2887 // p: init tool [for 'new_mem_startup']
nethercote71980f02004-01-24 18:18:54 +00002888 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002889 esp_at_startup___global_arg = esp_at_startup;
2890 VG_(parse_procselfmaps) ( build_segment_map_callback ); /* everything */
2891 esp_at_startup___global_arg = 0;
2892
2893 //--------------------------------------------------------------
nethercotef84f6952004-07-15 14:58:33 +00002894 // Protect client trampoline page (which is also sysinfo stuff)
2895 // p: segment stuff [otherwise get seg faults...]
nethercotec314eba2004-07-15 12:59:41 +00002896 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002897 VG_(mprotect)( (void *)VG_(client_trampoline_code),
2898 VG_(trampoline_code_length), VKI_PROT_READ|VKI_PROT_EXEC );
2899
2900 //==============================================================
2901 // Can use VG_(map)() after segments set up
2902 //==============================================================
nethercote71980f02004-01-24 18:18:54 +00002903
2904 //--------------------------------------------------------------
2905 // Allow GDB attach
2906 // p: process_cmd_line_options() [for VG_(clo_wait_for_gdb)]
2907 //--------------------------------------------------------------
2908 /* Hook to delay things long enough so we can get the pid and
2909 attach GDB in another shell. */
2910 if (VG_(clo_wait_for_gdb)) {
2911 VG_(printf)("pid=%d\n", VG_(getpid)());
2912 /* do "jump *$eip" to skip this in gdb */
2913 VG_(do_syscall)(__NR_pause);
2914 }
2915
2916 //--------------------------------------------------------------
nethercote1d447092004-02-01 17:29:59 +00002917 // Set up baseBlock
nethercote71980f02004-01-24 18:18:54 +00002918 // p: {pre,post}_clo_init() [for tool helper registration]
2919 // load_client() [for 'client_eip']
2920 // setup_client_stack() [for 'esp_at_startup']
2921 //--------------------------------------------------------------
2922 init_baseBlock(client_eip, esp_at_startup);
2923
2924 //--------------------------------------------------------------
2925 // Search for file descriptors that are inherited from our parent
2926 // p: process_cmd_line_options [for VG_(clo_track_fds)]
2927 //--------------------------------------------------------------
2928 if (VG_(clo_track_fds))
2929 VG_(init_preopened_fds)();
2930
2931 //--------------------------------------------------------------
2932 // Initialise the scheduler
2933 // p: init_baseBlock() [baseBlock regs copied into VG_(threads)[1]]
2934 // p: setup_file_descriptors() [else VG_(safe_fd)() breaks]
2935 //--------------------------------------------------------------
2936 VG_(scheduler_init)();
2937
2938 //--------------------------------------------------------------
2939 // Set up the ProxyLWP machinery
2940 // p: VG_(scheduler_init)()? [XXX: subtle dependency?]
2941 // - subs: VG_(sigstartup_actions)()?
2942 //--------------------------------------------------------------
2943 VG_(proxy_init)();
2944
2945 //--------------------------------------------------------------
2946 // Initialise the signal handling subsystem
2947 // p: VG_(atfork)(NULL, NULL, newpid) [else problems with sigmasks]
2948 // p: VG_(proxy_init)() [else breaks...]
2949 //--------------------------------------------------------------
2950 // Nb: temporarily parks the saved blocking-mask in saved_sigmask.
2951 VG_(sigstartup_actions)();
2952
2953 //--------------------------------------------------------------
2954 // Perhaps we're profiling Valgrind?
2955 // p: process_cmd_line_options() [for VG_(clo_profile)]
2956 // p: others?
2957 //
2958 // XXX: this seems to be broken? It always says the tool wasn't built
2959 // for profiling; vg_profile.c's functions don't seem to be overriding
2960 // vg_dummy_profile.c's?
2961 //
2962 // XXX: want this as early as possible. Looking for --profile
2963 // in pre_process_cmd_line_options() could get it earlier.
2964 //--------------------------------------------------------------
2965 if (VG_(clo_profile))
2966 VGP_(init_profiling)();
2967
2968 VGP_PUSHCC(VgpStartup);
2969
2970 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002971 // Read suppression file
2972 // p: process_cmd_line_options() [for VG_(clo_suppressions)]
2973 //--------------------------------------------------------------
2974 if (VG_(needs).core_errors || VG_(needs).skin_errors)
2975 VG_(load_suppressions)();
2976
2977 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002978 // Initialise translation table and translation cache
2979 // p: read_procselfmaps [so the anonymous mmaps for the TT/TC
2980 // aren't identified as part of the client, which would waste
2981 // > 20M of virtual address space.]
2982 //--------------------------------------------------------------
2983 VG_(init_tt_tc)();
2984
2985 //--------------------------------------------------------------
2986 // Read debug info to find glibc entry points to intercept
2987 // p: parse_procselfmaps? [XXX for debug info?]
2988 // p: init_tt_tc? [XXX ???]
2989 //--------------------------------------------------------------
2990 VG_(setup_code_redirect_table)();
2991
2992 //--------------------------------------------------------------
2993 // Verbosity message
2994 // p: end_rdtsc_calibration [so startup message is printed first]
2995 //--------------------------------------------------------------
2996 if (VG_(clo_verbosity) == 1)
2997 VG_(message)(Vg_UserMsg, "For more details, rerun with: -v");
2998 if (VG_(clo_verbosity) > 0)
2999 VG_(message)(Vg_UserMsg, "");
3000
3001 //--------------------------------------------------------------
3002 // Setup pointercheck
3003 // p: process_cmd_line_options() [for VG_(clo_pointercheck)]
3004 //--------------------------------------------------------------
3005 setup_pointercheck();
3006
nethercote71980f02004-01-24 18:18:54 +00003007 //--------------------------------------------------------------
3008 // Run!
3009 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00003010 VGP_POPCC(VgpStartup);
3011 VGP_PUSHCC(VgpSched);
3012
3013 if (__builtin_setjmp(&VG_(fatal_signal_jmpbuf)) == 0) {
3014 VG_(fatal_signal_set) = True;
nethercote47dd12c2004-06-22 14:18:42 +00003015 src = VG_(scheduler)( &exitcode );
nethercote71980f02004-01-24 18:18:54 +00003016 } else
3017 src = VgSrc_FatalSig;
3018
3019 VGP_POPCC(VgpSched);
nethercote71980f02004-01-24 18:18:54 +00003020
3021
3022
3023 //--------------------------------------------------------------
3024 // Finalisation: cleanup, messages, etc. Order no so important, only
3025 // affects what order the messages come.
3026 //--------------------------------------------------------------
3027 if (VG_(clo_verbosity) > 0)
3028 VG_(message)(Vg_UserMsg, "");
3029
3030 if (src == VgSrc_Deadlock) {
3031 VG_(message)(Vg_UserMsg,
3032 "Warning: pthread scheduler exited due to deadlock");
3033 }
3034
3035 /* Print out file descriptor summary and stats. */
3036 if (VG_(clo_track_fds))
3037 VG_(fd_stats)();
3038
3039 if (VG_(needs).core_errors || VG_(needs).skin_errors)
3040 VG_(show_all_errors)();
3041
nethercote47dd12c2004-06-22 14:18:42 +00003042 SK_(fini)( exitcode );
nethercote71980f02004-01-24 18:18:54 +00003043
3044 VG_(do_sanity_checks)( True /*include expensive checks*/ );
3045
3046 if (VG_(clo_verbosity) > 1)
3047 show_counts();
3048
3049 if (VG_(clo_verbosity) > 3)
3050 VG_(print_UInstr_histogram)();
3051
3052 if (0) {
3053 VG_(message)(Vg_DebugMsg, "");
3054 VG_(message)(Vg_DebugMsg,
3055 "------ Valgrind's internal memory use stats follow ------" );
3056 VG_(mallocSanityCheckAll)();
3057 VG_(show_all_arena_stats)();
3058 VG_(message)(Vg_DebugMsg,
3059 "------ Valgrind's ExeContext management stats follow ------" );
3060 VG_(show_ExeContext_stats)();
3061 }
3062
3063 if (VG_(clo_profile))
3064 VGP_(done_profiling)();
3065
nethercote71980f02004-01-24 18:18:54 +00003066 /* We're exiting, so nuke all the threads and clean up the proxy LWPs */
3067 vg_assert(src == VgSrc_FatalSig ||
3068 VG_(threads)[VG_(last_run_tid)].status == VgTs_Runnable ||
3069 VG_(threads)[VG_(last_run_tid)].status == VgTs_WaitJoiner);
3070 VG_(nuke_all_threads_except)(VG_INVALID_THREADID);
3071
3072 //--------------------------------------------------------------
3073 // Exit, according to the scheduler's return code
3074 //--------------------------------------------------------------
3075 switch (src) {
3076 case VgSrc_ExitSyscall: /* the normal way out */
3077 vg_assert(VG_(last_run_tid) > 0
3078 && VG_(last_run_tid) < VG_N_THREADS);
3079 VG_(proxy_shutdown)();
3080
3081 /* The thread's %EBX at the time it did __NR_exit() will hold
3082 the arg to __NR_exit(), so we just do __NR_exit() with
3083 that arg. */
nethercote47dd12c2004-06-22 14:18:42 +00003084 VG_(exit)( exitcode );
nethercote71980f02004-01-24 18:18:54 +00003085 /* NOT ALIVE HERE! */
3086 VG_(core_panic)("entered the afterlife in main() -- ExitSyscall");
3087 break; /* what the hell :) */
3088
3089 case VgSrc_Deadlock:
3090 /* Just exit now. No point in continuing. */
3091 VG_(proxy_shutdown)();
3092 VG_(exit)(0);
3093 VG_(core_panic)("entered the afterlife in main() -- Deadlock");
3094 break;
3095
nethercote71980f02004-01-24 18:18:54 +00003096 case VgSrc_FatalSig:
3097 /* We were killed by a fatal signal, so replicate the effect */
3098 vg_assert(VG_(fatal_sigNo) != -1);
3099 VG_(kill_self)(VG_(fatal_sigNo));
3100 VG_(core_panic)("main(): signal was supposed to be fatal");
3101 break;
3102
3103 default:
3104 VG_(core_panic)("main(): unexpected scheduler return code");
3105 }
3106
3107 abort();
3108}
3109
3110
sewardjde4a1d02002-03-22 01:27:54 +00003111/*--------------------------------------------------------------------*/
3112/*--- end vg_main.c ---*/
3113/*--------------------------------------------------------------------*/