blob: caa3e9243c0ab2bd25421e6433afe9f001d51180 [file] [log] [blame]
sewardjde4a1d02002-03-22 01:27:54 +00001
2/*--------------------------------------------------------------------*/
nethercote71980f02004-01-24 18:18:54 +00003/*--- Startup: the real stuff vg_main.c ---*/
sewardjde4a1d02002-03-22 01:27:54 +00004/*--------------------------------------------------------------------*/
5
6/*
njnc9539842002-10-02 13:26:35 +00007 This file is part of Valgrind, an extensible x86 protected-mode
8 emulator for monitoring program execution on x86-Unixes.
sewardjde4a1d02002-03-22 01:27:54 +00009
nethercotebb1c9912004-01-04 16:43:23 +000010 Copyright (C) 2000-2004 Julian Seward
sewardjde4a1d02002-03-22 01:27:54 +000011 jseward@acm.org
sewardjde4a1d02002-03-22 01:27:54 +000012
13 This program is free software; you can redistribute it and/or
14 modify it under the terms of the GNU General Public License as
15 published by the Free Software Foundation; either version 2 of the
16 License, or (at your option) any later version.
17
18 This program is distributed in the hope that it will be useful, but
19 WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 General Public License for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software
25 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
26 02111-1307, USA.
27
njn25e49d8e72002-09-23 09:36:25 +000028 The GNU General Public License is contained in the file COPYING.
sewardjde4a1d02002-03-22 01:27:54 +000029*/
30
nethercote71980f02004-01-24 18:18:54 +000031#define _FILE_OFFSET_BITS 64
sewardjde4a1d02002-03-22 01:27:54 +000032
nethercote71980f02004-01-24 18:18:54 +000033#include "vg_include.h"
34#include "ume.h"
35#include "ume_arch.h"
36#include "ume_archdefs.h"
37
38#include <dirent.h>
39#include <dlfcn.h>
40#include <errno.h>
41#include <fcntl.h>
42#include <stdio.h>
fitzhardingeb727d042004-01-06 00:18:21 +000043#include <stdlib.h>
nethercote71980f02004-01-24 18:18:54 +000044#include <string.h>
45#include <sys/mman.h>
46#include <sys/types.h>
47#include <sys/stat.h>
fitzhardingeb727d042004-01-06 00:18:21 +000048#include <sys/ptrace.h>
49#include <sys/signal.h>
fitzhardingeb727d042004-01-06 00:18:21 +000050#include <sys/wait.h>
51#include <unistd.h>
52
thughes74b8de22004-04-22 18:12:31 +000053#ifndef AT_DCACHEBSIZE
54#define AT_DCACHEBSIZE 19
55#endif /* AT_DCACHEBSIZE */
56
57#ifndef AT_ICACHEBSIZE
58#define AT_ICACHEBSIZE 20
59#endif /* AT_ICACHEBSIZE */
60
61#ifndef AT_UCACHEBSIZE
62#define AT_UCACHEBSIZE 21
63#endif /* AT_UCACHEBSIZE */
64
nethercote71980f02004-01-24 18:18:54 +000065#ifndef AT_SYSINFO
66#define AT_SYSINFO 32
67#endif /* AT_SYSINFO */
68
69#ifndef AT_SYSINFO_EHDR
70#define AT_SYSINFO_EHDR 33
71#endif /* AT_SYSINFO_EHDR */
72
73#ifndef AT_SECURE
74#define AT_SECURE 23 /* secure mode boolean */
75#endif /* AT_SECURE */
76
nethercote71980f02004-01-24 18:18:54 +000077/* redzone gap between client address space and shadow */
78#define REDZONE_SIZE (1 * 1024*1024)
79
80/* size multiple for client address space */
nethercotee94b2de2004-06-23 16:15:06 +000081#define CLIENT_SIZE_MULTIPLE (1 * 1024*1024)
nethercote71980f02004-01-24 18:18:54 +000082
nethercotee2097312004-06-27 12:29:56 +000083/* Proportion of client space for its heap (rest is for mmaps + stack) */
84#define CLIENT_HEAP_PROPORTION 0.333
nethercote71980f02004-01-24 18:18:54 +000085
86/*====================================================================*/
87/*=== Global entities not referenced from generated code ===*/
88/*====================================================================*/
89
sewardjde4a1d02002-03-22 01:27:54 +000090/* ---------------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +000091 Startup stuff
sewardjde4a1d02002-03-22 01:27:54 +000092 ------------------------------------------------------------------ */
nethercote71980f02004-01-24 18:18:54 +000093/* linker-defined base address */
94extern char kickstart_base;
sewardjde4a1d02002-03-22 01:27:54 +000095
nethercote71980f02004-01-24 18:18:54 +000096/* Client address space, lowest to highest (see top of ume.c) */
97Addr VG_(client_base); /* client address space limits */
fitzhardinge98abfc72003-12-16 02:05:15 +000098Addr VG_(client_end);
99Addr VG_(client_mapbase);
fitzhardinge92360792003-12-24 10:11:11 +0000100Addr VG_(client_trampoline_code);
fitzhardinge98abfc72003-12-16 02:05:15 +0000101Addr VG_(clstk_base);
102Addr VG_(clstk_end);
nethercote71980f02004-01-24 18:18:54 +0000103
104Addr VG_(brk_base); /* start of brk */
105Addr VG_(brk_limit); /* current brk */
106
107Addr VG_(shadow_base); /* skin's shadow memory */
fitzhardinge98abfc72003-12-16 02:05:15 +0000108Addr VG_(shadow_end);
nethercote71980f02004-01-24 18:18:54 +0000109
110Addr VG_(valgrind_base); /* valgrind's address range */
fitzhardinge98abfc72003-12-16 02:05:15 +0000111Addr VG_(valgrind_end);
112
fitzhardingeb50068f2004-02-24 23:42:55 +0000113vki_rlimit VG_(client_rlimit_data);
114
nethercote71980f02004-01-24 18:18:54 +0000115/* This is set early to indicate whether this CPU has the
116 SSE/fxsave/fxrestor features. */
117Bool VG_(have_ssestate);
118
119/* Indicates presence, and holds address of client's sysinfo page, a
120 feature of some modern kernels used to provide vsyscalls, etc. */
121Bool VG_(sysinfo_page_exists) = False;
122Addr VG_(sysinfo_page_addr) = 0;
123
fitzhardinge98abfc72003-12-16 02:05:15 +0000124/* stage1 (main) executable */
fitzhardingea49f9b52003-12-16 22:26:45 +0000125Int VG_(vgexecfd) = -1;
126
127/* client executable */
128Int VG_(clexecfd) = -1;
fitzhardinge98abfc72003-12-16 02:05:15 +0000129
130/* Path to library directory */
131const Char *VG_(libdir) = VG_LIBDIR;
132
133/* our argc/argv */
134Int VG_(vg_argc);
135Char **VG_(vg_argv);
136
jsgf855d93d2003-10-13 22:26:55 +0000137/* PID of the main thread */
138Int VG_(main_pid);
139
140/* PGRP of process */
141Int VG_(main_pgrp);
njn25e49d8e72002-09-23 09:36:25 +0000142
thughesad1c9562004-06-26 11:27:52 +0000143/* Application-visible file descriptor limits */
144Int VG_(fd_soft_limit) = -1;
145Int VG_(fd_hard_limit) = -1;
fitzhardingef0046f22003-12-18 02:39:22 +0000146
nethercote71980f02004-01-24 18:18:54 +0000147/* As deduced from esp_at_startup, the client's argc, argv[] and
148 envp[] as extracted from the client's stack at startup-time. */
149Int VG_(client_argc);
150Char** VG_(client_argv);
151Char** VG_(client_envp);
sewardjde4a1d02002-03-22 01:27:54 +0000152
153/* ---------------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +0000154 Running stuff
sewardjde4a1d02002-03-22 01:27:54 +0000155 ------------------------------------------------------------------ */
nethercote71980f02004-01-24 18:18:54 +0000156/* Our signal delivery stack. */
njn6eba4ef2003-05-01 08:06:41 +0000157UInt VG_(sigstack)[VG_SIGSTACK_SIZE_W];
sewardjde4a1d02002-03-22 01:27:54 +0000158
nethercote71980f02004-01-24 18:18:54 +0000159/* jmp_buf for fatal signals */
160Int VG_(fatal_sigNo) = -1;
161Bool VG_(fatal_signal_set) = False;
162jmp_buf VG_(fatal_signal_jmpbuf);
sewardjde4a1d02002-03-22 01:27:54 +0000163
nethercote71980f02004-01-24 18:18:54 +0000164/* Counts downwards in VG_(run_innerloop). */
165UInt VG_(dispatch_ctr);
sewardjde4a1d02002-03-22 01:27:54 +0000166
167/* 64-bit counter for the number of basic blocks done. */
168ULong VG_(bbs_done);
sewardjde4a1d02002-03-22 01:27:54 +0000169
sewardj7e87e382002-05-03 19:09:05 +0000170/* This is the ThreadId of the last thread the scheduler ran. */
171ThreadId VG_(last_run_tid) = 0;
172
nethercote71980f02004-01-24 18:18:54 +0000173/* Tell the logging mechanism whether we are logging to a file
174 descriptor or a socket descriptor. */
175Bool VG_(logging_to_filedes) = True;
176
sewardj73cf3bc2002-11-03 03:20:15 +0000177
nethercote71980f02004-01-24 18:18:54 +0000178/*====================================================================*/
179/*=== Counters, for profiling purposes only ===*/
180/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +0000181
182/* Number of lookups which miss the fast tt helper. */
183UInt VG_(tt_fast_misses) = 0;
184
185
sewardjc0d8f682002-11-30 00:49:43 +0000186/* Counts for TT/TC informational messages. */
sewardjde4a1d02002-03-22 01:27:54 +0000187
sewardjde4a1d02002-03-22 01:27:54 +0000188/* Number and total o/t size of translations overall. */
189UInt VG_(overall_in_count) = 0;
190UInt VG_(overall_in_osize) = 0;
191UInt VG_(overall_in_tsize) = 0;
192/* Number and total o/t size of discards overall. */
193UInt VG_(overall_out_count) = 0;
194UInt VG_(overall_out_osize) = 0;
195UInt VG_(overall_out_tsize) = 0;
sewardjc0d8f682002-11-30 00:49:43 +0000196/* The number of discards of TT/TC. */
197UInt VG_(number_of_tc_discards) = 0;
sewardj22854b92002-11-30 14:00:47 +0000198/* Counts of chain and unchain operations done. */
199UInt VG_(bb_enchain_count) = 0;
200UInt VG_(bb_dechain_count) = 0;
201/* Number of unchained jumps performed. */
202UInt VG_(unchained_jumps_done) = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000203
204
205/* Counts pertaining to the register allocator. */
206
207/* total number of uinstrs input to reg-alloc */
208UInt VG_(uinstrs_prealloc) = 0;
209
210/* total number of uinstrs added due to spill code */
211UInt VG_(uinstrs_spill) = 0;
212
213/* number of bbs requiring spill code */
214UInt VG_(translations_needing_spill) = 0;
215
216/* total of register ranks over all translations */
217UInt VG_(total_reg_rank) = 0;
218
219
sewardjde4a1d02002-03-22 01:27:54 +0000220/* Counts pertaining to internal sanity checking. */
sewardjde4a1d02002-03-22 01:27:54 +0000221UInt VG_(sanity_fast_count) = 0;
222UInt VG_(sanity_slow_count) = 0;
223
sewardj2e93c502002-04-12 11:12:52 +0000224/* Counts pertaining to the scheduler. */
225UInt VG_(num_scheduling_events_MINOR) = 0;
226UInt VG_(num_scheduling_events_MAJOR) = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000227
228
nethercote71980f02004-01-24 18:18:54 +0000229static __inline__ Int safe_idiv(Int a, Int b)
230{
231 return (b == 0 ? 0 : a / b);
232}
233
234static void show_counts ( void )
235{
236 VG_(message)(Vg_DebugMsg,
237 " TT/TC: %d tc sectors discarded.",
238 VG_(number_of_tc_discards) );
239 VG_(message)(Vg_DebugMsg,
240 " %d chainings, %d unchainings.",
241 VG_(bb_enchain_count), VG_(bb_dechain_count) );
242 VG_(message)(Vg_DebugMsg,
243 "translate: new %d (%d -> %d; ratio %d:10)",
244 VG_(overall_in_count),
245 VG_(overall_in_osize),
246 VG_(overall_in_tsize),
247 safe_idiv(10*VG_(overall_in_tsize), VG_(overall_in_osize)));
248 VG_(message)(Vg_DebugMsg,
249 " discard %d (%d -> %d; ratio %d:10).",
250 VG_(overall_out_count),
251 VG_(overall_out_osize),
252 VG_(overall_out_tsize),
253 safe_idiv(10*VG_(overall_out_tsize), VG_(overall_out_osize)));
254 VG_(message)(Vg_DebugMsg,
255 " dispatch: %llu jumps (bb entries), of which %u (%lu%%) were unchained.",
256 VG_(bbs_done),
257 VG_(unchained_jumps_done),
258 ((ULong)(100) * (ULong)(VG_(unchained_jumps_done)))
259 / ( VG_(bbs_done)==0 ? 1 : VG_(bbs_done) )
260 );
261
262 VG_(message)(Vg_DebugMsg,
263 " %d/%d major/minor sched events. %d tt_fast misses.",
264 VG_(num_scheduling_events_MAJOR),
265 VG_(num_scheduling_events_MINOR),
266 VG_(tt_fast_misses));
267
268 VG_(message)(Vg_DebugMsg,
269 "reg-alloc: %d t-req-spill, "
270 "%d+%d orig+spill uis, %d total-reg-r.",
271 VG_(translations_needing_spill),
272 VG_(uinstrs_prealloc),
273 VG_(uinstrs_spill),
274 VG_(total_reg_rank) );
275 VG_(message)(Vg_DebugMsg,
276 " sanity: %d cheap, %d expensive checks.",
277 VG_(sanity_fast_count),
278 VG_(sanity_slow_count) );
279 VG_(print_ccall_stats)();
280}
281
282
283/*====================================================================*/
284/*=== Miscellaneous global functions ===*/
285/*====================================================================*/
286
nethercote04d0fbc2004-01-26 16:48:06 +0000287/* Start debugger and get it to attach to this process. Called if the
288 user requests this service after an error has been shown, so she can
nethercote71980f02004-01-24 18:18:54 +0000289 poke around and look at parameters, memory, etc. You can't
nethercote04d0fbc2004-01-26 16:48:06 +0000290 meaningfully get the debugger to continue the program, though; to
291 continue, quit the debugger. */
292void VG_(start_debugger) ( Int tid )
nethercote71980f02004-01-24 18:18:54 +0000293{
294 Int pid;
295
296 if ((pid = fork()) == 0) {
297 ptrace(PTRACE_TRACEME, 0, NULL, NULL);
298 VG_(kkill)(VG_(getpid)(), VKI_SIGSTOP);
299
300 } else if (pid > 0) {
301 struct user_regs_struct regs;
302 Int status;
303 Int res;
304
305 if (VG_(is_running_thread)( tid )) {
fitzhardinged65dcad2004-03-13 02:06:58 +0000306 regs.cs = VG_(baseBlock)[VGOFF_(m_cs)];
307 regs.ss = VG_(baseBlock)[VGOFF_(m_ss)];
308 regs.ds = VG_(baseBlock)[VGOFF_(m_ds)];
309 regs.es = VG_(baseBlock)[VGOFF_(m_es)];
310 regs.fs = VG_(baseBlock)[VGOFF_(m_fs)];
311 regs.gs = VG_(baseBlock)[VGOFF_(m_gs)];
nethercote71980f02004-01-24 18:18:54 +0000312 regs.eax = VG_(baseBlock)[VGOFF_(m_eax)];
313 regs.ebx = VG_(baseBlock)[VGOFF_(m_ebx)];
314 regs.ecx = VG_(baseBlock)[VGOFF_(m_ecx)];
315 regs.edx = VG_(baseBlock)[VGOFF_(m_edx)];
316 regs.esi = VG_(baseBlock)[VGOFF_(m_esi)];
317 regs.edi = VG_(baseBlock)[VGOFF_(m_edi)];
318 regs.ebp = VG_(baseBlock)[VGOFF_(m_ebp)];
319 regs.esp = VG_(baseBlock)[VGOFF_(m_esp)];
320 regs.eflags = VG_(baseBlock)[VGOFF_(m_eflags)];
321 regs.eip = VG_(baseBlock)[VGOFF_(m_eip)];
322 } else {
323 ThreadState* tst = & VG_(threads)[ tid ];
324
fitzhardinged65dcad2004-03-13 02:06:58 +0000325 regs.cs = tst->m_cs;
326 regs.ss = tst->m_ss;
327 regs.ds = tst->m_ds;
328 regs.es = tst->m_es;
329 regs.fs = tst->m_fs;
330 regs.gs = tst->m_gs;
nethercote71980f02004-01-24 18:18:54 +0000331 regs.eax = tst->m_eax;
332 regs.ebx = tst->m_ebx;
333 regs.ecx = tst->m_ecx;
334 regs.edx = tst->m_edx;
335 regs.esi = tst->m_esi;
336 regs.edi = tst->m_edi;
337 regs.ebp = tst->m_ebp;
338 regs.esp = tst->m_esp;
339 regs.eflags = tst->m_eflags;
340 regs.eip = tst->m_eip;
341 }
342
343 if ((res = VG_(waitpid)(pid, &status, 0)) == pid &&
344 WIFSTOPPED(status) && WSTOPSIG(status) == SIGSTOP &&
345 ptrace(PTRACE_SETREGS, pid, NULL, &regs) == 0 &&
thughes1d160052004-04-21 15:39:57 +0000346 kill(pid, SIGSTOP) == 0 &&
347 ptrace(PTRACE_DETACH, pid, NULL, 0) == 0) {
nethercote04d0fbc2004-01-26 16:48:06 +0000348 Char pidbuf[15];
349 Char file[30];
350 Char buf[100];
351 Char *bufptr;
352 Char *cmdptr;
353
354 VG_(sprintf)(pidbuf, "%d", pid);
355 VG_(sprintf)(file, "/proc/%d/fd/%d", pid, VG_(clexecfd));
356
357 bufptr = buf;
358 cmdptr = VG_(clo_db_command);
359
360 while (*cmdptr) {
361 switch (*cmdptr) {
362 case '%':
363 switch (*++cmdptr) {
364 case 'f':
365 VG_(memcpy)(bufptr, file, VG_(strlen)(file));
366 bufptr += VG_(strlen)(file);
367 cmdptr++;
368 break;
369 case 'p':
370 VG_(memcpy)(bufptr, pidbuf, VG_(strlen)(pidbuf));
371 bufptr += VG_(strlen)(pidbuf);
372 cmdptr++;
373 break;
374 default:
375 *bufptr++ = *cmdptr++;
376 break;
377 }
378 break;
379 default:
380 *bufptr++ = *cmdptr++;
381 break;
382 }
383 }
384
385 *bufptr++ = '\0';
386
387 VG_(message)(Vg_UserMsg, "starting debugger with cmd: %s", buf);
nethercote71980f02004-01-24 18:18:54 +0000388 res = VG_(system)(buf);
389 if (res == 0) {
390 VG_(message)(Vg_UserMsg, "");
391 VG_(message)(Vg_UserMsg,
nethercote04d0fbc2004-01-26 16:48:06 +0000392 "Debugger has detached. Valgrind regains control. We continue.");
nethercote71980f02004-01-24 18:18:54 +0000393 } else {
394 VG_(message)(Vg_UserMsg, "Apparently failed!");
395 VG_(message)(Vg_UserMsg, "");
396 }
397 }
398
399 VG_(kkill)(pid, VKI_SIGKILL);
400 VG_(waitpid)(pid, &status, 0);
401 }
402}
403
404
405/* Print some helpful-ish text about unimplemented things, and give
406 up. */
407void VG_(unimplemented) ( Char* msg )
408{
409 VG_(message)(Vg_UserMsg, "");
410 VG_(message)(Vg_UserMsg,
411 "Valgrind detected that your program requires");
412 VG_(message)(Vg_UserMsg,
413 "the following unimplemented functionality:");
414 VG_(message)(Vg_UserMsg, " %s", msg);
415 VG_(message)(Vg_UserMsg,
416 "This may be because the functionality is hard to implement,");
417 VG_(message)(Vg_UserMsg,
418 "or because no reasonable program would behave this way,");
419 VG_(message)(Vg_UserMsg,
420 "or because nobody has yet needed it. In any case, let us know at");
421 VG_(message)(Vg_UserMsg,
422 "%s and/or try to work around the problem, if you can.", VG_BUGS_TO);
423 VG_(message)(Vg_UserMsg,
424 "");
425 VG_(message)(Vg_UserMsg,
426 "Valgrind has to exit now. Sorry. Bye!");
427 VG_(message)(Vg_UserMsg,
428 "");
429 VG_(pp_sched_status)();
430 VG_(exit)(1);
431}
432
433Addr VG_(get_stack_pointer) ( void )
434{
435 return VG_(baseBlock)[VGOFF_(m_esp)];
436}
437
438/* Debugging thing .. can be called from assembly with OYNK macro. */
439void VG_(oynk) ( Int n )
440{
441 OINK(n);
442}
443
444/* Initialize the PID and PGRP of scheduler LWP; this is also called
445 in any new children after fork. */
446static void newpid(ThreadId unused)
447{
448 /* PID of scheduler LWP */
449 VG_(main_pid) = VG_(getpid)();
450 VG_(main_pgrp) = VG_(getpgrp)();
451}
452
453/*====================================================================*/
454/*=== Check we were launched by stage 1 ===*/
455/*====================================================================*/
456
457/* Look for our AUXV table */
458static void scan_auxv(void)
459{
460 const struct ume_auxv *auxv = find_auxv((int *)ume_exec_esp);
461 int found = 0;
462
463 for (; auxv->a_type != AT_NULL; auxv++)
464 switch(auxv->a_type) {
465 case AT_UME_PADFD:
466 as_setpadfd(auxv->u.a_val);
467 found |= 1;
468 break;
469
470 case AT_UME_EXECFD:
471 VG_(vgexecfd) = auxv->u.a_val;
472 found |= 2;
473 break;
474 }
475
476 if ( ! (1|2) ) {
477 fprintf(stderr, "stage2 must be launched by stage1\n");
478 exit(127);
479 }
480}
481
482
483/*====================================================================*/
484/*=== Address space determination ===*/
485/*====================================================================*/
486
487/* Pad client space so it doesn't get filled in before the right time */
488static void layout_client_space(Addr argc_addr)
489{
490 VG_(client_base) = CLIENT_BASE;
nethercotec314eba2004-07-15 12:59:41 +0000491 VG_(valgrind_base) = (addr_t)&kickstart_base;
nethercote71980f02004-01-24 18:18:54 +0000492 VG_(valgrind_end) = ROUNDUP(argc_addr, 0x10000); /* stack */
493
nethercote71980f02004-01-24 18:18:54 +0000494 as_pad((void *)VG_(client_base), (void *)VG_(valgrind_base));
495}
496
497static void layout_remaining_space(float ratio)
498{
nethercotee567e702004-07-10 17:49:17 +0000499 Int ires;
500 void* vres;
501
nethercote71980f02004-01-24 18:18:54 +0000502 /* This tries to give the client as large as possible address space while
503 * taking into account the tool's shadow needs. */
504 addr_t client_size = ROUNDDN((VG_(valgrind_base) - REDZONE_SIZE) / (1. + ratio),
505 CLIENT_SIZE_MULTIPLE);
506 addr_t shadow_size = PGROUNDUP(client_size * ratio);
507
508 VG_(client_end) = VG_(client_base) + client_size;
509 VG_(client_mapbase) = PGROUNDDN((client_size/4)*3); /* where !FIXED mmap goes */
nethercotee2097312004-06-27 12:29:56 +0000510
511 /* where !FIXED mmap goes */
512 VG_(client_mapbase) = PGROUNDDN((addr_t)(client_size * CLIENT_HEAP_PROPORTION));
nethercote71980f02004-01-24 18:18:54 +0000513 VG_(client_trampoline_code) = VG_(client_end) - VKI_BYTES_PER_PAGE;
514
515 VG_(shadow_base) = VG_(client_end) + REDZONE_SIZE;
516 VG_(shadow_end) = VG_(shadow_base) + shadow_size;
517
nethercotee2097312004-06-27 12:29:56 +0000518#define SEGSIZE(a,b) ((VG_(b) - VG_(a))/(1024*1024))
519
nethercote71980f02004-01-24 18:18:54 +0000520 if (0)
nethercotee2097312004-06-27 12:29:56 +0000521 VG_(printf)(
522 "client_base %8x (%dMB)\n"
523 "client_mapbase %8x (%dMB)\n"
524 "client_end %8x (%dMB)\n"
525 "shadow_base %8x (%dMB)\n"
526 "shadow_end %8x (%dMB)\n"
527 "valgrind_base %8x (%dMB)\n"
nethercotee2097312004-06-27 12:29:56 +0000528 "valgrind_end %8x\n",
529 VG_(client_base), SEGSIZE(client_base, client_mapbase),
530 VG_(client_mapbase), SEGSIZE(client_mapbase, client_end),
531 VG_(client_end), SEGSIZE(client_end, shadow_base),
532 VG_(shadow_base), SEGSIZE(shadow_base, shadow_end),
533 VG_(shadow_end), SEGSIZE(shadow_end, valgrind_base),
nethercotec314eba2004-07-15 12:59:41 +0000534 VG_(valgrind_base), SEGSIZE(valgrind_base, valgrind_end),
nethercotee2097312004-06-27 12:29:56 +0000535 VG_(valgrind_end)
536 );
537
538#undef SEGSIZE
nethercote71980f02004-01-24 18:18:54 +0000539
540 // Ban redzone
nethercotee567e702004-07-10 17:49:17 +0000541 vres = mmap((void *)VG_(client_end), REDZONE_SIZE, PROT_NONE,
542 MAP_FIXED|MAP_ANON|MAP_PRIVATE, -1, 0);
543 vg_assert((void*)-1 != vres);
nethercote71980f02004-01-24 18:18:54 +0000544
545 // Make client hole
nethercotee567e702004-07-10 17:49:17 +0000546 ires = munmap((void*)VG_(client_base), client_size);
547 vg_assert(0 == ires);
nethercote71980f02004-01-24 18:18:54 +0000548
549 // Map shadow memory.
550 // Initially all inaccessible, incrementally initialized as it is used
nethercotee567e702004-07-10 17:49:17 +0000551 if (shadow_size != 0) {
552 vres = mmap((char *)VG_(shadow_base), shadow_size, PROT_NONE,
553 MAP_PRIVATE|MAP_ANON|MAP_FIXED, -1, 0);
554 vg_assert((void*)-1 != vres);
555 }
nethercote71980f02004-01-24 18:18:54 +0000556}
557
558/*====================================================================*/
559/*=== Command line setup ===*/
560/*====================================================================*/
561
562/* Nb: malloc'd memory never freed -- kept throughout like argv, envp */
563static char* get_file_clo(char* dir)
564{
565# define FLEN 512
566 Int fd, n;
567 struct stat s1;
568 char* f_clo = NULL;
569 char filename[FLEN];
570
571 snprintf(filename, FLEN, "%s/.valgrindrc", ( NULL == dir ? "" : dir ) );
572 fd = VG_(open)(filename, 0, VKI_S_IRUSR);
573 if ( fd > 0 ) {
574 if ( 0 == fstat(fd, &s1) ) {
575 f_clo = malloc(s1.st_size+1);
576 vg_assert(f_clo);
577 n = read(fd, f_clo, s1.st_size);
578 if (n == -1) n = 0;
579 f_clo[n] = '\0';
580 }
581 close(fd);
582 }
583 return f_clo;
584# undef FLEN
585}
586
nethercotee2097312004-06-27 12:29:56 +0000587#define ISSPACE(cc) ((cc) == ' ' || (cc) == '\t' || (cc) == '\n')
588
nethercote71980f02004-01-24 18:18:54 +0000589static Int count_args(char* s)
590{
591 Int n = 0;
592 if (s) {
593 char* cp = s;
594 while (True) {
595 // We have alternating sequences: blanks, non-blanks, blanks...
596 // count the non-blanks sequences.
597 while ( ISSPACE(*cp) ) cp++;
598 if ( !*cp ) break;
599 n++;
600 while ( !ISSPACE(*cp) && *cp ) cp++;
601 }
602 }
603 return n;
604}
605
606/* add args out of environment, skipping multiple spaces and -- args */
607static char** copy_args( char* s, char** to )
608{
609 if (s) {
610 char* cp = s;
611 while (True) {
612 // We have alternating sequences: blanks, non-blanks, blanks...
613 // copy the non-blanks sequences, and add terminating '\0'
614 while ( ISSPACE(*cp) ) cp++;
615 if ( !*cp ) break;
616 *to++ = cp;
617 while ( !ISSPACE(*cp) && *cp ) cp++;
618 if ( *cp ) *cp++ = '\0'; // terminate if necessary
619 if (VG_STREQ(to[-1], "--")) to--; // undo any '--' arg
620 }
621 }
622 return to;
623}
624
nethercotee2097312004-06-27 12:29:56 +0000625#undef ISSPACE
626
nethercote71980f02004-01-24 18:18:54 +0000627// Augment command line with arguments from environment and .valgrindrc
628// files.
629static void augment_command_line(Int* vg_argc_inout, char*** vg_argv_inout)
630{
631 int vg_argc = *vg_argc_inout;
632 char** vg_argv = *vg_argv_inout;
633
634 char* env_clo = getenv(VALGRINDOPTS);
635 char* f1_clo = get_file_clo( getenv("HOME") );
636 char* f2_clo = get_file_clo(".");
637
638 /* copy any extra args from file or environment, if present */
639 if ( (env_clo && *env_clo) || (f1_clo && *f1_clo) || (f2_clo && *f2_clo) ) {
640 /* ' ' separated extra options */
641 char **from;
642 char **to;
643 int env_arg_count, f1_arg_count, f2_arg_count;
644
645 env_arg_count = count_args(env_clo);
646 f1_arg_count = count_args(f1_clo);
647 f2_arg_count = count_args(f2_clo);
648
649 if (0)
650 printf("extra-argc=%d %d %d\n",
651 env_arg_count, f1_arg_count, f2_arg_count);
652
653 /* +2: +1 for null-termination, +1 for added '--' */
654 from = vg_argv;
655 vg_argv = malloc( (vg_argc + env_arg_count + f1_arg_count
656 + f2_arg_count + 2) * sizeof(char **));
657 to = vg_argv;
658
659 /* copy argv[0] */
660 *to++ = *from++;
661
662 /* Copy extra args from env var and file, in the order: ~/.valgrindrc,
663 * $VALGRIND_OPTS, ./.valgrindrc -- more local options are put later
664 * to override less local ones. */
665 to = copy_args(f1_clo, to);
666 to = copy_args(env_clo, to);
667 to = copy_args(f2_clo, to);
668
669 /* copy original arguments, stopping at command or -- */
670 while (*from) {
671 if (**from != '-')
672 break;
673 if (VG_STREQ(*from, "--")) {
674 from++; /* skip -- */
675 break;
676 }
677 *to++ = *from++;
678 }
679
680 /* add -- */
681 *to++ = "--";
682
683 vg_argc = to - vg_argv;
684
685 /* copy rest of original command line, then NULL */
686 while (*from) *to++ = *from++;
687 *to = NULL;
688 }
689
690 *vg_argc_inout = vg_argc;
691 *vg_argv_inout = vg_argv;
692}
693
694static void get_command_line( int argc, char** argv,
695 Int* vg_argc_out, Char*** vg_argv_out,
696 char*** cl_argv_out )
697{
698 int vg_argc;
699 char** vg_argv;
700 char** cl_argv;
701 char* env_clo = getenv(VALGRINDCLO);
702
703 if (env_clo != NULL && *env_clo != '\0') {
704 char *cp;
705 char **cpp;
706
707 /* OK, we're getting all our arguments from the environment - the
708 entire command line belongs to the client (including argv[0]) */
709 vg_argc = 1; /* argv[0] */
710 for (cp = env_clo; *cp; cp++)
711 if (*cp == '\01')
712 vg_argc++;
713
714 vg_argv = malloc(sizeof(char **) * (vg_argc + 1));
715
716 cpp = vg_argv;
717
718 *cpp++ = "valgrind"; /* nominal argv[0] */
719 *cpp++ = env_clo;
720
721 for (cp = env_clo; *cp; cp++) {
722 if (*cp == '\01') {
723 *cp++ = '\0'; /* chop it up in place */
724 *cpp++ = cp;
725 }
726 }
727 *cpp = NULL;
728 cl_argv = argv;
729
730 } else {
731 /* Count the arguments on the command line. */
732 vg_argv = argv;
733
734 for (vg_argc = 1; vg_argc < argc; vg_argc++) {
735 if (argv[vg_argc][0] != '-') /* exe name */
736 break;
737 if (VG_STREQ(argv[vg_argc], "--")) { /* dummy arg */
738 vg_argc++;
739 break;
740 }
741 }
742 cl_argv = &argv[vg_argc];
743
744 /* Get extra args from VALGRIND_OPTS and .valgrindrc files.
745 * Note we don't do this if getting args from VALGRINDCLO. */
746 augment_command_line(&vg_argc, &vg_argv);
747 }
748
749 if (0) {
750 Int i;
751 for (i = 0; i < vg_argc; i++)
752 printf("vg_argv[%d]=\"%s\"\n", i, vg_argv[i]);
753 }
754
755 *vg_argc_out = vg_argc;
756 *vg_argv_out = (Char**)vg_argv;
757 *cl_argv_out = cl_argv;
758}
759
760
761/*====================================================================*/
762/*=== Environment and stack setup ===*/
763/*====================================================================*/
764
765/* Scan a colon-separated list, and call a function on each element.
766 The string must be mutable, because we insert a temporary '\0', but
thughes4ad52d02004-06-27 17:37:21 +0000767 the string will end up unmodified. (*func) should return True if it
nethercote71980f02004-01-24 18:18:54 +0000768 doesn't need to see any more.
thughes4ad52d02004-06-27 17:37:21 +0000769
770 This routine will return True if (*func) returns True and False if
771 it reaches the end of the list without that happening.
nethercote71980f02004-01-24 18:18:54 +0000772*/
thughes4ad52d02004-06-27 17:37:21 +0000773static Bool scan_colsep(char *colsep, Bool (*func)(const char *))
nethercote71980f02004-01-24 18:18:54 +0000774{
775 char *cp, *entry;
776 int end;
777
778 if (colsep == NULL ||
779 *colsep == '\0')
thughes4ad52d02004-06-27 17:37:21 +0000780 return False;
nethercote71980f02004-01-24 18:18:54 +0000781
782 entry = cp = colsep;
783
784 do {
785 end = (*cp == '\0');
786
787 if (*cp == ':' || *cp == '\0') {
788 char save = *cp;
789
790 *cp = '\0';
thughes21942d92004-07-12 09:35:37 +0000791 if ((*func)(entry)) {
792 *cp = save;
thughes4ad52d02004-06-27 17:37:21 +0000793 return True;
thughes21942d92004-07-12 09:35:37 +0000794 }
nethercote71980f02004-01-24 18:18:54 +0000795 *cp = save;
796 entry = cp+1;
797 }
798 cp++;
799 } while(!end);
thughes4ad52d02004-06-27 17:37:21 +0000800
801 return False;
802}
803
804static Bool contains(const char *p) {
805 if (VG_STREQ(p, VG_(libdir))) {
806 return True;
807 }
808 return False;
nethercote71980f02004-01-24 18:18:54 +0000809}
810
811/* Prepare the client's environment. This is basically a copy of our
812 environment, except:
813 1. LD_LIBRARY_PATH=$VALGRINDLIB:$LD_LIBRARY_PATH
814 2. LD_PRELOAD=$VALGRINDLIB/vg_inject.so:($VALGRINDLIB/vgpreload_TOOL.so:)?$LD_PRELOAD
815
816 If any of these is missing, then it is added.
817
818 Yummy. String hacking in C.
819
820 If this needs to handle any more variables it should be hacked
821 into something table driven.
822 */
823static char **fix_environment(char **origenv, const char *preload)
824{
825 static const char inject_so[] = "vg_inject.so";
826 static const char ld_library_path[] = "LD_LIBRARY_PATH=";
827 static const char ld_preload[] = "LD_PRELOAD=";
828 static const char valgrind_clo[] = VALGRINDCLO "=";
829 static const int ld_library_path_len = sizeof(ld_library_path)-1;
830 static const int ld_preload_len = sizeof(ld_preload)-1;
831 static const int valgrind_clo_len = sizeof(valgrind_clo)-1;
832 int ld_preload_done = 0;
833 int ld_library_path_done = 0;
834 char *inject_path;
835 int inject_path_len;
836 int vgliblen = strlen(VG_(libdir));
837 char **cpp;
838 char **ret;
839 int envc;
840 const int preloadlen = (preload == NULL) ? 0 : strlen(preload);
841
842 /* Find the vg_inject.so; also make room for the tool preload
843 library */
844 inject_path_len = sizeof(inject_so) + vgliblen + preloadlen + 16;
845 inject_path = malloc(inject_path_len);
846
847 if (preload)
848 snprintf(inject_path, inject_path_len, "%s/%s:%s",
849 VG_(libdir), inject_so, preload);
850 else
851 snprintf(inject_path, inject_path_len, "%s/%s",
852 VG_(libdir), inject_so);
853
854 /* Count the original size of the env */
855 envc = 0; /* trailing NULL */
856 for (cpp = origenv; cpp && *cpp; cpp++)
857 envc++;
858
859 /* Allocate a new space */
860 ret = malloc(sizeof(char *) * (envc+3+1)); /* 3 new entries + NULL */
861
862 /* copy it over */
863 for (cpp = ret; *origenv; )
864 *cpp++ = *origenv++;
865 *cpp = NULL;
866
867 vg_assert(envc == (cpp - ret));
868
869 /* Walk over the new environment, mashing as we go */
870 for (cpp = ret; cpp && *cpp; cpp++) {
871 if (memcmp(*cpp, ld_library_path, ld_library_path_len) == 0) {
nethercote71980f02004-01-24 18:18:54 +0000872 /* If the LD_LIBRARY_PATH already contains libdir, then don't
873 bother adding it again, even if it isn't the first (it
874 seems that the Java runtime will keep reexecing itself
875 unless its paths are at the front of LD_LIBRARY_PATH) */
thughes4ad52d02004-06-27 17:37:21 +0000876 if (!scan_colsep(*cpp + ld_library_path_len, contains)) {
nethercote71980f02004-01-24 18:18:54 +0000877 int len = strlen(*cpp) + vgliblen*2 + 16;
878 char *cp = malloc(len);
879
880 snprintf(cp, len, "%s%s:%s",
881 ld_library_path, VG_(libdir),
882 (*cpp)+ld_library_path_len);
883
884 *cpp = cp;
885 }
886
887 ld_library_path_done = 1;
888 } else if (memcmp(*cpp, ld_preload, ld_preload_len) == 0) {
889 int len = strlen(*cpp) + inject_path_len;
890 char *cp = malloc(len);
891
892 snprintf(cp, len, "%s%s:%s",
893 ld_preload, inject_path, (*cpp)+ld_preload_len);
894
895 *cpp = cp;
896
897 ld_preload_done = 1;
898 } else if (memcmp(*cpp, valgrind_clo, valgrind_clo_len) == 0) {
899 *cpp = "";
900 }
901 }
902
903 /* Add the missing bits */
904
905 if (!ld_library_path_done) {
906 int len = ld_library_path_len + vgliblen*2 + 16;
907 char *cp = malloc(len);
908
909 snprintf(cp, len, "%s%s", ld_library_path, VG_(libdir));
910
911 ret[envc++] = cp;
912 }
913
914 if (!ld_preload_done) {
915 int len = ld_preload_len + inject_path_len;
916 char *cp = malloc(len);
917
918 snprintf(cp, len, "%s%s",
919 ld_preload, inject_path);
920
921 ret[envc++] = cp;
922 }
923
924 ret[envc] = NULL;
925
926 return ret;
927}
928
929extern char **environ; /* our environment */
930//#include <error.h>
931
932/* Add a string onto the string table, and return its address */
933static char *copy_str(char **tab, const char *str)
934{
935 char *cp = *tab;
936 char *orig = cp;
937
938 while(*str)
939 *cp++ = *str++;
940 *cp++ = '\0';
941
942 if (0)
943 printf("copied %p \"%s\" len %d\n",
944 orig, orig, cp-orig);
945
946 *tab = cp;
947
948 return orig;
949}
950
951/*
952 This sets up the client's initial stack, containing the args,
953 environment and aux vector.
954
955 The format of the stack is:
956
957 higher address +-----------------+
958 | Trampoline code |
959 +-----------------+
960 | |
961 : string table :
962 | |
963 +-----------------+
964 | AT_NULL |
965 - -
966 | auxv |
967 +-----------------+
968 | NULL |
969 - -
970 | envp |
971 +-----------------+
972 | NULL |
973 - -
974 | argv |
975 +-----------------+
976 | argc |
977 lower address +-----------------+ <- esp
978 | undefined |
979 : :
980 */
981static Addr setup_client_stack(char **orig_argv, char **orig_envp,
982 const struct exeinfo *info,
983 UInt** client_auxv)
984{
nethercotee567e702004-07-10 17:49:17 +0000985 void* res;
nethercote71980f02004-01-24 18:18:54 +0000986 char **cpp;
987 char *strtab; /* string table */
988 char *stringbase;
989 addr_t *ptr;
990 struct ume_auxv *auxv;
991 const struct ume_auxv *orig_auxv;
992 const struct ume_auxv *cauxv;
993 unsigned stringsize; /* total size of strings in bytes */
994 unsigned auxsize; /* total size of auxv in bytes */
995 int argc; /* total argc */
996 int envc; /* total number of env vars */
997 unsigned stacksize; /* total client stack size */
998 addr_t cl_esp; /* client stack base (initial esp) */
999
1000 /* use our own auxv as a prototype */
1001 orig_auxv = find_auxv(ume_exec_esp);
1002
1003 /* ==================== compute sizes ==================== */
1004
1005 /* first of all, work out how big the client stack will be */
1006 stringsize = 0;
1007
1008 /* paste on the extra args if the loader needs them (ie, the #!
1009 interpreter and its argument) */
1010 argc = 0;
1011 if (info->argv0 != NULL) {
1012 argc++;
1013 stringsize += strlen(info->argv0) + 1;
1014 }
1015 if (info->argv1 != NULL) {
1016 argc++;
1017 stringsize += strlen(info->argv1) + 1;
1018 }
1019
1020 /* now scan the args we're given... */
1021 for (cpp = orig_argv; *cpp; cpp++) {
1022 argc++;
1023 stringsize += strlen(*cpp) + 1;
1024 }
1025
1026 /* ...and the environment */
1027 envc = 0;
1028 for (cpp = orig_envp; cpp && *cpp; cpp++) {
1029 envc++;
1030 stringsize += strlen(*cpp) + 1;
1031 }
1032
1033 /* now, how big is the auxv? */
1034 auxsize = sizeof(*auxv); /* there's always at least one entry: AT_NULL */
1035 for (cauxv = orig_auxv; cauxv->a_type != AT_NULL; cauxv++) {
1036 if (cauxv->a_type == AT_PLATFORM)
1037 stringsize += strlen(cauxv->u.a_ptr) + 1;
1038 auxsize += sizeof(*cauxv);
1039 }
1040
1041 /* OK, now we know how big the client stack is */
1042 stacksize =
1043 sizeof(int) + /* argc */
1044 sizeof(char **)*argc + /* argv */
1045 sizeof(char **) + /* terminal NULL */
1046 sizeof(char **)*envc + /* envp */
1047 sizeof(char **) + /* terminal NULL */
1048 auxsize + /* auxv */
1049 ROUNDUP(stringsize, sizeof(int)) +/* strings (aligned) */
1050 VKI_BYTES_PER_PAGE; /* page for trampoline code */
1051
1052 /* cl_esp is the client's stack pointer */
1053 cl_esp = VG_(client_end) - stacksize;
1054 cl_esp = ROUNDDN(cl_esp, 16); /* make stack 16 byte aligned */
1055
nethercote71980f02004-01-24 18:18:54 +00001056 /* base of the string table (aligned) */
1057 stringbase = strtab = (char *)(VG_(client_trampoline_code) - ROUNDUP(stringsize, sizeof(int)));
1058
1059 VG_(clstk_base) = PGROUNDDN(cl_esp);
1060 VG_(clstk_end) = VG_(client_end);
1061
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 */
nethercotee567e702004-07-10 17:49:17 +00001072 res = mmap((void *)PGROUNDDN(cl_esp), VG_(client_end) - PGROUNDDN(cl_esp),
1073 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 --- */
1085 if (info->argv0) {
1086 *ptr++ = (addr_t)copy_str(&strtab, info->argv0);
1087 free(info->argv0);
1088 }
1089 if (info->argv1) {
1090 *ptr++ = (addr_t)copy_str(&strtab, info->argv1);
1091 free(info->argv1);
1092 }
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
1195 vg_assert((strtab-stringbase) == stringsize);
1196
nethercote5ee67ca2004-06-22 14:00:09 +00001197 /* We know the initial ESP is pointing at argc/argv */
1198 VG_(client_argc) = *(Int*)cl_esp;
1199 VG_(client_argv) = (Char**)(cl_esp + sizeof(Int));
1200
nethercote71980f02004-01-24 18:18:54 +00001201 return cl_esp;
1202}
1203
1204/*====================================================================*/
1205/*=== Find executable ===*/
1206/*====================================================================*/
1207
thughes4ad52d02004-06-27 17:37:21 +00001208static const char* executable_name;
1209
1210static Bool match_executable(const char *entry) {
1211 char buf[strlen(entry) + strlen(executable_name) + 2];
1212
1213 /* empty PATH element means . */
1214 if (*entry == '\0')
1215 entry = ".";
1216
1217 snprintf(buf, sizeof(buf), "%s/%s", entry, executable_name);
1218
1219 if (access(buf, R_OK|X_OK) == 0) {
1220 executable_name = strdup(buf);
1221 vg_assert(NULL != executable_name);
1222 return True;
1223 }
1224 return False;
1225}
1226
nethercote71980f02004-01-24 18:18:54 +00001227static const char* find_executable(const char* exec)
1228{
1229 vg_assert(NULL != exec);
thughes4ad52d02004-06-27 17:37:21 +00001230 executable_name = exec;
1231 if (strchr(executable_name, '/') == NULL) {
nethercote71980f02004-01-24 18:18:54 +00001232 /* no '/' - we need to search the path */
1233 char *path = getenv("PATH");
thughes4ad52d02004-06-27 17:37:21 +00001234 scan_colsep(path, match_executable);
nethercote71980f02004-01-24 18:18:54 +00001235 }
thughes4ad52d02004-06-27 17:37:21 +00001236 return executable_name;
nethercote71980f02004-01-24 18:18:54 +00001237}
1238
1239
1240/*====================================================================*/
1241/*=== Loading tools ===*/
1242/*====================================================================*/
1243
1244static void list_tools(void)
1245{
1246 DIR *dir = opendir(VG_(libdir));
1247 struct dirent *de;
1248 int first = 1;
1249
1250 if (dir == NULL) {
1251 fprintf(stderr, "Can't open %s: %s (installation problem?)\n",
nethercotef4928da2004-06-15 10:54:40 +00001252 VG_(libdir), strerror(errno));
nethercote71980f02004-01-24 18:18:54 +00001253 return;
1254 }
1255
nethercotef4928da2004-06-15 10:54:40 +00001256 while ((de = readdir(dir)) != NULL) {
nethercote71980f02004-01-24 18:18:54 +00001257 int len = strlen(de->d_name);
1258
1259 /* look for vgskin_TOOL.so names */
1260 if (len > (7+1+3) && /* "vgskin_" + at least 1-char toolname + ".so" */
nethercotef4928da2004-06-15 10:54:40 +00001261 strncmp(de->d_name, "vgskin_", 7) == 0 &&
1262 VG_STREQ(de->d_name + len - 3, ".so")) {
1263 if (first) {
1264 fprintf(stderr, "Available tools:\n");
1265 first = 0;
1266 }
1267 de->d_name[len-3] = '\0';
1268 fprintf(stderr, "\t%s\n", de->d_name+7);
nethercote71980f02004-01-24 18:18:54 +00001269 }
1270 }
1271
1272 closedir(dir);
1273
1274 if (first)
nethercotef4928da2004-06-15 10:54:40 +00001275 fprintf(stderr, "No tools available in \"%s\" (installation problem?)\n",
1276 VG_(libdir));
nethercote71980f02004-01-24 18:18:54 +00001277}
1278
1279
1280/* Find and load a tool, and check it looks ok. Also looks to see if there's
1281 * a matching vgpreload_*.so file, and returns its name in *preloadpath. */
1282static void load_tool( const char *toolname, void** handle_out,
1283 ToolInfo** toolinfo_out, char **preloadpath_out )
1284{
1285 Bool ok;
1286 int len = strlen(VG_(libdir)) + strlen(toolname)*2 + 16;
1287 char buf[len];
1288 void* handle;
1289 ToolInfo* toolinfo;
1290 char* preloadpath = NULL;
1291 Int* vg_malloc_redzonep;
1292
1293 // XXX: allowing full paths for --tool option -- does it make sense?
1294 // Doesn't allow for vgpreload_<tool>.so.
1295
1296 if (strchr(toolname, '/') != 0) {
1297 /* toolname contains '/', and so must be a pathname */
1298 handle = dlopen(toolname, RTLD_NOW);
1299 } else {
1300 /* just try in the libdir */
1301 snprintf(buf, len, "%s/vgskin_%s.so", VG_(libdir), toolname);
1302 handle = dlopen(buf, RTLD_NOW);
1303
1304 if (handle != NULL) {
1305 snprintf(buf, len, "%s/vgpreload_%s.so", VG_(libdir), toolname);
1306 if (access(buf, R_OK) == 0) {
1307 preloadpath = strdup(buf);
1308 vg_assert(NULL != preloadpath);
1309 }
1310 }
1311 }
1312
1313 ok = (NULL != handle);
1314 if (!ok) {
1315 fprintf(stderr, "Can't open tool \"%s\": %s\n", toolname, dlerror());
1316 goto bad_load;
1317 }
1318
1319 toolinfo = dlsym(handle, "vgSkin_tool_info");
1320 ok = (NULL != toolinfo);
1321 if (!ok) {
1322 fprintf(stderr, "Tool \"%s\" doesn't define SK_(tool_info) - "
1323 "add VG_DETERMINE_INTERFACE_VERSION?\n", toolname);
1324 goto bad_load;
1325 }
1326
1327 ok = (toolinfo->sizeof_ToolInfo == sizeof(*toolinfo) &&
1328 toolinfo->interface_major_version == VG_CORE_INTERFACE_MAJOR_VERSION &&
1329 toolinfo->sk_pre_clo_init != NULL);
1330 if (!ok) {
1331 fprintf(stderr, "Error:\n"
1332 " Tool and core interface versions do not match.\n"
1333 " Interface version used by core is: %d.%d (size %d)\n"
1334 " Interface version used by tool is: %d.%d (size %d)\n"
1335 " The major version numbers must match.\n",
1336 VG_CORE_INTERFACE_MAJOR_VERSION,
1337 VG_CORE_INTERFACE_MINOR_VERSION,
1338 sizeof(*toolinfo),
1339 toolinfo->interface_major_version,
1340 toolinfo->interface_minor_version,
1341 toolinfo->sizeof_ToolInfo);
1342 fprintf(stderr, " You need to at least recompile, and possibly update,\n");
1343 if (VG_CORE_INTERFACE_MAJOR_VERSION > toolinfo->interface_major_version)
1344 fprintf(stderr, " your skin to work with this version of Valgrind.\n");
1345 else
1346 fprintf(stderr, " your version of Valgrind to work with this skin.\n");
1347 goto bad_load;
1348 }
1349
1350 // Set redzone size for V's allocator
1351 vg_malloc_redzonep = dlsym(handle, STR(VG_(vg_malloc_redzone_szB)));
1352 if ( NULL != vg_malloc_redzonep ) {
1353 VG_(vg_malloc_redzone_szB) = *vg_malloc_redzonep;
1354 }
1355
1356 vg_assert(NULL != handle && NULL != toolinfo);
1357 *handle_out = handle;
1358 *toolinfo_out = toolinfo;
1359 *preloadpath_out = preloadpath;
1360 return;
1361
1362
1363 bad_load:
1364 if (handle != NULL)
1365 dlclose(handle);
1366
nethercotef4928da2004-06-15 10:54:40 +00001367 fprintf(stderr, "valgrind: couldn't load tool\n");
nethercote71980f02004-01-24 18:18:54 +00001368 list_tools();
1369 exit(127);
1370}
1371
nethercotef4928da2004-06-15 10:54:40 +00001372
1373/*====================================================================*/
1374/*=== Command line errors ===*/
1375/*====================================================================*/
1376
1377static void abort_msg ( void )
1378{
nethercotef8548672004-06-21 12:42:35 +00001379 VG_(clo_log_to) = VgLogTo_Fd;
1380 VG_(clo_log_fd) = 2; /* stderr */
nethercotef4928da2004-06-15 10:54:40 +00001381}
1382
1383void VG_(bad_option) ( Char* opt )
1384{
1385 abort_msg();
1386 VG_(printf)("valgrind: Bad option `%s'; aborting.\n", opt);
1387 VG_(printf)("valgrind: Use --help for more information.\n");
1388 VG_(exit)(1);
1389}
1390
1391static void missing_tool_option ( void )
1392{
1393 abort_msg();
1394 VG_(printf)("valgrind: Missing --tool option\n");
1395 list_tools();
1396 VG_(printf)("valgrind: Use --help for more information.\n");
1397 VG_(exit)(1);
1398}
1399
1400static void missing_prog ( void )
1401{
1402 abort_msg();
1403 VG_(printf)("valgrind: no program specified\n");
1404 VG_(printf)("valgrind: Use --help for more information.\n");
1405 VG_(exit)(1);
1406}
1407
1408static void config_error ( Char* msg )
1409{
1410 abort_msg();
1411 VG_(printf)("valgrind: Startup or configuration error:\n %s\n", msg);
1412 VG_(printf)("valgrind: Unable to start up properly. Giving up.\n");
1413 VG_(exit)(1);
1414}
1415
1416
nethercote71980f02004-01-24 18:18:54 +00001417/*====================================================================*/
1418/*=== Loading the client ===*/
1419/*====================================================================*/
1420
nethercotef4928da2004-06-15 10:54:40 +00001421static void load_client(char* cl_argv[], const char* exec, Int need_help,
nethercote71980f02004-01-24 18:18:54 +00001422 /*out*/struct exeinfo* info, /*out*/Addr* client_eip)
1423{
1424 // If they didn't specify an executable with --exec, and didn't specify
1425 // --help, then use client argv[0] (searching $PATH if necessary).
nethercotef4928da2004-06-15 10:54:40 +00001426 if (NULL == exec && !need_help) {
nethercote71980f02004-01-24 18:18:54 +00001427 if (cl_argv[0] == NULL ||
1428 ( NULL == (exec = find_executable(cl_argv[0])) ) )
1429 {
nethercotef4928da2004-06-15 10:54:40 +00001430 missing_prog();
nethercote71980f02004-01-24 18:18:54 +00001431 }
1432 }
1433
1434 info->map_base = VG_(client_mapbase);
nethercote71980f02004-01-24 18:18:54 +00001435
1436 info->exe_base = VG_(client_base);
1437 info->exe_end = VG_(client_end);
1438 info->argv = cl_argv;
1439
nethercotef4928da2004-06-15 10:54:40 +00001440 if (need_help) {
nethercote71980f02004-01-24 18:18:54 +00001441 VG_(clexecfd) = -1;
1442 info->argv0 = NULL;
1443 info->argv1 = NULL;
1444 } else {
1445 Int ret;
1446 VG_(clexecfd) = VG_(open)(exec, O_RDONLY, VKI_S_IRUSR);
1447 ret = do_exec(exec, info);
1448 if (ret != 0) {
nethercotef4928da2004-06-15 10:54:40 +00001449 fprintf(stderr, "valgrind: do_exec(%s) failed: %s\n", exec, strerror(ret));
nethercote71980f02004-01-24 18:18:54 +00001450 exit(127);
1451 }
1452 }
1453
1454 /* Copy necessary bits of 'info' that were filled in */
1455 *client_eip = info->init_eip;
1456 VG_(brk_base) = VG_(brk_limit) = info->brkbase;
1457}
1458
1459
1460/*====================================================================*/
1461/*=== Command-line: variables, processing ===*/
1462/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +00001463
njn25e49d8e72002-09-23 09:36:25 +00001464/* Define, and set defaults. */
1465Bool VG_(clo_error_limit) = True;
nethercote04d0fbc2004-01-26 16:48:06 +00001466Bool VG_(clo_db_attach) = False;
1467Char* VG_(clo_db_command) = VG_CLO_DEFAULT_DBCOMMAND;
njn43c799e2003-04-08 00:08:52 +00001468Bool VG_(clo_gen_suppressions) = False;
nethercote27fec902004-06-16 21:26:32 +00001469Int VG_(clo_sanity_level) = 1;
njn25e49d8e72002-09-23 09:36:25 +00001470Int VG_(clo_verbosity) = 1;
1471Bool VG_(clo_demangle) = True;
njn25e49d8e72002-09-23 09:36:25 +00001472Bool VG_(clo_trace_children) = False;
sewardj4cf05692002-10-27 20:28:29 +00001473
nethercotee1730692003-11-20 10:38:07 +00001474/* See big comment in vg_include.h for meaning of these three.
1475 fd is initially stdout, for --help, but gets moved to stderr by default
1476 immediately afterwards. */
sewardj4cf05692002-10-27 20:28:29 +00001477VgLogTo VG_(clo_log_to) = VgLogTo_Fd;
nethercotef8548672004-06-21 12:42:35 +00001478Int VG_(clo_log_fd) = 1;
1479Char* VG_(clo_log_name) = NULL;
sewardj4cf05692002-10-27 20:28:29 +00001480
sewardj6024b212003-07-13 10:54:33 +00001481Int VG_(clo_input_fd) = 0; /* stdin */
njn25e49d8e72002-09-23 09:36:25 +00001482Int VG_(clo_n_suppressions) = 0;
sewardjde4a1d02002-03-22 01:27:54 +00001483Char* VG_(clo_suppressions)[VG_CLO_MAX_SFILES];
njn25e49d8e72002-09-23 09:36:25 +00001484Bool VG_(clo_profile) = False;
1485Bool VG_(clo_single_step) = False;
1486Bool VG_(clo_optimise) = True;
1487UChar VG_(clo_trace_codegen) = 0; // 00000000b
1488Bool VG_(clo_trace_syscalls) = False;
1489Bool VG_(clo_trace_signals) = False;
1490Bool VG_(clo_trace_symtab) = False;
njn25e49d8e72002-09-23 09:36:25 +00001491Bool VG_(clo_trace_sched) = False;
1492Int VG_(clo_trace_pthread_level) = 0;
njn25e49d8e72002-09-23 09:36:25 +00001493Int VG_(clo_dump_error) = 0;
1494Int VG_(clo_backtrace_size) = 4;
1495Char* VG_(clo_weird_hacks) = NULL;
sewardj858964b2002-10-05 14:15:43 +00001496Bool VG_(clo_run_libc_freeres) = True;
rjwalshf5f536f2003-11-17 17:45:00 +00001497Bool VG_(clo_track_fds) = False;
sewardj22854b92002-11-30 14:00:47 +00001498Bool VG_(clo_chain_bb) = True;
nethercote77eba602003-11-13 17:35:04 +00001499Bool VG_(clo_show_below_main) = False;
fitzhardinge98abfc72003-12-16 02:05:15 +00001500Bool VG_(clo_pointercheck) = True;
fitzhardinge462f4f92003-12-18 02:10:54 +00001501Bool VG_(clo_branchpred) = False;
sewardj2370f3b2002-11-30 15:01:01 +00001502
jsgf855d93d2003-10-13 22:26:55 +00001503static Bool VG_(clo_wait_for_gdb) = False;
1504
1505/* If we're doing signal routing, poll for signals every 50mS by
1506 default. */
1507Int VG_(clo_signal_polltime) = 50;
1508
1509/* These flags reduce thread wakeup latency on syscall completion and
1510 signal delivery, respectively. The downside is possible unfairness. */
1511Bool VG_(clo_lowlat_syscalls) = False; /* low-latency syscalls */
1512Bool VG_(clo_lowlat_signals) = False; /* low-latency signals */
1513
sewardjde4a1d02002-03-22 01:27:54 +00001514
nethercote6c999f22004-01-31 22:55:15 +00001515void usage ( Bool debug_help )
njn7cf0bd32002-06-08 13:36:03 +00001516{
njn25e49d8e72002-09-23 09:36:25 +00001517 Char* usage1 =
nethercote71980f02004-01-24 18:18:54 +00001518"usage: valgrind --tool=<toolname> [options] prog-and-args\n"
njn25e49d8e72002-09-23 09:36:25 +00001519"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001520" common user options for all Valgrind tools, with defaults in [ ]:\n"
nethercote0d588502004-06-21 13:27:11 +00001521" --tool=<name> use the Valgrind tool named <name>\n"
nethercotea76368b2004-06-16 11:56:29 +00001522" -h --help show this message\n"
nethercote6c999f22004-01-31 22:55:15 +00001523" --help-debug show this message, plus debugging options\n"
njn25e49d8e72002-09-23 09:36:25 +00001524" --version show version\n"
njn25e49d8e72002-09-23 09:36:25 +00001525" -q --quiet run silently; only print error msgs\n"
1526" -v --verbose be more verbose, incl counts of errors\n"
nethercote77eba602003-11-13 17:35:04 +00001527" --trace-children=no|yes Valgrind-ise child processes? [no]\n"
nethercote0d588502004-06-21 13:27:11 +00001528" --track-fds=no|yes track open file descriptors? [no]\n"
nethercote2b0793f2003-12-02 10:41:18 +00001529"\n"
1530" uncommon user options for all Valgrind tools:\n"
nethercote0d588502004-06-21 13:27:11 +00001531" --run-libc-freeres=no|yes free up glibc memory at exit? [yes]\n"
1532" --weird-hacks=hack1,hack2,... recognised hacks: lax-ioctls [none]\n"
1533" --signal-polltime=<time> signal poll period (mS) for older kernels [50]\n"
1534" --lowlat-signals=no|yes improve thread signal wake-up latency [no]\n"
1535" --lowlat-syscalls=no|yes improve thread syscall wake-up latency [no]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001536" --pointercheck=no|yes enforce client address space limits [yes]\n"
njn25e49d8e72002-09-23 09:36:25 +00001537"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001538" user options for Valgrind tools that report errors:\n"
nethercotef8548672004-06-21 12:42:35 +00001539" --log-fd=<number> log messages to file descriptor [2=stderr]\n"
1540" --log-file=<file> log messages to <file>.pid<pid>\n"
1541" --log-socket=ipaddr:port log messages to socket ipaddr:port\n"
nethercote2b0793f2003-12-02 10:41:18 +00001542" --demangle=no|yes automatically demangle C++ names? [yes]\n"
1543" --num-callers=<number> show <num> callers in stack traces [4]\n"
1544" --error-limit=no|yes stop showing new errors if too many? [yes]\n"
1545" --show-below-main=no|yes continue stack traces below main() [no]\n"
1546" --suppressions=<filename> suppress errors described in <filename>\n"
1547" --gen-suppressions=no|yes print suppressions for errors detected [no]\n"
nethercote04d0fbc2004-01-26 16:48:06 +00001548" --db-attach=no|yes start debugger when errors detected? [no]\n"
1549" --db-command=<command> command to start debugger [gdb -nw %%f %%p]\n"
1550" --input-fd=<number> file descriptor for input [0=stdin]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001551"\n";
njn7cf0bd32002-06-08 13:36:03 +00001552
njn25e49d8e72002-09-23 09:36:25 +00001553 Char* usage2 =
1554"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001555" debugging options for all Valgrind tools:\n"
njn25e49d8e72002-09-23 09:36:25 +00001556" --sanity-level=<number> level of sanity checking to do [1]\n"
1557" --single-step=no|yes translate each instr separately? [no]\n"
1558" --optimise=no|yes improve intermediate code? [yes]\n"
nethercote137bc552003-11-14 17:47:54 +00001559" --profile=no|yes profile? (tool must be built for it) [no]\n"
sewardj22854b92002-11-30 14:00:47 +00001560" --chain-bb=no|yes do basic-block chaining? [yes]\n"
fitzhardinge462f4f92003-12-18 02:10:54 +00001561" --branchpred=yes|no generate branch prediction hints [no]\n"
njn25e49d8e72002-09-23 09:36:25 +00001562" --trace-codegen=<XXXXX> show generated code? (X = 0|1) [00000]\n"
1563" --trace-syscalls=no|yes show all system calls? [no]\n"
1564" --trace-signals=no|yes show signal handling details? [no]\n"
1565" --trace-symtab=no|yes show symbol table details? [no]\n"
njn25e49d8e72002-09-23 09:36:25 +00001566" --trace-sched=no|yes show thread scheduler details? [no]\n"
njn3e884182003-04-15 13:03:23 +00001567" --trace-pthread=none|some|all show pthread event details? [none]\n"
jsgf855d93d2003-10-13 22:26:55 +00001568" --wait-for-gdb=yes|no pause on startup to wait for gdb attach\n"
njn25e49d8e72002-09-23 09:36:25 +00001569"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001570" debugging options for Valgrind tools that report errors\n"
1571" --dump-error=<number> show translation for basic block associated\n"
1572" with <number>'th error context [0=show none]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001573"\n";
njn3e884182003-04-15 13:03:23 +00001574
1575 Char* usage3 =
1576"\n"
nethercote71980f02004-01-24 18:18:54 +00001577" Extra options read from ~/.valgrindrc, $VALGRIND_OPTS, ./.valgrindrc\n"
njn25e49d8e72002-09-23 09:36:25 +00001578"\n"
nethercotebb1c9912004-01-04 16:43:23 +00001579" Valgrind is Copyright (C) 2000-2004 Julian Seward\n"
njn25e49d8e72002-09-23 09:36:25 +00001580" and licensed under the GNU General Public License, version 2.\n"
1581" Bug reports, feedback, admiration, abuse, etc, to: %s.\n"
njnd04b7c62002-10-03 14:05:52 +00001582"\n"
nethercote137bc552003-11-14 17:47:54 +00001583" Tools are copyright and licensed by their authors. See each\n"
1584" tool's start-up message for more information.\n"
njn25e49d8e72002-09-23 09:36:25 +00001585"\n";
njn7cf0bd32002-06-08 13:36:03 +00001586
fitzhardinge98abfc72003-12-16 02:05:15 +00001587 VG_(printf)(usage1);
1588 if (VG_(details).name) {
1589 VG_(printf)(" user options for %s:\n", VG_(details).name);
fitzhardinge98abfc72003-12-16 02:05:15 +00001590 if (VG_(needs).command_line_options)
1591 SK_(print_usage)();
1592 else
1593 VG_(printf)(" (none)\n");
1594 }
nethercote6c999f22004-01-31 22:55:15 +00001595 if (debug_help) {
1596 VG_(printf)(usage2);
fitzhardinge98abfc72003-12-16 02:05:15 +00001597
nethercote6c999f22004-01-31 22:55:15 +00001598 if (VG_(details).name) {
1599 VG_(printf)(" debugging options for %s:\n", VG_(details).name);
1600
1601 if (VG_(needs).command_line_options)
1602 SK_(print_debug_usage)();
1603 else
1604 VG_(printf)(" (none)\n");
1605 }
fitzhardinge98abfc72003-12-16 02:05:15 +00001606 }
nethercote421281e2003-11-20 16:20:55 +00001607 VG_(printf)(usage3, VG_BUGS_TO);
nethercotef4928da2004-06-15 10:54:40 +00001608 VG_(exit)(0);
njn7cf0bd32002-06-08 13:36:03 +00001609}
sewardjde4a1d02002-03-22 01:27:54 +00001610
nethercote71980f02004-01-24 18:18:54 +00001611static void pre_process_cmd_line_options
nethercote6c999f22004-01-31 22:55:15 +00001612 ( Int* need_help, const char** tool, const char** exec )
sewardj1c1b1162003-02-23 01:25:51 +00001613{
nethercote71980f02004-01-24 18:18:54 +00001614 UInt i;
sewardjde4a1d02002-03-22 01:27:54 +00001615
nethercote71980f02004-01-24 18:18:54 +00001616 /* parse the options we have (only the options we care about now) */
1617 for (i = 1; i < VG_(vg_argc); i++) {
1618
1619 if (strcmp(VG_(vg_argv)[i], "--version") == 0) {
1620 printf("valgrind-" VERSION "\n");
nethercotef4928da2004-06-15 10:54:40 +00001621 exit(0);
nethercote71980f02004-01-24 18:18:54 +00001622
nethercotea76368b2004-06-16 11:56:29 +00001623 } else if (VG_CLO_STREQ(VG_(vg_argv)[i], "--help") ||
1624 VG_CLO_STREQ(VG_(vg_argv)[i], "-h")) {
nethercote6c999f22004-01-31 22:55:15 +00001625 *need_help = 1;
1626
nethercotef4928da2004-06-15 10:54:40 +00001627 } else if (VG_CLO_STREQ(VG_(vg_argv)[i], "--help-debug")) {
nethercote6c999f22004-01-31 22:55:15 +00001628 *need_help = 2;
nethercote71980f02004-01-24 18:18:54 +00001629
nethercotef4928da2004-06-15 10:54:40 +00001630 } else if (VG_CLO_STREQN(7, VG_(vg_argv)[i], "--tool=") ||
1631 VG_CLO_STREQN(7, VG_(vg_argv)[i], "--skin=")) {
nethercote71980f02004-01-24 18:18:54 +00001632 *tool = &VG_(vg_argv)[i][7];
1633
nethercotef4928da2004-06-15 10:54:40 +00001634 } else if (VG_CLO_STREQN(7, VG_(vg_argv)[i], "--exec=")) {
nethercote71980f02004-01-24 18:18:54 +00001635 *exec = &VG_(vg_argv)[i][7];
1636 }
1637 }
1638
nethercotef4928da2004-06-15 10:54:40 +00001639 /* If no tool specified, can act appropriately without loading tool */
nethercote71980f02004-01-24 18:18:54 +00001640 if (*tool == NULL) {
nethercotef4928da2004-06-15 10:54:40 +00001641 if (0 == *need_help) {
1642 // neither --tool nor --help/--help-debug specified
1643 missing_tool_option();
1644 } else {
1645 // Give help message, without any tool-specific help
1646 usage(/*help-debug?*/2 == *need_help);
1647 }
nethercote71980f02004-01-24 18:18:54 +00001648 }
1649}
1650
nethercote5ee67ca2004-06-22 14:00:09 +00001651static void process_cmd_line_options( UInt* client_auxv, const char* toolname )
nethercote71980f02004-01-24 18:18:54 +00001652{
nethercotef8548672004-06-21 12:42:35 +00001653 Int i, eventually_log_fd;
nethercote71980f02004-01-24 18:18:54 +00001654 Int *auxp;
1655 Int toolname_len = VG_(strlen)(toolname);
sewardjde4a1d02002-03-22 01:27:54 +00001656
nethercotee1730692003-11-20 10:38:07 +00001657 /* log to stderr by default, but usage message goes to stdout */
nethercotef8548672004-06-21 12:42:35 +00001658 eventually_log_fd = 2;
sewardjde4a1d02002-03-22 01:27:54 +00001659
sewardj19d81412002-06-03 01:10:40 +00001660 /* Check for sane path in ./configure --prefix=... */
fitzhardinge98abfc72003-12-16 02:05:15 +00001661 if (VG_LIBDIR[0] != '/')
sewardj19d81412002-06-03 01:10:40 +00001662 config_error("Please use absolute paths in "
1663 "./configure --prefix=... or --libdir=...");
sewardj38170912002-05-10 21:07:22 +00001664
nethercote71980f02004-01-24 18:18:54 +00001665 for (auxp = client_auxv; auxp[0] != VKI_AT_NULL; auxp += 2) {
fitzhardinge98abfc72003-12-16 02:05:15 +00001666 switch(auxp[0]) {
1667 case VKI_AT_SYSINFO:
1668 VG_(sysinfo_page_exists) = True;
fitzhardinge92360792003-12-24 10:11:11 +00001669 auxp[1] = (Int)(VG_(client_trampoline_code) + VG_(tramp_syscall_offset));
fitzhardinge98abfc72003-12-16 02:05:15 +00001670 VG_(sysinfo_page_addr) = auxp[1];
1671 break;
sewardjde4a1d02002-03-22 01:27:54 +00001672 }
fitzhardinge98abfc72003-12-16 02:05:15 +00001673 }
sewardjde4a1d02002-03-22 01:27:54 +00001674
nethercote71980f02004-01-24 18:18:54 +00001675 for (i = 1; i < VG_(vg_argc); i++) {
1676
1677 Char* arg = VG_(vg_argv)[i];
1678
1679 // XXX: allow colons in options, for Josef
1680
1681 /* Look for matching "--toolname:foo" */
1682 if (VG_(strstr)(arg, ":")) {
1683 if (VG_CLO_STREQN(2, arg, "--") &&
1684 VG_CLO_STREQN(toolname_len, arg+2, toolname) &&
1685 VG_CLO_STREQN(1, arg+2+toolname_len, ":"))
1686 {
1687 // prefix matches, convert "--toolname:foo" to "--foo"
1688 if (0)
1689 VG_(printf)("tool-specific arg: %s\n", arg);
1690 arg += toolname_len + 1;
1691 arg[0] = '-';
1692 arg[1] = '-';
1693
1694 } else {
1695 // prefix doesn't match, skip to next arg
1696 continue;
1697 }
1698 }
1699
fitzhardinge98abfc72003-12-16 02:05:15 +00001700 /* Ignore these options - they've already been handled */
nethercote71980f02004-01-24 18:18:54 +00001701 if (VG_CLO_STREQN(7, arg, "--tool=") ||
1702 VG_CLO_STREQN(7, arg, "--skin="))
fitzhardinge98abfc72003-12-16 02:05:15 +00001703 continue;
nethercote71980f02004-01-24 18:18:54 +00001704 if (VG_CLO_STREQN(7, arg, "--exec="))
fitzhardinge98abfc72003-12-16 02:05:15 +00001705 continue;
1706
nethercote71980f02004-01-24 18:18:54 +00001707 if ( VG_CLO_STREQ(arg, "--"))
fitzhardinge98abfc72003-12-16 02:05:15 +00001708 continue;
nethercote27fec902004-06-16 21:26:32 +00001709
nethercote71980f02004-01-24 18:18:54 +00001710 else if (VG_CLO_STREQ(arg, "-v") ||
1711 VG_CLO_STREQ(arg, "--verbose"))
sewardjde4a1d02002-03-22 01:27:54 +00001712 VG_(clo_verbosity)++;
nethercote27fec902004-06-16 21:26:32 +00001713
nethercote71980f02004-01-24 18:18:54 +00001714 else if (VG_CLO_STREQ(arg, "-q") ||
1715 VG_CLO_STREQ(arg, "--quiet"))
sewardjde4a1d02002-03-22 01:27:54 +00001716 VG_(clo_verbosity)--;
1717
nethercote27fec902004-06-16 21:26:32 +00001718 else VG_BOOL_CLO("--branchpred", VG_(clo_branchpred))
1719 else VG_BOOL_CLO("--chain-bb", VG_(clo_chain_bb))
1720 else VG_BOOL_CLO("--db-attach", VG_(clo_db_attach))
1721 else VG_BOOL_CLO("--demangle", VG_(clo_demangle))
1722 else VG_BOOL_CLO("--error-limit", VG_(clo_error_limit))
1723 else VG_BOOL_CLO("--gen-suppressions", VG_(clo_gen_suppressions))
1724 else VG_BOOL_CLO("--lowlat-signals", VG_(clo_lowlat_signals))
1725 else VG_BOOL_CLO("--lowlat-syscalls", VG_(clo_lowlat_syscalls))
1726 else VG_BOOL_CLO("--optimise", VG_(clo_optimise))
1727 else VG_BOOL_CLO("--pointercheck", VG_(clo_pointercheck))
1728 else VG_BOOL_CLO("--profile", VG_(clo_profile))
1729 else VG_BOOL_CLO("--run-libc-freeres", VG_(clo_run_libc_freeres))
1730 else VG_BOOL_CLO("--show-below-main", VG_(clo_show_below_main))
1731 else VG_BOOL_CLO("--single-step", VG_(clo_single_step))
1732 else VG_BOOL_CLO("--track-fds", VG_(clo_track_fds))
1733 else VG_BOOL_CLO("--trace-children", VG_(clo_trace_children))
1734 else VG_BOOL_CLO("--trace-sched", VG_(clo_trace_sched))
1735 else VG_BOOL_CLO("--trace-signals", VG_(clo_trace_signals))
1736 else VG_BOOL_CLO("--trace-symtab", VG_(clo_trace_symtab))
1737 else VG_BOOL_CLO("--trace-syscalls", VG_(clo_trace_syscalls))
1738 else VG_BOOL_CLO("--wait-for-gdb", VG_(clo_wait_for_gdb))
sewardj72f98ff2002-06-13 17:23:38 +00001739
nethercote27fec902004-06-16 21:26:32 +00001740 else VG_STR_CLO ("--db-command", VG_(clo_db_command))
1741 else VG_STR_CLO ("--weird-hacks", VG_(clo_weird_hacks))
sewardjde4a1d02002-03-22 01:27:54 +00001742
nethercote27fec902004-06-16 21:26:32 +00001743 else VG_NUM_CLO ("--dump-error", VG_(clo_dump_error))
1744 else VG_NUM_CLO ("--input-fd", VG_(clo_input_fd))
1745 else VG_NUM_CLO ("--sanity-level", VG_(clo_sanity_level))
1746 else VG_NUM_CLO ("--signal­polltime", VG_(clo_signal_polltime))
1747 else VG_BNUM_CLO("--num-callers", VG_(clo_backtrace_size), 1,
1748 VG_DEEPEST_BACKTRACE)
sewardjde4a1d02002-03-22 01:27:54 +00001749
nethercotef8548672004-06-21 12:42:35 +00001750 // for backwards compatibility, replaced by --log-fd
nethercote71980f02004-01-24 18:18:54 +00001751 else if (VG_CLO_STREQN(13, arg, "--logfile-fd=")) {
nethercotef8548672004-06-21 12:42:35 +00001752 VG_(clo_log_to) = VgLogTo_Fd;
1753 VG_(clo_log_name) = NULL;
1754 eventually_log_fd = (Int)VG_(atoll)(&arg[13]);
1755 }
1756 else if (VG_CLO_STREQN(9, arg, "--log-fd=")) {
1757 VG_(clo_log_to) = VgLogTo_Fd;
1758 VG_(clo_log_name) = NULL;
1759 eventually_log_fd = (Int)VG_(atoll)(&arg[9]);
sewardj4cf05692002-10-27 20:28:29 +00001760 }
1761
nethercotef8548672004-06-21 12:42:35 +00001762 // for backwards compatibility, replaced by --log-file
nethercote71980f02004-01-24 18:18:54 +00001763 else if (VG_CLO_STREQN(10, arg, "--logfile=")) {
nethercotef8548672004-06-21 12:42:35 +00001764 VG_(clo_log_to) = VgLogTo_File;
1765 VG_(clo_log_name) = &arg[10];
1766 }
1767 else if (VG_CLO_STREQN(11, arg, "--log-file=")) {
1768 VG_(clo_log_to) = VgLogTo_File;
1769 VG_(clo_log_name) = &arg[11];
sewardj4cf05692002-10-27 20:28:29 +00001770 }
sewardjde4a1d02002-03-22 01:27:54 +00001771
nethercotef8548672004-06-21 12:42:35 +00001772 // for backwards compatibility, replaced by --log-socket
nethercote71980f02004-01-24 18:18:54 +00001773 else if (VG_CLO_STREQN(12, arg, "--logsocket=")) {
nethercotef8548672004-06-21 12:42:35 +00001774 VG_(clo_log_to) = VgLogTo_Socket;
1775 VG_(clo_log_name) = &arg[12];
1776 }
1777 else if (VG_CLO_STREQN(13, arg, "--log-socket=")) {
1778 VG_(clo_log_to) = VgLogTo_Socket;
1779 VG_(clo_log_name) = &arg[13];
sewardj73cf3bc2002-11-03 03:20:15 +00001780 }
1781
nethercote71980f02004-01-24 18:18:54 +00001782 else if (VG_CLO_STREQN(15, arg, "--suppressions=")) {
sewardjde4a1d02002-03-22 01:27:54 +00001783 if (VG_(clo_n_suppressions) >= VG_CLO_MAX_SFILES) {
njn25e49d8e72002-09-23 09:36:25 +00001784 VG_(message)(Vg_UserMsg, "Too many suppression files specified.");
sewardjde4a1d02002-03-22 01:27:54 +00001785 VG_(message)(Vg_UserMsg,
1786 "Increase VG_CLO_MAX_SFILES and recompile.");
nethercote71980f02004-01-24 18:18:54 +00001787 VG_(bad_option)(arg);
sewardjde4a1d02002-03-22 01:27:54 +00001788 }
nethercote71980f02004-01-24 18:18:54 +00001789 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = &arg[15];
sewardjde4a1d02002-03-22 01:27:54 +00001790 VG_(clo_n_suppressions)++;
1791 }
sewardjde4a1d02002-03-22 01:27:54 +00001792
njn25e49d8e72002-09-23 09:36:25 +00001793 /* "vwxyz" --> 000zyxwv (binary) */
nethercote71980f02004-01-24 18:18:54 +00001794 else if (VG_CLO_STREQN(16, arg, "--trace-codegen=")) {
njn25e49d8e72002-09-23 09:36:25 +00001795 Int j;
nethercote71980f02004-01-24 18:18:54 +00001796 char* opt = & arg[16];
njn25e49d8e72002-09-23 09:36:25 +00001797
1798 if (5 != VG_(strlen)(opt)) {
1799 VG_(message)(Vg_UserMsg,
1800 "--trace-codegen argument must have 5 digits");
nethercote71980f02004-01-24 18:18:54 +00001801 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001802 }
1803 for (j = 0; j < 5; j++) {
1804 if ('0' == opt[j]) { /* do nothing */ }
1805 else if ('1' == opt[j]) VG_(clo_trace_codegen) |= (1 << j);
1806 else {
1807 VG_(message)(Vg_UserMsg, "--trace-codegen argument can only "
1808 "contain 0s and 1s");
nethercote71980f02004-01-24 18:18:54 +00001809 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001810 }
1811 }
1812 }
sewardjde4a1d02002-03-22 01:27:54 +00001813
nethercote71980f02004-01-24 18:18:54 +00001814 else if (VG_CLO_STREQ(arg, "--trace-pthread=none"))
sewardj45b4b372002-04-16 22:50:32 +00001815 VG_(clo_trace_pthread_level) = 0;
nethercote71980f02004-01-24 18:18:54 +00001816 else if (VG_CLO_STREQ(arg, "--trace-pthread=some"))
sewardj45b4b372002-04-16 22:50:32 +00001817 VG_(clo_trace_pthread_level) = 1;
nethercote71980f02004-01-24 18:18:54 +00001818 else if (VG_CLO_STREQ(arg, "--trace-pthread=all"))
sewardj45b4b372002-04-16 22:50:32 +00001819 VG_(clo_trace_pthread_level) = 2;
sewardj8937c812002-04-12 20:12:20 +00001820
nethercote71980f02004-01-24 18:18:54 +00001821 else if ( ! VG_(needs).command_line_options
1822 || ! SK_(process_cmd_line_option)(arg) ) {
nethercotef4928da2004-06-15 10:54:40 +00001823 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001824 }
sewardjde4a1d02002-03-22 01:27:54 +00001825 }
1826
nethercote27fec902004-06-16 21:26:32 +00001827 // Check various option values
1828
njnf9ebf672003-05-12 21:41:30 +00001829 if (VG_(clo_verbosity) < 0)
sewardjde4a1d02002-03-22 01:27:54 +00001830 VG_(clo_verbosity) = 0;
1831
nethercote04d0fbc2004-01-26 16:48:06 +00001832 if (VG_(clo_db_attach) && VG_(clo_trace_children)) {
sewardjde4a1d02002-03-22 01:27:54 +00001833 VG_(message)(Vg_UserMsg, "");
1834 VG_(message)(Vg_UserMsg,
nethercote04d0fbc2004-01-26 16:48:06 +00001835 "--db-attach=yes conflicts with --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001836 VG_(message)(Vg_UserMsg,
1837 "Please choose one or the other, but not both.");
nethercote04d0fbc2004-01-26 16:48:06 +00001838 VG_(bad_option)("--db-attach=yes and --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001839 }
1840
nethercotef8548672004-06-21 12:42:35 +00001841 /* Set up logging now. After this is done, VG_(clo_log_fd)
sewardj4cf05692002-10-27 20:28:29 +00001842 should be connected to whatever sink has been selected, and we
1843 indiscriminately chuck stuff into it without worrying what the
1844 nature of it is. Oh the wonder of Unix streams. */
1845
nethercotee1730692003-11-20 10:38:07 +00001846 /* So far we should be still attached to stdout, so we can show on
sewardj4cf05692002-10-27 20:28:29 +00001847 the terminal any problems to do with processing command line
1848 opts. */
nethercotef8548672004-06-21 12:42:35 +00001849 vg_assert(VG_(clo_log_fd) == 1 /* stdout */);
sewardj73cf3bc2002-11-03 03:20:15 +00001850 vg_assert(VG_(logging_to_filedes) == True);
sewardj4cf05692002-10-27 20:28:29 +00001851
1852 switch (VG_(clo_log_to)) {
sewardj73cf3bc2002-11-03 03:20:15 +00001853
sewardj4cf05692002-10-27 20:28:29 +00001854 case VgLogTo_Fd:
nethercotef8548672004-06-21 12:42:35 +00001855 vg_assert(VG_(clo_log_name) == NULL);
1856 VG_(clo_log_fd) = eventually_log_fd;
sewardj4cf05692002-10-27 20:28:29 +00001857 break;
sewardj73cf3bc2002-11-03 03:20:15 +00001858
sewardj4cf05692002-10-27 20:28:29 +00001859 case VgLogTo_File: {
1860 Char logfilename[1000];
jsgff3c3f1a2003-10-14 22:13:28 +00001861 Int seq = 0;
1862 Int pid = VG_(getpid)();
1863
nethercotef8548672004-06-21 12:42:35 +00001864 vg_assert(VG_(clo_log_name) != NULL);
1865 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
jsgff3c3f1a2003-10-14 22:13:28 +00001866
nethercote71980f02004-01-24 18:18:54 +00001867 for (;;) {
jsgff3c3f1a2003-10-14 22:13:28 +00001868 if (seq == 0)
1869 VG_(sprintf)(logfilename, "%s.pid%d",
nethercotef8548672004-06-21 12:42:35 +00001870 VG_(clo_log_name), pid );
jsgff3c3f1a2003-10-14 22:13:28 +00001871 else
1872 VG_(sprintf)(logfilename, "%s.pid%d.%d",
nethercotef8548672004-06-21 12:42:35 +00001873 VG_(clo_log_name), pid, seq );
jsgff3c3f1a2003-10-14 22:13:28 +00001874 seq++;
1875
nethercotef8548672004-06-21 12:42:35 +00001876 eventually_log_fd
jsgff3c3f1a2003-10-14 22:13:28 +00001877 = VG_(open)(logfilename,
1878 VKI_O_CREAT|VKI_O_WRONLY|VKI_O_EXCL|VKI_O_TRUNC,
1879 VKI_S_IRUSR|VKI_S_IWUSR);
nethercotef8548672004-06-21 12:42:35 +00001880 if (eventually_log_fd >= 0) {
1881 VG_(clo_log_fd) = VG_(safe_fd)(eventually_log_fd);
jsgff3c3f1a2003-10-14 22:13:28 +00001882 break;
1883 } else {
nethercotef8548672004-06-21 12:42:35 +00001884 if (eventually_log_fd != -VKI_EEXIST) {
jsgff3c3f1a2003-10-14 22:13:28 +00001885 VG_(message)(Vg_UserMsg,
1886 "Can't create/open log file `%s.pid%d'; giving up!",
nethercotef8548672004-06-21 12:42:35 +00001887 VG_(clo_log_name), pid);
jsgff3c3f1a2003-10-14 22:13:28 +00001888 VG_(bad_option)(
nethercotef8548672004-06-21 12:42:35 +00001889 "--log-file=<file> didn't work out for some reason.");
jsgff3c3f1a2003-10-14 22:13:28 +00001890 break;
1891 }
1892 }
1893 }
sewardj4cf05692002-10-27 20:28:29 +00001894 break;
sewardj73cf3bc2002-11-03 03:20:15 +00001895 }
1896
1897 case VgLogTo_Socket: {
nethercotef8548672004-06-21 12:42:35 +00001898 vg_assert(VG_(clo_log_name) != NULL);
1899 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
1900 eventually_log_fd = VG_(connect_via_socket)( VG_(clo_log_name) );
1901 if (eventually_log_fd == -1) {
sewardj73cf3bc2002-11-03 03:20:15 +00001902 VG_(message)(Vg_UserMsg,
nethercotef8548672004-06-21 12:42:35 +00001903 "Invalid --log-socket=ipaddr or --log-socket=ipaddr:port spec");
sewardj73cf3bc2002-11-03 03:20:15 +00001904 VG_(message)(Vg_UserMsg,
nethercotef8548672004-06-21 12:42:35 +00001905 "of `%s'; giving up!", VG_(clo_log_name) );
sewardj73cf3bc2002-11-03 03:20:15 +00001906 VG_(bad_option)(
nethercotef8548672004-06-21 12:42:35 +00001907 "--log-socket=");
sewardj4cf05692002-10-27 20:28:29 +00001908 }
nethercotef8548672004-06-21 12:42:35 +00001909 if (eventually_log_fd == -2) {
sewardj73cf3bc2002-11-03 03:20:15 +00001910 VG_(message)(Vg_UserMsg,
sewardj570f8902002-11-03 11:44:36 +00001911 "valgrind: failed to connect to logging server `%s'.",
nethercotef8548672004-06-21 12:42:35 +00001912 VG_(clo_log_name) );
sewardj570f8902002-11-03 11:44:36 +00001913 VG_(message)(Vg_UserMsg,
1914 "Log messages will sent to stderr instead." );
1915 VG_(message)(Vg_UserMsg,
1916 "" );
1917 /* We don't change anything here. */
1918 } else {
nethercotef8548672004-06-21 12:42:35 +00001919 vg_assert(eventually_log_fd > 0);
1920 VG_(clo_log_fd) = eventually_log_fd;
sewardj570f8902002-11-03 11:44:36 +00001921 VG_(logging_to_filedes) = False;
1922 }
sewardj73cf3bc2002-11-03 03:20:15 +00001923 break;
1924 }
1925
sewardj4cf05692002-10-27 20:28:29 +00001926 }
1927
nethercotef8548672004-06-21 12:42:35 +00001928 /* Move log_fd into the safe range, so it doesn't conflict with any app fds */
thughesad1c9562004-06-26 11:27:52 +00001929 eventually_log_fd = VG_(fcntl)(VG_(clo_log_fd), VKI_F_DUPFD, VG_(fd_hard_limit));
nethercotef8548672004-06-21 12:42:35 +00001930 if (eventually_log_fd < 0)
jsgf855d93d2003-10-13 22:26:55 +00001931 VG_(message)(Vg_UserMsg, "valgrind: failed to move logfile fd into safe range");
1932 else {
nethercotef8548672004-06-21 12:42:35 +00001933 VG_(clo_log_fd) = eventually_log_fd;
1934 VG_(fcntl)(VG_(clo_log_fd), VKI_F_SETFD, VKI_FD_CLOEXEC);
jsgf855d93d2003-10-13 22:26:55 +00001935 }
1936
sewardj4cf05692002-10-27 20:28:29 +00001937 /* Ok, the logging sink is running now. Print a suitable preamble.
1938 If logging to file or a socket, write details of parent PID and
1939 command line args, to help people trying to interpret the
1940 results of a run which encompasses multiple processes. */
sewardjde4a1d02002-03-22 01:27:54 +00001941
sewardj83adf412002-05-01 01:25:45 +00001942 if (VG_(clo_verbosity > 0)) {
njnd04b7c62002-10-03 14:05:52 +00001943 /* Skin details */
1944 VG_(message)(Vg_UserMsg, "%s%s%s, %s for x86-linux.",
1945 VG_(details).name,
1946 NULL == VG_(details).version ? "" : "-",
1947 NULL == VG_(details).version
1948 ? (Char*)"" : VG_(details).version,
1949 VG_(details).description);
1950 VG_(message)(Vg_UserMsg, "%s", VG_(details).copyright_author);
sewardj3b2736a2002-03-24 12:18:35 +00001951
njnd04b7c62002-10-03 14:05:52 +00001952 /* Core details */
1953 VG_(message)(Vg_UserMsg,
njn3e884182003-04-15 13:03:23 +00001954 "Using valgrind-%s, a program supervision framework for x86-linux.",
sewardj4aa62ba2002-10-05 15:49:27 +00001955 VERSION);
sewardjde4a1d02002-03-22 01:27:54 +00001956 VG_(message)(Vg_UserMsg,
nethercotebb1c9912004-01-04 16:43:23 +00001957 "Copyright (C) 2000-2004, and GNU GPL'd, by Julian Seward.");
njnd04b7c62002-10-03 14:05:52 +00001958 }
1959
nethercotec1e395d2003-11-10 13:26:49 +00001960 if (VG_(clo_verbosity) > 0 && VG_(clo_log_to) != VgLogTo_Fd) {
sewardj4cf05692002-10-27 20:28:29 +00001961 VG_(message)(Vg_UserMsg, "");
1962 VG_(message)(Vg_UserMsg,
1963 "My PID = %d, parent PID = %d. Prog and args are:",
1964 VG_(getpid)(), VG_(getppid)() );
1965 for (i = 0; i < VG_(client_argc); i++)
1966 VG_(message)(Vg_UserMsg, " %s", VG_(client_argv)[i]);
1967 }
1968
sewardjde4a1d02002-03-22 01:27:54 +00001969 if (VG_(clo_verbosity) > 1) {
nethercotea70f7352004-04-18 12:08:46 +00001970 Int fd;
sewardj4cf05692002-10-27 20:28:29 +00001971 if (VG_(clo_log_to) != VgLogTo_Fd)
1972 VG_(message)(Vg_UserMsg, "");
fitzhardinge98abfc72003-12-16 02:05:15 +00001973 VG_(message)(Vg_UserMsg, "Valgrind library directory: %s", VG_(libdir));
njn86dc2bc2003-09-09 07:26:21 +00001974 VG_(message)(Vg_UserMsg, "Command line");
1975 for (i = 0; i < VG_(client_argc); i++)
1976 VG_(message)(Vg_UserMsg, " %s", VG_(client_argv)[i]);
1977
sewardjde4a1d02002-03-22 01:27:54 +00001978 VG_(message)(Vg_UserMsg, "Startup, with flags:");
nethercote71980f02004-01-24 18:18:54 +00001979 for (i = 1; i < VG_(vg_argc); i++) {
1980 VG_(message)(Vg_UserMsg, " %s", VG_(vg_argv)[i]);
sewardjde4a1d02002-03-22 01:27:54 +00001981 }
nethercotea70f7352004-04-18 12:08:46 +00001982
1983 VG_(message)(Vg_UserMsg, "Contents of /proc/version:");
1984 fd = VG_(open) ( "/proc/version", VKI_O_RDONLY, 0 );
1985 if (fd < 0) {
1986 VG_(message)(Vg_UserMsg, " can't open /proc/version");
1987 } else {
1988 #define BUF_LEN 256
1989 Char version_buf[BUF_LEN];
1990 Int n = VG_(read) ( fd, version_buf, BUF_LEN );
1991 vg_assert(n <= 256);
1992 if (n > 0) {
1993 version_buf[n-1] = '\0';
1994 VG_(message)(Vg_UserMsg, " %s", version_buf);
1995 } else {
1996 VG_(message)(Vg_UserMsg, " (empty?)");
1997 }
1998 VG_(close)(fd);
1999 #undef BUF_LEN
2000 }
sewardjde4a1d02002-03-22 01:27:54 +00002001 }
2002
fitzhardinge98abfc72003-12-16 02:05:15 +00002003 if (VG_(clo_n_suppressions) < VG_CLO_MAX_SFILES-1 &&
njn25e49d8e72002-09-23 09:36:25 +00002004 (VG_(needs).core_errors || VG_(needs).skin_errors)) {
fitzhardinge98abfc72003-12-16 02:05:15 +00002005 /* If there are no suppression files specified and the skin
2006 needs one, load the default */
2007 static const Char default_supp[] = "default.supp";
2008 Int len = VG_(strlen)(VG_(libdir)) + 1 + sizeof(default_supp);
2009 Char *buf = VG_(arena_malloc)(VG_AR_CORE, len);
2010 VG_(sprintf)(buf, "%s/%s", VG_(libdir), default_supp);
2011 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = buf;
2012 VG_(clo_n_suppressions)++;
sewardjde4a1d02002-03-22 01:27:54 +00002013 }
sewardj4cf05692002-10-27 20:28:29 +00002014
njn6a230532003-07-21 10:38:23 +00002015 if (VG_(clo_gen_suppressions) &&
2016 !VG_(needs).core_errors && !VG_(needs).skin_errors) {
nethercotef4928da2004-06-15 10:54:40 +00002017 VG_(message)(Vg_UserMsg,
2018 "Can't use --gen-suppressions=yes with this tool,");
2019 VG_(message)(Vg_UserMsg,
2020 "as it doesn't generate errors.");
2021 VG_(bad_option)("--gen-suppressions=yes");
njn6a230532003-07-21 10:38:23 +00002022 }
sewardjde4a1d02002-03-22 01:27:54 +00002023}
2024
sewardjde4a1d02002-03-22 01:27:54 +00002025
nethercote71980f02004-01-24 18:18:54 +00002026/*====================================================================*/
2027/*=== File descriptor setup ===*/
2028/*====================================================================*/
2029
2030static void setup_file_descriptors(void)
2031{
2032 struct vki_rlimit rl;
2033
2034 /* Get the current file descriptor limits. */
2035 if (VG_(getrlimit)(VKI_RLIMIT_NOFILE, &rl) < 0) {
2036 rl.rlim_cur = 1024;
2037 rl.rlim_max = 1024;
2038 }
2039
2040 /* Work out where to move the soft limit to. */
2041 if (rl.rlim_cur + VG_N_RESERVED_FDS <= rl.rlim_max) {
2042 rl.rlim_cur = rl.rlim_cur + VG_N_RESERVED_FDS;
2043 } else {
2044 rl.rlim_cur = rl.rlim_max;
2045 }
2046
2047 /* Reserve some file descriptors for our use. */
thughesad1c9562004-06-26 11:27:52 +00002048 VG_(fd_soft_limit) = rl.rlim_cur - VG_N_RESERVED_FDS;
2049 VG_(fd_hard_limit) = rl.rlim_cur - VG_N_RESERVED_FDS;
nethercote71980f02004-01-24 18:18:54 +00002050
2051 /* Update the soft limit. */
2052 VG_(setrlimit)(VKI_RLIMIT_NOFILE, &rl);
2053
2054 if (VG_(vgexecfd) != -1)
2055 VG_(vgexecfd) = VG_(safe_fd)( VG_(vgexecfd) );
2056 if (VG_(clexecfd) != -1)
2057 VG_(clexecfd) = VG_(safe_fd)( VG_(clexecfd) );
2058}
2059
2060
2061/*====================================================================*/
nethercote1d447092004-02-01 17:29:59 +00002062/*=== baseBlock: definition + setup ===*/
nethercote71980f02004-01-24 18:18:54 +00002063/*====================================================================*/
2064
2065/* The variables storing offsets. */
2066
2067#define INVALID_OFFSET (-1)
2068
2069Int VGOFF_(m_eax) = INVALID_OFFSET;
2070Int VGOFF_(m_ecx) = INVALID_OFFSET;
2071Int VGOFF_(m_edx) = INVALID_OFFSET;
2072Int VGOFF_(m_ebx) = INVALID_OFFSET;
2073Int VGOFF_(m_esp) = INVALID_OFFSET;
2074Int VGOFF_(m_ebp) = INVALID_OFFSET;
2075Int VGOFF_(m_esi) = INVALID_OFFSET;
2076Int VGOFF_(m_edi) = INVALID_OFFSET;
2077Int VGOFF_(m_eflags) = INVALID_OFFSET;
2078Int VGOFF_(m_dflag) = INVALID_OFFSET;
2079Int VGOFF_(m_ssestate) = INVALID_OFFSET;
2080Int VGOFF_(ldt) = INVALID_OFFSET;
2081Int VGOFF_(tls) = INVALID_OFFSET;
2082Int VGOFF_(m_cs) = INVALID_OFFSET;
2083Int VGOFF_(m_ss) = INVALID_OFFSET;
2084Int VGOFF_(m_ds) = INVALID_OFFSET;
2085Int VGOFF_(m_es) = INVALID_OFFSET;
2086Int VGOFF_(m_fs) = INVALID_OFFSET;
2087Int VGOFF_(m_gs) = INVALID_OFFSET;
2088Int VGOFF_(m_eip) = INVALID_OFFSET;
2089Int VGOFF_(spillslots) = INVALID_OFFSET;
2090Int VGOFF_(sh_eax) = INVALID_OFFSET;
2091Int VGOFF_(sh_ecx) = INVALID_OFFSET;
2092Int VGOFF_(sh_edx) = INVALID_OFFSET;
2093Int VGOFF_(sh_ebx) = INVALID_OFFSET;
2094Int VGOFF_(sh_esp) = INVALID_OFFSET;
2095Int VGOFF_(sh_ebp) = INVALID_OFFSET;
2096Int VGOFF_(sh_esi) = INVALID_OFFSET;
2097Int VGOFF_(sh_edi) = INVALID_OFFSET;
2098Int VGOFF_(sh_eflags) = INVALID_OFFSET;
2099
2100Int VGOFF_(helper_idiv_64_32) = INVALID_OFFSET;
2101Int VGOFF_(helper_div_64_32) = INVALID_OFFSET;
2102Int VGOFF_(helper_idiv_32_16) = INVALID_OFFSET;
2103Int VGOFF_(helper_div_32_16) = INVALID_OFFSET;
2104Int VGOFF_(helper_idiv_16_8) = INVALID_OFFSET;
2105Int VGOFF_(helper_div_16_8) = INVALID_OFFSET;
2106Int VGOFF_(helper_imul_32_64) = INVALID_OFFSET;
2107Int VGOFF_(helper_mul_32_64) = INVALID_OFFSET;
2108Int VGOFF_(helper_imul_16_32) = INVALID_OFFSET;
2109Int VGOFF_(helper_mul_16_32) = INVALID_OFFSET;
2110Int VGOFF_(helper_imul_8_16) = INVALID_OFFSET;
2111Int VGOFF_(helper_mul_8_16) = INVALID_OFFSET;
2112Int VGOFF_(helper_CLD) = INVALID_OFFSET;
2113Int VGOFF_(helper_STD) = INVALID_OFFSET;
2114Int VGOFF_(helper_get_dirflag) = INVALID_OFFSET;
2115Int VGOFF_(helper_CLC) = INVALID_OFFSET;
2116Int VGOFF_(helper_STC) = INVALID_OFFSET;
nethercote1018bdd2004-02-11 23:33:29 +00002117Int VGOFF_(helper_CMC) = INVALID_OFFSET;
nethercote71980f02004-01-24 18:18:54 +00002118Int VGOFF_(helper_shldl) = INVALID_OFFSET;
2119Int VGOFF_(helper_shldw) = INVALID_OFFSET;
2120Int VGOFF_(helper_shrdl) = INVALID_OFFSET;
2121Int VGOFF_(helper_shrdw) = INVALID_OFFSET;
2122Int VGOFF_(helper_IN) = INVALID_OFFSET;
2123Int VGOFF_(helper_OUT) = INVALID_OFFSET;
2124Int VGOFF_(helper_RDTSC) = INVALID_OFFSET;
2125Int VGOFF_(helper_CPUID) = INVALID_OFFSET;
2126Int VGOFF_(helper_BSWAP) = INVALID_OFFSET;
nethercote1018bdd2004-02-11 23:33:29 +00002127Int VGOFF_(helper_bsfw) = INVALID_OFFSET;
2128Int VGOFF_(helper_bsfl) = INVALID_OFFSET;
2129Int VGOFF_(helper_bsrw) = INVALID_OFFSET;
2130Int VGOFF_(helper_bsrl) = INVALID_OFFSET;
nethercote71980f02004-01-24 18:18:54 +00002131Int VGOFF_(helper_fstsw_AX) = INVALID_OFFSET;
2132Int VGOFF_(helper_SAHF) = INVALID_OFFSET;
2133Int VGOFF_(helper_LAHF) = INVALID_OFFSET;
2134Int VGOFF_(helper_DAS) = INVALID_OFFSET;
2135Int VGOFF_(helper_DAA) = INVALID_OFFSET;
nethercote1018bdd2004-02-11 23:33:29 +00002136Int VGOFF_(helper_AAS) = INVALID_OFFSET;
2137Int VGOFF_(helper_AAA) = INVALID_OFFSET;
2138Int VGOFF_(helper_AAD) = INVALID_OFFSET;
2139Int VGOFF_(helper_AAM) = INVALID_OFFSET;
nethercote71980f02004-01-24 18:18:54 +00002140Int VGOFF_(helper_cmpxchg8b) = INVALID_OFFSET;
2141Int VGOFF_(helper_undefined_instruction) = INVALID_OFFSET;
2142
2143/* MAX_NONCOMPACT_HELPERS can be increased easily. If MAX_COMPACT_HELPERS is
2144 * increased too much, they won't really be compact any more... */
2145#define MAX_COMPACT_HELPERS 8
2146#define MAX_NONCOMPACT_HELPERS 50
2147
2148UInt VG_(n_compact_helpers) = 0;
2149UInt VG_(n_noncompact_helpers) = 0;
2150
2151Addr VG_(compact_helper_addrs) [MAX_COMPACT_HELPERS];
2152Int VG_(compact_helper_offsets)[MAX_COMPACT_HELPERS];
2153Addr VG_(noncompact_helper_addrs) [MAX_NONCOMPACT_HELPERS];
2154Int VG_(noncompact_helper_offsets)[MAX_NONCOMPACT_HELPERS];
2155
2156/* This is the actual defn of baseblock. */
2157UInt VG_(baseBlock)[VG_BASEBLOCK_WORDS];
2158
nethercote71980f02004-01-24 18:18:54 +00002159/* Words. */
2160static Int baB_off = 0;
2161
2162
sewardjfa492d42002-12-08 18:20:01 +00002163UInt VG_(insertDflag)(UInt eflags, Int d)
2164{
2165 vg_assert(d == 1 || d == -1);
2166 eflags &= ~EFlagD;
2167
2168 if (d < 0)
2169 eflags |= EFlagD;
2170
2171 return eflags;
2172}
2173
2174Int VG_(extractDflag)(UInt eflags)
2175{
2176 Int ret;
2177
2178 if (eflags & EFlagD)
2179 ret = -1;
2180 else
2181 ret = 1;
2182
2183 return ret;
2184}
2185
nethercote71980f02004-01-24 18:18:54 +00002186/* Returns the offset, in words. */
2187static Int alloc_BaB ( Int words )
sewardjde4a1d02002-03-22 01:27:54 +00002188{
nethercote71980f02004-01-24 18:18:54 +00002189 Int off = baB_off;
2190 baB_off += words;
2191 if (baB_off >= VG_BASEBLOCK_WORDS)
2192 VG_(core_panic)( "alloc_BaB: baseBlock is too small");
sewardjde4a1d02002-03-22 01:27:54 +00002193
nethercote71980f02004-01-24 18:18:54 +00002194 return off;
sewardjde4a1d02002-03-22 01:27:54 +00002195}
2196
nethercote71980f02004-01-24 18:18:54 +00002197/* Align offset, in *bytes* */
2198static void align_BaB ( UInt align )
njn25e49d8e72002-09-23 09:36:25 +00002199{
nethercote71980f02004-01-24 18:18:54 +00002200 vg_assert(2 == align || 4 == align || 8 == align || 16 == align);
2201 baB_off += (align-1);
2202 baB_off &= ~(align-1);
njn25e49d8e72002-09-23 09:36:25 +00002203}
2204
nethercote71980f02004-01-24 18:18:54 +00002205/* Allocate 1 word in baseBlock and set it to the given value. */
2206static Int alloc_BaB_1_set ( Addr a )
njn25e49d8e72002-09-23 09:36:25 +00002207{
nethercote71980f02004-01-24 18:18:54 +00002208 Int off = alloc_BaB(1);
2209 VG_(baseBlock)[off] = (UInt)a;
2210 return off;
njn25e49d8e72002-09-23 09:36:25 +00002211}
2212
nethercote71980f02004-01-24 18:18:54 +00002213/* Registers a function in compact_helper_addrs; compact_helper_offsets is
2214 filled in later. */
2215void VG_(register_compact_helper)(Addr a)
sewardjde4a1d02002-03-22 01:27:54 +00002216{
nethercote71980f02004-01-24 18:18:54 +00002217 if (MAX_COMPACT_HELPERS <= VG_(n_compact_helpers)) {
2218 VG_(printf)("Can only register %d compact helpers\n",
2219 MAX_COMPACT_HELPERS);
2220 VG_(core_panic)("Too many compact helpers registered");
2221 }
2222 VG_(compact_helper_addrs)[VG_(n_compact_helpers)] = a;
2223 VG_(n_compact_helpers)++;
2224}
2225
2226/* Registers a function in noncompact_helper_addrs; noncompact_helper_offsets
2227 * is filled in later.
2228 */
2229void VG_(register_noncompact_helper)(Addr a)
2230{
2231 if (MAX_NONCOMPACT_HELPERS <= VG_(n_noncompact_helpers)) {
2232 VG_(printf)("Can only register %d non-compact helpers\n",
2233 MAX_NONCOMPACT_HELPERS);
2234 VG_(printf)("Try increasing MAX_NON_COMPACT_HELPERS\n");
2235 VG_(core_panic)("Too many non-compact helpers registered");
2236 }
2237 VG_(noncompact_helper_addrs)[VG_(n_noncompact_helpers)] = a;
2238 VG_(n_noncompact_helpers)++;
2239}
2240
2241/* Allocate offsets in baseBlock for the skin helpers */
2242static
2243void assign_helpers_in_baseBlock(UInt n, Int offsets[], Addr addrs[])
2244{
2245 UInt i;
2246 for (i = 0; i < n; i++)
2247 offsets[i] = alloc_BaB_1_set( addrs[i] );
2248}
2249
2250Bool VG_(need_to_handle_esp_assignment)(void)
2251{
2252 return ( VG_(defined_new_mem_stack_4)() ||
2253 VG_(defined_die_mem_stack_4)() ||
2254 VG_(defined_new_mem_stack_8)() ||
2255 VG_(defined_die_mem_stack_8)() ||
2256 VG_(defined_new_mem_stack_12)() ||
2257 VG_(defined_die_mem_stack_12)() ||
2258 VG_(defined_new_mem_stack_16)() ||
2259 VG_(defined_die_mem_stack_16)() ||
2260 VG_(defined_new_mem_stack_32)() ||
2261 VG_(defined_die_mem_stack_32)() ||
2262 VG_(defined_new_mem_stack)() ||
2263 VG_(defined_die_mem_stack)()
2264 );
2265}
2266
2267/* Here we assign actual offsets. It's important to get the most
2268 popular referents within 128 bytes of the start, so we can take
2269 advantage of short addressing modes relative to %ebp. Popularity
2270 of offsets was measured on 22 Feb 02 running a KDE application, and
2271 the slots rearranged accordingly, with a 1.5% reduction in total
2272 size of translations. */
2273static void init_baseBlock ( Addr client_eip, Addr esp_at_startup )
2274{
2275 /* Those with offsets under 128 are carefully chosen. */
2276
2277 /* WORD offsets in this column */
2278 /* 0 */ VGOFF_(m_eax) = alloc_BaB_1_set(0);
2279 /* 1 */ VGOFF_(m_ecx) = alloc_BaB_1_set(0);
2280 /* 2 */ VGOFF_(m_edx) = alloc_BaB_1_set(0);
2281 /* 3 */ VGOFF_(m_ebx) = alloc_BaB_1_set(0);
2282 /* 4 */ VGOFF_(m_esp) = alloc_BaB_1_set(esp_at_startup);
2283 /* 5 */ VGOFF_(m_ebp) = alloc_BaB_1_set(0);
2284 /* 6 */ VGOFF_(m_esi) = alloc_BaB_1_set(0);
2285 /* 7 */ VGOFF_(m_edi) = alloc_BaB_1_set(0);
2286 /* 8 */ VGOFF_(m_eflags) = alloc_BaB_1_set(0);
2287
2288 if (VG_(needs).shadow_regs) {
2289 /* 9 */ VGOFF_(sh_eax) = alloc_BaB_1_set(0);
2290 /* 10 */ VGOFF_(sh_ecx) = alloc_BaB_1_set(0);
2291 /* 11 */ VGOFF_(sh_edx) = alloc_BaB_1_set(0);
2292 /* 12 */ VGOFF_(sh_ebx) = alloc_BaB_1_set(0);
2293 /* 13 */ VGOFF_(sh_esp) = alloc_BaB_1_set(0);
2294 /* 14 */ VGOFF_(sh_ebp) = alloc_BaB_1_set(0);
2295 /* 15 */ VGOFF_(sh_esi) = alloc_BaB_1_set(0);
2296 /* 16 */ VGOFF_(sh_edi) = alloc_BaB_1_set(0);
2297 /* 17 */ VGOFF_(sh_eflags) = alloc_BaB_1_set(0);
2298 VG_TRACK( post_regs_write_init );
2299 }
2300
2301 /* 9,10,11 or 18,19,20... depends on number whether shadow regs are used
2302 * and on compact helpers registered */
2303
2304 /* Make these most-frequently-called specialised ones compact, if they
2305 are used. */
2306 if (VG_(defined_new_mem_stack_4)())
2307 VG_(register_compact_helper)( (Addr) VG_(tool_interface).track_new_mem_stack_4);
2308
2309 if (VG_(defined_die_mem_stack_4)())
2310 VG_(register_compact_helper)( (Addr) VG_(tool_interface).track_die_mem_stack_4);
2311
2312 /* (9 or 18) + n_compact_helpers */
2313 /* Allocate slots for compact helpers */
2314 assign_helpers_in_baseBlock(VG_(n_compact_helpers),
2315 VG_(compact_helper_offsets),
2316 VG_(compact_helper_addrs));
2317
2318 /* (9/10 or 18/19) + n_compact_helpers */
2319 VGOFF_(m_eip) = alloc_BaB_1_set(client_eip);
2320
2321 /* There are currently 24 spill slots */
2322 /* (11+/20+ .. 32+/43+) + n_compact_helpers. This can overlap the magic
2323 * boundary at >= 32 words, but most spills are to low numbered spill
2324 * slots, so the ones above the boundary don't see much action. */
2325 VGOFF_(spillslots) = alloc_BaB(VG_MAX_SPILLSLOTS);
2326
2327 /* I gave up counting at this point. Since they're above the
2328 short-amode-boundary, there's no point. */
2329
2330 VGOFF_(m_dflag) = alloc_BaB_1_set(1); // 1 == forward D-flag
2331
2332 /* The FPU/SSE state. This _must_ be 16-byte aligned. Initial
2333 state doesn't matter much, as long as it's not totally borked. */
2334 align_BaB(16);
2335 VGOFF_(m_ssestate) = alloc_BaB(VG_SIZE_OF_SSESTATE_W);
2336 vg_assert(
2337 0 == ( ((UInt)(& VG_(baseBlock)[VGOFF_(m_ssestate)])) % 16 )
sewardj22854b92002-11-30 14:00:47 +00002338 );
2339
fitzhardingec2dbbac2004-01-23 23:09:01 +00002340 /* I assume that if we have SSE2 we also have SSE */
2341 VG_(have_ssestate) =
2342 VG_(cpu_has_feature)(VG_X86_FEAT_FXSR) &&
2343 VG_(cpu_has_feature)(VG_X86_FEAT_SSE);
2344
fitzhardinge98abfc72003-12-16 02:05:15 +00002345 /* set up an initial FPU state (doesn't really matter what it is,
2346 so long as it's somewhat valid) */
2347 if (!VG_(have_ssestate))
nethercote71980f02004-01-24 18:18:54 +00002348 asm volatile("fwait; fnsave %0; fwait; frstor %0; fwait"
2349 :
2350 : "m" (VG_(baseBlock)[VGOFF_(m_ssestate)])
2351 : "cc", "memory");
fitzhardinge98abfc72003-12-16 02:05:15 +00002352 else
nethercote71980f02004-01-24 18:18:54 +00002353 asm volatile("fwait; fxsave %0; fwait; andl $0xffbf, %1;"
2354 "fxrstor %0; fwait"
2355 :
2356 : "m" (VG_(baseBlock)[VGOFF_(m_ssestate)]),
2357 "m" (VG_(baseBlock)[VGOFF_(m_ssestate)+(24/4)])
2358 : "cc", "memory");
fitzhardinge98abfc72003-12-16 02:05:15 +00002359
njn0c7a5b52003-04-30 09:00:33 +00002360 if (0) {
2361 if (VG_(have_ssestate))
2362 VG_(printf)("Looks like a SSE-capable CPU\n");
2363 else
2364 VG_(printf)("Looks like a MMX-only CPU\n");
2365 }
sewardjb91ae7f2003-04-29 23:50:00 +00002366
nethercote71980f02004-01-24 18:18:54 +00002367 /* LDT pointer: pretend the root thread has an empty LDT to start with. */
2368 VGOFF_(ldt) = alloc_BaB_1_set((UInt)NULL);
jsgf855d93d2003-10-13 22:26:55 +00002369
nethercote71980f02004-01-24 18:18:54 +00002370 /* TLS pointer: pretend the root thread has no TLS array for now. */
2371 VGOFF_(tls) = alloc_BaB_1_set((UInt)NULL);
fitzhardingef0046f22003-12-18 02:39:22 +00002372
nethercote71980f02004-01-24 18:18:54 +00002373 /* segment registers */
2374 VGOFF_(m_cs) = alloc_BaB_1_set(0);
2375 VGOFF_(m_ss) = alloc_BaB_1_set(0);
2376 VGOFF_(m_ds) = alloc_BaB_1_set(0);
2377 VGOFF_(m_es) = alloc_BaB_1_set(0);
2378 VGOFF_(m_fs) = alloc_BaB_1_set(0);
2379 VGOFF_(m_gs) = alloc_BaB_1_set(0);
fitzhardingef0046f22003-12-18 02:39:22 +00002380
thughes35cec982004-04-21 15:16:43 +00002381 /* initialise %cs, %ds and %ss to point at the operating systems
2382 default code, data and stack segments */
2383 asm volatile("movw %%cs, %0"
2384 :
2385 : "m" (VG_(baseBlock)[VGOFF_(m_cs)]));
2386 asm volatile("movw %%ds, %0"
2387 :
2388 : "m" (VG_(baseBlock)[VGOFF_(m_ds)]));
2389 asm volatile("movw %%ss, %0"
2390 :
2391 : "m" (VG_(baseBlock)[VGOFF_(m_ss)]));
2392
nethercote71980f02004-01-24 18:18:54 +00002393 VG_(register_noncompact_helper)( (Addr) & VG_(do_useseg) );
fitzhardingef0046f22003-12-18 02:39:22 +00002394
nethercote71980f02004-01-24 18:18:54 +00002395#define REG(kind, size) \
2396 if (VG_(defined_##kind##_mem_stack##size)()) \
2397 VG_(register_noncompact_helper)( \
2398 (Addr) VG_(tool_interface).track_##kind##_mem_stack##size );
2399 REG(new, _8);
2400 REG(new, _12);
2401 REG(new, _16);
2402 REG(new, _32);
2403 REG(new, );
2404 REG(die, _8);
2405 REG(die, _12);
2406 REG(die, _16);
2407 REG(die, _32);
2408 REG(die, );
2409#undef REG
fitzhardingef0046f22003-12-18 02:39:22 +00002410
nethercote71980f02004-01-24 18:18:54 +00002411 if (VG_(need_to_handle_esp_assignment)())
2412 VG_(register_noncompact_helper)((Addr) VG_(unknown_esp_update));
fitzhardingeb791a192003-12-18 07:22:44 +00002413
nethercote71980f02004-01-24 18:18:54 +00002414# define HELPER(name) \
2415 VGOFF_(helper_##name) = alloc_BaB_1_set( (Addr) & VG_(helper_##name))
njn3e884182003-04-15 13:03:23 +00002416
nethercote71980f02004-01-24 18:18:54 +00002417 /* Helper functions. */
2418 HELPER(idiv_64_32); HELPER(div_64_32);
2419 HELPER(idiv_32_16); HELPER(div_32_16);
2420 HELPER(idiv_16_8); HELPER(div_16_8);
fitzhardinge98abfc72003-12-16 02:05:15 +00002421
nethercote71980f02004-01-24 18:18:54 +00002422 HELPER(imul_32_64); HELPER(mul_32_64);
2423 HELPER(imul_16_32); HELPER(mul_16_32);
2424 HELPER(imul_8_16); HELPER(mul_8_16);
njn25e49d8e72002-09-23 09:36:25 +00002425
nethercote71980f02004-01-24 18:18:54 +00002426 HELPER(CLD); HELPER(STD);
2427 HELPER(get_dirflag);
sewardjde4a1d02002-03-22 01:27:54 +00002428
nethercote71980f02004-01-24 18:18:54 +00002429 HELPER(CLC); HELPER(STC);
nethercote1018bdd2004-02-11 23:33:29 +00002430 HELPER(CMC);
jsgf855d93d2003-10-13 22:26:55 +00002431
nethercote71980f02004-01-24 18:18:54 +00002432 HELPER(shldl); HELPER(shldw);
2433 HELPER(shrdl); HELPER(shrdw);
njncc7bb472002-10-14 09:25:19 +00002434
nethercote71980f02004-01-24 18:18:54 +00002435 HELPER(RDTSC); HELPER(CPUID);
njncc7bb472002-10-14 09:25:19 +00002436
nethercote1018bdd2004-02-11 23:33:29 +00002437 HELPER(bsfw); HELPER(bsfl);
2438 HELPER(bsrw); HELPER(bsrl);
rjwalshf5f536f2003-11-17 17:45:00 +00002439
nethercote71980f02004-01-24 18:18:54 +00002440 HELPER(fstsw_AX);
2441 HELPER(SAHF); HELPER(LAHF);
2442 HELPER(DAS); HELPER(DAA);
nethercote1018bdd2004-02-11 23:33:29 +00002443 HELPER(AAS); HELPER(AAA);
2444 HELPER(AAD); HELPER(AAM);
nethercote71980f02004-01-24 18:18:54 +00002445 HELPER(IN); HELPER(OUT);
2446 HELPER(cmpxchg8b);
sewardj018f7622002-05-15 21:13:39 +00002447
nethercote71980f02004-01-24 18:18:54 +00002448 HELPER(undefined_instruction);
jsgf855d93d2003-10-13 22:26:55 +00002449
nethercote71980f02004-01-24 18:18:54 +00002450# undef HELPER
sewardjde4a1d02002-03-22 01:27:54 +00002451
nethercote71980f02004-01-24 18:18:54 +00002452 /* Allocate slots for noncompact helpers */
2453 assign_helpers_in_baseBlock(VG_(n_noncompact_helpers),
2454 VG_(noncompact_helper_offsets),
2455 VG_(noncompact_helper_addrs));
2456}
sewardjde4a1d02002-03-22 01:27:54 +00002457
sewardj5f07b662002-04-23 16:52:51 +00002458
nethercote71980f02004-01-24 18:18:54 +00002459/*====================================================================*/
2460/*=== Setup pointercheck ===*/
2461/*====================================================================*/
njn25e49d8e72002-09-23 09:36:25 +00002462
nethercote71980f02004-01-24 18:18:54 +00002463static void setup_pointercheck(void)
2464{
2465 int ret;
sewardj2e93c502002-04-12 11:12:52 +00002466
fitzhardinge98abfc72003-12-16 02:05:15 +00002467 if (VG_(clo_pointercheck)) {
nethercote71980f02004-01-24 18:18:54 +00002468 vki_modify_ldt_t ldt = {
2469 VG_POINTERCHECK_SEGIDX, // entry_number
2470 VG_(client_base), // base_addr
2471 (VG_(client_end)-VG_(client_base)) / VKI_BYTES_PER_PAGE, // limit
2472 1, // seg_32bit
2473 0, // contents: data, RW, non-expanding
2474 0, // ! read_exec_only
2475 1, // limit_in_pages
2476 0, // ! seg not present
2477 1, // useable
fitzhardinge98abfc72003-12-16 02:05:15 +00002478 };
nethercote71980f02004-01-24 18:18:54 +00002479 ret = VG_(do_syscall)(__NR_modify_ldt, 1, &ldt, sizeof(ldt));
fitzhardinge98abfc72003-12-16 02:05:15 +00002480 if (ret < 0) {
2481 VG_(message)(Vg_UserMsg,
2482 "Warning: ignoring --pointercheck=yes, "
2483 "because modify_ldt failed (errno=%d)", -ret);
2484 VG_(clo_pointercheck) = False;
2485 }
2486 }
sewardjde4a1d02002-03-22 01:27:54 +00002487}
2488
nethercote71980f02004-01-24 18:18:54 +00002489/*====================================================================*/
2490/*=== Initialise program data/text, etc. ===*/
2491/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +00002492
nethercote71980f02004-01-24 18:18:54 +00002493static void build_valgrind_map_callback
2494 ( Addr start, UInt size, Char rr, Char ww, Char xx,
2495 UInt dev, UInt ino, ULong foffset, const UChar* filename )
sewardjde4a1d02002-03-22 01:27:54 +00002496{
nethercote71980f02004-01-24 18:18:54 +00002497 UInt prot = 0;
2498 UInt flags = SF_MMAP|SF_NOSYMS;
2499 Bool is_stack_segment;
2500
2501 is_stack_segment =
2502 (start == VG_(clstk_base) && (start+size) == VG_(clstk_end));
2503
2504 /* Only record valgrind mappings for now, without loading any
2505 symbols. This is so we know where the free space is before we
2506 start allocating more memory (note: heap is OK, it's just mmap
2507 which is the problem here). */
2508 if (start >= VG_(valgrind_base) && (start+size) <= VG_(valgrind_end)) {
2509 flags |= SF_VALGRIND;
2510 VG_(map_file_segment)(start, size, prot, flags, dev, ino, foffset, filename);
2511 }
sewardjde4a1d02002-03-22 01:27:54 +00002512}
2513
nethercote71980f02004-01-24 18:18:54 +00002514// Global var used to pass local data to callback
2515Addr esp_at_startup___global_arg = 0;
sewardjde4a1d02002-03-22 01:27:54 +00002516
nethercote71980f02004-01-24 18:18:54 +00002517static void build_segment_map_callback
2518 ( Addr start, UInt size, Char rr, Char ww, Char xx,
2519 UInt dev, UInt ino, ULong foffset, const UChar* filename )
sewardj45b672d2003-07-25 19:58:11 +00002520{
nethercote71980f02004-01-24 18:18:54 +00002521 UInt prot = 0;
2522 UInt flags;
2523 Bool is_stack_segment;
2524 Addr r_esp;
sewardj45b672d2003-07-25 19:58:11 +00002525
nethercote71980f02004-01-24 18:18:54 +00002526 is_stack_segment
2527 = (start == VG_(clstk_base) && (start+size) == VG_(clstk_end));
fitzhardinge98abfc72003-12-16 02:05:15 +00002528
nethercote71980f02004-01-24 18:18:54 +00002529 if (rr == 'r') prot |= VKI_PROT_READ;
2530 if (ww == 'w') prot |= VKI_PROT_WRITE;
2531 if (xx == 'x') prot |= VKI_PROT_EXEC;
fitzhardinge98abfc72003-12-16 02:05:15 +00002532
nethercote71980f02004-01-24 18:18:54 +00002533 if (is_stack_segment)
2534 flags = SF_STACK | SF_GROWDOWN;
2535 else
2536 flags = SF_EXEC|SF_MMAP;
fitzhardinge98abfc72003-12-16 02:05:15 +00002537
nethercote71980f02004-01-24 18:18:54 +00002538 if (filename != NULL)
2539 flags |= SF_FILE;
fitzhardinge98abfc72003-12-16 02:05:15 +00002540
nethercote71980f02004-01-24 18:18:54 +00002541 if (start >= VG_(valgrind_base) && (start+size) <= VG_(valgrind_end))
2542 flags |= SF_VALGRIND;
fitzhardinge98abfc72003-12-16 02:05:15 +00002543
nethercote71980f02004-01-24 18:18:54 +00002544 VG_(map_file_segment)(start, size, prot, flags, dev, ino, foffset, filename);
fitzhardinge98abfc72003-12-16 02:05:15 +00002545
nethercote71980f02004-01-24 18:18:54 +00002546 if (VG_(is_client_addr)(start) && VG_(is_client_addr)(start+size-1))
2547 VG_TRACK( new_mem_startup, start, size, rr=='r', ww=='w', xx=='x' );
sewardj3e1eb1f2002-05-18 13:14:17 +00002548
nethercote71980f02004-01-24 18:18:54 +00002549 /* If this is the stack segment mark all below %esp as noaccess. */
2550 r_esp = esp_at_startup___global_arg;
2551 vg_assert(0 != r_esp);
2552 if (is_stack_segment) {
2553 if (0)
2554 VG_(message)(Vg_DebugMsg, "invalidating stack area: %x .. %x",
2555 start,r_esp);
2556 VG_TRACK( die_mem_stack, start, r_esp-start );
sewardjde4a1d02002-03-22 01:27:54 +00002557 }
sewardjde4a1d02002-03-22 01:27:54 +00002558}
2559
2560
nethercote71980f02004-01-24 18:18:54 +00002561/*====================================================================*/
2562/*=== Sanity check machinery (permanently engaged) ===*/
2563/*====================================================================*/
njn25e49d8e72002-09-23 09:36:25 +00002564
2565/* A fast sanity check -- suitable for calling circa once per
2566 millisecond. */
2567
2568void VG_(do_sanity_checks) ( Bool force_expensive )
2569{
njn37cea302002-09-30 11:24:00 +00002570 VGP_PUSHCC(VgpCoreCheapSanity);
2571
nethercote27fec902004-06-16 21:26:32 +00002572 if (VG_(clo_sanity_level) < 1) return;
njn25e49d8e72002-09-23 09:36:25 +00002573
2574 /* --- First do all the tests that we can do quickly. ---*/
2575
2576 VG_(sanity_fast_count)++;
2577
njn25e49d8e72002-09-23 09:36:25 +00002578 /* Check stuff pertaining to the memory check system. */
2579
2580 /* Check that nobody has spuriously claimed that the first or
2581 last 16 pages of memory have become accessible [...] */
njn37cea302002-09-30 11:24:00 +00002582 if (VG_(needs).sanity_checks) {
2583 VGP_PUSHCC(VgpSkinCheapSanity);
njn25e49d8e72002-09-23 09:36:25 +00002584 vg_assert(SK_(cheap_sanity_check)());
njn37cea302002-09-30 11:24:00 +00002585 VGP_POPCC(VgpSkinCheapSanity);
2586 }
njn25e49d8e72002-09-23 09:36:25 +00002587
2588 /* --- Now some more expensive checks. ---*/
2589
2590 /* Once every 25 times, check some more expensive stuff. */
2591 if ( force_expensive
nethercote27fec902004-06-16 21:26:32 +00002592 || VG_(clo_sanity_level) > 1
2593 || (VG_(clo_sanity_level) == 1 && (VG_(sanity_fast_count) % 25) == 0)) {
njn25e49d8e72002-09-23 09:36:25 +00002594
njn37cea302002-09-30 11:24:00 +00002595 VGP_PUSHCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002596 VG_(sanity_slow_count)++;
2597
jsgf855d93d2003-10-13 22:26:55 +00002598 VG_(proxy_sanity)();
2599
njn25e49d8e72002-09-23 09:36:25 +00002600# if 0
2601 { void zzzmemscan(void); zzzmemscan(); }
2602# endif
2603
2604 if ((VG_(sanity_fast_count) % 250) == 0)
2605 VG_(sanity_check_tc_tt)();
2606
2607 if (VG_(needs).sanity_checks) {
njn37cea302002-09-30 11:24:00 +00002608 VGP_PUSHCC(VgpSkinExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002609 vg_assert(SK_(expensive_sanity_check)());
njn37cea302002-09-30 11:24:00 +00002610 VGP_POPCC(VgpSkinExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002611 }
2612 /*
2613 if ((VG_(sanity_fast_count) % 500) == 0) VG_(mallocSanityCheckAll)();
2614 */
njn37cea302002-09-30 11:24:00 +00002615 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002616 }
2617
nethercote27fec902004-06-16 21:26:32 +00002618 if (VG_(clo_sanity_level) > 1) {
njn37cea302002-09-30 11:24:00 +00002619 VGP_PUSHCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002620 /* Check sanity of the low-level memory manager. Note that bugs
2621 in the client's code can cause this to fail, so we don't do
2622 this check unless specially asked for. And because it's
2623 potentially very expensive. */
2624 VG_(mallocSanityCheckAll)();
njn37cea302002-09-30 11:24:00 +00002625 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002626 }
njn37cea302002-09-30 11:24:00 +00002627 VGP_POPCC(VgpCoreCheapSanity);
njn25e49d8e72002-09-23 09:36:25 +00002628}
nethercote71980f02004-01-24 18:18:54 +00002629
2630
2631/*====================================================================*/
2632/*=== main() ===*/
2633/*====================================================================*/
2634
nethercotec314eba2004-07-15 12:59:41 +00002635/*
2636 This code decides on the layout of the client and Valgrind address
2637 spaces, loads valgrind.so and the skin.so into the valgrind part,
2638 loads the client executable (and the dynamic linker, if necessary)
2639 into the client part, and calls into Valgrind proper.
2640
2641 The code is careful not to allow spurious mappings to appear in the
2642 wrong parts of the address space. In particular, to make sure
2643 dlopen puts things in the right place, it will pad out the forbidden
2644 chunks of address space so that dlopen is forced to put things where
2645 we want them.
2646
2647 The memory map it creates is:
2648
2649 CLIENT_BASE +-------------------------+
2650 | client address space |
2651 : :
2652 : :
2653 | client stack |
2654 client_end +-------------------------+
2655 | redzone |
2656 shadow_base +-------------------------+
2657 | |
2658 : shadow memory for skins :
2659 | (may be 0 sized) |
2660 shadow_end +-------------------------+
2661 : gap (may be 0 sized) :
2662 valgrind_base +-------------------------+
2663 | kickstart executable |
2664 | valgrind heap vvvvvvvvv| (barely used)
2665 - -
2666 | valgrind .so files |
2667 | and mappings |
2668 - -
2669 | valgrind stack ^^^^^^^^^|
2670 valgrind_end +-------------------------+
2671 : kernel :
2672
2673 Nb: Before we can do general allocations with VG_(arena_malloc)() and
2674 VG_(mmap)(), we need to build the segment skip-list, so we know where
2675 we can put things. However, building that structure requires
2676 allocating memory. So we need to a bootstrapping process. It's done
2677 by making VG_(arena_malloc)() have a special static superblock that's
2678 used for the first 1MB's worth of allocations. This is enough to
2679 build the segment skip-list.
2680*/
2681
thughes4ad52d02004-06-27 17:37:21 +00002682static int prmap(void *start, void *end, const char *perm, off_t off,
2683 int maj, int min, int ino) {
2684 printf("mapping %10p-%10p %s %02x:%02x %d\n",
2685 start, end, perm, maj, min, ino);
2686 return True;
2687}
2688
nethercote71980f02004-01-24 18:18:54 +00002689int main(int argc, char **argv)
2690{
2691 char **cl_argv;
2692 const char *tool = NULL;
2693 const char *exec = NULL;
2694 char *preload; /* tool-specific LD_PRELOAD .so */
2695 char **env;
nethercote6c999f22004-01-31 22:55:15 +00002696 Int need_help = 0; // 0 = no, 1 = --help, 2 = --help-debug
nethercote71980f02004-01-24 18:18:54 +00002697 struct exeinfo info;
2698 ToolInfo *toolinfo = NULL;
2699 void *tool_dlhandle;
2700 Addr client_eip;
2701 Addr esp_at_startup; /* client's %esp at the point we gained control. */
2702 UInt * client_auxv;
2703 VgSchedReturnCode src;
nethercote47dd12c2004-06-22 14:18:42 +00002704 Int exitcode = 0;
fitzhardingeb50068f2004-02-24 23:42:55 +00002705 vki_rlimit zero = { 0, 0 };
nethercote71980f02004-01-24 18:18:54 +00002706
2707 //============================================================
2708 // Nb: startup is complex. Prerequisites are shown at every step.
2709 //
2710 // *** Be very careful when messing with the order ***
2711 //============================================================
2712
nethercotef4928da2004-06-15 10:54:40 +00002713 //============================================================
2714 // Command line argument handling order:
2715 // * If --help/--help-debug are present, show usage message
2716 // (if --tool is also present, that includes the tool-specific usage)
2717 // * Then, if --tool is missing, abort with error msg
2718 // * Then, if client is missing, abort with error msg
2719 // * Then, if any cmdline args are bad, abort with error msg
2720 //============================================================
2721
fitzhardingeb50068f2004-02-24 23:42:55 +00002722 // Get the current process datasize rlimit, and set it to zero.
2723 // This prevents any internal uses of brk() from having any effect.
2724 // We remember the old value so we can restore it on exec, so that
2725 // child processes will have a reasonable brk value.
2726 VG_(getrlimit)(VKI_RLIMIT_DATA, &VG_(client_rlimit_data));
2727 zero.rlim_max = VG_(client_rlimit_data).rlim_max;
2728 VG_(setrlimit)(VKI_RLIMIT_DATA, &zero);
2729
nethercote71980f02004-01-24 18:18:54 +00002730 //--------------------------------------------------------------
2731 // Check we were launched by stage1
nethercotec314eba2004-07-15 12:59:41 +00002732 // p: n/a
nethercote71980f02004-01-24 18:18:54 +00002733 //--------------------------------------------------------------
2734 scan_auxv();
2735
2736 if (0) {
nethercote71980f02004-01-24 18:18:54 +00002737 printf("========== main() ==========\n");
2738 foreach_map(prmap);
2739 }
2740
2741 //--------------------------------------------------------------
2742 // Look for alternative libdir
2743 // p: n/a
2744 //--------------------------------------------------------------
2745 { char *cp = getenv(VALGRINDLIB);
2746 if (cp != NULL)
2747 VG_(libdir) = cp;
2748 }
2749
2750 //--------------------------------------------------------------
2751 // Begin working out address space layout
2752 // p: n/a
2753 //--------------------------------------------------------------
2754 layout_client_space( (Addr) & argc );
2755
2756 //--------------------------------------------------------------
2757 // Get valgrind args + client args (inc. from VALGRIND_OPTS/.valgrindrc).
2758 // Pre-process the command line.
2759 // p: n/a
2760 //--------------------------------------------------------------
2761 get_command_line(argc, argv, &VG_(vg_argc), &VG_(vg_argv), &cl_argv);
2762 pre_process_cmd_line_options(&need_help, &tool, &exec);
2763
2764 //==============================================================
2765 // Nb: once a tool is specified, the tool.so must be loaded even if
2766 // they specified --help or didn't specify a client program.
2767 //==============================================================
2768
2769 //--------------------------------------------------------------
2770 // With client padded out, map in tool
2771 // p: layout_client_space() [for padding]
2772 // p: set-libdir [for VG_(libdir)]
2773 // p: pre_process_cmd_line_options() [for 'tool']
2774 //--------------------------------------------------------------
2775 load_tool(tool, &tool_dlhandle, &toolinfo, &preload);
2776
2777 //==============================================================
2778 // Can use VG_(malloc)() and VG_(arena_malloc)() only after load_tool()
nethercotec314eba2004-07-15 12:59:41 +00002779 // -- redzone size is now set. This is checked by vg_malloc2.c.
nethercote71980f02004-01-24 18:18:54 +00002780 //==============================================================
2781
2782 //--------------------------------------------------------------
2783 // Finalise address space layout
nethercotec314eba2004-07-15 12:59:41 +00002784 // p: layout_client_space(), load_tool() [for 'toolinfo']
nethercote71980f02004-01-24 18:18:54 +00002785 //--------------------------------------------------------------
2786 layout_remaining_space( toolinfo->shadow_ratio );
2787
2788 //--------------------------------------------------------------
2789 // Load client executable, finding in $PATH if necessary
2790 // p: layout_client_space() [so there's space]
2791 // p: pre_process_cmd_line_options() [for 'exec', 'need_help']
2792 // p: layout_remaining_space [so there's space]
2793 //--------------------------------------------------------------
nethercotef4928da2004-06-15 10:54:40 +00002794 load_client(cl_argv, exec, need_help, &info, &client_eip);
nethercote71980f02004-01-24 18:18:54 +00002795
2796 //--------------------------------------------------------------
2797 // Everything in place, unpad us
2798 // p: layout_remaining_space() [everything must be mapped in before now]
2799 // p: load_client() [ditto]
2800 //--------------------------------------------------------------
2801 as_unpad((void *)VG_(shadow_end), (void *)~0);
2802 as_closepadfile(); /* no more padding */
2803
2804 //--------------------------------------------------------------
2805 // Set up client's environment
2806 // p: set-libdir [for VG_(libdir)]
2807 // p: load_tool() [for 'preload']
2808 //--------------------------------------------------------------
2809 env = fix_environment(environ, preload);
2810
2811 //--------------------------------------------------------------
nethercote5ee67ca2004-06-22 14:00:09 +00002812 // Setup client stack, eip, and VG_(client_arg[cv])
nethercote71980f02004-01-24 18:18:54 +00002813 // p: load_client() [for 'info']
2814 // p: fix_environment() [for 'env']
2815 //--------------------------------------------------------------
2816 esp_at_startup = setup_client_stack(cl_argv, env, &info, &client_auxv);
2817
2818 if (0)
2819 printf("entry=%x client esp=%x vg_argc=%d brkbase=%x\n",
2820 client_eip, esp_at_startup, VG_(vg_argc), VG_(brk_base));
2821
2822 //==============================================================
2823 // Finished setting up operating environment. Now initialise
2824 // Valgrind. (This is where the old VG_(main)() started.)
2825 //==============================================================
2826
2827 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002828 // atfork
2829 // p: n/a
2830 //--------------------------------------------------------------
2831 VG_(atfork)(NULL, NULL, newpid);
2832 newpid(VG_INVALID_THREADID);
2833
2834 //--------------------------------------------------------------
2835 // setup file descriptors
2836 // p: n/a
2837 //--------------------------------------------------------------
2838 setup_file_descriptors();
2839
2840 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002841 // Read /proc/self/maps into a buffer
2842 // p: all memory layout, environment setup [so memory maps are right]
2843 //--------------------------------------------------------------
2844 VG_(read_procselfmaps)();
2845
2846 //--------------------------------------------------------------
2847 // Build segment map (Valgrind segments only)
2848 // p: read proc/self/maps
2849 // p: sk_pre_clo_init() [to setup new_mem_startup tracker]
2850 //--------------------------------------------------------------
2851 VG_(parse_procselfmaps) ( build_valgrind_map_callback );
2852
2853 //==============================================================
2854 // Can use VG_(arena_malloc)() with non-CORE arena after segments set up
2855 //==============================================================
2856
2857 //--------------------------------------------------------------
2858 // Init tool: pre_clo_init, process cmd line, post_clo_init
2859 // p: setup_client_stack() [for 'VG_(client_arg[cv]']
2860 // p: load_tool() [for 'tool']
2861 // p: setup_file_descriptors() [for 'VG_(fd_xxx_limit)']
2862 // p: parse_procselfmaps [so VG segments are setup so tool can
2863 // call VG_(malloc)]
nethercote71980f02004-01-24 18:18:54 +00002864 //--------------------------------------------------------------
2865 (*toolinfo->sk_pre_clo_init)();
2866 VG_(tool_init_dlsym)(tool_dlhandle);
2867 VG_(sanity_check_needs)();
2868
nethercotef4928da2004-06-15 10:54:40 +00002869 // If --tool and --help/--help-debug was given, now give the core+tool
2870 // help message
nethercotef4928da2004-06-15 10:54:40 +00002871 if (need_help) {
2872 usage(/*--help-debug?*/2 == need_help);
2873 }
nethercotec314eba2004-07-15 12:59:41 +00002874 process_cmd_line_options(client_auxv, tool);
2875
2876 SK_(post_clo_init)();
nethercotef4928da2004-06-15 10:54:40 +00002877
2878 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002879 // Build segment map (all segments)
2880 // p: setup_client_stack() [for 'esp_at_startup']
2881 // p: init tool [for 'new_mem_startup']
nethercote71980f02004-01-24 18:18:54 +00002882 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002883 esp_at_startup___global_arg = esp_at_startup;
2884 VG_(parse_procselfmaps) ( build_segment_map_callback ); /* everything */
2885 esp_at_startup___global_arg = 0;
2886
2887 //--------------------------------------------------------------
2888 // Initialize our trampoline page (which is also sysinfo stuff)
2889 // p: setup_client_stack() [for 'esp_at_startup']
2890 //--------------------------------------------------------------
2891 VG_(memcpy)( (void *)VG_(client_trampoline_code),
2892 &VG_(trampoline_code_start), VG_(trampoline_code_length) );
2893 VG_(mprotect)( (void *)VG_(client_trampoline_code),
2894 VG_(trampoline_code_length), VKI_PROT_READ|VKI_PROT_EXEC );
2895
2896 //==============================================================
2897 // Can use VG_(map)() after segments set up
2898 //==============================================================
nethercote71980f02004-01-24 18:18:54 +00002899
2900 //--------------------------------------------------------------
2901 // Allow GDB attach
2902 // p: process_cmd_line_options() [for VG_(clo_wait_for_gdb)]
2903 //--------------------------------------------------------------
2904 /* Hook to delay things long enough so we can get the pid and
2905 attach GDB in another shell. */
2906 if (VG_(clo_wait_for_gdb)) {
2907 VG_(printf)("pid=%d\n", VG_(getpid)());
2908 /* do "jump *$eip" to skip this in gdb */
2909 VG_(do_syscall)(__NR_pause);
2910 }
2911
2912 //--------------------------------------------------------------
nethercote1d447092004-02-01 17:29:59 +00002913 // Set up baseBlock
nethercote71980f02004-01-24 18:18:54 +00002914 // p: {pre,post}_clo_init() [for tool helper registration]
2915 // load_client() [for 'client_eip']
2916 // setup_client_stack() [for 'esp_at_startup']
2917 //--------------------------------------------------------------
2918 init_baseBlock(client_eip, esp_at_startup);
2919
2920 //--------------------------------------------------------------
2921 // Search for file descriptors that are inherited from our parent
2922 // p: process_cmd_line_options [for VG_(clo_track_fds)]
2923 //--------------------------------------------------------------
2924 if (VG_(clo_track_fds))
2925 VG_(init_preopened_fds)();
2926
2927 //--------------------------------------------------------------
2928 // Initialise the scheduler
2929 // p: init_baseBlock() [baseBlock regs copied into VG_(threads)[1]]
2930 // p: setup_file_descriptors() [else VG_(safe_fd)() breaks]
2931 //--------------------------------------------------------------
2932 VG_(scheduler_init)();
2933
2934 //--------------------------------------------------------------
2935 // Set up the ProxyLWP machinery
2936 // p: VG_(scheduler_init)()? [XXX: subtle dependency?]
2937 // - subs: VG_(sigstartup_actions)()?
2938 //--------------------------------------------------------------
2939 VG_(proxy_init)();
2940
2941 //--------------------------------------------------------------
2942 // Initialise the signal handling subsystem
2943 // p: VG_(atfork)(NULL, NULL, newpid) [else problems with sigmasks]
2944 // p: VG_(proxy_init)() [else breaks...]
2945 //--------------------------------------------------------------
2946 // Nb: temporarily parks the saved blocking-mask in saved_sigmask.
2947 VG_(sigstartup_actions)();
2948
2949 //--------------------------------------------------------------
2950 // Perhaps we're profiling Valgrind?
2951 // p: process_cmd_line_options() [for VG_(clo_profile)]
2952 // p: others?
2953 //
2954 // XXX: this seems to be broken? It always says the tool wasn't built
2955 // for profiling; vg_profile.c's functions don't seem to be overriding
2956 // vg_dummy_profile.c's?
2957 //
2958 // XXX: want this as early as possible. Looking for --profile
2959 // in pre_process_cmd_line_options() could get it earlier.
2960 //--------------------------------------------------------------
2961 if (VG_(clo_profile))
2962 VGP_(init_profiling)();
2963
2964 VGP_PUSHCC(VgpStartup);
2965
2966 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002967 // Read suppression file
2968 // p: process_cmd_line_options() [for VG_(clo_suppressions)]
2969 //--------------------------------------------------------------
2970 if (VG_(needs).core_errors || VG_(needs).skin_errors)
2971 VG_(load_suppressions)();
2972
2973 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002974 // Initialise translation table and translation cache
2975 // p: read_procselfmaps [so the anonymous mmaps for the TT/TC
2976 // aren't identified as part of the client, which would waste
2977 // > 20M of virtual address space.]
2978 //--------------------------------------------------------------
2979 VG_(init_tt_tc)();
2980
2981 //--------------------------------------------------------------
2982 // Read debug info to find glibc entry points to intercept
2983 // p: parse_procselfmaps? [XXX for debug info?]
2984 // p: init_tt_tc? [XXX ???]
2985 //--------------------------------------------------------------
2986 VG_(setup_code_redirect_table)();
2987
2988 //--------------------------------------------------------------
2989 // Verbosity message
2990 // p: end_rdtsc_calibration [so startup message is printed first]
2991 //--------------------------------------------------------------
2992 if (VG_(clo_verbosity) == 1)
2993 VG_(message)(Vg_UserMsg, "For more details, rerun with: -v");
2994 if (VG_(clo_verbosity) > 0)
2995 VG_(message)(Vg_UserMsg, "");
2996
2997 //--------------------------------------------------------------
2998 // Setup pointercheck
2999 // p: process_cmd_line_options() [for VG_(clo_pointercheck)]
3000 //--------------------------------------------------------------
3001 setup_pointercheck();
3002
nethercote71980f02004-01-24 18:18:54 +00003003 //--------------------------------------------------------------
3004 // Run!
3005 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00003006 VGP_POPCC(VgpStartup);
3007 VGP_PUSHCC(VgpSched);
3008
3009 if (__builtin_setjmp(&VG_(fatal_signal_jmpbuf)) == 0) {
3010 VG_(fatal_signal_set) = True;
nethercote47dd12c2004-06-22 14:18:42 +00003011 src = VG_(scheduler)( &exitcode );
nethercote71980f02004-01-24 18:18:54 +00003012 } else
3013 src = VgSrc_FatalSig;
3014
3015 VGP_POPCC(VgpSched);
nethercote71980f02004-01-24 18:18:54 +00003016
3017
3018
3019 //--------------------------------------------------------------
3020 // Finalisation: cleanup, messages, etc. Order no so important, only
3021 // affects what order the messages come.
3022 //--------------------------------------------------------------
3023 if (VG_(clo_verbosity) > 0)
3024 VG_(message)(Vg_UserMsg, "");
3025
3026 if (src == VgSrc_Deadlock) {
3027 VG_(message)(Vg_UserMsg,
3028 "Warning: pthread scheduler exited due to deadlock");
3029 }
3030
3031 /* Print out file descriptor summary and stats. */
3032 if (VG_(clo_track_fds))
3033 VG_(fd_stats)();
3034
3035 if (VG_(needs).core_errors || VG_(needs).skin_errors)
3036 VG_(show_all_errors)();
3037
nethercote47dd12c2004-06-22 14:18:42 +00003038 SK_(fini)( exitcode );
nethercote71980f02004-01-24 18:18:54 +00003039
3040 VG_(do_sanity_checks)( True /*include expensive checks*/ );
3041
3042 if (VG_(clo_verbosity) > 1)
3043 show_counts();
3044
3045 if (VG_(clo_verbosity) > 3)
3046 VG_(print_UInstr_histogram)();
3047
3048 if (0) {
3049 VG_(message)(Vg_DebugMsg, "");
3050 VG_(message)(Vg_DebugMsg,
3051 "------ Valgrind's internal memory use stats follow ------" );
3052 VG_(mallocSanityCheckAll)();
3053 VG_(show_all_arena_stats)();
3054 VG_(message)(Vg_DebugMsg,
3055 "------ Valgrind's ExeContext management stats follow ------" );
3056 VG_(show_ExeContext_stats)();
3057 }
3058
3059 if (VG_(clo_profile))
3060 VGP_(done_profiling)();
3061
nethercote71980f02004-01-24 18:18:54 +00003062 /* We're exiting, so nuke all the threads and clean up the proxy LWPs */
3063 vg_assert(src == VgSrc_FatalSig ||
3064 VG_(threads)[VG_(last_run_tid)].status == VgTs_Runnable ||
3065 VG_(threads)[VG_(last_run_tid)].status == VgTs_WaitJoiner);
3066 VG_(nuke_all_threads_except)(VG_INVALID_THREADID);
3067
3068 //--------------------------------------------------------------
3069 // Exit, according to the scheduler's return code
3070 //--------------------------------------------------------------
3071 switch (src) {
3072 case VgSrc_ExitSyscall: /* the normal way out */
3073 vg_assert(VG_(last_run_tid) > 0
3074 && VG_(last_run_tid) < VG_N_THREADS);
3075 VG_(proxy_shutdown)();
3076
3077 /* The thread's %EBX at the time it did __NR_exit() will hold
3078 the arg to __NR_exit(), so we just do __NR_exit() with
3079 that arg. */
nethercote47dd12c2004-06-22 14:18:42 +00003080 VG_(exit)( exitcode );
nethercote71980f02004-01-24 18:18:54 +00003081 /* NOT ALIVE HERE! */
3082 VG_(core_panic)("entered the afterlife in main() -- ExitSyscall");
3083 break; /* what the hell :) */
3084
3085 case VgSrc_Deadlock:
3086 /* Just exit now. No point in continuing. */
3087 VG_(proxy_shutdown)();
3088 VG_(exit)(0);
3089 VG_(core_panic)("entered the afterlife in main() -- Deadlock");
3090 break;
3091
nethercote71980f02004-01-24 18:18:54 +00003092 case VgSrc_FatalSig:
3093 /* We were killed by a fatal signal, so replicate the effect */
3094 vg_assert(VG_(fatal_sigNo) != -1);
3095 VG_(kill_self)(VG_(fatal_sigNo));
3096 VG_(core_panic)("main(): signal was supposed to be fatal");
3097 break;
3098
3099 default:
3100 VG_(core_panic)("main(): unexpected scheduler return code");
3101 }
3102
3103 abort();
3104}
3105
3106
sewardjde4a1d02002-03-22 01:27:54 +00003107/*--------------------------------------------------------------------*/
3108/*--- end vg_main.c ---*/
3109/*--------------------------------------------------------------------*/