blob: feae430dfcd4ef9d1a3b345cf879b83df3550b5f [file] [log] [blame]
sewardjde4a1d02002-03-22 01:27:54 +00001
2/*--------------------------------------------------------------------*/
njn04e16982005-05-31 00:23:43 +00003/*--- Startup: the real stuff m_main.c ---*/
sewardjde4a1d02002-03-22 01:27:54 +00004/*--------------------------------------------------------------------*/
5
6/*
njnb9c427c2004-12-01 14:14:42 +00007 This file is part of Valgrind, a dynamic binary instrumentation
8 framework.
sewardjde4a1d02002-03-22 01:27:54 +00009
njn53612422005-03-12 16:22:54 +000010 Copyright (C) 2000-2005 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
njnc7561b92005-06-19 01:24:32 +000033#include "pub_core_basics.h"
34#include "pub_core_threadstate.h"
njn899ce732005-06-21 00:28:11 +000035#include "pub_core_debuginfo.h" // Needed for pub_core_aspacemgr :(
sewardj55f9d1a2005-04-25 11:11:44 +000036#include "pub_core_aspacemgr.h"
njn2521d322005-05-08 14:45:13 +000037#include "pub_core_debuglog.h"
38#include "pub_core_errormgr.h"
39#include "pub_core_execontext.h"
njn97405b22005-06-02 03:39:33 +000040#include "pub_core_libcbase.h"
njn132bfcc2005-06-04 19:16:06 +000041#include "pub_core_libcassert.h"
njneb8896b2005-06-04 20:03:55 +000042#include "pub_core_libcfile.h"
njne9befc62005-06-11 15:51:30 +000043#include "pub_core_libcmman.h"
njn36a20fa2005-06-03 03:08:39 +000044#include "pub_core_libcprint.h"
njnf39e9a32005-06-12 02:43:17 +000045#include "pub_core_libcproc.h"
njnde62cbf2005-06-10 22:08:14 +000046#include "pub_core_libcsignal.h"
njnf536bbb2005-06-13 04:21:38 +000047#include "pub_core_machine.h"
njn04e16982005-05-31 00:23:43 +000048#include "pub_core_main.h"
njnaf1d7df2005-06-11 01:31:52 +000049#include "pub_core_mallocfree.h"
njn20242342005-05-16 23:31:24 +000050#include "pub_core_options.h"
njn31513b42005-06-01 03:09:59 +000051#include "pub_core_profile.h"
njnd1af0032005-05-29 17:01:48 +000052#include "pub_core_redir.h"
njnc7561b92005-06-19 01:24:32 +000053#include "pub_core_scheduler.h"
njn0c246472005-05-31 01:00:08 +000054#include "pub_core_signals.h"
njn2025cf92005-06-26 20:44:48 +000055#include "pub_core_stacks.h" // For VG_(register_stack)
njnc1b01812005-06-17 22:19:06 +000056#include "pub_core_syswrap.h"
njn2025cf92005-06-26 20:44:48 +000057#include "pub_core_translate.h" // For VG_(get_BB_profile)
njn43b9a8a2005-05-10 04:37:01 +000058#include "pub_core_tooliface.h"
njna7598f62005-06-18 03:27:58 +000059#include "pub_core_trampoline.h"
njn8bddf582005-05-13 23:40:55 +000060#include "pub_core_transtab.h"
njn08a2e172005-06-21 22:47:54 +000061#include "pub_core_ume.h"
nethercote71980f02004-01-24 18:18:54 +000062
63#include <dirent.h>
64#include <dlfcn.h>
65#include <errno.h>
nethercote71980f02004-01-24 18:18:54 +000066#include <stdio.h>
fitzhardingeb727d042004-01-06 00:18:21 +000067#include <stdlib.h>
nethercote71980f02004-01-24 18:18:54 +000068#include <string.h>
fitzhardingeb727d042004-01-06 00:18:21 +000069#include <unistd.h>
70
sewardjb5f6f512005-03-10 23:59:00 +000071#include "memcheck/memcheck.h"
72
thughes74b8de22004-04-22 18:12:31 +000073#ifndef AT_DCACHEBSIZE
74#define AT_DCACHEBSIZE 19
75#endif /* AT_DCACHEBSIZE */
76
77#ifndef AT_ICACHEBSIZE
78#define AT_ICACHEBSIZE 20
79#endif /* AT_ICACHEBSIZE */
80
81#ifndef AT_UCACHEBSIZE
82#define AT_UCACHEBSIZE 21
83#endif /* AT_UCACHEBSIZE */
84
nethercote71980f02004-01-24 18:18:54 +000085#ifndef AT_SYSINFO
86#define AT_SYSINFO 32
87#endif /* AT_SYSINFO */
88
89#ifndef AT_SYSINFO_EHDR
90#define AT_SYSINFO_EHDR 33
91#endif /* AT_SYSINFO_EHDR */
92
93#ifndef AT_SECURE
94#define AT_SECURE 23 /* secure mode boolean */
95#endif /* AT_SECURE */
96
nethercote71980f02004-01-24 18:18:54 +000097/* redzone gap between client address space and shadow */
98#define REDZONE_SIZE (1 * 1024*1024)
99
100/* size multiple for client address space */
nethercotee94b2de2004-06-23 16:15:06 +0000101#define CLIENT_SIZE_MULTIPLE (1 * 1024*1024)
nethercote71980f02004-01-24 18:18:54 +0000102
nethercotee2097312004-06-27 12:29:56 +0000103/* Proportion of client space for its heap (rest is for mmaps + stack) */
104#define CLIENT_HEAP_PROPORTION 0.333
nethercote71980f02004-01-24 18:18:54 +0000105
njn14319cc2005-03-13 06:26:22 +0000106/* Number of file descriptors that Valgrind tries to reserve for
107 it's own use - just a small constant. */
108#define N_RESERVED_FDS (10)
109
nethercote71980f02004-01-24 18:18:54 +0000110/*====================================================================*/
111/*=== Global entities not referenced from generated code ===*/
112/*====================================================================*/
113
sewardjde4a1d02002-03-22 01:27:54 +0000114/* ---------------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +0000115 Startup stuff
sewardjde4a1d02002-03-22 01:27:54 +0000116 ------------------------------------------------------------------ */
117
fitzhardinge98abfc72003-12-16 02:05:15 +0000118/* stage1 (main) executable */
nethercotef6a1d502004-08-09 12:21:57 +0000119static Int vgexecfd = -1;
fitzhardingea49f9b52003-12-16 22:26:45 +0000120
fitzhardinge98abfc72003-12-16 02:05:15 +0000121/* our argc/argv */
nethercotef6a1d502004-08-09 12:21:57 +0000122static Int vg_argc;
123static Char **vg_argv;
fitzhardinge98abfc72003-12-16 02:05:15 +0000124
sewardj51ac0872004-12-21 01:20:49 +0000125
nethercote71980f02004-01-24 18:18:54 +0000126/*====================================================================*/
127/*=== Counters, for profiling purposes only ===*/
128/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +0000129
nethercote3a42fb82004-08-03 18:08:50 +0000130static void print_all_stats ( void )
nethercote71980f02004-01-24 18:18:54 +0000131{
nethercote92e7b7f2004-08-07 17:52:25 +0000132 VG_(print_tt_tc_stats)();
nethercote844e7122004-08-02 15:27:22 +0000133 VG_(print_scheduler_stats)();
njn9271cbc2005-03-13 05:38:25 +0000134 VG_(print_ExeContext_stats)();
135
nethercote3a42fb82004-08-03 18:08:50 +0000136 // Memory stats
nethercote885dd912004-08-03 23:14:00 +0000137 if (VG_(clo_verbosity) > 2) {
nethercote3a42fb82004-08-03 18:08:50 +0000138 VG_(message)(Vg_DebugMsg, "");
139 VG_(message)(Vg_DebugMsg,
140 "------ Valgrind's internal memory use stats follow ------" );
nethercote885dd912004-08-03 23:14:00 +0000141 VG_(sanity_check_malloc_all)();
njn11adeb22005-07-03 20:22:39 +0000142 VG_(message)(Vg_DebugMsg, "------" );
nethercote3a42fb82004-08-03 18:08:50 +0000143 VG_(print_all_arena_stats)();
nethercote885dd912004-08-03 23:14:00 +0000144 VG_(message)(Vg_DebugMsg, "");
nethercote3a42fb82004-08-03 18:08:50 +0000145 }
nethercote71980f02004-01-24 18:18:54 +0000146}
147
148
149/*====================================================================*/
nethercote71980f02004-01-24 18:18:54 +0000150/*=== Check we were launched by stage 1 ===*/
151/*====================================================================*/
152
153/* Look for our AUXV table */
sewardjb5f6f512005-03-10 23:59:00 +0000154static int scan_auxv(void* init_sp)
nethercote71980f02004-01-24 18:18:54 +0000155{
njn62ff0f22005-06-21 23:03:36 +0000156 struct ume_auxv *auxv = VG_(find_auxv)((UWord*)init_sp);
nethercote31779c72004-07-30 21:50:15 +0000157 int padfile = -1, found = 0;
nethercote71980f02004-01-24 18:18:54 +0000158
159 for (; auxv->a_type != AT_NULL; auxv++)
160 switch(auxv->a_type) {
161 case AT_UME_PADFD:
nethercote31779c72004-07-30 21:50:15 +0000162 padfile = auxv->u.a_val;
nethercote71980f02004-01-24 18:18:54 +0000163 found |= 1;
164 break;
165
166 case AT_UME_EXECFD:
nethercotef6a1d502004-08-09 12:21:57 +0000167 vgexecfd = auxv->u.a_val;
nethercote71980f02004-01-24 18:18:54 +0000168 found |= 2;
169 break;
nethercote7f390022004-10-25 17:18:24 +0000170
sewardj10f08cf2005-06-29 10:16:14 +0000171# if defined(VGP_ppc32_linux)
cerion85665ca2005-06-20 15:51:07 +0000172 case AT_DCACHEBSIZE:
173 case AT_ICACHEBSIZE:
174 case AT_UCACHEBSIZE:
sewardj10f08cf2005-06-29 10:16:14 +0000175 if (auxv->u.a_val > 0) {
176 VG_(cache_line_size_ppc32) = auxv->u.a_val;
177 VG_(debugLog)(1, "main",
178 "PPC32 cache line size %u (type %u)\n",
179 (UInt)auxv->u.a_val, (UInt)auxv->a_type );
180 }
cerion85665ca2005-06-20 15:51:07 +0000181 break;
sewardjcdd81cb2005-08-04 23:52:21 +0000182
183 case AT_HWCAP:
184 VG_(debugLog)(1, "main", "PPC32 hwcaps(1): 0x%x\n", (UInt)auxv->u.a_val);
185 auxv->u.a_val &= ~0x10000000; /* claim there is no Altivec support */
186 VG_(debugLog)(1, "main", "PPC32 hwcaps(2): 0x%x\n", (UInt)auxv->u.a_val);
187 break;
sewardj10f08cf2005-06-29 10:16:14 +0000188# endif
cerion85665ca2005-06-20 15:51:07 +0000189
nethercote7f390022004-10-25 17:18:24 +0000190 case AT_PHDR:
njn13bfd852005-06-02 03:52:53 +0000191 VG_(valgrind_base) = VG_PGROUNDDN(auxv->u.a_val);
nethercote7f390022004-10-25 17:18:24 +0000192 break;
cerion85665ca2005-06-20 15:51:07 +0000193
sewardj10f08cf2005-06-29 10:16:14 +0000194 default:
195 break;
nethercote71980f02004-01-24 18:18:54 +0000196 }
197
nethercote361a14e2004-07-26 11:11:56 +0000198 if ( found != (1|2) ) {
199 fprintf(stderr, "valgrind: stage2 must be launched by stage1\n");
nethercote71980f02004-01-24 18:18:54 +0000200 exit(127);
201 }
nethercote31779c72004-07-30 21:50:15 +0000202 vg_assert(padfile >= 0);
203 return padfile;
nethercote71980f02004-01-24 18:18:54 +0000204}
205
206
207/*====================================================================*/
208/*=== Address space determination ===*/
209/*====================================================================*/
210
nethercote7f390022004-10-25 17:18:24 +0000211extern char _start[];
212
nethercote31779c72004-07-30 21:50:15 +0000213static void layout_remaining_space(Addr argc_addr, float ratio)
nethercote71980f02004-01-24 18:18:54 +0000214{
njn83407492005-06-19 16:10:47 +0000215 SysRes res;
216 Addr client_size, shadow_size;
nethercote71980f02004-01-24 18:18:54 +0000217
nethercote7f390022004-10-25 17:18:24 +0000218 // VG_(valgrind_base) should have been set by scan_auxv, but if not,
219 // this is a workable approximation
220 if (VG_(valgrind_base) == 0) {
njn13bfd852005-06-02 03:52:53 +0000221 VG_(valgrind_base) = VG_PGROUNDDN(&_start);
nethercote7f390022004-10-25 17:18:24 +0000222 }
223
njn13bfd852005-06-02 03:52:53 +0000224 VG_(valgrind_last) = VG_ROUNDUP(argc_addr, 0x10000) - 1; // stack
nethercote71980f02004-01-24 18:18:54 +0000225
nethercote31779c72004-07-30 21:50:15 +0000226 // This gives the client the largest possible address space while
227 // taking into account the tool's shadow needs.
njn13bfd852005-06-02 03:52:53 +0000228 client_size = VG_ROUNDDN((VG_(valgrind_base)-REDZONE_SIZE) / (1.+ratio),
nethercote71980f02004-01-24 18:18:54 +0000229 CLIENT_SIZE_MULTIPLE);
njn311c5d82005-05-15 21:03:42 +0000230 VG_(client_base) = 0;
nethercote71980f02004-01-24 18:18:54 +0000231 VG_(client_end) = VG_(client_base) + client_size;
nethercotee2097312004-06-27 12:29:56 +0000232 /* where !FIXED mmap goes */
nethercotebc7b4f42004-07-26 12:44:35 +0000233 VG_(client_mapbase) = VG_(client_base) +
njn13bfd852005-06-02 03:52:53 +0000234 VG_PGROUNDDN((Addr)(client_size * CLIENT_HEAP_PROPORTION));
nethercote71980f02004-01-24 18:18:54 +0000235
nethercote31779c72004-07-30 21:50:15 +0000236 VG_(shadow_base) = VG_(client_end) + REDZONE_SIZE;
nethercote410bfe62004-09-04 15:53:35 +0000237 VG_(shadow_end) = VG_(valgrind_base);
238 shadow_size = VG_(shadow_end) - VG_(shadow_base);
nethercote71980f02004-01-24 18:18:54 +0000239
nethercotee2097312004-06-27 12:29:56 +0000240#define SEGSIZE(a,b) ((VG_(b) - VG_(a))/(1024*1024))
241
nethercote71980f02004-01-24 18:18:54 +0000242 if (0)
nethercotee2097312004-06-27 12:29:56 +0000243 VG_(printf)(
tomb1d43182005-03-29 09:00:12 +0000244 "client_base %p (%dMB)\n"
245 "client_mapbase %p (%dMB)\n"
246 "client_end %p (%dMB)\n"
247 "shadow_base %p (%dMB)\n"
248 "shadow_end %p\n"
249 "valgrind_base %p (%dMB)\n"
250 "valgrind_last %p\n",
nethercotee2097312004-06-27 12:29:56 +0000251 VG_(client_base), SEGSIZE(client_base, client_mapbase),
252 VG_(client_mapbase), SEGSIZE(client_mapbase, client_end),
253 VG_(client_end), SEGSIZE(client_end, shadow_base),
254 VG_(shadow_base), SEGSIZE(shadow_base, shadow_end),
nethercote410bfe62004-09-04 15:53:35 +0000255 VG_(shadow_end),
nethercote820bd8c2004-09-07 23:04:49 +0000256 VG_(valgrind_base), SEGSIZE(valgrind_base, valgrind_last),
257 VG_(valgrind_last)
nethercotee2097312004-06-27 12:29:56 +0000258 );
259
260#undef SEGSIZE
nethercote71980f02004-01-24 18:18:54 +0000261
262 // Ban redzone
njn83407492005-06-19 16:10:47 +0000263 res = VG_(mmap_native)((void *)VG_(client_end), REDZONE_SIZE, VKI_PROT_NONE,
264 VKI_MAP_FIXED|VKI_MAP_ANONYMOUS|VKI_MAP_PRIVATE|VKI_MAP_NORESERVE,
265 -1, 0);
266 vg_assert(!res.isError);
nethercote71980f02004-01-24 18:18:54 +0000267
268 // Make client hole
njn83407492005-06-19 16:10:47 +0000269 res = VG_(munmap_native)((void*)VG_(client_base), client_size);
270 vg_assert(!res.isError);
nethercote71980f02004-01-24 18:18:54 +0000271
272 // Map shadow memory.
273 // Initially all inaccessible, incrementally initialized as it is used
nethercotee567e702004-07-10 17:49:17 +0000274 if (shadow_size != 0) {
njn83407492005-06-19 16:10:47 +0000275 res = VG_(mmap_native)((char *)VG_(shadow_base), shadow_size,
276 VKI_PROT_NONE,
277 VKI_MAP_PRIVATE|VKI_MAP_ANONYMOUS|VKI_MAP_FIXED|VKI_MAP_NORESERVE,
278 -1, 0);
279 if (res.isError) {
nethercoted4722622004-08-30 19:36:42 +0000280 fprintf(stderr,
nethercote8c1ce432004-10-08 14:01:14 +0000281 "valgrind: Could not allocate address space (%p bytes)\n"
282 "valgrind: for shadow memory\n"
283 "valgrind: Possible causes:\n"
284 "valgrind: - For some systems (especially under RedHat 8), Valgrind\n"
285 "valgrind: needs at least 1.5GB swap space.\n"
286 "valgrind: - Or, your virtual memory size may be limited (check\n"
287 "valgrind: with 'ulimit -v').\n"
288 "valgrind: - Or, your system may use a kernel that provides only a\n"
289 "valgrind: too-small (eg. 2GB) user address space.\n"
290 , (void*)shadow_size
291 );
nethercoted4722622004-08-30 19:36:42 +0000292 exit(1);
293 }
nethercotee567e702004-07-10 17:49:17 +0000294 }
nethercote71980f02004-01-24 18:18:54 +0000295}
296
297/*====================================================================*/
298/*=== Command line setup ===*/
299/*====================================================================*/
300
njndcc99d32005-06-19 15:34:59 +0000301// Note that we deliberately don't free the malloc'd memory. See comment
302// at call site.
nethercote71980f02004-01-24 18:18:54 +0000303static char* get_file_clo(char* dir)
304{
305# define FLEN 512
sewardj92645592005-07-23 09:18:34 +0000306 Int n;
307 SysRes fd;
njn909c3192005-06-19 15:46:27 +0000308 struct vki_stat s1;
sewardj92645592005-07-23 09:18:34 +0000309 Char* f_clo = NULL;
310 Char filename[FLEN];
nethercote71980f02004-01-24 18:18:54 +0000311
312 snprintf(filename, FLEN, "%s/.valgrindrc", ( NULL == dir ? "" : dir ) );
313 fd = VG_(open)(filename, 0, VKI_S_IRUSR);
sewardj92645592005-07-23 09:18:34 +0000314 if ( !fd.isError ) {
315 if ( 0 == VG_(fstat)(fd.val, &s1) ) {
nethercote71980f02004-01-24 18:18:54 +0000316 f_clo = malloc(s1.st_size+1);
317 vg_assert(f_clo);
sewardj92645592005-07-23 09:18:34 +0000318 n = VG_(read)(fd.val, f_clo, s1.st_size);
nethercote71980f02004-01-24 18:18:54 +0000319 if (n == -1) n = 0;
320 f_clo[n] = '\0';
321 }
sewardj92645592005-07-23 09:18:34 +0000322 VG_(close)(fd.val);
nethercote71980f02004-01-24 18:18:54 +0000323 }
324 return f_clo;
325# undef FLEN
326}
327
328static Int count_args(char* s)
329{
330 Int n = 0;
331 if (s) {
332 char* cp = s;
333 while (True) {
334 // We have alternating sequences: blanks, non-blanks, blanks...
335 // count the non-blanks sequences.
njn0c0f32a2005-03-26 04:14:01 +0000336 while ( VG_(isspace)(*cp) ) cp++;
nethercote71980f02004-01-24 18:18:54 +0000337 if ( !*cp ) break;
338 n++;
njn0c0f32a2005-03-26 04:14:01 +0000339 while ( !VG_(isspace)(*cp) && *cp ) cp++;
nethercote71980f02004-01-24 18:18:54 +0000340 }
341 }
342 return n;
343}
344
njndcc99d32005-06-19 15:34:59 +0000345// Add args out of environment, skipping multiple spaces and "--" args.
346// We split 's' into multiple strings by replacing whitespace with nuls,
347// eg. "--aa --bb --cc" --> "--aa\0--bb\0--cc". And for each new string
348// carved out of 's', we put a pointer to it in 'to'.
nethercote71980f02004-01-24 18:18:54 +0000349static char** copy_args( char* s, char** to )
350{
351 if (s) {
352 char* cp = s;
353 while (True) {
354 // We have alternating sequences: blanks, non-blanks, blanks...
355 // copy the non-blanks sequences, and add terminating '\0'
njn0c0f32a2005-03-26 04:14:01 +0000356 while ( VG_(isspace)(*cp) ) cp++;
nethercote71980f02004-01-24 18:18:54 +0000357 if ( !*cp ) break;
358 *to++ = cp;
njn0c0f32a2005-03-26 04:14:01 +0000359 while ( !VG_(isspace)(*cp) && *cp ) cp++;
njndcc99d32005-06-19 15:34:59 +0000360 if ( *cp ) *cp++ = '\0'; // terminate if not the last
nethercote71980f02004-01-24 18:18:54 +0000361 if (VG_STREQ(to[-1], "--")) to--; // undo any '--' arg
362 }
363 }
364 return to;
365}
366
367// Augment command line with arguments from environment and .valgrindrc
368// files.
369static void augment_command_line(Int* vg_argc_inout, char*** vg_argv_inout)
370{
nethercotef6a1d502004-08-09 12:21:57 +0000371 int vg_argc0 = *vg_argc_inout;
372 char** vg_argv0 = *vg_argv_inout;
nethercote71980f02004-01-24 18:18:54 +0000373
njndcc99d32005-06-19 15:34:59 +0000374 // get_file_clo() allocates the return value with malloc(). We do not
375 // free f1_clo and f2_clo as they get put into vg_argv[] which must persist.
nethercote71980f02004-01-24 18:18:54 +0000376 char* env_clo = getenv(VALGRINDOPTS);
377 char* f1_clo = get_file_clo( getenv("HOME") );
378 char* f2_clo = get_file_clo(".");
379
380 /* copy any extra args from file or environment, if present */
381 if ( (env_clo && *env_clo) || (f1_clo && *f1_clo) || (f2_clo && *f2_clo) ) {
382 /* ' ' separated extra options */
383 char **from;
384 char **to;
thughescaca0022004-09-13 10:20:34 +0000385 int orig_arg_count, env_arg_count, f1_arg_count, f2_arg_count;
386
387 for ( orig_arg_count = 0; vg_argv0[orig_arg_count]; orig_arg_count++ );
388
nethercote71980f02004-01-24 18:18:54 +0000389 env_arg_count = count_args(env_clo);
390 f1_arg_count = count_args(f1_clo);
391 f2_arg_count = count_args(f2_clo);
392
393 if (0)
394 printf("extra-argc=%d %d %d\n",
395 env_arg_count, f1_arg_count, f2_arg_count);
396
397 /* +2: +1 for null-termination, +1 for added '--' */
nethercotef6a1d502004-08-09 12:21:57 +0000398 from = vg_argv0;
thughescaca0022004-09-13 10:20:34 +0000399 vg_argv0 = malloc( (orig_arg_count + env_arg_count + f1_arg_count
nethercote71980f02004-01-24 18:18:54 +0000400 + f2_arg_count + 2) * sizeof(char **));
nethercotef6a1d502004-08-09 12:21:57 +0000401 vg_assert(vg_argv0);
402 to = vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000403
404 /* copy argv[0] */
405 *to++ = *from++;
406
407 /* Copy extra args from env var and file, in the order: ~/.valgrindrc,
408 * $VALGRIND_OPTS, ./.valgrindrc -- more local options are put later
409 * to override less local ones. */
410 to = copy_args(f1_clo, to);
411 to = copy_args(env_clo, to);
412 to = copy_args(f2_clo, to);
njna96e15a2005-05-24 21:36:32 +0000413
nethercote71980f02004-01-24 18:18:54 +0000414 /* copy original arguments, stopping at command or -- */
415 while (*from) {
416 if (**from != '-')
417 break;
418 if (VG_STREQ(*from, "--")) {
419 from++; /* skip -- */
420 break;
421 }
422 *to++ = *from++;
423 }
424
425 /* add -- */
426 *to++ = "--";
427
nethercotef6a1d502004-08-09 12:21:57 +0000428 vg_argc0 = to - vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000429
430 /* copy rest of original command line, then NULL */
431 while (*from) *to++ = *from++;
432 *to = NULL;
433 }
434
nethercotef6a1d502004-08-09 12:21:57 +0000435 *vg_argc_inout = vg_argc0;
436 *vg_argv_inout = vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000437}
438
nethercotef6a1d502004-08-09 12:21:57 +0000439#define VG_CLO_SEP '\01'
440
nethercote71980f02004-01-24 18:18:54 +0000441static void get_command_line( int argc, char** argv,
442 Int* vg_argc_out, Char*** vg_argv_out,
443 char*** cl_argv_out )
444{
nethercotef6a1d502004-08-09 12:21:57 +0000445 int vg_argc0;
446 char** vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000447 char** cl_argv;
448 char* env_clo = getenv(VALGRINDCLO);
449
450 if (env_clo != NULL && *env_clo != '\0') {
451 char *cp;
452 char **cpp;
453
nethercotef6a1d502004-08-09 12:21:57 +0000454 /* OK, VALGRINDCLO is set, which means we must be a child of another
455 Valgrind process using --trace-children, so we're getting all our
456 arguments from VALGRINDCLO, and the entire command line belongs to
457 the client (including argv[0]) */
458 vg_argc0 = 1; /* argv[0] */
nethercote71980f02004-01-24 18:18:54 +0000459 for (cp = env_clo; *cp; cp++)
nethercotef6a1d502004-08-09 12:21:57 +0000460 if (*cp == VG_CLO_SEP)
461 vg_argc0++;
nethercote71980f02004-01-24 18:18:54 +0000462
nethercotef6a1d502004-08-09 12:21:57 +0000463 vg_argv0 = malloc(sizeof(char **) * (vg_argc0 + 1));
464 vg_assert(vg_argv0);
nethercote71980f02004-01-24 18:18:54 +0000465
nethercotef6a1d502004-08-09 12:21:57 +0000466 cpp = vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000467
468 *cpp++ = "valgrind"; /* nominal argv[0] */
469 *cpp++ = env_clo;
470
nethercotef6a1d502004-08-09 12:21:57 +0000471 // Replace the VG_CLO_SEP args separator with '\0'
nethercote71980f02004-01-24 18:18:54 +0000472 for (cp = env_clo; *cp; cp++) {
nethercotef6a1d502004-08-09 12:21:57 +0000473 if (*cp == VG_CLO_SEP) {
nethercote71980f02004-01-24 18:18:54 +0000474 *cp++ = '\0'; /* chop it up in place */
475 *cpp++ = cp;
476 }
477 }
478 *cpp = NULL;
479 cl_argv = argv;
480
481 } else {
sewardjb5f6f512005-03-10 23:59:00 +0000482 Bool noaugment = False;
483
nethercote71980f02004-01-24 18:18:54 +0000484 /* Count the arguments on the command line. */
nethercotef6a1d502004-08-09 12:21:57 +0000485 vg_argv0 = argv;
nethercote71980f02004-01-24 18:18:54 +0000486
nethercotef6a1d502004-08-09 12:21:57 +0000487 for (vg_argc0 = 1; vg_argc0 < argc; vg_argc0++) {
sewardjb5f6f512005-03-10 23:59:00 +0000488 Char* arg = argv[vg_argc0];
489 if (arg[0] != '-') /* exe name */
nethercote71980f02004-01-24 18:18:54 +0000490 break;
sewardjb5f6f512005-03-10 23:59:00 +0000491 if (VG_STREQ(arg, "--")) { /* dummy arg */
nethercotef6a1d502004-08-09 12:21:57 +0000492 vg_argc0++;
nethercote71980f02004-01-24 18:18:54 +0000493 break;
494 }
njn45270a22005-03-27 01:00:11 +0000495 VG_BOOL_CLO(arg, "--command-line-only", noaugment)
nethercote71980f02004-01-24 18:18:54 +0000496 }
nethercotef6a1d502004-08-09 12:21:57 +0000497 cl_argv = &argv[vg_argc0];
nethercote71980f02004-01-24 18:18:54 +0000498
499 /* Get extra args from VALGRIND_OPTS and .valgrindrc files.
nethercotef6a1d502004-08-09 12:21:57 +0000500 Note we don't do this if getting args from VALGRINDCLO, as
sewardjb5f6f512005-03-10 23:59:00 +0000501 those extra args will already be present in VALGRINDCLO.
502 (We also don't do it when --command-line-only=yes.) */
503 if (!noaugment)
504 augment_command_line(&vg_argc0, &vg_argv0);
nethercote71980f02004-01-24 18:18:54 +0000505 }
506
507 if (0) {
508 Int i;
nethercotef6a1d502004-08-09 12:21:57 +0000509 for (i = 0; i < vg_argc0; i++)
510 printf("vg_argv0[%d]=\"%s\"\n", i, vg_argv0[i]);
nethercote71980f02004-01-24 18:18:54 +0000511 }
512
nethercotef6a1d502004-08-09 12:21:57 +0000513 *vg_argc_out = vg_argc0;
514 *vg_argv_out = (Char**)vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000515 *cl_argv_out = cl_argv;
516}
517
518
519/*====================================================================*/
520/*=== Environment and stack setup ===*/
521/*====================================================================*/
522
523/* Scan a colon-separated list, and call a function on each element.
524 The string must be mutable, because we insert a temporary '\0', but
thughes4ad52d02004-06-27 17:37:21 +0000525 the string will end up unmodified. (*func) should return True if it
nethercote71980f02004-01-24 18:18:54 +0000526 doesn't need to see any more.
thughes4ad52d02004-06-27 17:37:21 +0000527
528 This routine will return True if (*func) returns True and False if
529 it reaches the end of the list without that happening.
nethercote71980f02004-01-24 18:18:54 +0000530*/
thughes4ad52d02004-06-27 17:37:21 +0000531static Bool scan_colsep(char *colsep, Bool (*func)(const char *))
nethercote71980f02004-01-24 18:18:54 +0000532{
533 char *cp, *entry;
534 int end;
535
536 if (colsep == NULL ||
537 *colsep == '\0')
thughes4ad52d02004-06-27 17:37:21 +0000538 return False;
nethercote71980f02004-01-24 18:18:54 +0000539
540 entry = cp = colsep;
541
542 do {
543 end = (*cp == '\0');
544
545 if (*cp == ':' || *cp == '\0') {
546 char save = *cp;
547
548 *cp = '\0';
thughes21942d92004-07-12 09:35:37 +0000549 if ((*func)(entry)) {
550 *cp = save;
thughes4ad52d02004-06-27 17:37:21 +0000551 return True;
thughes21942d92004-07-12 09:35:37 +0000552 }
nethercote71980f02004-01-24 18:18:54 +0000553 *cp = save;
554 entry = cp+1;
555 }
556 cp++;
557 } while(!end);
thughes4ad52d02004-06-27 17:37:21 +0000558
559 return False;
560}
561
nethercote71980f02004-01-24 18:18:54 +0000562/* Prepare the client's environment. This is basically a copy of our
563 environment, except:
njn16eeb4e2005-06-16 03:56:58 +0000564 LD_PRELOAD=$VALGRINDLIB/vg_preload_core.so:($VALGRINDLIB/vgpreload_TOOL.so:)?$LD_PRELOAD
nethercote71980f02004-01-24 18:18:54 +0000565
sewardjb5f6f512005-03-10 23:59:00 +0000566 If this is missing, then it is added.
nethercote71980f02004-01-24 18:18:54 +0000567
568 Yummy. String hacking in C.
569
570 If this needs to handle any more variables it should be hacked
571 into something table driven.
572 */
573static char **fix_environment(char **origenv, const char *preload)
574{
njn16eeb4e2005-06-16 03:56:58 +0000575 static const char preload_core_so[] = "vg_preload_core.so";
nethercote71980f02004-01-24 18:18:54 +0000576 static const char ld_preload[] = "LD_PRELOAD=";
577 static const char valgrind_clo[] = VALGRINDCLO "=";
nethercote71980f02004-01-24 18:18:54 +0000578 static const int ld_preload_len = sizeof(ld_preload)-1;
579 static const int valgrind_clo_len = sizeof(valgrind_clo)-1;
580 int ld_preload_done = 0;
njn16eeb4e2005-06-16 03:56:58 +0000581 char *preload_core_path;
582 int preload_core_path_len;
nethercote71980f02004-01-24 18:18:54 +0000583 int vgliblen = strlen(VG_(libdir));
584 char **cpp;
585 char **ret;
586 int envc;
587 const int preloadlen = (preload == NULL) ? 0 : strlen(preload);
588
njn16eeb4e2005-06-16 03:56:58 +0000589 /* Find the vg_preload_core.so; also make room for the tool preload
nethercote71980f02004-01-24 18:18:54 +0000590 library */
njn16eeb4e2005-06-16 03:56:58 +0000591 preload_core_path_len = sizeof(preload_core_so) + vgliblen + preloadlen + 16;
592 preload_core_path = malloc(preload_core_path_len);
593 vg_assert(preload_core_path);
nethercote71980f02004-01-24 18:18:54 +0000594
595 if (preload)
njn16eeb4e2005-06-16 03:56:58 +0000596 snprintf(preload_core_path, preload_core_path_len, "%s/%s:%s",
597 VG_(libdir), preload_core_so, preload);
nethercote71980f02004-01-24 18:18:54 +0000598 else
njn16eeb4e2005-06-16 03:56:58 +0000599 snprintf(preload_core_path, preload_core_path_len, "%s/%s",
600 VG_(libdir), preload_core_so);
nethercote71980f02004-01-24 18:18:54 +0000601
602 /* Count the original size of the env */
603 envc = 0; /* trailing NULL */
604 for (cpp = origenv; cpp && *cpp; cpp++)
605 envc++;
606
607 /* Allocate a new space */
sewardjb5f6f512005-03-10 23:59:00 +0000608 ret = malloc(sizeof(char *) * (envc+1+1)); /* 1 new entry + NULL */
nethercote7c018f42004-07-17 16:40:50 +0000609 vg_assert(ret);
nethercote71980f02004-01-24 18:18:54 +0000610
611 /* copy it over */
612 for (cpp = ret; *origenv; )
613 *cpp++ = *origenv++;
614 *cpp = NULL;
615
616 vg_assert(envc == (cpp - ret));
617
618 /* Walk over the new environment, mashing as we go */
619 for (cpp = ret; cpp && *cpp; cpp++) {
sewardjb5f6f512005-03-10 23:59:00 +0000620 if (memcmp(*cpp, ld_preload, ld_preload_len) == 0) {
njn16eeb4e2005-06-16 03:56:58 +0000621 int len = strlen(*cpp) + preload_core_path_len;
nethercote71980f02004-01-24 18:18:54 +0000622 char *cp = malloc(len);
nethercote7c018f42004-07-17 16:40:50 +0000623 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000624
625 snprintf(cp, len, "%s%s:%s",
njn16eeb4e2005-06-16 03:56:58 +0000626 ld_preload, preload_core_path, (*cpp)+ld_preload_len);
nethercote71980f02004-01-24 18:18:54 +0000627
628 *cpp = cp;
629
630 ld_preload_done = 1;
631 } else if (memcmp(*cpp, valgrind_clo, valgrind_clo_len) == 0) {
632 *cpp = "";
633 }
634 }
635
636 /* Add the missing bits */
nethercote71980f02004-01-24 18:18:54 +0000637 if (!ld_preload_done) {
njn16eeb4e2005-06-16 03:56:58 +0000638 int len = ld_preload_len + preload_core_path_len;
nethercote71980f02004-01-24 18:18:54 +0000639 char *cp = malloc(len);
nethercote7c018f42004-07-17 16:40:50 +0000640 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000641
njn16eeb4e2005-06-16 03:56:58 +0000642 snprintf(cp, len, "%s%s", ld_preload, preload_core_path);
nethercote71980f02004-01-24 18:18:54 +0000643
644 ret[envc++] = cp;
645 }
646
njn16eeb4e2005-06-16 03:56:58 +0000647 free(preload_core_path);
nethercote71980f02004-01-24 18:18:54 +0000648 ret[envc] = NULL;
649
650 return ret;
651}
652
653extern char **environ; /* our environment */
nethercote71980f02004-01-24 18:18:54 +0000654
655/* Add a string onto the string table, and return its address */
656static char *copy_str(char **tab, const char *str)
657{
658 char *cp = *tab;
659 char *orig = cp;
660
661 while(*str)
662 *cp++ = *str++;
663 *cp++ = '\0';
664
665 if (0)
nethercote545fe672004-11-01 16:52:43 +0000666 printf("copied %p \"%s\" len %lld\n", orig, orig, (Long)(cp-orig));
nethercote71980f02004-01-24 18:18:54 +0000667
668 *tab = cp;
669
670 return orig;
671}
672
673/*
674 This sets up the client's initial stack, containing the args,
675 environment and aux vector.
676
677 The format of the stack is:
678
679 higher address +-----------------+
680 | Trampoline code |
681 +-----------------+
682 | |
683 : string table :
684 | |
685 +-----------------+
686 | AT_NULL |
687 - -
688 | auxv |
689 +-----------------+
690 | NULL |
691 - -
692 | envp |
693 +-----------------+
694 | NULL |
695 - -
696 | argv |
697 +-----------------+
698 | argc |
nethercote4ad74312004-10-26 09:59:49 +0000699 lower address +-----------------+ <- sp
nethercote71980f02004-01-24 18:18:54 +0000700 | undefined |
701 : :
702 */
nethercotec25c4492004-10-18 11:52:17 +0000703static Addr setup_client_stack(void* init_sp,
704 char **orig_argv, char **orig_envp,
nethercote71980f02004-01-24 18:18:54 +0000705 const struct exeinfo *info,
706 UInt** client_auxv)
707{
njn83407492005-06-19 16:10:47 +0000708 SysRes res;
nethercote71980f02004-01-24 18:18:54 +0000709 char **cpp;
710 char *strtab; /* string table */
711 char *stringbase;
nethercotea3c3cf22004-11-01 18:38:00 +0000712 Addr *ptr;
nethercote71980f02004-01-24 18:18:54 +0000713 struct ume_auxv *auxv;
714 const struct ume_auxv *orig_auxv;
715 const struct ume_auxv *cauxv;
716 unsigned stringsize; /* total size of strings in bytes */
717 unsigned auxsize; /* total size of auxv in bytes */
718 int argc; /* total argc */
719 int envc; /* total number of env vars */
720 unsigned stacksize; /* total client stack size */
nethercotea3c3cf22004-11-01 18:38:00 +0000721 Addr cl_esp; /* client stack base (initial esp) */
nethercote71980f02004-01-24 18:18:54 +0000722
723 /* use our own auxv as a prototype */
njn62ff0f22005-06-21 23:03:36 +0000724 orig_auxv = VG_(find_auxv)(init_sp);
nethercote71980f02004-01-24 18:18:54 +0000725
726 /* ==================== compute sizes ==================== */
727
728 /* first of all, work out how big the client stack will be */
729 stringsize = 0;
730
731 /* paste on the extra args if the loader needs them (ie, the #!
732 interpreter and its argument) */
733 argc = 0;
nethercoted6a56872004-07-26 15:32:47 +0000734 if (info->interp_name != NULL) {
nethercote71980f02004-01-24 18:18:54 +0000735 argc++;
nethercoted6a56872004-07-26 15:32:47 +0000736 stringsize += strlen(info->interp_name) + 1;
nethercote71980f02004-01-24 18:18:54 +0000737 }
nethercoted6a56872004-07-26 15:32:47 +0000738 if (info->interp_args != NULL) {
nethercote71980f02004-01-24 18:18:54 +0000739 argc++;
nethercoted6a56872004-07-26 15:32:47 +0000740 stringsize += strlen(info->interp_args) + 1;
nethercote71980f02004-01-24 18:18:54 +0000741 }
742
743 /* now scan the args we're given... */
744 for (cpp = orig_argv; *cpp; cpp++) {
745 argc++;
746 stringsize += strlen(*cpp) + 1;
747 }
748
749 /* ...and the environment */
750 envc = 0;
751 for (cpp = orig_envp; cpp && *cpp; cpp++) {
752 envc++;
753 stringsize += strlen(*cpp) + 1;
754 }
755
756 /* now, how big is the auxv? */
757 auxsize = sizeof(*auxv); /* there's always at least one entry: AT_NULL */
758 for (cauxv = orig_auxv; cauxv->a_type != AT_NULL; cauxv++) {
759 if (cauxv->a_type == AT_PLATFORM)
760 stringsize += strlen(cauxv->u.a_ptr) + 1;
761 auxsize += sizeof(*cauxv);
762 }
763
cerion85665ca2005-06-20 15:51:07 +0000764#if defined(VGP_ppc32_linux)
765 auxsize += 2 * sizeof(*cauxv);
766#endif
767
nethercote71980f02004-01-24 18:18:54 +0000768 /* OK, now we know how big the client stack is */
769 stacksize =
sewardj9d9cdea2005-03-23 03:06:30 +0000770 sizeof(Word) + /* argc */
nethercote71980f02004-01-24 18:18:54 +0000771 sizeof(char **)*argc + /* argv */
772 sizeof(char **) + /* terminal NULL */
773 sizeof(char **)*envc + /* envp */
774 sizeof(char **) + /* terminal NULL */
775 auxsize + /* auxv */
njn13bfd852005-06-02 03:52:53 +0000776 VG_ROUNDUP(stringsize, sizeof(Word)) +/* strings (aligned) */
nethercote5fd72bb2004-11-04 19:28:38 +0000777 VKI_PAGE_SIZE; /* page for trampoline code */
nethercote71980f02004-01-24 18:18:54 +0000778
sewardj79048ce2005-02-18 08:28:32 +0000779 if (0) VG_(printf)("stacksize = %d\n", stacksize);
780
nethercotef84f6952004-07-15 14:58:33 +0000781 // decide where stack goes!
782 VG_(clstk_end) = VG_(client_end);
783
nethercote71980f02004-01-24 18:18:54 +0000784 /* cl_esp is the client's stack pointer */
nethercotef84f6952004-07-15 14:58:33 +0000785 cl_esp = VG_(clstk_end) - stacksize;
njn13bfd852005-06-02 03:52:53 +0000786 cl_esp = VG_ROUNDDN(cl_esp, 16); /* make stack 16 byte aligned */
nethercote71980f02004-01-24 18:18:54 +0000787
nethercote71980f02004-01-24 18:18:54 +0000788 /* base of the string table (aligned) */
sewardjb9bce632005-06-21 01:41:34 +0000789 stringbase = strtab = (char *)(VG_(clstk_end)
njn13bfd852005-06-02 03:52:53 +0000790 - VG_ROUNDUP(stringsize, sizeof(int)));
nethercote71980f02004-01-24 18:18:54 +0000791
njn13bfd852005-06-02 03:52:53 +0000792 VG_(clstk_base) = VG_PGROUNDDN(cl_esp);
nethercote71980f02004-01-24 18:18:54 +0000793
sewardj79048ce2005-02-18 08:28:32 +0000794 if (0)
nethercote5ee67ca2004-06-22 14:00:09 +0000795 printf("stringsize=%d auxsize=%d stacksize=%d\n"
nethercote6a27d832004-09-07 10:17:02 +0000796 "clstk_base %p\n"
797 "clstk_end %p\n",
798 stringsize, auxsize, stacksize,
799 (void*)VG_(clstk_base), (void*)VG_(clstk_end));
nethercote5ee67ca2004-06-22 14:00:09 +0000800
nethercote71980f02004-01-24 18:18:54 +0000801 /* ==================== allocate space ==================== */
802
803 /* allocate a stack - mmap enough space for the stack */
njn83407492005-06-19 16:10:47 +0000804 res = VG_(mmap_native)((void *)VG_PGROUNDDN(cl_esp),
njn13bfd852005-06-02 03:52:53 +0000805 VG_(clstk_end) - VG_PGROUNDDN(cl_esp),
njn83407492005-06-19 16:10:47 +0000806 VKI_PROT_READ|VKI_PROT_WRITE|VKI_PROT_EXEC,
807 VKI_MAP_PRIVATE|VKI_MAP_ANONYMOUS|VKI_MAP_FIXED, -1, 0);
808 vg_assert(!res.isError);
nethercote71980f02004-01-24 18:18:54 +0000809
810 /* ==================== copy client stack ==================== */
811
nethercotea3c3cf22004-11-01 18:38:00 +0000812 ptr = (Addr*)cl_esp;
nethercote71980f02004-01-24 18:18:54 +0000813
814 /* --- argc --- */
815 *ptr++ = argc; /* client argc */
816
817 /* --- argv --- */
nethercoted6a56872004-07-26 15:32:47 +0000818 if (info->interp_name) {
nethercotea3c3cf22004-11-01 18:38:00 +0000819 *ptr++ = (Addr)copy_str(&strtab, info->interp_name);
nethercoted6a56872004-07-26 15:32:47 +0000820 free(info->interp_name);
nethercote71980f02004-01-24 18:18:54 +0000821 }
nethercoted6a56872004-07-26 15:32:47 +0000822 if (info->interp_args) {
nethercotea3c3cf22004-11-01 18:38:00 +0000823 *ptr++ = (Addr)copy_str(&strtab, info->interp_args);
nethercoted6a56872004-07-26 15:32:47 +0000824 free(info->interp_args);
nethercote71980f02004-01-24 18:18:54 +0000825 }
826 for (cpp = orig_argv; *cpp; ptr++, cpp++) {
nethercotea3c3cf22004-11-01 18:38:00 +0000827 *ptr = (Addr)copy_str(&strtab, *cpp);
nethercote71980f02004-01-24 18:18:54 +0000828 }
829 *ptr++ = 0;
830
831 /* --- envp --- */
832 VG_(client_envp) = (Char **)ptr;
833 for (cpp = orig_envp; cpp && *cpp; ptr++, cpp++)
nethercotea3c3cf22004-11-01 18:38:00 +0000834 *ptr = (Addr)copy_str(&strtab, *cpp);
nethercote71980f02004-01-24 18:18:54 +0000835 *ptr++ = 0;
836
837 /* --- auxv --- */
838 auxv = (struct ume_auxv *)ptr;
839 *client_auxv = (UInt *)auxv;
840
cerion85665ca2005-06-20 15:51:07 +0000841#if defined(VGP_ppc32_linux)
842 auxv[0].a_type = AT_IGNOREPPC;
843 auxv[0].u.a_val = AT_IGNOREPPC;
844 auxv[1].a_type = AT_IGNOREPPC;
845 auxv[1].u.a_val = AT_IGNOREPPC;
846 auxv += 2;
847#endif
848
nethercote71980f02004-01-24 18:18:54 +0000849 for (; orig_auxv->a_type != AT_NULL; auxv++, orig_auxv++) {
850 /* copy the entry... */
851 *auxv = *orig_auxv;
852
853 /* ...and fix up the copy */
854 switch(auxv->a_type) {
855 case AT_PHDR:
856 if (info->phdr == 0)
857 auxv->a_type = AT_IGNORE;
858 else
859 auxv->u.a_val = info->phdr;
860 break;
861
862 case AT_PHNUM:
863 if (info->phdr == 0)
864 auxv->a_type = AT_IGNORE;
865 else
866 auxv->u.a_val = info->phnum;
867 break;
868
869 case AT_BASE:
sewardjb5f6f512005-03-10 23:59:00 +0000870 auxv->u.a_val = info->interp_base;
nethercote71980f02004-01-24 18:18:54 +0000871 break;
872
873 case AT_PLATFORM: /* points to a platform description string */
874 auxv->u.a_ptr = copy_str(&strtab, orig_auxv->u.a_ptr);
875 break;
876
877 case AT_ENTRY:
878 auxv->u.a_val = info->entry;
879 break;
880
881 case AT_IGNORE:
882 case AT_EXECFD:
883 case AT_PHENT:
884 case AT_PAGESZ:
885 case AT_FLAGS:
886 case AT_NOTELF:
887 case AT_UID:
888 case AT_EUID:
889 case AT_GID:
890 case AT_EGID:
891 case AT_CLKTCK:
892 case AT_HWCAP:
893 case AT_FPUCW:
894 case AT_DCACHEBSIZE:
895 case AT_ICACHEBSIZE:
896 case AT_UCACHEBSIZE:
cerion85665ca2005-06-20 15:51:07 +0000897#if defined(VGP_ppc32_linux)
898 case AT_IGNOREPPC:
899#endif
nethercote71980f02004-01-24 18:18:54 +0000900 /* All these are pointerless, so we don't need to do anything
901 about them. */
902 break;
903
904 case AT_SECURE:
905 /* If this is 1, then it means that this program is running
906 suid, and therefore the dynamic linker should be careful
907 about LD_PRELOAD, etc. However, since stage1 (the thing
908 the kernel actually execve's) should never be SUID, and we
sewardjb5f6f512005-03-10 23:59:00 +0000909 need LD_PRELOAD to work for the client, we
nethercote71980f02004-01-24 18:18:54 +0000910 set AT_SECURE to 0. */
911 auxv->u.a_val = 0;
912 break;
913
914 case AT_SYSINFO:
915 /* Leave this unmolested for now, but we'll update it later
916 when we set up the client trampoline code page */
917 break;
918
cerion85665ca2005-06-20 15:51:07 +0000919#if !defined(VGP_ppc32_linux)
nethercote71980f02004-01-24 18:18:54 +0000920 case AT_SYSINFO_EHDR:
921 /* Trash this, because we don't reproduce it */
922 auxv->a_type = AT_IGNORE;
923 break;
cerion85665ca2005-06-20 15:51:07 +0000924#endif
nethercote71980f02004-01-24 18:18:54 +0000925
926 default:
927 /* stomp out anything we don't know about */
njn37569252005-06-21 00:28:43 +0000928 if (0)
nethercote545fe672004-11-01 16:52:43 +0000929 printf("stomping auxv entry %lld\n", (ULong)auxv->a_type);
nethercote71980f02004-01-24 18:18:54 +0000930 auxv->a_type = AT_IGNORE;
931 break;
932
933 }
934 }
935 *auxv = *orig_auxv;
936 vg_assert(auxv->a_type == AT_NULL);
937
938 vg_assert((strtab-stringbase) == stringsize);
939
nethercote5ee67ca2004-06-22 14:00:09 +0000940 /* We know the initial ESP is pointing at argc/argv */
941 VG_(client_argc) = *(Int*)cl_esp;
sewardj45f02c42005-02-05 18:27:14 +0000942 VG_(client_argv) = (Char**)(cl_esp + sizeof(HWord));
nethercote5ee67ca2004-06-22 14:00:09 +0000943
sewardj79048ce2005-02-18 08:28:32 +0000944 if (0) VG_(printf)("startup SP = %p\n", cl_esp);
nethercote71980f02004-01-24 18:18:54 +0000945 return cl_esp;
946}
947
948/*====================================================================*/
949/*=== Find executable ===*/
950/*====================================================================*/
951
thughes4ad52d02004-06-27 17:37:21 +0000952static const char* executable_name;
953
954static Bool match_executable(const char *entry) {
955 char buf[strlen(entry) + strlen(executable_name) + 2];
956
957 /* empty PATH element means . */
958 if (*entry == '\0')
959 entry = ".";
960
961 snprintf(buf, sizeof(buf), "%s/%s", entry, executable_name);
962
963 if (access(buf, R_OK|X_OK) == 0) {
964 executable_name = strdup(buf);
965 vg_assert(NULL != executable_name);
966 return True;
967 }
968 return False;
969}
970
nethercote71980f02004-01-24 18:18:54 +0000971static const char* find_executable(const char* exec)
972{
973 vg_assert(NULL != exec);
thughes4ad52d02004-06-27 17:37:21 +0000974 executable_name = exec;
975 if (strchr(executable_name, '/') == NULL) {
nethercote71980f02004-01-24 18:18:54 +0000976 /* no '/' - we need to search the path */
977 char *path = getenv("PATH");
thughes4ad52d02004-06-27 17:37:21 +0000978 scan_colsep(path, match_executable);
nethercote71980f02004-01-24 18:18:54 +0000979 }
thughes4ad52d02004-06-27 17:37:21 +0000980 return executable_name;
nethercote71980f02004-01-24 18:18:54 +0000981}
982
983
984/*====================================================================*/
985/*=== Loading tools ===*/
986/*====================================================================*/
987
988static void list_tools(void)
989{
990 DIR *dir = opendir(VG_(libdir));
991 struct dirent *de;
992 int first = 1;
993
994 if (dir == NULL) {
995 fprintf(stderr, "Can't open %s: %s (installation problem?)\n",
nethercotef4928da2004-06-15 10:54:40 +0000996 VG_(libdir), strerror(errno));
nethercote71980f02004-01-24 18:18:54 +0000997 return;
998 }
999
nethercotef4928da2004-06-15 10:54:40 +00001000 while ((de = readdir(dir)) != NULL) {
nethercote71980f02004-01-24 18:18:54 +00001001 int len = strlen(de->d_name);
1002
njn063c5402004-11-22 16:58:05 +00001003 /* look for vgtool_TOOL.so names */
1004 if (len > (7+1+3) && /* "vgtool_" + at least 1-char toolname + ".so" */
1005 strncmp(de->d_name, "vgtool_", 7) == 0 &&
nethercotef4928da2004-06-15 10:54:40 +00001006 VG_STREQ(de->d_name + len - 3, ".so")) {
1007 if (first) {
1008 fprintf(stderr, "Available tools:\n");
1009 first = 0;
1010 }
1011 de->d_name[len-3] = '\0';
1012 fprintf(stderr, "\t%s\n", de->d_name+7);
nethercote71980f02004-01-24 18:18:54 +00001013 }
1014 }
1015
1016 closedir(dir);
1017
1018 if (first)
nethercotef4928da2004-06-15 10:54:40 +00001019 fprintf(stderr, "No tools available in \"%s\" (installation problem?)\n",
1020 VG_(libdir));
nethercote71980f02004-01-24 18:18:54 +00001021}
1022
1023
1024/* Find and load a tool, and check it looks ok. Also looks to see if there's
1025 * a matching vgpreload_*.so file, and returns its name in *preloadpath. */
njn8a97c6d2005-03-31 04:37:24 +00001026static void load_tool( const char *toolname,
nethercote71980f02004-01-24 18:18:54 +00001027 ToolInfo** toolinfo_out, char **preloadpath_out )
1028{
1029 Bool ok;
sewardjb5f6f512005-03-10 23:59:00 +00001030 int len = strlen(VG_(libdir)) + strlen(toolname) + 16;
nethercote71980f02004-01-24 18:18:54 +00001031 char buf[len];
1032 void* handle;
1033 ToolInfo* toolinfo;
1034 char* preloadpath = NULL;
nethercote71980f02004-01-24 18:18:54 +00001035
1036 // XXX: allowing full paths for --tool option -- does it make sense?
1037 // Doesn't allow for vgpreload_<tool>.so.
1038
1039 if (strchr(toolname, '/') != 0) {
1040 /* toolname contains '/', and so must be a pathname */
1041 handle = dlopen(toolname, RTLD_NOW);
1042 } else {
1043 /* just try in the libdir */
njn063c5402004-11-22 16:58:05 +00001044 snprintf(buf, len, "%s/vgtool_%s.so", VG_(libdir), toolname);
nethercote71980f02004-01-24 18:18:54 +00001045 handle = dlopen(buf, RTLD_NOW);
1046
1047 if (handle != NULL) {
1048 snprintf(buf, len, "%s/vgpreload_%s.so", VG_(libdir), toolname);
1049 if (access(buf, R_OK) == 0) {
1050 preloadpath = strdup(buf);
1051 vg_assert(NULL != preloadpath);
1052 }
1053 }
1054 }
1055
1056 ok = (NULL != handle);
1057 if (!ok) {
1058 fprintf(stderr, "Can't open tool \"%s\": %s\n", toolname, dlerror());
1059 goto bad_load;
1060 }
1061
njn51d827b2005-05-09 01:02:08 +00001062 toolinfo = dlsym(handle, "vgPlain_tool_info");
nethercote71980f02004-01-24 18:18:54 +00001063 ok = (NULL != toolinfo);
1064 if (!ok) {
njn51d827b2005-05-09 01:02:08 +00001065 fprintf(stderr, "Tool \"%s\" doesn't define its ToolInfo - "
nethercote71980f02004-01-24 18:18:54 +00001066 "add VG_DETERMINE_INTERFACE_VERSION?\n", toolname);
1067 goto bad_load;
1068 }
1069
1070 ok = (toolinfo->sizeof_ToolInfo == sizeof(*toolinfo) &&
njn51d827b2005-05-09 01:02:08 +00001071 toolinfo->interface_version == VG_CORE_INTERFACE_VERSION &&
1072 toolinfo->tl_pre_clo_init != NULL);
nethercote71980f02004-01-24 18:18:54 +00001073 if (!ok) {
1074 fprintf(stderr, "Error:\n"
1075 " Tool and core interface versions do not match.\n"
njn51d827b2005-05-09 01:02:08 +00001076 " Interface version used by core is: %d (size %d)\n"
1077 " Interface version used by tool is: %d (size %d)\n"
1078 " The version numbers must match.\n",
1079 VG_CORE_INTERFACE_VERSION,
nethercote545fe672004-11-01 16:52:43 +00001080 (Int)sizeof(*toolinfo),
njn51d827b2005-05-09 01:02:08 +00001081 toolinfo->interface_version,
nethercote71980f02004-01-24 18:18:54 +00001082 toolinfo->sizeof_ToolInfo);
1083 fprintf(stderr, " You need to at least recompile, and possibly update,\n");
njn51d827b2005-05-09 01:02:08 +00001084 if (VG_CORE_INTERFACE_VERSION > toolinfo->interface_version)
nethercote996901a2004-08-03 13:29:09 +00001085 fprintf(stderr, " your tool to work with this version of Valgrind.\n");
nethercote71980f02004-01-24 18:18:54 +00001086 else
nethercote996901a2004-08-03 13:29:09 +00001087 fprintf(stderr, " your version of Valgrind to work with this tool.\n");
nethercote71980f02004-01-24 18:18:54 +00001088 goto bad_load;
1089 }
1090
njn8a97c6d2005-03-31 04:37:24 +00001091 vg_assert(NULL != toolinfo);
nethercote71980f02004-01-24 18:18:54 +00001092 *toolinfo_out = toolinfo;
1093 *preloadpath_out = preloadpath;
1094 return;
1095
1096
1097 bad_load:
1098 if (handle != NULL)
1099 dlclose(handle);
1100
nethercotef4928da2004-06-15 10:54:40 +00001101 fprintf(stderr, "valgrind: couldn't load tool\n");
nethercote71980f02004-01-24 18:18:54 +00001102 list_tools();
1103 exit(127);
1104}
1105
nethercotef4928da2004-06-15 10:54:40 +00001106
1107/*====================================================================*/
1108/*=== Command line errors ===*/
1109/*====================================================================*/
1110
njnbe9b47b2005-05-15 16:22:58 +00001111static void revert_to_stderr ( void )
nethercotef4928da2004-06-15 10:54:40 +00001112{
njnbe9b47b2005-05-15 16:22:58 +00001113 vg_assert( !VG_(logging_to_socket) );
nethercotef8548672004-06-21 12:42:35 +00001114 VG_(clo_log_fd) = 2; /* stderr */
nethercotef4928da2004-06-15 10:54:40 +00001115}
1116
1117void VG_(bad_option) ( Char* opt )
1118{
njnbe9b47b2005-05-15 16:22:58 +00001119 revert_to_stderr();
njn02bc4b82005-05-15 17:28:26 +00001120 VG_(printf)("valgrind: Bad option '%s'; aborting.\n", opt);
nethercotef4928da2004-06-15 10:54:40 +00001121 VG_(printf)("valgrind: Use --help for more information.\n");
1122 VG_(exit)(1);
1123}
1124
nethercotef4928da2004-06-15 10:54:40 +00001125static void missing_prog ( void )
1126{
njnbe9b47b2005-05-15 16:22:58 +00001127 revert_to_stderr();
nethercotef4928da2004-06-15 10:54:40 +00001128 VG_(printf)("valgrind: no program specified\n");
1129 VG_(printf)("valgrind: Use --help for more information.\n");
1130 VG_(exit)(1);
1131}
1132
1133static void config_error ( Char* msg )
1134{
njnbe9b47b2005-05-15 16:22:58 +00001135 revert_to_stderr();
nethercotef4928da2004-06-15 10:54:40 +00001136 VG_(printf)("valgrind: Startup or configuration error:\n %s\n", msg);
1137 VG_(printf)("valgrind: Unable to start up properly. Giving up.\n");
1138 VG_(exit)(1);
1139}
1140
1141
nethercote71980f02004-01-24 18:18:54 +00001142/*====================================================================*/
1143/*=== Loading the client ===*/
1144/*====================================================================*/
1145
nethercotef4928da2004-06-15 10:54:40 +00001146static void load_client(char* cl_argv[], const char* exec, Int need_help,
nethercote71980f02004-01-24 18:18:54 +00001147 /*out*/struct exeinfo* info, /*out*/Addr* client_eip)
1148{
1149 // If they didn't specify an executable with --exec, and didn't specify
1150 // --help, then use client argv[0] (searching $PATH if necessary).
nethercotef4928da2004-06-15 10:54:40 +00001151 if (NULL == exec && !need_help) {
nethercote71980f02004-01-24 18:18:54 +00001152 if (cl_argv[0] == NULL ||
1153 ( NULL == (exec = find_executable(cl_argv[0])) ) )
1154 {
nethercotef4928da2004-06-15 10:54:40 +00001155 missing_prog();
nethercote71980f02004-01-24 18:18:54 +00001156 }
1157 }
1158
1159 info->map_base = VG_(client_mapbase);
nethercote71980f02004-01-24 18:18:54 +00001160 info->exe_base = VG_(client_base);
1161 info->exe_end = VG_(client_end);
1162 info->argv = cl_argv;
1163
nethercotef4928da2004-06-15 10:54:40 +00001164 if (need_help) {
nethercote71980f02004-01-24 18:18:54 +00001165 VG_(clexecfd) = -1;
njnc8c93282004-11-29 16:05:54 +00001166 // Totally zero 'info' before continuing.
1167 VG_(memset)(info, 0, sizeof(*info));
nethercote71980f02004-01-24 18:18:54 +00001168 } else {
1169 Int ret;
sewardj92645592005-07-23 09:18:34 +00001170 /* HACK: assumes VG_(open) always succeeds */
1171 VG_(clexecfd) = VG_(open)(exec, VKI_O_RDONLY, VKI_S_IRUSR)
1172 .val;
njn62ff0f22005-06-21 23:03:36 +00001173 ret = VG_(do_exec)(exec, info);
nethercote71980f02004-01-24 18:18:54 +00001174 if (ret != 0) {
nethercoteea147e72004-07-26 15:43:57 +00001175 fprintf(stderr, "valgrind: do_exec(%s) failed: %s\n",
1176 exec, strerror(ret));
nethercote71980f02004-01-24 18:18:54 +00001177 exit(127);
1178 }
1179 }
1180
1181 /* Copy necessary bits of 'info' that were filled in */
1182 *client_eip = info->init_eip;
1183 VG_(brk_base) = VG_(brk_limit) = info->brkbase;
1184}
1185
nethercote969ecf12004-10-13 17:29:01 +00001186/*====================================================================*/
1187/*=== Address space unpadding ===*/
1188/*====================================================================*/
1189
1190typedef struct {
njn909c3192005-06-19 15:46:27 +00001191 char* killpad_start;
1192 char* killpad_end;
1193 struct vki_stat* killpad_padstat;
nethercote969ecf12004-10-13 17:29:01 +00001194} killpad_extra;
1195
1196static int killpad(char *segstart, char *segend, const char *perm, off_t off,
1197 int maj, int min, int ino, void* ex)
1198{
1199 killpad_extra* extra = ex;
1200 void *b, *e;
njn83407492005-06-19 16:10:47 +00001201 SysRes res;
nethercote969ecf12004-10-13 17:29:01 +00001202
1203 vg_assert(NULL != extra->killpad_padstat);
1204
1205 if (extra->killpad_padstat->st_dev != makedev(maj, min) ||
1206 extra->killpad_padstat->st_ino != ino)
1207 return 1;
1208
1209 if (segend <= extra->killpad_start || segstart >= extra->killpad_end)
1210 return 1;
1211
1212 if (segstart <= extra->killpad_start)
1213 b = extra->killpad_start;
1214 else
1215 b = segstart;
1216
1217 if (segend >= extra->killpad_end)
1218 e = extra->killpad_end;
1219 else
1220 e = segend;
1221
njn83407492005-06-19 16:10:47 +00001222 res = VG_(munmap_native)(b, (char *)e-(char *)b);
1223 vg_assert(!res.isError);
nethercote969ecf12004-10-13 17:29:01 +00001224
1225 return 1;
1226}
1227
1228// Remove padding of 'padfile' from a range of address space.
sewardj2c5ffbe2005-03-12 13:32:06 +00001229static void as_unpad(void *start, void *end, int padfile)
nethercote969ecf12004-10-13 17:29:01 +00001230{
njn909c3192005-06-19 15:46:27 +00001231 static struct vki_stat padstat;
nethercote969ecf12004-10-13 17:29:01 +00001232 killpad_extra extra;
1233 int res;
1234
sewardjb5f6f512005-03-10 23:59:00 +00001235 vg_assert(padfile >= 0);
nethercote969ecf12004-10-13 17:29:01 +00001236
njn909c3192005-06-19 15:46:27 +00001237 res = VG_(fstat)(padfile, &padstat);
nethercote969ecf12004-10-13 17:29:01 +00001238 vg_assert(0 == res);
1239 extra.killpad_padstat = &padstat;
1240 extra.killpad_start = start;
1241 extra.killpad_end = end;
njn62ff0f22005-06-21 23:03:36 +00001242 VG_(foreach_map)(killpad, &extra);
nethercote969ecf12004-10-13 17:29:01 +00001243}
1244
sewardj2c5ffbe2005-03-12 13:32:06 +00001245static void as_closepadfile(int padfile)
nethercote969ecf12004-10-13 17:29:01 +00001246{
1247 int res = close(padfile);
1248 vg_assert(0 == res);
1249}
1250
sewardj71bc3cb2005-05-19 00:25:45 +00001251/*====================================================================*/
1252/*=== Command-line: variables, processing, etc ===*/
1253/*====================================================================*/
1254
1255// See pub_{core,tool}_options.h for explanations of all these.
1256
sewardj2c5ffbe2005-03-12 13:32:06 +00001257static void usage ( Bool debug_help )
njn7cf0bd32002-06-08 13:36:03 +00001258{
njn25e49d8e72002-09-23 09:36:25 +00001259 Char* usage1 =
nethercote71980f02004-01-24 18:18:54 +00001260"usage: valgrind --tool=<toolname> [options] prog-and-args\n"
njn25e49d8e72002-09-23 09:36:25 +00001261"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001262" common user options for all Valgrind tools, with defaults in [ ]:\n"
sewardjb5f6f512005-03-10 23:59:00 +00001263" --tool=<name> use the Valgrind tool named <name> [memcheck]\n"
nethercotea76368b2004-06-16 11:56:29 +00001264" -h --help show this message\n"
nethercote6c999f22004-01-31 22:55:15 +00001265" --help-debug show this message, plus debugging options\n"
njn25e49d8e72002-09-23 09:36:25 +00001266" --version show version\n"
njn25e49d8e72002-09-23 09:36:25 +00001267" -q --quiet run silently; only print error msgs\n"
1268" -v --verbose be more verbose, incl counts of errors\n"
nethercote77eba602003-11-13 17:35:04 +00001269" --trace-children=no|yes Valgrind-ise child processes? [no]\n"
nethercote0d588502004-06-21 13:27:11 +00001270" --track-fds=no|yes track open file descriptors? [no]\n"
thughes6233a382004-08-21 11:10:44 +00001271" --time-stamp=no|yes add timestamps to log messages? [no]\n"
njnce545552005-07-25 22:36:52 +00001272" --log-fd=<number> log messages to file descriptor [2=stderr]\n"
1273" --log-file=<file> log messages to <file>.pid<pid>\n"
1274" --log-file-exactly=<file> log messages to <file>\n"
1275" --log-file-qualifier=<VAR> incorporate $VAR in logfile name [none]\n"
1276" --log-socket=ipaddr:port log messages to socket ipaddr:port\n"
nethercote2b0793f2003-12-02 10:41:18 +00001277"\n"
1278" uncommon user options for all Valgrind tools:\n"
nethercote0d588502004-06-21 13:27:11 +00001279" --run-libc-freeres=no|yes free up glibc memory at exit? [yes]\n"
sewardjb5f6f512005-03-10 23:59:00 +00001280" --weird-hacks=hack1,hack2,... recognised hacks: lax-ioctls,ioctl-mmap [none]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001281" --pointercheck=no|yes enforce client address space limits [yes]\n"
sewardjb1131a82005-03-19 15:12:21 +00001282" --show-emwarns=no|yes show warnings about emulation limits? [no]\n"
sewardj6c3a2192005-07-24 07:00:45 +00001283" --smc-check=none|stack|all checks for self-modifying code: none,\n"
1284" only for code found in stacks, or all [stack]\n"
njn25e49d8e72002-09-23 09:36:25 +00001285"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001286" user options for Valgrind tools that report errors:\n"
njnce545552005-07-25 22:36:52 +00001287" --xml=yes all output is in XML (Memcheck/Nulgrind only)\n"
njnc8ec9f82005-07-20 03:03:28 +00001288" --xml-user-comment=STR copy STR verbatim to XML output\n"
nethercote2b0793f2003-12-02 10:41:18 +00001289" --demangle=no|yes automatically demangle C++ names? [yes]\n"
njncc6cc142005-03-12 20:59:29 +00001290" --num-callers=<number> show <num> callers in stack traces [12]\n"
nethercote2b0793f2003-12-02 10:41:18 +00001291" --error-limit=no|yes stop showing new errors if too many? [yes]\n"
1292" --show-below-main=no|yes continue stack traces below main() [no]\n"
1293" --suppressions=<filename> suppress errors described in <filename>\n"
sewardjd153fae2005-01-10 17:24:47 +00001294" --gen-suppressions=no|yes|all print suppressions for errors? [no]\n"
nethercote04d0fbc2004-01-26 16:48:06 +00001295" --db-attach=no|yes start debugger when errors detected? [no]\n"
1296" --db-command=<command> command to start debugger [gdb -nw %%f %%p]\n"
1297" --input-fd=<number> file descriptor for input [0=stdin]\n"
sewardj97724e52005-04-02 23:40:59 +00001298" --max-stackframe=<number> assume stack switch for SP changes larger\n"
1299" than <number> bytes [2000000]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001300"\n";
njn7cf0bd32002-06-08 13:36:03 +00001301
njn25e49d8e72002-09-23 09:36:25 +00001302 Char* usage2 =
1303"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001304" debugging options for all Valgrind tools:\n"
njn25e49d8e72002-09-23 09:36:25 +00001305" --sanity-level=<number> level of sanity checking to do [1]\n"
nethercote137bc552003-11-14 17:47:54 +00001306" --profile=no|yes profile? (tool must be built for it) [no]\n"
sewardjfa8ec112005-01-19 11:55:34 +00001307" --trace-flags=<XXXXXXXX> show generated code? (X = 0|1) [00000000]\n"
1308" --profile-flags=<XXXXXXXX> ditto, but for profiling (X = 0|1) [00000000]\n"
sewardjc771b292004-11-30 18:55:21 +00001309" --trace-notbelow=<number> only show BBs above <number> [0]\n"
njn25e49d8e72002-09-23 09:36:25 +00001310" --trace-syscalls=no|yes show all system calls? [no]\n"
1311" --trace-signals=no|yes show signal handling details? [no]\n"
1312" --trace-symtab=no|yes show symbol table details? [no]\n"
sewardjce058b02005-05-01 08:55:38 +00001313" --trace-cfi=no|yes show call-frame-info details? [no]\n"
njn25e49d8e72002-09-23 09:36:25 +00001314" --trace-sched=no|yes show thread scheduler details? [no]\n"
jsgf855d93d2003-10-13 22:26:55 +00001315" --wait-for-gdb=yes|no pause on startup to wait for gdb attach\n"
sewardjb5f6f512005-03-10 23:59:00 +00001316#if 0
1317" --model-pthreads=yes|no model the pthreads library [no]\n"
1318#endif
1319" --command-line-only=no|yes only use command line options [no]\n"
njn613812e2005-03-11 04:57:30 +00001320"\n"
1321" --vex-iropt-verbosity 0 .. 9 [0]\n"
1322" --vex-iropt-level 0 .. 2 [2]\n"
1323" --vex-iropt-precise-memory-exns [no]\n"
sewardj8b635a42004-11-22 19:01:47 +00001324" --vex-iropt-unroll-thresh 0 .. 400 [120]\n"
1325" --vex-guest-max-insns 1 .. 100 [50]\n"
1326" --vex-guest-chase-thresh 0 .. 99 [10]\n"
1327"\n"
sewardjfa8ec112005-01-19 11:55:34 +00001328" --trace-flags and --profile-flags values (omit the middle space):\n"
sewardj2a99cf62004-11-24 10:44:19 +00001329" 1000 0000 show conversion into IR\n"
1330" 0100 0000 show after initial opt\n"
1331" 0010 0000 show after instrumentation\n"
1332" 0001 0000 show after second opt\n"
1333" 0000 1000 show after tree building\n"
1334" 0000 0100 show selecting insns\n"
1335" 0000 0010 show after reg-alloc\n"
1336" 0000 0001 show final assembly\n"
1337"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001338" debugging options for Valgrind tools that report errors\n"
1339" --dump-error=<number> show translation for basic block associated\n"
1340" with <number>'th error context [0=show none]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001341"\n";
njn3e884182003-04-15 13:03:23 +00001342
1343 Char* usage3 =
1344"\n"
nethercote71980f02004-01-24 18:18:54 +00001345" Extra options read from ~/.valgrindrc, $VALGRIND_OPTS, ./.valgrindrc\n"
njn25e49d8e72002-09-23 09:36:25 +00001346"\n"
njn53612422005-03-12 16:22:54 +00001347" Valgrind is Copyright (C) 2000-2005 Julian Seward et al.\n"
njn25e49d8e72002-09-23 09:36:25 +00001348" and licensed under the GNU General Public License, version 2.\n"
1349" Bug reports, feedback, admiration, abuse, etc, to: %s.\n"
njnd04b7c62002-10-03 14:05:52 +00001350"\n"
nethercote137bc552003-11-14 17:47:54 +00001351" Tools are copyright and licensed by their authors. See each\n"
1352" tool's start-up message for more information.\n"
njn25e49d8e72002-09-23 09:36:25 +00001353"\n";
njn7cf0bd32002-06-08 13:36:03 +00001354
njnbe9b47b2005-05-15 16:22:58 +00001355 // Ensure the message goes to stdout
1356 VG_(clo_log_fd) = 1;
1357 vg_assert( !VG_(logging_to_socket) );
1358
fitzhardinge98abfc72003-12-16 02:05:15 +00001359 VG_(printf)(usage1);
1360 if (VG_(details).name) {
1361 VG_(printf)(" user options for %s:\n", VG_(details).name);
fitzhardinge98abfc72003-12-16 02:05:15 +00001362 if (VG_(needs).command_line_options)
njn51d827b2005-05-09 01:02:08 +00001363 VG_TDICT_CALL(tool_print_usage);
fitzhardinge98abfc72003-12-16 02:05:15 +00001364 else
1365 VG_(printf)(" (none)\n");
1366 }
nethercote6c999f22004-01-31 22:55:15 +00001367 if (debug_help) {
1368 VG_(printf)(usage2);
fitzhardinge98abfc72003-12-16 02:05:15 +00001369
nethercote6c999f22004-01-31 22:55:15 +00001370 if (VG_(details).name) {
1371 VG_(printf)(" debugging options for %s:\n", VG_(details).name);
1372
1373 if (VG_(needs).command_line_options)
njn51d827b2005-05-09 01:02:08 +00001374 VG_TDICT_CALL(tool_print_debug_usage);
nethercote6c999f22004-01-31 22:55:15 +00001375 else
1376 VG_(printf)(" (none)\n");
1377 }
fitzhardinge98abfc72003-12-16 02:05:15 +00001378 }
nethercote421281e2003-11-20 16:20:55 +00001379 VG_(printf)(usage3, VG_BUGS_TO);
nethercotef4928da2004-06-15 10:54:40 +00001380 VG_(exit)(0);
njn7cf0bd32002-06-08 13:36:03 +00001381}
sewardjde4a1d02002-03-22 01:27:54 +00001382
nethercote71980f02004-01-24 18:18:54 +00001383static void pre_process_cmd_line_options
nethercote6c999f22004-01-31 22:55:15 +00001384 ( Int* need_help, const char** tool, const char** exec )
sewardj1c1b1162003-02-23 01:25:51 +00001385{
nethercote71980f02004-01-24 18:18:54 +00001386 UInt i;
sewardjde4a1d02002-03-22 01:27:54 +00001387
sewardj8b635a42004-11-22 19:01:47 +00001388 LibVEX_default_VexControl(& VG_(clo_vex_control));
1389
nethercote71980f02004-01-24 18:18:54 +00001390 /* parse the options we have (only the options we care about now) */
nethercotef6a1d502004-08-09 12:21:57 +00001391 for (i = 1; i < vg_argc; i++) {
nethercote71980f02004-01-24 18:18:54 +00001392
nethercotef6a1d502004-08-09 12:21:57 +00001393 if (strcmp(vg_argv[i], "--version") == 0) {
nethercote71980f02004-01-24 18:18:54 +00001394 printf("valgrind-" VERSION "\n");
nethercotef4928da2004-06-15 10:54:40 +00001395 exit(0);
nethercote71980f02004-01-24 18:18:54 +00001396
nethercotef6a1d502004-08-09 12:21:57 +00001397 } else if (VG_CLO_STREQ(vg_argv[i], "--help") ||
1398 VG_CLO_STREQ(vg_argv[i], "-h")) {
nethercote6c999f22004-01-31 22:55:15 +00001399 *need_help = 1;
1400
nethercotef6a1d502004-08-09 12:21:57 +00001401 } else if (VG_CLO_STREQ(vg_argv[i], "--help-debug")) {
nethercote6c999f22004-01-31 22:55:15 +00001402 *need_help = 2;
nethercote71980f02004-01-24 18:18:54 +00001403
nethercotef6c99d72004-11-09 14:35:43 +00001404 } else if (VG_CLO_STREQN(7, vg_argv[i], "--tool=")) {
nethercotef6a1d502004-08-09 12:21:57 +00001405 *tool = &vg_argv[i][7];
nethercote71980f02004-01-24 18:18:54 +00001406
nethercotef6a1d502004-08-09 12:21:57 +00001407 } else if (VG_CLO_STREQN(7, vg_argv[i], "--exec=")) {
1408 *exec = &vg_argv[i][7];
nethercote71980f02004-01-24 18:18:54 +00001409 }
1410 }
nethercote71980f02004-01-24 18:18:54 +00001411}
1412
nethercote5ee67ca2004-06-22 14:00:09 +00001413static void process_cmd_line_options( UInt* client_auxv, const char* toolname )
nethercote71980f02004-01-24 18:18:54 +00001414{
sewardj92645592005-07-23 09:18:34 +00001415 SysRes sres;
1416 Int i, eventually_log_fd;
1417 Int toolname_len = VG_(strlen)(toolname);
njnbe9b47b2005-05-15 16:22:58 +00001418 enum {
1419 VgLogTo_Fd,
1420 VgLogTo_File,
1421 VgLogTo_FileExactly,
1422 VgLogTo_Socket
1423 } log_to = VgLogTo_Fd; // Where is logging output to be sent?
sewardjde4a1d02002-03-22 01:27:54 +00001424
nethercotee1730692003-11-20 10:38:07 +00001425 /* log to stderr by default, but usage message goes to stdout */
nethercotef8548672004-06-21 12:42:35 +00001426 eventually_log_fd = 2;
sewardjde4a1d02002-03-22 01:27:54 +00001427
sewardj19d81412002-06-03 01:10:40 +00001428 /* Check for sane path in ./configure --prefix=... */
fitzhardinge98abfc72003-12-16 02:05:15 +00001429 if (VG_LIBDIR[0] != '/')
sewardj19d81412002-06-03 01:10:40 +00001430 config_error("Please use absolute paths in "
1431 "./configure --prefix=... or --libdir=...");
sewardj38170912002-05-10 21:07:22 +00001432
nethercotef6a1d502004-08-09 12:21:57 +00001433 for (i = 1; i < vg_argc; i++) {
nethercote71980f02004-01-24 18:18:54 +00001434
nethercotef6a1d502004-08-09 12:21:57 +00001435 Char* arg = vg_argv[i];
thughes3bfd5a02004-07-18 08:05:44 +00001436 Char* colon = arg;
nethercote71980f02004-01-24 18:18:54 +00001437
thughes3bfd5a02004-07-18 08:05:44 +00001438 /* Look for a colon in the switch name */
1439 while (*colon && *colon != ':' && *colon != '=')
1440 colon++;
nethercote71980f02004-01-24 18:18:54 +00001441
1442 /* Look for matching "--toolname:foo" */
thughes3bfd5a02004-07-18 08:05:44 +00001443 if (*colon == ':') {
nethercote71980f02004-01-24 18:18:54 +00001444 if (VG_CLO_STREQN(2, arg, "--") &&
1445 VG_CLO_STREQN(toolname_len, arg+2, toolname) &&
1446 VG_CLO_STREQN(1, arg+2+toolname_len, ":"))
1447 {
1448 // prefix matches, convert "--toolname:foo" to "--foo"
1449 if (0)
1450 VG_(printf)("tool-specific arg: %s\n", arg);
njn8c0b3bb2005-03-12 21:20:39 +00001451 arg = strdup(arg + toolname_len + 1);
nethercote71980f02004-01-24 18:18:54 +00001452 arg[0] = '-';
1453 arg[1] = '-';
1454
1455 } else {
1456 // prefix doesn't match, skip to next arg
1457 continue;
1458 }
1459 }
1460
fitzhardinge98abfc72003-12-16 02:05:15 +00001461 /* Ignore these options - they've already been handled */
njn45270a22005-03-27 01:00:11 +00001462 if (VG_CLO_STREQN( 7, arg, "--tool=")) goto skip_arg;
1463 if (VG_CLO_STREQN( 7, arg, "--exec=")) goto skip_arg;
1464 if (VG_CLO_STREQN(20, arg, "--command-line-only=")) goto skip_arg;
fitzhardinge98abfc72003-12-16 02:05:15 +00001465
njn45270a22005-03-27 01:00:11 +00001466 if ( VG_CLO_STREQ(arg, "--")) goto skip_arg;
nethercote27fec902004-06-16 21:26:32 +00001467
nethercote71980f02004-01-24 18:18:54 +00001468 else if (VG_CLO_STREQ(arg, "-v") ||
1469 VG_CLO_STREQ(arg, "--verbose"))
sewardjde4a1d02002-03-22 01:27:54 +00001470 VG_(clo_verbosity)++;
nethercote27fec902004-06-16 21:26:32 +00001471
nethercote71980f02004-01-24 18:18:54 +00001472 else if (VG_CLO_STREQ(arg, "-q") ||
1473 VG_CLO_STREQ(arg, "--quiet"))
sewardjde4a1d02002-03-22 01:27:54 +00001474 VG_(clo_verbosity)--;
1475
sewardj1cf558c2005-04-25 01:36:56 +00001476 else if (VG_CLO_STREQ(arg, "-d")) {
1477 /* do nothing */
1478 }
1479
sewardj71bc3cb2005-05-19 00:25:45 +00001480 else VG_BOOL_CLO(arg, "--xml", VG_(clo_xml))
njn45270a22005-03-27 01:00:11 +00001481 else VG_BOOL_CLO(arg, "--db-attach", VG_(clo_db_attach))
1482 else VG_BOOL_CLO(arg, "--demangle", VG_(clo_demangle))
1483 else VG_BOOL_CLO(arg, "--error-limit", VG_(clo_error_limit))
1484 else VG_BOOL_CLO(arg, "--pointercheck", VG_(clo_pointercheck))
njn45270a22005-03-27 01:00:11 +00001485 else VG_BOOL_CLO(arg, "--show-emwarns", VG_(clo_show_emwarns))
sewardj97724e52005-04-02 23:40:59 +00001486 else VG_NUM_CLO (arg, "--max-stackframe", VG_(clo_max_stackframe))
njn45270a22005-03-27 01:00:11 +00001487 else VG_BOOL_CLO(arg, "--profile", VG_(clo_profile))
1488 else VG_BOOL_CLO(arg, "--run-libc-freeres", VG_(clo_run_libc_freeres))
1489 else VG_BOOL_CLO(arg, "--show-below-main", VG_(clo_show_below_main))
1490 else VG_BOOL_CLO(arg, "--time-stamp", VG_(clo_time_stamp))
1491 else VG_BOOL_CLO(arg, "--track-fds", VG_(clo_track_fds))
1492 else VG_BOOL_CLO(arg, "--trace-children", VG_(clo_trace_children))
1493 else VG_BOOL_CLO(arg, "--trace-sched", VG_(clo_trace_sched))
1494 else VG_BOOL_CLO(arg, "--trace-signals", VG_(clo_trace_signals))
1495 else VG_BOOL_CLO(arg, "--trace-symtab", VG_(clo_trace_symtab))
sewardjce058b02005-05-01 08:55:38 +00001496 else VG_BOOL_CLO(arg, "--trace-cfi", VG_(clo_trace_cfi))
njn45270a22005-03-27 01:00:11 +00001497 else VG_BOOL_CLO(arg, "--trace-redir", VG_(clo_trace_redir))
1498 else VG_BOOL_CLO(arg, "--trace-syscalls", VG_(clo_trace_syscalls))
1499 else VG_BOOL_CLO(arg, "--trace-pthreads", VG_(clo_trace_pthreads))
1500 else VG_BOOL_CLO(arg, "--wait-for-gdb", VG_(clo_wait_for_gdb))
1501 else VG_BOOL_CLO(arg, "--model-pthreads", VG_(clo_model_pthreads))
sewardj72f98ff2002-06-13 17:23:38 +00001502
njn45270a22005-03-27 01:00:11 +00001503 else VG_STR_CLO (arg, "--db-command", VG_(clo_db_command))
1504 else VG_STR_CLO (arg, "--weird-hacks", VG_(clo_weird_hacks))
sewardjde4a1d02002-03-22 01:27:54 +00001505
njn45270a22005-03-27 01:00:11 +00001506 else VG_NUM_CLO (arg, "--dump-error", VG_(clo_dump_error))
1507 else VG_NUM_CLO (arg, "--input-fd", VG_(clo_input_fd))
1508 else VG_NUM_CLO (arg, "--sanity-level", VG_(clo_sanity_level))
1509 else VG_BNUM_CLO(arg, "--num-callers", VG_(clo_backtrace_size), 1,
1510 VG_DEEPEST_BACKTRACE)
sewardjde4a1d02002-03-22 01:27:54 +00001511
sewardj6c3a2192005-07-24 07:00:45 +00001512 else if (VG_CLO_STREQ(arg, "--smc-check=none"))
1513 VG_(clo_smc_check) = Vg_SmcNone;
1514 else if (VG_CLO_STREQ(arg, "--smc-check=stack"))
1515 VG_(clo_smc_check) = Vg_SmcStack;
1516 else if (VG_CLO_STREQ(arg, "--smc-check=all"))
1517 VG_(clo_smc_check) = Vg_SmcAll;
sewardj26412bd2005-07-07 10:05:05 +00001518
njn45270a22005-03-27 01:00:11 +00001519 else VG_BNUM_CLO(arg, "--vex-iropt-verbosity",
sewardj8b635a42004-11-22 19:01:47 +00001520 VG_(clo_vex_control).iropt_verbosity, 0, 10)
njn45270a22005-03-27 01:00:11 +00001521 else VG_BNUM_CLO(arg, "--vex-iropt-level",
sewardj8b635a42004-11-22 19:01:47 +00001522 VG_(clo_vex_control).iropt_level, 0, 2)
njn45270a22005-03-27 01:00:11 +00001523 else VG_BOOL_CLO(arg, "--vex-iropt-precise-memory-exns",
sewardj8b635a42004-11-22 19:01:47 +00001524 VG_(clo_vex_control).iropt_precise_memory_exns)
njn45270a22005-03-27 01:00:11 +00001525 else VG_BNUM_CLO(arg, "--vex-iropt-unroll-thresh",
sewardj8b635a42004-11-22 19:01:47 +00001526 VG_(clo_vex_control).iropt_unroll_thresh, 0, 400)
njn45270a22005-03-27 01:00:11 +00001527 else VG_BNUM_CLO(arg, "--vex-guest-max-insns",
sewardj8b635a42004-11-22 19:01:47 +00001528 VG_(clo_vex_control).guest_max_insns, 1, 100)
njn45270a22005-03-27 01:00:11 +00001529 else VG_BNUM_CLO(arg, "--vex-guest-chase-thresh",
sewardj8b635a42004-11-22 19:01:47 +00001530 VG_(clo_vex_control).guest_chase_thresh, 0, 99)
1531
nethercotef8548672004-06-21 12:42:35 +00001532 else if (VG_CLO_STREQN(9, arg, "--log-fd=")) {
njnbe9b47b2005-05-15 16:22:58 +00001533 log_to = VgLogTo_Fd;
nethercotef8548672004-06-21 12:42:35 +00001534 VG_(clo_log_name) = NULL;
1535 eventually_log_fd = (Int)VG_(atoll)(&arg[9]);
sewardj4cf05692002-10-27 20:28:29 +00001536 }
1537
nethercotef8548672004-06-21 12:42:35 +00001538 else if (VG_CLO_STREQN(11, arg, "--log-file=")) {
njnbe9b47b2005-05-15 16:22:58 +00001539 log_to = VgLogTo_File;
nethercotef8548672004-06-21 12:42:35 +00001540 VG_(clo_log_name) = &arg[11];
sewardj4cf05692002-10-27 20:28:29 +00001541 }
njnd6bc3c32005-03-27 00:44:31 +00001542
sewardjad311162005-07-19 11:25:02 +00001543 else if (VG_CLO_STREQN(11, arg, "--log-file=")) {
1544 log_to = VgLogTo_File;
1545 VG_(clo_log_name) = &arg[11];
1546 }
1547
1548 else if (VG_CLO_STREQN(21, arg, "--log-file-qualifier=")) {
1549 VG_(clo_log_file_qualifier) = &arg[21];
1550 }
1551
sewardj603d4102005-01-11 14:01:02 +00001552 else if (VG_CLO_STREQN(19, arg, "--log-file-exactly=")) {
njnbe9b47b2005-05-15 16:22:58 +00001553 log_to = VgLogTo_FileExactly;
sewardj603d4102005-01-11 14:01:02 +00001554 VG_(clo_log_name) = &arg[19];
1555 }
sewardjde4a1d02002-03-22 01:27:54 +00001556
nethercotef8548672004-06-21 12:42:35 +00001557 else if (VG_CLO_STREQN(13, arg, "--log-socket=")) {
njnbe9b47b2005-05-15 16:22:58 +00001558 log_to = VgLogTo_Socket;
nethercotef8548672004-06-21 12:42:35 +00001559 VG_(clo_log_name) = &arg[13];
sewardj73cf3bc2002-11-03 03:20:15 +00001560 }
1561
sewardj768db0e2005-07-19 14:18:56 +00001562 else if (VG_CLO_STREQN(19, arg, "--xml-user-comment=")) {
1563 VG_(clo_xml_user_comment) = &arg[19];
1564 }
1565
nethercote71980f02004-01-24 18:18:54 +00001566 else if (VG_CLO_STREQN(15, arg, "--suppressions=")) {
sewardjde4a1d02002-03-22 01:27:54 +00001567 if (VG_(clo_n_suppressions) >= VG_CLO_MAX_SFILES) {
njn25e49d8e72002-09-23 09:36:25 +00001568 VG_(message)(Vg_UserMsg, "Too many suppression files specified.");
sewardjde4a1d02002-03-22 01:27:54 +00001569 VG_(message)(Vg_UserMsg,
1570 "Increase VG_CLO_MAX_SFILES and recompile.");
nethercote71980f02004-01-24 18:18:54 +00001571 VG_(bad_option)(arg);
sewardjde4a1d02002-03-22 01:27:54 +00001572 }
nethercote71980f02004-01-24 18:18:54 +00001573 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = &arg[15];
sewardjde4a1d02002-03-22 01:27:54 +00001574 VG_(clo_n_suppressions)++;
1575 }
sewardjde4a1d02002-03-22 01:27:54 +00001576
sewardjfa8ec112005-01-19 11:55:34 +00001577 /* "stuvwxyz" --> stuvwxyz (binary) */
1578 else if (VG_CLO_STREQN(14, arg, "--trace-flags=")) {
1579 Int j;
1580 char* opt = & arg[14];
1581
1582 if (8 != VG_(strlen)(opt)) {
1583 VG_(message)(Vg_UserMsg,
1584 "--trace-flags argument must have 8 digits");
1585 VG_(bad_option)(arg);
1586 }
1587 for (j = 0; j < 8; j++) {
1588 if ('0' == opt[j]) { /* do nothing */ }
1589 else if ('1' == opt[j]) VG_(clo_trace_flags) |= (1 << (7-j));
1590 else {
1591 VG_(message)(Vg_UserMsg, "--trace-flags argument can only "
1592 "contain 0s and 1s");
1593 VG_(bad_option)(arg);
1594 }
1595 }
1596 }
1597
1598 /* "stuvwxyz" --> stuvwxyz (binary) */
1599 else if (VG_CLO_STREQN(16, arg, "--profile-flags=")) {
njn25e49d8e72002-09-23 09:36:25 +00001600 Int j;
nethercote71980f02004-01-24 18:18:54 +00001601 char* opt = & arg[16];
njn25e49d8e72002-09-23 09:36:25 +00001602
sewardj2a99cf62004-11-24 10:44:19 +00001603 if (8 != VG_(strlen)(opt)) {
njn25e49d8e72002-09-23 09:36:25 +00001604 VG_(message)(Vg_UserMsg,
sewardjfa8ec112005-01-19 11:55:34 +00001605 "--profile-flags argument must have 8 digits");
nethercote71980f02004-01-24 18:18:54 +00001606 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001607 }
sewardj8b635a42004-11-22 19:01:47 +00001608 for (j = 0; j < 8; j++) {
njn25e49d8e72002-09-23 09:36:25 +00001609 if ('0' == opt[j]) { /* do nothing */ }
sewardjfa8ec112005-01-19 11:55:34 +00001610 else if ('1' == opt[j]) VG_(clo_profile_flags) |= (1 << (7-j));
njn25e49d8e72002-09-23 09:36:25 +00001611 else {
sewardjfa8ec112005-01-19 11:55:34 +00001612 VG_(message)(Vg_UserMsg, "--profile-flags argument can only "
njn25e49d8e72002-09-23 09:36:25 +00001613 "contain 0s and 1s");
nethercote71980f02004-01-24 18:18:54 +00001614 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001615 }
1616 }
1617 }
sewardjde4a1d02002-03-22 01:27:54 +00001618
njn45270a22005-03-27 01:00:11 +00001619 else VG_NUM_CLO (arg, "--trace-notbelow", VG_(clo_trace_notbelow))
sewardjc771b292004-11-30 18:55:21 +00001620
sewardjd153fae2005-01-10 17:24:47 +00001621 else if (VG_CLO_STREQ(arg, "--gen-suppressions=no"))
1622 VG_(clo_gen_suppressions) = 0;
1623 else if (VG_CLO_STREQ(arg, "--gen-suppressions=yes"))
1624 VG_(clo_gen_suppressions) = 1;
1625 else if (VG_CLO_STREQ(arg, "--gen-suppressions=all"))
1626 VG_(clo_gen_suppressions) = 2;
1627
nethercote71980f02004-01-24 18:18:54 +00001628 else if ( ! VG_(needs).command_line_options
njn51d827b2005-05-09 01:02:08 +00001629 || ! VG_TDICT_CALL(tool_process_cmd_line_option, arg) ) {
nethercotef4928da2004-06-15 10:54:40 +00001630 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001631 }
njn8c0b3bb2005-03-12 21:20:39 +00001632 skip_arg:
1633 if (arg != vg_argv[i])
1634 free(arg);
sewardjde4a1d02002-03-22 01:27:54 +00001635 }
1636
sewardj998d40d2004-12-06 14:24:52 +00001637 /* Make VEX control parameters sane */
1638
1639 if (VG_(clo_vex_control).guest_chase_thresh
1640 >= VG_(clo_vex_control).guest_max_insns)
1641 VG_(clo_vex_control).guest_chase_thresh
1642 = VG_(clo_vex_control).guest_max_insns - 1;
1643
1644 if (VG_(clo_vex_control).guest_chase_thresh < 0)
1645 VG_(clo_vex_control).guest_chase_thresh = 0;
1646
1647 /* Check various option values */
nethercote27fec902004-06-16 21:26:32 +00001648
njnf9ebf672003-05-12 21:41:30 +00001649 if (VG_(clo_verbosity) < 0)
sewardjde4a1d02002-03-22 01:27:54 +00001650 VG_(clo_verbosity) = 0;
1651
nethercote04d0fbc2004-01-26 16:48:06 +00001652 if (VG_(clo_db_attach) && VG_(clo_trace_children)) {
sewardjde4a1d02002-03-22 01:27:54 +00001653 VG_(message)(Vg_UserMsg, "");
1654 VG_(message)(Vg_UserMsg,
nethercote04d0fbc2004-01-26 16:48:06 +00001655 "--db-attach=yes conflicts with --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001656 VG_(message)(Vg_UserMsg,
1657 "Please choose one or the other, but not both.");
nethercote04d0fbc2004-01-26 16:48:06 +00001658 VG_(bad_option)("--db-attach=yes and --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001659 }
1660
njnbe9b47b2005-05-15 16:22:58 +00001661 if (VG_(clo_gen_suppressions) > 0 &&
1662 !VG_(needs).core_errors && !VG_(needs).tool_errors) {
1663 VG_(message)(Vg_UserMsg,
1664 "Can't use --gen-suppressions= with this tool,");
1665 VG_(message)(Vg_UserMsg,
1666 "as it doesn't generate errors.");
1667 VG_(bad_option)("--gen-suppressions=");
1668 }
1669
sewardj71bc3cb2005-05-19 00:25:45 +00001670 /* If we've been asked to emit XML, mash around various other
1671 options so as to constrain the output somewhat, and to remove
1672 any need for user input during the run. */
1673 if (VG_(clo_xml)) {
1674 /* Disable suppression generation (requires user input) */
1675 VG_(clo_gen_suppressions) = 0;
1676 /* Disable attaching to GDB (requires user input) */
1677 VG_(clo_db_attach) = False;
1678 /* Set a known verbosity level */
1679 VG_(clo_verbosity) = 1;
1680 /* Disable error limits (this might be a bad idea!) */
1681 VG_(clo_error_limit) = False;
1682 /* Disable emulation warnings */
1683 VG_(clo_show_emwarns) = False;
1684 /* Disable waiting for GDB to debug Valgrind */
1685 VG_(clo_wait_for_gdb) = False;
1686 /* No file-descriptor leak checking yet */
1687 VG_(clo_track_fds) = False;
sewardj21f7f0c2005-07-06 19:46:48 +00001688 /* Disable timestamped output */
1689 VG_(clo_time_stamp) = False;
sewardj71bc3cb2005-05-19 00:25:45 +00001690 /* Also, we want to set options for the leak checker, but that
1691 will have to be done in Memcheck's flag-handling code, not
1692 here. */
1693 }
1694
njnbe9b47b2005-05-15 16:22:58 +00001695 /* All non-logging-related options have been checked. If the logging
1696 option specified is ok, we can switch to it, as we know we won't
1697 have to generate any other command-line-related error messages.
1698 (So far we should be still attached to stderr, so we can show on
1699 the terminal any problems to do with processing command line
1700 opts.)
1701
1702 So set up logging now. After this is done, VG_(clo_log_fd)
sewardj4cf05692002-10-27 20:28:29 +00001703 should be connected to whatever sink has been selected, and we
1704 indiscriminately chuck stuff into it without worrying what the
1705 nature of it is. Oh the wonder of Unix streams. */
1706
njnbe9b47b2005-05-15 16:22:58 +00001707 vg_assert(VG_(clo_log_fd) == 2 /* stderr */);
1708 vg_assert(VG_(logging_to_socket) == False);
sewardj4cf05692002-10-27 20:28:29 +00001709
njnbe9b47b2005-05-15 16:22:58 +00001710 switch (log_to) {
sewardj73cf3bc2002-11-03 03:20:15 +00001711
sewardj4cf05692002-10-27 20:28:29 +00001712 case VgLogTo_Fd:
nethercotef8548672004-06-21 12:42:35 +00001713 vg_assert(VG_(clo_log_name) == NULL);
1714 VG_(clo_log_fd) = eventually_log_fd;
sewardj4cf05692002-10-27 20:28:29 +00001715 break;
sewardj73cf3bc2002-11-03 03:20:15 +00001716
sewardj4cf05692002-10-27 20:28:29 +00001717 case VgLogTo_File: {
sewardjad311162005-07-19 11:25:02 +00001718 HChar logfilename[1000];
1719 Int seq = 0;
1720 Int pid = VG_(getpid)();
1721 HChar* qual = NULL;
jsgff3c3f1a2003-10-14 22:13:28 +00001722
nethercotef8548672004-06-21 12:42:35 +00001723 vg_assert(VG_(clo_log_name) != NULL);
1724 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
jsgff3c3f1a2003-10-14 22:13:28 +00001725
sewardjad311162005-07-19 11:25:02 +00001726 if (VG_(clo_log_file_qualifier)) {
1727 qual = VG_(getenv)(VG_(clo_log_file_qualifier));
1728 }
1729
nethercote71980f02004-01-24 18:18:54 +00001730 for (;;) {
sewardj92645592005-07-23 09:18:34 +00001731 HChar pidtxt[20], seqtxt[20];
1732
1733 VG_(sprintf)(pidtxt, "%d", pid);
1734
1735 if (seq == 0)
1736 seqtxt[0] = 0;
1737 else
1738 VG_(sprintf)(seqtxt, ".%d", seq);
1739
jsgff3c3f1a2003-10-14 22:13:28 +00001740 seq++;
1741
sewardj92645592005-07-23 09:18:34 +00001742 /* Result:
1743 if (qual) base_name ++ "." ++ qual ++ seqtxt
1744 if (not qual) base_name ++ "." ++ pid ++ seqtxt
1745 */
1746 VG_(sprintf)( logfilename,
1747 "%s.%s%s",
1748 VG_(clo_log_name),
1749 qual ? qual : pidtxt,
1750 seqtxt );
1751
njnbe9b47b2005-05-15 16:22:58 +00001752 // EXCL: it will fail with EEXIST if the file already exists.
sewardj92645592005-07-23 09:18:34 +00001753 sres
jsgff3c3f1a2003-10-14 22:13:28 +00001754 = VG_(open)(logfilename,
1755 VKI_O_CREAT|VKI_O_WRONLY|VKI_O_EXCL|VKI_O_TRUNC,
1756 VKI_S_IRUSR|VKI_S_IWUSR);
sewardj92645592005-07-23 09:18:34 +00001757 if (!sres.isError) {
1758 eventually_log_fd = sres.val;
nethercotef8548672004-06-21 12:42:35 +00001759 VG_(clo_log_fd) = VG_(safe_fd)(eventually_log_fd);
sewardj603d4102005-01-11 14:01:02 +00001760 break; /* for (;;) */
jsgff3c3f1a2003-10-14 22:13:28 +00001761 } else {
njnbe9b47b2005-05-15 16:22:58 +00001762 // If the file already existed, we try the next name. If it
1763 // was some other file error, we give up.
sewardj92645592005-07-23 09:18:34 +00001764 if (sres.val != VKI_EEXIST) {
jsgff3c3f1a2003-10-14 22:13:28 +00001765 VG_(message)(Vg_UserMsg,
njn02bc4b82005-05-15 17:28:26 +00001766 "Can't create/open log file '%s.pid%d'; giving up!",
nethercotef8548672004-06-21 12:42:35 +00001767 VG_(clo_log_name), pid);
jsgff3c3f1a2003-10-14 22:13:28 +00001768 VG_(bad_option)(
sewardj603d4102005-01-11 14:01:02 +00001769 "--log-file=<file> (didn't work out for some reason.)");
njnbe9b47b2005-05-15 16:22:58 +00001770 /*NOTREACHED*/
jsgff3c3f1a2003-10-14 22:13:28 +00001771 }
1772 }
1773 }
sewardj603d4102005-01-11 14:01:02 +00001774 break; /* switch (VG_(clo_log_to)) */
1775 }
1776
1777 case VgLogTo_FileExactly: {
sewardj603d4102005-01-11 14:01:02 +00001778 vg_assert(VG_(clo_log_name) != NULL);
1779 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
sewardj603d4102005-01-11 14:01:02 +00001780
sewardj92645592005-07-23 09:18:34 +00001781 sres
njnbe9b47b2005-05-15 16:22:58 +00001782 = VG_(open)(VG_(clo_log_name),
sewardj603d4102005-01-11 14:01:02 +00001783 VKI_O_CREAT|VKI_O_WRONLY|VKI_O_TRUNC,
1784 VKI_S_IRUSR|VKI_S_IWUSR);
sewardj92645592005-07-23 09:18:34 +00001785 if (!sres.isError) {
1786 eventually_log_fd = sres.val;
sewardj603d4102005-01-11 14:01:02 +00001787 VG_(clo_log_fd) = VG_(safe_fd)(eventually_log_fd);
njnbe9b47b2005-05-15 16:22:58 +00001788 } else {
sewardj603d4102005-01-11 14:01:02 +00001789 VG_(message)(Vg_UserMsg,
njn02bc4b82005-05-15 17:28:26 +00001790 "Can't create/open log file '%s'; giving up!",
sewardj603d4102005-01-11 14:01:02 +00001791 VG_(clo_log_name));
1792 VG_(bad_option)(
1793 "--log-file-exactly=<file> (didn't work out for some reason.)");
1794 /*NOTREACHED*/
1795 }
1796 break; /* switch (VG_(clo_log_to)) */
sewardj73cf3bc2002-11-03 03:20:15 +00001797 }
1798
1799 case VgLogTo_Socket: {
nethercotef8548672004-06-21 12:42:35 +00001800 vg_assert(VG_(clo_log_name) != NULL);
1801 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
1802 eventually_log_fd = VG_(connect_via_socket)( VG_(clo_log_name) );
1803 if (eventually_log_fd == -1) {
sewardj73cf3bc2002-11-03 03:20:15 +00001804 VG_(message)(Vg_UserMsg,
nethercotef8548672004-06-21 12:42:35 +00001805 "Invalid --log-socket=ipaddr or --log-socket=ipaddr:port spec");
sewardj73cf3bc2002-11-03 03:20:15 +00001806 VG_(message)(Vg_UserMsg,
njn02bc4b82005-05-15 17:28:26 +00001807 "of '%s'; giving up!", VG_(clo_log_name) );
sewardj73cf3bc2002-11-03 03:20:15 +00001808 VG_(bad_option)(
nethercotef8548672004-06-21 12:42:35 +00001809 "--log-socket=");
njnbe9b47b2005-05-15 16:22:58 +00001810 /*NOTREACHED*/
sewardj4cf05692002-10-27 20:28:29 +00001811 }
nethercotef8548672004-06-21 12:42:35 +00001812 if (eventually_log_fd == -2) {
sewardj73cf3bc2002-11-03 03:20:15 +00001813 VG_(message)(Vg_UserMsg,
njn02bc4b82005-05-15 17:28:26 +00001814 "valgrind: failed to connect to logging server '%s'.",
nethercotef8548672004-06-21 12:42:35 +00001815 VG_(clo_log_name) );
sewardj570f8902002-11-03 11:44:36 +00001816 VG_(message)(Vg_UserMsg,
1817 "Log messages will sent to stderr instead." );
1818 VG_(message)(Vg_UserMsg,
1819 "" );
1820 /* We don't change anything here. */
njnbe9b47b2005-05-15 16:22:58 +00001821 vg_assert(VG_(clo_log_fd) == 2);
sewardj570f8902002-11-03 11:44:36 +00001822 } else {
nethercotef8548672004-06-21 12:42:35 +00001823 vg_assert(eventually_log_fd > 0);
1824 VG_(clo_log_fd) = eventually_log_fd;
njnbe9b47b2005-05-15 16:22:58 +00001825 VG_(logging_to_socket) = True;
sewardj570f8902002-11-03 11:44:36 +00001826 }
sewardj73cf3bc2002-11-03 03:20:15 +00001827 break;
1828 }
sewardj4cf05692002-10-27 20:28:29 +00001829 }
1830
sewardj71bc3cb2005-05-19 00:25:45 +00001831
1832 /* Check that the requested tool actually supports XML output. */
cerion39655202005-07-13 14:18:24 +00001833 if (VG_(clo_xml) && 0 != VG_(strcmp)(toolname, "memcheck")
1834 && 0 != VG_(strcmp)(toolname, "none")) {
sewardj71bc3cb2005-05-19 00:25:45 +00001835 VG_(clo_xml) = False;
1836 VG_(message)(Vg_UserMsg,
cerion39655202005-07-13 14:18:24 +00001837 "Currently only Memcheck|None supports XML output.");
sewardj71bc3cb2005-05-19 00:25:45 +00001838 VG_(bad_option)("--xml=yes");
1839 /*NOTREACHED*/
1840 }
1841
njnbe9b47b2005-05-15 16:22:58 +00001842 // Move log_fd into the safe range, so it doesn't conflict with any app fds.
1843 // XXX: this is more or less duplicating the behaviour of the calls to
1844 // VG_(safe_fd)() above, although this does not close the original fd.
1845 // Perhaps the VG_(safe_fd)() calls above should be removed, and this
1846 // code should be replaced with a call to VG_(safe_fd)(). --njn
thughesad1c9562004-06-26 11:27:52 +00001847 eventually_log_fd = VG_(fcntl)(VG_(clo_log_fd), VKI_F_DUPFD, VG_(fd_hard_limit));
nethercotef8548672004-06-21 12:42:35 +00001848 if (eventually_log_fd < 0)
jsgf855d93d2003-10-13 22:26:55 +00001849 VG_(message)(Vg_UserMsg, "valgrind: failed to move logfile fd into safe range");
1850 else {
nethercotef8548672004-06-21 12:42:35 +00001851 VG_(clo_log_fd) = eventually_log_fd;
1852 VG_(fcntl)(VG_(clo_log_fd), VKI_F_SETFD, VKI_FD_CLOEXEC);
jsgf855d93d2003-10-13 22:26:55 +00001853 }
1854
sewardj4cf05692002-10-27 20:28:29 +00001855 /* Ok, the logging sink is running now. Print a suitable preamble.
1856 If logging to file or a socket, write details of parent PID and
1857 command line args, to help people trying to interpret the
1858 results of a run which encompasses multiple processes. */
sewardjde4a1d02002-03-22 01:27:54 +00001859
sewardj71bc3cb2005-05-19 00:25:45 +00001860 if (VG_(clo_xml)) {
sewardj8665d8e2005-06-01 17:35:23 +00001861 VG_(message)(Vg_UserMsg, "<?xml version=\"1.0\"?>");
1862 VG_(message)(Vg_UserMsg, "");
sewardj71bc3cb2005-05-19 00:25:45 +00001863 VG_(message)(Vg_UserMsg, "<valgrindoutput>");
1864 VG_(message)(Vg_UserMsg, "");
1865 VG_(message)(Vg_UserMsg, "<protocolversion>1</protocolversion>");
1866 VG_(message)(Vg_UserMsg, "");
1867 }
1868
sewardjd7bddad2005-06-13 16:48:32 +00001869 HChar* xpre = VG_(clo_xml) ? " <line>" : "";
1870 HChar* xpost = VG_(clo_xml) ? "</line>" : "";
sewardj71bc3cb2005-05-19 00:25:45 +00001871
sewardj83adf412002-05-01 01:25:45 +00001872 if (VG_(clo_verbosity > 0)) {
sewardjd7bddad2005-06-13 16:48:32 +00001873
1874 if (VG_(clo_xml))
1875 VG_(message)(Vg_UserMsg, "<preamble>");
1876
nethercote996901a2004-08-03 13:29:09 +00001877 /* Tool details */
sewardj71bc3cb2005-05-19 00:25:45 +00001878 VG_(message)(Vg_UserMsg, "%s%s%s%s, %s.%s",
1879 xpre,
njnd04b7c62002-10-03 14:05:52 +00001880 VG_(details).name,
njnb9c427c2004-12-01 14:14:42 +00001881 NULL == VG_(details).version ? "" : "-",
njnd04b7c62002-10-03 14:05:52 +00001882 NULL == VG_(details).version
1883 ? (Char*)"" : VG_(details).version,
sewardj71bc3cb2005-05-19 00:25:45 +00001884 VG_(details).description,
1885 xpost);
1886 VG_(message)(Vg_UserMsg, "%s%s%s",
1887 xpre, VG_(details).copyright_author, xpost);
sewardj3b2736a2002-03-24 12:18:35 +00001888
njnd04b7c62002-10-03 14:05:52 +00001889 /* Core details */
1890 VG_(message)(Vg_UserMsg,
sewardj71bc3cb2005-05-19 00:25:45 +00001891 "%sUsing LibVEX rev %s, a library for dynamic binary translation.%s",
1892 xpre, LibVEX_Version(), xpost );
sewardjc7025332004-12-13 18:30:39 +00001893 VG_(message)(Vg_UserMsg,
sewardj71bc3cb2005-05-19 00:25:45 +00001894 "%sCopyright (C) 2004-2005, and GNU GPL'd, by OpenWorks LLP.%s",
1895 xpre, xpost );
sewardjc7025332004-12-13 18:30:39 +00001896 VG_(message)(Vg_UserMsg,
sewardj71bc3cb2005-05-19 00:25:45 +00001897 "%sUsing valgrind-%s, a dynamic binary instrumentation framework.%s",
1898 xpre, VERSION, xpost);
sewardjde4a1d02002-03-22 01:27:54 +00001899 VG_(message)(Vg_UserMsg,
sewardj71bc3cb2005-05-19 00:25:45 +00001900 "%sCopyright (C) 2000-2005, and GNU GPL'd, by Julian Seward et al.%s",
1901 xpre, xpost );
sewardjd7bddad2005-06-13 16:48:32 +00001902
1903 if (VG_(clo_xml))
1904 VG_(message)(Vg_UserMsg, "</preamble>");
njnd04b7c62002-10-03 14:05:52 +00001905 }
1906
sewardjd94b90a2005-06-29 23:15:56 +00001907 if (!VG_(clo_xml) && VG_(clo_verbosity) > 0 && log_to != VgLogTo_Fd) {
sewardj4cf05692002-10-27 20:28:29 +00001908 VG_(message)(Vg_UserMsg, "");
1909 VG_(message)(Vg_UserMsg,
1910 "My PID = %d, parent PID = %d. Prog and args are:",
1911 VG_(getpid)(), VG_(getppid)() );
1912 for (i = 0; i < VG_(client_argc); i++)
1913 VG_(message)(Vg_UserMsg, " %s", VG_(client_argv)[i]);
sewardj5b742c32005-07-26 23:43:26 +00001914 if (VG_(clo_log_file_qualifier)) {
1915 HChar* val = VG_(getenv)(VG_(clo_log_file_qualifier));
1916 VG_(message)(Vg_UserMsg, "");
1917 VG_(message)(Vg_UserMsg, "Log file qualifier: var %s, value %s.",
1918 VG_(clo_log_file_qualifier),
1919 val ? val : "");
1920 }
sewardj4cf05692002-10-27 20:28:29 +00001921 }
sewardj71bc3cb2005-05-19 00:25:45 +00001922 else
1923 if (VG_(clo_xml)) {
1924 VG_(message)(Vg_UserMsg, "");
1925 VG_(message)(Vg_UserMsg, "<pid>%d</pid>", VG_(getpid)());
1926 VG_(message)(Vg_UserMsg, "<ppid>%d</ppid>", VG_(getppid)());
sewardj97f7e0c2005-07-19 15:00:25 +00001927 VG_(message)(Vg_UserMsg, "<tool>%t</tool>", toolname);
sewardjad311162005-07-19 11:25:02 +00001928 if (VG_(clo_log_file_qualifier)) {
1929 HChar* val = VG_(getenv)(VG_(clo_log_file_qualifier));
sewardj97f7e0c2005-07-19 15:00:25 +00001930 VG_(message)(Vg_UserMsg, "<logfilequalifier> <var>%t</var> "
1931 "<value>%t</value> </logfilequalifier>",
sewardjad311162005-07-19 11:25:02 +00001932 VG_(clo_log_file_qualifier),
1933 val ? val : "");
1934 }
sewardj768db0e2005-07-19 14:18:56 +00001935 if (VG_(clo_xml_user_comment)) {
1936 /* Note: the user comment itself is XML and is therefore to
1937 be passed through verbatim (%s) rather than escaped
1938 (%t). */
1939 VG_(message)(Vg_UserMsg, "<usercomment>%s</usercomment>",
1940 VG_(clo_xml_user_comment));
1941 }
sewardj71bc3cb2005-05-19 00:25:45 +00001942 VG_(message)(Vg_UserMsg, "");
sewardjb8a3dac2005-07-19 12:39:11 +00001943 VG_(message)(Vg_UserMsg, "<args>");
1944 VG_(message)(Vg_UserMsg, " <vargv>");
1945 for (i = 0; i < vg_argc; i++) {
1946 HChar* tag = i==0 ? "exe" : "arg";
sewardj768db0e2005-07-19 14:18:56 +00001947 VG_(message)(Vg_UserMsg, " <%s>%t</%s>",
sewardjb8a3dac2005-07-19 12:39:11 +00001948 tag, vg_argv[i], tag);
1949 }
1950 VG_(message)(Vg_UserMsg, " </vargv>");
1951 VG_(message)(Vg_UserMsg, " <argv>");
sewardj8665d8e2005-06-01 17:35:23 +00001952 for (i = 0; i < VG_(client_argc); i++) {
1953 HChar* tag = i==0 ? "exe" : "arg";
sewardj97f7e0c2005-07-19 15:00:25 +00001954 VG_(message)(Vg_UserMsg, " <%s>%t</%s>",
sewardj8665d8e2005-06-01 17:35:23 +00001955 tag, VG_(client_argv)[i], tag);
1956 }
sewardjb8a3dac2005-07-19 12:39:11 +00001957 VG_(message)(Vg_UserMsg, " </argv>");
1958 VG_(message)(Vg_UserMsg, "</args>");
sewardj71bc3cb2005-05-19 00:25:45 +00001959 }
sewardj4cf05692002-10-27 20:28:29 +00001960
sewardjde4a1d02002-03-22 01:27:54 +00001961 if (VG_(clo_verbosity) > 1) {
sewardj92645592005-07-23 09:18:34 +00001962 SysRes fd;
njnbe9b47b2005-05-15 16:22:58 +00001963 if (log_to != VgLogTo_Fd)
njn1fd5eb22005-03-13 05:43:23 +00001964 VG_(message)(Vg_DebugMsg, "");
1965 VG_(message)(Vg_DebugMsg, "Valgrind library directory: %s", VG_(libdir));
1966 VG_(message)(Vg_DebugMsg, "Command line");
njn86dc2bc2003-09-09 07:26:21 +00001967 for (i = 0; i < VG_(client_argc); i++)
njn1fd5eb22005-03-13 05:43:23 +00001968 VG_(message)(Vg_DebugMsg, " %s", VG_(client_argv)[i]);
njn86dc2bc2003-09-09 07:26:21 +00001969
njn1fd5eb22005-03-13 05:43:23 +00001970 VG_(message)(Vg_DebugMsg, "Startup, with flags:");
nethercotef6a1d502004-08-09 12:21:57 +00001971 for (i = 1; i < vg_argc; i++) {
njn1fd5eb22005-03-13 05:43:23 +00001972 VG_(message)(Vg_DebugMsg, " %s", vg_argv[i]);
sewardjde4a1d02002-03-22 01:27:54 +00001973 }
nethercotea70f7352004-04-18 12:08:46 +00001974
njn1fd5eb22005-03-13 05:43:23 +00001975 VG_(message)(Vg_DebugMsg, "Contents of /proc/version:");
nethercotea70f7352004-04-18 12:08:46 +00001976 fd = VG_(open) ( "/proc/version", VKI_O_RDONLY, 0 );
sewardj92645592005-07-23 09:18:34 +00001977 if (fd.isError) {
njn1fd5eb22005-03-13 05:43:23 +00001978 VG_(message)(Vg_DebugMsg, " can't open /proc/version");
nethercotea70f7352004-04-18 12:08:46 +00001979 } else {
sewardj71bc3cb2005-05-19 00:25:45 +00001980# define BUF_LEN 256
nethercotea70f7352004-04-18 12:08:46 +00001981 Char version_buf[BUF_LEN];
sewardj92645592005-07-23 09:18:34 +00001982 Int n = VG_(read) ( fd.val, version_buf, BUF_LEN );
njnbe9b47b2005-05-15 16:22:58 +00001983 vg_assert(n <= BUF_LEN);
nethercotea70f7352004-04-18 12:08:46 +00001984 if (n > 0) {
1985 version_buf[n-1] = '\0';
njn1fd5eb22005-03-13 05:43:23 +00001986 VG_(message)(Vg_DebugMsg, " %s", version_buf);
nethercotea70f7352004-04-18 12:08:46 +00001987 } else {
njn1fd5eb22005-03-13 05:43:23 +00001988 VG_(message)(Vg_DebugMsg, " (empty?)");
nethercotea70f7352004-04-18 12:08:46 +00001989 }
sewardj92645592005-07-23 09:18:34 +00001990 VG_(close)(fd.val);
sewardj71bc3cb2005-05-19 00:25:45 +00001991# undef BUF_LEN
nethercotea70f7352004-04-18 12:08:46 +00001992 }
sewardjde4a1d02002-03-22 01:27:54 +00001993 }
1994
fitzhardinge98abfc72003-12-16 02:05:15 +00001995 if (VG_(clo_n_suppressions) < VG_CLO_MAX_SFILES-1 &&
njn95ec8702004-11-22 16:46:13 +00001996 (VG_(needs).core_errors || VG_(needs).tool_errors)) {
njn842c26e2005-06-28 02:54:52 +00001997 /* If we haven't reached the max number of suppressions, load
1998 the default one. */
fitzhardinge98abfc72003-12-16 02:05:15 +00001999 static const Char default_supp[] = "default.supp";
2000 Int len = VG_(strlen)(VG_(libdir)) + 1 + sizeof(default_supp);
2001 Char *buf = VG_(arena_malloc)(VG_AR_CORE, len);
2002 VG_(sprintf)(buf, "%s/%s", VG_(libdir), default_supp);
2003 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = buf;
2004 VG_(clo_n_suppressions)++;
sewardjde4a1d02002-03-22 01:27:54 +00002005 }
2006}
2007
nethercotef6a1d502004-08-09 12:21:57 +00002008// Build the string for VALGRINDCLO.
2009Char* VG_(build_child_VALGRINDCLO)( Char* exename )
2010{
2011 /* If we're tracing the children, then we need to start it
2012 with our starter+arguments, which are copied into VALGRINDCLO,
2013 except the --exec= option is changed if present.
2014 */
2015 Int i;
2016 Char *exec;
2017 Char *cp;
2018 Char *optvar;
2019 Int optlen, execlen;
2020
2021 // All these allocated blocks are not free - because we're either
2022 // going to exec, or panic when we fail.
2023
2024 // Create --exec= option: "--exec=<exename>"
2025 exec = VG_(arena_malloc)(VG_AR_CORE,
2026 VG_(strlen)( exename ) + 7/*--exec=*/ + 1/*\0*/);
2027 vg_assert(NULL != exec);
2028 VG_(sprintf)(exec, "--exec=%s", exename);
2029
2030 // Allocate space for optvar (may overestimate by counting --exec twice,
2031 // no matter)
2032 optlen = 1;
2033 for (i = 0; i < vg_argc; i++)
2034 optlen += VG_(strlen)(vg_argv[i]) + 1;
2035 optlen += VG_(strlen)(exec)+1;
2036 optvar = VG_(arena_malloc)(VG_AR_CORE, optlen);
2037
2038 // Copy all valgrind args except the old --exec (if present)
2039 // VG_CLO_SEP is the separator.
2040 cp = optvar;
2041 for (i = 1; i < vg_argc; i++) {
2042 Char *arg = vg_argv[i];
2043
2044 if (VG_(memcmp)(arg, "--exec=", 7) == 0) {
2045 // don't copy existing --exec= arg
2046 } else if (VG_(strcmp)(arg, "--") == 0) {
2047 // stop at "--"
2048 break;
2049 } else {
2050 // copy non "--exec" arg
2051 Int len = VG_(strlen)(arg);
2052 VG_(memcpy)(cp, arg, len);
2053 cp += len;
2054 *cp++ = VG_CLO_SEP;
2055 }
2056 }
2057 // Add the new --exec= option
2058 execlen = VG_(strlen)(exec);
2059 VG_(memcpy)(cp, exec, execlen);
2060 cp += execlen;
2061 *cp++ = VG_CLO_SEP;
2062
2063 *cp = '\0';
2064
2065 return optvar;
2066}
2067
2068// Build "/proc/self/fd/<execfd>".
2069Char* VG_(build_child_exename)( void )
2070{
2071 Char* exename = VG_(arena_malloc)(VG_AR_CORE, 64);
2072 vg_assert(NULL != exename);
2073 VG_(sprintf)(exename, "/proc/self/fd/%d", vgexecfd);
2074 return exename;
2075}
2076
sewardjde4a1d02002-03-22 01:27:54 +00002077
nethercote71980f02004-01-24 18:18:54 +00002078/*====================================================================*/
2079/*=== File descriptor setup ===*/
2080/*====================================================================*/
2081
2082static void setup_file_descriptors(void)
2083{
2084 struct vki_rlimit rl;
2085
2086 /* Get the current file descriptor limits. */
2087 if (VG_(getrlimit)(VKI_RLIMIT_NOFILE, &rl) < 0) {
2088 rl.rlim_cur = 1024;
2089 rl.rlim_max = 1024;
2090 }
2091
2092 /* Work out where to move the soft limit to. */
njn14319cc2005-03-13 06:26:22 +00002093 if (rl.rlim_cur + N_RESERVED_FDS <= rl.rlim_max) {
2094 rl.rlim_cur = rl.rlim_cur + N_RESERVED_FDS;
nethercote71980f02004-01-24 18:18:54 +00002095 } else {
2096 rl.rlim_cur = rl.rlim_max;
2097 }
2098
2099 /* Reserve some file descriptors for our use. */
njn14319cc2005-03-13 06:26:22 +00002100 VG_(fd_soft_limit) = rl.rlim_cur - N_RESERVED_FDS;
2101 VG_(fd_hard_limit) = rl.rlim_cur - N_RESERVED_FDS;
nethercote71980f02004-01-24 18:18:54 +00002102
2103 /* Update the soft limit. */
2104 VG_(setrlimit)(VKI_RLIMIT_NOFILE, &rl);
2105
nethercotef6a1d502004-08-09 12:21:57 +00002106 if (vgexecfd != -1)
2107 vgexecfd = VG_(safe_fd)( vgexecfd );
nethercote71980f02004-01-24 18:18:54 +00002108 if (VG_(clexecfd) != -1)
2109 VG_(clexecfd) = VG_(safe_fd)( VG_(clexecfd) );
2110}
2111
nethercote71980f02004-01-24 18:18:54 +00002112/*====================================================================*/
nethercote71980f02004-01-24 18:18:54 +00002113/*=== Initialise program data/text, etc. ===*/
2114/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +00002115
sewardjb5f6f512005-03-10 23:59:00 +00002116static void build_valgrind_map_callback ( Addr start, SizeT size, UInt prot,
2117 UInt dev, UInt ino, ULong foffset,
2118 const UChar* filename )
sewardjde4a1d02002-03-22 01:27:54 +00002119{
nethercote71980f02004-01-24 18:18:54 +00002120 /* Only record valgrind mappings for now, without loading any
2121 symbols. This is so we know where the free space is before we
2122 start allocating more memory (note: heap is OK, it's just mmap
2123 which is the problem here). */
sewardjb5f6f512005-03-10 23:59:00 +00002124 if (start >= VG_(client_end) && start < VG_(valgrind_last)) {
sewardj8c615892005-04-25 02:38:28 +00002125 VG_(debugLog)(2, "main",
2126 "valgrind-seg: %p-%p prot 0x%x file=%s\n",
njna4469a72005-05-08 02:06:33 +00002127 (void*)start, (void*)(start+size), prot, filename);
sewardjb5f6f512005-03-10 23:59:00 +00002128 VG_(map_file_segment)(start, size, prot,
sewardj8c615892005-04-25 02:38:28 +00002129 SF_MMAP|SF_NOSYMS|SF_VALGRIND,
2130 dev, ino, foffset, filename);
sewardjb5f6f512005-03-10 23:59:00 +00002131 /* update VG_(valgrind_last) if it looks wrong */
2132 if (start+size > VG_(valgrind_last))
sewardj8c615892005-04-25 02:38:28 +00002133 VG_(valgrind_last) = start+size-1;
nethercote71980f02004-01-24 18:18:54 +00002134 }
sewardjde4a1d02002-03-22 01:27:54 +00002135}
2136
nethercote71980f02004-01-24 18:18:54 +00002137// Global var used to pass local data to callback
nethercote4ad74312004-10-26 09:59:49 +00002138Addr sp_at_startup___global_arg = 0;
sewardjde4a1d02002-03-22 01:27:54 +00002139
sewardjb5f6f512005-03-10 23:59:00 +00002140/*
2141 This second pass adds in client mappings, and loads symbol tables
2142 for all interesting mappings. The trouble is that things can
2143 change as we go, because we're calling the Tool to track memory as
2144 we find it.
2145
2146 So for Valgrind mappings, we don't replace any mappings which
2147 aren't still identical (which will include the .so mappings, so we
2148 will load their symtabs)>
2149 */
2150static void build_segment_map_callback ( Addr start, SizeT size, UInt prot,
2151 UInt dev, UInt ino, ULong foffset,
2152 const UChar* filename )
sewardj45b672d2003-07-25 19:58:11 +00002153{
nethercote71980f02004-01-24 18:18:54 +00002154 UInt flags;
2155 Bool is_stack_segment;
2156 Addr r_esp;
sewardj45b672d2003-07-25 19:58:11 +00002157
nethercote71980f02004-01-24 18:18:54 +00002158 is_stack_segment
2159 = (start == VG_(clstk_base) && (start+size) == VG_(clstk_end));
fitzhardinge98abfc72003-12-16 02:05:15 +00002160
sewardj8c615892005-04-25 02:38:28 +00002161 VG_(debugLog)(2, "main",
2162 "any-seg: %p-%p prot 0x%x stack=%d file=%s\n",
njna4469a72005-05-08 02:06:33 +00002163 (void*)start, (void*)(start+size), prot, is_stack_segment,
2164 filename);
fitzhardinge98abfc72003-12-16 02:05:15 +00002165
nethercote71980f02004-01-24 18:18:54 +00002166 if (is_stack_segment)
2167 flags = SF_STACK | SF_GROWDOWN;
2168 else
njn0ae787c2005-06-28 22:14:53 +00002169 flags = SF_MMAP;
fitzhardinge98abfc72003-12-16 02:05:15 +00002170
nethercote71980f02004-01-24 18:18:54 +00002171 if (filename != NULL)
2172 flags |= SF_FILE;
fitzhardinge98abfc72003-12-16 02:05:15 +00002173
sewardjb5f6f512005-03-10 23:59:00 +00002174#if 0
2175 // This needs to be fixed properly. jrs 20050307
2176 if (start >= VG_(client_end) && start < VG_(valgrind_last)) {
2177 Segment *s = VG_(find_segment_before)(start);
fitzhardinge98abfc72003-12-16 02:05:15 +00002178
sewardjb5f6f512005-03-10 23:59:00 +00002179 /* We have to be a bit careful about inserting new mappings into
2180 the Valgrind part of the address space. We're actively
2181 changing things as we parse these mappings, particularly in
2182 shadow memory, and so we don't want to overwrite those
2183 changes. Therefore, we only insert/update a mapping if it is
2184 mapped from a file or it exactly matches an existing mapping.
fitzhardinge98abfc72003-12-16 02:05:15 +00002185
sewardjb5f6f512005-03-10 23:59:00 +00002186 NOTE: we're only talking about the Segment list mapping
2187 metadata; this doesn't actually mmap anything more. */
2188 if (filename || (s && s->addr == start && s->len == size)) {
2189 flags |= SF_VALGRIND;
2190 VG_(map_file_segment)(start, size, prot, flags, dev, ino, foffset, filename);
2191 } else {
2192 /* assert range is already mapped */
2193 vg_assert(VG_(is_addressable)(start, size, VKI_PROT_NONE));
2194 }
2195 } else
2196#endif
2197 VG_(map_file_segment)(start, size, prot, flags, dev, ino, foffset, filename);
2198
2199 if (VG_(is_client_addr)(start) && VG_(is_client_addr)(start+size-1)) {
2200 VG_TRACK( new_mem_startup, start, size,
2201 !!(prot & VKI_PROT_READ),
2202 !!(prot & VKI_PROT_WRITE),
2203 !!(prot & VKI_PROT_EXEC));
2204 }
sewardj3e1eb1f2002-05-18 13:14:17 +00002205
nethercote71980f02004-01-24 18:18:54 +00002206 /* If this is the stack segment mark all below %esp as noaccess. */
nethercote4ad74312004-10-26 09:59:49 +00002207 r_esp = sp_at_startup___global_arg;
nethercote71980f02004-01-24 18:18:54 +00002208 vg_assert(0 != r_esp);
2209 if (is_stack_segment) {
sewardjb5f6f512005-03-10 23:59:00 +00002210 if (0) {
2211 VG_(message)(Vg_DebugMsg, "invalidating stack area: %p .. %p",
nethercote71980f02004-01-24 18:18:54 +00002212 start,r_esp);
sewardjb5f6f512005-03-10 23:59:00 +00002213 VG_(message)(Vg_DebugMsg, " validating stack area: %p .. %p",
2214 r_esp, start+size);
2215 }
nethercote71980f02004-01-24 18:18:54 +00002216 VG_TRACK( die_mem_stack, start, r_esp-start );
sewardjb5f6f512005-03-10 23:59:00 +00002217 // what's this for?
2218 //VG_TRACK( post_mem_write, r_esp, (start+size)-r_esp );
sewardjde4a1d02002-03-22 01:27:54 +00002219 }
sewardjde4a1d02002-03-22 01:27:54 +00002220}
2221
njn2da73352005-06-18 01:35:16 +00002222/*====================================================================*/
2223/*=== Initialise the first thread. ===*/
2224/*====================================================================*/
2225
2226/* Given a pointer to the ThreadArchState for thread 1 (the root
2227 thread), initialise the VEX guest state, and copy in essential
2228 starting values.
2229*/
2230static void init_thread1state ( Addr client_ip,
2231 Addr sp_at_startup,
2232 /*inout*/ ThreadArchState* arch )
2233{
2234#if defined(VGA_x86)
2235 vg_assert(0 == sizeof(VexGuestX86State) % 8);
2236
2237 /* Zero out the initial state, and set up the simulated FPU in a
2238 sane way. */
2239 LibVEX_GuestX86_initialise(&arch->vex);
2240
2241 /* Zero out the shadow area. */
2242 VG_(memset)(&arch->vex_shadow, 0, sizeof(VexGuestX86State));
2243
2244 /* Put essential stuff into the new state. */
2245 arch->vex.guest_ESP = sp_at_startup;
2246 arch->vex.guest_EIP = client_ip;
2247
2248 /* initialise %cs, %ds and %ss to point at the operating systems
2249 default code, data and stack segments */
2250 asm volatile("movw %%cs, %0" : : "m" (arch->vex.guest_CS));
2251 asm volatile("movw %%ds, %0" : : "m" (arch->vex.guest_DS));
2252 asm volatile("movw %%ss, %0" : : "m" (arch->vex.guest_SS));
cerion85665ca2005-06-20 15:51:07 +00002253
njn2da73352005-06-18 01:35:16 +00002254#elif defined(VGA_amd64)
2255 vg_assert(0 == sizeof(VexGuestAMD64State) % 8);
2256
2257 /* Zero out the initial state, and set up the simulated FPU in a
2258 sane way. */
2259 LibVEX_GuestAMD64_initialise(&arch->vex);
2260
2261 /* Zero out the shadow area. */
2262 VG_(memset)(&arch->vex_shadow, 0, sizeof(VexGuestAMD64State));
2263
2264 /* Put essential stuff into the new state. */
2265 arch->vex.guest_RSP = sp_at_startup;
2266 arch->vex.guest_RIP = client_ip;
cerion85665ca2005-06-20 15:51:07 +00002267
2268#elif defined(VGA_ppc32)
2269 vg_assert(0 == sizeof(VexGuestPPC32State) % 8);
2270
2271 /* Zero out the initial state, and set up the simulated FPU in a
2272 sane way. */
2273 LibVEX_GuestPPC32_initialise(&arch->vex);
2274
2275 /* Zero out the shadow area. */
2276 VG_(memset)(&arch->vex_shadow, 0, sizeof(VexGuestPPC32State));
2277
2278 /* Put essential stuff into the new state. */
2279 arch->vex.guest_GPR1 = sp_at_startup;
2280 arch->vex.guest_CIA = client_ip;
2281
njn2da73352005-06-18 01:35:16 +00002282#else
2283# error Unknown arch
2284#endif
2285 // Tell the tool that we just wrote to the registers.
2286 VG_TRACK( post_reg_write, Vg_CoreStartup, /*tid*/1, /*offset*/0,
2287 sizeof(VexGuestArchState));
2288}
2289
sewardjde4a1d02002-03-22 01:27:54 +00002290
nethercote71980f02004-01-24 18:18:54 +00002291/*====================================================================*/
njn2025cf92005-06-26 20:44:48 +00002292/*=== BB profiling ===*/
2293/*====================================================================*/
2294
2295static
2296void show_BB_profile ( BBProfEntry tops[], UInt n_tops, ULong score_total )
2297{
2298 ULong score_cumul, score_here;
2299 Char buf_cumul[10], buf_here[10];
2300 Char name[64];
2301 Int r;
2302
2303 VG_(printf)("\n");
2304 VG_(printf)("-----------------------------------------------------------\n");
2305 VG_(printf)("--- BEGIN BB Profile (summary of scores) ---\n");
2306 VG_(printf)("-----------------------------------------------------------\n");
2307 VG_(printf)("\n");
2308
2309 VG_(printf)("Total score = %lld\n\n", score_total);
2310
2311 score_cumul = 0;
2312 for (r = 0; r < n_tops; r++) {
2313 if (tops[r].addr == 0)
2314 continue;
2315 name[0] = 0;
2316 VG_(get_fnname_w_offset)(tops[r].addr, name, 64);
2317 name[63] = 0;
2318 score_here = tops[r].score;
2319 score_cumul += score_here;
2320 VG_(percentify)(score_cumul, score_total, 2, 6, buf_cumul);
2321 VG_(percentify)(score_here, score_total, 2, 6, buf_here);
2322 VG_(printf)("%3d: (%9lld %s) %9lld %s 0x%llx %s\n",
2323 r,
2324 score_cumul, buf_cumul,
2325 score_here, buf_here, tops[r].addr, name );
2326 }
2327
2328 VG_(printf)("\n");
2329 VG_(printf)("-----------------------------------------------------------\n");
2330 VG_(printf)("--- BB Profile (BB details) ---\n");
2331 VG_(printf)("-----------------------------------------------------------\n");
2332 VG_(printf)("\n");
2333
2334 score_cumul = 0;
2335 for (r = 0; r < n_tops; r++) {
2336 if (tops[r].addr == 0)
2337 continue;
2338 name[0] = 0;
2339 VG_(get_fnname_w_offset)(tops[r].addr, name, 64);
2340 name[63] = 0;
2341 score_here = tops[r].score;
2342 score_cumul += score_here;
2343 VG_(percentify)(score_cumul, score_total, 2, 6, buf_cumul);
2344 VG_(percentify)(score_here, score_total, 2, 6, buf_here);
2345 VG_(printf)("\n");
2346 VG_(printf)("=-=-=-=-=-=-=-=-=-=-=-=-=-= begin BB rank %d "
2347 "=-=-=-=-=-=-=-=-=-=-=-=-=-=\n\n", r);
2348 VG_(printf)("%3d: (%9lld %s) %9lld %s 0x%llx %s\n",
2349 r,
2350 score_cumul, buf_cumul,
2351 score_here, buf_here, tops[r].addr, name );
2352 VG_(printf)("\n");
2353 VG_(translate)(0, tops[r].addr, True, VG_(clo_profile_flags), 0);
2354 VG_(printf)("=-=-=-=-=-=-=-=-=-=-=-=-=-= end BB rank %d "
2355 "=-=-=-=-=-=-=-=-=-=-=-=-=-=\n\n", r);
2356 }
2357
2358 VG_(printf)("\n");
2359 VG_(printf)("-----------------------------------------------------------\n");
2360 VG_(printf)("--- END BB Profile ---\n");
2361 VG_(printf)("-----------------------------------------------------------\n");
2362 VG_(printf)("\n");
2363}
2364
2365
2366/*====================================================================*/
nethercote71980f02004-01-24 18:18:54 +00002367/*=== main() ===*/
2368/*====================================================================*/
2369
nethercotec314eba2004-07-15 12:59:41 +00002370/*
2371 This code decides on the layout of the client and Valgrind address
nethercote996901a2004-08-03 13:29:09 +00002372 spaces, loads valgrind.so and the tool.so into the valgrind part,
nethercotec314eba2004-07-15 12:59:41 +00002373 loads the client executable (and the dynamic linker, if necessary)
2374 into the client part, and calls into Valgrind proper.
2375
2376 The code is careful not to allow spurious mappings to appear in the
2377 wrong parts of the address space. In particular, to make sure
2378 dlopen puts things in the right place, it will pad out the forbidden
2379 chunks of address space so that dlopen is forced to put things where
2380 we want them.
2381
2382 The memory map it creates is:
2383
njn311c5d82005-05-15 21:03:42 +00002384 client_base +-------------------------+
nethercotec314eba2004-07-15 12:59:41 +00002385 | client address space |
2386 : :
2387 : :
2388 | client stack |
2389 client_end +-------------------------+
2390 | redzone |
2391 shadow_base +-------------------------+
2392 | |
nethercote996901a2004-08-03 13:29:09 +00002393 : shadow memory for tools :
nethercotec314eba2004-07-15 12:59:41 +00002394 | (may be 0 sized) |
2395 shadow_end +-------------------------+
nethercotec314eba2004-07-15 12:59:41 +00002396 valgrind_base +-------------------------+
2397 | kickstart executable |
2398 | valgrind heap vvvvvvvvv| (barely used)
2399 - -
2400 | valgrind .so files |
2401 | and mappings |
2402 - -
2403 | valgrind stack ^^^^^^^^^|
nethercote820bd8c2004-09-07 23:04:49 +00002404 valgrind_last +-------------------------+
nethercotec314eba2004-07-15 12:59:41 +00002405 : kernel :
2406
2407 Nb: Before we can do general allocations with VG_(arena_malloc)() and
2408 VG_(mmap)(), we need to build the segment skip-list, so we know where
2409 we can put things. However, building that structure requires
2410 allocating memory. So we need to a bootstrapping process. It's done
2411 by making VG_(arena_malloc)() have a special static superblock that's
2412 used for the first 1MB's worth of allocations. This is enough to
2413 build the segment skip-list.
2414*/
2415
thughes4ad52d02004-06-27 17:37:21 +00002416
sewardj1cf558c2005-04-25 01:36:56 +00002417/* This may be needed before m_mylibc is OK to run. */
2418static Int local_strcmp ( const HChar* s1, const HChar* s2 )
2419{
2420 while (True) {
2421 if (*s1 == 0 && *s2 == 0) return 0;
2422 if (*s1 == 0) return -1;
2423 if (*s2 == 0) return 1;
2424
2425 if (*(UChar*)s1 < *(UChar*)s2) return -1;
2426 if (*(UChar*)s1 > *(UChar*)s2) return 1;
2427
2428 s1++; s2++;
2429 }
2430}
2431
2432
sewardjb5f6f512005-03-10 23:59:00 +00002433int main(int argc, char **argv, char **envp)
nethercote71980f02004-01-24 18:18:54 +00002434{
2435 char **cl_argv;
sewardjb5f6f512005-03-10 23:59:00 +00002436 const char *tool = "memcheck"; // default to Memcheck
nethercote71980f02004-01-24 18:18:54 +00002437 const char *exec = NULL;
2438 char *preload; /* tool-specific LD_PRELOAD .so */
2439 char **env;
nethercote6c999f22004-01-31 22:55:15 +00002440 Int need_help = 0; // 0 = no, 1 = --help, 2 = --help-debug
nethercote71980f02004-01-24 18:18:54 +00002441 struct exeinfo info;
2442 ToolInfo *toolinfo = NULL;
nethercote71980f02004-01-24 18:18:54 +00002443 Addr client_eip;
nethercote4ad74312004-10-26 09:59:49 +00002444 Addr sp_at_startup; /* client's SP at the point we gained control. */
nethercote71980f02004-01-24 18:18:54 +00002445 UInt * client_auxv;
nethercote73b526f2004-10-31 18:48:21 +00002446 struct vki_rlimit zero = { 0, 0 };
sewardj1cf558c2005-04-25 01:36:56 +00002447 Int padfile, loglevel, i;
nethercote71980f02004-01-24 18:18:54 +00002448
2449 //============================================================
2450 // Nb: startup is complex. Prerequisites are shown at every step.
2451 //
2452 // *** Be very careful when messing with the order ***
2453 //============================================================
2454
sewardj1cf558c2005-04-25 01:36:56 +00002455 //--------------------------------------------------------------
2456 // Start up the logging mechanism
2457 // p: none
2458 //--------------------------------------------------------------
2459 /* Start the debugging-log system ASAP. First find out how many
2460 "-d"s were specified. This is a pre-scan of the command line. */
2461 loglevel = 0;
2462 for (i = 1; i < argc; i++) {
sewardj10759312005-05-30 23:52:47 +00002463 if (argv[i][0] != '-')
2464 break;
2465 if (0 == local_strcmp(argv[i], "--"))
2466 break;
2467 if (0 == local_strcmp(argv[i], "-d"))
2468 loglevel++;
sewardj1cf558c2005-04-25 01:36:56 +00002469 }
2470
2471 /* ... and start the debug logger. Now we can safely emit logging
2472 messages all through startup. */
sewardj10759312005-05-30 23:52:47 +00002473 VG_(debugLog_startup)(loglevel, "Stage 2 (main)");
sewardj1cf558c2005-04-25 01:36:56 +00002474
nethercotef4928da2004-06-15 10:54:40 +00002475 //============================================================
2476 // Command line argument handling order:
2477 // * If --help/--help-debug are present, show usage message
sewardjb5f6f512005-03-10 23:59:00 +00002478 // (including the tool-specific usage)
2479 // * (If no --tool option given, default to Memcheck)
nethercotef4928da2004-06-15 10:54:40 +00002480 // * Then, if client is missing, abort with error msg
2481 // * Then, if any cmdline args are bad, abort with error msg
2482 //============================================================
2483
fitzhardingeb50068f2004-02-24 23:42:55 +00002484 // Get the current process datasize rlimit, and set it to zero.
2485 // This prevents any internal uses of brk() from having any effect.
2486 // We remember the old value so we can restore it on exec, so that
2487 // child processes will have a reasonable brk value.
2488 VG_(getrlimit)(VKI_RLIMIT_DATA, &VG_(client_rlimit_data));
2489 zero.rlim_max = VG_(client_rlimit_data).rlim_max;
2490 VG_(setrlimit)(VKI_RLIMIT_DATA, &zero);
thughesc37184f2004-09-11 14:16:57 +00002491
2492 // Get the current process stack rlimit.
2493 VG_(getrlimit)(VKI_RLIMIT_STACK, &VG_(client_rlimit_stack));
2494
nethercote71980f02004-01-24 18:18:54 +00002495 //--------------------------------------------------------------
2496 // Check we were launched by stage1
sewardj51ac0872004-12-21 01:20:49 +00002497 // p: none
nethercote71980f02004-01-24 18:18:54 +00002498 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002499 VG_(debugLog)(1, "main", "Doing scan_auxv()\n");
nethercotec25c4492004-10-18 11:52:17 +00002500 {
sewardj1fbc1a52005-04-25 02:05:54 +00002501 void* init_sp = argv - 1;
2502 padfile = scan_auxv(init_sp);
nethercote71980f02004-01-24 18:18:54 +00002503 }
2504
2505 //--------------------------------------------------------------
2506 // Look for alternative libdir
sewardj51ac0872004-12-21 01:20:49 +00002507 // p: none
nethercote71980f02004-01-24 18:18:54 +00002508 //--------------------------------------------------------------
sewardj51ac0872004-12-21 01:20:49 +00002509 { HChar *cp = getenv(VALGRINDLIB);
nethercote71980f02004-01-24 18:18:54 +00002510 if (cp != NULL)
2511 VG_(libdir) = cp;
2512 }
2513
2514 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002515 // Get valgrind args + client args (inc. from VALGRIND_OPTS/.valgrindrc).
2516 // Pre-process the command line.
sewardj51ac0872004-12-21 01:20:49 +00002517 // p: none
nethercote71980f02004-01-24 18:18:54 +00002518 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002519 VG_(debugLog)(1, "main", "Preprocess command line opts\n");
nethercotef6a1d502004-08-09 12:21:57 +00002520 get_command_line(argc, argv, &vg_argc, &vg_argv, &cl_argv);
nethercote71980f02004-01-24 18:18:54 +00002521 pre_process_cmd_line_options(&need_help, &tool, &exec);
2522
sewardj10759312005-05-30 23:52:47 +00002523 /* If this process was created by exec done by another Valgrind
2524 process, the arguments will only show up at this point. Hence
2525 we need to also snoop around in vg_argv to see if anyone is
2526 asking for debug logging. */
2527 if (loglevel == 0) {
2528 for (i = 1; i < vg_argc; i++) {
2529 if (vg_argv[i][0] != '-')
2530 break;
2531 if (0 == local_strcmp(vg_argv[i], "--"))
2532 break;
2533 if (0 == local_strcmp(vg_argv[i], "-d"))
2534 loglevel++;
2535 }
2536 VG_(debugLog_startup)(loglevel, "Stage 2 (second go)");
2537 }
2538
nethercote71980f02004-01-24 18:18:54 +00002539 //==============================================================
2540 // Nb: once a tool is specified, the tool.so must be loaded even if
2541 // they specified --help or didn't specify a client program.
2542 //==============================================================
2543
2544 //--------------------------------------------------------------
2545 // With client padded out, map in tool
nethercote71980f02004-01-24 18:18:54 +00002546 // p: set-libdir [for VG_(libdir)]
2547 // p: pre_process_cmd_line_options() [for 'tool']
2548 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002549 VG_(debugLog)(1, "main", "Loading tool\n");
njn8a97c6d2005-03-31 04:37:24 +00002550 load_tool(tool, &toolinfo, &preload);
nethercote71980f02004-01-24 18:18:54 +00002551
2552 //==============================================================
2553 // Can use VG_(malloc)() and VG_(arena_malloc)() only after load_tool()
nethercotec314eba2004-07-15 12:59:41 +00002554 // -- redzone size is now set. This is checked by vg_malloc2.c.
nethercote71980f02004-01-24 18:18:54 +00002555 //==============================================================
2556
2557 //--------------------------------------------------------------
2558 // Finalise address space layout
nethercote31779c72004-07-30 21:50:15 +00002559 // p: load_tool() [for 'toolinfo']
nethercote71980f02004-01-24 18:18:54 +00002560 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002561 VG_(debugLog)(1, "main", "Laying out remaining space\n");
nethercote31779c72004-07-30 21:50:15 +00002562 layout_remaining_space( (Addr) & argc, toolinfo->shadow_ratio );
nethercote71980f02004-01-24 18:18:54 +00002563
2564 //--------------------------------------------------------------
2565 // Load client executable, finding in $PATH if necessary
nethercote71980f02004-01-24 18:18:54 +00002566 // p: pre_process_cmd_line_options() [for 'exec', 'need_help']
2567 // p: layout_remaining_space [so there's space]
2568 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002569 VG_(debugLog)(1, "main", "Loading client\n");
nethercotef4928da2004-06-15 10:54:40 +00002570 load_client(cl_argv, exec, need_help, &info, &client_eip);
nethercote71980f02004-01-24 18:18:54 +00002571
2572 //--------------------------------------------------------------
nethercote969ecf12004-10-13 17:29:01 +00002573 // Everything in place, remove padding done by stage1
nethercote71980f02004-01-24 18:18:54 +00002574 // p: layout_remaining_space() [everything must be mapped in before now]
2575 // p: load_client() [ditto]
2576 //--------------------------------------------------------------
nethercote31779c72004-07-30 21:50:15 +00002577 as_unpad((void *)VG_(shadow_end), (void *)~0, padfile);
2578 as_closepadfile(padfile); // no more padding
nethercote71980f02004-01-24 18:18:54 +00002579
2580 //--------------------------------------------------------------
2581 // Set up client's environment
2582 // p: set-libdir [for VG_(libdir)]
2583 // p: load_tool() [for 'preload']
2584 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002585 VG_(debugLog)(1, "main", "Setup client env\n");
sewardjb5f6f512005-03-10 23:59:00 +00002586 env = fix_environment(envp, preload);
nethercote71980f02004-01-24 18:18:54 +00002587
2588 //--------------------------------------------------------------
nethercote5ee67ca2004-06-22 14:00:09 +00002589 // Setup client stack, eip, and VG_(client_arg[cv])
nethercote71980f02004-01-24 18:18:54 +00002590 // p: load_client() [for 'info']
2591 // p: fix_environment() [for 'env']
2592 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002593 VG_(debugLog)(1, "main", "Setup client stack\n");
nethercotec25c4492004-10-18 11:52:17 +00002594 {
sewardj1fbc1a52005-04-25 02:05:54 +00002595 void* init_sp = argv - 1;
sewardjb5f6f512005-03-10 23:59:00 +00002596
sewardj1fbc1a52005-04-25 02:05:54 +00002597 sp_at_startup = setup_client_stack(init_sp, cl_argv, env, &info,
2598 &client_auxv);
2599 free(env);
nethercotec25c4492004-10-18 11:52:17 +00002600 }
nethercote71980f02004-01-24 18:18:54 +00002601
sewardj1fbc1a52005-04-25 02:05:54 +00002602 VG_(debugLog)(2, "main",
2603 "Client info: "
2604 "entry=%p client esp=%p vg_argc=%d brkbase=%p\n",
2605 (void*)client_eip, (void*)sp_at_startup, vg_argc,
2606 (void*)VG_(brk_base) );
nethercote71980f02004-01-24 18:18:54 +00002607
2608 //==============================================================
2609 // Finished setting up operating environment. Now initialise
2610 // Valgrind. (This is where the old VG_(main)() started.)
2611 //==============================================================
2612
2613 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002614 // setup file descriptors
2615 // p: n/a
2616 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002617 VG_(debugLog)(1, "main", "Setup file descriptors\n");
nethercote71980f02004-01-24 18:18:54 +00002618 setup_file_descriptors();
2619
2620 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002621 // Build segment map (Valgrind segments only)
njnd2252832004-11-26 10:53:33 +00002622 // p: tl_pre_clo_init() [to setup new_mem_startup tracker]
nethercotec314eba2004-07-15 12:59:41 +00002623 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002624 VG_(debugLog)(1, "main", "Parse /proc/self/maps (round 1)\n");
nethercotec314eba2004-07-15 12:59:41 +00002625 VG_(parse_procselfmaps) ( build_valgrind_map_callback );
2626
2627 //==============================================================
2628 // Can use VG_(arena_malloc)() with non-CORE arena after segments set up
2629 //==============================================================
2630
2631 //--------------------------------------------------------------
2632 // Init tool: pre_clo_init, process cmd line, post_clo_init
2633 // p: setup_client_stack() [for 'VG_(client_arg[cv]']
njn8a97c6d2005-03-31 04:37:24 +00002634 // p: load_tool() [for 'toolinfo']
nethercotec314eba2004-07-15 12:59:41 +00002635 // p: setup_file_descriptors() [for 'VG_(fd_xxx_limit)']
2636 // p: parse_procselfmaps [so VG segments are setup so tool can
2637 // call VG_(malloc)]
nethercote71980f02004-01-24 18:18:54 +00002638 //--------------------------------------------------------------
njn64c83242005-06-21 01:54:38 +00002639 {
2640 Char* s;
2641 Bool ok;
2642 VG_(debugLog)(1, "main", "Initialise the tool\n");
2643 (*toolinfo->tl_pre_clo_init)();
2644 ok = VG_(sanity_check_needs)( VG_(shadow_base) != VG_(shadow_end), &s );
2645 if (!ok) {
2646 VG_(tool_panic)(s);
2647 }
2648 }
nethercote71980f02004-01-24 18:18:54 +00002649
nethercotef4928da2004-06-15 10:54:40 +00002650 // If --tool and --help/--help-debug was given, now give the core+tool
2651 // help message
nethercotef4928da2004-06-15 10:54:40 +00002652 if (need_help) {
2653 usage(/*--help-debug?*/2 == need_help);
2654 }
nethercotec314eba2004-07-15 12:59:41 +00002655 process_cmd_line_options(client_auxv, tool);
2656
njn51d827b2005-05-09 01:02:08 +00002657 VG_TDICT_CALL(tool_post_clo_init);
nethercotef4928da2004-06-15 10:54:40 +00002658
2659 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002660 // Build segment map (all segments)
sewardjb5f6f512005-03-10 23:59:00 +00002661 // p: shadow/redzone segments
nethercote4ad74312004-10-26 09:59:49 +00002662 // p: setup_client_stack() [for 'sp_at_startup']
nethercotec314eba2004-07-15 12:59:41 +00002663 // p: init tool [for 'new_mem_startup']
nethercote71980f02004-01-24 18:18:54 +00002664 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002665 VG_(debugLog)(1, "main", "Parse /proc/self/maps (round 2)\n");
nethercote4ad74312004-10-26 09:59:49 +00002666 sp_at_startup___global_arg = sp_at_startup;
nethercotec314eba2004-07-15 12:59:41 +00002667 VG_(parse_procselfmaps) ( build_segment_map_callback ); /* everything */
nethercote4ad74312004-10-26 09:59:49 +00002668 sp_at_startup___global_arg = 0;
sewardjb5f6f512005-03-10 23:59:00 +00002669
nethercotec314eba2004-07-15 12:59:41 +00002670 //==============================================================
2671 // Can use VG_(map)() after segments set up
2672 //==============================================================
nethercote71980f02004-01-24 18:18:54 +00002673
2674 //--------------------------------------------------------------
2675 // Allow GDB attach
2676 // p: process_cmd_line_options() [for VG_(clo_wait_for_gdb)]
2677 //--------------------------------------------------------------
2678 /* Hook to delay things long enough so we can get the pid and
2679 attach GDB in another shell. */
2680 if (VG_(clo_wait_for_gdb)) {
sewardj8211a572005-06-23 21:37:47 +00002681 Long q, iters;
sewardj1fbc1a52005-04-25 02:05:54 +00002682 VG_(debugLog)(1, "main", "Wait for GDB\n");
sewardj93ab8572005-02-06 14:10:40 +00002683 VG_(printf)("pid=%d, entering delay loop\n", VG_(getpid)());
2684 /* jrs 20050206: I don't understand why this works on x86. On
2685 amd64 the obvious analogues (jump *$rip or jump *$rcx) don't
2686 work. */
2687 /* do "jump *$eip" to skip this in gdb (x86) */
2688 //VG_(do_syscall0)(__NR_pause);
sewardj8211a572005-06-23 21:37:47 +00002689
2690# if defined(VGP_x86_linux)
2691 iters = 5;
2692# elif defined(VGP_amd64_linux)
2693 iters = 10;
2694# elif defined(VGP_ppc32_linux)
sewardjd714d2e2005-07-08 18:24:04 +00002695 iters = 5;
sewardj8211a572005-06-23 21:37:47 +00002696# else
2697# error "Unknown plat"
2698# endif
2699
2700 iters *= 1000*1000*1000;
2701 for (q = 0; q < iters; q++)
2702 ;
nethercote71980f02004-01-24 18:18:54 +00002703 }
2704
sewardjb5d320c2005-03-13 18:57:15 +00002705 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002706 // Search for file descriptors that are inherited from our parent
2707 // p: process_cmd_line_options [for VG_(clo_track_fds)]
2708 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002709 if (VG_(clo_track_fds)) {
2710 VG_(debugLog)(1, "main", "Init preopened fds\n");
nethercote71980f02004-01-24 18:18:54 +00002711 VG_(init_preopened_fds)();
sewardj1fbc1a52005-04-25 02:05:54 +00002712 }
nethercote71980f02004-01-24 18:18:54 +00002713
2714 //--------------------------------------------------------------
2715 // Initialise the scheduler
nethercote71980f02004-01-24 18:18:54 +00002716 // p: setup_file_descriptors() [else VG_(safe_fd)() breaks]
2717 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002718 VG_(debugLog)(1, "main", "Initialise scheduler\n");
nethercote71980f02004-01-24 18:18:54 +00002719 VG_(scheduler_init)();
2720
2721 //--------------------------------------------------------------
sewardjb5f6f512005-03-10 23:59:00 +00002722 // Initialise the pthread model
2723 // p: ?
sewardj2a99cf62004-11-24 10:44:19 +00002724 // load_client() [for 'client_eip']
2725 // setup_client_stack() [for 'sp_at_startup']
2726 // setup_scheduler() [for the rest of state 1 stuff]
2727 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002728 VG_(debugLog)(1, "main", "Initialise thread 1's state\n");
njn2da73352005-06-18 01:35:16 +00002729 init_thread1state(client_eip, sp_at_startup, &VG_(threads)[1].arch);
njnea4b28c2004-11-30 16:04:58 +00002730
sewardj2a99cf62004-11-24 10:44:19 +00002731 //--------------------------------------------------------------
sewardj39b88fb2005-03-12 15:16:07 +00002732 // Initialise the pthread model
2733 // p: ?
nethercote71980f02004-01-24 18:18:54 +00002734 //--------------------------------------------------------------
sewardjb5f6f512005-03-10 23:59:00 +00002735 //if (VG_(clo_model_pthreads))
2736 // VG_(pthread_init)();
nethercote71980f02004-01-24 18:18:54 +00002737
2738 //--------------------------------------------------------------
2739 // Initialise the signal handling subsystem
sewardjb5f6f512005-03-10 23:59:00 +00002740 // p: n/a
nethercote71980f02004-01-24 18:18:54 +00002741 //--------------------------------------------------------------
2742 // Nb: temporarily parks the saved blocking-mask in saved_sigmask.
sewardj1fbc1a52005-04-25 02:05:54 +00002743 VG_(debugLog)(1, "main", "Initialise signal management\n");
nethercote71980f02004-01-24 18:18:54 +00002744 VG_(sigstartup_actions)();
2745
2746 //--------------------------------------------------------------
2747 // Perhaps we're profiling Valgrind?
2748 // p: process_cmd_line_options() [for VG_(clo_profile)]
2749 // p: others?
2750 //
2751 // XXX: this seems to be broken? It always says the tool wasn't built
2752 // for profiling; vg_profile.c's functions don't seem to be overriding
2753 // vg_dummy_profile.c's?
2754 //
2755 // XXX: want this as early as possible. Looking for --profile
2756 // in pre_process_cmd_line_options() could get it earlier.
2757 //--------------------------------------------------------------
2758 if (VG_(clo_profile))
njn31066fd2005-03-26 00:42:02 +00002759 VG_(init_profiling)();
nethercote71980f02004-01-24 18:18:54 +00002760
2761 VGP_PUSHCC(VgpStartup);
2762
2763 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002764 // Read suppression file
2765 // p: process_cmd_line_options() [for VG_(clo_suppressions)]
2766 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002767 if (VG_(needs).core_errors || VG_(needs).tool_errors) {
2768 VG_(debugLog)(1, "main", "Load suppressions\n");
nethercote71980f02004-01-24 18:18:54 +00002769 VG_(load_suppressions)();
sewardj1fbc1a52005-04-25 02:05:54 +00002770 }
nethercote71980f02004-01-24 18:18:54 +00002771
2772 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002773 // Initialise translation table and translation cache
2774 // p: read_procselfmaps [so the anonymous mmaps for the TT/TC
2775 // aren't identified as part of the client, which would waste
2776 // > 20M of virtual address space.]
2777 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002778 VG_(debugLog)(1, "main", "Initialise TT/TC\n");
nethercote71980f02004-01-24 18:18:54 +00002779 VG_(init_tt_tc)();
2780
2781 //--------------------------------------------------------------
sewardjb9bce632005-06-21 01:41:34 +00002782 // Initialise the redirect table.
sewardjb5d320c2005-03-13 18:57:15 +00002783 // p: parse_procselfmaps? [XXX for debug info?]
2784 // p: init_tt_tc [so it can call VG_(search_transtab) safely]
2785 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002786 VG_(debugLog)(1, "main", "Initialise redirects\n");
sewardjb5d320c2005-03-13 18:57:15 +00002787 VG_(setup_code_redirect_table)();
2788
2789 //--------------------------------------------------------------
sewardjb9bce632005-06-21 01:41:34 +00002790 // Tell the tool about permissions in our handwritten assembly
2791 // helpers.
2792 // p: init tool [for 'new_mem_startup']
2793 //--------------------------------------------------------------
2794 VG_(debugLog)(1, "main", "Tell tool about permissions for asm helpers\n");
2795 VG_TRACK( new_mem_startup,
2796 (Addr)&VG_(trampoline_stuff_start),
2797 &VG_(trampoline_stuff_end) - &VG_(trampoline_stuff_start),
2798 False, /* readable? */
2799 False, /* writable? */
2800 True /* executable? */ );
2801
2802 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002803 // Verbosity message
2804 // p: end_rdtsc_calibration [so startup message is printed first]
2805 //--------------------------------------------------------------
sewardj71bc3cb2005-05-19 00:25:45 +00002806 if (VG_(clo_verbosity) == 1 && !VG_(clo_xml))
nethercote71980f02004-01-24 18:18:54 +00002807 VG_(message)(Vg_UserMsg, "For more details, rerun with: -v");
2808 if (VG_(clo_verbosity) > 0)
2809 VG_(message)(Vg_UserMsg, "");
2810
2811 //--------------------------------------------------------------
2812 // Setup pointercheck
njn04e16982005-05-31 00:23:43 +00002813 // p: layout_remaining_space() [for VG_(client_{base,end})]
nethercote71980f02004-01-24 18:18:54 +00002814 // p: process_cmd_line_options() [for VG_(clo_pointercheck)]
2815 //--------------------------------------------------------------
nethercote775508a2004-09-07 22:38:23 +00002816 if (VG_(clo_pointercheck))
njn04e16982005-05-31 00:23:43 +00002817 VG_(clo_pointercheck) =
njnaf839f52005-06-23 03:27:57 +00002818 VG_(setup_pointercheck)( VG_(client_base), VG_(client_end));
nethercote71980f02004-01-24 18:18:54 +00002819
nethercote71980f02004-01-24 18:18:54 +00002820 //--------------------------------------------------------------
rjwalsh0140af52005-06-04 20:42:33 +00002821 // register client stack
2822 //--------------------------------------------------------------
njn945ed2e2005-06-24 03:28:30 +00002823 VG_(clstk_id) = VG_(register_stack)(VG_(clstk_base), VG_(clstk_end));
rjwalsh0140af52005-06-04 20:42:33 +00002824
2825 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002826 // Run!
2827 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002828 VGP_POPCC(VgpStartup);
nethercote71980f02004-01-24 18:18:54 +00002829
sewardj71bc3cb2005-05-19 00:25:45 +00002830 if (VG_(clo_xml)) {
sewardj68cde6f2005-07-19 12:17:51 +00002831 HChar buf[50];
2832 VG_(ctime)(buf);
sewardj753673f2005-08-09 22:03:08 +00002833 VG_(message)(Vg_UserMsg, "<status>\n"
2834 " <state>RUNNING</state>\n"
2835 " <time>%t</time>\n"
2836 "</status>",
2837 buf);
sewardj71bc3cb2005-05-19 00:25:45 +00002838 VG_(message)(Vg_UserMsg, "");
2839 }
2840
sewardj1fbc1a52005-04-25 02:05:54 +00002841 VG_(debugLog)(1, "main", "Running thread 1\n");
sewardj1d887112005-05-30 21:44:08 +00002842 /* As a result of the following call, the last thread standing
2843 eventually winds up running VG_(shutdown_actions_NORETURN) just
2844 below. */
njnaf839f52005-06-23 03:27:57 +00002845 VG_(main_thread_wrapper_NORETURN)(1);
nethercote71980f02004-01-24 18:18:54 +00002846
sewardj1d887112005-05-30 21:44:08 +00002847 /*NOTREACHED*/
2848 vg_assert(0);
sewardjb5f6f512005-03-10 23:59:00 +00002849}
2850
2851
njn9cb54ac2005-06-12 04:19:17 +00002852/* Final clean-up before terminating the process.
2853 Clean up the client by calling __libc_freeres() (if requested)
2854 This is Linux-specific?
2855*/
2856static void final_tidyup(ThreadId tid)
2857{
njnbc6d84d2005-06-19 18:58:03 +00002858 Addr __libc_freeres_wrapper;
2859
njn9cb54ac2005-06-12 04:19:17 +00002860 vg_assert(VG_(is_running_thread)(tid));
2861
njnbc6d84d2005-06-19 18:58:03 +00002862 if ( !VG_(needs).libc_freeres ||
2863 !VG_(clo_run_libc_freeres) ||
2864 0 == (__libc_freeres_wrapper = VG_(get_libc_freeres_wrapper)()) )
njn9cb54ac2005-06-12 04:19:17 +00002865 return; /* can't/won't do it */
2866
2867 if (VG_(clo_verbosity) > 2 ||
2868 VG_(clo_trace_syscalls) ||
2869 VG_(clo_trace_sched))
2870 VG_(message)(Vg_DebugMsg,
2871 "Caught __NR_exit; running __libc_freeres()");
2872
2873 /* point thread context to point to libc_freeres_wrapper */
njnf536bbb2005-06-13 04:21:38 +00002874 VG_(set_IP)(tid, __libc_freeres_wrapper);
njn9cb54ac2005-06-12 04:19:17 +00002875 // XXX should we use a special stack?
2876
2877 /* Block all blockable signals by copying the real block state into
2878 the thread's block state*/
2879 VG_(sigprocmask)(VKI_SIG_BLOCK, NULL, &VG_(threads)[tid].sig_mask);
2880 VG_(threads)[tid].tmp_sig_mask = VG_(threads)[tid].sig_mask;
2881
2882 /* and restore handlers to default */
2883 VG_(set_default_handler)(VKI_SIGSEGV);
2884 VG_(set_default_handler)(VKI_SIGBUS);
2885 VG_(set_default_handler)(VKI_SIGILL);
2886 VG_(set_default_handler)(VKI_SIGFPE);
2887
2888 // We were exiting, so assert that...
2889 vg_assert(VG_(is_exiting)(tid));
2890 // ...but now we're not again
2891 VG_(threads)[tid].exitreason = VgSrc_None;
2892
2893 // run until client thread exits - ideally with LIBC_FREERES_DONE,
2894 // but exit/exitgroup/signal will do
2895 VG_(scheduler)(tid);
2896
2897 vg_assert(VG_(is_exiting)(tid));
2898}
2899
sewardjb5f6f512005-03-10 23:59:00 +00002900/* Do everything which needs doing when the last thread exits */
sewardj1d887112005-05-30 21:44:08 +00002901void VG_(shutdown_actions_NORETURN) ( ThreadId tid,
2902 VgSchedReturnCode tids_schedretcode )
sewardjb5f6f512005-03-10 23:59:00 +00002903{
sewardj1d887112005-05-30 21:44:08 +00002904 VG_(debugLog)(1, "main", "entering VG_(shutdown_actions_NORETURN)\n");
2905
2906 vg_assert( VG_(count_living_threads)() == 1 );
sewardjb5f6f512005-03-10 23:59:00 +00002907 vg_assert(VG_(is_running_thread)(tid));
2908
2909 // Wait for all other threads to exit.
njn7b85dd52005-06-12 17:26:29 +00002910 VG_(reap_threads)(tid);
sewardjb5f6f512005-03-10 23:59:00 +00002911
2912 VG_(clo_model_pthreads) = False;
2913
2914 // Clean the client up before the final report
njn9cb54ac2005-06-12 04:19:17 +00002915 final_tidyup(tid);
sewardjb5f6f512005-03-10 23:59:00 +00002916
2917 // OK, done
2918 VG_(exit_thread)(tid);
2919
2920 /* should be no threads left */
2921 vg_assert(VG_(count_living_threads)() == 0);
2922
2923 VG_(threads)[tid].status = VgTs_Empty;
nethercote71980f02004-01-24 18:18:54 +00002924 //--------------------------------------------------------------
2925 // Finalisation: cleanup, messages, etc. Order no so important, only
2926 // affects what order the messages come.
2927 //--------------------------------------------------------------
2928 if (VG_(clo_verbosity) > 0)
2929 VG_(message)(Vg_UserMsg, "");
2930
sewardj71bc3cb2005-05-19 00:25:45 +00002931 if (VG_(clo_xml)) {
sewardj68cde6f2005-07-19 12:17:51 +00002932 HChar buf[50];
sewardj9f297ca2005-05-20 02:29:52 +00002933 if (VG_(needs).core_errors || VG_(needs).tool_errors) {
2934 VG_(show_error_counts_as_XML)();
2935 VG_(message)(Vg_UserMsg, "");
2936 }
sewardj68cde6f2005-07-19 12:17:51 +00002937 VG_(ctime)(buf);
sewardj753673f2005-08-09 22:03:08 +00002938 VG_(message)(Vg_UserMsg, "<status>\n"
2939 " <state>FINISHED</state>\n"
2940 " <time>%t</time>\n"
2941 "</status>",
2942 buf);
sewardj71bc3cb2005-05-19 00:25:45 +00002943 VG_(message)(Vg_UserMsg, "");
2944 }
2945
nethercote71980f02004-01-24 18:18:54 +00002946 /* Print out file descriptor summary and stats. */
2947 if (VG_(clo_track_fds))
nethercote3a42fb82004-08-03 18:08:50 +00002948 VG_(show_open_fds)();
nethercote71980f02004-01-24 18:18:54 +00002949
njn95ec8702004-11-22 16:46:13 +00002950 if (VG_(needs).core_errors || VG_(needs).tool_errors)
nethercote71980f02004-01-24 18:18:54 +00002951 VG_(show_all_errors)();
2952
njn51d827b2005-05-09 01:02:08 +00002953 VG_TDICT_CALL(tool_fini, 0/*exitcode*/);
nethercote71980f02004-01-24 18:18:54 +00002954
sewardj71bc3cb2005-05-19 00:25:45 +00002955 if (VG_(clo_xml)) {
2956 VG_(message)(Vg_UserMsg, "");
2957 VG_(message)(Vg_UserMsg, "</valgrindoutput>");
2958 VG_(message)(Vg_UserMsg, "");
2959 }
2960
nethercote885dd912004-08-03 23:14:00 +00002961 VG_(sanity_check_general)( True /*include expensive checks*/ );
nethercote71980f02004-01-24 18:18:54 +00002962
2963 if (VG_(clo_verbosity) > 1)
nethercote3a42fb82004-08-03 18:08:50 +00002964 print_all_stats();
nethercote71980f02004-01-24 18:18:54 +00002965
nethercote71980f02004-01-24 18:18:54 +00002966 if (VG_(clo_profile))
njn31066fd2005-03-26 00:42:02 +00002967 VG_(done_profiling)();
njn2025cf92005-06-26 20:44:48 +00002968
2969 if (VG_(clo_profile_flags) > 0) {
2970 #define N_MAX 100
2971 BBProfEntry tops[N_MAX];
2972 ULong score_total = VG_(get_BB_profile) (tops, N_MAX);
2973 show_BB_profile(tops, N_MAX, score_total);
2974 }
sewardjfa8ec112005-01-19 11:55:34 +00002975
sewardj8b635a42004-11-22 19:01:47 +00002976 /* Print Vex storage stats */
sewardjbf426512005-01-17 18:35:30 +00002977 if (0)
2978 LibVEX_ShowAllocStats();
sewardj1d887112005-05-30 21:44:08 +00002979
njn8aa35852005-06-10 22:59:56 +00002980 /* Ok, finally exit in the os-specific way, according to the scheduler's
2981 return code. In short, if the (last) thread exited by calling
2982 sys_exit, do likewise; if the (last) thread stopped due to a fatal
2983 signal, terminate the entire system with that same fatal signal. */
2984 VG_(debugLog)(1, "core_os",
njn7b85dd52005-06-12 17:26:29 +00002985 "VG_(terminate_NORETURN)(tid=%lld)\n", (ULong)tid);
njn8aa35852005-06-10 22:59:56 +00002986
2987 vg_assert(VG_(count_living_threads)() == 0);
2988
2989 switch (tids_schedretcode) {
2990 case VgSrc_ExitSyscall: /* the normal way out */
2991 VG_(exit)( VG_(threads)[tid].os_state.exitcode );
2992 /* NOT ALIVE HERE! */
2993 VG_(core_panic)("entered the afterlife in main() -- ExitSyscall");
2994 break; /* what the hell :) */
2995
2996 case VgSrc_FatalSig:
2997 /* We were killed by a fatal signal, so replicate the effect */
2998 vg_assert(VG_(threads)[tid].os_state.fatalsig != 0);
2999 VG_(kill_self)(VG_(threads)[tid].os_state.fatalsig);
3000 VG_(core_panic)("main(): signal was supposed to be fatal");
3001 break;
3002
3003 default:
3004 VG_(core_panic)("main(): unexpected scheduler return code");
3005 }
njne96be672005-05-08 19:08:54 +00003006}
sewardj8b635a42004-11-22 19:01:47 +00003007
sewardjde4a1d02002-03-22 01:27:54 +00003008/*--------------------------------------------------------------------*/
njn04e16982005-05-31 00:23:43 +00003009/*--- end ---*/
sewardjde4a1d02002-03-22 01:27:54 +00003010/*--------------------------------------------------------------------*/