blob: 990b70c2d12aed85305018f5f2c92d328b9f547f [file] [log] [blame]
sewardjde4a1d02002-03-22 01:27:54 +00001
2/*--------------------------------------------------------------------*/
nethercote71980f02004-01-24 18:18:54 +00003/*--- Startup: the real stuff vg_main.c ---*/
sewardjde4a1d02002-03-22 01:27:54 +00004/*--------------------------------------------------------------------*/
5
6/*
njnc9539842002-10-02 13:26:35 +00007 This file is part of Valgrind, an extensible x86 protected-mode
8 emulator for monitoring program execution on x86-Unixes.
sewardjde4a1d02002-03-22 01:27:54 +00009
nethercotebb1c9912004-01-04 16:43:23 +000010 Copyright (C) 2000-2004 Julian Seward
sewardjde4a1d02002-03-22 01:27:54 +000011 jseward@acm.org
sewardjde4a1d02002-03-22 01:27:54 +000012
13 This program is free software; you can redistribute it and/or
14 modify it under the terms of the GNU General Public License as
15 published by the Free Software Foundation; either version 2 of the
16 License, or (at your option) any later version.
17
18 This program is distributed in the hope that it will be useful, but
19 WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 General Public License for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software
25 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
26 02111-1307, USA.
27
njn25e49d8e72002-09-23 09:36:25 +000028 The GNU General Public License is contained in the file COPYING.
sewardjde4a1d02002-03-22 01:27:54 +000029*/
30
nethercote71980f02004-01-24 18:18:54 +000031#define _FILE_OFFSET_BITS 64
sewardjde4a1d02002-03-22 01:27:54 +000032
nethercote71980f02004-01-24 18:18:54 +000033#include "vg_include.h"
34#include "ume.h"
35#include "ume_arch.h"
36#include "ume_archdefs.h"
37
38#include <dirent.h>
39#include <dlfcn.h>
40#include <errno.h>
41#include <fcntl.h>
42#include <stdio.h>
fitzhardingeb727d042004-01-06 00:18:21 +000043#include <stdlib.h>
nethercote71980f02004-01-24 18:18:54 +000044#include <string.h>
45#include <sys/mman.h>
46#include <sys/types.h>
47#include <sys/stat.h>
fitzhardingeb727d042004-01-06 00:18:21 +000048#include <sys/ptrace.h>
49#include <sys/signal.h>
fitzhardingeb727d042004-01-06 00:18:21 +000050#include <sys/wait.h>
51#include <unistd.h>
52
thughes74b8de22004-04-22 18:12:31 +000053#ifndef AT_DCACHEBSIZE
54#define AT_DCACHEBSIZE 19
55#endif /* AT_DCACHEBSIZE */
56
57#ifndef AT_ICACHEBSIZE
58#define AT_ICACHEBSIZE 20
59#endif /* AT_ICACHEBSIZE */
60
61#ifndef AT_UCACHEBSIZE
62#define AT_UCACHEBSIZE 21
63#endif /* AT_UCACHEBSIZE */
64
nethercote71980f02004-01-24 18:18:54 +000065#ifndef AT_SYSINFO
66#define AT_SYSINFO 32
67#endif /* AT_SYSINFO */
68
69#ifndef AT_SYSINFO_EHDR
70#define AT_SYSINFO_EHDR 33
71#endif /* AT_SYSINFO_EHDR */
72
73#ifndef AT_SECURE
74#define AT_SECURE 23 /* secure mode boolean */
75#endif /* AT_SECURE */
76
nethercote71980f02004-01-24 18:18:54 +000077/* redzone gap between client address space and shadow */
78#define REDZONE_SIZE (1 * 1024*1024)
79
80/* size multiple for client address space */
nethercotee94b2de2004-06-23 16:15:06 +000081#define CLIENT_SIZE_MULTIPLE (1 * 1024*1024)
nethercote71980f02004-01-24 18:18:54 +000082
nethercotee2097312004-06-27 12:29:56 +000083/* Proportion of client space for its heap (rest is for mmaps + stack) */
84#define CLIENT_HEAP_PROPORTION 0.333
nethercote71980f02004-01-24 18:18:54 +000085
86/*====================================================================*/
87/*=== Global entities not referenced from generated code ===*/
88/*====================================================================*/
89
sewardjde4a1d02002-03-22 01:27:54 +000090/* ---------------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +000091 Startup stuff
sewardjde4a1d02002-03-22 01:27:54 +000092 ------------------------------------------------------------------ */
nethercote71980f02004-01-24 18:18:54 +000093/* linker-defined base address */
94extern char kickstart_base;
sewardjde4a1d02002-03-22 01:27:54 +000095
nethercote71980f02004-01-24 18:18:54 +000096/* Client address space, lowest to highest (see top of ume.c) */
97Addr VG_(client_base); /* client address space limits */
fitzhardinge98abfc72003-12-16 02:05:15 +000098Addr VG_(client_end);
99Addr VG_(client_mapbase);
fitzhardinge92360792003-12-24 10:11:11 +0000100Addr VG_(client_trampoline_code);
fitzhardinge98abfc72003-12-16 02:05:15 +0000101Addr VG_(clstk_base);
102Addr VG_(clstk_end);
nethercote71980f02004-01-24 18:18:54 +0000103
104Addr VG_(brk_base); /* start of brk */
105Addr VG_(brk_limit); /* current brk */
106
107Addr VG_(shadow_base); /* skin's shadow memory */
fitzhardinge98abfc72003-12-16 02:05:15 +0000108Addr VG_(shadow_end);
nethercote71980f02004-01-24 18:18:54 +0000109
110Addr VG_(valgrind_base); /* valgrind's address range */
fitzhardinge98abfc72003-12-16 02:05:15 +0000111Addr VG_(valgrind_end);
112
fitzhardingeb50068f2004-02-24 23:42:55 +0000113vki_rlimit VG_(client_rlimit_data);
114
nethercote71980f02004-01-24 18:18:54 +0000115/* This is set early to indicate whether this CPU has the
116 SSE/fxsave/fxrestor features. */
117Bool VG_(have_ssestate);
118
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
209static void show_counts ( void )
210{
211 VG_(message)(Vg_DebugMsg,
212 " TT/TC: %d tc sectors discarded.",
213 VG_(number_of_tc_discards) );
214 VG_(message)(Vg_DebugMsg,
215 " %d chainings, %d unchainings.",
216 VG_(bb_enchain_count), VG_(bb_dechain_count) );
217 VG_(message)(Vg_DebugMsg,
218 "translate: new %d (%d -> %d; ratio %d:10)",
219 VG_(overall_in_count),
220 VG_(overall_in_osize),
221 VG_(overall_in_tsize),
222 safe_idiv(10*VG_(overall_in_tsize), VG_(overall_in_osize)));
223 VG_(message)(Vg_DebugMsg,
224 " discard %d (%d -> %d; ratio %d:10).",
225 VG_(overall_out_count),
226 VG_(overall_out_osize),
227 VG_(overall_out_tsize),
228 safe_idiv(10*VG_(overall_out_tsize), VG_(overall_out_osize)));
229 VG_(message)(Vg_DebugMsg,
230 " dispatch: %llu jumps (bb entries), of which %u (%lu%%) were unchained.",
231 VG_(bbs_done),
232 VG_(unchained_jumps_done),
233 ((ULong)(100) * (ULong)(VG_(unchained_jumps_done)))
234 / ( VG_(bbs_done)==0 ? 1 : VG_(bbs_done) )
235 );
236
nethercote844e7122004-08-02 15:27:22 +0000237 VG_(print_scheduler_stats)();
nethercote71980f02004-01-24 18:18:54 +0000238 VG_(message)(Vg_DebugMsg,
nethercote844e7122004-08-02 15:27:22 +0000239 " %d tt_fast misses.", VG_(tt_fast_misses));
nethercote71980f02004-01-24 18:18:54 +0000240
nethercotebee3fd92004-08-02 15:17:43 +0000241 VG_(print_reg_alloc_stats)();
nethercote71980f02004-01-24 18:18:54 +0000242 VG_(message)(Vg_DebugMsg,
243 " sanity: %d cheap, %d expensive checks.",
nethercote297effd2004-08-02 15:07:57 +0000244 sanity_fast_count, sanity_slow_count );
nethercote71980f02004-01-24 18:18:54 +0000245 VG_(print_ccall_stats)();
246}
247
248
249/*====================================================================*/
250/*=== Miscellaneous global functions ===*/
251/*====================================================================*/
252
nethercote04d0fbc2004-01-26 16:48:06 +0000253/* Start debugger and get it to attach to this process. Called if the
254 user requests this service after an error has been shown, so she can
nethercote71980f02004-01-24 18:18:54 +0000255 poke around and look at parameters, memory, etc. You can't
nethercote04d0fbc2004-01-26 16:48:06 +0000256 meaningfully get the debugger to continue the program, though; to
257 continue, quit the debugger. */
258void VG_(start_debugger) ( Int tid )
nethercote71980f02004-01-24 18:18:54 +0000259{
260 Int pid;
261
262 if ((pid = fork()) == 0) {
263 ptrace(PTRACE_TRACEME, 0, NULL, NULL);
264 VG_(kkill)(VG_(getpid)(), VKI_SIGSTOP);
265
266 } else if (pid > 0) {
267 struct user_regs_struct regs;
268 Int status;
269 Int res;
270
271 if (VG_(is_running_thread)( tid )) {
fitzhardinged65dcad2004-03-13 02:06:58 +0000272 regs.cs = VG_(baseBlock)[VGOFF_(m_cs)];
273 regs.ss = VG_(baseBlock)[VGOFF_(m_ss)];
274 regs.ds = VG_(baseBlock)[VGOFF_(m_ds)];
275 regs.es = VG_(baseBlock)[VGOFF_(m_es)];
276 regs.fs = VG_(baseBlock)[VGOFF_(m_fs)];
277 regs.gs = VG_(baseBlock)[VGOFF_(m_gs)];
nethercote71980f02004-01-24 18:18:54 +0000278 regs.eax = VG_(baseBlock)[VGOFF_(m_eax)];
279 regs.ebx = VG_(baseBlock)[VGOFF_(m_ebx)];
280 regs.ecx = VG_(baseBlock)[VGOFF_(m_ecx)];
281 regs.edx = VG_(baseBlock)[VGOFF_(m_edx)];
282 regs.esi = VG_(baseBlock)[VGOFF_(m_esi)];
283 regs.edi = VG_(baseBlock)[VGOFF_(m_edi)];
284 regs.ebp = VG_(baseBlock)[VGOFF_(m_ebp)];
285 regs.esp = VG_(baseBlock)[VGOFF_(m_esp)];
286 regs.eflags = VG_(baseBlock)[VGOFF_(m_eflags)];
287 regs.eip = VG_(baseBlock)[VGOFF_(m_eip)];
288 } else {
289 ThreadState* tst = & VG_(threads)[ tid ];
290
fitzhardinged65dcad2004-03-13 02:06:58 +0000291 regs.cs = tst->m_cs;
292 regs.ss = tst->m_ss;
293 regs.ds = tst->m_ds;
294 regs.es = tst->m_es;
295 regs.fs = tst->m_fs;
296 regs.gs = tst->m_gs;
nethercote71980f02004-01-24 18:18:54 +0000297 regs.eax = tst->m_eax;
298 regs.ebx = tst->m_ebx;
299 regs.ecx = tst->m_ecx;
300 regs.edx = tst->m_edx;
301 regs.esi = tst->m_esi;
302 regs.edi = tst->m_edi;
303 regs.ebp = tst->m_ebp;
304 regs.esp = tst->m_esp;
305 regs.eflags = tst->m_eflags;
306 regs.eip = tst->m_eip;
307 }
308
309 if ((res = VG_(waitpid)(pid, &status, 0)) == pid &&
310 WIFSTOPPED(status) && WSTOPSIG(status) == SIGSTOP &&
311 ptrace(PTRACE_SETREGS, pid, NULL, &regs) == 0 &&
thughes1d160052004-04-21 15:39:57 +0000312 kill(pid, SIGSTOP) == 0 &&
313 ptrace(PTRACE_DETACH, pid, NULL, 0) == 0) {
nethercote04d0fbc2004-01-26 16:48:06 +0000314 Char pidbuf[15];
315 Char file[30];
316 Char buf[100];
317 Char *bufptr;
318 Char *cmdptr;
319
320 VG_(sprintf)(pidbuf, "%d", pid);
321 VG_(sprintf)(file, "/proc/%d/fd/%d", pid, VG_(clexecfd));
322
323 bufptr = buf;
324 cmdptr = VG_(clo_db_command);
325
326 while (*cmdptr) {
327 switch (*cmdptr) {
328 case '%':
329 switch (*++cmdptr) {
330 case 'f':
331 VG_(memcpy)(bufptr, file, VG_(strlen)(file));
332 bufptr += VG_(strlen)(file);
333 cmdptr++;
334 break;
335 case 'p':
336 VG_(memcpy)(bufptr, pidbuf, VG_(strlen)(pidbuf));
337 bufptr += VG_(strlen)(pidbuf);
338 cmdptr++;
339 break;
340 default:
341 *bufptr++ = *cmdptr++;
342 break;
343 }
344 break;
345 default:
346 *bufptr++ = *cmdptr++;
347 break;
348 }
349 }
350
351 *bufptr++ = '\0';
352
353 VG_(message)(Vg_UserMsg, "starting debugger with cmd: %s", buf);
nethercote71980f02004-01-24 18:18:54 +0000354 res = VG_(system)(buf);
355 if (res == 0) {
356 VG_(message)(Vg_UserMsg, "");
357 VG_(message)(Vg_UserMsg,
nethercote04d0fbc2004-01-26 16:48:06 +0000358 "Debugger has detached. Valgrind regains control. We continue.");
nethercote71980f02004-01-24 18:18:54 +0000359 } else {
360 VG_(message)(Vg_UserMsg, "Apparently failed!");
361 VG_(message)(Vg_UserMsg, "");
362 }
363 }
364
365 VG_(kkill)(pid, VKI_SIGKILL);
366 VG_(waitpid)(pid, &status, 0);
367 }
368}
369
370
371/* Print some helpful-ish text about unimplemented things, and give
372 up. */
373void VG_(unimplemented) ( Char* msg )
374{
375 VG_(message)(Vg_UserMsg, "");
376 VG_(message)(Vg_UserMsg,
377 "Valgrind detected that your program requires");
378 VG_(message)(Vg_UserMsg,
379 "the following unimplemented functionality:");
380 VG_(message)(Vg_UserMsg, " %s", msg);
381 VG_(message)(Vg_UserMsg,
382 "This may be because the functionality is hard to implement,");
383 VG_(message)(Vg_UserMsg,
384 "or because no reasonable program would behave this way,");
385 VG_(message)(Vg_UserMsg,
386 "or because nobody has yet needed it. In any case, let us know at");
387 VG_(message)(Vg_UserMsg,
388 "%s and/or try to work around the problem, if you can.", VG_BUGS_TO);
389 VG_(message)(Vg_UserMsg,
390 "");
391 VG_(message)(Vg_UserMsg,
392 "Valgrind has to exit now. Sorry. Bye!");
393 VG_(message)(Vg_UserMsg,
394 "");
395 VG_(pp_sched_status)();
396 VG_(exit)(1);
397}
398
399Addr VG_(get_stack_pointer) ( void )
400{
401 return VG_(baseBlock)[VGOFF_(m_esp)];
402}
403
404/* Debugging thing .. can be called from assembly with OYNK macro. */
405void VG_(oynk) ( Int n )
406{
407 OINK(n);
408}
409
410/* Initialize the PID and PGRP of scheduler LWP; this is also called
411 in any new children after fork. */
412static void newpid(ThreadId unused)
413{
414 /* PID of scheduler LWP */
415 VG_(main_pid) = VG_(getpid)();
416 VG_(main_pgrp) = VG_(getpgrp)();
417}
418
419/*====================================================================*/
420/*=== Check we were launched by stage 1 ===*/
421/*====================================================================*/
422
423/* Look for our AUXV table */
nethercote31779c72004-07-30 21:50:15 +0000424int scan_auxv(void)
nethercote71980f02004-01-24 18:18:54 +0000425{
426 const struct ume_auxv *auxv = find_auxv((int *)ume_exec_esp);
nethercote31779c72004-07-30 21:50:15 +0000427 int padfile = -1, found = 0;
nethercote71980f02004-01-24 18:18:54 +0000428
429 for (; auxv->a_type != AT_NULL; auxv++)
430 switch(auxv->a_type) {
431 case AT_UME_PADFD:
nethercote31779c72004-07-30 21:50:15 +0000432 padfile = auxv->u.a_val;
nethercote71980f02004-01-24 18:18:54 +0000433 found |= 1;
434 break;
435
436 case AT_UME_EXECFD:
437 VG_(vgexecfd) = auxv->u.a_val;
438 found |= 2;
439 break;
440 }
441
nethercote361a14e2004-07-26 11:11:56 +0000442 if ( found != (1|2) ) {
443 fprintf(stderr, "valgrind: stage2 must be launched by stage1\n");
nethercote71980f02004-01-24 18:18:54 +0000444 exit(127);
445 }
nethercote31779c72004-07-30 21:50:15 +0000446 vg_assert(padfile >= 0);
447 return padfile;
nethercote71980f02004-01-24 18:18:54 +0000448}
449
450
451/*====================================================================*/
452/*=== Address space determination ===*/
453/*====================================================================*/
454
nethercote31779c72004-07-30 21:50:15 +0000455static void layout_remaining_space(Addr argc_addr, float ratio)
nethercote71980f02004-01-24 18:18:54 +0000456{
nethercote31779c72004-07-30 21:50:15 +0000457 Int ires;
458 void* vres;
459 addr_t client_size, shadow_size;
nethercote71980f02004-01-24 18:18:54 +0000460
nethercote31779c72004-07-30 21:50:15 +0000461 VG_(valgrind_base) = (addr_t)&kickstart_base;
462 VG_(valgrind_end) = ROUNDUP(argc_addr, 0x10000); // stack
nethercote71980f02004-01-24 18:18:54 +0000463
nethercote31779c72004-07-30 21:50:15 +0000464 // This gives the client the largest possible address space while
465 // taking into account the tool's shadow needs.
466 client_size = ROUNDDN((VG_(valgrind_base)-REDZONE_SIZE) / (1.+ratio),
nethercote71980f02004-01-24 18:18:54 +0000467 CLIENT_SIZE_MULTIPLE);
nethercote31779c72004-07-30 21:50:15 +0000468 VG_(client_base) = CLIENT_BASE;
nethercote71980f02004-01-24 18:18:54 +0000469 VG_(client_end) = VG_(client_base) + client_size;
nethercotee2097312004-06-27 12:29:56 +0000470 /* where !FIXED mmap goes */
nethercotebc7b4f42004-07-26 12:44:35 +0000471 VG_(client_mapbase) = VG_(client_base) +
472 PGROUNDDN((addr_t)(client_size * CLIENT_HEAP_PROPORTION));
nethercote71980f02004-01-24 18:18:54 +0000473
nethercote31779c72004-07-30 21:50:15 +0000474 shadow_size = PGROUNDUP(client_size * ratio);
475 VG_(shadow_base) = VG_(client_end) + REDZONE_SIZE;
476 VG_(shadow_end) = VG_(shadow_base) + shadow_size;
nethercote71980f02004-01-24 18:18:54 +0000477
nethercotee2097312004-06-27 12:29:56 +0000478#define SEGSIZE(a,b) ((VG_(b) - VG_(a))/(1024*1024))
479
nethercote71980f02004-01-24 18:18:54 +0000480 if (0)
nethercotee2097312004-06-27 12:29:56 +0000481 VG_(printf)(
482 "client_base %8x (%dMB)\n"
483 "client_mapbase %8x (%dMB)\n"
484 "client_end %8x (%dMB)\n"
485 "shadow_base %8x (%dMB)\n"
486 "shadow_end %8x (%dMB)\n"
487 "valgrind_base %8x (%dMB)\n"
nethercotee2097312004-06-27 12:29:56 +0000488 "valgrind_end %8x\n",
489 VG_(client_base), SEGSIZE(client_base, client_mapbase),
490 VG_(client_mapbase), SEGSIZE(client_mapbase, client_end),
491 VG_(client_end), SEGSIZE(client_end, shadow_base),
492 VG_(shadow_base), SEGSIZE(shadow_base, shadow_end),
493 VG_(shadow_end), SEGSIZE(shadow_end, valgrind_base),
nethercotec314eba2004-07-15 12:59:41 +0000494 VG_(valgrind_base), SEGSIZE(valgrind_base, valgrind_end),
nethercotee2097312004-06-27 12:29:56 +0000495 VG_(valgrind_end)
496 );
497
498#undef SEGSIZE
nethercote71980f02004-01-24 18:18:54 +0000499
500 // Ban redzone
nethercotee567e702004-07-10 17:49:17 +0000501 vres = mmap((void *)VG_(client_end), REDZONE_SIZE, PROT_NONE,
502 MAP_FIXED|MAP_ANON|MAP_PRIVATE, -1, 0);
503 vg_assert((void*)-1 != vres);
nethercote71980f02004-01-24 18:18:54 +0000504
505 // Make client hole
nethercotee567e702004-07-10 17:49:17 +0000506 ires = munmap((void*)VG_(client_base), client_size);
507 vg_assert(0 == ires);
nethercote71980f02004-01-24 18:18:54 +0000508
509 // Map shadow memory.
510 // Initially all inaccessible, incrementally initialized as it is used
nethercotee567e702004-07-10 17:49:17 +0000511 if (shadow_size != 0) {
512 vres = mmap((char *)VG_(shadow_base), shadow_size, PROT_NONE,
513 MAP_PRIVATE|MAP_ANON|MAP_FIXED, -1, 0);
514 vg_assert((void*)-1 != vres);
515 }
nethercote71980f02004-01-24 18:18:54 +0000516}
517
518/*====================================================================*/
519/*=== Command line setup ===*/
520/*====================================================================*/
521
522/* Nb: malloc'd memory never freed -- kept throughout like argv, envp */
523static char* get_file_clo(char* dir)
524{
525# define FLEN 512
526 Int fd, n;
527 struct stat s1;
528 char* f_clo = NULL;
529 char filename[FLEN];
530
531 snprintf(filename, FLEN, "%s/.valgrindrc", ( NULL == dir ? "" : dir ) );
532 fd = VG_(open)(filename, 0, VKI_S_IRUSR);
533 if ( fd > 0 ) {
534 if ( 0 == fstat(fd, &s1) ) {
535 f_clo = malloc(s1.st_size+1);
536 vg_assert(f_clo);
537 n = read(fd, f_clo, s1.st_size);
538 if (n == -1) n = 0;
539 f_clo[n] = '\0';
540 }
541 close(fd);
542 }
543 return f_clo;
544# undef FLEN
545}
546
nethercotee2097312004-06-27 12:29:56 +0000547#define ISSPACE(cc) ((cc) == ' ' || (cc) == '\t' || (cc) == '\n')
548
nethercote71980f02004-01-24 18:18:54 +0000549static Int count_args(char* s)
550{
551 Int n = 0;
552 if (s) {
553 char* cp = s;
554 while (True) {
555 // We have alternating sequences: blanks, non-blanks, blanks...
556 // count the non-blanks sequences.
557 while ( ISSPACE(*cp) ) cp++;
558 if ( !*cp ) break;
559 n++;
560 while ( !ISSPACE(*cp) && *cp ) cp++;
561 }
562 }
563 return n;
564}
565
566/* add args out of environment, skipping multiple spaces and -- args */
567static char** copy_args( char* s, char** to )
568{
569 if (s) {
570 char* cp = s;
571 while (True) {
572 // We have alternating sequences: blanks, non-blanks, blanks...
573 // copy the non-blanks sequences, and add terminating '\0'
574 while ( ISSPACE(*cp) ) cp++;
575 if ( !*cp ) break;
576 *to++ = cp;
577 while ( !ISSPACE(*cp) && *cp ) cp++;
578 if ( *cp ) *cp++ = '\0'; // terminate if necessary
579 if (VG_STREQ(to[-1], "--")) to--; // undo any '--' arg
580 }
581 }
582 return to;
583}
584
nethercotee2097312004-06-27 12:29:56 +0000585#undef ISSPACE
586
nethercote71980f02004-01-24 18:18:54 +0000587// Augment command line with arguments from environment and .valgrindrc
588// files.
589static void augment_command_line(Int* vg_argc_inout, char*** vg_argv_inout)
590{
591 int vg_argc = *vg_argc_inout;
592 char** vg_argv = *vg_argv_inout;
593
594 char* env_clo = getenv(VALGRINDOPTS);
595 char* f1_clo = get_file_clo( getenv("HOME") );
596 char* f2_clo = get_file_clo(".");
597
598 /* copy any extra args from file or environment, if present */
599 if ( (env_clo && *env_clo) || (f1_clo && *f1_clo) || (f2_clo && *f2_clo) ) {
600 /* ' ' separated extra options */
601 char **from;
602 char **to;
603 int env_arg_count, f1_arg_count, f2_arg_count;
604
605 env_arg_count = count_args(env_clo);
606 f1_arg_count = count_args(f1_clo);
607 f2_arg_count = count_args(f2_clo);
608
609 if (0)
610 printf("extra-argc=%d %d %d\n",
611 env_arg_count, f1_arg_count, f2_arg_count);
612
613 /* +2: +1 for null-termination, +1 for added '--' */
614 from = vg_argv;
615 vg_argv = malloc( (vg_argc + env_arg_count + f1_arg_count
616 + f2_arg_count + 2) * sizeof(char **));
nethercote7c018f42004-07-17 16:40:50 +0000617 vg_assert(vg_argv);
nethercote71980f02004-01-24 18:18:54 +0000618 to = vg_argv;
619
620 /* copy argv[0] */
621 *to++ = *from++;
622
623 /* Copy extra args from env var and file, in the order: ~/.valgrindrc,
624 * $VALGRIND_OPTS, ./.valgrindrc -- more local options are put later
625 * to override less local ones. */
626 to = copy_args(f1_clo, to);
627 to = copy_args(env_clo, to);
628 to = copy_args(f2_clo, to);
629
630 /* copy original arguments, stopping at command or -- */
631 while (*from) {
632 if (**from != '-')
633 break;
634 if (VG_STREQ(*from, "--")) {
635 from++; /* skip -- */
636 break;
637 }
638 *to++ = *from++;
639 }
640
641 /* add -- */
642 *to++ = "--";
643
644 vg_argc = to - vg_argv;
645
646 /* copy rest of original command line, then NULL */
647 while (*from) *to++ = *from++;
648 *to = NULL;
649 }
650
651 *vg_argc_inout = vg_argc;
652 *vg_argv_inout = vg_argv;
653}
654
655static void get_command_line( int argc, char** argv,
656 Int* vg_argc_out, Char*** vg_argv_out,
657 char*** cl_argv_out )
658{
659 int vg_argc;
660 char** vg_argv;
661 char** cl_argv;
662 char* env_clo = getenv(VALGRINDCLO);
663
664 if (env_clo != NULL && *env_clo != '\0') {
665 char *cp;
666 char **cpp;
667
668 /* OK, we're getting all our arguments from the environment - the
669 entire command line belongs to the client (including argv[0]) */
670 vg_argc = 1; /* argv[0] */
671 for (cp = env_clo; *cp; cp++)
672 if (*cp == '\01')
673 vg_argc++;
674
675 vg_argv = malloc(sizeof(char **) * (vg_argc + 1));
nethercote7c018f42004-07-17 16:40:50 +0000676 vg_assert(vg_argv);
nethercote71980f02004-01-24 18:18:54 +0000677
678 cpp = vg_argv;
679
680 *cpp++ = "valgrind"; /* nominal argv[0] */
681 *cpp++ = env_clo;
682
683 for (cp = env_clo; *cp; cp++) {
684 if (*cp == '\01') {
685 *cp++ = '\0'; /* chop it up in place */
686 *cpp++ = cp;
687 }
688 }
689 *cpp = NULL;
690 cl_argv = argv;
691
692 } else {
693 /* Count the arguments on the command line. */
694 vg_argv = argv;
695
696 for (vg_argc = 1; vg_argc < argc; vg_argc++) {
697 if (argv[vg_argc][0] != '-') /* exe name */
698 break;
699 if (VG_STREQ(argv[vg_argc], "--")) { /* dummy arg */
700 vg_argc++;
701 break;
702 }
703 }
704 cl_argv = &argv[vg_argc];
705
706 /* Get extra args from VALGRIND_OPTS and .valgrindrc files.
707 * Note we don't do this if getting args from VALGRINDCLO. */
708 augment_command_line(&vg_argc, &vg_argv);
709 }
710
711 if (0) {
712 Int i;
713 for (i = 0; i < vg_argc; i++)
714 printf("vg_argv[%d]=\"%s\"\n", i, vg_argv[i]);
715 }
716
717 *vg_argc_out = vg_argc;
718 *vg_argv_out = (Char**)vg_argv;
719 *cl_argv_out = cl_argv;
720}
721
722
723/*====================================================================*/
724/*=== Environment and stack setup ===*/
725/*====================================================================*/
726
727/* Scan a colon-separated list, and call a function on each element.
728 The string must be mutable, because we insert a temporary '\0', but
thughes4ad52d02004-06-27 17:37:21 +0000729 the string will end up unmodified. (*func) should return True if it
nethercote71980f02004-01-24 18:18:54 +0000730 doesn't need to see any more.
thughes4ad52d02004-06-27 17:37:21 +0000731
732 This routine will return True if (*func) returns True and False if
733 it reaches the end of the list without that happening.
nethercote71980f02004-01-24 18:18:54 +0000734*/
thughes4ad52d02004-06-27 17:37:21 +0000735static Bool scan_colsep(char *colsep, Bool (*func)(const char *))
nethercote71980f02004-01-24 18:18:54 +0000736{
737 char *cp, *entry;
738 int end;
739
740 if (colsep == NULL ||
741 *colsep == '\0')
thughes4ad52d02004-06-27 17:37:21 +0000742 return False;
nethercote71980f02004-01-24 18:18:54 +0000743
744 entry = cp = colsep;
745
746 do {
747 end = (*cp == '\0');
748
749 if (*cp == ':' || *cp == '\0') {
750 char save = *cp;
751
752 *cp = '\0';
thughes21942d92004-07-12 09:35:37 +0000753 if ((*func)(entry)) {
754 *cp = save;
thughes4ad52d02004-06-27 17:37:21 +0000755 return True;
thughes21942d92004-07-12 09:35:37 +0000756 }
nethercote71980f02004-01-24 18:18:54 +0000757 *cp = save;
758 entry = cp+1;
759 }
760 cp++;
761 } while(!end);
thughes4ad52d02004-06-27 17:37:21 +0000762
763 return False;
764}
765
766static Bool contains(const char *p) {
767 if (VG_STREQ(p, VG_(libdir))) {
768 return True;
769 }
770 return False;
nethercote71980f02004-01-24 18:18:54 +0000771}
772
773/* Prepare the client's environment. This is basically a copy of our
774 environment, except:
775 1. LD_LIBRARY_PATH=$VALGRINDLIB:$LD_LIBRARY_PATH
776 2. LD_PRELOAD=$VALGRINDLIB/vg_inject.so:($VALGRINDLIB/vgpreload_TOOL.so:)?$LD_PRELOAD
777
778 If any of these is missing, then it is added.
779
780 Yummy. String hacking in C.
781
782 If this needs to handle any more variables it should be hacked
783 into something table driven.
784 */
785static char **fix_environment(char **origenv, const char *preload)
786{
787 static const char inject_so[] = "vg_inject.so";
788 static const char ld_library_path[] = "LD_LIBRARY_PATH=";
789 static const char ld_preload[] = "LD_PRELOAD=";
790 static const char valgrind_clo[] = VALGRINDCLO "=";
791 static const int ld_library_path_len = sizeof(ld_library_path)-1;
792 static const int ld_preload_len = sizeof(ld_preload)-1;
793 static const int valgrind_clo_len = sizeof(valgrind_clo)-1;
794 int ld_preload_done = 0;
795 int ld_library_path_done = 0;
796 char *inject_path;
797 int inject_path_len;
798 int vgliblen = strlen(VG_(libdir));
799 char **cpp;
800 char **ret;
801 int envc;
802 const int preloadlen = (preload == NULL) ? 0 : strlen(preload);
803
804 /* Find the vg_inject.so; also make room for the tool preload
805 library */
806 inject_path_len = sizeof(inject_so) + vgliblen + preloadlen + 16;
807 inject_path = malloc(inject_path_len);
nethercote7c018f42004-07-17 16:40:50 +0000808 vg_assert(inject_path);
nethercote71980f02004-01-24 18:18:54 +0000809
810 if (preload)
811 snprintf(inject_path, inject_path_len, "%s/%s:%s",
812 VG_(libdir), inject_so, preload);
813 else
814 snprintf(inject_path, inject_path_len, "%s/%s",
815 VG_(libdir), inject_so);
816
817 /* Count the original size of the env */
818 envc = 0; /* trailing NULL */
819 for (cpp = origenv; cpp && *cpp; cpp++)
820 envc++;
821
822 /* Allocate a new space */
823 ret = malloc(sizeof(char *) * (envc+3+1)); /* 3 new entries + NULL */
nethercote7c018f42004-07-17 16:40:50 +0000824 vg_assert(ret);
nethercote71980f02004-01-24 18:18:54 +0000825
826 /* copy it over */
827 for (cpp = ret; *origenv; )
828 *cpp++ = *origenv++;
829 *cpp = NULL;
830
831 vg_assert(envc == (cpp - ret));
832
833 /* Walk over the new environment, mashing as we go */
834 for (cpp = ret; cpp && *cpp; cpp++) {
835 if (memcmp(*cpp, ld_library_path, ld_library_path_len) == 0) {
nethercote71980f02004-01-24 18:18:54 +0000836 /* If the LD_LIBRARY_PATH already contains libdir, then don't
837 bother adding it again, even if it isn't the first (it
838 seems that the Java runtime will keep reexecing itself
839 unless its paths are at the front of LD_LIBRARY_PATH) */
thughes4ad52d02004-06-27 17:37:21 +0000840 if (!scan_colsep(*cpp + ld_library_path_len, contains)) {
nethercote71980f02004-01-24 18:18:54 +0000841 int len = strlen(*cpp) + vgliblen*2 + 16;
842 char *cp = malloc(len);
nethercote7c018f42004-07-17 16:40:50 +0000843 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000844
845 snprintf(cp, len, "%s%s:%s",
846 ld_library_path, VG_(libdir),
847 (*cpp)+ld_library_path_len);
848
849 *cpp = cp;
850 }
851
852 ld_library_path_done = 1;
853 } else if (memcmp(*cpp, ld_preload, ld_preload_len) == 0) {
854 int len = strlen(*cpp) + inject_path_len;
855 char *cp = malloc(len);
nethercote7c018f42004-07-17 16:40:50 +0000856 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000857
858 snprintf(cp, len, "%s%s:%s",
859 ld_preload, inject_path, (*cpp)+ld_preload_len);
860
861 *cpp = cp;
862
863 ld_preload_done = 1;
864 } else if (memcmp(*cpp, valgrind_clo, valgrind_clo_len) == 0) {
865 *cpp = "";
866 }
867 }
868
869 /* Add the missing bits */
870
871 if (!ld_library_path_done) {
872 int len = ld_library_path_len + vgliblen*2 + 16;
873 char *cp = malloc(len);
nethercote7c018f42004-07-17 16:40:50 +0000874 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000875
876 snprintf(cp, len, "%s%s", ld_library_path, VG_(libdir));
877
878 ret[envc++] = cp;
879 }
880
881 if (!ld_preload_done) {
882 int len = ld_preload_len + inject_path_len;
883 char *cp = malloc(len);
nethercote7c018f42004-07-17 16:40:50 +0000884 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000885
886 snprintf(cp, len, "%s%s",
887 ld_preload, inject_path);
888
889 ret[envc++] = cp;
890 }
891
892 ret[envc] = NULL;
893
894 return ret;
895}
896
897extern char **environ; /* our environment */
898//#include <error.h>
899
900/* Add a string onto the string table, and return its address */
901static char *copy_str(char **tab, const char *str)
902{
903 char *cp = *tab;
904 char *orig = cp;
905
906 while(*str)
907 *cp++ = *str++;
908 *cp++ = '\0';
909
910 if (0)
nethercotef84f6952004-07-15 14:58:33 +0000911 printf("copied %p \"%s\" len %d\n", orig, orig, cp-orig);
nethercote71980f02004-01-24 18:18:54 +0000912
913 *tab = cp;
914
915 return orig;
916}
917
918/*
919 This sets up the client's initial stack, containing the args,
920 environment and aux vector.
921
922 The format of the stack is:
923
924 higher address +-----------------+
925 | Trampoline code |
926 +-----------------+
927 | |
928 : string table :
929 | |
930 +-----------------+
931 | AT_NULL |
932 - -
933 | auxv |
934 +-----------------+
935 | NULL |
936 - -
937 | envp |
938 +-----------------+
939 | NULL |
940 - -
941 | argv |
942 +-----------------+
943 | argc |
944 lower address +-----------------+ <- esp
945 | undefined |
946 : :
947 */
948static Addr setup_client_stack(char **orig_argv, char **orig_envp,
949 const struct exeinfo *info,
950 UInt** client_auxv)
951{
nethercotee567e702004-07-10 17:49:17 +0000952 void* res;
nethercote71980f02004-01-24 18:18:54 +0000953 char **cpp;
954 char *strtab; /* string table */
955 char *stringbase;
956 addr_t *ptr;
957 struct ume_auxv *auxv;
958 const struct ume_auxv *orig_auxv;
959 const struct ume_auxv *cauxv;
960 unsigned stringsize; /* total size of strings in bytes */
961 unsigned auxsize; /* total size of auxv in bytes */
962 int argc; /* total argc */
963 int envc; /* total number of env vars */
964 unsigned stacksize; /* total client stack size */
965 addr_t cl_esp; /* client stack base (initial esp) */
966
967 /* use our own auxv as a prototype */
968 orig_auxv = find_auxv(ume_exec_esp);
969
970 /* ==================== compute sizes ==================== */
971
972 /* first of all, work out how big the client stack will be */
973 stringsize = 0;
974
975 /* paste on the extra args if the loader needs them (ie, the #!
976 interpreter and its argument) */
977 argc = 0;
nethercoted6a56872004-07-26 15:32:47 +0000978 if (info->interp_name != NULL) {
nethercote71980f02004-01-24 18:18:54 +0000979 argc++;
nethercoted6a56872004-07-26 15:32:47 +0000980 stringsize += strlen(info->interp_name) + 1;
nethercote71980f02004-01-24 18:18:54 +0000981 }
nethercoted6a56872004-07-26 15:32:47 +0000982 if (info->interp_args != NULL) {
nethercote71980f02004-01-24 18:18:54 +0000983 argc++;
nethercoted6a56872004-07-26 15:32:47 +0000984 stringsize += strlen(info->interp_args) + 1;
nethercote71980f02004-01-24 18:18:54 +0000985 }
986
987 /* now scan the args we're given... */
988 for (cpp = orig_argv; *cpp; cpp++) {
989 argc++;
990 stringsize += strlen(*cpp) + 1;
991 }
992
993 /* ...and the environment */
994 envc = 0;
995 for (cpp = orig_envp; cpp && *cpp; cpp++) {
996 envc++;
997 stringsize += strlen(*cpp) + 1;
998 }
999
1000 /* now, how big is the auxv? */
1001 auxsize = sizeof(*auxv); /* there's always at least one entry: AT_NULL */
1002 for (cauxv = orig_auxv; cauxv->a_type != AT_NULL; cauxv++) {
1003 if (cauxv->a_type == AT_PLATFORM)
1004 stringsize += strlen(cauxv->u.a_ptr) + 1;
1005 auxsize += sizeof(*cauxv);
1006 }
1007
1008 /* OK, now we know how big the client stack is */
1009 stacksize =
1010 sizeof(int) + /* argc */
1011 sizeof(char **)*argc + /* argv */
1012 sizeof(char **) + /* terminal NULL */
1013 sizeof(char **)*envc + /* envp */
1014 sizeof(char **) + /* terminal NULL */
1015 auxsize + /* auxv */
1016 ROUNDUP(stringsize, sizeof(int)) +/* strings (aligned) */
1017 VKI_BYTES_PER_PAGE; /* page for trampoline code */
1018
nethercotef84f6952004-07-15 14:58:33 +00001019 // decide where stack goes!
1020 VG_(clstk_end) = VG_(client_end);
1021
1022 VG_(client_trampoline_code) = VG_(clstk_end) - VKI_BYTES_PER_PAGE;
1023
nethercote71980f02004-01-24 18:18:54 +00001024 /* cl_esp is the client's stack pointer */
nethercotef84f6952004-07-15 14:58:33 +00001025 cl_esp = VG_(clstk_end) - stacksize;
nethercote71980f02004-01-24 18:18:54 +00001026 cl_esp = ROUNDDN(cl_esp, 16); /* make stack 16 byte aligned */
1027
nethercote71980f02004-01-24 18:18:54 +00001028 /* base of the string table (aligned) */
1029 stringbase = strtab = (char *)(VG_(client_trampoline_code) - ROUNDUP(stringsize, sizeof(int)));
1030
1031 VG_(clstk_base) = PGROUNDDN(cl_esp);
nethercote71980f02004-01-24 18:18:54 +00001032
nethercote5ee67ca2004-06-22 14:00:09 +00001033 if (0)
1034 printf("stringsize=%d auxsize=%d stacksize=%d\n"
1035 "clstk_base %x\n"
1036 "clstk_end %x\n",
1037 stringsize, auxsize, stacksize, VG_(clstk_base), VG_(clstk_end));
1038
1039
nethercote71980f02004-01-24 18:18:54 +00001040 /* ==================== allocate space ==================== */
1041
1042 /* allocate a stack - mmap enough space for the stack */
nethercotef84f6952004-07-15 14:58:33 +00001043 res = mmap((void *)PGROUNDDN(cl_esp), VG_(clstk_end) - PGROUNDDN(cl_esp),
nethercotee567e702004-07-10 17:49:17 +00001044 PROT_READ | PROT_WRITE | PROT_EXEC,
1045 MAP_PRIVATE | MAP_ANON | MAP_FIXED, -1, 0);
1046 vg_assert((void*)-1 != res);
nethercote71980f02004-01-24 18:18:54 +00001047
1048 /* ==================== copy client stack ==================== */
1049
1050 ptr = (addr_t *)cl_esp;
1051
1052 /* --- argc --- */
1053 *ptr++ = argc; /* client argc */
1054
1055 /* --- argv --- */
nethercoted6a56872004-07-26 15:32:47 +00001056 if (info->interp_name) {
1057 *ptr++ = (addr_t)copy_str(&strtab, info->interp_name);
1058 free(info->interp_name);
nethercote71980f02004-01-24 18:18:54 +00001059 }
nethercoted6a56872004-07-26 15:32:47 +00001060 if (info->interp_args) {
1061 *ptr++ = (addr_t)copy_str(&strtab, info->interp_args);
1062 free(info->interp_args);
nethercote71980f02004-01-24 18:18:54 +00001063 }
1064 for (cpp = orig_argv; *cpp; ptr++, cpp++) {
1065 *ptr = (addr_t)copy_str(&strtab, *cpp);
1066 }
1067 *ptr++ = 0;
1068
1069 /* --- envp --- */
1070 VG_(client_envp) = (Char **)ptr;
1071 for (cpp = orig_envp; cpp && *cpp; ptr++, cpp++)
1072 *ptr = (addr_t)copy_str(&strtab, *cpp);
1073 *ptr++ = 0;
1074
1075 /* --- auxv --- */
1076 auxv = (struct ume_auxv *)ptr;
1077 *client_auxv = (UInt *)auxv;
1078
1079 for (; orig_auxv->a_type != AT_NULL; auxv++, orig_auxv++) {
1080 /* copy the entry... */
1081 *auxv = *orig_auxv;
1082
1083 /* ...and fix up the copy */
1084 switch(auxv->a_type) {
1085 case AT_PHDR:
1086 if (info->phdr == 0)
1087 auxv->a_type = AT_IGNORE;
1088 else
1089 auxv->u.a_val = info->phdr;
1090 break;
1091
1092 case AT_PHNUM:
1093 if (info->phdr == 0)
1094 auxv->a_type = AT_IGNORE;
1095 else
1096 auxv->u.a_val = info->phnum;
1097 break;
1098
1099 case AT_BASE:
1100 if (info->interp_base == 0)
1101 auxv->a_type = AT_IGNORE;
1102 else
1103 auxv->u.a_val = info->interp_base;
1104 break;
1105
1106 case AT_PLATFORM: /* points to a platform description string */
1107 auxv->u.a_ptr = copy_str(&strtab, orig_auxv->u.a_ptr);
1108 break;
1109
1110 case AT_ENTRY:
1111 auxv->u.a_val = info->entry;
1112 break;
1113
1114 case AT_IGNORE:
1115 case AT_EXECFD:
1116 case AT_PHENT:
1117 case AT_PAGESZ:
1118 case AT_FLAGS:
1119 case AT_NOTELF:
1120 case AT_UID:
1121 case AT_EUID:
1122 case AT_GID:
1123 case AT_EGID:
1124 case AT_CLKTCK:
1125 case AT_HWCAP:
1126 case AT_FPUCW:
1127 case AT_DCACHEBSIZE:
1128 case AT_ICACHEBSIZE:
1129 case AT_UCACHEBSIZE:
1130 /* All these are pointerless, so we don't need to do anything
1131 about them. */
1132 break;
1133
1134 case AT_SECURE:
1135 /* If this is 1, then it means that this program is running
1136 suid, and therefore the dynamic linker should be careful
1137 about LD_PRELOAD, etc. However, since stage1 (the thing
1138 the kernel actually execve's) should never be SUID, and we
1139 need LD_PRELOAD/LD_LIBRARY_PATH to work for the client, we
1140 set AT_SECURE to 0. */
1141 auxv->u.a_val = 0;
1142 break;
1143
1144 case AT_SYSINFO:
1145 /* Leave this unmolested for now, but we'll update it later
1146 when we set up the client trampoline code page */
1147 break;
1148
1149 case AT_SYSINFO_EHDR:
1150 /* Trash this, because we don't reproduce it */
1151 auxv->a_type = AT_IGNORE;
1152 break;
1153
1154 default:
1155 /* stomp out anything we don't know about */
1156 if (0)
1157 printf("stomping auxv entry %d\n", auxv->a_type);
1158 auxv->a_type = AT_IGNORE;
1159 break;
1160
1161 }
1162 }
1163 *auxv = *orig_auxv;
1164 vg_assert(auxv->a_type == AT_NULL);
1165
nethercotef84f6952004-07-15 14:58:33 +00001166 /* --- trampoline page --- */
1167 VG_(memcpy)( (void *)VG_(client_trampoline_code),
1168 &VG_(trampoline_code_start), VG_(trampoline_code_length) );
1169
nethercote71980f02004-01-24 18:18:54 +00001170 vg_assert((strtab-stringbase) == stringsize);
1171
nethercote5ee67ca2004-06-22 14:00:09 +00001172 /* We know the initial ESP is pointing at argc/argv */
1173 VG_(client_argc) = *(Int*)cl_esp;
1174 VG_(client_argv) = (Char**)(cl_esp + sizeof(Int));
1175
nethercote71980f02004-01-24 18:18:54 +00001176 return cl_esp;
1177}
1178
1179/*====================================================================*/
1180/*=== Find executable ===*/
1181/*====================================================================*/
1182
thughes4ad52d02004-06-27 17:37:21 +00001183static const char* executable_name;
1184
1185static Bool match_executable(const char *entry) {
1186 char buf[strlen(entry) + strlen(executable_name) + 2];
1187
1188 /* empty PATH element means . */
1189 if (*entry == '\0')
1190 entry = ".";
1191
1192 snprintf(buf, sizeof(buf), "%s/%s", entry, executable_name);
1193
1194 if (access(buf, R_OK|X_OK) == 0) {
1195 executable_name = strdup(buf);
1196 vg_assert(NULL != executable_name);
1197 return True;
1198 }
1199 return False;
1200}
1201
nethercote71980f02004-01-24 18:18:54 +00001202static const char* find_executable(const char* exec)
1203{
1204 vg_assert(NULL != exec);
thughes4ad52d02004-06-27 17:37:21 +00001205 executable_name = exec;
1206 if (strchr(executable_name, '/') == NULL) {
nethercote71980f02004-01-24 18:18:54 +00001207 /* no '/' - we need to search the path */
1208 char *path = getenv("PATH");
thughes4ad52d02004-06-27 17:37:21 +00001209 scan_colsep(path, match_executable);
nethercote71980f02004-01-24 18:18:54 +00001210 }
thughes4ad52d02004-06-27 17:37:21 +00001211 return executable_name;
nethercote71980f02004-01-24 18:18:54 +00001212}
1213
1214
1215/*====================================================================*/
1216/*=== Loading tools ===*/
1217/*====================================================================*/
1218
1219static void list_tools(void)
1220{
1221 DIR *dir = opendir(VG_(libdir));
1222 struct dirent *de;
1223 int first = 1;
1224
1225 if (dir == NULL) {
1226 fprintf(stderr, "Can't open %s: %s (installation problem?)\n",
nethercotef4928da2004-06-15 10:54:40 +00001227 VG_(libdir), strerror(errno));
nethercote71980f02004-01-24 18:18:54 +00001228 return;
1229 }
1230
nethercotef4928da2004-06-15 10:54:40 +00001231 while ((de = readdir(dir)) != NULL) {
nethercote71980f02004-01-24 18:18:54 +00001232 int len = strlen(de->d_name);
1233
1234 /* look for vgskin_TOOL.so names */
1235 if (len > (7+1+3) && /* "vgskin_" + at least 1-char toolname + ".so" */
nethercotef4928da2004-06-15 10:54:40 +00001236 strncmp(de->d_name, "vgskin_", 7) == 0 &&
1237 VG_STREQ(de->d_name + len - 3, ".so")) {
1238 if (first) {
1239 fprintf(stderr, "Available tools:\n");
1240 first = 0;
1241 }
1242 de->d_name[len-3] = '\0';
1243 fprintf(stderr, "\t%s\n", de->d_name+7);
nethercote71980f02004-01-24 18:18:54 +00001244 }
1245 }
1246
1247 closedir(dir);
1248
1249 if (first)
nethercotef4928da2004-06-15 10:54:40 +00001250 fprintf(stderr, "No tools available in \"%s\" (installation problem?)\n",
1251 VG_(libdir));
nethercote71980f02004-01-24 18:18:54 +00001252}
1253
1254
1255/* Find and load a tool, and check it looks ok. Also looks to see if there's
1256 * a matching vgpreload_*.so file, and returns its name in *preloadpath. */
1257static void load_tool( const char *toolname, void** handle_out,
1258 ToolInfo** toolinfo_out, char **preloadpath_out )
1259{
1260 Bool ok;
1261 int len = strlen(VG_(libdir)) + strlen(toolname)*2 + 16;
1262 char buf[len];
1263 void* handle;
1264 ToolInfo* toolinfo;
1265 char* preloadpath = NULL;
1266 Int* vg_malloc_redzonep;
1267
1268 // XXX: allowing full paths for --tool option -- does it make sense?
1269 // Doesn't allow for vgpreload_<tool>.so.
1270
1271 if (strchr(toolname, '/') != 0) {
1272 /* toolname contains '/', and so must be a pathname */
1273 handle = dlopen(toolname, RTLD_NOW);
1274 } else {
1275 /* just try in the libdir */
1276 snprintf(buf, len, "%s/vgskin_%s.so", VG_(libdir), toolname);
1277 handle = dlopen(buf, RTLD_NOW);
1278
1279 if (handle != NULL) {
1280 snprintf(buf, len, "%s/vgpreload_%s.so", VG_(libdir), toolname);
1281 if (access(buf, R_OK) == 0) {
1282 preloadpath = strdup(buf);
1283 vg_assert(NULL != preloadpath);
1284 }
1285 }
1286 }
1287
1288 ok = (NULL != handle);
1289 if (!ok) {
1290 fprintf(stderr, "Can't open tool \"%s\": %s\n", toolname, dlerror());
1291 goto bad_load;
1292 }
1293
1294 toolinfo = dlsym(handle, "vgSkin_tool_info");
1295 ok = (NULL != toolinfo);
1296 if (!ok) {
1297 fprintf(stderr, "Tool \"%s\" doesn't define SK_(tool_info) - "
1298 "add VG_DETERMINE_INTERFACE_VERSION?\n", toolname);
1299 goto bad_load;
1300 }
1301
1302 ok = (toolinfo->sizeof_ToolInfo == sizeof(*toolinfo) &&
1303 toolinfo->interface_major_version == VG_CORE_INTERFACE_MAJOR_VERSION &&
1304 toolinfo->sk_pre_clo_init != NULL);
1305 if (!ok) {
1306 fprintf(stderr, "Error:\n"
1307 " Tool and core interface versions do not match.\n"
1308 " Interface version used by core is: %d.%d (size %d)\n"
1309 " Interface version used by tool is: %d.%d (size %d)\n"
1310 " The major version numbers must match.\n",
1311 VG_CORE_INTERFACE_MAJOR_VERSION,
1312 VG_CORE_INTERFACE_MINOR_VERSION,
1313 sizeof(*toolinfo),
1314 toolinfo->interface_major_version,
1315 toolinfo->interface_minor_version,
1316 toolinfo->sizeof_ToolInfo);
1317 fprintf(stderr, " You need to at least recompile, and possibly update,\n");
1318 if (VG_CORE_INTERFACE_MAJOR_VERSION > toolinfo->interface_major_version)
1319 fprintf(stderr, " your skin to work with this version of Valgrind.\n");
1320 else
1321 fprintf(stderr, " your version of Valgrind to work with this skin.\n");
1322 goto bad_load;
1323 }
1324
1325 // Set redzone size for V's allocator
1326 vg_malloc_redzonep = dlsym(handle, STR(VG_(vg_malloc_redzone_szB)));
1327 if ( NULL != vg_malloc_redzonep ) {
1328 VG_(vg_malloc_redzone_szB) = *vg_malloc_redzonep;
1329 }
1330
1331 vg_assert(NULL != handle && NULL != toolinfo);
1332 *handle_out = handle;
1333 *toolinfo_out = toolinfo;
1334 *preloadpath_out = preloadpath;
1335 return;
1336
1337
1338 bad_load:
1339 if (handle != NULL)
1340 dlclose(handle);
1341
nethercotef4928da2004-06-15 10:54:40 +00001342 fprintf(stderr, "valgrind: couldn't load tool\n");
nethercote71980f02004-01-24 18:18:54 +00001343 list_tools();
1344 exit(127);
1345}
1346
nethercotef4928da2004-06-15 10:54:40 +00001347
1348/*====================================================================*/
1349/*=== Command line errors ===*/
1350/*====================================================================*/
1351
1352static void abort_msg ( void )
1353{
nethercotef8548672004-06-21 12:42:35 +00001354 VG_(clo_log_to) = VgLogTo_Fd;
1355 VG_(clo_log_fd) = 2; /* stderr */
nethercotef4928da2004-06-15 10:54:40 +00001356}
1357
1358void VG_(bad_option) ( Char* opt )
1359{
1360 abort_msg();
1361 VG_(printf)("valgrind: Bad option `%s'; aborting.\n", opt);
1362 VG_(printf)("valgrind: Use --help for more information.\n");
1363 VG_(exit)(1);
1364}
1365
1366static void missing_tool_option ( void )
1367{
1368 abort_msg();
1369 VG_(printf)("valgrind: Missing --tool option\n");
1370 list_tools();
1371 VG_(printf)("valgrind: Use --help for more information.\n");
1372 VG_(exit)(1);
1373}
1374
1375static void missing_prog ( void )
1376{
1377 abort_msg();
1378 VG_(printf)("valgrind: no program specified\n");
1379 VG_(printf)("valgrind: Use --help for more information.\n");
1380 VG_(exit)(1);
1381}
1382
1383static void config_error ( Char* msg )
1384{
1385 abort_msg();
1386 VG_(printf)("valgrind: Startup or configuration error:\n %s\n", msg);
1387 VG_(printf)("valgrind: Unable to start up properly. Giving up.\n");
1388 VG_(exit)(1);
1389}
1390
1391
nethercote71980f02004-01-24 18:18:54 +00001392/*====================================================================*/
1393/*=== Loading the client ===*/
1394/*====================================================================*/
1395
nethercotef4928da2004-06-15 10:54:40 +00001396static void load_client(char* cl_argv[], const char* exec, Int need_help,
nethercote71980f02004-01-24 18:18:54 +00001397 /*out*/struct exeinfo* info, /*out*/Addr* client_eip)
1398{
1399 // If they didn't specify an executable with --exec, and didn't specify
1400 // --help, then use client argv[0] (searching $PATH if necessary).
nethercotef4928da2004-06-15 10:54:40 +00001401 if (NULL == exec && !need_help) {
nethercote71980f02004-01-24 18:18:54 +00001402 if (cl_argv[0] == NULL ||
1403 ( NULL == (exec = find_executable(cl_argv[0])) ) )
1404 {
nethercotef4928da2004-06-15 10:54:40 +00001405 missing_prog();
nethercote71980f02004-01-24 18:18:54 +00001406 }
1407 }
1408
1409 info->map_base = VG_(client_mapbase);
nethercote71980f02004-01-24 18:18:54 +00001410 info->exe_base = VG_(client_base);
1411 info->exe_end = VG_(client_end);
1412 info->argv = cl_argv;
1413
nethercotef4928da2004-06-15 10:54:40 +00001414 if (need_help) {
nethercote71980f02004-01-24 18:18:54 +00001415 VG_(clexecfd) = -1;
nethercoteea147e72004-07-26 15:43:57 +00001416 // Set the minimal number of entries in 'info' to continue.
nethercoted6a56872004-07-26 15:32:47 +00001417 info->interp_name = NULL;
1418 info->interp_args = NULL;
nethercote71980f02004-01-24 18:18:54 +00001419 } else {
1420 Int ret;
1421 VG_(clexecfd) = VG_(open)(exec, O_RDONLY, VKI_S_IRUSR);
1422 ret = do_exec(exec, info);
1423 if (ret != 0) {
nethercoteea147e72004-07-26 15:43:57 +00001424 fprintf(stderr, "valgrind: do_exec(%s) failed: %s\n",
1425 exec, strerror(ret));
nethercote71980f02004-01-24 18:18:54 +00001426 exit(127);
1427 }
1428 }
1429
1430 /* Copy necessary bits of 'info' that were filled in */
1431 *client_eip = info->init_eip;
1432 VG_(brk_base) = VG_(brk_limit) = info->brkbase;
1433}
1434
1435
1436/*====================================================================*/
1437/*=== Command-line: variables, processing ===*/
1438/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +00001439
njn25e49d8e72002-09-23 09:36:25 +00001440/* Define, and set defaults. */
1441Bool VG_(clo_error_limit) = True;
nethercote04d0fbc2004-01-26 16:48:06 +00001442Bool VG_(clo_db_attach) = False;
1443Char* VG_(clo_db_command) = VG_CLO_DEFAULT_DBCOMMAND;
njn43c799e2003-04-08 00:08:52 +00001444Bool VG_(clo_gen_suppressions) = False;
nethercote27fec902004-06-16 21:26:32 +00001445Int VG_(clo_sanity_level) = 1;
njn25e49d8e72002-09-23 09:36:25 +00001446Int VG_(clo_verbosity) = 1;
1447Bool VG_(clo_demangle) = True;
njn25e49d8e72002-09-23 09:36:25 +00001448Bool VG_(clo_trace_children) = False;
sewardj4cf05692002-10-27 20:28:29 +00001449
nethercotee1730692003-11-20 10:38:07 +00001450/* See big comment in vg_include.h for meaning of these three.
1451 fd is initially stdout, for --help, but gets moved to stderr by default
1452 immediately afterwards. */
sewardj4cf05692002-10-27 20:28:29 +00001453VgLogTo VG_(clo_log_to) = VgLogTo_Fd;
nethercotef8548672004-06-21 12:42:35 +00001454Int VG_(clo_log_fd) = 1;
1455Char* VG_(clo_log_name) = NULL;
sewardj4cf05692002-10-27 20:28:29 +00001456
sewardj6024b212003-07-13 10:54:33 +00001457Int VG_(clo_input_fd) = 0; /* stdin */
njn25e49d8e72002-09-23 09:36:25 +00001458Int VG_(clo_n_suppressions) = 0;
sewardjde4a1d02002-03-22 01:27:54 +00001459Char* VG_(clo_suppressions)[VG_CLO_MAX_SFILES];
njn25e49d8e72002-09-23 09:36:25 +00001460Bool VG_(clo_profile) = False;
1461Bool VG_(clo_single_step) = False;
1462Bool VG_(clo_optimise) = True;
1463UChar VG_(clo_trace_codegen) = 0; // 00000000b
1464Bool VG_(clo_trace_syscalls) = False;
1465Bool VG_(clo_trace_signals) = False;
1466Bool VG_(clo_trace_symtab) = False;
njn25e49d8e72002-09-23 09:36:25 +00001467Bool VG_(clo_trace_sched) = False;
1468Int VG_(clo_trace_pthread_level) = 0;
njn25e49d8e72002-09-23 09:36:25 +00001469Int VG_(clo_dump_error) = 0;
1470Int VG_(clo_backtrace_size) = 4;
1471Char* VG_(clo_weird_hacks) = NULL;
sewardj858964b2002-10-05 14:15:43 +00001472Bool VG_(clo_run_libc_freeres) = True;
rjwalshf5f536f2003-11-17 17:45:00 +00001473Bool VG_(clo_track_fds) = False;
sewardj22854b92002-11-30 14:00:47 +00001474Bool VG_(clo_chain_bb) = True;
nethercote77eba602003-11-13 17:35:04 +00001475Bool VG_(clo_show_below_main) = False;
fitzhardinge98abfc72003-12-16 02:05:15 +00001476Bool VG_(clo_pointercheck) = True;
fitzhardinge462f4f92003-12-18 02:10:54 +00001477Bool VG_(clo_branchpred) = False;
sewardj2370f3b2002-11-30 15:01:01 +00001478
jsgf855d93d2003-10-13 22:26:55 +00001479static Bool VG_(clo_wait_for_gdb) = False;
1480
1481/* If we're doing signal routing, poll for signals every 50mS by
1482 default. */
1483Int VG_(clo_signal_polltime) = 50;
1484
1485/* These flags reduce thread wakeup latency on syscall completion and
1486 signal delivery, respectively. The downside is possible unfairness. */
1487Bool VG_(clo_lowlat_syscalls) = False; /* low-latency syscalls */
1488Bool VG_(clo_lowlat_signals) = False; /* low-latency signals */
1489
sewardjde4a1d02002-03-22 01:27:54 +00001490
nethercote6c999f22004-01-31 22:55:15 +00001491void usage ( Bool debug_help )
njn7cf0bd32002-06-08 13:36:03 +00001492{
njn25e49d8e72002-09-23 09:36:25 +00001493 Char* usage1 =
nethercote71980f02004-01-24 18:18:54 +00001494"usage: valgrind --tool=<toolname> [options] prog-and-args\n"
njn25e49d8e72002-09-23 09:36:25 +00001495"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001496" common user options for all Valgrind tools, with defaults in [ ]:\n"
nethercote0d588502004-06-21 13:27:11 +00001497" --tool=<name> use the Valgrind tool named <name>\n"
nethercotea76368b2004-06-16 11:56:29 +00001498" -h --help show this message\n"
nethercote6c999f22004-01-31 22:55:15 +00001499" --help-debug show this message, plus debugging options\n"
njn25e49d8e72002-09-23 09:36:25 +00001500" --version show version\n"
njn25e49d8e72002-09-23 09:36:25 +00001501" -q --quiet run silently; only print error msgs\n"
1502" -v --verbose be more verbose, incl counts of errors\n"
nethercote77eba602003-11-13 17:35:04 +00001503" --trace-children=no|yes Valgrind-ise child processes? [no]\n"
nethercote0d588502004-06-21 13:27:11 +00001504" --track-fds=no|yes track open file descriptors? [no]\n"
nethercote2b0793f2003-12-02 10:41:18 +00001505"\n"
1506" uncommon user options for all Valgrind tools:\n"
nethercote0d588502004-06-21 13:27:11 +00001507" --run-libc-freeres=no|yes free up glibc memory at exit? [yes]\n"
1508" --weird-hacks=hack1,hack2,... recognised hacks: lax-ioctls [none]\n"
1509" --signal-polltime=<time> signal poll period (mS) for older kernels [50]\n"
1510" --lowlat-signals=no|yes improve thread signal wake-up latency [no]\n"
1511" --lowlat-syscalls=no|yes improve thread syscall wake-up latency [no]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001512" --pointercheck=no|yes enforce client address space limits [yes]\n"
njn25e49d8e72002-09-23 09:36:25 +00001513"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001514" user options for Valgrind tools that report errors:\n"
nethercotef8548672004-06-21 12:42:35 +00001515" --log-fd=<number> log messages to file descriptor [2=stderr]\n"
1516" --log-file=<file> log messages to <file>.pid<pid>\n"
1517" --log-socket=ipaddr:port log messages to socket ipaddr:port\n"
nethercote2b0793f2003-12-02 10:41:18 +00001518" --demangle=no|yes automatically demangle C++ names? [yes]\n"
1519" --num-callers=<number> show <num> callers in stack traces [4]\n"
1520" --error-limit=no|yes stop showing new errors if too many? [yes]\n"
1521" --show-below-main=no|yes continue stack traces below main() [no]\n"
1522" --suppressions=<filename> suppress errors described in <filename>\n"
1523" --gen-suppressions=no|yes print suppressions for errors detected [no]\n"
nethercote04d0fbc2004-01-26 16:48:06 +00001524" --db-attach=no|yes start debugger when errors detected? [no]\n"
1525" --db-command=<command> command to start debugger [gdb -nw %%f %%p]\n"
1526" --input-fd=<number> file descriptor for input [0=stdin]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001527"\n";
njn7cf0bd32002-06-08 13:36:03 +00001528
njn25e49d8e72002-09-23 09:36:25 +00001529 Char* usage2 =
1530"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001531" debugging options for all Valgrind tools:\n"
njn25e49d8e72002-09-23 09:36:25 +00001532" --sanity-level=<number> level of sanity checking to do [1]\n"
1533" --single-step=no|yes translate each instr separately? [no]\n"
1534" --optimise=no|yes improve intermediate code? [yes]\n"
nethercote137bc552003-11-14 17:47:54 +00001535" --profile=no|yes profile? (tool must be built for it) [no]\n"
sewardj22854b92002-11-30 14:00:47 +00001536" --chain-bb=no|yes do basic-block chaining? [yes]\n"
fitzhardinge462f4f92003-12-18 02:10:54 +00001537" --branchpred=yes|no generate branch prediction hints [no]\n"
njn25e49d8e72002-09-23 09:36:25 +00001538" --trace-codegen=<XXXXX> show generated code? (X = 0|1) [00000]\n"
1539" --trace-syscalls=no|yes show all system calls? [no]\n"
1540" --trace-signals=no|yes show signal handling details? [no]\n"
1541" --trace-symtab=no|yes show symbol table details? [no]\n"
njn25e49d8e72002-09-23 09:36:25 +00001542" --trace-sched=no|yes show thread scheduler details? [no]\n"
njn3e884182003-04-15 13:03:23 +00001543" --trace-pthread=none|some|all show pthread event details? [none]\n"
jsgf855d93d2003-10-13 22:26:55 +00001544" --wait-for-gdb=yes|no pause on startup to wait for gdb attach\n"
njn25e49d8e72002-09-23 09:36:25 +00001545"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001546" debugging options for Valgrind tools that report errors\n"
1547" --dump-error=<number> show translation for basic block associated\n"
1548" with <number>'th error context [0=show none]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001549"\n";
njn3e884182003-04-15 13:03:23 +00001550
1551 Char* usage3 =
1552"\n"
nethercote71980f02004-01-24 18:18:54 +00001553" Extra options read from ~/.valgrindrc, $VALGRIND_OPTS, ./.valgrindrc\n"
njn25e49d8e72002-09-23 09:36:25 +00001554"\n"
nethercote08fa9a72004-07-16 17:44:00 +00001555" Valgrind is Copyright (C) 2000-2004 Julian Seward et al.\n"
njn25e49d8e72002-09-23 09:36:25 +00001556" and licensed under the GNU General Public License, version 2.\n"
1557" Bug reports, feedback, admiration, abuse, etc, to: %s.\n"
njnd04b7c62002-10-03 14:05:52 +00001558"\n"
nethercote137bc552003-11-14 17:47:54 +00001559" Tools are copyright and licensed by their authors. See each\n"
1560" tool's start-up message for more information.\n"
njn25e49d8e72002-09-23 09:36:25 +00001561"\n";
njn7cf0bd32002-06-08 13:36:03 +00001562
fitzhardinge98abfc72003-12-16 02:05:15 +00001563 VG_(printf)(usage1);
1564 if (VG_(details).name) {
1565 VG_(printf)(" user options for %s:\n", VG_(details).name);
fitzhardinge98abfc72003-12-16 02:05:15 +00001566 if (VG_(needs).command_line_options)
1567 SK_(print_usage)();
1568 else
1569 VG_(printf)(" (none)\n");
1570 }
nethercote6c999f22004-01-31 22:55:15 +00001571 if (debug_help) {
1572 VG_(printf)(usage2);
fitzhardinge98abfc72003-12-16 02:05:15 +00001573
nethercote6c999f22004-01-31 22:55:15 +00001574 if (VG_(details).name) {
1575 VG_(printf)(" debugging options for %s:\n", VG_(details).name);
1576
1577 if (VG_(needs).command_line_options)
1578 SK_(print_debug_usage)();
1579 else
1580 VG_(printf)(" (none)\n");
1581 }
fitzhardinge98abfc72003-12-16 02:05:15 +00001582 }
nethercote421281e2003-11-20 16:20:55 +00001583 VG_(printf)(usage3, VG_BUGS_TO);
nethercotef4928da2004-06-15 10:54:40 +00001584 VG_(exit)(0);
njn7cf0bd32002-06-08 13:36:03 +00001585}
sewardjde4a1d02002-03-22 01:27:54 +00001586
nethercote71980f02004-01-24 18:18:54 +00001587static void pre_process_cmd_line_options
nethercote6c999f22004-01-31 22:55:15 +00001588 ( Int* need_help, const char** tool, const char** exec )
sewardj1c1b1162003-02-23 01:25:51 +00001589{
nethercote71980f02004-01-24 18:18:54 +00001590 UInt i;
sewardjde4a1d02002-03-22 01:27:54 +00001591
nethercote71980f02004-01-24 18:18:54 +00001592 /* parse the options we have (only the options we care about now) */
1593 for (i = 1; i < VG_(vg_argc); i++) {
1594
1595 if (strcmp(VG_(vg_argv)[i], "--version") == 0) {
1596 printf("valgrind-" VERSION "\n");
nethercotef4928da2004-06-15 10:54:40 +00001597 exit(0);
nethercote71980f02004-01-24 18:18:54 +00001598
nethercotea76368b2004-06-16 11:56:29 +00001599 } else if (VG_CLO_STREQ(VG_(vg_argv)[i], "--help") ||
1600 VG_CLO_STREQ(VG_(vg_argv)[i], "-h")) {
nethercote6c999f22004-01-31 22:55:15 +00001601 *need_help = 1;
1602
nethercotef4928da2004-06-15 10:54:40 +00001603 } else if (VG_CLO_STREQ(VG_(vg_argv)[i], "--help-debug")) {
nethercote6c999f22004-01-31 22:55:15 +00001604 *need_help = 2;
nethercote71980f02004-01-24 18:18:54 +00001605
nethercotef4928da2004-06-15 10:54:40 +00001606 } else if (VG_CLO_STREQN(7, VG_(vg_argv)[i], "--tool=") ||
1607 VG_CLO_STREQN(7, VG_(vg_argv)[i], "--skin=")) {
nethercote71980f02004-01-24 18:18:54 +00001608 *tool = &VG_(vg_argv)[i][7];
1609
nethercotef4928da2004-06-15 10:54:40 +00001610 } else if (VG_CLO_STREQN(7, VG_(vg_argv)[i], "--exec=")) {
nethercote71980f02004-01-24 18:18:54 +00001611 *exec = &VG_(vg_argv)[i][7];
1612 }
1613 }
1614
nethercotef4928da2004-06-15 10:54:40 +00001615 /* If no tool specified, can act appropriately without loading tool */
nethercote71980f02004-01-24 18:18:54 +00001616 if (*tool == NULL) {
nethercotef4928da2004-06-15 10:54:40 +00001617 if (0 == *need_help) {
1618 // neither --tool nor --help/--help-debug specified
1619 missing_tool_option();
1620 } else {
1621 // Give help message, without any tool-specific help
1622 usage(/*help-debug?*/2 == *need_help);
1623 }
nethercote71980f02004-01-24 18:18:54 +00001624 }
1625}
1626
nethercote5ee67ca2004-06-22 14:00:09 +00001627static void process_cmd_line_options( UInt* client_auxv, const char* toolname )
nethercote71980f02004-01-24 18:18:54 +00001628{
nethercotef8548672004-06-21 12:42:35 +00001629 Int i, eventually_log_fd;
nethercote71980f02004-01-24 18:18:54 +00001630 Int *auxp;
1631 Int toolname_len = VG_(strlen)(toolname);
sewardjde4a1d02002-03-22 01:27:54 +00001632
nethercotee1730692003-11-20 10:38:07 +00001633 /* log to stderr by default, but usage message goes to stdout */
nethercotef8548672004-06-21 12:42:35 +00001634 eventually_log_fd = 2;
sewardjde4a1d02002-03-22 01:27:54 +00001635
sewardj19d81412002-06-03 01:10:40 +00001636 /* Check for sane path in ./configure --prefix=... */
fitzhardinge98abfc72003-12-16 02:05:15 +00001637 if (VG_LIBDIR[0] != '/')
sewardj19d81412002-06-03 01:10:40 +00001638 config_error("Please use absolute paths in "
1639 "./configure --prefix=... or --libdir=...");
sewardj38170912002-05-10 21:07:22 +00001640
nethercote71980f02004-01-24 18:18:54 +00001641 for (auxp = client_auxv; auxp[0] != VKI_AT_NULL; auxp += 2) {
fitzhardinge98abfc72003-12-16 02:05:15 +00001642 switch(auxp[0]) {
1643 case VKI_AT_SYSINFO:
fitzhardinge92360792003-12-24 10:11:11 +00001644 auxp[1] = (Int)(VG_(client_trampoline_code) + VG_(tramp_syscall_offset));
fitzhardinge98abfc72003-12-16 02:05:15 +00001645 break;
sewardjde4a1d02002-03-22 01:27:54 +00001646 }
fitzhardinge98abfc72003-12-16 02:05:15 +00001647 }
sewardjde4a1d02002-03-22 01:27:54 +00001648
nethercote71980f02004-01-24 18:18:54 +00001649 for (i = 1; i < VG_(vg_argc); i++) {
1650
1651 Char* arg = VG_(vg_argv)[i];
thughes3bfd5a02004-07-18 08:05:44 +00001652 Char* colon = arg;
nethercote71980f02004-01-24 18:18:54 +00001653
thughes3bfd5a02004-07-18 08:05:44 +00001654 /* Look for a colon in the switch name */
1655 while (*colon && *colon != ':' && *colon != '=')
1656 colon++;
nethercote71980f02004-01-24 18:18:54 +00001657
1658 /* Look for matching "--toolname:foo" */
thughes3bfd5a02004-07-18 08:05:44 +00001659 if (*colon == ':') {
nethercote71980f02004-01-24 18:18:54 +00001660 if (VG_CLO_STREQN(2, arg, "--") &&
1661 VG_CLO_STREQN(toolname_len, arg+2, toolname) &&
1662 VG_CLO_STREQN(1, arg+2+toolname_len, ":"))
1663 {
1664 // prefix matches, convert "--toolname:foo" to "--foo"
1665 if (0)
1666 VG_(printf)("tool-specific arg: %s\n", arg);
1667 arg += toolname_len + 1;
1668 arg[0] = '-';
1669 arg[1] = '-';
1670
1671 } else {
1672 // prefix doesn't match, skip to next arg
1673 continue;
1674 }
1675 }
1676
fitzhardinge98abfc72003-12-16 02:05:15 +00001677 /* Ignore these options - they've already been handled */
nethercote71980f02004-01-24 18:18:54 +00001678 if (VG_CLO_STREQN(7, arg, "--tool=") ||
1679 VG_CLO_STREQN(7, arg, "--skin="))
fitzhardinge98abfc72003-12-16 02:05:15 +00001680 continue;
nethercote71980f02004-01-24 18:18:54 +00001681 if (VG_CLO_STREQN(7, arg, "--exec="))
fitzhardinge98abfc72003-12-16 02:05:15 +00001682 continue;
1683
nethercote71980f02004-01-24 18:18:54 +00001684 if ( VG_CLO_STREQ(arg, "--"))
fitzhardinge98abfc72003-12-16 02:05:15 +00001685 continue;
nethercote27fec902004-06-16 21:26:32 +00001686
nethercote71980f02004-01-24 18:18:54 +00001687 else if (VG_CLO_STREQ(arg, "-v") ||
1688 VG_CLO_STREQ(arg, "--verbose"))
sewardjde4a1d02002-03-22 01:27:54 +00001689 VG_(clo_verbosity)++;
nethercote27fec902004-06-16 21:26:32 +00001690
nethercote71980f02004-01-24 18:18:54 +00001691 else if (VG_CLO_STREQ(arg, "-q") ||
1692 VG_CLO_STREQ(arg, "--quiet"))
sewardjde4a1d02002-03-22 01:27:54 +00001693 VG_(clo_verbosity)--;
1694
nethercote27fec902004-06-16 21:26:32 +00001695 else VG_BOOL_CLO("--branchpred", VG_(clo_branchpred))
1696 else VG_BOOL_CLO("--chain-bb", VG_(clo_chain_bb))
1697 else VG_BOOL_CLO("--db-attach", VG_(clo_db_attach))
1698 else VG_BOOL_CLO("--demangle", VG_(clo_demangle))
1699 else VG_BOOL_CLO("--error-limit", VG_(clo_error_limit))
1700 else VG_BOOL_CLO("--gen-suppressions", VG_(clo_gen_suppressions))
1701 else VG_BOOL_CLO("--lowlat-signals", VG_(clo_lowlat_signals))
1702 else VG_BOOL_CLO("--lowlat-syscalls", VG_(clo_lowlat_syscalls))
1703 else VG_BOOL_CLO("--optimise", VG_(clo_optimise))
1704 else VG_BOOL_CLO("--pointercheck", VG_(clo_pointercheck))
1705 else VG_BOOL_CLO("--profile", VG_(clo_profile))
1706 else VG_BOOL_CLO("--run-libc-freeres", VG_(clo_run_libc_freeres))
1707 else VG_BOOL_CLO("--show-below-main", VG_(clo_show_below_main))
1708 else VG_BOOL_CLO("--single-step", VG_(clo_single_step))
1709 else VG_BOOL_CLO("--track-fds", VG_(clo_track_fds))
1710 else VG_BOOL_CLO("--trace-children", VG_(clo_trace_children))
1711 else VG_BOOL_CLO("--trace-sched", VG_(clo_trace_sched))
1712 else VG_BOOL_CLO("--trace-signals", VG_(clo_trace_signals))
1713 else VG_BOOL_CLO("--trace-symtab", VG_(clo_trace_symtab))
1714 else VG_BOOL_CLO("--trace-syscalls", VG_(clo_trace_syscalls))
1715 else VG_BOOL_CLO("--wait-for-gdb", VG_(clo_wait_for_gdb))
sewardj72f98ff2002-06-13 17:23:38 +00001716
nethercote27fec902004-06-16 21:26:32 +00001717 else VG_STR_CLO ("--db-command", VG_(clo_db_command))
1718 else VG_STR_CLO ("--weird-hacks", VG_(clo_weird_hacks))
sewardjde4a1d02002-03-22 01:27:54 +00001719
nethercote27fec902004-06-16 21:26:32 +00001720 else VG_NUM_CLO ("--dump-error", VG_(clo_dump_error))
1721 else VG_NUM_CLO ("--input-fd", VG_(clo_input_fd))
1722 else VG_NUM_CLO ("--sanity-level", VG_(clo_sanity_level))
1723 else VG_NUM_CLO ("--signal­polltime", VG_(clo_signal_polltime))
1724 else VG_BNUM_CLO("--num-callers", VG_(clo_backtrace_size), 1,
1725 VG_DEEPEST_BACKTRACE)
sewardjde4a1d02002-03-22 01:27:54 +00001726
nethercotef8548672004-06-21 12:42:35 +00001727 // for backwards compatibility, replaced by --log-fd
nethercote71980f02004-01-24 18:18:54 +00001728 else if (VG_CLO_STREQN(13, arg, "--logfile-fd=")) {
nethercotef8548672004-06-21 12:42:35 +00001729 VG_(clo_log_to) = VgLogTo_Fd;
1730 VG_(clo_log_name) = NULL;
1731 eventually_log_fd = (Int)VG_(atoll)(&arg[13]);
1732 }
1733 else if (VG_CLO_STREQN(9, arg, "--log-fd=")) {
1734 VG_(clo_log_to) = VgLogTo_Fd;
1735 VG_(clo_log_name) = NULL;
1736 eventually_log_fd = (Int)VG_(atoll)(&arg[9]);
sewardj4cf05692002-10-27 20:28:29 +00001737 }
1738
nethercotef8548672004-06-21 12:42:35 +00001739 // for backwards compatibility, replaced by --log-file
nethercote71980f02004-01-24 18:18:54 +00001740 else if (VG_CLO_STREQN(10, arg, "--logfile=")) {
nethercotef8548672004-06-21 12:42:35 +00001741 VG_(clo_log_to) = VgLogTo_File;
1742 VG_(clo_log_name) = &arg[10];
1743 }
1744 else if (VG_CLO_STREQN(11, arg, "--log-file=")) {
1745 VG_(clo_log_to) = VgLogTo_File;
1746 VG_(clo_log_name) = &arg[11];
sewardj4cf05692002-10-27 20:28:29 +00001747 }
sewardjde4a1d02002-03-22 01:27:54 +00001748
nethercotef8548672004-06-21 12:42:35 +00001749 // for backwards compatibility, replaced by --log-socket
nethercote71980f02004-01-24 18:18:54 +00001750 else if (VG_CLO_STREQN(12, arg, "--logsocket=")) {
nethercotef8548672004-06-21 12:42:35 +00001751 VG_(clo_log_to) = VgLogTo_Socket;
1752 VG_(clo_log_name) = &arg[12];
1753 }
1754 else if (VG_CLO_STREQN(13, arg, "--log-socket=")) {
1755 VG_(clo_log_to) = VgLogTo_Socket;
1756 VG_(clo_log_name) = &arg[13];
sewardj73cf3bc2002-11-03 03:20:15 +00001757 }
1758
nethercote71980f02004-01-24 18:18:54 +00001759 else if (VG_CLO_STREQN(15, arg, "--suppressions=")) {
sewardjde4a1d02002-03-22 01:27:54 +00001760 if (VG_(clo_n_suppressions) >= VG_CLO_MAX_SFILES) {
njn25e49d8e72002-09-23 09:36:25 +00001761 VG_(message)(Vg_UserMsg, "Too many suppression files specified.");
sewardjde4a1d02002-03-22 01:27:54 +00001762 VG_(message)(Vg_UserMsg,
1763 "Increase VG_CLO_MAX_SFILES and recompile.");
nethercote71980f02004-01-24 18:18:54 +00001764 VG_(bad_option)(arg);
sewardjde4a1d02002-03-22 01:27:54 +00001765 }
nethercote71980f02004-01-24 18:18:54 +00001766 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = &arg[15];
sewardjde4a1d02002-03-22 01:27:54 +00001767 VG_(clo_n_suppressions)++;
1768 }
sewardjde4a1d02002-03-22 01:27:54 +00001769
njn25e49d8e72002-09-23 09:36:25 +00001770 /* "vwxyz" --> 000zyxwv (binary) */
nethercote71980f02004-01-24 18:18:54 +00001771 else if (VG_CLO_STREQN(16, arg, "--trace-codegen=")) {
njn25e49d8e72002-09-23 09:36:25 +00001772 Int j;
nethercote71980f02004-01-24 18:18:54 +00001773 char* opt = & arg[16];
njn25e49d8e72002-09-23 09:36:25 +00001774
1775 if (5 != VG_(strlen)(opt)) {
1776 VG_(message)(Vg_UserMsg,
1777 "--trace-codegen argument must have 5 digits");
nethercote71980f02004-01-24 18:18:54 +00001778 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001779 }
1780 for (j = 0; j < 5; j++) {
1781 if ('0' == opt[j]) { /* do nothing */ }
1782 else if ('1' == opt[j]) VG_(clo_trace_codegen) |= (1 << j);
1783 else {
1784 VG_(message)(Vg_UserMsg, "--trace-codegen argument can only "
1785 "contain 0s and 1s");
nethercote71980f02004-01-24 18:18:54 +00001786 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001787 }
1788 }
1789 }
sewardjde4a1d02002-03-22 01:27:54 +00001790
nethercote71980f02004-01-24 18:18:54 +00001791 else if (VG_CLO_STREQ(arg, "--trace-pthread=none"))
sewardj45b4b372002-04-16 22:50:32 +00001792 VG_(clo_trace_pthread_level) = 0;
nethercote71980f02004-01-24 18:18:54 +00001793 else if (VG_CLO_STREQ(arg, "--trace-pthread=some"))
sewardj45b4b372002-04-16 22:50:32 +00001794 VG_(clo_trace_pthread_level) = 1;
nethercote71980f02004-01-24 18:18:54 +00001795 else if (VG_CLO_STREQ(arg, "--trace-pthread=all"))
sewardj45b4b372002-04-16 22:50:32 +00001796 VG_(clo_trace_pthread_level) = 2;
sewardj8937c812002-04-12 20:12:20 +00001797
nethercote71980f02004-01-24 18:18:54 +00001798 else if ( ! VG_(needs).command_line_options
1799 || ! SK_(process_cmd_line_option)(arg) ) {
nethercotef4928da2004-06-15 10:54:40 +00001800 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001801 }
sewardjde4a1d02002-03-22 01:27:54 +00001802 }
1803
nethercote27fec902004-06-16 21:26:32 +00001804 // Check various option values
1805
njnf9ebf672003-05-12 21:41:30 +00001806 if (VG_(clo_verbosity) < 0)
sewardjde4a1d02002-03-22 01:27:54 +00001807 VG_(clo_verbosity) = 0;
1808
nethercote04d0fbc2004-01-26 16:48:06 +00001809 if (VG_(clo_db_attach) && VG_(clo_trace_children)) {
sewardjde4a1d02002-03-22 01:27:54 +00001810 VG_(message)(Vg_UserMsg, "");
1811 VG_(message)(Vg_UserMsg,
nethercote04d0fbc2004-01-26 16:48:06 +00001812 "--db-attach=yes conflicts with --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001813 VG_(message)(Vg_UserMsg,
1814 "Please choose one or the other, but not both.");
nethercote04d0fbc2004-01-26 16:48:06 +00001815 VG_(bad_option)("--db-attach=yes and --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001816 }
1817
nethercotef8548672004-06-21 12:42:35 +00001818 /* Set up logging now. After this is done, VG_(clo_log_fd)
sewardj4cf05692002-10-27 20:28:29 +00001819 should be connected to whatever sink has been selected, and we
1820 indiscriminately chuck stuff into it without worrying what the
1821 nature of it is. Oh the wonder of Unix streams. */
1822
nethercotee1730692003-11-20 10:38:07 +00001823 /* So far we should be still attached to stdout, so we can show on
sewardj4cf05692002-10-27 20:28:29 +00001824 the terminal any problems to do with processing command line
1825 opts. */
nethercotef8548672004-06-21 12:42:35 +00001826 vg_assert(VG_(clo_log_fd) == 1 /* stdout */);
sewardj73cf3bc2002-11-03 03:20:15 +00001827 vg_assert(VG_(logging_to_filedes) == True);
sewardj4cf05692002-10-27 20:28:29 +00001828
1829 switch (VG_(clo_log_to)) {
sewardj73cf3bc2002-11-03 03:20:15 +00001830
sewardj4cf05692002-10-27 20:28:29 +00001831 case VgLogTo_Fd:
nethercotef8548672004-06-21 12:42:35 +00001832 vg_assert(VG_(clo_log_name) == NULL);
1833 VG_(clo_log_fd) = eventually_log_fd;
sewardj4cf05692002-10-27 20:28:29 +00001834 break;
sewardj73cf3bc2002-11-03 03:20:15 +00001835
sewardj4cf05692002-10-27 20:28:29 +00001836 case VgLogTo_File: {
1837 Char logfilename[1000];
jsgff3c3f1a2003-10-14 22:13:28 +00001838 Int seq = 0;
1839 Int pid = VG_(getpid)();
1840
nethercotef8548672004-06-21 12:42:35 +00001841 vg_assert(VG_(clo_log_name) != NULL);
1842 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
jsgff3c3f1a2003-10-14 22:13:28 +00001843
nethercote71980f02004-01-24 18:18:54 +00001844 for (;;) {
jsgff3c3f1a2003-10-14 22:13:28 +00001845 if (seq == 0)
1846 VG_(sprintf)(logfilename, "%s.pid%d",
nethercotef8548672004-06-21 12:42:35 +00001847 VG_(clo_log_name), pid );
jsgff3c3f1a2003-10-14 22:13:28 +00001848 else
1849 VG_(sprintf)(logfilename, "%s.pid%d.%d",
nethercotef8548672004-06-21 12:42:35 +00001850 VG_(clo_log_name), pid, seq );
jsgff3c3f1a2003-10-14 22:13:28 +00001851 seq++;
1852
nethercotef8548672004-06-21 12:42:35 +00001853 eventually_log_fd
jsgff3c3f1a2003-10-14 22:13:28 +00001854 = VG_(open)(logfilename,
1855 VKI_O_CREAT|VKI_O_WRONLY|VKI_O_EXCL|VKI_O_TRUNC,
1856 VKI_S_IRUSR|VKI_S_IWUSR);
nethercotef8548672004-06-21 12:42:35 +00001857 if (eventually_log_fd >= 0) {
1858 VG_(clo_log_fd) = VG_(safe_fd)(eventually_log_fd);
jsgff3c3f1a2003-10-14 22:13:28 +00001859 break;
1860 } else {
nethercotef8548672004-06-21 12:42:35 +00001861 if (eventually_log_fd != -VKI_EEXIST) {
jsgff3c3f1a2003-10-14 22:13:28 +00001862 VG_(message)(Vg_UserMsg,
1863 "Can't create/open log file `%s.pid%d'; giving up!",
nethercotef8548672004-06-21 12:42:35 +00001864 VG_(clo_log_name), pid);
jsgff3c3f1a2003-10-14 22:13:28 +00001865 VG_(bad_option)(
nethercotef8548672004-06-21 12:42:35 +00001866 "--log-file=<file> didn't work out for some reason.");
jsgff3c3f1a2003-10-14 22:13:28 +00001867 break;
1868 }
1869 }
1870 }
sewardj4cf05692002-10-27 20:28:29 +00001871 break;
sewardj73cf3bc2002-11-03 03:20:15 +00001872 }
1873
1874 case VgLogTo_Socket: {
nethercotef8548672004-06-21 12:42:35 +00001875 vg_assert(VG_(clo_log_name) != NULL);
1876 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
1877 eventually_log_fd = VG_(connect_via_socket)( VG_(clo_log_name) );
1878 if (eventually_log_fd == -1) {
sewardj73cf3bc2002-11-03 03:20:15 +00001879 VG_(message)(Vg_UserMsg,
nethercotef8548672004-06-21 12:42:35 +00001880 "Invalid --log-socket=ipaddr or --log-socket=ipaddr:port spec");
sewardj73cf3bc2002-11-03 03:20:15 +00001881 VG_(message)(Vg_UserMsg,
nethercotef8548672004-06-21 12:42:35 +00001882 "of `%s'; giving up!", VG_(clo_log_name) );
sewardj73cf3bc2002-11-03 03:20:15 +00001883 VG_(bad_option)(
nethercotef8548672004-06-21 12:42:35 +00001884 "--log-socket=");
sewardj4cf05692002-10-27 20:28:29 +00001885 }
nethercotef8548672004-06-21 12:42:35 +00001886 if (eventually_log_fd == -2) {
sewardj73cf3bc2002-11-03 03:20:15 +00001887 VG_(message)(Vg_UserMsg,
sewardj570f8902002-11-03 11:44:36 +00001888 "valgrind: failed to connect to logging server `%s'.",
nethercotef8548672004-06-21 12:42:35 +00001889 VG_(clo_log_name) );
sewardj570f8902002-11-03 11:44:36 +00001890 VG_(message)(Vg_UserMsg,
1891 "Log messages will sent to stderr instead." );
1892 VG_(message)(Vg_UserMsg,
1893 "" );
1894 /* We don't change anything here. */
1895 } else {
nethercotef8548672004-06-21 12:42:35 +00001896 vg_assert(eventually_log_fd > 0);
1897 VG_(clo_log_fd) = eventually_log_fd;
sewardj570f8902002-11-03 11:44:36 +00001898 VG_(logging_to_filedes) = False;
1899 }
sewardj73cf3bc2002-11-03 03:20:15 +00001900 break;
1901 }
1902
sewardj4cf05692002-10-27 20:28:29 +00001903 }
1904
nethercotef8548672004-06-21 12:42:35 +00001905 /* Move log_fd into the safe range, so it doesn't conflict with any app fds */
thughesad1c9562004-06-26 11:27:52 +00001906 eventually_log_fd = VG_(fcntl)(VG_(clo_log_fd), VKI_F_DUPFD, VG_(fd_hard_limit));
nethercotef8548672004-06-21 12:42:35 +00001907 if (eventually_log_fd < 0)
jsgf855d93d2003-10-13 22:26:55 +00001908 VG_(message)(Vg_UserMsg, "valgrind: failed to move logfile fd into safe range");
1909 else {
nethercotef8548672004-06-21 12:42:35 +00001910 VG_(clo_log_fd) = eventually_log_fd;
1911 VG_(fcntl)(VG_(clo_log_fd), VKI_F_SETFD, VKI_FD_CLOEXEC);
jsgf855d93d2003-10-13 22:26:55 +00001912 }
1913
sewardj4cf05692002-10-27 20:28:29 +00001914 /* Ok, the logging sink is running now. Print a suitable preamble.
1915 If logging to file or a socket, write details of parent PID and
1916 command line args, to help people trying to interpret the
1917 results of a run which encompasses multiple processes. */
sewardjde4a1d02002-03-22 01:27:54 +00001918
sewardj83adf412002-05-01 01:25:45 +00001919 if (VG_(clo_verbosity > 0)) {
njnd04b7c62002-10-03 14:05:52 +00001920 /* Skin details */
1921 VG_(message)(Vg_UserMsg, "%s%s%s, %s for x86-linux.",
1922 VG_(details).name,
1923 NULL == VG_(details).version ? "" : "-",
1924 NULL == VG_(details).version
1925 ? (Char*)"" : VG_(details).version,
1926 VG_(details).description);
1927 VG_(message)(Vg_UserMsg, "%s", VG_(details).copyright_author);
sewardj3b2736a2002-03-24 12:18:35 +00001928
njnd04b7c62002-10-03 14:05:52 +00001929 /* Core details */
1930 VG_(message)(Vg_UserMsg,
njn3e884182003-04-15 13:03:23 +00001931 "Using valgrind-%s, a program supervision framework for x86-linux.",
sewardj4aa62ba2002-10-05 15:49:27 +00001932 VERSION);
sewardjde4a1d02002-03-22 01:27:54 +00001933 VG_(message)(Vg_UserMsg,
nethercote08fa9a72004-07-16 17:44:00 +00001934 "Copyright (C) 2000-2004, and GNU GPL'd, by Julian Seward et al.");
njnd04b7c62002-10-03 14:05:52 +00001935 }
1936
nethercotec1e395d2003-11-10 13:26:49 +00001937 if (VG_(clo_verbosity) > 0 && VG_(clo_log_to) != VgLogTo_Fd) {
sewardj4cf05692002-10-27 20:28:29 +00001938 VG_(message)(Vg_UserMsg, "");
1939 VG_(message)(Vg_UserMsg,
1940 "My PID = %d, parent PID = %d. Prog and args are:",
1941 VG_(getpid)(), VG_(getppid)() );
1942 for (i = 0; i < VG_(client_argc); i++)
1943 VG_(message)(Vg_UserMsg, " %s", VG_(client_argv)[i]);
1944 }
1945
sewardjde4a1d02002-03-22 01:27:54 +00001946 if (VG_(clo_verbosity) > 1) {
nethercotea70f7352004-04-18 12:08:46 +00001947 Int fd;
sewardj4cf05692002-10-27 20:28:29 +00001948 if (VG_(clo_log_to) != VgLogTo_Fd)
1949 VG_(message)(Vg_UserMsg, "");
fitzhardinge98abfc72003-12-16 02:05:15 +00001950 VG_(message)(Vg_UserMsg, "Valgrind library directory: %s", VG_(libdir));
njn86dc2bc2003-09-09 07:26:21 +00001951 VG_(message)(Vg_UserMsg, "Command line");
1952 for (i = 0; i < VG_(client_argc); i++)
1953 VG_(message)(Vg_UserMsg, " %s", VG_(client_argv)[i]);
1954
sewardjde4a1d02002-03-22 01:27:54 +00001955 VG_(message)(Vg_UserMsg, "Startup, with flags:");
nethercote71980f02004-01-24 18:18:54 +00001956 for (i = 1; i < VG_(vg_argc); i++) {
1957 VG_(message)(Vg_UserMsg, " %s", VG_(vg_argv)[i]);
sewardjde4a1d02002-03-22 01:27:54 +00001958 }
nethercotea70f7352004-04-18 12:08:46 +00001959
1960 VG_(message)(Vg_UserMsg, "Contents of /proc/version:");
1961 fd = VG_(open) ( "/proc/version", VKI_O_RDONLY, 0 );
1962 if (fd < 0) {
1963 VG_(message)(Vg_UserMsg, " can't open /proc/version");
1964 } else {
1965 #define BUF_LEN 256
1966 Char version_buf[BUF_LEN];
1967 Int n = VG_(read) ( fd, version_buf, BUF_LEN );
1968 vg_assert(n <= 256);
1969 if (n > 0) {
1970 version_buf[n-1] = '\0';
1971 VG_(message)(Vg_UserMsg, " %s", version_buf);
1972 } else {
1973 VG_(message)(Vg_UserMsg, " (empty?)");
1974 }
1975 VG_(close)(fd);
1976 #undef BUF_LEN
1977 }
sewardjde4a1d02002-03-22 01:27:54 +00001978 }
1979
fitzhardinge98abfc72003-12-16 02:05:15 +00001980 if (VG_(clo_n_suppressions) < VG_CLO_MAX_SFILES-1 &&
njn25e49d8e72002-09-23 09:36:25 +00001981 (VG_(needs).core_errors || VG_(needs).skin_errors)) {
fitzhardinge98abfc72003-12-16 02:05:15 +00001982 /* If there are no suppression files specified and the skin
1983 needs one, load the default */
1984 static const Char default_supp[] = "default.supp";
1985 Int len = VG_(strlen)(VG_(libdir)) + 1 + sizeof(default_supp);
1986 Char *buf = VG_(arena_malloc)(VG_AR_CORE, len);
1987 VG_(sprintf)(buf, "%s/%s", VG_(libdir), default_supp);
1988 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = buf;
1989 VG_(clo_n_suppressions)++;
sewardjde4a1d02002-03-22 01:27:54 +00001990 }
sewardj4cf05692002-10-27 20:28:29 +00001991
njn6a230532003-07-21 10:38:23 +00001992 if (VG_(clo_gen_suppressions) &&
1993 !VG_(needs).core_errors && !VG_(needs).skin_errors) {
nethercotef4928da2004-06-15 10:54:40 +00001994 VG_(message)(Vg_UserMsg,
1995 "Can't use --gen-suppressions=yes with this tool,");
1996 VG_(message)(Vg_UserMsg,
1997 "as it doesn't generate errors.");
1998 VG_(bad_option)("--gen-suppressions=yes");
njn6a230532003-07-21 10:38:23 +00001999 }
sewardjde4a1d02002-03-22 01:27:54 +00002000}
2001
sewardjde4a1d02002-03-22 01:27:54 +00002002
nethercote71980f02004-01-24 18:18:54 +00002003/*====================================================================*/
2004/*=== File descriptor setup ===*/
2005/*====================================================================*/
2006
2007static void setup_file_descriptors(void)
2008{
2009 struct vki_rlimit rl;
2010
2011 /* Get the current file descriptor limits. */
2012 if (VG_(getrlimit)(VKI_RLIMIT_NOFILE, &rl) < 0) {
2013 rl.rlim_cur = 1024;
2014 rl.rlim_max = 1024;
2015 }
2016
2017 /* Work out where to move the soft limit to. */
2018 if (rl.rlim_cur + VG_N_RESERVED_FDS <= rl.rlim_max) {
2019 rl.rlim_cur = rl.rlim_cur + VG_N_RESERVED_FDS;
2020 } else {
2021 rl.rlim_cur = rl.rlim_max;
2022 }
2023
2024 /* Reserve some file descriptors for our use. */
thughesad1c9562004-06-26 11:27:52 +00002025 VG_(fd_soft_limit) = rl.rlim_cur - VG_N_RESERVED_FDS;
2026 VG_(fd_hard_limit) = rl.rlim_cur - VG_N_RESERVED_FDS;
nethercote71980f02004-01-24 18:18:54 +00002027
2028 /* Update the soft limit. */
2029 VG_(setrlimit)(VKI_RLIMIT_NOFILE, &rl);
2030
2031 if (VG_(vgexecfd) != -1)
2032 VG_(vgexecfd) = VG_(safe_fd)( VG_(vgexecfd) );
2033 if (VG_(clexecfd) != -1)
2034 VG_(clexecfd) = VG_(safe_fd)( VG_(clexecfd) );
2035}
2036
2037
2038/*====================================================================*/
nethercote1d447092004-02-01 17:29:59 +00002039/*=== baseBlock: definition + setup ===*/
nethercote71980f02004-01-24 18:18:54 +00002040/*====================================================================*/
2041
2042/* The variables storing offsets. */
2043
2044#define INVALID_OFFSET (-1)
2045
2046Int VGOFF_(m_eax) = INVALID_OFFSET;
2047Int VGOFF_(m_ecx) = INVALID_OFFSET;
2048Int VGOFF_(m_edx) = INVALID_OFFSET;
2049Int VGOFF_(m_ebx) = INVALID_OFFSET;
2050Int VGOFF_(m_esp) = INVALID_OFFSET;
2051Int VGOFF_(m_ebp) = INVALID_OFFSET;
2052Int VGOFF_(m_esi) = INVALID_OFFSET;
2053Int VGOFF_(m_edi) = INVALID_OFFSET;
2054Int VGOFF_(m_eflags) = INVALID_OFFSET;
2055Int VGOFF_(m_dflag) = INVALID_OFFSET;
2056Int VGOFF_(m_ssestate) = INVALID_OFFSET;
2057Int VGOFF_(ldt) = INVALID_OFFSET;
2058Int VGOFF_(tls) = INVALID_OFFSET;
2059Int VGOFF_(m_cs) = INVALID_OFFSET;
2060Int VGOFF_(m_ss) = INVALID_OFFSET;
2061Int VGOFF_(m_ds) = INVALID_OFFSET;
2062Int VGOFF_(m_es) = INVALID_OFFSET;
2063Int VGOFF_(m_fs) = INVALID_OFFSET;
2064Int VGOFF_(m_gs) = INVALID_OFFSET;
2065Int VGOFF_(m_eip) = INVALID_OFFSET;
2066Int VGOFF_(spillslots) = INVALID_OFFSET;
2067Int VGOFF_(sh_eax) = INVALID_OFFSET;
2068Int VGOFF_(sh_ecx) = INVALID_OFFSET;
2069Int VGOFF_(sh_edx) = INVALID_OFFSET;
2070Int VGOFF_(sh_ebx) = INVALID_OFFSET;
2071Int VGOFF_(sh_esp) = INVALID_OFFSET;
2072Int VGOFF_(sh_ebp) = INVALID_OFFSET;
2073Int VGOFF_(sh_esi) = INVALID_OFFSET;
2074Int VGOFF_(sh_edi) = INVALID_OFFSET;
2075Int VGOFF_(sh_eflags) = INVALID_OFFSET;
2076
2077Int VGOFF_(helper_idiv_64_32) = INVALID_OFFSET;
2078Int VGOFF_(helper_div_64_32) = INVALID_OFFSET;
2079Int VGOFF_(helper_idiv_32_16) = INVALID_OFFSET;
2080Int VGOFF_(helper_div_32_16) = INVALID_OFFSET;
2081Int VGOFF_(helper_idiv_16_8) = INVALID_OFFSET;
2082Int VGOFF_(helper_div_16_8) = INVALID_OFFSET;
2083Int VGOFF_(helper_imul_32_64) = INVALID_OFFSET;
2084Int VGOFF_(helper_mul_32_64) = INVALID_OFFSET;
2085Int VGOFF_(helper_imul_16_32) = INVALID_OFFSET;
2086Int VGOFF_(helper_mul_16_32) = INVALID_OFFSET;
2087Int VGOFF_(helper_imul_8_16) = INVALID_OFFSET;
2088Int VGOFF_(helper_mul_8_16) = INVALID_OFFSET;
2089Int VGOFF_(helper_CLD) = INVALID_OFFSET;
2090Int VGOFF_(helper_STD) = INVALID_OFFSET;
2091Int VGOFF_(helper_get_dirflag) = INVALID_OFFSET;
2092Int VGOFF_(helper_CLC) = INVALID_OFFSET;
2093Int VGOFF_(helper_STC) = INVALID_OFFSET;
nethercote1018bdd2004-02-11 23:33:29 +00002094Int VGOFF_(helper_CMC) = INVALID_OFFSET;
nethercote71980f02004-01-24 18:18:54 +00002095Int VGOFF_(helper_shldl) = INVALID_OFFSET;
2096Int VGOFF_(helper_shldw) = INVALID_OFFSET;
2097Int VGOFF_(helper_shrdl) = INVALID_OFFSET;
2098Int VGOFF_(helper_shrdw) = INVALID_OFFSET;
2099Int VGOFF_(helper_IN) = INVALID_OFFSET;
2100Int VGOFF_(helper_OUT) = INVALID_OFFSET;
2101Int VGOFF_(helper_RDTSC) = INVALID_OFFSET;
2102Int VGOFF_(helper_CPUID) = INVALID_OFFSET;
2103Int VGOFF_(helper_BSWAP) = INVALID_OFFSET;
nethercote1018bdd2004-02-11 23:33:29 +00002104Int VGOFF_(helper_bsfw) = INVALID_OFFSET;
2105Int VGOFF_(helper_bsfl) = INVALID_OFFSET;
2106Int VGOFF_(helper_bsrw) = INVALID_OFFSET;
2107Int VGOFF_(helper_bsrl) = INVALID_OFFSET;
nethercote71980f02004-01-24 18:18:54 +00002108Int VGOFF_(helper_fstsw_AX) = INVALID_OFFSET;
2109Int VGOFF_(helper_SAHF) = INVALID_OFFSET;
2110Int VGOFF_(helper_LAHF) = INVALID_OFFSET;
2111Int VGOFF_(helper_DAS) = INVALID_OFFSET;
2112Int VGOFF_(helper_DAA) = INVALID_OFFSET;
nethercote1018bdd2004-02-11 23:33:29 +00002113Int VGOFF_(helper_AAS) = INVALID_OFFSET;
2114Int VGOFF_(helper_AAA) = INVALID_OFFSET;
2115Int VGOFF_(helper_AAD) = INVALID_OFFSET;
2116Int VGOFF_(helper_AAM) = INVALID_OFFSET;
nethercote71980f02004-01-24 18:18:54 +00002117Int VGOFF_(helper_cmpxchg8b) = INVALID_OFFSET;
2118Int VGOFF_(helper_undefined_instruction) = INVALID_OFFSET;
2119
2120/* MAX_NONCOMPACT_HELPERS can be increased easily. If MAX_COMPACT_HELPERS is
2121 * increased too much, they won't really be compact any more... */
2122#define MAX_COMPACT_HELPERS 8
2123#define MAX_NONCOMPACT_HELPERS 50
2124
2125UInt VG_(n_compact_helpers) = 0;
2126UInt VG_(n_noncompact_helpers) = 0;
2127
2128Addr VG_(compact_helper_addrs) [MAX_COMPACT_HELPERS];
2129Int VG_(compact_helper_offsets)[MAX_COMPACT_HELPERS];
2130Addr VG_(noncompact_helper_addrs) [MAX_NONCOMPACT_HELPERS];
2131Int VG_(noncompact_helper_offsets)[MAX_NONCOMPACT_HELPERS];
2132
2133/* This is the actual defn of baseblock. */
2134UInt VG_(baseBlock)[VG_BASEBLOCK_WORDS];
2135
nethercote71980f02004-01-24 18:18:54 +00002136/* Words. */
2137static Int baB_off = 0;
2138
2139
nethercote71980f02004-01-24 18:18:54 +00002140/* Returns the offset, in words. */
2141static Int alloc_BaB ( Int words )
sewardjde4a1d02002-03-22 01:27:54 +00002142{
nethercote71980f02004-01-24 18:18:54 +00002143 Int off = baB_off;
2144 baB_off += words;
2145 if (baB_off >= VG_BASEBLOCK_WORDS)
2146 VG_(core_panic)( "alloc_BaB: baseBlock is too small");
sewardjde4a1d02002-03-22 01:27:54 +00002147
nethercote71980f02004-01-24 18:18:54 +00002148 return off;
sewardjde4a1d02002-03-22 01:27:54 +00002149}
2150
nethercote71980f02004-01-24 18:18:54 +00002151/* Align offset, in *bytes* */
2152static void align_BaB ( UInt align )
njn25e49d8e72002-09-23 09:36:25 +00002153{
nethercote71980f02004-01-24 18:18:54 +00002154 vg_assert(2 == align || 4 == align || 8 == align || 16 == align);
2155 baB_off += (align-1);
2156 baB_off &= ~(align-1);
njn25e49d8e72002-09-23 09:36:25 +00002157}
2158
nethercote71980f02004-01-24 18:18:54 +00002159/* Allocate 1 word in baseBlock and set it to the given value. */
2160static Int alloc_BaB_1_set ( Addr a )
njn25e49d8e72002-09-23 09:36:25 +00002161{
nethercote71980f02004-01-24 18:18:54 +00002162 Int off = alloc_BaB(1);
2163 VG_(baseBlock)[off] = (UInt)a;
2164 return off;
njn25e49d8e72002-09-23 09:36:25 +00002165}
2166
nethercote71980f02004-01-24 18:18:54 +00002167/* Registers a function in compact_helper_addrs; compact_helper_offsets is
2168 filled in later. */
2169void VG_(register_compact_helper)(Addr a)
sewardjde4a1d02002-03-22 01:27:54 +00002170{
nethercote71980f02004-01-24 18:18:54 +00002171 if (MAX_COMPACT_HELPERS <= VG_(n_compact_helpers)) {
2172 VG_(printf)("Can only register %d compact helpers\n",
2173 MAX_COMPACT_HELPERS);
2174 VG_(core_panic)("Too many compact helpers registered");
2175 }
2176 VG_(compact_helper_addrs)[VG_(n_compact_helpers)] = a;
2177 VG_(n_compact_helpers)++;
2178}
2179
2180/* Registers a function in noncompact_helper_addrs; noncompact_helper_offsets
2181 * is filled in later.
2182 */
2183void VG_(register_noncompact_helper)(Addr a)
2184{
2185 if (MAX_NONCOMPACT_HELPERS <= VG_(n_noncompact_helpers)) {
2186 VG_(printf)("Can only register %d non-compact helpers\n",
2187 MAX_NONCOMPACT_HELPERS);
2188 VG_(printf)("Try increasing MAX_NON_COMPACT_HELPERS\n");
2189 VG_(core_panic)("Too many non-compact helpers registered");
2190 }
2191 VG_(noncompact_helper_addrs)[VG_(n_noncompact_helpers)] = a;
2192 VG_(n_noncompact_helpers)++;
2193}
2194
2195/* Allocate offsets in baseBlock for the skin helpers */
2196static
2197void assign_helpers_in_baseBlock(UInt n, Int offsets[], Addr addrs[])
2198{
2199 UInt i;
2200 for (i = 0; i < n; i++)
2201 offsets[i] = alloc_BaB_1_set( addrs[i] );
2202}
2203
2204Bool VG_(need_to_handle_esp_assignment)(void)
2205{
2206 return ( VG_(defined_new_mem_stack_4)() ||
2207 VG_(defined_die_mem_stack_4)() ||
2208 VG_(defined_new_mem_stack_8)() ||
2209 VG_(defined_die_mem_stack_8)() ||
2210 VG_(defined_new_mem_stack_12)() ||
2211 VG_(defined_die_mem_stack_12)() ||
2212 VG_(defined_new_mem_stack_16)() ||
2213 VG_(defined_die_mem_stack_16)() ||
2214 VG_(defined_new_mem_stack_32)() ||
2215 VG_(defined_die_mem_stack_32)() ||
2216 VG_(defined_new_mem_stack)() ||
2217 VG_(defined_die_mem_stack)()
2218 );
2219}
2220
2221/* Here we assign actual offsets. It's important to get the most
2222 popular referents within 128 bytes of the start, so we can take
2223 advantage of short addressing modes relative to %ebp. Popularity
2224 of offsets was measured on 22 Feb 02 running a KDE application, and
2225 the slots rearranged accordingly, with a 1.5% reduction in total
2226 size of translations. */
2227static void init_baseBlock ( Addr client_eip, Addr esp_at_startup )
2228{
2229 /* Those with offsets under 128 are carefully chosen. */
2230
2231 /* WORD offsets in this column */
2232 /* 0 */ VGOFF_(m_eax) = alloc_BaB_1_set(0);
2233 /* 1 */ VGOFF_(m_ecx) = alloc_BaB_1_set(0);
2234 /* 2 */ VGOFF_(m_edx) = alloc_BaB_1_set(0);
2235 /* 3 */ VGOFF_(m_ebx) = alloc_BaB_1_set(0);
2236 /* 4 */ VGOFF_(m_esp) = alloc_BaB_1_set(esp_at_startup);
2237 /* 5 */ VGOFF_(m_ebp) = alloc_BaB_1_set(0);
2238 /* 6 */ VGOFF_(m_esi) = alloc_BaB_1_set(0);
2239 /* 7 */ VGOFF_(m_edi) = alloc_BaB_1_set(0);
2240 /* 8 */ VGOFF_(m_eflags) = alloc_BaB_1_set(0);
2241
2242 if (VG_(needs).shadow_regs) {
2243 /* 9 */ VGOFF_(sh_eax) = alloc_BaB_1_set(0);
2244 /* 10 */ VGOFF_(sh_ecx) = alloc_BaB_1_set(0);
2245 /* 11 */ VGOFF_(sh_edx) = alloc_BaB_1_set(0);
2246 /* 12 */ VGOFF_(sh_ebx) = alloc_BaB_1_set(0);
2247 /* 13 */ VGOFF_(sh_esp) = alloc_BaB_1_set(0);
2248 /* 14 */ VGOFF_(sh_ebp) = alloc_BaB_1_set(0);
2249 /* 15 */ VGOFF_(sh_esi) = alloc_BaB_1_set(0);
2250 /* 16 */ VGOFF_(sh_edi) = alloc_BaB_1_set(0);
2251 /* 17 */ VGOFF_(sh_eflags) = alloc_BaB_1_set(0);
2252 VG_TRACK( post_regs_write_init );
2253 }
2254
2255 /* 9,10,11 or 18,19,20... depends on number whether shadow regs are used
2256 * and on compact helpers registered */
2257
2258 /* Make these most-frequently-called specialised ones compact, if they
2259 are used. */
2260 if (VG_(defined_new_mem_stack_4)())
2261 VG_(register_compact_helper)( (Addr) VG_(tool_interface).track_new_mem_stack_4);
2262
2263 if (VG_(defined_die_mem_stack_4)())
2264 VG_(register_compact_helper)( (Addr) VG_(tool_interface).track_die_mem_stack_4);
2265
2266 /* (9 or 18) + n_compact_helpers */
2267 /* Allocate slots for compact helpers */
2268 assign_helpers_in_baseBlock(VG_(n_compact_helpers),
2269 VG_(compact_helper_offsets),
2270 VG_(compact_helper_addrs));
2271
2272 /* (9/10 or 18/19) + n_compact_helpers */
2273 VGOFF_(m_eip) = alloc_BaB_1_set(client_eip);
2274
2275 /* There are currently 24 spill slots */
2276 /* (11+/20+ .. 32+/43+) + n_compact_helpers. This can overlap the magic
2277 * boundary at >= 32 words, but most spills are to low numbered spill
2278 * slots, so the ones above the boundary don't see much action. */
2279 VGOFF_(spillslots) = alloc_BaB(VG_MAX_SPILLSLOTS);
2280
2281 /* I gave up counting at this point. Since they're above the
2282 short-amode-boundary, there's no point. */
2283
2284 VGOFF_(m_dflag) = alloc_BaB_1_set(1); // 1 == forward D-flag
2285
2286 /* The FPU/SSE state. This _must_ be 16-byte aligned. Initial
2287 state doesn't matter much, as long as it's not totally borked. */
2288 align_BaB(16);
2289 VGOFF_(m_ssestate) = alloc_BaB(VG_SIZE_OF_SSESTATE_W);
2290 vg_assert(
2291 0 == ( ((UInt)(& VG_(baseBlock)[VGOFF_(m_ssestate)])) % 16 )
sewardj22854b92002-11-30 14:00:47 +00002292 );
2293
fitzhardingec2dbbac2004-01-23 23:09:01 +00002294 /* I assume that if we have SSE2 we also have SSE */
2295 VG_(have_ssestate) =
2296 VG_(cpu_has_feature)(VG_X86_FEAT_FXSR) &&
2297 VG_(cpu_has_feature)(VG_X86_FEAT_SSE);
2298
fitzhardinge98abfc72003-12-16 02:05:15 +00002299 /* set up an initial FPU state (doesn't really matter what it is,
2300 so long as it's somewhat valid) */
2301 if (!VG_(have_ssestate))
nethercote71980f02004-01-24 18:18:54 +00002302 asm volatile("fwait; fnsave %0; fwait; frstor %0; fwait"
2303 :
2304 : "m" (VG_(baseBlock)[VGOFF_(m_ssestate)])
2305 : "cc", "memory");
fitzhardinge98abfc72003-12-16 02:05:15 +00002306 else
nethercote71980f02004-01-24 18:18:54 +00002307 asm volatile("fwait; fxsave %0; fwait; andl $0xffbf, %1;"
2308 "fxrstor %0; fwait"
2309 :
2310 : "m" (VG_(baseBlock)[VGOFF_(m_ssestate)]),
2311 "m" (VG_(baseBlock)[VGOFF_(m_ssestate)+(24/4)])
2312 : "cc", "memory");
fitzhardinge98abfc72003-12-16 02:05:15 +00002313
njn0c7a5b52003-04-30 09:00:33 +00002314 if (0) {
2315 if (VG_(have_ssestate))
2316 VG_(printf)("Looks like a SSE-capable CPU\n");
2317 else
2318 VG_(printf)("Looks like a MMX-only CPU\n");
2319 }
sewardjb91ae7f2003-04-29 23:50:00 +00002320
nethercote71980f02004-01-24 18:18:54 +00002321 /* LDT pointer: pretend the root thread has an empty LDT to start with. */
2322 VGOFF_(ldt) = alloc_BaB_1_set((UInt)NULL);
jsgf855d93d2003-10-13 22:26:55 +00002323
nethercote71980f02004-01-24 18:18:54 +00002324 /* TLS pointer: pretend the root thread has no TLS array for now. */
2325 VGOFF_(tls) = alloc_BaB_1_set((UInt)NULL);
fitzhardingef0046f22003-12-18 02:39:22 +00002326
nethercote71980f02004-01-24 18:18:54 +00002327 /* segment registers */
2328 VGOFF_(m_cs) = alloc_BaB_1_set(0);
2329 VGOFF_(m_ss) = alloc_BaB_1_set(0);
2330 VGOFF_(m_ds) = alloc_BaB_1_set(0);
2331 VGOFF_(m_es) = alloc_BaB_1_set(0);
2332 VGOFF_(m_fs) = alloc_BaB_1_set(0);
2333 VGOFF_(m_gs) = alloc_BaB_1_set(0);
fitzhardingef0046f22003-12-18 02:39:22 +00002334
thughes35cec982004-04-21 15:16:43 +00002335 /* initialise %cs, %ds and %ss to point at the operating systems
2336 default code, data and stack segments */
2337 asm volatile("movw %%cs, %0"
2338 :
2339 : "m" (VG_(baseBlock)[VGOFF_(m_cs)]));
2340 asm volatile("movw %%ds, %0"
2341 :
2342 : "m" (VG_(baseBlock)[VGOFF_(m_ds)]));
2343 asm volatile("movw %%ss, %0"
2344 :
2345 : "m" (VG_(baseBlock)[VGOFF_(m_ss)]));
2346
nethercote71980f02004-01-24 18:18:54 +00002347 VG_(register_noncompact_helper)( (Addr) & VG_(do_useseg) );
fitzhardingef0046f22003-12-18 02:39:22 +00002348
nethercote71980f02004-01-24 18:18:54 +00002349#define REG(kind, size) \
2350 if (VG_(defined_##kind##_mem_stack##size)()) \
2351 VG_(register_noncompact_helper)( \
2352 (Addr) VG_(tool_interface).track_##kind##_mem_stack##size );
2353 REG(new, _8);
2354 REG(new, _12);
2355 REG(new, _16);
2356 REG(new, _32);
2357 REG(new, );
2358 REG(die, _8);
2359 REG(die, _12);
2360 REG(die, _16);
2361 REG(die, _32);
2362 REG(die, );
2363#undef REG
fitzhardingef0046f22003-12-18 02:39:22 +00002364
nethercote71980f02004-01-24 18:18:54 +00002365 if (VG_(need_to_handle_esp_assignment)())
2366 VG_(register_noncompact_helper)((Addr) VG_(unknown_esp_update));
fitzhardingeb791a192003-12-18 07:22:44 +00002367
nethercote71980f02004-01-24 18:18:54 +00002368# define HELPER(name) \
2369 VGOFF_(helper_##name) = alloc_BaB_1_set( (Addr) & VG_(helper_##name))
njn3e884182003-04-15 13:03:23 +00002370
nethercote71980f02004-01-24 18:18:54 +00002371 /* Helper functions. */
2372 HELPER(idiv_64_32); HELPER(div_64_32);
2373 HELPER(idiv_32_16); HELPER(div_32_16);
2374 HELPER(idiv_16_8); HELPER(div_16_8);
fitzhardinge98abfc72003-12-16 02:05:15 +00002375
nethercote71980f02004-01-24 18:18:54 +00002376 HELPER(imul_32_64); HELPER(mul_32_64);
2377 HELPER(imul_16_32); HELPER(mul_16_32);
2378 HELPER(imul_8_16); HELPER(mul_8_16);
njn25e49d8e72002-09-23 09:36:25 +00002379
nethercote71980f02004-01-24 18:18:54 +00002380 HELPER(CLD); HELPER(STD);
2381 HELPER(get_dirflag);
sewardjde4a1d02002-03-22 01:27:54 +00002382
nethercote71980f02004-01-24 18:18:54 +00002383 HELPER(CLC); HELPER(STC);
nethercote1018bdd2004-02-11 23:33:29 +00002384 HELPER(CMC);
jsgf855d93d2003-10-13 22:26:55 +00002385
nethercote71980f02004-01-24 18:18:54 +00002386 HELPER(shldl); HELPER(shldw);
2387 HELPER(shrdl); HELPER(shrdw);
njncc7bb472002-10-14 09:25:19 +00002388
nethercote71980f02004-01-24 18:18:54 +00002389 HELPER(RDTSC); HELPER(CPUID);
njncc7bb472002-10-14 09:25:19 +00002390
nethercote1018bdd2004-02-11 23:33:29 +00002391 HELPER(bsfw); HELPER(bsfl);
2392 HELPER(bsrw); HELPER(bsrl);
rjwalshf5f536f2003-11-17 17:45:00 +00002393
nethercote71980f02004-01-24 18:18:54 +00002394 HELPER(fstsw_AX);
2395 HELPER(SAHF); HELPER(LAHF);
2396 HELPER(DAS); HELPER(DAA);
nethercote1018bdd2004-02-11 23:33:29 +00002397 HELPER(AAS); HELPER(AAA);
2398 HELPER(AAD); HELPER(AAM);
nethercote71980f02004-01-24 18:18:54 +00002399 HELPER(IN); HELPER(OUT);
2400 HELPER(cmpxchg8b);
sewardj018f7622002-05-15 21:13:39 +00002401
nethercote71980f02004-01-24 18:18:54 +00002402 HELPER(undefined_instruction);
jsgf855d93d2003-10-13 22:26:55 +00002403
nethercote71980f02004-01-24 18:18:54 +00002404# undef HELPER
sewardjde4a1d02002-03-22 01:27:54 +00002405
nethercote71980f02004-01-24 18:18:54 +00002406 /* Allocate slots for noncompact helpers */
2407 assign_helpers_in_baseBlock(VG_(n_noncompact_helpers),
2408 VG_(noncompact_helper_offsets),
2409 VG_(noncompact_helper_addrs));
2410}
sewardjde4a1d02002-03-22 01:27:54 +00002411
sewardj5f07b662002-04-23 16:52:51 +00002412
nethercote71980f02004-01-24 18:18:54 +00002413/*====================================================================*/
2414/*=== Setup pointercheck ===*/
2415/*====================================================================*/
njn25e49d8e72002-09-23 09:36:25 +00002416
nethercote71980f02004-01-24 18:18:54 +00002417static void setup_pointercheck(void)
2418{
2419 int ret;
sewardj2e93c502002-04-12 11:12:52 +00002420
fitzhardinge98abfc72003-12-16 02:05:15 +00002421 if (VG_(clo_pointercheck)) {
nethercote71980f02004-01-24 18:18:54 +00002422 vki_modify_ldt_t ldt = {
2423 VG_POINTERCHECK_SEGIDX, // entry_number
2424 VG_(client_base), // base_addr
2425 (VG_(client_end)-VG_(client_base)) / VKI_BYTES_PER_PAGE, // limit
2426 1, // seg_32bit
2427 0, // contents: data, RW, non-expanding
2428 0, // ! read_exec_only
2429 1, // limit_in_pages
2430 0, // ! seg not present
2431 1, // useable
fitzhardinge98abfc72003-12-16 02:05:15 +00002432 };
nethercote71980f02004-01-24 18:18:54 +00002433 ret = VG_(do_syscall)(__NR_modify_ldt, 1, &ldt, sizeof(ldt));
fitzhardinge98abfc72003-12-16 02:05:15 +00002434 if (ret < 0) {
2435 VG_(message)(Vg_UserMsg,
2436 "Warning: ignoring --pointercheck=yes, "
2437 "because modify_ldt failed (errno=%d)", -ret);
2438 VG_(clo_pointercheck) = False;
2439 }
2440 }
sewardjde4a1d02002-03-22 01:27:54 +00002441}
2442
nethercote71980f02004-01-24 18:18:54 +00002443/*====================================================================*/
2444/*=== Initialise program data/text, etc. ===*/
2445/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +00002446
nethercote71980f02004-01-24 18:18:54 +00002447static void build_valgrind_map_callback
2448 ( Addr start, UInt size, Char rr, Char ww, Char xx,
2449 UInt dev, UInt ino, ULong foffset, const UChar* filename )
sewardjde4a1d02002-03-22 01:27:54 +00002450{
nethercote71980f02004-01-24 18:18:54 +00002451 UInt prot = 0;
2452 UInt flags = SF_MMAP|SF_NOSYMS;
2453 Bool is_stack_segment;
2454
2455 is_stack_segment =
2456 (start == VG_(clstk_base) && (start+size) == VG_(clstk_end));
2457
2458 /* Only record valgrind mappings for now, without loading any
2459 symbols. This is so we know where the free space is before we
2460 start allocating more memory (note: heap is OK, it's just mmap
2461 which is the problem here). */
2462 if (start >= VG_(valgrind_base) && (start+size) <= VG_(valgrind_end)) {
2463 flags |= SF_VALGRIND;
2464 VG_(map_file_segment)(start, size, prot, flags, dev, ino, foffset, filename);
2465 }
sewardjde4a1d02002-03-22 01:27:54 +00002466}
2467
nethercote71980f02004-01-24 18:18:54 +00002468// Global var used to pass local data to callback
2469Addr esp_at_startup___global_arg = 0;
sewardjde4a1d02002-03-22 01:27:54 +00002470
nethercote71980f02004-01-24 18:18:54 +00002471static void build_segment_map_callback
2472 ( Addr start, UInt size, Char rr, Char ww, Char xx,
2473 UInt dev, UInt ino, ULong foffset, const UChar* filename )
sewardj45b672d2003-07-25 19:58:11 +00002474{
nethercote71980f02004-01-24 18:18:54 +00002475 UInt prot = 0;
2476 UInt flags;
2477 Bool is_stack_segment;
2478 Addr r_esp;
sewardj45b672d2003-07-25 19:58:11 +00002479
nethercote71980f02004-01-24 18:18:54 +00002480 is_stack_segment
2481 = (start == VG_(clstk_base) && (start+size) == VG_(clstk_end));
fitzhardinge98abfc72003-12-16 02:05:15 +00002482
nethercote71980f02004-01-24 18:18:54 +00002483 if (rr == 'r') prot |= VKI_PROT_READ;
2484 if (ww == 'w') prot |= VKI_PROT_WRITE;
2485 if (xx == 'x') prot |= VKI_PROT_EXEC;
fitzhardinge98abfc72003-12-16 02:05:15 +00002486
nethercote71980f02004-01-24 18:18:54 +00002487 if (is_stack_segment)
2488 flags = SF_STACK | SF_GROWDOWN;
2489 else
2490 flags = SF_EXEC|SF_MMAP;
fitzhardinge98abfc72003-12-16 02:05:15 +00002491
nethercote71980f02004-01-24 18:18:54 +00002492 if (filename != NULL)
2493 flags |= SF_FILE;
fitzhardinge98abfc72003-12-16 02:05:15 +00002494
nethercote71980f02004-01-24 18:18:54 +00002495 if (start >= VG_(valgrind_base) && (start+size) <= VG_(valgrind_end))
2496 flags |= SF_VALGRIND;
fitzhardinge98abfc72003-12-16 02:05:15 +00002497
nethercote71980f02004-01-24 18:18:54 +00002498 VG_(map_file_segment)(start, size, prot, flags, dev, ino, foffset, filename);
fitzhardinge98abfc72003-12-16 02:05:15 +00002499
nethercote71980f02004-01-24 18:18:54 +00002500 if (VG_(is_client_addr)(start) && VG_(is_client_addr)(start+size-1))
2501 VG_TRACK( new_mem_startup, start, size, rr=='r', ww=='w', xx=='x' );
sewardj3e1eb1f2002-05-18 13:14:17 +00002502
nethercote71980f02004-01-24 18:18:54 +00002503 /* If this is the stack segment mark all below %esp as noaccess. */
2504 r_esp = esp_at_startup___global_arg;
2505 vg_assert(0 != r_esp);
2506 if (is_stack_segment) {
2507 if (0)
2508 VG_(message)(Vg_DebugMsg, "invalidating stack area: %x .. %x",
2509 start,r_esp);
2510 VG_TRACK( die_mem_stack, start, r_esp-start );
sewardjde4a1d02002-03-22 01:27:54 +00002511 }
sewardjde4a1d02002-03-22 01:27:54 +00002512}
2513
2514
nethercote71980f02004-01-24 18:18:54 +00002515/*====================================================================*/
2516/*=== Sanity check machinery (permanently engaged) ===*/
2517/*====================================================================*/
njn25e49d8e72002-09-23 09:36:25 +00002518
2519/* A fast sanity check -- suitable for calling circa once per
2520 millisecond. */
2521
2522void VG_(do_sanity_checks) ( Bool force_expensive )
2523{
njn37cea302002-09-30 11:24:00 +00002524 VGP_PUSHCC(VgpCoreCheapSanity);
2525
nethercote27fec902004-06-16 21:26:32 +00002526 if (VG_(clo_sanity_level) < 1) return;
njn25e49d8e72002-09-23 09:36:25 +00002527
2528 /* --- First do all the tests that we can do quickly. ---*/
2529
nethercote297effd2004-08-02 15:07:57 +00002530 sanity_fast_count++;
njn25e49d8e72002-09-23 09:36:25 +00002531
njn25e49d8e72002-09-23 09:36:25 +00002532 /* Check stuff pertaining to the memory check system. */
2533
2534 /* Check that nobody has spuriously claimed that the first or
2535 last 16 pages of memory have become accessible [...] */
njn37cea302002-09-30 11:24:00 +00002536 if (VG_(needs).sanity_checks) {
2537 VGP_PUSHCC(VgpSkinCheapSanity);
njn25e49d8e72002-09-23 09:36:25 +00002538 vg_assert(SK_(cheap_sanity_check)());
njn37cea302002-09-30 11:24:00 +00002539 VGP_POPCC(VgpSkinCheapSanity);
2540 }
njn25e49d8e72002-09-23 09:36:25 +00002541
2542 /* --- Now some more expensive checks. ---*/
2543
2544 /* Once every 25 times, check some more expensive stuff. */
2545 if ( force_expensive
nethercote27fec902004-06-16 21:26:32 +00002546 || VG_(clo_sanity_level) > 1
nethercote297effd2004-08-02 15:07:57 +00002547 || (VG_(clo_sanity_level) == 1 && (sanity_fast_count % 25) == 0)) {
njn25e49d8e72002-09-23 09:36:25 +00002548
njn37cea302002-09-30 11:24:00 +00002549 VGP_PUSHCC(VgpCoreExpensiveSanity);
nethercote297effd2004-08-02 15:07:57 +00002550 sanity_slow_count++;
njn25e49d8e72002-09-23 09:36:25 +00002551
jsgf855d93d2003-10-13 22:26:55 +00002552 VG_(proxy_sanity)();
2553
njn25e49d8e72002-09-23 09:36:25 +00002554# if 0
2555 { void zzzmemscan(void); zzzmemscan(); }
2556# endif
2557
nethercote297effd2004-08-02 15:07:57 +00002558 if ((sanity_fast_count % 250) == 0)
njn25e49d8e72002-09-23 09:36:25 +00002559 VG_(sanity_check_tc_tt)();
2560
2561 if (VG_(needs).sanity_checks) {
njn37cea302002-09-30 11:24:00 +00002562 VGP_PUSHCC(VgpSkinExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002563 vg_assert(SK_(expensive_sanity_check)());
njn37cea302002-09-30 11:24:00 +00002564 VGP_POPCC(VgpSkinExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002565 }
2566 /*
nethercote297effd2004-08-02 15:07:57 +00002567 if ((sanity_fast_count % 500) == 0) VG_(mallocSanityCheckAll)();
njn25e49d8e72002-09-23 09:36:25 +00002568 */
njn37cea302002-09-30 11:24:00 +00002569 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002570 }
2571
nethercote27fec902004-06-16 21:26:32 +00002572 if (VG_(clo_sanity_level) > 1) {
njn37cea302002-09-30 11:24:00 +00002573 VGP_PUSHCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002574 /* Check sanity of the low-level memory manager. Note that bugs
2575 in the client's code can cause this to fail, so we don't do
2576 this check unless specially asked for. And because it's
2577 potentially very expensive. */
2578 VG_(mallocSanityCheckAll)();
njn37cea302002-09-30 11:24:00 +00002579 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002580 }
njn37cea302002-09-30 11:24:00 +00002581 VGP_POPCC(VgpCoreCheapSanity);
njn25e49d8e72002-09-23 09:36:25 +00002582}
nethercote71980f02004-01-24 18:18:54 +00002583
2584
2585/*====================================================================*/
2586/*=== main() ===*/
2587/*====================================================================*/
2588
nethercotec314eba2004-07-15 12:59:41 +00002589/*
2590 This code decides on the layout of the client and Valgrind address
2591 spaces, loads valgrind.so and the skin.so into the valgrind part,
2592 loads the client executable (and the dynamic linker, if necessary)
2593 into the client part, and calls into Valgrind proper.
2594
2595 The code is careful not to allow spurious mappings to appear in the
2596 wrong parts of the address space. In particular, to make sure
2597 dlopen puts things in the right place, it will pad out the forbidden
2598 chunks of address space so that dlopen is forced to put things where
2599 we want them.
2600
2601 The memory map it creates is:
2602
2603 CLIENT_BASE +-------------------------+
2604 | client address space |
2605 : :
2606 : :
2607 | client stack |
2608 client_end +-------------------------+
2609 | redzone |
2610 shadow_base +-------------------------+
2611 | |
2612 : shadow memory for skins :
2613 | (may be 0 sized) |
2614 shadow_end +-------------------------+
2615 : gap (may be 0 sized) :
2616 valgrind_base +-------------------------+
2617 | kickstart executable |
2618 | valgrind heap vvvvvvvvv| (barely used)
2619 - -
2620 | valgrind .so files |
2621 | and mappings |
2622 - -
2623 | valgrind stack ^^^^^^^^^|
2624 valgrind_end +-------------------------+
2625 : kernel :
2626
2627 Nb: Before we can do general allocations with VG_(arena_malloc)() and
2628 VG_(mmap)(), we need to build the segment skip-list, so we know where
2629 we can put things. However, building that structure requires
2630 allocating memory. So we need to a bootstrapping process. It's done
2631 by making VG_(arena_malloc)() have a special static superblock that's
2632 used for the first 1MB's worth of allocations. This is enough to
2633 build the segment skip-list.
2634*/
2635
nethercote31779c72004-07-30 21:50:15 +00002636static int prmap(char *start, char *end, const char *perm, off_t off,
2637 int maj, int min, int ino, void* dummy) {
thughes4ad52d02004-06-27 17:37:21 +00002638 printf("mapping %10p-%10p %s %02x:%02x %d\n",
2639 start, end, perm, maj, min, ino);
2640 return True;
2641}
2642
nethercote71980f02004-01-24 18:18:54 +00002643int main(int argc, char **argv)
2644{
2645 char **cl_argv;
2646 const char *tool = NULL;
2647 const char *exec = NULL;
2648 char *preload; /* tool-specific LD_PRELOAD .so */
2649 char **env;
nethercote6c999f22004-01-31 22:55:15 +00002650 Int need_help = 0; // 0 = no, 1 = --help, 2 = --help-debug
nethercote71980f02004-01-24 18:18:54 +00002651 struct exeinfo info;
2652 ToolInfo *toolinfo = NULL;
2653 void *tool_dlhandle;
2654 Addr client_eip;
2655 Addr esp_at_startup; /* client's %esp at the point we gained control. */
2656 UInt * client_auxv;
2657 VgSchedReturnCode src;
nethercote47dd12c2004-06-22 14:18:42 +00002658 Int exitcode = 0;
fitzhardingeb50068f2004-02-24 23:42:55 +00002659 vki_rlimit zero = { 0, 0 };
nethercote31779c72004-07-30 21:50:15 +00002660 Int padfile;
nethercote71980f02004-01-24 18:18:54 +00002661
2662 //============================================================
2663 // Nb: startup is complex. Prerequisites are shown at every step.
2664 //
2665 // *** Be very careful when messing with the order ***
2666 //============================================================
2667
nethercotef4928da2004-06-15 10:54:40 +00002668 //============================================================
2669 // Command line argument handling order:
2670 // * If --help/--help-debug are present, show usage message
2671 // (if --tool is also present, that includes the tool-specific usage)
2672 // * Then, if --tool is missing, abort with error msg
2673 // * Then, if client is missing, abort with error msg
2674 // * Then, if any cmdline args are bad, abort with error msg
2675 //============================================================
2676
fitzhardingeb50068f2004-02-24 23:42:55 +00002677 // Get the current process datasize rlimit, and set it to zero.
2678 // This prevents any internal uses of brk() from having any effect.
2679 // We remember the old value so we can restore it on exec, so that
2680 // child processes will have a reasonable brk value.
2681 VG_(getrlimit)(VKI_RLIMIT_DATA, &VG_(client_rlimit_data));
2682 zero.rlim_max = VG_(client_rlimit_data).rlim_max;
2683 VG_(setrlimit)(VKI_RLIMIT_DATA, &zero);
2684
nethercote71980f02004-01-24 18:18:54 +00002685 //--------------------------------------------------------------
2686 // Check we were launched by stage1
nethercotec314eba2004-07-15 12:59:41 +00002687 // p: n/a
nethercote71980f02004-01-24 18:18:54 +00002688 //--------------------------------------------------------------
nethercote31779c72004-07-30 21:50:15 +00002689 padfile = scan_auxv();
nethercote71980f02004-01-24 18:18:54 +00002690
2691 if (0) {
nethercote71980f02004-01-24 18:18:54 +00002692 printf("========== main() ==========\n");
nethercote31779c72004-07-30 21:50:15 +00002693 foreach_map(prmap, /*dummy*/NULL);
nethercote71980f02004-01-24 18:18:54 +00002694 }
2695
2696 //--------------------------------------------------------------
2697 // Look for alternative libdir
2698 // p: n/a
2699 //--------------------------------------------------------------
2700 { char *cp = getenv(VALGRINDLIB);
2701 if (cp != NULL)
2702 VG_(libdir) = cp;
2703 }
2704
2705 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002706 // Get valgrind args + client args (inc. from VALGRIND_OPTS/.valgrindrc).
2707 // Pre-process the command line.
2708 // p: n/a
2709 //--------------------------------------------------------------
2710 get_command_line(argc, argv, &VG_(vg_argc), &VG_(vg_argv), &cl_argv);
2711 pre_process_cmd_line_options(&need_help, &tool, &exec);
2712
2713 //==============================================================
2714 // Nb: once a tool is specified, the tool.so must be loaded even if
2715 // they specified --help or didn't specify a client program.
2716 //==============================================================
2717
2718 //--------------------------------------------------------------
2719 // With client padded out, map in tool
nethercote71980f02004-01-24 18:18:54 +00002720 // p: set-libdir [for VG_(libdir)]
2721 // p: pre_process_cmd_line_options() [for 'tool']
2722 //--------------------------------------------------------------
2723 load_tool(tool, &tool_dlhandle, &toolinfo, &preload);
2724
2725 //==============================================================
2726 // Can use VG_(malloc)() and VG_(arena_malloc)() only after load_tool()
nethercotec314eba2004-07-15 12:59:41 +00002727 // -- redzone size is now set. This is checked by vg_malloc2.c.
nethercote71980f02004-01-24 18:18:54 +00002728 //==============================================================
2729
2730 //--------------------------------------------------------------
2731 // Finalise address space layout
nethercote31779c72004-07-30 21:50:15 +00002732 // p: load_tool() [for 'toolinfo']
nethercote71980f02004-01-24 18:18:54 +00002733 //--------------------------------------------------------------
nethercote31779c72004-07-30 21:50:15 +00002734 layout_remaining_space( (Addr) & argc, toolinfo->shadow_ratio );
nethercote71980f02004-01-24 18:18:54 +00002735
2736 //--------------------------------------------------------------
2737 // Load client executable, finding in $PATH if necessary
nethercote71980f02004-01-24 18:18:54 +00002738 // p: pre_process_cmd_line_options() [for 'exec', 'need_help']
2739 // p: layout_remaining_space [so there's space]
2740 //--------------------------------------------------------------
nethercotef4928da2004-06-15 10:54:40 +00002741 load_client(cl_argv, exec, need_help, &info, &client_eip);
nethercote71980f02004-01-24 18:18:54 +00002742
2743 //--------------------------------------------------------------
2744 // Everything in place, unpad us
2745 // p: layout_remaining_space() [everything must be mapped in before now]
2746 // p: load_client() [ditto]
2747 //--------------------------------------------------------------
nethercote31779c72004-07-30 21:50:15 +00002748 as_unpad((void *)VG_(shadow_end), (void *)~0, padfile);
2749 as_closepadfile(padfile); // no more padding
nethercote71980f02004-01-24 18:18:54 +00002750
2751 //--------------------------------------------------------------
2752 // Set up client's environment
2753 // p: set-libdir [for VG_(libdir)]
2754 // p: load_tool() [for 'preload']
2755 //--------------------------------------------------------------
2756 env = fix_environment(environ, preload);
2757
2758 //--------------------------------------------------------------
nethercote5ee67ca2004-06-22 14:00:09 +00002759 // Setup client stack, eip, and VG_(client_arg[cv])
nethercote71980f02004-01-24 18:18:54 +00002760 // p: load_client() [for 'info']
2761 // p: fix_environment() [for 'env']
2762 //--------------------------------------------------------------
2763 esp_at_startup = setup_client_stack(cl_argv, env, &info, &client_auxv);
2764
2765 if (0)
2766 printf("entry=%x client esp=%x vg_argc=%d brkbase=%x\n",
2767 client_eip, esp_at_startup, VG_(vg_argc), VG_(brk_base));
2768
2769 //==============================================================
2770 // Finished setting up operating environment. Now initialise
2771 // Valgrind. (This is where the old VG_(main)() started.)
2772 //==============================================================
2773
2774 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002775 // atfork
2776 // p: n/a
2777 //--------------------------------------------------------------
2778 VG_(atfork)(NULL, NULL, newpid);
2779 newpid(VG_INVALID_THREADID);
2780
2781 //--------------------------------------------------------------
2782 // setup file descriptors
2783 // p: n/a
2784 //--------------------------------------------------------------
2785 setup_file_descriptors();
2786
2787 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002788 // Read /proc/self/maps into a buffer
2789 // p: all memory layout, environment setup [so memory maps are right]
2790 //--------------------------------------------------------------
2791 VG_(read_procselfmaps)();
2792
2793 //--------------------------------------------------------------
2794 // Build segment map (Valgrind segments only)
2795 // p: read proc/self/maps
2796 // p: sk_pre_clo_init() [to setup new_mem_startup tracker]
2797 //--------------------------------------------------------------
2798 VG_(parse_procselfmaps) ( build_valgrind_map_callback );
2799
2800 //==============================================================
2801 // Can use VG_(arena_malloc)() with non-CORE arena after segments set up
2802 //==============================================================
2803
2804 //--------------------------------------------------------------
2805 // Init tool: pre_clo_init, process cmd line, post_clo_init
2806 // p: setup_client_stack() [for 'VG_(client_arg[cv]']
2807 // p: load_tool() [for 'tool']
2808 // p: setup_file_descriptors() [for 'VG_(fd_xxx_limit)']
2809 // p: parse_procselfmaps [so VG segments are setup so tool can
2810 // call VG_(malloc)]
nethercote71980f02004-01-24 18:18:54 +00002811 //--------------------------------------------------------------
2812 (*toolinfo->sk_pre_clo_init)();
2813 VG_(tool_init_dlsym)(tool_dlhandle);
2814 VG_(sanity_check_needs)();
2815
nethercotef4928da2004-06-15 10:54:40 +00002816 // If --tool and --help/--help-debug was given, now give the core+tool
2817 // help message
nethercotef4928da2004-06-15 10:54:40 +00002818 if (need_help) {
2819 usage(/*--help-debug?*/2 == need_help);
2820 }
nethercotec314eba2004-07-15 12:59:41 +00002821 process_cmd_line_options(client_auxv, tool);
2822
2823 SK_(post_clo_init)();
nethercotef4928da2004-06-15 10:54:40 +00002824
2825 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002826 // Build segment map (all segments)
2827 // p: setup_client_stack() [for 'esp_at_startup']
2828 // p: init tool [for 'new_mem_startup']
nethercote71980f02004-01-24 18:18:54 +00002829 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002830 esp_at_startup___global_arg = esp_at_startup;
2831 VG_(parse_procselfmaps) ( build_segment_map_callback ); /* everything */
2832 esp_at_startup___global_arg = 0;
2833
2834 //--------------------------------------------------------------
nethercotef84f6952004-07-15 14:58:33 +00002835 // Protect client trampoline page (which is also sysinfo stuff)
2836 // p: segment stuff [otherwise get seg faults...]
nethercotec314eba2004-07-15 12:59:41 +00002837 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002838 VG_(mprotect)( (void *)VG_(client_trampoline_code),
2839 VG_(trampoline_code_length), VKI_PROT_READ|VKI_PROT_EXEC );
2840
2841 //==============================================================
2842 // Can use VG_(map)() after segments set up
2843 //==============================================================
nethercote71980f02004-01-24 18:18:54 +00002844
2845 //--------------------------------------------------------------
2846 // Allow GDB attach
2847 // p: process_cmd_line_options() [for VG_(clo_wait_for_gdb)]
2848 //--------------------------------------------------------------
2849 /* Hook to delay things long enough so we can get the pid and
2850 attach GDB in another shell. */
2851 if (VG_(clo_wait_for_gdb)) {
2852 VG_(printf)("pid=%d\n", VG_(getpid)());
2853 /* do "jump *$eip" to skip this in gdb */
2854 VG_(do_syscall)(__NR_pause);
2855 }
2856
2857 //--------------------------------------------------------------
nethercote1d447092004-02-01 17:29:59 +00002858 // Set up baseBlock
nethercote71980f02004-01-24 18:18:54 +00002859 // p: {pre,post}_clo_init() [for tool helper registration]
2860 // load_client() [for 'client_eip']
2861 // setup_client_stack() [for 'esp_at_startup']
2862 //--------------------------------------------------------------
2863 init_baseBlock(client_eip, esp_at_startup);
2864
2865 //--------------------------------------------------------------
2866 // Search for file descriptors that are inherited from our parent
2867 // p: process_cmd_line_options [for VG_(clo_track_fds)]
2868 //--------------------------------------------------------------
2869 if (VG_(clo_track_fds))
2870 VG_(init_preopened_fds)();
2871
2872 //--------------------------------------------------------------
2873 // Initialise the scheduler
2874 // p: init_baseBlock() [baseBlock regs copied into VG_(threads)[1]]
2875 // p: setup_file_descriptors() [else VG_(safe_fd)() breaks]
2876 //--------------------------------------------------------------
2877 VG_(scheduler_init)();
2878
2879 //--------------------------------------------------------------
2880 // Set up the ProxyLWP machinery
2881 // p: VG_(scheduler_init)()? [XXX: subtle dependency?]
2882 // - subs: VG_(sigstartup_actions)()?
2883 //--------------------------------------------------------------
2884 VG_(proxy_init)();
2885
2886 //--------------------------------------------------------------
2887 // Initialise the signal handling subsystem
2888 // p: VG_(atfork)(NULL, NULL, newpid) [else problems with sigmasks]
2889 // p: VG_(proxy_init)() [else breaks...]
2890 //--------------------------------------------------------------
2891 // Nb: temporarily parks the saved blocking-mask in saved_sigmask.
2892 VG_(sigstartup_actions)();
2893
2894 //--------------------------------------------------------------
2895 // Perhaps we're profiling Valgrind?
2896 // p: process_cmd_line_options() [for VG_(clo_profile)]
2897 // p: others?
2898 //
2899 // XXX: this seems to be broken? It always says the tool wasn't built
2900 // for profiling; vg_profile.c's functions don't seem to be overriding
2901 // vg_dummy_profile.c's?
2902 //
2903 // XXX: want this as early as possible. Looking for --profile
2904 // in pre_process_cmd_line_options() could get it earlier.
2905 //--------------------------------------------------------------
2906 if (VG_(clo_profile))
2907 VGP_(init_profiling)();
2908
2909 VGP_PUSHCC(VgpStartup);
2910
2911 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002912 // Read suppression file
2913 // p: process_cmd_line_options() [for VG_(clo_suppressions)]
2914 //--------------------------------------------------------------
2915 if (VG_(needs).core_errors || VG_(needs).skin_errors)
2916 VG_(load_suppressions)();
2917
2918 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002919 // Initialise translation table and translation cache
2920 // p: read_procselfmaps [so the anonymous mmaps for the TT/TC
2921 // aren't identified as part of the client, which would waste
2922 // > 20M of virtual address space.]
2923 //--------------------------------------------------------------
2924 VG_(init_tt_tc)();
2925
2926 //--------------------------------------------------------------
2927 // Read debug info to find glibc entry points to intercept
2928 // p: parse_procselfmaps? [XXX for debug info?]
2929 // p: init_tt_tc? [XXX ???]
2930 //--------------------------------------------------------------
2931 VG_(setup_code_redirect_table)();
2932
2933 //--------------------------------------------------------------
2934 // Verbosity message
2935 // p: end_rdtsc_calibration [so startup message is printed first]
2936 //--------------------------------------------------------------
2937 if (VG_(clo_verbosity) == 1)
2938 VG_(message)(Vg_UserMsg, "For more details, rerun with: -v");
2939 if (VG_(clo_verbosity) > 0)
2940 VG_(message)(Vg_UserMsg, "");
2941
2942 //--------------------------------------------------------------
2943 // Setup pointercheck
2944 // p: process_cmd_line_options() [for VG_(clo_pointercheck)]
2945 //--------------------------------------------------------------
2946 setup_pointercheck();
2947
nethercote71980f02004-01-24 18:18:54 +00002948 //--------------------------------------------------------------
2949 // Run!
2950 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002951 VGP_POPCC(VgpStartup);
2952 VGP_PUSHCC(VgpSched);
2953
nethercote31294822004-08-02 13:15:26 +00002954 VG_(fatal_signal_jmpbuf_ptr) = &fatal_signal_jmpbuf;
2955 if (__builtin_setjmp(VG_(fatal_signal_jmpbuf_ptr)) == 0) {
nethercote47dd12c2004-06-22 14:18:42 +00002956 src = VG_(scheduler)( &exitcode );
nethercote31294822004-08-02 13:15:26 +00002957 } else {
nethercote71980f02004-01-24 18:18:54 +00002958 src = VgSrc_FatalSig;
nethercote31294822004-08-02 13:15:26 +00002959 }
nethercote71980f02004-01-24 18:18:54 +00002960 VGP_POPCC(VgpSched);
nethercote71980f02004-01-24 18:18:54 +00002961
2962
2963
2964 //--------------------------------------------------------------
2965 // Finalisation: cleanup, messages, etc. Order no so important, only
2966 // affects what order the messages come.
2967 //--------------------------------------------------------------
2968 if (VG_(clo_verbosity) > 0)
2969 VG_(message)(Vg_UserMsg, "");
2970
2971 if (src == VgSrc_Deadlock) {
2972 VG_(message)(Vg_UserMsg,
2973 "Warning: pthread scheduler exited due to deadlock");
2974 }
2975
2976 /* Print out file descriptor summary and stats. */
2977 if (VG_(clo_track_fds))
2978 VG_(fd_stats)();
2979
2980 if (VG_(needs).core_errors || VG_(needs).skin_errors)
2981 VG_(show_all_errors)();
2982
nethercote47dd12c2004-06-22 14:18:42 +00002983 SK_(fini)( exitcode );
nethercote71980f02004-01-24 18:18:54 +00002984
2985 VG_(do_sanity_checks)( True /*include expensive checks*/ );
2986
2987 if (VG_(clo_verbosity) > 1)
2988 show_counts();
2989
2990 if (VG_(clo_verbosity) > 3)
2991 VG_(print_UInstr_histogram)();
2992
2993 if (0) {
2994 VG_(message)(Vg_DebugMsg, "");
2995 VG_(message)(Vg_DebugMsg,
2996 "------ Valgrind's internal memory use stats follow ------" );
2997 VG_(mallocSanityCheckAll)();
2998 VG_(show_all_arena_stats)();
2999 VG_(message)(Vg_DebugMsg,
3000 "------ Valgrind's ExeContext management stats follow ------" );
3001 VG_(show_ExeContext_stats)();
3002 }
3003
3004 if (VG_(clo_profile))
3005 VGP_(done_profiling)();
3006
nethercote71980f02004-01-24 18:18:54 +00003007 /* We're exiting, so nuke all the threads and clean up the proxy LWPs */
3008 vg_assert(src == VgSrc_FatalSig ||
3009 VG_(threads)[VG_(last_run_tid)].status == VgTs_Runnable ||
3010 VG_(threads)[VG_(last_run_tid)].status == VgTs_WaitJoiner);
3011 VG_(nuke_all_threads_except)(VG_INVALID_THREADID);
3012
3013 //--------------------------------------------------------------
3014 // Exit, according to the scheduler's return code
3015 //--------------------------------------------------------------
3016 switch (src) {
3017 case VgSrc_ExitSyscall: /* the normal way out */
nethercote85cdd342004-08-01 22:36:40 +00003018 vg_assert(VG_(last_run_tid) > 0 && VG_(last_run_tid) < VG_N_THREADS);
nethercote71980f02004-01-24 18:18:54 +00003019 VG_(proxy_shutdown)();
3020
3021 /* The thread's %EBX at the time it did __NR_exit() will hold
3022 the arg to __NR_exit(), so we just do __NR_exit() with
3023 that arg. */
nethercote47dd12c2004-06-22 14:18:42 +00003024 VG_(exit)( exitcode );
nethercote71980f02004-01-24 18:18:54 +00003025 /* NOT ALIVE HERE! */
3026 VG_(core_panic)("entered the afterlife in main() -- ExitSyscall");
3027 break; /* what the hell :) */
3028
3029 case VgSrc_Deadlock:
3030 /* Just exit now. No point in continuing. */
3031 VG_(proxy_shutdown)();
3032 VG_(exit)(0);
3033 VG_(core_panic)("entered the afterlife in main() -- Deadlock");
3034 break;
3035
nethercote71980f02004-01-24 18:18:54 +00003036 case VgSrc_FatalSig:
3037 /* We were killed by a fatal signal, so replicate the effect */
3038 vg_assert(VG_(fatal_sigNo) != -1);
3039 VG_(kill_self)(VG_(fatal_sigNo));
3040 VG_(core_panic)("main(): signal was supposed to be fatal");
3041 break;
3042
3043 default:
3044 VG_(core_panic)("main(): unexpected scheduler return code");
3045 }
3046
3047 abort();
3048}
3049
3050
sewardjde4a1d02002-03-22 01:27:54 +00003051/*--------------------------------------------------------------------*/
3052/*--- end vg_main.c ---*/
3053/*--------------------------------------------------------------------*/