blob: 7c8f50e62fa27932b2af131eb0571f8a8b07ebb9 [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
nethercote996901a2004-08-03 13:29:09 +0000107Addr VG_(shadow_base); /* tool'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
fitzhardinge98abfc72003-12-16 02:05:15 +0000119/* stage1 (main) executable */
fitzhardingea49f9b52003-12-16 22:26:45 +0000120Int VG_(vgexecfd) = -1;
121
122/* client executable */
123Int VG_(clexecfd) = -1;
fitzhardinge98abfc72003-12-16 02:05:15 +0000124
125/* Path to library directory */
126const Char *VG_(libdir) = VG_LIBDIR;
127
128/* our argc/argv */
129Int VG_(vg_argc);
130Char **VG_(vg_argv);
131
jsgf855d93d2003-10-13 22:26:55 +0000132/* PID of the main thread */
133Int VG_(main_pid);
134
135/* PGRP of process */
136Int VG_(main_pgrp);
njn25e49d8e72002-09-23 09:36:25 +0000137
thughesad1c9562004-06-26 11:27:52 +0000138/* Application-visible file descriptor limits */
139Int VG_(fd_soft_limit) = -1;
140Int VG_(fd_hard_limit) = -1;
fitzhardingef0046f22003-12-18 02:39:22 +0000141
nethercote71980f02004-01-24 18:18:54 +0000142/* As deduced from esp_at_startup, the client's argc, argv[] and
143 envp[] as extracted from the client's stack at startup-time. */
144Int VG_(client_argc);
145Char** VG_(client_argv);
146Char** VG_(client_envp);
sewardjde4a1d02002-03-22 01:27:54 +0000147
148/* ---------------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +0000149 Running stuff
sewardjde4a1d02002-03-22 01:27:54 +0000150 ------------------------------------------------------------------ */
nethercote71980f02004-01-24 18:18:54 +0000151/* Our signal delivery stack. */
njn6eba4ef2003-05-01 08:06:41 +0000152UInt VG_(sigstack)[VG_SIGSTACK_SIZE_W];
sewardjde4a1d02002-03-22 01:27:54 +0000153
nethercote31294822004-08-02 13:15:26 +0000154/* jmp_buf for fatal signals; VG_(fatal_signal_jmpbuf_ptr) is NULL until
155 the time is right that it can be used. */
156Int VG_(fatal_sigNo) = -1;
157jmp_buf* VG_(fatal_signal_jmpbuf_ptr) = NULL;
158jmp_buf fatal_signal_jmpbuf;
sewardjde4a1d02002-03-22 01:27:54 +0000159
nethercote71980f02004-01-24 18:18:54 +0000160/* Counts downwards in VG_(run_innerloop). */
161UInt VG_(dispatch_ctr);
sewardjde4a1d02002-03-22 01:27:54 +0000162
163/* 64-bit counter for the number of basic blocks done. */
164ULong VG_(bbs_done);
sewardjde4a1d02002-03-22 01:27:54 +0000165
sewardj7e87e382002-05-03 19:09:05 +0000166/* This is the ThreadId of the last thread the scheduler ran. */
167ThreadId VG_(last_run_tid) = 0;
168
nethercote71980f02004-01-24 18:18:54 +0000169/* Tell the logging mechanism whether we are logging to a file
170 descriptor or a socket descriptor. */
171Bool VG_(logging_to_filedes) = True;
172
sewardj73cf3bc2002-11-03 03:20:15 +0000173
nethercote71980f02004-01-24 18:18:54 +0000174/*====================================================================*/
175/*=== Counters, for profiling purposes only ===*/
176/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +0000177
178/* Number of lookups which miss the fast tt helper. */
179UInt VG_(tt_fast_misses) = 0;
180
181
sewardjc0d8f682002-11-30 00:49:43 +0000182/* Counts for TT/TC informational messages. */
sewardjde4a1d02002-03-22 01:27:54 +0000183
sewardjde4a1d02002-03-22 01:27:54 +0000184/* Number and total o/t size of translations overall. */
185UInt VG_(overall_in_count) = 0;
186UInt VG_(overall_in_osize) = 0;
187UInt VG_(overall_in_tsize) = 0;
188/* Number and total o/t size of discards overall. */
189UInt VG_(overall_out_count) = 0;
190UInt VG_(overall_out_osize) = 0;
191UInt VG_(overall_out_tsize) = 0;
sewardjc0d8f682002-11-30 00:49:43 +0000192/* The number of discards of TT/TC. */
193UInt VG_(number_of_tc_discards) = 0;
sewardj22854b92002-11-30 14:00:47 +0000194/* Counts of chain and unchain operations done. */
195UInt VG_(bb_enchain_count) = 0;
196UInt VG_(bb_dechain_count) = 0;
197/* Number of unchained jumps performed. */
198UInt VG_(unchained_jumps_done) = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000199
sewardjde4a1d02002-03-22 01:27:54 +0000200/* Counts pertaining to internal sanity checking. */
nethercote297effd2004-08-02 15:07:57 +0000201static UInt sanity_fast_count = 0;
202static UInt sanity_slow_count = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000203
nethercote71980f02004-01-24 18:18:54 +0000204static __inline__ Int safe_idiv(Int a, Int b)
205{
206 return (b == 0 ? 0 : a / b);
207}
208
nethercote3a42fb82004-08-03 18:08:50 +0000209static void print_all_stats ( void )
nethercote71980f02004-01-24 18:18:54 +0000210{
nethercote3a42fb82004-08-03 18:08:50 +0000211 // Translation stats
nethercote71980f02004-01-24 18:18:54 +0000212 VG_(message)(Vg_DebugMsg,
nethercote3a42fb82004-08-03 18:08:50 +0000213 " TT/TC: %d tc sectors discarded.",
nethercote71980f02004-01-24 18:18:54 +0000214 VG_(number_of_tc_discards) );
215 VG_(message)(Vg_DebugMsg,
nethercote3a42fb82004-08-03 18:08:50 +0000216 " %d tt_fast misses.", VG_(tt_fast_misses));
217 VG_(message)(Vg_DebugMsg,
nethercote71980f02004-01-24 18:18:54 +0000218 " %d chainings, %d unchainings.",
219 VG_(bb_enchain_count), VG_(bb_dechain_count) );
220 VG_(message)(Vg_DebugMsg,
221 "translate: new %d (%d -> %d; ratio %d:10)",
222 VG_(overall_in_count),
223 VG_(overall_in_osize),
224 VG_(overall_in_tsize),
225 safe_idiv(10*VG_(overall_in_tsize), VG_(overall_in_osize)));
226 VG_(message)(Vg_DebugMsg,
227 " discard %d (%d -> %d; ratio %d:10).",
228 VG_(overall_out_count),
229 VG_(overall_out_osize),
230 VG_(overall_out_tsize),
231 safe_idiv(10*VG_(overall_out_tsize), VG_(overall_out_osize)));
232 VG_(message)(Vg_DebugMsg,
nethercote3a42fb82004-08-03 18:08:50 +0000233 " dispatch: %llu jumps (bb entries); of them %u (%lu%%) unchained.",
nethercote71980f02004-01-24 18:18:54 +0000234 VG_(bbs_done),
235 VG_(unchained_jumps_done),
236 ((ULong)(100) * (ULong)(VG_(unchained_jumps_done)))
237 / ( VG_(bbs_done)==0 ? 1 : VG_(bbs_done) )
238 );
239
nethercote3a42fb82004-08-03 18:08:50 +0000240 // Scheduler stats
nethercote844e7122004-08-02 15:27:22 +0000241 VG_(print_scheduler_stats)();
nethercote71980f02004-01-24 18:18:54 +0000242
nethercote3a42fb82004-08-03 18:08:50 +0000243 // Reg-alloc stats
nethercotebee3fd92004-08-02 15:17:43 +0000244 VG_(print_reg_alloc_stats)();
nethercote71980f02004-01-24 18:18:54 +0000245 VG_(message)(Vg_DebugMsg,
246 " sanity: %d cheap, %d expensive checks.",
nethercote297effd2004-08-02 15:07:57 +0000247 sanity_fast_count, sanity_slow_count );
nethercote3a42fb82004-08-03 18:08:50 +0000248
249 // C call stats
nethercote71980f02004-01-24 18:18:54 +0000250 VG_(print_ccall_stats)();
nethercote3a42fb82004-08-03 18:08:50 +0000251
252 // UInstr histogram
253 if (VG_(clo_verbosity) > 3)
254 VG_(print_UInstr_histogram)();
255
256 // Memory stats
257 if (0) {
258 VG_(message)(Vg_DebugMsg, "");
259 VG_(message)(Vg_DebugMsg,
260 "------ Valgrind's internal memory use stats follow ------" );
261 VG_(mallocSanityCheckAll)();
262 VG_(print_all_arena_stats)();
263 VG_(message)(Vg_DebugMsg,
264 "------ Valgrind's ExeContext management stats follow ------" );
265 VG_(print_ExeContext_stats)();
266 }
nethercote71980f02004-01-24 18:18:54 +0000267}
268
269
270/*====================================================================*/
271/*=== Miscellaneous global functions ===*/
272/*====================================================================*/
273
nethercote04d0fbc2004-01-26 16:48:06 +0000274/* Start debugger and get it to attach to this process. Called if the
275 user requests this service after an error has been shown, so she can
nethercote71980f02004-01-24 18:18:54 +0000276 poke around and look at parameters, memory, etc. You can't
nethercote04d0fbc2004-01-26 16:48:06 +0000277 meaningfully get the debugger to continue the program, though; to
278 continue, quit the debugger. */
279void VG_(start_debugger) ( Int tid )
nethercote71980f02004-01-24 18:18:54 +0000280{
281 Int pid;
282
283 if ((pid = fork()) == 0) {
284 ptrace(PTRACE_TRACEME, 0, NULL, NULL);
285 VG_(kkill)(VG_(getpid)(), VKI_SIGSTOP);
286
287 } else if (pid > 0) {
288 struct user_regs_struct regs;
289 Int status;
290 Int res;
291
292 if (VG_(is_running_thread)( tid )) {
fitzhardinged65dcad2004-03-13 02:06:58 +0000293 regs.cs = VG_(baseBlock)[VGOFF_(m_cs)];
294 regs.ss = VG_(baseBlock)[VGOFF_(m_ss)];
295 regs.ds = VG_(baseBlock)[VGOFF_(m_ds)];
296 regs.es = VG_(baseBlock)[VGOFF_(m_es)];
297 regs.fs = VG_(baseBlock)[VGOFF_(m_fs)];
298 regs.gs = VG_(baseBlock)[VGOFF_(m_gs)];
nethercote71980f02004-01-24 18:18:54 +0000299 regs.eax = VG_(baseBlock)[VGOFF_(m_eax)];
300 regs.ebx = VG_(baseBlock)[VGOFF_(m_ebx)];
301 regs.ecx = VG_(baseBlock)[VGOFF_(m_ecx)];
302 regs.edx = VG_(baseBlock)[VGOFF_(m_edx)];
303 regs.esi = VG_(baseBlock)[VGOFF_(m_esi)];
304 regs.edi = VG_(baseBlock)[VGOFF_(m_edi)];
305 regs.ebp = VG_(baseBlock)[VGOFF_(m_ebp)];
306 regs.esp = VG_(baseBlock)[VGOFF_(m_esp)];
307 regs.eflags = VG_(baseBlock)[VGOFF_(m_eflags)];
308 regs.eip = VG_(baseBlock)[VGOFF_(m_eip)];
309 } else {
310 ThreadState* tst = & VG_(threads)[ tid ];
311
fitzhardinged65dcad2004-03-13 02:06:58 +0000312 regs.cs = tst->m_cs;
313 regs.ss = tst->m_ss;
314 regs.ds = tst->m_ds;
315 regs.es = tst->m_es;
316 regs.fs = tst->m_fs;
317 regs.gs = tst->m_gs;
nethercote71980f02004-01-24 18:18:54 +0000318 regs.eax = tst->m_eax;
319 regs.ebx = tst->m_ebx;
320 regs.ecx = tst->m_ecx;
321 regs.edx = tst->m_edx;
322 regs.esi = tst->m_esi;
323 regs.edi = tst->m_edi;
324 regs.ebp = tst->m_ebp;
325 regs.esp = tst->m_esp;
326 regs.eflags = tst->m_eflags;
327 regs.eip = tst->m_eip;
328 }
329
330 if ((res = VG_(waitpid)(pid, &status, 0)) == pid &&
331 WIFSTOPPED(status) && WSTOPSIG(status) == SIGSTOP &&
332 ptrace(PTRACE_SETREGS, pid, NULL, &regs) == 0 &&
thughes1d160052004-04-21 15:39:57 +0000333 kill(pid, SIGSTOP) == 0 &&
334 ptrace(PTRACE_DETACH, pid, NULL, 0) == 0) {
nethercote04d0fbc2004-01-26 16:48:06 +0000335 Char pidbuf[15];
336 Char file[30];
337 Char buf[100];
338 Char *bufptr;
339 Char *cmdptr;
340
341 VG_(sprintf)(pidbuf, "%d", pid);
342 VG_(sprintf)(file, "/proc/%d/fd/%d", pid, VG_(clexecfd));
343
344 bufptr = buf;
345 cmdptr = VG_(clo_db_command);
346
347 while (*cmdptr) {
348 switch (*cmdptr) {
349 case '%':
350 switch (*++cmdptr) {
351 case 'f':
352 VG_(memcpy)(bufptr, file, VG_(strlen)(file));
353 bufptr += VG_(strlen)(file);
354 cmdptr++;
355 break;
356 case 'p':
357 VG_(memcpy)(bufptr, pidbuf, VG_(strlen)(pidbuf));
358 bufptr += VG_(strlen)(pidbuf);
359 cmdptr++;
360 break;
361 default:
362 *bufptr++ = *cmdptr++;
363 break;
364 }
365 break;
366 default:
367 *bufptr++ = *cmdptr++;
368 break;
369 }
370 }
371
372 *bufptr++ = '\0';
373
374 VG_(message)(Vg_UserMsg, "starting debugger with cmd: %s", buf);
nethercote71980f02004-01-24 18:18:54 +0000375 res = VG_(system)(buf);
376 if (res == 0) {
377 VG_(message)(Vg_UserMsg, "");
378 VG_(message)(Vg_UserMsg,
nethercote04d0fbc2004-01-26 16:48:06 +0000379 "Debugger has detached. Valgrind regains control. We continue.");
nethercote71980f02004-01-24 18:18:54 +0000380 } else {
381 VG_(message)(Vg_UserMsg, "Apparently failed!");
382 VG_(message)(Vg_UserMsg, "");
383 }
384 }
385
386 VG_(kkill)(pid, VKI_SIGKILL);
387 VG_(waitpid)(pid, &status, 0);
388 }
389}
390
391
392/* Print some helpful-ish text about unimplemented things, and give
393 up. */
394void VG_(unimplemented) ( Char* msg )
395{
396 VG_(message)(Vg_UserMsg, "");
397 VG_(message)(Vg_UserMsg,
398 "Valgrind detected that your program requires");
399 VG_(message)(Vg_UserMsg,
400 "the following unimplemented functionality:");
401 VG_(message)(Vg_UserMsg, " %s", msg);
402 VG_(message)(Vg_UserMsg,
403 "This may be because the functionality is hard to implement,");
404 VG_(message)(Vg_UserMsg,
405 "or because no reasonable program would behave this way,");
406 VG_(message)(Vg_UserMsg,
407 "or because nobody has yet needed it. In any case, let us know at");
408 VG_(message)(Vg_UserMsg,
409 "%s and/or try to work around the problem, if you can.", VG_BUGS_TO);
410 VG_(message)(Vg_UserMsg,
411 "");
412 VG_(message)(Vg_UserMsg,
413 "Valgrind has to exit now. Sorry. Bye!");
414 VG_(message)(Vg_UserMsg,
415 "");
416 VG_(pp_sched_status)();
417 VG_(exit)(1);
418}
419
420Addr VG_(get_stack_pointer) ( void )
421{
422 return VG_(baseBlock)[VGOFF_(m_esp)];
423}
424
425/* Debugging thing .. can be called from assembly with OYNK macro. */
426void VG_(oynk) ( Int n )
427{
428 OINK(n);
429}
430
431/* Initialize the PID and PGRP of scheduler LWP; this is also called
432 in any new children after fork. */
433static void newpid(ThreadId unused)
434{
435 /* PID of scheduler LWP */
436 VG_(main_pid) = VG_(getpid)();
437 VG_(main_pgrp) = VG_(getpgrp)();
438}
439
440/*====================================================================*/
441/*=== Check we were launched by stage 1 ===*/
442/*====================================================================*/
443
444/* Look for our AUXV table */
nethercote31779c72004-07-30 21:50:15 +0000445int scan_auxv(void)
nethercote71980f02004-01-24 18:18:54 +0000446{
447 const struct ume_auxv *auxv = find_auxv((int *)ume_exec_esp);
nethercote31779c72004-07-30 21:50:15 +0000448 int padfile = -1, found = 0;
nethercote71980f02004-01-24 18:18:54 +0000449
450 for (; auxv->a_type != AT_NULL; auxv++)
451 switch(auxv->a_type) {
452 case AT_UME_PADFD:
nethercote31779c72004-07-30 21:50:15 +0000453 padfile = auxv->u.a_val;
nethercote71980f02004-01-24 18:18:54 +0000454 found |= 1;
455 break;
456
457 case AT_UME_EXECFD:
458 VG_(vgexecfd) = auxv->u.a_val;
459 found |= 2;
460 break;
461 }
462
nethercote361a14e2004-07-26 11:11:56 +0000463 if ( found != (1|2) ) {
464 fprintf(stderr, "valgrind: stage2 must be launched by stage1\n");
nethercote71980f02004-01-24 18:18:54 +0000465 exit(127);
466 }
nethercote31779c72004-07-30 21:50:15 +0000467 vg_assert(padfile >= 0);
468 return padfile;
nethercote71980f02004-01-24 18:18:54 +0000469}
470
471
472/*====================================================================*/
473/*=== Address space determination ===*/
474/*====================================================================*/
475
nethercote31779c72004-07-30 21:50:15 +0000476static void layout_remaining_space(Addr argc_addr, float ratio)
nethercote71980f02004-01-24 18:18:54 +0000477{
nethercote31779c72004-07-30 21:50:15 +0000478 Int ires;
479 void* vres;
480 addr_t client_size, shadow_size;
nethercote71980f02004-01-24 18:18:54 +0000481
nethercote31779c72004-07-30 21:50:15 +0000482 VG_(valgrind_base) = (addr_t)&kickstart_base;
483 VG_(valgrind_end) = ROUNDUP(argc_addr, 0x10000); // stack
nethercote71980f02004-01-24 18:18:54 +0000484
nethercote31779c72004-07-30 21:50:15 +0000485 // This gives the client the largest possible address space while
486 // taking into account the tool's shadow needs.
487 client_size = ROUNDDN((VG_(valgrind_base)-REDZONE_SIZE) / (1.+ratio),
nethercote71980f02004-01-24 18:18:54 +0000488 CLIENT_SIZE_MULTIPLE);
nethercote31779c72004-07-30 21:50:15 +0000489 VG_(client_base) = CLIENT_BASE;
nethercote71980f02004-01-24 18:18:54 +0000490 VG_(client_end) = VG_(client_base) + client_size;
nethercotee2097312004-06-27 12:29:56 +0000491 /* where !FIXED mmap goes */
nethercotebc7b4f42004-07-26 12:44:35 +0000492 VG_(client_mapbase) = VG_(client_base) +
493 PGROUNDDN((addr_t)(client_size * CLIENT_HEAP_PROPORTION));
nethercote71980f02004-01-24 18:18:54 +0000494
nethercote31779c72004-07-30 21:50:15 +0000495 shadow_size = PGROUNDUP(client_size * ratio);
496 VG_(shadow_base) = VG_(client_end) + REDZONE_SIZE;
497 VG_(shadow_end) = VG_(shadow_base) + shadow_size;
nethercote71980f02004-01-24 18:18:54 +0000498
nethercotee2097312004-06-27 12:29:56 +0000499#define SEGSIZE(a,b) ((VG_(b) - VG_(a))/(1024*1024))
500
nethercote71980f02004-01-24 18:18:54 +0000501 if (0)
nethercotee2097312004-06-27 12:29:56 +0000502 VG_(printf)(
503 "client_base %8x (%dMB)\n"
504 "client_mapbase %8x (%dMB)\n"
505 "client_end %8x (%dMB)\n"
506 "shadow_base %8x (%dMB)\n"
507 "shadow_end %8x (%dMB)\n"
508 "valgrind_base %8x (%dMB)\n"
nethercotee2097312004-06-27 12:29:56 +0000509 "valgrind_end %8x\n",
510 VG_(client_base), SEGSIZE(client_base, client_mapbase),
511 VG_(client_mapbase), SEGSIZE(client_mapbase, client_end),
512 VG_(client_end), SEGSIZE(client_end, shadow_base),
513 VG_(shadow_base), SEGSIZE(shadow_base, shadow_end),
514 VG_(shadow_end), SEGSIZE(shadow_end, valgrind_base),
nethercotec314eba2004-07-15 12:59:41 +0000515 VG_(valgrind_base), SEGSIZE(valgrind_base, valgrind_end),
nethercotee2097312004-06-27 12:29:56 +0000516 VG_(valgrind_end)
517 );
518
519#undef SEGSIZE
nethercote71980f02004-01-24 18:18:54 +0000520
521 // Ban redzone
nethercotee567e702004-07-10 17:49:17 +0000522 vres = mmap((void *)VG_(client_end), REDZONE_SIZE, PROT_NONE,
523 MAP_FIXED|MAP_ANON|MAP_PRIVATE, -1, 0);
524 vg_assert((void*)-1 != vres);
nethercote71980f02004-01-24 18:18:54 +0000525
526 // Make client hole
nethercotee567e702004-07-10 17:49:17 +0000527 ires = munmap((void*)VG_(client_base), client_size);
528 vg_assert(0 == ires);
nethercote71980f02004-01-24 18:18:54 +0000529
530 // Map shadow memory.
531 // Initially all inaccessible, incrementally initialized as it is used
nethercotee567e702004-07-10 17:49:17 +0000532 if (shadow_size != 0) {
533 vres = mmap((char *)VG_(shadow_base), shadow_size, PROT_NONE,
534 MAP_PRIVATE|MAP_ANON|MAP_FIXED, -1, 0);
535 vg_assert((void*)-1 != vres);
536 }
nethercote71980f02004-01-24 18:18:54 +0000537}
538
539/*====================================================================*/
540/*=== Command line setup ===*/
541/*====================================================================*/
542
543/* Nb: malloc'd memory never freed -- kept throughout like argv, envp */
544static char* get_file_clo(char* dir)
545{
546# define FLEN 512
547 Int fd, n;
548 struct stat s1;
549 char* f_clo = NULL;
550 char filename[FLEN];
551
552 snprintf(filename, FLEN, "%s/.valgrindrc", ( NULL == dir ? "" : dir ) );
553 fd = VG_(open)(filename, 0, VKI_S_IRUSR);
554 if ( fd > 0 ) {
555 if ( 0 == fstat(fd, &s1) ) {
556 f_clo = malloc(s1.st_size+1);
557 vg_assert(f_clo);
558 n = read(fd, f_clo, s1.st_size);
559 if (n == -1) n = 0;
560 f_clo[n] = '\0';
561 }
562 close(fd);
563 }
564 return f_clo;
565# undef FLEN
566}
567
nethercotee2097312004-06-27 12:29:56 +0000568#define ISSPACE(cc) ((cc) == ' ' || (cc) == '\t' || (cc) == '\n')
569
nethercote71980f02004-01-24 18:18:54 +0000570static Int count_args(char* s)
571{
572 Int n = 0;
573 if (s) {
574 char* cp = s;
575 while (True) {
576 // We have alternating sequences: blanks, non-blanks, blanks...
577 // count the non-blanks sequences.
578 while ( ISSPACE(*cp) ) cp++;
579 if ( !*cp ) break;
580 n++;
581 while ( !ISSPACE(*cp) && *cp ) cp++;
582 }
583 }
584 return n;
585}
586
587/* add args out of environment, skipping multiple spaces and -- args */
588static char** copy_args( char* s, char** to )
589{
590 if (s) {
591 char* cp = s;
592 while (True) {
593 // We have alternating sequences: blanks, non-blanks, blanks...
594 // copy the non-blanks sequences, and add terminating '\0'
595 while ( ISSPACE(*cp) ) cp++;
596 if ( !*cp ) break;
597 *to++ = cp;
598 while ( !ISSPACE(*cp) && *cp ) cp++;
599 if ( *cp ) *cp++ = '\0'; // terminate if necessary
600 if (VG_STREQ(to[-1], "--")) to--; // undo any '--' arg
601 }
602 }
603 return to;
604}
605
nethercotee2097312004-06-27 12:29:56 +0000606#undef ISSPACE
607
nethercote71980f02004-01-24 18:18:54 +0000608// Augment command line with arguments from environment and .valgrindrc
609// files.
610static void augment_command_line(Int* vg_argc_inout, char*** vg_argv_inout)
611{
612 int vg_argc = *vg_argc_inout;
613 char** vg_argv = *vg_argv_inout;
614
615 char* env_clo = getenv(VALGRINDOPTS);
616 char* f1_clo = get_file_clo( getenv("HOME") );
617 char* f2_clo = get_file_clo(".");
618
619 /* copy any extra args from file or environment, if present */
620 if ( (env_clo && *env_clo) || (f1_clo && *f1_clo) || (f2_clo && *f2_clo) ) {
621 /* ' ' separated extra options */
622 char **from;
623 char **to;
624 int env_arg_count, f1_arg_count, f2_arg_count;
625
626 env_arg_count = count_args(env_clo);
627 f1_arg_count = count_args(f1_clo);
628 f2_arg_count = count_args(f2_clo);
629
630 if (0)
631 printf("extra-argc=%d %d %d\n",
632 env_arg_count, f1_arg_count, f2_arg_count);
633
634 /* +2: +1 for null-termination, +1 for added '--' */
635 from = vg_argv;
636 vg_argv = malloc( (vg_argc + env_arg_count + f1_arg_count
637 + f2_arg_count + 2) * sizeof(char **));
nethercote7c018f42004-07-17 16:40:50 +0000638 vg_assert(vg_argv);
nethercote71980f02004-01-24 18:18:54 +0000639 to = vg_argv;
640
641 /* copy argv[0] */
642 *to++ = *from++;
643
644 /* Copy extra args from env var and file, in the order: ~/.valgrindrc,
645 * $VALGRIND_OPTS, ./.valgrindrc -- more local options are put later
646 * to override less local ones. */
647 to = copy_args(f1_clo, to);
648 to = copy_args(env_clo, to);
649 to = copy_args(f2_clo, to);
650
651 /* copy original arguments, stopping at command or -- */
652 while (*from) {
653 if (**from != '-')
654 break;
655 if (VG_STREQ(*from, "--")) {
656 from++; /* skip -- */
657 break;
658 }
659 *to++ = *from++;
660 }
661
662 /* add -- */
663 *to++ = "--";
664
665 vg_argc = to - vg_argv;
666
667 /* copy rest of original command line, then NULL */
668 while (*from) *to++ = *from++;
669 *to = NULL;
670 }
671
672 *vg_argc_inout = vg_argc;
673 *vg_argv_inout = vg_argv;
674}
675
676static void get_command_line( int argc, char** argv,
677 Int* vg_argc_out, Char*** vg_argv_out,
678 char*** cl_argv_out )
679{
680 int vg_argc;
681 char** vg_argv;
682 char** cl_argv;
683 char* env_clo = getenv(VALGRINDCLO);
684
685 if (env_clo != NULL && *env_clo != '\0') {
686 char *cp;
687 char **cpp;
688
689 /* OK, we're getting all our arguments from the environment - the
690 entire command line belongs to the client (including argv[0]) */
691 vg_argc = 1; /* argv[0] */
692 for (cp = env_clo; *cp; cp++)
693 if (*cp == '\01')
694 vg_argc++;
695
696 vg_argv = malloc(sizeof(char **) * (vg_argc + 1));
nethercote7c018f42004-07-17 16:40:50 +0000697 vg_assert(vg_argv);
nethercote71980f02004-01-24 18:18:54 +0000698
699 cpp = vg_argv;
700
701 *cpp++ = "valgrind"; /* nominal argv[0] */
702 *cpp++ = env_clo;
703
704 for (cp = env_clo; *cp; cp++) {
705 if (*cp == '\01') {
706 *cp++ = '\0'; /* chop it up in place */
707 *cpp++ = cp;
708 }
709 }
710 *cpp = NULL;
711 cl_argv = argv;
712
713 } else {
714 /* Count the arguments on the command line. */
715 vg_argv = argv;
716
717 for (vg_argc = 1; vg_argc < argc; vg_argc++) {
718 if (argv[vg_argc][0] != '-') /* exe name */
719 break;
720 if (VG_STREQ(argv[vg_argc], "--")) { /* dummy arg */
721 vg_argc++;
722 break;
723 }
724 }
725 cl_argv = &argv[vg_argc];
726
727 /* Get extra args from VALGRIND_OPTS and .valgrindrc files.
728 * Note we don't do this if getting args from VALGRINDCLO. */
729 augment_command_line(&vg_argc, &vg_argv);
730 }
731
732 if (0) {
733 Int i;
734 for (i = 0; i < vg_argc; i++)
735 printf("vg_argv[%d]=\"%s\"\n", i, vg_argv[i]);
736 }
737
738 *vg_argc_out = vg_argc;
739 *vg_argv_out = (Char**)vg_argv;
740 *cl_argv_out = cl_argv;
741}
742
743
744/*====================================================================*/
745/*=== Environment and stack setup ===*/
746/*====================================================================*/
747
748/* Scan a colon-separated list, and call a function on each element.
749 The string must be mutable, because we insert a temporary '\0', but
thughes4ad52d02004-06-27 17:37:21 +0000750 the string will end up unmodified. (*func) should return True if it
nethercote71980f02004-01-24 18:18:54 +0000751 doesn't need to see any more.
thughes4ad52d02004-06-27 17:37:21 +0000752
753 This routine will return True if (*func) returns True and False if
754 it reaches the end of the list without that happening.
nethercote71980f02004-01-24 18:18:54 +0000755*/
thughes4ad52d02004-06-27 17:37:21 +0000756static Bool scan_colsep(char *colsep, Bool (*func)(const char *))
nethercote71980f02004-01-24 18:18:54 +0000757{
758 char *cp, *entry;
759 int end;
760
761 if (colsep == NULL ||
762 *colsep == '\0')
thughes4ad52d02004-06-27 17:37:21 +0000763 return False;
nethercote71980f02004-01-24 18:18:54 +0000764
765 entry = cp = colsep;
766
767 do {
768 end = (*cp == '\0');
769
770 if (*cp == ':' || *cp == '\0') {
771 char save = *cp;
772
773 *cp = '\0';
thughes21942d92004-07-12 09:35:37 +0000774 if ((*func)(entry)) {
775 *cp = save;
thughes4ad52d02004-06-27 17:37:21 +0000776 return True;
thughes21942d92004-07-12 09:35:37 +0000777 }
nethercote71980f02004-01-24 18:18:54 +0000778 *cp = save;
779 entry = cp+1;
780 }
781 cp++;
782 } while(!end);
thughes4ad52d02004-06-27 17:37:21 +0000783
784 return False;
785}
786
787static Bool contains(const char *p) {
788 if (VG_STREQ(p, VG_(libdir))) {
789 return True;
790 }
791 return False;
nethercote71980f02004-01-24 18:18:54 +0000792}
793
794/* Prepare the client's environment. This is basically a copy of our
795 environment, except:
796 1. LD_LIBRARY_PATH=$VALGRINDLIB:$LD_LIBRARY_PATH
797 2. LD_PRELOAD=$VALGRINDLIB/vg_inject.so:($VALGRINDLIB/vgpreload_TOOL.so:)?$LD_PRELOAD
798
799 If any of these is missing, then it is added.
800
801 Yummy. String hacking in C.
802
803 If this needs to handle any more variables it should be hacked
804 into something table driven.
805 */
806static char **fix_environment(char **origenv, const char *preload)
807{
808 static const char inject_so[] = "vg_inject.so";
809 static const char ld_library_path[] = "LD_LIBRARY_PATH=";
810 static const char ld_preload[] = "LD_PRELOAD=";
811 static const char valgrind_clo[] = VALGRINDCLO "=";
812 static const int ld_library_path_len = sizeof(ld_library_path)-1;
813 static const int ld_preload_len = sizeof(ld_preload)-1;
814 static const int valgrind_clo_len = sizeof(valgrind_clo)-1;
815 int ld_preload_done = 0;
816 int ld_library_path_done = 0;
817 char *inject_path;
818 int inject_path_len;
819 int vgliblen = strlen(VG_(libdir));
820 char **cpp;
821 char **ret;
822 int envc;
823 const int preloadlen = (preload == NULL) ? 0 : strlen(preload);
824
825 /* Find the vg_inject.so; also make room for the tool preload
826 library */
827 inject_path_len = sizeof(inject_so) + vgliblen + preloadlen + 16;
828 inject_path = malloc(inject_path_len);
nethercote7c018f42004-07-17 16:40:50 +0000829 vg_assert(inject_path);
nethercote71980f02004-01-24 18:18:54 +0000830
831 if (preload)
832 snprintf(inject_path, inject_path_len, "%s/%s:%s",
833 VG_(libdir), inject_so, preload);
834 else
835 snprintf(inject_path, inject_path_len, "%s/%s",
836 VG_(libdir), inject_so);
837
838 /* Count the original size of the env */
839 envc = 0; /* trailing NULL */
840 for (cpp = origenv; cpp && *cpp; cpp++)
841 envc++;
842
843 /* Allocate a new space */
844 ret = malloc(sizeof(char *) * (envc+3+1)); /* 3 new entries + NULL */
nethercote7c018f42004-07-17 16:40:50 +0000845 vg_assert(ret);
nethercote71980f02004-01-24 18:18:54 +0000846
847 /* copy it over */
848 for (cpp = ret; *origenv; )
849 *cpp++ = *origenv++;
850 *cpp = NULL;
851
852 vg_assert(envc == (cpp - ret));
853
854 /* Walk over the new environment, mashing as we go */
855 for (cpp = ret; cpp && *cpp; cpp++) {
856 if (memcmp(*cpp, ld_library_path, ld_library_path_len) == 0) {
nethercote71980f02004-01-24 18:18:54 +0000857 /* If the LD_LIBRARY_PATH already contains libdir, then don't
858 bother adding it again, even if it isn't the first (it
859 seems that the Java runtime will keep reexecing itself
860 unless its paths are at the front of LD_LIBRARY_PATH) */
thughes4ad52d02004-06-27 17:37:21 +0000861 if (!scan_colsep(*cpp + ld_library_path_len, contains)) {
nethercote71980f02004-01-24 18:18:54 +0000862 int len = strlen(*cpp) + vgliblen*2 + 16;
863 char *cp = malloc(len);
nethercote7c018f42004-07-17 16:40:50 +0000864 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000865
866 snprintf(cp, len, "%s%s:%s",
867 ld_library_path, VG_(libdir),
868 (*cpp)+ld_library_path_len);
869
870 *cpp = cp;
871 }
872
873 ld_library_path_done = 1;
874 } else if (memcmp(*cpp, ld_preload, ld_preload_len) == 0) {
875 int len = strlen(*cpp) + inject_path_len;
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_preload, inject_path, (*cpp)+ld_preload_len);
881
882 *cpp = cp;
883
884 ld_preload_done = 1;
885 } else if (memcmp(*cpp, valgrind_clo, valgrind_clo_len) == 0) {
886 *cpp = "";
887 }
888 }
889
890 /* Add the missing bits */
891
892 if (!ld_library_path_done) {
893 int len = ld_library_path_len + vgliblen*2 + 16;
894 char *cp = malloc(len);
nethercote7c018f42004-07-17 16:40:50 +0000895 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000896
897 snprintf(cp, len, "%s%s", ld_library_path, VG_(libdir));
898
899 ret[envc++] = cp;
900 }
901
902 if (!ld_preload_done) {
903 int len = ld_preload_len + inject_path_len;
904 char *cp = malloc(len);
nethercote7c018f42004-07-17 16:40:50 +0000905 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000906
907 snprintf(cp, len, "%s%s",
908 ld_preload, inject_path);
909
910 ret[envc++] = cp;
911 }
912
913 ret[envc] = NULL;
914
915 return ret;
916}
917
918extern char **environ; /* our environment */
919//#include <error.h>
920
921/* Add a string onto the string table, and return its address */
922static char *copy_str(char **tab, const char *str)
923{
924 char *cp = *tab;
925 char *orig = cp;
926
927 while(*str)
928 *cp++ = *str++;
929 *cp++ = '\0';
930
931 if (0)
nethercotef84f6952004-07-15 14:58:33 +0000932 printf("copied %p \"%s\" len %d\n", orig, orig, cp-orig);
nethercote71980f02004-01-24 18:18:54 +0000933
934 *tab = cp;
935
936 return orig;
937}
938
939/*
940 This sets up the client's initial stack, containing the args,
941 environment and aux vector.
942
943 The format of the stack is:
944
945 higher address +-----------------+
946 | Trampoline code |
947 +-----------------+
948 | |
949 : string table :
950 | |
951 +-----------------+
952 | AT_NULL |
953 - -
954 | auxv |
955 +-----------------+
956 | NULL |
957 - -
958 | envp |
959 +-----------------+
960 | NULL |
961 - -
962 | argv |
963 +-----------------+
964 | argc |
965 lower address +-----------------+ <- esp
966 | undefined |
967 : :
968 */
969static Addr setup_client_stack(char **orig_argv, char **orig_envp,
970 const struct exeinfo *info,
971 UInt** client_auxv)
972{
nethercotee567e702004-07-10 17:49:17 +0000973 void* res;
nethercote71980f02004-01-24 18:18:54 +0000974 char **cpp;
975 char *strtab; /* string table */
976 char *stringbase;
977 addr_t *ptr;
978 struct ume_auxv *auxv;
979 const struct ume_auxv *orig_auxv;
980 const struct ume_auxv *cauxv;
981 unsigned stringsize; /* total size of strings in bytes */
982 unsigned auxsize; /* total size of auxv in bytes */
983 int argc; /* total argc */
984 int envc; /* total number of env vars */
985 unsigned stacksize; /* total client stack size */
986 addr_t cl_esp; /* client stack base (initial esp) */
987
988 /* use our own auxv as a prototype */
989 orig_auxv = find_auxv(ume_exec_esp);
990
991 /* ==================== compute sizes ==================== */
992
993 /* first of all, work out how big the client stack will be */
994 stringsize = 0;
995
996 /* paste on the extra args if the loader needs them (ie, the #!
997 interpreter and its argument) */
998 argc = 0;
nethercoted6a56872004-07-26 15:32:47 +0000999 if (info->interp_name != NULL) {
nethercote71980f02004-01-24 18:18:54 +00001000 argc++;
nethercoted6a56872004-07-26 15:32:47 +00001001 stringsize += strlen(info->interp_name) + 1;
nethercote71980f02004-01-24 18:18:54 +00001002 }
nethercoted6a56872004-07-26 15:32:47 +00001003 if (info->interp_args != NULL) {
nethercote71980f02004-01-24 18:18:54 +00001004 argc++;
nethercoted6a56872004-07-26 15:32:47 +00001005 stringsize += strlen(info->interp_args) + 1;
nethercote71980f02004-01-24 18:18:54 +00001006 }
1007
1008 /* now scan the args we're given... */
1009 for (cpp = orig_argv; *cpp; cpp++) {
1010 argc++;
1011 stringsize += strlen(*cpp) + 1;
1012 }
1013
1014 /* ...and the environment */
1015 envc = 0;
1016 for (cpp = orig_envp; cpp && *cpp; cpp++) {
1017 envc++;
1018 stringsize += strlen(*cpp) + 1;
1019 }
1020
1021 /* now, how big is the auxv? */
1022 auxsize = sizeof(*auxv); /* there's always at least one entry: AT_NULL */
1023 for (cauxv = orig_auxv; cauxv->a_type != AT_NULL; cauxv++) {
1024 if (cauxv->a_type == AT_PLATFORM)
1025 stringsize += strlen(cauxv->u.a_ptr) + 1;
1026 auxsize += sizeof(*cauxv);
1027 }
1028
1029 /* OK, now we know how big the client stack is */
1030 stacksize =
1031 sizeof(int) + /* argc */
1032 sizeof(char **)*argc + /* argv */
1033 sizeof(char **) + /* terminal NULL */
1034 sizeof(char **)*envc + /* envp */
1035 sizeof(char **) + /* terminal NULL */
1036 auxsize + /* auxv */
1037 ROUNDUP(stringsize, sizeof(int)) +/* strings (aligned) */
1038 VKI_BYTES_PER_PAGE; /* page for trampoline code */
1039
nethercotef84f6952004-07-15 14:58:33 +00001040 // decide where stack goes!
1041 VG_(clstk_end) = VG_(client_end);
1042
1043 VG_(client_trampoline_code) = VG_(clstk_end) - VKI_BYTES_PER_PAGE;
1044
nethercote71980f02004-01-24 18:18:54 +00001045 /* cl_esp is the client's stack pointer */
nethercotef84f6952004-07-15 14:58:33 +00001046 cl_esp = VG_(clstk_end) - stacksize;
nethercote71980f02004-01-24 18:18:54 +00001047 cl_esp = ROUNDDN(cl_esp, 16); /* make stack 16 byte aligned */
1048
nethercote71980f02004-01-24 18:18:54 +00001049 /* base of the string table (aligned) */
1050 stringbase = strtab = (char *)(VG_(client_trampoline_code) - ROUNDUP(stringsize, sizeof(int)));
1051
1052 VG_(clstk_base) = PGROUNDDN(cl_esp);
nethercote71980f02004-01-24 18:18:54 +00001053
nethercote5ee67ca2004-06-22 14:00:09 +00001054 if (0)
1055 printf("stringsize=%d auxsize=%d stacksize=%d\n"
1056 "clstk_base %x\n"
1057 "clstk_end %x\n",
1058 stringsize, auxsize, stacksize, VG_(clstk_base), VG_(clstk_end));
1059
1060
nethercote71980f02004-01-24 18:18:54 +00001061 /* ==================== allocate space ==================== */
1062
1063 /* allocate a stack - mmap enough space for the stack */
nethercotef84f6952004-07-15 14:58:33 +00001064 res = mmap((void *)PGROUNDDN(cl_esp), VG_(clstk_end) - PGROUNDDN(cl_esp),
nethercotee567e702004-07-10 17:49:17 +00001065 PROT_READ | PROT_WRITE | PROT_EXEC,
1066 MAP_PRIVATE | MAP_ANON | MAP_FIXED, -1, 0);
1067 vg_assert((void*)-1 != res);
nethercote71980f02004-01-24 18:18:54 +00001068
1069 /* ==================== copy client stack ==================== */
1070
1071 ptr = (addr_t *)cl_esp;
1072
1073 /* --- argc --- */
1074 *ptr++ = argc; /* client argc */
1075
1076 /* --- argv --- */
nethercoted6a56872004-07-26 15:32:47 +00001077 if (info->interp_name) {
1078 *ptr++ = (addr_t)copy_str(&strtab, info->interp_name);
1079 free(info->interp_name);
nethercote71980f02004-01-24 18:18:54 +00001080 }
nethercoted6a56872004-07-26 15:32:47 +00001081 if (info->interp_args) {
1082 *ptr++ = (addr_t)copy_str(&strtab, info->interp_args);
1083 free(info->interp_args);
nethercote71980f02004-01-24 18:18:54 +00001084 }
1085 for (cpp = orig_argv; *cpp; ptr++, cpp++) {
1086 *ptr = (addr_t)copy_str(&strtab, *cpp);
1087 }
1088 *ptr++ = 0;
1089
1090 /* --- envp --- */
1091 VG_(client_envp) = (Char **)ptr;
1092 for (cpp = orig_envp; cpp && *cpp; ptr++, cpp++)
1093 *ptr = (addr_t)copy_str(&strtab, *cpp);
1094 *ptr++ = 0;
1095
1096 /* --- auxv --- */
1097 auxv = (struct ume_auxv *)ptr;
1098 *client_auxv = (UInt *)auxv;
1099
1100 for (; orig_auxv->a_type != AT_NULL; auxv++, orig_auxv++) {
1101 /* copy the entry... */
1102 *auxv = *orig_auxv;
1103
1104 /* ...and fix up the copy */
1105 switch(auxv->a_type) {
1106 case AT_PHDR:
1107 if (info->phdr == 0)
1108 auxv->a_type = AT_IGNORE;
1109 else
1110 auxv->u.a_val = info->phdr;
1111 break;
1112
1113 case AT_PHNUM:
1114 if (info->phdr == 0)
1115 auxv->a_type = AT_IGNORE;
1116 else
1117 auxv->u.a_val = info->phnum;
1118 break;
1119
1120 case AT_BASE:
1121 if (info->interp_base == 0)
1122 auxv->a_type = AT_IGNORE;
1123 else
1124 auxv->u.a_val = info->interp_base;
1125 break;
1126
1127 case AT_PLATFORM: /* points to a platform description string */
1128 auxv->u.a_ptr = copy_str(&strtab, orig_auxv->u.a_ptr);
1129 break;
1130
1131 case AT_ENTRY:
1132 auxv->u.a_val = info->entry;
1133 break;
1134
1135 case AT_IGNORE:
1136 case AT_EXECFD:
1137 case AT_PHENT:
1138 case AT_PAGESZ:
1139 case AT_FLAGS:
1140 case AT_NOTELF:
1141 case AT_UID:
1142 case AT_EUID:
1143 case AT_GID:
1144 case AT_EGID:
1145 case AT_CLKTCK:
1146 case AT_HWCAP:
1147 case AT_FPUCW:
1148 case AT_DCACHEBSIZE:
1149 case AT_ICACHEBSIZE:
1150 case AT_UCACHEBSIZE:
1151 /* All these are pointerless, so we don't need to do anything
1152 about them. */
1153 break;
1154
1155 case AT_SECURE:
1156 /* If this is 1, then it means that this program is running
1157 suid, and therefore the dynamic linker should be careful
1158 about LD_PRELOAD, etc. However, since stage1 (the thing
1159 the kernel actually execve's) should never be SUID, and we
1160 need LD_PRELOAD/LD_LIBRARY_PATH to work for the client, we
1161 set AT_SECURE to 0. */
1162 auxv->u.a_val = 0;
1163 break;
1164
1165 case AT_SYSINFO:
1166 /* Leave this unmolested for now, but we'll update it later
1167 when we set up the client trampoline code page */
1168 break;
1169
1170 case AT_SYSINFO_EHDR:
1171 /* Trash this, because we don't reproduce it */
1172 auxv->a_type = AT_IGNORE;
1173 break;
1174
1175 default:
1176 /* stomp out anything we don't know about */
1177 if (0)
1178 printf("stomping auxv entry %d\n", auxv->a_type);
1179 auxv->a_type = AT_IGNORE;
1180 break;
1181
1182 }
1183 }
1184 *auxv = *orig_auxv;
1185 vg_assert(auxv->a_type == AT_NULL);
1186
nethercotef84f6952004-07-15 14:58:33 +00001187 /* --- trampoline page --- */
1188 VG_(memcpy)( (void *)VG_(client_trampoline_code),
1189 &VG_(trampoline_code_start), VG_(trampoline_code_length) );
1190
nethercote71980f02004-01-24 18:18:54 +00001191 vg_assert((strtab-stringbase) == stringsize);
1192
nethercote5ee67ca2004-06-22 14:00:09 +00001193 /* We know the initial ESP is pointing at argc/argv */
1194 VG_(client_argc) = *(Int*)cl_esp;
1195 VG_(client_argv) = (Char**)(cl_esp + sizeof(Int));
1196
nethercote71980f02004-01-24 18:18:54 +00001197 return cl_esp;
1198}
1199
1200/*====================================================================*/
1201/*=== Find executable ===*/
1202/*====================================================================*/
1203
thughes4ad52d02004-06-27 17:37:21 +00001204static const char* executable_name;
1205
1206static Bool match_executable(const char *entry) {
1207 char buf[strlen(entry) + strlen(executable_name) + 2];
1208
1209 /* empty PATH element means . */
1210 if (*entry == '\0')
1211 entry = ".";
1212
1213 snprintf(buf, sizeof(buf), "%s/%s", entry, executable_name);
1214
1215 if (access(buf, R_OK|X_OK) == 0) {
1216 executable_name = strdup(buf);
1217 vg_assert(NULL != executable_name);
1218 return True;
1219 }
1220 return False;
1221}
1222
nethercote71980f02004-01-24 18:18:54 +00001223static const char* find_executable(const char* exec)
1224{
1225 vg_assert(NULL != exec);
thughes4ad52d02004-06-27 17:37:21 +00001226 executable_name = exec;
1227 if (strchr(executable_name, '/') == NULL) {
nethercote71980f02004-01-24 18:18:54 +00001228 /* no '/' - we need to search the path */
1229 char *path = getenv("PATH");
thughes4ad52d02004-06-27 17:37:21 +00001230 scan_colsep(path, match_executable);
nethercote71980f02004-01-24 18:18:54 +00001231 }
thughes4ad52d02004-06-27 17:37:21 +00001232 return executable_name;
nethercote71980f02004-01-24 18:18:54 +00001233}
1234
1235
1236/*====================================================================*/
1237/*=== Loading tools ===*/
1238/*====================================================================*/
1239
1240static void list_tools(void)
1241{
1242 DIR *dir = opendir(VG_(libdir));
1243 struct dirent *de;
1244 int first = 1;
1245
1246 if (dir == NULL) {
1247 fprintf(stderr, "Can't open %s: %s (installation problem?)\n",
nethercotef4928da2004-06-15 10:54:40 +00001248 VG_(libdir), strerror(errno));
nethercote71980f02004-01-24 18:18:54 +00001249 return;
1250 }
1251
nethercotef4928da2004-06-15 10:54:40 +00001252 while ((de = readdir(dir)) != NULL) {
nethercote71980f02004-01-24 18:18:54 +00001253 int len = strlen(de->d_name);
1254
1255 /* look for vgskin_TOOL.so names */
1256 if (len > (7+1+3) && /* "vgskin_" + at least 1-char toolname + ".so" */
nethercotef4928da2004-06-15 10:54:40 +00001257 strncmp(de->d_name, "vgskin_", 7) == 0 &&
1258 VG_STREQ(de->d_name + len - 3, ".so")) {
1259 if (first) {
1260 fprintf(stderr, "Available tools:\n");
1261 first = 0;
1262 }
1263 de->d_name[len-3] = '\0';
1264 fprintf(stderr, "\t%s\n", de->d_name+7);
nethercote71980f02004-01-24 18:18:54 +00001265 }
1266 }
1267
1268 closedir(dir);
1269
1270 if (first)
nethercotef4928da2004-06-15 10:54:40 +00001271 fprintf(stderr, "No tools available in \"%s\" (installation problem?)\n",
1272 VG_(libdir));
nethercote71980f02004-01-24 18:18:54 +00001273}
1274
1275
1276/* Find and load a tool, and check it looks ok. Also looks to see if there's
1277 * a matching vgpreload_*.so file, and returns its name in *preloadpath. */
1278static void load_tool( const char *toolname, void** handle_out,
1279 ToolInfo** toolinfo_out, char **preloadpath_out )
1280{
1281 Bool ok;
1282 int len = strlen(VG_(libdir)) + strlen(toolname)*2 + 16;
1283 char buf[len];
1284 void* handle;
1285 ToolInfo* toolinfo;
1286 char* preloadpath = NULL;
1287 Int* vg_malloc_redzonep;
1288
1289 // XXX: allowing full paths for --tool option -- does it make sense?
1290 // Doesn't allow for vgpreload_<tool>.so.
1291
1292 if (strchr(toolname, '/') != 0) {
1293 /* toolname contains '/', and so must be a pathname */
1294 handle = dlopen(toolname, RTLD_NOW);
1295 } else {
1296 /* just try in the libdir */
1297 snprintf(buf, len, "%s/vgskin_%s.so", VG_(libdir), toolname);
1298 handle = dlopen(buf, RTLD_NOW);
1299
1300 if (handle != NULL) {
1301 snprintf(buf, len, "%s/vgpreload_%s.so", VG_(libdir), toolname);
1302 if (access(buf, R_OK) == 0) {
1303 preloadpath = strdup(buf);
1304 vg_assert(NULL != preloadpath);
1305 }
1306 }
1307 }
1308
1309 ok = (NULL != handle);
1310 if (!ok) {
1311 fprintf(stderr, "Can't open tool \"%s\": %s\n", toolname, dlerror());
1312 goto bad_load;
1313 }
1314
1315 toolinfo = dlsym(handle, "vgSkin_tool_info");
1316 ok = (NULL != toolinfo);
1317 if (!ok) {
1318 fprintf(stderr, "Tool \"%s\" doesn't define SK_(tool_info) - "
1319 "add VG_DETERMINE_INTERFACE_VERSION?\n", toolname);
1320 goto bad_load;
1321 }
1322
1323 ok = (toolinfo->sizeof_ToolInfo == sizeof(*toolinfo) &&
1324 toolinfo->interface_major_version == VG_CORE_INTERFACE_MAJOR_VERSION &&
1325 toolinfo->sk_pre_clo_init != NULL);
1326 if (!ok) {
1327 fprintf(stderr, "Error:\n"
1328 " Tool and core interface versions do not match.\n"
1329 " Interface version used by core is: %d.%d (size %d)\n"
1330 " Interface version used by tool is: %d.%d (size %d)\n"
1331 " The major version numbers must match.\n",
1332 VG_CORE_INTERFACE_MAJOR_VERSION,
1333 VG_CORE_INTERFACE_MINOR_VERSION,
1334 sizeof(*toolinfo),
1335 toolinfo->interface_major_version,
1336 toolinfo->interface_minor_version,
1337 toolinfo->sizeof_ToolInfo);
1338 fprintf(stderr, " You need to at least recompile, and possibly update,\n");
1339 if (VG_CORE_INTERFACE_MAJOR_VERSION > toolinfo->interface_major_version)
nethercote996901a2004-08-03 13:29:09 +00001340 fprintf(stderr, " your tool to work with this version of Valgrind.\n");
nethercote71980f02004-01-24 18:18:54 +00001341 else
nethercote996901a2004-08-03 13:29:09 +00001342 fprintf(stderr, " your version of Valgrind to work with this tool.\n");
nethercote71980f02004-01-24 18:18:54 +00001343 goto bad_load;
1344 }
1345
1346 // Set redzone size for V's allocator
1347 vg_malloc_redzonep = dlsym(handle, STR(VG_(vg_malloc_redzone_szB)));
1348 if ( NULL != vg_malloc_redzonep ) {
1349 VG_(vg_malloc_redzone_szB) = *vg_malloc_redzonep;
1350 }
1351
1352 vg_assert(NULL != handle && NULL != toolinfo);
1353 *handle_out = handle;
1354 *toolinfo_out = toolinfo;
1355 *preloadpath_out = preloadpath;
1356 return;
1357
1358
1359 bad_load:
1360 if (handle != NULL)
1361 dlclose(handle);
1362
nethercotef4928da2004-06-15 10:54:40 +00001363 fprintf(stderr, "valgrind: couldn't load tool\n");
nethercote71980f02004-01-24 18:18:54 +00001364 list_tools();
1365 exit(127);
1366}
1367
nethercotef4928da2004-06-15 10:54:40 +00001368
1369/*====================================================================*/
1370/*=== Command line errors ===*/
1371/*====================================================================*/
1372
1373static void abort_msg ( void )
1374{
nethercotef8548672004-06-21 12:42:35 +00001375 VG_(clo_log_to) = VgLogTo_Fd;
1376 VG_(clo_log_fd) = 2; /* stderr */
nethercotef4928da2004-06-15 10:54:40 +00001377}
1378
1379void VG_(bad_option) ( Char* opt )
1380{
1381 abort_msg();
1382 VG_(printf)("valgrind: Bad option `%s'; aborting.\n", opt);
1383 VG_(printf)("valgrind: Use --help for more information.\n");
1384 VG_(exit)(1);
1385}
1386
1387static void missing_tool_option ( void )
1388{
1389 abort_msg();
1390 VG_(printf)("valgrind: Missing --tool option\n");
1391 list_tools();
1392 VG_(printf)("valgrind: Use --help for more information.\n");
1393 VG_(exit)(1);
1394}
1395
1396static void missing_prog ( void )
1397{
1398 abort_msg();
1399 VG_(printf)("valgrind: no program specified\n");
1400 VG_(printf)("valgrind: Use --help for more information.\n");
1401 VG_(exit)(1);
1402}
1403
1404static void config_error ( Char* msg )
1405{
1406 abort_msg();
1407 VG_(printf)("valgrind: Startup or configuration error:\n %s\n", msg);
1408 VG_(printf)("valgrind: Unable to start up properly. Giving up.\n");
1409 VG_(exit)(1);
1410}
1411
1412
nethercote71980f02004-01-24 18:18:54 +00001413/*====================================================================*/
1414/*=== Loading the client ===*/
1415/*====================================================================*/
1416
nethercotef4928da2004-06-15 10:54:40 +00001417static void load_client(char* cl_argv[], const char* exec, Int need_help,
nethercote71980f02004-01-24 18:18:54 +00001418 /*out*/struct exeinfo* info, /*out*/Addr* client_eip)
1419{
1420 // If they didn't specify an executable with --exec, and didn't specify
1421 // --help, then use client argv[0] (searching $PATH if necessary).
nethercotef4928da2004-06-15 10:54:40 +00001422 if (NULL == exec && !need_help) {
nethercote71980f02004-01-24 18:18:54 +00001423 if (cl_argv[0] == NULL ||
1424 ( NULL == (exec = find_executable(cl_argv[0])) ) )
1425 {
nethercotef4928da2004-06-15 10:54:40 +00001426 missing_prog();
nethercote71980f02004-01-24 18:18:54 +00001427 }
1428 }
1429
1430 info->map_base = VG_(client_mapbase);
nethercote71980f02004-01-24 18:18:54 +00001431 info->exe_base = VG_(client_base);
1432 info->exe_end = VG_(client_end);
1433 info->argv = cl_argv;
1434
nethercotef4928da2004-06-15 10:54:40 +00001435 if (need_help) {
nethercote71980f02004-01-24 18:18:54 +00001436 VG_(clexecfd) = -1;
nethercoteea147e72004-07-26 15:43:57 +00001437 // Set the minimal number of entries in 'info' to continue.
nethercoted6a56872004-07-26 15:32:47 +00001438 info->interp_name = NULL;
1439 info->interp_args = NULL;
nethercote71980f02004-01-24 18:18:54 +00001440 } else {
1441 Int ret;
1442 VG_(clexecfd) = VG_(open)(exec, O_RDONLY, VKI_S_IRUSR);
1443 ret = do_exec(exec, info);
1444 if (ret != 0) {
nethercoteea147e72004-07-26 15:43:57 +00001445 fprintf(stderr, "valgrind: do_exec(%s) failed: %s\n",
1446 exec, strerror(ret));
nethercote71980f02004-01-24 18:18:54 +00001447 exit(127);
1448 }
1449 }
1450
1451 /* Copy necessary bits of 'info' that were filled in */
1452 *client_eip = info->init_eip;
1453 VG_(brk_base) = VG_(brk_limit) = info->brkbase;
1454}
1455
1456
1457/*====================================================================*/
1458/*=== Command-line: variables, processing ===*/
1459/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +00001460
njn25e49d8e72002-09-23 09:36:25 +00001461/* Define, and set defaults. */
1462Bool VG_(clo_error_limit) = True;
nethercote04d0fbc2004-01-26 16:48:06 +00001463Bool VG_(clo_db_attach) = False;
1464Char* VG_(clo_db_command) = VG_CLO_DEFAULT_DBCOMMAND;
njn43c799e2003-04-08 00:08:52 +00001465Bool VG_(clo_gen_suppressions) = False;
nethercote27fec902004-06-16 21:26:32 +00001466Int VG_(clo_sanity_level) = 1;
njn25e49d8e72002-09-23 09:36:25 +00001467Int VG_(clo_verbosity) = 1;
1468Bool VG_(clo_demangle) = True;
njn25e49d8e72002-09-23 09:36:25 +00001469Bool VG_(clo_trace_children) = False;
sewardj4cf05692002-10-27 20:28:29 +00001470
nethercotee1730692003-11-20 10:38:07 +00001471/* See big comment in vg_include.h for meaning of these three.
1472 fd is initially stdout, for --help, but gets moved to stderr by default
1473 immediately afterwards. */
sewardj4cf05692002-10-27 20:28:29 +00001474VgLogTo VG_(clo_log_to) = VgLogTo_Fd;
nethercotef8548672004-06-21 12:42:35 +00001475Int VG_(clo_log_fd) = 1;
1476Char* VG_(clo_log_name) = NULL;
sewardj4cf05692002-10-27 20:28:29 +00001477
sewardj6024b212003-07-13 10:54:33 +00001478Int VG_(clo_input_fd) = 0; /* stdin */
njn25e49d8e72002-09-23 09:36:25 +00001479Int VG_(clo_n_suppressions) = 0;
sewardjde4a1d02002-03-22 01:27:54 +00001480Char* VG_(clo_suppressions)[VG_CLO_MAX_SFILES];
njn25e49d8e72002-09-23 09:36:25 +00001481Bool VG_(clo_profile) = False;
1482Bool VG_(clo_single_step) = False;
1483Bool VG_(clo_optimise) = True;
1484UChar VG_(clo_trace_codegen) = 0; // 00000000b
1485Bool VG_(clo_trace_syscalls) = False;
1486Bool VG_(clo_trace_signals) = False;
1487Bool VG_(clo_trace_symtab) = False;
njn25e49d8e72002-09-23 09:36:25 +00001488Bool VG_(clo_trace_sched) = False;
1489Int VG_(clo_trace_pthread_level) = 0;
njn25e49d8e72002-09-23 09:36:25 +00001490Int VG_(clo_dump_error) = 0;
1491Int VG_(clo_backtrace_size) = 4;
1492Char* VG_(clo_weird_hacks) = NULL;
sewardj858964b2002-10-05 14:15:43 +00001493Bool VG_(clo_run_libc_freeres) = True;
rjwalshf5f536f2003-11-17 17:45:00 +00001494Bool VG_(clo_track_fds) = False;
sewardj22854b92002-11-30 14:00:47 +00001495Bool VG_(clo_chain_bb) = True;
nethercote77eba602003-11-13 17:35:04 +00001496Bool VG_(clo_show_below_main) = False;
fitzhardinge98abfc72003-12-16 02:05:15 +00001497Bool VG_(clo_pointercheck) = True;
fitzhardinge462f4f92003-12-18 02:10:54 +00001498Bool VG_(clo_branchpred) = False;
sewardj2370f3b2002-11-30 15:01:01 +00001499
jsgf855d93d2003-10-13 22:26:55 +00001500static Bool VG_(clo_wait_for_gdb) = False;
1501
1502/* If we're doing signal routing, poll for signals every 50mS by
1503 default. */
1504Int VG_(clo_signal_polltime) = 50;
1505
1506/* These flags reduce thread wakeup latency on syscall completion and
1507 signal delivery, respectively. The downside is possible unfairness. */
1508Bool VG_(clo_lowlat_syscalls) = False; /* low-latency syscalls */
1509Bool VG_(clo_lowlat_signals) = False; /* low-latency signals */
1510
sewardjde4a1d02002-03-22 01:27:54 +00001511
nethercote6c999f22004-01-31 22:55:15 +00001512void usage ( Bool debug_help )
njn7cf0bd32002-06-08 13:36:03 +00001513{
njn25e49d8e72002-09-23 09:36:25 +00001514 Char* usage1 =
nethercote71980f02004-01-24 18:18:54 +00001515"usage: valgrind --tool=<toolname> [options] prog-and-args\n"
njn25e49d8e72002-09-23 09:36:25 +00001516"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001517" common user options for all Valgrind tools, with defaults in [ ]:\n"
nethercote0d588502004-06-21 13:27:11 +00001518" --tool=<name> use the Valgrind tool named <name>\n"
nethercotea76368b2004-06-16 11:56:29 +00001519" -h --help show this message\n"
nethercote6c999f22004-01-31 22:55:15 +00001520" --help-debug show this message, plus debugging options\n"
njn25e49d8e72002-09-23 09:36:25 +00001521" --version show version\n"
njn25e49d8e72002-09-23 09:36:25 +00001522" -q --quiet run silently; only print error msgs\n"
1523" -v --verbose be more verbose, incl counts of errors\n"
nethercote77eba602003-11-13 17:35:04 +00001524" --trace-children=no|yes Valgrind-ise child processes? [no]\n"
nethercote0d588502004-06-21 13:27:11 +00001525" --track-fds=no|yes track open file descriptors? [no]\n"
nethercote2b0793f2003-12-02 10:41:18 +00001526"\n"
1527" uncommon user options for all Valgrind tools:\n"
nethercote0d588502004-06-21 13:27:11 +00001528" --run-libc-freeres=no|yes free up glibc memory at exit? [yes]\n"
1529" --weird-hacks=hack1,hack2,... recognised hacks: lax-ioctls [none]\n"
1530" --signal-polltime=<time> signal poll period (mS) for older kernels [50]\n"
1531" --lowlat-signals=no|yes improve thread signal wake-up latency [no]\n"
1532" --lowlat-syscalls=no|yes improve thread syscall wake-up latency [no]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001533" --pointercheck=no|yes enforce client address space limits [yes]\n"
njn25e49d8e72002-09-23 09:36:25 +00001534"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001535" user options for Valgrind tools that report errors:\n"
nethercotef8548672004-06-21 12:42:35 +00001536" --log-fd=<number> log messages to file descriptor [2=stderr]\n"
1537" --log-file=<file> log messages to <file>.pid<pid>\n"
1538" --log-socket=ipaddr:port log messages to socket ipaddr:port\n"
nethercote2b0793f2003-12-02 10:41:18 +00001539" --demangle=no|yes automatically demangle C++ names? [yes]\n"
1540" --num-callers=<number> show <num> callers in stack traces [4]\n"
1541" --error-limit=no|yes stop showing new errors if too many? [yes]\n"
1542" --show-below-main=no|yes continue stack traces below main() [no]\n"
1543" --suppressions=<filename> suppress errors described in <filename>\n"
1544" --gen-suppressions=no|yes print suppressions for errors detected [no]\n"
nethercote04d0fbc2004-01-26 16:48:06 +00001545" --db-attach=no|yes start debugger when errors detected? [no]\n"
1546" --db-command=<command> command to start debugger [gdb -nw %%f %%p]\n"
1547" --input-fd=<number> file descriptor for input [0=stdin]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001548"\n";
njn7cf0bd32002-06-08 13:36:03 +00001549
njn25e49d8e72002-09-23 09:36:25 +00001550 Char* usage2 =
1551"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001552" debugging options for all Valgrind tools:\n"
njn25e49d8e72002-09-23 09:36:25 +00001553" --sanity-level=<number> level of sanity checking to do [1]\n"
1554" --single-step=no|yes translate each instr separately? [no]\n"
1555" --optimise=no|yes improve intermediate code? [yes]\n"
nethercote137bc552003-11-14 17:47:54 +00001556" --profile=no|yes profile? (tool must be built for it) [no]\n"
sewardj22854b92002-11-30 14:00:47 +00001557" --chain-bb=no|yes do basic-block chaining? [yes]\n"
fitzhardinge462f4f92003-12-18 02:10:54 +00001558" --branchpred=yes|no generate branch prediction hints [no]\n"
njn25e49d8e72002-09-23 09:36:25 +00001559" --trace-codegen=<XXXXX> show generated code? (X = 0|1) [00000]\n"
1560" --trace-syscalls=no|yes show all system calls? [no]\n"
1561" --trace-signals=no|yes show signal handling details? [no]\n"
1562" --trace-symtab=no|yes show symbol table details? [no]\n"
njn25e49d8e72002-09-23 09:36:25 +00001563" --trace-sched=no|yes show thread scheduler details? [no]\n"
njn3e884182003-04-15 13:03:23 +00001564" --trace-pthread=none|some|all show pthread event details? [none]\n"
jsgf855d93d2003-10-13 22:26:55 +00001565" --wait-for-gdb=yes|no pause on startup to wait for gdb attach\n"
njn25e49d8e72002-09-23 09:36:25 +00001566"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001567" debugging options for Valgrind tools that report errors\n"
1568" --dump-error=<number> show translation for basic block associated\n"
1569" with <number>'th error context [0=show none]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001570"\n";
njn3e884182003-04-15 13:03:23 +00001571
1572 Char* usage3 =
1573"\n"
nethercote71980f02004-01-24 18:18:54 +00001574" Extra options read from ~/.valgrindrc, $VALGRIND_OPTS, ./.valgrindrc\n"
njn25e49d8e72002-09-23 09:36:25 +00001575"\n"
nethercote08fa9a72004-07-16 17:44:00 +00001576" Valgrind is Copyright (C) 2000-2004 Julian Seward et al.\n"
njn25e49d8e72002-09-23 09:36:25 +00001577" and licensed under the GNU General Public License, version 2.\n"
1578" Bug reports, feedback, admiration, abuse, etc, to: %s.\n"
njnd04b7c62002-10-03 14:05:52 +00001579"\n"
nethercote137bc552003-11-14 17:47:54 +00001580" Tools are copyright and licensed by their authors. See each\n"
1581" tool's start-up message for more information.\n"
njn25e49d8e72002-09-23 09:36:25 +00001582"\n";
njn7cf0bd32002-06-08 13:36:03 +00001583
fitzhardinge98abfc72003-12-16 02:05:15 +00001584 VG_(printf)(usage1);
1585 if (VG_(details).name) {
1586 VG_(printf)(" user options for %s:\n", VG_(details).name);
fitzhardinge98abfc72003-12-16 02:05:15 +00001587 if (VG_(needs).command_line_options)
1588 SK_(print_usage)();
1589 else
1590 VG_(printf)(" (none)\n");
1591 }
nethercote6c999f22004-01-31 22:55:15 +00001592 if (debug_help) {
1593 VG_(printf)(usage2);
fitzhardinge98abfc72003-12-16 02:05:15 +00001594
nethercote6c999f22004-01-31 22:55:15 +00001595 if (VG_(details).name) {
1596 VG_(printf)(" debugging options for %s:\n", VG_(details).name);
1597
1598 if (VG_(needs).command_line_options)
1599 SK_(print_debug_usage)();
1600 else
1601 VG_(printf)(" (none)\n");
1602 }
fitzhardinge98abfc72003-12-16 02:05:15 +00001603 }
nethercote421281e2003-11-20 16:20:55 +00001604 VG_(printf)(usage3, VG_BUGS_TO);
nethercotef4928da2004-06-15 10:54:40 +00001605 VG_(exit)(0);
njn7cf0bd32002-06-08 13:36:03 +00001606}
sewardjde4a1d02002-03-22 01:27:54 +00001607
nethercote71980f02004-01-24 18:18:54 +00001608static void pre_process_cmd_line_options
nethercote6c999f22004-01-31 22:55:15 +00001609 ( Int* need_help, const char** tool, const char** exec )
sewardj1c1b1162003-02-23 01:25:51 +00001610{
nethercote71980f02004-01-24 18:18:54 +00001611 UInt i;
sewardjde4a1d02002-03-22 01:27:54 +00001612
nethercote71980f02004-01-24 18:18:54 +00001613 /* parse the options we have (only the options we care about now) */
1614 for (i = 1; i < VG_(vg_argc); i++) {
1615
1616 if (strcmp(VG_(vg_argv)[i], "--version") == 0) {
1617 printf("valgrind-" VERSION "\n");
nethercotef4928da2004-06-15 10:54:40 +00001618 exit(0);
nethercote71980f02004-01-24 18:18:54 +00001619
nethercotea76368b2004-06-16 11:56:29 +00001620 } else if (VG_CLO_STREQ(VG_(vg_argv)[i], "--help") ||
1621 VG_CLO_STREQ(VG_(vg_argv)[i], "-h")) {
nethercote6c999f22004-01-31 22:55:15 +00001622 *need_help = 1;
1623
nethercotef4928da2004-06-15 10:54:40 +00001624 } else if (VG_CLO_STREQ(VG_(vg_argv)[i], "--help-debug")) {
nethercote6c999f22004-01-31 22:55:15 +00001625 *need_help = 2;
nethercote71980f02004-01-24 18:18:54 +00001626
nethercotef4928da2004-06-15 10:54:40 +00001627 } else if (VG_CLO_STREQN(7, VG_(vg_argv)[i], "--tool=") ||
1628 VG_CLO_STREQN(7, VG_(vg_argv)[i], "--skin=")) {
nethercote71980f02004-01-24 18:18:54 +00001629 *tool = &VG_(vg_argv)[i][7];
1630
nethercotef4928da2004-06-15 10:54:40 +00001631 } else if (VG_CLO_STREQN(7, VG_(vg_argv)[i], "--exec=")) {
nethercote71980f02004-01-24 18:18:54 +00001632 *exec = &VG_(vg_argv)[i][7];
1633 }
1634 }
1635
nethercotef4928da2004-06-15 10:54:40 +00001636 /* If no tool specified, can act appropriately without loading tool */
nethercote71980f02004-01-24 18:18:54 +00001637 if (*tool == NULL) {
nethercotef4928da2004-06-15 10:54:40 +00001638 if (0 == *need_help) {
1639 // neither --tool nor --help/--help-debug specified
1640 missing_tool_option();
1641 } else {
1642 // Give help message, without any tool-specific help
1643 usage(/*help-debug?*/2 == *need_help);
1644 }
nethercote71980f02004-01-24 18:18:54 +00001645 }
1646}
1647
nethercote5ee67ca2004-06-22 14:00:09 +00001648static void process_cmd_line_options( UInt* client_auxv, const char* toolname )
nethercote71980f02004-01-24 18:18:54 +00001649{
nethercotef8548672004-06-21 12:42:35 +00001650 Int i, eventually_log_fd;
nethercote71980f02004-01-24 18:18:54 +00001651 Int *auxp;
1652 Int toolname_len = VG_(strlen)(toolname);
sewardjde4a1d02002-03-22 01:27:54 +00001653
nethercotee1730692003-11-20 10:38:07 +00001654 /* log to stderr by default, but usage message goes to stdout */
nethercotef8548672004-06-21 12:42:35 +00001655 eventually_log_fd = 2;
sewardjde4a1d02002-03-22 01:27:54 +00001656
sewardj19d81412002-06-03 01:10:40 +00001657 /* Check for sane path in ./configure --prefix=... */
fitzhardinge98abfc72003-12-16 02:05:15 +00001658 if (VG_LIBDIR[0] != '/')
sewardj19d81412002-06-03 01:10:40 +00001659 config_error("Please use absolute paths in "
1660 "./configure --prefix=... or --libdir=...");
sewardj38170912002-05-10 21:07:22 +00001661
nethercote71980f02004-01-24 18:18:54 +00001662 for (auxp = client_auxv; auxp[0] != VKI_AT_NULL; auxp += 2) {
fitzhardinge98abfc72003-12-16 02:05:15 +00001663 switch(auxp[0]) {
1664 case VKI_AT_SYSINFO:
fitzhardinge92360792003-12-24 10:11:11 +00001665 auxp[1] = (Int)(VG_(client_trampoline_code) + VG_(tramp_syscall_offset));
fitzhardinge98abfc72003-12-16 02:05:15 +00001666 break;
sewardjde4a1d02002-03-22 01:27:54 +00001667 }
fitzhardinge98abfc72003-12-16 02:05:15 +00001668 }
sewardjde4a1d02002-03-22 01:27:54 +00001669
nethercote71980f02004-01-24 18:18:54 +00001670 for (i = 1; i < VG_(vg_argc); i++) {
1671
1672 Char* arg = VG_(vg_argv)[i];
thughes3bfd5a02004-07-18 08:05:44 +00001673 Char* colon = arg;
nethercote71980f02004-01-24 18:18:54 +00001674
thughes3bfd5a02004-07-18 08:05:44 +00001675 /* Look for a colon in the switch name */
1676 while (*colon && *colon != ':' && *colon != '=')
1677 colon++;
nethercote71980f02004-01-24 18:18:54 +00001678
1679 /* Look for matching "--toolname:foo" */
thughes3bfd5a02004-07-18 08:05:44 +00001680 if (*colon == ':') {
nethercote71980f02004-01-24 18:18:54 +00001681 if (VG_CLO_STREQN(2, arg, "--") &&
1682 VG_CLO_STREQN(toolname_len, arg+2, toolname) &&
1683 VG_CLO_STREQN(1, arg+2+toolname_len, ":"))
1684 {
1685 // prefix matches, convert "--toolname:foo" to "--foo"
1686 if (0)
1687 VG_(printf)("tool-specific arg: %s\n", arg);
1688 arg += toolname_len + 1;
1689 arg[0] = '-';
1690 arg[1] = '-';
1691
1692 } else {
1693 // prefix doesn't match, skip to next arg
1694 continue;
1695 }
1696 }
1697
fitzhardinge98abfc72003-12-16 02:05:15 +00001698 /* Ignore these options - they've already been handled */
nethercote71980f02004-01-24 18:18:54 +00001699 if (VG_CLO_STREQN(7, arg, "--tool=") ||
1700 VG_CLO_STREQN(7, arg, "--skin="))
fitzhardinge98abfc72003-12-16 02:05:15 +00001701 continue;
nethercote71980f02004-01-24 18:18:54 +00001702 if (VG_CLO_STREQN(7, arg, "--exec="))
fitzhardinge98abfc72003-12-16 02:05:15 +00001703 continue;
1704
nethercote71980f02004-01-24 18:18:54 +00001705 if ( VG_CLO_STREQ(arg, "--"))
fitzhardinge98abfc72003-12-16 02:05:15 +00001706 continue;
nethercote27fec902004-06-16 21:26:32 +00001707
nethercote71980f02004-01-24 18:18:54 +00001708 else if (VG_CLO_STREQ(arg, "-v") ||
1709 VG_CLO_STREQ(arg, "--verbose"))
sewardjde4a1d02002-03-22 01:27:54 +00001710 VG_(clo_verbosity)++;
nethercote27fec902004-06-16 21:26:32 +00001711
nethercote71980f02004-01-24 18:18:54 +00001712 else if (VG_CLO_STREQ(arg, "-q") ||
1713 VG_CLO_STREQ(arg, "--quiet"))
sewardjde4a1d02002-03-22 01:27:54 +00001714 VG_(clo_verbosity)--;
1715
nethercote27fec902004-06-16 21:26:32 +00001716 else VG_BOOL_CLO("--branchpred", VG_(clo_branchpred))
1717 else VG_BOOL_CLO("--chain-bb", VG_(clo_chain_bb))
1718 else VG_BOOL_CLO("--db-attach", VG_(clo_db_attach))
1719 else VG_BOOL_CLO("--demangle", VG_(clo_demangle))
1720 else VG_BOOL_CLO("--error-limit", VG_(clo_error_limit))
1721 else VG_BOOL_CLO("--gen-suppressions", VG_(clo_gen_suppressions))
1722 else VG_BOOL_CLO("--lowlat-signals", VG_(clo_lowlat_signals))
1723 else VG_BOOL_CLO("--lowlat-syscalls", VG_(clo_lowlat_syscalls))
1724 else VG_BOOL_CLO("--optimise", VG_(clo_optimise))
1725 else VG_BOOL_CLO("--pointercheck", VG_(clo_pointercheck))
1726 else VG_BOOL_CLO("--profile", VG_(clo_profile))
1727 else VG_BOOL_CLO("--run-libc-freeres", VG_(clo_run_libc_freeres))
1728 else VG_BOOL_CLO("--show-below-main", VG_(clo_show_below_main))
1729 else VG_BOOL_CLO("--single-step", VG_(clo_single_step))
1730 else VG_BOOL_CLO("--track-fds", VG_(clo_track_fds))
1731 else VG_BOOL_CLO("--trace-children", VG_(clo_trace_children))
1732 else VG_BOOL_CLO("--trace-sched", VG_(clo_trace_sched))
1733 else VG_BOOL_CLO("--trace-signals", VG_(clo_trace_signals))
1734 else VG_BOOL_CLO("--trace-symtab", VG_(clo_trace_symtab))
1735 else VG_BOOL_CLO("--trace-syscalls", VG_(clo_trace_syscalls))
1736 else VG_BOOL_CLO("--wait-for-gdb", VG_(clo_wait_for_gdb))
sewardj72f98ff2002-06-13 17:23:38 +00001737
nethercote27fec902004-06-16 21:26:32 +00001738 else VG_STR_CLO ("--db-command", VG_(clo_db_command))
1739 else VG_STR_CLO ("--weird-hacks", VG_(clo_weird_hacks))
sewardjde4a1d02002-03-22 01:27:54 +00001740
nethercote27fec902004-06-16 21:26:32 +00001741 else VG_NUM_CLO ("--dump-error", VG_(clo_dump_error))
1742 else VG_NUM_CLO ("--input-fd", VG_(clo_input_fd))
1743 else VG_NUM_CLO ("--sanity-level", VG_(clo_sanity_level))
1744 else VG_NUM_CLO ("--signal­polltime", VG_(clo_signal_polltime))
1745 else VG_BNUM_CLO("--num-callers", VG_(clo_backtrace_size), 1,
1746 VG_DEEPEST_BACKTRACE)
sewardjde4a1d02002-03-22 01:27:54 +00001747
nethercotef8548672004-06-21 12:42:35 +00001748 // for backwards compatibility, replaced by --log-fd
nethercote71980f02004-01-24 18:18:54 +00001749 else if (VG_CLO_STREQN(13, arg, "--logfile-fd=")) {
nethercotef8548672004-06-21 12:42:35 +00001750 VG_(clo_log_to) = VgLogTo_Fd;
1751 VG_(clo_log_name) = NULL;
1752 eventually_log_fd = (Int)VG_(atoll)(&arg[13]);
1753 }
1754 else if (VG_CLO_STREQN(9, arg, "--log-fd=")) {
1755 VG_(clo_log_to) = VgLogTo_Fd;
1756 VG_(clo_log_name) = NULL;
1757 eventually_log_fd = (Int)VG_(atoll)(&arg[9]);
sewardj4cf05692002-10-27 20:28:29 +00001758 }
1759
nethercotef8548672004-06-21 12:42:35 +00001760 // for backwards compatibility, replaced by --log-file
nethercote71980f02004-01-24 18:18:54 +00001761 else if (VG_CLO_STREQN(10, arg, "--logfile=")) {
nethercotef8548672004-06-21 12:42:35 +00001762 VG_(clo_log_to) = VgLogTo_File;
1763 VG_(clo_log_name) = &arg[10];
1764 }
1765 else if (VG_CLO_STREQN(11, arg, "--log-file=")) {
1766 VG_(clo_log_to) = VgLogTo_File;
1767 VG_(clo_log_name) = &arg[11];
sewardj4cf05692002-10-27 20:28:29 +00001768 }
sewardjde4a1d02002-03-22 01:27:54 +00001769
nethercotef8548672004-06-21 12:42:35 +00001770 // for backwards compatibility, replaced by --log-socket
nethercote71980f02004-01-24 18:18:54 +00001771 else if (VG_CLO_STREQN(12, arg, "--logsocket=")) {
nethercotef8548672004-06-21 12:42:35 +00001772 VG_(clo_log_to) = VgLogTo_Socket;
1773 VG_(clo_log_name) = &arg[12];
1774 }
1775 else if (VG_CLO_STREQN(13, arg, "--log-socket=")) {
1776 VG_(clo_log_to) = VgLogTo_Socket;
1777 VG_(clo_log_name) = &arg[13];
sewardj73cf3bc2002-11-03 03:20:15 +00001778 }
1779
nethercote71980f02004-01-24 18:18:54 +00001780 else if (VG_CLO_STREQN(15, arg, "--suppressions=")) {
sewardjde4a1d02002-03-22 01:27:54 +00001781 if (VG_(clo_n_suppressions) >= VG_CLO_MAX_SFILES) {
njn25e49d8e72002-09-23 09:36:25 +00001782 VG_(message)(Vg_UserMsg, "Too many suppression files specified.");
sewardjde4a1d02002-03-22 01:27:54 +00001783 VG_(message)(Vg_UserMsg,
1784 "Increase VG_CLO_MAX_SFILES and recompile.");
nethercote71980f02004-01-24 18:18:54 +00001785 VG_(bad_option)(arg);
sewardjde4a1d02002-03-22 01:27:54 +00001786 }
nethercote71980f02004-01-24 18:18:54 +00001787 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = &arg[15];
sewardjde4a1d02002-03-22 01:27:54 +00001788 VG_(clo_n_suppressions)++;
1789 }
sewardjde4a1d02002-03-22 01:27:54 +00001790
njn25e49d8e72002-09-23 09:36:25 +00001791 /* "vwxyz" --> 000zyxwv (binary) */
nethercote71980f02004-01-24 18:18:54 +00001792 else if (VG_CLO_STREQN(16, arg, "--trace-codegen=")) {
njn25e49d8e72002-09-23 09:36:25 +00001793 Int j;
nethercote71980f02004-01-24 18:18:54 +00001794 char* opt = & arg[16];
njn25e49d8e72002-09-23 09:36:25 +00001795
1796 if (5 != VG_(strlen)(opt)) {
1797 VG_(message)(Vg_UserMsg,
1798 "--trace-codegen argument must have 5 digits");
nethercote71980f02004-01-24 18:18:54 +00001799 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001800 }
1801 for (j = 0; j < 5; j++) {
1802 if ('0' == opt[j]) { /* do nothing */ }
1803 else if ('1' == opt[j]) VG_(clo_trace_codegen) |= (1 << j);
1804 else {
1805 VG_(message)(Vg_UserMsg, "--trace-codegen argument can only "
1806 "contain 0s and 1s");
nethercote71980f02004-01-24 18:18:54 +00001807 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001808 }
1809 }
1810 }
sewardjde4a1d02002-03-22 01:27:54 +00001811
nethercote71980f02004-01-24 18:18:54 +00001812 else if (VG_CLO_STREQ(arg, "--trace-pthread=none"))
sewardj45b4b372002-04-16 22:50:32 +00001813 VG_(clo_trace_pthread_level) = 0;
nethercote71980f02004-01-24 18:18:54 +00001814 else if (VG_CLO_STREQ(arg, "--trace-pthread=some"))
sewardj45b4b372002-04-16 22:50:32 +00001815 VG_(clo_trace_pthread_level) = 1;
nethercote71980f02004-01-24 18:18:54 +00001816 else if (VG_CLO_STREQ(arg, "--trace-pthread=all"))
sewardj45b4b372002-04-16 22:50:32 +00001817 VG_(clo_trace_pthread_level) = 2;
sewardj8937c812002-04-12 20:12:20 +00001818
nethercote71980f02004-01-24 18:18:54 +00001819 else if ( ! VG_(needs).command_line_options
1820 || ! SK_(process_cmd_line_option)(arg) ) {
nethercotef4928da2004-06-15 10:54:40 +00001821 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001822 }
sewardjde4a1d02002-03-22 01:27:54 +00001823 }
1824
nethercote27fec902004-06-16 21:26:32 +00001825 // Check various option values
1826
njnf9ebf672003-05-12 21:41:30 +00001827 if (VG_(clo_verbosity) < 0)
sewardjde4a1d02002-03-22 01:27:54 +00001828 VG_(clo_verbosity) = 0;
1829
nethercote04d0fbc2004-01-26 16:48:06 +00001830 if (VG_(clo_db_attach) && VG_(clo_trace_children)) {
sewardjde4a1d02002-03-22 01:27:54 +00001831 VG_(message)(Vg_UserMsg, "");
1832 VG_(message)(Vg_UserMsg,
nethercote04d0fbc2004-01-26 16:48:06 +00001833 "--db-attach=yes conflicts with --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001834 VG_(message)(Vg_UserMsg,
1835 "Please choose one or the other, but not both.");
nethercote04d0fbc2004-01-26 16:48:06 +00001836 VG_(bad_option)("--db-attach=yes and --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001837 }
1838
nethercotef8548672004-06-21 12:42:35 +00001839 /* Set up logging now. After this is done, VG_(clo_log_fd)
sewardj4cf05692002-10-27 20:28:29 +00001840 should be connected to whatever sink has been selected, and we
1841 indiscriminately chuck stuff into it without worrying what the
1842 nature of it is. Oh the wonder of Unix streams. */
1843
nethercotee1730692003-11-20 10:38:07 +00001844 /* So far we should be still attached to stdout, so we can show on
sewardj4cf05692002-10-27 20:28:29 +00001845 the terminal any problems to do with processing command line
1846 opts. */
nethercotef8548672004-06-21 12:42:35 +00001847 vg_assert(VG_(clo_log_fd) == 1 /* stdout */);
sewardj73cf3bc2002-11-03 03:20:15 +00001848 vg_assert(VG_(logging_to_filedes) == True);
sewardj4cf05692002-10-27 20:28:29 +00001849
1850 switch (VG_(clo_log_to)) {
sewardj73cf3bc2002-11-03 03:20:15 +00001851
sewardj4cf05692002-10-27 20:28:29 +00001852 case VgLogTo_Fd:
nethercotef8548672004-06-21 12:42:35 +00001853 vg_assert(VG_(clo_log_name) == NULL);
1854 VG_(clo_log_fd) = eventually_log_fd;
sewardj4cf05692002-10-27 20:28:29 +00001855 break;
sewardj73cf3bc2002-11-03 03:20:15 +00001856
sewardj4cf05692002-10-27 20:28:29 +00001857 case VgLogTo_File: {
1858 Char logfilename[1000];
jsgff3c3f1a2003-10-14 22:13:28 +00001859 Int seq = 0;
1860 Int pid = VG_(getpid)();
1861
nethercotef8548672004-06-21 12:42:35 +00001862 vg_assert(VG_(clo_log_name) != NULL);
1863 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
jsgff3c3f1a2003-10-14 22:13:28 +00001864
nethercote71980f02004-01-24 18:18:54 +00001865 for (;;) {
jsgff3c3f1a2003-10-14 22:13:28 +00001866 if (seq == 0)
1867 VG_(sprintf)(logfilename, "%s.pid%d",
nethercotef8548672004-06-21 12:42:35 +00001868 VG_(clo_log_name), pid );
jsgff3c3f1a2003-10-14 22:13:28 +00001869 else
1870 VG_(sprintf)(logfilename, "%s.pid%d.%d",
nethercotef8548672004-06-21 12:42:35 +00001871 VG_(clo_log_name), pid, seq );
jsgff3c3f1a2003-10-14 22:13:28 +00001872 seq++;
1873
nethercotef8548672004-06-21 12:42:35 +00001874 eventually_log_fd
jsgff3c3f1a2003-10-14 22:13:28 +00001875 = VG_(open)(logfilename,
1876 VKI_O_CREAT|VKI_O_WRONLY|VKI_O_EXCL|VKI_O_TRUNC,
1877 VKI_S_IRUSR|VKI_S_IWUSR);
nethercotef8548672004-06-21 12:42:35 +00001878 if (eventually_log_fd >= 0) {
1879 VG_(clo_log_fd) = VG_(safe_fd)(eventually_log_fd);
jsgff3c3f1a2003-10-14 22:13:28 +00001880 break;
1881 } else {
nethercotef8548672004-06-21 12:42:35 +00001882 if (eventually_log_fd != -VKI_EEXIST) {
jsgff3c3f1a2003-10-14 22:13:28 +00001883 VG_(message)(Vg_UserMsg,
1884 "Can't create/open log file `%s.pid%d'; giving up!",
nethercotef8548672004-06-21 12:42:35 +00001885 VG_(clo_log_name), pid);
jsgff3c3f1a2003-10-14 22:13:28 +00001886 VG_(bad_option)(
nethercotef8548672004-06-21 12:42:35 +00001887 "--log-file=<file> didn't work out for some reason.");
jsgff3c3f1a2003-10-14 22:13:28 +00001888 break;
1889 }
1890 }
1891 }
sewardj4cf05692002-10-27 20:28:29 +00001892 break;
sewardj73cf3bc2002-11-03 03:20:15 +00001893 }
1894
1895 case VgLogTo_Socket: {
nethercotef8548672004-06-21 12:42:35 +00001896 vg_assert(VG_(clo_log_name) != NULL);
1897 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
1898 eventually_log_fd = VG_(connect_via_socket)( VG_(clo_log_name) );
1899 if (eventually_log_fd == -1) {
sewardj73cf3bc2002-11-03 03:20:15 +00001900 VG_(message)(Vg_UserMsg,
nethercotef8548672004-06-21 12:42:35 +00001901 "Invalid --log-socket=ipaddr or --log-socket=ipaddr:port spec");
sewardj73cf3bc2002-11-03 03:20:15 +00001902 VG_(message)(Vg_UserMsg,
nethercotef8548672004-06-21 12:42:35 +00001903 "of `%s'; giving up!", VG_(clo_log_name) );
sewardj73cf3bc2002-11-03 03:20:15 +00001904 VG_(bad_option)(
nethercotef8548672004-06-21 12:42:35 +00001905 "--log-socket=");
sewardj4cf05692002-10-27 20:28:29 +00001906 }
nethercotef8548672004-06-21 12:42:35 +00001907 if (eventually_log_fd == -2) {
sewardj73cf3bc2002-11-03 03:20:15 +00001908 VG_(message)(Vg_UserMsg,
sewardj570f8902002-11-03 11:44:36 +00001909 "valgrind: failed to connect to logging server `%s'.",
nethercotef8548672004-06-21 12:42:35 +00001910 VG_(clo_log_name) );
sewardj570f8902002-11-03 11:44:36 +00001911 VG_(message)(Vg_UserMsg,
1912 "Log messages will sent to stderr instead." );
1913 VG_(message)(Vg_UserMsg,
1914 "" );
1915 /* We don't change anything here. */
1916 } else {
nethercotef8548672004-06-21 12:42:35 +00001917 vg_assert(eventually_log_fd > 0);
1918 VG_(clo_log_fd) = eventually_log_fd;
sewardj570f8902002-11-03 11:44:36 +00001919 VG_(logging_to_filedes) = False;
1920 }
sewardj73cf3bc2002-11-03 03:20:15 +00001921 break;
1922 }
1923
sewardj4cf05692002-10-27 20:28:29 +00001924 }
1925
nethercotef8548672004-06-21 12:42:35 +00001926 /* Move log_fd into the safe range, so it doesn't conflict with any app fds */
thughesad1c9562004-06-26 11:27:52 +00001927 eventually_log_fd = VG_(fcntl)(VG_(clo_log_fd), VKI_F_DUPFD, VG_(fd_hard_limit));
nethercotef8548672004-06-21 12:42:35 +00001928 if (eventually_log_fd < 0)
jsgf855d93d2003-10-13 22:26:55 +00001929 VG_(message)(Vg_UserMsg, "valgrind: failed to move logfile fd into safe range");
1930 else {
nethercotef8548672004-06-21 12:42:35 +00001931 VG_(clo_log_fd) = eventually_log_fd;
1932 VG_(fcntl)(VG_(clo_log_fd), VKI_F_SETFD, VKI_FD_CLOEXEC);
jsgf855d93d2003-10-13 22:26:55 +00001933 }
1934
sewardj4cf05692002-10-27 20:28:29 +00001935 /* Ok, the logging sink is running now. Print a suitable preamble.
1936 If logging to file or a socket, write details of parent PID and
1937 command line args, to help people trying to interpret the
1938 results of a run which encompasses multiple processes. */
sewardjde4a1d02002-03-22 01:27:54 +00001939
sewardj83adf412002-05-01 01:25:45 +00001940 if (VG_(clo_verbosity > 0)) {
nethercote996901a2004-08-03 13:29:09 +00001941 /* Tool details */
njnd04b7c62002-10-03 14:05:52 +00001942 VG_(message)(Vg_UserMsg, "%s%s%s, %s for x86-linux.",
1943 VG_(details).name,
1944 NULL == VG_(details).version ? "" : "-",
1945 NULL == VG_(details).version
1946 ? (Char*)"" : VG_(details).version,
1947 VG_(details).description);
1948 VG_(message)(Vg_UserMsg, "%s", VG_(details).copyright_author);
sewardj3b2736a2002-03-24 12:18:35 +00001949
njnd04b7c62002-10-03 14:05:52 +00001950 /* Core details */
1951 VG_(message)(Vg_UserMsg,
njn3e884182003-04-15 13:03:23 +00001952 "Using valgrind-%s, a program supervision framework for x86-linux.",
sewardj4aa62ba2002-10-05 15:49:27 +00001953 VERSION);
sewardjde4a1d02002-03-22 01:27:54 +00001954 VG_(message)(Vg_UserMsg,
nethercote08fa9a72004-07-16 17:44:00 +00001955 "Copyright (C) 2000-2004, and GNU GPL'd, by Julian Seward et al.");
njnd04b7c62002-10-03 14:05:52 +00001956 }
1957
nethercotec1e395d2003-11-10 13:26:49 +00001958 if (VG_(clo_verbosity) > 0 && VG_(clo_log_to) != VgLogTo_Fd) {
sewardj4cf05692002-10-27 20:28:29 +00001959 VG_(message)(Vg_UserMsg, "");
1960 VG_(message)(Vg_UserMsg,
1961 "My PID = %d, parent PID = %d. Prog and args are:",
1962 VG_(getpid)(), VG_(getppid)() );
1963 for (i = 0; i < VG_(client_argc); i++)
1964 VG_(message)(Vg_UserMsg, " %s", VG_(client_argv)[i]);
1965 }
1966
sewardjde4a1d02002-03-22 01:27:54 +00001967 if (VG_(clo_verbosity) > 1) {
nethercotea70f7352004-04-18 12:08:46 +00001968 Int fd;
sewardj4cf05692002-10-27 20:28:29 +00001969 if (VG_(clo_log_to) != VgLogTo_Fd)
1970 VG_(message)(Vg_UserMsg, "");
fitzhardinge98abfc72003-12-16 02:05:15 +00001971 VG_(message)(Vg_UserMsg, "Valgrind library directory: %s", VG_(libdir));
njn86dc2bc2003-09-09 07:26:21 +00001972 VG_(message)(Vg_UserMsg, "Command line");
1973 for (i = 0; i < VG_(client_argc); i++)
1974 VG_(message)(Vg_UserMsg, " %s", VG_(client_argv)[i]);
1975
sewardjde4a1d02002-03-22 01:27:54 +00001976 VG_(message)(Vg_UserMsg, "Startup, with flags:");
nethercote71980f02004-01-24 18:18:54 +00001977 for (i = 1; i < VG_(vg_argc); i++) {
1978 VG_(message)(Vg_UserMsg, " %s", VG_(vg_argv)[i]);
sewardjde4a1d02002-03-22 01:27:54 +00001979 }
nethercotea70f7352004-04-18 12:08:46 +00001980
1981 VG_(message)(Vg_UserMsg, "Contents of /proc/version:");
1982 fd = VG_(open) ( "/proc/version", VKI_O_RDONLY, 0 );
1983 if (fd < 0) {
1984 VG_(message)(Vg_UserMsg, " can't open /proc/version");
1985 } else {
1986 #define BUF_LEN 256
1987 Char version_buf[BUF_LEN];
1988 Int n = VG_(read) ( fd, version_buf, BUF_LEN );
1989 vg_assert(n <= 256);
1990 if (n > 0) {
1991 version_buf[n-1] = '\0';
1992 VG_(message)(Vg_UserMsg, " %s", version_buf);
1993 } else {
1994 VG_(message)(Vg_UserMsg, " (empty?)");
1995 }
1996 VG_(close)(fd);
1997 #undef BUF_LEN
1998 }
sewardjde4a1d02002-03-22 01:27:54 +00001999 }
2000
fitzhardinge98abfc72003-12-16 02:05:15 +00002001 if (VG_(clo_n_suppressions) < VG_CLO_MAX_SFILES-1 &&
njn25e49d8e72002-09-23 09:36:25 +00002002 (VG_(needs).core_errors || VG_(needs).skin_errors)) {
nethercote996901a2004-08-03 13:29:09 +00002003 /* If there are no suppression files specified and the tool
fitzhardinge98abfc72003-12-16 02:05:15 +00002004 needs one, load the default */
2005 static const Char default_supp[] = "default.supp";
2006 Int len = VG_(strlen)(VG_(libdir)) + 1 + sizeof(default_supp);
2007 Char *buf = VG_(arena_malloc)(VG_AR_CORE, len);
2008 VG_(sprintf)(buf, "%s/%s", VG_(libdir), default_supp);
2009 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = buf;
2010 VG_(clo_n_suppressions)++;
sewardjde4a1d02002-03-22 01:27:54 +00002011 }
sewardj4cf05692002-10-27 20:28:29 +00002012
njn6a230532003-07-21 10:38:23 +00002013 if (VG_(clo_gen_suppressions) &&
2014 !VG_(needs).core_errors && !VG_(needs).skin_errors) {
nethercotef4928da2004-06-15 10:54:40 +00002015 VG_(message)(Vg_UserMsg,
2016 "Can't use --gen-suppressions=yes with this tool,");
2017 VG_(message)(Vg_UserMsg,
2018 "as it doesn't generate errors.");
2019 VG_(bad_option)("--gen-suppressions=yes");
njn6a230532003-07-21 10:38:23 +00002020 }
sewardjde4a1d02002-03-22 01:27:54 +00002021}
2022
sewardjde4a1d02002-03-22 01:27:54 +00002023
nethercote71980f02004-01-24 18:18:54 +00002024/*====================================================================*/
2025/*=== File descriptor setup ===*/
2026/*====================================================================*/
2027
2028static void setup_file_descriptors(void)
2029{
2030 struct vki_rlimit rl;
2031
2032 /* Get the current file descriptor limits. */
2033 if (VG_(getrlimit)(VKI_RLIMIT_NOFILE, &rl) < 0) {
2034 rl.rlim_cur = 1024;
2035 rl.rlim_max = 1024;
2036 }
2037
2038 /* Work out where to move the soft limit to. */
2039 if (rl.rlim_cur + VG_N_RESERVED_FDS <= rl.rlim_max) {
2040 rl.rlim_cur = rl.rlim_cur + VG_N_RESERVED_FDS;
2041 } else {
2042 rl.rlim_cur = rl.rlim_max;
2043 }
2044
2045 /* Reserve some file descriptors for our use. */
thughesad1c9562004-06-26 11:27:52 +00002046 VG_(fd_soft_limit) = rl.rlim_cur - VG_N_RESERVED_FDS;
2047 VG_(fd_hard_limit) = rl.rlim_cur - VG_N_RESERVED_FDS;
nethercote71980f02004-01-24 18:18:54 +00002048
2049 /* Update the soft limit. */
2050 VG_(setrlimit)(VKI_RLIMIT_NOFILE, &rl);
2051
2052 if (VG_(vgexecfd) != -1)
2053 VG_(vgexecfd) = VG_(safe_fd)( VG_(vgexecfd) );
2054 if (VG_(clexecfd) != -1)
2055 VG_(clexecfd) = VG_(safe_fd)( VG_(clexecfd) );
2056}
2057
2058
2059/*====================================================================*/
nethercote1d447092004-02-01 17:29:59 +00002060/*=== baseBlock: definition + setup ===*/
nethercote71980f02004-01-24 18:18:54 +00002061/*====================================================================*/
2062
2063/* The variables storing offsets. */
2064
2065#define INVALID_OFFSET (-1)
2066
2067Int VGOFF_(m_eax) = INVALID_OFFSET;
2068Int VGOFF_(m_ecx) = INVALID_OFFSET;
2069Int VGOFF_(m_edx) = INVALID_OFFSET;
2070Int VGOFF_(m_ebx) = INVALID_OFFSET;
2071Int VGOFF_(m_esp) = INVALID_OFFSET;
2072Int VGOFF_(m_ebp) = INVALID_OFFSET;
2073Int VGOFF_(m_esi) = INVALID_OFFSET;
2074Int VGOFF_(m_edi) = INVALID_OFFSET;
2075Int VGOFF_(m_eflags) = INVALID_OFFSET;
2076Int VGOFF_(m_dflag) = INVALID_OFFSET;
2077Int VGOFF_(m_ssestate) = INVALID_OFFSET;
2078Int VGOFF_(ldt) = INVALID_OFFSET;
2079Int VGOFF_(tls) = INVALID_OFFSET;
2080Int VGOFF_(m_cs) = INVALID_OFFSET;
2081Int VGOFF_(m_ss) = INVALID_OFFSET;
2082Int VGOFF_(m_ds) = INVALID_OFFSET;
2083Int VGOFF_(m_es) = INVALID_OFFSET;
2084Int VGOFF_(m_fs) = INVALID_OFFSET;
2085Int VGOFF_(m_gs) = INVALID_OFFSET;
2086Int VGOFF_(m_eip) = INVALID_OFFSET;
2087Int VGOFF_(spillslots) = INVALID_OFFSET;
2088Int VGOFF_(sh_eax) = INVALID_OFFSET;
2089Int VGOFF_(sh_ecx) = INVALID_OFFSET;
2090Int VGOFF_(sh_edx) = INVALID_OFFSET;
2091Int VGOFF_(sh_ebx) = INVALID_OFFSET;
2092Int VGOFF_(sh_esp) = INVALID_OFFSET;
2093Int VGOFF_(sh_ebp) = INVALID_OFFSET;
2094Int VGOFF_(sh_esi) = INVALID_OFFSET;
2095Int VGOFF_(sh_edi) = INVALID_OFFSET;
2096Int VGOFF_(sh_eflags) = INVALID_OFFSET;
2097
2098Int VGOFF_(helper_idiv_64_32) = INVALID_OFFSET;
2099Int VGOFF_(helper_div_64_32) = INVALID_OFFSET;
2100Int VGOFF_(helper_idiv_32_16) = INVALID_OFFSET;
2101Int VGOFF_(helper_div_32_16) = INVALID_OFFSET;
2102Int VGOFF_(helper_idiv_16_8) = INVALID_OFFSET;
2103Int VGOFF_(helper_div_16_8) = INVALID_OFFSET;
2104Int VGOFF_(helper_imul_32_64) = INVALID_OFFSET;
2105Int VGOFF_(helper_mul_32_64) = INVALID_OFFSET;
2106Int VGOFF_(helper_imul_16_32) = INVALID_OFFSET;
2107Int VGOFF_(helper_mul_16_32) = INVALID_OFFSET;
2108Int VGOFF_(helper_imul_8_16) = INVALID_OFFSET;
2109Int VGOFF_(helper_mul_8_16) = INVALID_OFFSET;
2110Int VGOFF_(helper_CLD) = INVALID_OFFSET;
2111Int VGOFF_(helper_STD) = INVALID_OFFSET;
2112Int VGOFF_(helper_get_dirflag) = INVALID_OFFSET;
2113Int VGOFF_(helper_CLC) = INVALID_OFFSET;
2114Int VGOFF_(helper_STC) = INVALID_OFFSET;
nethercote1018bdd2004-02-11 23:33:29 +00002115Int VGOFF_(helper_CMC) = INVALID_OFFSET;
nethercote71980f02004-01-24 18:18:54 +00002116Int VGOFF_(helper_shldl) = INVALID_OFFSET;
2117Int VGOFF_(helper_shldw) = INVALID_OFFSET;
2118Int VGOFF_(helper_shrdl) = INVALID_OFFSET;
2119Int VGOFF_(helper_shrdw) = INVALID_OFFSET;
2120Int VGOFF_(helper_IN) = INVALID_OFFSET;
2121Int VGOFF_(helper_OUT) = INVALID_OFFSET;
2122Int VGOFF_(helper_RDTSC) = INVALID_OFFSET;
2123Int VGOFF_(helper_CPUID) = INVALID_OFFSET;
2124Int VGOFF_(helper_BSWAP) = INVALID_OFFSET;
nethercote1018bdd2004-02-11 23:33:29 +00002125Int VGOFF_(helper_bsfw) = INVALID_OFFSET;
2126Int VGOFF_(helper_bsfl) = INVALID_OFFSET;
2127Int VGOFF_(helper_bsrw) = INVALID_OFFSET;
2128Int VGOFF_(helper_bsrl) = INVALID_OFFSET;
nethercote71980f02004-01-24 18:18:54 +00002129Int VGOFF_(helper_fstsw_AX) = INVALID_OFFSET;
2130Int VGOFF_(helper_SAHF) = INVALID_OFFSET;
2131Int VGOFF_(helper_LAHF) = INVALID_OFFSET;
2132Int VGOFF_(helper_DAS) = INVALID_OFFSET;
2133Int VGOFF_(helper_DAA) = INVALID_OFFSET;
nethercote1018bdd2004-02-11 23:33:29 +00002134Int VGOFF_(helper_AAS) = INVALID_OFFSET;
2135Int VGOFF_(helper_AAA) = INVALID_OFFSET;
2136Int VGOFF_(helper_AAD) = INVALID_OFFSET;
2137Int VGOFF_(helper_AAM) = INVALID_OFFSET;
nethercote71980f02004-01-24 18:18:54 +00002138Int VGOFF_(helper_cmpxchg8b) = INVALID_OFFSET;
2139Int VGOFF_(helper_undefined_instruction) = INVALID_OFFSET;
2140
2141/* MAX_NONCOMPACT_HELPERS can be increased easily. If MAX_COMPACT_HELPERS is
2142 * increased too much, they won't really be compact any more... */
2143#define MAX_COMPACT_HELPERS 8
2144#define MAX_NONCOMPACT_HELPERS 50
2145
nethercote81f9a6f2004-08-03 15:45:46 +00002146/* For storing tool-specific helpers, determined at runtime. The addr
2147 * and offset arrays together form a (addr, offset) map that allows a
2148 * helper's baseBlock offset to be computed from its address. It's done
2149 * like this so CCALLs can use the function address rather than having to
2150 * muck around with offsets. */
2151static UInt VG_(n_compact_helpers) = 0;
2152static UInt VG_(n_noncompact_helpers) = 0;
2153static Addr VG_(compact_helper_addrs) [MAX_COMPACT_HELPERS];
2154static Int VG_(compact_helper_offsets)[MAX_COMPACT_HELPERS];
2155static Addr VG_(noncompact_helper_addrs) [MAX_NONCOMPACT_HELPERS];
2156static Int VG_(noncompact_helper_offsets)[MAX_NONCOMPACT_HELPERS];
nethercote71980f02004-01-24 18:18:54 +00002157
2158/* This is the actual defn of baseblock. */
2159UInt VG_(baseBlock)[VG_BASEBLOCK_WORDS];
2160
nethercote71980f02004-01-24 18:18:54 +00002161/* Words. */
2162static Int baB_off = 0;
2163
2164
nethercote71980f02004-01-24 18:18:54 +00002165/* Returns the offset, in words. */
2166static Int alloc_BaB ( Int words )
sewardjde4a1d02002-03-22 01:27:54 +00002167{
nethercote71980f02004-01-24 18:18:54 +00002168 Int off = baB_off;
2169 baB_off += words;
2170 if (baB_off >= VG_BASEBLOCK_WORDS)
2171 VG_(core_panic)( "alloc_BaB: baseBlock is too small");
sewardjde4a1d02002-03-22 01:27:54 +00002172
nethercote71980f02004-01-24 18:18:54 +00002173 return off;
sewardjde4a1d02002-03-22 01:27:54 +00002174}
2175
nethercote71980f02004-01-24 18:18:54 +00002176/* Align offset, in *bytes* */
2177static void align_BaB ( UInt align )
njn25e49d8e72002-09-23 09:36:25 +00002178{
nethercote71980f02004-01-24 18:18:54 +00002179 vg_assert(2 == align || 4 == align || 8 == align || 16 == align);
2180 baB_off += (align-1);
2181 baB_off &= ~(align-1);
njn25e49d8e72002-09-23 09:36:25 +00002182}
2183
nethercote71980f02004-01-24 18:18:54 +00002184/* Allocate 1 word in baseBlock and set it to the given value. */
2185static Int alloc_BaB_1_set ( Addr a )
njn25e49d8e72002-09-23 09:36:25 +00002186{
nethercote71980f02004-01-24 18:18:54 +00002187 Int off = alloc_BaB(1);
2188 VG_(baseBlock)[off] = (UInt)a;
2189 return off;
njn25e49d8e72002-09-23 09:36:25 +00002190}
2191
nethercote71980f02004-01-24 18:18:54 +00002192/* Registers a function in compact_helper_addrs; compact_helper_offsets is
2193 filled in later. */
2194void VG_(register_compact_helper)(Addr a)
sewardjde4a1d02002-03-22 01:27:54 +00002195{
nethercote71980f02004-01-24 18:18:54 +00002196 if (MAX_COMPACT_HELPERS <= VG_(n_compact_helpers)) {
2197 VG_(printf)("Can only register %d compact helpers\n",
2198 MAX_COMPACT_HELPERS);
2199 VG_(core_panic)("Too many compact helpers registered");
2200 }
2201 VG_(compact_helper_addrs)[VG_(n_compact_helpers)] = a;
2202 VG_(n_compact_helpers)++;
2203}
2204
2205/* Registers a function in noncompact_helper_addrs; noncompact_helper_offsets
2206 * is filled in later.
2207 */
2208void VG_(register_noncompact_helper)(Addr a)
2209{
2210 if (MAX_NONCOMPACT_HELPERS <= VG_(n_noncompact_helpers)) {
2211 VG_(printf)("Can only register %d non-compact helpers\n",
2212 MAX_NONCOMPACT_HELPERS);
2213 VG_(printf)("Try increasing MAX_NON_COMPACT_HELPERS\n");
2214 VG_(core_panic)("Too many non-compact helpers registered");
2215 }
2216 VG_(noncompact_helper_addrs)[VG_(n_noncompact_helpers)] = a;
2217 VG_(n_noncompact_helpers)++;
2218}
2219
nethercote996901a2004-08-03 13:29:09 +00002220/* Allocate offsets in baseBlock for the tool helpers */
nethercote71980f02004-01-24 18:18:54 +00002221static
2222void assign_helpers_in_baseBlock(UInt n, Int offsets[], Addr addrs[])
2223{
2224 UInt i;
2225 for (i = 0; i < n; i++)
2226 offsets[i] = alloc_BaB_1_set( addrs[i] );
2227}
2228
2229Bool VG_(need_to_handle_esp_assignment)(void)
2230{
2231 return ( VG_(defined_new_mem_stack_4)() ||
2232 VG_(defined_die_mem_stack_4)() ||
2233 VG_(defined_new_mem_stack_8)() ||
2234 VG_(defined_die_mem_stack_8)() ||
2235 VG_(defined_new_mem_stack_12)() ||
2236 VG_(defined_die_mem_stack_12)() ||
2237 VG_(defined_new_mem_stack_16)() ||
2238 VG_(defined_die_mem_stack_16)() ||
2239 VG_(defined_new_mem_stack_32)() ||
2240 VG_(defined_die_mem_stack_32)() ||
2241 VG_(defined_new_mem_stack)() ||
2242 VG_(defined_die_mem_stack)()
2243 );
2244}
2245
2246/* Here we assign actual offsets. It's important to get the most
2247 popular referents within 128 bytes of the start, so we can take
2248 advantage of short addressing modes relative to %ebp. Popularity
2249 of offsets was measured on 22 Feb 02 running a KDE application, and
2250 the slots rearranged accordingly, with a 1.5% reduction in total
2251 size of translations. */
2252static void init_baseBlock ( Addr client_eip, Addr esp_at_startup )
2253{
2254 /* Those with offsets under 128 are carefully chosen. */
2255
2256 /* WORD offsets in this column */
2257 /* 0 */ VGOFF_(m_eax) = alloc_BaB_1_set(0);
2258 /* 1 */ VGOFF_(m_ecx) = alloc_BaB_1_set(0);
2259 /* 2 */ VGOFF_(m_edx) = alloc_BaB_1_set(0);
2260 /* 3 */ VGOFF_(m_ebx) = alloc_BaB_1_set(0);
2261 /* 4 */ VGOFF_(m_esp) = alloc_BaB_1_set(esp_at_startup);
2262 /* 5 */ VGOFF_(m_ebp) = alloc_BaB_1_set(0);
2263 /* 6 */ VGOFF_(m_esi) = alloc_BaB_1_set(0);
2264 /* 7 */ VGOFF_(m_edi) = alloc_BaB_1_set(0);
2265 /* 8 */ VGOFF_(m_eflags) = alloc_BaB_1_set(0);
2266
2267 if (VG_(needs).shadow_regs) {
2268 /* 9 */ VGOFF_(sh_eax) = alloc_BaB_1_set(0);
2269 /* 10 */ VGOFF_(sh_ecx) = alloc_BaB_1_set(0);
2270 /* 11 */ VGOFF_(sh_edx) = alloc_BaB_1_set(0);
2271 /* 12 */ VGOFF_(sh_ebx) = alloc_BaB_1_set(0);
2272 /* 13 */ VGOFF_(sh_esp) = alloc_BaB_1_set(0);
2273 /* 14 */ VGOFF_(sh_ebp) = alloc_BaB_1_set(0);
2274 /* 15 */ VGOFF_(sh_esi) = alloc_BaB_1_set(0);
2275 /* 16 */ VGOFF_(sh_edi) = alloc_BaB_1_set(0);
2276 /* 17 */ VGOFF_(sh_eflags) = alloc_BaB_1_set(0);
2277 VG_TRACK( post_regs_write_init );
2278 }
2279
2280 /* 9,10,11 or 18,19,20... depends on number whether shadow regs are used
2281 * and on compact helpers registered */
2282
2283 /* Make these most-frequently-called specialised ones compact, if they
2284 are used. */
2285 if (VG_(defined_new_mem_stack_4)())
2286 VG_(register_compact_helper)( (Addr) VG_(tool_interface).track_new_mem_stack_4);
2287
2288 if (VG_(defined_die_mem_stack_4)())
2289 VG_(register_compact_helper)( (Addr) VG_(tool_interface).track_die_mem_stack_4);
2290
2291 /* (9 or 18) + n_compact_helpers */
2292 /* Allocate slots for compact helpers */
2293 assign_helpers_in_baseBlock(VG_(n_compact_helpers),
2294 VG_(compact_helper_offsets),
2295 VG_(compact_helper_addrs));
2296
2297 /* (9/10 or 18/19) + n_compact_helpers */
2298 VGOFF_(m_eip) = alloc_BaB_1_set(client_eip);
2299
2300 /* There are currently 24 spill slots */
2301 /* (11+/20+ .. 32+/43+) + n_compact_helpers. This can overlap the magic
2302 * boundary at >= 32 words, but most spills are to low numbered spill
2303 * slots, so the ones above the boundary don't see much action. */
2304 VGOFF_(spillslots) = alloc_BaB(VG_MAX_SPILLSLOTS);
2305
2306 /* I gave up counting at this point. Since they're above the
2307 short-amode-boundary, there's no point. */
2308
2309 VGOFF_(m_dflag) = alloc_BaB_1_set(1); // 1 == forward D-flag
2310
2311 /* The FPU/SSE state. This _must_ be 16-byte aligned. Initial
2312 state doesn't matter much, as long as it's not totally borked. */
2313 align_BaB(16);
2314 VGOFF_(m_ssestate) = alloc_BaB(VG_SIZE_OF_SSESTATE_W);
2315 vg_assert(
2316 0 == ( ((UInt)(& VG_(baseBlock)[VGOFF_(m_ssestate)])) % 16 )
sewardj22854b92002-11-30 14:00:47 +00002317 );
2318
fitzhardingec2dbbac2004-01-23 23:09:01 +00002319 /* I assume that if we have SSE2 we also have SSE */
2320 VG_(have_ssestate) =
2321 VG_(cpu_has_feature)(VG_X86_FEAT_FXSR) &&
2322 VG_(cpu_has_feature)(VG_X86_FEAT_SSE);
2323
fitzhardinge98abfc72003-12-16 02:05:15 +00002324 /* set up an initial FPU state (doesn't really matter what it is,
2325 so long as it's somewhat valid) */
2326 if (!VG_(have_ssestate))
nethercote71980f02004-01-24 18:18:54 +00002327 asm volatile("fwait; fnsave %0; fwait; frstor %0; fwait"
2328 :
2329 : "m" (VG_(baseBlock)[VGOFF_(m_ssestate)])
2330 : "cc", "memory");
fitzhardinge98abfc72003-12-16 02:05:15 +00002331 else
nethercote71980f02004-01-24 18:18:54 +00002332 asm volatile("fwait; fxsave %0; fwait; andl $0xffbf, %1;"
2333 "fxrstor %0; fwait"
2334 :
2335 : "m" (VG_(baseBlock)[VGOFF_(m_ssestate)]),
2336 "m" (VG_(baseBlock)[VGOFF_(m_ssestate)+(24/4)])
2337 : "cc", "memory");
fitzhardinge98abfc72003-12-16 02:05:15 +00002338
njn0c7a5b52003-04-30 09:00:33 +00002339 if (0) {
2340 if (VG_(have_ssestate))
2341 VG_(printf)("Looks like a SSE-capable CPU\n");
2342 else
2343 VG_(printf)("Looks like a MMX-only CPU\n");
2344 }
sewardjb91ae7f2003-04-29 23:50:00 +00002345
nethercote71980f02004-01-24 18:18:54 +00002346 /* LDT pointer: pretend the root thread has an empty LDT to start with. */
2347 VGOFF_(ldt) = alloc_BaB_1_set((UInt)NULL);
jsgf855d93d2003-10-13 22:26:55 +00002348
nethercote71980f02004-01-24 18:18:54 +00002349 /* TLS pointer: pretend the root thread has no TLS array for now. */
2350 VGOFF_(tls) = alloc_BaB_1_set((UInt)NULL);
fitzhardingef0046f22003-12-18 02:39:22 +00002351
nethercote71980f02004-01-24 18:18:54 +00002352 /* segment registers */
2353 VGOFF_(m_cs) = alloc_BaB_1_set(0);
2354 VGOFF_(m_ss) = alloc_BaB_1_set(0);
2355 VGOFF_(m_ds) = alloc_BaB_1_set(0);
2356 VGOFF_(m_es) = alloc_BaB_1_set(0);
2357 VGOFF_(m_fs) = alloc_BaB_1_set(0);
2358 VGOFF_(m_gs) = alloc_BaB_1_set(0);
fitzhardingef0046f22003-12-18 02:39:22 +00002359
thughes35cec982004-04-21 15:16:43 +00002360 /* initialise %cs, %ds and %ss to point at the operating systems
2361 default code, data and stack segments */
2362 asm volatile("movw %%cs, %0"
2363 :
2364 : "m" (VG_(baseBlock)[VGOFF_(m_cs)]));
2365 asm volatile("movw %%ds, %0"
2366 :
2367 : "m" (VG_(baseBlock)[VGOFF_(m_ds)]));
2368 asm volatile("movw %%ss, %0"
2369 :
2370 : "m" (VG_(baseBlock)[VGOFF_(m_ss)]));
2371
nethercote71980f02004-01-24 18:18:54 +00002372 VG_(register_noncompact_helper)( (Addr) & VG_(do_useseg) );
fitzhardingef0046f22003-12-18 02:39:22 +00002373
nethercote71980f02004-01-24 18:18:54 +00002374#define REG(kind, size) \
2375 if (VG_(defined_##kind##_mem_stack##size)()) \
2376 VG_(register_noncompact_helper)( \
2377 (Addr) VG_(tool_interface).track_##kind##_mem_stack##size );
2378 REG(new, _8);
2379 REG(new, _12);
2380 REG(new, _16);
2381 REG(new, _32);
2382 REG(new, );
2383 REG(die, _8);
2384 REG(die, _12);
2385 REG(die, _16);
2386 REG(die, _32);
2387 REG(die, );
2388#undef REG
fitzhardingef0046f22003-12-18 02:39:22 +00002389
nethercote71980f02004-01-24 18:18:54 +00002390 if (VG_(need_to_handle_esp_assignment)())
2391 VG_(register_noncompact_helper)((Addr) VG_(unknown_esp_update));
fitzhardingeb791a192003-12-18 07:22:44 +00002392
nethercote71980f02004-01-24 18:18:54 +00002393# define HELPER(name) \
2394 VGOFF_(helper_##name) = alloc_BaB_1_set( (Addr) & VG_(helper_##name))
njn3e884182003-04-15 13:03:23 +00002395
nethercote71980f02004-01-24 18:18:54 +00002396 /* Helper functions. */
2397 HELPER(idiv_64_32); HELPER(div_64_32);
2398 HELPER(idiv_32_16); HELPER(div_32_16);
2399 HELPER(idiv_16_8); HELPER(div_16_8);
fitzhardinge98abfc72003-12-16 02:05:15 +00002400
nethercote71980f02004-01-24 18:18:54 +00002401 HELPER(imul_32_64); HELPER(mul_32_64);
2402 HELPER(imul_16_32); HELPER(mul_16_32);
2403 HELPER(imul_8_16); HELPER(mul_8_16);
njn25e49d8e72002-09-23 09:36:25 +00002404
nethercote71980f02004-01-24 18:18:54 +00002405 HELPER(CLD); HELPER(STD);
2406 HELPER(get_dirflag);
sewardjde4a1d02002-03-22 01:27:54 +00002407
nethercote71980f02004-01-24 18:18:54 +00002408 HELPER(CLC); HELPER(STC);
nethercote1018bdd2004-02-11 23:33:29 +00002409 HELPER(CMC);
jsgf855d93d2003-10-13 22:26:55 +00002410
nethercote71980f02004-01-24 18:18:54 +00002411 HELPER(shldl); HELPER(shldw);
2412 HELPER(shrdl); HELPER(shrdw);
njncc7bb472002-10-14 09:25:19 +00002413
nethercote71980f02004-01-24 18:18:54 +00002414 HELPER(RDTSC); HELPER(CPUID);
njncc7bb472002-10-14 09:25:19 +00002415
nethercote1018bdd2004-02-11 23:33:29 +00002416 HELPER(bsfw); HELPER(bsfl);
2417 HELPER(bsrw); HELPER(bsrl);
rjwalshf5f536f2003-11-17 17:45:00 +00002418
nethercote71980f02004-01-24 18:18:54 +00002419 HELPER(fstsw_AX);
2420 HELPER(SAHF); HELPER(LAHF);
2421 HELPER(DAS); HELPER(DAA);
nethercote1018bdd2004-02-11 23:33:29 +00002422 HELPER(AAS); HELPER(AAA);
2423 HELPER(AAD); HELPER(AAM);
nethercote71980f02004-01-24 18:18:54 +00002424 HELPER(IN); HELPER(OUT);
2425 HELPER(cmpxchg8b);
sewardj018f7622002-05-15 21:13:39 +00002426
nethercote71980f02004-01-24 18:18:54 +00002427 HELPER(undefined_instruction);
jsgf855d93d2003-10-13 22:26:55 +00002428
nethercote71980f02004-01-24 18:18:54 +00002429# undef HELPER
sewardjde4a1d02002-03-22 01:27:54 +00002430
nethercote71980f02004-01-24 18:18:54 +00002431 /* Allocate slots for noncompact helpers */
2432 assign_helpers_in_baseBlock(VG_(n_noncompact_helpers),
2433 VG_(noncompact_helper_offsets),
2434 VG_(noncompact_helper_addrs));
2435}
sewardjde4a1d02002-03-22 01:27:54 +00002436
nethercote81f9a6f2004-08-03 15:45:46 +00002437// Finds the baseBlock offset of a tool-specified helper.
2438// Searches through compacts first, then non-compacts.
2439Int VG_(helper_offset)(Addr a)
2440{
2441 UInt i;
2442 Char buf[100];
2443
2444 for (i = 0; i < VG_(n_compact_helpers); i++)
2445 if (VG_(compact_helper_addrs)[i] == a)
2446 return VG_(compact_helper_offsets)[i];
2447 for (i = 0; i < VG_(n_noncompact_helpers); i++)
2448 if (VG_(noncompact_helper_addrs)[i] == a)
2449 return VG_(noncompact_helper_offsets)[i];
2450
2451 /* Shouldn't get here */
2452 VG_(get_fnname) ( a, buf, 100 );
2453
2454 VG_(printf)(
2455 "\nCouldn't find offset of helper from its address (%p: %s).\n"
2456 "A helper function probably used hasn't been registered?\n\n", a, buf);
2457
2458 VG_(printf)(" compact helpers: ");
2459 for (i = 0; i < VG_(n_compact_helpers); i++)
2460 VG_(printf)("%p ", VG_(compact_helper_addrs)[i]);
2461
2462 VG_(printf)("\n non-compact helpers: ");
2463 for (i = 0; i < VG_(n_noncompact_helpers); i++)
2464 VG_(printf)("%p ", VG_(noncompact_helper_addrs)[i]);
2465
2466 VG_(printf)("\n");
2467 VG_(skin_panic)("Unfound helper");
2468}
2469
sewardj5f07b662002-04-23 16:52:51 +00002470
nethercote71980f02004-01-24 18:18:54 +00002471/*====================================================================*/
2472/*=== Setup pointercheck ===*/
2473/*====================================================================*/
njn25e49d8e72002-09-23 09:36:25 +00002474
nethercote71980f02004-01-24 18:18:54 +00002475static void setup_pointercheck(void)
2476{
2477 int ret;
sewardj2e93c502002-04-12 11:12:52 +00002478
fitzhardinge98abfc72003-12-16 02:05:15 +00002479 if (VG_(clo_pointercheck)) {
nethercote71980f02004-01-24 18:18:54 +00002480 vki_modify_ldt_t ldt = {
2481 VG_POINTERCHECK_SEGIDX, // entry_number
2482 VG_(client_base), // base_addr
2483 (VG_(client_end)-VG_(client_base)) / VKI_BYTES_PER_PAGE, // limit
2484 1, // seg_32bit
2485 0, // contents: data, RW, non-expanding
2486 0, // ! read_exec_only
2487 1, // limit_in_pages
2488 0, // ! seg not present
2489 1, // useable
fitzhardinge98abfc72003-12-16 02:05:15 +00002490 };
nethercote71980f02004-01-24 18:18:54 +00002491 ret = VG_(do_syscall)(__NR_modify_ldt, 1, &ldt, sizeof(ldt));
fitzhardinge98abfc72003-12-16 02:05:15 +00002492 if (ret < 0) {
2493 VG_(message)(Vg_UserMsg,
2494 "Warning: ignoring --pointercheck=yes, "
2495 "because modify_ldt failed (errno=%d)", -ret);
2496 VG_(clo_pointercheck) = False;
2497 }
2498 }
sewardjde4a1d02002-03-22 01:27:54 +00002499}
2500
nethercote71980f02004-01-24 18:18:54 +00002501/*====================================================================*/
2502/*=== Initialise program data/text, etc. ===*/
2503/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +00002504
nethercote71980f02004-01-24 18:18:54 +00002505static void build_valgrind_map_callback
2506 ( Addr start, UInt size, Char rr, Char ww, Char xx,
2507 UInt dev, UInt ino, ULong foffset, const UChar* filename )
sewardjde4a1d02002-03-22 01:27:54 +00002508{
nethercote71980f02004-01-24 18:18:54 +00002509 UInt prot = 0;
2510 UInt flags = SF_MMAP|SF_NOSYMS;
2511 Bool is_stack_segment;
2512
2513 is_stack_segment =
2514 (start == VG_(clstk_base) && (start+size) == VG_(clstk_end));
2515
2516 /* Only record valgrind mappings for now, without loading any
2517 symbols. This is so we know where the free space is before we
2518 start allocating more memory (note: heap is OK, it's just mmap
2519 which is the problem here). */
2520 if (start >= VG_(valgrind_base) && (start+size) <= VG_(valgrind_end)) {
2521 flags |= SF_VALGRIND;
2522 VG_(map_file_segment)(start, size, prot, flags, dev, ino, foffset, filename);
2523 }
sewardjde4a1d02002-03-22 01:27:54 +00002524}
2525
nethercote71980f02004-01-24 18:18:54 +00002526// Global var used to pass local data to callback
2527Addr esp_at_startup___global_arg = 0;
sewardjde4a1d02002-03-22 01:27:54 +00002528
nethercote71980f02004-01-24 18:18:54 +00002529static void build_segment_map_callback
2530 ( Addr start, UInt size, Char rr, Char ww, Char xx,
2531 UInt dev, UInt ino, ULong foffset, const UChar* filename )
sewardj45b672d2003-07-25 19:58:11 +00002532{
nethercote71980f02004-01-24 18:18:54 +00002533 UInt prot = 0;
2534 UInt flags;
2535 Bool is_stack_segment;
2536 Addr r_esp;
sewardj45b672d2003-07-25 19:58:11 +00002537
nethercote71980f02004-01-24 18:18:54 +00002538 is_stack_segment
2539 = (start == VG_(clstk_base) && (start+size) == VG_(clstk_end));
fitzhardinge98abfc72003-12-16 02:05:15 +00002540
nethercote71980f02004-01-24 18:18:54 +00002541 if (rr == 'r') prot |= VKI_PROT_READ;
2542 if (ww == 'w') prot |= VKI_PROT_WRITE;
2543 if (xx == 'x') prot |= VKI_PROT_EXEC;
fitzhardinge98abfc72003-12-16 02:05:15 +00002544
nethercote71980f02004-01-24 18:18:54 +00002545 if (is_stack_segment)
2546 flags = SF_STACK | SF_GROWDOWN;
2547 else
2548 flags = SF_EXEC|SF_MMAP;
fitzhardinge98abfc72003-12-16 02:05:15 +00002549
nethercote71980f02004-01-24 18:18:54 +00002550 if (filename != NULL)
2551 flags |= SF_FILE;
fitzhardinge98abfc72003-12-16 02:05:15 +00002552
nethercote71980f02004-01-24 18:18:54 +00002553 if (start >= VG_(valgrind_base) && (start+size) <= VG_(valgrind_end))
2554 flags |= SF_VALGRIND;
fitzhardinge98abfc72003-12-16 02:05:15 +00002555
nethercote71980f02004-01-24 18:18:54 +00002556 VG_(map_file_segment)(start, size, prot, flags, dev, ino, foffset, filename);
fitzhardinge98abfc72003-12-16 02:05:15 +00002557
nethercote71980f02004-01-24 18:18:54 +00002558 if (VG_(is_client_addr)(start) && VG_(is_client_addr)(start+size-1))
2559 VG_TRACK( new_mem_startup, start, size, rr=='r', ww=='w', xx=='x' );
sewardj3e1eb1f2002-05-18 13:14:17 +00002560
nethercote71980f02004-01-24 18:18:54 +00002561 /* If this is the stack segment mark all below %esp as noaccess. */
2562 r_esp = esp_at_startup___global_arg;
2563 vg_assert(0 != r_esp);
2564 if (is_stack_segment) {
2565 if (0)
2566 VG_(message)(Vg_DebugMsg, "invalidating stack area: %x .. %x",
2567 start,r_esp);
2568 VG_TRACK( die_mem_stack, start, r_esp-start );
sewardjde4a1d02002-03-22 01:27:54 +00002569 }
sewardjde4a1d02002-03-22 01:27:54 +00002570}
2571
2572
nethercote71980f02004-01-24 18:18:54 +00002573/*====================================================================*/
2574/*=== Sanity check machinery (permanently engaged) ===*/
2575/*====================================================================*/
njn25e49d8e72002-09-23 09:36:25 +00002576
2577/* A fast sanity check -- suitable for calling circa once per
2578 millisecond. */
2579
2580void VG_(do_sanity_checks) ( Bool force_expensive )
2581{
njn37cea302002-09-30 11:24:00 +00002582 VGP_PUSHCC(VgpCoreCheapSanity);
2583
nethercote27fec902004-06-16 21:26:32 +00002584 if (VG_(clo_sanity_level) < 1) return;
njn25e49d8e72002-09-23 09:36:25 +00002585
2586 /* --- First do all the tests that we can do quickly. ---*/
2587
nethercote297effd2004-08-02 15:07:57 +00002588 sanity_fast_count++;
njn25e49d8e72002-09-23 09:36:25 +00002589
njn25e49d8e72002-09-23 09:36:25 +00002590 /* Check stuff pertaining to the memory check system. */
2591
2592 /* Check that nobody has spuriously claimed that the first or
2593 last 16 pages of memory have become accessible [...] */
njn37cea302002-09-30 11:24:00 +00002594 if (VG_(needs).sanity_checks) {
2595 VGP_PUSHCC(VgpSkinCheapSanity);
njn25e49d8e72002-09-23 09:36:25 +00002596 vg_assert(SK_(cheap_sanity_check)());
njn37cea302002-09-30 11:24:00 +00002597 VGP_POPCC(VgpSkinCheapSanity);
2598 }
njn25e49d8e72002-09-23 09:36:25 +00002599
2600 /* --- Now some more expensive checks. ---*/
2601
2602 /* Once every 25 times, check some more expensive stuff. */
2603 if ( force_expensive
nethercote27fec902004-06-16 21:26:32 +00002604 || VG_(clo_sanity_level) > 1
nethercote297effd2004-08-02 15:07:57 +00002605 || (VG_(clo_sanity_level) == 1 && (sanity_fast_count % 25) == 0)) {
njn25e49d8e72002-09-23 09:36:25 +00002606
njn37cea302002-09-30 11:24:00 +00002607 VGP_PUSHCC(VgpCoreExpensiveSanity);
nethercote297effd2004-08-02 15:07:57 +00002608 sanity_slow_count++;
njn25e49d8e72002-09-23 09:36:25 +00002609
jsgf855d93d2003-10-13 22:26:55 +00002610 VG_(proxy_sanity)();
2611
njn25e49d8e72002-09-23 09:36:25 +00002612# if 0
2613 { void zzzmemscan(void); zzzmemscan(); }
2614# endif
2615
nethercote297effd2004-08-02 15:07:57 +00002616 if ((sanity_fast_count % 250) == 0)
njn25e49d8e72002-09-23 09:36:25 +00002617 VG_(sanity_check_tc_tt)();
2618
2619 if (VG_(needs).sanity_checks) {
njn37cea302002-09-30 11:24:00 +00002620 VGP_PUSHCC(VgpSkinExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002621 vg_assert(SK_(expensive_sanity_check)());
njn37cea302002-09-30 11:24:00 +00002622 VGP_POPCC(VgpSkinExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002623 }
2624 /*
nethercote297effd2004-08-02 15:07:57 +00002625 if ((sanity_fast_count % 500) == 0) VG_(mallocSanityCheckAll)();
njn25e49d8e72002-09-23 09:36:25 +00002626 */
njn37cea302002-09-30 11:24:00 +00002627 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002628 }
2629
nethercote27fec902004-06-16 21:26:32 +00002630 if (VG_(clo_sanity_level) > 1) {
njn37cea302002-09-30 11:24:00 +00002631 VGP_PUSHCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002632 /* Check sanity of the low-level memory manager. Note that bugs
2633 in the client's code can cause this to fail, so we don't do
2634 this check unless specially asked for. And because it's
2635 potentially very expensive. */
2636 VG_(mallocSanityCheckAll)();
njn37cea302002-09-30 11:24:00 +00002637 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002638 }
njn37cea302002-09-30 11:24:00 +00002639 VGP_POPCC(VgpCoreCheapSanity);
njn25e49d8e72002-09-23 09:36:25 +00002640}
nethercote71980f02004-01-24 18:18:54 +00002641
2642
2643/*====================================================================*/
2644/*=== main() ===*/
2645/*====================================================================*/
2646
nethercotec314eba2004-07-15 12:59:41 +00002647/*
2648 This code decides on the layout of the client and Valgrind address
nethercote996901a2004-08-03 13:29:09 +00002649 spaces, loads valgrind.so and the tool.so into the valgrind part,
nethercotec314eba2004-07-15 12:59:41 +00002650 loads the client executable (and the dynamic linker, if necessary)
2651 into the client part, and calls into Valgrind proper.
2652
2653 The code is careful not to allow spurious mappings to appear in the
2654 wrong parts of the address space. In particular, to make sure
2655 dlopen puts things in the right place, it will pad out the forbidden
2656 chunks of address space so that dlopen is forced to put things where
2657 we want them.
2658
2659 The memory map it creates is:
2660
2661 CLIENT_BASE +-------------------------+
2662 | client address space |
2663 : :
2664 : :
2665 | client stack |
2666 client_end +-------------------------+
2667 | redzone |
2668 shadow_base +-------------------------+
2669 | |
nethercote996901a2004-08-03 13:29:09 +00002670 : shadow memory for tools :
nethercotec314eba2004-07-15 12:59:41 +00002671 | (may be 0 sized) |
2672 shadow_end +-------------------------+
2673 : gap (may be 0 sized) :
2674 valgrind_base +-------------------------+
2675 | kickstart executable |
2676 | valgrind heap vvvvvvvvv| (barely used)
2677 - -
2678 | valgrind .so files |
2679 | and mappings |
2680 - -
2681 | valgrind stack ^^^^^^^^^|
2682 valgrind_end +-------------------------+
2683 : kernel :
2684
2685 Nb: Before we can do general allocations with VG_(arena_malloc)() and
2686 VG_(mmap)(), we need to build the segment skip-list, so we know where
2687 we can put things. However, building that structure requires
2688 allocating memory. So we need to a bootstrapping process. It's done
2689 by making VG_(arena_malloc)() have a special static superblock that's
2690 used for the first 1MB's worth of allocations. This is enough to
2691 build the segment skip-list.
2692*/
2693
nethercote31779c72004-07-30 21:50:15 +00002694static int prmap(char *start, char *end, const char *perm, off_t off,
2695 int maj, int min, int ino, void* dummy) {
thughes4ad52d02004-06-27 17:37:21 +00002696 printf("mapping %10p-%10p %s %02x:%02x %d\n",
2697 start, end, perm, maj, min, ino);
2698 return True;
2699}
2700
nethercote71980f02004-01-24 18:18:54 +00002701int main(int argc, char **argv)
2702{
2703 char **cl_argv;
2704 const char *tool = NULL;
2705 const char *exec = NULL;
2706 char *preload; /* tool-specific LD_PRELOAD .so */
2707 char **env;
nethercote6c999f22004-01-31 22:55:15 +00002708 Int need_help = 0; // 0 = no, 1 = --help, 2 = --help-debug
nethercote71980f02004-01-24 18:18:54 +00002709 struct exeinfo info;
2710 ToolInfo *toolinfo = NULL;
2711 void *tool_dlhandle;
2712 Addr client_eip;
2713 Addr esp_at_startup; /* client's %esp at the point we gained control. */
2714 UInt * client_auxv;
2715 VgSchedReturnCode src;
nethercote47dd12c2004-06-22 14:18:42 +00002716 Int exitcode = 0;
fitzhardingeb50068f2004-02-24 23:42:55 +00002717 vki_rlimit zero = { 0, 0 };
nethercote31779c72004-07-30 21:50:15 +00002718 Int padfile;
nethercote71980f02004-01-24 18:18:54 +00002719
2720 //============================================================
2721 // Nb: startup is complex. Prerequisites are shown at every step.
2722 //
2723 // *** Be very careful when messing with the order ***
2724 //============================================================
2725
nethercotef4928da2004-06-15 10:54:40 +00002726 //============================================================
2727 // Command line argument handling order:
2728 // * If --help/--help-debug are present, show usage message
2729 // (if --tool is also present, that includes the tool-specific usage)
2730 // * Then, if --tool is missing, abort with error msg
2731 // * Then, if client is missing, abort with error msg
2732 // * Then, if any cmdline args are bad, abort with error msg
2733 //============================================================
2734
fitzhardingeb50068f2004-02-24 23:42:55 +00002735 // Get the current process datasize rlimit, and set it to zero.
2736 // This prevents any internal uses of brk() from having any effect.
2737 // We remember the old value so we can restore it on exec, so that
2738 // child processes will have a reasonable brk value.
2739 VG_(getrlimit)(VKI_RLIMIT_DATA, &VG_(client_rlimit_data));
2740 zero.rlim_max = VG_(client_rlimit_data).rlim_max;
2741 VG_(setrlimit)(VKI_RLIMIT_DATA, &zero);
2742
nethercote71980f02004-01-24 18:18:54 +00002743 //--------------------------------------------------------------
2744 // Check we were launched by stage1
nethercotec314eba2004-07-15 12:59:41 +00002745 // p: n/a
nethercote71980f02004-01-24 18:18:54 +00002746 //--------------------------------------------------------------
nethercote31779c72004-07-30 21:50:15 +00002747 padfile = scan_auxv();
nethercote71980f02004-01-24 18:18:54 +00002748
2749 if (0) {
nethercote71980f02004-01-24 18:18:54 +00002750 printf("========== main() ==========\n");
nethercote31779c72004-07-30 21:50:15 +00002751 foreach_map(prmap, /*dummy*/NULL);
nethercote71980f02004-01-24 18:18:54 +00002752 }
2753
2754 //--------------------------------------------------------------
2755 // Look for alternative libdir
2756 // p: n/a
2757 //--------------------------------------------------------------
2758 { char *cp = getenv(VALGRINDLIB);
2759 if (cp != NULL)
2760 VG_(libdir) = cp;
2761 }
2762
2763 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002764 // Get valgrind args + client args (inc. from VALGRIND_OPTS/.valgrindrc).
2765 // Pre-process the command line.
2766 // p: n/a
2767 //--------------------------------------------------------------
2768 get_command_line(argc, argv, &VG_(vg_argc), &VG_(vg_argv), &cl_argv);
2769 pre_process_cmd_line_options(&need_help, &tool, &exec);
2770
2771 //==============================================================
2772 // Nb: once a tool is specified, the tool.so must be loaded even if
2773 // they specified --help or didn't specify a client program.
2774 //==============================================================
2775
2776 //--------------------------------------------------------------
2777 // With client padded out, map in tool
nethercote71980f02004-01-24 18:18:54 +00002778 // p: set-libdir [for VG_(libdir)]
2779 // p: pre_process_cmd_line_options() [for 'tool']
2780 //--------------------------------------------------------------
2781 load_tool(tool, &tool_dlhandle, &toolinfo, &preload);
2782
2783 //==============================================================
2784 // Can use VG_(malloc)() and VG_(arena_malloc)() only after load_tool()
nethercotec314eba2004-07-15 12:59:41 +00002785 // -- redzone size is now set. This is checked by vg_malloc2.c.
nethercote71980f02004-01-24 18:18:54 +00002786 //==============================================================
2787
2788 //--------------------------------------------------------------
2789 // Finalise address space layout
nethercote31779c72004-07-30 21:50:15 +00002790 // p: load_tool() [for 'toolinfo']
nethercote71980f02004-01-24 18:18:54 +00002791 //--------------------------------------------------------------
nethercote31779c72004-07-30 21:50:15 +00002792 layout_remaining_space( (Addr) & argc, toolinfo->shadow_ratio );
nethercote71980f02004-01-24 18:18:54 +00002793
2794 //--------------------------------------------------------------
2795 // Load client executable, finding in $PATH if necessary
nethercote71980f02004-01-24 18:18:54 +00002796 // p: pre_process_cmd_line_options() [for 'exec', 'need_help']
2797 // p: layout_remaining_space [so there's space]
2798 //--------------------------------------------------------------
nethercotef4928da2004-06-15 10:54:40 +00002799 load_client(cl_argv, exec, need_help, &info, &client_eip);
nethercote71980f02004-01-24 18:18:54 +00002800
2801 //--------------------------------------------------------------
2802 // Everything in place, unpad us
2803 // p: layout_remaining_space() [everything must be mapped in before now]
2804 // p: load_client() [ditto]
2805 //--------------------------------------------------------------
nethercote31779c72004-07-30 21:50:15 +00002806 as_unpad((void *)VG_(shadow_end), (void *)~0, padfile);
2807 as_closepadfile(padfile); // no more padding
nethercote71980f02004-01-24 18:18:54 +00002808
2809 //--------------------------------------------------------------
2810 // Set up client's environment
2811 // p: set-libdir [for VG_(libdir)]
2812 // p: load_tool() [for 'preload']
2813 //--------------------------------------------------------------
2814 env = fix_environment(environ, preload);
2815
2816 //--------------------------------------------------------------
nethercote5ee67ca2004-06-22 14:00:09 +00002817 // Setup client stack, eip, and VG_(client_arg[cv])
nethercote71980f02004-01-24 18:18:54 +00002818 // p: load_client() [for 'info']
2819 // p: fix_environment() [for 'env']
2820 //--------------------------------------------------------------
2821 esp_at_startup = setup_client_stack(cl_argv, env, &info, &client_auxv);
2822
2823 if (0)
2824 printf("entry=%x client esp=%x vg_argc=%d brkbase=%x\n",
2825 client_eip, esp_at_startup, VG_(vg_argc), VG_(brk_base));
2826
2827 //==============================================================
2828 // Finished setting up operating environment. Now initialise
2829 // Valgrind. (This is where the old VG_(main)() started.)
2830 //==============================================================
2831
2832 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002833 // atfork
2834 // p: n/a
2835 //--------------------------------------------------------------
2836 VG_(atfork)(NULL, NULL, newpid);
2837 newpid(VG_INVALID_THREADID);
2838
2839 //--------------------------------------------------------------
2840 // setup file descriptors
2841 // p: n/a
2842 //--------------------------------------------------------------
2843 setup_file_descriptors();
2844
2845 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002846 // Read /proc/self/maps into a buffer
2847 // p: all memory layout, environment setup [so memory maps are right]
2848 //--------------------------------------------------------------
2849 VG_(read_procselfmaps)();
2850
2851 //--------------------------------------------------------------
2852 // Build segment map (Valgrind segments only)
2853 // p: read proc/self/maps
2854 // p: sk_pre_clo_init() [to setup new_mem_startup tracker]
2855 //--------------------------------------------------------------
2856 VG_(parse_procselfmaps) ( build_valgrind_map_callback );
2857
2858 //==============================================================
2859 // Can use VG_(arena_malloc)() with non-CORE arena after segments set up
2860 //==============================================================
2861
2862 //--------------------------------------------------------------
2863 // Init tool: pre_clo_init, process cmd line, post_clo_init
2864 // p: setup_client_stack() [for 'VG_(client_arg[cv]']
2865 // p: load_tool() [for 'tool']
2866 // p: setup_file_descriptors() [for 'VG_(fd_xxx_limit)']
2867 // p: parse_procselfmaps [so VG segments are setup so tool can
2868 // call VG_(malloc)]
nethercote71980f02004-01-24 18:18:54 +00002869 //--------------------------------------------------------------
2870 (*toolinfo->sk_pre_clo_init)();
2871 VG_(tool_init_dlsym)(tool_dlhandle);
2872 VG_(sanity_check_needs)();
2873
nethercotef4928da2004-06-15 10:54:40 +00002874 // If --tool and --help/--help-debug was given, now give the core+tool
2875 // help message
nethercotef4928da2004-06-15 10:54:40 +00002876 if (need_help) {
2877 usage(/*--help-debug?*/2 == need_help);
2878 }
nethercotec314eba2004-07-15 12:59:41 +00002879 process_cmd_line_options(client_auxv, tool);
2880
2881 SK_(post_clo_init)();
nethercotef4928da2004-06-15 10:54:40 +00002882
2883 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002884 // Build segment map (all segments)
2885 // p: setup_client_stack() [for 'esp_at_startup']
2886 // p: init tool [for 'new_mem_startup']
nethercote71980f02004-01-24 18:18:54 +00002887 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002888 esp_at_startup___global_arg = esp_at_startup;
2889 VG_(parse_procselfmaps) ( build_segment_map_callback ); /* everything */
2890 esp_at_startup___global_arg = 0;
2891
2892 //--------------------------------------------------------------
nethercotef84f6952004-07-15 14:58:33 +00002893 // Protect client trampoline page (which is also sysinfo stuff)
2894 // p: segment stuff [otherwise get seg faults...]
nethercotec314eba2004-07-15 12:59:41 +00002895 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002896 VG_(mprotect)( (void *)VG_(client_trampoline_code),
2897 VG_(trampoline_code_length), VKI_PROT_READ|VKI_PROT_EXEC );
2898
2899 //==============================================================
2900 // Can use VG_(map)() after segments set up
2901 //==============================================================
nethercote71980f02004-01-24 18:18:54 +00002902
2903 //--------------------------------------------------------------
2904 // Allow GDB attach
2905 // p: process_cmd_line_options() [for VG_(clo_wait_for_gdb)]
2906 //--------------------------------------------------------------
2907 /* Hook to delay things long enough so we can get the pid and
2908 attach GDB in another shell. */
2909 if (VG_(clo_wait_for_gdb)) {
2910 VG_(printf)("pid=%d\n", VG_(getpid)());
2911 /* do "jump *$eip" to skip this in gdb */
2912 VG_(do_syscall)(__NR_pause);
2913 }
2914
2915 //--------------------------------------------------------------
nethercote1d447092004-02-01 17:29:59 +00002916 // Set up baseBlock
nethercote71980f02004-01-24 18:18:54 +00002917 // p: {pre,post}_clo_init() [for tool helper registration]
2918 // load_client() [for 'client_eip']
2919 // setup_client_stack() [for 'esp_at_startup']
2920 //--------------------------------------------------------------
2921 init_baseBlock(client_eip, esp_at_startup);
2922
2923 //--------------------------------------------------------------
2924 // Search for file descriptors that are inherited from our parent
2925 // p: process_cmd_line_options [for VG_(clo_track_fds)]
2926 //--------------------------------------------------------------
2927 if (VG_(clo_track_fds))
2928 VG_(init_preopened_fds)();
2929
2930 //--------------------------------------------------------------
2931 // Initialise the scheduler
2932 // p: init_baseBlock() [baseBlock regs copied into VG_(threads)[1]]
2933 // p: setup_file_descriptors() [else VG_(safe_fd)() breaks]
2934 //--------------------------------------------------------------
2935 VG_(scheduler_init)();
2936
2937 //--------------------------------------------------------------
2938 // Set up the ProxyLWP machinery
2939 // p: VG_(scheduler_init)()? [XXX: subtle dependency?]
nethercote71980f02004-01-24 18:18:54 +00002940 //--------------------------------------------------------------
2941 VG_(proxy_init)();
2942
2943 //--------------------------------------------------------------
2944 // Initialise the signal handling subsystem
2945 // p: VG_(atfork)(NULL, NULL, newpid) [else problems with sigmasks]
2946 // p: VG_(proxy_init)() [else breaks...]
2947 //--------------------------------------------------------------
2948 // Nb: temporarily parks the saved blocking-mask in saved_sigmask.
2949 VG_(sigstartup_actions)();
2950
2951 //--------------------------------------------------------------
2952 // Perhaps we're profiling Valgrind?
2953 // p: process_cmd_line_options() [for VG_(clo_profile)]
2954 // p: others?
2955 //
2956 // XXX: this seems to be broken? It always says the tool wasn't built
2957 // for profiling; vg_profile.c's functions don't seem to be overriding
2958 // vg_dummy_profile.c's?
2959 //
2960 // XXX: want this as early as possible. Looking for --profile
2961 // in pre_process_cmd_line_options() could get it earlier.
2962 //--------------------------------------------------------------
2963 if (VG_(clo_profile))
2964 VGP_(init_profiling)();
2965
2966 VGP_PUSHCC(VgpStartup);
2967
2968 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002969 // Read suppression file
2970 // p: process_cmd_line_options() [for VG_(clo_suppressions)]
2971 //--------------------------------------------------------------
2972 if (VG_(needs).core_errors || VG_(needs).skin_errors)
2973 VG_(load_suppressions)();
2974
2975 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002976 // Initialise translation table and translation cache
2977 // p: read_procselfmaps [so the anonymous mmaps for the TT/TC
2978 // aren't identified as part of the client, which would waste
2979 // > 20M of virtual address space.]
2980 //--------------------------------------------------------------
2981 VG_(init_tt_tc)();
2982
2983 //--------------------------------------------------------------
2984 // Read debug info to find glibc entry points to intercept
2985 // p: parse_procselfmaps? [XXX for debug info?]
2986 // p: init_tt_tc? [XXX ???]
2987 //--------------------------------------------------------------
2988 VG_(setup_code_redirect_table)();
2989
2990 //--------------------------------------------------------------
2991 // Verbosity message
2992 // p: end_rdtsc_calibration [so startup message is printed first]
2993 //--------------------------------------------------------------
2994 if (VG_(clo_verbosity) == 1)
2995 VG_(message)(Vg_UserMsg, "For more details, rerun with: -v");
2996 if (VG_(clo_verbosity) > 0)
2997 VG_(message)(Vg_UserMsg, "");
2998
2999 //--------------------------------------------------------------
3000 // Setup pointercheck
3001 // p: process_cmd_line_options() [for VG_(clo_pointercheck)]
3002 //--------------------------------------------------------------
3003 setup_pointercheck();
3004
nethercote71980f02004-01-24 18:18:54 +00003005 //--------------------------------------------------------------
3006 // Run!
3007 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00003008 VGP_POPCC(VgpStartup);
3009 VGP_PUSHCC(VgpSched);
3010
nethercote31294822004-08-02 13:15:26 +00003011 VG_(fatal_signal_jmpbuf_ptr) = &fatal_signal_jmpbuf;
3012 if (__builtin_setjmp(VG_(fatal_signal_jmpbuf_ptr)) == 0) {
nethercote47dd12c2004-06-22 14:18:42 +00003013 src = VG_(scheduler)( &exitcode );
nethercote31294822004-08-02 13:15:26 +00003014 } else {
nethercote71980f02004-01-24 18:18:54 +00003015 src = VgSrc_FatalSig;
nethercote31294822004-08-02 13:15:26 +00003016 }
nethercote71980f02004-01-24 18:18:54 +00003017 VGP_POPCC(VgpSched);
nethercote71980f02004-01-24 18:18:54 +00003018
3019
3020
3021 //--------------------------------------------------------------
3022 // Finalisation: cleanup, messages, etc. Order no so important, only
3023 // affects what order the messages come.
3024 //--------------------------------------------------------------
3025 if (VG_(clo_verbosity) > 0)
3026 VG_(message)(Vg_UserMsg, "");
3027
3028 if (src == VgSrc_Deadlock) {
3029 VG_(message)(Vg_UserMsg,
3030 "Warning: pthread scheduler exited due to deadlock");
3031 }
3032
3033 /* Print out file descriptor summary and stats. */
3034 if (VG_(clo_track_fds))
nethercote3a42fb82004-08-03 18:08:50 +00003035 VG_(show_open_fds)();
nethercote71980f02004-01-24 18:18:54 +00003036
3037 if (VG_(needs).core_errors || VG_(needs).skin_errors)
3038 VG_(show_all_errors)();
3039
nethercote47dd12c2004-06-22 14:18:42 +00003040 SK_(fini)( exitcode );
nethercote71980f02004-01-24 18:18:54 +00003041
3042 VG_(do_sanity_checks)( True /*include expensive checks*/ );
3043
3044 if (VG_(clo_verbosity) > 1)
nethercote3a42fb82004-08-03 18:08:50 +00003045 print_all_stats();
nethercote71980f02004-01-24 18:18:54 +00003046
nethercote71980f02004-01-24 18:18:54 +00003047 if (VG_(clo_profile))
3048 VGP_(done_profiling)();
3049
nethercote71980f02004-01-24 18:18:54 +00003050 /* We're exiting, so nuke all the threads and clean up the proxy LWPs */
3051 vg_assert(src == VgSrc_FatalSig ||
3052 VG_(threads)[VG_(last_run_tid)].status == VgTs_Runnable ||
3053 VG_(threads)[VG_(last_run_tid)].status == VgTs_WaitJoiner);
3054 VG_(nuke_all_threads_except)(VG_INVALID_THREADID);
3055
3056 //--------------------------------------------------------------
3057 // Exit, according to the scheduler's return code
3058 //--------------------------------------------------------------
3059 switch (src) {
3060 case VgSrc_ExitSyscall: /* the normal way out */
nethercote85cdd342004-08-01 22:36:40 +00003061 vg_assert(VG_(last_run_tid) > 0 && VG_(last_run_tid) < VG_N_THREADS);
nethercote71980f02004-01-24 18:18:54 +00003062 VG_(proxy_shutdown)();
3063
3064 /* The thread's %EBX at the time it did __NR_exit() will hold
3065 the arg to __NR_exit(), so we just do __NR_exit() with
3066 that arg. */
nethercote47dd12c2004-06-22 14:18:42 +00003067 VG_(exit)( exitcode );
nethercote71980f02004-01-24 18:18:54 +00003068 /* NOT ALIVE HERE! */
3069 VG_(core_panic)("entered the afterlife in main() -- ExitSyscall");
3070 break; /* what the hell :) */
3071
3072 case VgSrc_Deadlock:
3073 /* Just exit now. No point in continuing. */
3074 VG_(proxy_shutdown)();
3075 VG_(exit)(0);
3076 VG_(core_panic)("entered the afterlife in main() -- Deadlock");
3077 break;
3078
nethercote71980f02004-01-24 18:18:54 +00003079 case VgSrc_FatalSig:
3080 /* We were killed by a fatal signal, so replicate the effect */
3081 vg_assert(VG_(fatal_sigNo) != -1);
3082 VG_(kill_self)(VG_(fatal_sigNo));
3083 VG_(core_panic)("main(): signal was supposed to be fatal");
3084 break;
3085
3086 default:
3087 VG_(core_panic)("main(): unexpected scheduler return code");
3088 }
3089
3090 abort();
3091}
3092
3093
sewardjde4a1d02002-03-22 01:27:54 +00003094/*--------------------------------------------------------------------*/
3095/*--- end vg_main.c ---*/
3096/*--------------------------------------------------------------------*/