blob: b70eb5fc63c27db8ba624e66e93252fd02f29b1d [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
200
201/* Counts pertaining to the register allocator. */
202
203/* total number of uinstrs input to reg-alloc */
204UInt VG_(uinstrs_prealloc) = 0;
205
206/* total number of uinstrs added due to spill code */
207UInt VG_(uinstrs_spill) = 0;
208
209/* number of bbs requiring spill code */
210UInt VG_(translations_needing_spill) = 0;
211
212/* total of register ranks over all translations */
213UInt VG_(total_reg_rank) = 0;
214
215
sewardjde4a1d02002-03-22 01:27:54 +0000216/* Counts pertaining to internal sanity checking. */
nethercote297effd2004-08-02 15:07:57 +0000217static UInt sanity_fast_count = 0;
218static UInt sanity_slow_count = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000219
sewardj2e93c502002-04-12 11:12:52 +0000220/* Counts pertaining to the scheduler. */
221UInt VG_(num_scheduling_events_MINOR) = 0;
222UInt VG_(num_scheduling_events_MAJOR) = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000223
224
nethercote71980f02004-01-24 18:18:54 +0000225static __inline__ Int safe_idiv(Int a, Int b)
226{
227 return (b == 0 ? 0 : a / b);
228}
229
230static void show_counts ( void )
231{
232 VG_(message)(Vg_DebugMsg,
233 " TT/TC: %d tc sectors discarded.",
234 VG_(number_of_tc_discards) );
235 VG_(message)(Vg_DebugMsg,
236 " %d chainings, %d unchainings.",
237 VG_(bb_enchain_count), VG_(bb_dechain_count) );
238 VG_(message)(Vg_DebugMsg,
239 "translate: new %d (%d -> %d; ratio %d:10)",
240 VG_(overall_in_count),
241 VG_(overall_in_osize),
242 VG_(overall_in_tsize),
243 safe_idiv(10*VG_(overall_in_tsize), VG_(overall_in_osize)));
244 VG_(message)(Vg_DebugMsg,
245 " discard %d (%d -> %d; ratio %d:10).",
246 VG_(overall_out_count),
247 VG_(overall_out_osize),
248 VG_(overall_out_tsize),
249 safe_idiv(10*VG_(overall_out_tsize), VG_(overall_out_osize)));
250 VG_(message)(Vg_DebugMsg,
251 " dispatch: %llu jumps (bb entries), of which %u (%lu%%) were unchained.",
252 VG_(bbs_done),
253 VG_(unchained_jumps_done),
254 ((ULong)(100) * (ULong)(VG_(unchained_jumps_done)))
255 / ( VG_(bbs_done)==0 ? 1 : VG_(bbs_done) )
256 );
257
258 VG_(message)(Vg_DebugMsg,
259 " %d/%d major/minor sched events. %d tt_fast misses.",
260 VG_(num_scheduling_events_MAJOR),
261 VG_(num_scheduling_events_MINOR),
262 VG_(tt_fast_misses));
263
264 VG_(message)(Vg_DebugMsg,
265 "reg-alloc: %d t-req-spill, "
266 "%d+%d orig+spill uis, %d total-reg-r.",
267 VG_(translations_needing_spill),
268 VG_(uinstrs_prealloc),
269 VG_(uinstrs_spill),
270 VG_(total_reg_rank) );
271 VG_(message)(Vg_DebugMsg,
272 " sanity: %d cheap, %d expensive checks.",
nethercote297effd2004-08-02 15:07:57 +0000273 sanity_fast_count, sanity_slow_count );
nethercote71980f02004-01-24 18:18:54 +0000274 VG_(print_ccall_stats)();
275}
276
277
278/*====================================================================*/
279/*=== Miscellaneous global functions ===*/
280/*====================================================================*/
281
nethercote04d0fbc2004-01-26 16:48:06 +0000282/* Start debugger and get it to attach to this process. Called if the
283 user requests this service after an error has been shown, so she can
nethercote71980f02004-01-24 18:18:54 +0000284 poke around and look at parameters, memory, etc. You can't
nethercote04d0fbc2004-01-26 16:48:06 +0000285 meaningfully get the debugger to continue the program, though; to
286 continue, quit the debugger. */
287void VG_(start_debugger) ( Int tid )
nethercote71980f02004-01-24 18:18:54 +0000288{
289 Int pid;
290
291 if ((pid = fork()) == 0) {
292 ptrace(PTRACE_TRACEME, 0, NULL, NULL);
293 VG_(kkill)(VG_(getpid)(), VKI_SIGSTOP);
294
295 } else if (pid > 0) {
296 struct user_regs_struct regs;
297 Int status;
298 Int res;
299
300 if (VG_(is_running_thread)( tid )) {
fitzhardinged65dcad2004-03-13 02:06:58 +0000301 regs.cs = VG_(baseBlock)[VGOFF_(m_cs)];
302 regs.ss = VG_(baseBlock)[VGOFF_(m_ss)];
303 regs.ds = VG_(baseBlock)[VGOFF_(m_ds)];
304 regs.es = VG_(baseBlock)[VGOFF_(m_es)];
305 regs.fs = VG_(baseBlock)[VGOFF_(m_fs)];
306 regs.gs = VG_(baseBlock)[VGOFF_(m_gs)];
nethercote71980f02004-01-24 18:18:54 +0000307 regs.eax = VG_(baseBlock)[VGOFF_(m_eax)];
308 regs.ebx = VG_(baseBlock)[VGOFF_(m_ebx)];
309 regs.ecx = VG_(baseBlock)[VGOFF_(m_ecx)];
310 regs.edx = VG_(baseBlock)[VGOFF_(m_edx)];
311 regs.esi = VG_(baseBlock)[VGOFF_(m_esi)];
312 regs.edi = VG_(baseBlock)[VGOFF_(m_edi)];
313 regs.ebp = VG_(baseBlock)[VGOFF_(m_ebp)];
314 regs.esp = VG_(baseBlock)[VGOFF_(m_esp)];
315 regs.eflags = VG_(baseBlock)[VGOFF_(m_eflags)];
316 regs.eip = VG_(baseBlock)[VGOFF_(m_eip)];
317 } else {
318 ThreadState* tst = & VG_(threads)[ tid ];
319
fitzhardinged65dcad2004-03-13 02:06:58 +0000320 regs.cs = tst->m_cs;
321 regs.ss = tst->m_ss;
322 regs.ds = tst->m_ds;
323 regs.es = tst->m_es;
324 regs.fs = tst->m_fs;
325 regs.gs = tst->m_gs;
nethercote71980f02004-01-24 18:18:54 +0000326 regs.eax = tst->m_eax;
327 regs.ebx = tst->m_ebx;
328 regs.ecx = tst->m_ecx;
329 regs.edx = tst->m_edx;
330 regs.esi = tst->m_esi;
331 regs.edi = tst->m_edi;
332 regs.ebp = tst->m_ebp;
333 regs.esp = tst->m_esp;
334 regs.eflags = tst->m_eflags;
335 regs.eip = tst->m_eip;
336 }
337
338 if ((res = VG_(waitpid)(pid, &status, 0)) == pid &&
339 WIFSTOPPED(status) && WSTOPSIG(status) == SIGSTOP &&
340 ptrace(PTRACE_SETREGS, pid, NULL, &regs) == 0 &&
thughes1d160052004-04-21 15:39:57 +0000341 kill(pid, SIGSTOP) == 0 &&
342 ptrace(PTRACE_DETACH, pid, NULL, 0) == 0) {
nethercote04d0fbc2004-01-26 16:48:06 +0000343 Char pidbuf[15];
344 Char file[30];
345 Char buf[100];
346 Char *bufptr;
347 Char *cmdptr;
348
349 VG_(sprintf)(pidbuf, "%d", pid);
350 VG_(sprintf)(file, "/proc/%d/fd/%d", pid, VG_(clexecfd));
351
352 bufptr = buf;
353 cmdptr = VG_(clo_db_command);
354
355 while (*cmdptr) {
356 switch (*cmdptr) {
357 case '%':
358 switch (*++cmdptr) {
359 case 'f':
360 VG_(memcpy)(bufptr, file, VG_(strlen)(file));
361 bufptr += VG_(strlen)(file);
362 cmdptr++;
363 break;
364 case 'p':
365 VG_(memcpy)(bufptr, pidbuf, VG_(strlen)(pidbuf));
366 bufptr += VG_(strlen)(pidbuf);
367 cmdptr++;
368 break;
369 default:
370 *bufptr++ = *cmdptr++;
371 break;
372 }
373 break;
374 default:
375 *bufptr++ = *cmdptr++;
376 break;
377 }
378 }
379
380 *bufptr++ = '\0';
381
382 VG_(message)(Vg_UserMsg, "starting debugger with cmd: %s", buf);
nethercote71980f02004-01-24 18:18:54 +0000383 res = VG_(system)(buf);
384 if (res == 0) {
385 VG_(message)(Vg_UserMsg, "");
386 VG_(message)(Vg_UserMsg,
nethercote04d0fbc2004-01-26 16:48:06 +0000387 "Debugger has detached. Valgrind regains control. We continue.");
nethercote71980f02004-01-24 18:18:54 +0000388 } else {
389 VG_(message)(Vg_UserMsg, "Apparently failed!");
390 VG_(message)(Vg_UserMsg, "");
391 }
392 }
393
394 VG_(kkill)(pid, VKI_SIGKILL);
395 VG_(waitpid)(pid, &status, 0);
396 }
397}
398
399
400/* Print some helpful-ish text about unimplemented things, and give
401 up. */
402void VG_(unimplemented) ( Char* msg )
403{
404 VG_(message)(Vg_UserMsg, "");
405 VG_(message)(Vg_UserMsg,
406 "Valgrind detected that your program requires");
407 VG_(message)(Vg_UserMsg,
408 "the following unimplemented functionality:");
409 VG_(message)(Vg_UserMsg, " %s", msg);
410 VG_(message)(Vg_UserMsg,
411 "This may be because the functionality is hard to implement,");
412 VG_(message)(Vg_UserMsg,
413 "or because no reasonable program would behave this way,");
414 VG_(message)(Vg_UserMsg,
415 "or because nobody has yet needed it. In any case, let us know at");
416 VG_(message)(Vg_UserMsg,
417 "%s and/or try to work around the problem, if you can.", VG_BUGS_TO);
418 VG_(message)(Vg_UserMsg,
419 "");
420 VG_(message)(Vg_UserMsg,
421 "Valgrind has to exit now. Sorry. Bye!");
422 VG_(message)(Vg_UserMsg,
423 "");
424 VG_(pp_sched_status)();
425 VG_(exit)(1);
426}
427
428Addr VG_(get_stack_pointer) ( void )
429{
430 return VG_(baseBlock)[VGOFF_(m_esp)];
431}
432
433/* Debugging thing .. can be called from assembly with OYNK macro. */
434void VG_(oynk) ( Int n )
435{
436 OINK(n);
437}
438
439/* Initialize the PID and PGRP of scheduler LWP; this is also called
440 in any new children after fork. */
441static void newpid(ThreadId unused)
442{
443 /* PID of scheduler LWP */
444 VG_(main_pid) = VG_(getpid)();
445 VG_(main_pgrp) = VG_(getpgrp)();
446}
447
448/*====================================================================*/
449/*=== Check we were launched by stage 1 ===*/
450/*====================================================================*/
451
452/* Look for our AUXV table */
nethercote31779c72004-07-30 21:50:15 +0000453int scan_auxv(void)
nethercote71980f02004-01-24 18:18:54 +0000454{
455 const struct ume_auxv *auxv = find_auxv((int *)ume_exec_esp);
nethercote31779c72004-07-30 21:50:15 +0000456 int padfile = -1, found = 0;
nethercote71980f02004-01-24 18:18:54 +0000457
458 for (; auxv->a_type != AT_NULL; auxv++)
459 switch(auxv->a_type) {
460 case AT_UME_PADFD:
nethercote31779c72004-07-30 21:50:15 +0000461 padfile = auxv->u.a_val;
nethercote71980f02004-01-24 18:18:54 +0000462 found |= 1;
463 break;
464
465 case AT_UME_EXECFD:
466 VG_(vgexecfd) = auxv->u.a_val;
467 found |= 2;
468 break;
469 }
470
nethercote361a14e2004-07-26 11:11:56 +0000471 if ( found != (1|2) ) {
472 fprintf(stderr, "valgrind: stage2 must be launched by stage1\n");
nethercote71980f02004-01-24 18:18:54 +0000473 exit(127);
474 }
nethercote31779c72004-07-30 21:50:15 +0000475 vg_assert(padfile >= 0);
476 return padfile;
nethercote71980f02004-01-24 18:18:54 +0000477}
478
479
480/*====================================================================*/
481/*=== Address space determination ===*/
482/*====================================================================*/
483
nethercote31779c72004-07-30 21:50:15 +0000484static void layout_remaining_space(Addr argc_addr, float ratio)
nethercote71980f02004-01-24 18:18:54 +0000485{
nethercote31779c72004-07-30 21:50:15 +0000486 Int ires;
487 void* vres;
488 addr_t client_size, shadow_size;
nethercote71980f02004-01-24 18:18:54 +0000489
nethercote31779c72004-07-30 21:50:15 +0000490 VG_(valgrind_base) = (addr_t)&kickstart_base;
491 VG_(valgrind_end) = ROUNDUP(argc_addr, 0x10000); // stack
nethercote71980f02004-01-24 18:18:54 +0000492
nethercote31779c72004-07-30 21:50:15 +0000493 // This gives the client the largest possible address space while
494 // taking into account the tool's shadow needs.
495 client_size = ROUNDDN((VG_(valgrind_base)-REDZONE_SIZE) / (1.+ratio),
nethercote71980f02004-01-24 18:18:54 +0000496 CLIENT_SIZE_MULTIPLE);
nethercote31779c72004-07-30 21:50:15 +0000497 VG_(client_base) = CLIENT_BASE;
nethercote71980f02004-01-24 18:18:54 +0000498 VG_(client_end) = VG_(client_base) + client_size;
nethercotee2097312004-06-27 12:29:56 +0000499 /* where !FIXED mmap goes */
nethercotebc7b4f42004-07-26 12:44:35 +0000500 VG_(client_mapbase) = VG_(client_base) +
501 PGROUNDDN((addr_t)(client_size * CLIENT_HEAP_PROPORTION));
nethercote71980f02004-01-24 18:18:54 +0000502
nethercote31779c72004-07-30 21:50:15 +0000503 shadow_size = PGROUNDUP(client_size * ratio);
504 VG_(shadow_base) = VG_(client_end) + REDZONE_SIZE;
505 VG_(shadow_end) = VG_(shadow_base) + shadow_size;
nethercote71980f02004-01-24 18:18:54 +0000506
nethercotee2097312004-06-27 12:29:56 +0000507#define SEGSIZE(a,b) ((VG_(b) - VG_(a))/(1024*1024))
508
nethercote71980f02004-01-24 18:18:54 +0000509 if (0)
nethercotee2097312004-06-27 12:29:56 +0000510 VG_(printf)(
511 "client_base %8x (%dMB)\n"
512 "client_mapbase %8x (%dMB)\n"
513 "client_end %8x (%dMB)\n"
514 "shadow_base %8x (%dMB)\n"
515 "shadow_end %8x (%dMB)\n"
516 "valgrind_base %8x (%dMB)\n"
nethercotee2097312004-06-27 12:29:56 +0000517 "valgrind_end %8x\n",
518 VG_(client_base), SEGSIZE(client_base, client_mapbase),
519 VG_(client_mapbase), SEGSIZE(client_mapbase, client_end),
520 VG_(client_end), SEGSIZE(client_end, shadow_base),
521 VG_(shadow_base), SEGSIZE(shadow_base, shadow_end),
522 VG_(shadow_end), SEGSIZE(shadow_end, valgrind_base),
nethercotec314eba2004-07-15 12:59:41 +0000523 VG_(valgrind_base), SEGSIZE(valgrind_base, valgrind_end),
nethercotee2097312004-06-27 12:29:56 +0000524 VG_(valgrind_end)
525 );
526
527#undef SEGSIZE
nethercote71980f02004-01-24 18:18:54 +0000528
529 // Ban redzone
nethercotee567e702004-07-10 17:49:17 +0000530 vres = mmap((void *)VG_(client_end), REDZONE_SIZE, PROT_NONE,
531 MAP_FIXED|MAP_ANON|MAP_PRIVATE, -1, 0);
532 vg_assert((void*)-1 != vres);
nethercote71980f02004-01-24 18:18:54 +0000533
534 // Make client hole
nethercotee567e702004-07-10 17:49:17 +0000535 ires = munmap((void*)VG_(client_base), client_size);
536 vg_assert(0 == ires);
nethercote71980f02004-01-24 18:18:54 +0000537
538 // Map shadow memory.
539 // Initially all inaccessible, incrementally initialized as it is used
nethercotee567e702004-07-10 17:49:17 +0000540 if (shadow_size != 0) {
541 vres = mmap((char *)VG_(shadow_base), shadow_size, PROT_NONE,
542 MAP_PRIVATE|MAP_ANON|MAP_FIXED, -1, 0);
543 vg_assert((void*)-1 != vres);
544 }
nethercote71980f02004-01-24 18:18:54 +0000545}
546
547/*====================================================================*/
548/*=== Command line setup ===*/
549/*====================================================================*/
550
551/* Nb: malloc'd memory never freed -- kept throughout like argv, envp */
552static char* get_file_clo(char* dir)
553{
554# define FLEN 512
555 Int fd, n;
556 struct stat s1;
557 char* f_clo = NULL;
558 char filename[FLEN];
559
560 snprintf(filename, FLEN, "%s/.valgrindrc", ( NULL == dir ? "" : dir ) );
561 fd = VG_(open)(filename, 0, VKI_S_IRUSR);
562 if ( fd > 0 ) {
563 if ( 0 == fstat(fd, &s1) ) {
564 f_clo = malloc(s1.st_size+1);
565 vg_assert(f_clo);
566 n = read(fd, f_clo, s1.st_size);
567 if (n == -1) n = 0;
568 f_clo[n] = '\0';
569 }
570 close(fd);
571 }
572 return f_clo;
573# undef FLEN
574}
575
nethercotee2097312004-06-27 12:29:56 +0000576#define ISSPACE(cc) ((cc) == ' ' || (cc) == '\t' || (cc) == '\n')
577
nethercote71980f02004-01-24 18:18:54 +0000578static Int count_args(char* s)
579{
580 Int n = 0;
581 if (s) {
582 char* cp = s;
583 while (True) {
584 // We have alternating sequences: blanks, non-blanks, blanks...
585 // count the non-blanks sequences.
586 while ( ISSPACE(*cp) ) cp++;
587 if ( !*cp ) break;
588 n++;
589 while ( !ISSPACE(*cp) && *cp ) cp++;
590 }
591 }
592 return n;
593}
594
595/* add args out of environment, skipping multiple spaces and -- args */
596static char** copy_args( char* s, char** to )
597{
598 if (s) {
599 char* cp = s;
600 while (True) {
601 // We have alternating sequences: blanks, non-blanks, blanks...
602 // copy the non-blanks sequences, and add terminating '\0'
603 while ( ISSPACE(*cp) ) cp++;
604 if ( !*cp ) break;
605 *to++ = cp;
606 while ( !ISSPACE(*cp) && *cp ) cp++;
607 if ( *cp ) *cp++ = '\0'; // terminate if necessary
608 if (VG_STREQ(to[-1], "--")) to--; // undo any '--' arg
609 }
610 }
611 return to;
612}
613
nethercotee2097312004-06-27 12:29:56 +0000614#undef ISSPACE
615
nethercote71980f02004-01-24 18:18:54 +0000616// Augment command line with arguments from environment and .valgrindrc
617// files.
618static void augment_command_line(Int* vg_argc_inout, char*** vg_argv_inout)
619{
620 int vg_argc = *vg_argc_inout;
621 char** vg_argv = *vg_argv_inout;
622
623 char* env_clo = getenv(VALGRINDOPTS);
624 char* f1_clo = get_file_clo( getenv("HOME") );
625 char* f2_clo = get_file_clo(".");
626
627 /* copy any extra args from file or environment, if present */
628 if ( (env_clo && *env_clo) || (f1_clo && *f1_clo) || (f2_clo && *f2_clo) ) {
629 /* ' ' separated extra options */
630 char **from;
631 char **to;
632 int env_arg_count, f1_arg_count, f2_arg_count;
633
634 env_arg_count = count_args(env_clo);
635 f1_arg_count = count_args(f1_clo);
636 f2_arg_count = count_args(f2_clo);
637
638 if (0)
639 printf("extra-argc=%d %d %d\n",
640 env_arg_count, f1_arg_count, f2_arg_count);
641
642 /* +2: +1 for null-termination, +1 for added '--' */
643 from = vg_argv;
644 vg_argv = malloc( (vg_argc + env_arg_count + f1_arg_count
645 + f2_arg_count + 2) * sizeof(char **));
nethercote7c018f42004-07-17 16:40:50 +0000646 vg_assert(vg_argv);
nethercote71980f02004-01-24 18:18:54 +0000647 to = vg_argv;
648
649 /* copy argv[0] */
650 *to++ = *from++;
651
652 /* Copy extra args from env var and file, in the order: ~/.valgrindrc,
653 * $VALGRIND_OPTS, ./.valgrindrc -- more local options are put later
654 * to override less local ones. */
655 to = copy_args(f1_clo, to);
656 to = copy_args(env_clo, to);
657 to = copy_args(f2_clo, to);
658
659 /* copy original arguments, stopping at command or -- */
660 while (*from) {
661 if (**from != '-')
662 break;
663 if (VG_STREQ(*from, "--")) {
664 from++; /* skip -- */
665 break;
666 }
667 *to++ = *from++;
668 }
669
670 /* add -- */
671 *to++ = "--";
672
673 vg_argc = to - vg_argv;
674
675 /* copy rest of original command line, then NULL */
676 while (*from) *to++ = *from++;
677 *to = NULL;
678 }
679
680 *vg_argc_inout = vg_argc;
681 *vg_argv_inout = vg_argv;
682}
683
684static void get_command_line( int argc, char** argv,
685 Int* vg_argc_out, Char*** vg_argv_out,
686 char*** cl_argv_out )
687{
688 int vg_argc;
689 char** vg_argv;
690 char** cl_argv;
691 char* env_clo = getenv(VALGRINDCLO);
692
693 if (env_clo != NULL && *env_clo != '\0') {
694 char *cp;
695 char **cpp;
696
697 /* OK, we're getting all our arguments from the environment - the
698 entire command line belongs to the client (including argv[0]) */
699 vg_argc = 1; /* argv[0] */
700 for (cp = env_clo; *cp; cp++)
701 if (*cp == '\01')
702 vg_argc++;
703
704 vg_argv = malloc(sizeof(char **) * (vg_argc + 1));
nethercote7c018f42004-07-17 16:40:50 +0000705 vg_assert(vg_argv);
nethercote71980f02004-01-24 18:18:54 +0000706
707 cpp = vg_argv;
708
709 *cpp++ = "valgrind"; /* nominal argv[0] */
710 *cpp++ = env_clo;
711
712 for (cp = env_clo; *cp; cp++) {
713 if (*cp == '\01') {
714 *cp++ = '\0'; /* chop it up in place */
715 *cpp++ = cp;
716 }
717 }
718 *cpp = NULL;
719 cl_argv = argv;
720
721 } else {
722 /* Count the arguments on the command line. */
723 vg_argv = argv;
724
725 for (vg_argc = 1; vg_argc < argc; vg_argc++) {
726 if (argv[vg_argc][0] != '-') /* exe name */
727 break;
728 if (VG_STREQ(argv[vg_argc], "--")) { /* dummy arg */
729 vg_argc++;
730 break;
731 }
732 }
733 cl_argv = &argv[vg_argc];
734
735 /* Get extra args from VALGRIND_OPTS and .valgrindrc files.
736 * Note we don't do this if getting args from VALGRINDCLO. */
737 augment_command_line(&vg_argc, &vg_argv);
738 }
739
740 if (0) {
741 Int i;
742 for (i = 0; i < vg_argc; i++)
743 printf("vg_argv[%d]=\"%s\"\n", i, vg_argv[i]);
744 }
745
746 *vg_argc_out = vg_argc;
747 *vg_argv_out = (Char**)vg_argv;
748 *cl_argv_out = cl_argv;
749}
750
751
752/*====================================================================*/
753/*=== Environment and stack setup ===*/
754/*====================================================================*/
755
756/* Scan a colon-separated list, and call a function on each element.
757 The string must be mutable, because we insert a temporary '\0', but
thughes4ad52d02004-06-27 17:37:21 +0000758 the string will end up unmodified. (*func) should return True if it
nethercote71980f02004-01-24 18:18:54 +0000759 doesn't need to see any more.
thughes4ad52d02004-06-27 17:37:21 +0000760
761 This routine will return True if (*func) returns True and False if
762 it reaches the end of the list without that happening.
nethercote71980f02004-01-24 18:18:54 +0000763*/
thughes4ad52d02004-06-27 17:37:21 +0000764static Bool scan_colsep(char *colsep, Bool (*func)(const char *))
nethercote71980f02004-01-24 18:18:54 +0000765{
766 char *cp, *entry;
767 int end;
768
769 if (colsep == NULL ||
770 *colsep == '\0')
thughes4ad52d02004-06-27 17:37:21 +0000771 return False;
nethercote71980f02004-01-24 18:18:54 +0000772
773 entry = cp = colsep;
774
775 do {
776 end = (*cp == '\0');
777
778 if (*cp == ':' || *cp == '\0') {
779 char save = *cp;
780
781 *cp = '\0';
thughes21942d92004-07-12 09:35:37 +0000782 if ((*func)(entry)) {
783 *cp = save;
thughes4ad52d02004-06-27 17:37:21 +0000784 return True;
thughes21942d92004-07-12 09:35:37 +0000785 }
nethercote71980f02004-01-24 18:18:54 +0000786 *cp = save;
787 entry = cp+1;
788 }
789 cp++;
790 } while(!end);
thughes4ad52d02004-06-27 17:37:21 +0000791
792 return False;
793}
794
795static Bool contains(const char *p) {
796 if (VG_STREQ(p, VG_(libdir))) {
797 return True;
798 }
799 return False;
nethercote71980f02004-01-24 18:18:54 +0000800}
801
802/* Prepare the client's environment. This is basically a copy of our
803 environment, except:
804 1. LD_LIBRARY_PATH=$VALGRINDLIB:$LD_LIBRARY_PATH
805 2. LD_PRELOAD=$VALGRINDLIB/vg_inject.so:($VALGRINDLIB/vgpreload_TOOL.so:)?$LD_PRELOAD
806
807 If any of these is missing, then it is added.
808
809 Yummy. String hacking in C.
810
811 If this needs to handle any more variables it should be hacked
812 into something table driven.
813 */
814static char **fix_environment(char **origenv, const char *preload)
815{
816 static const char inject_so[] = "vg_inject.so";
817 static const char ld_library_path[] = "LD_LIBRARY_PATH=";
818 static const char ld_preload[] = "LD_PRELOAD=";
819 static const char valgrind_clo[] = VALGRINDCLO "=";
820 static const int ld_library_path_len = sizeof(ld_library_path)-1;
821 static const int ld_preload_len = sizeof(ld_preload)-1;
822 static const int valgrind_clo_len = sizeof(valgrind_clo)-1;
823 int ld_preload_done = 0;
824 int ld_library_path_done = 0;
825 char *inject_path;
826 int inject_path_len;
827 int vgliblen = strlen(VG_(libdir));
828 char **cpp;
829 char **ret;
830 int envc;
831 const int preloadlen = (preload == NULL) ? 0 : strlen(preload);
832
833 /* Find the vg_inject.so; also make room for the tool preload
834 library */
835 inject_path_len = sizeof(inject_so) + vgliblen + preloadlen + 16;
836 inject_path = malloc(inject_path_len);
nethercote7c018f42004-07-17 16:40:50 +0000837 vg_assert(inject_path);
nethercote71980f02004-01-24 18:18:54 +0000838
839 if (preload)
840 snprintf(inject_path, inject_path_len, "%s/%s:%s",
841 VG_(libdir), inject_so, preload);
842 else
843 snprintf(inject_path, inject_path_len, "%s/%s",
844 VG_(libdir), inject_so);
845
846 /* Count the original size of the env */
847 envc = 0; /* trailing NULL */
848 for (cpp = origenv; cpp && *cpp; cpp++)
849 envc++;
850
851 /* Allocate a new space */
852 ret = malloc(sizeof(char *) * (envc+3+1)); /* 3 new entries + NULL */
nethercote7c018f42004-07-17 16:40:50 +0000853 vg_assert(ret);
nethercote71980f02004-01-24 18:18:54 +0000854
855 /* copy it over */
856 for (cpp = ret; *origenv; )
857 *cpp++ = *origenv++;
858 *cpp = NULL;
859
860 vg_assert(envc == (cpp - ret));
861
862 /* Walk over the new environment, mashing as we go */
863 for (cpp = ret; cpp && *cpp; cpp++) {
864 if (memcmp(*cpp, ld_library_path, ld_library_path_len) == 0) {
nethercote71980f02004-01-24 18:18:54 +0000865 /* If the LD_LIBRARY_PATH already contains libdir, then don't
866 bother adding it again, even if it isn't the first (it
867 seems that the Java runtime will keep reexecing itself
868 unless its paths are at the front of LD_LIBRARY_PATH) */
thughes4ad52d02004-06-27 17:37:21 +0000869 if (!scan_colsep(*cpp + ld_library_path_len, contains)) {
nethercote71980f02004-01-24 18:18:54 +0000870 int len = strlen(*cpp) + vgliblen*2 + 16;
871 char *cp = malloc(len);
nethercote7c018f42004-07-17 16:40:50 +0000872 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000873
874 snprintf(cp, len, "%s%s:%s",
875 ld_library_path, VG_(libdir),
876 (*cpp)+ld_library_path_len);
877
878 *cpp = cp;
879 }
880
881 ld_library_path_done = 1;
882 } else if (memcmp(*cpp, ld_preload, ld_preload_len) == 0) {
883 int len = strlen(*cpp) + inject_path_len;
884 char *cp = malloc(len);
nethercote7c018f42004-07-17 16:40:50 +0000885 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000886
887 snprintf(cp, len, "%s%s:%s",
888 ld_preload, inject_path, (*cpp)+ld_preload_len);
889
890 *cpp = cp;
891
892 ld_preload_done = 1;
893 } else if (memcmp(*cpp, valgrind_clo, valgrind_clo_len) == 0) {
894 *cpp = "";
895 }
896 }
897
898 /* Add the missing bits */
899
900 if (!ld_library_path_done) {
901 int len = ld_library_path_len + vgliblen*2 + 16;
902 char *cp = malloc(len);
nethercote7c018f42004-07-17 16:40:50 +0000903 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000904
905 snprintf(cp, len, "%s%s", ld_library_path, VG_(libdir));
906
907 ret[envc++] = cp;
908 }
909
910 if (!ld_preload_done) {
911 int len = ld_preload_len + inject_path_len;
912 char *cp = malloc(len);
nethercote7c018f42004-07-17 16:40:50 +0000913 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000914
915 snprintf(cp, len, "%s%s",
916 ld_preload, inject_path);
917
918 ret[envc++] = cp;
919 }
920
921 ret[envc] = NULL;
922
923 return ret;
924}
925
926extern char **environ; /* our environment */
927//#include <error.h>
928
929/* Add a string onto the string table, and return its address */
930static char *copy_str(char **tab, const char *str)
931{
932 char *cp = *tab;
933 char *orig = cp;
934
935 while(*str)
936 *cp++ = *str++;
937 *cp++ = '\0';
938
939 if (0)
nethercotef84f6952004-07-15 14:58:33 +0000940 printf("copied %p \"%s\" len %d\n", orig, orig, cp-orig);
nethercote71980f02004-01-24 18:18:54 +0000941
942 *tab = cp;
943
944 return orig;
945}
946
947/*
948 This sets up the client's initial stack, containing the args,
949 environment and aux vector.
950
951 The format of the stack is:
952
953 higher address +-----------------+
954 | Trampoline code |
955 +-----------------+
956 | |
957 : string table :
958 | |
959 +-----------------+
960 | AT_NULL |
961 - -
962 | auxv |
963 +-----------------+
964 | NULL |
965 - -
966 | envp |
967 +-----------------+
968 | NULL |
969 - -
970 | argv |
971 +-----------------+
972 | argc |
973 lower address +-----------------+ <- esp
974 | undefined |
975 : :
976 */
977static Addr setup_client_stack(char **orig_argv, char **orig_envp,
978 const struct exeinfo *info,
979 UInt** client_auxv)
980{
nethercotee567e702004-07-10 17:49:17 +0000981 void* res;
nethercote71980f02004-01-24 18:18:54 +0000982 char **cpp;
983 char *strtab; /* string table */
984 char *stringbase;
985 addr_t *ptr;
986 struct ume_auxv *auxv;
987 const struct ume_auxv *orig_auxv;
988 const struct ume_auxv *cauxv;
989 unsigned stringsize; /* total size of strings in bytes */
990 unsigned auxsize; /* total size of auxv in bytes */
991 int argc; /* total argc */
992 int envc; /* total number of env vars */
993 unsigned stacksize; /* total client stack size */
994 addr_t cl_esp; /* client stack base (initial esp) */
995
996 /* use our own auxv as a prototype */
997 orig_auxv = find_auxv(ume_exec_esp);
998
999 /* ==================== compute sizes ==================== */
1000
1001 /* first of all, work out how big the client stack will be */
1002 stringsize = 0;
1003
1004 /* paste on the extra args if the loader needs them (ie, the #!
1005 interpreter and its argument) */
1006 argc = 0;
nethercoted6a56872004-07-26 15:32:47 +00001007 if (info->interp_name != NULL) {
nethercote71980f02004-01-24 18:18:54 +00001008 argc++;
nethercoted6a56872004-07-26 15:32:47 +00001009 stringsize += strlen(info->interp_name) + 1;
nethercote71980f02004-01-24 18:18:54 +00001010 }
nethercoted6a56872004-07-26 15:32:47 +00001011 if (info->interp_args != NULL) {
nethercote71980f02004-01-24 18:18:54 +00001012 argc++;
nethercoted6a56872004-07-26 15:32:47 +00001013 stringsize += strlen(info->interp_args) + 1;
nethercote71980f02004-01-24 18:18:54 +00001014 }
1015
1016 /* now scan the args we're given... */
1017 for (cpp = orig_argv; *cpp; cpp++) {
1018 argc++;
1019 stringsize += strlen(*cpp) + 1;
1020 }
1021
1022 /* ...and the environment */
1023 envc = 0;
1024 for (cpp = orig_envp; cpp && *cpp; cpp++) {
1025 envc++;
1026 stringsize += strlen(*cpp) + 1;
1027 }
1028
1029 /* now, how big is the auxv? */
1030 auxsize = sizeof(*auxv); /* there's always at least one entry: AT_NULL */
1031 for (cauxv = orig_auxv; cauxv->a_type != AT_NULL; cauxv++) {
1032 if (cauxv->a_type == AT_PLATFORM)
1033 stringsize += strlen(cauxv->u.a_ptr) + 1;
1034 auxsize += sizeof(*cauxv);
1035 }
1036
1037 /* OK, now we know how big the client stack is */
1038 stacksize =
1039 sizeof(int) + /* argc */
1040 sizeof(char **)*argc + /* argv */
1041 sizeof(char **) + /* terminal NULL */
1042 sizeof(char **)*envc + /* envp */
1043 sizeof(char **) + /* terminal NULL */
1044 auxsize + /* auxv */
1045 ROUNDUP(stringsize, sizeof(int)) +/* strings (aligned) */
1046 VKI_BYTES_PER_PAGE; /* page for trampoline code */
1047
nethercotef84f6952004-07-15 14:58:33 +00001048 // decide where stack goes!
1049 VG_(clstk_end) = VG_(client_end);
1050
1051 VG_(client_trampoline_code) = VG_(clstk_end) - VKI_BYTES_PER_PAGE;
1052
nethercote71980f02004-01-24 18:18:54 +00001053 /* cl_esp is the client's stack pointer */
nethercotef84f6952004-07-15 14:58:33 +00001054 cl_esp = VG_(clstk_end) - stacksize;
nethercote71980f02004-01-24 18:18:54 +00001055 cl_esp = ROUNDDN(cl_esp, 16); /* make stack 16 byte aligned */
1056
nethercote71980f02004-01-24 18:18:54 +00001057 /* base of the string table (aligned) */
1058 stringbase = strtab = (char *)(VG_(client_trampoline_code) - ROUNDUP(stringsize, sizeof(int)));
1059
1060 VG_(clstk_base) = PGROUNDDN(cl_esp);
nethercote71980f02004-01-24 18:18:54 +00001061
nethercote5ee67ca2004-06-22 14:00:09 +00001062 if (0)
1063 printf("stringsize=%d auxsize=%d stacksize=%d\n"
1064 "clstk_base %x\n"
1065 "clstk_end %x\n",
1066 stringsize, auxsize, stacksize, VG_(clstk_base), VG_(clstk_end));
1067
1068
nethercote71980f02004-01-24 18:18:54 +00001069 /* ==================== allocate space ==================== */
1070
1071 /* allocate a stack - mmap enough space for the stack */
nethercotef84f6952004-07-15 14:58:33 +00001072 res = mmap((void *)PGROUNDDN(cl_esp), VG_(clstk_end) - PGROUNDDN(cl_esp),
nethercotee567e702004-07-10 17:49:17 +00001073 PROT_READ | PROT_WRITE | PROT_EXEC,
1074 MAP_PRIVATE | MAP_ANON | MAP_FIXED, -1, 0);
1075 vg_assert((void*)-1 != res);
nethercote71980f02004-01-24 18:18:54 +00001076
1077 /* ==================== copy client stack ==================== */
1078
1079 ptr = (addr_t *)cl_esp;
1080
1081 /* --- argc --- */
1082 *ptr++ = argc; /* client argc */
1083
1084 /* --- argv --- */
nethercoted6a56872004-07-26 15:32:47 +00001085 if (info->interp_name) {
1086 *ptr++ = (addr_t)copy_str(&strtab, info->interp_name);
1087 free(info->interp_name);
nethercote71980f02004-01-24 18:18:54 +00001088 }
nethercoted6a56872004-07-26 15:32:47 +00001089 if (info->interp_args) {
1090 *ptr++ = (addr_t)copy_str(&strtab, info->interp_args);
1091 free(info->interp_args);
nethercote71980f02004-01-24 18:18:54 +00001092 }
1093 for (cpp = orig_argv; *cpp; ptr++, cpp++) {
1094 *ptr = (addr_t)copy_str(&strtab, *cpp);
1095 }
1096 *ptr++ = 0;
1097
1098 /* --- envp --- */
1099 VG_(client_envp) = (Char **)ptr;
1100 for (cpp = orig_envp; cpp && *cpp; ptr++, cpp++)
1101 *ptr = (addr_t)copy_str(&strtab, *cpp);
1102 *ptr++ = 0;
1103
1104 /* --- auxv --- */
1105 auxv = (struct ume_auxv *)ptr;
1106 *client_auxv = (UInt *)auxv;
1107
1108 for (; orig_auxv->a_type != AT_NULL; auxv++, orig_auxv++) {
1109 /* copy the entry... */
1110 *auxv = *orig_auxv;
1111
1112 /* ...and fix up the copy */
1113 switch(auxv->a_type) {
1114 case AT_PHDR:
1115 if (info->phdr == 0)
1116 auxv->a_type = AT_IGNORE;
1117 else
1118 auxv->u.a_val = info->phdr;
1119 break;
1120
1121 case AT_PHNUM:
1122 if (info->phdr == 0)
1123 auxv->a_type = AT_IGNORE;
1124 else
1125 auxv->u.a_val = info->phnum;
1126 break;
1127
1128 case AT_BASE:
1129 if (info->interp_base == 0)
1130 auxv->a_type = AT_IGNORE;
1131 else
1132 auxv->u.a_val = info->interp_base;
1133 break;
1134
1135 case AT_PLATFORM: /* points to a platform description string */
1136 auxv->u.a_ptr = copy_str(&strtab, orig_auxv->u.a_ptr);
1137 break;
1138
1139 case AT_ENTRY:
1140 auxv->u.a_val = info->entry;
1141 break;
1142
1143 case AT_IGNORE:
1144 case AT_EXECFD:
1145 case AT_PHENT:
1146 case AT_PAGESZ:
1147 case AT_FLAGS:
1148 case AT_NOTELF:
1149 case AT_UID:
1150 case AT_EUID:
1151 case AT_GID:
1152 case AT_EGID:
1153 case AT_CLKTCK:
1154 case AT_HWCAP:
1155 case AT_FPUCW:
1156 case AT_DCACHEBSIZE:
1157 case AT_ICACHEBSIZE:
1158 case AT_UCACHEBSIZE:
1159 /* All these are pointerless, so we don't need to do anything
1160 about them. */
1161 break;
1162
1163 case AT_SECURE:
1164 /* If this is 1, then it means that this program is running
1165 suid, and therefore the dynamic linker should be careful
1166 about LD_PRELOAD, etc. However, since stage1 (the thing
1167 the kernel actually execve's) should never be SUID, and we
1168 need LD_PRELOAD/LD_LIBRARY_PATH to work for the client, we
1169 set AT_SECURE to 0. */
1170 auxv->u.a_val = 0;
1171 break;
1172
1173 case AT_SYSINFO:
1174 /* Leave this unmolested for now, but we'll update it later
1175 when we set up the client trampoline code page */
1176 break;
1177
1178 case AT_SYSINFO_EHDR:
1179 /* Trash this, because we don't reproduce it */
1180 auxv->a_type = AT_IGNORE;
1181 break;
1182
1183 default:
1184 /* stomp out anything we don't know about */
1185 if (0)
1186 printf("stomping auxv entry %d\n", auxv->a_type);
1187 auxv->a_type = AT_IGNORE;
1188 break;
1189
1190 }
1191 }
1192 *auxv = *orig_auxv;
1193 vg_assert(auxv->a_type == AT_NULL);
1194
nethercotef84f6952004-07-15 14:58:33 +00001195 /* --- trampoline page --- */
1196 VG_(memcpy)( (void *)VG_(client_trampoline_code),
1197 &VG_(trampoline_code_start), VG_(trampoline_code_length) );
1198
nethercote71980f02004-01-24 18:18:54 +00001199 vg_assert((strtab-stringbase) == stringsize);
1200
nethercote5ee67ca2004-06-22 14:00:09 +00001201 /* We know the initial ESP is pointing at argc/argv */
1202 VG_(client_argc) = *(Int*)cl_esp;
1203 VG_(client_argv) = (Char**)(cl_esp + sizeof(Int));
1204
nethercote71980f02004-01-24 18:18:54 +00001205 return cl_esp;
1206}
1207
1208/*====================================================================*/
1209/*=== Find executable ===*/
1210/*====================================================================*/
1211
thughes4ad52d02004-06-27 17:37:21 +00001212static const char* executable_name;
1213
1214static Bool match_executable(const char *entry) {
1215 char buf[strlen(entry) + strlen(executable_name) + 2];
1216
1217 /* empty PATH element means . */
1218 if (*entry == '\0')
1219 entry = ".";
1220
1221 snprintf(buf, sizeof(buf), "%s/%s", entry, executable_name);
1222
1223 if (access(buf, R_OK|X_OK) == 0) {
1224 executable_name = strdup(buf);
1225 vg_assert(NULL != executable_name);
1226 return True;
1227 }
1228 return False;
1229}
1230
nethercote71980f02004-01-24 18:18:54 +00001231static const char* find_executable(const char* exec)
1232{
1233 vg_assert(NULL != exec);
thughes4ad52d02004-06-27 17:37:21 +00001234 executable_name = exec;
1235 if (strchr(executable_name, '/') == NULL) {
nethercote71980f02004-01-24 18:18:54 +00001236 /* no '/' - we need to search the path */
1237 char *path = getenv("PATH");
thughes4ad52d02004-06-27 17:37:21 +00001238 scan_colsep(path, match_executable);
nethercote71980f02004-01-24 18:18:54 +00001239 }
thughes4ad52d02004-06-27 17:37:21 +00001240 return executable_name;
nethercote71980f02004-01-24 18:18:54 +00001241}
1242
1243
1244/*====================================================================*/
1245/*=== Loading tools ===*/
1246/*====================================================================*/
1247
1248static void list_tools(void)
1249{
1250 DIR *dir = opendir(VG_(libdir));
1251 struct dirent *de;
1252 int first = 1;
1253
1254 if (dir == NULL) {
1255 fprintf(stderr, "Can't open %s: %s (installation problem?)\n",
nethercotef4928da2004-06-15 10:54:40 +00001256 VG_(libdir), strerror(errno));
nethercote71980f02004-01-24 18:18:54 +00001257 return;
1258 }
1259
nethercotef4928da2004-06-15 10:54:40 +00001260 while ((de = readdir(dir)) != NULL) {
nethercote71980f02004-01-24 18:18:54 +00001261 int len = strlen(de->d_name);
1262
1263 /* look for vgskin_TOOL.so names */
1264 if (len > (7+1+3) && /* "vgskin_" + at least 1-char toolname + ".so" */
nethercotef4928da2004-06-15 10:54:40 +00001265 strncmp(de->d_name, "vgskin_", 7) == 0 &&
1266 VG_STREQ(de->d_name + len - 3, ".so")) {
1267 if (first) {
1268 fprintf(stderr, "Available tools:\n");
1269 first = 0;
1270 }
1271 de->d_name[len-3] = '\0';
1272 fprintf(stderr, "\t%s\n", de->d_name+7);
nethercote71980f02004-01-24 18:18:54 +00001273 }
1274 }
1275
1276 closedir(dir);
1277
1278 if (first)
nethercotef4928da2004-06-15 10:54:40 +00001279 fprintf(stderr, "No tools available in \"%s\" (installation problem?)\n",
1280 VG_(libdir));
nethercote71980f02004-01-24 18:18:54 +00001281}
1282
1283
1284/* Find and load a tool, and check it looks ok. Also looks to see if there's
1285 * a matching vgpreload_*.so file, and returns its name in *preloadpath. */
1286static void load_tool( const char *toolname, void** handle_out,
1287 ToolInfo** toolinfo_out, char **preloadpath_out )
1288{
1289 Bool ok;
1290 int len = strlen(VG_(libdir)) + strlen(toolname)*2 + 16;
1291 char buf[len];
1292 void* handle;
1293 ToolInfo* toolinfo;
1294 char* preloadpath = NULL;
1295 Int* vg_malloc_redzonep;
1296
1297 // XXX: allowing full paths for --tool option -- does it make sense?
1298 // Doesn't allow for vgpreload_<tool>.so.
1299
1300 if (strchr(toolname, '/') != 0) {
1301 /* toolname contains '/', and so must be a pathname */
1302 handle = dlopen(toolname, RTLD_NOW);
1303 } else {
1304 /* just try in the libdir */
1305 snprintf(buf, len, "%s/vgskin_%s.so", VG_(libdir), toolname);
1306 handle = dlopen(buf, RTLD_NOW);
1307
1308 if (handle != NULL) {
1309 snprintf(buf, len, "%s/vgpreload_%s.so", VG_(libdir), toolname);
1310 if (access(buf, R_OK) == 0) {
1311 preloadpath = strdup(buf);
1312 vg_assert(NULL != preloadpath);
1313 }
1314 }
1315 }
1316
1317 ok = (NULL != handle);
1318 if (!ok) {
1319 fprintf(stderr, "Can't open tool \"%s\": %s\n", toolname, dlerror());
1320 goto bad_load;
1321 }
1322
1323 toolinfo = dlsym(handle, "vgSkin_tool_info");
1324 ok = (NULL != toolinfo);
1325 if (!ok) {
1326 fprintf(stderr, "Tool \"%s\" doesn't define SK_(tool_info) - "
1327 "add VG_DETERMINE_INTERFACE_VERSION?\n", toolname);
1328 goto bad_load;
1329 }
1330
1331 ok = (toolinfo->sizeof_ToolInfo == sizeof(*toolinfo) &&
1332 toolinfo->interface_major_version == VG_CORE_INTERFACE_MAJOR_VERSION &&
1333 toolinfo->sk_pre_clo_init != NULL);
1334 if (!ok) {
1335 fprintf(stderr, "Error:\n"
1336 " Tool and core interface versions do not match.\n"
1337 " Interface version used by core is: %d.%d (size %d)\n"
1338 " Interface version used by tool is: %d.%d (size %d)\n"
1339 " The major version numbers must match.\n",
1340 VG_CORE_INTERFACE_MAJOR_VERSION,
1341 VG_CORE_INTERFACE_MINOR_VERSION,
1342 sizeof(*toolinfo),
1343 toolinfo->interface_major_version,
1344 toolinfo->interface_minor_version,
1345 toolinfo->sizeof_ToolInfo);
1346 fprintf(stderr, " You need to at least recompile, and possibly update,\n");
1347 if (VG_CORE_INTERFACE_MAJOR_VERSION > toolinfo->interface_major_version)
1348 fprintf(stderr, " your skin to work with this version of Valgrind.\n");
1349 else
1350 fprintf(stderr, " your version of Valgrind to work with this skin.\n");
1351 goto bad_load;
1352 }
1353
1354 // Set redzone size for V's allocator
1355 vg_malloc_redzonep = dlsym(handle, STR(VG_(vg_malloc_redzone_szB)));
1356 if ( NULL != vg_malloc_redzonep ) {
1357 VG_(vg_malloc_redzone_szB) = *vg_malloc_redzonep;
1358 }
1359
1360 vg_assert(NULL != handle && NULL != toolinfo);
1361 *handle_out = handle;
1362 *toolinfo_out = toolinfo;
1363 *preloadpath_out = preloadpath;
1364 return;
1365
1366
1367 bad_load:
1368 if (handle != NULL)
1369 dlclose(handle);
1370
nethercotef4928da2004-06-15 10:54:40 +00001371 fprintf(stderr, "valgrind: couldn't load tool\n");
nethercote71980f02004-01-24 18:18:54 +00001372 list_tools();
1373 exit(127);
1374}
1375
nethercotef4928da2004-06-15 10:54:40 +00001376
1377/*====================================================================*/
1378/*=== Command line errors ===*/
1379/*====================================================================*/
1380
1381static void abort_msg ( void )
1382{
nethercotef8548672004-06-21 12:42:35 +00001383 VG_(clo_log_to) = VgLogTo_Fd;
1384 VG_(clo_log_fd) = 2; /* stderr */
nethercotef4928da2004-06-15 10:54:40 +00001385}
1386
1387void VG_(bad_option) ( Char* opt )
1388{
1389 abort_msg();
1390 VG_(printf)("valgrind: Bad option `%s'; aborting.\n", opt);
1391 VG_(printf)("valgrind: Use --help for more information.\n");
1392 VG_(exit)(1);
1393}
1394
1395static void missing_tool_option ( void )
1396{
1397 abort_msg();
1398 VG_(printf)("valgrind: Missing --tool option\n");
1399 list_tools();
1400 VG_(printf)("valgrind: Use --help for more information.\n");
1401 VG_(exit)(1);
1402}
1403
1404static void missing_prog ( void )
1405{
1406 abort_msg();
1407 VG_(printf)("valgrind: no program specified\n");
1408 VG_(printf)("valgrind: Use --help for more information.\n");
1409 VG_(exit)(1);
1410}
1411
1412static void config_error ( Char* msg )
1413{
1414 abort_msg();
1415 VG_(printf)("valgrind: Startup or configuration error:\n %s\n", msg);
1416 VG_(printf)("valgrind: Unable to start up properly. Giving up.\n");
1417 VG_(exit)(1);
1418}
1419
1420
nethercote71980f02004-01-24 18:18:54 +00001421/*====================================================================*/
1422/*=== Loading the client ===*/
1423/*====================================================================*/
1424
nethercotef4928da2004-06-15 10:54:40 +00001425static void load_client(char* cl_argv[], const char* exec, Int need_help,
nethercote71980f02004-01-24 18:18:54 +00001426 /*out*/struct exeinfo* info, /*out*/Addr* client_eip)
1427{
1428 // If they didn't specify an executable with --exec, and didn't specify
1429 // --help, then use client argv[0] (searching $PATH if necessary).
nethercotef4928da2004-06-15 10:54:40 +00001430 if (NULL == exec && !need_help) {
nethercote71980f02004-01-24 18:18:54 +00001431 if (cl_argv[0] == NULL ||
1432 ( NULL == (exec = find_executable(cl_argv[0])) ) )
1433 {
nethercotef4928da2004-06-15 10:54:40 +00001434 missing_prog();
nethercote71980f02004-01-24 18:18:54 +00001435 }
1436 }
1437
1438 info->map_base = VG_(client_mapbase);
nethercote71980f02004-01-24 18:18:54 +00001439 info->exe_base = VG_(client_base);
1440 info->exe_end = VG_(client_end);
1441 info->argv = cl_argv;
1442
nethercotef4928da2004-06-15 10:54:40 +00001443 if (need_help) {
nethercote71980f02004-01-24 18:18:54 +00001444 VG_(clexecfd) = -1;
nethercoteea147e72004-07-26 15:43:57 +00001445 // Set the minimal number of entries in 'info' to continue.
nethercoted6a56872004-07-26 15:32:47 +00001446 info->interp_name = NULL;
1447 info->interp_args = NULL;
nethercote71980f02004-01-24 18:18:54 +00001448 } else {
1449 Int ret;
1450 VG_(clexecfd) = VG_(open)(exec, O_RDONLY, VKI_S_IRUSR);
1451 ret = do_exec(exec, info);
1452 if (ret != 0) {
nethercoteea147e72004-07-26 15:43:57 +00001453 fprintf(stderr, "valgrind: do_exec(%s) failed: %s\n",
1454 exec, strerror(ret));
nethercote71980f02004-01-24 18:18:54 +00001455 exit(127);
1456 }
1457 }
1458
1459 /* Copy necessary bits of 'info' that were filled in */
1460 *client_eip = info->init_eip;
1461 VG_(brk_base) = VG_(brk_limit) = info->brkbase;
1462}
1463
1464
1465/*====================================================================*/
1466/*=== Command-line: variables, processing ===*/
1467/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +00001468
njn25e49d8e72002-09-23 09:36:25 +00001469/* Define, and set defaults. */
1470Bool VG_(clo_error_limit) = True;
nethercote04d0fbc2004-01-26 16:48:06 +00001471Bool VG_(clo_db_attach) = False;
1472Char* VG_(clo_db_command) = VG_CLO_DEFAULT_DBCOMMAND;
njn43c799e2003-04-08 00:08:52 +00001473Bool VG_(clo_gen_suppressions) = False;
nethercote27fec902004-06-16 21:26:32 +00001474Int VG_(clo_sanity_level) = 1;
njn25e49d8e72002-09-23 09:36:25 +00001475Int VG_(clo_verbosity) = 1;
1476Bool VG_(clo_demangle) = True;
njn25e49d8e72002-09-23 09:36:25 +00001477Bool VG_(clo_trace_children) = False;
sewardj4cf05692002-10-27 20:28:29 +00001478
nethercotee1730692003-11-20 10:38:07 +00001479/* See big comment in vg_include.h for meaning of these three.
1480 fd is initially stdout, for --help, but gets moved to stderr by default
1481 immediately afterwards. */
sewardj4cf05692002-10-27 20:28:29 +00001482VgLogTo VG_(clo_log_to) = VgLogTo_Fd;
nethercotef8548672004-06-21 12:42:35 +00001483Int VG_(clo_log_fd) = 1;
1484Char* VG_(clo_log_name) = NULL;
sewardj4cf05692002-10-27 20:28:29 +00001485
sewardj6024b212003-07-13 10:54:33 +00001486Int VG_(clo_input_fd) = 0; /* stdin */
njn25e49d8e72002-09-23 09:36:25 +00001487Int VG_(clo_n_suppressions) = 0;
sewardjde4a1d02002-03-22 01:27:54 +00001488Char* VG_(clo_suppressions)[VG_CLO_MAX_SFILES];
njn25e49d8e72002-09-23 09:36:25 +00001489Bool VG_(clo_profile) = False;
1490Bool VG_(clo_single_step) = False;
1491Bool VG_(clo_optimise) = True;
1492UChar VG_(clo_trace_codegen) = 0; // 00000000b
1493Bool VG_(clo_trace_syscalls) = False;
1494Bool VG_(clo_trace_signals) = False;
1495Bool VG_(clo_trace_symtab) = False;
njn25e49d8e72002-09-23 09:36:25 +00001496Bool VG_(clo_trace_sched) = False;
1497Int VG_(clo_trace_pthread_level) = 0;
njn25e49d8e72002-09-23 09:36:25 +00001498Int VG_(clo_dump_error) = 0;
1499Int VG_(clo_backtrace_size) = 4;
1500Char* VG_(clo_weird_hacks) = NULL;
sewardj858964b2002-10-05 14:15:43 +00001501Bool VG_(clo_run_libc_freeres) = True;
rjwalshf5f536f2003-11-17 17:45:00 +00001502Bool VG_(clo_track_fds) = False;
sewardj22854b92002-11-30 14:00:47 +00001503Bool VG_(clo_chain_bb) = True;
nethercote77eba602003-11-13 17:35:04 +00001504Bool VG_(clo_show_below_main) = False;
fitzhardinge98abfc72003-12-16 02:05:15 +00001505Bool VG_(clo_pointercheck) = True;
fitzhardinge462f4f92003-12-18 02:10:54 +00001506Bool VG_(clo_branchpred) = False;
sewardj2370f3b2002-11-30 15:01:01 +00001507
jsgf855d93d2003-10-13 22:26:55 +00001508static Bool VG_(clo_wait_for_gdb) = False;
1509
1510/* If we're doing signal routing, poll for signals every 50mS by
1511 default. */
1512Int VG_(clo_signal_polltime) = 50;
1513
1514/* These flags reduce thread wakeup latency on syscall completion and
1515 signal delivery, respectively. The downside is possible unfairness. */
1516Bool VG_(clo_lowlat_syscalls) = False; /* low-latency syscalls */
1517Bool VG_(clo_lowlat_signals) = False; /* low-latency signals */
1518
sewardjde4a1d02002-03-22 01:27:54 +00001519
nethercote6c999f22004-01-31 22:55:15 +00001520void usage ( Bool debug_help )
njn7cf0bd32002-06-08 13:36:03 +00001521{
njn25e49d8e72002-09-23 09:36:25 +00001522 Char* usage1 =
nethercote71980f02004-01-24 18:18:54 +00001523"usage: valgrind --tool=<toolname> [options] prog-and-args\n"
njn25e49d8e72002-09-23 09:36:25 +00001524"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001525" common user options for all Valgrind tools, with defaults in [ ]:\n"
nethercote0d588502004-06-21 13:27:11 +00001526" --tool=<name> use the Valgrind tool named <name>\n"
nethercotea76368b2004-06-16 11:56:29 +00001527" -h --help show this message\n"
nethercote6c999f22004-01-31 22:55:15 +00001528" --help-debug show this message, plus debugging options\n"
njn25e49d8e72002-09-23 09:36:25 +00001529" --version show version\n"
njn25e49d8e72002-09-23 09:36:25 +00001530" -q --quiet run silently; only print error msgs\n"
1531" -v --verbose be more verbose, incl counts of errors\n"
nethercote77eba602003-11-13 17:35:04 +00001532" --trace-children=no|yes Valgrind-ise child processes? [no]\n"
nethercote0d588502004-06-21 13:27:11 +00001533" --track-fds=no|yes track open file descriptors? [no]\n"
nethercote2b0793f2003-12-02 10:41:18 +00001534"\n"
1535" uncommon user options for all Valgrind tools:\n"
nethercote0d588502004-06-21 13:27:11 +00001536" --run-libc-freeres=no|yes free up glibc memory at exit? [yes]\n"
1537" --weird-hacks=hack1,hack2,... recognised hacks: lax-ioctls [none]\n"
1538" --signal-polltime=<time> signal poll period (mS) for older kernels [50]\n"
1539" --lowlat-signals=no|yes improve thread signal wake-up latency [no]\n"
1540" --lowlat-syscalls=no|yes improve thread syscall wake-up latency [no]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001541" --pointercheck=no|yes enforce client address space limits [yes]\n"
njn25e49d8e72002-09-23 09:36:25 +00001542"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001543" user options for Valgrind tools that report errors:\n"
nethercotef8548672004-06-21 12:42:35 +00001544" --log-fd=<number> log messages to file descriptor [2=stderr]\n"
1545" --log-file=<file> log messages to <file>.pid<pid>\n"
1546" --log-socket=ipaddr:port log messages to socket ipaddr:port\n"
nethercote2b0793f2003-12-02 10:41:18 +00001547" --demangle=no|yes automatically demangle C++ names? [yes]\n"
1548" --num-callers=<number> show <num> callers in stack traces [4]\n"
1549" --error-limit=no|yes stop showing new errors if too many? [yes]\n"
1550" --show-below-main=no|yes continue stack traces below main() [no]\n"
1551" --suppressions=<filename> suppress errors described in <filename>\n"
1552" --gen-suppressions=no|yes print suppressions for errors detected [no]\n"
nethercote04d0fbc2004-01-26 16:48:06 +00001553" --db-attach=no|yes start debugger when errors detected? [no]\n"
1554" --db-command=<command> command to start debugger [gdb -nw %%f %%p]\n"
1555" --input-fd=<number> file descriptor for input [0=stdin]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001556"\n";
njn7cf0bd32002-06-08 13:36:03 +00001557
njn25e49d8e72002-09-23 09:36:25 +00001558 Char* usage2 =
1559"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001560" debugging options for all Valgrind tools:\n"
njn25e49d8e72002-09-23 09:36:25 +00001561" --sanity-level=<number> level of sanity checking to do [1]\n"
1562" --single-step=no|yes translate each instr separately? [no]\n"
1563" --optimise=no|yes improve intermediate code? [yes]\n"
nethercote137bc552003-11-14 17:47:54 +00001564" --profile=no|yes profile? (tool must be built for it) [no]\n"
sewardj22854b92002-11-30 14:00:47 +00001565" --chain-bb=no|yes do basic-block chaining? [yes]\n"
fitzhardinge462f4f92003-12-18 02:10:54 +00001566" --branchpred=yes|no generate branch prediction hints [no]\n"
njn25e49d8e72002-09-23 09:36:25 +00001567" --trace-codegen=<XXXXX> show generated code? (X = 0|1) [00000]\n"
1568" --trace-syscalls=no|yes show all system calls? [no]\n"
1569" --trace-signals=no|yes show signal handling details? [no]\n"
1570" --trace-symtab=no|yes show symbol table details? [no]\n"
njn25e49d8e72002-09-23 09:36:25 +00001571" --trace-sched=no|yes show thread scheduler details? [no]\n"
njn3e884182003-04-15 13:03:23 +00001572" --trace-pthread=none|some|all show pthread event details? [none]\n"
jsgf855d93d2003-10-13 22:26:55 +00001573" --wait-for-gdb=yes|no pause on startup to wait for gdb attach\n"
njn25e49d8e72002-09-23 09:36:25 +00001574"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001575" debugging options for Valgrind tools that report errors\n"
1576" --dump-error=<number> show translation for basic block associated\n"
1577" with <number>'th error context [0=show none]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001578"\n";
njn3e884182003-04-15 13:03:23 +00001579
1580 Char* usage3 =
1581"\n"
nethercote71980f02004-01-24 18:18:54 +00001582" Extra options read from ~/.valgrindrc, $VALGRIND_OPTS, ./.valgrindrc\n"
njn25e49d8e72002-09-23 09:36:25 +00001583"\n"
nethercote08fa9a72004-07-16 17:44:00 +00001584" Valgrind is Copyright (C) 2000-2004 Julian Seward et al.\n"
njn25e49d8e72002-09-23 09:36:25 +00001585" and licensed under the GNU General Public License, version 2.\n"
1586" Bug reports, feedback, admiration, abuse, etc, to: %s.\n"
njnd04b7c62002-10-03 14:05:52 +00001587"\n"
nethercote137bc552003-11-14 17:47:54 +00001588" Tools are copyright and licensed by their authors. See each\n"
1589" tool's start-up message for more information.\n"
njn25e49d8e72002-09-23 09:36:25 +00001590"\n";
njn7cf0bd32002-06-08 13:36:03 +00001591
fitzhardinge98abfc72003-12-16 02:05:15 +00001592 VG_(printf)(usage1);
1593 if (VG_(details).name) {
1594 VG_(printf)(" user options for %s:\n", VG_(details).name);
fitzhardinge98abfc72003-12-16 02:05:15 +00001595 if (VG_(needs).command_line_options)
1596 SK_(print_usage)();
1597 else
1598 VG_(printf)(" (none)\n");
1599 }
nethercote6c999f22004-01-31 22:55:15 +00001600 if (debug_help) {
1601 VG_(printf)(usage2);
fitzhardinge98abfc72003-12-16 02:05:15 +00001602
nethercote6c999f22004-01-31 22:55:15 +00001603 if (VG_(details).name) {
1604 VG_(printf)(" debugging options for %s:\n", VG_(details).name);
1605
1606 if (VG_(needs).command_line_options)
1607 SK_(print_debug_usage)();
1608 else
1609 VG_(printf)(" (none)\n");
1610 }
fitzhardinge98abfc72003-12-16 02:05:15 +00001611 }
nethercote421281e2003-11-20 16:20:55 +00001612 VG_(printf)(usage3, VG_BUGS_TO);
nethercotef4928da2004-06-15 10:54:40 +00001613 VG_(exit)(0);
njn7cf0bd32002-06-08 13:36:03 +00001614}
sewardjde4a1d02002-03-22 01:27:54 +00001615
nethercote71980f02004-01-24 18:18:54 +00001616static void pre_process_cmd_line_options
nethercote6c999f22004-01-31 22:55:15 +00001617 ( Int* need_help, const char** tool, const char** exec )
sewardj1c1b1162003-02-23 01:25:51 +00001618{
nethercote71980f02004-01-24 18:18:54 +00001619 UInt i;
sewardjde4a1d02002-03-22 01:27:54 +00001620
nethercote71980f02004-01-24 18:18:54 +00001621 /* parse the options we have (only the options we care about now) */
1622 for (i = 1; i < VG_(vg_argc); i++) {
1623
1624 if (strcmp(VG_(vg_argv)[i], "--version") == 0) {
1625 printf("valgrind-" VERSION "\n");
nethercotef4928da2004-06-15 10:54:40 +00001626 exit(0);
nethercote71980f02004-01-24 18:18:54 +00001627
nethercotea76368b2004-06-16 11:56:29 +00001628 } else if (VG_CLO_STREQ(VG_(vg_argv)[i], "--help") ||
1629 VG_CLO_STREQ(VG_(vg_argv)[i], "-h")) {
nethercote6c999f22004-01-31 22:55:15 +00001630 *need_help = 1;
1631
nethercotef4928da2004-06-15 10:54:40 +00001632 } else if (VG_CLO_STREQ(VG_(vg_argv)[i], "--help-debug")) {
nethercote6c999f22004-01-31 22:55:15 +00001633 *need_help = 2;
nethercote71980f02004-01-24 18:18:54 +00001634
nethercotef4928da2004-06-15 10:54:40 +00001635 } else if (VG_CLO_STREQN(7, VG_(vg_argv)[i], "--tool=") ||
1636 VG_CLO_STREQN(7, VG_(vg_argv)[i], "--skin=")) {
nethercote71980f02004-01-24 18:18:54 +00001637 *tool = &VG_(vg_argv)[i][7];
1638
nethercotef4928da2004-06-15 10:54:40 +00001639 } else if (VG_CLO_STREQN(7, VG_(vg_argv)[i], "--exec=")) {
nethercote71980f02004-01-24 18:18:54 +00001640 *exec = &VG_(vg_argv)[i][7];
1641 }
1642 }
1643
nethercotef4928da2004-06-15 10:54:40 +00001644 /* If no tool specified, can act appropriately without loading tool */
nethercote71980f02004-01-24 18:18:54 +00001645 if (*tool == NULL) {
nethercotef4928da2004-06-15 10:54:40 +00001646 if (0 == *need_help) {
1647 // neither --tool nor --help/--help-debug specified
1648 missing_tool_option();
1649 } else {
1650 // Give help message, without any tool-specific help
1651 usage(/*help-debug?*/2 == *need_help);
1652 }
nethercote71980f02004-01-24 18:18:54 +00001653 }
1654}
1655
nethercote5ee67ca2004-06-22 14:00:09 +00001656static void process_cmd_line_options( UInt* client_auxv, const char* toolname )
nethercote71980f02004-01-24 18:18:54 +00001657{
nethercotef8548672004-06-21 12:42:35 +00001658 Int i, eventually_log_fd;
nethercote71980f02004-01-24 18:18:54 +00001659 Int *auxp;
1660 Int toolname_len = VG_(strlen)(toolname);
sewardjde4a1d02002-03-22 01:27:54 +00001661
nethercotee1730692003-11-20 10:38:07 +00001662 /* log to stderr by default, but usage message goes to stdout */
nethercotef8548672004-06-21 12:42:35 +00001663 eventually_log_fd = 2;
sewardjde4a1d02002-03-22 01:27:54 +00001664
sewardj19d81412002-06-03 01:10:40 +00001665 /* Check for sane path in ./configure --prefix=... */
fitzhardinge98abfc72003-12-16 02:05:15 +00001666 if (VG_LIBDIR[0] != '/')
sewardj19d81412002-06-03 01:10:40 +00001667 config_error("Please use absolute paths in "
1668 "./configure --prefix=... or --libdir=...");
sewardj38170912002-05-10 21:07:22 +00001669
nethercote71980f02004-01-24 18:18:54 +00001670 for (auxp = client_auxv; auxp[0] != VKI_AT_NULL; auxp += 2) {
fitzhardinge98abfc72003-12-16 02:05:15 +00001671 switch(auxp[0]) {
1672 case VKI_AT_SYSINFO:
fitzhardinge92360792003-12-24 10:11:11 +00001673 auxp[1] = (Int)(VG_(client_trampoline_code) + VG_(tramp_syscall_offset));
fitzhardinge98abfc72003-12-16 02:05:15 +00001674 break;
sewardjde4a1d02002-03-22 01:27:54 +00001675 }
fitzhardinge98abfc72003-12-16 02:05:15 +00001676 }
sewardjde4a1d02002-03-22 01:27:54 +00001677
nethercote71980f02004-01-24 18:18:54 +00001678 for (i = 1; i < VG_(vg_argc); i++) {
1679
1680 Char* arg = VG_(vg_argv)[i];
thughes3bfd5a02004-07-18 08:05:44 +00001681 Char* colon = arg;
nethercote71980f02004-01-24 18:18:54 +00001682
thughes3bfd5a02004-07-18 08:05:44 +00001683 /* Look for a colon in the switch name */
1684 while (*colon && *colon != ':' && *colon != '=')
1685 colon++;
nethercote71980f02004-01-24 18:18:54 +00001686
1687 /* Look for matching "--toolname:foo" */
thughes3bfd5a02004-07-18 08:05:44 +00001688 if (*colon == ':') {
nethercote71980f02004-01-24 18:18:54 +00001689 if (VG_CLO_STREQN(2, arg, "--") &&
1690 VG_CLO_STREQN(toolname_len, arg+2, toolname) &&
1691 VG_CLO_STREQN(1, arg+2+toolname_len, ":"))
1692 {
1693 // prefix matches, convert "--toolname:foo" to "--foo"
1694 if (0)
1695 VG_(printf)("tool-specific arg: %s\n", arg);
1696 arg += toolname_len + 1;
1697 arg[0] = '-';
1698 arg[1] = '-';
1699
1700 } else {
1701 // prefix doesn't match, skip to next arg
1702 continue;
1703 }
1704 }
1705
fitzhardinge98abfc72003-12-16 02:05:15 +00001706 /* Ignore these options - they've already been handled */
nethercote71980f02004-01-24 18:18:54 +00001707 if (VG_CLO_STREQN(7, arg, "--tool=") ||
1708 VG_CLO_STREQN(7, arg, "--skin="))
fitzhardinge98abfc72003-12-16 02:05:15 +00001709 continue;
nethercote71980f02004-01-24 18:18:54 +00001710 if (VG_CLO_STREQN(7, arg, "--exec="))
fitzhardinge98abfc72003-12-16 02:05:15 +00001711 continue;
1712
nethercote71980f02004-01-24 18:18:54 +00001713 if ( VG_CLO_STREQ(arg, "--"))
fitzhardinge98abfc72003-12-16 02:05:15 +00001714 continue;
nethercote27fec902004-06-16 21:26:32 +00001715
nethercote71980f02004-01-24 18:18:54 +00001716 else if (VG_CLO_STREQ(arg, "-v") ||
1717 VG_CLO_STREQ(arg, "--verbose"))
sewardjde4a1d02002-03-22 01:27:54 +00001718 VG_(clo_verbosity)++;
nethercote27fec902004-06-16 21:26:32 +00001719
nethercote71980f02004-01-24 18:18:54 +00001720 else if (VG_CLO_STREQ(arg, "-q") ||
1721 VG_CLO_STREQ(arg, "--quiet"))
sewardjde4a1d02002-03-22 01:27:54 +00001722 VG_(clo_verbosity)--;
1723
nethercote27fec902004-06-16 21:26:32 +00001724 else VG_BOOL_CLO("--branchpred", VG_(clo_branchpred))
1725 else VG_BOOL_CLO("--chain-bb", VG_(clo_chain_bb))
1726 else VG_BOOL_CLO("--db-attach", VG_(clo_db_attach))
1727 else VG_BOOL_CLO("--demangle", VG_(clo_demangle))
1728 else VG_BOOL_CLO("--error-limit", VG_(clo_error_limit))
1729 else VG_BOOL_CLO("--gen-suppressions", VG_(clo_gen_suppressions))
1730 else VG_BOOL_CLO("--lowlat-signals", VG_(clo_lowlat_signals))
1731 else VG_BOOL_CLO("--lowlat-syscalls", VG_(clo_lowlat_syscalls))
1732 else VG_BOOL_CLO("--optimise", VG_(clo_optimise))
1733 else VG_BOOL_CLO("--pointercheck", VG_(clo_pointercheck))
1734 else VG_BOOL_CLO("--profile", VG_(clo_profile))
1735 else VG_BOOL_CLO("--run-libc-freeres", VG_(clo_run_libc_freeres))
1736 else VG_BOOL_CLO("--show-below-main", VG_(clo_show_below_main))
1737 else VG_BOOL_CLO("--single-step", VG_(clo_single_step))
1738 else VG_BOOL_CLO("--track-fds", VG_(clo_track_fds))
1739 else VG_BOOL_CLO("--trace-children", VG_(clo_trace_children))
1740 else VG_BOOL_CLO("--trace-sched", VG_(clo_trace_sched))
1741 else VG_BOOL_CLO("--trace-signals", VG_(clo_trace_signals))
1742 else VG_BOOL_CLO("--trace-symtab", VG_(clo_trace_symtab))
1743 else VG_BOOL_CLO("--trace-syscalls", VG_(clo_trace_syscalls))
1744 else VG_BOOL_CLO("--wait-for-gdb", VG_(clo_wait_for_gdb))
sewardj72f98ff2002-06-13 17:23:38 +00001745
nethercote27fec902004-06-16 21:26:32 +00001746 else VG_STR_CLO ("--db-command", VG_(clo_db_command))
1747 else VG_STR_CLO ("--weird-hacks", VG_(clo_weird_hacks))
sewardjde4a1d02002-03-22 01:27:54 +00001748
nethercote27fec902004-06-16 21:26:32 +00001749 else VG_NUM_CLO ("--dump-error", VG_(clo_dump_error))
1750 else VG_NUM_CLO ("--input-fd", VG_(clo_input_fd))
1751 else VG_NUM_CLO ("--sanity-level", VG_(clo_sanity_level))
1752 else VG_NUM_CLO ("--signal­polltime", VG_(clo_signal_polltime))
1753 else VG_BNUM_CLO("--num-callers", VG_(clo_backtrace_size), 1,
1754 VG_DEEPEST_BACKTRACE)
sewardjde4a1d02002-03-22 01:27:54 +00001755
nethercotef8548672004-06-21 12:42:35 +00001756 // for backwards compatibility, replaced by --log-fd
nethercote71980f02004-01-24 18:18:54 +00001757 else if (VG_CLO_STREQN(13, arg, "--logfile-fd=")) {
nethercotef8548672004-06-21 12:42:35 +00001758 VG_(clo_log_to) = VgLogTo_Fd;
1759 VG_(clo_log_name) = NULL;
1760 eventually_log_fd = (Int)VG_(atoll)(&arg[13]);
1761 }
1762 else if (VG_CLO_STREQN(9, arg, "--log-fd=")) {
1763 VG_(clo_log_to) = VgLogTo_Fd;
1764 VG_(clo_log_name) = NULL;
1765 eventually_log_fd = (Int)VG_(atoll)(&arg[9]);
sewardj4cf05692002-10-27 20:28:29 +00001766 }
1767
nethercotef8548672004-06-21 12:42:35 +00001768 // for backwards compatibility, replaced by --log-file
nethercote71980f02004-01-24 18:18:54 +00001769 else if (VG_CLO_STREQN(10, arg, "--logfile=")) {
nethercotef8548672004-06-21 12:42:35 +00001770 VG_(clo_log_to) = VgLogTo_File;
1771 VG_(clo_log_name) = &arg[10];
1772 }
1773 else if (VG_CLO_STREQN(11, arg, "--log-file=")) {
1774 VG_(clo_log_to) = VgLogTo_File;
1775 VG_(clo_log_name) = &arg[11];
sewardj4cf05692002-10-27 20:28:29 +00001776 }
sewardjde4a1d02002-03-22 01:27:54 +00001777
nethercotef8548672004-06-21 12:42:35 +00001778 // for backwards compatibility, replaced by --log-socket
nethercote71980f02004-01-24 18:18:54 +00001779 else if (VG_CLO_STREQN(12, arg, "--logsocket=")) {
nethercotef8548672004-06-21 12:42:35 +00001780 VG_(clo_log_to) = VgLogTo_Socket;
1781 VG_(clo_log_name) = &arg[12];
1782 }
1783 else if (VG_CLO_STREQN(13, arg, "--log-socket=")) {
1784 VG_(clo_log_to) = VgLogTo_Socket;
1785 VG_(clo_log_name) = &arg[13];
sewardj73cf3bc2002-11-03 03:20:15 +00001786 }
1787
nethercote71980f02004-01-24 18:18:54 +00001788 else if (VG_CLO_STREQN(15, arg, "--suppressions=")) {
sewardjde4a1d02002-03-22 01:27:54 +00001789 if (VG_(clo_n_suppressions) >= VG_CLO_MAX_SFILES) {
njn25e49d8e72002-09-23 09:36:25 +00001790 VG_(message)(Vg_UserMsg, "Too many suppression files specified.");
sewardjde4a1d02002-03-22 01:27:54 +00001791 VG_(message)(Vg_UserMsg,
1792 "Increase VG_CLO_MAX_SFILES and recompile.");
nethercote71980f02004-01-24 18:18:54 +00001793 VG_(bad_option)(arg);
sewardjde4a1d02002-03-22 01:27:54 +00001794 }
nethercote71980f02004-01-24 18:18:54 +00001795 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = &arg[15];
sewardjde4a1d02002-03-22 01:27:54 +00001796 VG_(clo_n_suppressions)++;
1797 }
sewardjde4a1d02002-03-22 01:27:54 +00001798
njn25e49d8e72002-09-23 09:36:25 +00001799 /* "vwxyz" --> 000zyxwv (binary) */
nethercote71980f02004-01-24 18:18:54 +00001800 else if (VG_CLO_STREQN(16, arg, "--trace-codegen=")) {
njn25e49d8e72002-09-23 09:36:25 +00001801 Int j;
nethercote71980f02004-01-24 18:18:54 +00001802 char* opt = & arg[16];
njn25e49d8e72002-09-23 09:36:25 +00001803
1804 if (5 != VG_(strlen)(opt)) {
1805 VG_(message)(Vg_UserMsg,
1806 "--trace-codegen argument must have 5 digits");
nethercote71980f02004-01-24 18:18:54 +00001807 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001808 }
1809 for (j = 0; j < 5; j++) {
1810 if ('0' == opt[j]) { /* do nothing */ }
1811 else if ('1' == opt[j]) VG_(clo_trace_codegen) |= (1 << j);
1812 else {
1813 VG_(message)(Vg_UserMsg, "--trace-codegen argument can only "
1814 "contain 0s and 1s");
nethercote71980f02004-01-24 18:18:54 +00001815 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001816 }
1817 }
1818 }
sewardjde4a1d02002-03-22 01:27:54 +00001819
nethercote71980f02004-01-24 18:18:54 +00001820 else if (VG_CLO_STREQ(arg, "--trace-pthread=none"))
sewardj45b4b372002-04-16 22:50:32 +00001821 VG_(clo_trace_pthread_level) = 0;
nethercote71980f02004-01-24 18:18:54 +00001822 else if (VG_CLO_STREQ(arg, "--trace-pthread=some"))
sewardj45b4b372002-04-16 22:50:32 +00001823 VG_(clo_trace_pthread_level) = 1;
nethercote71980f02004-01-24 18:18:54 +00001824 else if (VG_CLO_STREQ(arg, "--trace-pthread=all"))
sewardj45b4b372002-04-16 22:50:32 +00001825 VG_(clo_trace_pthread_level) = 2;
sewardj8937c812002-04-12 20:12:20 +00001826
nethercote71980f02004-01-24 18:18:54 +00001827 else if ( ! VG_(needs).command_line_options
1828 || ! SK_(process_cmd_line_option)(arg) ) {
nethercotef4928da2004-06-15 10:54:40 +00001829 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001830 }
sewardjde4a1d02002-03-22 01:27:54 +00001831 }
1832
nethercote27fec902004-06-16 21:26:32 +00001833 // Check various option values
1834
njnf9ebf672003-05-12 21:41:30 +00001835 if (VG_(clo_verbosity) < 0)
sewardjde4a1d02002-03-22 01:27:54 +00001836 VG_(clo_verbosity) = 0;
1837
nethercote04d0fbc2004-01-26 16:48:06 +00001838 if (VG_(clo_db_attach) && VG_(clo_trace_children)) {
sewardjde4a1d02002-03-22 01:27:54 +00001839 VG_(message)(Vg_UserMsg, "");
1840 VG_(message)(Vg_UserMsg,
nethercote04d0fbc2004-01-26 16:48:06 +00001841 "--db-attach=yes conflicts with --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001842 VG_(message)(Vg_UserMsg,
1843 "Please choose one or the other, but not both.");
nethercote04d0fbc2004-01-26 16:48:06 +00001844 VG_(bad_option)("--db-attach=yes and --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001845 }
1846
nethercotef8548672004-06-21 12:42:35 +00001847 /* Set up logging now. After this is done, VG_(clo_log_fd)
sewardj4cf05692002-10-27 20:28:29 +00001848 should be connected to whatever sink has been selected, and we
1849 indiscriminately chuck stuff into it without worrying what the
1850 nature of it is. Oh the wonder of Unix streams. */
1851
nethercotee1730692003-11-20 10:38:07 +00001852 /* So far we should be still attached to stdout, so we can show on
sewardj4cf05692002-10-27 20:28:29 +00001853 the terminal any problems to do with processing command line
1854 opts. */
nethercotef8548672004-06-21 12:42:35 +00001855 vg_assert(VG_(clo_log_fd) == 1 /* stdout */);
sewardj73cf3bc2002-11-03 03:20:15 +00001856 vg_assert(VG_(logging_to_filedes) == True);
sewardj4cf05692002-10-27 20:28:29 +00001857
1858 switch (VG_(clo_log_to)) {
sewardj73cf3bc2002-11-03 03:20:15 +00001859
sewardj4cf05692002-10-27 20:28:29 +00001860 case VgLogTo_Fd:
nethercotef8548672004-06-21 12:42:35 +00001861 vg_assert(VG_(clo_log_name) == NULL);
1862 VG_(clo_log_fd) = eventually_log_fd;
sewardj4cf05692002-10-27 20:28:29 +00001863 break;
sewardj73cf3bc2002-11-03 03:20:15 +00001864
sewardj4cf05692002-10-27 20:28:29 +00001865 case VgLogTo_File: {
1866 Char logfilename[1000];
jsgff3c3f1a2003-10-14 22:13:28 +00001867 Int seq = 0;
1868 Int pid = VG_(getpid)();
1869
nethercotef8548672004-06-21 12:42:35 +00001870 vg_assert(VG_(clo_log_name) != NULL);
1871 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
jsgff3c3f1a2003-10-14 22:13:28 +00001872
nethercote71980f02004-01-24 18:18:54 +00001873 for (;;) {
jsgff3c3f1a2003-10-14 22:13:28 +00001874 if (seq == 0)
1875 VG_(sprintf)(logfilename, "%s.pid%d",
nethercotef8548672004-06-21 12:42:35 +00001876 VG_(clo_log_name), pid );
jsgff3c3f1a2003-10-14 22:13:28 +00001877 else
1878 VG_(sprintf)(logfilename, "%s.pid%d.%d",
nethercotef8548672004-06-21 12:42:35 +00001879 VG_(clo_log_name), pid, seq );
jsgff3c3f1a2003-10-14 22:13:28 +00001880 seq++;
1881
nethercotef8548672004-06-21 12:42:35 +00001882 eventually_log_fd
jsgff3c3f1a2003-10-14 22:13:28 +00001883 = VG_(open)(logfilename,
1884 VKI_O_CREAT|VKI_O_WRONLY|VKI_O_EXCL|VKI_O_TRUNC,
1885 VKI_S_IRUSR|VKI_S_IWUSR);
nethercotef8548672004-06-21 12:42:35 +00001886 if (eventually_log_fd >= 0) {
1887 VG_(clo_log_fd) = VG_(safe_fd)(eventually_log_fd);
jsgff3c3f1a2003-10-14 22:13:28 +00001888 break;
1889 } else {
nethercotef8548672004-06-21 12:42:35 +00001890 if (eventually_log_fd != -VKI_EEXIST) {
jsgff3c3f1a2003-10-14 22:13:28 +00001891 VG_(message)(Vg_UserMsg,
1892 "Can't create/open log file `%s.pid%d'; giving up!",
nethercotef8548672004-06-21 12:42:35 +00001893 VG_(clo_log_name), pid);
jsgff3c3f1a2003-10-14 22:13:28 +00001894 VG_(bad_option)(
nethercotef8548672004-06-21 12:42:35 +00001895 "--log-file=<file> didn't work out for some reason.");
jsgff3c3f1a2003-10-14 22:13:28 +00001896 break;
1897 }
1898 }
1899 }
sewardj4cf05692002-10-27 20:28:29 +00001900 break;
sewardj73cf3bc2002-11-03 03:20:15 +00001901 }
1902
1903 case VgLogTo_Socket: {
nethercotef8548672004-06-21 12:42:35 +00001904 vg_assert(VG_(clo_log_name) != NULL);
1905 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
1906 eventually_log_fd = VG_(connect_via_socket)( VG_(clo_log_name) );
1907 if (eventually_log_fd == -1) {
sewardj73cf3bc2002-11-03 03:20:15 +00001908 VG_(message)(Vg_UserMsg,
nethercotef8548672004-06-21 12:42:35 +00001909 "Invalid --log-socket=ipaddr or --log-socket=ipaddr:port spec");
sewardj73cf3bc2002-11-03 03:20:15 +00001910 VG_(message)(Vg_UserMsg,
nethercotef8548672004-06-21 12:42:35 +00001911 "of `%s'; giving up!", VG_(clo_log_name) );
sewardj73cf3bc2002-11-03 03:20:15 +00001912 VG_(bad_option)(
nethercotef8548672004-06-21 12:42:35 +00001913 "--log-socket=");
sewardj4cf05692002-10-27 20:28:29 +00001914 }
nethercotef8548672004-06-21 12:42:35 +00001915 if (eventually_log_fd == -2) {
sewardj73cf3bc2002-11-03 03:20:15 +00001916 VG_(message)(Vg_UserMsg,
sewardj570f8902002-11-03 11:44:36 +00001917 "valgrind: failed to connect to logging server `%s'.",
nethercotef8548672004-06-21 12:42:35 +00001918 VG_(clo_log_name) );
sewardj570f8902002-11-03 11:44:36 +00001919 VG_(message)(Vg_UserMsg,
1920 "Log messages will sent to stderr instead." );
1921 VG_(message)(Vg_UserMsg,
1922 "" );
1923 /* We don't change anything here. */
1924 } else {
nethercotef8548672004-06-21 12:42:35 +00001925 vg_assert(eventually_log_fd > 0);
1926 VG_(clo_log_fd) = eventually_log_fd;
sewardj570f8902002-11-03 11:44:36 +00001927 VG_(logging_to_filedes) = False;
1928 }
sewardj73cf3bc2002-11-03 03:20:15 +00001929 break;
1930 }
1931
sewardj4cf05692002-10-27 20:28:29 +00001932 }
1933
nethercotef8548672004-06-21 12:42:35 +00001934 /* Move log_fd into the safe range, so it doesn't conflict with any app fds */
thughesad1c9562004-06-26 11:27:52 +00001935 eventually_log_fd = VG_(fcntl)(VG_(clo_log_fd), VKI_F_DUPFD, VG_(fd_hard_limit));
nethercotef8548672004-06-21 12:42:35 +00001936 if (eventually_log_fd < 0)
jsgf855d93d2003-10-13 22:26:55 +00001937 VG_(message)(Vg_UserMsg, "valgrind: failed to move logfile fd into safe range");
1938 else {
nethercotef8548672004-06-21 12:42:35 +00001939 VG_(clo_log_fd) = eventually_log_fd;
1940 VG_(fcntl)(VG_(clo_log_fd), VKI_F_SETFD, VKI_FD_CLOEXEC);
jsgf855d93d2003-10-13 22:26:55 +00001941 }
1942
sewardj4cf05692002-10-27 20:28:29 +00001943 /* Ok, the logging sink is running now. Print a suitable preamble.
1944 If logging to file or a socket, write details of parent PID and
1945 command line args, to help people trying to interpret the
1946 results of a run which encompasses multiple processes. */
sewardjde4a1d02002-03-22 01:27:54 +00001947
sewardj83adf412002-05-01 01:25:45 +00001948 if (VG_(clo_verbosity > 0)) {
njnd04b7c62002-10-03 14:05:52 +00001949 /* Skin details */
1950 VG_(message)(Vg_UserMsg, "%s%s%s, %s for x86-linux.",
1951 VG_(details).name,
1952 NULL == VG_(details).version ? "" : "-",
1953 NULL == VG_(details).version
1954 ? (Char*)"" : VG_(details).version,
1955 VG_(details).description);
1956 VG_(message)(Vg_UserMsg, "%s", VG_(details).copyright_author);
sewardj3b2736a2002-03-24 12:18:35 +00001957
njnd04b7c62002-10-03 14:05:52 +00001958 /* Core details */
1959 VG_(message)(Vg_UserMsg,
njn3e884182003-04-15 13:03:23 +00001960 "Using valgrind-%s, a program supervision framework for x86-linux.",
sewardj4aa62ba2002-10-05 15:49:27 +00001961 VERSION);
sewardjde4a1d02002-03-22 01:27:54 +00001962 VG_(message)(Vg_UserMsg,
nethercote08fa9a72004-07-16 17:44:00 +00001963 "Copyright (C) 2000-2004, and GNU GPL'd, by Julian Seward et al.");
njnd04b7c62002-10-03 14:05:52 +00001964 }
1965
nethercotec1e395d2003-11-10 13:26:49 +00001966 if (VG_(clo_verbosity) > 0 && VG_(clo_log_to) != VgLogTo_Fd) {
sewardj4cf05692002-10-27 20:28:29 +00001967 VG_(message)(Vg_UserMsg, "");
1968 VG_(message)(Vg_UserMsg,
1969 "My PID = %d, parent PID = %d. Prog and args are:",
1970 VG_(getpid)(), VG_(getppid)() );
1971 for (i = 0; i < VG_(client_argc); i++)
1972 VG_(message)(Vg_UserMsg, " %s", VG_(client_argv)[i]);
1973 }
1974
sewardjde4a1d02002-03-22 01:27:54 +00001975 if (VG_(clo_verbosity) > 1) {
nethercotea70f7352004-04-18 12:08:46 +00001976 Int fd;
sewardj4cf05692002-10-27 20:28:29 +00001977 if (VG_(clo_log_to) != VgLogTo_Fd)
1978 VG_(message)(Vg_UserMsg, "");
fitzhardinge98abfc72003-12-16 02:05:15 +00001979 VG_(message)(Vg_UserMsg, "Valgrind library directory: %s", VG_(libdir));
njn86dc2bc2003-09-09 07:26:21 +00001980 VG_(message)(Vg_UserMsg, "Command line");
1981 for (i = 0; i < VG_(client_argc); i++)
1982 VG_(message)(Vg_UserMsg, " %s", VG_(client_argv)[i]);
1983
sewardjde4a1d02002-03-22 01:27:54 +00001984 VG_(message)(Vg_UserMsg, "Startup, with flags:");
nethercote71980f02004-01-24 18:18:54 +00001985 for (i = 1; i < VG_(vg_argc); i++) {
1986 VG_(message)(Vg_UserMsg, " %s", VG_(vg_argv)[i]);
sewardjde4a1d02002-03-22 01:27:54 +00001987 }
nethercotea70f7352004-04-18 12:08:46 +00001988
1989 VG_(message)(Vg_UserMsg, "Contents of /proc/version:");
1990 fd = VG_(open) ( "/proc/version", VKI_O_RDONLY, 0 );
1991 if (fd < 0) {
1992 VG_(message)(Vg_UserMsg, " can't open /proc/version");
1993 } else {
1994 #define BUF_LEN 256
1995 Char version_buf[BUF_LEN];
1996 Int n = VG_(read) ( fd, version_buf, BUF_LEN );
1997 vg_assert(n <= 256);
1998 if (n > 0) {
1999 version_buf[n-1] = '\0';
2000 VG_(message)(Vg_UserMsg, " %s", version_buf);
2001 } else {
2002 VG_(message)(Vg_UserMsg, " (empty?)");
2003 }
2004 VG_(close)(fd);
2005 #undef BUF_LEN
2006 }
sewardjde4a1d02002-03-22 01:27:54 +00002007 }
2008
fitzhardinge98abfc72003-12-16 02:05:15 +00002009 if (VG_(clo_n_suppressions) < VG_CLO_MAX_SFILES-1 &&
njn25e49d8e72002-09-23 09:36:25 +00002010 (VG_(needs).core_errors || VG_(needs).skin_errors)) {
fitzhardinge98abfc72003-12-16 02:05:15 +00002011 /* If there are no suppression files specified and the skin
2012 needs one, load the default */
2013 static const Char default_supp[] = "default.supp";
2014 Int len = VG_(strlen)(VG_(libdir)) + 1 + sizeof(default_supp);
2015 Char *buf = VG_(arena_malloc)(VG_AR_CORE, len);
2016 VG_(sprintf)(buf, "%s/%s", VG_(libdir), default_supp);
2017 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = buf;
2018 VG_(clo_n_suppressions)++;
sewardjde4a1d02002-03-22 01:27:54 +00002019 }
sewardj4cf05692002-10-27 20:28:29 +00002020
njn6a230532003-07-21 10:38:23 +00002021 if (VG_(clo_gen_suppressions) &&
2022 !VG_(needs).core_errors && !VG_(needs).skin_errors) {
nethercotef4928da2004-06-15 10:54:40 +00002023 VG_(message)(Vg_UserMsg,
2024 "Can't use --gen-suppressions=yes with this tool,");
2025 VG_(message)(Vg_UserMsg,
2026 "as it doesn't generate errors.");
2027 VG_(bad_option)("--gen-suppressions=yes");
njn6a230532003-07-21 10:38:23 +00002028 }
sewardjde4a1d02002-03-22 01:27:54 +00002029}
2030
sewardjde4a1d02002-03-22 01:27:54 +00002031
nethercote71980f02004-01-24 18:18:54 +00002032/*====================================================================*/
2033/*=== File descriptor setup ===*/
2034/*====================================================================*/
2035
2036static void setup_file_descriptors(void)
2037{
2038 struct vki_rlimit rl;
2039
2040 /* Get the current file descriptor limits. */
2041 if (VG_(getrlimit)(VKI_RLIMIT_NOFILE, &rl) < 0) {
2042 rl.rlim_cur = 1024;
2043 rl.rlim_max = 1024;
2044 }
2045
2046 /* Work out where to move the soft limit to. */
2047 if (rl.rlim_cur + VG_N_RESERVED_FDS <= rl.rlim_max) {
2048 rl.rlim_cur = rl.rlim_cur + VG_N_RESERVED_FDS;
2049 } else {
2050 rl.rlim_cur = rl.rlim_max;
2051 }
2052
2053 /* Reserve some file descriptors for our use. */
thughesad1c9562004-06-26 11:27:52 +00002054 VG_(fd_soft_limit) = rl.rlim_cur - VG_N_RESERVED_FDS;
2055 VG_(fd_hard_limit) = rl.rlim_cur - VG_N_RESERVED_FDS;
nethercote71980f02004-01-24 18:18:54 +00002056
2057 /* Update the soft limit. */
2058 VG_(setrlimit)(VKI_RLIMIT_NOFILE, &rl);
2059
2060 if (VG_(vgexecfd) != -1)
2061 VG_(vgexecfd) = VG_(safe_fd)( VG_(vgexecfd) );
2062 if (VG_(clexecfd) != -1)
2063 VG_(clexecfd) = VG_(safe_fd)( VG_(clexecfd) );
2064}
2065
2066
2067/*====================================================================*/
nethercote1d447092004-02-01 17:29:59 +00002068/*=== baseBlock: definition + setup ===*/
nethercote71980f02004-01-24 18:18:54 +00002069/*====================================================================*/
2070
2071/* The variables storing offsets. */
2072
2073#define INVALID_OFFSET (-1)
2074
2075Int VGOFF_(m_eax) = INVALID_OFFSET;
2076Int VGOFF_(m_ecx) = INVALID_OFFSET;
2077Int VGOFF_(m_edx) = INVALID_OFFSET;
2078Int VGOFF_(m_ebx) = INVALID_OFFSET;
2079Int VGOFF_(m_esp) = INVALID_OFFSET;
2080Int VGOFF_(m_ebp) = INVALID_OFFSET;
2081Int VGOFF_(m_esi) = INVALID_OFFSET;
2082Int VGOFF_(m_edi) = INVALID_OFFSET;
2083Int VGOFF_(m_eflags) = INVALID_OFFSET;
2084Int VGOFF_(m_dflag) = INVALID_OFFSET;
2085Int VGOFF_(m_ssestate) = INVALID_OFFSET;
2086Int VGOFF_(ldt) = INVALID_OFFSET;
2087Int VGOFF_(tls) = INVALID_OFFSET;
2088Int VGOFF_(m_cs) = INVALID_OFFSET;
2089Int VGOFF_(m_ss) = INVALID_OFFSET;
2090Int VGOFF_(m_ds) = INVALID_OFFSET;
2091Int VGOFF_(m_es) = INVALID_OFFSET;
2092Int VGOFF_(m_fs) = INVALID_OFFSET;
2093Int VGOFF_(m_gs) = INVALID_OFFSET;
2094Int VGOFF_(m_eip) = INVALID_OFFSET;
2095Int VGOFF_(spillslots) = INVALID_OFFSET;
2096Int VGOFF_(sh_eax) = INVALID_OFFSET;
2097Int VGOFF_(sh_ecx) = INVALID_OFFSET;
2098Int VGOFF_(sh_edx) = INVALID_OFFSET;
2099Int VGOFF_(sh_ebx) = INVALID_OFFSET;
2100Int VGOFF_(sh_esp) = INVALID_OFFSET;
2101Int VGOFF_(sh_ebp) = INVALID_OFFSET;
2102Int VGOFF_(sh_esi) = INVALID_OFFSET;
2103Int VGOFF_(sh_edi) = INVALID_OFFSET;
2104Int VGOFF_(sh_eflags) = INVALID_OFFSET;
2105
2106Int VGOFF_(helper_idiv_64_32) = INVALID_OFFSET;
2107Int VGOFF_(helper_div_64_32) = INVALID_OFFSET;
2108Int VGOFF_(helper_idiv_32_16) = INVALID_OFFSET;
2109Int VGOFF_(helper_div_32_16) = INVALID_OFFSET;
2110Int VGOFF_(helper_idiv_16_8) = INVALID_OFFSET;
2111Int VGOFF_(helper_div_16_8) = INVALID_OFFSET;
2112Int VGOFF_(helper_imul_32_64) = INVALID_OFFSET;
2113Int VGOFF_(helper_mul_32_64) = INVALID_OFFSET;
2114Int VGOFF_(helper_imul_16_32) = INVALID_OFFSET;
2115Int VGOFF_(helper_mul_16_32) = INVALID_OFFSET;
2116Int VGOFF_(helper_imul_8_16) = INVALID_OFFSET;
2117Int VGOFF_(helper_mul_8_16) = INVALID_OFFSET;
2118Int VGOFF_(helper_CLD) = INVALID_OFFSET;
2119Int VGOFF_(helper_STD) = INVALID_OFFSET;
2120Int VGOFF_(helper_get_dirflag) = INVALID_OFFSET;
2121Int VGOFF_(helper_CLC) = INVALID_OFFSET;
2122Int VGOFF_(helper_STC) = INVALID_OFFSET;
nethercote1018bdd2004-02-11 23:33:29 +00002123Int VGOFF_(helper_CMC) = INVALID_OFFSET;
nethercote71980f02004-01-24 18:18:54 +00002124Int VGOFF_(helper_shldl) = INVALID_OFFSET;
2125Int VGOFF_(helper_shldw) = INVALID_OFFSET;
2126Int VGOFF_(helper_shrdl) = INVALID_OFFSET;
2127Int VGOFF_(helper_shrdw) = INVALID_OFFSET;
2128Int VGOFF_(helper_IN) = INVALID_OFFSET;
2129Int VGOFF_(helper_OUT) = INVALID_OFFSET;
2130Int VGOFF_(helper_RDTSC) = INVALID_OFFSET;
2131Int VGOFF_(helper_CPUID) = INVALID_OFFSET;
2132Int VGOFF_(helper_BSWAP) = INVALID_OFFSET;
nethercote1018bdd2004-02-11 23:33:29 +00002133Int VGOFF_(helper_bsfw) = INVALID_OFFSET;
2134Int VGOFF_(helper_bsfl) = INVALID_OFFSET;
2135Int VGOFF_(helper_bsrw) = INVALID_OFFSET;
2136Int VGOFF_(helper_bsrl) = INVALID_OFFSET;
nethercote71980f02004-01-24 18:18:54 +00002137Int VGOFF_(helper_fstsw_AX) = INVALID_OFFSET;
2138Int VGOFF_(helper_SAHF) = INVALID_OFFSET;
2139Int VGOFF_(helper_LAHF) = INVALID_OFFSET;
2140Int VGOFF_(helper_DAS) = INVALID_OFFSET;
2141Int VGOFF_(helper_DAA) = INVALID_OFFSET;
nethercote1018bdd2004-02-11 23:33:29 +00002142Int VGOFF_(helper_AAS) = INVALID_OFFSET;
2143Int VGOFF_(helper_AAA) = INVALID_OFFSET;
2144Int VGOFF_(helper_AAD) = INVALID_OFFSET;
2145Int VGOFF_(helper_AAM) = INVALID_OFFSET;
nethercote71980f02004-01-24 18:18:54 +00002146Int VGOFF_(helper_cmpxchg8b) = INVALID_OFFSET;
2147Int VGOFF_(helper_undefined_instruction) = INVALID_OFFSET;
2148
2149/* MAX_NONCOMPACT_HELPERS can be increased easily. If MAX_COMPACT_HELPERS is
2150 * increased too much, they won't really be compact any more... */
2151#define MAX_COMPACT_HELPERS 8
2152#define MAX_NONCOMPACT_HELPERS 50
2153
2154UInt VG_(n_compact_helpers) = 0;
2155UInt VG_(n_noncompact_helpers) = 0;
2156
2157Addr VG_(compact_helper_addrs) [MAX_COMPACT_HELPERS];
2158Int VG_(compact_helper_offsets)[MAX_COMPACT_HELPERS];
2159Addr VG_(noncompact_helper_addrs) [MAX_NONCOMPACT_HELPERS];
2160Int VG_(noncompact_helper_offsets)[MAX_NONCOMPACT_HELPERS];
2161
2162/* This is the actual defn of baseblock. */
2163UInt VG_(baseBlock)[VG_BASEBLOCK_WORDS];
2164
nethercote71980f02004-01-24 18:18:54 +00002165/* Words. */
2166static Int baB_off = 0;
2167
2168
nethercote71980f02004-01-24 18:18:54 +00002169/* Returns the offset, in words. */
2170static Int alloc_BaB ( Int words )
sewardjde4a1d02002-03-22 01:27:54 +00002171{
nethercote71980f02004-01-24 18:18:54 +00002172 Int off = baB_off;
2173 baB_off += words;
2174 if (baB_off >= VG_BASEBLOCK_WORDS)
2175 VG_(core_panic)( "alloc_BaB: baseBlock is too small");
sewardjde4a1d02002-03-22 01:27:54 +00002176
nethercote71980f02004-01-24 18:18:54 +00002177 return off;
sewardjde4a1d02002-03-22 01:27:54 +00002178}
2179
nethercote71980f02004-01-24 18:18:54 +00002180/* Align offset, in *bytes* */
2181static void align_BaB ( UInt align )
njn25e49d8e72002-09-23 09:36:25 +00002182{
nethercote71980f02004-01-24 18:18:54 +00002183 vg_assert(2 == align || 4 == align || 8 == align || 16 == align);
2184 baB_off += (align-1);
2185 baB_off &= ~(align-1);
njn25e49d8e72002-09-23 09:36:25 +00002186}
2187
nethercote71980f02004-01-24 18:18:54 +00002188/* Allocate 1 word in baseBlock and set it to the given value. */
2189static Int alloc_BaB_1_set ( Addr a )
njn25e49d8e72002-09-23 09:36:25 +00002190{
nethercote71980f02004-01-24 18:18:54 +00002191 Int off = alloc_BaB(1);
2192 VG_(baseBlock)[off] = (UInt)a;
2193 return off;
njn25e49d8e72002-09-23 09:36:25 +00002194}
2195
nethercote71980f02004-01-24 18:18:54 +00002196/* Registers a function in compact_helper_addrs; compact_helper_offsets is
2197 filled in later. */
2198void VG_(register_compact_helper)(Addr a)
sewardjde4a1d02002-03-22 01:27:54 +00002199{
nethercote71980f02004-01-24 18:18:54 +00002200 if (MAX_COMPACT_HELPERS <= VG_(n_compact_helpers)) {
2201 VG_(printf)("Can only register %d compact helpers\n",
2202 MAX_COMPACT_HELPERS);
2203 VG_(core_panic)("Too many compact helpers registered");
2204 }
2205 VG_(compact_helper_addrs)[VG_(n_compact_helpers)] = a;
2206 VG_(n_compact_helpers)++;
2207}
2208
2209/* Registers a function in noncompact_helper_addrs; noncompact_helper_offsets
2210 * is filled in later.
2211 */
2212void VG_(register_noncompact_helper)(Addr a)
2213{
2214 if (MAX_NONCOMPACT_HELPERS <= VG_(n_noncompact_helpers)) {
2215 VG_(printf)("Can only register %d non-compact helpers\n",
2216 MAX_NONCOMPACT_HELPERS);
2217 VG_(printf)("Try increasing MAX_NON_COMPACT_HELPERS\n");
2218 VG_(core_panic)("Too many non-compact helpers registered");
2219 }
2220 VG_(noncompact_helper_addrs)[VG_(n_noncompact_helpers)] = a;
2221 VG_(n_noncompact_helpers)++;
2222}
2223
2224/* Allocate offsets in baseBlock for the skin helpers */
2225static
2226void assign_helpers_in_baseBlock(UInt n, Int offsets[], Addr addrs[])
2227{
2228 UInt i;
2229 for (i = 0; i < n; i++)
2230 offsets[i] = alloc_BaB_1_set( addrs[i] );
2231}
2232
2233Bool VG_(need_to_handle_esp_assignment)(void)
2234{
2235 return ( VG_(defined_new_mem_stack_4)() ||
2236 VG_(defined_die_mem_stack_4)() ||
2237 VG_(defined_new_mem_stack_8)() ||
2238 VG_(defined_die_mem_stack_8)() ||
2239 VG_(defined_new_mem_stack_12)() ||
2240 VG_(defined_die_mem_stack_12)() ||
2241 VG_(defined_new_mem_stack_16)() ||
2242 VG_(defined_die_mem_stack_16)() ||
2243 VG_(defined_new_mem_stack_32)() ||
2244 VG_(defined_die_mem_stack_32)() ||
2245 VG_(defined_new_mem_stack)() ||
2246 VG_(defined_die_mem_stack)()
2247 );
2248}
2249
2250/* Here we assign actual offsets. It's important to get the most
2251 popular referents within 128 bytes of the start, so we can take
2252 advantage of short addressing modes relative to %ebp. Popularity
2253 of offsets was measured on 22 Feb 02 running a KDE application, and
2254 the slots rearranged accordingly, with a 1.5% reduction in total
2255 size of translations. */
2256static void init_baseBlock ( Addr client_eip, Addr esp_at_startup )
2257{
2258 /* Those with offsets under 128 are carefully chosen. */
2259
2260 /* WORD offsets in this column */
2261 /* 0 */ VGOFF_(m_eax) = alloc_BaB_1_set(0);
2262 /* 1 */ VGOFF_(m_ecx) = alloc_BaB_1_set(0);
2263 /* 2 */ VGOFF_(m_edx) = alloc_BaB_1_set(0);
2264 /* 3 */ VGOFF_(m_ebx) = alloc_BaB_1_set(0);
2265 /* 4 */ VGOFF_(m_esp) = alloc_BaB_1_set(esp_at_startup);
2266 /* 5 */ VGOFF_(m_ebp) = alloc_BaB_1_set(0);
2267 /* 6 */ VGOFF_(m_esi) = alloc_BaB_1_set(0);
2268 /* 7 */ VGOFF_(m_edi) = alloc_BaB_1_set(0);
2269 /* 8 */ VGOFF_(m_eflags) = alloc_BaB_1_set(0);
2270
2271 if (VG_(needs).shadow_regs) {
2272 /* 9 */ VGOFF_(sh_eax) = alloc_BaB_1_set(0);
2273 /* 10 */ VGOFF_(sh_ecx) = alloc_BaB_1_set(0);
2274 /* 11 */ VGOFF_(sh_edx) = alloc_BaB_1_set(0);
2275 /* 12 */ VGOFF_(sh_ebx) = alloc_BaB_1_set(0);
2276 /* 13 */ VGOFF_(sh_esp) = alloc_BaB_1_set(0);
2277 /* 14 */ VGOFF_(sh_ebp) = alloc_BaB_1_set(0);
2278 /* 15 */ VGOFF_(sh_esi) = alloc_BaB_1_set(0);
2279 /* 16 */ VGOFF_(sh_edi) = alloc_BaB_1_set(0);
2280 /* 17 */ VGOFF_(sh_eflags) = alloc_BaB_1_set(0);
2281 VG_TRACK( post_regs_write_init );
2282 }
2283
2284 /* 9,10,11 or 18,19,20... depends on number whether shadow regs are used
2285 * and on compact helpers registered */
2286
2287 /* Make these most-frequently-called specialised ones compact, if they
2288 are used. */
2289 if (VG_(defined_new_mem_stack_4)())
2290 VG_(register_compact_helper)( (Addr) VG_(tool_interface).track_new_mem_stack_4);
2291
2292 if (VG_(defined_die_mem_stack_4)())
2293 VG_(register_compact_helper)( (Addr) VG_(tool_interface).track_die_mem_stack_4);
2294
2295 /* (9 or 18) + n_compact_helpers */
2296 /* Allocate slots for compact helpers */
2297 assign_helpers_in_baseBlock(VG_(n_compact_helpers),
2298 VG_(compact_helper_offsets),
2299 VG_(compact_helper_addrs));
2300
2301 /* (9/10 or 18/19) + n_compact_helpers */
2302 VGOFF_(m_eip) = alloc_BaB_1_set(client_eip);
2303
2304 /* There are currently 24 spill slots */
2305 /* (11+/20+ .. 32+/43+) + n_compact_helpers. This can overlap the magic
2306 * boundary at >= 32 words, but most spills are to low numbered spill
2307 * slots, so the ones above the boundary don't see much action. */
2308 VGOFF_(spillslots) = alloc_BaB(VG_MAX_SPILLSLOTS);
2309
2310 /* I gave up counting at this point. Since they're above the
2311 short-amode-boundary, there's no point. */
2312
2313 VGOFF_(m_dflag) = alloc_BaB_1_set(1); // 1 == forward D-flag
2314
2315 /* The FPU/SSE state. This _must_ be 16-byte aligned. Initial
2316 state doesn't matter much, as long as it's not totally borked. */
2317 align_BaB(16);
2318 VGOFF_(m_ssestate) = alloc_BaB(VG_SIZE_OF_SSESTATE_W);
2319 vg_assert(
2320 0 == ( ((UInt)(& VG_(baseBlock)[VGOFF_(m_ssestate)])) % 16 )
sewardj22854b92002-11-30 14:00:47 +00002321 );
2322
fitzhardingec2dbbac2004-01-23 23:09:01 +00002323 /* I assume that if we have SSE2 we also have SSE */
2324 VG_(have_ssestate) =
2325 VG_(cpu_has_feature)(VG_X86_FEAT_FXSR) &&
2326 VG_(cpu_has_feature)(VG_X86_FEAT_SSE);
2327
fitzhardinge98abfc72003-12-16 02:05:15 +00002328 /* set up an initial FPU state (doesn't really matter what it is,
2329 so long as it's somewhat valid) */
2330 if (!VG_(have_ssestate))
nethercote71980f02004-01-24 18:18:54 +00002331 asm volatile("fwait; fnsave %0; fwait; frstor %0; fwait"
2332 :
2333 : "m" (VG_(baseBlock)[VGOFF_(m_ssestate)])
2334 : "cc", "memory");
fitzhardinge98abfc72003-12-16 02:05:15 +00002335 else
nethercote71980f02004-01-24 18:18:54 +00002336 asm volatile("fwait; fxsave %0; fwait; andl $0xffbf, %1;"
2337 "fxrstor %0; fwait"
2338 :
2339 : "m" (VG_(baseBlock)[VGOFF_(m_ssestate)]),
2340 "m" (VG_(baseBlock)[VGOFF_(m_ssestate)+(24/4)])
2341 : "cc", "memory");
fitzhardinge98abfc72003-12-16 02:05:15 +00002342
njn0c7a5b52003-04-30 09:00:33 +00002343 if (0) {
2344 if (VG_(have_ssestate))
2345 VG_(printf)("Looks like a SSE-capable CPU\n");
2346 else
2347 VG_(printf)("Looks like a MMX-only CPU\n");
2348 }
sewardjb91ae7f2003-04-29 23:50:00 +00002349
nethercote71980f02004-01-24 18:18:54 +00002350 /* LDT pointer: pretend the root thread has an empty LDT to start with. */
2351 VGOFF_(ldt) = alloc_BaB_1_set((UInt)NULL);
jsgf855d93d2003-10-13 22:26:55 +00002352
nethercote71980f02004-01-24 18:18:54 +00002353 /* TLS pointer: pretend the root thread has no TLS array for now. */
2354 VGOFF_(tls) = alloc_BaB_1_set((UInt)NULL);
fitzhardingef0046f22003-12-18 02:39:22 +00002355
nethercote71980f02004-01-24 18:18:54 +00002356 /* segment registers */
2357 VGOFF_(m_cs) = alloc_BaB_1_set(0);
2358 VGOFF_(m_ss) = alloc_BaB_1_set(0);
2359 VGOFF_(m_ds) = alloc_BaB_1_set(0);
2360 VGOFF_(m_es) = alloc_BaB_1_set(0);
2361 VGOFF_(m_fs) = alloc_BaB_1_set(0);
2362 VGOFF_(m_gs) = alloc_BaB_1_set(0);
fitzhardingef0046f22003-12-18 02:39:22 +00002363
thughes35cec982004-04-21 15:16:43 +00002364 /* initialise %cs, %ds and %ss to point at the operating systems
2365 default code, data and stack segments */
2366 asm volatile("movw %%cs, %0"
2367 :
2368 : "m" (VG_(baseBlock)[VGOFF_(m_cs)]));
2369 asm volatile("movw %%ds, %0"
2370 :
2371 : "m" (VG_(baseBlock)[VGOFF_(m_ds)]));
2372 asm volatile("movw %%ss, %0"
2373 :
2374 : "m" (VG_(baseBlock)[VGOFF_(m_ss)]));
2375
nethercote71980f02004-01-24 18:18:54 +00002376 VG_(register_noncompact_helper)( (Addr) & VG_(do_useseg) );
fitzhardingef0046f22003-12-18 02:39:22 +00002377
nethercote71980f02004-01-24 18:18:54 +00002378#define REG(kind, size) \
2379 if (VG_(defined_##kind##_mem_stack##size)()) \
2380 VG_(register_noncompact_helper)( \
2381 (Addr) VG_(tool_interface).track_##kind##_mem_stack##size );
2382 REG(new, _8);
2383 REG(new, _12);
2384 REG(new, _16);
2385 REG(new, _32);
2386 REG(new, );
2387 REG(die, _8);
2388 REG(die, _12);
2389 REG(die, _16);
2390 REG(die, _32);
2391 REG(die, );
2392#undef REG
fitzhardingef0046f22003-12-18 02:39:22 +00002393
nethercote71980f02004-01-24 18:18:54 +00002394 if (VG_(need_to_handle_esp_assignment)())
2395 VG_(register_noncompact_helper)((Addr) VG_(unknown_esp_update));
fitzhardingeb791a192003-12-18 07:22:44 +00002396
nethercote71980f02004-01-24 18:18:54 +00002397# define HELPER(name) \
2398 VGOFF_(helper_##name) = alloc_BaB_1_set( (Addr) & VG_(helper_##name))
njn3e884182003-04-15 13:03:23 +00002399
nethercote71980f02004-01-24 18:18:54 +00002400 /* Helper functions. */
2401 HELPER(idiv_64_32); HELPER(div_64_32);
2402 HELPER(idiv_32_16); HELPER(div_32_16);
2403 HELPER(idiv_16_8); HELPER(div_16_8);
fitzhardinge98abfc72003-12-16 02:05:15 +00002404
nethercote71980f02004-01-24 18:18:54 +00002405 HELPER(imul_32_64); HELPER(mul_32_64);
2406 HELPER(imul_16_32); HELPER(mul_16_32);
2407 HELPER(imul_8_16); HELPER(mul_8_16);
njn25e49d8e72002-09-23 09:36:25 +00002408
nethercote71980f02004-01-24 18:18:54 +00002409 HELPER(CLD); HELPER(STD);
2410 HELPER(get_dirflag);
sewardjde4a1d02002-03-22 01:27:54 +00002411
nethercote71980f02004-01-24 18:18:54 +00002412 HELPER(CLC); HELPER(STC);
nethercote1018bdd2004-02-11 23:33:29 +00002413 HELPER(CMC);
jsgf855d93d2003-10-13 22:26:55 +00002414
nethercote71980f02004-01-24 18:18:54 +00002415 HELPER(shldl); HELPER(shldw);
2416 HELPER(shrdl); HELPER(shrdw);
njncc7bb472002-10-14 09:25:19 +00002417
nethercote71980f02004-01-24 18:18:54 +00002418 HELPER(RDTSC); HELPER(CPUID);
njncc7bb472002-10-14 09:25:19 +00002419
nethercote1018bdd2004-02-11 23:33:29 +00002420 HELPER(bsfw); HELPER(bsfl);
2421 HELPER(bsrw); HELPER(bsrl);
rjwalshf5f536f2003-11-17 17:45:00 +00002422
nethercote71980f02004-01-24 18:18:54 +00002423 HELPER(fstsw_AX);
2424 HELPER(SAHF); HELPER(LAHF);
2425 HELPER(DAS); HELPER(DAA);
nethercote1018bdd2004-02-11 23:33:29 +00002426 HELPER(AAS); HELPER(AAA);
2427 HELPER(AAD); HELPER(AAM);
nethercote71980f02004-01-24 18:18:54 +00002428 HELPER(IN); HELPER(OUT);
2429 HELPER(cmpxchg8b);
sewardj018f7622002-05-15 21:13:39 +00002430
nethercote71980f02004-01-24 18:18:54 +00002431 HELPER(undefined_instruction);
jsgf855d93d2003-10-13 22:26:55 +00002432
nethercote71980f02004-01-24 18:18:54 +00002433# undef HELPER
sewardjde4a1d02002-03-22 01:27:54 +00002434
nethercote71980f02004-01-24 18:18:54 +00002435 /* Allocate slots for noncompact helpers */
2436 assign_helpers_in_baseBlock(VG_(n_noncompact_helpers),
2437 VG_(noncompact_helper_offsets),
2438 VG_(noncompact_helper_addrs));
2439}
sewardjde4a1d02002-03-22 01:27:54 +00002440
sewardj5f07b662002-04-23 16:52:51 +00002441
nethercote71980f02004-01-24 18:18:54 +00002442/*====================================================================*/
2443/*=== Setup pointercheck ===*/
2444/*====================================================================*/
njn25e49d8e72002-09-23 09:36:25 +00002445
nethercote71980f02004-01-24 18:18:54 +00002446static void setup_pointercheck(void)
2447{
2448 int ret;
sewardj2e93c502002-04-12 11:12:52 +00002449
fitzhardinge98abfc72003-12-16 02:05:15 +00002450 if (VG_(clo_pointercheck)) {
nethercote71980f02004-01-24 18:18:54 +00002451 vki_modify_ldt_t ldt = {
2452 VG_POINTERCHECK_SEGIDX, // entry_number
2453 VG_(client_base), // base_addr
2454 (VG_(client_end)-VG_(client_base)) / VKI_BYTES_PER_PAGE, // limit
2455 1, // seg_32bit
2456 0, // contents: data, RW, non-expanding
2457 0, // ! read_exec_only
2458 1, // limit_in_pages
2459 0, // ! seg not present
2460 1, // useable
fitzhardinge98abfc72003-12-16 02:05:15 +00002461 };
nethercote71980f02004-01-24 18:18:54 +00002462 ret = VG_(do_syscall)(__NR_modify_ldt, 1, &ldt, sizeof(ldt));
fitzhardinge98abfc72003-12-16 02:05:15 +00002463 if (ret < 0) {
2464 VG_(message)(Vg_UserMsg,
2465 "Warning: ignoring --pointercheck=yes, "
2466 "because modify_ldt failed (errno=%d)", -ret);
2467 VG_(clo_pointercheck) = False;
2468 }
2469 }
sewardjde4a1d02002-03-22 01:27:54 +00002470}
2471
nethercote71980f02004-01-24 18:18:54 +00002472/*====================================================================*/
2473/*=== Initialise program data/text, etc. ===*/
2474/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +00002475
nethercote71980f02004-01-24 18:18:54 +00002476static void build_valgrind_map_callback
2477 ( Addr start, UInt size, Char rr, Char ww, Char xx,
2478 UInt dev, UInt ino, ULong foffset, const UChar* filename )
sewardjde4a1d02002-03-22 01:27:54 +00002479{
nethercote71980f02004-01-24 18:18:54 +00002480 UInt prot = 0;
2481 UInt flags = SF_MMAP|SF_NOSYMS;
2482 Bool is_stack_segment;
2483
2484 is_stack_segment =
2485 (start == VG_(clstk_base) && (start+size) == VG_(clstk_end));
2486
2487 /* Only record valgrind mappings for now, without loading any
2488 symbols. This is so we know where the free space is before we
2489 start allocating more memory (note: heap is OK, it's just mmap
2490 which is the problem here). */
2491 if (start >= VG_(valgrind_base) && (start+size) <= VG_(valgrind_end)) {
2492 flags |= SF_VALGRIND;
2493 VG_(map_file_segment)(start, size, prot, flags, dev, ino, foffset, filename);
2494 }
sewardjde4a1d02002-03-22 01:27:54 +00002495}
2496
nethercote71980f02004-01-24 18:18:54 +00002497// Global var used to pass local data to callback
2498Addr esp_at_startup___global_arg = 0;
sewardjde4a1d02002-03-22 01:27:54 +00002499
nethercote71980f02004-01-24 18:18:54 +00002500static void build_segment_map_callback
2501 ( Addr start, UInt size, Char rr, Char ww, Char xx,
2502 UInt dev, UInt ino, ULong foffset, const UChar* filename )
sewardj45b672d2003-07-25 19:58:11 +00002503{
nethercote71980f02004-01-24 18:18:54 +00002504 UInt prot = 0;
2505 UInt flags;
2506 Bool is_stack_segment;
2507 Addr r_esp;
sewardj45b672d2003-07-25 19:58:11 +00002508
nethercote71980f02004-01-24 18:18:54 +00002509 is_stack_segment
2510 = (start == VG_(clstk_base) && (start+size) == VG_(clstk_end));
fitzhardinge98abfc72003-12-16 02:05:15 +00002511
nethercote71980f02004-01-24 18:18:54 +00002512 if (rr == 'r') prot |= VKI_PROT_READ;
2513 if (ww == 'w') prot |= VKI_PROT_WRITE;
2514 if (xx == 'x') prot |= VKI_PROT_EXEC;
fitzhardinge98abfc72003-12-16 02:05:15 +00002515
nethercote71980f02004-01-24 18:18:54 +00002516 if (is_stack_segment)
2517 flags = SF_STACK | SF_GROWDOWN;
2518 else
2519 flags = SF_EXEC|SF_MMAP;
fitzhardinge98abfc72003-12-16 02:05:15 +00002520
nethercote71980f02004-01-24 18:18:54 +00002521 if (filename != NULL)
2522 flags |= SF_FILE;
fitzhardinge98abfc72003-12-16 02:05:15 +00002523
nethercote71980f02004-01-24 18:18:54 +00002524 if (start >= VG_(valgrind_base) && (start+size) <= VG_(valgrind_end))
2525 flags |= SF_VALGRIND;
fitzhardinge98abfc72003-12-16 02:05:15 +00002526
nethercote71980f02004-01-24 18:18:54 +00002527 VG_(map_file_segment)(start, size, prot, flags, dev, ino, foffset, filename);
fitzhardinge98abfc72003-12-16 02:05:15 +00002528
nethercote71980f02004-01-24 18:18:54 +00002529 if (VG_(is_client_addr)(start) && VG_(is_client_addr)(start+size-1))
2530 VG_TRACK( new_mem_startup, start, size, rr=='r', ww=='w', xx=='x' );
sewardj3e1eb1f2002-05-18 13:14:17 +00002531
nethercote71980f02004-01-24 18:18:54 +00002532 /* If this is the stack segment mark all below %esp as noaccess. */
2533 r_esp = esp_at_startup___global_arg;
2534 vg_assert(0 != r_esp);
2535 if (is_stack_segment) {
2536 if (0)
2537 VG_(message)(Vg_DebugMsg, "invalidating stack area: %x .. %x",
2538 start,r_esp);
2539 VG_TRACK( die_mem_stack, start, r_esp-start );
sewardjde4a1d02002-03-22 01:27:54 +00002540 }
sewardjde4a1d02002-03-22 01:27:54 +00002541}
2542
2543
nethercote71980f02004-01-24 18:18:54 +00002544/*====================================================================*/
2545/*=== Sanity check machinery (permanently engaged) ===*/
2546/*====================================================================*/
njn25e49d8e72002-09-23 09:36:25 +00002547
2548/* A fast sanity check -- suitable for calling circa once per
2549 millisecond. */
2550
2551void VG_(do_sanity_checks) ( Bool force_expensive )
2552{
njn37cea302002-09-30 11:24:00 +00002553 VGP_PUSHCC(VgpCoreCheapSanity);
2554
nethercote27fec902004-06-16 21:26:32 +00002555 if (VG_(clo_sanity_level) < 1) return;
njn25e49d8e72002-09-23 09:36:25 +00002556
2557 /* --- First do all the tests that we can do quickly. ---*/
2558
nethercote297effd2004-08-02 15:07:57 +00002559 sanity_fast_count++;
njn25e49d8e72002-09-23 09:36:25 +00002560
njn25e49d8e72002-09-23 09:36:25 +00002561 /* Check stuff pertaining to the memory check system. */
2562
2563 /* Check that nobody has spuriously claimed that the first or
2564 last 16 pages of memory have become accessible [...] */
njn37cea302002-09-30 11:24:00 +00002565 if (VG_(needs).sanity_checks) {
2566 VGP_PUSHCC(VgpSkinCheapSanity);
njn25e49d8e72002-09-23 09:36:25 +00002567 vg_assert(SK_(cheap_sanity_check)());
njn37cea302002-09-30 11:24:00 +00002568 VGP_POPCC(VgpSkinCheapSanity);
2569 }
njn25e49d8e72002-09-23 09:36:25 +00002570
2571 /* --- Now some more expensive checks. ---*/
2572
2573 /* Once every 25 times, check some more expensive stuff. */
2574 if ( force_expensive
nethercote27fec902004-06-16 21:26:32 +00002575 || VG_(clo_sanity_level) > 1
nethercote297effd2004-08-02 15:07:57 +00002576 || (VG_(clo_sanity_level) == 1 && (sanity_fast_count % 25) == 0)) {
njn25e49d8e72002-09-23 09:36:25 +00002577
njn37cea302002-09-30 11:24:00 +00002578 VGP_PUSHCC(VgpCoreExpensiveSanity);
nethercote297effd2004-08-02 15:07:57 +00002579 sanity_slow_count++;
njn25e49d8e72002-09-23 09:36:25 +00002580
jsgf855d93d2003-10-13 22:26:55 +00002581 VG_(proxy_sanity)();
2582
njn25e49d8e72002-09-23 09:36:25 +00002583# if 0
2584 { void zzzmemscan(void); zzzmemscan(); }
2585# endif
2586
nethercote297effd2004-08-02 15:07:57 +00002587 if ((sanity_fast_count % 250) == 0)
njn25e49d8e72002-09-23 09:36:25 +00002588 VG_(sanity_check_tc_tt)();
2589
2590 if (VG_(needs).sanity_checks) {
njn37cea302002-09-30 11:24:00 +00002591 VGP_PUSHCC(VgpSkinExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002592 vg_assert(SK_(expensive_sanity_check)());
njn37cea302002-09-30 11:24:00 +00002593 VGP_POPCC(VgpSkinExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002594 }
2595 /*
nethercote297effd2004-08-02 15:07:57 +00002596 if ((sanity_fast_count % 500) == 0) VG_(mallocSanityCheckAll)();
njn25e49d8e72002-09-23 09:36:25 +00002597 */
njn37cea302002-09-30 11:24:00 +00002598 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002599 }
2600
nethercote27fec902004-06-16 21:26:32 +00002601 if (VG_(clo_sanity_level) > 1) {
njn37cea302002-09-30 11:24:00 +00002602 VGP_PUSHCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002603 /* Check sanity of the low-level memory manager. Note that bugs
2604 in the client's code can cause this to fail, so we don't do
2605 this check unless specially asked for. And because it's
2606 potentially very expensive. */
2607 VG_(mallocSanityCheckAll)();
njn37cea302002-09-30 11:24:00 +00002608 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002609 }
njn37cea302002-09-30 11:24:00 +00002610 VGP_POPCC(VgpCoreCheapSanity);
njn25e49d8e72002-09-23 09:36:25 +00002611}
nethercote71980f02004-01-24 18:18:54 +00002612
2613
2614/*====================================================================*/
2615/*=== main() ===*/
2616/*====================================================================*/
2617
nethercotec314eba2004-07-15 12:59:41 +00002618/*
2619 This code decides on the layout of the client and Valgrind address
2620 spaces, loads valgrind.so and the skin.so into the valgrind part,
2621 loads the client executable (and the dynamic linker, if necessary)
2622 into the client part, and calls into Valgrind proper.
2623
2624 The code is careful not to allow spurious mappings to appear in the
2625 wrong parts of the address space. In particular, to make sure
2626 dlopen puts things in the right place, it will pad out the forbidden
2627 chunks of address space so that dlopen is forced to put things where
2628 we want them.
2629
2630 The memory map it creates is:
2631
2632 CLIENT_BASE +-------------------------+
2633 | client address space |
2634 : :
2635 : :
2636 | client stack |
2637 client_end +-------------------------+
2638 | redzone |
2639 shadow_base +-------------------------+
2640 | |
2641 : shadow memory for skins :
2642 | (may be 0 sized) |
2643 shadow_end +-------------------------+
2644 : gap (may be 0 sized) :
2645 valgrind_base +-------------------------+
2646 | kickstart executable |
2647 | valgrind heap vvvvvvvvv| (barely used)
2648 - -
2649 | valgrind .so files |
2650 | and mappings |
2651 - -
2652 | valgrind stack ^^^^^^^^^|
2653 valgrind_end +-------------------------+
2654 : kernel :
2655
2656 Nb: Before we can do general allocations with VG_(arena_malloc)() and
2657 VG_(mmap)(), we need to build the segment skip-list, so we know where
2658 we can put things. However, building that structure requires
2659 allocating memory. So we need to a bootstrapping process. It's done
2660 by making VG_(arena_malloc)() have a special static superblock that's
2661 used for the first 1MB's worth of allocations. This is enough to
2662 build the segment skip-list.
2663*/
2664
nethercote31779c72004-07-30 21:50:15 +00002665static int prmap(char *start, char *end, const char *perm, off_t off,
2666 int maj, int min, int ino, void* dummy) {
thughes4ad52d02004-06-27 17:37:21 +00002667 printf("mapping %10p-%10p %s %02x:%02x %d\n",
2668 start, end, perm, maj, min, ino);
2669 return True;
2670}
2671
nethercote71980f02004-01-24 18:18:54 +00002672int main(int argc, char **argv)
2673{
2674 char **cl_argv;
2675 const char *tool = NULL;
2676 const char *exec = NULL;
2677 char *preload; /* tool-specific LD_PRELOAD .so */
2678 char **env;
nethercote6c999f22004-01-31 22:55:15 +00002679 Int need_help = 0; // 0 = no, 1 = --help, 2 = --help-debug
nethercote71980f02004-01-24 18:18:54 +00002680 struct exeinfo info;
2681 ToolInfo *toolinfo = NULL;
2682 void *tool_dlhandle;
2683 Addr client_eip;
2684 Addr esp_at_startup; /* client's %esp at the point we gained control. */
2685 UInt * client_auxv;
2686 VgSchedReturnCode src;
nethercote47dd12c2004-06-22 14:18:42 +00002687 Int exitcode = 0;
fitzhardingeb50068f2004-02-24 23:42:55 +00002688 vki_rlimit zero = { 0, 0 };
nethercote31779c72004-07-30 21:50:15 +00002689 Int padfile;
nethercote71980f02004-01-24 18:18:54 +00002690
2691 //============================================================
2692 // Nb: startup is complex. Prerequisites are shown at every step.
2693 //
2694 // *** Be very careful when messing with the order ***
2695 //============================================================
2696
nethercotef4928da2004-06-15 10:54:40 +00002697 //============================================================
2698 // Command line argument handling order:
2699 // * If --help/--help-debug are present, show usage message
2700 // (if --tool is also present, that includes the tool-specific usage)
2701 // * Then, if --tool is missing, abort with error msg
2702 // * Then, if client is missing, abort with error msg
2703 // * Then, if any cmdline args are bad, abort with error msg
2704 //============================================================
2705
fitzhardingeb50068f2004-02-24 23:42:55 +00002706 // Get the current process datasize rlimit, and set it to zero.
2707 // This prevents any internal uses of brk() from having any effect.
2708 // We remember the old value so we can restore it on exec, so that
2709 // child processes will have a reasonable brk value.
2710 VG_(getrlimit)(VKI_RLIMIT_DATA, &VG_(client_rlimit_data));
2711 zero.rlim_max = VG_(client_rlimit_data).rlim_max;
2712 VG_(setrlimit)(VKI_RLIMIT_DATA, &zero);
2713
nethercote71980f02004-01-24 18:18:54 +00002714 //--------------------------------------------------------------
2715 // Check we were launched by stage1
nethercotec314eba2004-07-15 12:59:41 +00002716 // p: n/a
nethercote71980f02004-01-24 18:18:54 +00002717 //--------------------------------------------------------------
nethercote31779c72004-07-30 21:50:15 +00002718 padfile = scan_auxv();
nethercote71980f02004-01-24 18:18:54 +00002719
2720 if (0) {
nethercote71980f02004-01-24 18:18:54 +00002721 printf("========== main() ==========\n");
nethercote31779c72004-07-30 21:50:15 +00002722 foreach_map(prmap, /*dummy*/NULL);
nethercote71980f02004-01-24 18:18:54 +00002723 }
2724
2725 //--------------------------------------------------------------
2726 // Look for alternative libdir
2727 // p: n/a
2728 //--------------------------------------------------------------
2729 { char *cp = getenv(VALGRINDLIB);
2730 if (cp != NULL)
2731 VG_(libdir) = cp;
2732 }
2733
2734 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002735 // Get valgrind args + client args (inc. from VALGRIND_OPTS/.valgrindrc).
2736 // Pre-process the command line.
2737 // p: n/a
2738 //--------------------------------------------------------------
2739 get_command_line(argc, argv, &VG_(vg_argc), &VG_(vg_argv), &cl_argv);
2740 pre_process_cmd_line_options(&need_help, &tool, &exec);
2741
2742 //==============================================================
2743 // Nb: once a tool is specified, the tool.so must be loaded even if
2744 // they specified --help or didn't specify a client program.
2745 //==============================================================
2746
2747 //--------------------------------------------------------------
2748 // With client padded out, map in tool
nethercote71980f02004-01-24 18:18:54 +00002749 // p: set-libdir [for VG_(libdir)]
2750 // p: pre_process_cmd_line_options() [for 'tool']
2751 //--------------------------------------------------------------
2752 load_tool(tool, &tool_dlhandle, &toolinfo, &preload);
2753
2754 //==============================================================
2755 // Can use VG_(malloc)() and VG_(arena_malloc)() only after load_tool()
nethercotec314eba2004-07-15 12:59:41 +00002756 // -- redzone size is now set. This is checked by vg_malloc2.c.
nethercote71980f02004-01-24 18:18:54 +00002757 //==============================================================
2758
2759 //--------------------------------------------------------------
2760 // Finalise address space layout
nethercote31779c72004-07-30 21:50:15 +00002761 // p: load_tool() [for 'toolinfo']
nethercote71980f02004-01-24 18:18:54 +00002762 //--------------------------------------------------------------
nethercote31779c72004-07-30 21:50:15 +00002763 layout_remaining_space( (Addr) & argc, toolinfo->shadow_ratio );
nethercote71980f02004-01-24 18:18:54 +00002764
2765 //--------------------------------------------------------------
2766 // Load client executable, finding in $PATH if necessary
nethercote71980f02004-01-24 18:18:54 +00002767 // p: pre_process_cmd_line_options() [for 'exec', 'need_help']
2768 // p: layout_remaining_space [so there's space]
2769 //--------------------------------------------------------------
nethercotef4928da2004-06-15 10:54:40 +00002770 load_client(cl_argv, exec, need_help, &info, &client_eip);
nethercote71980f02004-01-24 18:18:54 +00002771
2772 //--------------------------------------------------------------
2773 // Everything in place, unpad us
2774 // p: layout_remaining_space() [everything must be mapped in before now]
2775 // p: load_client() [ditto]
2776 //--------------------------------------------------------------
nethercote31779c72004-07-30 21:50:15 +00002777 as_unpad((void *)VG_(shadow_end), (void *)~0, padfile);
2778 as_closepadfile(padfile); // no more padding
nethercote71980f02004-01-24 18:18:54 +00002779
2780 //--------------------------------------------------------------
2781 // Set up client's environment
2782 // p: set-libdir [for VG_(libdir)]
2783 // p: load_tool() [for 'preload']
2784 //--------------------------------------------------------------
2785 env = fix_environment(environ, preload);
2786
2787 //--------------------------------------------------------------
nethercote5ee67ca2004-06-22 14:00:09 +00002788 // Setup client stack, eip, and VG_(client_arg[cv])
nethercote71980f02004-01-24 18:18:54 +00002789 // p: load_client() [for 'info']
2790 // p: fix_environment() [for 'env']
2791 //--------------------------------------------------------------
2792 esp_at_startup = setup_client_stack(cl_argv, env, &info, &client_auxv);
2793
2794 if (0)
2795 printf("entry=%x client esp=%x vg_argc=%d brkbase=%x\n",
2796 client_eip, esp_at_startup, VG_(vg_argc), VG_(brk_base));
2797
2798 //==============================================================
2799 // Finished setting up operating environment. Now initialise
2800 // Valgrind. (This is where the old VG_(main)() started.)
2801 //==============================================================
2802
2803 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002804 // atfork
2805 // p: n/a
2806 //--------------------------------------------------------------
2807 VG_(atfork)(NULL, NULL, newpid);
2808 newpid(VG_INVALID_THREADID);
2809
2810 //--------------------------------------------------------------
2811 // setup file descriptors
2812 // p: n/a
2813 //--------------------------------------------------------------
2814 setup_file_descriptors();
2815
2816 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002817 // Read /proc/self/maps into a buffer
2818 // p: all memory layout, environment setup [so memory maps are right]
2819 //--------------------------------------------------------------
2820 VG_(read_procselfmaps)();
2821
2822 //--------------------------------------------------------------
2823 // Build segment map (Valgrind segments only)
2824 // p: read proc/self/maps
2825 // p: sk_pre_clo_init() [to setup new_mem_startup tracker]
2826 //--------------------------------------------------------------
2827 VG_(parse_procselfmaps) ( build_valgrind_map_callback );
2828
2829 //==============================================================
2830 // Can use VG_(arena_malloc)() with non-CORE arena after segments set up
2831 //==============================================================
2832
2833 //--------------------------------------------------------------
2834 // Init tool: pre_clo_init, process cmd line, post_clo_init
2835 // p: setup_client_stack() [for 'VG_(client_arg[cv]']
2836 // p: load_tool() [for 'tool']
2837 // p: setup_file_descriptors() [for 'VG_(fd_xxx_limit)']
2838 // p: parse_procselfmaps [so VG segments are setup so tool can
2839 // call VG_(malloc)]
nethercote71980f02004-01-24 18:18:54 +00002840 //--------------------------------------------------------------
2841 (*toolinfo->sk_pre_clo_init)();
2842 VG_(tool_init_dlsym)(tool_dlhandle);
2843 VG_(sanity_check_needs)();
2844
nethercotef4928da2004-06-15 10:54:40 +00002845 // If --tool and --help/--help-debug was given, now give the core+tool
2846 // help message
nethercotef4928da2004-06-15 10:54:40 +00002847 if (need_help) {
2848 usage(/*--help-debug?*/2 == need_help);
2849 }
nethercotec314eba2004-07-15 12:59:41 +00002850 process_cmd_line_options(client_auxv, tool);
2851
2852 SK_(post_clo_init)();
nethercotef4928da2004-06-15 10:54:40 +00002853
2854 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002855 // Build segment map (all segments)
2856 // p: setup_client_stack() [for 'esp_at_startup']
2857 // p: init tool [for 'new_mem_startup']
nethercote71980f02004-01-24 18:18:54 +00002858 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002859 esp_at_startup___global_arg = esp_at_startup;
2860 VG_(parse_procselfmaps) ( build_segment_map_callback ); /* everything */
2861 esp_at_startup___global_arg = 0;
2862
2863 //--------------------------------------------------------------
nethercotef84f6952004-07-15 14:58:33 +00002864 // Protect client trampoline page (which is also sysinfo stuff)
2865 // p: segment stuff [otherwise get seg faults...]
nethercotec314eba2004-07-15 12:59:41 +00002866 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002867 VG_(mprotect)( (void *)VG_(client_trampoline_code),
2868 VG_(trampoline_code_length), VKI_PROT_READ|VKI_PROT_EXEC );
2869
2870 //==============================================================
2871 // Can use VG_(map)() after segments set up
2872 //==============================================================
nethercote71980f02004-01-24 18:18:54 +00002873
2874 //--------------------------------------------------------------
2875 // Allow GDB attach
2876 // p: process_cmd_line_options() [for VG_(clo_wait_for_gdb)]
2877 //--------------------------------------------------------------
2878 /* Hook to delay things long enough so we can get the pid and
2879 attach GDB in another shell. */
2880 if (VG_(clo_wait_for_gdb)) {
2881 VG_(printf)("pid=%d\n", VG_(getpid)());
2882 /* do "jump *$eip" to skip this in gdb */
2883 VG_(do_syscall)(__NR_pause);
2884 }
2885
2886 //--------------------------------------------------------------
nethercote1d447092004-02-01 17:29:59 +00002887 // Set up baseBlock
nethercote71980f02004-01-24 18:18:54 +00002888 // p: {pre,post}_clo_init() [for tool helper registration]
2889 // load_client() [for 'client_eip']
2890 // setup_client_stack() [for 'esp_at_startup']
2891 //--------------------------------------------------------------
2892 init_baseBlock(client_eip, esp_at_startup);
2893
2894 //--------------------------------------------------------------
2895 // Search for file descriptors that are inherited from our parent
2896 // p: process_cmd_line_options [for VG_(clo_track_fds)]
2897 //--------------------------------------------------------------
2898 if (VG_(clo_track_fds))
2899 VG_(init_preopened_fds)();
2900
2901 //--------------------------------------------------------------
2902 // Initialise the scheduler
2903 // p: init_baseBlock() [baseBlock regs copied into VG_(threads)[1]]
2904 // p: setup_file_descriptors() [else VG_(safe_fd)() breaks]
2905 //--------------------------------------------------------------
2906 VG_(scheduler_init)();
2907
2908 //--------------------------------------------------------------
2909 // Set up the ProxyLWP machinery
2910 // p: VG_(scheduler_init)()? [XXX: subtle dependency?]
2911 // - subs: VG_(sigstartup_actions)()?
2912 //--------------------------------------------------------------
2913 VG_(proxy_init)();
2914
2915 //--------------------------------------------------------------
2916 // Initialise the signal handling subsystem
2917 // p: VG_(atfork)(NULL, NULL, newpid) [else problems with sigmasks]
2918 // p: VG_(proxy_init)() [else breaks...]
2919 //--------------------------------------------------------------
2920 // Nb: temporarily parks the saved blocking-mask in saved_sigmask.
2921 VG_(sigstartup_actions)();
2922
2923 //--------------------------------------------------------------
2924 // Perhaps we're profiling Valgrind?
2925 // p: process_cmd_line_options() [for VG_(clo_profile)]
2926 // p: others?
2927 //
2928 // XXX: this seems to be broken? It always says the tool wasn't built
2929 // for profiling; vg_profile.c's functions don't seem to be overriding
2930 // vg_dummy_profile.c's?
2931 //
2932 // XXX: want this as early as possible. Looking for --profile
2933 // in pre_process_cmd_line_options() could get it earlier.
2934 //--------------------------------------------------------------
2935 if (VG_(clo_profile))
2936 VGP_(init_profiling)();
2937
2938 VGP_PUSHCC(VgpStartup);
2939
2940 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002941 // Read suppression file
2942 // p: process_cmd_line_options() [for VG_(clo_suppressions)]
2943 //--------------------------------------------------------------
2944 if (VG_(needs).core_errors || VG_(needs).skin_errors)
2945 VG_(load_suppressions)();
2946
2947 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002948 // Initialise translation table and translation cache
2949 // p: read_procselfmaps [so the anonymous mmaps for the TT/TC
2950 // aren't identified as part of the client, which would waste
2951 // > 20M of virtual address space.]
2952 //--------------------------------------------------------------
2953 VG_(init_tt_tc)();
2954
2955 //--------------------------------------------------------------
2956 // Read debug info to find glibc entry points to intercept
2957 // p: parse_procselfmaps? [XXX for debug info?]
2958 // p: init_tt_tc? [XXX ???]
2959 //--------------------------------------------------------------
2960 VG_(setup_code_redirect_table)();
2961
2962 //--------------------------------------------------------------
2963 // Verbosity message
2964 // p: end_rdtsc_calibration [so startup message is printed first]
2965 //--------------------------------------------------------------
2966 if (VG_(clo_verbosity) == 1)
2967 VG_(message)(Vg_UserMsg, "For more details, rerun with: -v");
2968 if (VG_(clo_verbosity) > 0)
2969 VG_(message)(Vg_UserMsg, "");
2970
2971 //--------------------------------------------------------------
2972 // Setup pointercheck
2973 // p: process_cmd_line_options() [for VG_(clo_pointercheck)]
2974 //--------------------------------------------------------------
2975 setup_pointercheck();
2976
nethercote71980f02004-01-24 18:18:54 +00002977 //--------------------------------------------------------------
2978 // Run!
2979 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002980 VGP_POPCC(VgpStartup);
2981 VGP_PUSHCC(VgpSched);
2982
nethercote31294822004-08-02 13:15:26 +00002983 VG_(fatal_signal_jmpbuf_ptr) = &fatal_signal_jmpbuf;
2984 if (__builtin_setjmp(VG_(fatal_signal_jmpbuf_ptr)) == 0) {
nethercote47dd12c2004-06-22 14:18:42 +00002985 src = VG_(scheduler)( &exitcode );
nethercote31294822004-08-02 13:15:26 +00002986 } else {
nethercote71980f02004-01-24 18:18:54 +00002987 src = VgSrc_FatalSig;
nethercote31294822004-08-02 13:15:26 +00002988 }
nethercote71980f02004-01-24 18:18:54 +00002989 VGP_POPCC(VgpSched);
nethercote71980f02004-01-24 18:18:54 +00002990
2991
2992
2993 //--------------------------------------------------------------
2994 // Finalisation: cleanup, messages, etc. Order no so important, only
2995 // affects what order the messages come.
2996 //--------------------------------------------------------------
2997 if (VG_(clo_verbosity) > 0)
2998 VG_(message)(Vg_UserMsg, "");
2999
3000 if (src == VgSrc_Deadlock) {
3001 VG_(message)(Vg_UserMsg,
3002 "Warning: pthread scheduler exited due to deadlock");
3003 }
3004
3005 /* Print out file descriptor summary and stats. */
3006 if (VG_(clo_track_fds))
3007 VG_(fd_stats)();
3008
3009 if (VG_(needs).core_errors || VG_(needs).skin_errors)
3010 VG_(show_all_errors)();
3011
nethercote47dd12c2004-06-22 14:18:42 +00003012 SK_(fini)( exitcode );
nethercote71980f02004-01-24 18:18:54 +00003013
3014 VG_(do_sanity_checks)( True /*include expensive checks*/ );
3015
3016 if (VG_(clo_verbosity) > 1)
3017 show_counts();
3018
3019 if (VG_(clo_verbosity) > 3)
3020 VG_(print_UInstr_histogram)();
3021
3022 if (0) {
3023 VG_(message)(Vg_DebugMsg, "");
3024 VG_(message)(Vg_DebugMsg,
3025 "------ Valgrind's internal memory use stats follow ------" );
3026 VG_(mallocSanityCheckAll)();
3027 VG_(show_all_arena_stats)();
3028 VG_(message)(Vg_DebugMsg,
3029 "------ Valgrind's ExeContext management stats follow ------" );
3030 VG_(show_ExeContext_stats)();
3031 }
3032
3033 if (VG_(clo_profile))
3034 VGP_(done_profiling)();
3035
nethercote71980f02004-01-24 18:18:54 +00003036 /* We're exiting, so nuke all the threads and clean up the proxy LWPs */
3037 vg_assert(src == VgSrc_FatalSig ||
3038 VG_(threads)[VG_(last_run_tid)].status == VgTs_Runnable ||
3039 VG_(threads)[VG_(last_run_tid)].status == VgTs_WaitJoiner);
3040 VG_(nuke_all_threads_except)(VG_INVALID_THREADID);
3041
3042 //--------------------------------------------------------------
3043 // Exit, according to the scheduler's return code
3044 //--------------------------------------------------------------
3045 switch (src) {
3046 case VgSrc_ExitSyscall: /* the normal way out */
nethercote85cdd342004-08-01 22:36:40 +00003047 vg_assert(VG_(last_run_tid) > 0 && VG_(last_run_tid) < VG_N_THREADS);
nethercote71980f02004-01-24 18:18:54 +00003048 VG_(proxy_shutdown)();
3049
3050 /* The thread's %EBX at the time it did __NR_exit() will hold
3051 the arg to __NR_exit(), so we just do __NR_exit() with
3052 that arg. */
nethercote47dd12c2004-06-22 14:18:42 +00003053 VG_(exit)( exitcode );
nethercote71980f02004-01-24 18:18:54 +00003054 /* NOT ALIVE HERE! */
3055 VG_(core_panic)("entered the afterlife in main() -- ExitSyscall");
3056 break; /* what the hell :) */
3057
3058 case VgSrc_Deadlock:
3059 /* Just exit now. No point in continuing. */
3060 VG_(proxy_shutdown)();
3061 VG_(exit)(0);
3062 VG_(core_panic)("entered the afterlife in main() -- Deadlock");
3063 break;
3064
nethercote71980f02004-01-24 18:18:54 +00003065 case VgSrc_FatalSig:
3066 /* We were killed by a fatal signal, so replicate the effect */
3067 vg_assert(VG_(fatal_sigNo) != -1);
3068 VG_(kill_self)(VG_(fatal_sigNo));
3069 VG_(core_panic)("main(): signal was supposed to be fatal");
3070 break;
3071
3072 default:
3073 VG_(core_panic)("main(): unexpected scheduler return code");
3074 }
3075
3076 abort();
3077}
3078
3079
sewardjde4a1d02002-03-22 01:27:54 +00003080/*--------------------------------------------------------------------*/
3081/*--- end vg_main.c ---*/
3082/*--------------------------------------------------------------------*/