blob: 53777e4eb51c2b004277d120c4c815431c29db7d [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/* Amount to reserve for Valgrind's internal mappings */
78#define VALGRIND_MAPSIZE (128*1024*1024)
79
80/* redzone gap between client address space and shadow */
81#define REDZONE_SIZE (1 * 1024*1024)
82
83/* size multiple for client address space */
nethercotee94b2de2004-06-23 16:15:06 +000084#define CLIENT_SIZE_MULTIPLE (1 * 1024*1024)
nethercote71980f02004-01-24 18:18:54 +000085
86#define ISSPACE(cc) ((cc) == ' ' || (cc) == '\t' || (cc) == '\n')
87
88/*====================================================================*/
89/*=== Global entities not referenced from generated code ===*/
90/*====================================================================*/
91
sewardjde4a1d02002-03-22 01:27:54 +000092/* ---------------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +000093 Startup stuff
sewardjde4a1d02002-03-22 01:27:54 +000094 ------------------------------------------------------------------ */
nethercote71980f02004-01-24 18:18:54 +000095/* linker-defined base address */
96extern char kickstart_base;
sewardjde4a1d02002-03-22 01:27:54 +000097
nethercote71980f02004-01-24 18:18:54 +000098/* Client address space, lowest to highest (see top of ume.c) */
99Addr VG_(client_base); /* client address space limits */
fitzhardinge98abfc72003-12-16 02:05:15 +0000100Addr VG_(client_end);
101Addr VG_(client_mapbase);
fitzhardinge92360792003-12-24 10:11:11 +0000102Addr VG_(client_trampoline_code);
fitzhardinge98abfc72003-12-16 02:05:15 +0000103Addr VG_(clstk_base);
104Addr VG_(clstk_end);
nethercote71980f02004-01-24 18:18:54 +0000105
106Addr VG_(brk_base); /* start of brk */
107Addr VG_(brk_limit); /* current brk */
108
109Addr VG_(shadow_base); /* skin's shadow memory */
fitzhardinge98abfc72003-12-16 02:05:15 +0000110Addr VG_(shadow_end);
nethercote71980f02004-01-24 18:18:54 +0000111
112Addr VG_(valgrind_base); /* valgrind's address range */
113Addr VG_(valgrind_mmap_end); /* valgrind's mmaps are between valgrind_base and here */
fitzhardinge98abfc72003-12-16 02:05:15 +0000114Addr VG_(valgrind_end);
115
fitzhardingeb50068f2004-02-24 23:42:55 +0000116vki_rlimit VG_(client_rlimit_data);
117
nethercote71980f02004-01-24 18:18:54 +0000118/* This is set early to indicate whether this CPU has the
119 SSE/fxsave/fxrestor features. */
120Bool VG_(have_ssestate);
121
122/* Indicates presence, and holds address of client's sysinfo page, a
123 feature of some modern kernels used to provide vsyscalls, etc. */
124Bool VG_(sysinfo_page_exists) = False;
125Addr VG_(sysinfo_page_addr) = 0;
126
fitzhardinge98abfc72003-12-16 02:05:15 +0000127/* stage1 (main) executable */
fitzhardingea49f9b52003-12-16 22:26:45 +0000128Int VG_(vgexecfd) = -1;
129
130/* client executable */
131Int VG_(clexecfd) = -1;
fitzhardinge98abfc72003-12-16 02:05:15 +0000132
133/* Path to library directory */
134const Char *VG_(libdir) = VG_LIBDIR;
135
136/* our argc/argv */
137Int VG_(vg_argc);
138Char **VG_(vg_argv);
139
jsgf855d93d2003-10-13 22:26:55 +0000140/* PID of the main thread */
141Int VG_(main_pid);
142
143/* PGRP of process */
144Int VG_(main_pgrp);
njn25e49d8e72002-09-23 09:36:25 +0000145
thughesad1c9562004-06-26 11:27:52 +0000146/* Application-visible file descriptor limits */
147Int VG_(fd_soft_limit) = -1;
148Int VG_(fd_hard_limit) = -1;
fitzhardingef0046f22003-12-18 02:39:22 +0000149
nethercote71980f02004-01-24 18:18:54 +0000150/* As deduced from esp_at_startup, the client's argc, argv[] and
151 envp[] as extracted from the client's stack at startup-time. */
152Int VG_(client_argc);
153Char** VG_(client_argv);
154Char** VG_(client_envp);
sewardjde4a1d02002-03-22 01:27:54 +0000155
156/* ---------------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +0000157 Running stuff
sewardjde4a1d02002-03-22 01:27:54 +0000158 ------------------------------------------------------------------ */
nethercote71980f02004-01-24 18:18:54 +0000159/* Our signal delivery stack. */
njn6eba4ef2003-05-01 08:06:41 +0000160UInt VG_(sigstack)[VG_SIGSTACK_SIZE_W];
sewardjde4a1d02002-03-22 01:27:54 +0000161
nethercote71980f02004-01-24 18:18:54 +0000162/* jmp_buf for fatal signals */
163Int VG_(fatal_sigNo) = -1;
164Bool VG_(fatal_signal_set) = False;
165jmp_buf VG_(fatal_signal_jmpbuf);
sewardjde4a1d02002-03-22 01:27:54 +0000166
nethercote71980f02004-01-24 18:18:54 +0000167/* Counts downwards in VG_(run_innerloop). */
168UInt VG_(dispatch_ctr);
sewardjde4a1d02002-03-22 01:27:54 +0000169
170/* 64-bit counter for the number of basic blocks done. */
171ULong VG_(bbs_done);
sewardjde4a1d02002-03-22 01:27:54 +0000172
sewardj7e87e382002-05-03 19:09:05 +0000173/* This is the ThreadId of the last thread the scheduler ran. */
174ThreadId VG_(last_run_tid) = 0;
175
nethercote71980f02004-01-24 18:18:54 +0000176/* Tell the logging mechanism whether we are logging to a file
177 descriptor or a socket descriptor. */
178Bool VG_(logging_to_filedes) = True;
179
sewardj73cf3bc2002-11-03 03:20:15 +0000180
nethercote71980f02004-01-24 18:18:54 +0000181/*====================================================================*/
182/*=== Counters, for profiling purposes only ===*/
183/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +0000184
185/* Number of lookups which miss the fast tt helper. */
186UInt VG_(tt_fast_misses) = 0;
187
188
sewardjc0d8f682002-11-30 00:49:43 +0000189/* Counts for TT/TC informational messages. */
sewardjde4a1d02002-03-22 01:27:54 +0000190
sewardjde4a1d02002-03-22 01:27:54 +0000191/* Number and total o/t size of translations overall. */
192UInt VG_(overall_in_count) = 0;
193UInt VG_(overall_in_osize) = 0;
194UInt VG_(overall_in_tsize) = 0;
195/* Number and total o/t size of discards overall. */
196UInt VG_(overall_out_count) = 0;
197UInt VG_(overall_out_osize) = 0;
198UInt VG_(overall_out_tsize) = 0;
sewardjc0d8f682002-11-30 00:49:43 +0000199/* The number of discards of TT/TC. */
200UInt VG_(number_of_tc_discards) = 0;
sewardj22854b92002-11-30 14:00:47 +0000201/* Counts of chain and unchain operations done. */
202UInt VG_(bb_enchain_count) = 0;
203UInt VG_(bb_dechain_count) = 0;
204/* Number of unchained jumps performed. */
205UInt VG_(unchained_jumps_done) = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000206
207
208/* Counts pertaining to the register allocator. */
209
210/* total number of uinstrs input to reg-alloc */
211UInt VG_(uinstrs_prealloc) = 0;
212
213/* total number of uinstrs added due to spill code */
214UInt VG_(uinstrs_spill) = 0;
215
216/* number of bbs requiring spill code */
217UInt VG_(translations_needing_spill) = 0;
218
219/* total of register ranks over all translations */
220UInt VG_(total_reg_rank) = 0;
221
222
sewardjde4a1d02002-03-22 01:27:54 +0000223/* Counts pertaining to internal sanity checking. */
sewardjde4a1d02002-03-22 01:27:54 +0000224UInt VG_(sanity_fast_count) = 0;
225UInt VG_(sanity_slow_count) = 0;
226
sewardj2e93c502002-04-12 11:12:52 +0000227/* Counts pertaining to the scheduler. */
228UInt VG_(num_scheduling_events_MINOR) = 0;
229UInt VG_(num_scheduling_events_MAJOR) = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000230
231
nethercote71980f02004-01-24 18:18:54 +0000232static __inline__ Int safe_idiv(Int a, Int b)
233{
234 return (b == 0 ? 0 : a / b);
235}
236
237static void show_counts ( void )
238{
239 VG_(message)(Vg_DebugMsg,
240 " TT/TC: %d tc sectors discarded.",
241 VG_(number_of_tc_discards) );
242 VG_(message)(Vg_DebugMsg,
243 " %d chainings, %d unchainings.",
244 VG_(bb_enchain_count), VG_(bb_dechain_count) );
245 VG_(message)(Vg_DebugMsg,
246 "translate: new %d (%d -> %d; ratio %d:10)",
247 VG_(overall_in_count),
248 VG_(overall_in_osize),
249 VG_(overall_in_tsize),
250 safe_idiv(10*VG_(overall_in_tsize), VG_(overall_in_osize)));
251 VG_(message)(Vg_DebugMsg,
252 " discard %d (%d -> %d; ratio %d:10).",
253 VG_(overall_out_count),
254 VG_(overall_out_osize),
255 VG_(overall_out_tsize),
256 safe_idiv(10*VG_(overall_out_tsize), VG_(overall_out_osize)));
257 VG_(message)(Vg_DebugMsg,
258 " dispatch: %llu jumps (bb entries), of which %u (%lu%%) were unchained.",
259 VG_(bbs_done),
260 VG_(unchained_jumps_done),
261 ((ULong)(100) * (ULong)(VG_(unchained_jumps_done)))
262 / ( VG_(bbs_done)==0 ? 1 : VG_(bbs_done) )
263 );
264
265 VG_(message)(Vg_DebugMsg,
266 " %d/%d major/minor sched events. %d tt_fast misses.",
267 VG_(num_scheduling_events_MAJOR),
268 VG_(num_scheduling_events_MINOR),
269 VG_(tt_fast_misses));
270
271 VG_(message)(Vg_DebugMsg,
272 "reg-alloc: %d t-req-spill, "
273 "%d+%d orig+spill uis, %d total-reg-r.",
274 VG_(translations_needing_spill),
275 VG_(uinstrs_prealloc),
276 VG_(uinstrs_spill),
277 VG_(total_reg_rank) );
278 VG_(message)(Vg_DebugMsg,
279 " sanity: %d cheap, %d expensive checks.",
280 VG_(sanity_fast_count),
281 VG_(sanity_slow_count) );
282 VG_(print_ccall_stats)();
283}
284
285
286/*====================================================================*/
287/*=== Miscellaneous global functions ===*/
288/*====================================================================*/
289
nethercote04d0fbc2004-01-26 16:48:06 +0000290/* Start debugger and get it to attach to this process. Called if the
291 user requests this service after an error has been shown, so she can
nethercote71980f02004-01-24 18:18:54 +0000292 poke around and look at parameters, memory, etc. You can't
nethercote04d0fbc2004-01-26 16:48:06 +0000293 meaningfully get the debugger to continue the program, though; to
294 continue, quit the debugger. */
295void VG_(start_debugger) ( Int tid )
nethercote71980f02004-01-24 18:18:54 +0000296{
297 Int pid;
298
299 if ((pid = fork()) == 0) {
300 ptrace(PTRACE_TRACEME, 0, NULL, NULL);
301 VG_(kkill)(VG_(getpid)(), VKI_SIGSTOP);
302
303 } else if (pid > 0) {
304 struct user_regs_struct regs;
305 Int status;
306 Int res;
307
308 if (VG_(is_running_thread)( tid )) {
fitzhardinged65dcad2004-03-13 02:06:58 +0000309 regs.cs = VG_(baseBlock)[VGOFF_(m_cs)];
310 regs.ss = VG_(baseBlock)[VGOFF_(m_ss)];
311 regs.ds = VG_(baseBlock)[VGOFF_(m_ds)];
312 regs.es = VG_(baseBlock)[VGOFF_(m_es)];
313 regs.fs = VG_(baseBlock)[VGOFF_(m_fs)];
314 regs.gs = VG_(baseBlock)[VGOFF_(m_gs)];
nethercote71980f02004-01-24 18:18:54 +0000315 regs.eax = VG_(baseBlock)[VGOFF_(m_eax)];
316 regs.ebx = VG_(baseBlock)[VGOFF_(m_ebx)];
317 regs.ecx = VG_(baseBlock)[VGOFF_(m_ecx)];
318 regs.edx = VG_(baseBlock)[VGOFF_(m_edx)];
319 regs.esi = VG_(baseBlock)[VGOFF_(m_esi)];
320 regs.edi = VG_(baseBlock)[VGOFF_(m_edi)];
321 regs.ebp = VG_(baseBlock)[VGOFF_(m_ebp)];
322 regs.esp = VG_(baseBlock)[VGOFF_(m_esp)];
323 regs.eflags = VG_(baseBlock)[VGOFF_(m_eflags)];
324 regs.eip = VG_(baseBlock)[VGOFF_(m_eip)];
325 } else {
326 ThreadState* tst = & VG_(threads)[ tid ];
327
fitzhardinged65dcad2004-03-13 02:06:58 +0000328 regs.cs = tst->m_cs;
329 regs.ss = tst->m_ss;
330 regs.ds = tst->m_ds;
331 regs.es = tst->m_es;
332 regs.fs = tst->m_fs;
333 regs.gs = tst->m_gs;
nethercote71980f02004-01-24 18:18:54 +0000334 regs.eax = tst->m_eax;
335 regs.ebx = tst->m_ebx;
336 regs.ecx = tst->m_ecx;
337 regs.edx = tst->m_edx;
338 regs.esi = tst->m_esi;
339 regs.edi = tst->m_edi;
340 regs.ebp = tst->m_ebp;
341 regs.esp = tst->m_esp;
342 regs.eflags = tst->m_eflags;
343 regs.eip = tst->m_eip;
344 }
345
346 if ((res = VG_(waitpid)(pid, &status, 0)) == pid &&
347 WIFSTOPPED(status) && WSTOPSIG(status) == SIGSTOP &&
348 ptrace(PTRACE_SETREGS, pid, NULL, &regs) == 0 &&
thughes1d160052004-04-21 15:39:57 +0000349 kill(pid, SIGSTOP) == 0 &&
350 ptrace(PTRACE_DETACH, pid, NULL, 0) == 0) {
nethercote04d0fbc2004-01-26 16:48:06 +0000351 Char pidbuf[15];
352 Char file[30];
353 Char buf[100];
354 Char *bufptr;
355 Char *cmdptr;
356
357 VG_(sprintf)(pidbuf, "%d", pid);
358 VG_(sprintf)(file, "/proc/%d/fd/%d", pid, VG_(clexecfd));
359
360 bufptr = buf;
361 cmdptr = VG_(clo_db_command);
362
363 while (*cmdptr) {
364 switch (*cmdptr) {
365 case '%':
366 switch (*++cmdptr) {
367 case 'f':
368 VG_(memcpy)(bufptr, file, VG_(strlen)(file));
369 bufptr += VG_(strlen)(file);
370 cmdptr++;
371 break;
372 case 'p':
373 VG_(memcpy)(bufptr, pidbuf, VG_(strlen)(pidbuf));
374 bufptr += VG_(strlen)(pidbuf);
375 cmdptr++;
376 break;
377 default:
378 *bufptr++ = *cmdptr++;
379 break;
380 }
381 break;
382 default:
383 *bufptr++ = *cmdptr++;
384 break;
385 }
386 }
387
388 *bufptr++ = '\0';
389
390 VG_(message)(Vg_UserMsg, "starting debugger with cmd: %s", buf);
nethercote71980f02004-01-24 18:18:54 +0000391 res = VG_(system)(buf);
392 if (res == 0) {
393 VG_(message)(Vg_UserMsg, "");
394 VG_(message)(Vg_UserMsg,
nethercote04d0fbc2004-01-26 16:48:06 +0000395 "Debugger has detached. Valgrind regains control. We continue.");
nethercote71980f02004-01-24 18:18:54 +0000396 } else {
397 VG_(message)(Vg_UserMsg, "Apparently failed!");
398 VG_(message)(Vg_UserMsg, "");
399 }
400 }
401
402 VG_(kkill)(pid, VKI_SIGKILL);
403 VG_(waitpid)(pid, &status, 0);
404 }
405}
406
407
408/* Print some helpful-ish text about unimplemented things, and give
409 up. */
410void VG_(unimplemented) ( Char* msg )
411{
412 VG_(message)(Vg_UserMsg, "");
413 VG_(message)(Vg_UserMsg,
414 "Valgrind detected that your program requires");
415 VG_(message)(Vg_UserMsg,
416 "the following unimplemented functionality:");
417 VG_(message)(Vg_UserMsg, " %s", msg);
418 VG_(message)(Vg_UserMsg,
419 "This may be because the functionality is hard to implement,");
420 VG_(message)(Vg_UserMsg,
421 "or because no reasonable program would behave this way,");
422 VG_(message)(Vg_UserMsg,
423 "or because nobody has yet needed it. In any case, let us know at");
424 VG_(message)(Vg_UserMsg,
425 "%s and/or try to work around the problem, if you can.", VG_BUGS_TO);
426 VG_(message)(Vg_UserMsg,
427 "");
428 VG_(message)(Vg_UserMsg,
429 "Valgrind has to exit now. Sorry. Bye!");
430 VG_(message)(Vg_UserMsg,
431 "");
432 VG_(pp_sched_status)();
433 VG_(exit)(1);
434}
435
436Addr VG_(get_stack_pointer) ( void )
437{
438 return VG_(baseBlock)[VGOFF_(m_esp)];
439}
440
441/* Debugging thing .. can be called from assembly with OYNK macro. */
442void VG_(oynk) ( Int n )
443{
444 OINK(n);
445}
446
447/* Initialize the PID and PGRP of scheduler LWP; this is also called
448 in any new children after fork. */
449static void newpid(ThreadId unused)
450{
451 /* PID of scheduler LWP */
452 VG_(main_pid) = VG_(getpid)();
453 VG_(main_pgrp) = VG_(getpgrp)();
454}
455
456/*====================================================================*/
457/*=== Check we were launched by stage 1 ===*/
458/*====================================================================*/
459
460/* Look for our AUXV table */
461static void scan_auxv(void)
462{
463 const struct ume_auxv *auxv = find_auxv((int *)ume_exec_esp);
464 int found = 0;
465
466 for (; auxv->a_type != AT_NULL; auxv++)
467 switch(auxv->a_type) {
468 case AT_UME_PADFD:
469 as_setpadfd(auxv->u.a_val);
470 found |= 1;
471 break;
472
473 case AT_UME_EXECFD:
474 VG_(vgexecfd) = auxv->u.a_val;
475 found |= 2;
476 break;
477 }
478
479 if ( ! (1|2) ) {
480 fprintf(stderr, "stage2 must be launched by stage1\n");
481 exit(127);
482 }
483}
484
485
486/*====================================================================*/
487/*=== Address space determination ===*/
488/*====================================================================*/
489
490/* Pad client space so it doesn't get filled in before the right time */
491static void layout_client_space(Addr argc_addr)
492{
493 VG_(client_base) = CLIENT_BASE;
494 VG_(valgrind_mmap_end) = (addr_t)&kickstart_base; /* end of V's mmaps */
495 VG_(valgrind_base) = VG_(valgrind_mmap_end) - VALGRIND_MAPSIZE;
496 VG_(valgrind_end) = ROUNDUP(argc_addr, 0x10000); /* stack */
497
498 if (0)
499 printf("client base: %x\n"
500 "valgrind base--end: %x--%x (%x)\n"
501 "valgrind mmap end: %x\n\n",
502 VG_(client_base),
503 VG_(valgrind_base), VG_(valgrind_end),
504 VG_(valgrind_end) - VG_(valgrind_base),
505 VG_(valgrind_mmap_end));
506
507 as_pad((void *)VG_(client_base), (void *)VG_(valgrind_base));
508}
509
510static void layout_remaining_space(float ratio)
511{
512 /* This tries to give the client as large as possible address space while
513 * taking into account the tool's shadow needs. */
514 addr_t client_size = ROUNDDN((VG_(valgrind_base) - REDZONE_SIZE) / (1. + ratio),
515 CLIENT_SIZE_MULTIPLE);
516 addr_t shadow_size = PGROUNDUP(client_size * ratio);
517
518 VG_(client_end) = VG_(client_base) + client_size;
519 VG_(client_mapbase) = PGROUNDDN((client_size/4)*3); /* where !FIXED mmap goes */
520 VG_(client_trampoline_code) = VG_(client_end) - VKI_BYTES_PER_PAGE;
521
522 VG_(shadow_base) = VG_(client_end) + REDZONE_SIZE;
523 VG_(shadow_end) = VG_(shadow_base) + shadow_size;
524
525 if (0)
526 printf("client base--end: %x--%x (%x)\n"
527 "client mapbase: %x\n"
528 "shadow base--end: %x--%x (%x)\n\n",
529 VG_(client_base), VG_(client_end), client_size,
530 VG_(client_mapbase),
531 VG_(shadow_base), VG_(shadow_end), shadow_size);
532
533 // Ban redzone
534 mmap((void *)VG_(client_end), REDZONE_SIZE, PROT_NONE,
535 MAP_FIXED|MAP_ANON|MAP_PRIVATE, -1, 0);
536
537 // Make client hole
538 munmap((void*)VG_(client_base), client_size);
539
540 // Map shadow memory.
541 // Initially all inaccessible, incrementally initialized as it is used
542 if (shadow_size != 0)
543 mmap((char *)VG_(shadow_base), shadow_size, PROT_NONE,
544 MAP_PRIVATE|MAP_ANON|MAP_FIXED, -1, 0);
545}
546
547/*====================================================================*/
548/*=== Command line setup ===*/
549/*====================================================================*/
550
551/* Nb: malloc'd memory never freed -- kept throughout like argv, envp */
552static char* get_file_clo(char* dir)
553{
554# define FLEN 512
555 Int fd, n;
556 struct stat s1;
557 char* f_clo = NULL;
558 char filename[FLEN];
559
560 snprintf(filename, FLEN, "%s/.valgrindrc", ( NULL == dir ? "" : dir ) );
561 fd = VG_(open)(filename, 0, VKI_S_IRUSR);
562 if ( fd > 0 ) {
563 if ( 0 == fstat(fd, &s1) ) {
564 f_clo = malloc(s1.st_size+1);
565 vg_assert(f_clo);
566 n = read(fd, f_clo, s1.st_size);
567 if (n == -1) n = 0;
568 f_clo[n] = '\0';
569 }
570 close(fd);
571 }
572 return f_clo;
573# undef FLEN
574}
575
576static Int count_args(char* s)
577{
578 Int n = 0;
579 if (s) {
580 char* cp = s;
581 while (True) {
582 // We have alternating sequences: blanks, non-blanks, blanks...
583 // count the non-blanks sequences.
584 while ( ISSPACE(*cp) ) cp++;
585 if ( !*cp ) break;
586 n++;
587 while ( !ISSPACE(*cp) && *cp ) cp++;
588 }
589 }
590 return n;
591}
592
593/* add args out of environment, skipping multiple spaces and -- args */
594static char** copy_args( char* s, char** to )
595{
596 if (s) {
597 char* cp = s;
598 while (True) {
599 // We have alternating sequences: blanks, non-blanks, blanks...
600 // copy the non-blanks sequences, and add terminating '\0'
601 while ( ISSPACE(*cp) ) cp++;
602 if ( !*cp ) break;
603 *to++ = cp;
604 while ( !ISSPACE(*cp) && *cp ) cp++;
605 if ( *cp ) *cp++ = '\0'; // terminate if necessary
606 if (VG_STREQ(to[-1], "--")) to--; // undo any '--' arg
607 }
608 }
609 return to;
610}
611
612// Augment command line with arguments from environment and .valgrindrc
613// files.
614static void augment_command_line(Int* vg_argc_inout, char*** vg_argv_inout)
615{
616 int vg_argc = *vg_argc_inout;
617 char** vg_argv = *vg_argv_inout;
618
619 char* env_clo = getenv(VALGRINDOPTS);
620 char* f1_clo = get_file_clo( getenv("HOME") );
621 char* f2_clo = get_file_clo(".");
622
623 /* copy any extra args from file or environment, if present */
624 if ( (env_clo && *env_clo) || (f1_clo && *f1_clo) || (f2_clo && *f2_clo) ) {
625 /* ' ' separated extra options */
626 char **from;
627 char **to;
628 int env_arg_count, f1_arg_count, f2_arg_count;
629
630 env_arg_count = count_args(env_clo);
631 f1_arg_count = count_args(f1_clo);
632 f2_arg_count = count_args(f2_clo);
633
634 if (0)
635 printf("extra-argc=%d %d %d\n",
636 env_arg_count, f1_arg_count, f2_arg_count);
637
638 /* +2: +1 for null-termination, +1 for added '--' */
639 from = vg_argv;
640 vg_argv = malloc( (vg_argc + env_arg_count + f1_arg_count
641 + f2_arg_count + 2) * sizeof(char **));
642 to = vg_argv;
643
644 /* copy argv[0] */
645 *to++ = *from++;
646
647 /* Copy extra args from env var and file, in the order: ~/.valgrindrc,
648 * $VALGRIND_OPTS, ./.valgrindrc -- more local options are put later
649 * to override less local ones. */
650 to = copy_args(f1_clo, to);
651 to = copy_args(env_clo, to);
652 to = copy_args(f2_clo, to);
653
654 /* copy original arguments, stopping at command or -- */
655 while (*from) {
656 if (**from != '-')
657 break;
658 if (VG_STREQ(*from, "--")) {
659 from++; /* skip -- */
660 break;
661 }
662 *to++ = *from++;
663 }
664
665 /* add -- */
666 *to++ = "--";
667
668 vg_argc = to - vg_argv;
669
670 /* copy rest of original command line, then NULL */
671 while (*from) *to++ = *from++;
672 *to = NULL;
673 }
674
675 *vg_argc_inout = vg_argc;
676 *vg_argv_inout = vg_argv;
677}
678
679static void get_command_line( int argc, char** argv,
680 Int* vg_argc_out, Char*** vg_argv_out,
681 char*** cl_argv_out )
682{
683 int vg_argc;
684 char** vg_argv;
685 char** cl_argv;
686 char* env_clo = getenv(VALGRINDCLO);
687
688 if (env_clo != NULL && *env_clo != '\0') {
689 char *cp;
690 char **cpp;
691
692 /* OK, we're getting all our arguments from the environment - the
693 entire command line belongs to the client (including argv[0]) */
694 vg_argc = 1; /* argv[0] */
695 for (cp = env_clo; *cp; cp++)
696 if (*cp == '\01')
697 vg_argc++;
698
699 vg_argv = malloc(sizeof(char **) * (vg_argc + 1));
700
701 cpp = vg_argv;
702
703 *cpp++ = "valgrind"; /* nominal argv[0] */
704 *cpp++ = env_clo;
705
706 for (cp = env_clo; *cp; cp++) {
707 if (*cp == '\01') {
708 *cp++ = '\0'; /* chop it up in place */
709 *cpp++ = cp;
710 }
711 }
712 *cpp = NULL;
713 cl_argv = argv;
714
715 } else {
716 /* Count the arguments on the command line. */
717 vg_argv = argv;
718
719 for (vg_argc = 1; vg_argc < argc; vg_argc++) {
720 if (argv[vg_argc][0] != '-') /* exe name */
721 break;
722 if (VG_STREQ(argv[vg_argc], "--")) { /* dummy arg */
723 vg_argc++;
724 break;
725 }
726 }
727 cl_argv = &argv[vg_argc];
728
729 /* Get extra args from VALGRIND_OPTS and .valgrindrc files.
730 * Note we don't do this if getting args from VALGRINDCLO. */
731 augment_command_line(&vg_argc, &vg_argv);
732 }
733
734 if (0) {
735 Int i;
736 for (i = 0; i < vg_argc; i++)
737 printf("vg_argv[%d]=\"%s\"\n", i, vg_argv[i]);
738 }
739
740 *vg_argc_out = vg_argc;
741 *vg_argv_out = (Char**)vg_argv;
742 *cl_argv_out = cl_argv;
743}
744
745
746/*====================================================================*/
747/*=== Environment and stack setup ===*/
748/*====================================================================*/
749
750/* Scan a colon-separated list, and call a function on each element.
751 The string must be mutable, because we insert a temporary '\0', but
752 the string will end up unmodified. (*func) should return 1 if it
753 doesn't need to see any more.
754*/
755static void scan_colsep(char *colsep, int (*func)(const char *))
756{
757 char *cp, *entry;
758 int end;
759
760 if (colsep == NULL ||
761 *colsep == '\0')
762 return;
763
764 entry = cp = colsep;
765
766 do {
767 end = (*cp == '\0');
768
769 if (*cp == ':' || *cp == '\0') {
770 char save = *cp;
771
772 *cp = '\0';
773 if ((*func)(entry))
774 end = 1;
775 *cp = save;
776 entry = cp+1;
777 }
778 cp++;
779 } while(!end);
780}
781
782/* Prepare the client's environment. This is basically a copy of our
783 environment, except:
784 1. LD_LIBRARY_PATH=$VALGRINDLIB:$LD_LIBRARY_PATH
785 2. LD_PRELOAD=$VALGRINDLIB/vg_inject.so:($VALGRINDLIB/vgpreload_TOOL.so:)?$LD_PRELOAD
786
787 If any of these is missing, then it is added.
788
789 Yummy. String hacking in C.
790
791 If this needs to handle any more variables it should be hacked
792 into something table driven.
793 */
794static char **fix_environment(char **origenv, const char *preload)
795{
796 static const char inject_so[] = "vg_inject.so";
797 static const char ld_library_path[] = "LD_LIBRARY_PATH=";
798 static const char ld_preload[] = "LD_PRELOAD=";
799 static const char valgrind_clo[] = VALGRINDCLO "=";
800 static const int ld_library_path_len = sizeof(ld_library_path)-1;
801 static const int ld_preload_len = sizeof(ld_preload)-1;
802 static const int valgrind_clo_len = sizeof(valgrind_clo)-1;
803 int ld_preload_done = 0;
804 int ld_library_path_done = 0;
805 char *inject_path;
806 int inject_path_len;
807 int vgliblen = strlen(VG_(libdir));
808 char **cpp;
809 char **ret;
810 int envc;
811 const int preloadlen = (preload == NULL) ? 0 : strlen(preload);
812
813 /* Find the vg_inject.so; also make room for the tool preload
814 library */
815 inject_path_len = sizeof(inject_so) + vgliblen + preloadlen + 16;
816 inject_path = malloc(inject_path_len);
817
818 if (preload)
819 snprintf(inject_path, inject_path_len, "%s/%s:%s",
820 VG_(libdir), inject_so, preload);
821 else
822 snprintf(inject_path, inject_path_len, "%s/%s",
823 VG_(libdir), inject_so);
824
825 /* Count the original size of the env */
826 envc = 0; /* trailing NULL */
827 for (cpp = origenv; cpp && *cpp; cpp++)
828 envc++;
829
830 /* Allocate a new space */
831 ret = malloc(sizeof(char *) * (envc+3+1)); /* 3 new entries + NULL */
832
833 /* copy it over */
834 for (cpp = ret; *origenv; )
835 *cpp++ = *origenv++;
836 *cpp = NULL;
837
838 vg_assert(envc == (cpp - ret));
839
840 /* Walk over the new environment, mashing as we go */
841 for (cpp = ret; cpp && *cpp; cpp++) {
842 if (memcmp(*cpp, ld_library_path, ld_library_path_len) == 0) {
843 int done = 0;
844 int contains(const char *p) {
845 if (VG_STREQ(p, VG_(libdir))) {
846 done = 1;
847 return 1;
848 }
849 return 0;
850 }
851
852 /* If the LD_LIBRARY_PATH already contains libdir, then don't
853 bother adding it again, even if it isn't the first (it
854 seems that the Java runtime will keep reexecing itself
855 unless its paths are at the front of LD_LIBRARY_PATH) */
856 scan_colsep(*cpp + ld_library_path_len, contains);
857
858 if (!done) {
859 int len = strlen(*cpp) + vgliblen*2 + 16;
860 char *cp = malloc(len);
861
862 snprintf(cp, len, "%s%s:%s",
863 ld_library_path, VG_(libdir),
864 (*cpp)+ld_library_path_len);
865
866 *cpp = cp;
867 }
868
869 ld_library_path_done = 1;
870 } else if (memcmp(*cpp, ld_preload, ld_preload_len) == 0) {
871 int len = strlen(*cpp) + inject_path_len;
872 char *cp = malloc(len);
873
874 snprintf(cp, len, "%s%s:%s",
875 ld_preload, inject_path, (*cpp)+ld_preload_len);
876
877 *cpp = cp;
878
879 ld_preload_done = 1;
880 } else if (memcmp(*cpp, valgrind_clo, valgrind_clo_len) == 0) {
881 *cpp = "";
882 }
883 }
884
885 /* Add the missing bits */
886
887 if (!ld_library_path_done) {
888 int len = ld_library_path_len + vgliblen*2 + 16;
889 char *cp = malloc(len);
890
891 snprintf(cp, len, "%s%s", ld_library_path, VG_(libdir));
892
893 ret[envc++] = cp;
894 }
895
896 if (!ld_preload_done) {
897 int len = ld_preload_len + inject_path_len;
898 char *cp = malloc(len);
899
900 snprintf(cp, len, "%s%s",
901 ld_preload, inject_path);
902
903 ret[envc++] = cp;
904 }
905
906 ret[envc] = NULL;
907
908 return ret;
909}
910
911extern char **environ; /* our environment */
912//#include <error.h>
913
914/* Add a string onto the string table, and return its address */
915static char *copy_str(char **tab, const char *str)
916{
917 char *cp = *tab;
918 char *orig = cp;
919
920 while(*str)
921 *cp++ = *str++;
922 *cp++ = '\0';
923
924 if (0)
925 printf("copied %p \"%s\" len %d\n",
926 orig, orig, cp-orig);
927
928 *tab = cp;
929
930 return orig;
931}
932
933/*
934 This sets up the client's initial stack, containing the args,
935 environment and aux vector.
936
937 The format of the stack is:
938
939 higher address +-----------------+
940 | Trampoline code |
941 +-----------------+
942 | |
943 : string table :
944 | |
945 +-----------------+
946 | AT_NULL |
947 - -
948 | auxv |
949 +-----------------+
950 | NULL |
951 - -
952 | envp |
953 +-----------------+
954 | NULL |
955 - -
956 | argv |
957 +-----------------+
958 | argc |
959 lower address +-----------------+ <- esp
960 | undefined |
961 : :
962 */
963static Addr setup_client_stack(char **orig_argv, char **orig_envp,
964 const struct exeinfo *info,
965 UInt** client_auxv)
966{
967 char **cpp;
968 char *strtab; /* string table */
969 char *stringbase;
970 addr_t *ptr;
971 struct ume_auxv *auxv;
972 const struct ume_auxv *orig_auxv;
973 const struct ume_auxv *cauxv;
974 unsigned stringsize; /* total size of strings in bytes */
975 unsigned auxsize; /* total size of auxv in bytes */
976 int argc; /* total argc */
977 int envc; /* total number of env vars */
978 unsigned stacksize; /* total client stack size */
979 addr_t cl_esp; /* client stack base (initial esp) */
980
981 /* use our own auxv as a prototype */
982 orig_auxv = find_auxv(ume_exec_esp);
983
984 /* ==================== compute sizes ==================== */
985
986 /* first of all, work out how big the client stack will be */
987 stringsize = 0;
988
989 /* paste on the extra args if the loader needs them (ie, the #!
990 interpreter and its argument) */
991 argc = 0;
992 if (info->argv0 != NULL) {
993 argc++;
994 stringsize += strlen(info->argv0) + 1;
995 }
996 if (info->argv1 != NULL) {
997 argc++;
998 stringsize += strlen(info->argv1) + 1;
999 }
1000
1001 /* now scan the args we're given... */
1002 for (cpp = orig_argv; *cpp; cpp++) {
1003 argc++;
1004 stringsize += strlen(*cpp) + 1;
1005 }
1006
1007 /* ...and the environment */
1008 envc = 0;
1009 for (cpp = orig_envp; cpp && *cpp; cpp++) {
1010 envc++;
1011 stringsize += strlen(*cpp) + 1;
1012 }
1013
1014 /* now, how big is the auxv? */
1015 auxsize = sizeof(*auxv); /* there's always at least one entry: AT_NULL */
1016 for (cauxv = orig_auxv; cauxv->a_type != AT_NULL; cauxv++) {
1017 if (cauxv->a_type == AT_PLATFORM)
1018 stringsize += strlen(cauxv->u.a_ptr) + 1;
1019 auxsize += sizeof(*cauxv);
1020 }
1021
1022 /* OK, now we know how big the client stack is */
1023 stacksize =
1024 sizeof(int) + /* argc */
1025 sizeof(char **)*argc + /* argv */
1026 sizeof(char **) + /* terminal NULL */
1027 sizeof(char **)*envc + /* envp */
1028 sizeof(char **) + /* terminal NULL */
1029 auxsize + /* auxv */
1030 ROUNDUP(stringsize, sizeof(int)) +/* strings (aligned) */
1031 VKI_BYTES_PER_PAGE; /* page for trampoline code */
1032
1033 /* cl_esp is the client's stack pointer */
1034 cl_esp = VG_(client_end) - stacksize;
1035 cl_esp = ROUNDDN(cl_esp, 16); /* make stack 16 byte aligned */
1036
nethercote71980f02004-01-24 18:18:54 +00001037 /* base of the string table (aligned) */
1038 stringbase = strtab = (char *)(VG_(client_trampoline_code) - ROUNDUP(stringsize, sizeof(int)));
1039
1040 VG_(clstk_base) = PGROUNDDN(cl_esp);
1041 VG_(clstk_end) = VG_(client_end);
1042
nethercote5ee67ca2004-06-22 14:00:09 +00001043 if (0)
1044 printf("stringsize=%d auxsize=%d stacksize=%d\n"
1045 "clstk_base %x\n"
1046 "clstk_end %x\n",
1047 stringsize, auxsize, stacksize, VG_(clstk_base), VG_(clstk_end));
1048
1049
nethercote71980f02004-01-24 18:18:54 +00001050 /* ==================== allocate space ==================== */
1051
1052 /* allocate a stack - mmap enough space for the stack */
1053 mmap((void *)PGROUNDDN(cl_esp),
1054 VG_(client_end) - PGROUNDDN(cl_esp),
1055 PROT_READ | PROT_WRITE | PROT_EXEC,
1056 MAP_PRIVATE | MAP_ANON | MAP_FIXED, -1, 0);
1057
1058
1059 /* ==================== copy client stack ==================== */
1060
1061 ptr = (addr_t *)cl_esp;
1062
1063 /* --- argc --- */
1064 *ptr++ = argc; /* client argc */
1065
1066 /* --- argv --- */
1067 if (info->argv0) {
1068 *ptr++ = (addr_t)copy_str(&strtab, info->argv0);
1069 free(info->argv0);
1070 }
1071 if (info->argv1) {
1072 *ptr++ = (addr_t)copy_str(&strtab, info->argv1);
1073 free(info->argv1);
1074 }
1075 for (cpp = orig_argv; *cpp; ptr++, cpp++) {
1076 *ptr = (addr_t)copy_str(&strtab, *cpp);
1077 }
1078 *ptr++ = 0;
1079
1080 /* --- envp --- */
1081 VG_(client_envp) = (Char **)ptr;
1082 for (cpp = orig_envp; cpp && *cpp; ptr++, cpp++)
1083 *ptr = (addr_t)copy_str(&strtab, *cpp);
1084 *ptr++ = 0;
1085
1086 /* --- auxv --- */
1087 auxv = (struct ume_auxv *)ptr;
1088 *client_auxv = (UInt *)auxv;
1089
1090 for (; orig_auxv->a_type != AT_NULL; auxv++, orig_auxv++) {
1091 /* copy the entry... */
1092 *auxv = *orig_auxv;
1093
1094 /* ...and fix up the copy */
1095 switch(auxv->a_type) {
1096 case AT_PHDR:
1097 if (info->phdr == 0)
1098 auxv->a_type = AT_IGNORE;
1099 else
1100 auxv->u.a_val = info->phdr;
1101 break;
1102
1103 case AT_PHNUM:
1104 if (info->phdr == 0)
1105 auxv->a_type = AT_IGNORE;
1106 else
1107 auxv->u.a_val = info->phnum;
1108 break;
1109
1110 case AT_BASE:
1111 if (info->interp_base == 0)
1112 auxv->a_type = AT_IGNORE;
1113 else
1114 auxv->u.a_val = info->interp_base;
1115 break;
1116
1117 case AT_PLATFORM: /* points to a platform description string */
1118 auxv->u.a_ptr = copy_str(&strtab, orig_auxv->u.a_ptr);
1119 break;
1120
1121 case AT_ENTRY:
1122 auxv->u.a_val = info->entry;
1123 break;
1124
1125 case AT_IGNORE:
1126 case AT_EXECFD:
1127 case AT_PHENT:
1128 case AT_PAGESZ:
1129 case AT_FLAGS:
1130 case AT_NOTELF:
1131 case AT_UID:
1132 case AT_EUID:
1133 case AT_GID:
1134 case AT_EGID:
1135 case AT_CLKTCK:
1136 case AT_HWCAP:
1137 case AT_FPUCW:
1138 case AT_DCACHEBSIZE:
1139 case AT_ICACHEBSIZE:
1140 case AT_UCACHEBSIZE:
1141 /* All these are pointerless, so we don't need to do anything
1142 about them. */
1143 break;
1144
1145 case AT_SECURE:
1146 /* If this is 1, then it means that this program is running
1147 suid, and therefore the dynamic linker should be careful
1148 about LD_PRELOAD, etc. However, since stage1 (the thing
1149 the kernel actually execve's) should never be SUID, and we
1150 need LD_PRELOAD/LD_LIBRARY_PATH to work for the client, we
1151 set AT_SECURE to 0. */
1152 auxv->u.a_val = 0;
1153 break;
1154
1155 case AT_SYSINFO:
1156 /* Leave this unmolested for now, but we'll update it later
1157 when we set up the client trampoline code page */
1158 break;
1159
1160 case AT_SYSINFO_EHDR:
1161 /* Trash this, because we don't reproduce it */
1162 auxv->a_type = AT_IGNORE;
1163 break;
1164
1165 default:
1166 /* stomp out anything we don't know about */
1167 if (0)
1168 printf("stomping auxv entry %d\n", auxv->a_type);
1169 auxv->a_type = AT_IGNORE;
1170 break;
1171
1172 }
1173 }
1174 *auxv = *orig_auxv;
1175 vg_assert(auxv->a_type == AT_NULL);
1176
1177 vg_assert((strtab-stringbase) == stringsize);
1178
nethercote5ee67ca2004-06-22 14:00:09 +00001179 /* We know the initial ESP is pointing at argc/argv */
1180 VG_(client_argc) = *(Int*)cl_esp;
1181 VG_(client_argv) = (Char**)(cl_esp + sizeof(Int));
1182
nethercote71980f02004-01-24 18:18:54 +00001183 return cl_esp;
1184}
1185
1186/*====================================================================*/
1187/*=== Find executable ===*/
1188/*====================================================================*/
1189
1190static const char* find_executable(const char* exec)
1191{
1192 vg_assert(NULL != exec);
1193 if (strchr(exec, '/') == NULL) {
1194 /* no '/' - we need to search the path */
1195 char *path = getenv("PATH");
1196 int pathlen = path ? strlen(path) : 0;
1197
1198 int match_exe(const char *entry) {
1199 char buf[pathlen + strlen(entry) + 3];
1200
1201 /* empty PATH element means . */
1202 if (*entry == '\0')
1203 entry = ".";
1204
1205 snprintf(buf, sizeof(buf), "%s/%s", entry, exec);
1206
1207 if (access(buf, R_OK|X_OK) == 0) {
1208 exec = strdup(buf);
1209 vg_assert(NULL != exec);
1210 return 1;
1211 }
1212 return 0;
1213 }
1214 scan_colsep(path, match_exe);
1215 }
1216 return exec;
1217}
1218
1219
1220/*====================================================================*/
1221/*=== Loading tools ===*/
1222/*====================================================================*/
1223
1224static void list_tools(void)
1225{
1226 DIR *dir = opendir(VG_(libdir));
1227 struct dirent *de;
1228 int first = 1;
1229
1230 if (dir == NULL) {
1231 fprintf(stderr, "Can't open %s: %s (installation problem?)\n",
nethercotef4928da2004-06-15 10:54:40 +00001232 VG_(libdir), strerror(errno));
nethercote71980f02004-01-24 18:18:54 +00001233 return;
1234 }
1235
nethercotef4928da2004-06-15 10:54:40 +00001236 while ((de = readdir(dir)) != NULL) {
nethercote71980f02004-01-24 18:18:54 +00001237 int len = strlen(de->d_name);
1238
1239 /* look for vgskin_TOOL.so names */
1240 if (len > (7+1+3) && /* "vgskin_" + at least 1-char toolname + ".so" */
nethercotef4928da2004-06-15 10:54:40 +00001241 strncmp(de->d_name, "vgskin_", 7) == 0 &&
1242 VG_STREQ(de->d_name + len - 3, ".so")) {
1243 if (first) {
1244 fprintf(stderr, "Available tools:\n");
1245 first = 0;
1246 }
1247 de->d_name[len-3] = '\0';
1248 fprintf(stderr, "\t%s\n", de->d_name+7);
nethercote71980f02004-01-24 18:18:54 +00001249 }
1250 }
1251
1252 closedir(dir);
1253
1254 if (first)
nethercotef4928da2004-06-15 10:54:40 +00001255 fprintf(stderr, "No tools available in \"%s\" (installation problem?)\n",
1256 VG_(libdir));
nethercote71980f02004-01-24 18:18:54 +00001257}
1258
1259
1260/* Find and load a tool, and check it looks ok. Also looks to see if there's
1261 * a matching vgpreload_*.so file, and returns its name in *preloadpath. */
1262static void load_tool( const char *toolname, void** handle_out,
1263 ToolInfo** toolinfo_out, char **preloadpath_out )
1264{
1265 Bool ok;
1266 int len = strlen(VG_(libdir)) + strlen(toolname)*2 + 16;
1267 char buf[len];
1268 void* handle;
1269 ToolInfo* toolinfo;
1270 char* preloadpath = NULL;
1271 Int* vg_malloc_redzonep;
1272
1273 // XXX: allowing full paths for --tool option -- does it make sense?
1274 // Doesn't allow for vgpreload_<tool>.so.
1275
1276 if (strchr(toolname, '/') != 0) {
1277 /* toolname contains '/', and so must be a pathname */
1278 handle = dlopen(toolname, RTLD_NOW);
1279 } else {
1280 /* just try in the libdir */
1281 snprintf(buf, len, "%s/vgskin_%s.so", VG_(libdir), toolname);
1282 handle = dlopen(buf, RTLD_NOW);
1283
1284 if (handle != NULL) {
1285 snprintf(buf, len, "%s/vgpreload_%s.so", VG_(libdir), toolname);
1286 if (access(buf, R_OK) == 0) {
1287 preloadpath = strdup(buf);
1288 vg_assert(NULL != preloadpath);
1289 }
1290 }
1291 }
1292
1293 ok = (NULL != handle);
1294 if (!ok) {
1295 fprintf(stderr, "Can't open tool \"%s\": %s\n", toolname, dlerror());
1296 goto bad_load;
1297 }
1298
1299 toolinfo = dlsym(handle, "vgSkin_tool_info");
1300 ok = (NULL != toolinfo);
1301 if (!ok) {
1302 fprintf(stderr, "Tool \"%s\" doesn't define SK_(tool_info) - "
1303 "add VG_DETERMINE_INTERFACE_VERSION?\n", toolname);
1304 goto bad_load;
1305 }
1306
1307 ok = (toolinfo->sizeof_ToolInfo == sizeof(*toolinfo) &&
1308 toolinfo->interface_major_version == VG_CORE_INTERFACE_MAJOR_VERSION &&
1309 toolinfo->sk_pre_clo_init != NULL);
1310 if (!ok) {
1311 fprintf(stderr, "Error:\n"
1312 " Tool and core interface versions do not match.\n"
1313 " Interface version used by core is: %d.%d (size %d)\n"
1314 " Interface version used by tool is: %d.%d (size %d)\n"
1315 " The major version numbers must match.\n",
1316 VG_CORE_INTERFACE_MAJOR_VERSION,
1317 VG_CORE_INTERFACE_MINOR_VERSION,
1318 sizeof(*toolinfo),
1319 toolinfo->interface_major_version,
1320 toolinfo->interface_minor_version,
1321 toolinfo->sizeof_ToolInfo);
1322 fprintf(stderr, " You need to at least recompile, and possibly update,\n");
1323 if (VG_CORE_INTERFACE_MAJOR_VERSION > toolinfo->interface_major_version)
1324 fprintf(stderr, " your skin to work with this version of Valgrind.\n");
1325 else
1326 fprintf(stderr, " your version of Valgrind to work with this skin.\n");
1327 goto bad_load;
1328 }
1329
1330 // Set redzone size for V's allocator
1331 vg_malloc_redzonep = dlsym(handle, STR(VG_(vg_malloc_redzone_szB)));
1332 if ( NULL != vg_malloc_redzonep ) {
1333 VG_(vg_malloc_redzone_szB) = *vg_malloc_redzonep;
1334 }
1335
1336 vg_assert(NULL != handle && NULL != toolinfo);
1337 *handle_out = handle;
1338 *toolinfo_out = toolinfo;
1339 *preloadpath_out = preloadpath;
1340 return;
1341
1342
1343 bad_load:
1344 if (handle != NULL)
1345 dlclose(handle);
1346
nethercotef4928da2004-06-15 10:54:40 +00001347 fprintf(stderr, "valgrind: couldn't load tool\n");
nethercote71980f02004-01-24 18:18:54 +00001348 list_tools();
1349 exit(127);
1350}
1351
nethercotef4928da2004-06-15 10:54:40 +00001352
1353/*====================================================================*/
1354/*=== Command line errors ===*/
1355/*====================================================================*/
1356
1357static void abort_msg ( void )
1358{
nethercotef8548672004-06-21 12:42:35 +00001359 VG_(clo_log_to) = VgLogTo_Fd;
1360 VG_(clo_log_fd) = 2; /* stderr */
nethercotef4928da2004-06-15 10:54:40 +00001361}
1362
1363void VG_(bad_option) ( Char* opt )
1364{
1365 abort_msg();
1366 VG_(printf)("valgrind: Bad option `%s'; aborting.\n", opt);
1367 VG_(printf)("valgrind: Use --help for more information.\n");
1368 VG_(exit)(1);
1369}
1370
1371static void missing_tool_option ( void )
1372{
1373 abort_msg();
1374 VG_(printf)("valgrind: Missing --tool option\n");
1375 list_tools();
1376 VG_(printf)("valgrind: Use --help for more information.\n");
1377 VG_(exit)(1);
1378}
1379
1380static void missing_prog ( void )
1381{
1382 abort_msg();
1383 VG_(printf)("valgrind: no program specified\n");
1384 VG_(printf)("valgrind: Use --help for more information.\n");
1385 VG_(exit)(1);
1386}
1387
1388static void config_error ( Char* msg )
1389{
1390 abort_msg();
1391 VG_(printf)("valgrind: Startup or configuration error:\n %s\n", msg);
1392 VG_(printf)("valgrind: Unable to start up properly. Giving up.\n");
1393 VG_(exit)(1);
1394}
1395
1396
nethercote71980f02004-01-24 18:18:54 +00001397/*====================================================================*/
1398/*=== Loading the client ===*/
1399/*====================================================================*/
1400
nethercotef4928da2004-06-15 10:54:40 +00001401static void load_client(char* cl_argv[], const char* exec, Int need_help,
nethercote71980f02004-01-24 18:18:54 +00001402 /*out*/struct exeinfo* info, /*out*/Addr* client_eip)
1403{
1404 // If they didn't specify an executable with --exec, and didn't specify
1405 // --help, then use client argv[0] (searching $PATH if necessary).
nethercotef4928da2004-06-15 10:54:40 +00001406 if (NULL == exec && !need_help) {
nethercote71980f02004-01-24 18:18:54 +00001407 if (cl_argv[0] == NULL ||
1408 ( NULL == (exec = find_executable(cl_argv[0])) ) )
1409 {
nethercotef4928da2004-06-15 10:54:40 +00001410 missing_prog();
nethercote71980f02004-01-24 18:18:54 +00001411 }
1412 }
1413
1414 info->map_base = VG_(client_mapbase);
nethercote71980f02004-01-24 18:18:54 +00001415
1416 info->exe_base = VG_(client_base);
1417 info->exe_end = VG_(client_end);
1418 info->argv = cl_argv;
1419
nethercotef4928da2004-06-15 10:54:40 +00001420 if (need_help) {
nethercote71980f02004-01-24 18:18:54 +00001421 VG_(clexecfd) = -1;
1422 info->argv0 = NULL;
1423 info->argv1 = NULL;
1424 } else {
1425 Int ret;
1426 VG_(clexecfd) = VG_(open)(exec, O_RDONLY, VKI_S_IRUSR);
1427 ret = do_exec(exec, info);
1428 if (ret != 0) {
nethercotef4928da2004-06-15 10:54:40 +00001429 fprintf(stderr, "valgrind: do_exec(%s) failed: %s\n", exec, strerror(ret));
nethercote71980f02004-01-24 18:18:54 +00001430 exit(127);
1431 }
1432 }
1433
1434 /* Copy necessary bits of 'info' that were filled in */
1435 *client_eip = info->init_eip;
1436 VG_(brk_base) = VG_(brk_limit) = info->brkbase;
1437}
1438
1439
1440/*====================================================================*/
1441/*=== Command-line: variables, processing ===*/
1442/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +00001443
njn25e49d8e72002-09-23 09:36:25 +00001444/* Define, and set defaults. */
1445Bool VG_(clo_error_limit) = True;
nethercote04d0fbc2004-01-26 16:48:06 +00001446Bool VG_(clo_db_attach) = False;
1447Char* VG_(clo_db_command) = VG_CLO_DEFAULT_DBCOMMAND;
njn43c799e2003-04-08 00:08:52 +00001448Bool VG_(clo_gen_suppressions) = False;
nethercote27fec902004-06-16 21:26:32 +00001449Int VG_(clo_sanity_level) = 1;
njn25e49d8e72002-09-23 09:36:25 +00001450Int VG_(clo_verbosity) = 1;
1451Bool VG_(clo_demangle) = True;
njn25e49d8e72002-09-23 09:36:25 +00001452Bool VG_(clo_trace_children) = False;
sewardj4cf05692002-10-27 20:28:29 +00001453
nethercotee1730692003-11-20 10:38:07 +00001454/* See big comment in vg_include.h for meaning of these three.
1455 fd is initially stdout, for --help, but gets moved to stderr by default
1456 immediately afterwards. */
sewardj4cf05692002-10-27 20:28:29 +00001457VgLogTo VG_(clo_log_to) = VgLogTo_Fd;
nethercotef8548672004-06-21 12:42:35 +00001458Int VG_(clo_log_fd) = 1;
1459Char* VG_(clo_log_name) = NULL;
sewardj4cf05692002-10-27 20:28:29 +00001460
sewardj6024b212003-07-13 10:54:33 +00001461Int VG_(clo_input_fd) = 0; /* stdin */
njn25e49d8e72002-09-23 09:36:25 +00001462Int VG_(clo_n_suppressions) = 0;
sewardjde4a1d02002-03-22 01:27:54 +00001463Char* VG_(clo_suppressions)[VG_CLO_MAX_SFILES];
njn25e49d8e72002-09-23 09:36:25 +00001464Bool VG_(clo_profile) = False;
1465Bool VG_(clo_single_step) = False;
1466Bool VG_(clo_optimise) = True;
1467UChar VG_(clo_trace_codegen) = 0; // 00000000b
1468Bool VG_(clo_trace_syscalls) = False;
1469Bool VG_(clo_trace_signals) = False;
1470Bool VG_(clo_trace_symtab) = False;
njn25e49d8e72002-09-23 09:36:25 +00001471Bool VG_(clo_trace_sched) = False;
1472Int VG_(clo_trace_pthread_level) = 0;
njn25e49d8e72002-09-23 09:36:25 +00001473Int VG_(clo_dump_error) = 0;
1474Int VG_(clo_backtrace_size) = 4;
1475Char* VG_(clo_weird_hacks) = NULL;
sewardj858964b2002-10-05 14:15:43 +00001476Bool VG_(clo_run_libc_freeres) = True;
rjwalshf5f536f2003-11-17 17:45:00 +00001477Bool VG_(clo_track_fds) = False;
sewardj22854b92002-11-30 14:00:47 +00001478Bool VG_(clo_chain_bb) = True;
nethercote77eba602003-11-13 17:35:04 +00001479Bool VG_(clo_show_below_main) = False;
fitzhardinge98abfc72003-12-16 02:05:15 +00001480Bool VG_(clo_pointercheck) = True;
fitzhardinge462f4f92003-12-18 02:10:54 +00001481Bool VG_(clo_branchpred) = False;
sewardj2370f3b2002-11-30 15:01:01 +00001482
jsgf855d93d2003-10-13 22:26:55 +00001483static Bool VG_(clo_wait_for_gdb) = False;
1484
1485/* If we're doing signal routing, poll for signals every 50mS by
1486 default. */
1487Int VG_(clo_signal_polltime) = 50;
1488
1489/* These flags reduce thread wakeup latency on syscall completion and
1490 signal delivery, respectively. The downside is possible unfairness. */
1491Bool VG_(clo_lowlat_syscalls) = False; /* low-latency syscalls */
1492Bool VG_(clo_lowlat_signals) = False; /* low-latency signals */
1493
sewardjde4a1d02002-03-22 01:27:54 +00001494
nethercote6c999f22004-01-31 22:55:15 +00001495void usage ( Bool debug_help )
njn7cf0bd32002-06-08 13:36:03 +00001496{
njn25e49d8e72002-09-23 09:36:25 +00001497 Char* usage1 =
nethercote71980f02004-01-24 18:18:54 +00001498"usage: valgrind --tool=<toolname> [options] prog-and-args\n"
njn25e49d8e72002-09-23 09:36:25 +00001499"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001500" common user options for all Valgrind tools, with defaults in [ ]:\n"
nethercote0d588502004-06-21 13:27:11 +00001501" --tool=<name> use the Valgrind tool named <name>\n"
nethercotea76368b2004-06-16 11:56:29 +00001502" -h --help show this message\n"
nethercote6c999f22004-01-31 22:55:15 +00001503" --help-debug show this message, plus debugging options\n"
njn25e49d8e72002-09-23 09:36:25 +00001504" --version show version\n"
njn25e49d8e72002-09-23 09:36:25 +00001505" -q --quiet run silently; only print error msgs\n"
1506" -v --verbose be more verbose, incl counts of errors\n"
nethercote77eba602003-11-13 17:35:04 +00001507" --trace-children=no|yes Valgrind-ise child processes? [no]\n"
nethercote0d588502004-06-21 13:27:11 +00001508" --track-fds=no|yes track open file descriptors? [no]\n"
nethercote2b0793f2003-12-02 10:41:18 +00001509"\n"
1510" uncommon user options for all Valgrind tools:\n"
nethercote0d588502004-06-21 13:27:11 +00001511" --run-libc-freeres=no|yes free up glibc memory at exit? [yes]\n"
1512" --weird-hacks=hack1,hack2,... recognised hacks: lax-ioctls [none]\n"
1513" --signal-polltime=<time> signal poll period (mS) for older kernels [50]\n"
1514" --lowlat-signals=no|yes improve thread signal wake-up latency [no]\n"
1515" --lowlat-syscalls=no|yes improve thread syscall wake-up latency [no]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001516" --pointercheck=no|yes enforce client address space limits [yes]\n"
njn25e49d8e72002-09-23 09:36:25 +00001517"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001518" user options for Valgrind tools that report errors:\n"
nethercotef8548672004-06-21 12:42:35 +00001519" --log-fd=<number> log messages to file descriptor [2=stderr]\n"
1520" --log-file=<file> log messages to <file>.pid<pid>\n"
1521" --log-socket=ipaddr:port log messages to socket ipaddr:port\n"
nethercote2b0793f2003-12-02 10:41:18 +00001522" --demangle=no|yes automatically demangle C++ names? [yes]\n"
1523" --num-callers=<number> show <num> callers in stack traces [4]\n"
1524" --error-limit=no|yes stop showing new errors if too many? [yes]\n"
1525" --show-below-main=no|yes continue stack traces below main() [no]\n"
1526" --suppressions=<filename> suppress errors described in <filename>\n"
1527" --gen-suppressions=no|yes print suppressions for errors detected [no]\n"
nethercote04d0fbc2004-01-26 16:48:06 +00001528" --db-attach=no|yes start debugger when errors detected? [no]\n"
1529" --db-command=<command> command to start debugger [gdb -nw %%f %%p]\n"
1530" --input-fd=<number> file descriptor for input [0=stdin]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001531"\n";
njn7cf0bd32002-06-08 13:36:03 +00001532
njn25e49d8e72002-09-23 09:36:25 +00001533 Char* usage2 =
1534"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001535" debugging options for all Valgrind tools:\n"
njn25e49d8e72002-09-23 09:36:25 +00001536" --sanity-level=<number> level of sanity checking to do [1]\n"
1537" --single-step=no|yes translate each instr separately? [no]\n"
1538" --optimise=no|yes improve intermediate code? [yes]\n"
nethercote137bc552003-11-14 17:47:54 +00001539" --profile=no|yes profile? (tool must be built for it) [no]\n"
sewardj22854b92002-11-30 14:00:47 +00001540" --chain-bb=no|yes do basic-block chaining? [yes]\n"
fitzhardinge462f4f92003-12-18 02:10:54 +00001541" --branchpred=yes|no generate branch prediction hints [no]\n"
njn25e49d8e72002-09-23 09:36:25 +00001542" --trace-codegen=<XXXXX> show generated code? (X = 0|1) [00000]\n"
1543" --trace-syscalls=no|yes show all system calls? [no]\n"
1544" --trace-signals=no|yes show signal handling details? [no]\n"
1545" --trace-symtab=no|yes show symbol table details? [no]\n"
njn25e49d8e72002-09-23 09:36:25 +00001546" --trace-sched=no|yes show thread scheduler details? [no]\n"
njn3e884182003-04-15 13:03:23 +00001547" --trace-pthread=none|some|all show pthread event details? [none]\n"
jsgf855d93d2003-10-13 22:26:55 +00001548" --wait-for-gdb=yes|no pause on startup to wait for gdb attach\n"
njn25e49d8e72002-09-23 09:36:25 +00001549"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001550" debugging options for Valgrind tools that report errors\n"
1551" --dump-error=<number> show translation for basic block associated\n"
1552" with <number>'th error context [0=show none]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001553"\n";
njn3e884182003-04-15 13:03:23 +00001554
1555 Char* usage3 =
1556"\n"
nethercote71980f02004-01-24 18:18:54 +00001557" Extra options read from ~/.valgrindrc, $VALGRIND_OPTS, ./.valgrindrc\n"
njn25e49d8e72002-09-23 09:36:25 +00001558"\n"
nethercotebb1c9912004-01-04 16:43:23 +00001559" Valgrind is Copyright (C) 2000-2004 Julian Seward\n"
njn25e49d8e72002-09-23 09:36:25 +00001560" and licensed under the GNU General Public License, version 2.\n"
1561" Bug reports, feedback, admiration, abuse, etc, to: %s.\n"
njnd04b7c62002-10-03 14:05:52 +00001562"\n"
nethercote137bc552003-11-14 17:47:54 +00001563" Tools are copyright and licensed by their authors. See each\n"
1564" tool's start-up message for more information.\n"
njn25e49d8e72002-09-23 09:36:25 +00001565"\n";
njn7cf0bd32002-06-08 13:36:03 +00001566
fitzhardinge98abfc72003-12-16 02:05:15 +00001567 VG_(printf)(usage1);
1568 if (VG_(details).name) {
1569 VG_(printf)(" user options for %s:\n", VG_(details).name);
fitzhardinge98abfc72003-12-16 02:05:15 +00001570 if (VG_(needs).command_line_options)
1571 SK_(print_usage)();
1572 else
1573 VG_(printf)(" (none)\n");
1574 }
nethercote6c999f22004-01-31 22:55:15 +00001575 if (debug_help) {
1576 VG_(printf)(usage2);
fitzhardinge98abfc72003-12-16 02:05:15 +00001577
nethercote6c999f22004-01-31 22:55:15 +00001578 if (VG_(details).name) {
1579 VG_(printf)(" debugging options for %s:\n", VG_(details).name);
1580
1581 if (VG_(needs).command_line_options)
1582 SK_(print_debug_usage)();
1583 else
1584 VG_(printf)(" (none)\n");
1585 }
fitzhardinge98abfc72003-12-16 02:05:15 +00001586 }
nethercote421281e2003-11-20 16:20:55 +00001587 VG_(printf)(usage3, VG_BUGS_TO);
nethercotef4928da2004-06-15 10:54:40 +00001588 VG_(exit)(0);
njn7cf0bd32002-06-08 13:36:03 +00001589}
sewardjde4a1d02002-03-22 01:27:54 +00001590
nethercote71980f02004-01-24 18:18:54 +00001591static void pre_process_cmd_line_options
nethercote6c999f22004-01-31 22:55:15 +00001592 ( Int* need_help, const char** tool, const char** exec )
sewardj1c1b1162003-02-23 01:25:51 +00001593{
nethercote71980f02004-01-24 18:18:54 +00001594 UInt i;
sewardjde4a1d02002-03-22 01:27:54 +00001595
nethercote71980f02004-01-24 18:18:54 +00001596 /* parse the options we have (only the options we care about now) */
1597 for (i = 1; i < VG_(vg_argc); i++) {
1598
1599 if (strcmp(VG_(vg_argv)[i], "--version") == 0) {
1600 printf("valgrind-" VERSION "\n");
nethercotef4928da2004-06-15 10:54:40 +00001601 exit(0);
nethercote71980f02004-01-24 18:18:54 +00001602
nethercotea76368b2004-06-16 11:56:29 +00001603 } else if (VG_CLO_STREQ(VG_(vg_argv)[i], "--help") ||
1604 VG_CLO_STREQ(VG_(vg_argv)[i], "-h")) {
nethercote6c999f22004-01-31 22:55:15 +00001605 *need_help = 1;
1606
nethercotef4928da2004-06-15 10:54:40 +00001607 } else if (VG_CLO_STREQ(VG_(vg_argv)[i], "--help-debug")) {
nethercote6c999f22004-01-31 22:55:15 +00001608 *need_help = 2;
nethercote71980f02004-01-24 18:18:54 +00001609
nethercotef4928da2004-06-15 10:54:40 +00001610 } else if (VG_CLO_STREQN(7, VG_(vg_argv)[i], "--tool=") ||
1611 VG_CLO_STREQN(7, VG_(vg_argv)[i], "--skin=")) {
nethercote71980f02004-01-24 18:18:54 +00001612 *tool = &VG_(vg_argv)[i][7];
1613
nethercotef4928da2004-06-15 10:54:40 +00001614 } else if (VG_CLO_STREQN(7, VG_(vg_argv)[i], "--exec=")) {
nethercote71980f02004-01-24 18:18:54 +00001615 *exec = &VG_(vg_argv)[i][7];
1616 }
1617 }
1618
nethercotef4928da2004-06-15 10:54:40 +00001619 /* If no tool specified, can act appropriately without loading tool */
nethercote71980f02004-01-24 18:18:54 +00001620 if (*tool == NULL) {
nethercotef4928da2004-06-15 10:54:40 +00001621 if (0 == *need_help) {
1622 // neither --tool nor --help/--help-debug specified
1623 missing_tool_option();
1624 } else {
1625 // Give help message, without any tool-specific help
1626 usage(/*help-debug?*/2 == *need_help);
1627 }
nethercote71980f02004-01-24 18:18:54 +00001628 }
1629}
1630
nethercote5ee67ca2004-06-22 14:00:09 +00001631static void process_cmd_line_options( UInt* client_auxv, const char* toolname )
nethercote71980f02004-01-24 18:18:54 +00001632{
nethercotef8548672004-06-21 12:42:35 +00001633 Int i, eventually_log_fd;
nethercote71980f02004-01-24 18:18:54 +00001634 Int *auxp;
1635 Int toolname_len = VG_(strlen)(toolname);
sewardjde4a1d02002-03-22 01:27:54 +00001636
nethercotee1730692003-11-20 10:38:07 +00001637 /* log to stderr by default, but usage message goes to stdout */
nethercotef8548672004-06-21 12:42:35 +00001638 eventually_log_fd = 2;
sewardjde4a1d02002-03-22 01:27:54 +00001639
sewardj19d81412002-06-03 01:10:40 +00001640 /* Check for sane path in ./configure --prefix=... */
fitzhardinge98abfc72003-12-16 02:05:15 +00001641 if (VG_LIBDIR[0] != '/')
sewardj19d81412002-06-03 01:10:40 +00001642 config_error("Please use absolute paths in "
1643 "./configure --prefix=... or --libdir=...");
sewardj38170912002-05-10 21:07:22 +00001644
nethercote71980f02004-01-24 18:18:54 +00001645 for (auxp = client_auxv; auxp[0] != VKI_AT_NULL; auxp += 2) {
fitzhardinge98abfc72003-12-16 02:05:15 +00001646 switch(auxp[0]) {
1647 case VKI_AT_SYSINFO:
1648 VG_(sysinfo_page_exists) = True;
fitzhardinge92360792003-12-24 10:11:11 +00001649 auxp[1] = (Int)(VG_(client_trampoline_code) + VG_(tramp_syscall_offset));
fitzhardinge98abfc72003-12-16 02:05:15 +00001650 VG_(sysinfo_page_addr) = auxp[1];
1651 break;
sewardjde4a1d02002-03-22 01:27:54 +00001652 }
fitzhardinge98abfc72003-12-16 02:05:15 +00001653 }
sewardjde4a1d02002-03-22 01:27:54 +00001654
nethercote71980f02004-01-24 18:18:54 +00001655 for (i = 1; i < VG_(vg_argc); i++) {
1656
1657 Char* arg = VG_(vg_argv)[i];
1658
1659 // XXX: allow colons in options, for Josef
1660
1661 /* Look for matching "--toolname:foo" */
1662 if (VG_(strstr)(arg, ":")) {
1663 if (VG_CLO_STREQN(2, arg, "--") &&
1664 VG_CLO_STREQN(toolname_len, arg+2, toolname) &&
1665 VG_CLO_STREQN(1, arg+2+toolname_len, ":"))
1666 {
1667 // prefix matches, convert "--toolname:foo" to "--foo"
1668 if (0)
1669 VG_(printf)("tool-specific arg: %s\n", arg);
1670 arg += toolname_len + 1;
1671 arg[0] = '-';
1672 arg[1] = '-';
1673
1674 } else {
1675 // prefix doesn't match, skip to next arg
1676 continue;
1677 }
1678 }
1679
fitzhardinge98abfc72003-12-16 02:05:15 +00001680 /* Ignore these options - they've already been handled */
nethercote71980f02004-01-24 18:18:54 +00001681 if (VG_CLO_STREQN(7, arg, "--tool=") ||
1682 VG_CLO_STREQN(7, arg, "--skin="))
fitzhardinge98abfc72003-12-16 02:05:15 +00001683 continue;
nethercote71980f02004-01-24 18:18:54 +00001684 if (VG_CLO_STREQN(7, arg, "--exec="))
fitzhardinge98abfc72003-12-16 02:05:15 +00001685 continue;
1686
nethercote71980f02004-01-24 18:18:54 +00001687 if ( VG_CLO_STREQ(arg, "--"))
fitzhardinge98abfc72003-12-16 02:05:15 +00001688 continue;
nethercote27fec902004-06-16 21:26:32 +00001689
nethercote71980f02004-01-24 18:18:54 +00001690 else if (VG_CLO_STREQ(arg, "-v") ||
1691 VG_CLO_STREQ(arg, "--verbose"))
sewardjde4a1d02002-03-22 01:27:54 +00001692 VG_(clo_verbosity)++;
nethercote27fec902004-06-16 21:26:32 +00001693
nethercote71980f02004-01-24 18:18:54 +00001694 else if (VG_CLO_STREQ(arg, "-q") ||
1695 VG_CLO_STREQ(arg, "--quiet"))
sewardjde4a1d02002-03-22 01:27:54 +00001696 VG_(clo_verbosity)--;
1697
nethercote27fec902004-06-16 21:26:32 +00001698 else VG_BOOL_CLO("--branchpred", VG_(clo_branchpred))
1699 else VG_BOOL_CLO("--chain-bb", VG_(clo_chain_bb))
1700 else VG_BOOL_CLO("--db-attach", VG_(clo_db_attach))
1701 else VG_BOOL_CLO("--demangle", VG_(clo_demangle))
1702 else VG_BOOL_CLO("--error-limit", VG_(clo_error_limit))
1703 else VG_BOOL_CLO("--gen-suppressions", VG_(clo_gen_suppressions))
1704 else VG_BOOL_CLO("--lowlat-signals", VG_(clo_lowlat_signals))
1705 else VG_BOOL_CLO("--lowlat-syscalls", VG_(clo_lowlat_syscalls))
1706 else VG_BOOL_CLO("--optimise", VG_(clo_optimise))
1707 else VG_BOOL_CLO("--pointercheck", VG_(clo_pointercheck))
1708 else VG_BOOL_CLO("--profile", VG_(clo_profile))
1709 else VG_BOOL_CLO("--run-libc-freeres", VG_(clo_run_libc_freeres))
1710 else VG_BOOL_CLO("--show-below-main", VG_(clo_show_below_main))
1711 else VG_BOOL_CLO("--single-step", VG_(clo_single_step))
1712 else VG_BOOL_CLO("--track-fds", VG_(clo_track_fds))
1713 else VG_BOOL_CLO("--trace-children", VG_(clo_trace_children))
1714 else VG_BOOL_CLO("--trace-sched", VG_(clo_trace_sched))
1715 else VG_BOOL_CLO("--trace-signals", VG_(clo_trace_signals))
1716 else VG_BOOL_CLO("--trace-symtab", VG_(clo_trace_symtab))
1717 else VG_BOOL_CLO("--trace-syscalls", VG_(clo_trace_syscalls))
1718 else VG_BOOL_CLO("--wait-for-gdb", VG_(clo_wait_for_gdb))
sewardj72f98ff2002-06-13 17:23:38 +00001719
nethercote27fec902004-06-16 21:26:32 +00001720 else VG_STR_CLO ("--db-command", VG_(clo_db_command))
1721 else VG_STR_CLO ("--weird-hacks", VG_(clo_weird_hacks))
sewardjde4a1d02002-03-22 01:27:54 +00001722
nethercote27fec902004-06-16 21:26:32 +00001723 else VG_NUM_CLO ("--dump-error", VG_(clo_dump_error))
1724 else VG_NUM_CLO ("--input-fd", VG_(clo_input_fd))
1725 else VG_NUM_CLO ("--sanity-level", VG_(clo_sanity_level))
1726 else VG_NUM_CLO ("--signal­polltime", VG_(clo_signal_polltime))
1727 else VG_BNUM_CLO("--num-callers", VG_(clo_backtrace_size), 1,
1728 VG_DEEPEST_BACKTRACE)
sewardjde4a1d02002-03-22 01:27:54 +00001729
nethercotef8548672004-06-21 12:42:35 +00001730 // for backwards compatibility, replaced by --log-fd
nethercote71980f02004-01-24 18:18:54 +00001731 else if (VG_CLO_STREQN(13, arg, "--logfile-fd=")) {
nethercotef8548672004-06-21 12:42:35 +00001732 VG_(clo_log_to) = VgLogTo_Fd;
1733 VG_(clo_log_name) = NULL;
1734 eventually_log_fd = (Int)VG_(atoll)(&arg[13]);
1735 }
1736 else if (VG_CLO_STREQN(9, arg, "--log-fd=")) {
1737 VG_(clo_log_to) = VgLogTo_Fd;
1738 VG_(clo_log_name) = NULL;
1739 eventually_log_fd = (Int)VG_(atoll)(&arg[9]);
sewardj4cf05692002-10-27 20:28:29 +00001740 }
1741
nethercotef8548672004-06-21 12:42:35 +00001742 // for backwards compatibility, replaced by --log-file
nethercote71980f02004-01-24 18:18:54 +00001743 else if (VG_CLO_STREQN(10, arg, "--logfile=")) {
nethercotef8548672004-06-21 12:42:35 +00001744 VG_(clo_log_to) = VgLogTo_File;
1745 VG_(clo_log_name) = &arg[10];
1746 }
1747 else if (VG_CLO_STREQN(11, arg, "--log-file=")) {
1748 VG_(clo_log_to) = VgLogTo_File;
1749 VG_(clo_log_name) = &arg[11];
sewardj4cf05692002-10-27 20:28:29 +00001750 }
sewardjde4a1d02002-03-22 01:27:54 +00001751
nethercotef8548672004-06-21 12:42:35 +00001752 // for backwards compatibility, replaced by --log-socket
nethercote71980f02004-01-24 18:18:54 +00001753 else if (VG_CLO_STREQN(12, arg, "--logsocket=")) {
nethercotef8548672004-06-21 12:42:35 +00001754 VG_(clo_log_to) = VgLogTo_Socket;
1755 VG_(clo_log_name) = &arg[12];
1756 }
1757 else if (VG_CLO_STREQN(13, arg, "--log-socket=")) {
1758 VG_(clo_log_to) = VgLogTo_Socket;
1759 VG_(clo_log_name) = &arg[13];
sewardj73cf3bc2002-11-03 03:20:15 +00001760 }
1761
nethercote71980f02004-01-24 18:18:54 +00001762 else if (VG_CLO_STREQN(15, arg, "--suppressions=")) {
sewardjde4a1d02002-03-22 01:27:54 +00001763 if (VG_(clo_n_suppressions) >= VG_CLO_MAX_SFILES) {
njn25e49d8e72002-09-23 09:36:25 +00001764 VG_(message)(Vg_UserMsg, "Too many suppression files specified.");
sewardjde4a1d02002-03-22 01:27:54 +00001765 VG_(message)(Vg_UserMsg,
1766 "Increase VG_CLO_MAX_SFILES and recompile.");
nethercote71980f02004-01-24 18:18:54 +00001767 VG_(bad_option)(arg);
sewardjde4a1d02002-03-22 01:27:54 +00001768 }
nethercote71980f02004-01-24 18:18:54 +00001769 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = &arg[15];
sewardjde4a1d02002-03-22 01:27:54 +00001770 VG_(clo_n_suppressions)++;
1771 }
sewardjde4a1d02002-03-22 01:27:54 +00001772
njn25e49d8e72002-09-23 09:36:25 +00001773 /* "vwxyz" --> 000zyxwv (binary) */
nethercote71980f02004-01-24 18:18:54 +00001774 else if (VG_CLO_STREQN(16, arg, "--trace-codegen=")) {
njn25e49d8e72002-09-23 09:36:25 +00001775 Int j;
nethercote71980f02004-01-24 18:18:54 +00001776 char* opt = & arg[16];
njn25e49d8e72002-09-23 09:36:25 +00001777
1778 if (5 != VG_(strlen)(opt)) {
1779 VG_(message)(Vg_UserMsg,
1780 "--trace-codegen argument must have 5 digits");
nethercote71980f02004-01-24 18:18:54 +00001781 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001782 }
1783 for (j = 0; j < 5; j++) {
1784 if ('0' == opt[j]) { /* do nothing */ }
1785 else if ('1' == opt[j]) VG_(clo_trace_codegen) |= (1 << j);
1786 else {
1787 VG_(message)(Vg_UserMsg, "--trace-codegen argument can only "
1788 "contain 0s and 1s");
nethercote71980f02004-01-24 18:18:54 +00001789 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001790 }
1791 }
1792 }
sewardjde4a1d02002-03-22 01:27:54 +00001793
nethercote71980f02004-01-24 18:18:54 +00001794 else if (VG_CLO_STREQ(arg, "--trace-pthread=none"))
sewardj45b4b372002-04-16 22:50:32 +00001795 VG_(clo_trace_pthread_level) = 0;
nethercote71980f02004-01-24 18:18:54 +00001796 else if (VG_CLO_STREQ(arg, "--trace-pthread=some"))
sewardj45b4b372002-04-16 22:50:32 +00001797 VG_(clo_trace_pthread_level) = 1;
nethercote71980f02004-01-24 18:18:54 +00001798 else if (VG_CLO_STREQ(arg, "--trace-pthread=all"))
sewardj45b4b372002-04-16 22:50:32 +00001799 VG_(clo_trace_pthread_level) = 2;
sewardj8937c812002-04-12 20:12:20 +00001800
nethercote71980f02004-01-24 18:18:54 +00001801 else if ( ! VG_(needs).command_line_options
1802 || ! SK_(process_cmd_line_option)(arg) ) {
nethercotef4928da2004-06-15 10:54:40 +00001803 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001804 }
sewardjde4a1d02002-03-22 01:27:54 +00001805 }
1806
nethercote27fec902004-06-16 21:26:32 +00001807 // Check various option values
1808
njnf9ebf672003-05-12 21:41:30 +00001809 if (VG_(clo_verbosity) < 0)
sewardjde4a1d02002-03-22 01:27:54 +00001810 VG_(clo_verbosity) = 0;
1811
nethercote04d0fbc2004-01-26 16:48:06 +00001812 if (VG_(clo_db_attach) && VG_(clo_trace_children)) {
sewardjde4a1d02002-03-22 01:27:54 +00001813 VG_(message)(Vg_UserMsg, "");
1814 VG_(message)(Vg_UserMsg,
nethercote04d0fbc2004-01-26 16:48:06 +00001815 "--db-attach=yes conflicts with --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001816 VG_(message)(Vg_UserMsg,
1817 "Please choose one or the other, but not both.");
nethercote04d0fbc2004-01-26 16:48:06 +00001818 VG_(bad_option)("--db-attach=yes and --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001819 }
1820
nethercotef8548672004-06-21 12:42:35 +00001821 /* Set up logging now. After this is done, VG_(clo_log_fd)
sewardj4cf05692002-10-27 20:28:29 +00001822 should be connected to whatever sink has been selected, and we
1823 indiscriminately chuck stuff into it without worrying what the
1824 nature of it is. Oh the wonder of Unix streams. */
1825
nethercotee1730692003-11-20 10:38:07 +00001826 /* So far we should be still attached to stdout, so we can show on
sewardj4cf05692002-10-27 20:28:29 +00001827 the terminal any problems to do with processing command line
1828 opts. */
nethercotef8548672004-06-21 12:42:35 +00001829 vg_assert(VG_(clo_log_fd) == 1 /* stdout */);
sewardj73cf3bc2002-11-03 03:20:15 +00001830 vg_assert(VG_(logging_to_filedes) == True);
sewardj4cf05692002-10-27 20:28:29 +00001831
1832 switch (VG_(clo_log_to)) {
sewardj73cf3bc2002-11-03 03:20:15 +00001833
sewardj4cf05692002-10-27 20:28:29 +00001834 case VgLogTo_Fd:
nethercotef8548672004-06-21 12:42:35 +00001835 vg_assert(VG_(clo_log_name) == NULL);
1836 VG_(clo_log_fd) = eventually_log_fd;
sewardj4cf05692002-10-27 20:28:29 +00001837 break;
sewardj73cf3bc2002-11-03 03:20:15 +00001838
sewardj4cf05692002-10-27 20:28:29 +00001839 case VgLogTo_File: {
1840 Char logfilename[1000];
jsgff3c3f1a2003-10-14 22:13:28 +00001841 Int seq = 0;
1842 Int pid = VG_(getpid)();
1843
nethercotef8548672004-06-21 12:42:35 +00001844 vg_assert(VG_(clo_log_name) != NULL);
1845 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
jsgff3c3f1a2003-10-14 22:13:28 +00001846
nethercote71980f02004-01-24 18:18:54 +00001847 for (;;) {
jsgff3c3f1a2003-10-14 22:13:28 +00001848 if (seq == 0)
1849 VG_(sprintf)(logfilename, "%s.pid%d",
nethercotef8548672004-06-21 12:42:35 +00001850 VG_(clo_log_name), pid );
jsgff3c3f1a2003-10-14 22:13:28 +00001851 else
1852 VG_(sprintf)(logfilename, "%s.pid%d.%d",
nethercotef8548672004-06-21 12:42:35 +00001853 VG_(clo_log_name), pid, seq );
jsgff3c3f1a2003-10-14 22:13:28 +00001854 seq++;
1855
nethercotef8548672004-06-21 12:42:35 +00001856 eventually_log_fd
jsgff3c3f1a2003-10-14 22:13:28 +00001857 = VG_(open)(logfilename,
1858 VKI_O_CREAT|VKI_O_WRONLY|VKI_O_EXCL|VKI_O_TRUNC,
1859 VKI_S_IRUSR|VKI_S_IWUSR);
nethercotef8548672004-06-21 12:42:35 +00001860 if (eventually_log_fd >= 0) {
1861 VG_(clo_log_fd) = VG_(safe_fd)(eventually_log_fd);
jsgff3c3f1a2003-10-14 22:13:28 +00001862 break;
1863 } else {
nethercotef8548672004-06-21 12:42:35 +00001864 if (eventually_log_fd != -VKI_EEXIST) {
jsgff3c3f1a2003-10-14 22:13:28 +00001865 VG_(message)(Vg_UserMsg,
1866 "Can't create/open log file `%s.pid%d'; giving up!",
nethercotef8548672004-06-21 12:42:35 +00001867 VG_(clo_log_name), pid);
jsgff3c3f1a2003-10-14 22:13:28 +00001868 VG_(bad_option)(
nethercotef8548672004-06-21 12:42:35 +00001869 "--log-file=<file> didn't work out for some reason.");
jsgff3c3f1a2003-10-14 22:13:28 +00001870 break;
1871 }
1872 }
1873 }
sewardj4cf05692002-10-27 20:28:29 +00001874 break;
sewardj73cf3bc2002-11-03 03:20:15 +00001875 }
1876
1877 case VgLogTo_Socket: {
nethercotef8548672004-06-21 12:42:35 +00001878 vg_assert(VG_(clo_log_name) != NULL);
1879 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
1880 eventually_log_fd = VG_(connect_via_socket)( VG_(clo_log_name) );
1881 if (eventually_log_fd == -1) {
sewardj73cf3bc2002-11-03 03:20:15 +00001882 VG_(message)(Vg_UserMsg,
nethercotef8548672004-06-21 12:42:35 +00001883 "Invalid --log-socket=ipaddr or --log-socket=ipaddr:port spec");
sewardj73cf3bc2002-11-03 03:20:15 +00001884 VG_(message)(Vg_UserMsg,
nethercotef8548672004-06-21 12:42:35 +00001885 "of `%s'; giving up!", VG_(clo_log_name) );
sewardj73cf3bc2002-11-03 03:20:15 +00001886 VG_(bad_option)(
nethercotef8548672004-06-21 12:42:35 +00001887 "--log-socket=");
sewardj4cf05692002-10-27 20:28:29 +00001888 }
nethercotef8548672004-06-21 12:42:35 +00001889 if (eventually_log_fd == -2) {
sewardj73cf3bc2002-11-03 03:20:15 +00001890 VG_(message)(Vg_UserMsg,
sewardj570f8902002-11-03 11:44:36 +00001891 "valgrind: failed to connect to logging server `%s'.",
nethercotef8548672004-06-21 12:42:35 +00001892 VG_(clo_log_name) );
sewardj570f8902002-11-03 11:44:36 +00001893 VG_(message)(Vg_UserMsg,
1894 "Log messages will sent to stderr instead." );
1895 VG_(message)(Vg_UserMsg,
1896 "" );
1897 /* We don't change anything here. */
1898 } else {
nethercotef8548672004-06-21 12:42:35 +00001899 vg_assert(eventually_log_fd > 0);
1900 VG_(clo_log_fd) = eventually_log_fd;
sewardj570f8902002-11-03 11:44:36 +00001901 VG_(logging_to_filedes) = False;
1902 }
sewardj73cf3bc2002-11-03 03:20:15 +00001903 break;
1904 }
1905
sewardj4cf05692002-10-27 20:28:29 +00001906 }
1907
nethercotef8548672004-06-21 12:42:35 +00001908 /* Move log_fd into the safe range, so it doesn't conflict with any app fds */
thughesad1c9562004-06-26 11:27:52 +00001909 eventually_log_fd = VG_(fcntl)(VG_(clo_log_fd), VKI_F_DUPFD, VG_(fd_hard_limit));
nethercotef8548672004-06-21 12:42:35 +00001910 if (eventually_log_fd < 0)
jsgf855d93d2003-10-13 22:26:55 +00001911 VG_(message)(Vg_UserMsg, "valgrind: failed to move logfile fd into safe range");
1912 else {
nethercotef8548672004-06-21 12:42:35 +00001913 VG_(clo_log_fd) = eventually_log_fd;
1914 VG_(fcntl)(VG_(clo_log_fd), VKI_F_SETFD, VKI_FD_CLOEXEC);
jsgf855d93d2003-10-13 22:26:55 +00001915 }
1916
sewardj4cf05692002-10-27 20:28:29 +00001917 /* Ok, the logging sink is running now. Print a suitable preamble.
1918 If logging to file or a socket, write details of parent PID and
1919 command line args, to help people trying to interpret the
1920 results of a run which encompasses multiple processes. */
sewardjde4a1d02002-03-22 01:27:54 +00001921
sewardj83adf412002-05-01 01:25:45 +00001922 if (VG_(clo_verbosity > 0)) {
njnd04b7c62002-10-03 14:05:52 +00001923 /* Skin details */
1924 VG_(message)(Vg_UserMsg, "%s%s%s, %s for x86-linux.",
1925 VG_(details).name,
1926 NULL == VG_(details).version ? "" : "-",
1927 NULL == VG_(details).version
1928 ? (Char*)"" : VG_(details).version,
1929 VG_(details).description);
1930 VG_(message)(Vg_UserMsg, "%s", VG_(details).copyright_author);
sewardj3b2736a2002-03-24 12:18:35 +00001931
njnd04b7c62002-10-03 14:05:52 +00001932 /* Core details */
1933 VG_(message)(Vg_UserMsg,
njn3e884182003-04-15 13:03:23 +00001934 "Using valgrind-%s, a program supervision framework for x86-linux.",
sewardj4aa62ba2002-10-05 15:49:27 +00001935 VERSION);
sewardjde4a1d02002-03-22 01:27:54 +00001936 VG_(message)(Vg_UserMsg,
nethercotebb1c9912004-01-04 16:43:23 +00001937 "Copyright (C) 2000-2004, and GNU GPL'd, by Julian Seward.");
njnd04b7c62002-10-03 14:05:52 +00001938 }
1939
nethercotec1e395d2003-11-10 13:26:49 +00001940 if (VG_(clo_verbosity) > 0 && VG_(clo_log_to) != VgLogTo_Fd) {
sewardj4cf05692002-10-27 20:28:29 +00001941 VG_(message)(Vg_UserMsg, "");
1942 VG_(message)(Vg_UserMsg,
1943 "My PID = %d, parent PID = %d. Prog and args are:",
1944 VG_(getpid)(), VG_(getppid)() );
1945 for (i = 0; i < VG_(client_argc); i++)
1946 VG_(message)(Vg_UserMsg, " %s", VG_(client_argv)[i]);
1947 }
1948
sewardjde4a1d02002-03-22 01:27:54 +00001949 if (VG_(clo_verbosity) > 1) {
nethercotea70f7352004-04-18 12:08:46 +00001950 Int fd;
sewardj4cf05692002-10-27 20:28:29 +00001951 if (VG_(clo_log_to) != VgLogTo_Fd)
1952 VG_(message)(Vg_UserMsg, "");
fitzhardinge98abfc72003-12-16 02:05:15 +00001953 VG_(message)(Vg_UserMsg, "Valgrind library directory: %s", VG_(libdir));
njn86dc2bc2003-09-09 07:26:21 +00001954 VG_(message)(Vg_UserMsg, "Command line");
1955 for (i = 0; i < VG_(client_argc); i++)
1956 VG_(message)(Vg_UserMsg, " %s", VG_(client_argv)[i]);
1957
sewardjde4a1d02002-03-22 01:27:54 +00001958 VG_(message)(Vg_UserMsg, "Startup, with flags:");
nethercote71980f02004-01-24 18:18:54 +00001959 for (i = 1; i < VG_(vg_argc); i++) {
1960 VG_(message)(Vg_UserMsg, " %s", VG_(vg_argv)[i]);
sewardjde4a1d02002-03-22 01:27:54 +00001961 }
nethercotea70f7352004-04-18 12:08:46 +00001962
1963 VG_(message)(Vg_UserMsg, "Contents of /proc/version:");
1964 fd = VG_(open) ( "/proc/version", VKI_O_RDONLY, 0 );
1965 if (fd < 0) {
1966 VG_(message)(Vg_UserMsg, " can't open /proc/version");
1967 } else {
1968 #define BUF_LEN 256
1969 Char version_buf[BUF_LEN];
1970 Int n = VG_(read) ( fd, version_buf, BUF_LEN );
1971 vg_assert(n <= 256);
1972 if (n > 0) {
1973 version_buf[n-1] = '\0';
1974 VG_(message)(Vg_UserMsg, " %s", version_buf);
1975 } else {
1976 VG_(message)(Vg_UserMsg, " (empty?)");
1977 }
1978 VG_(close)(fd);
1979 #undef BUF_LEN
1980 }
sewardjde4a1d02002-03-22 01:27:54 +00001981 }
1982
fitzhardinge98abfc72003-12-16 02:05:15 +00001983 if (VG_(clo_n_suppressions) < VG_CLO_MAX_SFILES-1 &&
njn25e49d8e72002-09-23 09:36:25 +00001984 (VG_(needs).core_errors || VG_(needs).skin_errors)) {
fitzhardinge98abfc72003-12-16 02:05:15 +00001985 /* If there are no suppression files specified and the skin
1986 needs one, load the default */
1987 static const Char default_supp[] = "default.supp";
1988 Int len = VG_(strlen)(VG_(libdir)) + 1 + sizeof(default_supp);
1989 Char *buf = VG_(arena_malloc)(VG_AR_CORE, len);
1990 VG_(sprintf)(buf, "%s/%s", VG_(libdir), default_supp);
1991 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = buf;
1992 VG_(clo_n_suppressions)++;
sewardjde4a1d02002-03-22 01:27:54 +00001993 }
sewardj4cf05692002-10-27 20:28:29 +00001994
njn6a230532003-07-21 10:38:23 +00001995 if (VG_(clo_gen_suppressions) &&
1996 !VG_(needs).core_errors && !VG_(needs).skin_errors) {
nethercotef4928da2004-06-15 10:54:40 +00001997 VG_(message)(Vg_UserMsg,
1998 "Can't use --gen-suppressions=yes with this tool,");
1999 VG_(message)(Vg_UserMsg,
2000 "as it doesn't generate errors.");
2001 VG_(bad_option)("--gen-suppressions=yes");
njn6a230532003-07-21 10:38:23 +00002002 }
sewardjde4a1d02002-03-22 01:27:54 +00002003}
2004
sewardjde4a1d02002-03-22 01:27:54 +00002005
nethercote71980f02004-01-24 18:18:54 +00002006/*====================================================================*/
2007/*=== File descriptor setup ===*/
2008/*====================================================================*/
2009
2010static void setup_file_descriptors(void)
2011{
2012 struct vki_rlimit rl;
2013
2014 /* Get the current file descriptor limits. */
2015 if (VG_(getrlimit)(VKI_RLIMIT_NOFILE, &rl) < 0) {
2016 rl.rlim_cur = 1024;
2017 rl.rlim_max = 1024;
2018 }
2019
2020 /* Work out where to move the soft limit to. */
2021 if (rl.rlim_cur + VG_N_RESERVED_FDS <= rl.rlim_max) {
2022 rl.rlim_cur = rl.rlim_cur + VG_N_RESERVED_FDS;
2023 } else {
2024 rl.rlim_cur = rl.rlim_max;
2025 }
2026
2027 /* Reserve some file descriptors for our use. */
thughesad1c9562004-06-26 11:27:52 +00002028 VG_(fd_soft_limit) = rl.rlim_cur - VG_N_RESERVED_FDS;
2029 VG_(fd_hard_limit) = rl.rlim_cur - VG_N_RESERVED_FDS;
nethercote71980f02004-01-24 18:18:54 +00002030
2031 /* Update the soft limit. */
2032 VG_(setrlimit)(VKI_RLIMIT_NOFILE, &rl);
2033
2034 if (VG_(vgexecfd) != -1)
2035 VG_(vgexecfd) = VG_(safe_fd)( VG_(vgexecfd) );
2036 if (VG_(clexecfd) != -1)
2037 VG_(clexecfd) = VG_(safe_fd)( VG_(clexecfd) );
2038}
2039
2040
2041/*====================================================================*/
nethercote1d447092004-02-01 17:29:59 +00002042/*=== baseBlock: definition + setup ===*/
nethercote71980f02004-01-24 18:18:54 +00002043/*====================================================================*/
2044
2045/* The variables storing offsets. */
2046
2047#define INVALID_OFFSET (-1)
2048
2049Int VGOFF_(m_eax) = INVALID_OFFSET;
2050Int VGOFF_(m_ecx) = INVALID_OFFSET;
2051Int VGOFF_(m_edx) = INVALID_OFFSET;
2052Int VGOFF_(m_ebx) = INVALID_OFFSET;
2053Int VGOFF_(m_esp) = INVALID_OFFSET;
2054Int VGOFF_(m_ebp) = INVALID_OFFSET;
2055Int VGOFF_(m_esi) = INVALID_OFFSET;
2056Int VGOFF_(m_edi) = INVALID_OFFSET;
2057Int VGOFF_(m_eflags) = INVALID_OFFSET;
2058Int VGOFF_(m_dflag) = INVALID_OFFSET;
2059Int VGOFF_(m_ssestate) = INVALID_OFFSET;
2060Int VGOFF_(ldt) = INVALID_OFFSET;
2061Int VGOFF_(tls) = INVALID_OFFSET;
2062Int VGOFF_(m_cs) = INVALID_OFFSET;
2063Int VGOFF_(m_ss) = INVALID_OFFSET;
2064Int VGOFF_(m_ds) = INVALID_OFFSET;
2065Int VGOFF_(m_es) = INVALID_OFFSET;
2066Int VGOFF_(m_fs) = INVALID_OFFSET;
2067Int VGOFF_(m_gs) = INVALID_OFFSET;
2068Int VGOFF_(m_eip) = INVALID_OFFSET;
2069Int VGOFF_(spillslots) = INVALID_OFFSET;
2070Int VGOFF_(sh_eax) = INVALID_OFFSET;
2071Int VGOFF_(sh_ecx) = INVALID_OFFSET;
2072Int VGOFF_(sh_edx) = INVALID_OFFSET;
2073Int VGOFF_(sh_ebx) = INVALID_OFFSET;
2074Int VGOFF_(sh_esp) = INVALID_OFFSET;
2075Int VGOFF_(sh_ebp) = INVALID_OFFSET;
2076Int VGOFF_(sh_esi) = INVALID_OFFSET;
2077Int VGOFF_(sh_edi) = INVALID_OFFSET;
2078Int VGOFF_(sh_eflags) = INVALID_OFFSET;
2079
2080Int VGOFF_(helper_idiv_64_32) = INVALID_OFFSET;
2081Int VGOFF_(helper_div_64_32) = INVALID_OFFSET;
2082Int VGOFF_(helper_idiv_32_16) = INVALID_OFFSET;
2083Int VGOFF_(helper_div_32_16) = INVALID_OFFSET;
2084Int VGOFF_(helper_idiv_16_8) = INVALID_OFFSET;
2085Int VGOFF_(helper_div_16_8) = INVALID_OFFSET;
2086Int VGOFF_(helper_imul_32_64) = INVALID_OFFSET;
2087Int VGOFF_(helper_mul_32_64) = INVALID_OFFSET;
2088Int VGOFF_(helper_imul_16_32) = INVALID_OFFSET;
2089Int VGOFF_(helper_mul_16_32) = INVALID_OFFSET;
2090Int VGOFF_(helper_imul_8_16) = INVALID_OFFSET;
2091Int VGOFF_(helper_mul_8_16) = INVALID_OFFSET;
2092Int VGOFF_(helper_CLD) = INVALID_OFFSET;
2093Int VGOFF_(helper_STD) = INVALID_OFFSET;
2094Int VGOFF_(helper_get_dirflag) = INVALID_OFFSET;
2095Int VGOFF_(helper_CLC) = INVALID_OFFSET;
2096Int VGOFF_(helper_STC) = INVALID_OFFSET;
nethercote1018bdd2004-02-11 23:33:29 +00002097Int VGOFF_(helper_CMC) = INVALID_OFFSET;
nethercote71980f02004-01-24 18:18:54 +00002098Int VGOFF_(helper_shldl) = INVALID_OFFSET;
2099Int VGOFF_(helper_shldw) = INVALID_OFFSET;
2100Int VGOFF_(helper_shrdl) = INVALID_OFFSET;
2101Int VGOFF_(helper_shrdw) = INVALID_OFFSET;
2102Int VGOFF_(helper_IN) = INVALID_OFFSET;
2103Int VGOFF_(helper_OUT) = INVALID_OFFSET;
2104Int VGOFF_(helper_RDTSC) = INVALID_OFFSET;
2105Int VGOFF_(helper_CPUID) = INVALID_OFFSET;
2106Int VGOFF_(helper_BSWAP) = INVALID_OFFSET;
nethercote1018bdd2004-02-11 23:33:29 +00002107Int VGOFF_(helper_bsfw) = INVALID_OFFSET;
2108Int VGOFF_(helper_bsfl) = INVALID_OFFSET;
2109Int VGOFF_(helper_bsrw) = INVALID_OFFSET;
2110Int VGOFF_(helper_bsrl) = INVALID_OFFSET;
nethercote71980f02004-01-24 18:18:54 +00002111Int VGOFF_(helper_fstsw_AX) = INVALID_OFFSET;
2112Int VGOFF_(helper_SAHF) = INVALID_OFFSET;
2113Int VGOFF_(helper_LAHF) = INVALID_OFFSET;
2114Int VGOFF_(helper_DAS) = INVALID_OFFSET;
2115Int VGOFF_(helper_DAA) = INVALID_OFFSET;
nethercote1018bdd2004-02-11 23:33:29 +00002116Int VGOFF_(helper_AAS) = INVALID_OFFSET;
2117Int VGOFF_(helper_AAA) = INVALID_OFFSET;
2118Int VGOFF_(helper_AAD) = INVALID_OFFSET;
2119Int VGOFF_(helper_AAM) = INVALID_OFFSET;
nethercote71980f02004-01-24 18:18:54 +00002120Int VGOFF_(helper_cmpxchg8b) = INVALID_OFFSET;
2121Int VGOFF_(helper_undefined_instruction) = INVALID_OFFSET;
2122
2123/* MAX_NONCOMPACT_HELPERS can be increased easily. If MAX_COMPACT_HELPERS is
2124 * increased too much, they won't really be compact any more... */
2125#define MAX_COMPACT_HELPERS 8
2126#define MAX_NONCOMPACT_HELPERS 50
2127
2128UInt VG_(n_compact_helpers) = 0;
2129UInt VG_(n_noncompact_helpers) = 0;
2130
2131Addr VG_(compact_helper_addrs) [MAX_COMPACT_HELPERS];
2132Int VG_(compact_helper_offsets)[MAX_COMPACT_HELPERS];
2133Addr VG_(noncompact_helper_addrs) [MAX_NONCOMPACT_HELPERS];
2134Int VG_(noncompact_helper_offsets)[MAX_NONCOMPACT_HELPERS];
2135
2136/* This is the actual defn of baseblock. */
2137UInt VG_(baseBlock)[VG_BASEBLOCK_WORDS];
2138
nethercote71980f02004-01-24 18:18:54 +00002139/* Words. */
2140static Int baB_off = 0;
2141
2142
sewardjfa492d42002-12-08 18:20:01 +00002143UInt VG_(insertDflag)(UInt eflags, Int d)
2144{
2145 vg_assert(d == 1 || d == -1);
2146 eflags &= ~EFlagD;
2147
2148 if (d < 0)
2149 eflags |= EFlagD;
2150
2151 return eflags;
2152}
2153
2154Int VG_(extractDflag)(UInt eflags)
2155{
2156 Int ret;
2157
2158 if (eflags & EFlagD)
2159 ret = -1;
2160 else
2161 ret = 1;
2162
2163 return ret;
2164}
2165
nethercote71980f02004-01-24 18:18:54 +00002166/* Returns the offset, in words. */
2167static Int alloc_BaB ( Int words )
sewardjde4a1d02002-03-22 01:27:54 +00002168{
nethercote71980f02004-01-24 18:18:54 +00002169 Int off = baB_off;
2170 baB_off += words;
2171 if (baB_off >= VG_BASEBLOCK_WORDS)
2172 VG_(core_panic)( "alloc_BaB: baseBlock is too small");
sewardjde4a1d02002-03-22 01:27:54 +00002173
nethercote71980f02004-01-24 18:18:54 +00002174 return off;
sewardjde4a1d02002-03-22 01:27:54 +00002175}
2176
nethercote71980f02004-01-24 18:18:54 +00002177/* Align offset, in *bytes* */
2178static void align_BaB ( UInt align )
njn25e49d8e72002-09-23 09:36:25 +00002179{
nethercote71980f02004-01-24 18:18:54 +00002180 vg_assert(2 == align || 4 == align || 8 == align || 16 == align);
2181 baB_off += (align-1);
2182 baB_off &= ~(align-1);
njn25e49d8e72002-09-23 09:36:25 +00002183}
2184
nethercote71980f02004-01-24 18:18:54 +00002185/* Allocate 1 word in baseBlock and set it to the given value. */
2186static Int alloc_BaB_1_set ( Addr a )
njn25e49d8e72002-09-23 09:36:25 +00002187{
nethercote71980f02004-01-24 18:18:54 +00002188 Int off = alloc_BaB(1);
2189 VG_(baseBlock)[off] = (UInt)a;
2190 return off;
njn25e49d8e72002-09-23 09:36:25 +00002191}
2192
nethercote71980f02004-01-24 18:18:54 +00002193/* Registers a function in compact_helper_addrs; compact_helper_offsets is
2194 filled in later. */
2195void VG_(register_compact_helper)(Addr a)
sewardjde4a1d02002-03-22 01:27:54 +00002196{
nethercote71980f02004-01-24 18:18:54 +00002197 if (MAX_COMPACT_HELPERS <= VG_(n_compact_helpers)) {
2198 VG_(printf)("Can only register %d compact helpers\n",
2199 MAX_COMPACT_HELPERS);
2200 VG_(core_panic)("Too many compact helpers registered");
2201 }
2202 VG_(compact_helper_addrs)[VG_(n_compact_helpers)] = a;
2203 VG_(n_compact_helpers)++;
2204}
2205
2206/* Registers a function in noncompact_helper_addrs; noncompact_helper_offsets
2207 * is filled in later.
2208 */
2209void VG_(register_noncompact_helper)(Addr a)
2210{
2211 if (MAX_NONCOMPACT_HELPERS <= VG_(n_noncompact_helpers)) {
2212 VG_(printf)("Can only register %d non-compact helpers\n",
2213 MAX_NONCOMPACT_HELPERS);
2214 VG_(printf)("Try increasing MAX_NON_COMPACT_HELPERS\n");
2215 VG_(core_panic)("Too many non-compact helpers registered");
2216 }
2217 VG_(noncompact_helper_addrs)[VG_(n_noncompact_helpers)] = a;
2218 VG_(n_noncompact_helpers)++;
2219}
2220
2221/* Allocate offsets in baseBlock for the skin helpers */
2222static
2223void assign_helpers_in_baseBlock(UInt n, Int offsets[], Addr addrs[])
2224{
2225 UInt i;
2226 for (i = 0; i < n; i++)
2227 offsets[i] = alloc_BaB_1_set( addrs[i] );
2228}
2229
2230Bool VG_(need_to_handle_esp_assignment)(void)
2231{
2232 return ( VG_(defined_new_mem_stack_4)() ||
2233 VG_(defined_die_mem_stack_4)() ||
2234 VG_(defined_new_mem_stack_8)() ||
2235 VG_(defined_die_mem_stack_8)() ||
2236 VG_(defined_new_mem_stack_12)() ||
2237 VG_(defined_die_mem_stack_12)() ||
2238 VG_(defined_new_mem_stack_16)() ||
2239 VG_(defined_die_mem_stack_16)() ||
2240 VG_(defined_new_mem_stack_32)() ||
2241 VG_(defined_die_mem_stack_32)() ||
2242 VG_(defined_new_mem_stack)() ||
2243 VG_(defined_die_mem_stack)()
2244 );
2245}
2246
2247/* Here we assign actual offsets. It's important to get the most
2248 popular referents within 128 bytes of the start, so we can take
2249 advantage of short addressing modes relative to %ebp. Popularity
2250 of offsets was measured on 22 Feb 02 running a KDE application, and
2251 the slots rearranged accordingly, with a 1.5% reduction in total
2252 size of translations. */
2253static void init_baseBlock ( Addr client_eip, Addr esp_at_startup )
2254{
2255 /* Those with offsets under 128 are carefully chosen. */
2256
2257 /* WORD offsets in this column */
2258 /* 0 */ VGOFF_(m_eax) = alloc_BaB_1_set(0);
2259 /* 1 */ VGOFF_(m_ecx) = alloc_BaB_1_set(0);
2260 /* 2 */ VGOFF_(m_edx) = alloc_BaB_1_set(0);
2261 /* 3 */ VGOFF_(m_ebx) = alloc_BaB_1_set(0);
2262 /* 4 */ VGOFF_(m_esp) = alloc_BaB_1_set(esp_at_startup);
2263 /* 5 */ VGOFF_(m_ebp) = alloc_BaB_1_set(0);
2264 /* 6 */ VGOFF_(m_esi) = alloc_BaB_1_set(0);
2265 /* 7 */ VGOFF_(m_edi) = alloc_BaB_1_set(0);
2266 /* 8 */ VGOFF_(m_eflags) = alloc_BaB_1_set(0);
2267
2268 if (VG_(needs).shadow_regs) {
2269 /* 9 */ VGOFF_(sh_eax) = alloc_BaB_1_set(0);
2270 /* 10 */ VGOFF_(sh_ecx) = alloc_BaB_1_set(0);
2271 /* 11 */ VGOFF_(sh_edx) = alloc_BaB_1_set(0);
2272 /* 12 */ VGOFF_(sh_ebx) = alloc_BaB_1_set(0);
2273 /* 13 */ VGOFF_(sh_esp) = alloc_BaB_1_set(0);
2274 /* 14 */ VGOFF_(sh_ebp) = alloc_BaB_1_set(0);
2275 /* 15 */ VGOFF_(sh_esi) = alloc_BaB_1_set(0);
2276 /* 16 */ VGOFF_(sh_edi) = alloc_BaB_1_set(0);
2277 /* 17 */ VGOFF_(sh_eflags) = alloc_BaB_1_set(0);
2278 VG_TRACK( post_regs_write_init );
2279 }
2280
2281 /* 9,10,11 or 18,19,20... depends on number whether shadow regs are used
2282 * and on compact helpers registered */
2283
2284 /* Make these most-frequently-called specialised ones compact, if they
2285 are used. */
2286 if (VG_(defined_new_mem_stack_4)())
2287 VG_(register_compact_helper)( (Addr) VG_(tool_interface).track_new_mem_stack_4);
2288
2289 if (VG_(defined_die_mem_stack_4)())
2290 VG_(register_compact_helper)( (Addr) VG_(tool_interface).track_die_mem_stack_4);
2291
2292 /* (9 or 18) + n_compact_helpers */
2293 /* Allocate slots for compact helpers */
2294 assign_helpers_in_baseBlock(VG_(n_compact_helpers),
2295 VG_(compact_helper_offsets),
2296 VG_(compact_helper_addrs));
2297
2298 /* (9/10 or 18/19) + n_compact_helpers */
2299 VGOFF_(m_eip) = alloc_BaB_1_set(client_eip);
2300
2301 /* There are currently 24 spill slots */
2302 /* (11+/20+ .. 32+/43+) + n_compact_helpers. This can overlap the magic
2303 * boundary at >= 32 words, but most spills are to low numbered spill
2304 * slots, so the ones above the boundary don't see much action. */
2305 VGOFF_(spillslots) = alloc_BaB(VG_MAX_SPILLSLOTS);
2306
2307 /* I gave up counting at this point. Since they're above the
2308 short-amode-boundary, there's no point. */
2309
2310 VGOFF_(m_dflag) = alloc_BaB_1_set(1); // 1 == forward D-flag
2311
2312 /* The FPU/SSE state. This _must_ be 16-byte aligned. Initial
2313 state doesn't matter much, as long as it's not totally borked. */
2314 align_BaB(16);
2315 VGOFF_(m_ssestate) = alloc_BaB(VG_SIZE_OF_SSESTATE_W);
2316 vg_assert(
2317 0 == ( ((UInt)(& VG_(baseBlock)[VGOFF_(m_ssestate)])) % 16 )
sewardj22854b92002-11-30 14:00:47 +00002318 );
2319
fitzhardingec2dbbac2004-01-23 23:09:01 +00002320 /* I assume that if we have SSE2 we also have SSE */
2321 VG_(have_ssestate) =
2322 VG_(cpu_has_feature)(VG_X86_FEAT_FXSR) &&
2323 VG_(cpu_has_feature)(VG_X86_FEAT_SSE);
2324
fitzhardinge98abfc72003-12-16 02:05:15 +00002325 /* set up an initial FPU state (doesn't really matter what it is,
2326 so long as it's somewhat valid) */
2327 if (!VG_(have_ssestate))
nethercote71980f02004-01-24 18:18:54 +00002328 asm volatile("fwait; fnsave %0; fwait; frstor %0; fwait"
2329 :
2330 : "m" (VG_(baseBlock)[VGOFF_(m_ssestate)])
2331 : "cc", "memory");
fitzhardinge98abfc72003-12-16 02:05:15 +00002332 else
nethercote71980f02004-01-24 18:18:54 +00002333 asm volatile("fwait; fxsave %0; fwait; andl $0xffbf, %1;"
2334 "fxrstor %0; fwait"
2335 :
2336 : "m" (VG_(baseBlock)[VGOFF_(m_ssestate)]),
2337 "m" (VG_(baseBlock)[VGOFF_(m_ssestate)+(24/4)])
2338 : "cc", "memory");
fitzhardinge98abfc72003-12-16 02:05:15 +00002339
njn0c7a5b52003-04-30 09:00:33 +00002340 if (0) {
2341 if (VG_(have_ssestate))
2342 VG_(printf)("Looks like a SSE-capable CPU\n");
2343 else
2344 VG_(printf)("Looks like a MMX-only CPU\n");
2345 }
sewardjb91ae7f2003-04-29 23:50:00 +00002346
nethercote71980f02004-01-24 18:18:54 +00002347 /* LDT pointer: pretend the root thread has an empty LDT to start with. */
2348 VGOFF_(ldt) = alloc_BaB_1_set((UInt)NULL);
jsgf855d93d2003-10-13 22:26:55 +00002349
nethercote71980f02004-01-24 18:18:54 +00002350 /* TLS pointer: pretend the root thread has no TLS array for now. */
2351 VGOFF_(tls) = alloc_BaB_1_set((UInt)NULL);
fitzhardingef0046f22003-12-18 02:39:22 +00002352
nethercote71980f02004-01-24 18:18:54 +00002353 /* segment registers */
2354 VGOFF_(m_cs) = alloc_BaB_1_set(0);
2355 VGOFF_(m_ss) = alloc_BaB_1_set(0);
2356 VGOFF_(m_ds) = alloc_BaB_1_set(0);
2357 VGOFF_(m_es) = alloc_BaB_1_set(0);
2358 VGOFF_(m_fs) = alloc_BaB_1_set(0);
2359 VGOFF_(m_gs) = alloc_BaB_1_set(0);
fitzhardingef0046f22003-12-18 02:39:22 +00002360
thughes35cec982004-04-21 15:16:43 +00002361 /* initialise %cs, %ds and %ss to point at the operating systems
2362 default code, data and stack segments */
2363 asm volatile("movw %%cs, %0"
2364 :
2365 : "m" (VG_(baseBlock)[VGOFF_(m_cs)]));
2366 asm volatile("movw %%ds, %0"
2367 :
2368 : "m" (VG_(baseBlock)[VGOFF_(m_ds)]));
2369 asm volatile("movw %%ss, %0"
2370 :
2371 : "m" (VG_(baseBlock)[VGOFF_(m_ss)]));
2372
nethercote71980f02004-01-24 18:18:54 +00002373 VG_(register_noncompact_helper)( (Addr) & VG_(do_useseg) );
fitzhardingef0046f22003-12-18 02:39:22 +00002374
nethercote71980f02004-01-24 18:18:54 +00002375#define REG(kind, size) \
2376 if (VG_(defined_##kind##_mem_stack##size)()) \
2377 VG_(register_noncompact_helper)( \
2378 (Addr) VG_(tool_interface).track_##kind##_mem_stack##size );
2379 REG(new, _8);
2380 REG(new, _12);
2381 REG(new, _16);
2382 REG(new, _32);
2383 REG(new, );
2384 REG(die, _8);
2385 REG(die, _12);
2386 REG(die, _16);
2387 REG(die, _32);
2388 REG(die, );
2389#undef REG
fitzhardingef0046f22003-12-18 02:39:22 +00002390
nethercote71980f02004-01-24 18:18:54 +00002391 if (VG_(need_to_handle_esp_assignment)())
2392 VG_(register_noncompact_helper)((Addr) VG_(unknown_esp_update));
fitzhardingeb791a192003-12-18 07:22:44 +00002393
nethercote71980f02004-01-24 18:18:54 +00002394# define HELPER(name) \
2395 VGOFF_(helper_##name) = alloc_BaB_1_set( (Addr) & VG_(helper_##name))
njn3e884182003-04-15 13:03:23 +00002396
nethercote71980f02004-01-24 18:18:54 +00002397 /* Helper functions. */
2398 HELPER(idiv_64_32); HELPER(div_64_32);
2399 HELPER(idiv_32_16); HELPER(div_32_16);
2400 HELPER(idiv_16_8); HELPER(div_16_8);
fitzhardinge98abfc72003-12-16 02:05:15 +00002401
nethercote71980f02004-01-24 18:18:54 +00002402 HELPER(imul_32_64); HELPER(mul_32_64);
2403 HELPER(imul_16_32); HELPER(mul_16_32);
2404 HELPER(imul_8_16); HELPER(mul_8_16);
njn25e49d8e72002-09-23 09:36:25 +00002405
nethercote71980f02004-01-24 18:18:54 +00002406 HELPER(CLD); HELPER(STD);
2407 HELPER(get_dirflag);
sewardjde4a1d02002-03-22 01:27:54 +00002408
nethercote71980f02004-01-24 18:18:54 +00002409 HELPER(CLC); HELPER(STC);
nethercote1018bdd2004-02-11 23:33:29 +00002410 HELPER(CMC);
jsgf855d93d2003-10-13 22:26:55 +00002411
nethercote71980f02004-01-24 18:18:54 +00002412 HELPER(shldl); HELPER(shldw);
2413 HELPER(shrdl); HELPER(shrdw);
njncc7bb472002-10-14 09:25:19 +00002414
nethercote71980f02004-01-24 18:18:54 +00002415 HELPER(RDTSC); HELPER(CPUID);
njncc7bb472002-10-14 09:25:19 +00002416
nethercote1018bdd2004-02-11 23:33:29 +00002417 HELPER(bsfw); HELPER(bsfl);
2418 HELPER(bsrw); HELPER(bsrl);
rjwalshf5f536f2003-11-17 17:45:00 +00002419
nethercote71980f02004-01-24 18:18:54 +00002420 HELPER(fstsw_AX);
2421 HELPER(SAHF); HELPER(LAHF);
2422 HELPER(DAS); HELPER(DAA);
nethercote1018bdd2004-02-11 23:33:29 +00002423 HELPER(AAS); HELPER(AAA);
2424 HELPER(AAD); HELPER(AAM);
nethercote71980f02004-01-24 18:18:54 +00002425 HELPER(IN); HELPER(OUT);
2426 HELPER(cmpxchg8b);
sewardj018f7622002-05-15 21:13:39 +00002427
nethercote71980f02004-01-24 18:18:54 +00002428 HELPER(undefined_instruction);
jsgf855d93d2003-10-13 22:26:55 +00002429
nethercote71980f02004-01-24 18:18:54 +00002430# undef HELPER
sewardjde4a1d02002-03-22 01:27:54 +00002431
nethercote71980f02004-01-24 18:18:54 +00002432 /* Allocate slots for noncompact helpers */
2433 assign_helpers_in_baseBlock(VG_(n_noncompact_helpers),
2434 VG_(noncompact_helper_offsets),
2435 VG_(noncompact_helper_addrs));
2436}
sewardjde4a1d02002-03-22 01:27:54 +00002437
sewardj5f07b662002-04-23 16:52:51 +00002438
nethercote71980f02004-01-24 18:18:54 +00002439/*====================================================================*/
2440/*=== Setup pointercheck ===*/
2441/*====================================================================*/
njn25e49d8e72002-09-23 09:36:25 +00002442
nethercote71980f02004-01-24 18:18:54 +00002443static void setup_pointercheck(void)
2444{
2445 int ret;
sewardj2e93c502002-04-12 11:12:52 +00002446
fitzhardinge98abfc72003-12-16 02:05:15 +00002447 if (VG_(clo_pointercheck)) {
nethercote71980f02004-01-24 18:18:54 +00002448 vki_modify_ldt_t ldt = {
2449 VG_POINTERCHECK_SEGIDX, // entry_number
2450 VG_(client_base), // base_addr
2451 (VG_(client_end)-VG_(client_base)) / VKI_BYTES_PER_PAGE, // limit
2452 1, // seg_32bit
2453 0, // contents: data, RW, non-expanding
2454 0, // ! read_exec_only
2455 1, // limit_in_pages
2456 0, // ! seg not present
2457 1, // useable
fitzhardinge98abfc72003-12-16 02:05:15 +00002458 };
nethercote71980f02004-01-24 18:18:54 +00002459 ret = VG_(do_syscall)(__NR_modify_ldt, 1, &ldt, sizeof(ldt));
fitzhardinge98abfc72003-12-16 02:05:15 +00002460 if (ret < 0) {
2461 VG_(message)(Vg_UserMsg,
2462 "Warning: ignoring --pointercheck=yes, "
2463 "because modify_ldt failed (errno=%d)", -ret);
2464 VG_(clo_pointercheck) = False;
2465 }
2466 }
sewardjde4a1d02002-03-22 01:27:54 +00002467}
2468
nethercote71980f02004-01-24 18:18:54 +00002469/*====================================================================*/
2470/*=== Initialise program data/text, etc. ===*/
2471/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +00002472
nethercote71980f02004-01-24 18:18:54 +00002473static void build_valgrind_map_callback
2474 ( Addr start, UInt size, Char rr, Char ww, Char xx,
2475 UInt dev, UInt ino, ULong foffset, const UChar* filename )
sewardjde4a1d02002-03-22 01:27:54 +00002476{
nethercote71980f02004-01-24 18:18:54 +00002477 UInt prot = 0;
2478 UInt flags = SF_MMAP|SF_NOSYMS;
2479 Bool is_stack_segment;
2480
2481 is_stack_segment =
2482 (start == VG_(clstk_base) && (start+size) == VG_(clstk_end));
2483
2484 /* Only record valgrind mappings for now, without loading any
2485 symbols. This is so we know where the free space is before we
2486 start allocating more memory (note: heap is OK, it's just mmap
2487 which is the problem here). */
2488 if (start >= VG_(valgrind_base) && (start+size) <= VG_(valgrind_end)) {
2489 flags |= SF_VALGRIND;
2490 VG_(map_file_segment)(start, size, prot, flags, dev, ino, foffset, filename);
2491 }
sewardjde4a1d02002-03-22 01:27:54 +00002492}
2493
nethercote71980f02004-01-24 18:18:54 +00002494// Global var used to pass local data to callback
2495Addr esp_at_startup___global_arg = 0;
sewardjde4a1d02002-03-22 01:27:54 +00002496
nethercote71980f02004-01-24 18:18:54 +00002497static void build_segment_map_callback
2498 ( Addr start, UInt size, Char rr, Char ww, Char xx,
2499 UInt dev, UInt ino, ULong foffset, const UChar* filename )
sewardj45b672d2003-07-25 19:58:11 +00002500{
nethercote71980f02004-01-24 18:18:54 +00002501 UInt prot = 0;
2502 UInt flags;
2503 Bool is_stack_segment;
2504 Addr r_esp;
sewardj45b672d2003-07-25 19:58:11 +00002505
nethercote71980f02004-01-24 18:18:54 +00002506 is_stack_segment
2507 = (start == VG_(clstk_base) && (start+size) == VG_(clstk_end));
fitzhardinge98abfc72003-12-16 02:05:15 +00002508
nethercote71980f02004-01-24 18:18:54 +00002509 if (rr == 'r') prot |= VKI_PROT_READ;
2510 if (ww == 'w') prot |= VKI_PROT_WRITE;
2511 if (xx == 'x') prot |= VKI_PROT_EXEC;
fitzhardinge98abfc72003-12-16 02:05:15 +00002512
nethercote71980f02004-01-24 18:18:54 +00002513 if (is_stack_segment)
2514 flags = SF_STACK | SF_GROWDOWN;
2515 else
2516 flags = SF_EXEC|SF_MMAP;
fitzhardinge98abfc72003-12-16 02:05:15 +00002517
nethercote71980f02004-01-24 18:18:54 +00002518 if (filename != NULL)
2519 flags |= SF_FILE;
fitzhardinge98abfc72003-12-16 02:05:15 +00002520
nethercote71980f02004-01-24 18:18:54 +00002521 if (start >= VG_(valgrind_base) && (start+size) <= VG_(valgrind_end))
2522 flags |= SF_VALGRIND;
fitzhardinge98abfc72003-12-16 02:05:15 +00002523
nethercote71980f02004-01-24 18:18:54 +00002524 VG_(map_file_segment)(start, size, prot, flags, dev, ino, foffset, filename);
fitzhardinge98abfc72003-12-16 02:05:15 +00002525
nethercote71980f02004-01-24 18:18:54 +00002526 if (VG_(is_client_addr)(start) && VG_(is_client_addr)(start+size-1))
2527 VG_TRACK( new_mem_startup, start, size, rr=='r', ww=='w', xx=='x' );
sewardj3e1eb1f2002-05-18 13:14:17 +00002528
nethercote71980f02004-01-24 18:18:54 +00002529 /* If this is the stack segment mark all below %esp as noaccess. */
2530 r_esp = esp_at_startup___global_arg;
2531 vg_assert(0 != r_esp);
2532 if (is_stack_segment) {
2533 if (0)
2534 VG_(message)(Vg_DebugMsg, "invalidating stack area: %x .. %x",
2535 start,r_esp);
2536 VG_TRACK( die_mem_stack, start, r_esp-start );
sewardjde4a1d02002-03-22 01:27:54 +00002537 }
sewardjde4a1d02002-03-22 01:27:54 +00002538}
2539
2540
nethercote71980f02004-01-24 18:18:54 +00002541/*====================================================================*/
2542/*=== Sanity check machinery (permanently engaged) ===*/
2543/*====================================================================*/
njn25e49d8e72002-09-23 09:36:25 +00002544
2545/* A fast sanity check -- suitable for calling circa once per
2546 millisecond. */
2547
2548void VG_(do_sanity_checks) ( Bool force_expensive )
2549{
njn37cea302002-09-30 11:24:00 +00002550 VGP_PUSHCC(VgpCoreCheapSanity);
2551
nethercote27fec902004-06-16 21:26:32 +00002552 if (VG_(clo_sanity_level) < 1) return;
njn25e49d8e72002-09-23 09:36:25 +00002553
2554 /* --- First do all the tests that we can do quickly. ---*/
2555
2556 VG_(sanity_fast_count)++;
2557
njn25e49d8e72002-09-23 09:36:25 +00002558 /* Check stuff pertaining to the memory check system. */
2559
2560 /* Check that nobody has spuriously claimed that the first or
2561 last 16 pages of memory have become accessible [...] */
njn37cea302002-09-30 11:24:00 +00002562 if (VG_(needs).sanity_checks) {
2563 VGP_PUSHCC(VgpSkinCheapSanity);
njn25e49d8e72002-09-23 09:36:25 +00002564 vg_assert(SK_(cheap_sanity_check)());
njn37cea302002-09-30 11:24:00 +00002565 VGP_POPCC(VgpSkinCheapSanity);
2566 }
njn25e49d8e72002-09-23 09:36:25 +00002567
2568 /* --- Now some more expensive checks. ---*/
2569
2570 /* Once every 25 times, check some more expensive stuff. */
2571 if ( force_expensive
nethercote27fec902004-06-16 21:26:32 +00002572 || VG_(clo_sanity_level) > 1
2573 || (VG_(clo_sanity_level) == 1 && (VG_(sanity_fast_count) % 25) == 0)) {
njn25e49d8e72002-09-23 09:36:25 +00002574
njn37cea302002-09-30 11:24:00 +00002575 VGP_PUSHCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002576 VG_(sanity_slow_count)++;
2577
jsgf855d93d2003-10-13 22:26:55 +00002578 VG_(proxy_sanity)();
2579
njn25e49d8e72002-09-23 09:36:25 +00002580# if 0
2581 { void zzzmemscan(void); zzzmemscan(); }
2582# endif
2583
2584 if ((VG_(sanity_fast_count) % 250) == 0)
2585 VG_(sanity_check_tc_tt)();
2586
2587 if (VG_(needs).sanity_checks) {
njn37cea302002-09-30 11:24:00 +00002588 VGP_PUSHCC(VgpSkinExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002589 vg_assert(SK_(expensive_sanity_check)());
njn37cea302002-09-30 11:24:00 +00002590 VGP_POPCC(VgpSkinExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002591 }
2592 /*
2593 if ((VG_(sanity_fast_count) % 500) == 0) VG_(mallocSanityCheckAll)();
2594 */
njn37cea302002-09-30 11:24:00 +00002595 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002596 }
2597
nethercote27fec902004-06-16 21:26:32 +00002598 if (VG_(clo_sanity_level) > 1) {
njn37cea302002-09-30 11:24:00 +00002599 VGP_PUSHCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002600 /* Check sanity of the low-level memory manager. Note that bugs
2601 in the client's code can cause this to fail, so we don't do
2602 this check unless specially asked for. And because it's
2603 potentially very expensive. */
2604 VG_(mallocSanityCheckAll)();
njn37cea302002-09-30 11:24:00 +00002605 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002606 }
njn37cea302002-09-30 11:24:00 +00002607 VGP_POPCC(VgpCoreCheapSanity);
njn25e49d8e72002-09-23 09:36:25 +00002608}
nethercote71980f02004-01-24 18:18:54 +00002609
2610
2611/*====================================================================*/
2612/*=== main() ===*/
2613/*====================================================================*/
2614
2615int main(int argc, char **argv)
2616{
2617 char **cl_argv;
2618 const char *tool = NULL;
2619 const char *exec = NULL;
2620 char *preload; /* tool-specific LD_PRELOAD .so */
2621 char **env;
nethercote6c999f22004-01-31 22:55:15 +00002622 Int need_help = 0; // 0 = no, 1 = --help, 2 = --help-debug
nethercote71980f02004-01-24 18:18:54 +00002623 struct exeinfo info;
2624 ToolInfo *toolinfo = NULL;
2625 void *tool_dlhandle;
2626 Addr client_eip;
2627 Addr esp_at_startup; /* client's %esp at the point we gained control. */
2628 UInt * client_auxv;
2629 VgSchedReturnCode src;
nethercote47dd12c2004-06-22 14:18:42 +00002630 Int exitcode = 0;
fitzhardingeb50068f2004-02-24 23:42:55 +00002631 vki_rlimit zero = { 0, 0 };
nethercote71980f02004-01-24 18:18:54 +00002632
2633 //============================================================
2634 // Nb: startup is complex. Prerequisites are shown at every step.
2635 //
2636 // *** Be very careful when messing with the order ***
2637 //============================================================
2638
nethercotef4928da2004-06-15 10:54:40 +00002639 //============================================================
2640 // Command line argument handling order:
2641 // * If --help/--help-debug are present, show usage message
2642 // (if --tool is also present, that includes the tool-specific usage)
2643 // * Then, if --tool is missing, abort with error msg
2644 // * Then, if client is missing, abort with error msg
2645 // * Then, if any cmdline args are bad, abort with error msg
2646 //============================================================
2647
fitzhardingeb50068f2004-02-24 23:42:55 +00002648 // Get the current process datasize rlimit, and set it to zero.
2649 // This prevents any internal uses of brk() from having any effect.
2650 // We remember the old value so we can restore it on exec, so that
2651 // child processes will have a reasonable brk value.
2652 VG_(getrlimit)(VKI_RLIMIT_DATA, &VG_(client_rlimit_data));
2653 zero.rlim_max = VG_(client_rlimit_data).rlim_max;
2654 VG_(setrlimit)(VKI_RLIMIT_DATA, &zero);
2655
nethercote71980f02004-01-24 18:18:54 +00002656 //--------------------------------------------------------------
2657 // Check we were launched by stage1
2658 // p: n/a [must be first step]
2659 //--------------------------------------------------------------
2660 scan_auxv();
2661
2662 if (0) {
2663 int prmap(void *start, void *end, const char *perm, off_t off,
2664 int maj, int min, int ino) {
2665 printf("mapping %10p-%10p %s %02x:%02x %d\n",
2666 start, end, perm, maj, min, ino);
2667 return True;
2668 }
2669 printf("========== main() ==========\n");
2670 foreach_map(prmap);
2671 }
2672
2673 //--------------------------------------------------------------
2674 // Look for alternative libdir
2675 // p: n/a
2676 //--------------------------------------------------------------
2677 { char *cp = getenv(VALGRINDLIB);
2678 if (cp != NULL)
2679 VG_(libdir) = cp;
2680 }
2681
2682 //--------------------------------------------------------------
2683 // Begin working out address space layout
2684 // p: n/a
2685 //--------------------------------------------------------------
2686 layout_client_space( (Addr) & argc );
2687
2688 //--------------------------------------------------------------
2689 // Get valgrind args + client args (inc. from VALGRIND_OPTS/.valgrindrc).
2690 // Pre-process the command line.
2691 // p: n/a
2692 //--------------------------------------------------------------
2693 get_command_line(argc, argv, &VG_(vg_argc), &VG_(vg_argv), &cl_argv);
2694 pre_process_cmd_line_options(&need_help, &tool, &exec);
2695
2696 //==============================================================
2697 // Nb: once a tool is specified, the tool.so must be loaded even if
2698 // they specified --help or didn't specify a client program.
2699 //==============================================================
2700
2701 //--------------------------------------------------------------
2702 // With client padded out, map in tool
2703 // p: layout_client_space() [for padding]
2704 // p: set-libdir [for VG_(libdir)]
2705 // p: pre_process_cmd_line_options() [for 'tool']
2706 //--------------------------------------------------------------
2707 load_tool(tool, &tool_dlhandle, &toolinfo, &preload);
2708
2709 //==============================================================
2710 // Can use VG_(malloc)() and VG_(arena_malloc)() only after load_tool()
2711 // -- redzone size is now set.
2712 //==============================================================
2713
2714 //--------------------------------------------------------------
2715 // Finalise address space layout
2716 // p: layout_client_space(), load_tool() [for 'toolinfo']
2717 //--------------------------------------------------------------
2718 layout_remaining_space( toolinfo->shadow_ratio );
2719
2720 //--------------------------------------------------------------
2721 // Load client executable, finding in $PATH if necessary
2722 // p: layout_client_space() [so there's space]
2723 // p: pre_process_cmd_line_options() [for 'exec', 'need_help']
2724 // p: layout_remaining_space [so there's space]
2725 //--------------------------------------------------------------
nethercotef4928da2004-06-15 10:54:40 +00002726 load_client(cl_argv, exec, need_help, &info, &client_eip);
nethercote71980f02004-01-24 18:18:54 +00002727
2728 //--------------------------------------------------------------
2729 // Everything in place, unpad us
2730 // p: layout_remaining_space() [everything must be mapped in before now]
2731 // p: load_client() [ditto]
2732 //--------------------------------------------------------------
2733 as_unpad((void *)VG_(shadow_end), (void *)~0);
2734 as_closepadfile(); /* no more padding */
2735
2736 //--------------------------------------------------------------
2737 // Set up client's environment
2738 // p: set-libdir [for VG_(libdir)]
2739 // p: load_tool() [for 'preload']
2740 //--------------------------------------------------------------
2741 env = fix_environment(environ, preload);
2742
2743 //--------------------------------------------------------------
nethercote5ee67ca2004-06-22 14:00:09 +00002744 // Setup client stack, eip, and VG_(client_arg[cv])
nethercote71980f02004-01-24 18:18:54 +00002745 // p: load_client() [for 'info']
2746 // p: fix_environment() [for 'env']
2747 //--------------------------------------------------------------
2748 esp_at_startup = setup_client_stack(cl_argv, env, &info, &client_auxv);
2749
2750 if (0)
2751 printf("entry=%x client esp=%x vg_argc=%d brkbase=%x\n",
2752 client_eip, esp_at_startup, VG_(vg_argc), VG_(brk_base));
2753
2754 //==============================================================
2755 // Finished setting up operating environment. Now initialise
2756 // Valgrind. (This is where the old VG_(main)() started.)
2757 //==============================================================
2758
2759 //--------------------------------------------------------------
2760 // Read /proc/self/maps into a buffer
2761 // p: all memory layout, environment setup [so memory maps are right]
2762 //--------------------------------------------------------------
2763 VG_(read_procselfmaps)();
2764
2765 //--------------------------------------------------------------
2766 // atfork
2767 // p: n/a
2768 //--------------------------------------------------------------
2769 VG_(atfork)(NULL, NULL, newpid);
2770 newpid(VG_INVALID_THREADID);
2771
2772 //--------------------------------------------------------------
2773 // setup file descriptors
2774 // p: n/a
2775 //--------------------------------------------------------------
2776 setup_file_descriptors();
2777
2778 //--------------------------------------------------------------
2779 // Setup tool
2780 // p: VG_(read_procselfmaps)() [so if sk_pre_clo_init calls
2781 // VG_(malloc), any mmap'd superblocks aren't erroneously
2782 // identified later as being owned by the client]
2783 // XXX: is that necessary, now that we look for V's segments separately?
2784 // XXX: alternatively, if sk_pre_clo_init does use VG_(malloc)(), is it
2785 // wrong to ignore any segments that might add in parse_procselfmaps?
nethercote5ee67ca2004-06-22 14:00:09 +00002786 // p: setup_client_stack() [for 'VG_(client_arg[cv]']
nethercote71980f02004-01-24 18:18:54 +00002787 //--------------------------------------------------------------
2788 (*toolinfo->sk_pre_clo_init)();
2789 VG_(tool_init_dlsym)(tool_dlhandle);
2790 VG_(sanity_check_needs)();
2791
2792 //--------------------------------------------------------------
nethercotef4928da2004-06-15 10:54:40 +00002793 // If --tool and --help/--help-debug was given, now give the core+tool
2794 // help message
2795 // p: pre_clo_init()
2796 //--------------------------------------------------------------
2797 if (need_help) {
2798 usage(/*--help-debug?*/2 == need_help);
2799 }
2800
2801 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002802 // Process Valgrind's + tool's command-line options
2803 // p: load_tool() [for 'tool']
thughesad1c9562004-06-26 11:27:52 +00002804 // p: setup_file_descriptors() [for 'VG_(fd_xxx_limit)']
nethercote71980f02004-01-24 18:18:54 +00002805 // p: sk_pre_clo_init [to set 'command_line_options' need]
2806 //--------------------------------------------------------------
nethercote5ee67ca2004-06-22 14:00:09 +00002807 process_cmd_line_options(client_auxv, tool);
nethercote71980f02004-01-24 18:18:54 +00002808
2809 //--------------------------------------------------------------
2810 // Allow GDB attach
2811 // p: process_cmd_line_options() [for VG_(clo_wait_for_gdb)]
2812 //--------------------------------------------------------------
2813 /* Hook to delay things long enough so we can get the pid and
2814 attach GDB in another shell. */
2815 if (VG_(clo_wait_for_gdb)) {
2816 VG_(printf)("pid=%d\n", VG_(getpid)());
2817 /* do "jump *$eip" to skip this in gdb */
2818 VG_(do_syscall)(__NR_pause);
2819 }
2820
2821 //--------------------------------------------------------------
2822 // Setup tool, post command-line processing
2823 // p: process_cmd_line_options [tool assumes it]
2824 //--------------------------------------------------------------
2825 SK_(post_clo_init)();
2826
2827 //--------------------------------------------------------------
nethercote1d447092004-02-01 17:29:59 +00002828 // Set up baseBlock
nethercote71980f02004-01-24 18:18:54 +00002829 // p: {pre,post}_clo_init() [for tool helper registration]
2830 // load_client() [for 'client_eip']
2831 // setup_client_stack() [for 'esp_at_startup']
2832 //--------------------------------------------------------------
2833 init_baseBlock(client_eip, esp_at_startup);
2834
2835 //--------------------------------------------------------------
2836 // Search for file descriptors that are inherited from our parent
2837 // p: process_cmd_line_options [for VG_(clo_track_fds)]
2838 //--------------------------------------------------------------
2839 if (VG_(clo_track_fds))
2840 VG_(init_preopened_fds)();
2841
2842 //--------------------------------------------------------------
2843 // Initialise the scheduler
2844 // p: init_baseBlock() [baseBlock regs copied into VG_(threads)[1]]
2845 // p: setup_file_descriptors() [else VG_(safe_fd)() breaks]
2846 //--------------------------------------------------------------
2847 VG_(scheduler_init)();
2848
2849 //--------------------------------------------------------------
2850 // Set up the ProxyLWP machinery
2851 // p: VG_(scheduler_init)()? [XXX: subtle dependency?]
2852 // - subs: VG_(sigstartup_actions)()?
2853 //--------------------------------------------------------------
2854 VG_(proxy_init)();
2855
2856 //--------------------------------------------------------------
2857 // Initialise the signal handling subsystem
2858 // p: VG_(atfork)(NULL, NULL, newpid) [else problems with sigmasks]
2859 // p: VG_(proxy_init)() [else breaks...]
2860 //--------------------------------------------------------------
2861 // Nb: temporarily parks the saved blocking-mask in saved_sigmask.
2862 VG_(sigstartup_actions)();
2863
2864 //--------------------------------------------------------------
2865 // Perhaps we're profiling Valgrind?
2866 // p: process_cmd_line_options() [for VG_(clo_profile)]
2867 // p: others?
2868 //
2869 // XXX: this seems to be broken? It always says the tool wasn't built
2870 // for profiling; vg_profile.c's functions don't seem to be overriding
2871 // vg_dummy_profile.c's?
2872 //
2873 // XXX: want this as early as possible. Looking for --profile
2874 // in pre_process_cmd_line_options() could get it earlier.
2875 //--------------------------------------------------------------
2876 if (VG_(clo_profile))
2877 VGP_(init_profiling)();
2878
2879 VGP_PUSHCC(VgpStartup);
2880
2881 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002882 // Reserve Valgrind's kickstart, heap and stack
2883 // p: XXX ???
2884 //--------------------------------------------------------------
2885 VG_(map_segment)(VG_(valgrind_mmap_end),
2886 VG_(valgrind_end)-VG_(valgrind_mmap_end),
2887 VKI_PROT_NONE, SF_VALGRIND|SF_FIXED);
2888
2889 //--------------------------------------------------------------
2890 // Identify Valgrind's segments
2891 // p: read proc/self/maps
2892 // p: VG_(map_segment) [XXX ???]
2893 // p: sk_pre_clo_init() [to setup new_mem_startup tracker]
2894 //--------------------------------------------------------------
2895 VG_(parse_procselfmaps) ( build_valgrind_map_callback );
2896
2897 // XXX: I can't see why these two need to be separate; could they be
2898 // folded together? If not, need a comment explaining why.
2899 //
2900 // XXX: can we merge reading and parsing of /proc/self/maps?
2901 //
2902 // XXX: can we dynamically allocate the /proc/self/maps buffer? (or mmap
2903 // it?) Or does that disturb its contents...
2904
2905 //--------------------------------------------------------------
2906 // Build segment map (all segments)
2907 // p: setup_client_stack() [for 'esp_at_startup']
2908 //--------------------------------------------------------------
2909 esp_at_startup___global_arg = esp_at_startup;
2910 VG_(parse_procselfmaps) ( build_segment_map_callback ); /* everything */
2911 esp_at_startup___global_arg = 0;
2912
2913 //==============================================================
2914 // Can only use VG_(map)() after VG_(map_segment)() [XXX ???]
2915 //==============================================================
2916
2917 //--------------------------------------------------------------
2918 // Build segment map (all segments)
2919 // p: setup_client_stack() [for 'esp_at_startup']
2920 //--------------------------------------------------------------
2921 /* Initialize our trampoline page (which is also sysinfo stuff) */
2922 VG_(memcpy)( (void *)VG_(client_trampoline_code),
2923 &VG_(trampoline_code_start), VG_(trampoline_code_length) );
2924 VG_(mprotect)( (void *)VG_(client_trampoline_code),
2925 VG_(trampoline_code_length), VKI_PROT_READ|VKI_PROT_EXEC );
2926
2927 //--------------------------------------------------------------
2928 // Read suppression file
2929 // p: process_cmd_line_options() [for VG_(clo_suppressions)]
2930 //--------------------------------------------------------------
2931 if (VG_(needs).core_errors || VG_(needs).skin_errors)
2932 VG_(load_suppressions)();
2933
2934 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002935 // Initialise translation table and translation cache
2936 // p: read_procselfmaps [so the anonymous mmaps for the TT/TC
2937 // aren't identified as part of the client, which would waste
2938 // > 20M of virtual address space.]
2939 //--------------------------------------------------------------
2940 VG_(init_tt_tc)();
2941
2942 //--------------------------------------------------------------
2943 // Read debug info to find glibc entry points to intercept
2944 // p: parse_procselfmaps? [XXX for debug info?]
2945 // p: init_tt_tc? [XXX ???]
2946 //--------------------------------------------------------------
2947 VG_(setup_code_redirect_table)();
2948
2949 //--------------------------------------------------------------
2950 // Verbosity message
2951 // p: end_rdtsc_calibration [so startup message is printed first]
2952 //--------------------------------------------------------------
2953 if (VG_(clo_verbosity) == 1)
2954 VG_(message)(Vg_UserMsg, "For more details, rerun with: -v");
2955 if (VG_(clo_verbosity) > 0)
2956 VG_(message)(Vg_UserMsg, "");
2957
2958 //--------------------------------------------------------------
2959 // Setup pointercheck
2960 // p: process_cmd_line_options() [for VG_(clo_pointercheck)]
2961 //--------------------------------------------------------------
2962 setup_pointercheck();
2963
2964
2965
2966 //--------------------------------------------------------------
2967 // Run!
2968 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002969 VGP_POPCC(VgpStartup);
2970 VGP_PUSHCC(VgpSched);
2971
2972 if (__builtin_setjmp(&VG_(fatal_signal_jmpbuf)) == 0) {
2973 VG_(fatal_signal_set) = True;
nethercote47dd12c2004-06-22 14:18:42 +00002974 src = VG_(scheduler)( &exitcode );
nethercote71980f02004-01-24 18:18:54 +00002975 } else
2976 src = VgSrc_FatalSig;
2977
2978 VGP_POPCC(VgpSched);
nethercote71980f02004-01-24 18:18:54 +00002979
2980
2981
2982 //--------------------------------------------------------------
2983 // Finalisation: cleanup, messages, etc. Order no so important, only
2984 // affects what order the messages come.
2985 //--------------------------------------------------------------
2986 if (VG_(clo_verbosity) > 0)
2987 VG_(message)(Vg_UserMsg, "");
2988
2989 if (src == VgSrc_Deadlock) {
2990 VG_(message)(Vg_UserMsg,
2991 "Warning: pthread scheduler exited due to deadlock");
2992 }
2993
2994 /* Print out file descriptor summary and stats. */
2995 if (VG_(clo_track_fds))
2996 VG_(fd_stats)();
2997
2998 if (VG_(needs).core_errors || VG_(needs).skin_errors)
2999 VG_(show_all_errors)();
3000
nethercote47dd12c2004-06-22 14:18:42 +00003001 SK_(fini)( exitcode );
nethercote71980f02004-01-24 18:18:54 +00003002
3003 VG_(do_sanity_checks)( True /*include expensive checks*/ );
3004
3005 if (VG_(clo_verbosity) > 1)
3006 show_counts();
3007
3008 if (VG_(clo_verbosity) > 3)
3009 VG_(print_UInstr_histogram)();
3010
3011 if (0) {
3012 VG_(message)(Vg_DebugMsg, "");
3013 VG_(message)(Vg_DebugMsg,
3014 "------ Valgrind's internal memory use stats follow ------" );
3015 VG_(mallocSanityCheckAll)();
3016 VG_(show_all_arena_stats)();
3017 VG_(message)(Vg_DebugMsg,
3018 "------ Valgrind's ExeContext management stats follow ------" );
3019 VG_(show_ExeContext_stats)();
3020 }
3021
3022 if (VG_(clo_profile))
3023 VGP_(done_profiling)();
3024
nethercote71980f02004-01-24 18:18:54 +00003025 /* We're exiting, so nuke all the threads and clean up the proxy LWPs */
3026 vg_assert(src == VgSrc_FatalSig ||
3027 VG_(threads)[VG_(last_run_tid)].status == VgTs_Runnable ||
3028 VG_(threads)[VG_(last_run_tid)].status == VgTs_WaitJoiner);
3029 VG_(nuke_all_threads_except)(VG_INVALID_THREADID);
3030
3031 //--------------------------------------------------------------
3032 // Exit, according to the scheduler's return code
3033 //--------------------------------------------------------------
3034 switch (src) {
3035 case VgSrc_ExitSyscall: /* the normal way out */
3036 vg_assert(VG_(last_run_tid) > 0
3037 && VG_(last_run_tid) < VG_N_THREADS);
3038 VG_(proxy_shutdown)();
3039
3040 /* The thread's %EBX at the time it did __NR_exit() will hold
3041 the arg to __NR_exit(), so we just do __NR_exit() with
3042 that arg. */
nethercote47dd12c2004-06-22 14:18:42 +00003043 VG_(exit)( exitcode );
nethercote71980f02004-01-24 18:18:54 +00003044 /* NOT ALIVE HERE! */
3045 VG_(core_panic)("entered the afterlife in main() -- ExitSyscall");
3046 break; /* what the hell :) */
3047
3048 case VgSrc_Deadlock:
3049 /* Just exit now. No point in continuing. */
3050 VG_(proxy_shutdown)();
3051 VG_(exit)(0);
3052 VG_(core_panic)("entered the afterlife in main() -- Deadlock");
3053 break;
3054
nethercote71980f02004-01-24 18:18:54 +00003055 case VgSrc_FatalSig:
3056 /* We were killed by a fatal signal, so replicate the effect */
3057 vg_assert(VG_(fatal_sigNo) != -1);
3058 VG_(kill_self)(VG_(fatal_sigNo));
3059 VG_(core_panic)("main(): signal was supposed to be fatal");
3060 break;
3061
3062 default:
3063 VG_(core_panic)("main(): unexpected scheduler return code");
3064 }
3065
3066 abort();
3067}
3068
3069
sewardjde4a1d02002-03-22 01:27:54 +00003070/*--------------------------------------------------------------------*/
3071/*--- end vg_main.c ---*/
3072/*--------------------------------------------------------------------*/