blob: 41897a44c5d9d14905d14b9dce444f597122ca09 [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
nethercote996901a2004-08-03 13:29:09 +0000107Addr VG_(shadow_base); /* tool's shadow memory */
fitzhardinge98abfc72003-12-16 02:05:15 +0000108Addr VG_(shadow_end);
nethercote71980f02004-01-24 18:18:54 +0000109
110Addr VG_(valgrind_base); /* valgrind's address range */
fitzhardinge98abfc72003-12-16 02:05:15 +0000111Addr VG_(valgrind_end);
112
fitzhardingeb50068f2004-02-24 23:42:55 +0000113vki_rlimit VG_(client_rlimit_data);
114
nethercote71980f02004-01-24 18:18:54 +0000115/* This is set early to indicate whether this CPU has the
116 SSE/fxsave/fxrestor features. */
117Bool VG_(have_ssestate);
118
fitzhardinge98abfc72003-12-16 02:05:15 +0000119/* stage1 (main) executable */
fitzhardingea49f9b52003-12-16 22:26:45 +0000120Int VG_(vgexecfd) = -1;
121
122/* client executable */
123Int VG_(clexecfd) = -1;
fitzhardinge98abfc72003-12-16 02:05:15 +0000124
125/* Path to library directory */
126const Char *VG_(libdir) = VG_LIBDIR;
127
128/* our argc/argv */
129Int VG_(vg_argc);
130Char **VG_(vg_argv);
131
jsgf855d93d2003-10-13 22:26:55 +0000132/* PID of the main thread */
133Int VG_(main_pid);
134
135/* PGRP of process */
136Int VG_(main_pgrp);
njn25e49d8e72002-09-23 09:36:25 +0000137
thughesad1c9562004-06-26 11:27:52 +0000138/* Application-visible file descriptor limits */
139Int VG_(fd_soft_limit) = -1;
140Int VG_(fd_hard_limit) = -1;
fitzhardingef0046f22003-12-18 02:39:22 +0000141
nethercote71980f02004-01-24 18:18:54 +0000142/* As deduced from esp_at_startup, the client's argc, argv[] and
143 envp[] as extracted from the client's stack at startup-time. */
144Int VG_(client_argc);
145Char** VG_(client_argv);
146Char** VG_(client_envp);
sewardjde4a1d02002-03-22 01:27:54 +0000147
148/* ---------------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +0000149 Running stuff
sewardjde4a1d02002-03-22 01:27:54 +0000150 ------------------------------------------------------------------ */
nethercote71980f02004-01-24 18:18:54 +0000151/* Our signal delivery stack. */
njn6eba4ef2003-05-01 08:06:41 +0000152UInt VG_(sigstack)[VG_SIGSTACK_SIZE_W];
sewardjde4a1d02002-03-22 01:27:54 +0000153
nethercote31294822004-08-02 13:15:26 +0000154/* jmp_buf for fatal signals; VG_(fatal_signal_jmpbuf_ptr) is NULL until
155 the time is right that it can be used. */
nethercote92e7b7f2004-08-07 17:52:25 +0000156 Int VG_(fatal_sigNo) = -1;
157 jmp_buf* VG_(fatal_signal_jmpbuf_ptr) = NULL;
158static jmp_buf fatal_signal_jmpbuf;
sewardjde4a1d02002-03-22 01:27:54 +0000159
nethercote71980f02004-01-24 18:18:54 +0000160/* Counts downwards in VG_(run_innerloop). */
161UInt VG_(dispatch_ctr);
sewardjde4a1d02002-03-22 01:27:54 +0000162
163/* 64-bit counter for the number of basic blocks done. */
164ULong VG_(bbs_done);
sewardjde4a1d02002-03-22 01:27:54 +0000165
sewardj7e87e382002-05-03 19:09:05 +0000166/* This is the ThreadId of the last thread the scheduler ran. */
167ThreadId VG_(last_run_tid) = 0;
168
nethercote71980f02004-01-24 18:18:54 +0000169/* Tell the logging mechanism whether we are logging to a file
170 descriptor or a socket descriptor. */
171Bool VG_(logging_to_filedes) = True;
172
sewardj73cf3bc2002-11-03 03:20:15 +0000173
nethercote71980f02004-01-24 18:18:54 +0000174/*====================================================================*/
175/*=== Counters, for profiling purposes only ===*/
176/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +0000177
nethercote92e7b7f2004-08-07 17:52:25 +0000178// These ones maintained by vg_dispatch.S
179UInt VG_(bb_enchain_count) = 0; // Number of chain operations done
180UInt VG_(bb_dechain_count) = 0; // Number of unchain operations done
181UInt VG_(unchained_jumps_done) = 0; // Number of unchained jumps done
sewardjde4a1d02002-03-22 01:27:54 +0000182
sewardjde4a1d02002-03-22 01:27:54 +0000183/* Counts pertaining to internal sanity checking. */
nethercote297effd2004-08-02 15:07:57 +0000184static UInt sanity_fast_count = 0;
185static UInt sanity_slow_count = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000186
nethercote3a42fb82004-08-03 18:08:50 +0000187static void print_all_stats ( void )
nethercote71980f02004-01-24 18:18:54 +0000188{
nethercote3a42fb82004-08-03 18:08:50 +0000189 // Translation stats
nethercote92e7b7f2004-08-07 17:52:25 +0000190 VG_(print_tt_tc_stats)();
nethercote71980f02004-01-24 18:18:54 +0000191 VG_(message)(Vg_DebugMsg,
nethercote92e7b7f2004-08-07 17:52:25 +0000192 "chainings: %d chainings, %d unchainings.",
nethercote71980f02004-01-24 18:18:54 +0000193 VG_(bb_enchain_count), VG_(bb_dechain_count) );
194 VG_(message)(Vg_DebugMsg,
nethercote3a42fb82004-08-03 18:08:50 +0000195 " dispatch: %llu jumps (bb entries); of them %u (%lu%%) unchained.",
nethercote71980f02004-01-24 18:18:54 +0000196 VG_(bbs_done),
197 VG_(unchained_jumps_done),
198 ((ULong)(100) * (ULong)(VG_(unchained_jumps_done)))
199 / ( VG_(bbs_done)==0 ? 1 : VG_(bbs_done) )
200 );
201
nethercote3a42fb82004-08-03 18:08:50 +0000202 // Scheduler stats
nethercote844e7122004-08-02 15:27:22 +0000203 VG_(print_scheduler_stats)();
nethercote71980f02004-01-24 18:18:54 +0000204
nethercote3a42fb82004-08-03 18:08:50 +0000205 // Reg-alloc stats
nethercotebee3fd92004-08-02 15:17:43 +0000206 VG_(print_reg_alloc_stats)();
nethercote71980f02004-01-24 18:18:54 +0000207 VG_(message)(Vg_DebugMsg,
208 " sanity: %d cheap, %d expensive checks.",
nethercote297effd2004-08-02 15:07:57 +0000209 sanity_fast_count, sanity_slow_count );
nethercote3a42fb82004-08-03 18:08:50 +0000210
211 // C call stats
nethercote71980f02004-01-24 18:18:54 +0000212 VG_(print_ccall_stats)();
nethercote3a42fb82004-08-03 18:08:50 +0000213
214 // UInstr histogram
215 if (VG_(clo_verbosity) > 3)
216 VG_(print_UInstr_histogram)();
217
218 // Memory stats
nethercote885dd912004-08-03 23:14:00 +0000219 if (VG_(clo_verbosity) > 2) {
nethercote3a42fb82004-08-03 18:08:50 +0000220 VG_(message)(Vg_DebugMsg, "");
221 VG_(message)(Vg_DebugMsg,
222 "------ Valgrind's internal memory use stats follow ------" );
nethercote885dd912004-08-03 23:14:00 +0000223 VG_(sanity_check_malloc_all)();
nethercote3a42fb82004-08-03 18:08:50 +0000224 VG_(print_all_arena_stats)();
nethercote885dd912004-08-03 23:14:00 +0000225 VG_(message)(Vg_DebugMsg, "");
nethercote3a42fb82004-08-03 18:08:50 +0000226 VG_(message)(Vg_DebugMsg,
227 "------ Valgrind's ExeContext management stats follow ------" );
228 VG_(print_ExeContext_stats)();
229 }
nethercote71980f02004-01-24 18:18:54 +0000230}
231
232
233/*====================================================================*/
234/*=== Miscellaneous global functions ===*/
235/*====================================================================*/
236
nethercote04d0fbc2004-01-26 16:48:06 +0000237/* Start debugger and get it to attach to this process. Called if the
238 user requests this service after an error has been shown, so she can
nethercote71980f02004-01-24 18:18:54 +0000239 poke around and look at parameters, memory, etc. You can't
nethercote04d0fbc2004-01-26 16:48:06 +0000240 meaningfully get the debugger to continue the program, though; to
241 continue, quit the debugger. */
242void VG_(start_debugger) ( Int tid )
nethercote71980f02004-01-24 18:18:54 +0000243{
244 Int pid;
245
246 if ((pid = fork()) == 0) {
247 ptrace(PTRACE_TRACEME, 0, NULL, NULL);
248 VG_(kkill)(VG_(getpid)(), VKI_SIGSTOP);
249
250 } else if (pid > 0) {
251 struct user_regs_struct regs;
252 Int status;
253 Int res;
254
255 if (VG_(is_running_thread)( tid )) {
fitzhardinged65dcad2004-03-13 02:06:58 +0000256 regs.cs = VG_(baseBlock)[VGOFF_(m_cs)];
257 regs.ss = VG_(baseBlock)[VGOFF_(m_ss)];
258 regs.ds = VG_(baseBlock)[VGOFF_(m_ds)];
259 regs.es = VG_(baseBlock)[VGOFF_(m_es)];
260 regs.fs = VG_(baseBlock)[VGOFF_(m_fs)];
261 regs.gs = VG_(baseBlock)[VGOFF_(m_gs)];
nethercote71980f02004-01-24 18:18:54 +0000262 regs.eax = VG_(baseBlock)[VGOFF_(m_eax)];
263 regs.ebx = VG_(baseBlock)[VGOFF_(m_ebx)];
264 regs.ecx = VG_(baseBlock)[VGOFF_(m_ecx)];
265 regs.edx = VG_(baseBlock)[VGOFF_(m_edx)];
266 regs.esi = VG_(baseBlock)[VGOFF_(m_esi)];
267 regs.edi = VG_(baseBlock)[VGOFF_(m_edi)];
268 regs.ebp = VG_(baseBlock)[VGOFF_(m_ebp)];
269 regs.esp = VG_(baseBlock)[VGOFF_(m_esp)];
270 regs.eflags = VG_(baseBlock)[VGOFF_(m_eflags)];
271 regs.eip = VG_(baseBlock)[VGOFF_(m_eip)];
272 } else {
273 ThreadState* tst = & VG_(threads)[ tid ];
274
fitzhardinged65dcad2004-03-13 02:06:58 +0000275 regs.cs = tst->m_cs;
276 regs.ss = tst->m_ss;
277 regs.ds = tst->m_ds;
278 regs.es = tst->m_es;
279 regs.fs = tst->m_fs;
280 regs.gs = tst->m_gs;
nethercote71980f02004-01-24 18:18:54 +0000281 regs.eax = tst->m_eax;
282 regs.ebx = tst->m_ebx;
283 regs.ecx = tst->m_ecx;
284 regs.edx = tst->m_edx;
285 regs.esi = tst->m_esi;
286 regs.edi = tst->m_edi;
287 regs.ebp = tst->m_ebp;
288 regs.esp = tst->m_esp;
289 regs.eflags = tst->m_eflags;
290 regs.eip = tst->m_eip;
291 }
292
293 if ((res = VG_(waitpid)(pid, &status, 0)) == pid &&
294 WIFSTOPPED(status) && WSTOPSIG(status) == SIGSTOP &&
295 ptrace(PTRACE_SETREGS, pid, NULL, &regs) == 0 &&
thughes1d160052004-04-21 15:39:57 +0000296 kill(pid, SIGSTOP) == 0 &&
297 ptrace(PTRACE_DETACH, pid, NULL, 0) == 0) {
nethercote04d0fbc2004-01-26 16:48:06 +0000298 Char pidbuf[15];
299 Char file[30];
300 Char buf[100];
301 Char *bufptr;
302 Char *cmdptr;
303
304 VG_(sprintf)(pidbuf, "%d", pid);
305 VG_(sprintf)(file, "/proc/%d/fd/%d", pid, VG_(clexecfd));
306
307 bufptr = buf;
308 cmdptr = VG_(clo_db_command);
309
310 while (*cmdptr) {
311 switch (*cmdptr) {
312 case '%':
313 switch (*++cmdptr) {
314 case 'f':
315 VG_(memcpy)(bufptr, file, VG_(strlen)(file));
316 bufptr += VG_(strlen)(file);
317 cmdptr++;
318 break;
319 case 'p':
320 VG_(memcpy)(bufptr, pidbuf, VG_(strlen)(pidbuf));
321 bufptr += VG_(strlen)(pidbuf);
322 cmdptr++;
323 break;
324 default:
325 *bufptr++ = *cmdptr++;
326 break;
327 }
328 break;
329 default:
330 *bufptr++ = *cmdptr++;
331 break;
332 }
333 }
334
335 *bufptr++ = '\0';
336
337 VG_(message)(Vg_UserMsg, "starting debugger with cmd: %s", buf);
nethercote71980f02004-01-24 18:18:54 +0000338 res = VG_(system)(buf);
339 if (res == 0) {
340 VG_(message)(Vg_UserMsg, "");
341 VG_(message)(Vg_UserMsg,
nethercote04d0fbc2004-01-26 16:48:06 +0000342 "Debugger has detached. Valgrind regains control. We continue.");
nethercote71980f02004-01-24 18:18:54 +0000343 } else {
344 VG_(message)(Vg_UserMsg, "Apparently failed!");
345 VG_(message)(Vg_UserMsg, "");
346 }
347 }
348
349 VG_(kkill)(pid, VKI_SIGKILL);
350 VG_(waitpid)(pid, &status, 0);
351 }
352}
353
354
355/* Print some helpful-ish text about unimplemented things, and give
356 up. */
357void VG_(unimplemented) ( Char* msg )
358{
359 VG_(message)(Vg_UserMsg, "");
360 VG_(message)(Vg_UserMsg,
361 "Valgrind detected that your program requires");
362 VG_(message)(Vg_UserMsg,
363 "the following unimplemented functionality:");
364 VG_(message)(Vg_UserMsg, " %s", msg);
365 VG_(message)(Vg_UserMsg,
366 "This may be because the functionality is hard to implement,");
367 VG_(message)(Vg_UserMsg,
368 "or because no reasonable program would behave this way,");
369 VG_(message)(Vg_UserMsg,
370 "or because nobody has yet needed it. In any case, let us know at");
371 VG_(message)(Vg_UserMsg,
372 "%s and/or try to work around the problem, if you can.", VG_BUGS_TO);
373 VG_(message)(Vg_UserMsg,
374 "");
375 VG_(message)(Vg_UserMsg,
376 "Valgrind has to exit now. Sorry. Bye!");
377 VG_(message)(Vg_UserMsg,
378 "");
379 VG_(pp_sched_status)();
380 VG_(exit)(1);
381}
382
383Addr VG_(get_stack_pointer) ( void )
384{
385 return VG_(baseBlock)[VGOFF_(m_esp)];
386}
387
388/* Debugging thing .. can be called from assembly with OYNK macro. */
389void VG_(oynk) ( Int n )
390{
391 OINK(n);
392}
393
394/* Initialize the PID and PGRP of scheduler LWP; this is also called
395 in any new children after fork. */
396static void newpid(ThreadId unused)
397{
398 /* PID of scheduler LWP */
399 VG_(main_pid) = VG_(getpid)();
400 VG_(main_pgrp) = VG_(getpgrp)();
401}
402
403/*====================================================================*/
404/*=== Check we were launched by stage 1 ===*/
405/*====================================================================*/
406
407/* Look for our AUXV table */
nethercote31779c72004-07-30 21:50:15 +0000408int scan_auxv(void)
nethercote71980f02004-01-24 18:18:54 +0000409{
410 const struct ume_auxv *auxv = find_auxv((int *)ume_exec_esp);
nethercote31779c72004-07-30 21:50:15 +0000411 int padfile = -1, found = 0;
nethercote71980f02004-01-24 18:18:54 +0000412
413 for (; auxv->a_type != AT_NULL; auxv++)
414 switch(auxv->a_type) {
415 case AT_UME_PADFD:
nethercote31779c72004-07-30 21:50:15 +0000416 padfile = auxv->u.a_val;
nethercote71980f02004-01-24 18:18:54 +0000417 found |= 1;
418 break;
419
420 case AT_UME_EXECFD:
421 VG_(vgexecfd) = auxv->u.a_val;
422 found |= 2;
423 break;
424 }
425
nethercote361a14e2004-07-26 11:11:56 +0000426 if ( found != (1|2) ) {
427 fprintf(stderr, "valgrind: stage2 must be launched by stage1\n");
nethercote71980f02004-01-24 18:18:54 +0000428 exit(127);
429 }
nethercote31779c72004-07-30 21:50:15 +0000430 vg_assert(padfile >= 0);
431 return padfile;
nethercote71980f02004-01-24 18:18:54 +0000432}
433
434
435/*====================================================================*/
436/*=== Address space determination ===*/
437/*====================================================================*/
438
nethercote31779c72004-07-30 21:50:15 +0000439static void layout_remaining_space(Addr argc_addr, float ratio)
nethercote71980f02004-01-24 18:18:54 +0000440{
nethercote31779c72004-07-30 21:50:15 +0000441 Int ires;
442 void* vres;
443 addr_t client_size, shadow_size;
nethercote71980f02004-01-24 18:18:54 +0000444
nethercote31779c72004-07-30 21:50:15 +0000445 VG_(valgrind_base) = (addr_t)&kickstart_base;
446 VG_(valgrind_end) = ROUNDUP(argc_addr, 0x10000); // stack
nethercote71980f02004-01-24 18:18:54 +0000447
nethercote31779c72004-07-30 21:50:15 +0000448 // This gives the client the largest possible address space while
449 // taking into account the tool's shadow needs.
450 client_size = ROUNDDN((VG_(valgrind_base)-REDZONE_SIZE) / (1.+ratio),
nethercote71980f02004-01-24 18:18:54 +0000451 CLIENT_SIZE_MULTIPLE);
nethercote31779c72004-07-30 21:50:15 +0000452 VG_(client_base) = CLIENT_BASE;
nethercote71980f02004-01-24 18:18:54 +0000453 VG_(client_end) = VG_(client_base) + client_size;
nethercotee2097312004-06-27 12:29:56 +0000454 /* where !FIXED mmap goes */
nethercotebc7b4f42004-07-26 12:44:35 +0000455 VG_(client_mapbase) = VG_(client_base) +
456 PGROUNDDN((addr_t)(client_size * CLIENT_HEAP_PROPORTION));
nethercote71980f02004-01-24 18:18:54 +0000457
nethercote31779c72004-07-30 21:50:15 +0000458 shadow_size = PGROUNDUP(client_size * ratio);
459 VG_(shadow_base) = VG_(client_end) + REDZONE_SIZE;
460 VG_(shadow_end) = VG_(shadow_base) + shadow_size;
nethercote71980f02004-01-24 18:18:54 +0000461
nethercotee2097312004-06-27 12:29:56 +0000462#define SEGSIZE(a,b) ((VG_(b) - VG_(a))/(1024*1024))
463
nethercote71980f02004-01-24 18:18:54 +0000464 if (0)
nethercotee2097312004-06-27 12:29:56 +0000465 VG_(printf)(
466 "client_base %8x (%dMB)\n"
467 "client_mapbase %8x (%dMB)\n"
468 "client_end %8x (%dMB)\n"
469 "shadow_base %8x (%dMB)\n"
470 "shadow_end %8x (%dMB)\n"
471 "valgrind_base %8x (%dMB)\n"
nethercotee2097312004-06-27 12:29:56 +0000472 "valgrind_end %8x\n",
473 VG_(client_base), SEGSIZE(client_base, client_mapbase),
474 VG_(client_mapbase), SEGSIZE(client_mapbase, client_end),
475 VG_(client_end), SEGSIZE(client_end, shadow_base),
476 VG_(shadow_base), SEGSIZE(shadow_base, shadow_end),
477 VG_(shadow_end), SEGSIZE(shadow_end, valgrind_base),
nethercotec314eba2004-07-15 12:59:41 +0000478 VG_(valgrind_base), SEGSIZE(valgrind_base, valgrind_end),
nethercotee2097312004-06-27 12:29:56 +0000479 VG_(valgrind_end)
480 );
481
482#undef SEGSIZE
nethercote71980f02004-01-24 18:18:54 +0000483
484 // Ban redzone
nethercotee567e702004-07-10 17:49:17 +0000485 vres = mmap((void *)VG_(client_end), REDZONE_SIZE, PROT_NONE,
486 MAP_FIXED|MAP_ANON|MAP_PRIVATE, -1, 0);
487 vg_assert((void*)-1 != vres);
nethercote71980f02004-01-24 18:18:54 +0000488
489 // Make client hole
nethercotee567e702004-07-10 17:49:17 +0000490 ires = munmap((void*)VG_(client_base), client_size);
491 vg_assert(0 == ires);
nethercote71980f02004-01-24 18:18:54 +0000492
493 // Map shadow memory.
494 // Initially all inaccessible, incrementally initialized as it is used
nethercotee567e702004-07-10 17:49:17 +0000495 if (shadow_size != 0) {
496 vres = mmap((char *)VG_(shadow_base), shadow_size, PROT_NONE,
497 MAP_PRIVATE|MAP_ANON|MAP_FIXED, -1, 0);
498 vg_assert((void*)-1 != vres);
499 }
nethercote71980f02004-01-24 18:18:54 +0000500}
501
502/*====================================================================*/
503/*=== Command line setup ===*/
504/*====================================================================*/
505
506/* Nb: malloc'd memory never freed -- kept throughout like argv, envp */
507static char* get_file_clo(char* dir)
508{
509# define FLEN 512
510 Int fd, n;
511 struct stat s1;
512 char* f_clo = NULL;
513 char filename[FLEN];
514
515 snprintf(filename, FLEN, "%s/.valgrindrc", ( NULL == dir ? "" : dir ) );
516 fd = VG_(open)(filename, 0, VKI_S_IRUSR);
517 if ( fd > 0 ) {
518 if ( 0 == fstat(fd, &s1) ) {
519 f_clo = malloc(s1.st_size+1);
520 vg_assert(f_clo);
521 n = read(fd, f_clo, s1.st_size);
522 if (n == -1) n = 0;
523 f_clo[n] = '\0';
524 }
525 close(fd);
526 }
527 return f_clo;
528# undef FLEN
529}
530
nethercotee2097312004-06-27 12:29:56 +0000531#define ISSPACE(cc) ((cc) == ' ' || (cc) == '\t' || (cc) == '\n')
532
nethercote71980f02004-01-24 18:18:54 +0000533static Int count_args(char* s)
534{
535 Int n = 0;
536 if (s) {
537 char* cp = s;
538 while (True) {
539 // We have alternating sequences: blanks, non-blanks, blanks...
540 // count the non-blanks sequences.
541 while ( ISSPACE(*cp) ) cp++;
542 if ( !*cp ) break;
543 n++;
544 while ( !ISSPACE(*cp) && *cp ) cp++;
545 }
546 }
547 return n;
548}
549
550/* add args out of environment, skipping multiple spaces and -- args */
551static char** copy_args( char* s, char** to )
552{
553 if (s) {
554 char* cp = s;
555 while (True) {
556 // We have alternating sequences: blanks, non-blanks, blanks...
557 // copy the non-blanks sequences, and add terminating '\0'
558 while ( ISSPACE(*cp) ) cp++;
559 if ( !*cp ) break;
560 *to++ = cp;
561 while ( !ISSPACE(*cp) && *cp ) cp++;
562 if ( *cp ) *cp++ = '\0'; // terminate if necessary
563 if (VG_STREQ(to[-1], "--")) to--; // undo any '--' arg
564 }
565 }
566 return to;
567}
568
nethercotee2097312004-06-27 12:29:56 +0000569#undef ISSPACE
570
nethercote71980f02004-01-24 18:18:54 +0000571// Augment command line with arguments from environment and .valgrindrc
572// files.
573static void augment_command_line(Int* vg_argc_inout, char*** vg_argv_inout)
574{
575 int vg_argc = *vg_argc_inout;
576 char** vg_argv = *vg_argv_inout;
577
578 char* env_clo = getenv(VALGRINDOPTS);
579 char* f1_clo = get_file_clo( getenv("HOME") );
580 char* f2_clo = get_file_clo(".");
581
582 /* copy any extra args from file or environment, if present */
583 if ( (env_clo && *env_clo) || (f1_clo && *f1_clo) || (f2_clo && *f2_clo) ) {
584 /* ' ' separated extra options */
585 char **from;
586 char **to;
587 int env_arg_count, f1_arg_count, f2_arg_count;
588
589 env_arg_count = count_args(env_clo);
590 f1_arg_count = count_args(f1_clo);
591 f2_arg_count = count_args(f2_clo);
592
593 if (0)
594 printf("extra-argc=%d %d %d\n",
595 env_arg_count, f1_arg_count, f2_arg_count);
596
597 /* +2: +1 for null-termination, +1 for added '--' */
598 from = vg_argv;
599 vg_argv = malloc( (vg_argc + env_arg_count + f1_arg_count
600 + f2_arg_count + 2) * sizeof(char **));
nethercote7c018f42004-07-17 16:40:50 +0000601 vg_assert(vg_argv);
nethercote71980f02004-01-24 18:18:54 +0000602 to = vg_argv;
603
604 /* copy argv[0] */
605 *to++ = *from++;
606
607 /* Copy extra args from env var and file, in the order: ~/.valgrindrc,
608 * $VALGRIND_OPTS, ./.valgrindrc -- more local options are put later
609 * to override less local ones. */
610 to = copy_args(f1_clo, to);
611 to = copy_args(env_clo, to);
612 to = copy_args(f2_clo, to);
613
614 /* copy original arguments, stopping at command or -- */
615 while (*from) {
616 if (**from != '-')
617 break;
618 if (VG_STREQ(*from, "--")) {
619 from++; /* skip -- */
620 break;
621 }
622 *to++ = *from++;
623 }
624
625 /* add -- */
626 *to++ = "--";
627
628 vg_argc = to - vg_argv;
629
630 /* copy rest of original command line, then NULL */
631 while (*from) *to++ = *from++;
632 *to = NULL;
633 }
634
635 *vg_argc_inout = vg_argc;
636 *vg_argv_inout = vg_argv;
637}
638
639static void get_command_line( int argc, char** argv,
640 Int* vg_argc_out, Char*** vg_argv_out,
641 char*** cl_argv_out )
642{
643 int vg_argc;
644 char** vg_argv;
645 char** cl_argv;
646 char* env_clo = getenv(VALGRINDCLO);
647
648 if (env_clo != NULL && *env_clo != '\0') {
649 char *cp;
650 char **cpp;
651
652 /* OK, we're getting all our arguments from the environment - the
653 entire command line belongs to the client (including argv[0]) */
654 vg_argc = 1; /* argv[0] */
655 for (cp = env_clo; *cp; cp++)
656 if (*cp == '\01')
657 vg_argc++;
658
659 vg_argv = malloc(sizeof(char **) * (vg_argc + 1));
nethercote7c018f42004-07-17 16:40:50 +0000660 vg_assert(vg_argv);
nethercote71980f02004-01-24 18:18:54 +0000661
662 cpp = vg_argv;
663
664 *cpp++ = "valgrind"; /* nominal argv[0] */
665 *cpp++ = env_clo;
666
667 for (cp = env_clo; *cp; cp++) {
668 if (*cp == '\01') {
669 *cp++ = '\0'; /* chop it up in place */
670 *cpp++ = cp;
671 }
672 }
673 *cpp = NULL;
674 cl_argv = argv;
675
676 } else {
677 /* Count the arguments on the command line. */
678 vg_argv = argv;
679
680 for (vg_argc = 1; vg_argc < argc; vg_argc++) {
681 if (argv[vg_argc][0] != '-') /* exe name */
682 break;
683 if (VG_STREQ(argv[vg_argc], "--")) { /* dummy arg */
684 vg_argc++;
685 break;
686 }
687 }
688 cl_argv = &argv[vg_argc];
689
690 /* Get extra args from VALGRIND_OPTS and .valgrindrc files.
691 * Note we don't do this if getting args from VALGRINDCLO. */
692 augment_command_line(&vg_argc, &vg_argv);
693 }
694
695 if (0) {
696 Int i;
697 for (i = 0; i < vg_argc; i++)
698 printf("vg_argv[%d]=\"%s\"\n", i, vg_argv[i]);
699 }
700
701 *vg_argc_out = vg_argc;
702 *vg_argv_out = (Char**)vg_argv;
703 *cl_argv_out = cl_argv;
704}
705
706
707/*====================================================================*/
708/*=== Environment and stack setup ===*/
709/*====================================================================*/
710
711/* Scan a colon-separated list, and call a function on each element.
712 The string must be mutable, because we insert a temporary '\0', but
thughes4ad52d02004-06-27 17:37:21 +0000713 the string will end up unmodified. (*func) should return True if it
nethercote71980f02004-01-24 18:18:54 +0000714 doesn't need to see any more.
thughes4ad52d02004-06-27 17:37:21 +0000715
716 This routine will return True if (*func) returns True and False if
717 it reaches the end of the list without that happening.
nethercote71980f02004-01-24 18:18:54 +0000718*/
thughes4ad52d02004-06-27 17:37:21 +0000719static Bool scan_colsep(char *colsep, Bool (*func)(const char *))
nethercote71980f02004-01-24 18:18:54 +0000720{
721 char *cp, *entry;
722 int end;
723
724 if (colsep == NULL ||
725 *colsep == '\0')
thughes4ad52d02004-06-27 17:37:21 +0000726 return False;
nethercote71980f02004-01-24 18:18:54 +0000727
728 entry = cp = colsep;
729
730 do {
731 end = (*cp == '\0');
732
733 if (*cp == ':' || *cp == '\0') {
734 char save = *cp;
735
736 *cp = '\0';
thughes21942d92004-07-12 09:35:37 +0000737 if ((*func)(entry)) {
738 *cp = save;
thughes4ad52d02004-06-27 17:37:21 +0000739 return True;
thughes21942d92004-07-12 09:35:37 +0000740 }
nethercote71980f02004-01-24 18:18:54 +0000741 *cp = save;
742 entry = cp+1;
743 }
744 cp++;
745 } while(!end);
thughes4ad52d02004-06-27 17:37:21 +0000746
747 return False;
748}
749
750static Bool contains(const char *p) {
751 if (VG_STREQ(p, VG_(libdir))) {
752 return True;
753 }
754 return False;
nethercote71980f02004-01-24 18:18:54 +0000755}
756
757/* Prepare the client's environment. This is basically a copy of our
758 environment, except:
759 1. LD_LIBRARY_PATH=$VALGRINDLIB:$LD_LIBRARY_PATH
760 2. LD_PRELOAD=$VALGRINDLIB/vg_inject.so:($VALGRINDLIB/vgpreload_TOOL.so:)?$LD_PRELOAD
761
762 If any of these is missing, then it is added.
763
764 Yummy. String hacking in C.
765
766 If this needs to handle any more variables it should be hacked
767 into something table driven.
768 */
769static char **fix_environment(char **origenv, const char *preload)
770{
771 static const char inject_so[] = "vg_inject.so";
772 static const char ld_library_path[] = "LD_LIBRARY_PATH=";
773 static const char ld_preload[] = "LD_PRELOAD=";
774 static const char valgrind_clo[] = VALGRINDCLO "=";
775 static const int ld_library_path_len = sizeof(ld_library_path)-1;
776 static const int ld_preload_len = sizeof(ld_preload)-1;
777 static const int valgrind_clo_len = sizeof(valgrind_clo)-1;
778 int ld_preload_done = 0;
779 int ld_library_path_done = 0;
780 char *inject_path;
781 int inject_path_len;
782 int vgliblen = strlen(VG_(libdir));
783 char **cpp;
784 char **ret;
785 int envc;
786 const int preloadlen = (preload == NULL) ? 0 : strlen(preload);
787
788 /* Find the vg_inject.so; also make room for the tool preload
789 library */
790 inject_path_len = sizeof(inject_so) + vgliblen + preloadlen + 16;
791 inject_path = malloc(inject_path_len);
nethercote7c018f42004-07-17 16:40:50 +0000792 vg_assert(inject_path);
nethercote71980f02004-01-24 18:18:54 +0000793
794 if (preload)
795 snprintf(inject_path, inject_path_len, "%s/%s:%s",
796 VG_(libdir), inject_so, preload);
797 else
798 snprintf(inject_path, inject_path_len, "%s/%s",
799 VG_(libdir), inject_so);
800
801 /* Count the original size of the env */
802 envc = 0; /* trailing NULL */
803 for (cpp = origenv; cpp && *cpp; cpp++)
804 envc++;
805
806 /* Allocate a new space */
807 ret = malloc(sizeof(char *) * (envc+3+1)); /* 3 new entries + NULL */
nethercote7c018f42004-07-17 16:40:50 +0000808 vg_assert(ret);
nethercote71980f02004-01-24 18:18:54 +0000809
810 /* copy it over */
811 for (cpp = ret; *origenv; )
812 *cpp++ = *origenv++;
813 *cpp = NULL;
814
815 vg_assert(envc == (cpp - ret));
816
817 /* Walk over the new environment, mashing as we go */
818 for (cpp = ret; cpp && *cpp; cpp++) {
819 if (memcmp(*cpp, ld_library_path, ld_library_path_len) == 0) {
nethercote71980f02004-01-24 18:18:54 +0000820 /* If the LD_LIBRARY_PATH already contains libdir, then don't
821 bother adding it again, even if it isn't the first (it
822 seems that the Java runtime will keep reexecing itself
823 unless its paths are at the front of LD_LIBRARY_PATH) */
thughes4ad52d02004-06-27 17:37:21 +0000824 if (!scan_colsep(*cpp + ld_library_path_len, contains)) {
nethercote71980f02004-01-24 18:18:54 +0000825 int len = strlen(*cpp) + vgliblen*2 + 16;
826 char *cp = malloc(len);
nethercote7c018f42004-07-17 16:40:50 +0000827 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000828
829 snprintf(cp, len, "%s%s:%s",
830 ld_library_path, VG_(libdir),
831 (*cpp)+ld_library_path_len);
832
833 *cpp = cp;
834 }
835
836 ld_library_path_done = 1;
837 } else if (memcmp(*cpp, ld_preload, ld_preload_len) == 0) {
838 int len = strlen(*cpp) + inject_path_len;
839 char *cp = malloc(len);
nethercote7c018f42004-07-17 16:40:50 +0000840 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000841
842 snprintf(cp, len, "%s%s:%s",
843 ld_preload, inject_path, (*cpp)+ld_preload_len);
844
845 *cpp = cp;
846
847 ld_preload_done = 1;
848 } else if (memcmp(*cpp, valgrind_clo, valgrind_clo_len) == 0) {
849 *cpp = "";
850 }
851 }
852
853 /* Add the missing bits */
854
855 if (!ld_library_path_done) {
856 int len = ld_library_path_len + vgliblen*2 + 16;
857 char *cp = malloc(len);
nethercote7c018f42004-07-17 16:40:50 +0000858 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000859
860 snprintf(cp, len, "%s%s", ld_library_path, VG_(libdir));
861
862 ret[envc++] = cp;
863 }
864
865 if (!ld_preload_done) {
866 int len = ld_preload_len + inject_path_len;
867 char *cp = malloc(len);
nethercote7c018f42004-07-17 16:40:50 +0000868 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000869
870 snprintf(cp, len, "%s%s",
871 ld_preload, inject_path);
872
873 ret[envc++] = cp;
874 }
875
876 ret[envc] = NULL;
877
878 return ret;
879}
880
881extern char **environ; /* our environment */
882//#include <error.h>
883
884/* Add a string onto the string table, and return its address */
885static char *copy_str(char **tab, const char *str)
886{
887 char *cp = *tab;
888 char *orig = cp;
889
890 while(*str)
891 *cp++ = *str++;
892 *cp++ = '\0';
893
894 if (0)
nethercotef84f6952004-07-15 14:58:33 +0000895 printf("copied %p \"%s\" len %d\n", orig, orig, cp-orig);
nethercote71980f02004-01-24 18:18:54 +0000896
897 *tab = cp;
898
899 return orig;
900}
901
902/*
903 This sets up the client's initial stack, containing the args,
904 environment and aux vector.
905
906 The format of the stack is:
907
908 higher address +-----------------+
909 | Trampoline code |
910 +-----------------+
911 | |
912 : string table :
913 | |
914 +-----------------+
915 | AT_NULL |
916 - -
917 | auxv |
918 +-----------------+
919 | NULL |
920 - -
921 | envp |
922 +-----------------+
923 | NULL |
924 - -
925 | argv |
926 +-----------------+
927 | argc |
928 lower address +-----------------+ <- esp
929 | undefined |
930 : :
931 */
932static Addr setup_client_stack(char **orig_argv, char **orig_envp,
933 const struct exeinfo *info,
934 UInt** client_auxv)
935{
nethercotee567e702004-07-10 17:49:17 +0000936 void* res;
nethercote71980f02004-01-24 18:18:54 +0000937 char **cpp;
938 char *strtab; /* string table */
939 char *stringbase;
940 addr_t *ptr;
941 struct ume_auxv *auxv;
942 const struct ume_auxv *orig_auxv;
943 const struct ume_auxv *cauxv;
944 unsigned stringsize; /* total size of strings in bytes */
945 unsigned auxsize; /* total size of auxv in bytes */
946 int argc; /* total argc */
947 int envc; /* total number of env vars */
948 unsigned stacksize; /* total client stack size */
949 addr_t cl_esp; /* client stack base (initial esp) */
950
951 /* use our own auxv as a prototype */
952 orig_auxv = find_auxv(ume_exec_esp);
953
954 /* ==================== compute sizes ==================== */
955
956 /* first of all, work out how big the client stack will be */
957 stringsize = 0;
958
959 /* paste on the extra args if the loader needs them (ie, the #!
960 interpreter and its argument) */
961 argc = 0;
nethercoted6a56872004-07-26 15:32:47 +0000962 if (info->interp_name != NULL) {
nethercote71980f02004-01-24 18:18:54 +0000963 argc++;
nethercoted6a56872004-07-26 15:32:47 +0000964 stringsize += strlen(info->interp_name) + 1;
nethercote71980f02004-01-24 18:18:54 +0000965 }
nethercoted6a56872004-07-26 15:32:47 +0000966 if (info->interp_args != NULL) {
nethercote71980f02004-01-24 18:18:54 +0000967 argc++;
nethercoted6a56872004-07-26 15:32:47 +0000968 stringsize += strlen(info->interp_args) + 1;
nethercote71980f02004-01-24 18:18:54 +0000969 }
970
971 /* now scan the args we're given... */
972 for (cpp = orig_argv; *cpp; cpp++) {
973 argc++;
974 stringsize += strlen(*cpp) + 1;
975 }
976
977 /* ...and the environment */
978 envc = 0;
979 for (cpp = orig_envp; cpp && *cpp; cpp++) {
980 envc++;
981 stringsize += strlen(*cpp) + 1;
982 }
983
984 /* now, how big is the auxv? */
985 auxsize = sizeof(*auxv); /* there's always at least one entry: AT_NULL */
986 for (cauxv = orig_auxv; cauxv->a_type != AT_NULL; cauxv++) {
987 if (cauxv->a_type == AT_PLATFORM)
988 stringsize += strlen(cauxv->u.a_ptr) + 1;
989 auxsize += sizeof(*cauxv);
990 }
991
992 /* OK, now we know how big the client stack is */
993 stacksize =
994 sizeof(int) + /* argc */
995 sizeof(char **)*argc + /* argv */
996 sizeof(char **) + /* terminal NULL */
997 sizeof(char **)*envc + /* envp */
998 sizeof(char **) + /* terminal NULL */
999 auxsize + /* auxv */
1000 ROUNDUP(stringsize, sizeof(int)) +/* strings (aligned) */
1001 VKI_BYTES_PER_PAGE; /* page for trampoline code */
1002
nethercotef84f6952004-07-15 14:58:33 +00001003 // decide where stack goes!
1004 VG_(clstk_end) = VG_(client_end);
1005
1006 VG_(client_trampoline_code) = VG_(clstk_end) - VKI_BYTES_PER_PAGE;
1007
nethercote71980f02004-01-24 18:18:54 +00001008 /* cl_esp is the client's stack pointer */
nethercotef84f6952004-07-15 14:58:33 +00001009 cl_esp = VG_(clstk_end) - stacksize;
nethercote71980f02004-01-24 18:18:54 +00001010 cl_esp = ROUNDDN(cl_esp, 16); /* make stack 16 byte aligned */
1011
nethercote71980f02004-01-24 18:18:54 +00001012 /* base of the string table (aligned) */
1013 stringbase = strtab = (char *)(VG_(client_trampoline_code) - ROUNDUP(stringsize, sizeof(int)));
1014
1015 VG_(clstk_base) = PGROUNDDN(cl_esp);
nethercote71980f02004-01-24 18:18:54 +00001016
nethercote5ee67ca2004-06-22 14:00:09 +00001017 if (0)
1018 printf("stringsize=%d auxsize=%d stacksize=%d\n"
1019 "clstk_base %x\n"
1020 "clstk_end %x\n",
1021 stringsize, auxsize, stacksize, VG_(clstk_base), VG_(clstk_end));
1022
1023
nethercote71980f02004-01-24 18:18:54 +00001024 /* ==================== allocate space ==================== */
1025
1026 /* allocate a stack - mmap enough space for the stack */
nethercotef84f6952004-07-15 14:58:33 +00001027 res = mmap((void *)PGROUNDDN(cl_esp), VG_(clstk_end) - PGROUNDDN(cl_esp),
nethercotee567e702004-07-10 17:49:17 +00001028 PROT_READ | PROT_WRITE | PROT_EXEC,
1029 MAP_PRIVATE | MAP_ANON | MAP_FIXED, -1, 0);
1030 vg_assert((void*)-1 != res);
nethercote71980f02004-01-24 18:18:54 +00001031
1032 /* ==================== copy client stack ==================== */
1033
1034 ptr = (addr_t *)cl_esp;
1035
1036 /* --- argc --- */
1037 *ptr++ = argc; /* client argc */
1038
1039 /* --- argv --- */
nethercoted6a56872004-07-26 15:32:47 +00001040 if (info->interp_name) {
1041 *ptr++ = (addr_t)copy_str(&strtab, info->interp_name);
1042 free(info->interp_name);
nethercote71980f02004-01-24 18:18:54 +00001043 }
nethercoted6a56872004-07-26 15:32:47 +00001044 if (info->interp_args) {
1045 *ptr++ = (addr_t)copy_str(&strtab, info->interp_args);
1046 free(info->interp_args);
nethercote71980f02004-01-24 18:18:54 +00001047 }
1048 for (cpp = orig_argv; *cpp; ptr++, cpp++) {
1049 *ptr = (addr_t)copy_str(&strtab, *cpp);
1050 }
1051 *ptr++ = 0;
1052
1053 /* --- envp --- */
1054 VG_(client_envp) = (Char **)ptr;
1055 for (cpp = orig_envp; cpp && *cpp; ptr++, cpp++)
1056 *ptr = (addr_t)copy_str(&strtab, *cpp);
1057 *ptr++ = 0;
1058
1059 /* --- auxv --- */
1060 auxv = (struct ume_auxv *)ptr;
1061 *client_auxv = (UInt *)auxv;
1062
1063 for (; orig_auxv->a_type != AT_NULL; auxv++, orig_auxv++) {
1064 /* copy the entry... */
1065 *auxv = *orig_auxv;
1066
1067 /* ...and fix up the copy */
1068 switch(auxv->a_type) {
1069 case AT_PHDR:
1070 if (info->phdr == 0)
1071 auxv->a_type = AT_IGNORE;
1072 else
1073 auxv->u.a_val = info->phdr;
1074 break;
1075
1076 case AT_PHNUM:
1077 if (info->phdr == 0)
1078 auxv->a_type = AT_IGNORE;
1079 else
1080 auxv->u.a_val = info->phnum;
1081 break;
1082
1083 case AT_BASE:
1084 if (info->interp_base == 0)
1085 auxv->a_type = AT_IGNORE;
1086 else
1087 auxv->u.a_val = info->interp_base;
1088 break;
1089
1090 case AT_PLATFORM: /* points to a platform description string */
1091 auxv->u.a_ptr = copy_str(&strtab, orig_auxv->u.a_ptr);
1092 break;
1093
1094 case AT_ENTRY:
1095 auxv->u.a_val = info->entry;
1096 break;
1097
1098 case AT_IGNORE:
1099 case AT_EXECFD:
1100 case AT_PHENT:
1101 case AT_PAGESZ:
1102 case AT_FLAGS:
1103 case AT_NOTELF:
1104 case AT_UID:
1105 case AT_EUID:
1106 case AT_GID:
1107 case AT_EGID:
1108 case AT_CLKTCK:
1109 case AT_HWCAP:
1110 case AT_FPUCW:
1111 case AT_DCACHEBSIZE:
1112 case AT_ICACHEBSIZE:
1113 case AT_UCACHEBSIZE:
1114 /* All these are pointerless, so we don't need to do anything
1115 about them. */
1116 break;
1117
1118 case AT_SECURE:
1119 /* If this is 1, then it means that this program is running
1120 suid, and therefore the dynamic linker should be careful
1121 about LD_PRELOAD, etc. However, since stage1 (the thing
1122 the kernel actually execve's) should never be SUID, and we
1123 need LD_PRELOAD/LD_LIBRARY_PATH to work for the client, we
1124 set AT_SECURE to 0. */
1125 auxv->u.a_val = 0;
1126 break;
1127
1128 case AT_SYSINFO:
1129 /* Leave this unmolested for now, but we'll update it later
1130 when we set up the client trampoline code page */
1131 break;
1132
1133 case AT_SYSINFO_EHDR:
1134 /* Trash this, because we don't reproduce it */
1135 auxv->a_type = AT_IGNORE;
1136 break;
1137
1138 default:
1139 /* stomp out anything we don't know about */
1140 if (0)
1141 printf("stomping auxv entry %d\n", auxv->a_type);
1142 auxv->a_type = AT_IGNORE;
1143 break;
1144
1145 }
1146 }
1147 *auxv = *orig_auxv;
1148 vg_assert(auxv->a_type == AT_NULL);
1149
nethercotef84f6952004-07-15 14:58:33 +00001150 /* --- trampoline page --- */
1151 VG_(memcpy)( (void *)VG_(client_trampoline_code),
1152 &VG_(trampoline_code_start), VG_(trampoline_code_length) );
1153
nethercote71980f02004-01-24 18:18:54 +00001154 vg_assert((strtab-stringbase) == stringsize);
1155
nethercote5ee67ca2004-06-22 14:00:09 +00001156 /* We know the initial ESP is pointing at argc/argv */
1157 VG_(client_argc) = *(Int*)cl_esp;
1158 VG_(client_argv) = (Char**)(cl_esp + sizeof(Int));
1159
nethercote71980f02004-01-24 18:18:54 +00001160 return cl_esp;
1161}
1162
1163/*====================================================================*/
1164/*=== Find executable ===*/
1165/*====================================================================*/
1166
thughes4ad52d02004-06-27 17:37:21 +00001167static const char* executable_name;
1168
1169static Bool match_executable(const char *entry) {
1170 char buf[strlen(entry) + strlen(executable_name) + 2];
1171
1172 /* empty PATH element means . */
1173 if (*entry == '\0')
1174 entry = ".";
1175
1176 snprintf(buf, sizeof(buf), "%s/%s", entry, executable_name);
1177
1178 if (access(buf, R_OK|X_OK) == 0) {
1179 executable_name = strdup(buf);
1180 vg_assert(NULL != executable_name);
1181 return True;
1182 }
1183 return False;
1184}
1185
nethercote71980f02004-01-24 18:18:54 +00001186static const char* find_executable(const char* exec)
1187{
1188 vg_assert(NULL != exec);
thughes4ad52d02004-06-27 17:37:21 +00001189 executable_name = exec;
1190 if (strchr(executable_name, '/') == NULL) {
nethercote71980f02004-01-24 18:18:54 +00001191 /* no '/' - we need to search the path */
1192 char *path = getenv("PATH");
thughes4ad52d02004-06-27 17:37:21 +00001193 scan_colsep(path, match_executable);
nethercote71980f02004-01-24 18:18:54 +00001194 }
thughes4ad52d02004-06-27 17:37:21 +00001195 return executable_name;
nethercote71980f02004-01-24 18:18:54 +00001196}
1197
1198
1199/*====================================================================*/
1200/*=== Loading tools ===*/
1201/*====================================================================*/
1202
1203static void list_tools(void)
1204{
1205 DIR *dir = opendir(VG_(libdir));
1206 struct dirent *de;
1207 int first = 1;
1208
1209 if (dir == NULL) {
1210 fprintf(stderr, "Can't open %s: %s (installation problem?)\n",
nethercotef4928da2004-06-15 10:54:40 +00001211 VG_(libdir), strerror(errno));
nethercote71980f02004-01-24 18:18:54 +00001212 return;
1213 }
1214
nethercotef4928da2004-06-15 10:54:40 +00001215 while ((de = readdir(dir)) != NULL) {
nethercote71980f02004-01-24 18:18:54 +00001216 int len = strlen(de->d_name);
1217
1218 /* look for vgskin_TOOL.so names */
1219 if (len > (7+1+3) && /* "vgskin_" + at least 1-char toolname + ".so" */
nethercotef4928da2004-06-15 10:54:40 +00001220 strncmp(de->d_name, "vgskin_", 7) == 0 &&
1221 VG_STREQ(de->d_name + len - 3, ".so")) {
1222 if (first) {
1223 fprintf(stderr, "Available tools:\n");
1224 first = 0;
1225 }
1226 de->d_name[len-3] = '\0';
1227 fprintf(stderr, "\t%s\n", de->d_name+7);
nethercote71980f02004-01-24 18:18:54 +00001228 }
1229 }
1230
1231 closedir(dir);
1232
1233 if (first)
nethercotef4928da2004-06-15 10:54:40 +00001234 fprintf(stderr, "No tools available in \"%s\" (installation problem?)\n",
1235 VG_(libdir));
nethercote71980f02004-01-24 18:18:54 +00001236}
1237
1238
1239/* Find and load a tool, and check it looks ok. Also looks to see if there's
1240 * a matching vgpreload_*.so file, and returns its name in *preloadpath. */
1241static void load_tool( const char *toolname, void** handle_out,
1242 ToolInfo** toolinfo_out, char **preloadpath_out )
1243{
1244 Bool ok;
1245 int len = strlen(VG_(libdir)) + strlen(toolname)*2 + 16;
1246 char buf[len];
1247 void* handle;
1248 ToolInfo* toolinfo;
1249 char* preloadpath = NULL;
1250 Int* vg_malloc_redzonep;
1251
1252 // XXX: allowing full paths for --tool option -- does it make sense?
1253 // Doesn't allow for vgpreload_<tool>.so.
1254
1255 if (strchr(toolname, '/') != 0) {
1256 /* toolname contains '/', and so must be a pathname */
1257 handle = dlopen(toolname, RTLD_NOW);
1258 } else {
1259 /* just try in the libdir */
1260 snprintf(buf, len, "%s/vgskin_%s.so", VG_(libdir), toolname);
1261 handle = dlopen(buf, RTLD_NOW);
1262
1263 if (handle != NULL) {
1264 snprintf(buf, len, "%s/vgpreload_%s.so", VG_(libdir), toolname);
1265 if (access(buf, R_OK) == 0) {
1266 preloadpath = strdup(buf);
1267 vg_assert(NULL != preloadpath);
1268 }
1269 }
1270 }
1271
1272 ok = (NULL != handle);
1273 if (!ok) {
1274 fprintf(stderr, "Can't open tool \"%s\": %s\n", toolname, dlerror());
1275 goto bad_load;
1276 }
1277
1278 toolinfo = dlsym(handle, "vgSkin_tool_info");
1279 ok = (NULL != toolinfo);
1280 if (!ok) {
1281 fprintf(stderr, "Tool \"%s\" doesn't define SK_(tool_info) - "
1282 "add VG_DETERMINE_INTERFACE_VERSION?\n", toolname);
1283 goto bad_load;
1284 }
1285
1286 ok = (toolinfo->sizeof_ToolInfo == sizeof(*toolinfo) &&
1287 toolinfo->interface_major_version == VG_CORE_INTERFACE_MAJOR_VERSION &&
1288 toolinfo->sk_pre_clo_init != NULL);
1289 if (!ok) {
1290 fprintf(stderr, "Error:\n"
1291 " Tool and core interface versions do not match.\n"
1292 " Interface version used by core is: %d.%d (size %d)\n"
1293 " Interface version used by tool is: %d.%d (size %d)\n"
1294 " The major version numbers must match.\n",
1295 VG_CORE_INTERFACE_MAJOR_VERSION,
1296 VG_CORE_INTERFACE_MINOR_VERSION,
1297 sizeof(*toolinfo),
1298 toolinfo->interface_major_version,
1299 toolinfo->interface_minor_version,
1300 toolinfo->sizeof_ToolInfo);
1301 fprintf(stderr, " You need to at least recompile, and possibly update,\n");
1302 if (VG_CORE_INTERFACE_MAJOR_VERSION > toolinfo->interface_major_version)
nethercote996901a2004-08-03 13:29:09 +00001303 fprintf(stderr, " your tool to work with this version of Valgrind.\n");
nethercote71980f02004-01-24 18:18:54 +00001304 else
nethercote996901a2004-08-03 13:29:09 +00001305 fprintf(stderr, " your version of Valgrind to work with this tool.\n");
nethercote71980f02004-01-24 18:18:54 +00001306 goto bad_load;
1307 }
1308
1309 // Set redzone size for V's allocator
1310 vg_malloc_redzonep = dlsym(handle, STR(VG_(vg_malloc_redzone_szB)));
1311 if ( NULL != vg_malloc_redzonep ) {
1312 VG_(vg_malloc_redzone_szB) = *vg_malloc_redzonep;
1313 }
1314
1315 vg_assert(NULL != handle && NULL != toolinfo);
1316 *handle_out = handle;
1317 *toolinfo_out = toolinfo;
1318 *preloadpath_out = preloadpath;
1319 return;
1320
1321
1322 bad_load:
1323 if (handle != NULL)
1324 dlclose(handle);
1325
nethercotef4928da2004-06-15 10:54:40 +00001326 fprintf(stderr, "valgrind: couldn't load tool\n");
nethercote71980f02004-01-24 18:18:54 +00001327 list_tools();
1328 exit(127);
1329}
1330
nethercotef4928da2004-06-15 10:54:40 +00001331
1332/*====================================================================*/
1333/*=== Command line errors ===*/
1334/*====================================================================*/
1335
1336static void abort_msg ( void )
1337{
nethercotef8548672004-06-21 12:42:35 +00001338 VG_(clo_log_to) = VgLogTo_Fd;
1339 VG_(clo_log_fd) = 2; /* stderr */
nethercotef4928da2004-06-15 10:54:40 +00001340}
1341
1342void VG_(bad_option) ( Char* opt )
1343{
1344 abort_msg();
1345 VG_(printf)("valgrind: Bad option `%s'; aborting.\n", opt);
1346 VG_(printf)("valgrind: Use --help for more information.\n");
1347 VG_(exit)(1);
1348}
1349
1350static void missing_tool_option ( void )
1351{
1352 abort_msg();
1353 VG_(printf)("valgrind: Missing --tool option\n");
1354 list_tools();
1355 VG_(printf)("valgrind: Use --help for more information.\n");
1356 VG_(exit)(1);
1357}
1358
1359static void missing_prog ( void )
1360{
1361 abort_msg();
1362 VG_(printf)("valgrind: no program specified\n");
1363 VG_(printf)("valgrind: Use --help for more information.\n");
1364 VG_(exit)(1);
1365}
1366
1367static void config_error ( Char* msg )
1368{
1369 abort_msg();
1370 VG_(printf)("valgrind: Startup or configuration error:\n %s\n", msg);
1371 VG_(printf)("valgrind: Unable to start up properly. Giving up.\n");
1372 VG_(exit)(1);
1373}
1374
1375
nethercote71980f02004-01-24 18:18:54 +00001376/*====================================================================*/
1377/*=== Loading the client ===*/
1378/*====================================================================*/
1379
nethercotef4928da2004-06-15 10:54:40 +00001380static void load_client(char* cl_argv[], const char* exec, Int need_help,
nethercote71980f02004-01-24 18:18:54 +00001381 /*out*/struct exeinfo* info, /*out*/Addr* client_eip)
1382{
1383 // If they didn't specify an executable with --exec, and didn't specify
1384 // --help, then use client argv[0] (searching $PATH if necessary).
nethercotef4928da2004-06-15 10:54:40 +00001385 if (NULL == exec && !need_help) {
nethercote71980f02004-01-24 18:18:54 +00001386 if (cl_argv[0] == NULL ||
1387 ( NULL == (exec = find_executable(cl_argv[0])) ) )
1388 {
nethercotef4928da2004-06-15 10:54:40 +00001389 missing_prog();
nethercote71980f02004-01-24 18:18:54 +00001390 }
1391 }
1392
1393 info->map_base = VG_(client_mapbase);
nethercote71980f02004-01-24 18:18:54 +00001394 info->exe_base = VG_(client_base);
1395 info->exe_end = VG_(client_end);
1396 info->argv = cl_argv;
1397
nethercotef4928da2004-06-15 10:54:40 +00001398 if (need_help) {
nethercote71980f02004-01-24 18:18:54 +00001399 VG_(clexecfd) = -1;
nethercoteea147e72004-07-26 15:43:57 +00001400 // Set the minimal number of entries in 'info' to continue.
nethercoted6a56872004-07-26 15:32:47 +00001401 info->interp_name = NULL;
1402 info->interp_args = NULL;
nethercote71980f02004-01-24 18:18:54 +00001403 } else {
1404 Int ret;
1405 VG_(clexecfd) = VG_(open)(exec, O_RDONLY, VKI_S_IRUSR);
1406 ret = do_exec(exec, info);
1407 if (ret != 0) {
nethercoteea147e72004-07-26 15:43:57 +00001408 fprintf(stderr, "valgrind: do_exec(%s) failed: %s\n",
1409 exec, strerror(ret));
nethercote71980f02004-01-24 18:18:54 +00001410 exit(127);
1411 }
1412 }
1413
1414 /* Copy necessary bits of 'info' that were filled in */
1415 *client_eip = info->init_eip;
1416 VG_(brk_base) = VG_(brk_limit) = info->brkbase;
1417}
1418
1419
1420/*====================================================================*/
1421/*=== Command-line: variables, processing ===*/
1422/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +00001423
njn25e49d8e72002-09-23 09:36:25 +00001424/* Define, and set defaults. */
1425Bool VG_(clo_error_limit) = True;
nethercote04d0fbc2004-01-26 16:48:06 +00001426Bool VG_(clo_db_attach) = False;
1427Char* VG_(clo_db_command) = VG_CLO_DEFAULT_DBCOMMAND;
njn43c799e2003-04-08 00:08:52 +00001428Bool VG_(clo_gen_suppressions) = False;
nethercote27fec902004-06-16 21:26:32 +00001429Int VG_(clo_sanity_level) = 1;
njn25e49d8e72002-09-23 09:36:25 +00001430Int VG_(clo_verbosity) = 1;
1431Bool VG_(clo_demangle) = True;
njn25e49d8e72002-09-23 09:36:25 +00001432Bool VG_(clo_trace_children) = False;
sewardj4cf05692002-10-27 20:28:29 +00001433
nethercotee1730692003-11-20 10:38:07 +00001434/* See big comment in vg_include.h for meaning of these three.
1435 fd is initially stdout, for --help, but gets moved to stderr by default
1436 immediately afterwards. */
sewardj4cf05692002-10-27 20:28:29 +00001437VgLogTo VG_(clo_log_to) = VgLogTo_Fd;
nethercotef8548672004-06-21 12:42:35 +00001438Int VG_(clo_log_fd) = 1;
1439Char* VG_(clo_log_name) = NULL;
sewardj4cf05692002-10-27 20:28:29 +00001440
sewardj6024b212003-07-13 10:54:33 +00001441Int VG_(clo_input_fd) = 0; /* stdin */
njn25e49d8e72002-09-23 09:36:25 +00001442Int VG_(clo_n_suppressions) = 0;
sewardjde4a1d02002-03-22 01:27:54 +00001443Char* VG_(clo_suppressions)[VG_CLO_MAX_SFILES];
njn25e49d8e72002-09-23 09:36:25 +00001444Bool VG_(clo_profile) = False;
1445Bool VG_(clo_single_step) = False;
1446Bool VG_(clo_optimise) = True;
1447UChar VG_(clo_trace_codegen) = 0; // 00000000b
1448Bool VG_(clo_trace_syscalls) = False;
1449Bool VG_(clo_trace_signals) = False;
1450Bool VG_(clo_trace_symtab) = False;
njn25e49d8e72002-09-23 09:36:25 +00001451Bool VG_(clo_trace_sched) = False;
1452Int VG_(clo_trace_pthread_level) = 0;
njn25e49d8e72002-09-23 09:36:25 +00001453Int VG_(clo_dump_error) = 0;
1454Int VG_(clo_backtrace_size) = 4;
1455Char* VG_(clo_weird_hacks) = NULL;
sewardj858964b2002-10-05 14:15:43 +00001456Bool VG_(clo_run_libc_freeres) = True;
rjwalshf5f536f2003-11-17 17:45:00 +00001457Bool VG_(clo_track_fds) = False;
sewardj22854b92002-11-30 14:00:47 +00001458Bool VG_(clo_chain_bb) = True;
nethercote77eba602003-11-13 17:35:04 +00001459Bool VG_(clo_show_below_main) = False;
fitzhardinge98abfc72003-12-16 02:05:15 +00001460Bool VG_(clo_pointercheck) = True;
fitzhardinge462f4f92003-12-18 02:10:54 +00001461Bool VG_(clo_branchpred) = False;
sewardj2370f3b2002-11-30 15:01:01 +00001462
jsgf855d93d2003-10-13 22:26:55 +00001463static Bool VG_(clo_wait_for_gdb) = False;
1464
1465/* If we're doing signal routing, poll for signals every 50mS by
1466 default. */
1467Int VG_(clo_signal_polltime) = 50;
1468
1469/* These flags reduce thread wakeup latency on syscall completion and
1470 signal delivery, respectively. The downside is possible unfairness. */
1471Bool VG_(clo_lowlat_syscalls) = False; /* low-latency syscalls */
1472Bool VG_(clo_lowlat_signals) = False; /* low-latency signals */
1473
sewardjde4a1d02002-03-22 01:27:54 +00001474
nethercote6c999f22004-01-31 22:55:15 +00001475void usage ( Bool debug_help )
njn7cf0bd32002-06-08 13:36:03 +00001476{
njn25e49d8e72002-09-23 09:36:25 +00001477 Char* usage1 =
nethercote71980f02004-01-24 18:18:54 +00001478"usage: valgrind --tool=<toolname> [options] prog-and-args\n"
njn25e49d8e72002-09-23 09:36:25 +00001479"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001480" common user options for all Valgrind tools, with defaults in [ ]:\n"
nethercote0d588502004-06-21 13:27:11 +00001481" --tool=<name> use the Valgrind tool named <name>\n"
nethercotea76368b2004-06-16 11:56:29 +00001482" -h --help show this message\n"
nethercote6c999f22004-01-31 22:55:15 +00001483" --help-debug show this message, plus debugging options\n"
njn25e49d8e72002-09-23 09:36:25 +00001484" --version show version\n"
njn25e49d8e72002-09-23 09:36:25 +00001485" -q --quiet run silently; only print error msgs\n"
1486" -v --verbose be more verbose, incl counts of errors\n"
nethercote77eba602003-11-13 17:35:04 +00001487" --trace-children=no|yes Valgrind-ise child processes? [no]\n"
nethercote0d588502004-06-21 13:27:11 +00001488" --track-fds=no|yes track open file descriptors? [no]\n"
nethercote2b0793f2003-12-02 10:41:18 +00001489"\n"
1490" uncommon user options for all Valgrind tools:\n"
nethercote0d588502004-06-21 13:27:11 +00001491" --run-libc-freeres=no|yes free up glibc memory at exit? [yes]\n"
1492" --weird-hacks=hack1,hack2,... recognised hacks: lax-ioctls [none]\n"
1493" --signal-polltime=<time> signal poll period (mS) for older kernels [50]\n"
1494" --lowlat-signals=no|yes improve thread signal wake-up latency [no]\n"
1495" --lowlat-syscalls=no|yes improve thread syscall wake-up latency [no]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001496" --pointercheck=no|yes enforce client address space limits [yes]\n"
njn25e49d8e72002-09-23 09:36:25 +00001497"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001498" user options for Valgrind tools that report errors:\n"
nethercotef8548672004-06-21 12:42:35 +00001499" --log-fd=<number> log messages to file descriptor [2=stderr]\n"
1500" --log-file=<file> log messages to <file>.pid<pid>\n"
1501" --log-socket=ipaddr:port log messages to socket ipaddr:port\n"
nethercote2b0793f2003-12-02 10:41:18 +00001502" --demangle=no|yes automatically demangle C++ names? [yes]\n"
1503" --num-callers=<number> show <num> callers in stack traces [4]\n"
1504" --error-limit=no|yes stop showing new errors if too many? [yes]\n"
1505" --show-below-main=no|yes continue stack traces below main() [no]\n"
1506" --suppressions=<filename> suppress errors described in <filename>\n"
1507" --gen-suppressions=no|yes print suppressions for errors detected [no]\n"
nethercote04d0fbc2004-01-26 16:48:06 +00001508" --db-attach=no|yes start debugger when errors detected? [no]\n"
1509" --db-command=<command> command to start debugger [gdb -nw %%f %%p]\n"
1510" --input-fd=<number> file descriptor for input [0=stdin]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001511"\n";
njn7cf0bd32002-06-08 13:36:03 +00001512
njn25e49d8e72002-09-23 09:36:25 +00001513 Char* usage2 =
1514"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001515" debugging options for all Valgrind tools:\n"
njn25e49d8e72002-09-23 09:36:25 +00001516" --sanity-level=<number> level of sanity checking to do [1]\n"
1517" --single-step=no|yes translate each instr separately? [no]\n"
1518" --optimise=no|yes improve intermediate code? [yes]\n"
nethercote137bc552003-11-14 17:47:54 +00001519" --profile=no|yes profile? (tool must be built for it) [no]\n"
sewardj22854b92002-11-30 14:00:47 +00001520" --chain-bb=no|yes do basic-block chaining? [yes]\n"
fitzhardinge462f4f92003-12-18 02:10:54 +00001521" --branchpred=yes|no generate branch prediction hints [no]\n"
njn25e49d8e72002-09-23 09:36:25 +00001522" --trace-codegen=<XXXXX> show generated code? (X = 0|1) [00000]\n"
1523" --trace-syscalls=no|yes show all system calls? [no]\n"
1524" --trace-signals=no|yes show signal handling details? [no]\n"
1525" --trace-symtab=no|yes show symbol table details? [no]\n"
njn25e49d8e72002-09-23 09:36:25 +00001526" --trace-sched=no|yes show thread scheduler details? [no]\n"
njn3e884182003-04-15 13:03:23 +00001527" --trace-pthread=none|some|all show pthread event details? [none]\n"
jsgf855d93d2003-10-13 22:26:55 +00001528" --wait-for-gdb=yes|no pause on startup to wait for gdb attach\n"
njn25e49d8e72002-09-23 09:36:25 +00001529"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001530" debugging options for Valgrind tools that report errors\n"
1531" --dump-error=<number> show translation for basic block associated\n"
1532" with <number>'th error context [0=show none]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001533"\n";
njn3e884182003-04-15 13:03:23 +00001534
1535 Char* usage3 =
1536"\n"
nethercote71980f02004-01-24 18:18:54 +00001537" Extra options read from ~/.valgrindrc, $VALGRIND_OPTS, ./.valgrindrc\n"
njn25e49d8e72002-09-23 09:36:25 +00001538"\n"
nethercote08fa9a72004-07-16 17:44:00 +00001539" Valgrind is Copyright (C) 2000-2004 Julian Seward et al.\n"
njn25e49d8e72002-09-23 09:36:25 +00001540" and licensed under the GNU General Public License, version 2.\n"
1541" Bug reports, feedback, admiration, abuse, etc, to: %s.\n"
njnd04b7c62002-10-03 14:05:52 +00001542"\n"
nethercote137bc552003-11-14 17:47:54 +00001543" Tools are copyright and licensed by their authors. See each\n"
1544" tool's start-up message for more information.\n"
njn25e49d8e72002-09-23 09:36:25 +00001545"\n";
njn7cf0bd32002-06-08 13:36:03 +00001546
fitzhardinge98abfc72003-12-16 02:05:15 +00001547 VG_(printf)(usage1);
1548 if (VG_(details).name) {
1549 VG_(printf)(" user options for %s:\n", VG_(details).name);
fitzhardinge98abfc72003-12-16 02:05:15 +00001550 if (VG_(needs).command_line_options)
1551 SK_(print_usage)();
1552 else
1553 VG_(printf)(" (none)\n");
1554 }
nethercote6c999f22004-01-31 22:55:15 +00001555 if (debug_help) {
1556 VG_(printf)(usage2);
fitzhardinge98abfc72003-12-16 02:05:15 +00001557
nethercote6c999f22004-01-31 22:55:15 +00001558 if (VG_(details).name) {
1559 VG_(printf)(" debugging options for %s:\n", VG_(details).name);
1560
1561 if (VG_(needs).command_line_options)
1562 SK_(print_debug_usage)();
1563 else
1564 VG_(printf)(" (none)\n");
1565 }
fitzhardinge98abfc72003-12-16 02:05:15 +00001566 }
nethercote421281e2003-11-20 16:20:55 +00001567 VG_(printf)(usage3, VG_BUGS_TO);
nethercotef4928da2004-06-15 10:54:40 +00001568 VG_(exit)(0);
njn7cf0bd32002-06-08 13:36:03 +00001569}
sewardjde4a1d02002-03-22 01:27:54 +00001570
nethercote71980f02004-01-24 18:18:54 +00001571static void pre_process_cmd_line_options
nethercote6c999f22004-01-31 22:55:15 +00001572 ( Int* need_help, const char** tool, const char** exec )
sewardj1c1b1162003-02-23 01:25:51 +00001573{
nethercote71980f02004-01-24 18:18:54 +00001574 UInt i;
sewardjde4a1d02002-03-22 01:27:54 +00001575
nethercote71980f02004-01-24 18:18:54 +00001576 /* parse the options we have (only the options we care about now) */
1577 for (i = 1; i < VG_(vg_argc); i++) {
1578
1579 if (strcmp(VG_(vg_argv)[i], "--version") == 0) {
1580 printf("valgrind-" VERSION "\n");
nethercotef4928da2004-06-15 10:54:40 +00001581 exit(0);
nethercote71980f02004-01-24 18:18:54 +00001582
nethercotea76368b2004-06-16 11:56:29 +00001583 } else if (VG_CLO_STREQ(VG_(vg_argv)[i], "--help") ||
1584 VG_CLO_STREQ(VG_(vg_argv)[i], "-h")) {
nethercote6c999f22004-01-31 22:55:15 +00001585 *need_help = 1;
1586
nethercotef4928da2004-06-15 10:54:40 +00001587 } else if (VG_CLO_STREQ(VG_(vg_argv)[i], "--help-debug")) {
nethercote6c999f22004-01-31 22:55:15 +00001588 *need_help = 2;
nethercote71980f02004-01-24 18:18:54 +00001589
nethercotef4928da2004-06-15 10:54:40 +00001590 } else if (VG_CLO_STREQN(7, VG_(vg_argv)[i], "--tool=") ||
1591 VG_CLO_STREQN(7, VG_(vg_argv)[i], "--skin=")) {
nethercote71980f02004-01-24 18:18:54 +00001592 *tool = &VG_(vg_argv)[i][7];
1593
nethercotef4928da2004-06-15 10:54:40 +00001594 } else if (VG_CLO_STREQN(7, VG_(vg_argv)[i], "--exec=")) {
nethercote71980f02004-01-24 18:18:54 +00001595 *exec = &VG_(vg_argv)[i][7];
1596 }
1597 }
1598
nethercotef4928da2004-06-15 10:54:40 +00001599 /* If no tool specified, can act appropriately without loading tool */
nethercote71980f02004-01-24 18:18:54 +00001600 if (*tool == NULL) {
nethercotef4928da2004-06-15 10:54:40 +00001601 if (0 == *need_help) {
1602 // neither --tool nor --help/--help-debug specified
1603 missing_tool_option();
1604 } else {
1605 // Give help message, without any tool-specific help
1606 usage(/*help-debug?*/2 == *need_help);
1607 }
nethercote71980f02004-01-24 18:18:54 +00001608 }
1609}
1610
nethercote5ee67ca2004-06-22 14:00:09 +00001611static void process_cmd_line_options( UInt* client_auxv, const char* toolname )
nethercote71980f02004-01-24 18:18:54 +00001612{
nethercotef8548672004-06-21 12:42:35 +00001613 Int i, eventually_log_fd;
nethercote71980f02004-01-24 18:18:54 +00001614 Int *auxp;
1615 Int toolname_len = VG_(strlen)(toolname);
sewardjde4a1d02002-03-22 01:27:54 +00001616
nethercotee1730692003-11-20 10:38:07 +00001617 /* log to stderr by default, but usage message goes to stdout */
nethercotef8548672004-06-21 12:42:35 +00001618 eventually_log_fd = 2;
sewardjde4a1d02002-03-22 01:27:54 +00001619
sewardj19d81412002-06-03 01:10:40 +00001620 /* Check for sane path in ./configure --prefix=... */
fitzhardinge98abfc72003-12-16 02:05:15 +00001621 if (VG_LIBDIR[0] != '/')
sewardj19d81412002-06-03 01:10:40 +00001622 config_error("Please use absolute paths in "
1623 "./configure --prefix=... or --libdir=...");
sewardj38170912002-05-10 21:07:22 +00001624
nethercote71980f02004-01-24 18:18:54 +00001625 for (auxp = client_auxv; auxp[0] != VKI_AT_NULL; auxp += 2) {
fitzhardinge98abfc72003-12-16 02:05:15 +00001626 switch(auxp[0]) {
1627 case VKI_AT_SYSINFO:
fitzhardinge92360792003-12-24 10:11:11 +00001628 auxp[1] = (Int)(VG_(client_trampoline_code) + VG_(tramp_syscall_offset));
fitzhardinge98abfc72003-12-16 02:05:15 +00001629 break;
sewardjde4a1d02002-03-22 01:27:54 +00001630 }
fitzhardinge98abfc72003-12-16 02:05:15 +00001631 }
sewardjde4a1d02002-03-22 01:27:54 +00001632
nethercote71980f02004-01-24 18:18:54 +00001633 for (i = 1; i < VG_(vg_argc); i++) {
1634
1635 Char* arg = VG_(vg_argv)[i];
thughes3bfd5a02004-07-18 08:05:44 +00001636 Char* colon = arg;
nethercote71980f02004-01-24 18:18:54 +00001637
thughes3bfd5a02004-07-18 08:05:44 +00001638 /* Look for a colon in the switch name */
1639 while (*colon && *colon != ':' && *colon != '=')
1640 colon++;
nethercote71980f02004-01-24 18:18:54 +00001641
1642 /* Look for matching "--toolname:foo" */
thughes3bfd5a02004-07-18 08:05:44 +00001643 if (*colon == ':') {
nethercote71980f02004-01-24 18:18:54 +00001644 if (VG_CLO_STREQN(2, arg, "--") &&
1645 VG_CLO_STREQN(toolname_len, arg+2, toolname) &&
1646 VG_CLO_STREQN(1, arg+2+toolname_len, ":"))
1647 {
1648 // prefix matches, convert "--toolname:foo" to "--foo"
1649 if (0)
1650 VG_(printf)("tool-specific arg: %s\n", arg);
1651 arg += toolname_len + 1;
1652 arg[0] = '-';
1653 arg[1] = '-';
1654
1655 } else {
1656 // prefix doesn't match, skip to next arg
1657 continue;
1658 }
1659 }
1660
fitzhardinge98abfc72003-12-16 02:05:15 +00001661 /* Ignore these options - they've already been handled */
nethercote71980f02004-01-24 18:18:54 +00001662 if (VG_CLO_STREQN(7, arg, "--tool=") ||
1663 VG_CLO_STREQN(7, arg, "--skin="))
fitzhardinge98abfc72003-12-16 02:05:15 +00001664 continue;
nethercote71980f02004-01-24 18:18:54 +00001665 if (VG_CLO_STREQN(7, arg, "--exec="))
fitzhardinge98abfc72003-12-16 02:05:15 +00001666 continue;
1667
nethercote71980f02004-01-24 18:18:54 +00001668 if ( VG_CLO_STREQ(arg, "--"))
fitzhardinge98abfc72003-12-16 02:05:15 +00001669 continue;
nethercote27fec902004-06-16 21:26:32 +00001670
nethercote71980f02004-01-24 18:18:54 +00001671 else if (VG_CLO_STREQ(arg, "-v") ||
1672 VG_CLO_STREQ(arg, "--verbose"))
sewardjde4a1d02002-03-22 01:27:54 +00001673 VG_(clo_verbosity)++;
nethercote27fec902004-06-16 21:26:32 +00001674
nethercote71980f02004-01-24 18:18:54 +00001675 else if (VG_CLO_STREQ(arg, "-q") ||
1676 VG_CLO_STREQ(arg, "--quiet"))
sewardjde4a1d02002-03-22 01:27:54 +00001677 VG_(clo_verbosity)--;
1678
nethercote27fec902004-06-16 21:26:32 +00001679 else VG_BOOL_CLO("--branchpred", VG_(clo_branchpred))
1680 else VG_BOOL_CLO("--chain-bb", VG_(clo_chain_bb))
1681 else VG_BOOL_CLO("--db-attach", VG_(clo_db_attach))
1682 else VG_BOOL_CLO("--demangle", VG_(clo_demangle))
1683 else VG_BOOL_CLO("--error-limit", VG_(clo_error_limit))
1684 else VG_BOOL_CLO("--gen-suppressions", VG_(clo_gen_suppressions))
1685 else VG_BOOL_CLO("--lowlat-signals", VG_(clo_lowlat_signals))
1686 else VG_BOOL_CLO("--lowlat-syscalls", VG_(clo_lowlat_syscalls))
1687 else VG_BOOL_CLO("--optimise", VG_(clo_optimise))
1688 else VG_BOOL_CLO("--pointercheck", VG_(clo_pointercheck))
1689 else VG_BOOL_CLO("--profile", VG_(clo_profile))
1690 else VG_BOOL_CLO("--run-libc-freeres", VG_(clo_run_libc_freeres))
1691 else VG_BOOL_CLO("--show-below-main", VG_(clo_show_below_main))
1692 else VG_BOOL_CLO("--single-step", VG_(clo_single_step))
1693 else VG_BOOL_CLO("--track-fds", VG_(clo_track_fds))
1694 else VG_BOOL_CLO("--trace-children", VG_(clo_trace_children))
1695 else VG_BOOL_CLO("--trace-sched", VG_(clo_trace_sched))
1696 else VG_BOOL_CLO("--trace-signals", VG_(clo_trace_signals))
1697 else VG_BOOL_CLO("--trace-symtab", VG_(clo_trace_symtab))
1698 else VG_BOOL_CLO("--trace-syscalls", VG_(clo_trace_syscalls))
1699 else VG_BOOL_CLO("--wait-for-gdb", VG_(clo_wait_for_gdb))
sewardj72f98ff2002-06-13 17:23:38 +00001700
nethercote27fec902004-06-16 21:26:32 +00001701 else VG_STR_CLO ("--db-command", VG_(clo_db_command))
1702 else VG_STR_CLO ("--weird-hacks", VG_(clo_weird_hacks))
sewardjde4a1d02002-03-22 01:27:54 +00001703
nethercote27fec902004-06-16 21:26:32 +00001704 else VG_NUM_CLO ("--dump-error", VG_(clo_dump_error))
1705 else VG_NUM_CLO ("--input-fd", VG_(clo_input_fd))
1706 else VG_NUM_CLO ("--sanity-level", VG_(clo_sanity_level))
1707 else VG_NUM_CLO ("--signal­polltime", VG_(clo_signal_polltime))
1708 else VG_BNUM_CLO("--num-callers", VG_(clo_backtrace_size), 1,
1709 VG_DEEPEST_BACKTRACE)
sewardjde4a1d02002-03-22 01:27:54 +00001710
nethercotef8548672004-06-21 12:42:35 +00001711 // for backwards compatibility, replaced by --log-fd
nethercote71980f02004-01-24 18:18:54 +00001712 else if (VG_CLO_STREQN(13, arg, "--logfile-fd=")) {
nethercotef8548672004-06-21 12:42:35 +00001713 VG_(clo_log_to) = VgLogTo_Fd;
1714 VG_(clo_log_name) = NULL;
1715 eventually_log_fd = (Int)VG_(atoll)(&arg[13]);
1716 }
1717 else if (VG_CLO_STREQN(9, arg, "--log-fd=")) {
1718 VG_(clo_log_to) = VgLogTo_Fd;
1719 VG_(clo_log_name) = NULL;
1720 eventually_log_fd = (Int)VG_(atoll)(&arg[9]);
sewardj4cf05692002-10-27 20:28:29 +00001721 }
1722
nethercotef8548672004-06-21 12:42:35 +00001723 // for backwards compatibility, replaced by --log-file
nethercote71980f02004-01-24 18:18:54 +00001724 else if (VG_CLO_STREQN(10, arg, "--logfile=")) {
nethercotef8548672004-06-21 12:42:35 +00001725 VG_(clo_log_to) = VgLogTo_File;
1726 VG_(clo_log_name) = &arg[10];
1727 }
1728 else if (VG_CLO_STREQN(11, arg, "--log-file=")) {
1729 VG_(clo_log_to) = VgLogTo_File;
1730 VG_(clo_log_name) = &arg[11];
sewardj4cf05692002-10-27 20:28:29 +00001731 }
sewardjde4a1d02002-03-22 01:27:54 +00001732
nethercotef8548672004-06-21 12:42:35 +00001733 // for backwards compatibility, replaced by --log-socket
nethercote71980f02004-01-24 18:18:54 +00001734 else if (VG_CLO_STREQN(12, arg, "--logsocket=")) {
nethercotef8548672004-06-21 12:42:35 +00001735 VG_(clo_log_to) = VgLogTo_Socket;
1736 VG_(clo_log_name) = &arg[12];
1737 }
1738 else if (VG_CLO_STREQN(13, arg, "--log-socket=")) {
1739 VG_(clo_log_to) = VgLogTo_Socket;
1740 VG_(clo_log_name) = &arg[13];
sewardj73cf3bc2002-11-03 03:20:15 +00001741 }
1742
nethercote71980f02004-01-24 18:18:54 +00001743 else if (VG_CLO_STREQN(15, arg, "--suppressions=")) {
sewardjde4a1d02002-03-22 01:27:54 +00001744 if (VG_(clo_n_suppressions) >= VG_CLO_MAX_SFILES) {
njn25e49d8e72002-09-23 09:36:25 +00001745 VG_(message)(Vg_UserMsg, "Too many suppression files specified.");
sewardjde4a1d02002-03-22 01:27:54 +00001746 VG_(message)(Vg_UserMsg,
1747 "Increase VG_CLO_MAX_SFILES and recompile.");
nethercote71980f02004-01-24 18:18:54 +00001748 VG_(bad_option)(arg);
sewardjde4a1d02002-03-22 01:27:54 +00001749 }
nethercote71980f02004-01-24 18:18:54 +00001750 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = &arg[15];
sewardjde4a1d02002-03-22 01:27:54 +00001751 VG_(clo_n_suppressions)++;
1752 }
sewardjde4a1d02002-03-22 01:27:54 +00001753
njn25e49d8e72002-09-23 09:36:25 +00001754 /* "vwxyz" --> 000zyxwv (binary) */
nethercote71980f02004-01-24 18:18:54 +00001755 else if (VG_CLO_STREQN(16, arg, "--trace-codegen=")) {
njn25e49d8e72002-09-23 09:36:25 +00001756 Int j;
nethercote71980f02004-01-24 18:18:54 +00001757 char* opt = & arg[16];
njn25e49d8e72002-09-23 09:36:25 +00001758
1759 if (5 != VG_(strlen)(opt)) {
1760 VG_(message)(Vg_UserMsg,
1761 "--trace-codegen argument must have 5 digits");
nethercote71980f02004-01-24 18:18:54 +00001762 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001763 }
1764 for (j = 0; j < 5; j++) {
1765 if ('0' == opt[j]) { /* do nothing */ }
1766 else if ('1' == opt[j]) VG_(clo_trace_codegen) |= (1 << j);
1767 else {
1768 VG_(message)(Vg_UserMsg, "--trace-codegen argument can only "
1769 "contain 0s and 1s");
nethercote71980f02004-01-24 18:18:54 +00001770 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001771 }
1772 }
1773 }
sewardjde4a1d02002-03-22 01:27:54 +00001774
nethercote71980f02004-01-24 18:18:54 +00001775 else if (VG_CLO_STREQ(arg, "--trace-pthread=none"))
sewardj45b4b372002-04-16 22:50:32 +00001776 VG_(clo_trace_pthread_level) = 0;
nethercote71980f02004-01-24 18:18:54 +00001777 else if (VG_CLO_STREQ(arg, "--trace-pthread=some"))
sewardj45b4b372002-04-16 22:50:32 +00001778 VG_(clo_trace_pthread_level) = 1;
nethercote71980f02004-01-24 18:18:54 +00001779 else if (VG_CLO_STREQ(arg, "--trace-pthread=all"))
sewardj45b4b372002-04-16 22:50:32 +00001780 VG_(clo_trace_pthread_level) = 2;
sewardj8937c812002-04-12 20:12:20 +00001781
nethercote71980f02004-01-24 18:18:54 +00001782 else if ( ! VG_(needs).command_line_options
1783 || ! SK_(process_cmd_line_option)(arg) ) {
nethercotef4928da2004-06-15 10:54:40 +00001784 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001785 }
sewardjde4a1d02002-03-22 01:27:54 +00001786 }
1787
nethercote27fec902004-06-16 21:26:32 +00001788 // Check various option values
1789
njnf9ebf672003-05-12 21:41:30 +00001790 if (VG_(clo_verbosity) < 0)
sewardjde4a1d02002-03-22 01:27:54 +00001791 VG_(clo_verbosity) = 0;
1792
nethercote04d0fbc2004-01-26 16:48:06 +00001793 if (VG_(clo_db_attach) && VG_(clo_trace_children)) {
sewardjde4a1d02002-03-22 01:27:54 +00001794 VG_(message)(Vg_UserMsg, "");
1795 VG_(message)(Vg_UserMsg,
nethercote04d0fbc2004-01-26 16:48:06 +00001796 "--db-attach=yes conflicts with --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001797 VG_(message)(Vg_UserMsg,
1798 "Please choose one or the other, but not both.");
nethercote04d0fbc2004-01-26 16:48:06 +00001799 VG_(bad_option)("--db-attach=yes and --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001800 }
1801
nethercotef8548672004-06-21 12:42:35 +00001802 /* Set up logging now. After this is done, VG_(clo_log_fd)
sewardj4cf05692002-10-27 20:28:29 +00001803 should be connected to whatever sink has been selected, and we
1804 indiscriminately chuck stuff into it without worrying what the
1805 nature of it is. Oh the wonder of Unix streams. */
1806
nethercotee1730692003-11-20 10:38:07 +00001807 /* So far we should be still attached to stdout, so we can show on
sewardj4cf05692002-10-27 20:28:29 +00001808 the terminal any problems to do with processing command line
1809 opts. */
nethercotef8548672004-06-21 12:42:35 +00001810 vg_assert(VG_(clo_log_fd) == 1 /* stdout */);
sewardj73cf3bc2002-11-03 03:20:15 +00001811 vg_assert(VG_(logging_to_filedes) == True);
sewardj4cf05692002-10-27 20:28:29 +00001812
1813 switch (VG_(clo_log_to)) {
sewardj73cf3bc2002-11-03 03:20:15 +00001814
sewardj4cf05692002-10-27 20:28:29 +00001815 case VgLogTo_Fd:
nethercotef8548672004-06-21 12:42:35 +00001816 vg_assert(VG_(clo_log_name) == NULL);
1817 VG_(clo_log_fd) = eventually_log_fd;
sewardj4cf05692002-10-27 20:28:29 +00001818 break;
sewardj73cf3bc2002-11-03 03:20:15 +00001819
sewardj4cf05692002-10-27 20:28:29 +00001820 case VgLogTo_File: {
1821 Char logfilename[1000];
jsgff3c3f1a2003-10-14 22:13:28 +00001822 Int seq = 0;
1823 Int pid = VG_(getpid)();
1824
nethercotef8548672004-06-21 12:42:35 +00001825 vg_assert(VG_(clo_log_name) != NULL);
1826 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
jsgff3c3f1a2003-10-14 22:13:28 +00001827
nethercote71980f02004-01-24 18:18:54 +00001828 for (;;) {
jsgff3c3f1a2003-10-14 22:13:28 +00001829 if (seq == 0)
1830 VG_(sprintf)(logfilename, "%s.pid%d",
nethercotef8548672004-06-21 12:42:35 +00001831 VG_(clo_log_name), pid );
jsgff3c3f1a2003-10-14 22:13:28 +00001832 else
1833 VG_(sprintf)(logfilename, "%s.pid%d.%d",
nethercotef8548672004-06-21 12:42:35 +00001834 VG_(clo_log_name), pid, seq );
jsgff3c3f1a2003-10-14 22:13:28 +00001835 seq++;
1836
nethercotef8548672004-06-21 12:42:35 +00001837 eventually_log_fd
jsgff3c3f1a2003-10-14 22:13:28 +00001838 = VG_(open)(logfilename,
1839 VKI_O_CREAT|VKI_O_WRONLY|VKI_O_EXCL|VKI_O_TRUNC,
1840 VKI_S_IRUSR|VKI_S_IWUSR);
nethercotef8548672004-06-21 12:42:35 +00001841 if (eventually_log_fd >= 0) {
1842 VG_(clo_log_fd) = VG_(safe_fd)(eventually_log_fd);
jsgff3c3f1a2003-10-14 22:13:28 +00001843 break;
1844 } else {
nethercotef8548672004-06-21 12:42:35 +00001845 if (eventually_log_fd != -VKI_EEXIST) {
jsgff3c3f1a2003-10-14 22:13:28 +00001846 VG_(message)(Vg_UserMsg,
1847 "Can't create/open log file `%s.pid%d'; giving up!",
nethercotef8548672004-06-21 12:42:35 +00001848 VG_(clo_log_name), pid);
jsgff3c3f1a2003-10-14 22:13:28 +00001849 VG_(bad_option)(
nethercotef8548672004-06-21 12:42:35 +00001850 "--log-file=<file> didn't work out for some reason.");
jsgff3c3f1a2003-10-14 22:13:28 +00001851 break;
1852 }
1853 }
1854 }
sewardj4cf05692002-10-27 20:28:29 +00001855 break;
sewardj73cf3bc2002-11-03 03:20:15 +00001856 }
1857
1858 case VgLogTo_Socket: {
nethercotef8548672004-06-21 12:42:35 +00001859 vg_assert(VG_(clo_log_name) != NULL);
1860 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
1861 eventually_log_fd = VG_(connect_via_socket)( VG_(clo_log_name) );
1862 if (eventually_log_fd == -1) {
sewardj73cf3bc2002-11-03 03:20:15 +00001863 VG_(message)(Vg_UserMsg,
nethercotef8548672004-06-21 12:42:35 +00001864 "Invalid --log-socket=ipaddr or --log-socket=ipaddr:port spec");
sewardj73cf3bc2002-11-03 03:20:15 +00001865 VG_(message)(Vg_UserMsg,
nethercotef8548672004-06-21 12:42:35 +00001866 "of `%s'; giving up!", VG_(clo_log_name) );
sewardj73cf3bc2002-11-03 03:20:15 +00001867 VG_(bad_option)(
nethercotef8548672004-06-21 12:42:35 +00001868 "--log-socket=");
sewardj4cf05692002-10-27 20:28:29 +00001869 }
nethercotef8548672004-06-21 12:42:35 +00001870 if (eventually_log_fd == -2) {
sewardj73cf3bc2002-11-03 03:20:15 +00001871 VG_(message)(Vg_UserMsg,
sewardj570f8902002-11-03 11:44:36 +00001872 "valgrind: failed to connect to logging server `%s'.",
nethercotef8548672004-06-21 12:42:35 +00001873 VG_(clo_log_name) );
sewardj570f8902002-11-03 11:44:36 +00001874 VG_(message)(Vg_UserMsg,
1875 "Log messages will sent to stderr instead." );
1876 VG_(message)(Vg_UserMsg,
1877 "" );
1878 /* We don't change anything here. */
1879 } else {
nethercotef8548672004-06-21 12:42:35 +00001880 vg_assert(eventually_log_fd > 0);
1881 VG_(clo_log_fd) = eventually_log_fd;
sewardj570f8902002-11-03 11:44:36 +00001882 VG_(logging_to_filedes) = False;
1883 }
sewardj73cf3bc2002-11-03 03:20:15 +00001884 break;
1885 }
1886
sewardj4cf05692002-10-27 20:28:29 +00001887 }
1888
nethercotef8548672004-06-21 12:42:35 +00001889 /* Move log_fd into the safe range, so it doesn't conflict with any app fds */
thughesad1c9562004-06-26 11:27:52 +00001890 eventually_log_fd = VG_(fcntl)(VG_(clo_log_fd), VKI_F_DUPFD, VG_(fd_hard_limit));
nethercotef8548672004-06-21 12:42:35 +00001891 if (eventually_log_fd < 0)
jsgf855d93d2003-10-13 22:26:55 +00001892 VG_(message)(Vg_UserMsg, "valgrind: failed to move logfile fd into safe range");
1893 else {
nethercotef8548672004-06-21 12:42:35 +00001894 VG_(clo_log_fd) = eventually_log_fd;
1895 VG_(fcntl)(VG_(clo_log_fd), VKI_F_SETFD, VKI_FD_CLOEXEC);
jsgf855d93d2003-10-13 22:26:55 +00001896 }
1897
sewardj4cf05692002-10-27 20:28:29 +00001898 /* Ok, the logging sink is running now. Print a suitable preamble.
1899 If logging to file or a socket, write details of parent PID and
1900 command line args, to help people trying to interpret the
1901 results of a run which encompasses multiple processes. */
sewardjde4a1d02002-03-22 01:27:54 +00001902
sewardj83adf412002-05-01 01:25:45 +00001903 if (VG_(clo_verbosity > 0)) {
nethercote996901a2004-08-03 13:29:09 +00001904 /* Tool details */
njnd04b7c62002-10-03 14:05:52 +00001905 VG_(message)(Vg_UserMsg, "%s%s%s, %s for x86-linux.",
1906 VG_(details).name,
1907 NULL == VG_(details).version ? "" : "-",
1908 NULL == VG_(details).version
1909 ? (Char*)"" : VG_(details).version,
1910 VG_(details).description);
1911 VG_(message)(Vg_UserMsg, "%s", VG_(details).copyright_author);
sewardj3b2736a2002-03-24 12:18:35 +00001912
njnd04b7c62002-10-03 14:05:52 +00001913 /* Core details */
1914 VG_(message)(Vg_UserMsg,
njn3e884182003-04-15 13:03:23 +00001915 "Using valgrind-%s, a program supervision framework for x86-linux.",
sewardj4aa62ba2002-10-05 15:49:27 +00001916 VERSION);
sewardjde4a1d02002-03-22 01:27:54 +00001917 VG_(message)(Vg_UserMsg,
nethercote08fa9a72004-07-16 17:44:00 +00001918 "Copyright (C) 2000-2004, and GNU GPL'd, by Julian Seward et al.");
njnd04b7c62002-10-03 14:05:52 +00001919 }
1920
nethercotec1e395d2003-11-10 13:26:49 +00001921 if (VG_(clo_verbosity) > 0 && VG_(clo_log_to) != VgLogTo_Fd) {
sewardj4cf05692002-10-27 20:28:29 +00001922 VG_(message)(Vg_UserMsg, "");
1923 VG_(message)(Vg_UserMsg,
1924 "My PID = %d, parent PID = %d. Prog and args are:",
1925 VG_(getpid)(), VG_(getppid)() );
1926 for (i = 0; i < VG_(client_argc); i++)
1927 VG_(message)(Vg_UserMsg, " %s", VG_(client_argv)[i]);
1928 }
1929
sewardjde4a1d02002-03-22 01:27:54 +00001930 if (VG_(clo_verbosity) > 1) {
nethercotea70f7352004-04-18 12:08:46 +00001931 Int fd;
sewardj4cf05692002-10-27 20:28:29 +00001932 if (VG_(clo_log_to) != VgLogTo_Fd)
1933 VG_(message)(Vg_UserMsg, "");
fitzhardinge98abfc72003-12-16 02:05:15 +00001934 VG_(message)(Vg_UserMsg, "Valgrind library directory: %s", VG_(libdir));
njn86dc2bc2003-09-09 07:26:21 +00001935 VG_(message)(Vg_UserMsg, "Command line");
1936 for (i = 0; i < VG_(client_argc); i++)
1937 VG_(message)(Vg_UserMsg, " %s", VG_(client_argv)[i]);
1938
sewardjde4a1d02002-03-22 01:27:54 +00001939 VG_(message)(Vg_UserMsg, "Startup, with flags:");
nethercote71980f02004-01-24 18:18:54 +00001940 for (i = 1; i < VG_(vg_argc); i++) {
1941 VG_(message)(Vg_UserMsg, " %s", VG_(vg_argv)[i]);
sewardjde4a1d02002-03-22 01:27:54 +00001942 }
nethercotea70f7352004-04-18 12:08:46 +00001943
1944 VG_(message)(Vg_UserMsg, "Contents of /proc/version:");
1945 fd = VG_(open) ( "/proc/version", VKI_O_RDONLY, 0 );
1946 if (fd < 0) {
1947 VG_(message)(Vg_UserMsg, " can't open /proc/version");
1948 } else {
1949 #define BUF_LEN 256
1950 Char version_buf[BUF_LEN];
1951 Int n = VG_(read) ( fd, version_buf, BUF_LEN );
1952 vg_assert(n <= 256);
1953 if (n > 0) {
1954 version_buf[n-1] = '\0';
1955 VG_(message)(Vg_UserMsg, " %s", version_buf);
1956 } else {
1957 VG_(message)(Vg_UserMsg, " (empty?)");
1958 }
1959 VG_(close)(fd);
1960 #undef BUF_LEN
1961 }
sewardjde4a1d02002-03-22 01:27:54 +00001962 }
1963
fitzhardinge98abfc72003-12-16 02:05:15 +00001964 if (VG_(clo_n_suppressions) < VG_CLO_MAX_SFILES-1 &&
njn25e49d8e72002-09-23 09:36:25 +00001965 (VG_(needs).core_errors || VG_(needs).skin_errors)) {
nethercote996901a2004-08-03 13:29:09 +00001966 /* If there are no suppression files specified and the tool
fitzhardinge98abfc72003-12-16 02:05:15 +00001967 needs one, load the default */
1968 static const Char default_supp[] = "default.supp";
1969 Int len = VG_(strlen)(VG_(libdir)) + 1 + sizeof(default_supp);
1970 Char *buf = VG_(arena_malloc)(VG_AR_CORE, len);
1971 VG_(sprintf)(buf, "%s/%s", VG_(libdir), default_supp);
1972 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = buf;
1973 VG_(clo_n_suppressions)++;
sewardjde4a1d02002-03-22 01:27:54 +00001974 }
sewardj4cf05692002-10-27 20:28:29 +00001975
njn6a230532003-07-21 10:38:23 +00001976 if (VG_(clo_gen_suppressions) &&
1977 !VG_(needs).core_errors && !VG_(needs).skin_errors) {
nethercotef4928da2004-06-15 10:54:40 +00001978 VG_(message)(Vg_UserMsg,
1979 "Can't use --gen-suppressions=yes with this tool,");
1980 VG_(message)(Vg_UserMsg,
1981 "as it doesn't generate errors.");
1982 VG_(bad_option)("--gen-suppressions=yes");
njn6a230532003-07-21 10:38:23 +00001983 }
sewardjde4a1d02002-03-22 01:27:54 +00001984}
1985
sewardjde4a1d02002-03-22 01:27:54 +00001986
nethercote71980f02004-01-24 18:18:54 +00001987/*====================================================================*/
1988/*=== File descriptor setup ===*/
1989/*====================================================================*/
1990
1991static void setup_file_descriptors(void)
1992{
1993 struct vki_rlimit rl;
1994
1995 /* Get the current file descriptor limits. */
1996 if (VG_(getrlimit)(VKI_RLIMIT_NOFILE, &rl) < 0) {
1997 rl.rlim_cur = 1024;
1998 rl.rlim_max = 1024;
1999 }
2000
2001 /* Work out where to move the soft limit to. */
2002 if (rl.rlim_cur + VG_N_RESERVED_FDS <= rl.rlim_max) {
2003 rl.rlim_cur = rl.rlim_cur + VG_N_RESERVED_FDS;
2004 } else {
2005 rl.rlim_cur = rl.rlim_max;
2006 }
2007
2008 /* Reserve some file descriptors for our use. */
thughesad1c9562004-06-26 11:27:52 +00002009 VG_(fd_soft_limit) = rl.rlim_cur - VG_N_RESERVED_FDS;
2010 VG_(fd_hard_limit) = rl.rlim_cur - VG_N_RESERVED_FDS;
nethercote71980f02004-01-24 18:18:54 +00002011
2012 /* Update the soft limit. */
2013 VG_(setrlimit)(VKI_RLIMIT_NOFILE, &rl);
2014
2015 if (VG_(vgexecfd) != -1)
2016 VG_(vgexecfd) = VG_(safe_fd)( VG_(vgexecfd) );
2017 if (VG_(clexecfd) != -1)
2018 VG_(clexecfd) = VG_(safe_fd)( VG_(clexecfd) );
2019}
2020
2021
2022/*====================================================================*/
nethercote1d447092004-02-01 17:29:59 +00002023/*=== baseBlock: definition + setup ===*/
nethercote71980f02004-01-24 18:18:54 +00002024/*====================================================================*/
2025
2026/* The variables storing offsets. */
2027
2028#define INVALID_OFFSET (-1)
2029
2030Int VGOFF_(m_eax) = INVALID_OFFSET;
2031Int VGOFF_(m_ecx) = INVALID_OFFSET;
2032Int VGOFF_(m_edx) = INVALID_OFFSET;
2033Int VGOFF_(m_ebx) = INVALID_OFFSET;
2034Int VGOFF_(m_esp) = INVALID_OFFSET;
2035Int VGOFF_(m_ebp) = INVALID_OFFSET;
2036Int VGOFF_(m_esi) = INVALID_OFFSET;
2037Int VGOFF_(m_edi) = INVALID_OFFSET;
2038Int VGOFF_(m_eflags) = INVALID_OFFSET;
2039Int VGOFF_(m_dflag) = INVALID_OFFSET;
2040Int VGOFF_(m_ssestate) = INVALID_OFFSET;
2041Int VGOFF_(ldt) = INVALID_OFFSET;
2042Int VGOFF_(tls) = INVALID_OFFSET;
2043Int VGOFF_(m_cs) = INVALID_OFFSET;
2044Int VGOFF_(m_ss) = INVALID_OFFSET;
2045Int VGOFF_(m_ds) = INVALID_OFFSET;
2046Int VGOFF_(m_es) = INVALID_OFFSET;
2047Int VGOFF_(m_fs) = INVALID_OFFSET;
2048Int VGOFF_(m_gs) = INVALID_OFFSET;
2049Int VGOFF_(m_eip) = INVALID_OFFSET;
2050Int VGOFF_(spillslots) = INVALID_OFFSET;
2051Int VGOFF_(sh_eax) = INVALID_OFFSET;
2052Int VGOFF_(sh_ecx) = INVALID_OFFSET;
2053Int VGOFF_(sh_edx) = INVALID_OFFSET;
2054Int VGOFF_(sh_ebx) = INVALID_OFFSET;
2055Int VGOFF_(sh_esp) = INVALID_OFFSET;
2056Int VGOFF_(sh_ebp) = INVALID_OFFSET;
2057Int VGOFF_(sh_esi) = INVALID_OFFSET;
2058Int VGOFF_(sh_edi) = INVALID_OFFSET;
2059Int VGOFF_(sh_eflags) = INVALID_OFFSET;
2060
2061Int VGOFF_(helper_idiv_64_32) = INVALID_OFFSET;
2062Int VGOFF_(helper_div_64_32) = INVALID_OFFSET;
2063Int VGOFF_(helper_idiv_32_16) = INVALID_OFFSET;
2064Int VGOFF_(helper_div_32_16) = INVALID_OFFSET;
2065Int VGOFF_(helper_idiv_16_8) = INVALID_OFFSET;
2066Int VGOFF_(helper_div_16_8) = INVALID_OFFSET;
2067Int VGOFF_(helper_imul_32_64) = INVALID_OFFSET;
2068Int VGOFF_(helper_mul_32_64) = INVALID_OFFSET;
2069Int VGOFF_(helper_imul_16_32) = INVALID_OFFSET;
2070Int VGOFF_(helper_mul_16_32) = INVALID_OFFSET;
2071Int VGOFF_(helper_imul_8_16) = INVALID_OFFSET;
2072Int VGOFF_(helper_mul_8_16) = INVALID_OFFSET;
2073Int VGOFF_(helper_CLD) = INVALID_OFFSET;
2074Int VGOFF_(helper_STD) = INVALID_OFFSET;
2075Int VGOFF_(helper_get_dirflag) = INVALID_OFFSET;
2076Int VGOFF_(helper_CLC) = INVALID_OFFSET;
2077Int VGOFF_(helper_STC) = INVALID_OFFSET;
nethercote1018bdd2004-02-11 23:33:29 +00002078Int VGOFF_(helper_CMC) = INVALID_OFFSET;
nethercote71980f02004-01-24 18:18:54 +00002079Int VGOFF_(helper_shldl) = INVALID_OFFSET;
2080Int VGOFF_(helper_shldw) = INVALID_OFFSET;
2081Int VGOFF_(helper_shrdl) = INVALID_OFFSET;
2082Int VGOFF_(helper_shrdw) = INVALID_OFFSET;
2083Int VGOFF_(helper_IN) = INVALID_OFFSET;
2084Int VGOFF_(helper_OUT) = INVALID_OFFSET;
2085Int VGOFF_(helper_RDTSC) = INVALID_OFFSET;
2086Int VGOFF_(helper_CPUID) = INVALID_OFFSET;
2087Int VGOFF_(helper_BSWAP) = INVALID_OFFSET;
nethercote1018bdd2004-02-11 23:33:29 +00002088Int VGOFF_(helper_bsfw) = INVALID_OFFSET;
2089Int VGOFF_(helper_bsfl) = INVALID_OFFSET;
2090Int VGOFF_(helper_bsrw) = INVALID_OFFSET;
2091Int VGOFF_(helper_bsrl) = INVALID_OFFSET;
nethercote71980f02004-01-24 18:18:54 +00002092Int VGOFF_(helper_fstsw_AX) = INVALID_OFFSET;
2093Int VGOFF_(helper_SAHF) = INVALID_OFFSET;
2094Int VGOFF_(helper_LAHF) = INVALID_OFFSET;
2095Int VGOFF_(helper_DAS) = INVALID_OFFSET;
2096Int VGOFF_(helper_DAA) = INVALID_OFFSET;
nethercote1018bdd2004-02-11 23:33:29 +00002097Int VGOFF_(helper_AAS) = INVALID_OFFSET;
2098Int VGOFF_(helper_AAA) = INVALID_OFFSET;
2099Int VGOFF_(helper_AAD) = INVALID_OFFSET;
2100Int VGOFF_(helper_AAM) = INVALID_OFFSET;
nethercote71980f02004-01-24 18:18:54 +00002101Int VGOFF_(helper_cmpxchg8b) = INVALID_OFFSET;
2102Int VGOFF_(helper_undefined_instruction) = INVALID_OFFSET;
2103
2104/* MAX_NONCOMPACT_HELPERS can be increased easily. If MAX_COMPACT_HELPERS is
2105 * increased too much, they won't really be compact any more... */
2106#define MAX_COMPACT_HELPERS 8
2107#define MAX_NONCOMPACT_HELPERS 50
2108
nethercote81f9a6f2004-08-03 15:45:46 +00002109/* For storing tool-specific helpers, determined at runtime. The addr
2110 * and offset arrays together form a (addr, offset) map that allows a
2111 * helper's baseBlock offset to be computed from its address. It's done
2112 * like this so CCALLs can use the function address rather than having to
2113 * muck around with offsets. */
2114static UInt VG_(n_compact_helpers) = 0;
2115static UInt VG_(n_noncompact_helpers) = 0;
2116static Addr VG_(compact_helper_addrs) [MAX_COMPACT_HELPERS];
2117static Int VG_(compact_helper_offsets)[MAX_COMPACT_HELPERS];
2118static Addr VG_(noncompact_helper_addrs) [MAX_NONCOMPACT_HELPERS];
2119static Int VG_(noncompact_helper_offsets)[MAX_NONCOMPACT_HELPERS];
nethercote71980f02004-01-24 18:18:54 +00002120
2121/* This is the actual defn of baseblock. */
2122UInt VG_(baseBlock)[VG_BASEBLOCK_WORDS];
2123
nethercote71980f02004-01-24 18:18:54 +00002124/* Words. */
2125static Int baB_off = 0;
2126
2127
nethercote71980f02004-01-24 18:18:54 +00002128/* Returns the offset, in words. */
2129static Int alloc_BaB ( Int words )
sewardjde4a1d02002-03-22 01:27:54 +00002130{
nethercote71980f02004-01-24 18:18:54 +00002131 Int off = baB_off;
2132 baB_off += words;
2133 if (baB_off >= VG_BASEBLOCK_WORDS)
2134 VG_(core_panic)( "alloc_BaB: baseBlock is too small");
sewardjde4a1d02002-03-22 01:27:54 +00002135
nethercote71980f02004-01-24 18:18:54 +00002136 return off;
sewardjde4a1d02002-03-22 01:27:54 +00002137}
2138
nethercote71980f02004-01-24 18:18:54 +00002139/* Align offset, in *bytes* */
2140static void align_BaB ( UInt align )
njn25e49d8e72002-09-23 09:36:25 +00002141{
nethercote71980f02004-01-24 18:18:54 +00002142 vg_assert(2 == align || 4 == align || 8 == align || 16 == align);
2143 baB_off += (align-1);
2144 baB_off &= ~(align-1);
njn25e49d8e72002-09-23 09:36:25 +00002145}
2146
nethercote71980f02004-01-24 18:18:54 +00002147/* Allocate 1 word in baseBlock and set it to the given value. */
2148static Int alloc_BaB_1_set ( Addr a )
njn25e49d8e72002-09-23 09:36:25 +00002149{
nethercote71980f02004-01-24 18:18:54 +00002150 Int off = alloc_BaB(1);
2151 VG_(baseBlock)[off] = (UInt)a;
2152 return off;
njn25e49d8e72002-09-23 09:36:25 +00002153}
2154
nethercote71980f02004-01-24 18:18:54 +00002155/* Registers a function in compact_helper_addrs; compact_helper_offsets is
2156 filled in later. */
2157void VG_(register_compact_helper)(Addr a)
sewardjde4a1d02002-03-22 01:27:54 +00002158{
nethercote71980f02004-01-24 18:18:54 +00002159 if (MAX_COMPACT_HELPERS <= VG_(n_compact_helpers)) {
2160 VG_(printf)("Can only register %d compact helpers\n",
2161 MAX_COMPACT_HELPERS);
2162 VG_(core_panic)("Too many compact helpers registered");
2163 }
2164 VG_(compact_helper_addrs)[VG_(n_compact_helpers)] = a;
2165 VG_(n_compact_helpers)++;
2166}
2167
2168/* Registers a function in noncompact_helper_addrs; noncompact_helper_offsets
2169 * is filled in later.
2170 */
2171void VG_(register_noncompact_helper)(Addr a)
2172{
2173 if (MAX_NONCOMPACT_HELPERS <= VG_(n_noncompact_helpers)) {
2174 VG_(printf)("Can only register %d non-compact helpers\n",
2175 MAX_NONCOMPACT_HELPERS);
2176 VG_(printf)("Try increasing MAX_NON_COMPACT_HELPERS\n");
2177 VG_(core_panic)("Too many non-compact helpers registered");
2178 }
2179 VG_(noncompact_helper_addrs)[VG_(n_noncompact_helpers)] = a;
2180 VG_(n_noncompact_helpers)++;
2181}
2182
nethercote996901a2004-08-03 13:29:09 +00002183/* Allocate offsets in baseBlock for the tool helpers */
nethercote71980f02004-01-24 18:18:54 +00002184static
2185void assign_helpers_in_baseBlock(UInt n, Int offsets[], Addr addrs[])
2186{
2187 UInt i;
2188 for (i = 0; i < n; i++)
2189 offsets[i] = alloc_BaB_1_set( addrs[i] );
2190}
2191
2192Bool VG_(need_to_handle_esp_assignment)(void)
2193{
2194 return ( VG_(defined_new_mem_stack_4)() ||
2195 VG_(defined_die_mem_stack_4)() ||
2196 VG_(defined_new_mem_stack_8)() ||
2197 VG_(defined_die_mem_stack_8)() ||
2198 VG_(defined_new_mem_stack_12)() ||
2199 VG_(defined_die_mem_stack_12)() ||
2200 VG_(defined_new_mem_stack_16)() ||
2201 VG_(defined_die_mem_stack_16)() ||
2202 VG_(defined_new_mem_stack_32)() ||
2203 VG_(defined_die_mem_stack_32)() ||
2204 VG_(defined_new_mem_stack)() ||
2205 VG_(defined_die_mem_stack)()
2206 );
2207}
2208
2209/* Here we assign actual offsets. It's important to get the most
2210 popular referents within 128 bytes of the start, so we can take
2211 advantage of short addressing modes relative to %ebp. Popularity
2212 of offsets was measured on 22 Feb 02 running a KDE application, and
2213 the slots rearranged accordingly, with a 1.5% reduction in total
2214 size of translations. */
2215static void init_baseBlock ( Addr client_eip, Addr esp_at_startup )
2216{
2217 /* Those with offsets under 128 are carefully chosen. */
2218
2219 /* WORD offsets in this column */
2220 /* 0 */ VGOFF_(m_eax) = alloc_BaB_1_set(0);
2221 /* 1 */ VGOFF_(m_ecx) = alloc_BaB_1_set(0);
2222 /* 2 */ VGOFF_(m_edx) = alloc_BaB_1_set(0);
2223 /* 3 */ VGOFF_(m_ebx) = alloc_BaB_1_set(0);
2224 /* 4 */ VGOFF_(m_esp) = alloc_BaB_1_set(esp_at_startup);
2225 /* 5 */ VGOFF_(m_ebp) = alloc_BaB_1_set(0);
2226 /* 6 */ VGOFF_(m_esi) = alloc_BaB_1_set(0);
2227 /* 7 */ VGOFF_(m_edi) = alloc_BaB_1_set(0);
2228 /* 8 */ VGOFF_(m_eflags) = alloc_BaB_1_set(0);
2229
2230 if (VG_(needs).shadow_regs) {
2231 /* 9 */ VGOFF_(sh_eax) = alloc_BaB_1_set(0);
2232 /* 10 */ VGOFF_(sh_ecx) = alloc_BaB_1_set(0);
2233 /* 11 */ VGOFF_(sh_edx) = alloc_BaB_1_set(0);
2234 /* 12 */ VGOFF_(sh_ebx) = alloc_BaB_1_set(0);
2235 /* 13 */ VGOFF_(sh_esp) = alloc_BaB_1_set(0);
2236 /* 14 */ VGOFF_(sh_ebp) = alloc_BaB_1_set(0);
2237 /* 15 */ VGOFF_(sh_esi) = alloc_BaB_1_set(0);
2238 /* 16 */ VGOFF_(sh_edi) = alloc_BaB_1_set(0);
2239 /* 17 */ VGOFF_(sh_eflags) = alloc_BaB_1_set(0);
2240 VG_TRACK( post_regs_write_init );
2241 }
2242
2243 /* 9,10,11 or 18,19,20... depends on number whether shadow regs are used
2244 * and on compact helpers registered */
2245
2246 /* Make these most-frequently-called specialised ones compact, if they
2247 are used. */
2248 if (VG_(defined_new_mem_stack_4)())
2249 VG_(register_compact_helper)( (Addr) VG_(tool_interface).track_new_mem_stack_4);
2250
2251 if (VG_(defined_die_mem_stack_4)())
2252 VG_(register_compact_helper)( (Addr) VG_(tool_interface).track_die_mem_stack_4);
2253
2254 /* (9 or 18) + n_compact_helpers */
2255 /* Allocate slots for compact helpers */
2256 assign_helpers_in_baseBlock(VG_(n_compact_helpers),
2257 VG_(compact_helper_offsets),
2258 VG_(compact_helper_addrs));
2259
2260 /* (9/10 or 18/19) + n_compact_helpers */
2261 VGOFF_(m_eip) = alloc_BaB_1_set(client_eip);
2262
2263 /* There are currently 24 spill slots */
2264 /* (11+/20+ .. 32+/43+) + n_compact_helpers. This can overlap the magic
2265 * boundary at >= 32 words, but most spills are to low numbered spill
2266 * slots, so the ones above the boundary don't see much action. */
2267 VGOFF_(spillslots) = alloc_BaB(VG_MAX_SPILLSLOTS);
2268
2269 /* I gave up counting at this point. Since they're above the
2270 short-amode-boundary, there's no point. */
2271
2272 VGOFF_(m_dflag) = alloc_BaB_1_set(1); // 1 == forward D-flag
2273
2274 /* The FPU/SSE state. This _must_ be 16-byte aligned. Initial
2275 state doesn't matter much, as long as it's not totally borked. */
2276 align_BaB(16);
2277 VGOFF_(m_ssestate) = alloc_BaB(VG_SIZE_OF_SSESTATE_W);
2278 vg_assert(
2279 0 == ( ((UInt)(& VG_(baseBlock)[VGOFF_(m_ssestate)])) % 16 )
sewardj22854b92002-11-30 14:00:47 +00002280 );
2281
fitzhardingec2dbbac2004-01-23 23:09:01 +00002282 /* I assume that if we have SSE2 we also have SSE */
2283 VG_(have_ssestate) =
2284 VG_(cpu_has_feature)(VG_X86_FEAT_FXSR) &&
2285 VG_(cpu_has_feature)(VG_X86_FEAT_SSE);
2286
fitzhardinge98abfc72003-12-16 02:05:15 +00002287 /* set up an initial FPU state (doesn't really matter what it is,
2288 so long as it's somewhat valid) */
2289 if (!VG_(have_ssestate))
nethercote71980f02004-01-24 18:18:54 +00002290 asm volatile("fwait; fnsave %0; fwait; frstor %0; fwait"
2291 :
2292 : "m" (VG_(baseBlock)[VGOFF_(m_ssestate)])
2293 : "cc", "memory");
fitzhardinge98abfc72003-12-16 02:05:15 +00002294 else
nethercote71980f02004-01-24 18:18:54 +00002295 asm volatile("fwait; fxsave %0; fwait; andl $0xffbf, %1;"
2296 "fxrstor %0; fwait"
2297 :
2298 : "m" (VG_(baseBlock)[VGOFF_(m_ssestate)]),
2299 "m" (VG_(baseBlock)[VGOFF_(m_ssestate)+(24/4)])
2300 : "cc", "memory");
fitzhardinge98abfc72003-12-16 02:05:15 +00002301
njn0c7a5b52003-04-30 09:00:33 +00002302 if (0) {
2303 if (VG_(have_ssestate))
2304 VG_(printf)("Looks like a SSE-capable CPU\n");
2305 else
2306 VG_(printf)("Looks like a MMX-only CPU\n");
2307 }
sewardjb91ae7f2003-04-29 23:50:00 +00002308
nethercote71980f02004-01-24 18:18:54 +00002309 /* LDT pointer: pretend the root thread has an empty LDT to start with. */
2310 VGOFF_(ldt) = alloc_BaB_1_set((UInt)NULL);
jsgf855d93d2003-10-13 22:26:55 +00002311
nethercote71980f02004-01-24 18:18:54 +00002312 /* TLS pointer: pretend the root thread has no TLS array for now. */
2313 VGOFF_(tls) = alloc_BaB_1_set((UInt)NULL);
fitzhardingef0046f22003-12-18 02:39:22 +00002314
nethercote71980f02004-01-24 18:18:54 +00002315 /* segment registers */
2316 VGOFF_(m_cs) = alloc_BaB_1_set(0);
2317 VGOFF_(m_ss) = alloc_BaB_1_set(0);
2318 VGOFF_(m_ds) = alloc_BaB_1_set(0);
2319 VGOFF_(m_es) = alloc_BaB_1_set(0);
2320 VGOFF_(m_fs) = alloc_BaB_1_set(0);
2321 VGOFF_(m_gs) = alloc_BaB_1_set(0);
fitzhardingef0046f22003-12-18 02:39:22 +00002322
thughes35cec982004-04-21 15:16:43 +00002323 /* initialise %cs, %ds and %ss to point at the operating systems
2324 default code, data and stack segments */
2325 asm volatile("movw %%cs, %0"
2326 :
2327 : "m" (VG_(baseBlock)[VGOFF_(m_cs)]));
2328 asm volatile("movw %%ds, %0"
2329 :
2330 : "m" (VG_(baseBlock)[VGOFF_(m_ds)]));
2331 asm volatile("movw %%ss, %0"
2332 :
2333 : "m" (VG_(baseBlock)[VGOFF_(m_ss)]));
2334
nethercote71980f02004-01-24 18:18:54 +00002335 VG_(register_noncompact_helper)( (Addr) & VG_(do_useseg) );
fitzhardingef0046f22003-12-18 02:39:22 +00002336
nethercote71980f02004-01-24 18:18:54 +00002337#define REG(kind, size) \
2338 if (VG_(defined_##kind##_mem_stack##size)()) \
2339 VG_(register_noncompact_helper)( \
2340 (Addr) VG_(tool_interface).track_##kind##_mem_stack##size );
2341 REG(new, _8);
2342 REG(new, _12);
2343 REG(new, _16);
2344 REG(new, _32);
2345 REG(new, );
2346 REG(die, _8);
2347 REG(die, _12);
2348 REG(die, _16);
2349 REG(die, _32);
2350 REG(die, );
2351#undef REG
fitzhardingef0046f22003-12-18 02:39:22 +00002352
nethercote71980f02004-01-24 18:18:54 +00002353 if (VG_(need_to_handle_esp_assignment)())
2354 VG_(register_noncompact_helper)((Addr) VG_(unknown_esp_update));
fitzhardingeb791a192003-12-18 07:22:44 +00002355
nethercote71980f02004-01-24 18:18:54 +00002356# define HELPER(name) \
2357 VGOFF_(helper_##name) = alloc_BaB_1_set( (Addr) & VG_(helper_##name))
njn3e884182003-04-15 13:03:23 +00002358
nethercote71980f02004-01-24 18:18:54 +00002359 /* Helper functions. */
2360 HELPER(idiv_64_32); HELPER(div_64_32);
2361 HELPER(idiv_32_16); HELPER(div_32_16);
2362 HELPER(idiv_16_8); HELPER(div_16_8);
fitzhardinge98abfc72003-12-16 02:05:15 +00002363
nethercote71980f02004-01-24 18:18:54 +00002364 HELPER(imul_32_64); HELPER(mul_32_64);
2365 HELPER(imul_16_32); HELPER(mul_16_32);
2366 HELPER(imul_8_16); HELPER(mul_8_16);
njn25e49d8e72002-09-23 09:36:25 +00002367
nethercote71980f02004-01-24 18:18:54 +00002368 HELPER(CLD); HELPER(STD);
2369 HELPER(get_dirflag);
sewardjde4a1d02002-03-22 01:27:54 +00002370
nethercote71980f02004-01-24 18:18:54 +00002371 HELPER(CLC); HELPER(STC);
nethercote1018bdd2004-02-11 23:33:29 +00002372 HELPER(CMC);
jsgf855d93d2003-10-13 22:26:55 +00002373
nethercote71980f02004-01-24 18:18:54 +00002374 HELPER(shldl); HELPER(shldw);
2375 HELPER(shrdl); HELPER(shrdw);
njncc7bb472002-10-14 09:25:19 +00002376
nethercote71980f02004-01-24 18:18:54 +00002377 HELPER(RDTSC); HELPER(CPUID);
njncc7bb472002-10-14 09:25:19 +00002378
nethercote1018bdd2004-02-11 23:33:29 +00002379 HELPER(bsfw); HELPER(bsfl);
2380 HELPER(bsrw); HELPER(bsrl);
rjwalshf5f536f2003-11-17 17:45:00 +00002381
nethercote71980f02004-01-24 18:18:54 +00002382 HELPER(fstsw_AX);
2383 HELPER(SAHF); HELPER(LAHF);
2384 HELPER(DAS); HELPER(DAA);
nethercote1018bdd2004-02-11 23:33:29 +00002385 HELPER(AAS); HELPER(AAA);
2386 HELPER(AAD); HELPER(AAM);
nethercote71980f02004-01-24 18:18:54 +00002387 HELPER(IN); HELPER(OUT);
2388 HELPER(cmpxchg8b);
sewardj018f7622002-05-15 21:13:39 +00002389
nethercote71980f02004-01-24 18:18:54 +00002390 HELPER(undefined_instruction);
jsgf855d93d2003-10-13 22:26:55 +00002391
nethercote71980f02004-01-24 18:18:54 +00002392# undef HELPER
sewardjde4a1d02002-03-22 01:27:54 +00002393
nethercote71980f02004-01-24 18:18:54 +00002394 /* Allocate slots for noncompact helpers */
2395 assign_helpers_in_baseBlock(VG_(n_noncompact_helpers),
2396 VG_(noncompact_helper_offsets),
2397 VG_(noncompact_helper_addrs));
2398}
sewardjde4a1d02002-03-22 01:27:54 +00002399
nethercote81f9a6f2004-08-03 15:45:46 +00002400// Finds the baseBlock offset of a tool-specified helper.
2401// Searches through compacts first, then non-compacts.
2402Int VG_(helper_offset)(Addr a)
2403{
2404 UInt i;
2405 Char buf[100];
2406
2407 for (i = 0; i < VG_(n_compact_helpers); i++)
2408 if (VG_(compact_helper_addrs)[i] == a)
2409 return VG_(compact_helper_offsets)[i];
2410 for (i = 0; i < VG_(n_noncompact_helpers); i++)
2411 if (VG_(noncompact_helper_addrs)[i] == a)
2412 return VG_(noncompact_helper_offsets)[i];
2413
2414 /* Shouldn't get here */
2415 VG_(get_fnname) ( a, buf, 100 );
2416
2417 VG_(printf)(
2418 "\nCouldn't find offset of helper from its address (%p: %s).\n"
2419 "A helper function probably used hasn't been registered?\n\n", a, buf);
2420
2421 VG_(printf)(" compact helpers: ");
2422 for (i = 0; i < VG_(n_compact_helpers); i++)
2423 VG_(printf)("%p ", VG_(compact_helper_addrs)[i]);
2424
2425 VG_(printf)("\n non-compact helpers: ");
2426 for (i = 0; i < VG_(n_noncompact_helpers); i++)
2427 VG_(printf)("%p ", VG_(noncompact_helper_addrs)[i]);
2428
2429 VG_(printf)("\n");
2430 VG_(skin_panic)("Unfound helper");
2431}
2432
sewardj5f07b662002-04-23 16:52:51 +00002433
nethercote71980f02004-01-24 18:18:54 +00002434/*====================================================================*/
2435/*=== Setup pointercheck ===*/
2436/*====================================================================*/
njn25e49d8e72002-09-23 09:36:25 +00002437
nethercote71980f02004-01-24 18:18:54 +00002438static void setup_pointercheck(void)
2439{
2440 int ret;
sewardj2e93c502002-04-12 11:12:52 +00002441
fitzhardinge98abfc72003-12-16 02:05:15 +00002442 if (VG_(clo_pointercheck)) {
nethercote71980f02004-01-24 18:18:54 +00002443 vki_modify_ldt_t ldt = {
2444 VG_POINTERCHECK_SEGIDX, // entry_number
2445 VG_(client_base), // base_addr
2446 (VG_(client_end)-VG_(client_base)) / VKI_BYTES_PER_PAGE, // limit
2447 1, // seg_32bit
2448 0, // contents: data, RW, non-expanding
2449 0, // ! read_exec_only
2450 1, // limit_in_pages
2451 0, // ! seg not present
2452 1, // useable
fitzhardinge98abfc72003-12-16 02:05:15 +00002453 };
nethercote71980f02004-01-24 18:18:54 +00002454 ret = VG_(do_syscall)(__NR_modify_ldt, 1, &ldt, sizeof(ldt));
fitzhardinge98abfc72003-12-16 02:05:15 +00002455 if (ret < 0) {
2456 VG_(message)(Vg_UserMsg,
2457 "Warning: ignoring --pointercheck=yes, "
2458 "because modify_ldt failed (errno=%d)", -ret);
2459 VG_(clo_pointercheck) = False;
2460 }
2461 }
sewardjde4a1d02002-03-22 01:27:54 +00002462}
2463
nethercote71980f02004-01-24 18:18:54 +00002464/*====================================================================*/
2465/*=== Initialise program data/text, etc. ===*/
2466/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +00002467
nethercote71980f02004-01-24 18:18:54 +00002468static void build_valgrind_map_callback
2469 ( Addr start, UInt size, Char rr, Char ww, Char xx,
2470 UInt dev, UInt ino, ULong foffset, const UChar* filename )
sewardjde4a1d02002-03-22 01:27:54 +00002471{
nethercote71980f02004-01-24 18:18:54 +00002472 UInt prot = 0;
2473 UInt flags = SF_MMAP|SF_NOSYMS;
2474 Bool is_stack_segment;
2475
2476 is_stack_segment =
2477 (start == VG_(clstk_base) && (start+size) == VG_(clstk_end));
2478
2479 /* Only record valgrind mappings for now, without loading any
2480 symbols. This is so we know where the free space is before we
2481 start allocating more memory (note: heap is OK, it's just mmap
2482 which is the problem here). */
2483 if (start >= VG_(valgrind_base) && (start+size) <= VG_(valgrind_end)) {
2484 flags |= SF_VALGRIND;
2485 VG_(map_file_segment)(start, size, prot, flags, dev, ino, foffset, filename);
2486 }
sewardjde4a1d02002-03-22 01:27:54 +00002487}
2488
nethercote71980f02004-01-24 18:18:54 +00002489// Global var used to pass local data to callback
2490Addr esp_at_startup___global_arg = 0;
sewardjde4a1d02002-03-22 01:27:54 +00002491
nethercote71980f02004-01-24 18:18:54 +00002492static void build_segment_map_callback
2493 ( Addr start, UInt size, Char rr, Char ww, Char xx,
2494 UInt dev, UInt ino, ULong foffset, const UChar* filename )
sewardj45b672d2003-07-25 19:58:11 +00002495{
nethercote71980f02004-01-24 18:18:54 +00002496 UInt prot = 0;
2497 UInt flags;
2498 Bool is_stack_segment;
2499 Addr r_esp;
sewardj45b672d2003-07-25 19:58:11 +00002500
nethercote71980f02004-01-24 18:18:54 +00002501 is_stack_segment
2502 = (start == VG_(clstk_base) && (start+size) == VG_(clstk_end));
fitzhardinge98abfc72003-12-16 02:05:15 +00002503
nethercote71980f02004-01-24 18:18:54 +00002504 if (rr == 'r') prot |= VKI_PROT_READ;
2505 if (ww == 'w') prot |= VKI_PROT_WRITE;
2506 if (xx == 'x') prot |= VKI_PROT_EXEC;
fitzhardinge98abfc72003-12-16 02:05:15 +00002507
nethercote71980f02004-01-24 18:18:54 +00002508 if (is_stack_segment)
2509 flags = SF_STACK | SF_GROWDOWN;
2510 else
2511 flags = SF_EXEC|SF_MMAP;
fitzhardinge98abfc72003-12-16 02:05:15 +00002512
nethercote71980f02004-01-24 18:18:54 +00002513 if (filename != NULL)
2514 flags |= SF_FILE;
fitzhardinge98abfc72003-12-16 02:05:15 +00002515
nethercote71980f02004-01-24 18:18:54 +00002516 if (start >= VG_(valgrind_base) && (start+size) <= VG_(valgrind_end))
2517 flags |= SF_VALGRIND;
fitzhardinge98abfc72003-12-16 02:05:15 +00002518
nethercote71980f02004-01-24 18:18:54 +00002519 VG_(map_file_segment)(start, size, prot, flags, dev, ino, foffset, filename);
fitzhardinge98abfc72003-12-16 02:05:15 +00002520
nethercote71980f02004-01-24 18:18:54 +00002521 if (VG_(is_client_addr)(start) && VG_(is_client_addr)(start+size-1))
2522 VG_TRACK( new_mem_startup, start, size, rr=='r', ww=='w', xx=='x' );
sewardj3e1eb1f2002-05-18 13:14:17 +00002523
nethercote71980f02004-01-24 18:18:54 +00002524 /* If this is the stack segment mark all below %esp as noaccess. */
2525 r_esp = esp_at_startup___global_arg;
2526 vg_assert(0 != r_esp);
2527 if (is_stack_segment) {
2528 if (0)
2529 VG_(message)(Vg_DebugMsg, "invalidating stack area: %x .. %x",
2530 start,r_esp);
2531 VG_TRACK( die_mem_stack, start, r_esp-start );
sewardjde4a1d02002-03-22 01:27:54 +00002532 }
sewardjde4a1d02002-03-22 01:27:54 +00002533}
2534
2535
nethercote71980f02004-01-24 18:18:54 +00002536/*====================================================================*/
2537/*=== Sanity check machinery (permanently engaged) ===*/
2538/*====================================================================*/
njn25e49d8e72002-09-23 09:36:25 +00002539
2540/* A fast sanity check -- suitable for calling circa once per
2541 millisecond. */
2542
nethercote885dd912004-08-03 23:14:00 +00002543void VG_(sanity_check_general) ( Bool force_expensive )
njn25e49d8e72002-09-23 09:36:25 +00002544{
njn37cea302002-09-30 11:24:00 +00002545 VGP_PUSHCC(VgpCoreCheapSanity);
2546
nethercote27fec902004-06-16 21:26:32 +00002547 if (VG_(clo_sanity_level) < 1) return;
njn25e49d8e72002-09-23 09:36:25 +00002548
2549 /* --- First do all the tests that we can do quickly. ---*/
2550
nethercote297effd2004-08-02 15:07:57 +00002551 sanity_fast_count++;
njn25e49d8e72002-09-23 09:36:25 +00002552
njn25e49d8e72002-09-23 09:36:25 +00002553 /* Check stuff pertaining to the memory check system. */
2554
2555 /* Check that nobody has spuriously claimed that the first or
2556 last 16 pages of memory have become accessible [...] */
njn37cea302002-09-30 11:24:00 +00002557 if (VG_(needs).sanity_checks) {
2558 VGP_PUSHCC(VgpSkinCheapSanity);
njn25e49d8e72002-09-23 09:36:25 +00002559 vg_assert(SK_(cheap_sanity_check)());
njn37cea302002-09-30 11:24:00 +00002560 VGP_POPCC(VgpSkinCheapSanity);
2561 }
njn25e49d8e72002-09-23 09:36:25 +00002562
2563 /* --- Now some more expensive checks. ---*/
2564
2565 /* Once every 25 times, check some more expensive stuff. */
2566 if ( force_expensive
nethercote27fec902004-06-16 21:26:32 +00002567 || VG_(clo_sanity_level) > 1
nethercote297effd2004-08-02 15:07:57 +00002568 || (VG_(clo_sanity_level) == 1 && (sanity_fast_count % 25) == 0)) {
njn25e49d8e72002-09-23 09:36:25 +00002569
njn37cea302002-09-30 11:24:00 +00002570 VGP_PUSHCC(VgpCoreExpensiveSanity);
nethercote297effd2004-08-02 15:07:57 +00002571 sanity_slow_count++;
njn25e49d8e72002-09-23 09:36:25 +00002572
nethercote885dd912004-08-03 23:14:00 +00002573 VG_(sanity_check_proxy)();
jsgf855d93d2003-10-13 22:26:55 +00002574
njn25e49d8e72002-09-23 09:36:25 +00002575# if 0
2576 { void zzzmemscan(void); zzzmemscan(); }
2577# endif
2578
nethercote297effd2004-08-02 15:07:57 +00002579 if ((sanity_fast_count % 250) == 0)
nethercote92e7b7f2004-08-07 17:52:25 +00002580 VG_(sanity_check_tt_tc)();
njn25e49d8e72002-09-23 09:36:25 +00002581
2582 if (VG_(needs).sanity_checks) {
njn37cea302002-09-30 11:24:00 +00002583 VGP_PUSHCC(VgpSkinExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002584 vg_assert(SK_(expensive_sanity_check)());
njn37cea302002-09-30 11:24:00 +00002585 VGP_POPCC(VgpSkinExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002586 }
2587 /*
nethercote297effd2004-08-02 15:07:57 +00002588 if ((sanity_fast_count % 500) == 0) VG_(mallocSanityCheckAll)();
njn25e49d8e72002-09-23 09:36:25 +00002589 */
njn37cea302002-09-30 11:24:00 +00002590 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002591 }
2592
nethercote27fec902004-06-16 21:26:32 +00002593 if (VG_(clo_sanity_level) > 1) {
njn37cea302002-09-30 11:24:00 +00002594 VGP_PUSHCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002595 /* Check sanity of the low-level memory manager. Note that bugs
2596 in the client's code can cause this to fail, so we don't do
2597 this check unless specially asked for. And because it's
2598 potentially very expensive. */
nethercote885dd912004-08-03 23:14:00 +00002599 VG_(sanity_check_malloc_all)();
njn37cea302002-09-30 11:24:00 +00002600 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002601 }
njn37cea302002-09-30 11:24:00 +00002602 VGP_POPCC(VgpCoreCheapSanity);
njn25e49d8e72002-09-23 09:36:25 +00002603}
nethercote71980f02004-01-24 18:18:54 +00002604
2605
2606/*====================================================================*/
2607/*=== main() ===*/
2608/*====================================================================*/
2609
nethercotec314eba2004-07-15 12:59:41 +00002610/*
2611 This code decides on the layout of the client and Valgrind address
nethercote996901a2004-08-03 13:29:09 +00002612 spaces, loads valgrind.so and the tool.so into the valgrind part,
nethercotec314eba2004-07-15 12:59:41 +00002613 loads the client executable (and the dynamic linker, if necessary)
2614 into the client part, and calls into Valgrind proper.
2615
2616 The code is careful not to allow spurious mappings to appear in the
2617 wrong parts of the address space. In particular, to make sure
2618 dlopen puts things in the right place, it will pad out the forbidden
2619 chunks of address space so that dlopen is forced to put things where
2620 we want them.
2621
2622 The memory map it creates is:
2623
2624 CLIENT_BASE +-------------------------+
2625 | client address space |
2626 : :
2627 : :
2628 | client stack |
2629 client_end +-------------------------+
2630 | redzone |
2631 shadow_base +-------------------------+
2632 | |
nethercote996901a2004-08-03 13:29:09 +00002633 : shadow memory for tools :
nethercotec314eba2004-07-15 12:59:41 +00002634 | (may be 0 sized) |
2635 shadow_end +-------------------------+
2636 : gap (may be 0 sized) :
2637 valgrind_base +-------------------------+
2638 | kickstart executable |
2639 | valgrind heap vvvvvvvvv| (barely used)
2640 - -
2641 | valgrind .so files |
2642 | and mappings |
2643 - -
2644 | valgrind stack ^^^^^^^^^|
2645 valgrind_end +-------------------------+
2646 : kernel :
2647
2648 Nb: Before we can do general allocations with VG_(arena_malloc)() and
2649 VG_(mmap)(), we need to build the segment skip-list, so we know where
2650 we can put things. However, building that structure requires
2651 allocating memory. So we need to a bootstrapping process. It's done
2652 by making VG_(arena_malloc)() have a special static superblock that's
2653 used for the first 1MB's worth of allocations. This is enough to
2654 build the segment skip-list.
2655*/
2656
nethercote31779c72004-07-30 21:50:15 +00002657static int prmap(char *start, char *end, const char *perm, off_t off,
2658 int maj, int min, int ino, void* dummy) {
thughes4ad52d02004-06-27 17:37:21 +00002659 printf("mapping %10p-%10p %s %02x:%02x %d\n",
2660 start, end, perm, maj, min, ino);
2661 return True;
2662}
2663
nethercote71980f02004-01-24 18:18:54 +00002664int main(int argc, char **argv)
2665{
2666 char **cl_argv;
2667 const char *tool = NULL;
2668 const char *exec = NULL;
2669 char *preload; /* tool-specific LD_PRELOAD .so */
2670 char **env;
nethercote6c999f22004-01-31 22:55:15 +00002671 Int need_help = 0; // 0 = no, 1 = --help, 2 = --help-debug
nethercote71980f02004-01-24 18:18:54 +00002672 struct exeinfo info;
2673 ToolInfo *toolinfo = NULL;
2674 void *tool_dlhandle;
2675 Addr client_eip;
2676 Addr esp_at_startup; /* client's %esp at the point we gained control. */
2677 UInt * client_auxv;
2678 VgSchedReturnCode src;
nethercote47dd12c2004-06-22 14:18:42 +00002679 Int exitcode = 0;
fitzhardingeb50068f2004-02-24 23:42:55 +00002680 vki_rlimit zero = { 0, 0 };
nethercote31779c72004-07-30 21:50:15 +00002681 Int padfile;
nethercote71980f02004-01-24 18:18:54 +00002682
2683 //============================================================
2684 // Nb: startup is complex. Prerequisites are shown at every step.
2685 //
2686 // *** Be very careful when messing with the order ***
2687 //============================================================
2688
nethercotef4928da2004-06-15 10:54:40 +00002689 //============================================================
2690 // Command line argument handling order:
2691 // * If --help/--help-debug are present, show usage message
2692 // (if --tool is also present, that includes the tool-specific usage)
2693 // * Then, if --tool is missing, abort with error msg
2694 // * Then, if client is missing, abort with error msg
2695 // * Then, if any cmdline args are bad, abort with error msg
2696 //============================================================
2697
fitzhardingeb50068f2004-02-24 23:42:55 +00002698 // Get the current process datasize rlimit, and set it to zero.
2699 // This prevents any internal uses of brk() from having any effect.
2700 // We remember the old value so we can restore it on exec, so that
2701 // child processes will have a reasonable brk value.
2702 VG_(getrlimit)(VKI_RLIMIT_DATA, &VG_(client_rlimit_data));
2703 zero.rlim_max = VG_(client_rlimit_data).rlim_max;
2704 VG_(setrlimit)(VKI_RLIMIT_DATA, &zero);
2705
nethercote71980f02004-01-24 18:18:54 +00002706 //--------------------------------------------------------------
2707 // Check we were launched by stage1
nethercotec314eba2004-07-15 12:59:41 +00002708 // p: n/a
nethercote71980f02004-01-24 18:18:54 +00002709 //--------------------------------------------------------------
nethercote31779c72004-07-30 21:50:15 +00002710 padfile = scan_auxv();
nethercote71980f02004-01-24 18:18:54 +00002711
2712 if (0) {
nethercote71980f02004-01-24 18:18:54 +00002713 printf("========== main() ==========\n");
nethercote31779c72004-07-30 21:50:15 +00002714 foreach_map(prmap, /*dummy*/NULL);
nethercote71980f02004-01-24 18:18:54 +00002715 }
2716
2717 //--------------------------------------------------------------
2718 // Look for alternative libdir
2719 // p: n/a
2720 //--------------------------------------------------------------
2721 { char *cp = getenv(VALGRINDLIB);
2722 if (cp != NULL)
2723 VG_(libdir) = cp;
2724 }
2725
2726 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002727 // Get valgrind args + client args (inc. from VALGRIND_OPTS/.valgrindrc).
2728 // Pre-process the command line.
2729 // p: n/a
2730 //--------------------------------------------------------------
2731 get_command_line(argc, argv, &VG_(vg_argc), &VG_(vg_argv), &cl_argv);
2732 pre_process_cmd_line_options(&need_help, &tool, &exec);
2733
2734 //==============================================================
2735 // Nb: once a tool is specified, the tool.so must be loaded even if
2736 // they specified --help or didn't specify a client program.
2737 //==============================================================
2738
2739 //--------------------------------------------------------------
2740 // With client padded out, map in tool
nethercote71980f02004-01-24 18:18:54 +00002741 // p: set-libdir [for VG_(libdir)]
2742 // p: pre_process_cmd_line_options() [for 'tool']
2743 //--------------------------------------------------------------
2744 load_tool(tool, &tool_dlhandle, &toolinfo, &preload);
2745
2746 //==============================================================
2747 // Can use VG_(malloc)() and VG_(arena_malloc)() only after load_tool()
nethercotec314eba2004-07-15 12:59:41 +00002748 // -- redzone size is now set. This is checked by vg_malloc2.c.
nethercote71980f02004-01-24 18:18:54 +00002749 //==============================================================
2750
2751 //--------------------------------------------------------------
2752 // Finalise address space layout
nethercote31779c72004-07-30 21:50:15 +00002753 // p: load_tool() [for 'toolinfo']
nethercote71980f02004-01-24 18:18:54 +00002754 //--------------------------------------------------------------
nethercote31779c72004-07-30 21:50:15 +00002755 layout_remaining_space( (Addr) & argc, toolinfo->shadow_ratio );
nethercote71980f02004-01-24 18:18:54 +00002756
2757 //--------------------------------------------------------------
2758 // Load client executable, finding in $PATH if necessary
nethercote71980f02004-01-24 18:18:54 +00002759 // p: pre_process_cmd_line_options() [for 'exec', 'need_help']
2760 // p: layout_remaining_space [so there's space]
2761 //--------------------------------------------------------------
nethercotef4928da2004-06-15 10:54:40 +00002762 load_client(cl_argv, exec, need_help, &info, &client_eip);
nethercote71980f02004-01-24 18:18:54 +00002763
2764 //--------------------------------------------------------------
2765 // Everything in place, unpad us
2766 // p: layout_remaining_space() [everything must be mapped in before now]
2767 // p: load_client() [ditto]
2768 //--------------------------------------------------------------
nethercote31779c72004-07-30 21:50:15 +00002769 as_unpad((void *)VG_(shadow_end), (void *)~0, padfile);
2770 as_closepadfile(padfile); // no more padding
nethercote71980f02004-01-24 18:18:54 +00002771
2772 //--------------------------------------------------------------
2773 // Set up client's environment
2774 // p: set-libdir [for VG_(libdir)]
2775 // p: load_tool() [for 'preload']
2776 //--------------------------------------------------------------
2777 env = fix_environment(environ, preload);
2778
2779 //--------------------------------------------------------------
nethercote5ee67ca2004-06-22 14:00:09 +00002780 // Setup client stack, eip, and VG_(client_arg[cv])
nethercote71980f02004-01-24 18:18:54 +00002781 // p: load_client() [for 'info']
2782 // p: fix_environment() [for 'env']
2783 //--------------------------------------------------------------
2784 esp_at_startup = setup_client_stack(cl_argv, env, &info, &client_auxv);
2785
2786 if (0)
2787 printf("entry=%x client esp=%x vg_argc=%d brkbase=%x\n",
2788 client_eip, esp_at_startup, VG_(vg_argc), VG_(brk_base));
2789
2790 //==============================================================
2791 // Finished setting up operating environment. Now initialise
2792 // Valgrind. (This is where the old VG_(main)() started.)
2793 //==============================================================
2794
2795 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002796 // atfork
2797 // p: n/a
2798 //--------------------------------------------------------------
2799 VG_(atfork)(NULL, NULL, newpid);
2800 newpid(VG_INVALID_THREADID);
2801
2802 //--------------------------------------------------------------
2803 // setup file descriptors
2804 // p: n/a
2805 //--------------------------------------------------------------
2806 setup_file_descriptors();
2807
2808 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002809 // Read /proc/self/maps into a buffer
2810 // p: all memory layout, environment setup [so memory maps are right]
2811 //--------------------------------------------------------------
2812 VG_(read_procselfmaps)();
2813
2814 //--------------------------------------------------------------
2815 // Build segment map (Valgrind segments only)
2816 // p: read proc/self/maps
2817 // p: sk_pre_clo_init() [to setup new_mem_startup tracker]
2818 //--------------------------------------------------------------
2819 VG_(parse_procselfmaps) ( build_valgrind_map_callback );
2820
2821 //==============================================================
2822 // Can use VG_(arena_malloc)() with non-CORE arena after segments set up
2823 //==============================================================
2824
2825 //--------------------------------------------------------------
2826 // Init tool: pre_clo_init, process cmd line, post_clo_init
2827 // p: setup_client_stack() [for 'VG_(client_arg[cv]']
2828 // p: load_tool() [for 'tool']
2829 // p: setup_file_descriptors() [for 'VG_(fd_xxx_limit)']
2830 // p: parse_procselfmaps [so VG segments are setup so tool can
2831 // call VG_(malloc)]
nethercote71980f02004-01-24 18:18:54 +00002832 //--------------------------------------------------------------
2833 (*toolinfo->sk_pre_clo_init)();
2834 VG_(tool_init_dlsym)(tool_dlhandle);
2835 VG_(sanity_check_needs)();
2836
nethercotef4928da2004-06-15 10:54:40 +00002837 // If --tool and --help/--help-debug was given, now give the core+tool
2838 // help message
nethercotef4928da2004-06-15 10:54:40 +00002839 if (need_help) {
2840 usage(/*--help-debug?*/2 == need_help);
2841 }
nethercotec314eba2004-07-15 12:59:41 +00002842 process_cmd_line_options(client_auxv, tool);
2843
2844 SK_(post_clo_init)();
nethercotef4928da2004-06-15 10:54:40 +00002845
2846 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002847 // Build segment map (all segments)
2848 // p: setup_client_stack() [for 'esp_at_startup']
2849 // p: init tool [for 'new_mem_startup']
nethercote71980f02004-01-24 18:18:54 +00002850 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002851 esp_at_startup___global_arg = esp_at_startup;
2852 VG_(parse_procselfmaps) ( build_segment_map_callback ); /* everything */
2853 esp_at_startup___global_arg = 0;
2854
2855 //--------------------------------------------------------------
nethercotef84f6952004-07-15 14:58:33 +00002856 // Protect client trampoline page (which is also sysinfo stuff)
2857 // p: segment stuff [otherwise get seg faults...]
nethercotec314eba2004-07-15 12:59:41 +00002858 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002859 VG_(mprotect)( (void *)VG_(client_trampoline_code),
2860 VG_(trampoline_code_length), VKI_PROT_READ|VKI_PROT_EXEC );
2861
2862 //==============================================================
2863 // Can use VG_(map)() after segments set up
2864 //==============================================================
nethercote71980f02004-01-24 18:18:54 +00002865
2866 //--------------------------------------------------------------
2867 // Allow GDB attach
2868 // p: process_cmd_line_options() [for VG_(clo_wait_for_gdb)]
2869 //--------------------------------------------------------------
2870 /* Hook to delay things long enough so we can get the pid and
2871 attach GDB in another shell. */
2872 if (VG_(clo_wait_for_gdb)) {
2873 VG_(printf)("pid=%d\n", VG_(getpid)());
2874 /* do "jump *$eip" to skip this in gdb */
2875 VG_(do_syscall)(__NR_pause);
2876 }
2877
2878 //--------------------------------------------------------------
nethercote1d447092004-02-01 17:29:59 +00002879 // Set up baseBlock
nethercote71980f02004-01-24 18:18:54 +00002880 // p: {pre,post}_clo_init() [for tool helper registration]
2881 // load_client() [for 'client_eip']
2882 // setup_client_stack() [for 'esp_at_startup']
2883 //--------------------------------------------------------------
2884 init_baseBlock(client_eip, esp_at_startup);
2885
2886 //--------------------------------------------------------------
2887 // Search for file descriptors that are inherited from our parent
2888 // p: process_cmd_line_options [for VG_(clo_track_fds)]
2889 //--------------------------------------------------------------
2890 if (VG_(clo_track_fds))
2891 VG_(init_preopened_fds)();
2892
2893 //--------------------------------------------------------------
2894 // Initialise the scheduler
2895 // p: init_baseBlock() [baseBlock regs copied into VG_(threads)[1]]
2896 // p: setup_file_descriptors() [else VG_(safe_fd)() breaks]
2897 //--------------------------------------------------------------
2898 VG_(scheduler_init)();
2899
2900 //--------------------------------------------------------------
2901 // Set up the ProxyLWP machinery
2902 // p: VG_(scheduler_init)()? [XXX: subtle dependency?]
nethercote71980f02004-01-24 18:18:54 +00002903 //--------------------------------------------------------------
2904 VG_(proxy_init)();
2905
2906 //--------------------------------------------------------------
2907 // Initialise the signal handling subsystem
2908 // p: VG_(atfork)(NULL, NULL, newpid) [else problems with sigmasks]
2909 // p: VG_(proxy_init)() [else breaks...]
2910 //--------------------------------------------------------------
2911 // Nb: temporarily parks the saved blocking-mask in saved_sigmask.
2912 VG_(sigstartup_actions)();
2913
2914 //--------------------------------------------------------------
2915 // Perhaps we're profiling Valgrind?
2916 // p: process_cmd_line_options() [for VG_(clo_profile)]
2917 // p: others?
2918 //
2919 // XXX: this seems to be broken? It always says the tool wasn't built
2920 // for profiling; vg_profile.c's functions don't seem to be overriding
2921 // vg_dummy_profile.c's?
2922 //
2923 // XXX: want this as early as possible. Looking for --profile
2924 // in pre_process_cmd_line_options() could get it earlier.
2925 //--------------------------------------------------------------
2926 if (VG_(clo_profile))
2927 VGP_(init_profiling)();
2928
2929 VGP_PUSHCC(VgpStartup);
2930
2931 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002932 // Read suppression file
2933 // p: process_cmd_line_options() [for VG_(clo_suppressions)]
2934 //--------------------------------------------------------------
2935 if (VG_(needs).core_errors || VG_(needs).skin_errors)
2936 VG_(load_suppressions)();
2937
2938 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002939 // Initialise translation table and translation cache
2940 // p: read_procselfmaps [so the anonymous mmaps for the TT/TC
2941 // aren't identified as part of the client, which would waste
2942 // > 20M of virtual address space.]
2943 //--------------------------------------------------------------
2944 VG_(init_tt_tc)();
2945
2946 //--------------------------------------------------------------
2947 // Read debug info to find glibc entry points to intercept
2948 // p: parse_procselfmaps? [XXX for debug info?]
2949 // p: init_tt_tc? [XXX ???]
2950 //--------------------------------------------------------------
2951 VG_(setup_code_redirect_table)();
2952
2953 //--------------------------------------------------------------
2954 // Verbosity message
2955 // p: end_rdtsc_calibration [so startup message is printed first]
2956 //--------------------------------------------------------------
2957 if (VG_(clo_verbosity) == 1)
2958 VG_(message)(Vg_UserMsg, "For more details, rerun with: -v");
2959 if (VG_(clo_verbosity) > 0)
2960 VG_(message)(Vg_UserMsg, "");
2961
2962 //--------------------------------------------------------------
2963 // Setup pointercheck
2964 // p: process_cmd_line_options() [for VG_(clo_pointercheck)]
2965 //--------------------------------------------------------------
2966 setup_pointercheck();
2967
nethercote71980f02004-01-24 18:18:54 +00002968 //--------------------------------------------------------------
2969 // Run!
2970 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002971 VGP_POPCC(VgpStartup);
2972 VGP_PUSHCC(VgpSched);
2973
nethercote31294822004-08-02 13:15:26 +00002974 VG_(fatal_signal_jmpbuf_ptr) = &fatal_signal_jmpbuf;
2975 if (__builtin_setjmp(VG_(fatal_signal_jmpbuf_ptr)) == 0) {
nethercote47dd12c2004-06-22 14:18:42 +00002976 src = VG_(scheduler)( &exitcode );
nethercote31294822004-08-02 13:15:26 +00002977 } else {
nethercote71980f02004-01-24 18:18:54 +00002978 src = VgSrc_FatalSig;
nethercote31294822004-08-02 13:15:26 +00002979 }
nethercote71980f02004-01-24 18:18:54 +00002980 VGP_POPCC(VgpSched);
nethercote71980f02004-01-24 18:18:54 +00002981
2982
2983
2984 //--------------------------------------------------------------
2985 // Finalisation: cleanup, messages, etc. Order no so important, only
2986 // affects what order the messages come.
2987 //--------------------------------------------------------------
2988 if (VG_(clo_verbosity) > 0)
2989 VG_(message)(Vg_UserMsg, "");
2990
2991 if (src == VgSrc_Deadlock) {
2992 VG_(message)(Vg_UserMsg,
2993 "Warning: pthread scheduler exited due to deadlock");
2994 }
2995
2996 /* Print out file descriptor summary and stats. */
2997 if (VG_(clo_track_fds))
nethercote3a42fb82004-08-03 18:08:50 +00002998 VG_(show_open_fds)();
nethercote71980f02004-01-24 18:18:54 +00002999
3000 if (VG_(needs).core_errors || VG_(needs).skin_errors)
3001 VG_(show_all_errors)();
3002
nethercote47dd12c2004-06-22 14:18:42 +00003003 SK_(fini)( exitcode );
nethercote71980f02004-01-24 18:18:54 +00003004
nethercote885dd912004-08-03 23:14:00 +00003005 VG_(sanity_check_general)( True /*include expensive checks*/ );
nethercote71980f02004-01-24 18:18:54 +00003006
3007 if (VG_(clo_verbosity) > 1)
nethercote3a42fb82004-08-03 18:08:50 +00003008 print_all_stats();
nethercote71980f02004-01-24 18:18:54 +00003009
nethercote71980f02004-01-24 18:18:54 +00003010 if (VG_(clo_profile))
3011 VGP_(done_profiling)();
3012
nethercote71980f02004-01-24 18:18:54 +00003013 /* We're exiting, so nuke all the threads and clean up the proxy LWPs */
3014 vg_assert(src == VgSrc_FatalSig ||
3015 VG_(threads)[VG_(last_run_tid)].status == VgTs_Runnable ||
3016 VG_(threads)[VG_(last_run_tid)].status == VgTs_WaitJoiner);
3017 VG_(nuke_all_threads_except)(VG_INVALID_THREADID);
3018
3019 //--------------------------------------------------------------
3020 // Exit, according to the scheduler's return code
3021 //--------------------------------------------------------------
3022 switch (src) {
3023 case VgSrc_ExitSyscall: /* the normal way out */
nethercote85cdd342004-08-01 22:36:40 +00003024 vg_assert(VG_(last_run_tid) > 0 && VG_(last_run_tid) < VG_N_THREADS);
nethercote71980f02004-01-24 18:18:54 +00003025 VG_(proxy_shutdown)();
3026
3027 /* The thread's %EBX at the time it did __NR_exit() will hold
3028 the arg to __NR_exit(), so we just do __NR_exit() with
3029 that arg. */
nethercote47dd12c2004-06-22 14:18:42 +00003030 VG_(exit)( exitcode );
nethercote71980f02004-01-24 18:18:54 +00003031 /* NOT ALIVE HERE! */
3032 VG_(core_panic)("entered the afterlife in main() -- ExitSyscall");
3033 break; /* what the hell :) */
3034
3035 case VgSrc_Deadlock:
3036 /* Just exit now. No point in continuing. */
3037 VG_(proxy_shutdown)();
3038 VG_(exit)(0);
3039 VG_(core_panic)("entered the afterlife in main() -- Deadlock");
3040 break;
3041
nethercote71980f02004-01-24 18:18:54 +00003042 case VgSrc_FatalSig:
3043 /* We were killed by a fatal signal, so replicate the effect */
3044 vg_assert(VG_(fatal_sigNo) != -1);
3045 VG_(kill_self)(VG_(fatal_sigNo));
3046 VG_(core_panic)("main(): signal was supposed to be fatal");
3047 break;
3048
3049 default:
3050 VG_(core_panic)("main(): unexpected scheduler return code");
3051 }
3052
3053 abort();
3054}
3055
3056
sewardjde4a1d02002-03-22 01:27:54 +00003057/*--------------------------------------------------------------------*/
3058/*--- end vg_main.c ---*/
3059/*--------------------------------------------------------------------*/