blob: 86ca8e1dd26a1de4bca568769c613d09f3a00125 [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 */
nethercote31779c72004-07-30 21:50:15 +0000458int scan_auxv(void)
nethercote71980f02004-01-24 18:18:54 +0000459{
460 const struct ume_auxv *auxv = find_auxv((int *)ume_exec_esp);
nethercote31779c72004-07-30 21:50:15 +0000461 int padfile = -1, found = 0;
nethercote71980f02004-01-24 18:18:54 +0000462
463 for (; auxv->a_type != AT_NULL; auxv++)
464 switch(auxv->a_type) {
465 case AT_UME_PADFD:
nethercote31779c72004-07-30 21:50:15 +0000466 padfile = auxv->u.a_val;
nethercote71980f02004-01-24 18:18:54 +0000467 found |= 1;
468 break;
469
470 case AT_UME_EXECFD:
471 VG_(vgexecfd) = auxv->u.a_val;
472 found |= 2;
473 break;
474 }
475
nethercote361a14e2004-07-26 11:11:56 +0000476 if ( found != (1|2) ) {
477 fprintf(stderr, "valgrind: stage2 must be launched by stage1\n");
nethercote71980f02004-01-24 18:18:54 +0000478 exit(127);
479 }
nethercote31779c72004-07-30 21:50:15 +0000480 vg_assert(padfile >= 0);
481 return padfile;
nethercote71980f02004-01-24 18:18:54 +0000482}
483
484
485/*====================================================================*/
486/*=== Address space determination ===*/
487/*====================================================================*/
488
nethercote31779c72004-07-30 21:50:15 +0000489static void layout_remaining_space(Addr argc_addr, float ratio)
nethercote71980f02004-01-24 18:18:54 +0000490{
nethercote31779c72004-07-30 21:50:15 +0000491 Int ires;
492 void* vres;
493 addr_t client_size, shadow_size;
nethercote71980f02004-01-24 18:18:54 +0000494
nethercote31779c72004-07-30 21:50:15 +0000495 VG_(valgrind_base) = (addr_t)&kickstart_base;
496 VG_(valgrind_end) = ROUNDUP(argc_addr, 0x10000); // stack
nethercote71980f02004-01-24 18:18:54 +0000497
nethercote31779c72004-07-30 21:50:15 +0000498 // This gives the client the largest possible address space while
499 // taking into account the tool's shadow needs.
500 client_size = ROUNDDN((VG_(valgrind_base)-REDZONE_SIZE) / (1.+ratio),
nethercote71980f02004-01-24 18:18:54 +0000501 CLIENT_SIZE_MULTIPLE);
nethercote31779c72004-07-30 21:50:15 +0000502 VG_(client_base) = CLIENT_BASE;
nethercote71980f02004-01-24 18:18:54 +0000503 VG_(client_end) = VG_(client_base) + client_size;
nethercotee2097312004-06-27 12:29:56 +0000504 /* where !FIXED mmap goes */
nethercotebc7b4f42004-07-26 12:44:35 +0000505 VG_(client_mapbase) = VG_(client_base) +
506 PGROUNDDN((addr_t)(client_size * CLIENT_HEAP_PROPORTION));
nethercote71980f02004-01-24 18:18:54 +0000507
nethercote31779c72004-07-30 21:50:15 +0000508 shadow_size = PGROUNDUP(client_size * ratio);
509 VG_(shadow_base) = VG_(client_end) + REDZONE_SIZE;
510 VG_(shadow_end) = VG_(shadow_base) + shadow_size;
nethercote71980f02004-01-24 18:18:54 +0000511
nethercotee2097312004-06-27 12:29:56 +0000512#define SEGSIZE(a,b) ((VG_(b) - VG_(a))/(1024*1024))
513
nethercote71980f02004-01-24 18:18:54 +0000514 if (0)
nethercotee2097312004-06-27 12:29:56 +0000515 VG_(printf)(
516 "client_base %8x (%dMB)\n"
517 "client_mapbase %8x (%dMB)\n"
518 "client_end %8x (%dMB)\n"
519 "shadow_base %8x (%dMB)\n"
520 "shadow_end %8x (%dMB)\n"
521 "valgrind_base %8x (%dMB)\n"
nethercotee2097312004-06-27 12:29:56 +0000522 "valgrind_end %8x\n",
523 VG_(client_base), SEGSIZE(client_base, client_mapbase),
524 VG_(client_mapbase), SEGSIZE(client_mapbase, client_end),
525 VG_(client_end), SEGSIZE(client_end, shadow_base),
526 VG_(shadow_base), SEGSIZE(shadow_base, shadow_end),
527 VG_(shadow_end), SEGSIZE(shadow_end, valgrind_base),
nethercotec314eba2004-07-15 12:59:41 +0000528 VG_(valgrind_base), SEGSIZE(valgrind_base, valgrind_end),
nethercotee2097312004-06-27 12:29:56 +0000529 VG_(valgrind_end)
530 );
531
532#undef SEGSIZE
nethercote71980f02004-01-24 18:18:54 +0000533
534 // Ban redzone
nethercotee567e702004-07-10 17:49:17 +0000535 vres = mmap((void *)VG_(client_end), REDZONE_SIZE, PROT_NONE,
536 MAP_FIXED|MAP_ANON|MAP_PRIVATE, -1, 0);
537 vg_assert((void*)-1 != vres);
nethercote71980f02004-01-24 18:18:54 +0000538
539 // Make client hole
nethercotee567e702004-07-10 17:49:17 +0000540 ires = munmap((void*)VG_(client_base), client_size);
541 vg_assert(0 == ires);
nethercote71980f02004-01-24 18:18:54 +0000542
543 // Map shadow memory.
544 // Initially all inaccessible, incrementally initialized as it is used
nethercotee567e702004-07-10 17:49:17 +0000545 if (shadow_size != 0) {
546 vres = mmap((char *)VG_(shadow_base), shadow_size, PROT_NONE,
547 MAP_PRIVATE|MAP_ANON|MAP_FIXED, -1, 0);
548 vg_assert((void*)-1 != vres);
549 }
nethercote71980f02004-01-24 18:18:54 +0000550}
551
552/*====================================================================*/
553/*=== Command line setup ===*/
554/*====================================================================*/
555
556/* Nb: malloc'd memory never freed -- kept throughout like argv, envp */
557static char* get_file_clo(char* dir)
558{
559# define FLEN 512
560 Int fd, n;
561 struct stat s1;
562 char* f_clo = NULL;
563 char filename[FLEN];
564
565 snprintf(filename, FLEN, "%s/.valgrindrc", ( NULL == dir ? "" : dir ) );
566 fd = VG_(open)(filename, 0, VKI_S_IRUSR);
567 if ( fd > 0 ) {
568 if ( 0 == fstat(fd, &s1) ) {
569 f_clo = malloc(s1.st_size+1);
570 vg_assert(f_clo);
571 n = read(fd, f_clo, s1.st_size);
572 if (n == -1) n = 0;
573 f_clo[n] = '\0';
574 }
575 close(fd);
576 }
577 return f_clo;
578# undef FLEN
579}
580
nethercotee2097312004-06-27 12:29:56 +0000581#define ISSPACE(cc) ((cc) == ' ' || (cc) == '\t' || (cc) == '\n')
582
nethercote71980f02004-01-24 18:18:54 +0000583static Int count_args(char* s)
584{
585 Int n = 0;
586 if (s) {
587 char* cp = s;
588 while (True) {
589 // We have alternating sequences: blanks, non-blanks, blanks...
590 // count the non-blanks sequences.
591 while ( ISSPACE(*cp) ) cp++;
592 if ( !*cp ) break;
593 n++;
594 while ( !ISSPACE(*cp) && *cp ) cp++;
595 }
596 }
597 return n;
598}
599
600/* add args out of environment, skipping multiple spaces and -- args */
601static char** copy_args( char* s, char** to )
602{
603 if (s) {
604 char* cp = s;
605 while (True) {
606 // We have alternating sequences: blanks, non-blanks, blanks...
607 // copy the non-blanks sequences, and add terminating '\0'
608 while ( ISSPACE(*cp) ) cp++;
609 if ( !*cp ) break;
610 *to++ = cp;
611 while ( !ISSPACE(*cp) && *cp ) cp++;
612 if ( *cp ) *cp++ = '\0'; // terminate if necessary
613 if (VG_STREQ(to[-1], "--")) to--; // undo any '--' arg
614 }
615 }
616 return to;
617}
618
nethercotee2097312004-06-27 12:29:56 +0000619#undef ISSPACE
620
nethercote71980f02004-01-24 18:18:54 +0000621// Augment command line with arguments from environment and .valgrindrc
622// files.
623static void augment_command_line(Int* vg_argc_inout, char*** vg_argv_inout)
624{
625 int vg_argc = *vg_argc_inout;
626 char** vg_argv = *vg_argv_inout;
627
628 char* env_clo = getenv(VALGRINDOPTS);
629 char* f1_clo = get_file_clo( getenv("HOME") );
630 char* f2_clo = get_file_clo(".");
631
632 /* copy any extra args from file or environment, if present */
633 if ( (env_clo && *env_clo) || (f1_clo && *f1_clo) || (f2_clo && *f2_clo) ) {
634 /* ' ' separated extra options */
635 char **from;
636 char **to;
637 int env_arg_count, f1_arg_count, f2_arg_count;
638
639 env_arg_count = count_args(env_clo);
640 f1_arg_count = count_args(f1_clo);
641 f2_arg_count = count_args(f2_clo);
642
643 if (0)
644 printf("extra-argc=%d %d %d\n",
645 env_arg_count, f1_arg_count, f2_arg_count);
646
647 /* +2: +1 for null-termination, +1 for added '--' */
648 from = vg_argv;
649 vg_argv = malloc( (vg_argc + env_arg_count + f1_arg_count
650 + f2_arg_count + 2) * sizeof(char **));
nethercote7c018f42004-07-17 16:40:50 +0000651 vg_assert(vg_argv);
nethercote71980f02004-01-24 18:18:54 +0000652 to = vg_argv;
653
654 /* copy argv[0] */
655 *to++ = *from++;
656
657 /* Copy extra args from env var and file, in the order: ~/.valgrindrc,
658 * $VALGRIND_OPTS, ./.valgrindrc -- more local options are put later
659 * to override less local ones. */
660 to = copy_args(f1_clo, to);
661 to = copy_args(env_clo, to);
662 to = copy_args(f2_clo, to);
663
664 /* copy original arguments, stopping at command or -- */
665 while (*from) {
666 if (**from != '-')
667 break;
668 if (VG_STREQ(*from, "--")) {
669 from++; /* skip -- */
670 break;
671 }
672 *to++ = *from++;
673 }
674
675 /* add -- */
676 *to++ = "--";
677
678 vg_argc = to - vg_argv;
679
680 /* copy rest of original command line, then NULL */
681 while (*from) *to++ = *from++;
682 *to = NULL;
683 }
684
685 *vg_argc_inout = vg_argc;
686 *vg_argv_inout = vg_argv;
687}
688
689static void get_command_line( int argc, char** argv,
690 Int* vg_argc_out, Char*** vg_argv_out,
691 char*** cl_argv_out )
692{
693 int vg_argc;
694 char** vg_argv;
695 char** cl_argv;
696 char* env_clo = getenv(VALGRINDCLO);
697
698 if (env_clo != NULL && *env_clo != '\0') {
699 char *cp;
700 char **cpp;
701
702 /* OK, we're getting all our arguments from the environment - the
703 entire command line belongs to the client (including argv[0]) */
704 vg_argc = 1; /* argv[0] */
705 for (cp = env_clo; *cp; cp++)
706 if (*cp == '\01')
707 vg_argc++;
708
709 vg_argv = malloc(sizeof(char **) * (vg_argc + 1));
nethercote7c018f42004-07-17 16:40:50 +0000710 vg_assert(vg_argv);
nethercote71980f02004-01-24 18:18:54 +0000711
712 cpp = vg_argv;
713
714 *cpp++ = "valgrind"; /* nominal argv[0] */
715 *cpp++ = env_clo;
716
717 for (cp = env_clo; *cp; cp++) {
718 if (*cp == '\01') {
719 *cp++ = '\0'; /* chop it up in place */
720 *cpp++ = cp;
721 }
722 }
723 *cpp = NULL;
724 cl_argv = argv;
725
726 } else {
727 /* Count the arguments on the command line. */
728 vg_argv = argv;
729
730 for (vg_argc = 1; vg_argc < argc; vg_argc++) {
731 if (argv[vg_argc][0] != '-') /* exe name */
732 break;
733 if (VG_STREQ(argv[vg_argc], "--")) { /* dummy arg */
734 vg_argc++;
735 break;
736 }
737 }
738 cl_argv = &argv[vg_argc];
739
740 /* Get extra args from VALGRIND_OPTS and .valgrindrc files.
741 * Note we don't do this if getting args from VALGRINDCLO. */
742 augment_command_line(&vg_argc, &vg_argv);
743 }
744
745 if (0) {
746 Int i;
747 for (i = 0; i < vg_argc; i++)
748 printf("vg_argv[%d]=\"%s\"\n", i, vg_argv[i]);
749 }
750
751 *vg_argc_out = vg_argc;
752 *vg_argv_out = (Char**)vg_argv;
753 *cl_argv_out = cl_argv;
754}
755
756
757/*====================================================================*/
758/*=== Environment and stack setup ===*/
759/*====================================================================*/
760
761/* Scan a colon-separated list, and call a function on each element.
762 The string must be mutable, because we insert a temporary '\0', but
thughes4ad52d02004-06-27 17:37:21 +0000763 the string will end up unmodified. (*func) should return True if it
nethercote71980f02004-01-24 18:18:54 +0000764 doesn't need to see any more.
thughes4ad52d02004-06-27 17:37:21 +0000765
766 This routine will return True if (*func) returns True and False if
767 it reaches the end of the list without that happening.
nethercote71980f02004-01-24 18:18:54 +0000768*/
thughes4ad52d02004-06-27 17:37:21 +0000769static Bool scan_colsep(char *colsep, Bool (*func)(const char *))
nethercote71980f02004-01-24 18:18:54 +0000770{
771 char *cp, *entry;
772 int end;
773
774 if (colsep == NULL ||
775 *colsep == '\0')
thughes4ad52d02004-06-27 17:37:21 +0000776 return False;
nethercote71980f02004-01-24 18:18:54 +0000777
778 entry = cp = colsep;
779
780 do {
781 end = (*cp == '\0');
782
783 if (*cp == ':' || *cp == '\0') {
784 char save = *cp;
785
786 *cp = '\0';
thughes21942d92004-07-12 09:35:37 +0000787 if ((*func)(entry)) {
788 *cp = save;
thughes4ad52d02004-06-27 17:37:21 +0000789 return True;
thughes21942d92004-07-12 09:35:37 +0000790 }
nethercote71980f02004-01-24 18:18:54 +0000791 *cp = save;
792 entry = cp+1;
793 }
794 cp++;
795 } while(!end);
thughes4ad52d02004-06-27 17:37:21 +0000796
797 return False;
798}
799
800static Bool contains(const char *p) {
801 if (VG_STREQ(p, VG_(libdir))) {
802 return True;
803 }
804 return False;
nethercote71980f02004-01-24 18:18:54 +0000805}
806
807/* Prepare the client's environment. This is basically a copy of our
808 environment, except:
809 1. LD_LIBRARY_PATH=$VALGRINDLIB:$LD_LIBRARY_PATH
810 2. LD_PRELOAD=$VALGRINDLIB/vg_inject.so:($VALGRINDLIB/vgpreload_TOOL.so:)?$LD_PRELOAD
811
812 If any of these is missing, then it is added.
813
814 Yummy. String hacking in C.
815
816 If this needs to handle any more variables it should be hacked
817 into something table driven.
818 */
819static char **fix_environment(char **origenv, const char *preload)
820{
821 static const char inject_so[] = "vg_inject.so";
822 static const char ld_library_path[] = "LD_LIBRARY_PATH=";
823 static const char ld_preload[] = "LD_PRELOAD=";
824 static const char valgrind_clo[] = VALGRINDCLO "=";
825 static const int ld_library_path_len = sizeof(ld_library_path)-1;
826 static const int ld_preload_len = sizeof(ld_preload)-1;
827 static const int valgrind_clo_len = sizeof(valgrind_clo)-1;
828 int ld_preload_done = 0;
829 int ld_library_path_done = 0;
830 char *inject_path;
831 int inject_path_len;
832 int vgliblen = strlen(VG_(libdir));
833 char **cpp;
834 char **ret;
835 int envc;
836 const int preloadlen = (preload == NULL) ? 0 : strlen(preload);
837
838 /* Find the vg_inject.so; also make room for the tool preload
839 library */
840 inject_path_len = sizeof(inject_so) + vgliblen + preloadlen + 16;
841 inject_path = malloc(inject_path_len);
nethercote7c018f42004-07-17 16:40:50 +0000842 vg_assert(inject_path);
nethercote71980f02004-01-24 18:18:54 +0000843
844 if (preload)
845 snprintf(inject_path, inject_path_len, "%s/%s:%s",
846 VG_(libdir), inject_so, preload);
847 else
848 snprintf(inject_path, inject_path_len, "%s/%s",
849 VG_(libdir), inject_so);
850
851 /* Count the original size of the env */
852 envc = 0; /* trailing NULL */
853 for (cpp = origenv; cpp && *cpp; cpp++)
854 envc++;
855
856 /* Allocate a new space */
857 ret = malloc(sizeof(char *) * (envc+3+1)); /* 3 new entries + NULL */
nethercote7c018f42004-07-17 16:40:50 +0000858 vg_assert(ret);
nethercote71980f02004-01-24 18:18:54 +0000859
860 /* copy it over */
861 for (cpp = ret; *origenv; )
862 *cpp++ = *origenv++;
863 *cpp = NULL;
864
865 vg_assert(envc == (cpp - ret));
866
867 /* Walk over the new environment, mashing as we go */
868 for (cpp = ret; cpp && *cpp; cpp++) {
869 if (memcmp(*cpp, ld_library_path, ld_library_path_len) == 0) {
nethercote71980f02004-01-24 18:18:54 +0000870 /* If the LD_LIBRARY_PATH already contains libdir, then don't
871 bother adding it again, even if it isn't the first (it
872 seems that the Java runtime will keep reexecing itself
873 unless its paths are at the front of LD_LIBRARY_PATH) */
thughes4ad52d02004-06-27 17:37:21 +0000874 if (!scan_colsep(*cpp + ld_library_path_len, contains)) {
nethercote71980f02004-01-24 18:18:54 +0000875 int len = strlen(*cpp) + vgliblen*2 + 16;
876 char *cp = malloc(len);
nethercote7c018f42004-07-17 16:40:50 +0000877 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000878
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);
nethercote7c018f42004-07-17 16:40:50 +0000890 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000891
892 snprintf(cp, len, "%s%s:%s",
893 ld_preload, inject_path, (*cpp)+ld_preload_len);
894
895 *cpp = cp;
896
897 ld_preload_done = 1;
898 } else if (memcmp(*cpp, valgrind_clo, valgrind_clo_len) == 0) {
899 *cpp = "";
900 }
901 }
902
903 /* Add the missing bits */
904
905 if (!ld_library_path_done) {
906 int len = ld_library_path_len + vgliblen*2 + 16;
907 char *cp = malloc(len);
nethercote7c018f42004-07-17 16:40:50 +0000908 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000909
910 snprintf(cp, len, "%s%s", ld_library_path, VG_(libdir));
911
912 ret[envc++] = cp;
913 }
914
915 if (!ld_preload_done) {
916 int len = ld_preload_len + inject_path_len;
917 char *cp = malloc(len);
nethercote7c018f42004-07-17 16:40:50 +0000918 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000919
920 snprintf(cp, len, "%s%s",
921 ld_preload, inject_path);
922
923 ret[envc++] = cp;
924 }
925
926 ret[envc] = NULL;
927
928 return ret;
929}
930
931extern char **environ; /* our environment */
932//#include <error.h>
933
934/* Add a string onto the string table, and return its address */
935static char *copy_str(char **tab, const char *str)
936{
937 char *cp = *tab;
938 char *orig = cp;
939
940 while(*str)
941 *cp++ = *str++;
942 *cp++ = '\0';
943
944 if (0)
nethercotef84f6952004-07-15 14:58:33 +0000945 printf("copied %p \"%s\" len %d\n", orig, orig, cp-orig);
nethercote71980f02004-01-24 18:18:54 +0000946
947 *tab = cp;
948
949 return orig;
950}
951
952/*
953 This sets up the client's initial stack, containing the args,
954 environment and aux vector.
955
956 The format of the stack is:
957
958 higher address +-----------------+
959 | Trampoline code |
960 +-----------------+
961 | |
962 : string table :
963 | |
964 +-----------------+
965 | AT_NULL |
966 - -
967 | auxv |
968 +-----------------+
969 | NULL |
970 - -
971 | envp |
972 +-----------------+
973 | NULL |
974 - -
975 | argv |
976 +-----------------+
977 | argc |
978 lower address +-----------------+ <- esp
979 | undefined |
980 : :
981 */
982static Addr setup_client_stack(char **orig_argv, char **orig_envp,
983 const struct exeinfo *info,
984 UInt** client_auxv)
985{
nethercotee567e702004-07-10 17:49:17 +0000986 void* res;
nethercote71980f02004-01-24 18:18:54 +0000987 char **cpp;
988 char *strtab; /* string table */
989 char *stringbase;
990 addr_t *ptr;
991 struct ume_auxv *auxv;
992 const struct ume_auxv *orig_auxv;
993 const struct ume_auxv *cauxv;
994 unsigned stringsize; /* total size of strings in bytes */
995 unsigned auxsize; /* total size of auxv in bytes */
996 int argc; /* total argc */
997 int envc; /* total number of env vars */
998 unsigned stacksize; /* total client stack size */
999 addr_t cl_esp; /* client stack base (initial esp) */
1000
1001 /* use our own auxv as a prototype */
1002 orig_auxv = find_auxv(ume_exec_esp);
1003
1004 /* ==================== compute sizes ==================== */
1005
1006 /* first of all, work out how big the client stack will be */
1007 stringsize = 0;
1008
1009 /* paste on the extra args if the loader needs them (ie, the #!
1010 interpreter and its argument) */
1011 argc = 0;
nethercoted6a56872004-07-26 15:32:47 +00001012 if (info->interp_name != NULL) {
nethercote71980f02004-01-24 18:18:54 +00001013 argc++;
nethercoted6a56872004-07-26 15:32:47 +00001014 stringsize += strlen(info->interp_name) + 1;
nethercote71980f02004-01-24 18:18:54 +00001015 }
nethercoted6a56872004-07-26 15:32:47 +00001016 if (info->interp_args != NULL) {
nethercote71980f02004-01-24 18:18:54 +00001017 argc++;
nethercoted6a56872004-07-26 15:32:47 +00001018 stringsize += strlen(info->interp_args) + 1;
nethercote71980f02004-01-24 18:18:54 +00001019 }
1020
1021 /* now scan the args we're given... */
1022 for (cpp = orig_argv; *cpp; cpp++) {
1023 argc++;
1024 stringsize += strlen(*cpp) + 1;
1025 }
1026
1027 /* ...and the environment */
1028 envc = 0;
1029 for (cpp = orig_envp; cpp && *cpp; cpp++) {
1030 envc++;
1031 stringsize += strlen(*cpp) + 1;
1032 }
1033
1034 /* now, how big is the auxv? */
1035 auxsize = sizeof(*auxv); /* there's always at least one entry: AT_NULL */
1036 for (cauxv = orig_auxv; cauxv->a_type != AT_NULL; cauxv++) {
1037 if (cauxv->a_type == AT_PLATFORM)
1038 stringsize += strlen(cauxv->u.a_ptr) + 1;
1039 auxsize += sizeof(*cauxv);
1040 }
1041
1042 /* OK, now we know how big the client stack is */
1043 stacksize =
1044 sizeof(int) + /* argc */
1045 sizeof(char **)*argc + /* argv */
1046 sizeof(char **) + /* terminal NULL */
1047 sizeof(char **)*envc + /* envp */
1048 sizeof(char **) + /* terminal NULL */
1049 auxsize + /* auxv */
1050 ROUNDUP(stringsize, sizeof(int)) +/* strings (aligned) */
1051 VKI_BYTES_PER_PAGE; /* page for trampoline code */
1052
nethercotef84f6952004-07-15 14:58:33 +00001053 // decide where stack goes!
1054 VG_(clstk_end) = VG_(client_end);
1055
1056 VG_(client_trampoline_code) = VG_(clstk_end) - VKI_BYTES_PER_PAGE;
1057
nethercote71980f02004-01-24 18:18:54 +00001058 /* cl_esp is the client's stack pointer */
nethercotef84f6952004-07-15 14:58:33 +00001059 cl_esp = VG_(clstk_end) - stacksize;
nethercote71980f02004-01-24 18:18:54 +00001060 cl_esp = ROUNDDN(cl_esp, 16); /* make stack 16 byte aligned */
1061
nethercote71980f02004-01-24 18:18:54 +00001062 /* base of the string table (aligned) */
1063 stringbase = strtab = (char *)(VG_(client_trampoline_code) - ROUNDUP(stringsize, sizeof(int)));
1064
1065 VG_(clstk_base) = PGROUNDDN(cl_esp);
nethercote71980f02004-01-24 18:18:54 +00001066
nethercote5ee67ca2004-06-22 14:00:09 +00001067 if (0)
1068 printf("stringsize=%d auxsize=%d stacksize=%d\n"
1069 "clstk_base %x\n"
1070 "clstk_end %x\n",
1071 stringsize, auxsize, stacksize, VG_(clstk_base), VG_(clstk_end));
1072
1073
nethercote71980f02004-01-24 18:18:54 +00001074 /* ==================== allocate space ==================== */
1075
1076 /* allocate a stack - mmap enough space for the stack */
nethercotef84f6952004-07-15 14:58:33 +00001077 res = mmap((void *)PGROUNDDN(cl_esp), VG_(clstk_end) - PGROUNDDN(cl_esp),
nethercotee567e702004-07-10 17:49:17 +00001078 PROT_READ | PROT_WRITE | PROT_EXEC,
1079 MAP_PRIVATE | MAP_ANON | MAP_FIXED, -1, 0);
1080 vg_assert((void*)-1 != res);
nethercote71980f02004-01-24 18:18:54 +00001081
1082 /* ==================== copy client stack ==================== */
1083
1084 ptr = (addr_t *)cl_esp;
1085
1086 /* --- argc --- */
1087 *ptr++ = argc; /* client argc */
1088
1089 /* --- argv --- */
nethercoted6a56872004-07-26 15:32:47 +00001090 if (info->interp_name) {
1091 *ptr++ = (addr_t)copy_str(&strtab, info->interp_name);
1092 free(info->interp_name);
nethercote71980f02004-01-24 18:18:54 +00001093 }
nethercoted6a56872004-07-26 15:32:47 +00001094 if (info->interp_args) {
1095 *ptr++ = (addr_t)copy_str(&strtab, info->interp_args);
1096 free(info->interp_args);
nethercote71980f02004-01-24 18:18:54 +00001097 }
1098 for (cpp = orig_argv; *cpp; ptr++, cpp++) {
1099 *ptr = (addr_t)copy_str(&strtab, *cpp);
1100 }
1101 *ptr++ = 0;
1102
1103 /* --- envp --- */
1104 VG_(client_envp) = (Char **)ptr;
1105 for (cpp = orig_envp; cpp && *cpp; ptr++, cpp++)
1106 *ptr = (addr_t)copy_str(&strtab, *cpp);
1107 *ptr++ = 0;
1108
1109 /* --- auxv --- */
1110 auxv = (struct ume_auxv *)ptr;
1111 *client_auxv = (UInt *)auxv;
1112
1113 for (; orig_auxv->a_type != AT_NULL; auxv++, orig_auxv++) {
1114 /* copy the entry... */
1115 *auxv = *orig_auxv;
1116
1117 /* ...and fix up the copy */
1118 switch(auxv->a_type) {
1119 case AT_PHDR:
1120 if (info->phdr == 0)
1121 auxv->a_type = AT_IGNORE;
1122 else
1123 auxv->u.a_val = info->phdr;
1124 break;
1125
1126 case AT_PHNUM:
1127 if (info->phdr == 0)
1128 auxv->a_type = AT_IGNORE;
1129 else
1130 auxv->u.a_val = info->phnum;
1131 break;
1132
1133 case AT_BASE:
1134 if (info->interp_base == 0)
1135 auxv->a_type = AT_IGNORE;
1136 else
1137 auxv->u.a_val = info->interp_base;
1138 break;
1139
1140 case AT_PLATFORM: /* points to a platform description string */
1141 auxv->u.a_ptr = copy_str(&strtab, orig_auxv->u.a_ptr);
1142 break;
1143
1144 case AT_ENTRY:
1145 auxv->u.a_val = info->entry;
1146 break;
1147
1148 case AT_IGNORE:
1149 case AT_EXECFD:
1150 case AT_PHENT:
1151 case AT_PAGESZ:
1152 case AT_FLAGS:
1153 case AT_NOTELF:
1154 case AT_UID:
1155 case AT_EUID:
1156 case AT_GID:
1157 case AT_EGID:
1158 case AT_CLKTCK:
1159 case AT_HWCAP:
1160 case AT_FPUCW:
1161 case AT_DCACHEBSIZE:
1162 case AT_ICACHEBSIZE:
1163 case AT_UCACHEBSIZE:
1164 /* All these are pointerless, so we don't need to do anything
1165 about them. */
1166 break;
1167
1168 case AT_SECURE:
1169 /* If this is 1, then it means that this program is running
1170 suid, and therefore the dynamic linker should be careful
1171 about LD_PRELOAD, etc. However, since stage1 (the thing
1172 the kernel actually execve's) should never be SUID, and we
1173 need LD_PRELOAD/LD_LIBRARY_PATH to work for the client, we
1174 set AT_SECURE to 0. */
1175 auxv->u.a_val = 0;
1176 break;
1177
1178 case AT_SYSINFO:
1179 /* Leave this unmolested for now, but we'll update it later
1180 when we set up the client trampoline code page */
1181 break;
1182
1183 case AT_SYSINFO_EHDR:
1184 /* Trash this, because we don't reproduce it */
1185 auxv->a_type = AT_IGNORE;
1186 break;
1187
1188 default:
1189 /* stomp out anything we don't know about */
1190 if (0)
1191 printf("stomping auxv entry %d\n", auxv->a_type);
1192 auxv->a_type = AT_IGNORE;
1193 break;
1194
1195 }
1196 }
1197 *auxv = *orig_auxv;
1198 vg_assert(auxv->a_type == AT_NULL);
1199
nethercotef84f6952004-07-15 14:58:33 +00001200 /* --- trampoline page --- */
1201 VG_(memcpy)( (void *)VG_(client_trampoline_code),
1202 &VG_(trampoline_code_start), VG_(trampoline_code_length) );
1203
nethercote71980f02004-01-24 18:18:54 +00001204 vg_assert((strtab-stringbase) == stringsize);
1205
nethercote5ee67ca2004-06-22 14:00:09 +00001206 /* We know the initial ESP is pointing at argc/argv */
1207 VG_(client_argc) = *(Int*)cl_esp;
1208 VG_(client_argv) = (Char**)(cl_esp + sizeof(Int));
1209
nethercote71980f02004-01-24 18:18:54 +00001210 return cl_esp;
1211}
1212
1213/*====================================================================*/
1214/*=== Find executable ===*/
1215/*====================================================================*/
1216
thughes4ad52d02004-06-27 17:37:21 +00001217static const char* executable_name;
1218
1219static Bool match_executable(const char *entry) {
1220 char buf[strlen(entry) + strlen(executable_name) + 2];
1221
1222 /* empty PATH element means . */
1223 if (*entry == '\0')
1224 entry = ".";
1225
1226 snprintf(buf, sizeof(buf), "%s/%s", entry, executable_name);
1227
1228 if (access(buf, R_OK|X_OK) == 0) {
1229 executable_name = strdup(buf);
1230 vg_assert(NULL != executable_name);
1231 return True;
1232 }
1233 return False;
1234}
1235
nethercote71980f02004-01-24 18:18:54 +00001236static const char* find_executable(const char* exec)
1237{
1238 vg_assert(NULL != exec);
thughes4ad52d02004-06-27 17:37:21 +00001239 executable_name = exec;
1240 if (strchr(executable_name, '/') == NULL) {
nethercote71980f02004-01-24 18:18:54 +00001241 /* no '/' - we need to search the path */
1242 char *path = getenv("PATH");
thughes4ad52d02004-06-27 17:37:21 +00001243 scan_colsep(path, match_executable);
nethercote71980f02004-01-24 18:18:54 +00001244 }
thughes4ad52d02004-06-27 17:37:21 +00001245 return executable_name;
nethercote71980f02004-01-24 18:18:54 +00001246}
1247
1248
1249/*====================================================================*/
1250/*=== Loading tools ===*/
1251/*====================================================================*/
1252
1253static void list_tools(void)
1254{
1255 DIR *dir = opendir(VG_(libdir));
1256 struct dirent *de;
1257 int first = 1;
1258
1259 if (dir == NULL) {
1260 fprintf(stderr, "Can't open %s: %s (installation problem?)\n",
nethercotef4928da2004-06-15 10:54:40 +00001261 VG_(libdir), strerror(errno));
nethercote71980f02004-01-24 18:18:54 +00001262 return;
1263 }
1264
nethercotef4928da2004-06-15 10:54:40 +00001265 while ((de = readdir(dir)) != NULL) {
nethercote71980f02004-01-24 18:18:54 +00001266 int len = strlen(de->d_name);
1267
1268 /* look for vgskin_TOOL.so names */
1269 if (len > (7+1+3) && /* "vgskin_" + at least 1-char toolname + ".so" */
nethercotef4928da2004-06-15 10:54:40 +00001270 strncmp(de->d_name, "vgskin_", 7) == 0 &&
1271 VG_STREQ(de->d_name + len - 3, ".so")) {
1272 if (first) {
1273 fprintf(stderr, "Available tools:\n");
1274 first = 0;
1275 }
1276 de->d_name[len-3] = '\0';
1277 fprintf(stderr, "\t%s\n", de->d_name+7);
nethercote71980f02004-01-24 18:18:54 +00001278 }
1279 }
1280
1281 closedir(dir);
1282
1283 if (first)
nethercotef4928da2004-06-15 10:54:40 +00001284 fprintf(stderr, "No tools available in \"%s\" (installation problem?)\n",
1285 VG_(libdir));
nethercote71980f02004-01-24 18:18:54 +00001286}
1287
1288
1289/* Find and load a tool, and check it looks ok. Also looks to see if there's
1290 * a matching vgpreload_*.so file, and returns its name in *preloadpath. */
1291static void load_tool( const char *toolname, void** handle_out,
1292 ToolInfo** toolinfo_out, char **preloadpath_out )
1293{
1294 Bool ok;
1295 int len = strlen(VG_(libdir)) + strlen(toolname)*2 + 16;
1296 char buf[len];
1297 void* handle;
1298 ToolInfo* toolinfo;
1299 char* preloadpath = NULL;
1300 Int* vg_malloc_redzonep;
1301
1302 // XXX: allowing full paths for --tool option -- does it make sense?
1303 // Doesn't allow for vgpreload_<tool>.so.
1304
1305 if (strchr(toolname, '/') != 0) {
1306 /* toolname contains '/', and so must be a pathname */
1307 handle = dlopen(toolname, RTLD_NOW);
1308 } else {
1309 /* just try in the libdir */
1310 snprintf(buf, len, "%s/vgskin_%s.so", VG_(libdir), toolname);
1311 handle = dlopen(buf, RTLD_NOW);
1312
1313 if (handle != NULL) {
1314 snprintf(buf, len, "%s/vgpreload_%s.so", VG_(libdir), toolname);
1315 if (access(buf, R_OK) == 0) {
1316 preloadpath = strdup(buf);
1317 vg_assert(NULL != preloadpath);
1318 }
1319 }
1320 }
1321
1322 ok = (NULL != handle);
1323 if (!ok) {
1324 fprintf(stderr, "Can't open tool \"%s\": %s\n", toolname, dlerror());
1325 goto bad_load;
1326 }
1327
1328 toolinfo = dlsym(handle, "vgSkin_tool_info");
1329 ok = (NULL != toolinfo);
1330 if (!ok) {
1331 fprintf(stderr, "Tool \"%s\" doesn't define SK_(tool_info) - "
1332 "add VG_DETERMINE_INTERFACE_VERSION?\n", toolname);
1333 goto bad_load;
1334 }
1335
1336 ok = (toolinfo->sizeof_ToolInfo == sizeof(*toolinfo) &&
1337 toolinfo->interface_major_version == VG_CORE_INTERFACE_MAJOR_VERSION &&
1338 toolinfo->sk_pre_clo_init != NULL);
1339 if (!ok) {
1340 fprintf(stderr, "Error:\n"
1341 " Tool and core interface versions do not match.\n"
1342 " Interface version used by core is: %d.%d (size %d)\n"
1343 " Interface version used by tool is: %d.%d (size %d)\n"
1344 " The major version numbers must match.\n",
1345 VG_CORE_INTERFACE_MAJOR_VERSION,
1346 VG_CORE_INTERFACE_MINOR_VERSION,
1347 sizeof(*toolinfo),
1348 toolinfo->interface_major_version,
1349 toolinfo->interface_minor_version,
1350 toolinfo->sizeof_ToolInfo);
1351 fprintf(stderr, " You need to at least recompile, and possibly update,\n");
1352 if (VG_CORE_INTERFACE_MAJOR_VERSION > toolinfo->interface_major_version)
1353 fprintf(stderr, " your skin to work with this version of Valgrind.\n");
1354 else
1355 fprintf(stderr, " your version of Valgrind to work with this skin.\n");
1356 goto bad_load;
1357 }
1358
1359 // Set redzone size for V's allocator
1360 vg_malloc_redzonep = dlsym(handle, STR(VG_(vg_malloc_redzone_szB)));
1361 if ( NULL != vg_malloc_redzonep ) {
1362 VG_(vg_malloc_redzone_szB) = *vg_malloc_redzonep;
1363 }
1364
1365 vg_assert(NULL != handle && NULL != toolinfo);
1366 *handle_out = handle;
1367 *toolinfo_out = toolinfo;
1368 *preloadpath_out = preloadpath;
1369 return;
1370
1371
1372 bad_load:
1373 if (handle != NULL)
1374 dlclose(handle);
1375
nethercotef4928da2004-06-15 10:54:40 +00001376 fprintf(stderr, "valgrind: couldn't load tool\n");
nethercote71980f02004-01-24 18:18:54 +00001377 list_tools();
1378 exit(127);
1379}
1380
nethercotef4928da2004-06-15 10:54:40 +00001381
1382/*====================================================================*/
1383/*=== Command line errors ===*/
1384/*====================================================================*/
1385
1386static void abort_msg ( void )
1387{
nethercotef8548672004-06-21 12:42:35 +00001388 VG_(clo_log_to) = VgLogTo_Fd;
1389 VG_(clo_log_fd) = 2; /* stderr */
nethercotef4928da2004-06-15 10:54:40 +00001390}
1391
1392void VG_(bad_option) ( Char* opt )
1393{
1394 abort_msg();
1395 VG_(printf)("valgrind: Bad option `%s'; aborting.\n", opt);
1396 VG_(printf)("valgrind: Use --help for more information.\n");
1397 VG_(exit)(1);
1398}
1399
1400static void missing_tool_option ( void )
1401{
1402 abort_msg();
1403 VG_(printf)("valgrind: Missing --tool option\n");
1404 list_tools();
1405 VG_(printf)("valgrind: Use --help for more information.\n");
1406 VG_(exit)(1);
1407}
1408
1409static void missing_prog ( void )
1410{
1411 abort_msg();
1412 VG_(printf)("valgrind: no program specified\n");
1413 VG_(printf)("valgrind: Use --help for more information.\n");
1414 VG_(exit)(1);
1415}
1416
1417static void config_error ( Char* msg )
1418{
1419 abort_msg();
1420 VG_(printf)("valgrind: Startup or configuration error:\n %s\n", msg);
1421 VG_(printf)("valgrind: Unable to start up properly. Giving up.\n");
1422 VG_(exit)(1);
1423}
1424
1425
nethercote71980f02004-01-24 18:18:54 +00001426/*====================================================================*/
1427/*=== Loading the client ===*/
1428/*====================================================================*/
1429
nethercotef4928da2004-06-15 10:54:40 +00001430static void load_client(char* cl_argv[], const char* exec, Int need_help,
nethercote71980f02004-01-24 18:18:54 +00001431 /*out*/struct exeinfo* info, /*out*/Addr* client_eip)
1432{
1433 // If they didn't specify an executable with --exec, and didn't specify
1434 // --help, then use client argv[0] (searching $PATH if necessary).
nethercotef4928da2004-06-15 10:54:40 +00001435 if (NULL == exec && !need_help) {
nethercote71980f02004-01-24 18:18:54 +00001436 if (cl_argv[0] == NULL ||
1437 ( NULL == (exec = find_executable(cl_argv[0])) ) )
1438 {
nethercotef4928da2004-06-15 10:54:40 +00001439 missing_prog();
nethercote71980f02004-01-24 18:18:54 +00001440 }
1441 }
1442
1443 info->map_base = VG_(client_mapbase);
nethercote71980f02004-01-24 18:18:54 +00001444 info->exe_base = VG_(client_base);
1445 info->exe_end = VG_(client_end);
1446 info->argv = cl_argv;
1447
nethercotef4928da2004-06-15 10:54:40 +00001448 if (need_help) {
nethercote71980f02004-01-24 18:18:54 +00001449 VG_(clexecfd) = -1;
nethercoteea147e72004-07-26 15:43:57 +00001450 // Set the minimal number of entries in 'info' to continue.
nethercoted6a56872004-07-26 15:32:47 +00001451 info->interp_name = NULL;
1452 info->interp_args = NULL;
nethercote71980f02004-01-24 18:18:54 +00001453 } else {
1454 Int ret;
1455 VG_(clexecfd) = VG_(open)(exec, O_RDONLY, VKI_S_IRUSR);
1456 ret = do_exec(exec, info);
1457 if (ret != 0) {
nethercoteea147e72004-07-26 15:43:57 +00001458 fprintf(stderr, "valgrind: do_exec(%s) failed: %s\n",
1459 exec, strerror(ret));
nethercote71980f02004-01-24 18:18:54 +00001460 exit(127);
1461 }
1462 }
1463
1464 /* Copy necessary bits of 'info' that were filled in */
1465 *client_eip = info->init_eip;
1466 VG_(brk_base) = VG_(brk_limit) = info->brkbase;
1467}
1468
1469
1470/*====================================================================*/
1471/*=== Command-line: variables, processing ===*/
1472/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +00001473
njn25e49d8e72002-09-23 09:36:25 +00001474/* Define, and set defaults. */
1475Bool VG_(clo_error_limit) = True;
nethercote04d0fbc2004-01-26 16:48:06 +00001476Bool VG_(clo_db_attach) = False;
1477Char* VG_(clo_db_command) = VG_CLO_DEFAULT_DBCOMMAND;
njn43c799e2003-04-08 00:08:52 +00001478Bool VG_(clo_gen_suppressions) = False;
nethercote27fec902004-06-16 21:26:32 +00001479Int VG_(clo_sanity_level) = 1;
njn25e49d8e72002-09-23 09:36:25 +00001480Int VG_(clo_verbosity) = 1;
1481Bool VG_(clo_demangle) = True;
njn25e49d8e72002-09-23 09:36:25 +00001482Bool VG_(clo_trace_children) = False;
sewardj4cf05692002-10-27 20:28:29 +00001483
nethercotee1730692003-11-20 10:38:07 +00001484/* See big comment in vg_include.h for meaning of these three.
1485 fd is initially stdout, for --help, but gets moved to stderr by default
1486 immediately afterwards. */
sewardj4cf05692002-10-27 20:28:29 +00001487VgLogTo VG_(clo_log_to) = VgLogTo_Fd;
nethercotef8548672004-06-21 12:42:35 +00001488Int VG_(clo_log_fd) = 1;
1489Char* VG_(clo_log_name) = NULL;
sewardj4cf05692002-10-27 20:28:29 +00001490
sewardj6024b212003-07-13 10:54:33 +00001491Int VG_(clo_input_fd) = 0; /* stdin */
njn25e49d8e72002-09-23 09:36:25 +00001492Int VG_(clo_n_suppressions) = 0;
sewardjde4a1d02002-03-22 01:27:54 +00001493Char* VG_(clo_suppressions)[VG_CLO_MAX_SFILES];
njn25e49d8e72002-09-23 09:36:25 +00001494Bool VG_(clo_profile) = False;
1495Bool VG_(clo_single_step) = False;
1496Bool VG_(clo_optimise) = True;
1497UChar VG_(clo_trace_codegen) = 0; // 00000000b
1498Bool VG_(clo_trace_syscalls) = False;
1499Bool VG_(clo_trace_signals) = False;
1500Bool VG_(clo_trace_symtab) = False;
njn25e49d8e72002-09-23 09:36:25 +00001501Bool VG_(clo_trace_sched) = False;
1502Int VG_(clo_trace_pthread_level) = 0;
njn25e49d8e72002-09-23 09:36:25 +00001503Int VG_(clo_dump_error) = 0;
1504Int VG_(clo_backtrace_size) = 4;
1505Char* VG_(clo_weird_hacks) = NULL;
sewardj858964b2002-10-05 14:15:43 +00001506Bool VG_(clo_run_libc_freeres) = True;
rjwalshf5f536f2003-11-17 17:45:00 +00001507Bool VG_(clo_track_fds) = False;
sewardj22854b92002-11-30 14:00:47 +00001508Bool VG_(clo_chain_bb) = True;
nethercote77eba602003-11-13 17:35:04 +00001509Bool VG_(clo_show_below_main) = False;
fitzhardinge98abfc72003-12-16 02:05:15 +00001510Bool VG_(clo_pointercheck) = True;
fitzhardinge462f4f92003-12-18 02:10:54 +00001511Bool VG_(clo_branchpred) = False;
sewardj2370f3b2002-11-30 15:01:01 +00001512
jsgf855d93d2003-10-13 22:26:55 +00001513static Bool VG_(clo_wait_for_gdb) = False;
1514
1515/* If we're doing signal routing, poll for signals every 50mS by
1516 default. */
1517Int VG_(clo_signal_polltime) = 50;
1518
1519/* These flags reduce thread wakeup latency on syscall completion and
1520 signal delivery, respectively. The downside is possible unfairness. */
1521Bool VG_(clo_lowlat_syscalls) = False; /* low-latency syscalls */
1522Bool VG_(clo_lowlat_signals) = False; /* low-latency signals */
1523
sewardjde4a1d02002-03-22 01:27:54 +00001524
nethercote6c999f22004-01-31 22:55:15 +00001525void usage ( Bool debug_help )
njn7cf0bd32002-06-08 13:36:03 +00001526{
njn25e49d8e72002-09-23 09:36:25 +00001527 Char* usage1 =
nethercote71980f02004-01-24 18:18:54 +00001528"usage: valgrind --tool=<toolname> [options] prog-and-args\n"
njn25e49d8e72002-09-23 09:36:25 +00001529"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001530" common user options for all Valgrind tools, with defaults in [ ]:\n"
nethercote0d588502004-06-21 13:27:11 +00001531" --tool=<name> use the Valgrind tool named <name>\n"
nethercotea76368b2004-06-16 11:56:29 +00001532" -h --help show this message\n"
nethercote6c999f22004-01-31 22:55:15 +00001533" --help-debug show this message, plus debugging options\n"
njn25e49d8e72002-09-23 09:36:25 +00001534" --version show version\n"
njn25e49d8e72002-09-23 09:36:25 +00001535" -q --quiet run silently; only print error msgs\n"
1536" -v --verbose be more verbose, incl counts of errors\n"
nethercote77eba602003-11-13 17:35:04 +00001537" --trace-children=no|yes Valgrind-ise child processes? [no]\n"
nethercote0d588502004-06-21 13:27:11 +00001538" --track-fds=no|yes track open file descriptors? [no]\n"
nethercote2b0793f2003-12-02 10:41:18 +00001539"\n"
1540" uncommon user options for all Valgrind tools:\n"
nethercote0d588502004-06-21 13:27:11 +00001541" --run-libc-freeres=no|yes free up glibc memory at exit? [yes]\n"
1542" --weird-hacks=hack1,hack2,... recognised hacks: lax-ioctls [none]\n"
1543" --signal-polltime=<time> signal poll period (mS) for older kernels [50]\n"
1544" --lowlat-signals=no|yes improve thread signal wake-up latency [no]\n"
1545" --lowlat-syscalls=no|yes improve thread syscall wake-up latency [no]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001546" --pointercheck=no|yes enforce client address space limits [yes]\n"
njn25e49d8e72002-09-23 09:36:25 +00001547"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001548" user options for Valgrind tools that report errors:\n"
nethercotef8548672004-06-21 12:42:35 +00001549" --log-fd=<number> log messages to file descriptor [2=stderr]\n"
1550" --log-file=<file> log messages to <file>.pid<pid>\n"
1551" --log-socket=ipaddr:port log messages to socket ipaddr:port\n"
nethercote2b0793f2003-12-02 10:41:18 +00001552" --demangle=no|yes automatically demangle C++ names? [yes]\n"
1553" --num-callers=<number> show <num> callers in stack traces [4]\n"
1554" --error-limit=no|yes stop showing new errors if too many? [yes]\n"
1555" --show-below-main=no|yes continue stack traces below main() [no]\n"
1556" --suppressions=<filename> suppress errors described in <filename>\n"
1557" --gen-suppressions=no|yes print suppressions for errors detected [no]\n"
nethercote04d0fbc2004-01-26 16:48:06 +00001558" --db-attach=no|yes start debugger when errors detected? [no]\n"
1559" --db-command=<command> command to start debugger [gdb -nw %%f %%p]\n"
1560" --input-fd=<number> file descriptor for input [0=stdin]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001561"\n";
njn7cf0bd32002-06-08 13:36:03 +00001562
njn25e49d8e72002-09-23 09:36:25 +00001563 Char* usage2 =
1564"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001565" debugging options for all Valgrind tools:\n"
njn25e49d8e72002-09-23 09:36:25 +00001566" --sanity-level=<number> level of sanity checking to do [1]\n"
1567" --single-step=no|yes translate each instr separately? [no]\n"
1568" --optimise=no|yes improve intermediate code? [yes]\n"
nethercote137bc552003-11-14 17:47:54 +00001569" --profile=no|yes profile? (tool must be built for it) [no]\n"
sewardj22854b92002-11-30 14:00:47 +00001570" --chain-bb=no|yes do basic-block chaining? [yes]\n"
fitzhardinge462f4f92003-12-18 02:10:54 +00001571" --branchpred=yes|no generate branch prediction hints [no]\n"
njn25e49d8e72002-09-23 09:36:25 +00001572" --trace-codegen=<XXXXX> show generated code? (X = 0|1) [00000]\n"
1573" --trace-syscalls=no|yes show all system calls? [no]\n"
1574" --trace-signals=no|yes show signal handling details? [no]\n"
1575" --trace-symtab=no|yes show symbol table details? [no]\n"
njn25e49d8e72002-09-23 09:36:25 +00001576" --trace-sched=no|yes show thread scheduler details? [no]\n"
njn3e884182003-04-15 13:03:23 +00001577" --trace-pthread=none|some|all show pthread event details? [none]\n"
jsgf855d93d2003-10-13 22:26:55 +00001578" --wait-for-gdb=yes|no pause on startup to wait for gdb attach\n"
njn25e49d8e72002-09-23 09:36:25 +00001579"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001580" debugging options for Valgrind tools that report errors\n"
1581" --dump-error=<number> show translation for basic block associated\n"
1582" with <number>'th error context [0=show none]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001583"\n";
njn3e884182003-04-15 13:03:23 +00001584
1585 Char* usage3 =
1586"\n"
nethercote71980f02004-01-24 18:18:54 +00001587" Extra options read from ~/.valgrindrc, $VALGRIND_OPTS, ./.valgrindrc\n"
njn25e49d8e72002-09-23 09:36:25 +00001588"\n"
nethercote08fa9a72004-07-16 17:44:00 +00001589" Valgrind is Copyright (C) 2000-2004 Julian Seward et al.\n"
njn25e49d8e72002-09-23 09:36:25 +00001590" and licensed under the GNU General Public License, version 2.\n"
1591" Bug reports, feedback, admiration, abuse, etc, to: %s.\n"
njnd04b7c62002-10-03 14:05:52 +00001592"\n"
nethercote137bc552003-11-14 17:47:54 +00001593" Tools are copyright and licensed by their authors. See each\n"
1594" tool's start-up message for more information.\n"
njn25e49d8e72002-09-23 09:36:25 +00001595"\n";
njn7cf0bd32002-06-08 13:36:03 +00001596
fitzhardinge98abfc72003-12-16 02:05:15 +00001597 VG_(printf)(usage1);
1598 if (VG_(details).name) {
1599 VG_(printf)(" user options for %s:\n", VG_(details).name);
fitzhardinge98abfc72003-12-16 02:05:15 +00001600 if (VG_(needs).command_line_options)
1601 SK_(print_usage)();
1602 else
1603 VG_(printf)(" (none)\n");
1604 }
nethercote6c999f22004-01-31 22:55:15 +00001605 if (debug_help) {
1606 VG_(printf)(usage2);
fitzhardinge98abfc72003-12-16 02:05:15 +00001607
nethercote6c999f22004-01-31 22:55:15 +00001608 if (VG_(details).name) {
1609 VG_(printf)(" debugging options for %s:\n", VG_(details).name);
1610
1611 if (VG_(needs).command_line_options)
1612 SK_(print_debug_usage)();
1613 else
1614 VG_(printf)(" (none)\n");
1615 }
fitzhardinge98abfc72003-12-16 02:05:15 +00001616 }
nethercote421281e2003-11-20 16:20:55 +00001617 VG_(printf)(usage3, VG_BUGS_TO);
nethercotef4928da2004-06-15 10:54:40 +00001618 VG_(exit)(0);
njn7cf0bd32002-06-08 13:36:03 +00001619}
sewardjde4a1d02002-03-22 01:27:54 +00001620
nethercote71980f02004-01-24 18:18:54 +00001621static void pre_process_cmd_line_options
nethercote6c999f22004-01-31 22:55:15 +00001622 ( Int* need_help, const char** tool, const char** exec )
sewardj1c1b1162003-02-23 01:25:51 +00001623{
nethercote71980f02004-01-24 18:18:54 +00001624 UInt i;
sewardjde4a1d02002-03-22 01:27:54 +00001625
nethercote71980f02004-01-24 18:18:54 +00001626 /* parse the options we have (only the options we care about now) */
1627 for (i = 1; i < VG_(vg_argc); i++) {
1628
1629 if (strcmp(VG_(vg_argv)[i], "--version") == 0) {
1630 printf("valgrind-" VERSION "\n");
nethercotef4928da2004-06-15 10:54:40 +00001631 exit(0);
nethercote71980f02004-01-24 18:18:54 +00001632
nethercotea76368b2004-06-16 11:56:29 +00001633 } else if (VG_CLO_STREQ(VG_(vg_argv)[i], "--help") ||
1634 VG_CLO_STREQ(VG_(vg_argv)[i], "-h")) {
nethercote6c999f22004-01-31 22:55:15 +00001635 *need_help = 1;
1636
nethercotef4928da2004-06-15 10:54:40 +00001637 } else if (VG_CLO_STREQ(VG_(vg_argv)[i], "--help-debug")) {
nethercote6c999f22004-01-31 22:55:15 +00001638 *need_help = 2;
nethercote71980f02004-01-24 18:18:54 +00001639
nethercotef4928da2004-06-15 10:54:40 +00001640 } else if (VG_CLO_STREQN(7, VG_(vg_argv)[i], "--tool=") ||
1641 VG_CLO_STREQN(7, VG_(vg_argv)[i], "--skin=")) {
nethercote71980f02004-01-24 18:18:54 +00001642 *tool = &VG_(vg_argv)[i][7];
1643
nethercotef4928da2004-06-15 10:54:40 +00001644 } else if (VG_CLO_STREQN(7, VG_(vg_argv)[i], "--exec=")) {
nethercote71980f02004-01-24 18:18:54 +00001645 *exec = &VG_(vg_argv)[i][7];
1646 }
1647 }
1648
nethercotef4928da2004-06-15 10:54:40 +00001649 /* If no tool specified, can act appropriately without loading tool */
nethercote71980f02004-01-24 18:18:54 +00001650 if (*tool == NULL) {
nethercotef4928da2004-06-15 10:54:40 +00001651 if (0 == *need_help) {
1652 // neither --tool nor --help/--help-debug specified
1653 missing_tool_option();
1654 } else {
1655 // Give help message, without any tool-specific help
1656 usage(/*help-debug?*/2 == *need_help);
1657 }
nethercote71980f02004-01-24 18:18:54 +00001658 }
1659}
1660
nethercote5ee67ca2004-06-22 14:00:09 +00001661static void process_cmd_line_options( UInt* client_auxv, const char* toolname )
nethercote71980f02004-01-24 18:18:54 +00001662{
nethercotef8548672004-06-21 12:42:35 +00001663 Int i, eventually_log_fd;
nethercote71980f02004-01-24 18:18:54 +00001664 Int *auxp;
1665 Int toolname_len = VG_(strlen)(toolname);
sewardjde4a1d02002-03-22 01:27:54 +00001666
nethercotee1730692003-11-20 10:38:07 +00001667 /* log to stderr by default, but usage message goes to stdout */
nethercotef8548672004-06-21 12:42:35 +00001668 eventually_log_fd = 2;
sewardjde4a1d02002-03-22 01:27:54 +00001669
sewardj19d81412002-06-03 01:10:40 +00001670 /* Check for sane path in ./configure --prefix=... */
fitzhardinge98abfc72003-12-16 02:05:15 +00001671 if (VG_LIBDIR[0] != '/')
sewardj19d81412002-06-03 01:10:40 +00001672 config_error("Please use absolute paths in "
1673 "./configure --prefix=... or --libdir=...");
sewardj38170912002-05-10 21:07:22 +00001674
nethercote71980f02004-01-24 18:18:54 +00001675 for (auxp = client_auxv; auxp[0] != VKI_AT_NULL; auxp += 2) {
fitzhardinge98abfc72003-12-16 02:05:15 +00001676 switch(auxp[0]) {
1677 case VKI_AT_SYSINFO:
1678 VG_(sysinfo_page_exists) = True;
fitzhardinge92360792003-12-24 10:11:11 +00001679 auxp[1] = (Int)(VG_(client_trampoline_code) + VG_(tramp_syscall_offset));
fitzhardinge98abfc72003-12-16 02:05:15 +00001680 VG_(sysinfo_page_addr) = auxp[1];
1681 break;
sewardjde4a1d02002-03-22 01:27:54 +00001682 }
fitzhardinge98abfc72003-12-16 02:05:15 +00001683 }
sewardjde4a1d02002-03-22 01:27:54 +00001684
nethercote71980f02004-01-24 18:18:54 +00001685 for (i = 1; i < VG_(vg_argc); i++) {
1686
1687 Char* arg = VG_(vg_argv)[i];
thughes3bfd5a02004-07-18 08:05:44 +00001688 Char* colon = arg;
nethercote71980f02004-01-24 18:18:54 +00001689
thughes3bfd5a02004-07-18 08:05:44 +00001690 /* Look for a colon in the switch name */
1691 while (*colon && *colon != ':' && *colon != '=')
1692 colon++;
nethercote71980f02004-01-24 18:18:54 +00001693
1694 /* Look for matching "--toolname:foo" */
thughes3bfd5a02004-07-18 08:05:44 +00001695 if (*colon == ':') {
nethercote71980f02004-01-24 18:18:54 +00001696 if (VG_CLO_STREQN(2, arg, "--") &&
1697 VG_CLO_STREQN(toolname_len, arg+2, toolname) &&
1698 VG_CLO_STREQN(1, arg+2+toolname_len, ":"))
1699 {
1700 // prefix matches, convert "--toolname:foo" to "--foo"
1701 if (0)
1702 VG_(printf)("tool-specific arg: %s\n", arg);
1703 arg += toolname_len + 1;
1704 arg[0] = '-';
1705 arg[1] = '-';
1706
1707 } else {
1708 // prefix doesn't match, skip to next arg
1709 continue;
1710 }
1711 }
1712
fitzhardinge98abfc72003-12-16 02:05:15 +00001713 /* Ignore these options - they've already been handled */
nethercote71980f02004-01-24 18:18:54 +00001714 if (VG_CLO_STREQN(7, arg, "--tool=") ||
1715 VG_CLO_STREQN(7, arg, "--skin="))
fitzhardinge98abfc72003-12-16 02:05:15 +00001716 continue;
nethercote71980f02004-01-24 18:18:54 +00001717 if (VG_CLO_STREQN(7, arg, "--exec="))
fitzhardinge98abfc72003-12-16 02:05:15 +00001718 continue;
1719
nethercote71980f02004-01-24 18:18:54 +00001720 if ( VG_CLO_STREQ(arg, "--"))
fitzhardinge98abfc72003-12-16 02:05:15 +00001721 continue;
nethercote27fec902004-06-16 21:26:32 +00001722
nethercote71980f02004-01-24 18:18:54 +00001723 else if (VG_CLO_STREQ(arg, "-v") ||
1724 VG_CLO_STREQ(arg, "--verbose"))
sewardjde4a1d02002-03-22 01:27:54 +00001725 VG_(clo_verbosity)++;
nethercote27fec902004-06-16 21:26:32 +00001726
nethercote71980f02004-01-24 18:18:54 +00001727 else if (VG_CLO_STREQ(arg, "-q") ||
1728 VG_CLO_STREQ(arg, "--quiet"))
sewardjde4a1d02002-03-22 01:27:54 +00001729 VG_(clo_verbosity)--;
1730
nethercote27fec902004-06-16 21:26:32 +00001731 else VG_BOOL_CLO("--branchpred", VG_(clo_branchpred))
1732 else VG_BOOL_CLO("--chain-bb", VG_(clo_chain_bb))
1733 else VG_BOOL_CLO("--db-attach", VG_(clo_db_attach))
1734 else VG_BOOL_CLO("--demangle", VG_(clo_demangle))
1735 else VG_BOOL_CLO("--error-limit", VG_(clo_error_limit))
1736 else VG_BOOL_CLO("--gen-suppressions", VG_(clo_gen_suppressions))
1737 else VG_BOOL_CLO("--lowlat-signals", VG_(clo_lowlat_signals))
1738 else VG_BOOL_CLO("--lowlat-syscalls", VG_(clo_lowlat_syscalls))
1739 else VG_BOOL_CLO("--optimise", VG_(clo_optimise))
1740 else VG_BOOL_CLO("--pointercheck", VG_(clo_pointercheck))
1741 else VG_BOOL_CLO("--profile", VG_(clo_profile))
1742 else VG_BOOL_CLO("--run-libc-freeres", VG_(clo_run_libc_freeres))
1743 else VG_BOOL_CLO("--show-below-main", VG_(clo_show_below_main))
1744 else VG_BOOL_CLO("--single-step", VG_(clo_single_step))
1745 else VG_BOOL_CLO("--track-fds", VG_(clo_track_fds))
1746 else VG_BOOL_CLO("--trace-children", VG_(clo_trace_children))
1747 else VG_BOOL_CLO("--trace-sched", VG_(clo_trace_sched))
1748 else VG_BOOL_CLO("--trace-signals", VG_(clo_trace_signals))
1749 else VG_BOOL_CLO("--trace-symtab", VG_(clo_trace_symtab))
1750 else VG_BOOL_CLO("--trace-syscalls", VG_(clo_trace_syscalls))
1751 else VG_BOOL_CLO("--wait-for-gdb", VG_(clo_wait_for_gdb))
sewardj72f98ff2002-06-13 17:23:38 +00001752
nethercote27fec902004-06-16 21:26:32 +00001753 else VG_STR_CLO ("--db-command", VG_(clo_db_command))
1754 else VG_STR_CLO ("--weird-hacks", VG_(clo_weird_hacks))
sewardjde4a1d02002-03-22 01:27:54 +00001755
nethercote27fec902004-06-16 21:26:32 +00001756 else VG_NUM_CLO ("--dump-error", VG_(clo_dump_error))
1757 else VG_NUM_CLO ("--input-fd", VG_(clo_input_fd))
1758 else VG_NUM_CLO ("--sanity-level", VG_(clo_sanity_level))
1759 else VG_NUM_CLO ("--signal­polltime", VG_(clo_signal_polltime))
1760 else VG_BNUM_CLO("--num-callers", VG_(clo_backtrace_size), 1,
1761 VG_DEEPEST_BACKTRACE)
sewardjde4a1d02002-03-22 01:27:54 +00001762
nethercotef8548672004-06-21 12:42:35 +00001763 // for backwards compatibility, replaced by --log-fd
nethercote71980f02004-01-24 18:18:54 +00001764 else if (VG_CLO_STREQN(13, arg, "--logfile-fd=")) {
nethercotef8548672004-06-21 12:42:35 +00001765 VG_(clo_log_to) = VgLogTo_Fd;
1766 VG_(clo_log_name) = NULL;
1767 eventually_log_fd = (Int)VG_(atoll)(&arg[13]);
1768 }
1769 else if (VG_CLO_STREQN(9, arg, "--log-fd=")) {
1770 VG_(clo_log_to) = VgLogTo_Fd;
1771 VG_(clo_log_name) = NULL;
1772 eventually_log_fd = (Int)VG_(atoll)(&arg[9]);
sewardj4cf05692002-10-27 20:28:29 +00001773 }
1774
nethercotef8548672004-06-21 12:42:35 +00001775 // for backwards compatibility, replaced by --log-file
nethercote71980f02004-01-24 18:18:54 +00001776 else if (VG_CLO_STREQN(10, arg, "--logfile=")) {
nethercotef8548672004-06-21 12:42:35 +00001777 VG_(clo_log_to) = VgLogTo_File;
1778 VG_(clo_log_name) = &arg[10];
1779 }
1780 else if (VG_CLO_STREQN(11, arg, "--log-file=")) {
1781 VG_(clo_log_to) = VgLogTo_File;
1782 VG_(clo_log_name) = &arg[11];
sewardj4cf05692002-10-27 20:28:29 +00001783 }
sewardjde4a1d02002-03-22 01:27:54 +00001784
nethercotef8548672004-06-21 12:42:35 +00001785 // for backwards compatibility, replaced by --log-socket
nethercote71980f02004-01-24 18:18:54 +00001786 else if (VG_CLO_STREQN(12, arg, "--logsocket=")) {
nethercotef8548672004-06-21 12:42:35 +00001787 VG_(clo_log_to) = VgLogTo_Socket;
1788 VG_(clo_log_name) = &arg[12];
1789 }
1790 else if (VG_CLO_STREQN(13, arg, "--log-socket=")) {
1791 VG_(clo_log_to) = VgLogTo_Socket;
1792 VG_(clo_log_name) = &arg[13];
sewardj73cf3bc2002-11-03 03:20:15 +00001793 }
1794
nethercote71980f02004-01-24 18:18:54 +00001795 else if (VG_CLO_STREQN(15, arg, "--suppressions=")) {
sewardjde4a1d02002-03-22 01:27:54 +00001796 if (VG_(clo_n_suppressions) >= VG_CLO_MAX_SFILES) {
njn25e49d8e72002-09-23 09:36:25 +00001797 VG_(message)(Vg_UserMsg, "Too many suppression files specified.");
sewardjde4a1d02002-03-22 01:27:54 +00001798 VG_(message)(Vg_UserMsg,
1799 "Increase VG_CLO_MAX_SFILES and recompile.");
nethercote71980f02004-01-24 18:18:54 +00001800 VG_(bad_option)(arg);
sewardjde4a1d02002-03-22 01:27:54 +00001801 }
nethercote71980f02004-01-24 18:18:54 +00001802 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = &arg[15];
sewardjde4a1d02002-03-22 01:27:54 +00001803 VG_(clo_n_suppressions)++;
1804 }
sewardjde4a1d02002-03-22 01:27:54 +00001805
njn25e49d8e72002-09-23 09:36:25 +00001806 /* "vwxyz" --> 000zyxwv (binary) */
nethercote71980f02004-01-24 18:18:54 +00001807 else if (VG_CLO_STREQN(16, arg, "--trace-codegen=")) {
njn25e49d8e72002-09-23 09:36:25 +00001808 Int j;
nethercote71980f02004-01-24 18:18:54 +00001809 char* opt = & arg[16];
njn25e49d8e72002-09-23 09:36:25 +00001810
1811 if (5 != VG_(strlen)(opt)) {
1812 VG_(message)(Vg_UserMsg,
1813 "--trace-codegen argument must have 5 digits");
nethercote71980f02004-01-24 18:18:54 +00001814 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001815 }
1816 for (j = 0; j < 5; j++) {
1817 if ('0' == opt[j]) { /* do nothing */ }
1818 else if ('1' == opt[j]) VG_(clo_trace_codegen) |= (1 << j);
1819 else {
1820 VG_(message)(Vg_UserMsg, "--trace-codegen argument can only "
1821 "contain 0s and 1s");
nethercote71980f02004-01-24 18:18:54 +00001822 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001823 }
1824 }
1825 }
sewardjde4a1d02002-03-22 01:27:54 +00001826
nethercote71980f02004-01-24 18:18:54 +00001827 else if (VG_CLO_STREQ(arg, "--trace-pthread=none"))
sewardj45b4b372002-04-16 22:50:32 +00001828 VG_(clo_trace_pthread_level) = 0;
nethercote71980f02004-01-24 18:18:54 +00001829 else if (VG_CLO_STREQ(arg, "--trace-pthread=some"))
sewardj45b4b372002-04-16 22:50:32 +00001830 VG_(clo_trace_pthread_level) = 1;
nethercote71980f02004-01-24 18:18:54 +00001831 else if (VG_CLO_STREQ(arg, "--trace-pthread=all"))
sewardj45b4b372002-04-16 22:50:32 +00001832 VG_(clo_trace_pthread_level) = 2;
sewardj8937c812002-04-12 20:12:20 +00001833
nethercote71980f02004-01-24 18:18:54 +00001834 else if ( ! VG_(needs).command_line_options
1835 || ! SK_(process_cmd_line_option)(arg) ) {
nethercotef4928da2004-06-15 10:54:40 +00001836 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001837 }
sewardjde4a1d02002-03-22 01:27:54 +00001838 }
1839
nethercote27fec902004-06-16 21:26:32 +00001840 // Check various option values
1841
njnf9ebf672003-05-12 21:41:30 +00001842 if (VG_(clo_verbosity) < 0)
sewardjde4a1d02002-03-22 01:27:54 +00001843 VG_(clo_verbosity) = 0;
1844
nethercote04d0fbc2004-01-26 16:48:06 +00001845 if (VG_(clo_db_attach) && VG_(clo_trace_children)) {
sewardjde4a1d02002-03-22 01:27:54 +00001846 VG_(message)(Vg_UserMsg, "");
1847 VG_(message)(Vg_UserMsg,
nethercote04d0fbc2004-01-26 16:48:06 +00001848 "--db-attach=yes conflicts with --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001849 VG_(message)(Vg_UserMsg,
1850 "Please choose one or the other, but not both.");
nethercote04d0fbc2004-01-26 16:48:06 +00001851 VG_(bad_option)("--db-attach=yes and --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001852 }
1853
nethercotef8548672004-06-21 12:42:35 +00001854 /* Set up logging now. After this is done, VG_(clo_log_fd)
sewardj4cf05692002-10-27 20:28:29 +00001855 should be connected to whatever sink has been selected, and we
1856 indiscriminately chuck stuff into it without worrying what the
1857 nature of it is. Oh the wonder of Unix streams. */
1858
nethercotee1730692003-11-20 10:38:07 +00001859 /* So far we should be still attached to stdout, so we can show on
sewardj4cf05692002-10-27 20:28:29 +00001860 the terminal any problems to do with processing command line
1861 opts. */
nethercotef8548672004-06-21 12:42:35 +00001862 vg_assert(VG_(clo_log_fd) == 1 /* stdout */);
sewardj73cf3bc2002-11-03 03:20:15 +00001863 vg_assert(VG_(logging_to_filedes) == True);
sewardj4cf05692002-10-27 20:28:29 +00001864
1865 switch (VG_(clo_log_to)) {
sewardj73cf3bc2002-11-03 03:20:15 +00001866
sewardj4cf05692002-10-27 20:28:29 +00001867 case VgLogTo_Fd:
nethercotef8548672004-06-21 12:42:35 +00001868 vg_assert(VG_(clo_log_name) == NULL);
1869 VG_(clo_log_fd) = eventually_log_fd;
sewardj4cf05692002-10-27 20:28:29 +00001870 break;
sewardj73cf3bc2002-11-03 03:20:15 +00001871
sewardj4cf05692002-10-27 20:28:29 +00001872 case VgLogTo_File: {
1873 Char logfilename[1000];
jsgff3c3f1a2003-10-14 22:13:28 +00001874 Int seq = 0;
1875 Int pid = VG_(getpid)();
1876
nethercotef8548672004-06-21 12:42:35 +00001877 vg_assert(VG_(clo_log_name) != NULL);
1878 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
jsgff3c3f1a2003-10-14 22:13:28 +00001879
nethercote71980f02004-01-24 18:18:54 +00001880 for (;;) {
jsgff3c3f1a2003-10-14 22:13:28 +00001881 if (seq == 0)
1882 VG_(sprintf)(logfilename, "%s.pid%d",
nethercotef8548672004-06-21 12:42:35 +00001883 VG_(clo_log_name), pid );
jsgff3c3f1a2003-10-14 22:13:28 +00001884 else
1885 VG_(sprintf)(logfilename, "%s.pid%d.%d",
nethercotef8548672004-06-21 12:42:35 +00001886 VG_(clo_log_name), pid, seq );
jsgff3c3f1a2003-10-14 22:13:28 +00001887 seq++;
1888
nethercotef8548672004-06-21 12:42:35 +00001889 eventually_log_fd
jsgff3c3f1a2003-10-14 22:13:28 +00001890 = VG_(open)(logfilename,
1891 VKI_O_CREAT|VKI_O_WRONLY|VKI_O_EXCL|VKI_O_TRUNC,
1892 VKI_S_IRUSR|VKI_S_IWUSR);
nethercotef8548672004-06-21 12:42:35 +00001893 if (eventually_log_fd >= 0) {
1894 VG_(clo_log_fd) = VG_(safe_fd)(eventually_log_fd);
jsgff3c3f1a2003-10-14 22:13:28 +00001895 break;
1896 } else {
nethercotef8548672004-06-21 12:42:35 +00001897 if (eventually_log_fd != -VKI_EEXIST) {
jsgff3c3f1a2003-10-14 22:13:28 +00001898 VG_(message)(Vg_UserMsg,
1899 "Can't create/open log file `%s.pid%d'; giving up!",
nethercotef8548672004-06-21 12:42:35 +00001900 VG_(clo_log_name), pid);
jsgff3c3f1a2003-10-14 22:13:28 +00001901 VG_(bad_option)(
nethercotef8548672004-06-21 12:42:35 +00001902 "--log-file=<file> didn't work out for some reason.");
jsgff3c3f1a2003-10-14 22:13:28 +00001903 break;
1904 }
1905 }
1906 }
sewardj4cf05692002-10-27 20:28:29 +00001907 break;
sewardj73cf3bc2002-11-03 03:20:15 +00001908 }
1909
1910 case VgLogTo_Socket: {
nethercotef8548672004-06-21 12:42:35 +00001911 vg_assert(VG_(clo_log_name) != NULL);
1912 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
1913 eventually_log_fd = VG_(connect_via_socket)( VG_(clo_log_name) );
1914 if (eventually_log_fd == -1) {
sewardj73cf3bc2002-11-03 03:20:15 +00001915 VG_(message)(Vg_UserMsg,
nethercotef8548672004-06-21 12:42:35 +00001916 "Invalid --log-socket=ipaddr or --log-socket=ipaddr:port spec");
sewardj73cf3bc2002-11-03 03:20:15 +00001917 VG_(message)(Vg_UserMsg,
nethercotef8548672004-06-21 12:42:35 +00001918 "of `%s'; giving up!", VG_(clo_log_name) );
sewardj73cf3bc2002-11-03 03:20:15 +00001919 VG_(bad_option)(
nethercotef8548672004-06-21 12:42:35 +00001920 "--log-socket=");
sewardj4cf05692002-10-27 20:28:29 +00001921 }
nethercotef8548672004-06-21 12:42:35 +00001922 if (eventually_log_fd == -2) {
sewardj73cf3bc2002-11-03 03:20:15 +00001923 VG_(message)(Vg_UserMsg,
sewardj570f8902002-11-03 11:44:36 +00001924 "valgrind: failed to connect to logging server `%s'.",
nethercotef8548672004-06-21 12:42:35 +00001925 VG_(clo_log_name) );
sewardj570f8902002-11-03 11:44:36 +00001926 VG_(message)(Vg_UserMsg,
1927 "Log messages will sent to stderr instead." );
1928 VG_(message)(Vg_UserMsg,
1929 "" );
1930 /* We don't change anything here. */
1931 } else {
nethercotef8548672004-06-21 12:42:35 +00001932 vg_assert(eventually_log_fd > 0);
1933 VG_(clo_log_fd) = eventually_log_fd;
sewardj570f8902002-11-03 11:44:36 +00001934 VG_(logging_to_filedes) = False;
1935 }
sewardj73cf3bc2002-11-03 03:20:15 +00001936 break;
1937 }
1938
sewardj4cf05692002-10-27 20:28:29 +00001939 }
1940
nethercotef8548672004-06-21 12:42:35 +00001941 /* Move log_fd into the safe range, so it doesn't conflict with any app fds */
thughesad1c9562004-06-26 11:27:52 +00001942 eventually_log_fd = VG_(fcntl)(VG_(clo_log_fd), VKI_F_DUPFD, VG_(fd_hard_limit));
nethercotef8548672004-06-21 12:42:35 +00001943 if (eventually_log_fd < 0)
jsgf855d93d2003-10-13 22:26:55 +00001944 VG_(message)(Vg_UserMsg, "valgrind: failed to move logfile fd into safe range");
1945 else {
nethercotef8548672004-06-21 12:42:35 +00001946 VG_(clo_log_fd) = eventually_log_fd;
1947 VG_(fcntl)(VG_(clo_log_fd), VKI_F_SETFD, VKI_FD_CLOEXEC);
jsgf855d93d2003-10-13 22:26:55 +00001948 }
1949
sewardj4cf05692002-10-27 20:28:29 +00001950 /* Ok, the logging sink is running now. Print a suitable preamble.
1951 If logging to file or a socket, write details of parent PID and
1952 command line args, to help people trying to interpret the
1953 results of a run which encompasses multiple processes. */
sewardjde4a1d02002-03-22 01:27:54 +00001954
sewardj83adf412002-05-01 01:25:45 +00001955 if (VG_(clo_verbosity > 0)) {
njnd04b7c62002-10-03 14:05:52 +00001956 /* Skin details */
1957 VG_(message)(Vg_UserMsg, "%s%s%s, %s for x86-linux.",
1958 VG_(details).name,
1959 NULL == VG_(details).version ? "" : "-",
1960 NULL == VG_(details).version
1961 ? (Char*)"" : VG_(details).version,
1962 VG_(details).description);
1963 VG_(message)(Vg_UserMsg, "%s", VG_(details).copyright_author);
sewardj3b2736a2002-03-24 12:18:35 +00001964
njnd04b7c62002-10-03 14:05:52 +00001965 /* Core details */
1966 VG_(message)(Vg_UserMsg,
njn3e884182003-04-15 13:03:23 +00001967 "Using valgrind-%s, a program supervision framework for x86-linux.",
sewardj4aa62ba2002-10-05 15:49:27 +00001968 VERSION);
sewardjde4a1d02002-03-22 01:27:54 +00001969 VG_(message)(Vg_UserMsg,
nethercote08fa9a72004-07-16 17:44:00 +00001970 "Copyright (C) 2000-2004, and GNU GPL'd, by Julian Seward et al.");
njnd04b7c62002-10-03 14:05:52 +00001971 }
1972
nethercotec1e395d2003-11-10 13:26:49 +00001973 if (VG_(clo_verbosity) > 0 && VG_(clo_log_to) != VgLogTo_Fd) {
sewardj4cf05692002-10-27 20:28:29 +00001974 VG_(message)(Vg_UserMsg, "");
1975 VG_(message)(Vg_UserMsg,
1976 "My PID = %d, parent PID = %d. Prog and args are:",
1977 VG_(getpid)(), VG_(getppid)() );
1978 for (i = 0; i < VG_(client_argc); i++)
1979 VG_(message)(Vg_UserMsg, " %s", VG_(client_argv)[i]);
1980 }
1981
sewardjde4a1d02002-03-22 01:27:54 +00001982 if (VG_(clo_verbosity) > 1) {
nethercotea70f7352004-04-18 12:08:46 +00001983 Int fd;
sewardj4cf05692002-10-27 20:28:29 +00001984 if (VG_(clo_log_to) != VgLogTo_Fd)
1985 VG_(message)(Vg_UserMsg, "");
fitzhardinge98abfc72003-12-16 02:05:15 +00001986 VG_(message)(Vg_UserMsg, "Valgrind library directory: %s", VG_(libdir));
njn86dc2bc2003-09-09 07:26:21 +00001987 VG_(message)(Vg_UserMsg, "Command line");
1988 for (i = 0; i < VG_(client_argc); i++)
1989 VG_(message)(Vg_UserMsg, " %s", VG_(client_argv)[i]);
1990
sewardjde4a1d02002-03-22 01:27:54 +00001991 VG_(message)(Vg_UserMsg, "Startup, with flags:");
nethercote71980f02004-01-24 18:18:54 +00001992 for (i = 1; i < VG_(vg_argc); i++) {
1993 VG_(message)(Vg_UserMsg, " %s", VG_(vg_argv)[i]);
sewardjde4a1d02002-03-22 01:27:54 +00001994 }
nethercotea70f7352004-04-18 12:08:46 +00001995
1996 VG_(message)(Vg_UserMsg, "Contents of /proc/version:");
1997 fd = VG_(open) ( "/proc/version", VKI_O_RDONLY, 0 );
1998 if (fd < 0) {
1999 VG_(message)(Vg_UserMsg, " can't open /proc/version");
2000 } else {
2001 #define BUF_LEN 256
2002 Char version_buf[BUF_LEN];
2003 Int n = VG_(read) ( fd, version_buf, BUF_LEN );
2004 vg_assert(n <= 256);
2005 if (n > 0) {
2006 version_buf[n-1] = '\0';
2007 VG_(message)(Vg_UserMsg, " %s", version_buf);
2008 } else {
2009 VG_(message)(Vg_UserMsg, " (empty?)");
2010 }
2011 VG_(close)(fd);
2012 #undef BUF_LEN
2013 }
sewardjde4a1d02002-03-22 01:27:54 +00002014 }
2015
fitzhardinge98abfc72003-12-16 02:05:15 +00002016 if (VG_(clo_n_suppressions) < VG_CLO_MAX_SFILES-1 &&
njn25e49d8e72002-09-23 09:36:25 +00002017 (VG_(needs).core_errors || VG_(needs).skin_errors)) {
fitzhardinge98abfc72003-12-16 02:05:15 +00002018 /* If there are no suppression files specified and the skin
2019 needs one, load the default */
2020 static const Char default_supp[] = "default.supp";
2021 Int len = VG_(strlen)(VG_(libdir)) + 1 + sizeof(default_supp);
2022 Char *buf = VG_(arena_malloc)(VG_AR_CORE, len);
2023 VG_(sprintf)(buf, "%s/%s", VG_(libdir), default_supp);
2024 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = buf;
2025 VG_(clo_n_suppressions)++;
sewardjde4a1d02002-03-22 01:27:54 +00002026 }
sewardj4cf05692002-10-27 20:28:29 +00002027
njn6a230532003-07-21 10:38:23 +00002028 if (VG_(clo_gen_suppressions) &&
2029 !VG_(needs).core_errors && !VG_(needs).skin_errors) {
nethercotef4928da2004-06-15 10:54:40 +00002030 VG_(message)(Vg_UserMsg,
2031 "Can't use --gen-suppressions=yes with this tool,");
2032 VG_(message)(Vg_UserMsg,
2033 "as it doesn't generate errors.");
2034 VG_(bad_option)("--gen-suppressions=yes");
njn6a230532003-07-21 10:38:23 +00002035 }
sewardjde4a1d02002-03-22 01:27:54 +00002036}
2037
sewardjde4a1d02002-03-22 01:27:54 +00002038
nethercote71980f02004-01-24 18:18:54 +00002039/*====================================================================*/
2040/*=== File descriptor setup ===*/
2041/*====================================================================*/
2042
2043static void setup_file_descriptors(void)
2044{
2045 struct vki_rlimit rl;
2046
2047 /* Get the current file descriptor limits. */
2048 if (VG_(getrlimit)(VKI_RLIMIT_NOFILE, &rl) < 0) {
2049 rl.rlim_cur = 1024;
2050 rl.rlim_max = 1024;
2051 }
2052
2053 /* Work out where to move the soft limit to. */
2054 if (rl.rlim_cur + VG_N_RESERVED_FDS <= rl.rlim_max) {
2055 rl.rlim_cur = rl.rlim_cur + VG_N_RESERVED_FDS;
2056 } else {
2057 rl.rlim_cur = rl.rlim_max;
2058 }
2059
2060 /* Reserve some file descriptors for our use. */
thughesad1c9562004-06-26 11:27:52 +00002061 VG_(fd_soft_limit) = rl.rlim_cur - VG_N_RESERVED_FDS;
2062 VG_(fd_hard_limit) = rl.rlim_cur - VG_N_RESERVED_FDS;
nethercote71980f02004-01-24 18:18:54 +00002063
2064 /* Update the soft limit. */
2065 VG_(setrlimit)(VKI_RLIMIT_NOFILE, &rl);
2066
2067 if (VG_(vgexecfd) != -1)
2068 VG_(vgexecfd) = VG_(safe_fd)( VG_(vgexecfd) );
2069 if (VG_(clexecfd) != -1)
2070 VG_(clexecfd) = VG_(safe_fd)( VG_(clexecfd) );
2071}
2072
2073
2074/*====================================================================*/
nethercote1d447092004-02-01 17:29:59 +00002075/*=== baseBlock: definition + setup ===*/
nethercote71980f02004-01-24 18:18:54 +00002076/*====================================================================*/
2077
2078/* The variables storing offsets. */
2079
2080#define INVALID_OFFSET (-1)
2081
2082Int VGOFF_(m_eax) = INVALID_OFFSET;
2083Int VGOFF_(m_ecx) = INVALID_OFFSET;
2084Int VGOFF_(m_edx) = INVALID_OFFSET;
2085Int VGOFF_(m_ebx) = INVALID_OFFSET;
2086Int VGOFF_(m_esp) = INVALID_OFFSET;
2087Int VGOFF_(m_ebp) = INVALID_OFFSET;
2088Int VGOFF_(m_esi) = INVALID_OFFSET;
2089Int VGOFF_(m_edi) = INVALID_OFFSET;
2090Int VGOFF_(m_eflags) = INVALID_OFFSET;
2091Int VGOFF_(m_dflag) = INVALID_OFFSET;
2092Int VGOFF_(m_ssestate) = INVALID_OFFSET;
2093Int VGOFF_(ldt) = INVALID_OFFSET;
2094Int VGOFF_(tls) = INVALID_OFFSET;
2095Int VGOFF_(m_cs) = INVALID_OFFSET;
2096Int VGOFF_(m_ss) = INVALID_OFFSET;
2097Int VGOFF_(m_ds) = INVALID_OFFSET;
2098Int VGOFF_(m_es) = INVALID_OFFSET;
2099Int VGOFF_(m_fs) = INVALID_OFFSET;
2100Int VGOFF_(m_gs) = INVALID_OFFSET;
2101Int VGOFF_(m_eip) = INVALID_OFFSET;
2102Int VGOFF_(spillslots) = INVALID_OFFSET;
2103Int VGOFF_(sh_eax) = INVALID_OFFSET;
2104Int VGOFF_(sh_ecx) = INVALID_OFFSET;
2105Int VGOFF_(sh_edx) = INVALID_OFFSET;
2106Int VGOFF_(sh_ebx) = INVALID_OFFSET;
2107Int VGOFF_(sh_esp) = INVALID_OFFSET;
2108Int VGOFF_(sh_ebp) = INVALID_OFFSET;
2109Int VGOFF_(sh_esi) = INVALID_OFFSET;
2110Int VGOFF_(sh_edi) = INVALID_OFFSET;
2111Int VGOFF_(sh_eflags) = INVALID_OFFSET;
2112
2113Int VGOFF_(helper_idiv_64_32) = INVALID_OFFSET;
2114Int VGOFF_(helper_div_64_32) = INVALID_OFFSET;
2115Int VGOFF_(helper_idiv_32_16) = INVALID_OFFSET;
2116Int VGOFF_(helper_div_32_16) = INVALID_OFFSET;
2117Int VGOFF_(helper_idiv_16_8) = INVALID_OFFSET;
2118Int VGOFF_(helper_div_16_8) = INVALID_OFFSET;
2119Int VGOFF_(helper_imul_32_64) = INVALID_OFFSET;
2120Int VGOFF_(helper_mul_32_64) = INVALID_OFFSET;
2121Int VGOFF_(helper_imul_16_32) = INVALID_OFFSET;
2122Int VGOFF_(helper_mul_16_32) = INVALID_OFFSET;
2123Int VGOFF_(helper_imul_8_16) = INVALID_OFFSET;
2124Int VGOFF_(helper_mul_8_16) = INVALID_OFFSET;
2125Int VGOFF_(helper_CLD) = INVALID_OFFSET;
2126Int VGOFF_(helper_STD) = INVALID_OFFSET;
2127Int VGOFF_(helper_get_dirflag) = INVALID_OFFSET;
2128Int VGOFF_(helper_CLC) = INVALID_OFFSET;
2129Int VGOFF_(helper_STC) = INVALID_OFFSET;
nethercote1018bdd2004-02-11 23:33:29 +00002130Int VGOFF_(helper_CMC) = INVALID_OFFSET;
nethercote71980f02004-01-24 18:18:54 +00002131Int VGOFF_(helper_shldl) = INVALID_OFFSET;
2132Int VGOFF_(helper_shldw) = INVALID_OFFSET;
2133Int VGOFF_(helper_shrdl) = INVALID_OFFSET;
2134Int VGOFF_(helper_shrdw) = INVALID_OFFSET;
2135Int VGOFF_(helper_IN) = INVALID_OFFSET;
2136Int VGOFF_(helper_OUT) = INVALID_OFFSET;
2137Int VGOFF_(helper_RDTSC) = INVALID_OFFSET;
2138Int VGOFF_(helper_CPUID) = INVALID_OFFSET;
2139Int VGOFF_(helper_BSWAP) = INVALID_OFFSET;
nethercote1018bdd2004-02-11 23:33:29 +00002140Int VGOFF_(helper_bsfw) = INVALID_OFFSET;
2141Int VGOFF_(helper_bsfl) = INVALID_OFFSET;
2142Int VGOFF_(helper_bsrw) = INVALID_OFFSET;
2143Int VGOFF_(helper_bsrl) = INVALID_OFFSET;
nethercote71980f02004-01-24 18:18:54 +00002144Int VGOFF_(helper_fstsw_AX) = INVALID_OFFSET;
2145Int VGOFF_(helper_SAHF) = INVALID_OFFSET;
2146Int VGOFF_(helper_LAHF) = INVALID_OFFSET;
2147Int VGOFF_(helper_DAS) = INVALID_OFFSET;
2148Int VGOFF_(helper_DAA) = INVALID_OFFSET;
nethercote1018bdd2004-02-11 23:33:29 +00002149Int VGOFF_(helper_AAS) = INVALID_OFFSET;
2150Int VGOFF_(helper_AAA) = INVALID_OFFSET;
2151Int VGOFF_(helper_AAD) = INVALID_OFFSET;
2152Int VGOFF_(helper_AAM) = INVALID_OFFSET;
nethercote71980f02004-01-24 18:18:54 +00002153Int VGOFF_(helper_cmpxchg8b) = INVALID_OFFSET;
2154Int VGOFF_(helper_undefined_instruction) = INVALID_OFFSET;
2155
2156/* MAX_NONCOMPACT_HELPERS can be increased easily. If MAX_COMPACT_HELPERS is
2157 * increased too much, they won't really be compact any more... */
2158#define MAX_COMPACT_HELPERS 8
2159#define MAX_NONCOMPACT_HELPERS 50
2160
2161UInt VG_(n_compact_helpers) = 0;
2162UInt VG_(n_noncompact_helpers) = 0;
2163
2164Addr VG_(compact_helper_addrs) [MAX_COMPACT_HELPERS];
2165Int VG_(compact_helper_offsets)[MAX_COMPACT_HELPERS];
2166Addr VG_(noncompact_helper_addrs) [MAX_NONCOMPACT_HELPERS];
2167Int VG_(noncompact_helper_offsets)[MAX_NONCOMPACT_HELPERS];
2168
2169/* This is the actual defn of baseblock. */
2170UInt VG_(baseBlock)[VG_BASEBLOCK_WORDS];
2171
nethercote71980f02004-01-24 18:18:54 +00002172/* Words. */
2173static Int baB_off = 0;
2174
2175
sewardjfa492d42002-12-08 18:20:01 +00002176UInt VG_(insertDflag)(UInt eflags, Int d)
2177{
2178 vg_assert(d == 1 || d == -1);
2179 eflags &= ~EFlagD;
2180
2181 if (d < 0)
2182 eflags |= EFlagD;
2183
2184 return eflags;
2185}
2186
2187Int VG_(extractDflag)(UInt eflags)
2188{
2189 Int ret;
2190
2191 if (eflags & EFlagD)
2192 ret = -1;
2193 else
2194 ret = 1;
2195
2196 return ret;
2197}
2198
nethercote71980f02004-01-24 18:18:54 +00002199/* Returns the offset, in words. */
2200static Int alloc_BaB ( Int words )
sewardjde4a1d02002-03-22 01:27:54 +00002201{
nethercote71980f02004-01-24 18:18:54 +00002202 Int off = baB_off;
2203 baB_off += words;
2204 if (baB_off >= VG_BASEBLOCK_WORDS)
2205 VG_(core_panic)( "alloc_BaB: baseBlock is too small");
sewardjde4a1d02002-03-22 01:27:54 +00002206
nethercote71980f02004-01-24 18:18:54 +00002207 return off;
sewardjde4a1d02002-03-22 01:27:54 +00002208}
2209
nethercote71980f02004-01-24 18:18:54 +00002210/* Align offset, in *bytes* */
2211static void align_BaB ( UInt align )
njn25e49d8e72002-09-23 09:36:25 +00002212{
nethercote71980f02004-01-24 18:18:54 +00002213 vg_assert(2 == align || 4 == align || 8 == align || 16 == align);
2214 baB_off += (align-1);
2215 baB_off &= ~(align-1);
njn25e49d8e72002-09-23 09:36:25 +00002216}
2217
nethercote71980f02004-01-24 18:18:54 +00002218/* Allocate 1 word in baseBlock and set it to the given value. */
2219static Int alloc_BaB_1_set ( Addr a )
njn25e49d8e72002-09-23 09:36:25 +00002220{
nethercote71980f02004-01-24 18:18:54 +00002221 Int off = alloc_BaB(1);
2222 VG_(baseBlock)[off] = (UInt)a;
2223 return off;
njn25e49d8e72002-09-23 09:36:25 +00002224}
2225
nethercote71980f02004-01-24 18:18:54 +00002226/* Registers a function in compact_helper_addrs; compact_helper_offsets is
2227 filled in later. */
2228void VG_(register_compact_helper)(Addr a)
sewardjde4a1d02002-03-22 01:27:54 +00002229{
nethercote71980f02004-01-24 18:18:54 +00002230 if (MAX_COMPACT_HELPERS <= VG_(n_compact_helpers)) {
2231 VG_(printf)("Can only register %d compact helpers\n",
2232 MAX_COMPACT_HELPERS);
2233 VG_(core_panic)("Too many compact helpers registered");
2234 }
2235 VG_(compact_helper_addrs)[VG_(n_compact_helpers)] = a;
2236 VG_(n_compact_helpers)++;
2237}
2238
2239/* Registers a function in noncompact_helper_addrs; noncompact_helper_offsets
2240 * is filled in later.
2241 */
2242void VG_(register_noncompact_helper)(Addr a)
2243{
2244 if (MAX_NONCOMPACT_HELPERS <= VG_(n_noncompact_helpers)) {
2245 VG_(printf)("Can only register %d non-compact helpers\n",
2246 MAX_NONCOMPACT_HELPERS);
2247 VG_(printf)("Try increasing MAX_NON_COMPACT_HELPERS\n");
2248 VG_(core_panic)("Too many non-compact helpers registered");
2249 }
2250 VG_(noncompact_helper_addrs)[VG_(n_noncompact_helpers)] = a;
2251 VG_(n_noncompact_helpers)++;
2252}
2253
2254/* Allocate offsets in baseBlock for the skin helpers */
2255static
2256void assign_helpers_in_baseBlock(UInt n, Int offsets[], Addr addrs[])
2257{
2258 UInt i;
2259 for (i = 0; i < n; i++)
2260 offsets[i] = alloc_BaB_1_set( addrs[i] );
2261}
2262
2263Bool VG_(need_to_handle_esp_assignment)(void)
2264{
2265 return ( VG_(defined_new_mem_stack_4)() ||
2266 VG_(defined_die_mem_stack_4)() ||
2267 VG_(defined_new_mem_stack_8)() ||
2268 VG_(defined_die_mem_stack_8)() ||
2269 VG_(defined_new_mem_stack_12)() ||
2270 VG_(defined_die_mem_stack_12)() ||
2271 VG_(defined_new_mem_stack_16)() ||
2272 VG_(defined_die_mem_stack_16)() ||
2273 VG_(defined_new_mem_stack_32)() ||
2274 VG_(defined_die_mem_stack_32)() ||
2275 VG_(defined_new_mem_stack)() ||
2276 VG_(defined_die_mem_stack)()
2277 );
2278}
2279
2280/* Here we assign actual offsets. It's important to get the most
2281 popular referents within 128 bytes of the start, so we can take
2282 advantage of short addressing modes relative to %ebp. Popularity
2283 of offsets was measured on 22 Feb 02 running a KDE application, and
2284 the slots rearranged accordingly, with a 1.5% reduction in total
2285 size of translations. */
2286static void init_baseBlock ( Addr client_eip, Addr esp_at_startup )
2287{
2288 /* Those with offsets under 128 are carefully chosen. */
2289
2290 /* WORD offsets in this column */
2291 /* 0 */ VGOFF_(m_eax) = alloc_BaB_1_set(0);
2292 /* 1 */ VGOFF_(m_ecx) = alloc_BaB_1_set(0);
2293 /* 2 */ VGOFF_(m_edx) = alloc_BaB_1_set(0);
2294 /* 3 */ VGOFF_(m_ebx) = alloc_BaB_1_set(0);
2295 /* 4 */ VGOFF_(m_esp) = alloc_BaB_1_set(esp_at_startup);
2296 /* 5 */ VGOFF_(m_ebp) = alloc_BaB_1_set(0);
2297 /* 6 */ VGOFF_(m_esi) = alloc_BaB_1_set(0);
2298 /* 7 */ VGOFF_(m_edi) = alloc_BaB_1_set(0);
2299 /* 8 */ VGOFF_(m_eflags) = alloc_BaB_1_set(0);
2300
2301 if (VG_(needs).shadow_regs) {
2302 /* 9 */ VGOFF_(sh_eax) = alloc_BaB_1_set(0);
2303 /* 10 */ VGOFF_(sh_ecx) = alloc_BaB_1_set(0);
2304 /* 11 */ VGOFF_(sh_edx) = alloc_BaB_1_set(0);
2305 /* 12 */ VGOFF_(sh_ebx) = alloc_BaB_1_set(0);
2306 /* 13 */ VGOFF_(sh_esp) = alloc_BaB_1_set(0);
2307 /* 14 */ VGOFF_(sh_ebp) = alloc_BaB_1_set(0);
2308 /* 15 */ VGOFF_(sh_esi) = alloc_BaB_1_set(0);
2309 /* 16 */ VGOFF_(sh_edi) = alloc_BaB_1_set(0);
2310 /* 17 */ VGOFF_(sh_eflags) = alloc_BaB_1_set(0);
2311 VG_TRACK( post_regs_write_init );
2312 }
2313
2314 /* 9,10,11 or 18,19,20... depends on number whether shadow regs are used
2315 * and on compact helpers registered */
2316
2317 /* Make these most-frequently-called specialised ones compact, if they
2318 are used. */
2319 if (VG_(defined_new_mem_stack_4)())
2320 VG_(register_compact_helper)( (Addr) VG_(tool_interface).track_new_mem_stack_4);
2321
2322 if (VG_(defined_die_mem_stack_4)())
2323 VG_(register_compact_helper)( (Addr) VG_(tool_interface).track_die_mem_stack_4);
2324
2325 /* (9 or 18) + n_compact_helpers */
2326 /* Allocate slots for compact helpers */
2327 assign_helpers_in_baseBlock(VG_(n_compact_helpers),
2328 VG_(compact_helper_offsets),
2329 VG_(compact_helper_addrs));
2330
2331 /* (9/10 or 18/19) + n_compact_helpers */
2332 VGOFF_(m_eip) = alloc_BaB_1_set(client_eip);
2333
2334 /* There are currently 24 spill slots */
2335 /* (11+/20+ .. 32+/43+) + n_compact_helpers. This can overlap the magic
2336 * boundary at >= 32 words, but most spills are to low numbered spill
2337 * slots, so the ones above the boundary don't see much action. */
2338 VGOFF_(spillslots) = alloc_BaB(VG_MAX_SPILLSLOTS);
2339
2340 /* I gave up counting at this point. Since they're above the
2341 short-amode-boundary, there's no point. */
2342
2343 VGOFF_(m_dflag) = alloc_BaB_1_set(1); // 1 == forward D-flag
2344
2345 /* The FPU/SSE state. This _must_ be 16-byte aligned. Initial
2346 state doesn't matter much, as long as it's not totally borked. */
2347 align_BaB(16);
2348 VGOFF_(m_ssestate) = alloc_BaB(VG_SIZE_OF_SSESTATE_W);
2349 vg_assert(
2350 0 == ( ((UInt)(& VG_(baseBlock)[VGOFF_(m_ssestate)])) % 16 )
sewardj22854b92002-11-30 14:00:47 +00002351 );
2352
fitzhardingec2dbbac2004-01-23 23:09:01 +00002353 /* I assume that if we have SSE2 we also have SSE */
2354 VG_(have_ssestate) =
2355 VG_(cpu_has_feature)(VG_X86_FEAT_FXSR) &&
2356 VG_(cpu_has_feature)(VG_X86_FEAT_SSE);
2357
fitzhardinge98abfc72003-12-16 02:05:15 +00002358 /* set up an initial FPU state (doesn't really matter what it is,
2359 so long as it's somewhat valid) */
2360 if (!VG_(have_ssestate))
nethercote71980f02004-01-24 18:18:54 +00002361 asm volatile("fwait; fnsave %0; fwait; frstor %0; fwait"
2362 :
2363 : "m" (VG_(baseBlock)[VGOFF_(m_ssestate)])
2364 : "cc", "memory");
fitzhardinge98abfc72003-12-16 02:05:15 +00002365 else
nethercote71980f02004-01-24 18:18:54 +00002366 asm volatile("fwait; fxsave %0; fwait; andl $0xffbf, %1;"
2367 "fxrstor %0; fwait"
2368 :
2369 : "m" (VG_(baseBlock)[VGOFF_(m_ssestate)]),
2370 "m" (VG_(baseBlock)[VGOFF_(m_ssestate)+(24/4)])
2371 : "cc", "memory");
fitzhardinge98abfc72003-12-16 02:05:15 +00002372
njn0c7a5b52003-04-30 09:00:33 +00002373 if (0) {
2374 if (VG_(have_ssestate))
2375 VG_(printf)("Looks like a SSE-capable CPU\n");
2376 else
2377 VG_(printf)("Looks like a MMX-only CPU\n");
2378 }
sewardjb91ae7f2003-04-29 23:50:00 +00002379
nethercote71980f02004-01-24 18:18:54 +00002380 /* LDT pointer: pretend the root thread has an empty LDT to start with. */
2381 VGOFF_(ldt) = alloc_BaB_1_set((UInt)NULL);
jsgf855d93d2003-10-13 22:26:55 +00002382
nethercote71980f02004-01-24 18:18:54 +00002383 /* TLS pointer: pretend the root thread has no TLS array for now. */
2384 VGOFF_(tls) = alloc_BaB_1_set((UInt)NULL);
fitzhardingef0046f22003-12-18 02:39:22 +00002385
nethercote71980f02004-01-24 18:18:54 +00002386 /* segment registers */
2387 VGOFF_(m_cs) = alloc_BaB_1_set(0);
2388 VGOFF_(m_ss) = alloc_BaB_1_set(0);
2389 VGOFF_(m_ds) = alloc_BaB_1_set(0);
2390 VGOFF_(m_es) = alloc_BaB_1_set(0);
2391 VGOFF_(m_fs) = alloc_BaB_1_set(0);
2392 VGOFF_(m_gs) = alloc_BaB_1_set(0);
fitzhardingef0046f22003-12-18 02:39:22 +00002393
thughes35cec982004-04-21 15:16:43 +00002394 /* initialise %cs, %ds and %ss to point at the operating systems
2395 default code, data and stack segments */
2396 asm volatile("movw %%cs, %0"
2397 :
2398 : "m" (VG_(baseBlock)[VGOFF_(m_cs)]));
2399 asm volatile("movw %%ds, %0"
2400 :
2401 : "m" (VG_(baseBlock)[VGOFF_(m_ds)]));
2402 asm volatile("movw %%ss, %0"
2403 :
2404 : "m" (VG_(baseBlock)[VGOFF_(m_ss)]));
2405
nethercote71980f02004-01-24 18:18:54 +00002406 VG_(register_noncompact_helper)( (Addr) & VG_(do_useseg) );
fitzhardingef0046f22003-12-18 02:39:22 +00002407
nethercote71980f02004-01-24 18:18:54 +00002408#define REG(kind, size) \
2409 if (VG_(defined_##kind##_mem_stack##size)()) \
2410 VG_(register_noncompact_helper)( \
2411 (Addr) VG_(tool_interface).track_##kind##_mem_stack##size );
2412 REG(new, _8);
2413 REG(new, _12);
2414 REG(new, _16);
2415 REG(new, _32);
2416 REG(new, );
2417 REG(die, _8);
2418 REG(die, _12);
2419 REG(die, _16);
2420 REG(die, _32);
2421 REG(die, );
2422#undef REG
fitzhardingef0046f22003-12-18 02:39:22 +00002423
nethercote71980f02004-01-24 18:18:54 +00002424 if (VG_(need_to_handle_esp_assignment)())
2425 VG_(register_noncompact_helper)((Addr) VG_(unknown_esp_update));
fitzhardingeb791a192003-12-18 07:22:44 +00002426
nethercote71980f02004-01-24 18:18:54 +00002427# define HELPER(name) \
2428 VGOFF_(helper_##name) = alloc_BaB_1_set( (Addr) & VG_(helper_##name))
njn3e884182003-04-15 13:03:23 +00002429
nethercote71980f02004-01-24 18:18:54 +00002430 /* Helper functions. */
2431 HELPER(idiv_64_32); HELPER(div_64_32);
2432 HELPER(idiv_32_16); HELPER(div_32_16);
2433 HELPER(idiv_16_8); HELPER(div_16_8);
fitzhardinge98abfc72003-12-16 02:05:15 +00002434
nethercote71980f02004-01-24 18:18:54 +00002435 HELPER(imul_32_64); HELPER(mul_32_64);
2436 HELPER(imul_16_32); HELPER(mul_16_32);
2437 HELPER(imul_8_16); HELPER(mul_8_16);
njn25e49d8e72002-09-23 09:36:25 +00002438
nethercote71980f02004-01-24 18:18:54 +00002439 HELPER(CLD); HELPER(STD);
2440 HELPER(get_dirflag);
sewardjde4a1d02002-03-22 01:27:54 +00002441
nethercote71980f02004-01-24 18:18:54 +00002442 HELPER(CLC); HELPER(STC);
nethercote1018bdd2004-02-11 23:33:29 +00002443 HELPER(CMC);
jsgf855d93d2003-10-13 22:26:55 +00002444
nethercote71980f02004-01-24 18:18:54 +00002445 HELPER(shldl); HELPER(shldw);
2446 HELPER(shrdl); HELPER(shrdw);
njncc7bb472002-10-14 09:25:19 +00002447
nethercote71980f02004-01-24 18:18:54 +00002448 HELPER(RDTSC); HELPER(CPUID);
njncc7bb472002-10-14 09:25:19 +00002449
nethercote1018bdd2004-02-11 23:33:29 +00002450 HELPER(bsfw); HELPER(bsfl);
2451 HELPER(bsrw); HELPER(bsrl);
rjwalshf5f536f2003-11-17 17:45:00 +00002452
nethercote71980f02004-01-24 18:18:54 +00002453 HELPER(fstsw_AX);
2454 HELPER(SAHF); HELPER(LAHF);
2455 HELPER(DAS); HELPER(DAA);
nethercote1018bdd2004-02-11 23:33:29 +00002456 HELPER(AAS); HELPER(AAA);
2457 HELPER(AAD); HELPER(AAM);
nethercote71980f02004-01-24 18:18:54 +00002458 HELPER(IN); HELPER(OUT);
2459 HELPER(cmpxchg8b);
sewardj018f7622002-05-15 21:13:39 +00002460
nethercote71980f02004-01-24 18:18:54 +00002461 HELPER(undefined_instruction);
jsgf855d93d2003-10-13 22:26:55 +00002462
nethercote71980f02004-01-24 18:18:54 +00002463# undef HELPER
sewardjde4a1d02002-03-22 01:27:54 +00002464
nethercote71980f02004-01-24 18:18:54 +00002465 /* Allocate slots for noncompact helpers */
2466 assign_helpers_in_baseBlock(VG_(n_noncompact_helpers),
2467 VG_(noncompact_helper_offsets),
2468 VG_(noncompact_helper_addrs));
2469}
sewardjde4a1d02002-03-22 01:27:54 +00002470
sewardj5f07b662002-04-23 16:52:51 +00002471
nethercote71980f02004-01-24 18:18:54 +00002472/*====================================================================*/
2473/*=== Setup pointercheck ===*/
2474/*====================================================================*/
njn25e49d8e72002-09-23 09:36:25 +00002475
nethercote71980f02004-01-24 18:18:54 +00002476static void setup_pointercheck(void)
2477{
2478 int ret;
sewardj2e93c502002-04-12 11:12:52 +00002479
fitzhardinge98abfc72003-12-16 02:05:15 +00002480 if (VG_(clo_pointercheck)) {
nethercote71980f02004-01-24 18:18:54 +00002481 vki_modify_ldt_t ldt = {
2482 VG_POINTERCHECK_SEGIDX, // entry_number
2483 VG_(client_base), // base_addr
2484 (VG_(client_end)-VG_(client_base)) / VKI_BYTES_PER_PAGE, // limit
2485 1, // seg_32bit
2486 0, // contents: data, RW, non-expanding
2487 0, // ! read_exec_only
2488 1, // limit_in_pages
2489 0, // ! seg not present
2490 1, // useable
fitzhardinge98abfc72003-12-16 02:05:15 +00002491 };
nethercote71980f02004-01-24 18:18:54 +00002492 ret = VG_(do_syscall)(__NR_modify_ldt, 1, &ldt, sizeof(ldt));
fitzhardinge98abfc72003-12-16 02:05:15 +00002493 if (ret < 0) {
2494 VG_(message)(Vg_UserMsg,
2495 "Warning: ignoring --pointercheck=yes, "
2496 "because modify_ldt failed (errno=%d)", -ret);
2497 VG_(clo_pointercheck) = False;
2498 }
2499 }
sewardjde4a1d02002-03-22 01:27:54 +00002500}
2501
nethercote71980f02004-01-24 18:18:54 +00002502/*====================================================================*/
2503/*=== Initialise program data/text, etc. ===*/
2504/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +00002505
nethercote71980f02004-01-24 18:18:54 +00002506static void build_valgrind_map_callback
2507 ( Addr start, UInt size, Char rr, Char ww, Char xx,
2508 UInt dev, UInt ino, ULong foffset, const UChar* filename )
sewardjde4a1d02002-03-22 01:27:54 +00002509{
nethercote71980f02004-01-24 18:18:54 +00002510 UInt prot = 0;
2511 UInt flags = SF_MMAP|SF_NOSYMS;
2512 Bool is_stack_segment;
2513
2514 is_stack_segment =
2515 (start == VG_(clstk_base) && (start+size) == VG_(clstk_end));
2516
2517 /* Only record valgrind mappings for now, without loading any
2518 symbols. This is so we know where the free space is before we
2519 start allocating more memory (note: heap is OK, it's just mmap
2520 which is the problem here). */
2521 if (start >= VG_(valgrind_base) && (start+size) <= VG_(valgrind_end)) {
2522 flags |= SF_VALGRIND;
2523 VG_(map_file_segment)(start, size, prot, flags, dev, ino, foffset, filename);
2524 }
sewardjde4a1d02002-03-22 01:27:54 +00002525}
2526
nethercote71980f02004-01-24 18:18:54 +00002527// Global var used to pass local data to callback
2528Addr esp_at_startup___global_arg = 0;
sewardjde4a1d02002-03-22 01:27:54 +00002529
nethercote71980f02004-01-24 18:18:54 +00002530static void build_segment_map_callback
2531 ( Addr start, UInt size, Char rr, Char ww, Char xx,
2532 UInt dev, UInt ino, ULong foffset, const UChar* filename )
sewardj45b672d2003-07-25 19:58:11 +00002533{
nethercote71980f02004-01-24 18:18:54 +00002534 UInt prot = 0;
2535 UInt flags;
2536 Bool is_stack_segment;
2537 Addr r_esp;
sewardj45b672d2003-07-25 19:58:11 +00002538
nethercote71980f02004-01-24 18:18:54 +00002539 is_stack_segment
2540 = (start == VG_(clstk_base) && (start+size) == VG_(clstk_end));
fitzhardinge98abfc72003-12-16 02:05:15 +00002541
nethercote71980f02004-01-24 18:18:54 +00002542 if (rr == 'r') prot |= VKI_PROT_READ;
2543 if (ww == 'w') prot |= VKI_PROT_WRITE;
2544 if (xx == 'x') prot |= VKI_PROT_EXEC;
fitzhardinge98abfc72003-12-16 02:05:15 +00002545
nethercote71980f02004-01-24 18:18:54 +00002546 if (is_stack_segment)
2547 flags = SF_STACK | SF_GROWDOWN;
2548 else
2549 flags = SF_EXEC|SF_MMAP;
fitzhardinge98abfc72003-12-16 02:05:15 +00002550
nethercote71980f02004-01-24 18:18:54 +00002551 if (filename != NULL)
2552 flags |= SF_FILE;
fitzhardinge98abfc72003-12-16 02:05:15 +00002553
nethercote71980f02004-01-24 18:18:54 +00002554 if (start >= VG_(valgrind_base) && (start+size) <= VG_(valgrind_end))
2555 flags |= SF_VALGRIND;
fitzhardinge98abfc72003-12-16 02:05:15 +00002556
nethercote71980f02004-01-24 18:18:54 +00002557 VG_(map_file_segment)(start, size, prot, flags, dev, ino, foffset, filename);
fitzhardinge98abfc72003-12-16 02:05:15 +00002558
nethercote71980f02004-01-24 18:18:54 +00002559 if (VG_(is_client_addr)(start) && VG_(is_client_addr)(start+size-1))
2560 VG_TRACK( new_mem_startup, start, size, rr=='r', ww=='w', xx=='x' );
sewardj3e1eb1f2002-05-18 13:14:17 +00002561
nethercote71980f02004-01-24 18:18:54 +00002562 /* If this is the stack segment mark all below %esp as noaccess. */
2563 r_esp = esp_at_startup___global_arg;
2564 vg_assert(0 != r_esp);
2565 if (is_stack_segment) {
2566 if (0)
2567 VG_(message)(Vg_DebugMsg, "invalidating stack area: %x .. %x",
2568 start,r_esp);
2569 VG_TRACK( die_mem_stack, start, r_esp-start );
sewardjde4a1d02002-03-22 01:27:54 +00002570 }
sewardjde4a1d02002-03-22 01:27:54 +00002571}
2572
2573
nethercote71980f02004-01-24 18:18:54 +00002574/*====================================================================*/
2575/*=== Sanity check machinery (permanently engaged) ===*/
2576/*====================================================================*/
njn25e49d8e72002-09-23 09:36:25 +00002577
2578/* A fast sanity check -- suitable for calling circa once per
2579 millisecond. */
2580
2581void VG_(do_sanity_checks) ( Bool force_expensive )
2582{
njn37cea302002-09-30 11:24:00 +00002583 VGP_PUSHCC(VgpCoreCheapSanity);
2584
nethercote27fec902004-06-16 21:26:32 +00002585 if (VG_(clo_sanity_level) < 1) return;
njn25e49d8e72002-09-23 09:36:25 +00002586
2587 /* --- First do all the tests that we can do quickly. ---*/
2588
2589 VG_(sanity_fast_count)++;
2590
njn25e49d8e72002-09-23 09:36:25 +00002591 /* Check stuff pertaining to the memory check system. */
2592
2593 /* Check that nobody has spuriously claimed that the first or
2594 last 16 pages of memory have become accessible [...] */
njn37cea302002-09-30 11:24:00 +00002595 if (VG_(needs).sanity_checks) {
2596 VGP_PUSHCC(VgpSkinCheapSanity);
njn25e49d8e72002-09-23 09:36:25 +00002597 vg_assert(SK_(cheap_sanity_check)());
njn37cea302002-09-30 11:24:00 +00002598 VGP_POPCC(VgpSkinCheapSanity);
2599 }
njn25e49d8e72002-09-23 09:36:25 +00002600
2601 /* --- Now some more expensive checks. ---*/
2602
2603 /* Once every 25 times, check some more expensive stuff. */
2604 if ( force_expensive
nethercote27fec902004-06-16 21:26:32 +00002605 || VG_(clo_sanity_level) > 1
2606 || (VG_(clo_sanity_level) == 1 && (VG_(sanity_fast_count) % 25) == 0)) {
njn25e49d8e72002-09-23 09:36:25 +00002607
njn37cea302002-09-30 11:24:00 +00002608 VGP_PUSHCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002609 VG_(sanity_slow_count)++;
2610
jsgf855d93d2003-10-13 22:26:55 +00002611 VG_(proxy_sanity)();
2612
njn25e49d8e72002-09-23 09:36:25 +00002613# if 0
2614 { void zzzmemscan(void); zzzmemscan(); }
2615# endif
2616
2617 if ((VG_(sanity_fast_count) % 250) == 0)
2618 VG_(sanity_check_tc_tt)();
2619
2620 if (VG_(needs).sanity_checks) {
njn37cea302002-09-30 11:24:00 +00002621 VGP_PUSHCC(VgpSkinExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002622 vg_assert(SK_(expensive_sanity_check)());
njn37cea302002-09-30 11:24:00 +00002623 VGP_POPCC(VgpSkinExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002624 }
2625 /*
2626 if ((VG_(sanity_fast_count) % 500) == 0) VG_(mallocSanityCheckAll)();
2627 */
njn37cea302002-09-30 11:24:00 +00002628 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002629 }
2630
nethercote27fec902004-06-16 21:26:32 +00002631 if (VG_(clo_sanity_level) > 1) {
njn37cea302002-09-30 11:24:00 +00002632 VGP_PUSHCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002633 /* Check sanity of the low-level memory manager. Note that bugs
2634 in the client's code can cause this to fail, so we don't do
2635 this check unless specially asked for. And because it's
2636 potentially very expensive. */
2637 VG_(mallocSanityCheckAll)();
njn37cea302002-09-30 11:24:00 +00002638 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002639 }
njn37cea302002-09-30 11:24:00 +00002640 VGP_POPCC(VgpCoreCheapSanity);
njn25e49d8e72002-09-23 09:36:25 +00002641}
nethercote71980f02004-01-24 18:18:54 +00002642
2643
2644/*====================================================================*/
2645/*=== main() ===*/
2646/*====================================================================*/
2647
nethercotec314eba2004-07-15 12:59:41 +00002648/*
2649 This code decides on the layout of the client and Valgrind address
2650 spaces, loads valgrind.so and the skin.so into the valgrind part,
2651 loads the client executable (and the dynamic linker, if necessary)
2652 into the client part, and calls into Valgrind proper.
2653
2654 The code is careful not to allow spurious mappings to appear in the
2655 wrong parts of the address space. In particular, to make sure
2656 dlopen puts things in the right place, it will pad out the forbidden
2657 chunks of address space so that dlopen is forced to put things where
2658 we want them.
2659
2660 The memory map it creates is:
2661
2662 CLIENT_BASE +-------------------------+
2663 | client address space |
2664 : :
2665 : :
2666 | client stack |
2667 client_end +-------------------------+
2668 | redzone |
2669 shadow_base +-------------------------+
2670 | |
2671 : shadow memory for skins :
2672 | (may be 0 sized) |
2673 shadow_end +-------------------------+
2674 : gap (may be 0 sized) :
2675 valgrind_base +-------------------------+
2676 | kickstart executable |
2677 | valgrind heap vvvvvvvvv| (barely used)
2678 - -
2679 | valgrind .so files |
2680 | and mappings |
2681 - -
2682 | valgrind stack ^^^^^^^^^|
2683 valgrind_end +-------------------------+
2684 : kernel :
2685
2686 Nb: Before we can do general allocations with VG_(arena_malloc)() and
2687 VG_(mmap)(), we need to build the segment skip-list, so we know where
2688 we can put things. However, building that structure requires
2689 allocating memory. So we need to a bootstrapping process. It's done
2690 by making VG_(arena_malloc)() have a special static superblock that's
2691 used for the first 1MB's worth of allocations. This is enough to
2692 build the segment skip-list.
2693*/
2694
nethercote31779c72004-07-30 21:50:15 +00002695static int prmap(char *start, char *end, const char *perm, off_t off,
2696 int maj, int min, int ino, void* dummy) {
thughes4ad52d02004-06-27 17:37:21 +00002697 printf("mapping %10p-%10p %s %02x:%02x %d\n",
2698 start, end, perm, maj, min, ino);
2699 return True;
2700}
2701
nethercote71980f02004-01-24 18:18:54 +00002702int main(int argc, char **argv)
2703{
2704 char **cl_argv;
2705 const char *tool = NULL;
2706 const char *exec = NULL;
2707 char *preload; /* tool-specific LD_PRELOAD .so */
2708 char **env;
nethercote6c999f22004-01-31 22:55:15 +00002709 Int need_help = 0; // 0 = no, 1 = --help, 2 = --help-debug
nethercote71980f02004-01-24 18:18:54 +00002710 struct exeinfo info;
2711 ToolInfo *toolinfo = NULL;
2712 void *tool_dlhandle;
2713 Addr client_eip;
2714 Addr esp_at_startup; /* client's %esp at the point we gained control. */
2715 UInt * client_auxv;
2716 VgSchedReturnCode src;
nethercote47dd12c2004-06-22 14:18:42 +00002717 Int exitcode = 0;
fitzhardingeb50068f2004-02-24 23:42:55 +00002718 vki_rlimit zero = { 0, 0 };
nethercote31779c72004-07-30 21:50:15 +00002719 Int padfile;
nethercote71980f02004-01-24 18:18:54 +00002720
2721 //============================================================
2722 // Nb: startup is complex. Prerequisites are shown at every step.
2723 //
2724 // *** Be very careful when messing with the order ***
2725 //============================================================
2726
nethercotef4928da2004-06-15 10:54:40 +00002727 //============================================================
2728 // Command line argument handling order:
2729 // * If --help/--help-debug are present, show usage message
2730 // (if --tool is also present, that includes the tool-specific usage)
2731 // * Then, if --tool is missing, abort with error msg
2732 // * Then, if client is missing, abort with error msg
2733 // * Then, if any cmdline args are bad, abort with error msg
2734 //============================================================
2735
fitzhardingeb50068f2004-02-24 23:42:55 +00002736 // Get the current process datasize rlimit, and set it to zero.
2737 // This prevents any internal uses of brk() from having any effect.
2738 // We remember the old value so we can restore it on exec, so that
2739 // child processes will have a reasonable brk value.
2740 VG_(getrlimit)(VKI_RLIMIT_DATA, &VG_(client_rlimit_data));
2741 zero.rlim_max = VG_(client_rlimit_data).rlim_max;
2742 VG_(setrlimit)(VKI_RLIMIT_DATA, &zero);
2743
nethercote71980f02004-01-24 18:18:54 +00002744 //--------------------------------------------------------------
2745 // Check we were launched by stage1
nethercotec314eba2004-07-15 12:59:41 +00002746 // p: n/a
nethercote71980f02004-01-24 18:18:54 +00002747 //--------------------------------------------------------------
nethercote31779c72004-07-30 21:50:15 +00002748 padfile = scan_auxv();
nethercote71980f02004-01-24 18:18:54 +00002749
2750 if (0) {
nethercote71980f02004-01-24 18:18:54 +00002751 printf("========== main() ==========\n");
nethercote31779c72004-07-30 21:50:15 +00002752 foreach_map(prmap, /*dummy*/NULL);
nethercote71980f02004-01-24 18:18:54 +00002753 }
2754
2755 //--------------------------------------------------------------
2756 // Look for alternative libdir
2757 // p: n/a
2758 //--------------------------------------------------------------
2759 { char *cp = getenv(VALGRINDLIB);
2760 if (cp != NULL)
2761 VG_(libdir) = cp;
2762 }
2763
2764 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002765 // Get valgrind args + client args (inc. from VALGRIND_OPTS/.valgrindrc).
2766 // Pre-process the command line.
2767 // p: n/a
2768 //--------------------------------------------------------------
2769 get_command_line(argc, argv, &VG_(vg_argc), &VG_(vg_argv), &cl_argv);
2770 pre_process_cmd_line_options(&need_help, &tool, &exec);
2771
2772 //==============================================================
2773 // Nb: once a tool is specified, the tool.so must be loaded even if
2774 // they specified --help or didn't specify a client program.
2775 //==============================================================
2776
2777 //--------------------------------------------------------------
2778 // With client padded out, map in tool
nethercote71980f02004-01-24 18:18:54 +00002779 // p: set-libdir [for VG_(libdir)]
2780 // p: pre_process_cmd_line_options() [for 'tool']
2781 //--------------------------------------------------------------
2782 load_tool(tool, &tool_dlhandle, &toolinfo, &preload);
2783
2784 //==============================================================
2785 // Can use VG_(malloc)() and VG_(arena_malloc)() only after load_tool()
nethercotec314eba2004-07-15 12:59:41 +00002786 // -- redzone size is now set. This is checked by vg_malloc2.c.
nethercote71980f02004-01-24 18:18:54 +00002787 //==============================================================
2788
2789 //--------------------------------------------------------------
2790 // Finalise address space layout
nethercote31779c72004-07-30 21:50:15 +00002791 // p: load_tool() [for 'toolinfo']
nethercote71980f02004-01-24 18:18:54 +00002792 //--------------------------------------------------------------
nethercote31779c72004-07-30 21:50:15 +00002793 layout_remaining_space( (Addr) & argc, toolinfo->shadow_ratio );
nethercote71980f02004-01-24 18:18:54 +00002794
2795 //--------------------------------------------------------------
2796 // Load client executable, finding in $PATH if necessary
nethercote71980f02004-01-24 18:18:54 +00002797 // 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 //--------------------------------------------------------------
nethercote31779c72004-07-30 21:50:15 +00002807 as_unpad((void *)VG_(shadow_end), (void *)~0, padfile);
2808 as_closepadfile(padfile); // no more padding
nethercote71980f02004-01-24 18:18:54 +00002809
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/*--------------------------------------------------------------------*/