blob: f3470c5516cad2ef0934720a4300657030db458e [file] [log] [blame]
sewardjde4a1d02002-03-22 01:27:54 +00001
2/*--------------------------------------------------------------------*/
nethercote71980f02004-01-24 18:18:54 +00003/*--- Startup: the real stuff vg_main.c ---*/
sewardjde4a1d02002-03-22 01:27:54 +00004/*--------------------------------------------------------------------*/
5
6/*
njnc9539842002-10-02 13:26:35 +00007 This file is part of Valgrind, an extensible x86 protected-mode
8 emulator for monitoring program execution on x86-Unixes.
sewardjde4a1d02002-03-22 01:27:54 +00009
nethercotebb1c9912004-01-04 16:43:23 +000010 Copyright (C) 2000-2004 Julian Seward
sewardjde4a1d02002-03-22 01:27:54 +000011 jseward@acm.org
sewardjde4a1d02002-03-22 01:27:54 +000012
13 This program is free software; you can redistribute it and/or
14 modify it under the terms of the GNU General Public License as
15 published by the Free Software Foundation; either version 2 of the
16 License, or (at your option) any later version.
17
18 This program is distributed in the hope that it will be useful, but
19 WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 General Public License for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software
25 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
26 02111-1307, USA.
27
njn25e49d8e72002-09-23 09:36:25 +000028 The GNU General Public License is contained in the file COPYING.
sewardjde4a1d02002-03-22 01:27:54 +000029*/
30
nethercote71980f02004-01-24 18:18:54 +000031#define _FILE_OFFSET_BITS 64
sewardjde4a1d02002-03-22 01:27:54 +000032
nethercote71980f02004-01-24 18:18:54 +000033#include "vg_include.h"
34#include "ume.h"
35#include "ume_arch.h"
36#include "ume_archdefs.h"
37
38#include <dirent.h>
39#include <dlfcn.h>
40#include <errno.h>
41#include <fcntl.h>
42#include <stdio.h>
fitzhardingeb727d042004-01-06 00:18:21 +000043#include <stdlib.h>
nethercote71980f02004-01-24 18:18:54 +000044#include <string.h>
45#include <sys/mman.h>
46#include <sys/types.h>
47#include <sys/stat.h>
fitzhardingeb727d042004-01-06 00:18:21 +000048#include <sys/ptrace.h>
49#include <sys/signal.h>
fitzhardingeb727d042004-01-06 00:18:21 +000050#include <sys/wait.h>
51#include <unistd.h>
52
thughes74b8de22004-04-22 18:12:31 +000053#ifndef AT_DCACHEBSIZE
54#define AT_DCACHEBSIZE 19
55#endif /* AT_DCACHEBSIZE */
56
57#ifndef AT_ICACHEBSIZE
58#define AT_ICACHEBSIZE 20
59#endif /* AT_ICACHEBSIZE */
60
61#ifndef AT_UCACHEBSIZE
62#define AT_UCACHEBSIZE 21
63#endif /* AT_UCACHEBSIZE */
64
nethercote71980f02004-01-24 18:18:54 +000065#ifndef AT_SYSINFO
66#define AT_SYSINFO 32
67#endif /* AT_SYSINFO */
68
69#ifndef AT_SYSINFO_EHDR
70#define AT_SYSINFO_EHDR 33
71#endif /* AT_SYSINFO_EHDR */
72
73#ifndef AT_SECURE
74#define AT_SECURE 23 /* secure mode boolean */
75#endif /* AT_SECURE */
76
nethercote71980f02004-01-24 18:18:54 +000077/* redzone gap between client address space and shadow */
78#define REDZONE_SIZE (1 * 1024*1024)
79
80/* size multiple for client address space */
nethercotee94b2de2004-06-23 16:15:06 +000081#define CLIENT_SIZE_MULTIPLE (1 * 1024*1024)
nethercote71980f02004-01-24 18:18:54 +000082
nethercotee2097312004-06-27 12:29:56 +000083/* Proportion of client space for its heap (rest is for mmaps + stack) */
84#define CLIENT_HEAP_PROPORTION 0.333
nethercote71980f02004-01-24 18:18:54 +000085
86/*====================================================================*/
87/*=== Global entities not referenced from generated code ===*/
88/*====================================================================*/
89
sewardjde4a1d02002-03-22 01:27:54 +000090/* ---------------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +000091 Startup stuff
sewardjde4a1d02002-03-22 01:27:54 +000092 ------------------------------------------------------------------ */
nethercote71980f02004-01-24 18:18:54 +000093/* linker-defined base address */
94extern char kickstart_base;
sewardjde4a1d02002-03-22 01:27:54 +000095
nethercote71980f02004-01-24 18:18:54 +000096/* Client address space, lowest to highest (see top of ume.c) */
97Addr VG_(client_base); /* client address space limits */
fitzhardinge98abfc72003-12-16 02:05:15 +000098Addr VG_(client_end);
99Addr VG_(client_mapbase);
fitzhardinge92360792003-12-24 10:11:11 +0000100Addr VG_(client_trampoline_code);
fitzhardinge98abfc72003-12-16 02:05:15 +0000101Addr VG_(clstk_base);
102Addr VG_(clstk_end);
nethercote71980f02004-01-24 18:18:54 +0000103
104Addr VG_(brk_base); /* start of brk */
105Addr VG_(brk_limit); /* current brk */
106
107Addr VG_(shadow_base); /* skin's shadow memory */
fitzhardinge98abfc72003-12-16 02:05:15 +0000108Addr VG_(shadow_end);
nethercote71980f02004-01-24 18:18:54 +0000109
110Addr VG_(valgrind_base); /* valgrind's address range */
fitzhardinge98abfc72003-12-16 02:05:15 +0000111Addr VG_(valgrind_end);
112
fitzhardingeb50068f2004-02-24 23:42:55 +0000113vki_rlimit VG_(client_rlimit_data);
114
nethercote71980f02004-01-24 18:18:54 +0000115/* This is set early to indicate whether this CPU has the
116 SSE/fxsave/fxrestor features. */
117Bool VG_(have_ssestate);
118
119/* Indicates presence, and holds address of client's sysinfo page, a
120 feature of some modern kernels used to provide vsyscalls, etc. */
121Bool VG_(sysinfo_page_exists) = False;
122Addr VG_(sysinfo_page_addr) = 0;
123
fitzhardinge98abfc72003-12-16 02:05:15 +0000124/* stage1 (main) executable */
fitzhardingea49f9b52003-12-16 22:26:45 +0000125Int VG_(vgexecfd) = -1;
126
127/* client executable */
128Int VG_(clexecfd) = -1;
fitzhardinge98abfc72003-12-16 02:05:15 +0000129
130/* Path to library directory */
131const Char *VG_(libdir) = VG_LIBDIR;
132
133/* our argc/argv */
134Int VG_(vg_argc);
135Char **VG_(vg_argv);
136
jsgf855d93d2003-10-13 22:26:55 +0000137/* PID of the main thread */
138Int VG_(main_pid);
139
140/* PGRP of process */
141Int VG_(main_pgrp);
njn25e49d8e72002-09-23 09:36:25 +0000142
thughesad1c9562004-06-26 11:27:52 +0000143/* Application-visible file descriptor limits */
144Int VG_(fd_soft_limit) = -1;
145Int VG_(fd_hard_limit) = -1;
fitzhardingef0046f22003-12-18 02:39:22 +0000146
nethercote71980f02004-01-24 18:18:54 +0000147/* As deduced from esp_at_startup, the client's argc, argv[] and
148 envp[] as extracted from the client's stack at startup-time. */
149Int VG_(client_argc);
150Char** VG_(client_argv);
151Char** VG_(client_envp);
sewardjde4a1d02002-03-22 01:27:54 +0000152
153/* ---------------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +0000154 Running stuff
sewardjde4a1d02002-03-22 01:27:54 +0000155 ------------------------------------------------------------------ */
nethercote71980f02004-01-24 18:18:54 +0000156/* Our signal delivery stack. */
njn6eba4ef2003-05-01 08:06:41 +0000157UInt VG_(sigstack)[VG_SIGSTACK_SIZE_W];
sewardjde4a1d02002-03-22 01:27:54 +0000158
nethercote71980f02004-01-24 18:18:54 +0000159/* jmp_buf for fatal signals */
160Int VG_(fatal_sigNo) = -1;
161Bool VG_(fatal_signal_set) = False;
162jmp_buf VG_(fatal_signal_jmpbuf);
sewardjde4a1d02002-03-22 01:27:54 +0000163
nethercote71980f02004-01-24 18:18:54 +0000164/* Counts downwards in VG_(run_innerloop). */
165UInt VG_(dispatch_ctr);
sewardjde4a1d02002-03-22 01:27:54 +0000166
167/* 64-bit counter for the number of basic blocks done. */
168ULong VG_(bbs_done);
sewardjde4a1d02002-03-22 01:27:54 +0000169
sewardj7e87e382002-05-03 19:09:05 +0000170/* This is the ThreadId of the last thread the scheduler ran. */
171ThreadId VG_(last_run_tid) = 0;
172
nethercote71980f02004-01-24 18:18:54 +0000173/* Tell the logging mechanism whether we are logging to a file
174 descriptor or a socket descriptor. */
175Bool VG_(logging_to_filedes) = True;
176
sewardj73cf3bc2002-11-03 03:20:15 +0000177
nethercote71980f02004-01-24 18:18:54 +0000178/*====================================================================*/
179/*=== Counters, for profiling purposes only ===*/
180/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +0000181
182/* Number of lookups which miss the fast tt helper. */
183UInt VG_(tt_fast_misses) = 0;
184
185
sewardjc0d8f682002-11-30 00:49:43 +0000186/* Counts for TT/TC informational messages. */
sewardjde4a1d02002-03-22 01:27:54 +0000187
sewardjde4a1d02002-03-22 01:27:54 +0000188/* Number and total o/t size of translations overall. */
189UInt VG_(overall_in_count) = 0;
190UInt VG_(overall_in_osize) = 0;
191UInt VG_(overall_in_tsize) = 0;
192/* Number and total o/t size of discards overall. */
193UInt VG_(overall_out_count) = 0;
194UInt VG_(overall_out_osize) = 0;
195UInt VG_(overall_out_tsize) = 0;
sewardjc0d8f682002-11-30 00:49:43 +0000196/* The number of discards of TT/TC. */
197UInt VG_(number_of_tc_discards) = 0;
sewardj22854b92002-11-30 14:00:47 +0000198/* Counts of chain and unchain operations done. */
199UInt VG_(bb_enchain_count) = 0;
200UInt VG_(bb_dechain_count) = 0;
201/* Number of unchained jumps performed. */
202UInt VG_(unchained_jumps_done) = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000203
204
205/* Counts pertaining to the register allocator. */
206
207/* total number of uinstrs input to reg-alloc */
208UInt VG_(uinstrs_prealloc) = 0;
209
210/* total number of uinstrs added due to spill code */
211UInt VG_(uinstrs_spill) = 0;
212
213/* number of bbs requiring spill code */
214UInt VG_(translations_needing_spill) = 0;
215
216/* total of register ranks over all translations */
217UInt VG_(total_reg_rank) = 0;
218
219
sewardjde4a1d02002-03-22 01:27:54 +0000220/* Counts pertaining to internal sanity checking. */
sewardjde4a1d02002-03-22 01:27:54 +0000221UInt VG_(sanity_fast_count) = 0;
222UInt VG_(sanity_slow_count) = 0;
223
sewardj2e93c502002-04-12 11:12:52 +0000224/* Counts pertaining to the scheduler. */
225UInt VG_(num_scheduling_events_MINOR) = 0;
226UInt VG_(num_scheduling_events_MAJOR) = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000227
228
nethercote71980f02004-01-24 18:18:54 +0000229static __inline__ Int safe_idiv(Int a, Int b)
230{
231 return (b == 0 ? 0 : a / b);
232}
233
234static void show_counts ( void )
235{
236 VG_(message)(Vg_DebugMsg,
237 " TT/TC: %d tc sectors discarded.",
238 VG_(number_of_tc_discards) );
239 VG_(message)(Vg_DebugMsg,
240 " %d chainings, %d unchainings.",
241 VG_(bb_enchain_count), VG_(bb_dechain_count) );
242 VG_(message)(Vg_DebugMsg,
243 "translate: new %d (%d -> %d; ratio %d:10)",
244 VG_(overall_in_count),
245 VG_(overall_in_osize),
246 VG_(overall_in_tsize),
247 safe_idiv(10*VG_(overall_in_tsize), VG_(overall_in_osize)));
248 VG_(message)(Vg_DebugMsg,
249 " discard %d (%d -> %d; ratio %d:10).",
250 VG_(overall_out_count),
251 VG_(overall_out_osize),
252 VG_(overall_out_tsize),
253 safe_idiv(10*VG_(overall_out_tsize), VG_(overall_out_osize)));
254 VG_(message)(Vg_DebugMsg,
255 " dispatch: %llu jumps (bb entries), of which %u (%lu%%) were unchained.",
256 VG_(bbs_done),
257 VG_(unchained_jumps_done),
258 ((ULong)(100) * (ULong)(VG_(unchained_jumps_done)))
259 / ( VG_(bbs_done)==0 ? 1 : VG_(bbs_done) )
260 );
261
262 VG_(message)(Vg_DebugMsg,
263 " %d/%d major/minor sched events. %d tt_fast misses.",
264 VG_(num_scheduling_events_MAJOR),
265 VG_(num_scheduling_events_MINOR),
266 VG_(tt_fast_misses));
267
268 VG_(message)(Vg_DebugMsg,
269 "reg-alloc: %d t-req-spill, "
270 "%d+%d orig+spill uis, %d total-reg-r.",
271 VG_(translations_needing_spill),
272 VG_(uinstrs_prealloc),
273 VG_(uinstrs_spill),
274 VG_(total_reg_rank) );
275 VG_(message)(Vg_DebugMsg,
276 " sanity: %d cheap, %d expensive checks.",
277 VG_(sanity_fast_count),
278 VG_(sanity_slow_count) );
279 VG_(print_ccall_stats)();
280}
281
282
283/*====================================================================*/
284/*=== Miscellaneous global functions ===*/
285/*====================================================================*/
286
nethercote04d0fbc2004-01-26 16:48:06 +0000287/* Start debugger and get it to attach to this process. Called if the
288 user requests this service after an error has been shown, so she can
nethercote71980f02004-01-24 18:18:54 +0000289 poke around and look at parameters, memory, etc. You can't
nethercote04d0fbc2004-01-26 16:48:06 +0000290 meaningfully get the debugger to continue the program, though; to
291 continue, quit the debugger. */
292void VG_(start_debugger) ( Int tid )
nethercote71980f02004-01-24 18:18:54 +0000293{
294 Int pid;
295
296 if ((pid = fork()) == 0) {
297 ptrace(PTRACE_TRACEME, 0, NULL, NULL);
298 VG_(kkill)(VG_(getpid)(), VKI_SIGSTOP);
299
300 } else if (pid > 0) {
301 struct user_regs_struct regs;
302 Int status;
303 Int res;
304
305 if (VG_(is_running_thread)( tid )) {
fitzhardinged65dcad2004-03-13 02:06:58 +0000306 regs.cs = VG_(baseBlock)[VGOFF_(m_cs)];
307 regs.ss = VG_(baseBlock)[VGOFF_(m_ss)];
308 regs.ds = VG_(baseBlock)[VGOFF_(m_ds)];
309 regs.es = VG_(baseBlock)[VGOFF_(m_es)];
310 regs.fs = VG_(baseBlock)[VGOFF_(m_fs)];
311 regs.gs = VG_(baseBlock)[VGOFF_(m_gs)];
nethercote71980f02004-01-24 18:18:54 +0000312 regs.eax = VG_(baseBlock)[VGOFF_(m_eax)];
313 regs.ebx = VG_(baseBlock)[VGOFF_(m_ebx)];
314 regs.ecx = VG_(baseBlock)[VGOFF_(m_ecx)];
315 regs.edx = VG_(baseBlock)[VGOFF_(m_edx)];
316 regs.esi = VG_(baseBlock)[VGOFF_(m_esi)];
317 regs.edi = VG_(baseBlock)[VGOFF_(m_edi)];
318 regs.ebp = VG_(baseBlock)[VGOFF_(m_ebp)];
319 regs.esp = VG_(baseBlock)[VGOFF_(m_esp)];
320 regs.eflags = VG_(baseBlock)[VGOFF_(m_eflags)];
321 regs.eip = VG_(baseBlock)[VGOFF_(m_eip)];
322 } else {
323 ThreadState* tst = & VG_(threads)[ tid ];
324
fitzhardinged65dcad2004-03-13 02:06:58 +0000325 regs.cs = tst->m_cs;
326 regs.ss = tst->m_ss;
327 regs.ds = tst->m_ds;
328 regs.es = tst->m_es;
329 regs.fs = tst->m_fs;
330 regs.gs = tst->m_gs;
nethercote71980f02004-01-24 18:18:54 +0000331 regs.eax = tst->m_eax;
332 regs.ebx = tst->m_ebx;
333 regs.ecx = tst->m_ecx;
334 regs.edx = tst->m_edx;
335 regs.esi = tst->m_esi;
336 regs.edi = tst->m_edi;
337 regs.ebp = tst->m_ebp;
338 regs.esp = tst->m_esp;
339 regs.eflags = tst->m_eflags;
340 regs.eip = tst->m_eip;
341 }
342
343 if ((res = VG_(waitpid)(pid, &status, 0)) == pid &&
344 WIFSTOPPED(status) && WSTOPSIG(status) == SIGSTOP &&
345 ptrace(PTRACE_SETREGS, pid, NULL, &regs) == 0 &&
thughes1d160052004-04-21 15:39:57 +0000346 kill(pid, SIGSTOP) == 0 &&
347 ptrace(PTRACE_DETACH, pid, NULL, 0) == 0) {
nethercote04d0fbc2004-01-26 16:48:06 +0000348 Char pidbuf[15];
349 Char file[30];
350 Char buf[100];
351 Char *bufptr;
352 Char *cmdptr;
353
354 VG_(sprintf)(pidbuf, "%d", pid);
355 VG_(sprintf)(file, "/proc/%d/fd/%d", pid, VG_(clexecfd));
356
357 bufptr = buf;
358 cmdptr = VG_(clo_db_command);
359
360 while (*cmdptr) {
361 switch (*cmdptr) {
362 case '%':
363 switch (*++cmdptr) {
364 case 'f':
365 VG_(memcpy)(bufptr, file, VG_(strlen)(file));
366 bufptr += VG_(strlen)(file);
367 cmdptr++;
368 break;
369 case 'p':
370 VG_(memcpy)(bufptr, pidbuf, VG_(strlen)(pidbuf));
371 bufptr += VG_(strlen)(pidbuf);
372 cmdptr++;
373 break;
374 default:
375 *bufptr++ = *cmdptr++;
376 break;
377 }
378 break;
379 default:
380 *bufptr++ = *cmdptr++;
381 break;
382 }
383 }
384
385 *bufptr++ = '\0';
386
387 VG_(message)(Vg_UserMsg, "starting debugger with cmd: %s", buf);
nethercote71980f02004-01-24 18:18:54 +0000388 res = VG_(system)(buf);
389 if (res == 0) {
390 VG_(message)(Vg_UserMsg, "");
391 VG_(message)(Vg_UserMsg,
nethercote04d0fbc2004-01-26 16:48:06 +0000392 "Debugger has detached. Valgrind regains control. We continue.");
nethercote71980f02004-01-24 18:18:54 +0000393 } else {
394 VG_(message)(Vg_UserMsg, "Apparently failed!");
395 VG_(message)(Vg_UserMsg, "");
396 }
397 }
398
399 VG_(kkill)(pid, VKI_SIGKILL);
400 VG_(waitpid)(pid, &status, 0);
401 }
402}
403
404
405/* Print some helpful-ish text about unimplemented things, and give
406 up. */
407void VG_(unimplemented) ( Char* msg )
408{
409 VG_(message)(Vg_UserMsg, "");
410 VG_(message)(Vg_UserMsg,
411 "Valgrind detected that your program requires");
412 VG_(message)(Vg_UserMsg,
413 "the following unimplemented functionality:");
414 VG_(message)(Vg_UserMsg, " %s", msg);
415 VG_(message)(Vg_UserMsg,
416 "This may be because the functionality is hard to implement,");
417 VG_(message)(Vg_UserMsg,
418 "or because no reasonable program would behave this way,");
419 VG_(message)(Vg_UserMsg,
420 "or because nobody has yet needed it. In any case, let us know at");
421 VG_(message)(Vg_UserMsg,
422 "%s and/or try to work around the problem, if you can.", VG_BUGS_TO);
423 VG_(message)(Vg_UserMsg,
424 "");
425 VG_(message)(Vg_UserMsg,
426 "Valgrind has to exit now. Sorry. Bye!");
427 VG_(message)(Vg_UserMsg,
428 "");
429 VG_(pp_sched_status)();
430 VG_(exit)(1);
431}
432
433Addr VG_(get_stack_pointer) ( void )
434{
435 return VG_(baseBlock)[VGOFF_(m_esp)];
436}
437
438/* Debugging thing .. can be called from assembly with OYNK macro. */
439void VG_(oynk) ( Int n )
440{
441 OINK(n);
442}
443
444/* Initialize the PID and PGRP of scheduler LWP; this is also called
445 in any new children after fork. */
446static void newpid(ThreadId unused)
447{
448 /* PID of scheduler LWP */
449 VG_(main_pid) = VG_(getpid)();
450 VG_(main_pgrp) = VG_(getpgrp)();
451}
452
453/*====================================================================*/
454/*=== Check we were launched by stage 1 ===*/
455/*====================================================================*/
456
457/* Look for our AUXV table */
458static void scan_auxv(void)
459{
460 const struct ume_auxv *auxv = find_auxv((int *)ume_exec_esp);
461 int found = 0;
462
463 for (; auxv->a_type != AT_NULL; auxv++)
464 switch(auxv->a_type) {
465 case AT_UME_PADFD:
466 as_setpadfd(auxv->u.a_val);
467 found |= 1;
468 break;
469
470 case AT_UME_EXECFD:
471 VG_(vgexecfd) = auxv->u.a_val;
472 found |= 2;
473 break;
474 }
475
nethercote361a14e2004-07-26 11:11:56 +0000476 if ( found != (1|2) ) {
477 fprintf(stderr, "valgrind: stage2 must be launched by stage1\n");
nethercote71980f02004-01-24 18:18:54 +0000478 exit(127);
479 }
480}
481
482
483/*====================================================================*/
484/*=== Address space determination ===*/
485/*====================================================================*/
486
487/* Pad client space so it doesn't get filled in before the right time */
488static void layout_client_space(Addr argc_addr)
489{
490 VG_(client_base) = CLIENT_BASE;
nethercotec314eba2004-07-15 12:59:41 +0000491 VG_(valgrind_base) = (addr_t)&kickstart_base;
nethercote71980f02004-01-24 18:18:54 +0000492 VG_(valgrind_end) = ROUNDUP(argc_addr, 0x10000); /* stack */
493
nethercote71980f02004-01-24 18:18:54 +0000494 as_pad((void *)VG_(client_base), (void *)VG_(valgrind_base));
495}
496
497static void layout_remaining_space(float ratio)
498{
nethercotee567e702004-07-10 17:49:17 +0000499 Int ires;
500 void* vres;
501
nethercote71980f02004-01-24 18:18:54 +0000502 /* This tries to give the client as large as possible address space while
503 * taking into account the tool's shadow needs. */
504 addr_t client_size = ROUNDDN((VG_(valgrind_base) - REDZONE_SIZE) / (1. + ratio),
505 CLIENT_SIZE_MULTIPLE);
506 addr_t shadow_size = PGROUNDUP(client_size * ratio);
507
508 VG_(client_end) = VG_(client_base) + client_size;
nethercotee2097312004-06-27 12:29:56 +0000509 /* where !FIXED mmap goes */
nethercotebc7b4f42004-07-26 12:44:35 +0000510 VG_(client_mapbase) = VG_(client_base) +
511 PGROUNDDN((addr_t)(client_size * CLIENT_HEAP_PROPORTION));
nethercote71980f02004-01-24 18:18:54 +0000512
513 VG_(shadow_base) = VG_(client_end) + REDZONE_SIZE;
514 VG_(shadow_end) = VG_(shadow_base) + shadow_size;
515
nethercotee2097312004-06-27 12:29:56 +0000516#define SEGSIZE(a,b) ((VG_(b) - VG_(a))/(1024*1024))
517
nethercote71980f02004-01-24 18:18:54 +0000518 if (0)
nethercotee2097312004-06-27 12:29:56 +0000519 VG_(printf)(
520 "client_base %8x (%dMB)\n"
521 "client_mapbase %8x (%dMB)\n"
522 "client_end %8x (%dMB)\n"
523 "shadow_base %8x (%dMB)\n"
524 "shadow_end %8x (%dMB)\n"
525 "valgrind_base %8x (%dMB)\n"
nethercotee2097312004-06-27 12:29:56 +0000526 "valgrind_end %8x\n",
527 VG_(client_base), SEGSIZE(client_base, client_mapbase),
528 VG_(client_mapbase), SEGSIZE(client_mapbase, client_end),
529 VG_(client_end), SEGSIZE(client_end, shadow_base),
530 VG_(shadow_base), SEGSIZE(shadow_base, shadow_end),
531 VG_(shadow_end), SEGSIZE(shadow_end, valgrind_base),
nethercotec314eba2004-07-15 12:59:41 +0000532 VG_(valgrind_base), SEGSIZE(valgrind_base, valgrind_end),
nethercotee2097312004-06-27 12:29:56 +0000533 VG_(valgrind_end)
534 );
535
536#undef SEGSIZE
nethercote71980f02004-01-24 18:18:54 +0000537
538 // Ban redzone
nethercotee567e702004-07-10 17:49:17 +0000539 vres = mmap((void *)VG_(client_end), REDZONE_SIZE, PROT_NONE,
540 MAP_FIXED|MAP_ANON|MAP_PRIVATE, -1, 0);
541 vg_assert((void*)-1 != vres);
nethercote71980f02004-01-24 18:18:54 +0000542
543 // Make client hole
nethercotee567e702004-07-10 17:49:17 +0000544 ires = munmap((void*)VG_(client_base), client_size);
545 vg_assert(0 == ires);
nethercote71980f02004-01-24 18:18:54 +0000546
547 // Map shadow memory.
548 // Initially all inaccessible, incrementally initialized as it is used
nethercotee567e702004-07-10 17:49:17 +0000549 if (shadow_size != 0) {
550 vres = mmap((char *)VG_(shadow_base), shadow_size, PROT_NONE,
551 MAP_PRIVATE|MAP_ANON|MAP_FIXED, -1, 0);
552 vg_assert((void*)-1 != vres);
553 }
nethercote71980f02004-01-24 18:18:54 +0000554}
555
556/*====================================================================*/
557/*=== Command line setup ===*/
558/*====================================================================*/
559
560/* Nb: malloc'd memory never freed -- kept throughout like argv, envp */
561static char* get_file_clo(char* dir)
562{
563# define FLEN 512
564 Int fd, n;
565 struct stat s1;
566 char* f_clo = NULL;
567 char filename[FLEN];
568
569 snprintf(filename, FLEN, "%s/.valgrindrc", ( NULL == dir ? "" : dir ) );
570 fd = VG_(open)(filename, 0, VKI_S_IRUSR);
571 if ( fd > 0 ) {
572 if ( 0 == fstat(fd, &s1) ) {
573 f_clo = malloc(s1.st_size+1);
574 vg_assert(f_clo);
575 n = read(fd, f_clo, s1.st_size);
576 if (n == -1) n = 0;
577 f_clo[n] = '\0';
578 }
579 close(fd);
580 }
581 return f_clo;
582# undef FLEN
583}
584
nethercotee2097312004-06-27 12:29:56 +0000585#define ISSPACE(cc) ((cc) == ' ' || (cc) == '\t' || (cc) == '\n')
586
nethercote71980f02004-01-24 18:18:54 +0000587static Int count_args(char* s)
588{
589 Int n = 0;
590 if (s) {
591 char* cp = s;
592 while (True) {
593 // We have alternating sequences: blanks, non-blanks, blanks...
594 // count the non-blanks sequences.
595 while ( ISSPACE(*cp) ) cp++;
596 if ( !*cp ) break;
597 n++;
598 while ( !ISSPACE(*cp) && *cp ) cp++;
599 }
600 }
601 return n;
602}
603
604/* add args out of environment, skipping multiple spaces and -- args */
605static char** copy_args( char* s, char** to )
606{
607 if (s) {
608 char* cp = s;
609 while (True) {
610 // We have alternating sequences: blanks, non-blanks, blanks...
611 // copy the non-blanks sequences, and add terminating '\0'
612 while ( ISSPACE(*cp) ) cp++;
613 if ( !*cp ) break;
614 *to++ = cp;
615 while ( !ISSPACE(*cp) && *cp ) cp++;
616 if ( *cp ) *cp++ = '\0'; // terminate if necessary
617 if (VG_STREQ(to[-1], "--")) to--; // undo any '--' arg
618 }
619 }
620 return to;
621}
622
nethercotee2097312004-06-27 12:29:56 +0000623#undef ISSPACE
624
nethercote71980f02004-01-24 18:18:54 +0000625// Augment command line with arguments from environment and .valgrindrc
626// files.
627static void augment_command_line(Int* vg_argc_inout, char*** vg_argv_inout)
628{
629 int vg_argc = *vg_argc_inout;
630 char** vg_argv = *vg_argv_inout;
631
632 char* env_clo = getenv(VALGRINDOPTS);
633 char* f1_clo = get_file_clo( getenv("HOME") );
634 char* f2_clo = get_file_clo(".");
635
636 /* copy any extra args from file or environment, if present */
637 if ( (env_clo && *env_clo) || (f1_clo && *f1_clo) || (f2_clo && *f2_clo) ) {
638 /* ' ' separated extra options */
639 char **from;
640 char **to;
641 int env_arg_count, f1_arg_count, f2_arg_count;
642
643 env_arg_count = count_args(env_clo);
644 f1_arg_count = count_args(f1_clo);
645 f2_arg_count = count_args(f2_clo);
646
647 if (0)
648 printf("extra-argc=%d %d %d\n",
649 env_arg_count, f1_arg_count, f2_arg_count);
650
651 /* +2: +1 for null-termination, +1 for added '--' */
652 from = vg_argv;
653 vg_argv = malloc( (vg_argc + env_arg_count + f1_arg_count
654 + f2_arg_count + 2) * sizeof(char **));
nethercote7c018f42004-07-17 16:40:50 +0000655 vg_assert(vg_argv);
nethercote71980f02004-01-24 18:18:54 +0000656 to = vg_argv;
657
658 /* copy argv[0] */
659 *to++ = *from++;
660
661 /* Copy extra args from env var and file, in the order: ~/.valgrindrc,
662 * $VALGRIND_OPTS, ./.valgrindrc -- more local options are put later
663 * to override less local ones. */
664 to = copy_args(f1_clo, to);
665 to = copy_args(env_clo, to);
666 to = copy_args(f2_clo, to);
667
668 /* copy original arguments, stopping at command or -- */
669 while (*from) {
670 if (**from != '-')
671 break;
672 if (VG_STREQ(*from, "--")) {
673 from++; /* skip -- */
674 break;
675 }
676 *to++ = *from++;
677 }
678
679 /* add -- */
680 *to++ = "--";
681
682 vg_argc = to - vg_argv;
683
684 /* copy rest of original command line, then NULL */
685 while (*from) *to++ = *from++;
686 *to = NULL;
687 }
688
689 *vg_argc_inout = vg_argc;
690 *vg_argv_inout = vg_argv;
691}
692
693static void get_command_line( int argc, char** argv,
694 Int* vg_argc_out, Char*** vg_argv_out,
695 char*** cl_argv_out )
696{
697 int vg_argc;
698 char** vg_argv;
699 char** cl_argv;
700 char* env_clo = getenv(VALGRINDCLO);
701
702 if (env_clo != NULL && *env_clo != '\0') {
703 char *cp;
704 char **cpp;
705
706 /* OK, we're getting all our arguments from the environment - the
707 entire command line belongs to the client (including argv[0]) */
708 vg_argc = 1; /* argv[0] */
709 for (cp = env_clo; *cp; cp++)
710 if (*cp == '\01')
711 vg_argc++;
712
713 vg_argv = malloc(sizeof(char **) * (vg_argc + 1));
nethercote7c018f42004-07-17 16:40:50 +0000714 vg_assert(vg_argv);
nethercote71980f02004-01-24 18:18:54 +0000715
716 cpp = vg_argv;
717
718 *cpp++ = "valgrind"; /* nominal argv[0] */
719 *cpp++ = env_clo;
720
721 for (cp = env_clo; *cp; cp++) {
722 if (*cp == '\01') {
723 *cp++ = '\0'; /* chop it up in place */
724 *cpp++ = cp;
725 }
726 }
727 *cpp = NULL;
728 cl_argv = argv;
729
730 } else {
731 /* Count the arguments on the command line. */
732 vg_argv = argv;
733
734 for (vg_argc = 1; vg_argc < argc; vg_argc++) {
735 if (argv[vg_argc][0] != '-') /* exe name */
736 break;
737 if (VG_STREQ(argv[vg_argc], "--")) { /* dummy arg */
738 vg_argc++;
739 break;
740 }
741 }
742 cl_argv = &argv[vg_argc];
743
744 /* Get extra args from VALGRIND_OPTS and .valgrindrc files.
745 * Note we don't do this if getting args from VALGRINDCLO. */
746 augment_command_line(&vg_argc, &vg_argv);
747 }
748
749 if (0) {
750 Int i;
751 for (i = 0; i < vg_argc; i++)
752 printf("vg_argv[%d]=\"%s\"\n", i, vg_argv[i]);
753 }
754
755 *vg_argc_out = vg_argc;
756 *vg_argv_out = (Char**)vg_argv;
757 *cl_argv_out = cl_argv;
758}
759
760
761/*====================================================================*/
762/*=== Environment and stack setup ===*/
763/*====================================================================*/
764
765/* Scan a colon-separated list, and call a function on each element.
766 The string must be mutable, because we insert a temporary '\0', but
thughes4ad52d02004-06-27 17:37:21 +0000767 the string will end up unmodified. (*func) should return True if it
nethercote71980f02004-01-24 18:18:54 +0000768 doesn't need to see any more.
thughes4ad52d02004-06-27 17:37:21 +0000769
770 This routine will return True if (*func) returns True and False if
771 it reaches the end of the list without that happening.
nethercote71980f02004-01-24 18:18:54 +0000772*/
thughes4ad52d02004-06-27 17:37:21 +0000773static Bool scan_colsep(char *colsep, Bool (*func)(const char *))
nethercote71980f02004-01-24 18:18:54 +0000774{
775 char *cp, *entry;
776 int end;
777
778 if (colsep == NULL ||
779 *colsep == '\0')
thughes4ad52d02004-06-27 17:37:21 +0000780 return False;
nethercote71980f02004-01-24 18:18:54 +0000781
782 entry = cp = colsep;
783
784 do {
785 end = (*cp == '\0');
786
787 if (*cp == ':' || *cp == '\0') {
788 char save = *cp;
789
790 *cp = '\0';
thughes21942d92004-07-12 09:35:37 +0000791 if ((*func)(entry)) {
792 *cp = save;
thughes4ad52d02004-06-27 17:37:21 +0000793 return True;
thughes21942d92004-07-12 09:35:37 +0000794 }
nethercote71980f02004-01-24 18:18:54 +0000795 *cp = save;
796 entry = cp+1;
797 }
798 cp++;
799 } while(!end);
thughes4ad52d02004-06-27 17:37:21 +0000800
801 return False;
802}
803
804static Bool contains(const char *p) {
805 if (VG_STREQ(p, VG_(libdir))) {
806 return True;
807 }
808 return False;
nethercote71980f02004-01-24 18:18:54 +0000809}
810
811/* Prepare the client's environment. This is basically a copy of our
812 environment, except:
813 1. LD_LIBRARY_PATH=$VALGRINDLIB:$LD_LIBRARY_PATH
814 2. LD_PRELOAD=$VALGRINDLIB/vg_inject.so:($VALGRINDLIB/vgpreload_TOOL.so:)?$LD_PRELOAD
815
816 If any of these is missing, then it is added.
817
818 Yummy. String hacking in C.
819
820 If this needs to handle any more variables it should be hacked
821 into something table driven.
822 */
823static char **fix_environment(char **origenv, const char *preload)
824{
825 static const char inject_so[] = "vg_inject.so";
826 static const char ld_library_path[] = "LD_LIBRARY_PATH=";
827 static const char ld_preload[] = "LD_PRELOAD=";
828 static const char valgrind_clo[] = VALGRINDCLO "=";
829 static const int ld_library_path_len = sizeof(ld_library_path)-1;
830 static const int ld_preload_len = sizeof(ld_preload)-1;
831 static const int valgrind_clo_len = sizeof(valgrind_clo)-1;
832 int ld_preload_done = 0;
833 int ld_library_path_done = 0;
834 char *inject_path;
835 int inject_path_len;
836 int vgliblen = strlen(VG_(libdir));
837 char **cpp;
838 char **ret;
839 int envc;
840 const int preloadlen = (preload == NULL) ? 0 : strlen(preload);
841
842 /* Find the vg_inject.so; also make room for the tool preload
843 library */
844 inject_path_len = sizeof(inject_so) + vgliblen + preloadlen + 16;
845 inject_path = malloc(inject_path_len);
nethercote7c018f42004-07-17 16:40:50 +0000846 vg_assert(inject_path);
nethercote71980f02004-01-24 18:18:54 +0000847
848 if (preload)
849 snprintf(inject_path, inject_path_len, "%s/%s:%s",
850 VG_(libdir), inject_so, preload);
851 else
852 snprintf(inject_path, inject_path_len, "%s/%s",
853 VG_(libdir), inject_so);
854
855 /* Count the original size of the env */
856 envc = 0; /* trailing NULL */
857 for (cpp = origenv; cpp && *cpp; cpp++)
858 envc++;
859
860 /* Allocate a new space */
861 ret = malloc(sizeof(char *) * (envc+3+1)); /* 3 new entries + NULL */
nethercote7c018f42004-07-17 16:40:50 +0000862 vg_assert(ret);
nethercote71980f02004-01-24 18:18:54 +0000863
864 /* copy it over */
865 for (cpp = ret; *origenv; )
866 *cpp++ = *origenv++;
867 *cpp = NULL;
868
869 vg_assert(envc == (cpp - ret));
870
871 /* Walk over the new environment, mashing as we go */
872 for (cpp = ret; cpp && *cpp; cpp++) {
873 if (memcmp(*cpp, ld_library_path, ld_library_path_len) == 0) {
nethercote71980f02004-01-24 18:18:54 +0000874 /* If the LD_LIBRARY_PATH already contains libdir, then don't
875 bother adding it again, even if it isn't the first (it
876 seems that the Java runtime will keep reexecing itself
877 unless its paths are at the front of LD_LIBRARY_PATH) */
thughes4ad52d02004-06-27 17:37:21 +0000878 if (!scan_colsep(*cpp + ld_library_path_len, contains)) {
nethercote71980f02004-01-24 18:18:54 +0000879 int len = strlen(*cpp) + vgliblen*2 + 16;
880 char *cp = malloc(len);
nethercote7c018f42004-07-17 16:40:50 +0000881 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000882
883 snprintf(cp, len, "%s%s:%s",
884 ld_library_path, VG_(libdir),
885 (*cpp)+ld_library_path_len);
886
887 *cpp = cp;
888 }
889
890 ld_library_path_done = 1;
891 } else if (memcmp(*cpp, ld_preload, ld_preload_len) == 0) {
892 int len = strlen(*cpp) + inject_path_len;
893 char *cp = malloc(len);
nethercote7c018f42004-07-17 16:40:50 +0000894 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000895
896 snprintf(cp, len, "%s%s:%s",
897 ld_preload, inject_path, (*cpp)+ld_preload_len);
898
899 *cpp = cp;
900
901 ld_preload_done = 1;
902 } else if (memcmp(*cpp, valgrind_clo, valgrind_clo_len) == 0) {
903 *cpp = "";
904 }
905 }
906
907 /* Add the missing bits */
908
909 if (!ld_library_path_done) {
910 int len = ld_library_path_len + vgliblen*2 + 16;
911 char *cp = malloc(len);
nethercote7c018f42004-07-17 16:40:50 +0000912 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000913
914 snprintf(cp, len, "%s%s", ld_library_path, VG_(libdir));
915
916 ret[envc++] = cp;
917 }
918
919 if (!ld_preload_done) {
920 int len = ld_preload_len + inject_path_len;
921 char *cp = malloc(len);
nethercote7c018f42004-07-17 16:40:50 +0000922 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000923
924 snprintf(cp, len, "%s%s",
925 ld_preload, inject_path);
926
927 ret[envc++] = cp;
928 }
929
930 ret[envc] = NULL;
931
932 return ret;
933}
934
935extern char **environ; /* our environment */
936//#include <error.h>
937
938/* Add a string onto the string table, and return its address */
939static char *copy_str(char **tab, const char *str)
940{
941 char *cp = *tab;
942 char *orig = cp;
943
944 while(*str)
945 *cp++ = *str++;
946 *cp++ = '\0';
947
948 if (0)
nethercotef84f6952004-07-15 14:58:33 +0000949 printf("copied %p \"%s\" len %d\n", orig, orig, cp-orig);
nethercote71980f02004-01-24 18:18:54 +0000950
951 *tab = cp;
952
953 return orig;
954}
955
956/*
957 This sets up the client's initial stack, containing the args,
958 environment and aux vector.
959
960 The format of the stack is:
961
962 higher address +-----------------+
963 | Trampoline code |
964 +-----------------+
965 | |
966 : string table :
967 | |
968 +-----------------+
969 | AT_NULL |
970 - -
971 | auxv |
972 +-----------------+
973 | NULL |
974 - -
975 | envp |
976 +-----------------+
977 | NULL |
978 - -
979 | argv |
980 +-----------------+
981 | argc |
982 lower address +-----------------+ <- esp
983 | undefined |
984 : :
985 */
986static Addr setup_client_stack(char **orig_argv, char **orig_envp,
987 const struct exeinfo *info,
988 UInt** client_auxv)
989{
nethercotee567e702004-07-10 17:49:17 +0000990 void* res;
nethercote71980f02004-01-24 18:18:54 +0000991 char **cpp;
992 char *strtab; /* string table */
993 char *stringbase;
994 addr_t *ptr;
995 struct ume_auxv *auxv;
996 const struct ume_auxv *orig_auxv;
997 const struct ume_auxv *cauxv;
998 unsigned stringsize; /* total size of strings in bytes */
999 unsigned auxsize; /* total size of auxv in bytes */
1000 int argc; /* total argc */
1001 int envc; /* total number of env vars */
1002 unsigned stacksize; /* total client stack size */
1003 addr_t cl_esp; /* client stack base (initial esp) */
1004
1005 /* use our own auxv as a prototype */
1006 orig_auxv = find_auxv(ume_exec_esp);
1007
1008 /* ==================== compute sizes ==================== */
1009
1010 /* first of all, work out how big the client stack will be */
1011 stringsize = 0;
1012
1013 /* paste on the extra args if the loader needs them (ie, the #!
1014 interpreter and its argument) */
1015 argc = 0;
nethercoted6a56872004-07-26 15:32:47 +00001016 if (info->interp_name != NULL) {
nethercote71980f02004-01-24 18:18:54 +00001017 argc++;
nethercoted6a56872004-07-26 15:32:47 +00001018 stringsize += strlen(info->interp_name) + 1;
nethercote71980f02004-01-24 18:18:54 +00001019 }
nethercoted6a56872004-07-26 15:32:47 +00001020 if (info->interp_args != NULL) {
nethercote71980f02004-01-24 18:18:54 +00001021 argc++;
nethercoted6a56872004-07-26 15:32:47 +00001022 stringsize += strlen(info->interp_args) + 1;
nethercote71980f02004-01-24 18:18:54 +00001023 }
1024
1025 /* now scan the args we're given... */
1026 for (cpp = orig_argv; *cpp; cpp++) {
1027 argc++;
1028 stringsize += strlen(*cpp) + 1;
1029 }
1030
1031 /* ...and the environment */
1032 envc = 0;
1033 for (cpp = orig_envp; cpp && *cpp; cpp++) {
1034 envc++;
1035 stringsize += strlen(*cpp) + 1;
1036 }
1037
1038 /* now, how big is the auxv? */
1039 auxsize = sizeof(*auxv); /* there's always at least one entry: AT_NULL */
1040 for (cauxv = orig_auxv; cauxv->a_type != AT_NULL; cauxv++) {
1041 if (cauxv->a_type == AT_PLATFORM)
1042 stringsize += strlen(cauxv->u.a_ptr) + 1;
1043 auxsize += sizeof(*cauxv);
1044 }
1045
1046 /* OK, now we know how big the client stack is */
1047 stacksize =
1048 sizeof(int) + /* argc */
1049 sizeof(char **)*argc + /* argv */
1050 sizeof(char **) + /* terminal NULL */
1051 sizeof(char **)*envc + /* envp */
1052 sizeof(char **) + /* terminal NULL */
1053 auxsize + /* auxv */
1054 ROUNDUP(stringsize, sizeof(int)) +/* strings (aligned) */
1055 VKI_BYTES_PER_PAGE; /* page for trampoline code */
1056
nethercotef84f6952004-07-15 14:58:33 +00001057 // decide where stack goes!
1058 VG_(clstk_end) = VG_(client_end);
1059
1060 VG_(client_trampoline_code) = VG_(clstk_end) - VKI_BYTES_PER_PAGE;
1061
nethercote71980f02004-01-24 18:18:54 +00001062 /* cl_esp is the client's stack pointer */
nethercotef84f6952004-07-15 14:58:33 +00001063 cl_esp = VG_(clstk_end) - stacksize;
nethercote71980f02004-01-24 18:18:54 +00001064 cl_esp = ROUNDDN(cl_esp, 16); /* make stack 16 byte aligned */
1065
nethercote71980f02004-01-24 18:18:54 +00001066 /* base of the string table (aligned) */
1067 stringbase = strtab = (char *)(VG_(client_trampoline_code) - ROUNDUP(stringsize, sizeof(int)));
1068
1069 VG_(clstk_base) = PGROUNDDN(cl_esp);
nethercote71980f02004-01-24 18:18:54 +00001070
nethercote5ee67ca2004-06-22 14:00:09 +00001071 if (0)
1072 printf("stringsize=%d auxsize=%d stacksize=%d\n"
1073 "clstk_base %x\n"
1074 "clstk_end %x\n",
1075 stringsize, auxsize, stacksize, VG_(clstk_base), VG_(clstk_end));
1076
1077
nethercote71980f02004-01-24 18:18:54 +00001078 /* ==================== allocate space ==================== */
1079
1080 /* allocate a stack - mmap enough space for the stack */
nethercotef84f6952004-07-15 14:58:33 +00001081 res = mmap((void *)PGROUNDDN(cl_esp), VG_(clstk_end) - PGROUNDDN(cl_esp),
nethercotee567e702004-07-10 17:49:17 +00001082 PROT_READ | PROT_WRITE | PROT_EXEC,
1083 MAP_PRIVATE | MAP_ANON | MAP_FIXED, -1, 0);
1084 vg_assert((void*)-1 != res);
nethercote71980f02004-01-24 18:18:54 +00001085
1086 /* ==================== copy client stack ==================== */
1087
1088 ptr = (addr_t *)cl_esp;
1089
1090 /* --- argc --- */
1091 *ptr++ = argc; /* client argc */
1092
1093 /* --- argv --- */
nethercoted6a56872004-07-26 15:32:47 +00001094 if (info->interp_name) {
1095 *ptr++ = (addr_t)copy_str(&strtab, info->interp_name);
1096 free(info->interp_name);
nethercote71980f02004-01-24 18:18:54 +00001097 }
nethercoted6a56872004-07-26 15:32:47 +00001098 if (info->interp_args) {
1099 *ptr++ = (addr_t)copy_str(&strtab, info->interp_args);
1100 free(info->interp_args);
nethercote71980f02004-01-24 18:18:54 +00001101 }
1102 for (cpp = orig_argv; *cpp; ptr++, cpp++) {
1103 *ptr = (addr_t)copy_str(&strtab, *cpp);
1104 }
1105 *ptr++ = 0;
1106
1107 /* --- envp --- */
1108 VG_(client_envp) = (Char **)ptr;
1109 for (cpp = orig_envp; cpp && *cpp; ptr++, cpp++)
1110 *ptr = (addr_t)copy_str(&strtab, *cpp);
1111 *ptr++ = 0;
1112
1113 /* --- auxv --- */
1114 auxv = (struct ume_auxv *)ptr;
1115 *client_auxv = (UInt *)auxv;
1116
1117 for (; orig_auxv->a_type != AT_NULL; auxv++, orig_auxv++) {
1118 /* copy the entry... */
1119 *auxv = *orig_auxv;
1120
1121 /* ...and fix up the copy */
1122 switch(auxv->a_type) {
1123 case AT_PHDR:
1124 if (info->phdr == 0)
1125 auxv->a_type = AT_IGNORE;
1126 else
1127 auxv->u.a_val = info->phdr;
1128 break;
1129
1130 case AT_PHNUM:
1131 if (info->phdr == 0)
1132 auxv->a_type = AT_IGNORE;
1133 else
1134 auxv->u.a_val = info->phnum;
1135 break;
1136
1137 case AT_BASE:
1138 if (info->interp_base == 0)
1139 auxv->a_type = AT_IGNORE;
1140 else
1141 auxv->u.a_val = info->interp_base;
1142 break;
1143
1144 case AT_PLATFORM: /* points to a platform description string */
1145 auxv->u.a_ptr = copy_str(&strtab, orig_auxv->u.a_ptr);
1146 break;
1147
1148 case AT_ENTRY:
1149 auxv->u.a_val = info->entry;
1150 break;
1151
1152 case AT_IGNORE:
1153 case AT_EXECFD:
1154 case AT_PHENT:
1155 case AT_PAGESZ:
1156 case AT_FLAGS:
1157 case AT_NOTELF:
1158 case AT_UID:
1159 case AT_EUID:
1160 case AT_GID:
1161 case AT_EGID:
1162 case AT_CLKTCK:
1163 case AT_HWCAP:
1164 case AT_FPUCW:
1165 case AT_DCACHEBSIZE:
1166 case AT_ICACHEBSIZE:
1167 case AT_UCACHEBSIZE:
1168 /* All these are pointerless, so we don't need to do anything
1169 about them. */
1170 break;
1171
1172 case AT_SECURE:
1173 /* If this is 1, then it means that this program is running
1174 suid, and therefore the dynamic linker should be careful
1175 about LD_PRELOAD, etc. However, since stage1 (the thing
1176 the kernel actually execve's) should never be SUID, and we
1177 need LD_PRELOAD/LD_LIBRARY_PATH to work for the client, we
1178 set AT_SECURE to 0. */
1179 auxv->u.a_val = 0;
1180 break;
1181
1182 case AT_SYSINFO:
1183 /* Leave this unmolested for now, but we'll update it later
1184 when we set up the client trampoline code page */
1185 break;
1186
1187 case AT_SYSINFO_EHDR:
1188 /* Trash this, because we don't reproduce it */
1189 auxv->a_type = AT_IGNORE;
1190 break;
1191
1192 default:
1193 /* stomp out anything we don't know about */
1194 if (0)
1195 printf("stomping auxv entry %d\n", auxv->a_type);
1196 auxv->a_type = AT_IGNORE;
1197 break;
1198
1199 }
1200 }
1201 *auxv = *orig_auxv;
1202 vg_assert(auxv->a_type == AT_NULL);
1203
nethercotef84f6952004-07-15 14:58:33 +00001204 /* --- trampoline page --- */
1205 VG_(memcpy)( (void *)VG_(client_trampoline_code),
1206 &VG_(trampoline_code_start), VG_(trampoline_code_length) );
1207
nethercote71980f02004-01-24 18:18:54 +00001208 vg_assert((strtab-stringbase) == stringsize);
1209
nethercote5ee67ca2004-06-22 14:00:09 +00001210 /* We know the initial ESP is pointing at argc/argv */
1211 VG_(client_argc) = *(Int*)cl_esp;
1212 VG_(client_argv) = (Char**)(cl_esp + sizeof(Int));
1213
nethercote71980f02004-01-24 18:18:54 +00001214 return cl_esp;
1215}
1216
1217/*====================================================================*/
1218/*=== Find executable ===*/
1219/*====================================================================*/
1220
thughes4ad52d02004-06-27 17:37:21 +00001221static const char* executable_name;
1222
1223static Bool match_executable(const char *entry) {
1224 char buf[strlen(entry) + strlen(executable_name) + 2];
1225
1226 /* empty PATH element means . */
1227 if (*entry == '\0')
1228 entry = ".";
1229
1230 snprintf(buf, sizeof(buf), "%s/%s", entry, executable_name);
1231
1232 if (access(buf, R_OK|X_OK) == 0) {
1233 executable_name = strdup(buf);
1234 vg_assert(NULL != executable_name);
1235 return True;
1236 }
1237 return False;
1238}
1239
nethercote71980f02004-01-24 18:18:54 +00001240static const char* find_executable(const char* exec)
1241{
1242 vg_assert(NULL != exec);
thughes4ad52d02004-06-27 17:37:21 +00001243 executable_name = exec;
1244 if (strchr(executable_name, '/') == NULL) {
nethercote71980f02004-01-24 18:18:54 +00001245 /* no '/' - we need to search the path */
1246 char *path = getenv("PATH");
thughes4ad52d02004-06-27 17:37:21 +00001247 scan_colsep(path, match_executable);
nethercote71980f02004-01-24 18:18:54 +00001248 }
thughes4ad52d02004-06-27 17:37:21 +00001249 return executable_name;
nethercote71980f02004-01-24 18:18:54 +00001250}
1251
1252
1253/*====================================================================*/
1254/*=== Loading tools ===*/
1255/*====================================================================*/
1256
1257static void list_tools(void)
1258{
1259 DIR *dir = opendir(VG_(libdir));
1260 struct dirent *de;
1261 int first = 1;
1262
1263 if (dir == NULL) {
1264 fprintf(stderr, "Can't open %s: %s (installation problem?)\n",
nethercotef4928da2004-06-15 10:54:40 +00001265 VG_(libdir), strerror(errno));
nethercote71980f02004-01-24 18:18:54 +00001266 return;
1267 }
1268
nethercotef4928da2004-06-15 10:54:40 +00001269 while ((de = readdir(dir)) != NULL) {
nethercote71980f02004-01-24 18:18:54 +00001270 int len = strlen(de->d_name);
1271
1272 /* look for vgskin_TOOL.so names */
1273 if (len > (7+1+3) && /* "vgskin_" + at least 1-char toolname + ".so" */
nethercotef4928da2004-06-15 10:54:40 +00001274 strncmp(de->d_name, "vgskin_", 7) == 0 &&
1275 VG_STREQ(de->d_name + len - 3, ".so")) {
1276 if (first) {
1277 fprintf(stderr, "Available tools:\n");
1278 first = 0;
1279 }
1280 de->d_name[len-3] = '\0';
1281 fprintf(stderr, "\t%s\n", de->d_name+7);
nethercote71980f02004-01-24 18:18:54 +00001282 }
1283 }
1284
1285 closedir(dir);
1286
1287 if (first)
nethercotef4928da2004-06-15 10:54:40 +00001288 fprintf(stderr, "No tools available in \"%s\" (installation problem?)\n",
1289 VG_(libdir));
nethercote71980f02004-01-24 18:18:54 +00001290}
1291
1292
1293/* Find and load a tool, and check it looks ok. Also looks to see if there's
1294 * a matching vgpreload_*.so file, and returns its name in *preloadpath. */
1295static void load_tool( const char *toolname, void** handle_out,
1296 ToolInfo** toolinfo_out, char **preloadpath_out )
1297{
1298 Bool ok;
1299 int len = strlen(VG_(libdir)) + strlen(toolname)*2 + 16;
1300 char buf[len];
1301 void* handle;
1302 ToolInfo* toolinfo;
1303 char* preloadpath = NULL;
1304 Int* vg_malloc_redzonep;
1305
1306 // XXX: allowing full paths for --tool option -- does it make sense?
1307 // Doesn't allow for vgpreload_<tool>.so.
1308
1309 if (strchr(toolname, '/') != 0) {
1310 /* toolname contains '/', and so must be a pathname */
1311 handle = dlopen(toolname, RTLD_NOW);
1312 } else {
1313 /* just try in the libdir */
1314 snprintf(buf, len, "%s/vgskin_%s.so", VG_(libdir), toolname);
1315 handle = dlopen(buf, RTLD_NOW);
1316
1317 if (handle != NULL) {
1318 snprintf(buf, len, "%s/vgpreload_%s.so", VG_(libdir), toolname);
1319 if (access(buf, R_OK) == 0) {
1320 preloadpath = strdup(buf);
1321 vg_assert(NULL != preloadpath);
1322 }
1323 }
1324 }
1325
1326 ok = (NULL != handle);
1327 if (!ok) {
1328 fprintf(stderr, "Can't open tool \"%s\": %s\n", toolname, dlerror());
1329 goto bad_load;
1330 }
1331
1332 toolinfo = dlsym(handle, "vgSkin_tool_info");
1333 ok = (NULL != toolinfo);
1334 if (!ok) {
1335 fprintf(stderr, "Tool \"%s\" doesn't define SK_(tool_info) - "
1336 "add VG_DETERMINE_INTERFACE_VERSION?\n", toolname);
1337 goto bad_load;
1338 }
1339
1340 ok = (toolinfo->sizeof_ToolInfo == sizeof(*toolinfo) &&
1341 toolinfo->interface_major_version == VG_CORE_INTERFACE_MAJOR_VERSION &&
1342 toolinfo->sk_pre_clo_init != NULL);
1343 if (!ok) {
1344 fprintf(stderr, "Error:\n"
1345 " Tool and core interface versions do not match.\n"
1346 " Interface version used by core is: %d.%d (size %d)\n"
1347 " Interface version used by tool is: %d.%d (size %d)\n"
1348 " The major version numbers must match.\n",
1349 VG_CORE_INTERFACE_MAJOR_VERSION,
1350 VG_CORE_INTERFACE_MINOR_VERSION,
1351 sizeof(*toolinfo),
1352 toolinfo->interface_major_version,
1353 toolinfo->interface_minor_version,
1354 toolinfo->sizeof_ToolInfo);
1355 fprintf(stderr, " You need to at least recompile, and possibly update,\n");
1356 if (VG_CORE_INTERFACE_MAJOR_VERSION > toolinfo->interface_major_version)
1357 fprintf(stderr, " your skin to work with this version of Valgrind.\n");
1358 else
1359 fprintf(stderr, " your version of Valgrind to work with this skin.\n");
1360 goto bad_load;
1361 }
1362
1363 // Set redzone size for V's allocator
1364 vg_malloc_redzonep = dlsym(handle, STR(VG_(vg_malloc_redzone_szB)));
1365 if ( NULL != vg_malloc_redzonep ) {
1366 VG_(vg_malloc_redzone_szB) = *vg_malloc_redzonep;
1367 }
1368
1369 vg_assert(NULL != handle && NULL != toolinfo);
1370 *handle_out = handle;
1371 *toolinfo_out = toolinfo;
1372 *preloadpath_out = preloadpath;
1373 return;
1374
1375
1376 bad_load:
1377 if (handle != NULL)
1378 dlclose(handle);
1379
nethercotef4928da2004-06-15 10:54:40 +00001380 fprintf(stderr, "valgrind: couldn't load tool\n");
nethercote71980f02004-01-24 18:18:54 +00001381 list_tools();
1382 exit(127);
1383}
1384
nethercotef4928da2004-06-15 10:54:40 +00001385
1386/*====================================================================*/
1387/*=== Command line errors ===*/
1388/*====================================================================*/
1389
1390static void abort_msg ( void )
1391{
nethercotef8548672004-06-21 12:42:35 +00001392 VG_(clo_log_to) = VgLogTo_Fd;
1393 VG_(clo_log_fd) = 2; /* stderr */
nethercotef4928da2004-06-15 10:54:40 +00001394}
1395
1396void VG_(bad_option) ( Char* opt )
1397{
1398 abort_msg();
1399 VG_(printf)("valgrind: Bad option `%s'; aborting.\n", opt);
1400 VG_(printf)("valgrind: Use --help for more information.\n");
1401 VG_(exit)(1);
1402}
1403
1404static void missing_tool_option ( void )
1405{
1406 abort_msg();
1407 VG_(printf)("valgrind: Missing --tool option\n");
1408 list_tools();
1409 VG_(printf)("valgrind: Use --help for more information.\n");
1410 VG_(exit)(1);
1411}
1412
1413static void missing_prog ( void )
1414{
1415 abort_msg();
1416 VG_(printf)("valgrind: no program specified\n");
1417 VG_(printf)("valgrind: Use --help for more information.\n");
1418 VG_(exit)(1);
1419}
1420
1421static void config_error ( Char* msg )
1422{
1423 abort_msg();
1424 VG_(printf)("valgrind: Startup or configuration error:\n %s\n", msg);
1425 VG_(printf)("valgrind: Unable to start up properly. Giving up.\n");
1426 VG_(exit)(1);
1427}
1428
1429
nethercote71980f02004-01-24 18:18:54 +00001430/*====================================================================*/
1431/*=== Loading the client ===*/
1432/*====================================================================*/
1433
nethercotef4928da2004-06-15 10:54:40 +00001434static void load_client(char* cl_argv[], const char* exec, Int need_help,
nethercote71980f02004-01-24 18:18:54 +00001435 /*out*/struct exeinfo* info, /*out*/Addr* client_eip)
1436{
1437 // If they didn't specify an executable with --exec, and didn't specify
1438 // --help, then use client argv[0] (searching $PATH if necessary).
nethercotef4928da2004-06-15 10:54:40 +00001439 if (NULL == exec && !need_help) {
nethercote71980f02004-01-24 18:18:54 +00001440 if (cl_argv[0] == NULL ||
1441 ( NULL == (exec = find_executable(cl_argv[0])) ) )
1442 {
nethercotef4928da2004-06-15 10:54:40 +00001443 missing_prog();
nethercote71980f02004-01-24 18:18:54 +00001444 }
1445 }
1446
1447 info->map_base = VG_(client_mapbase);
nethercote71980f02004-01-24 18:18:54 +00001448
1449 info->exe_base = VG_(client_base);
1450 info->exe_end = VG_(client_end);
1451 info->argv = cl_argv;
1452
nethercotef4928da2004-06-15 10:54:40 +00001453 if (need_help) {
nethercote71980f02004-01-24 18:18:54 +00001454 VG_(clexecfd) = -1;
nethercoted6a56872004-07-26 15:32:47 +00001455 info->interp_name = NULL;
1456 info->interp_args = NULL;
nethercote71980f02004-01-24 18:18:54 +00001457 } else {
1458 Int ret;
1459 VG_(clexecfd) = VG_(open)(exec, O_RDONLY, VKI_S_IRUSR);
1460 ret = do_exec(exec, info);
1461 if (ret != 0) {
nethercotef4928da2004-06-15 10:54:40 +00001462 fprintf(stderr, "valgrind: do_exec(%s) failed: %s\n", exec, strerror(ret));
nethercote71980f02004-01-24 18:18:54 +00001463 exit(127);
1464 }
1465 }
1466
1467 /* Copy necessary bits of 'info' that were filled in */
1468 *client_eip = info->init_eip;
1469 VG_(brk_base) = VG_(brk_limit) = info->brkbase;
1470}
1471
1472
1473/*====================================================================*/
1474/*=== Command-line: variables, processing ===*/
1475/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +00001476
njn25e49d8e72002-09-23 09:36:25 +00001477/* Define, and set defaults. */
1478Bool VG_(clo_error_limit) = True;
nethercote04d0fbc2004-01-26 16:48:06 +00001479Bool VG_(clo_db_attach) = False;
1480Char* VG_(clo_db_command) = VG_CLO_DEFAULT_DBCOMMAND;
njn43c799e2003-04-08 00:08:52 +00001481Bool VG_(clo_gen_suppressions) = False;
nethercote27fec902004-06-16 21:26:32 +00001482Int VG_(clo_sanity_level) = 1;
njn25e49d8e72002-09-23 09:36:25 +00001483Int VG_(clo_verbosity) = 1;
1484Bool VG_(clo_demangle) = True;
njn25e49d8e72002-09-23 09:36:25 +00001485Bool VG_(clo_trace_children) = False;
sewardj4cf05692002-10-27 20:28:29 +00001486
nethercotee1730692003-11-20 10:38:07 +00001487/* See big comment in vg_include.h for meaning of these three.
1488 fd is initially stdout, for --help, but gets moved to stderr by default
1489 immediately afterwards. */
sewardj4cf05692002-10-27 20:28:29 +00001490VgLogTo VG_(clo_log_to) = VgLogTo_Fd;
nethercotef8548672004-06-21 12:42:35 +00001491Int VG_(clo_log_fd) = 1;
1492Char* VG_(clo_log_name) = NULL;
sewardj4cf05692002-10-27 20:28:29 +00001493
sewardj6024b212003-07-13 10:54:33 +00001494Int VG_(clo_input_fd) = 0; /* stdin */
njn25e49d8e72002-09-23 09:36:25 +00001495Int VG_(clo_n_suppressions) = 0;
sewardjde4a1d02002-03-22 01:27:54 +00001496Char* VG_(clo_suppressions)[VG_CLO_MAX_SFILES];
njn25e49d8e72002-09-23 09:36:25 +00001497Bool VG_(clo_profile) = False;
1498Bool VG_(clo_single_step) = False;
1499Bool VG_(clo_optimise) = True;
1500UChar VG_(clo_trace_codegen) = 0; // 00000000b
1501Bool VG_(clo_trace_syscalls) = False;
1502Bool VG_(clo_trace_signals) = False;
1503Bool VG_(clo_trace_symtab) = False;
njn25e49d8e72002-09-23 09:36:25 +00001504Bool VG_(clo_trace_sched) = False;
1505Int VG_(clo_trace_pthread_level) = 0;
njn25e49d8e72002-09-23 09:36:25 +00001506Int VG_(clo_dump_error) = 0;
1507Int VG_(clo_backtrace_size) = 4;
1508Char* VG_(clo_weird_hacks) = NULL;
sewardj858964b2002-10-05 14:15:43 +00001509Bool VG_(clo_run_libc_freeres) = True;
rjwalshf5f536f2003-11-17 17:45:00 +00001510Bool VG_(clo_track_fds) = False;
sewardj22854b92002-11-30 14:00:47 +00001511Bool VG_(clo_chain_bb) = True;
nethercote77eba602003-11-13 17:35:04 +00001512Bool VG_(clo_show_below_main) = False;
fitzhardinge98abfc72003-12-16 02:05:15 +00001513Bool VG_(clo_pointercheck) = True;
fitzhardinge462f4f92003-12-18 02:10:54 +00001514Bool VG_(clo_branchpred) = False;
sewardj2370f3b2002-11-30 15:01:01 +00001515
jsgf855d93d2003-10-13 22:26:55 +00001516static Bool VG_(clo_wait_for_gdb) = False;
1517
1518/* If we're doing signal routing, poll for signals every 50mS by
1519 default. */
1520Int VG_(clo_signal_polltime) = 50;
1521
1522/* These flags reduce thread wakeup latency on syscall completion and
1523 signal delivery, respectively. The downside is possible unfairness. */
1524Bool VG_(clo_lowlat_syscalls) = False; /* low-latency syscalls */
1525Bool VG_(clo_lowlat_signals) = False; /* low-latency signals */
1526
sewardjde4a1d02002-03-22 01:27:54 +00001527
nethercote6c999f22004-01-31 22:55:15 +00001528void usage ( Bool debug_help )
njn7cf0bd32002-06-08 13:36:03 +00001529{
njn25e49d8e72002-09-23 09:36:25 +00001530 Char* usage1 =
nethercote71980f02004-01-24 18:18:54 +00001531"usage: valgrind --tool=<toolname> [options] prog-and-args\n"
njn25e49d8e72002-09-23 09:36:25 +00001532"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001533" common user options for all Valgrind tools, with defaults in [ ]:\n"
nethercote0d588502004-06-21 13:27:11 +00001534" --tool=<name> use the Valgrind tool named <name>\n"
nethercotea76368b2004-06-16 11:56:29 +00001535" -h --help show this message\n"
nethercote6c999f22004-01-31 22:55:15 +00001536" --help-debug show this message, plus debugging options\n"
njn25e49d8e72002-09-23 09:36:25 +00001537" --version show version\n"
njn25e49d8e72002-09-23 09:36:25 +00001538" -q --quiet run silently; only print error msgs\n"
1539" -v --verbose be more verbose, incl counts of errors\n"
nethercote77eba602003-11-13 17:35:04 +00001540" --trace-children=no|yes Valgrind-ise child processes? [no]\n"
nethercote0d588502004-06-21 13:27:11 +00001541" --track-fds=no|yes track open file descriptors? [no]\n"
nethercote2b0793f2003-12-02 10:41:18 +00001542"\n"
1543" uncommon user options for all Valgrind tools:\n"
nethercote0d588502004-06-21 13:27:11 +00001544" --run-libc-freeres=no|yes free up glibc memory at exit? [yes]\n"
1545" --weird-hacks=hack1,hack2,... recognised hacks: lax-ioctls [none]\n"
1546" --signal-polltime=<time> signal poll period (mS) for older kernels [50]\n"
1547" --lowlat-signals=no|yes improve thread signal wake-up latency [no]\n"
1548" --lowlat-syscalls=no|yes improve thread syscall wake-up latency [no]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001549" --pointercheck=no|yes enforce client address space limits [yes]\n"
njn25e49d8e72002-09-23 09:36:25 +00001550"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001551" user options for Valgrind tools that report errors:\n"
nethercotef8548672004-06-21 12:42:35 +00001552" --log-fd=<number> log messages to file descriptor [2=stderr]\n"
1553" --log-file=<file> log messages to <file>.pid<pid>\n"
1554" --log-socket=ipaddr:port log messages to socket ipaddr:port\n"
nethercote2b0793f2003-12-02 10:41:18 +00001555" --demangle=no|yes automatically demangle C++ names? [yes]\n"
1556" --num-callers=<number> show <num> callers in stack traces [4]\n"
1557" --error-limit=no|yes stop showing new errors if too many? [yes]\n"
1558" --show-below-main=no|yes continue stack traces below main() [no]\n"
1559" --suppressions=<filename> suppress errors described in <filename>\n"
1560" --gen-suppressions=no|yes print suppressions for errors detected [no]\n"
nethercote04d0fbc2004-01-26 16:48:06 +00001561" --db-attach=no|yes start debugger when errors detected? [no]\n"
1562" --db-command=<command> command to start debugger [gdb -nw %%f %%p]\n"
1563" --input-fd=<number> file descriptor for input [0=stdin]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001564"\n";
njn7cf0bd32002-06-08 13:36:03 +00001565
njn25e49d8e72002-09-23 09:36:25 +00001566 Char* usage2 =
1567"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001568" debugging options for all Valgrind tools:\n"
njn25e49d8e72002-09-23 09:36:25 +00001569" --sanity-level=<number> level of sanity checking to do [1]\n"
1570" --single-step=no|yes translate each instr separately? [no]\n"
1571" --optimise=no|yes improve intermediate code? [yes]\n"
nethercote137bc552003-11-14 17:47:54 +00001572" --profile=no|yes profile? (tool must be built for it) [no]\n"
sewardj22854b92002-11-30 14:00:47 +00001573" --chain-bb=no|yes do basic-block chaining? [yes]\n"
fitzhardinge462f4f92003-12-18 02:10:54 +00001574" --branchpred=yes|no generate branch prediction hints [no]\n"
njn25e49d8e72002-09-23 09:36:25 +00001575" --trace-codegen=<XXXXX> show generated code? (X = 0|1) [00000]\n"
1576" --trace-syscalls=no|yes show all system calls? [no]\n"
1577" --trace-signals=no|yes show signal handling details? [no]\n"
1578" --trace-symtab=no|yes show symbol table details? [no]\n"
njn25e49d8e72002-09-23 09:36:25 +00001579" --trace-sched=no|yes show thread scheduler details? [no]\n"
njn3e884182003-04-15 13:03:23 +00001580" --trace-pthread=none|some|all show pthread event details? [none]\n"
jsgf855d93d2003-10-13 22:26:55 +00001581" --wait-for-gdb=yes|no pause on startup to wait for gdb attach\n"
njn25e49d8e72002-09-23 09:36:25 +00001582"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001583" debugging options for Valgrind tools that report errors\n"
1584" --dump-error=<number> show translation for basic block associated\n"
1585" with <number>'th error context [0=show none]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001586"\n";
njn3e884182003-04-15 13:03:23 +00001587
1588 Char* usage3 =
1589"\n"
nethercote71980f02004-01-24 18:18:54 +00001590" Extra options read from ~/.valgrindrc, $VALGRIND_OPTS, ./.valgrindrc\n"
njn25e49d8e72002-09-23 09:36:25 +00001591"\n"
nethercote08fa9a72004-07-16 17:44:00 +00001592" Valgrind is Copyright (C) 2000-2004 Julian Seward et al.\n"
njn25e49d8e72002-09-23 09:36:25 +00001593" and licensed under the GNU General Public License, version 2.\n"
1594" Bug reports, feedback, admiration, abuse, etc, to: %s.\n"
njnd04b7c62002-10-03 14:05:52 +00001595"\n"
nethercote137bc552003-11-14 17:47:54 +00001596" Tools are copyright and licensed by their authors. See each\n"
1597" tool's start-up message for more information.\n"
njn25e49d8e72002-09-23 09:36:25 +00001598"\n";
njn7cf0bd32002-06-08 13:36:03 +00001599
fitzhardinge98abfc72003-12-16 02:05:15 +00001600 VG_(printf)(usage1);
1601 if (VG_(details).name) {
1602 VG_(printf)(" user options for %s:\n", VG_(details).name);
fitzhardinge98abfc72003-12-16 02:05:15 +00001603 if (VG_(needs).command_line_options)
1604 SK_(print_usage)();
1605 else
1606 VG_(printf)(" (none)\n");
1607 }
nethercote6c999f22004-01-31 22:55:15 +00001608 if (debug_help) {
1609 VG_(printf)(usage2);
fitzhardinge98abfc72003-12-16 02:05:15 +00001610
nethercote6c999f22004-01-31 22:55:15 +00001611 if (VG_(details).name) {
1612 VG_(printf)(" debugging options for %s:\n", VG_(details).name);
1613
1614 if (VG_(needs).command_line_options)
1615 SK_(print_debug_usage)();
1616 else
1617 VG_(printf)(" (none)\n");
1618 }
fitzhardinge98abfc72003-12-16 02:05:15 +00001619 }
nethercote421281e2003-11-20 16:20:55 +00001620 VG_(printf)(usage3, VG_BUGS_TO);
nethercotef4928da2004-06-15 10:54:40 +00001621 VG_(exit)(0);
njn7cf0bd32002-06-08 13:36:03 +00001622}
sewardjde4a1d02002-03-22 01:27:54 +00001623
nethercote71980f02004-01-24 18:18:54 +00001624static void pre_process_cmd_line_options
nethercote6c999f22004-01-31 22:55:15 +00001625 ( Int* need_help, const char** tool, const char** exec )
sewardj1c1b1162003-02-23 01:25:51 +00001626{
nethercote71980f02004-01-24 18:18:54 +00001627 UInt i;
sewardjde4a1d02002-03-22 01:27:54 +00001628
nethercote71980f02004-01-24 18:18:54 +00001629 /* parse the options we have (only the options we care about now) */
1630 for (i = 1; i < VG_(vg_argc); i++) {
1631
1632 if (strcmp(VG_(vg_argv)[i], "--version") == 0) {
1633 printf("valgrind-" VERSION "\n");
nethercotef4928da2004-06-15 10:54:40 +00001634 exit(0);
nethercote71980f02004-01-24 18:18:54 +00001635
nethercotea76368b2004-06-16 11:56:29 +00001636 } else if (VG_CLO_STREQ(VG_(vg_argv)[i], "--help") ||
1637 VG_CLO_STREQ(VG_(vg_argv)[i], "-h")) {
nethercote6c999f22004-01-31 22:55:15 +00001638 *need_help = 1;
1639
nethercotef4928da2004-06-15 10:54:40 +00001640 } else if (VG_CLO_STREQ(VG_(vg_argv)[i], "--help-debug")) {
nethercote6c999f22004-01-31 22:55:15 +00001641 *need_help = 2;
nethercote71980f02004-01-24 18:18:54 +00001642
nethercotef4928da2004-06-15 10:54:40 +00001643 } else if (VG_CLO_STREQN(7, VG_(vg_argv)[i], "--tool=") ||
1644 VG_CLO_STREQN(7, VG_(vg_argv)[i], "--skin=")) {
nethercote71980f02004-01-24 18:18:54 +00001645 *tool = &VG_(vg_argv)[i][7];
1646
nethercotef4928da2004-06-15 10:54:40 +00001647 } else if (VG_CLO_STREQN(7, VG_(vg_argv)[i], "--exec=")) {
nethercote71980f02004-01-24 18:18:54 +00001648 *exec = &VG_(vg_argv)[i][7];
1649 }
1650 }
1651
nethercotef4928da2004-06-15 10:54:40 +00001652 /* If no tool specified, can act appropriately without loading tool */
nethercote71980f02004-01-24 18:18:54 +00001653 if (*tool == NULL) {
nethercotef4928da2004-06-15 10:54:40 +00001654 if (0 == *need_help) {
1655 // neither --tool nor --help/--help-debug specified
1656 missing_tool_option();
1657 } else {
1658 // Give help message, without any tool-specific help
1659 usage(/*help-debug?*/2 == *need_help);
1660 }
nethercote71980f02004-01-24 18:18:54 +00001661 }
1662}
1663
nethercote5ee67ca2004-06-22 14:00:09 +00001664static void process_cmd_line_options( UInt* client_auxv, const char* toolname )
nethercote71980f02004-01-24 18:18:54 +00001665{
nethercotef8548672004-06-21 12:42:35 +00001666 Int i, eventually_log_fd;
nethercote71980f02004-01-24 18:18:54 +00001667 Int *auxp;
1668 Int toolname_len = VG_(strlen)(toolname);
sewardjde4a1d02002-03-22 01:27:54 +00001669
nethercotee1730692003-11-20 10:38:07 +00001670 /* log to stderr by default, but usage message goes to stdout */
nethercotef8548672004-06-21 12:42:35 +00001671 eventually_log_fd = 2;
sewardjde4a1d02002-03-22 01:27:54 +00001672
sewardj19d81412002-06-03 01:10:40 +00001673 /* Check for sane path in ./configure --prefix=... */
fitzhardinge98abfc72003-12-16 02:05:15 +00001674 if (VG_LIBDIR[0] != '/')
sewardj19d81412002-06-03 01:10:40 +00001675 config_error("Please use absolute paths in "
1676 "./configure --prefix=... or --libdir=...");
sewardj38170912002-05-10 21:07:22 +00001677
nethercote71980f02004-01-24 18:18:54 +00001678 for (auxp = client_auxv; auxp[0] != VKI_AT_NULL; auxp += 2) {
fitzhardinge98abfc72003-12-16 02:05:15 +00001679 switch(auxp[0]) {
1680 case VKI_AT_SYSINFO:
1681 VG_(sysinfo_page_exists) = True;
fitzhardinge92360792003-12-24 10:11:11 +00001682 auxp[1] = (Int)(VG_(client_trampoline_code) + VG_(tramp_syscall_offset));
fitzhardinge98abfc72003-12-16 02:05:15 +00001683 VG_(sysinfo_page_addr) = auxp[1];
1684 break;
sewardjde4a1d02002-03-22 01:27:54 +00001685 }
fitzhardinge98abfc72003-12-16 02:05:15 +00001686 }
sewardjde4a1d02002-03-22 01:27:54 +00001687
nethercote71980f02004-01-24 18:18:54 +00001688 for (i = 1; i < VG_(vg_argc); i++) {
1689
1690 Char* arg = VG_(vg_argv)[i];
thughes3bfd5a02004-07-18 08:05:44 +00001691 Char* colon = arg;
nethercote71980f02004-01-24 18:18:54 +00001692
thughes3bfd5a02004-07-18 08:05:44 +00001693 /* Look for a colon in the switch name */
1694 while (*colon && *colon != ':' && *colon != '=')
1695 colon++;
nethercote71980f02004-01-24 18:18:54 +00001696
1697 /* Look for matching "--toolname:foo" */
thughes3bfd5a02004-07-18 08:05:44 +00001698 if (*colon == ':') {
nethercote71980f02004-01-24 18:18:54 +00001699 if (VG_CLO_STREQN(2, arg, "--") &&
1700 VG_CLO_STREQN(toolname_len, arg+2, toolname) &&
1701 VG_CLO_STREQN(1, arg+2+toolname_len, ":"))
1702 {
1703 // prefix matches, convert "--toolname:foo" to "--foo"
1704 if (0)
1705 VG_(printf)("tool-specific arg: %s\n", arg);
1706 arg += toolname_len + 1;
1707 arg[0] = '-';
1708 arg[1] = '-';
1709
1710 } else {
1711 // prefix doesn't match, skip to next arg
1712 continue;
1713 }
1714 }
1715
fitzhardinge98abfc72003-12-16 02:05:15 +00001716 /* Ignore these options - they've already been handled */
nethercote71980f02004-01-24 18:18:54 +00001717 if (VG_CLO_STREQN(7, arg, "--tool=") ||
1718 VG_CLO_STREQN(7, arg, "--skin="))
fitzhardinge98abfc72003-12-16 02:05:15 +00001719 continue;
nethercote71980f02004-01-24 18:18:54 +00001720 if (VG_CLO_STREQN(7, arg, "--exec="))
fitzhardinge98abfc72003-12-16 02:05:15 +00001721 continue;
1722
nethercote71980f02004-01-24 18:18:54 +00001723 if ( VG_CLO_STREQ(arg, "--"))
fitzhardinge98abfc72003-12-16 02:05:15 +00001724 continue;
nethercote27fec902004-06-16 21:26:32 +00001725
nethercote71980f02004-01-24 18:18:54 +00001726 else if (VG_CLO_STREQ(arg, "-v") ||
1727 VG_CLO_STREQ(arg, "--verbose"))
sewardjde4a1d02002-03-22 01:27:54 +00001728 VG_(clo_verbosity)++;
nethercote27fec902004-06-16 21:26:32 +00001729
nethercote71980f02004-01-24 18:18:54 +00001730 else if (VG_CLO_STREQ(arg, "-q") ||
1731 VG_CLO_STREQ(arg, "--quiet"))
sewardjde4a1d02002-03-22 01:27:54 +00001732 VG_(clo_verbosity)--;
1733
nethercote27fec902004-06-16 21:26:32 +00001734 else VG_BOOL_CLO("--branchpred", VG_(clo_branchpred))
1735 else VG_BOOL_CLO("--chain-bb", VG_(clo_chain_bb))
1736 else VG_BOOL_CLO("--db-attach", VG_(clo_db_attach))
1737 else VG_BOOL_CLO("--demangle", VG_(clo_demangle))
1738 else VG_BOOL_CLO("--error-limit", VG_(clo_error_limit))
1739 else VG_BOOL_CLO("--gen-suppressions", VG_(clo_gen_suppressions))
1740 else VG_BOOL_CLO("--lowlat-signals", VG_(clo_lowlat_signals))
1741 else VG_BOOL_CLO("--lowlat-syscalls", VG_(clo_lowlat_syscalls))
1742 else VG_BOOL_CLO("--optimise", VG_(clo_optimise))
1743 else VG_BOOL_CLO("--pointercheck", VG_(clo_pointercheck))
1744 else VG_BOOL_CLO("--profile", VG_(clo_profile))
1745 else VG_BOOL_CLO("--run-libc-freeres", VG_(clo_run_libc_freeres))
1746 else VG_BOOL_CLO("--show-below-main", VG_(clo_show_below_main))
1747 else VG_BOOL_CLO("--single-step", VG_(clo_single_step))
1748 else VG_BOOL_CLO("--track-fds", VG_(clo_track_fds))
1749 else VG_BOOL_CLO("--trace-children", VG_(clo_trace_children))
1750 else VG_BOOL_CLO("--trace-sched", VG_(clo_trace_sched))
1751 else VG_BOOL_CLO("--trace-signals", VG_(clo_trace_signals))
1752 else VG_BOOL_CLO("--trace-symtab", VG_(clo_trace_symtab))
1753 else VG_BOOL_CLO("--trace-syscalls", VG_(clo_trace_syscalls))
1754 else VG_BOOL_CLO("--wait-for-gdb", VG_(clo_wait_for_gdb))
sewardj72f98ff2002-06-13 17:23:38 +00001755
nethercote27fec902004-06-16 21:26:32 +00001756 else VG_STR_CLO ("--db-command", VG_(clo_db_command))
1757 else VG_STR_CLO ("--weird-hacks", VG_(clo_weird_hacks))
sewardjde4a1d02002-03-22 01:27:54 +00001758
nethercote27fec902004-06-16 21:26:32 +00001759 else VG_NUM_CLO ("--dump-error", VG_(clo_dump_error))
1760 else VG_NUM_CLO ("--input-fd", VG_(clo_input_fd))
1761 else VG_NUM_CLO ("--sanity-level", VG_(clo_sanity_level))
1762 else VG_NUM_CLO ("--signal­polltime", VG_(clo_signal_polltime))
1763 else VG_BNUM_CLO("--num-callers", VG_(clo_backtrace_size), 1,
1764 VG_DEEPEST_BACKTRACE)
sewardjde4a1d02002-03-22 01:27:54 +00001765
nethercotef8548672004-06-21 12:42:35 +00001766 // for backwards compatibility, replaced by --log-fd
nethercote71980f02004-01-24 18:18:54 +00001767 else if (VG_CLO_STREQN(13, arg, "--logfile-fd=")) {
nethercotef8548672004-06-21 12:42:35 +00001768 VG_(clo_log_to) = VgLogTo_Fd;
1769 VG_(clo_log_name) = NULL;
1770 eventually_log_fd = (Int)VG_(atoll)(&arg[13]);
1771 }
1772 else if (VG_CLO_STREQN(9, arg, "--log-fd=")) {
1773 VG_(clo_log_to) = VgLogTo_Fd;
1774 VG_(clo_log_name) = NULL;
1775 eventually_log_fd = (Int)VG_(atoll)(&arg[9]);
sewardj4cf05692002-10-27 20:28:29 +00001776 }
1777
nethercotef8548672004-06-21 12:42:35 +00001778 // for backwards compatibility, replaced by --log-file
nethercote71980f02004-01-24 18:18:54 +00001779 else if (VG_CLO_STREQN(10, arg, "--logfile=")) {
nethercotef8548672004-06-21 12:42:35 +00001780 VG_(clo_log_to) = VgLogTo_File;
1781 VG_(clo_log_name) = &arg[10];
1782 }
1783 else if (VG_CLO_STREQN(11, arg, "--log-file=")) {
1784 VG_(clo_log_to) = VgLogTo_File;
1785 VG_(clo_log_name) = &arg[11];
sewardj4cf05692002-10-27 20:28:29 +00001786 }
sewardjde4a1d02002-03-22 01:27:54 +00001787
nethercotef8548672004-06-21 12:42:35 +00001788 // for backwards compatibility, replaced by --log-socket
nethercote71980f02004-01-24 18:18:54 +00001789 else if (VG_CLO_STREQN(12, arg, "--logsocket=")) {
nethercotef8548672004-06-21 12:42:35 +00001790 VG_(clo_log_to) = VgLogTo_Socket;
1791 VG_(clo_log_name) = &arg[12];
1792 }
1793 else if (VG_CLO_STREQN(13, arg, "--log-socket=")) {
1794 VG_(clo_log_to) = VgLogTo_Socket;
1795 VG_(clo_log_name) = &arg[13];
sewardj73cf3bc2002-11-03 03:20:15 +00001796 }
1797
nethercote71980f02004-01-24 18:18:54 +00001798 else if (VG_CLO_STREQN(15, arg, "--suppressions=")) {
sewardjde4a1d02002-03-22 01:27:54 +00001799 if (VG_(clo_n_suppressions) >= VG_CLO_MAX_SFILES) {
njn25e49d8e72002-09-23 09:36:25 +00001800 VG_(message)(Vg_UserMsg, "Too many suppression files specified.");
sewardjde4a1d02002-03-22 01:27:54 +00001801 VG_(message)(Vg_UserMsg,
1802 "Increase VG_CLO_MAX_SFILES and recompile.");
nethercote71980f02004-01-24 18:18:54 +00001803 VG_(bad_option)(arg);
sewardjde4a1d02002-03-22 01:27:54 +00001804 }
nethercote71980f02004-01-24 18:18:54 +00001805 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = &arg[15];
sewardjde4a1d02002-03-22 01:27:54 +00001806 VG_(clo_n_suppressions)++;
1807 }
sewardjde4a1d02002-03-22 01:27:54 +00001808
njn25e49d8e72002-09-23 09:36:25 +00001809 /* "vwxyz" --> 000zyxwv (binary) */
nethercote71980f02004-01-24 18:18:54 +00001810 else if (VG_CLO_STREQN(16, arg, "--trace-codegen=")) {
njn25e49d8e72002-09-23 09:36:25 +00001811 Int j;
nethercote71980f02004-01-24 18:18:54 +00001812 char* opt = & arg[16];
njn25e49d8e72002-09-23 09:36:25 +00001813
1814 if (5 != VG_(strlen)(opt)) {
1815 VG_(message)(Vg_UserMsg,
1816 "--trace-codegen argument must have 5 digits");
nethercote71980f02004-01-24 18:18:54 +00001817 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001818 }
1819 for (j = 0; j < 5; j++) {
1820 if ('0' == opt[j]) { /* do nothing */ }
1821 else if ('1' == opt[j]) VG_(clo_trace_codegen) |= (1 << j);
1822 else {
1823 VG_(message)(Vg_UserMsg, "--trace-codegen argument can only "
1824 "contain 0s and 1s");
nethercote71980f02004-01-24 18:18:54 +00001825 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001826 }
1827 }
1828 }
sewardjde4a1d02002-03-22 01:27:54 +00001829
nethercote71980f02004-01-24 18:18:54 +00001830 else if (VG_CLO_STREQ(arg, "--trace-pthread=none"))
sewardj45b4b372002-04-16 22:50:32 +00001831 VG_(clo_trace_pthread_level) = 0;
nethercote71980f02004-01-24 18:18:54 +00001832 else if (VG_CLO_STREQ(arg, "--trace-pthread=some"))
sewardj45b4b372002-04-16 22:50:32 +00001833 VG_(clo_trace_pthread_level) = 1;
nethercote71980f02004-01-24 18:18:54 +00001834 else if (VG_CLO_STREQ(arg, "--trace-pthread=all"))
sewardj45b4b372002-04-16 22:50:32 +00001835 VG_(clo_trace_pthread_level) = 2;
sewardj8937c812002-04-12 20:12:20 +00001836
nethercote71980f02004-01-24 18:18:54 +00001837 else if ( ! VG_(needs).command_line_options
1838 || ! SK_(process_cmd_line_option)(arg) ) {
nethercotef4928da2004-06-15 10:54:40 +00001839 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001840 }
sewardjde4a1d02002-03-22 01:27:54 +00001841 }
1842
nethercote27fec902004-06-16 21:26:32 +00001843 // Check various option values
1844
njnf9ebf672003-05-12 21:41:30 +00001845 if (VG_(clo_verbosity) < 0)
sewardjde4a1d02002-03-22 01:27:54 +00001846 VG_(clo_verbosity) = 0;
1847
nethercote04d0fbc2004-01-26 16:48:06 +00001848 if (VG_(clo_db_attach) && VG_(clo_trace_children)) {
sewardjde4a1d02002-03-22 01:27:54 +00001849 VG_(message)(Vg_UserMsg, "");
1850 VG_(message)(Vg_UserMsg,
nethercote04d0fbc2004-01-26 16:48:06 +00001851 "--db-attach=yes conflicts with --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001852 VG_(message)(Vg_UserMsg,
1853 "Please choose one or the other, but not both.");
nethercote04d0fbc2004-01-26 16:48:06 +00001854 VG_(bad_option)("--db-attach=yes and --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001855 }
1856
nethercotef8548672004-06-21 12:42:35 +00001857 /* Set up logging now. After this is done, VG_(clo_log_fd)
sewardj4cf05692002-10-27 20:28:29 +00001858 should be connected to whatever sink has been selected, and we
1859 indiscriminately chuck stuff into it without worrying what the
1860 nature of it is. Oh the wonder of Unix streams. */
1861
nethercotee1730692003-11-20 10:38:07 +00001862 /* So far we should be still attached to stdout, so we can show on
sewardj4cf05692002-10-27 20:28:29 +00001863 the terminal any problems to do with processing command line
1864 opts. */
nethercotef8548672004-06-21 12:42:35 +00001865 vg_assert(VG_(clo_log_fd) == 1 /* stdout */);
sewardj73cf3bc2002-11-03 03:20:15 +00001866 vg_assert(VG_(logging_to_filedes) == True);
sewardj4cf05692002-10-27 20:28:29 +00001867
1868 switch (VG_(clo_log_to)) {
sewardj73cf3bc2002-11-03 03:20:15 +00001869
sewardj4cf05692002-10-27 20:28:29 +00001870 case VgLogTo_Fd:
nethercotef8548672004-06-21 12:42:35 +00001871 vg_assert(VG_(clo_log_name) == NULL);
1872 VG_(clo_log_fd) = eventually_log_fd;
sewardj4cf05692002-10-27 20:28:29 +00001873 break;
sewardj73cf3bc2002-11-03 03:20:15 +00001874
sewardj4cf05692002-10-27 20:28:29 +00001875 case VgLogTo_File: {
1876 Char logfilename[1000];
jsgff3c3f1a2003-10-14 22:13:28 +00001877 Int seq = 0;
1878 Int pid = VG_(getpid)();
1879
nethercotef8548672004-06-21 12:42:35 +00001880 vg_assert(VG_(clo_log_name) != NULL);
1881 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
jsgff3c3f1a2003-10-14 22:13:28 +00001882
nethercote71980f02004-01-24 18:18:54 +00001883 for (;;) {
jsgff3c3f1a2003-10-14 22:13:28 +00001884 if (seq == 0)
1885 VG_(sprintf)(logfilename, "%s.pid%d",
nethercotef8548672004-06-21 12:42:35 +00001886 VG_(clo_log_name), pid );
jsgff3c3f1a2003-10-14 22:13:28 +00001887 else
1888 VG_(sprintf)(logfilename, "%s.pid%d.%d",
nethercotef8548672004-06-21 12:42:35 +00001889 VG_(clo_log_name), pid, seq );
jsgff3c3f1a2003-10-14 22:13:28 +00001890 seq++;
1891
nethercotef8548672004-06-21 12:42:35 +00001892 eventually_log_fd
jsgff3c3f1a2003-10-14 22:13:28 +00001893 = VG_(open)(logfilename,
1894 VKI_O_CREAT|VKI_O_WRONLY|VKI_O_EXCL|VKI_O_TRUNC,
1895 VKI_S_IRUSR|VKI_S_IWUSR);
nethercotef8548672004-06-21 12:42:35 +00001896 if (eventually_log_fd >= 0) {
1897 VG_(clo_log_fd) = VG_(safe_fd)(eventually_log_fd);
jsgff3c3f1a2003-10-14 22:13:28 +00001898 break;
1899 } else {
nethercotef8548672004-06-21 12:42:35 +00001900 if (eventually_log_fd != -VKI_EEXIST) {
jsgff3c3f1a2003-10-14 22:13:28 +00001901 VG_(message)(Vg_UserMsg,
1902 "Can't create/open log file `%s.pid%d'; giving up!",
nethercotef8548672004-06-21 12:42:35 +00001903 VG_(clo_log_name), pid);
jsgff3c3f1a2003-10-14 22:13:28 +00001904 VG_(bad_option)(
nethercotef8548672004-06-21 12:42:35 +00001905 "--log-file=<file> didn't work out for some reason.");
jsgff3c3f1a2003-10-14 22:13:28 +00001906 break;
1907 }
1908 }
1909 }
sewardj4cf05692002-10-27 20:28:29 +00001910 break;
sewardj73cf3bc2002-11-03 03:20:15 +00001911 }
1912
1913 case VgLogTo_Socket: {
nethercotef8548672004-06-21 12:42:35 +00001914 vg_assert(VG_(clo_log_name) != NULL);
1915 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
1916 eventually_log_fd = VG_(connect_via_socket)( VG_(clo_log_name) );
1917 if (eventually_log_fd == -1) {
sewardj73cf3bc2002-11-03 03:20:15 +00001918 VG_(message)(Vg_UserMsg,
nethercotef8548672004-06-21 12:42:35 +00001919 "Invalid --log-socket=ipaddr or --log-socket=ipaddr:port spec");
sewardj73cf3bc2002-11-03 03:20:15 +00001920 VG_(message)(Vg_UserMsg,
nethercotef8548672004-06-21 12:42:35 +00001921 "of `%s'; giving up!", VG_(clo_log_name) );
sewardj73cf3bc2002-11-03 03:20:15 +00001922 VG_(bad_option)(
nethercotef8548672004-06-21 12:42:35 +00001923 "--log-socket=");
sewardj4cf05692002-10-27 20:28:29 +00001924 }
nethercotef8548672004-06-21 12:42:35 +00001925 if (eventually_log_fd == -2) {
sewardj73cf3bc2002-11-03 03:20:15 +00001926 VG_(message)(Vg_UserMsg,
sewardj570f8902002-11-03 11:44:36 +00001927 "valgrind: failed to connect to logging server `%s'.",
nethercotef8548672004-06-21 12:42:35 +00001928 VG_(clo_log_name) );
sewardj570f8902002-11-03 11:44:36 +00001929 VG_(message)(Vg_UserMsg,
1930 "Log messages will sent to stderr instead." );
1931 VG_(message)(Vg_UserMsg,
1932 "" );
1933 /* We don't change anything here. */
1934 } else {
nethercotef8548672004-06-21 12:42:35 +00001935 vg_assert(eventually_log_fd > 0);
1936 VG_(clo_log_fd) = eventually_log_fd;
sewardj570f8902002-11-03 11:44:36 +00001937 VG_(logging_to_filedes) = False;
1938 }
sewardj73cf3bc2002-11-03 03:20:15 +00001939 break;
1940 }
1941
sewardj4cf05692002-10-27 20:28:29 +00001942 }
1943
nethercotef8548672004-06-21 12:42:35 +00001944 /* Move log_fd into the safe range, so it doesn't conflict with any app fds */
thughesad1c9562004-06-26 11:27:52 +00001945 eventually_log_fd = VG_(fcntl)(VG_(clo_log_fd), VKI_F_DUPFD, VG_(fd_hard_limit));
nethercotef8548672004-06-21 12:42:35 +00001946 if (eventually_log_fd < 0)
jsgf855d93d2003-10-13 22:26:55 +00001947 VG_(message)(Vg_UserMsg, "valgrind: failed to move logfile fd into safe range");
1948 else {
nethercotef8548672004-06-21 12:42:35 +00001949 VG_(clo_log_fd) = eventually_log_fd;
1950 VG_(fcntl)(VG_(clo_log_fd), VKI_F_SETFD, VKI_FD_CLOEXEC);
jsgf855d93d2003-10-13 22:26:55 +00001951 }
1952
sewardj4cf05692002-10-27 20:28:29 +00001953 /* Ok, the logging sink is running now. Print a suitable preamble.
1954 If logging to file or a socket, write details of parent PID and
1955 command line args, to help people trying to interpret the
1956 results of a run which encompasses multiple processes. */
sewardjde4a1d02002-03-22 01:27:54 +00001957
sewardj83adf412002-05-01 01:25:45 +00001958 if (VG_(clo_verbosity > 0)) {
njnd04b7c62002-10-03 14:05:52 +00001959 /* Skin details */
1960 VG_(message)(Vg_UserMsg, "%s%s%s, %s for x86-linux.",
1961 VG_(details).name,
1962 NULL == VG_(details).version ? "" : "-",
1963 NULL == VG_(details).version
1964 ? (Char*)"" : VG_(details).version,
1965 VG_(details).description);
1966 VG_(message)(Vg_UserMsg, "%s", VG_(details).copyright_author);
sewardj3b2736a2002-03-24 12:18:35 +00001967
njnd04b7c62002-10-03 14:05:52 +00001968 /* Core details */
1969 VG_(message)(Vg_UserMsg,
njn3e884182003-04-15 13:03:23 +00001970 "Using valgrind-%s, a program supervision framework for x86-linux.",
sewardj4aa62ba2002-10-05 15:49:27 +00001971 VERSION);
sewardjde4a1d02002-03-22 01:27:54 +00001972 VG_(message)(Vg_UserMsg,
nethercote08fa9a72004-07-16 17:44:00 +00001973 "Copyright (C) 2000-2004, and GNU GPL'd, by Julian Seward et al.");
njnd04b7c62002-10-03 14:05:52 +00001974 }
1975
nethercotec1e395d2003-11-10 13:26:49 +00001976 if (VG_(clo_verbosity) > 0 && VG_(clo_log_to) != VgLogTo_Fd) {
sewardj4cf05692002-10-27 20:28:29 +00001977 VG_(message)(Vg_UserMsg, "");
1978 VG_(message)(Vg_UserMsg,
1979 "My PID = %d, parent PID = %d. Prog and args are:",
1980 VG_(getpid)(), VG_(getppid)() );
1981 for (i = 0; i < VG_(client_argc); i++)
1982 VG_(message)(Vg_UserMsg, " %s", VG_(client_argv)[i]);
1983 }
1984
sewardjde4a1d02002-03-22 01:27:54 +00001985 if (VG_(clo_verbosity) > 1) {
nethercotea70f7352004-04-18 12:08:46 +00001986 Int fd;
sewardj4cf05692002-10-27 20:28:29 +00001987 if (VG_(clo_log_to) != VgLogTo_Fd)
1988 VG_(message)(Vg_UserMsg, "");
fitzhardinge98abfc72003-12-16 02:05:15 +00001989 VG_(message)(Vg_UserMsg, "Valgrind library directory: %s", VG_(libdir));
njn86dc2bc2003-09-09 07:26:21 +00001990 VG_(message)(Vg_UserMsg, "Command line");
1991 for (i = 0; i < VG_(client_argc); i++)
1992 VG_(message)(Vg_UserMsg, " %s", VG_(client_argv)[i]);
1993
sewardjde4a1d02002-03-22 01:27:54 +00001994 VG_(message)(Vg_UserMsg, "Startup, with flags:");
nethercote71980f02004-01-24 18:18:54 +00001995 for (i = 1; i < VG_(vg_argc); i++) {
1996 VG_(message)(Vg_UserMsg, " %s", VG_(vg_argv)[i]);
sewardjde4a1d02002-03-22 01:27:54 +00001997 }
nethercotea70f7352004-04-18 12:08:46 +00001998
1999 VG_(message)(Vg_UserMsg, "Contents of /proc/version:");
2000 fd = VG_(open) ( "/proc/version", VKI_O_RDONLY, 0 );
2001 if (fd < 0) {
2002 VG_(message)(Vg_UserMsg, " can't open /proc/version");
2003 } else {
2004 #define BUF_LEN 256
2005 Char version_buf[BUF_LEN];
2006 Int n = VG_(read) ( fd, version_buf, BUF_LEN );
2007 vg_assert(n <= 256);
2008 if (n > 0) {
2009 version_buf[n-1] = '\0';
2010 VG_(message)(Vg_UserMsg, " %s", version_buf);
2011 } else {
2012 VG_(message)(Vg_UserMsg, " (empty?)");
2013 }
2014 VG_(close)(fd);
2015 #undef BUF_LEN
2016 }
sewardjde4a1d02002-03-22 01:27:54 +00002017 }
2018
fitzhardinge98abfc72003-12-16 02:05:15 +00002019 if (VG_(clo_n_suppressions) < VG_CLO_MAX_SFILES-1 &&
njn25e49d8e72002-09-23 09:36:25 +00002020 (VG_(needs).core_errors || VG_(needs).skin_errors)) {
fitzhardinge98abfc72003-12-16 02:05:15 +00002021 /* If there are no suppression files specified and the skin
2022 needs one, load the default */
2023 static const Char default_supp[] = "default.supp";
2024 Int len = VG_(strlen)(VG_(libdir)) + 1 + sizeof(default_supp);
2025 Char *buf = VG_(arena_malloc)(VG_AR_CORE, len);
2026 VG_(sprintf)(buf, "%s/%s", VG_(libdir), default_supp);
2027 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = buf;
2028 VG_(clo_n_suppressions)++;
sewardjde4a1d02002-03-22 01:27:54 +00002029 }
sewardj4cf05692002-10-27 20:28:29 +00002030
njn6a230532003-07-21 10:38:23 +00002031 if (VG_(clo_gen_suppressions) &&
2032 !VG_(needs).core_errors && !VG_(needs).skin_errors) {
nethercotef4928da2004-06-15 10:54:40 +00002033 VG_(message)(Vg_UserMsg,
2034 "Can't use --gen-suppressions=yes with this tool,");
2035 VG_(message)(Vg_UserMsg,
2036 "as it doesn't generate errors.");
2037 VG_(bad_option)("--gen-suppressions=yes");
njn6a230532003-07-21 10:38:23 +00002038 }
sewardjde4a1d02002-03-22 01:27:54 +00002039}
2040
sewardjde4a1d02002-03-22 01:27:54 +00002041
nethercote71980f02004-01-24 18:18:54 +00002042/*====================================================================*/
2043/*=== File descriptor setup ===*/
2044/*====================================================================*/
2045
2046static void setup_file_descriptors(void)
2047{
2048 struct vki_rlimit rl;
2049
2050 /* Get the current file descriptor limits. */
2051 if (VG_(getrlimit)(VKI_RLIMIT_NOFILE, &rl) < 0) {
2052 rl.rlim_cur = 1024;
2053 rl.rlim_max = 1024;
2054 }
2055
2056 /* Work out where to move the soft limit to. */
2057 if (rl.rlim_cur + VG_N_RESERVED_FDS <= rl.rlim_max) {
2058 rl.rlim_cur = rl.rlim_cur + VG_N_RESERVED_FDS;
2059 } else {
2060 rl.rlim_cur = rl.rlim_max;
2061 }
2062
2063 /* Reserve some file descriptors for our use. */
thughesad1c9562004-06-26 11:27:52 +00002064 VG_(fd_soft_limit) = rl.rlim_cur - VG_N_RESERVED_FDS;
2065 VG_(fd_hard_limit) = rl.rlim_cur - VG_N_RESERVED_FDS;
nethercote71980f02004-01-24 18:18:54 +00002066
2067 /* Update the soft limit. */
2068 VG_(setrlimit)(VKI_RLIMIT_NOFILE, &rl);
2069
2070 if (VG_(vgexecfd) != -1)
2071 VG_(vgexecfd) = VG_(safe_fd)( VG_(vgexecfd) );
2072 if (VG_(clexecfd) != -1)
2073 VG_(clexecfd) = VG_(safe_fd)( VG_(clexecfd) );
2074}
2075
2076
2077/*====================================================================*/
nethercote1d447092004-02-01 17:29:59 +00002078/*=== baseBlock: definition + setup ===*/
nethercote71980f02004-01-24 18:18:54 +00002079/*====================================================================*/
2080
2081/* The variables storing offsets. */
2082
2083#define INVALID_OFFSET (-1)
2084
2085Int VGOFF_(m_eax) = INVALID_OFFSET;
2086Int VGOFF_(m_ecx) = INVALID_OFFSET;
2087Int VGOFF_(m_edx) = INVALID_OFFSET;
2088Int VGOFF_(m_ebx) = INVALID_OFFSET;
2089Int VGOFF_(m_esp) = INVALID_OFFSET;
2090Int VGOFF_(m_ebp) = INVALID_OFFSET;
2091Int VGOFF_(m_esi) = INVALID_OFFSET;
2092Int VGOFF_(m_edi) = INVALID_OFFSET;
2093Int VGOFF_(m_eflags) = INVALID_OFFSET;
2094Int VGOFF_(m_dflag) = INVALID_OFFSET;
2095Int VGOFF_(m_ssestate) = INVALID_OFFSET;
2096Int VGOFF_(ldt) = INVALID_OFFSET;
2097Int VGOFF_(tls) = INVALID_OFFSET;
2098Int VGOFF_(m_cs) = INVALID_OFFSET;
2099Int VGOFF_(m_ss) = INVALID_OFFSET;
2100Int VGOFF_(m_ds) = INVALID_OFFSET;
2101Int VGOFF_(m_es) = INVALID_OFFSET;
2102Int VGOFF_(m_fs) = INVALID_OFFSET;
2103Int VGOFF_(m_gs) = INVALID_OFFSET;
2104Int VGOFF_(m_eip) = INVALID_OFFSET;
2105Int VGOFF_(spillslots) = INVALID_OFFSET;
2106Int VGOFF_(sh_eax) = INVALID_OFFSET;
2107Int VGOFF_(sh_ecx) = INVALID_OFFSET;
2108Int VGOFF_(sh_edx) = INVALID_OFFSET;
2109Int VGOFF_(sh_ebx) = INVALID_OFFSET;
2110Int VGOFF_(sh_esp) = INVALID_OFFSET;
2111Int VGOFF_(sh_ebp) = INVALID_OFFSET;
2112Int VGOFF_(sh_esi) = INVALID_OFFSET;
2113Int VGOFF_(sh_edi) = INVALID_OFFSET;
2114Int VGOFF_(sh_eflags) = INVALID_OFFSET;
2115
2116Int VGOFF_(helper_idiv_64_32) = INVALID_OFFSET;
2117Int VGOFF_(helper_div_64_32) = INVALID_OFFSET;
2118Int VGOFF_(helper_idiv_32_16) = INVALID_OFFSET;
2119Int VGOFF_(helper_div_32_16) = INVALID_OFFSET;
2120Int VGOFF_(helper_idiv_16_8) = INVALID_OFFSET;
2121Int VGOFF_(helper_div_16_8) = INVALID_OFFSET;
2122Int VGOFF_(helper_imul_32_64) = INVALID_OFFSET;
2123Int VGOFF_(helper_mul_32_64) = INVALID_OFFSET;
2124Int VGOFF_(helper_imul_16_32) = INVALID_OFFSET;
2125Int VGOFF_(helper_mul_16_32) = INVALID_OFFSET;
2126Int VGOFF_(helper_imul_8_16) = INVALID_OFFSET;
2127Int VGOFF_(helper_mul_8_16) = INVALID_OFFSET;
2128Int VGOFF_(helper_CLD) = INVALID_OFFSET;
2129Int VGOFF_(helper_STD) = INVALID_OFFSET;
2130Int VGOFF_(helper_get_dirflag) = INVALID_OFFSET;
2131Int VGOFF_(helper_CLC) = INVALID_OFFSET;
2132Int VGOFF_(helper_STC) = INVALID_OFFSET;
nethercote1018bdd2004-02-11 23:33:29 +00002133Int VGOFF_(helper_CMC) = INVALID_OFFSET;
nethercote71980f02004-01-24 18:18:54 +00002134Int VGOFF_(helper_shldl) = INVALID_OFFSET;
2135Int VGOFF_(helper_shldw) = INVALID_OFFSET;
2136Int VGOFF_(helper_shrdl) = INVALID_OFFSET;
2137Int VGOFF_(helper_shrdw) = INVALID_OFFSET;
2138Int VGOFF_(helper_IN) = INVALID_OFFSET;
2139Int VGOFF_(helper_OUT) = INVALID_OFFSET;
2140Int VGOFF_(helper_RDTSC) = INVALID_OFFSET;
2141Int VGOFF_(helper_CPUID) = INVALID_OFFSET;
2142Int VGOFF_(helper_BSWAP) = INVALID_OFFSET;
nethercote1018bdd2004-02-11 23:33:29 +00002143Int VGOFF_(helper_bsfw) = INVALID_OFFSET;
2144Int VGOFF_(helper_bsfl) = INVALID_OFFSET;
2145Int VGOFF_(helper_bsrw) = INVALID_OFFSET;
2146Int VGOFF_(helper_bsrl) = INVALID_OFFSET;
nethercote71980f02004-01-24 18:18:54 +00002147Int VGOFF_(helper_fstsw_AX) = INVALID_OFFSET;
2148Int VGOFF_(helper_SAHF) = INVALID_OFFSET;
2149Int VGOFF_(helper_LAHF) = INVALID_OFFSET;
2150Int VGOFF_(helper_DAS) = INVALID_OFFSET;
2151Int VGOFF_(helper_DAA) = INVALID_OFFSET;
nethercote1018bdd2004-02-11 23:33:29 +00002152Int VGOFF_(helper_AAS) = INVALID_OFFSET;
2153Int VGOFF_(helper_AAA) = INVALID_OFFSET;
2154Int VGOFF_(helper_AAD) = INVALID_OFFSET;
2155Int VGOFF_(helper_AAM) = INVALID_OFFSET;
nethercote71980f02004-01-24 18:18:54 +00002156Int VGOFF_(helper_cmpxchg8b) = INVALID_OFFSET;
2157Int VGOFF_(helper_undefined_instruction) = INVALID_OFFSET;
2158
2159/* MAX_NONCOMPACT_HELPERS can be increased easily. If MAX_COMPACT_HELPERS is
2160 * increased too much, they won't really be compact any more... */
2161#define MAX_COMPACT_HELPERS 8
2162#define MAX_NONCOMPACT_HELPERS 50
2163
2164UInt VG_(n_compact_helpers) = 0;
2165UInt VG_(n_noncompact_helpers) = 0;
2166
2167Addr VG_(compact_helper_addrs) [MAX_COMPACT_HELPERS];
2168Int VG_(compact_helper_offsets)[MAX_COMPACT_HELPERS];
2169Addr VG_(noncompact_helper_addrs) [MAX_NONCOMPACT_HELPERS];
2170Int VG_(noncompact_helper_offsets)[MAX_NONCOMPACT_HELPERS];
2171
2172/* This is the actual defn of baseblock. */
2173UInt VG_(baseBlock)[VG_BASEBLOCK_WORDS];
2174
nethercote71980f02004-01-24 18:18:54 +00002175/* Words. */
2176static Int baB_off = 0;
2177
2178
sewardjfa492d42002-12-08 18:20:01 +00002179UInt VG_(insertDflag)(UInt eflags, Int d)
2180{
2181 vg_assert(d == 1 || d == -1);
2182 eflags &= ~EFlagD;
2183
2184 if (d < 0)
2185 eflags |= EFlagD;
2186
2187 return eflags;
2188}
2189
2190Int VG_(extractDflag)(UInt eflags)
2191{
2192 Int ret;
2193
2194 if (eflags & EFlagD)
2195 ret = -1;
2196 else
2197 ret = 1;
2198
2199 return ret;
2200}
2201
nethercote71980f02004-01-24 18:18:54 +00002202/* Returns the offset, in words. */
2203static Int alloc_BaB ( Int words )
sewardjde4a1d02002-03-22 01:27:54 +00002204{
nethercote71980f02004-01-24 18:18:54 +00002205 Int off = baB_off;
2206 baB_off += words;
2207 if (baB_off >= VG_BASEBLOCK_WORDS)
2208 VG_(core_panic)( "alloc_BaB: baseBlock is too small");
sewardjde4a1d02002-03-22 01:27:54 +00002209
nethercote71980f02004-01-24 18:18:54 +00002210 return off;
sewardjde4a1d02002-03-22 01:27:54 +00002211}
2212
nethercote71980f02004-01-24 18:18:54 +00002213/* Align offset, in *bytes* */
2214static void align_BaB ( UInt align )
njn25e49d8e72002-09-23 09:36:25 +00002215{
nethercote71980f02004-01-24 18:18:54 +00002216 vg_assert(2 == align || 4 == align || 8 == align || 16 == align);
2217 baB_off += (align-1);
2218 baB_off &= ~(align-1);
njn25e49d8e72002-09-23 09:36:25 +00002219}
2220
nethercote71980f02004-01-24 18:18:54 +00002221/* Allocate 1 word in baseBlock and set it to the given value. */
2222static Int alloc_BaB_1_set ( Addr a )
njn25e49d8e72002-09-23 09:36:25 +00002223{
nethercote71980f02004-01-24 18:18:54 +00002224 Int off = alloc_BaB(1);
2225 VG_(baseBlock)[off] = (UInt)a;
2226 return off;
njn25e49d8e72002-09-23 09:36:25 +00002227}
2228
nethercote71980f02004-01-24 18:18:54 +00002229/* Registers a function in compact_helper_addrs; compact_helper_offsets is
2230 filled in later. */
2231void VG_(register_compact_helper)(Addr a)
sewardjde4a1d02002-03-22 01:27:54 +00002232{
nethercote71980f02004-01-24 18:18:54 +00002233 if (MAX_COMPACT_HELPERS <= VG_(n_compact_helpers)) {
2234 VG_(printf)("Can only register %d compact helpers\n",
2235 MAX_COMPACT_HELPERS);
2236 VG_(core_panic)("Too many compact helpers registered");
2237 }
2238 VG_(compact_helper_addrs)[VG_(n_compact_helpers)] = a;
2239 VG_(n_compact_helpers)++;
2240}
2241
2242/* Registers a function in noncompact_helper_addrs; noncompact_helper_offsets
2243 * is filled in later.
2244 */
2245void VG_(register_noncompact_helper)(Addr a)
2246{
2247 if (MAX_NONCOMPACT_HELPERS <= VG_(n_noncompact_helpers)) {
2248 VG_(printf)("Can only register %d non-compact helpers\n",
2249 MAX_NONCOMPACT_HELPERS);
2250 VG_(printf)("Try increasing MAX_NON_COMPACT_HELPERS\n");
2251 VG_(core_panic)("Too many non-compact helpers registered");
2252 }
2253 VG_(noncompact_helper_addrs)[VG_(n_noncompact_helpers)] = a;
2254 VG_(n_noncompact_helpers)++;
2255}
2256
2257/* Allocate offsets in baseBlock for the skin helpers */
2258static
2259void assign_helpers_in_baseBlock(UInt n, Int offsets[], Addr addrs[])
2260{
2261 UInt i;
2262 for (i = 0; i < n; i++)
2263 offsets[i] = alloc_BaB_1_set( addrs[i] );
2264}
2265
2266Bool VG_(need_to_handle_esp_assignment)(void)
2267{
2268 return ( VG_(defined_new_mem_stack_4)() ||
2269 VG_(defined_die_mem_stack_4)() ||
2270 VG_(defined_new_mem_stack_8)() ||
2271 VG_(defined_die_mem_stack_8)() ||
2272 VG_(defined_new_mem_stack_12)() ||
2273 VG_(defined_die_mem_stack_12)() ||
2274 VG_(defined_new_mem_stack_16)() ||
2275 VG_(defined_die_mem_stack_16)() ||
2276 VG_(defined_new_mem_stack_32)() ||
2277 VG_(defined_die_mem_stack_32)() ||
2278 VG_(defined_new_mem_stack)() ||
2279 VG_(defined_die_mem_stack)()
2280 );
2281}
2282
2283/* Here we assign actual offsets. It's important to get the most
2284 popular referents within 128 bytes of the start, so we can take
2285 advantage of short addressing modes relative to %ebp. Popularity
2286 of offsets was measured on 22 Feb 02 running a KDE application, and
2287 the slots rearranged accordingly, with a 1.5% reduction in total
2288 size of translations. */
2289static void init_baseBlock ( Addr client_eip, Addr esp_at_startup )
2290{
2291 /* Those with offsets under 128 are carefully chosen. */
2292
2293 /* WORD offsets in this column */
2294 /* 0 */ VGOFF_(m_eax) = alloc_BaB_1_set(0);
2295 /* 1 */ VGOFF_(m_ecx) = alloc_BaB_1_set(0);
2296 /* 2 */ VGOFF_(m_edx) = alloc_BaB_1_set(0);
2297 /* 3 */ VGOFF_(m_ebx) = alloc_BaB_1_set(0);
2298 /* 4 */ VGOFF_(m_esp) = alloc_BaB_1_set(esp_at_startup);
2299 /* 5 */ VGOFF_(m_ebp) = alloc_BaB_1_set(0);
2300 /* 6 */ VGOFF_(m_esi) = alloc_BaB_1_set(0);
2301 /* 7 */ VGOFF_(m_edi) = alloc_BaB_1_set(0);
2302 /* 8 */ VGOFF_(m_eflags) = alloc_BaB_1_set(0);
2303
2304 if (VG_(needs).shadow_regs) {
2305 /* 9 */ VGOFF_(sh_eax) = alloc_BaB_1_set(0);
2306 /* 10 */ VGOFF_(sh_ecx) = alloc_BaB_1_set(0);
2307 /* 11 */ VGOFF_(sh_edx) = alloc_BaB_1_set(0);
2308 /* 12 */ VGOFF_(sh_ebx) = alloc_BaB_1_set(0);
2309 /* 13 */ VGOFF_(sh_esp) = alloc_BaB_1_set(0);
2310 /* 14 */ VGOFF_(sh_ebp) = alloc_BaB_1_set(0);
2311 /* 15 */ VGOFF_(sh_esi) = alloc_BaB_1_set(0);
2312 /* 16 */ VGOFF_(sh_edi) = alloc_BaB_1_set(0);
2313 /* 17 */ VGOFF_(sh_eflags) = alloc_BaB_1_set(0);
2314 VG_TRACK( post_regs_write_init );
2315 }
2316
2317 /* 9,10,11 or 18,19,20... depends on number whether shadow regs are used
2318 * and on compact helpers registered */
2319
2320 /* Make these most-frequently-called specialised ones compact, if they
2321 are used. */
2322 if (VG_(defined_new_mem_stack_4)())
2323 VG_(register_compact_helper)( (Addr) VG_(tool_interface).track_new_mem_stack_4);
2324
2325 if (VG_(defined_die_mem_stack_4)())
2326 VG_(register_compact_helper)( (Addr) VG_(tool_interface).track_die_mem_stack_4);
2327
2328 /* (9 or 18) + n_compact_helpers */
2329 /* Allocate slots for compact helpers */
2330 assign_helpers_in_baseBlock(VG_(n_compact_helpers),
2331 VG_(compact_helper_offsets),
2332 VG_(compact_helper_addrs));
2333
2334 /* (9/10 or 18/19) + n_compact_helpers */
2335 VGOFF_(m_eip) = alloc_BaB_1_set(client_eip);
2336
2337 /* There are currently 24 spill slots */
2338 /* (11+/20+ .. 32+/43+) + n_compact_helpers. This can overlap the magic
2339 * boundary at >= 32 words, but most spills are to low numbered spill
2340 * slots, so the ones above the boundary don't see much action. */
2341 VGOFF_(spillslots) = alloc_BaB(VG_MAX_SPILLSLOTS);
2342
2343 /* I gave up counting at this point. Since they're above the
2344 short-amode-boundary, there's no point. */
2345
2346 VGOFF_(m_dflag) = alloc_BaB_1_set(1); // 1 == forward D-flag
2347
2348 /* The FPU/SSE state. This _must_ be 16-byte aligned. Initial
2349 state doesn't matter much, as long as it's not totally borked. */
2350 align_BaB(16);
2351 VGOFF_(m_ssestate) = alloc_BaB(VG_SIZE_OF_SSESTATE_W);
2352 vg_assert(
2353 0 == ( ((UInt)(& VG_(baseBlock)[VGOFF_(m_ssestate)])) % 16 )
sewardj22854b92002-11-30 14:00:47 +00002354 );
2355
fitzhardingec2dbbac2004-01-23 23:09:01 +00002356 /* I assume that if we have SSE2 we also have SSE */
2357 VG_(have_ssestate) =
2358 VG_(cpu_has_feature)(VG_X86_FEAT_FXSR) &&
2359 VG_(cpu_has_feature)(VG_X86_FEAT_SSE);
2360
fitzhardinge98abfc72003-12-16 02:05:15 +00002361 /* set up an initial FPU state (doesn't really matter what it is,
2362 so long as it's somewhat valid) */
2363 if (!VG_(have_ssestate))
nethercote71980f02004-01-24 18:18:54 +00002364 asm volatile("fwait; fnsave %0; fwait; frstor %0; fwait"
2365 :
2366 : "m" (VG_(baseBlock)[VGOFF_(m_ssestate)])
2367 : "cc", "memory");
fitzhardinge98abfc72003-12-16 02:05:15 +00002368 else
nethercote71980f02004-01-24 18:18:54 +00002369 asm volatile("fwait; fxsave %0; fwait; andl $0xffbf, %1;"
2370 "fxrstor %0; fwait"
2371 :
2372 : "m" (VG_(baseBlock)[VGOFF_(m_ssestate)]),
2373 "m" (VG_(baseBlock)[VGOFF_(m_ssestate)+(24/4)])
2374 : "cc", "memory");
fitzhardinge98abfc72003-12-16 02:05:15 +00002375
njn0c7a5b52003-04-30 09:00:33 +00002376 if (0) {
2377 if (VG_(have_ssestate))
2378 VG_(printf)("Looks like a SSE-capable CPU\n");
2379 else
2380 VG_(printf)("Looks like a MMX-only CPU\n");
2381 }
sewardjb91ae7f2003-04-29 23:50:00 +00002382
nethercote71980f02004-01-24 18:18:54 +00002383 /* LDT pointer: pretend the root thread has an empty LDT to start with. */
2384 VGOFF_(ldt) = alloc_BaB_1_set((UInt)NULL);
jsgf855d93d2003-10-13 22:26:55 +00002385
nethercote71980f02004-01-24 18:18:54 +00002386 /* TLS pointer: pretend the root thread has no TLS array for now. */
2387 VGOFF_(tls) = alloc_BaB_1_set((UInt)NULL);
fitzhardingef0046f22003-12-18 02:39:22 +00002388
nethercote71980f02004-01-24 18:18:54 +00002389 /* segment registers */
2390 VGOFF_(m_cs) = alloc_BaB_1_set(0);
2391 VGOFF_(m_ss) = alloc_BaB_1_set(0);
2392 VGOFF_(m_ds) = alloc_BaB_1_set(0);
2393 VGOFF_(m_es) = alloc_BaB_1_set(0);
2394 VGOFF_(m_fs) = alloc_BaB_1_set(0);
2395 VGOFF_(m_gs) = alloc_BaB_1_set(0);
fitzhardingef0046f22003-12-18 02:39:22 +00002396
thughes35cec982004-04-21 15:16:43 +00002397 /* initialise %cs, %ds and %ss to point at the operating systems
2398 default code, data and stack segments */
2399 asm volatile("movw %%cs, %0"
2400 :
2401 : "m" (VG_(baseBlock)[VGOFF_(m_cs)]));
2402 asm volatile("movw %%ds, %0"
2403 :
2404 : "m" (VG_(baseBlock)[VGOFF_(m_ds)]));
2405 asm volatile("movw %%ss, %0"
2406 :
2407 : "m" (VG_(baseBlock)[VGOFF_(m_ss)]));
2408
nethercote71980f02004-01-24 18:18:54 +00002409 VG_(register_noncompact_helper)( (Addr) & VG_(do_useseg) );
fitzhardingef0046f22003-12-18 02:39:22 +00002410
nethercote71980f02004-01-24 18:18:54 +00002411#define REG(kind, size) \
2412 if (VG_(defined_##kind##_mem_stack##size)()) \
2413 VG_(register_noncompact_helper)( \
2414 (Addr) VG_(tool_interface).track_##kind##_mem_stack##size );
2415 REG(new, _8);
2416 REG(new, _12);
2417 REG(new, _16);
2418 REG(new, _32);
2419 REG(new, );
2420 REG(die, _8);
2421 REG(die, _12);
2422 REG(die, _16);
2423 REG(die, _32);
2424 REG(die, );
2425#undef REG
fitzhardingef0046f22003-12-18 02:39:22 +00002426
nethercote71980f02004-01-24 18:18:54 +00002427 if (VG_(need_to_handle_esp_assignment)())
2428 VG_(register_noncompact_helper)((Addr) VG_(unknown_esp_update));
fitzhardingeb791a192003-12-18 07:22:44 +00002429
nethercote71980f02004-01-24 18:18:54 +00002430# define HELPER(name) \
2431 VGOFF_(helper_##name) = alloc_BaB_1_set( (Addr) & VG_(helper_##name))
njn3e884182003-04-15 13:03:23 +00002432
nethercote71980f02004-01-24 18:18:54 +00002433 /* Helper functions. */
2434 HELPER(idiv_64_32); HELPER(div_64_32);
2435 HELPER(idiv_32_16); HELPER(div_32_16);
2436 HELPER(idiv_16_8); HELPER(div_16_8);
fitzhardinge98abfc72003-12-16 02:05:15 +00002437
nethercote71980f02004-01-24 18:18:54 +00002438 HELPER(imul_32_64); HELPER(mul_32_64);
2439 HELPER(imul_16_32); HELPER(mul_16_32);
2440 HELPER(imul_8_16); HELPER(mul_8_16);
njn25e49d8e72002-09-23 09:36:25 +00002441
nethercote71980f02004-01-24 18:18:54 +00002442 HELPER(CLD); HELPER(STD);
2443 HELPER(get_dirflag);
sewardjde4a1d02002-03-22 01:27:54 +00002444
nethercote71980f02004-01-24 18:18:54 +00002445 HELPER(CLC); HELPER(STC);
nethercote1018bdd2004-02-11 23:33:29 +00002446 HELPER(CMC);
jsgf855d93d2003-10-13 22:26:55 +00002447
nethercote71980f02004-01-24 18:18:54 +00002448 HELPER(shldl); HELPER(shldw);
2449 HELPER(shrdl); HELPER(shrdw);
njncc7bb472002-10-14 09:25:19 +00002450
nethercote71980f02004-01-24 18:18:54 +00002451 HELPER(RDTSC); HELPER(CPUID);
njncc7bb472002-10-14 09:25:19 +00002452
nethercote1018bdd2004-02-11 23:33:29 +00002453 HELPER(bsfw); HELPER(bsfl);
2454 HELPER(bsrw); HELPER(bsrl);
rjwalshf5f536f2003-11-17 17:45:00 +00002455
nethercote71980f02004-01-24 18:18:54 +00002456 HELPER(fstsw_AX);
2457 HELPER(SAHF); HELPER(LAHF);
2458 HELPER(DAS); HELPER(DAA);
nethercote1018bdd2004-02-11 23:33:29 +00002459 HELPER(AAS); HELPER(AAA);
2460 HELPER(AAD); HELPER(AAM);
nethercote71980f02004-01-24 18:18:54 +00002461 HELPER(IN); HELPER(OUT);
2462 HELPER(cmpxchg8b);
sewardj018f7622002-05-15 21:13:39 +00002463
nethercote71980f02004-01-24 18:18:54 +00002464 HELPER(undefined_instruction);
jsgf855d93d2003-10-13 22:26:55 +00002465
nethercote71980f02004-01-24 18:18:54 +00002466# undef HELPER
sewardjde4a1d02002-03-22 01:27:54 +00002467
nethercote71980f02004-01-24 18:18:54 +00002468 /* Allocate slots for noncompact helpers */
2469 assign_helpers_in_baseBlock(VG_(n_noncompact_helpers),
2470 VG_(noncompact_helper_offsets),
2471 VG_(noncompact_helper_addrs));
2472}
sewardjde4a1d02002-03-22 01:27:54 +00002473
sewardj5f07b662002-04-23 16:52:51 +00002474
nethercote71980f02004-01-24 18:18:54 +00002475/*====================================================================*/
2476/*=== Setup pointercheck ===*/
2477/*====================================================================*/
njn25e49d8e72002-09-23 09:36:25 +00002478
nethercote71980f02004-01-24 18:18:54 +00002479static void setup_pointercheck(void)
2480{
2481 int ret;
sewardj2e93c502002-04-12 11:12:52 +00002482
fitzhardinge98abfc72003-12-16 02:05:15 +00002483 if (VG_(clo_pointercheck)) {
nethercote71980f02004-01-24 18:18:54 +00002484 vki_modify_ldt_t ldt = {
2485 VG_POINTERCHECK_SEGIDX, // entry_number
2486 VG_(client_base), // base_addr
2487 (VG_(client_end)-VG_(client_base)) / VKI_BYTES_PER_PAGE, // limit
2488 1, // seg_32bit
2489 0, // contents: data, RW, non-expanding
2490 0, // ! read_exec_only
2491 1, // limit_in_pages
2492 0, // ! seg not present
2493 1, // useable
fitzhardinge98abfc72003-12-16 02:05:15 +00002494 };
nethercote71980f02004-01-24 18:18:54 +00002495 ret = VG_(do_syscall)(__NR_modify_ldt, 1, &ldt, sizeof(ldt));
fitzhardinge98abfc72003-12-16 02:05:15 +00002496 if (ret < 0) {
2497 VG_(message)(Vg_UserMsg,
2498 "Warning: ignoring --pointercheck=yes, "
2499 "because modify_ldt failed (errno=%d)", -ret);
2500 VG_(clo_pointercheck) = False;
2501 }
2502 }
sewardjde4a1d02002-03-22 01:27:54 +00002503}
2504
nethercote71980f02004-01-24 18:18:54 +00002505/*====================================================================*/
2506/*=== Initialise program data/text, etc. ===*/
2507/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +00002508
nethercote71980f02004-01-24 18:18:54 +00002509static void build_valgrind_map_callback
2510 ( Addr start, UInt size, Char rr, Char ww, Char xx,
2511 UInt dev, UInt ino, ULong foffset, const UChar* filename )
sewardjde4a1d02002-03-22 01:27:54 +00002512{
nethercote71980f02004-01-24 18:18:54 +00002513 UInt prot = 0;
2514 UInt flags = SF_MMAP|SF_NOSYMS;
2515 Bool is_stack_segment;
2516
2517 is_stack_segment =
2518 (start == VG_(clstk_base) && (start+size) == VG_(clstk_end));
2519
2520 /* Only record valgrind mappings for now, without loading any
2521 symbols. This is so we know where the free space is before we
2522 start allocating more memory (note: heap is OK, it's just mmap
2523 which is the problem here). */
2524 if (start >= VG_(valgrind_base) && (start+size) <= VG_(valgrind_end)) {
2525 flags |= SF_VALGRIND;
2526 VG_(map_file_segment)(start, size, prot, flags, dev, ino, foffset, filename);
2527 }
sewardjde4a1d02002-03-22 01:27:54 +00002528}
2529
nethercote71980f02004-01-24 18:18:54 +00002530// Global var used to pass local data to callback
2531Addr esp_at_startup___global_arg = 0;
sewardjde4a1d02002-03-22 01:27:54 +00002532
nethercote71980f02004-01-24 18:18:54 +00002533static void build_segment_map_callback
2534 ( Addr start, UInt size, Char rr, Char ww, Char xx,
2535 UInt dev, UInt ino, ULong foffset, const UChar* filename )
sewardj45b672d2003-07-25 19:58:11 +00002536{
nethercote71980f02004-01-24 18:18:54 +00002537 UInt prot = 0;
2538 UInt flags;
2539 Bool is_stack_segment;
2540 Addr r_esp;
sewardj45b672d2003-07-25 19:58:11 +00002541
nethercote71980f02004-01-24 18:18:54 +00002542 is_stack_segment
2543 = (start == VG_(clstk_base) && (start+size) == VG_(clstk_end));
fitzhardinge98abfc72003-12-16 02:05:15 +00002544
nethercote71980f02004-01-24 18:18:54 +00002545 if (rr == 'r') prot |= VKI_PROT_READ;
2546 if (ww == 'w') prot |= VKI_PROT_WRITE;
2547 if (xx == 'x') prot |= VKI_PROT_EXEC;
fitzhardinge98abfc72003-12-16 02:05:15 +00002548
nethercote71980f02004-01-24 18:18:54 +00002549 if (is_stack_segment)
2550 flags = SF_STACK | SF_GROWDOWN;
2551 else
2552 flags = SF_EXEC|SF_MMAP;
fitzhardinge98abfc72003-12-16 02:05:15 +00002553
nethercote71980f02004-01-24 18:18:54 +00002554 if (filename != NULL)
2555 flags |= SF_FILE;
fitzhardinge98abfc72003-12-16 02:05:15 +00002556
nethercote71980f02004-01-24 18:18:54 +00002557 if (start >= VG_(valgrind_base) && (start+size) <= VG_(valgrind_end))
2558 flags |= SF_VALGRIND;
fitzhardinge98abfc72003-12-16 02:05:15 +00002559
nethercote71980f02004-01-24 18:18:54 +00002560 VG_(map_file_segment)(start, size, prot, flags, dev, ino, foffset, filename);
fitzhardinge98abfc72003-12-16 02:05:15 +00002561
nethercote71980f02004-01-24 18:18:54 +00002562 if (VG_(is_client_addr)(start) && VG_(is_client_addr)(start+size-1))
2563 VG_TRACK( new_mem_startup, start, size, rr=='r', ww=='w', xx=='x' );
sewardj3e1eb1f2002-05-18 13:14:17 +00002564
nethercote71980f02004-01-24 18:18:54 +00002565 /* If this is the stack segment mark all below %esp as noaccess. */
2566 r_esp = esp_at_startup___global_arg;
2567 vg_assert(0 != r_esp);
2568 if (is_stack_segment) {
2569 if (0)
2570 VG_(message)(Vg_DebugMsg, "invalidating stack area: %x .. %x",
2571 start,r_esp);
2572 VG_TRACK( die_mem_stack, start, r_esp-start );
sewardjde4a1d02002-03-22 01:27:54 +00002573 }
sewardjde4a1d02002-03-22 01:27:54 +00002574}
2575
2576
nethercote71980f02004-01-24 18:18:54 +00002577/*====================================================================*/
2578/*=== Sanity check machinery (permanently engaged) ===*/
2579/*====================================================================*/
njn25e49d8e72002-09-23 09:36:25 +00002580
2581/* A fast sanity check -- suitable for calling circa once per
2582 millisecond. */
2583
2584void VG_(do_sanity_checks) ( Bool force_expensive )
2585{
njn37cea302002-09-30 11:24:00 +00002586 VGP_PUSHCC(VgpCoreCheapSanity);
2587
nethercote27fec902004-06-16 21:26:32 +00002588 if (VG_(clo_sanity_level) < 1) return;
njn25e49d8e72002-09-23 09:36:25 +00002589
2590 /* --- First do all the tests that we can do quickly. ---*/
2591
2592 VG_(sanity_fast_count)++;
2593
njn25e49d8e72002-09-23 09:36:25 +00002594 /* Check stuff pertaining to the memory check system. */
2595
2596 /* Check that nobody has spuriously claimed that the first or
2597 last 16 pages of memory have become accessible [...] */
njn37cea302002-09-30 11:24:00 +00002598 if (VG_(needs).sanity_checks) {
2599 VGP_PUSHCC(VgpSkinCheapSanity);
njn25e49d8e72002-09-23 09:36:25 +00002600 vg_assert(SK_(cheap_sanity_check)());
njn37cea302002-09-30 11:24:00 +00002601 VGP_POPCC(VgpSkinCheapSanity);
2602 }
njn25e49d8e72002-09-23 09:36:25 +00002603
2604 /* --- Now some more expensive checks. ---*/
2605
2606 /* Once every 25 times, check some more expensive stuff. */
2607 if ( force_expensive
nethercote27fec902004-06-16 21:26:32 +00002608 || VG_(clo_sanity_level) > 1
2609 || (VG_(clo_sanity_level) == 1 && (VG_(sanity_fast_count) % 25) == 0)) {
njn25e49d8e72002-09-23 09:36:25 +00002610
njn37cea302002-09-30 11:24:00 +00002611 VGP_PUSHCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002612 VG_(sanity_slow_count)++;
2613
jsgf855d93d2003-10-13 22:26:55 +00002614 VG_(proxy_sanity)();
2615
njn25e49d8e72002-09-23 09:36:25 +00002616# if 0
2617 { void zzzmemscan(void); zzzmemscan(); }
2618# endif
2619
2620 if ((VG_(sanity_fast_count) % 250) == 0)
2621 VG_(sanity_check_tc_tt)();
2622
2623 if (VG_(needs).sanity_checks) {
njn37cea302002-09-30 11:24:00 +00002624 VGP_PUSHCC(VgpSkinExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002625 vg_assert(SK_(expensive_sanity_check)());
njn37cea302002-09-30 11:24:00 +00002626 VGP_POPCC(VgpSkinExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002627 }
2628 /*
2629 if ((VG_(sanity_fast_count) % 500) == 0) VG_(mallocSanityCheckAll)();
2630 */
njn37cea302002-09-30 11:24:00 +00002631 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002632 }
2633
nethercote27fec902004-06-16 21:26:32 +00002634 if (VG_(clo_sanity_level) > 1) {
njn37cea302002-09-30 11:24:00 +00002635 VGP_PUSHCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002636 /* Check sanity of the low-level memory manager. Note that bugs
2637 in the client's code can cause this to fail, so we don't do
2638 this check unless specially asked for. And because it's
2639 potentially very expensive. */
2640 VG_(mallocSanityCheckAll)();
njn37cea302002-09-30 11:24:00 +00002641 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002642 }
njn37cea302002-09-30 11:24:00 +00002643 VGP_POPCC(VgpCoreCheapSanity);
njn25e49d8e72002-09-23 09:36:25 +00002644}
nethercote71980f02004-01-24 18:18:54 +00002645
2646
2647/*====================================================================*/
2648/*=== main() ===*/
2649/*====================================================================*/
2650
nethercotec314eba2004-07-15 12:59:41 +00002651/*
2652 This code decides on the layout of the client and Valgrind address
2653 spaces, loads valgrind.so and the skin.so into the valgrind part,
2654 loads the client executable (and the dynamic linker, if necessary)
2655 into the client part, and calls into Valgrind proper.
2656
2657 The code is careful not to allow spurious mappings to appear in the
2658 wrong parts of the address space. In particular, to make sure
2659 dlopen puts things in the right place, it will pad out the forbidden
2660 chunks of address space so that dlopen is forced to put things where
2661 we want them.
2662
2663 The memory map it creates is:
2664
2665 CLIENT_BASE +-------------------------+
2666 | client address space |
2667 : :
2668 : :
2669 | client stack |
2670 client_end +-------------------------+
2671 | redzone |
2672 shadow_base +-------------------------+
2673 | |
2674 : shadow memory for skins :
2675 | (may be 0 sized) |
2676 shadow_end +-------------------------+
2677 : gap (may be 0 sized) :
2678 valgrind_base +-------------------------+
2679 | kickstart executable |
2680 | valgrind heap vvvvvvvvv| (barely used)
2681 - -
2682 | valgrind .so files |
2683 | and mappings |
2684 - -
2685 | valgrind stack ^^^^^^^^^|
2686 valgrind_end +-------------------------+
2687 : kernel :
2688
2689 Nb: Before we can do general allocations with VG_(arena_malloc)() and
2690 VG_(mmap)(), we need to build the segment skip-list, so we know where
2691 we can put things. However, building that structure requires
2692 allocating memory. So we need to a bootstrapping process. It's done
2693 by making VG_(arena_malloc)() have a special static superblock that's
2694 used for the first 1MB's worth of allocations. This is enough to
2695 build the segment skip-list.
2696*/
2697
thughes4ad52d02004-06-27 17:37:21 +00002698static int prmap(void *start, void *end, const char *perm, off_t off,
2699 int maj, int min, int ino) {
2700 printf("mapping %10p-%10p %s %02x:%02x %d\n",
2701 start, end, perm, maj, min, ino);
2702 return True;
2703}
2704
nethercote71980f02004-01-24 18:18:54 +00002705int main(int argc, char **argv)
2706{
2707 char **cl_argv;
2708 const char *tool = NULL;
2709 const char *exec = NULL;
2710 char *preload; /* tool-specific LD_PRELOAD .so */
2711 char **env;
nethercote6c999f22004-01-31 22:55:15 +00002712 Int need_help = 0; // 0 = no, 1 = --help, 2 = --help-debug
nethercote71980f02004-01-24 18:18:54 +00002713 struct exeinfo info;
2714 ToolInfo *toolinfo = NULL;
2715 void *tool_dlhandle;
2716 Addr client_eip;
2717 Addr esp_at_startup; /* client's %esp at the point we gained control. */
2718 UInt * client_auxv;
2719 VgSchedReturnCode src;
nethercote47dd12c2004-06-22 14:18:42 +00002720 Int exitcode = 0;
fitzhardingeb50068f2004-02-24 23:42:55 +00002721 vki_rlimit zero = { 0, 0 };
nethercote71980f02004-01-24 18:18:54 +00002722
2723 //============================================================
2724 // Nb: startup is complex. Prerequisites are shown at every step.
2725 //
2726 // *** Be very careful when messing with the order ***
2727 //============================================================
2728
nethercotef4928da2004-06-15 10:54:40 +00002729 //============================================================
2730 // Command line argument handling order:
2731 // * If --help/--help-debug are present, show usage message
2732 // (if --tool is also present, that includes the tool-specific usage)
2733 // * Then, if --tool is missing, abort with error msg
2734 // * Then, if client is missing, abort with error msg
2735 // * Then, if any cmdline args are bad, abort with error msg
2736 //============================================================
2737
fitzhardingeb50068f2004-02-24 23:42:55 +00002738 // Get the current process datasize rlimit, and set it to zero.
2739 // This prevents any internal uses of brk() from having any effect.
2740 // We remember the old value so we can restore it on exec, so that
2741 // child processes will have a reasonable brk value.
2742 VG_(getrlimit)(VKI_RLIMIT_DATA, &VG_(client_rlimit_data));
2743 zero.rlim_max = VG_(client_rlimit_data).rlim_max;
2744 VG_(setrlimit)(VKI_RLIMIT_DATA, &zero);
2745
nethercote71980f02004-01-24 18:18:54 +00002746 //--------------------------------------------------------------
2747 // Check we were launched by stage1
nethercotec314eba2004-07-15 12:59:41 +00002748 // p: n/a
nethercote71980f02004-01-24 18:18:54 +00002749 //--------------------------------------------------------------
2750 scan_auxv();
2751
2752 if (0) {
nethercote71980f02004-01-24 18:18:54 +00002753 printf("========== main() ==========\n");
2754 foreach_map(prmap);
2755 }
2756
2757 //--------------------------------------------------------------
2758 // Look for alternative libdir
2759 // p: n/a
2760 //--------------------------------------------------------------
2761 { char *cp = getenv(VALGRINDLIB);
2762 if (cp != NULL)
2763 VG_(libdir) = cp;
2764 }
2765
2766 //--------------------------------------------------------------
2767 // Begin working out address space layout
2768 // p: n/a
2769 //--------------------------------------------------------------
2770 layout_client_space( (Addr) & argc );
2771
2772 //--------------------------------------------------------------
2773 // Get valgrind args + client args (inc. from VALGRIND_OPTS/.valgrindrc).
2774 // Pre-process the command line.
2775 // p: n/a
2776 //--------------------------------------------------------------
2777 get_command_line(argc, argv, &VG_(vg_argc), &VG_(vg_argv), &cl_argv);
2778 pre_process_cmd_line_options(&need_help, &tool, &exec);
2779
2780 //==============================================================
2781 // Nb: once a tool is specified, the tool.so must be loaded even if
2782 // they specified --help or didn't specify a client program.
2783 //==============================================================
2784
2785 //--------------------------------------------------------------
2786 // With client padded out, map in tool
2787 // p: layout_client_space() [for padding]
2788 // p: set-libdir [for VG_(libdir)]
2789 // p: pre_process_cmd_line_options() [for 'tool']
2790 //--------------------------------------------------------------
2791 load_tool(tool, &tool_dlhandle, &toolinfo, &preload);
2792
2793 //==============================================================
2794 // Can use VG_(malloc)() and VG_(arena_malloc)() only after load_tool()
nethercotec314eba2004-07-15 12:59:41 +00002795 // -- redzone size is now set. This is checked by vg_malloc2.c.
nethercote71980f02004-01-24 18:18:54 +00002796 //==============================================================
2797
2798 //--------------------------------------------------------------
2799 // Finalise address space layout
nethercotec314eba2004-07-15 12:59:41 +00002800 // p: layout_client_space(), load_tool() [for 'toolinfo']
nethercote71980f02004-01-24 18:18:54 +00002801 //--------------------------------------------------------------
2802 layout_remaining_space( toolinfo->shadow_ratio );
2803
2804 //--------------------------------------------------------------
2805 // Load client executable, finding in $PATH if necessary
2806 // p: layout_client_space() [so there's space]
2807 // p: pre_process_cmd_line_options() [for 'exec', 'need_help']
2808 // p: layout_remaining_space [so there's space]
2809 //--------------------------------------------------------------
nethercotef4928da2004-06-15 10:54:40 +00002810 load_client(cl_argv, exec, need_help, &info, &client_eip);
nethercote71980f02004-01-24 18:18:54 +00002811
2812 //--------------------------------------------------------------
2813 // Everything in place, unpad us
2814 // p: layout_remaining_space() [everything must be mapped in before now]
2815 // p: load_client() [ditto]
2816 //--------------------------------------------------------------
2817 as_unpad((void *)VG_(shadow_end), (void *)~0);
2818 as_closepadfile(); /* no more padding */
2819
2820 //--------------------------------------------------------------
2821 // Set up client's environment
2822 // p: set-libdir [for VG_(libdir)]
2823 // p: load_tool() [for 'preload']
2824 //--------------------------------------------------------------
2825 env = fix_environment(environ, preload);
2826
2827 //--------------------------------------------------------------
nethercote5ee67ca2004-06-22 14:00:09 +00002828 // Setup client stack, eip, and VG_(client_arg[cv])
nethercote71980f02004-01-24 18:18:54 +00002829 // p: load_client() [for 'info']
2830 // p: fix_environment() [for 'env']
2831 //--------------------------------------------------------------
2832 esp_at_startup = setup_client_stack(cl_argv, env, &info, &client_auxv);
2833
2834 if (0)
2835 printf("entry=%x client esp=%x vg_argc=%d brkbase=%x\n",
2836 client_eip, esp_at_startup, VG_(vg_argc), VG_(brk_base));
2837
2838 //==============================================================
2839 // Finished setting up operating environment. Now initialise
2840 // Valgrind. (This is where the old VG_(main)() started.)
2841 //==============================================================
2842
2843 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002844 // atfork
2845 // p: n/a
2846 //--------------------------------------------------------------
2847 VG_(atfork)(NULL, NULL, newpid);
2848 newpid(VG_INVALID_THREADID);
2849
2850 //--------------------------------------------------------------
2851 // setup file descriptors
2852 // p: n/a
2853 //--------------------------------------------------------------
2854 setup_file_descriptors();
2855
2856 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002857 // Read /proc/self/maps into a buffer
2858 // p: all memory layout, environment setup [so memory maps are right]
2859 //--------------------------------------------------------------
2860 VG_(read_procselfmaps)();
2861
2862 //--------------------------------------------------------------
2863 // Build segment map (Valgrind segments only)
2864 // p: read proc/self/maps
2865 // p: sk_pre_clo_init() [to setup new_mem_startup tracker]
2866 //--------------------------------------------------------------
2867 VG_(parse_procselfmaps) ( build_valgrind_map_callback );
2868
2869 //==============================================================
2870 // Can use VG_(arena_malloc)() with non-CORE arena after segments set up
2871 //==============================================================
2872
2873 //--------------------------------------------------------------
2874 // Init tool: pre_clo_init, process cmd line, post_clo_init
2875 // p: setup_client_stack() [for 'VG_(client_arg[cv]']
2876 // p: load_tool() [for 'tool']
2877 // p: setup_file_descriptors() [for 'VG_(fd_xxx_limit)']
2878 // p: parse_procselfmaps [so VG segments are setup so tool can
2879 // call VG_(malloc)]
nethercote71980f02004-01-24 18:18:54 +00002880 //--------------------------------------------------------------
2881 (*toolinfo->sk_pre_clo_init)();
2882 VG_(tool_init_dlsym)(tool_dlhandle);
2883 VG_(sanity_check_needs)();
2884
nethercotef4928da2004-06-15 10:54:40 +00002885 // If --tool and --help/--help-debug was given, now give the core+tool
2886 // help message
nethercotef4928da2004-06-15 10:54:40 +00002887 if (need_help) {
2888 usage(/*--help-debug?*/2 == need_help);
2889 }
nethercotec314eba2004-07-15 12:59:41 +00002890 process_cmd_line_options(client_auxv, tool);
2891
2892 SK_(post_clo_init)();
nethercotef4928da2004-06-15 10:54:40 +00002893
2894 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002895 // Build segment map (all segments)
2896 // p: setup_client_stack() [for 'esp_at_startup']
2897 // p: init tool [for 'new_mem_startup']
nethercote71980f02004-01-24 18:18:54 +00002898 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002899 esp_at_startup___global_arg = esp_at_startup;
2900 VG_(parse_procselfmaps) ( build_segment_map_callback ); /* everything */
2901 esp_at_startup___global_arg = 0;
2902
2903 //--------------------------------------------------------------
nethercotef84f6952004-07-15 14:58:33 +00002904 // Protect client trampoline page (which is also sysinfo stuff)
2905 // p: segment stuff [otherwise get seg faults...]
nethercotec314eba2004-07-15 12:59:41 +00002906 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002907 VG_(mprotect)( (void *)VG_(client_trampoline_code),
2908 VG_(trampoline_code_length), VKI_PROT_READ|VKI_PROT_EXEC );
2909
2910 //==============================================================
2911 // Can use VG_(map)() after segments set up
2912 //==============================================================
nethercote71980f02004-01-24 18:18:54 +00002913
2914 //--------------------------------------------------------------
2915 // Allow GDB attach
2916 // p: process_cmd_line_options() [for VG_(clo_wait_for_gdb)]
2917 //--------------------------------------------------------------
2918 /* Hook to delay things long enough so we can get the pid and
2919 attach GDB in another shell. */
2920 if (VG_(clo_wait_for_gdb)) {
2921 VG_(printf)("pid=%d\n", VG_(getpid)());
2922 /* do "jump *$eip" to skip this in gdb */
2923 VG_(do_syscall)(__NR_pause);
2924 }
2925
2926 //--------------------------------------------------------------
nethercote1d447092004-02-01 17:29:59 +00002927 // Set up baseBlock
nethercote71980f02004-01-24 18:18:54 +00002928 // p: {pre,post}_clo_init() [for tool helper registration]
2929 // load_client() [for 'client_eip']
2930 // setup_client_stack() [for 'esp_at_startup']
2931 //--------------------------------------------------------------
2932 init_baseBlock(client_eip, esp_at_startup);
2933
2934 //--------------------------------------------------------------
2935 // Search for file descriptors that are inherited from our parent
2936 // p: process_cmd_line_options [for VG_(clo_track_fds)]
2937 //--------------------------------------------------------------
2938 if (VG_(clo_track_fds))
2939 VG_(init_preopened_fds)();
2940
2941 //--------------------------------------------------------------
2942 // Initialise the scheduler
2943 // p: init_baseBlock() [baseBlock regs copied into VG_(threads)[1]]
2944 // p: setup_file_descriptors() [else VG_(safe_fd)() breaks]
2945 //--------------------------------------------------------------
2946 VG_(scheduler_init)();
2947
2948 //--------------------------------------------------------------
2949 // Set up the ProxyLWP machinery
2950 // p: VG_(scheduler_init)()? [XXX: subtle dependency?]
2951 // - subs: VG_(sigstartup_actions)()?
2952 //--------------------------------------------------------------
2953 VG_(proxy_init)();
2954
2955 //--------------------------------------------------------------
2956 // Initialise the signal handling subsystem
2957 // p: VG_(atfork)(NULL, NULL, newpid) [else problems with sigmasks]
2958 // p: VG_(proxy_init)() [else breaks...]
2959 //--------------------------------------------------------------
2960 // Nb: temporarily parks the saved blocking-mask in saved_sigmask.
2961 VG_(sigstartup_actions)();
2962
2963 //--------------------------------------------------------------
2964 // Perhaps we're profiling Valgrind?
2965 // p: process_cmd_line_options() [for VG_(clo_profile)]
2966 // p: others?
2967 //
2968 // XXX: this seems to be broken? It always says the tool wasn't built
2969 // for profiling; vg_profile.c's functions don't seem to be overriding
2970 // vg_dummy_profile.c's?
2971 //
2972 // XXX: want this as early as possible. Looking for --profile
2973 // in pre_process_cmd_line_options() could get it earlier.
2974 //--------------------------------------------------------------
2975 if (VG_(clo_profile))
2976 VGP_(init_profiling)();
2977
2978 VGP_PUSHCC(VgpStartup);
2979
2980 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002981 // Read suppression file
2982 // p: process_cmd_line_options() [for VG_(clo_suppressions)]
2983 //--------------------------------------------------------------
2984 if (VG_(needs).core_errors || VG_(needs).skin_errors)
2985 VG_(load_suppressions)();
2986
2987 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002988 // Initialise translation table and translation cache
2989 // p: read_procselfmaps [so the anonymous mmaps for the TT/TC
2990 // aren't identified as part of the client, which would waste
2991 // > 20M of virtual address space.]
2992 //--------------------------------------------------------------
2993 VG_(init_tt_tc)();
2994
2995 //--------------------------------------------------------------
2996 // Read debug info to find glibc entry points to intercept
2997 // p: parse_procselfmaps? [XXX for debug info?]
2998 // p: init_tt_tc? [XXX ???]
2999 //--------------------------------------------------------------
3000 VG_(setup_code_redirect_table)();
3001
3002 //--------------------------------------------------------------
3003 // Verbosity message
3004 // p: end_rdtsc_calibration [so startup message is printed first]
3005 //--------------------------------------------------------------
3006 if (VG_(clo_verbosity) == 1)
3007 VG_(message)(Vg_UserMsg, "For more details, rerun with: -v");
3008 if (VG_(clo_verbosity) > 0)
3009 VG_(message)(Vg_UserMsg, "");
3010
3011 //--------------------------------------------------------------
3012 // Setup pointercheck
3013 // p: process_cmd_line_options() [for VG_(clo_pointercheck)]
3014 //--------------------------------------------------------------
3015 setup_pointercheck();
3016
nethercote71980f02004-01-24 18:18:54 +00003017 //--------------------------------------------------------------
3018 // Run!
3019 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00003020 VGP_POPCC(VgpStartup);
3021 VGP_PUSHCC(VgpSched);
3022
3023 if (__builtin_setjmp(&VG_(fatal_signal_jmpbuf)) == 0) {
3024 VG_(fatal_signal_set) = True;
nethercote47dd12c2004-06-22 14:18:42 +00003025 src = VG_(scheduler)( &exitcode );
nethercote71980f02004-01-24 18:18:54 +00003026 } else
3027 src = VgSrc_FatalSig;
3028
3029 VGP_POPCC(VgpSched);
nethercote71980f02004-01-24 18:18:54 +00003030
3031
3032
3033 //--------------------------------------------------------------
3034 // Finalisation: cleanup, messages, etc. Order no so important, only
3035 // affects what order the messages come.
3036 //--------------------------------------------------------------
3037 if (VG_(clo_verbosity) > 0)
3038 VG_(message)(Vg_UserMsg, "");
3039
3040 if (src == VgSrc_Deadlock) {
3041 VG_(message)(Vg_UserMsg,
3042 "Warning: pthread scheduler exited due to deadlock");
3043 }
3044
3045 /* Print out file descriptor summary and stats. */
3046 if (VG_(clo_track_fds))
3047 VG_(fd_stats)();
3048
3049 if (VG_(needs).core_errors || VG_(needs).skin_errors)
3050 VG_(show_all_errors)();
3051
nethercote47dd12c2004-06-22 14:18:42 +00003052 SK_(fini)( exitcode );
nethercote71980f02004-01-24 18:18:54 +00003053
3054 VG_(do_sanity_checks)( True /*include expensive checks*/ );
3055
3056 if (VG_(clo_verbosity) > 1)
3057 show_counts();
3058
3059 if (VG_(clo_verbosity) > 3)
3060 VG_(print_UInstr_histogram)();
3061
3062 if (0) {
3063 VG_(message)(Vg_DebugMsg, "");
3064 VG_(message)(Vg_DebugMsg,
3065 "------ Valgrind's internal memory use stats follow ------" );
3066 VG_(mallocSanityCheckAll)();
3067 VG_(show_all_arena_stats)();
3068 VG_(message)(Vg_DebugMsg,
3069 "------ Valgrind's ExeContext management stats follow ------" );
3070 VG_(show_ExeContext_stats)();
3071 }
3072
3073 if (VG_(clo_profile))
3074 VGP_(done_profiling)();
3075
nethercote71980f02004-01-24 18:18:54 +00003076 /* We're exiting, so nuke all the threads and clean up the proxy LWPs */
3077 vg_assert(src == VgSrc_FatalSig ||
3078 VG_(threads)[VG_(last_run_tid)].status == VgTs_Runnable ||
3079 VG_(threads)[VG_(last_run_tid)].status == VgTs_WaitJoiner);
3080 VG_(nuke_all_threads_except)(VG_INVALID_THREADID);
3081
3082 //--------------------------------------------------------------
3083 // Exit, according to the scheduler's return code
3084 //--------------------------------------------------------------
3085 switch (src) {
3086 case VgSrc_ExitSyscall: /* the normal way out */
3087 vg_assert(VG_(last_run_tid) > 0
3088 && VG_(last_run_tid) < VG_N_THREADS);
3089 VG_(proxy_shutdown)();
3090
3091 /* The thread's %EBX at the time it did __NR_exit() will hold
3092 the arg to __NR_exit(), so we just do __NR_exit() with
3093 that arg. */
nethercote47dd12c2004-06-22 14:18:42 +00003094 VG_(exit)( exitcode );
nethercote71980f02004-01-24 18:18:54 +00003095 /* NOT ALIVE HERE! */
3096 VG_(core_panic)("entered the afterlife in main() -- ExitSyscall");
3097 break; /* what the hell :) */
3098
3099 case VgSrc_Deadlock:
3100 /* Just exit now. No point in continuing. */
3101 VG_(proxy_shutdown)();
3102 VG_(exit)(0);
3103 VG_(core_panic)("entered the afterlife in main() -- Deadlock");
3104 break;
3105
nethercote71980f02004-01-24 18:18:54 +00003106 case VgSrc_FatalSig:
3107 /* We were killed by a fatal signal, so replicate the effect */
3108 vg_assert(VG_(fatal_sigNo) != -1);
3109 VG_(kill_self)(VG_(fatal_sigNo));
3110 VG_(core_panic)("main(): signal was supposed to be fatal");
3111 break;
3112
3113 default:
3114 VG_(core_panic)("main(): unexpected scheduler return code");
3115 }
3116
3117 abort();
3118}
3119
3120
sewardjde4a1d02002-03-22 01:27:54 +00003121/*--------------------------------------------------------------------*/
3122/*--- end vg_main.c ---*/
3123/*--------------------------------------------------------------------*/