blob: b417e9cd73e3c6d4e16ecbd5d44904e05e862428 [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;
sewardj10f08cf2005-06-29 10:16:14 +0000182# endif
cerion85665ca2005-06-20 15:51:07 +0000183
nethercote7f390022004-10-25 17:18:24 +0000184 case AT_PHDR:
njn13bfd852005-06-02 03:52:53 +0000185 VG_(valgrind_base) = VG_PGROUNDDN(auxv->u.a_val);
nethercote7f390022004-10-25 17:18:24 +0000186 break;
cerion85665ca2005-06-20 15:51:07 +0000187
sewardj10f08cf2005-06-29 10:16:14 +0000188 default:
189 break;
nethercote71980f02004-01-24 18:18:54 +0000190 }
191
nethercote361a14e2004-07-26 11:11:56 +0000192 if ( found != (1|2) ) {
193 fprintf(stderr, "valgrind: stage2 must be launched by stage1\n");
nethercote71980f02004-01-24 18:18:54 +0000194 exit(127);
195 }
nethercote31779c72004-07-30 21:50:15 +0000196 vg_assert(padfile >= 0);
197 return padfile;
nethercote71980f02004-01-24 18:18:54 +0000198}
199
200
201/*====================================================================*/
202/*=== Address space determination ===*/
203/*====================================================================*/
204
nethercote7f390022004-10-25 17:18:24 +0000205extern char _start[];
206
nethercote31779c72004-07-30 21:50:15 +0000207static void layout_remaining_space(Addr argc_addr, float ratio)
nethercote71980f02004-01-24 18:18:54 +0000208{
njn83407492005-06-19 16:10:47 +0000209 SysRes res;
210 Addr client_size, shadow_size;
nethercote71980f02004-01-24 18:18:54 +0000211
nethercote7f390022004-10-25 17:18:24 +0000212 // VG_(valgrind_base) should have been set by scan_auxv, but if not,
213 // this is a workable approximation
214 if (VG_(valgrind_base) == 0) {
njn13bfd852005-06-02 03:52:53 +0000215 VG_(valgrind_base) = VG_PGROUNDDN(&_start);
nethercote7f390022004-10-25 17:18:24 +0000216 }
217
njn13bfd852005-06-02 03:52:53 +0000218 VG_(valgrind_last) = VG_ROUNDUP(argc_addr, 0x10000) - 1; // stack
nethercote71980f02004-01-24 18:18:54 +0000219
nethercote31779c72004-07-30 21:50:15 +0000220 // This gives the client the largest possible address space while
221 // taking into account the tool's shadow needs.
njn13bfd852005-06-02 03:52:53 +0000222 client_size = VG_ROUNDDN((VG_(valgrind_base)-REDZONE_SIZE) / (1.+ratio),
nethercote71980f02004-01-24 18:18:54 +0000223 CLIENT_SIZE_MULTIPLE);
njn311c5d82005-05-15 21:03:42 +0000224 VG_(client_base) = 0;
nethercote71980f02004-01-24 18:18:54 +0000225 VG_(client_end) = VG_(client_base) + client_size;
nethercotee2097312004-06-27 12:29:56 +0000226 /* where !FIXED mmap goes */
nethercotebc7b4f42004-07-26 12:44:35 +0000227 VG_(client_mapbase) = VG_(client_base) +
njn13bfd852005-06-02 03:52:53 +0000228 VG_PGROUNDDN((Addr)(client_size * CLIENT_HEAP_PROPORTION));
nethercote71980f02004-01-24 18:18:54 +0000229
nethercote31779c72004-07-30 21:50:15 +0000230 VG_(shadow_base) = VG_(client_end) + REDZONE_SIZE;
nethercote410bfe62004-09-04 15:53:35 +0000231 VG_(shadow_end) = VG_(valgrind_base);
232 shadow_size = VG_(shadow_end) - VG_(shadow_base);
nethercote71980f02004-01-24 18:18:54 +0000233
nethercotee2097312004-06-27 12:29:56 +0000234#define SEGSIZE(a,b) ((VG_(b) - VG_(a))/(1024*1024))
235
nethercote71980f02004-01-24 18:18:54 +0000236 if (0)
nethercotee2097312004-06-27 12:29:56 +0000237 VG_(printf)(
tomb1d43182005-03-29 09:00:12 +0000238 "client_base %p (%dMB)\n"
239 "client_mapbase %p (%dMB)\n"
240 "client_end %p (%dMB)\n"
241 "shadow_base %p (%dMB)\n"
242 "shadow_end %p\n"
243 "valgrind_base %p (%dMB)\n"
244 "valgrind_last %p\n",
nethercotee2097312004-06-27 12:29:56 +0000245 VG_(client_base), SEGSIZE(client_base, client_mapbase),
246 VG_(client_mapbase), SEGSIZE(client_mapbase, client_end),
247 VG_(client_end), SEGSIZE(client_end, shadow_base),
248 VG_(shadow_base), SEGSIZE(shadow_base, shadow_end),
nethercote410bfe62004-09-04 15:53:35 +0000249 VG_(shadow_end),
nethercote820bd8c2004-09-07 23:04:49 +0000250 VG_(valgrind_base), SEGSIZE(valgrind_base, valgrind_last),
251 VG_(valgrind_last)
nethercotee2097312004-06-27 12:29:56 +0000252 );
253
254#undef SEGSIZE
nethercote71980f02004-01-24 18:18:54 +0000255
256 // Ban redzone
njn83407492005-06-19 16:10:47 +0000257 res = VG_(mmap_native)((void *)VG_(client_end), REDZONE_SIZE, VKI_PROT_NONE,
258 VKI_MAP_FIXED|VKI_MAP_ANONYMOUS|VKI_MAP_PRIVATE|VKI_MAP_NORESERVE,
259 -1, 0);
260 vg_assert(!res.isError);
nethercote71980f02004-01-24 18:18:54 +0000261
262 // Make client hole
njn83407492005-06-19 16:10:47 +0000263 res = VG_(munmap_native)((void*)VG_(client_base), client_size);
264 vg_assert(!res.isError);
nethercote71980f02004-01-24 18:18:54 +0000265
266 // Map shadow memory.
267 // Initially all inaccessible, incrementally initialized as it is used
nethercotee567e702004-07-10 17:49:17 +0000268 if (shadow_size != 0) {
njn83407492005-06-19 16:10:47 +0000269 res = VG_(mmap_native)((char *)VG_(shadow_base), shadow_size,
270 VKI_PROT_NONE,
271 VKI_MAP_PRIVATE|VKI_MAP_ANONYMOUS|VKI_MAP_FIXED|VKI_MAP_NORESERVE,
272 -1, 0);
273 if (res.isError) {
nethercoted4722622004-08-30 19:36:42 +0000274 fprintf(stderr,
nethercote8c1ce432004-10-08 14:01:14 +0000275 "valgrind: Could not allocate address space (%p bytes)\n"
276 "valgrind: for shadow memory\n"
277 "valgrind: Possible causes:\n"
278 "valgrind: - For some systems (especially under RedHat 8), Valgrind\n"
279 "valgrind: needs at least 1.5GB swap space.\n"
280 "valgrind: - Or, your virtual memory size may be limited (check\n"
281 "valgrind: with 'ulimit -v').\n"
282 "valgrind: - Or, your system may use a kernel that provides only a\n"
283 "valgrind: too-small (eg. 2GB) user address space.\n"
284 , (void*)shadow_size
285 );
nethercoted4722622004-08-30 19:36:42 +0000286 exit(1);
287 }
nethercotee567e702004-07-10 17:49:17 +0000288 }
nethercote71980f02004-01-24 18:18:54 +0000289}
290
291/*====================================================================*/
292/*=== Command line setup ===*/
293/*====================================================================*/
294
njndcc99d32005-06-19 15:34:59 +0000295// Note that we deliberately don't free the malloc'd memory. See comment
296// at call site.
nethercote71980f02004-01-24 18:18:54 +0000297static char* get_file_clo(char* dir)
298{
299# define FLEN 512
sewardj92645592005-07-23 09:18:34 +0000300 Int n;
301 SysRes fd;
njn909c3192005-06-19 15:46:27 +0000302 struct vki_stat s1;
sewardj92645592005-07-23 09:18:34 +0000303 Char* f_clo = NULL;
304 Char filename[FLEN];
nethercote71980f02004-01-24 18:18:54 +0000305
306 snprintf(filename, FLEN, "%s/.valgrindrc", ( NULL == dir ? "" : dir ) );
307 fd = VG_(open)(filename, 0, VKI_S_IRUSR);
sewardj92645592005-07-23 09:18:34 +0000308 if ( !fd.isError ) {
309 if ( 0 == VG_(fstat)(fd.val, &s1) ) {
nethercote71980f02004-01-24 18:18:54 +0000310 f_clo = malloc(s1.st_size+1);
311 vg_assert(f_clo);
sewardj92645592005-07-23 09:18:34 +0000312 n = VG_(read)(fd.val, f_clo, s1.st_size);
nethercote71980f02004-01-24 18:18:54 +0000313 if (n == -1) n = 0;
314 f_clo[n] = '\0';
315 }
sewardj92645592005-07-23 09:18:34 +0000316 VG_(close)(fd.val);
nethercote71980f02004-01-24 18:18:54 +0000317 }
318 return f_clo;
319# undef FLEN
320}
321
322static Int count_args(char* s)
323{
324 Int n = 0;
325 if (s) {
326 char* cp = s;
327 while (True) {
328 // We have alternating sequences: blanks, non-blanks, blanks...
329 // count the non-blanks sequences.
njn0c0f32a2005-03-26 04:14:01 +0000330 while ( VG_(isspace)(*cp) ) cp++;
nethercote71980f02004-01-24 18:18:54 +0000331 if ( !*cp ) break;
332 n++;
njn0c0f32a2005-03-26 04:14:01 +0000333 while ( !VG_(isspace)(*cp) && *cp ) cp++;
nethercote71980f02004-01-24 18:18:54 +0000334 }
335 }
336 return n;
337}
338
njndcc99d32005-06-19 15:34:59 +0000339// Add args out of environment, skipping multiple spaces and "--" args.
340// We split 's' into multiple strings by replacing whitespace with nuls,
341// eg. "--aa --bb --cc" --> "--aa\0--bb\0--cc". And for each new string
342// carved out of 's', we put a pointer to it in 'to'.
nethercote71980f02004-01-24 18:18:54 +0000343static char** copy_args( char* s, char** to )
344{
345 if (s) {
346 char* cp = s;
347 while (True) {
348 // We have alternating sequences: blanks, non-blanks, blanks...
349 // copy the non-blanks sequences, and add terminating '\0'
njn0c0f32a2005-03-26 04:14:01 +0000350 while ( VG_(isspace)(*cp) ) cp++;
nethercote71980f02004-01-24 18:18:54 +0000351 if ( !*cp ) break;
352 *to++ = cp;
njn0c0f32a2005-03-26 04:14:01 +0000353 while ( !VG_(isspace)(*cp) && *cp ) cp++;
njndcc99d32005-06-19 15:34:59 +0000354 if ( *cp ) *cp++ = '\0'; // terminate if not the last
nethercote71980f02004-01-24 18:18:54 +0000355 if (VG_STREQ(to[-1], "--")) to--; // undo any '--' arg
356 }
357 }
358 return to;
359}
360
361// Augment command line with arguments from environment and .valgrindrc
362// files.
363static void augment_command_line(Int* vg_argc_inout, char*** vg_argv_inout)
364{
nethercotef6a1d502004-08-09 12:21:57 +0000365 int vg_argc0 = *vg_argc_inout;
366 char** vg_argv0 = *vg_argv_inout;
nethercote71980f02004-01-24 18:18:54 +0000367
njndcc99d32005-06-19 15:34:59 +0000368 // get_file_clo() allocates the return value with malloc(). We do not
369 // free f1_clo and f2_clo as they get put into vg_argv[] which must persist.
nethercote71980f02004-01-24 18:18:54 +0000370 char* env_clo = getenv(VALGRINDOPTS);
371 char* f1_clo = get_file_clo( getenv("HOME") );
372 char* f2_clo = get_file_clo(".");
373
374 /* copy any extra args from file or environment, if present */
375 if ( (env_clo && *env_clo) || (f1_clo && *f1_clo) || (f2_clo && *f2_clo) ) {
376 /* ' ' separated extra options */
377 char **from;
378 char **to;
thughescaca0022004-09-13 10:20:34 +0000379 int orig_arg_count, env_arg_count, f1_arg_count, f2_arg_count;
380
381 for ( orig_arg_count = 0; vg_argv0[orig_arg_count]; orig_arg_count++ );
382
nethercote71980f02004-01-24 18:18:54 +0000383 env_arg_count = count_args(env_clo);
384 f1_arg_count = count_args(f1_clo);
385 f2_arg_count = count_args(f2_clo);
386
387 if (0)
388 printf("extra-argc=%d %d %d\n",
389 env_arg_count, f1_arg_count, f2_arg_count);
390
391 /* +2: +1 for null-termination, +1 for added '--' */
nethercotef6a1d502004-08-09 12:21:57 +0000392 from = vg_argv0;
thughescaca0022004-09-13 10:20:34 +0000393 vg_argv0 = malloc( (orig_arg_count + env_arg_count + f1_arg_count
nethercote71980f02004-01-24 18:18:54 +0000394 + f2_arg_count + 2) * sizeof(char **));
nethercotef6a1d502004-08-09 12:21:57 +0000395 vg_assert(vg_argv0);
396 to = vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000397
398 /* copy argv[0] */
399 *to++ = *from++;
400
401 /* Copy extra args from env var and file, in the order: ~/.valgrindrc,
402 * $VALGRIND_OPTS, ./.valgrindrc -- more local options are put later
403 * to override less local ones. */
404 to = copy_args(f1_clo, to);
405 to = copy_args(env_clo, to);
406 to = copy_args(f2_clo, to);
njna96e15a2005-05-24 21:36:32 +0000407
nethercote71980f02004-01-24 18:18:54 +0000408 /* copy original arguments, stopping at command or -- */
409 while (*from) {
410 if (**from != '-')
411 break;
412 if (VG_STREQ(*from, "--")) {
413 from++; /* skip -- */
414 break;
415 }
416 *to++ = *from++;
417 }
418
419 /* add -- */
420 *to++ = "--";
421
nethercotef6a1d502004-08-09 12:21:57 +0000422 vg_argc0 = to - vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000423
424 /* copy rest of original command line, then NULL */
425 while (*from) *to++ = *from++;
426 *to = NULL;
427 }
428
nethercotef6a1d502004-08-09 12:21:57 +0000429 *vg_argc_inout = vg_argc0;
430 *vg_argv_inout = vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000431}
432
nethercotef6a1d502004-08-09 12:21:57 +0000433#define VG_CLO_SEP '\01'
434
nethercote71980f02004-01-24 18:18:54 +0000435static void get_command_line( int argc, char** argv,
436 Int* vg_argc_out, Char*** vg_argv_out,
437 char*** cl_argv_out )
438{
nethercotef6a1d502004-08-09 12:21:57 +0000439 int vg_argc0;
440 char** vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000441 char** cl_argv;
442 char* env_clo = getenv(VALGRINDCLO);
443
444 if (env_clo != NULL && *env_clo != '\0') {
445 char *cp;
446 char **cpp;
447
nethercotef6a1d502004-08-09 12:21:57 +0000448 /* OK, VALGRINDCLO is set, which means we must be a child of another
449 Valgrind process using --trace-children, so we're getting all our
450 arguments from VALGRINDCLO, and the entire command line belongs to
451 the client (including argv[0]) */
452 vg_argc0 = 1; /* argv[0] */
nethercote71980f02004-01-24 18:18:54 +0000453 for (cp = env_clo; *cp; cp++)
nethercotef6a1d502004-08-09 12:21:57 +0000454 if (*cp == VG_CLO_SEP)
455 vg_argc0++;
nethercote71980f02004-01-24 18:18:54 +0000456
nethercotef6a1d502004-08-09 12:21:57 +0000457 vg_argv0 = malloc(sizeof(char **) * (vg_argc0 + 1));
458 vg_assert(vg_argv0);
nethercote71980f02004-01-24 18:18:54 +0000459
nethercotef6a1d502004-08-09 12:21:57 +0000460 cpp = vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000461
462 *cpp++ = "valgrind"; /* nominal argv[0] */
463 *cpp++ = env_clo;
464
nethercotef6a1d502004-08-09 12:21:57 +0000465 // Replace the VG_CLO_SEP args separator with '\0'
nethercote71980f02004-01-24 18:18:54 +0000466 for (cp = env_clo; *cp; cp++) {
nethercotef6a1d502004-08-09 12:21:57 +0000467 if (*cp == VG_CLO_SEP) {
nethercote71980f02004-01-24 18:18:54 +0000468 *cp++ = '\0'; /* chop it up in place */
469 *cpp++ = cp;
470 }
471 }
472 *cpp = NULL;
473 cl_argv = argv;
474
475 } else {
sewardjb5f6f512005-03-10 23:59:00 +0000476 Bool noaugment = False;
477
nethercote71980f02004-01-24 18:18:54 +0000478 /* Count the arguments on the command line. */
nethercotef6a1d502004-08-09 12:21:57 +0000479 vg_argv0 = argv;
nethercote71980f02004-01-24 18:18:54 +0000480
nethercotef6a1d502004-08-09 12:21:57 +0000481 for (vg_argc0 = 1; vg_argc0 < argc; vg_argc0++) {
sewardjb5f6f512005-03-10 23:59:00 +0000482 Char* arg = argv[vg_argc0];
483 if (arg[0] != '-') /* exe name */
nethercote71980f02004-01-24 18:18:54 +0000484 break;
sewardjb5f6f512005-03-10 23:59:00 +0000485 if (VG_STREQ(arg, "--")) { /* dummy arg */
nethercotef6a1d502004-08-09 12:21:57 +0000486 vg_argc0++;
nethercote71980f02004-01-24 18:18:54 +0000487 break;
488 }
njn45270a22005-03-27 01:00:11 +0000489 VG_BOOL_CLO(arg, "--command-line-only", noaugment)
nethercote71980f02004-01-24 18:18:54 +0000490 }
nethercotef6a1d502004-08-09 12:21:57 +0000491 cl_argv = &argv[vg_argc0];
nethercote71980f02004-01-24 18:18:54 +0000492
493 /* Get extra args from VALGRIND_OPTS and .valgrindrc files.
nethercotef6a1d502004-08-09 12:21:57 +0000494 Note we don't do this if getting args from VALGRINDCLO, as
sewardjb5f6f512005-03-10 23:59:00 +0000495 those extra args will already be present in VALGRINDCLO.
496 (We also don't do it when --command-line-only=yes.) */
497 if (!noaugment)
498 augment_command_line(&vg_argc0, &vg_argv0);
nethercote71980f02004-01-24 18:18:54 +0000499 }
500
501 if (0) {
502 Int i;
nethercotef6a1d502004-08-09 12:21:57 +0000503 for (i = 0; i < vg_argc0; i++)
504 printf("vg_argv0[%d]=\"%s\"\n", i, vg_argv0[i]);
nethercote71980f02004-01-24 18:18:54 +0000505 }
506
nethercotef6a1d502004-08-09 12:21:57 +0000507 *vg_argc_out = vg_argc0;
508 *vg_argv_out = (Char**)vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000509 *cl_argv_out = cl_argv;
510}
511
512
513/*====================================================================*/
514/*=== Environment and stack setup ===*/
515/*====================================================================*/
516
517/* Scan a colon-separated list, and call a function on each element.
518 The string must be mutable, because we insert a temporary '\0', but
thughes4ad52d02004-06-27 17:37:21 +0000519 the string will end up unmodified. (*func) should return True if it
nethercote71980f02004-01-24 18:18:54 +0000520 doesn't need to see any more.
thughes4ad52d02004-06-27 17:37:21 +0000521
522 This routine will return True if (*func) returns True and False if
523 it reaches the end of the list without that happening.
nethercote71980f02004-01-24 18:18:54 +0000524*/
thughes4ad52d02004-06-27 17:37:21 +0000525static Bool scan_colsep(char *colsep, Bool (*func)(const char *))
nethercote71980f02004-01-24 18:18:54 +0000526{
527 char *cp, *entry;
528 int end;
529
530 if (colsep == NULL ||
531 *colsep == '\0')
thughes4ad52d02004-06-27 17:37:21 +0000532 return False;
nethercote71980f02004-01-24 18:18:54 +0000533
534 entry = cp = colsep;
535
536 do {
537 end = (*cp == '\0');
538
539 if (*cp == ':' || *cp == '\0') {
540 char save = *cp;
541
542 *cp = '\0';
thughes21942d92004-07-12 09:35:37 +0000543 if ((*func)(entry)) {
544 *cp = save;
thughes4ad52d02004-06-27 17:37:21 +0000545 return True;
thughes21942d92004-07-12 09:35:37 +0000546 }
nethercote71980f02004-01-24 18:18:54 +0000547 *cp = save;
548 entry = cp+1;
549 }
550 cp++;
551 } while(!end);
thughes4ad52d02004-06-27 17:37:21 +0000552
553 return False;
554}
555
nethercote71980f02004-01-24 18:18:54 +0000556/* Prepare the client's environment. This is basically a copy of our
557 environment, except:
njn16eeb4e2005-06-16 03:56:58 +0000558 LD_PRELOAD=$VALGRINDLIB/vg_preload_core.so:($VALGRINDLIB/vgpreload_TOOL.so:)?$LD_PRELOAD
nethercote71980f02004-01-24 18:18:54 +0000559
sewardjb5f6f512005-03-10 23:59:00 +0000560 If this is missing, then it is added.
nethercote71980f02004-01-24 18:18:54 +0000561
562 Yummy. String hacking in C.
563
564 If this needs to handle any more variables it should be hacked
565 into something table driven.
566 */
567static char **fix_environment(char **origenv, const char *preload)
568{
njn16eeb4e2005-06-16 03:56:58 +0000569 static const char preload_core_so[] = "vg_preload_core.so";
nethercote71980f02004-01-24 18:18:54 +0000570 static const char ld_preload[] = "LD_PRELOAD=";
571 static const char valgrind_clo[] = VALGRINDCLO "=";
nethercote71980f02004-01-24 18:18:54 +0000572 static const int ld_preload_len = sizeof(ld_preload)-1;
573 static const int valgrind_clo_len = sizeof(valgrind_clo)-1;
574 int ld_preload_done = 0;
njn16eeb4e2005-06-16 03:56:58 +0000575 char *preload_core_path;
576 int preload_core_path_len;
nethercote71980f02004-01-24 18:18:54 +0000577 int vgliblen = strlen(VG_(libdir));
578 char **cpp;
579 char **ret;
580 int envc;
581 const int preloadlen = (preload == NULL) ? 0 : strlen(preload);
582
njn16eeb4e2005-06-16 03:56:58 +0000583 /* Find the vg_preload_core.so; also make room for the tool preload
nethercote71980f02004-01-24 18:18:54 +0000584 library */
njn16eeb4e2005-06-16 03:56:58 +0000585 preload_core_path_len = sizeof(preload_core_so) + vgliblen + preloadlen + 16;
586 preload_core_path = malloc(preload_core_path_len);
587 vg_assert(preload_core_path);
nethercote71980f02004-01-24 18:18:54 +0000588
589 if (preload)
njn16eeb4e2005-06-16 03:56:58 +0000590 snprintf(preload_core_path, preload_core_path_len, "%s/%s:%s",
591 VG_(libdir), preload_core_so, preload);
nethercote71980f02004-01-24 18:18:54 +0000592 else
njn16eeb4e2005-06-16 03:56:58 +0000593 snprintf(preload_core_path, preload_core_path_len, "%s/%s",
594 VG_(libdir), preload_core_so);
nethercote71980f02004-01-24 18:18:54 +0000595
596 /* Count the original size of the env */
597 envc = 0; /* trailing NULL */
598 for (cpp = origenv; cpp && *cpp; cpp++)
599 envc++;
600
601 /* Allocate a new space */
sewardjb5f6f512005-03-10 23:59:00 +0000602 ret = malloc(sizeof(char *) * (envc+1+1)); /* 1 new entry + NULL */
nethercote7c018f42004-07-17 16:40:50 +0000603 vg_assert(ret);
nethercote71980f02004-01-24 18:18:54 +0000604
605 /* copy it over */
606 for (cpp = ret; *origenv; )
607 *cpp++ = *origenv++;
608 *cpp = NULL;
609
610 vg_assert(envc == (cpp - ret));
611
612 /* Walk over the new environment, mashing as we go */
613 for (cpp = ret; cpp && *cpp; cpp++) {
sewardjb5f6f512005-03-10 23:59:00 +0000614 if (memcmp(*cpp, ld_preload, ld_preload_len) == 0) {
njn16eeb4e2005-06-16 03:56:58 +0000615 int len = strlen(*cpp) + preload_core_path_len;
nethercote71980f02004-01-24 18:18:54 +0000616 char *cp = malloc(len);
nethercote7c018f42004-07-17 16:40:50 +0000617 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000618
619 snprintf(cp, len, "%s%s:%s",
njn16eeb4e2005-06-16 03:56:58 +0000620 ld_preload, preload_core_path, (*cpp)+ld_preload_len);
nethercote71980f02004-01-24 18:18:54 +0000621
622 *cpp = cp;
623
624 ld_preload_done = 1;
625 } else if (memcmp(*cpp, valgrind_clo, valgrind_clo_len) == 0) {
626 *cpp = "";
627 }
628 }
629
630 /* Add the missing bits */
nethercote71980f02004-01-24 18:18:54 +0000631 if (!ld_preload_done) {
njn16eeb4e2005-06-16 03:56:58 +0000632 int len = ld_preload_len + preload_core_path_len;
nethercote71980f02004-01-24 18:18:54 +0000633 char *cp = malloc(len);
nethercote7c018f42004-07-17 16:40:50 +0000634 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000635
njn16eeb4e2005-06-16 03:56:58 +0000636 snprintf(cp, len, "%s%s", ld_preload, preload_core_path);
nethercote71980f02004-01-24 18:18:54 +0000637
638 ret[envc++] = cp;
639 }
640
njn16eeb4e2005-06-16 03:56:58 +0000641 free(preload_core_path);
nethercote71980f02004-01-24 18:18:54 +0000642 ret[envc] = NULL;
643
644 return ret;
645}
646
647extern char **environ; /* our environment */
nethercote71980f02004-01-24 18:18:54 +0000648
649/* Add a string onto the string table, and return its address */
650static char *copy_str(char **tab, const char *str)
651{
652 char *cp = *tab;
653 char *orig = cp;
654
655 while(*str)
656 *cp++ = *str++;
657 *cp++ = '\0';
658
659 if (0)
nethercote545fe672004-11-01 16:52:43 +0000660 printf("copied %p \"%s\" len %lld\n", orig, orig, (Long)(cp-orig));
nethercote71980f02004-01-24 18:18:54 +0000661
662 *tab = cp;
663
664 return orig;
665}
666
667/*
668 This sets up the client's initial stack, containing the args,
669 environment and aux vector.
670
671 The format of the stack is:
672
673 higher address +-----------------+
674 | Trampoline code |
675 +-----------------+
676 | |
677 : string table :
678 | |
679 +-----------------+
680 | AT_NULL |
681 - -
682 | auxv |
683 +-----------------+
684 | NULL |
685 - -
686 | envp |
687 +-----------------+
688 | NULL |
689 - -
690 | argv |
691 +-----------------+
692 | argc |
nethercote4ad74312004-10-26 09:59:49 +0000693 lower address +-----------------+ <- sp
nethercote71980f02004-01-24 18:18:54 +0000694 | undefined |
695 : :
696 */
nethercotec25c4492004-10-18 11:52:17 +0000697static Addr setup_client_stack(void* init_sp,
698 char **orig_argv, char **orig_envp,
nethercote71980f02004-01-24 18:18:54 +0000699 const struct exeinfo *info,
700 UInt** client_auxv)
701{
njn83407492005-06-19 16:10:47 +0000702 SysRes res;
nethercote71980f02004-01-24 18:18:54 +0000703 char **cpp;
704 char *strtab; /* string table */
705 char *stringbase;
nethercotea3c3cf22004-11-01 18:38:00 +0000706 Addr *ptr;
nethercote71980f02004-01-24 18:18:54 +0000707 struct ume_auxv *auxv;
708 const struct ume_auxv *orig_auxv;
709 const struct ume_auxv *cauxv;
710 unsigned stringsize; /* total size of strings in bytes */
711 unsigned auxsize; /* total size of auxv in bytes */
712 int argc; /* total argc */
713 int envc; /* total number of env vars */
714 unsigned stacksize; /* total client stack size */
nethercotea3c3cf22004-11-01 18:38:00 +0000715 Addr cl_esp; /* client stack base (initial esp) */
nethercote71980f02004-01-24 18:18:54 +0000716
717 /* use our own auxv as a prototype */
njn62ff0f22005-06-21 23:03:36 +0000718 orig_auxv = VG_(find_auxv)(init_sp);
nethercote71980f02004-01-24 18:18:54 +0000719
720 /* ==================== compute sizes ==================== */
721
722 /* first of all, work out how big the client stack will be */
723 stringsize = 0;
724
725 /* paste on the extra args if the loader needs them (ie, the #!
726 interpreter and its argument) */
727 argc = 0;
nethercoted6a56872004-07-26 15:32:47 +0000728 if (info->interp_name != NULL) {
nethercote71980f02004-01-24 18:18:54 +0000729 argc++;
nethercoted6a56872004-07-26 15:32:47 +0000730 stringsize += strlen(info->interp_name) + 1;
nethercote71980f02004-01-24 18:18:54 +0000731 }
nethercoted6a56872004-07-26 15:32:47 +0000732 if (info->interp_args != NULL) {
nethercote71980f02004-01-24 18:18:54 +0000733 argc++;
nethercoted6a56872004-07-26 15:32:47 +0000734 stringsize += strlen(info->interp_args) + 1;
nethercote71980f02004-01-24 18:18:54 +0000735 }
736
737 /* now scan the args we're given... */
738 for (cpp = orig_argv; *cpp; cpp++) {
739 argc++;
740 stringsize += strlen(*cpp) + 1;
741 }
742
743 /* ...and the environment */
744 envc = 0;
745 for (cpp = orig_envp; cpp && *cpp; cpp++) {
746 envc++;
747 stringsize += strlen(*cpp) + 1;
748 }
749
750 /* now, how big is the auxv? */
751 auxsize = sizeof(*auxv); /* there's always at least one entry: AT_NULL */
752 for (cauxv = orig_auxv; cauxv->a_type != AT_NULL; cauxv++) {
753 if (cauxv->a_type == AT_PLATFORM)
754 stringsize += strlen(cauxv->u.a_ptr) + 1;
755 auxsize += sizeof(*cauxv);
756 }
757
cerion85665ca2005-06-20 15:51:07 +0000758#if defined(VGP_ppc32_linux)
759 auxsize += 2 * sizeof(*cauxv);
760#endif
761
nethercote71980f02004-01-24 18:18:54 +0000762 /* OK, now we know how big the client stack is */
763 stacksize =
sewardj9d9cdea2005-03-23 03:06:30 +0000764 sizeof(Word) + /* argc */
nethercote71980f02004-01-24 18:18:54 +0000765 sizeof(char **)*argc + /* argv */
766 sizeof(char **) + /* terminal NULL */
767 sizeof(char **)*envc + /* envp */
768 sizeof(char **) + /* terminal NULL */
769 auxsize + /* auxv */
njn13bfd852005-06-02 03:52:53 +0000770 VG_ROUNDUP(stringsize, sizeof(Word)) +/* strings (aligned) */
nethercote5fd72bb2004-11-04 19:28:38 +0000771 VKI_PAGE_SIZE; /* page for trampoline code */
nethercote71980f02004-01-24 18:18:54 +0000772
sewardj79048ce2005-02-18 08:28:32 +0000773 if (0) VG_(printf)("stacksize = %d\n", stacksize);
774
nethercotef84f6952004-07-15 14:58:33 +0000775 // decide where stack goes!
776 VG_(clstk_end) = VG_(client_end);
777
nethercote71980f02004-01-24 18:18:54 +0000778 /* cl_esp is the client's stack pointer */
nethercotef84f6952004-07-15 14:58:33 +0000779 cl_esp = VG_(clstk_end) - stacksize;
njn13bfd852005-06-02 03:52:53 +0000780 cl_esp = VG_ROUNDDN(cl_esp, 16); /* make stack 16 byte aligned */
nethercote71980f02004-01-24 18:18:54 +0000781
nethercote71980f02004-01-24 18:18:54 +0000782 /* base of the string table (aligned) */
sewardjb9bce632005-06-21 01:41:34 +0000783 stringbase = strtab = (char *)(VG_(clstk_end)
njn13bfd852005-06-02 03:52:53 +0000784 - VG_ROUNDUP(stringsize, sizeof(int)));
nethercote71980f02004-01-24 18:18:54 +0000785
njn13bfd852005-06-02 03:52:53 +0000786 VG_(clstk_base) = VG_PGROUNDDN(cl_esp);
nethercote71980f02004-01-24 18:18:54 +0000787
sewardj79048ce2005-02-18 08:28:32 +0000788 if (0)
nethercote5ee67ca2004-06-22 14:00:09 +0000789 printf("stringsize=%d auxsize=%d stacksize=%d\n"
nethercote6a27d832004-09-07 10:17:02 +0000790 "clstk_base %p\n"
791 "clstk_end %p\n",
792 stringsize, auxsize, stacksize,
793 (void*)VG_(clstk_base), (void*)VG_(clstk_end));
nethercote5ee67ca2004-06-22 14:00:09 +0000794
nethercote71980f02004-01-24 18:18:54 +0000795 /* ==================== allocate space ==================== */
796
797 /* allocate a stack - mmap enough space for the stack */
njn83407492005-06-19 16:10:47 +0000798 res = VG_(mmap_native)((void *)VG_PGROUNDDN(cl_esp),
njn13bfd852005-06-02 03:52:53 +0000799 VG_(clstk_end) - VG_PGROUNDDN(cl_esp),
njn83407492005-06-19 16:10:47 +0000800 VKI_PROT_READ|VKI_PROT_WRITE|VKI_PROT_EXEC,
801 VKI_MAP_PRIVATE|VKI_MAP_ANONYMOUS|VKI_MAP_FIXED, -1, 0);
802 vg_assert(!res.isError);
nethercote71980f02004-01-24 18:18:54 +0000803
804 /* ==================== copy client stack ==================== */
805
nethercotea3c3cf22004-11-01 18:38:00 +0000806 ptr = (Addr*)cl_esp;
nethercote71980f02004-01-24 18:18:54 +0000807
808 /* --- argc --- */
809 *ptr++ = argc; /* client argc */
810
811 /* --- argv --- */
nethercoted6a56872004-07-26 15:32:47 +0000812 if (info->interp_name) {
nethercotea3c3cf22004-11-01 18:38:00 +0000813 *ptr++ = (Addr)copy_str(&strtab, info->interp_name);
nethercoted6a56872004-07-26 15:32:47 +0000814 free(info->interp_name);
nethercote71980f02004-01-24 18:18:54 +0000815 }
nethercoted6a56872004-07-26 15:32:47 +0000816 if (info->interp_args) {
nethercotea3c3cf22004-11-01 18:38:00 +0000817 *ptr++ = (Addr)copy_str(&strtab, info->interp_args);
nethercoted6a56872004-07-26 15:32:47 +0000818 free(info->interp_args);
nethercote71980f02004-01-24 18:18:54 +0000819 }
820 for (cpp = orig_argv; *cpp; ptr++, cpp++) {
nethercotea3c3cf22004-11-01 18:38:00 +0000821 *ptr = (Addr)copy_str(&strtab, *cpp);
nethercote71980f02004-01-24 18:18:54 +0000822 }
823 *ptr++ = 0;
824
825 /* --- envp --- */
826 VG_(client_envp) = (Char **)ptr;
827 for (cpp = orig_envp; cpp && *cpp; ptr++, cpp++)
nethercotea3c3cf22004-11-01 18:38:00 +0000828 *ptr = (Addr)copy_str(&strtab, *cpp);
nethercote71980f02004-01-24 18:18:54 +0000829 *ptr++ = 0;
830
831 /* --- auxv --- */
832 auxv = (struct ume_auxv *)ptr;
833 *client_auxv = (UInt *)auxv;
834
cerion85665ca2005-06-20 15:51:07 +0000835#if defined(VGP_ppc32_linux)
836 auxv[0].a_type = AT_IGNOREPPC;
837 auxv[0].u.a_val = AT_IGNOREPPC;
838 auxv[1].a_type = AT_IGNOREPPC;
839 auxv[1].u.a_val = AT_IGNOREPPC;
840 auxv += 2;
841#endif
842
nethercote71980f02004-01-24 18:18:54 +0000843 for (; orig_auxv->a_type != AT_NULL; auxv++, orig_auxv++) {
844 /* copy the entry... */
845 *auxv = *orig_auxv;
846
847 /* ...and fix up the copy */
848 switch(auxv->a_type) {
849 case AT_PHDR:
850 if (info->phdr == 0)
851 auxv->a_type = AT_IGNORE;
852 else
853 auxv->u.a_val = info->phdr;
854 break;
855
856 case AT_PHNUM:
857 if (info->phdr == 0)
858 auxv->a_type = AT_IGNORE;
859 else
860 auxv->u.a_val = info->phnum;
861 break;
862
863 case AT_BASE:
sewardjb5f6f512005-03-10 23:59:00 +0000864 auxv->u.a_val = info->interp_base;
nethercote71980f02004-01-24 18:18:54 +0000865 break;
866
867 case AT_PLATFORM: /* points to a platform description string */
868 auxv->u.a_ptr = copy_str(&strtab, orig_auxv->u.a_ptr);
869 break;
870
871 case AT_ENTRY:
872 auxv->u.a_val = info->entry;
873 break;
874
875 case AT_IGNORE:
876 case AT_EXECFD:
877 case AT_PHENT:
878 case AT_PAGESZ:
879 case AT_FLAGS:
880 case AT_NOTELF:
881 case AT_UID:
882 case AT_EUID:
883 case AT_GID:
884 case AT_EGID:
885 case AT_CLKTCK:
886 case AT_HWCAP:
887 case AT_FPUCW:
888 case AT_DCACHEBSIZE:
889 case AT_ICACHEBSIZE:
890 case AT_UCACHEBSIZE:
cerion85665ca2005-06-20 15:51:07 +0000891#if defined(VGP_ppc32_linux)
892 case AT_IGNOREPPC:
893#endif
nethercote71980f02004-01-24 18:18:54 +0000894 /* All these are pointerless, so we don't need to do anything
895 about them. */
896 break;
897
898 case AT_SECURE:
899 /* If this is 1, then it means that this program is running
900 suid, and therefore the dynamic linker should be careful
901 about LD_PRELOAD, etc. However, since stage1 (the thing
902 the kernel actually execve's) should never be SUID, and we
sewardjb5f6f512005-03-10 23:59:00 +0000903 need LD_PRELOAD to work for the client, we
nethercote71980f02004-01-24 18:18:54 +0000904 set AT_SECURE to 0. */
905 auxv->u.a_val = 0;
906 break;
907
908 case AT_SYSINFO:
909 /* Leave this unmolested for now, but we'll update it later
910 when we set up the client trampoline code page */
911 break;
912
cerion85665ca2005-06-20 15:51:07 +0000913#if !defined(VGP_ppc32_linux)
nethercote71980f02004-01-24 18:18:54 +0000914 case AT_SYSINFO_EHDR:
915 /* Trash this, because we don't reproduce it */
916 auxv->a_type = AT_IGNORE;
917 break;
cerion85665ca2005-06-20 15:51:07 +0000918#endif
nethercote71980f02004-01-24 18:18:54 +0000919
920 default:
921 /* stomp out anything we don't know about */
njn37569252005-06-21 00:28:43 +0000922 if (0)
nethercote545fe672004-11-01 16:52:43 +0000923 printf("stomping auxv entry %lld\n", (ULong)auxv->a_type);
nethercote71980f02004-01-24 18:18:54 +0000924 auxv->a_type = AT_IGNORE;
925 break;
926
927 }
928 }
929 *auxv = *orig_auxv;
930 vg_assert(auxv->a_type == AT_NULL);
931
932 vg_assert((strtab-stringbase) == stringsize);
933
nethercote5ee67ca2004-06-22 14:00:09 +0000934 /* We know the initial ESP is pointing at argc/argv */
935 VG_(client_argc) = *(Int*)cl_esp;
sewardj45f02c42005-02-05 18:27:14 +0000936 VG_(client_argv) = (Char**)(cl_esp + sizeof(HWord));
nethercote5ee67ca2004-06-22 14:00:09 +0000937
sewardj79048ce2005-02-18 08:28:32 +0000938 if (0) VG_(printf)("startup SP = %p\n", cl_esp);
nethercote71980f02004-01-24 18:18:54 +0000939 return cl_esp;
940}
941
942/*====================================================================*/
943/*=== Find executable ===*/
944/*====================================================================*/
945
thughes4ad52d02004-06-27 17:37:21 +0000946static const char* executable_name;
947
948static Bool match_executable(const char *entry) {
949 char buf[strlen(entry) + strlen(executable_name) + 2];
950
951 /* empty PATH element means . */
952 if (*entry == '\0')
953 entry = ".";
954
955 snprintf(buf, sizeof(buf), "%s/%s", entry, executable_name);
956
957 if (access(buf, R_OK|X_OK) == 0) {
958 executable_name = strdup(buf);
959 vg_assert(NULL != executable_name);
960 return True;
961 }
962 return False;
963}
964
nethercote71980f02004-01-24 18:18:54 +0000965static const char* find_executable(const char* exec)
966{
967 vg_assert(NULL != exec);
thughes4ad52d02004-06-27 17:37:21 +0000968 executable_name = exec;
969 if (strchr(executable_name, '/') == NULL) {
nethercote71980f02004-01-24 18:18:54 +0000970 /* no '/' - we need to search the path */
971 char *path = getenv("PATH");
thughes4ad52d02004-06-27 17:37:21 +0000972 scan_colsep(path, match_executable);
nethercote71980f02004-01-24 18:18:54 +0000973 }
thughes4ad52d02004-06-27 17:37:21 +0000974 return executable_name;
nethercote71980f02004-01-24 18:18:54 +0000975}
976
977
978/*====================================================================*/
979/*=== Loading tools ===*/
980/*====================================================================*/
981
982static void list_tools(void)
983{
984 DIR *dir = opendir(VG_(libdir));
985 struct dirent *de;
986 int first = 1;
987
988 if (dir == NULL) {
989 fprintf(stderr, "Can't open %s: %s (installation problem?)\n",
nethercotef4928da2004-06-15 10:54:40 +0000990 VG_(libdir), strerror(errno));
nethercote71980f02004-01-24 18:18:54 +0000991 return;
992 }
993
nethercotef4928da2004-06-15 10:54:40 +0000994 while ((de = readdir(dir)) != NULL) {
nethercote71980f02004-01-24 18:18:54 +0000995 int len = strlen(de->d_name);
996
njn063c5402004-11-22 16:58:05 +0000997 /* look for vgtool_TOOL.so names */
998 if (len > (7+1+3) && /* "vgtool_" + at least 1-char toolname + ".so" */
999 strncmp(de->d_name, "vgtool_", 7) == 0 &&
nethercotef4928da2004-06-15 10:54:40 +00001000 VG_STREQ(de->d_name + len - 3, ".so")) {
1001 if (first) {
1002 fprintf(stderr, "Available tools:\n");
1003 first = 0;
1004 }
1005 de->d_name[len-3] = '\0';
1006 fprintf(stderr, "\t%s\n", de->d_name+7);
nethercote71980f02004-01-24 18:18:54 +00001007 }
1008 }
1009
1010 closedir(dir);
1011
1012 if (first)
nethercotef4928da2004-06-15 10:54:40 +00001013 fprintf(stderr, "No tools available in \"%s\" (installation problem?)\n",
1014 VG_(libdir));
nethercote71980f02004-01-24 18:18:54 +00001015}
1016
1017
1018/* Find and load a tool, and check it looks ok. Also looks to see if there's
1019 * a matching vgpreload_*.so file, and returns its name in *preloadpath. */
njn8a97c6d2005-03-31 04:37:24 +00001020static void load_tool( const char *toolname,
nethercote71980f02004-01-24 18:18:54 +00001021 ToolInfo** toolinfo_out, char **preloadpath_out )
1022{
1023 Bool ok;
sewardjb5f6f512005-03-10 23:59:00 +00001024 int len = strlen(VG_(libdir)) + strlen(toolname) + 16;
nethercote71980f02004-01-24 18:18:54 +00001025 char buf[len];
1026 void* handle;
1027 ToolInfo* toolinfo;
1028 char* preloadpath = NULL;
nethercote71980f02004-01-24 18:18:54 +00001029
1030 // XXX: allowing full paths for --tool option -- does it make sense?
1031 // Doesn't allow for vgpreload_<tool>.so.
1032
1033 if (strchr(toolname, '/') != 0) {
1034 /* toolname contains '/', and so must be a pathname */
1035 handle = dlopen(toolname, RTLD_NOW);
1036 } else {
1037 /* just try in the libdir */
njn063c5402004-11-22 16:58:05 +00001038 snprintf(buf, len, "%s/vgtool_%s.so", VG_(libdir), toolname);
nethercote71980f02004-01-24 18:18:54 +00001039 handle = dlopen(buf, RTLD_NOW);
1040
1041 if (handle != NULL) {
1042 snprintf(buf, len, "%s/vgpreload_%s.so", VG_(libdir), toolname);
1043 if (access(buf, R_OK) == 0) {
1044 preloadpath = strdup(buf);
1045 vg_assert(NULL != preloadpath);
1046 }
1047 }
1048 }
1049
1050 ok = (NULL != handle);
1051 if (!ok) {
1052 fprintf(stderr, "Can't open tool \"%s\": %s\n", toolname, dlerror());
1053 goto bad_load;
1054 }
1055
njn51d827b2005-05-09 01:02:08 +00001056 toolinfo = dlsym(handle, "vgPlain_tool_info");
nethercote71980f02004-01-24 18:18:54 +00001057 ok = (NULL != toolinfo);
1058 if (!ok) {
njn51d827b2005-05-09 01:02:08 +00001059 fprintf(stderr, "Tool \"%s\" doesn't define its ToolInfo - "
nethercote71980f02004-01-24 18:18:54 +00001060 "add VG_DETERMINE_INTERFACE_VERSION?\n", toolname);
1061 goto bad_load;
1062 }
1063
1064 ok = (toolinfo->sizeof_ToolInfo == sizeof(*toolinfo) &&
njn51d827b2005-05-09 01:02:08 +00001065 toolinfo->interface_version == VG_CORE_INTERFACE_VERSION &&
1066 toolinfo->tl_pre_clo_init != NULL);
nethercote71980f02004-01-24 18:18:54 +00001067 if (!ok) {
1068 fprintf(stderr, "Error:\n"
1069 " Tool and core interface versions do not match.\n"
njn51d827b2005-05-09 01:02:08 +00001070 " Interface version used by core is: %d (size %d)\n"
1071 " Interface version used by tool is: %d (size %d)\n"
1072 " The version numbers must match.\n",
1073 VG_CORE_INTERFACE_VERSION,
nethercote545fe672004-11-01 16:52:43 +00001074 (Int)sizeof(*toolinfo),
njn51d827b2005-05-09 01:02:08 +00001075 toolinfo->interface_version,
nethercote71980f02004-01-24 18:18:54 +00001076 toolinfo->sizeof_ToolInfo);
1077 fprintf(stderr, " You need to at least recompile, and possibly update,\n");
njn51d827b2005-05-09 01:02:08 +00001078 if (VG_CORE_INTERFACE_VERSION > toolinfo->interface_version)
nethercote996901a2004-08-03 13:29:09 +00001079 fprintf(stderr, " your tool to work with this version of Valgrind.\n");
nethercote71980f02004-01-24 18:18:54 +00001080 else
nethercote996901a2004-08-03 13:29:09 +00001081 fprintf(stderr, " your version of Valgrind to work with this tool.\n");
nethercote71980f02004-01-24 18:18:54 +00001082 goto bad_load;
1083 }
1084
njn8a97c6d2005-03-31 04:37:24 +00001085 vg_assert(NULL != toolinfo);
nethercote71980f02004-01-24 18:18:54 +00001086 *toolinfo_out = toolinfo;
1087 *preloadpath_out = preloadpath;
1088 return;
1089
1090
1091 bad_load:
1092 if (handle != NULL)
1093 dlclose(handle);
1094
nethercotef4928da2004-06-15 10:54:40 +00001095 fprintf(stderr, "valgrind: couldn't load tool\n");
nethercote71980f02004-01-24 18:18:54 +00001096 list_tools();
1097 exit(127);
1098}
1099
nethercotef4928da2004-06-15 10:54:40 +00001100
1101/*====================================================================*/
1102/*=== Command line errors ===*/
1103/*====================================================================*/
1104
njnbe9b47b2005-05-15 16:22:58 +00001105static void revert_to_stderr ( void )
nethercotef4928da2004-06-15 10:54:40 +00001106{
njnbe9b47b2005-05-15 16:22:58 +00001107 vg_assert( !VG_(logging_to_socket) );
nethercotef8548672004-06-21 12:42:35 +00001108 VG_(clo_log_fd) = 2; /* stderr */
nethercotef4928da2004-06-15 10:54:40 +00001109}
1110
1111void VG_(bad_option) ( Char* opt )
1112{
njnbe9b47b2005-05-15 16:22:58 +00001113 revert_to_stderr();
njn02bc4b82005-05-15 17:28:26 +00001114 VG_(printf)("valgrind: Bad option '%s'; aborting.\n", opt);
nethercotef4928da2004-06-15 10:54:40 +00001115 VG_(printf)("valgrind: Use --help for more information.\n");
1116 VG_(exit)(1);
1117}
1118
nethercotef4928da2004-06-15 10:54:40 +00001119static void missing_prog ( void )
1120{
njnbe9b47b2005-05-15 16:22:58 +00001121 revert_to_stderr();
nethercotef4928da2004-06-15 10:54:40 +00001122 VG_(printf)("valgrind: no program specified\n");
1123 VG_(printf)("valgrind: Use --help for more information.\n");
1124 VG_(exit)(1);
1125}
1126
1127static void config_error ( Char* msg )
1128{
njnbe9b47b2005-05-15 16:22:58 +00001129 revert_to_stderr();
nethercotef4928da2004-06-15 10:54:40 +00001130 VG_(printf)("valgrind: Startup or configuration error:\n %s\n", msg);
1131 VG_(printf)("valgrind: Unable to start up properly. Giving up.\n");
1132 VG_(exit)(1);
1133}
1134
1135
nethercote71980f02004-01-24 18:18:54 +00001136/*====================================================================*/
1137/*=== Loading the client ===*/
1138/*====================================================================*/
1139
nethercotef4928da2004-06-15 10:54:40 +00001140static void load_client(char* cl_argv[], const char* exec, Int need_help,
nethercote71980f02004-01-24 18:18:54 +00001141 /*out*/struct exeinfo* info, /*out*/Addr* client_eip)
1142{
1143 // If they didn't specify an executable with --exec, and didn't specify
1144 // --help, then use client argv[0] (searching $PATH if necessary).
nethercotef4928da2004-06-15 10:54:40 +00001145 if (NULL == exec && !need_help) {
nethercote71980f02004-01-24 18:18:54 +00001146 if (cl_argv[0] == NULL ||
1147 ( NULL == (exec = find_executable(cl_argv[0])) ) )
1148 {
nethercotef4928da2004-06-15 10:54:40 +00001149 missing_prog();
nethercote71980f02004-01-24 18:18:54 +00001150 }
1151 }
1152
1153 info->map_base = VG_(client_mapbase);
nethercote71980f02004-01-24 18:18:54 +00001154 info->exe_base = VG_(client_base);
1155 info->exe_end = VG_(client_end);
1156 info->argv = cl_argv;
1157
nethercotef4928da2004-06-15 10:54:40 +00001158 if (need_help) {
nethercote71980f02004-01-24 18:18:54 +00001159 VG_(clexecfd) = -1;
njnc8c93282004-11-29 16:05:54 +00001160 // Totally zero 'info' before continuing.
1161 VG_(memset)(info, 0, sizeof(*info));
nethercote71980f02004-01-24 18:18:54 +00001162 } else {
1163 Int ret;
sewardj92645592005-07-23 09:18:34 +00001164 /* HACK: assumes VG_(open) always succeeds */
1165 VG_(clexecfd) = VG_(open)(exec, VKI_O_RDONLY, VKI_S_IRUSR)
1166 .val;
njn62ff0f22005-06-21 23:03:36 +00001167 ret = VG_(do_exec)(exec, info);
nethercote71980f02004-01-24 18:18:54 +00001168 if (ret != 0) {
nethercoteea147e72004-07-26 15:43:57 +00001169 fprintf(stderr, "valgrind: do_exec(%s) failed: %s\n",
1170 exec, strerror(ret));
nethercote71980f02004-01-24 18:18:54 +00001171 exit(127);
1172 }
1173 }
1174
1175 /* Copy necessary bits of 'info' that were filled in */
1176 *client_eip = info->init_eip;
1177 VG_(brk_base) = VG_(brk_limit) = info->brkbase;
1178}
1179
nethercote969ecf12004-10-13 17:29:01 +00001180/*====================================================================*/
1181/*=== Address space unpadding ===*/
1182/*====================================================================*/
1183
1184typedef struct {
njn909c3192005-06-19 15:46:27 +00001185 char* killpad_start;
1186 char* killpad_end;
1187 struct vki_stat* killpad_padstat;
nethercote969ecf12004-10-13 17:29:01 +00001188} killpad_extra;
1189
1190static int killpad(char *segstart, char *segend, const char *perm, off_t off,
1191 int maj, int min, int ino, void* ex)
1192{
1193 killpad_extra* extra = ex;
1194 void *b, *e;
njn83407492005-06-19 16:10:47 +00001195 SysRes res;
nethercote969ecf12004-10-13 17:29:01 +00001196
1197 vg_assert(NULL != extra->killpad_padstat);
1198
1199 if (extra->killpad_padstat->st_dev != makedev(maj, min) ||
1200 extra->killpad_padstat->st_ino != ino)
1201 return 1;
1202
1203 if (segend <= extra->killpad_start || segstart >= extra->killpad_end)
1204 return 1;
1205
1206 if (segstart <= extra->killpad_start)
1207 b = extra->killpad_start;
1208 else
1209 b = segstart;
1210
1211 if (segend >= extra->killpad_end)
1212 e = extra->killpad_end;
1213 else
1214 e = segend;
1215
njn83407492005-06-19 16:10:47 +00001216 res = VG_(munmap_native)(b, (char *)e-(char *)b);
1217 vg_assert(!res.isError);
nethercote969ecf12004-10-13 17:29:01 +00001218
1219 return 1;
1220}
1221
1222// Remove padding of 'padfile' from a range of address space.
sewardj2c5ffbe2005-03-12 13:32:06 +00001223static void as_unpad(void *start, void *end, int padfile)
nethercote969ecf12004-10-13 17:29:01 +00001224{
njn909c3192005-06-19 15:46:27 +00001225 static struct vki_stat padstat;
nethercote969ecf12004-10-13 17:29:01 +00001226 killpad_extra extra;
1227 int res;
1228
sewardjb5f6f512005-03-10 23:59:00 +00001229 vg_assert(padfile >= 0);
nethercote969ecf12004-10-13 17:29:01 +00001230
njn909c3192005-06-19 15:46:27 +00001231 res = VG_(fstat)(padfile, &padstat);
nethercote969ecf12004-10-13 17:29:01 +00001232 vg_assert(0 == res);
1233 extra.killpad_padstat = &padstat;
1234 extra.killpad_start = start;
1235 extra.killpad_end = end;
njn62ff0f22005-06-21 23:03:36 +00001236 VG_(foreach_map)(killpad, &extra);
nethercote969ecf12004-10-13 17:29:01 +00001237}
1238
sewardj2c5ffbe2005-03-12 13:32:06 +00001239static void as_closepadfile(int padfile)
nethercote969ecf12004-10-13 17:29:01 +00001240{
1241 int res = close(padfile);
1242 vg_assert(0 == res);
1243}
1244
sewardj71bc3cb2005-05-19 00:25:45 +00001245/*====================================================================*/
1246/*=== Command-line: variables, processing, etc ===*/
1247/*====================================================================*/
1248
1249// See pub_{core,tool}_options.h for explanations of all these.
1250
sewardj2c5ffbe2005-03-12 13:32:06 +00001251static void usage ( Bool debug_help )
njn7cf0bd32002-06-08 13:36:03 +00001252{
njn25e49d8e72002-09-23 09:36:25 +00001253 Char* usage1 =
nethercote71980f02004-01-24 18:18:54 +00001254"usage: valgrind --tool=<toolname> [options] prog-and-args\n"
njn25e49d8e72002-09-23 09:36:25 +00001255"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001256" common user options for all Valgrind tools, with defaults in [ ]:\n"
sewardjb5f6f512005-03-10 23:59:00 +00001257" --tool=<name> use the Valgrind tool named <name> [memcheck]\n"
nethercotea76368b2004-06-16 11:56:29 +00001258" -h --help show this message\n"
nethercote6c999f22004-01-31 22:55:15 +00001259" --help-debug show this message, plus debugging options\n"
njn25e49d8e72002-09-23 09:36:25 +00001260" --version show version\n"
njn25e49d8e72002-09-23 09:36:25 +00001261" -q --quiet run silently; only print error msgs\n"
1262" -v --verbose be more verbose, incl counts of errors\n"
nethercote77eba602003-11-13 17:35:04 +00001263" --trace-children=no|yes Valgrind-ise child processes? [no]\n"
nethercote0d588502004-06-21 13:27:11 +00001264" --track-fds=no|yes track open file descriptors? [no]\n"
thughes6233a382004-08-21 11:10:44 +00001265" --time-stamp=no|yes add timestamps to log messages? [no]\n"
njnce545552005-07-25 22:36:52 +00001266" --log-fd=<number> log messages to file descriptor [2=stderr]\n"
1267" --log-file=<file> log messages to <file>.pid<pid>\n"
1268" --log-file-exactly=<file> log messages to <file>\n"
1269" --log-file-qualifier=<VAR> incorporate $VAR in logfile name [none]\n"
1270" --log-socket=ipaddr:port log messages to socket ipaddr:port\n"
nethercote2b0793f2003-12-02 10:41:18 +00001271"\n"
1272" uncommon user options for all Valgrind tools:\n"
nethercote0d588502004-06-21 13:27:11 +00001273" --run-libc-freeres=no|yes free up glibc memory at exit? [yes]\n"
sewardjb5f6f512005-03-10 23:59:00 +00001274" --weird-hacks=hack1,hack2,... recognised hacks: lax-ioctls,ioctl-mmap [none]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001275" --pointercheck=no|yes enforce client address space limits [yes]\n"
sewardjb1131a82005-03-19 15:12:21 +00001276" --show-emwarns=no|yes show warnings about emulation limits? [no]\n"
sewardj6c3a2192005-07-24 07:00:45 +00001277" --smc-check=none|stack|all checks for self-modifying code: none,\n"
1278" only for code found in stacks, or all [stack]\n"
njn25e49d8e72002-09-23 09:36:25 +00001279"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001280" user options for Valgrind tools that report errors:\n"
njnce545552005-07-25 22:36:52 +00001281" --xml=yes all output is in XML (Memcheck/Nulgrind only)\n"
njnc8ec9f82005-07-20 03:03:28 +00001282" --xml-user-comment=STR copy STR verbatim to XML output\n"
nethercote2b0793f2003-12-02 10:41:18 +00001283" --demangle=no|yes automatically demangle C++ names? [yes]\n"
njncc6cc142005-03-12 20:59:29 +00001284" --num-callers=<number> show <num> callers in stack traces [12]\n"
nethercote2b0793f2003-12-02 10:41:18 +00001285" --error-limit=no|yes stop showing new errors if too many? [yes]\n"
1286" --show-below-main=no|yes continue stack traces below main() [no]\n"
1287" --suppressions=<filename> suppress errors described in <filename>\n"
sewardjd153fae2005-01-10 17:24:47 +00001288" --gen-suppressions=no|yes|all print suppressions for errors? [no]\n"
nethercote04d0fbc2004-01-26 16:48:06 +00001289" --db-attach=no|yes start debugger when errors detected? [no]\n"
1290" --db-command=<command> command to start debugger [gdb -nw %%f %%p]\n"
1291" --input-fd=<number> file descriptor for input [0=stdin]\n"
sewardj97724e52005-04-02 23:40:59 +00001292" --max-stackframe=<number> assume stack switch for SP changes larger\n"
1293" than <number> bytes [2000000]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001294"\n";
njn7cf0bd32002-06-08 13:36:03 +00001295
njn25e49d8e72002-09-23 09:36:25 +00001296 Char* usage2 =
1297"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001298" debugging options for all Valgrind tools:\n"
njn25e49d8e72002-09-23 09:36:25 +00001299" --sanity-level=<number> level of sanity checking to do [1]\n"
nethercote137bc552003-11-14 17:47:54 +00001300" --profile=no|yes profile? (tool must be built for it) [no]\n"
sewardjfa8ec112005-01-19 11:55:34 +00001301" --trace-flags=<XXXXXXXX> show generated code? (X = 0|1) [00000000]\n"
1302" --profile-flags=<XXXXXXXX> ditto, but for profiling (X = 0|1) [00000000]\n"
sewardjc771b292004-11-30 18:55:21 +00001303" --trace-notbelow=<number> only show BBs above <number> [0]\n"
njn25e49d8e72002-09-23 09:36:25 +00001304" --trace-syscalls=no|yes show all system calls? [no]\n"
1305" --trace-signals=no|yes show signal handling details? [no]\n"
1306" --trace-symtab=no|yes show symbol table details? [no]\n"
sewardjce058b02005-05-01 08:55:38 +00001307" --trace-cfi=no|yes show call-frame-info details? [no]\n"
njn25e49d8e72002-09-23 09:36:25 +00001308" --trace-sched=no|yes show thread scheduler details? [no]\n"
jsgf855d93d2003-10-13 22:26:55 +00001309" --wait-for-gdb=yes|no pause on startup to wait for gdb attach\n"
sewardjb5f6f512005-03-10 23:59:00 +00001310#if 0
1311" --model-pthreads=yes|no model the pthreads library [no]\n"
1312#endif
1313" --command-line-only=no|yes only use command line options [no]\n"
njn613812e2005-03-11 04:57:30 +00001314"\n"
1315" --vex-iropt-verbosity 0 .. 9 [0]\n"
1316" --vex-iropt-level 0 .. 2 [2]\n"
1317" --vex-iropt-precise-memory-exns [no]\n"
sewardj8b635a42004-11-22 19:01:47 +00001318" --vex-iropt-unroll-thresh 0 .. 400 [120]\n"
1319" --vex-guest-max-insns 1 .. 100 [50]\n"
1320" --vex-guest-chase-thresh 0 .. 99 [10]\n"
1321"\n"
sewardjfa8ec112005-01-19 11:55:34 +00001322" --trace-flags and --profile-flags values (omit the middle space):\n"
sewardj2a99cf62004-11-24 10:44:19 +00001323" 1000 0000 show conversion into IR\n"
1324" 0100 0000 show after initial opt\n"
1325" 0010 0000 show after instrumentation\n"
1326" 0001 0000 show after second opt\n"
1327" 0000 1000 show after tree building\n"
1328" 0000 0100 show selecting insns\n"
1329" 0000 0010 show after reg-alloc\n"
1330" 0000 0001 show final assembly\n"
1331"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001332" debugging options for Valgrind tools that report errors\n"
1333" --dump-error=<number> show translation for basic block associated\n"
1334" with <number>'th error context [0=show none]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001335"\n";
njn3e884182003-04-15 13:03:23 +00001336
1337 Char* usage3 =
1338"\n"
nethercote71980f02004-01-24 18:18:54 +00001339" Extra options read from ~/.valgrindrc, $VALGRIND_OPTS, ./.valgrindrc\n"
njn25e49d8e72002-09-23 09:36:25 +00001340"\n"
njn53612422005-03-12 16:22:54 +00001341" Valgrind is Copyright (C) 2000-2005 Julian Seward et al.\n"
njn25e49d8e72002-09-23 09:36:25 +00001342" and licensed under the GNU General Public License, version 2.\n"
1343" Bug reports, feedback, admiration, abuse, etc, to: %s.\n"
njnd04b7c62002-10-03 14:05:52 +00001344"\n"
nethercote137bc552003-11-14 17:47:54 +00001345" Tools are copyright and licensed by their authors. See each\n"
1346" tool's start-up message for more information.\n"
njn25e49d8e72002-09-23 09:36:25 +00001347"\n";
njn7cf0bd32002-06-08 13:36:03 +00001348
njnbe9b47b2005-05-15 16:22:58 +00001349 // Ensure the message goes to stdout
1350 VG_(clo_log_fd) = 1;
1351 vg_assert( !VG_(logging_to_socket) );
1352
fitzhardinge98abfc72003-12-16 02:05:15 +00001353 VG_(printf)(usage1);
1354 if (VG_(details).name) {
1355 VG_(printf)(" user options for %s:\n", VG_(details).name);
fitzhardinge98abfc72003-12-16 02:05:15 +00001356 if (VG_(needs).command_line_options)
njn51d827b2005-05-09 01:02:08 +00001357 VG_TDICT_CALL(tool_print_usage);
fitzhardinge98abfc72003-12-16 02:05:15 +00001358 else
1359 VG_(printf)(" (none)\n");
1360 }
nethercote6c999f22004-01-31 22:55:15 +00001361 if (debug_help) {
1362 VG_(printf)(usage2);
fitzhardinge98abfc72003-12-16 02:05:15 +00001363
nethercote6c999f22004-01-31 22:55:15 +00001364 if (VG_(details).name) {
1365 VG_(printf)(" debugging options for %s:\n", VG_(details).name);
1366
1367 if (VG_(needs).command_line_options)
njn51d827b2005-05-09 01:02:08 +00001368 VG_TDICT_CALL(tool_print_debug_usage);
nethercote6c999f22004-01-31 22:55:15 +00001369 else
1370 VG_(printf)(" (none)\n");
1371 }
fitzhardinge98abfc72003-12-16 02:05:15 +00001372 }
nethercote421281e2003-11-20 16:20:55 +00001373 VG_(printf)(usage3, VG_BUGS_TO);
nethercotef4928da2004-06-15 10:54:40 +00001374 VG_(exit)(0);
njn7cf0bd32002-06-08 13:36:03 +00001375}
sewardjde4a1d02002-03-22 01:27:54 +00001376
nethercote71980f02004-01-24 18:18:54 +00001377static void pre_process_cmd_line_options
nethercote6c999f22004-01-31 22:55:15 +00001378 ( Int* need_help, const char** tool, const char** exec )
sewardj1c1b1162003-02-23 01:25:51 +00001379{
nethercote71980f02004-01-24 18:18:54 +00001380 UInt i;
sewardjde4a1d02002-03-22 01:27:54 +00001381
sewardj8b635a42004-11-22 19:01:47 +00001382 LibVEX_default_VexControl(& VG_(clo_vex_control));
1383
nethercote71980f02004-01-24 18:18:54 +00001384 /* parse the options we have (only the options we care about now) */
nethercotef6a1d502004-08-09 12:21:57 +00001385 for (i = 1; i < vg_argc; i++) {
nethercote71980f02004-01-24 18:18:54 +00001386
nethercotef6a1d502004-08-09 12:21:57 +00001387 if (strcmp(vg_argv[i], "--version") == 0) {
nethercote71980f02004-01-24 18:18:54 +00001388 printf("valgrind-" VERSION "\n");
nethercotef4928da2004-06-15 10:54:40 +00001389 exit(0);
nethercote71980f02004-01-24 18:18:54 +00001390
nethercotef6a1d502004-08-09 12:21:57 +00001391 } else if (VG_CLO_STREQ(vg_argv[i], "--help") ||
1392 VG_CLO_STREQ(vg_argv[i], "-h")) {
nethercote6c999f22004-01-31 22:55:15 +00001393 *need_help = 1;
1394
nethercotef6a1d502004-08-09 12:21:57 +00001395 } else if (VG_CLO_STREQ(vg_argv[i], "--help-debug")) {
nethercote6c999f22004-01-31 22:55:15 +00001396 *need_help = 2;
nethercote71980f02004-01-24 18:18:54 +00001397
nethercotef6c99d72004-11-09 14:35:43 +00001398 } else if (VG_CLO_STREQN(7, vg_argv[i], "--tool=")) {
nethercotef6a1d502004-08-09 12:21:57 +00001399 *tool = &vg_argv[i][7];
nethercote71980f02004-01-24 18:18:54 +00001400
nethercotef6a1d502004-08-09 12:21:57 +00001401 } else if (VG_CLO_STREQN(7, vg_argv[i], "--exec=")) {
1402 *exec = &vg_argv[i][7];
nethercote71980f02004-01-24 18:18:54 +00001403 }
1404 }
nethercote71980f02004-01-24 18:18:54 +00001405}
1406
nethercote5ee67ca2004-06-22 14:00:09 +00001407static void process_cmd_line_options( UInt* client_auxv, const char* toolname )
nethercote71980f02004-01-24 18:18:54 +00001408{
sewardj92645592005-07-23 09:18:34 +00001409 SysRes sres;
1410 Int i, eventually_log_fd;
1411 Int toolname_len = VG_(strlen)(toolname);
njnbe9b47b2005-05-15 16:22:58 +00001412 enum {
1413 VgLogTo_Fd,
1414 VgLogTo_File,
1415 VgLogTo_FileExactly,
1416 VgLogTo_Socket
1417 } log_to = VgLogTo_Fd; // Where is logging output to be sent?
sewardjde4a1d02002-03-22 01:27:54 +00001418
nethercotee1730692003-11-20 10:38:07 +00001419 /* log to stderr by default, but usage message goes to stdout */
nethercotef8548672004-06-21 12:42:35 +00001420 eventually_log_fd = 2;
sewardjde4a1d02002-03-22 01:27:54 +00001421
sewardj19d81412002-06-03 01:10:40 +00001422 /* Check for sane path in ./configure --prefix=... */
fitzhardinge98abfc72003-12-16 02:05:15 +00001423 if (VG_LIBDIR[0] != '/')
sewardj19d81412002-06-03 01:10:40 +00001424 config_error("Please use absolute paths in "
1425 "./configure --prefix=... or --libdir=...");
sewardj38170912002-05-10 21:07:22 +00001426
nethercotef6a1d502004-08-09 12:21:57 +00001427 for (i = 1; i < vg_argc; i++) {
nethercote71980f02004-01-24 18:18:54 +00001428
nethercotef6a1d502004-08-09 12:21:57 +00001429 Char* arg = vg_argv[i];
thughes3bfd5a02004-07-18 08:05:44 +00001430 Char* colon = arg;
nethercote71980f02004-01-24 18:18:54 +00001431
thughes3bfd5a02004-07-18 08:05:44 +00001432 /* Look for a colon in the switch name */
1433 while (*colon && *colon != ':' && *colon != '=')
1434 colon++;
nethercote71980f02004-01-24 18:18:54 +00001435
1436 /* Look for matching "--toolname:foo" */
thughes3bfd5a02004-07-18 08:05:44 +00001437 if (*colon == ':') {
nethercote71980f02004-01-24 18:18:54 +00001438 if (VG_CLO_STREQN(2, arg, "--") &&
1439 VG_CLO_STREQN(toolname_len, arg+2, toolname) &&
1440 VG_CLO_STREQN(1, arg+2+toolname_len, ":"))
1441 {
1442 // prefix matches, convert "--toolname:foo" to "--foo"
1443 if (0)
1444 VG_(printf)("tool-specific arg: %s\n", arg);
njn8c0b3bb2005-03-12 21:20:39 +00001445 arg = strdup(arg + toolname_len + 1);
nethercote71980f02004-01-24 18:18:54 +00001446 arg[0] = '-';
1447 arg[1] = '-';
1448
1449 } else {
1450 // prefix doesn't match, skip to next arg
1451 continue;
1452 }
1453 }
1454
fitzhardinge98abfc72003-12-16 02:05:15 +00001455 /* Ignore these options - they've already been handled */
njn45270a22005-03-27 01:00:11 +00001456 if (VG_CLO_STREQN( 7, arg, "--tool=")) goto skip_arg;
1457 if (VG_CLO_STREQN( 7, arg, "--exec=")) goto skip_arg;
1458 if (VG_CLO_STREQN(20, arg, "--command-line-only=")) goto skip_arg;
fitzhardinge98abfc72003-12-16 02:05:15 +00001459
njn45270a22005-03-27 01:00:11 +00001460 if ( VG_CLO_STREQ(arg, "--")) goto skip_arg;
nethercote27fec902004-06-16 21:26:32 +00001461
nethercote71980f02004-01-24 18:18:54 +00001462 else if (VG_CLO_STREQ(arg, "-v") ||
1463 VG_CLO_STREQ(arg, "--verbose"))
sewardjde4a1d02002-03-22 01:27:54 +00001464 VG_(clo_verbosity)++;
nethercote27fec902004-06-16 21:26:32 +00001465
nethercote71980f02004-01-24 18:18:54 +00001466 else if (VG_CLO_STREQ(arg, "-q") ||
1467 VG_CLO_STREQ(arg, "--quiet"))
sewardjde4a1d02002-03-22 01:27:54 +00001468 VG_(clo_verbosity)--;
1469
sewardj1cf558c2005-04-25 01:36:56 +00001470 else if (VG_CLO_STREQ(arg, "-d")) {
1471 /* do nothing */
1472 }
1473
sewardj71bc3cb2005-05-19 00:25:45 +00001474 else VG_BOOL_CLO(arg, "--xml", VG_(clo_xml))
njn45270a22005-03-27 01:00:11 +00001475 else VG_BOOL_CLO(arg, "--db-attach", VG_(clo_db_attach))
1476 else VG_BOOL_CLO(arg, "--demangle", VG_(clo_demangle))
1477 else VG_BOOL_CLO(arg, "--error-limit", VG_(clo_error_limit))
1478 else VG_BOOL_CLO(arg, "--pointercheck", VG_(clo_pointercheck))
njn45270a22005-03-27 01:00:11 +00001479 else VG_BOOL_CLO(arg, "--show-emwarns", VG_(clo_show_emwarns))
sewardj97724e52005-04-02 23:40:59 +00001480 else VG_NUM_CLO (arg, "--max-stackframe", VG_(clo_max_stackframe))
njn45270a22005-03-27 01:00:11 +00001481 else VG_BOOL_CLO(arg, "--profile", VG_(clo_profile))
1482 else VG_BOOL_CLO(arg, "--run-libc-freeres", VG_(clo_run_libc_freeres))
1483 else VG_BOOL_CLO(arg, "--show-below-main", VG_(clo_show_below_main))
1484 else VG_BOOL_CLO(arg, "--time-stamp", VG_(clo_time_stamp))
1485 else VG_BOOL_CLO(arg, "--track-fds", VG_(clo_track_fds))
1486 else VG_BOOL_CLO(arg, "--trace-children", VG_(clo_trace_children))
1487 else VG_BOOL_CLO(arg, "--trace-sched", VG_(clo_trace_sched))
1488 else VG_BOOL_CLO(arg, "--trace-signals", VG_(clo_trace_signals))
1489 else VG_BOOL_CLO(arg, "--trace-symtab", VG_(clo_trace_symtab))
sewardjce058b02005-05-01 08:55:38 +00001490 else VG_BOOL_CLO(arg, "--trace-cfi", VG_(clo_trace_cfi))
njn45270a22005-03-27 01:00:11 +00001491 else VG_BOOL_CLO(arg, "--trace-redir", VG_(clo_trace_redir))
1492 else VG_BOOL_CLO(arg, "--trace-syscalls", VG_(clo_trace_syscalls))
1493 else VG_BOOL_CLO(arg, "--trace-pthreads", VG_(clo_trace_pthreads))
1494 else VG_BOOL_CLO(arg, "--wait-for-gdb", VG_(clo_wait_for_gdb))
1495 else VG_BOOL_CLO(arg, "--model-pthreads", VG_(clo_model_pthreads))
sewardj72f98ff2002-06-13 17:23:38 +00001496
njn45270a22005-03-27 01:00:11 +00001497 else VG_STR_CLO (arg, "--db-command", VG_(clo_db_command))
1498 else VG_STR_CLO (arg, "--weird-hacks", VG_(clo_weird_hacks))
sewardjde4a1d02002-03-22 01:27:54 +00001499
njn45270a22005-03-27 01:00:11 +00001500 else VG_NUM_CLO (arg, "--dump-error", VG_(clo_dump_error))
1501 else VG_NUM_CLO (arg, "--input-fd", VG_(clo_input_fd))
1502 else VG_NUM_CLO (arg, "--sanity-level", VG_(clo_sanity_level))
1503 else VG_BNUM_CLO(arg, "--num-callers", VG_(clo_backtrace_size), 1,
1504 VG_DEEPEST_BACKTRACE)
sewardjde4a1d02002-03-22 01:27:54 +00001505
sewardj6c3a2192005-07-24 07:00:45 +00001506 else if (VG_CLO_STREQ(arg, "--smc-check=none"))
1507 VG_(clo_smc_check) = Vg_SmcNone;
1508 else if (VG_CLO_STREQ(arg, "--smc-check=stack"))
1509 VG_(clo_smc_check) = Vg_SmcStack;
1510 else if (VG_CLO_STREQ(arg, "--smc-check=all"))
1511 VG_(clo_smc_check) = Vg_SmcAll;
sewardj26412bd2005-07-07 10:05:05 +00001512
njn45270a22005-03-27 01:00:11 +00001513 else VG_BNUM_CLO(arg, "--vex-iropt-verbosity",
sewardj8b635a42004-11-22 19:01:47 +00001514 VG_(clo_vex_control).iropt_verbosity, 0, 10)
njn45270a22005-03-27 01:00:11 +00001515 else VG_BNUM_CLO(arg, "--vex-iropt-level",
sewardj8b635a42004-11-22 19:01:47 +00001516 VG_(clo_vex_control).iropt_level, 0, 2)
njn45270a22005-03-27 01:00:11 +00001517 else VG_BOOL_CLO(arg, "--vex-iropt-precise-memory-exns",
sewardj8b635a42004-11-22 19:01:47 +00001518 VG_(clo_vex_control).iropt_precise_memory_exns)
njn45270a22005-03-27 01:00:11 +00001519 else VG_BNUM_CLO(arg, "--vex-iropt-unroll-thresh",
sewardj8b635a42004-11-22 19:01:47 +00001520 VG_(clo_vex_control).iropt_unroll_thresh, 0, 400)
njn45270a22005-03-27 01:00:11 +00001521 else VG_BNUM_CLO(arg, "--vex-guest-max-insns",
sewardj8b635a42004-11-22 19:01:47 +00001522 VG_(clo_vex_control).guest_max_insns, 1, 100)
njn45270a22005-03-27 01:00:11 +00001523 else VG_BNUM_CLO(arg, "--vex-guest-chase-thresh",
sewardj8b635a42004-11-22 19:01:47 +00001524 VG_(clo_vex_control).guest_chase_thresh, 0, 99)
1525
nethercotef8548672004-06-21 12:42:35 +00001526 else if (VG_CLO_STREQN(9, arg, "--log-fd=")) {
njnbe9b47b2005-05-15 16:22:58 +00001527 log_to = VgLogTo_Fd;
nethercotef8548672004-06-21 12:42:35 +00001528 VG_(clo_log_name) = NULL;
1529 eventually_log_fd = (Int)VG_(atoll)(&arg[9]);
sewardj4cf05692002-10-27 20:28:29 +00001530 }
1531
nethercotef8548672004-06-21 12:42:35 +00001532 else if (VG_CLO_STREQN(11, arg, "--log-file=")) {
njnbe9b47b2005-05-15 16:22:58 +00001533 log_to = VgLogTo_File;
nethercotef8548672004-06-21 12:42:35 +00001534 VG_(clo_log_name) = &arg[11];
sewardj4cf05692002-10-27 20:28:29 +00001535 }
njnd6bc3c32005-03-27 00:44:31 +00001536
sewardjad311162005-07-19 11:25:02 +00001537 else if (VG_CLO_STREQN(11, arg, "--log-file=")) {
1538 log_to = VgLogTo_File;
1539 VG_(clo_log_name) = &arg[11];
1540 }
1541
1542 else if (VG_CLO_STREQN(21, arg, "--log-file-qualifier=")) {
1543 VG_(clo_log_file_qualifier) = &arg[21];
1544 }
1545
sewardj603d4102005-01-11 14:01:02 +00001546 else if (VG_CLO_STREQN(19, arg, "--log-file-exactly=")) {
njnbe9b47b2005-05-15 16:22:58 +00001547 log_to = VgLogTo_FileExactly;
sewardj603d4102005-01-11 14:01:02 +00001548 VG_(clo_log_name) = &arg[19];
1549 }
sewardjde4a1d02002-03-22 01:27:54 +00001550
nethercotef8548672004-06-21 12:42:35 +00001551 else if (VG_CLO_STREQN(13, arg, "--log-socket=")) {
njnbe9b47b2005-05-15 16:22:58 +00001552 log_to = VgLogTo_Socket;
nethercotef8548672004-06-21 12:42:35 +00001553 VG_(clo_log_name) = &arg[13];
sewardj73cf3bc2002-11-03 03:20:15 +00001554 }
1555
sewardj768db0e2005-07-19 14:18:56 +00001556 else if (VG_CLO_STREQN(19, arg, "--xml-user-comment=")) {
1557 VG_(clo_xml_user_comment) = &arg[19];
1558 }
1559
nethercote71980f02004-01-24 18:18:54 +00001560 else if (VG_CLO_STREQN(15, arg, "--suppressions=")) {
sewardjde4a1d02002-03-22 01:27:54 +00001561 if (VG_(clo_n_suppressions) >= VG_CLO_MAX_SFILES) {
njn25e49d8e72002-09-23 09:36:25 +00001562 VG_(message)(Vg_UserMsg, "Too many suppression files specified.");
sewardjde4a1d02002-03-22 01:27:54 +00001563 VG_(message)(Vg_UserMsg,
1564 "Increase VG_CLO_MAX_SFILES and recompile.");
nethercote71980f02004-01-24 18:18:54 +00001565 VG_(bad_option)(arg);
sewardjde4a1d02002-03-22 01:27:54 +00001566 }
nethercote71980f02004-01-24 18:18:54 +00001567 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = &arg[15];
sewardjde4a1d02002-03-22 01:27:54 +00001568 VG_(clo_n_suppressions)++;
1569 }
sewardjde4a1d02002-03-22 01:27:54 +00001570
sewardjfa8ec112005-01-19 11:55:34 +00001571 /* "stuvwxyz" --> stuvwxyz (binary) */
1572 else if (VG_CLO_STREQN(14, arg, "--trace-flags=")) {
1573 Int j;
1574 char* opt = & arg[14];
1575
1576 if (8 != VG_(strlen)(opt)) {
1577 VG_(message)(Vg_UserMsg,
1578 "--trace-flags argument must have 8 digits");
1579 VG_(bad_option)(arg);
1580 }
1581 for (j = 0; j < 8; j++) {
1582 if ('0' == opt[j]) { /* do nothing */ }
1583 else if ('1' == opt[j]) VG_(clo_trace_flags) |= (1 << (7-j));
1584 else {
1585 VG_(message)(Vg_UserMsg, "--trace-flags argument can only "
1586 "contain 0s and 1s");
1587 VG_(bad_option)(arg);
1588 }
1589 }
1590 }
1591
1592 /* "stuvwxyz" --> stuvwxyz (binary) */
1593 else if (VG_CLO_STREQN(16, arg, "--profile-flags=")) {
njn25e49d8e72002-09-23 09:36:25 +00001594 Int j;
nethercote71980f02004-01-24 18:18:54 +00001595 char* opt = & arg[16];
njn25e49d8e72002-09-23 09:36:25 +00001596
sewardj2a99cf62004-11-24 10:44:19 +00001597 if (8 != VG_(strlen)(opt)) {
njn25e49d8e72002-09-23 09:36:25 +00001598 VG_(message)(Vg_UserMsg,
sewardjfa8ec112005-01-19 11:55:34 +00001599 "--profile-flags argument must have 8 digits");
nethercote71980f02004-01-24 18:18:54 +00001600 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001601 }
sewardj8b635a42004-11-22 19:01:47 +00001602 for (j = 0; j < 8; j++) {
njn25e49d8e72002-09-23 09:36:25 +00001603 if ('0' == opt[j]) { /* do nothing */ }
sewardjfa8ec112005-01-19 11:55:34 +00001604 else if ('1' == opt[j]) VG_(clo_profile_flags) |= (1 << (7-j));
njn25e49d8e72002-09-23 09:36:25 +00001605 else {
sewardjfa8ec112005-01-19 11:55:34 +00001606 VG_(message)(Vg_UserMsg, "--profile-flags argument can only "
njn25e49d8e72002-09-23 09:36:25 +00001607 "contain 0s and 1s");
nethercote71980f02004-01-24 18:18:54 +00001608 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001609 }
1610 }
1611 }
sewardjde4a1d02002-03-22 01:27:54 +00001612
njn45270a22005-03-27 01:00:11 +00001613 else VG_NUM_CLO (arg, "--trace-notbelow", VG_(clo_trace_notbelow))
sewardjc771b292004-11-30 18:55:21 +00001614
sewardjd153fae2005-01-10 17:24:47 +00001615 else if (VG_CLO_STREQ(arg, "--gen-suppressions=no"))
1616 VG_(clo_gen_suppressions) = 0;
1617 else if (VG_CLO_STREQ(arg, "--gen-suppressions=yes"))
1618 VG_(clo_gen_suppressions) = 1;
1619 else if (VG_CLO_STREQ(arg, "--gen-suppressions=all"))
1620 VG_(clo_gen_suppressions) = 2;
1621
nethercote71980f02004-01-24 18:18:54 +00001622 else if ( ! VG_(needs).command_line_options
njn51d827b2005-05-09 01:02:08 +00001623 || ! VG_TDICT_CALL(tool_process_cmd_line_option, arg) ) {
nethercotef4928da2004-06-15 10:54:40 +00001624 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001625 }
njn8c0b3bb2005-03-12 21:20:39 +00001626 skip_arg:
1627 if (arg != vg_argv[i])
1628 free(arg);
sewardjde4a1d02002-03-22 01:27:54 +00001629 }
1630
sewardj998d40d2004-12-06 14:24:52 +00001631 /* Make VEX control parameters sane */
1632
1633 if (VG_(clo_vex_control).guest_chase_thresh
1634 >= VG_(clo_vex_control).guest_max_insns)
1635 VG_(clo_vex_control).guest_chase_thresh
1636 = VG_(clo_vex_control).guest_max_insns - 1;
1637
1638 if (VG_(clo_vex_control).guest_chase_thresh < 0)
1639 VG_(clo_vex_control).guest_chase_thresh = 0;
1640
1641 /* Check various option values */
nethercote27fec902004-06-16 21:26:32 +00001642
njnf9ebf672003-05-12 21:41:30 +00001643 if (VG_(clo_verbosity) < 0)
sewardjde4a1d02002-03-22 01:27:54 +00001644 VG_(clo_verbosity) = 0;
1645
nethercote04d0fbc2004-01-26 16:48:06 +00001646 if (VG_(clo_db_attach) && VG_(clo_trace_children)) {
sewardjde4a1d02002-03-22 01:27:54 +00001647 VG_(message)(Vg_UserMsg, "");
1648 VG_(message)(Vg_UserMsg,
nethercote04d0fbc2004-01-26 16:48:06 +00001649 "--db-attach=yes conflicts with --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001650 VG_(message)(Vg_UserMsg,
1651 "Please choose one or the other, but not both.");
nethercote04d0fbc2004-01-26 16:48:06 +00001652 VG_(bad_option)("--db-attach=yes and --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001653 }
1654
njnbe9b47b2005-05-15 16:22:58 +00001655 if (VG_(clo_gen_suppressions) > 0 &&
1656 !VG_(needs).core_errors && !VG_(needs).tool_errors) {
1657 VG_(message)(Vg_UserMsg,
1658 "Can't use --gen-suppressions= with this tool,");
1659 VG_(message)(Vg_UserMsg,
1660 "as it doesn't generate errors.");
1661 VG_(bad_option)("--gen-suppressions=");
1662 }
1663
sewardj71bc3cb2005-05-19 00:25:45 +00001664 /* If we've been asked to emit XML, mash around various other
1665 options so as to constrain the output somewhat, and to remove
1666 any need for user input during the run. */
1667 if (VG_(clo_xml)) {
1668 /* Disable suppression generation (requires user input) */
1669 VG_(clo_gen_suppressions) = 0;
1670 /* Disable attaching to GDB (requires user input) */
1671 VG_(clo_db_attach) = False;
1672 /* Set a known verbosity level */
1673 VG_(clo_verbosity) = 1;
1674 /* Disable error limits (this might be a bad idea!) */
1675 VG_(clo_error_limit) = False;
1676 /* Disable emulation warnings */
1677 VG_(clo_show_emwarns) = False;
1678 /* Disable waiting for GDB to debug Valgrind */
1679 VG_(clo_wait_for_gdb) = False;
1680 /* No file-descriptor leak checking yet */
1681 VG_(clo_track_fds) = False;
sewardj21f7f0c2005-07-06 19:46:48 +00001682 /* Disable timestamped output */
1683 VG_(clo_time_stamp) = False;
sewardj71bc3cb2005-05-19 00:25:45 +00001684 /* Also, we want to set options for the leak checker, but that
1685 will have to be done in Memcheck's flag-handling code, not
1686 here. */
1687 }
1688
njnbe9b47b2005-05-15 16:22:58 +00001689 /* All non-logging-related options have been checked. If the logging
1690 option specified is ok, we can switch to it, as we know we won't
1691 have to generate any other command-line-related error messages.
1692 (So far we should be still attached to stderr, so we can show on
1693 the terminal any problems to do with processing command line
1694 opts.)
1695
1696 So set up logging now. After this is done, VG_(clo_log_fd)
sewardj4cf05692002-10-27 20:28:29 +00001697 should be connected to whatever sink has been selected, and we
1698 indiscriminately chuck stuff into it without worrying what the
1699 nature of it is. Oh the wonder of Unix streams. */
1700
njnbe9b47b2005-05-15 16:22:58 +00001701 vg_assert(VG_(clo_log_fd) == 2 /* stderr */);
1702 vg_assert(VG_(logging_to_socket) == False);
sewardj4cf05692002-10-27 20:28:29 +00001703
njnbe9b47b2005-05-15 16:22:58 +00001704 switch (log_to) {
sewardj73cf3bc2002-11-03 03:20:15 +00001705
sewardj4cf05692002-10-27 20:28:29 +00001706 case VgLogTo_Fd:
nethercotef8548672004-06-21 12:42:35 +00001707 vg_assert(VG_(clo_log_name) == NULL);
1708 VG_(clo_log_fd) = eventually_log_fd;
sewardj4cf05692002-10-27 20:28:29 +00001709 break;
sewardj73cf3bc2002-11-03 03:20:15 +00001710
sewardj4cf05692002-10-27 20:28:29 +00001711 case VgLogTo_File: {
sewardjad311162005-07-19 11:25:02 +00001712 HChar logfilename[1000];
1713 Int seq = 0;
1714 Int pid = VG_(getpid)();
1715 HChar* qual = NULL;
jsgff3c3f1a2003-10-14 22:13:28 +00001716
nethercotef8548672004-06-21 12:42:35 +00001717 vg_assert(VG_(clo_log_name) != NULL);
1718 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
jsgff3c3f1a2003-10-14 22:13:28 +00001719
sewardjad311162005-07-19 11:25:02 +00001720 if (VG_(clo_log_file_qualifier)) {
1721 qual = VG_(getenv)(VG_(clo_log_file_qualifier));
1722 }
1723
nethercote71980f02004-01-24 18:18:54 +00001724 for (;;) {
sewardj92645592005-07-23 09:18:34 +00001725 HChar pidtxt[20], seqtxt[20];
1726
1727 VG_(sprintf)(pidtxt, "%d", pid);
1728
1729 if (seq == 0)
1730 seqtxt[0] = 0;
1731 else
1732 VG_(sprintf)(seqtxt, ".%d", seq);
1733
jsgff3c3f1a2003-10-14 22:13:28 +00001734 seq++;
1735
sewardj92645592005-07-23 09:18:34 +00001736 /* Result:
1737 if (qual) base_name ++ "." ++ qual ++ seqtxt
1738 if (not qual) base_name ++ "." ++ pid ++ seqtxt
1739 */
1740 VG_(sprintf)( logfilename,
1741 "%s.%s%s",
1742 VG_(clo_log_name),
1743 qual ? qual : pidtxt,
1744 seqtxt );
1745
njnbe9b47b2005-05-15 16:22:58 +00001746 // EXCL: it will fail with EEXIST if the file already exists.
sewardj92645592005-07-23 09:18:34 +00001747 sres
jsgff3c3f1a2003-10-14 22:13:28 +00001748 = VG_(open)(logfilename,
1749 VKI_O_CREAT|VKI_O_WRONLY|VKI_O_EXCL|VKI_O_TRUNC,
1750 VKI_S_IRUSR|VKI_S_IWUSR);
sewardj92645592005-07-23 09:18:34 +00001751 if (!sres.isError) {
1752 eventually_log_fd = sres.val;
nethercotef8548672004-06-21 12:42:35 +00001753 VG_(clo_log_fd) = VG_(safe_fd)(eventually_log_fd);
sewardj603d4102005-01-11 14:01:02 +00001754 break; /* for (;;) */
jsgff3c3f1a2003-10-14 22:13:28 +00001755 } else {
njnbe9b47b2005-05-15 16:22:58 +00001756 // If the file already existed, we try the next name. If it
1757 // was some other file error, we give up.
sewardj92645592005-07-23 09:18:34 +00001758 if (sres.val != VKI_EEXIST) {
jsgff3c3f1a2003-10-14 22:13:28 +00001759 VG_(message)(Vg_UserMsg,
njn02bc4b82005-05-15 17:28:26 +00001760 "Can't create/open log file '%s.pid%d'; giving up!",
nethercotef8548672004-06-21 12:42:35 +00001761 VG_(clo_log_name), pid);
jsgff3c3f1a2003-10-14 22:13:28 +00001762 VG_(bad_option)(
sewardj603d4102005-01-11 14:01:02 +00001763 "--log-file=<file> (didn't work out for some reason.)");
njnbe9b47b2005-05-15 16:22:58 +00001764 /*NOTREACHED*/
jsgff3c3f1a2003-10-14 22:13:28 +00001765 }
1766 }
1767 }
sewardj603d4102005-01-11 14:01:02 +00001768 break; /* switch (VG_(clo_log_to)) */
1769 }
1770
1771 case VgLogTo_FileExactly: {
sewardj603d4102005-01-11 14:01:02 +00001772 vg_assert(VG_(clo_log_name) != NULL);
1773 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
sewardj603d4102005-01-11 14:01:02 +00001774
sewardj92645592005-07-23 09:18:34 +00001775 sres
njnbe9b47b2005-05-15 16:22:58 +00001776 = VG_(open)(VG_(clo_log_name),
sewardj603d4102005-01-11 14:01:02 +00001777 VKI_O_CREAT|VKI_O_WRONLY|VKI_O_TRUNC,
1778 VKI_S_IRUSR|VKI_S_IWUSR);
sewardj92645592005-07-23 09:18:34 +00001779 if (!sres.isError) {
1780 eventually_log_fd = sres.val;
sewardj603d4102005-01-11 14:01:02 +00001781 VG_(clo_log_fd) = VG_(safe_fd)(eventually_log_fd);
njnbe9b47b2005-05-15 16:22:58 +00001782 } else {
sewardj603d4102005-01-11 14:01:02 +00001783 VG_(message)(Vg_UserMsg,
njn02bc4b82005-05-15 17:28:26 +00001784 "Can't create/open log file '%s'; giving up!",
sewardj603d4102005-01-11 14:01:02 +00001785 VG_(clo_log_name));
1786 VG_(bad_option)(
1787 "--log-file-exactly=<file> (didn't work out for some reason.)");
1788 /*NOTREACHED*/
1789 }
1790 break; /* switch (VG_(clo_log_to)) */
sewardj73cf3bc2002-11-03 03:20:15 +00001791 }
1792
1793 case VgLogTo_Socket: {
nethercotef8548672004-06-21 12:42:35 +00001794 vg_assert(VG_(clo_log_name) != NULL);
1795 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
1796 eventually_log_fd = VG_(connect_via_socket)( VG_(clo_log_name) );
1797 if (eventually_log_fd == -1) {
sewardj73cf3bc2002-11-03 03:20:15 +00001798 VG_(message)(Vg_UserMsg,
nethercotef8548672004-06-21 12:42:35 +00001799 "Invalid --log-socket=ipaddr or --log-socket=ipaddr:port spec");
sewardj73cf3bc2002-11-03 03:20:15 +00001800 VG_(message)(Vg_UserMsg,
njn02bc4b82005-05-15 17:28:26 +00001801 "of '%s'; giving up!", VG_(clo_log_name) );
sewardj73cf3bc2002-11-03 03:20:15 +00001802 VG_(bad_option)(
nethercotef8548672004-06-21 12:42:35 +00001803 "--log-socket=");
njnbe9b47b2005-05-15 16:22:58 +00001804 /*NOTREACHED*/
sewardj4cf05692002-10-27 20:28:29 +00001805 }
nethercotef8548672004-06-21 12:42:35 +00001806 if (eventually_log_fd == -2) {
sewardj73cf3bc2002-11-03 03:20:15 +00001807 VG_(message)(Vg_UserMsg,
njn02bc4b82005-05-15 17:28:26 +00001808 "valgrind: failed to connect to logging server '%s'.",
nethercotef8548672004-06-21 12:42:35 +00001809 VG_(clo_log_name) );
sewardj570f8902002-11-03 11:44:36 +00001810 VG_(message)(Vg_UserMsg,
1811 "Log messages will sent to stderr instead." );
1812 VG_(message)(Vg_UserMsg,
1813 "" );
1814 /* We don't change anything here. */
njnbe9b47b2005-05-15 16:22:58 +00001815 vg_assert(VG_(clo_log_fd) == 2);
sewardj570f8902002-11-03 11:44:36 +00001816 } else {
nethercotef8548672004-06-21 12:42:35 +00001817 vg_assert(eventually_log_fd > 0);
1818 VG_(clo_log_fd) = eventually_log_fd;
njnbe9b47b2005-05-15 16:22:58 +00001819 VG_(logging_to_socket) = True;
sewardj570f8902002-11-03 11:44:36 +00001820 }
sewardj73cf3bc2002-11-03 03:20:15 +00001821 break;
1822 }
sewardj4cf05692002-10-27 20:28:29 +00001823 }
1824
sewardj71bc3cb2005-05-19 00:25:45 +00001825
1826 /* Check that the requested tool actually supports XML output. */
cerion39655202005-07-13 14:18:24 +00001827 if (VG_(clo_xml) && 0 != VG_(strcmp)(toolname, "memcheck")
1828 && 0 != VG_(strcmp)(toolname, "none")) {
sewardj71bc3cb2005-05-19 00:25:45 +00001829 VG_(clo_xml) = False;
1830 VG_(message)(Vg_UserMsg,
cerion39655202005-07-13 14:18:24 +00001831 "Currently only Memcheck|None supports XML output.");
sewardj71bc3cb2005-05-19 00:25:45 +00001832 VG_(bad_option)("--xml=yes");
1833 /*NOTREACHED*/
1834 }
1835
njnbe9b47b2005-05-15 16:22:58 +00001836 // Move log_fd into the safe range, so it doesn't conflict with any app fds.
1837 // XXX: this is more or less duplicating the behaviour of the calls to
1838 // VG_(safe_fd)() above, although this does not close the original fd.
1839 // Perhaps the VG_(safe_fd)() calls above should be removed, and this
1840 // code should be replaced with a call to VG_(safe_fd)(). --njn
thughesad1c9562004-06-26 11:27:52 +00001841 eventually_log_fd = VG_(fcntl)(VG_(clo_log_fd), VKI_F_DUPFD, VG_(fd_hard_limit));
nethercotef8548672004-06-21 12:42:35 +00001842 if (eventually_log_fd < 0)
jsgf855d93d2003-10-13 22:26:55 +00001843 VG_(message)(Vg_UserMsg, "valgrind: failed to move logfile fd into safe range");
1844 else {
nethercotef8548672004-06-21 12:42:35 +00001845 VG_(clo_log_fd) = eventually_log_fd;
1846 VG_(fcntl)(VG_(clo_log_fd), VKI_F_SETFD, VKI_FD_CLOEXEC);
jsgf855d93d2003-10-13 22:26:55 +00001847 }
1848
sewardj4cf05692002-10-27 20:28:29 +00001849 /* Ok, the logging sink is running now. Print a suitable preamble.
1850 If logging to file or a socket, write details of parent PID and
1851 command line args, to help people trying to interpret the
1852 results of a run which encompasses multiple processes. */
sewardjde4a1d02002-03-22 01:27:54 +00001853
sewardj71bc3cb2005-05-19 00:25:45 +00001854 if (VG_(clo_xml)) {
sewardj8665d8e2005-06-01 17:35:23 +00001855 VG_(message)(Vg_UserMsg, "<?xml version=\"1.0\"?>");
1856 VG_(message)(Vg_UserMsg, "");
sewardj71bc3cb2005-05-19 00:25:45 +00001857 VG_(message)(Vg_UserMsg, "<valgrindoutput>");
1858 VG_(message)(Vg_UserMsg, "");
1859 VG_(message)(Vg_UserMsg, "<protocolversion>1</protocolversion>");
1860 VG_(message)(Vg_UserMsg, "");
1861 }
1862
sewardjd7bddad2005-06-13 16:48:32 +00001863 HChar* xpre = VG_(clo_xml) ? " <line>" : "";
1864 HChar* xpost = VG_(clo_xml) ? "</line>" : "";
sewardj71bc3cb2005-05-19 00:25:45 +00001865
sewardj83adf412002-05-01 01:25:45 +00001866 if (VG_(clo_verbosity > 0)) {
sewardjd7bddad2005-06-13 16:48:32 +00001867
1868 if (VG_(clo_xml))
1869 VG_(message)(Vg_UserMsg, "<preamble>");
1870
nethercote996901a2004-08-03 13:29:09 +00001871 /* Tool details */
sewardj71bc3cb2005-05-19 00:25:45 +00001872 VG_(message)(Vg_UserMsg, "%s%s%s%s, %s.%s",
1873 xpre,
njnd04b7c62002-10-03 14:05:52 +00001874 VG_(details).name,
njnb9c427c2004-12-01 14:14:42 +00001875 NULL == VG_(details).version ? "" : "-",
njnd04b7c62002-10-03 14:05:52 +00001876 NULL == VG_(details).version
1877 ? (Char*)"" : VG_(details).version,
sewardj71bc3cb2005-05-19 00:25:45 +00001878 VG_(details).description,
1879 xpost);
1880 VG_(message)(Vg_UserMsg, "%s%s%s",
1881 xpre, VG_(details).copyright_author, xpost);
sewardj3b2736a2002-03-24 12:18:35 +00001882
njnd04b7c62002-10-03 14:05:52 +00001883 /* Core details */
1884 VG_(message)(Vg_UserMsg,
sewardj71bc3cb2005-05-19 00:25:45 +00001885 "%sUsing LibVEX rev %s, a library for dynamic binary translation.%s",
1886 xpre, LibVEX_Version(), xpost );
sewardjc7025332004-12-13 18:30:39 +00001887 VG_(message)(Vg_UserMsg,
sewardj71bc3cb2005-05-19 00:25:45 +00001888 "%sCopyright (C) 2004-2005, and GNU GPL'd, by OpenWorks LLP.%s",
1889 xpre, xpost );
sewardjc7025332004-12-13 18:30:39 +00001890 VG_(message)(Vg_UserMsg,
sewardj71bc3cb2005-05-19 00:25:45 +00001891 "%sUsing valgrind-%s, a dynamic binary instrumentation framework.%s",
1892 xpre, VERSION, xpost);
sewardjde4a1d02002-03-22 01:27:54 +00001893 VG_(message)(Vg_UserMsg,
sewardj71bc3cb2005-05-19 00:25:45 +00001894 "%sCopyright (C) 2000-2005, and GNU GPL'd, by Julian Seward et al.%s",
1895 xpre, xpost );
sewardjd7bddad2005-06-13 16:48:32 +00001896
1897 if (VG_(clo_xml))
1898 VG_(message)(Vg_UserMsg, "</preamble>");
njnd04b7c62002-10-03 14:05:52 +00001899 }
1900
sewardjd94b90a2005-06-29 23:15:56 +00001901 if (!VG_(clo_xml) && VG_(clo_verbosity) > 0 && log_to != VgLogTo_Fd) {
sewardj4cf05692002-10-27 20:28:29 +00001902 VG_(message)(Vg_UserMsg, "");
1903 VG_(message)(Vg_UserMsg,
1904 "My PID = %d, parent PID = %d. Prog and args are:",
1905 VG_(getpid)(), VG_(getppid)() );
1906 for (i = 0; i < VG_(client_argc); i++)
1907 VG_(message)(Vg_UserMsg, " %s", VG_(client_argv)[i]);
sewardj5b742c32005-07-26 23:43:26 +00001908 if (VG_(clo_log_file_qualifier)) {
1909 HChar* val = VG_(getenv)(VG_(clo_log_file_qualifier));
1910 VG_(message)(Vg_UserMsg, "");
1911 VG_(message)(Vg_UserMsg, "Log file qualifier: var %s, value %s.",
1912 VG_(clo_log_file_qualifier),
1913 val ? val : "");
1914 }
sewardj4cf05692002-10-27 20:28:29 +00001915 }
sewardj71bc3cb2005-05-19 00:25:45 +00001916 else
1917 if (VG_(clo_xml)) {
1918 VG_(message)(Vg_UserMsg, "");
1919 VG_(message)(Vg_UserMsg, "<pid>%d</pid>", VG_(getpid)());
1920 VG_(message)(Vg_UserMsg, "<ppid>%d</ppid>", VG_(getppid)());
sewardj97f7e0c2005-07-19 15:00:25 +00001921 VG_(message)(Vg_UserMsg, "<tool>%t</tool>", toolname);
sewardjad311162005-07-19 11:25:02 +00001922 if (VG_(clo_log_file_qualifier)) {
1923 HChar* val = VG_(getenv)(VG_(clo_log_file_qualifier));
sewardj97f7e0c2005-07-19 15:00:25 +00001924 VG_(message)(Vg_UserMsg, "<logfilequalifier> <var>%t</var> "
1925 "<value>%t</value> </logfilequalifier>",
sewardjad311162005-07-19 11:25:02 +00001926 VG_(clo_log_file_qualifier),
1927 val ? val : "");
1928 }
sewardj768db0e2005-07-19 14:18:56 +00001929 if (VG_(clo_xml_user_comment)) {
1930 /* Note: the user comment itself is XML and is therefore to
1931 be passed through verbatim (%s) rather than escaped
1932 (%t). */
1933 VG_(message)(Vg_UserMsg, "<usercomment>%s</usercomment>",
1934 VG_(clo_xml_user_comment));
1935 }
sewardj71bc3cb2005-05-19 00:25:45 +00001936 VG_(message)(Vg_UserMsg, "");
sewardjb8a3dac2005-07-19 12:39:11 +00001937 VG_(message)(Vg_UserMsg, "<args>");
1938 VG_(message)(Vg_UserMsg, " <vargv>");
1939 for (i = 0; i < vg_argc; i++) {
1940 HChar* tag = i==0 ? "exe" : "arg";
sewardj768db0e2005-07-19 14:18:56 +00001941 VG_(message)(Vg_UserMsg, " <%s>%t</%s>",
sewardjb8a3dac2005-07-19 12:39:11 +00001942 tag, vg_argv[i], tag);
1943 }
1944 VG_(message)(Vg_UserMsg, " </vargv>");
1945 VG_(message)(Vg_UserMsg, " <argv>");
sewardj8665d8e2005-06-01 17:35:23 +00001946 for (i = 0; i < VG_(client_argc); i++) {
1947 HChar* tag = i==0 ? "exe" : "arg";
sewardj97f7e0c2005-07-19 15:00:25 +00001948 VG_(message)(Vg_UserMsg, " <%s>%t</%s>",
sewardj8665d8e2005-06-01 17:35:23 +00001949 tag, VG_(client_argv)[i], tag);
1950 }
sewardjb8a3dac2005-07-19 12:39:11 +00001951 VG_(message)(Vg_UserMsg, " </argv>");
1952 VG_(message)(Vg_UserMsg, "</args>");
sewardj71bc3cb2005-05-19 00:25:45 +00001953 }
sewardj4cf05692002-10-27 20:28:29 +00001954
sewardjde4a1d02002-03-22 01:27:54 +00001955 if (VG_(clo_verbosity) > 1) {
sewardj92645592005-07-23 09:18:34 +00001956 SysRes fd;
njnbe9b47b2005-05-15 16:22:58 +00001957 if (log_to != VgLogTo_Fd)
njn1fd5eb22005-03-13 05:43:23 +00001958 VG_(message)(Vg_DebugMsg, "");
1959 VG_(message)(Vg_DebugMsg, "Valgrind library directory: %s", VG_(libdir));
1960 VG_(message)(Vg_DebugMsg, "Command line");
njn86dc2bc2003-09-09 07:26:21 +00001961 for (i = 0; i < VG_(client_argc); i++)
njn1fd5eb22005-03-13 05:43:23 +00001962 VG_(message)(Vg_DebugMsg, " %s", VG_(client_argv)[i]);
njn86dc2bc2003-09-09 07:26:21 +00001963
njn1fd5eb22005-03-13 05:43:23 +00001964 VG_(message)(Vg_DebugMsg, "Startup, with flags:");
nethercotef6a1d502004-08-09 12:21:57 +00001965 for (i = 1; i < vg_argc; i++) {
njn1fd5eb22005-03-13 05:43:23 +00001966 VG_(message)(Vg_DebugMsg, " %s", vg_argv[i]);
sewardjde4a1d02002-03-22 01:27:54 +00001967 }
nethercotea70f7352004-04-18 12:08:46 +00001968
njn1fd5eb22005-03-13 05:43:23 +00001969 VG_(message)(Vg_DebugMsg, "Contents of /proc/version:");
nethercotea70f7352004-04-18 12:08:46 +00001970 fd = VG_(open) ( "/proc/version", VKI_O_RDONLY, 0 );
sewardj92645592005-07-23 09:18:34 +00001971 if (fd.isError) {
njn1fd5eb22005-03-13 05:43:23 +00001972 VG_(message)(Vg_DebugMsg, " can't open /proc/version");
nethercotea70f7352004-04-18 12:08:46 +00001973 } else {
sewardj71bc3cb2005-05-19 00:25:45 +00001974# define BUF_LEN 256
nethercotea70f7352004-04-18 12:08:46 +00001975 Char version_buf[BUF_LEN];
sewardj92645592005-07-23 09:18:34 +00001976 Int n = VG_(read) ( fd.val, version_buf, BUF_LEN );
njnbe9b47b2005-05-15 16:22:58 +00001977 vg_assert(n <= BUF_LEN);
nethercotea70f7352004-04-18 12:08:46 +00001978 if (n > 0) {
1979 version_buf[n-1] = '\0';
njn1fd5eb22005-03-13 05:43:23 +00001980 VG_(message)(Vg_DebugMsg, " %s", version_buf);
nethercotea70f7352004-04-18 12:08:46 +00001981 } else {
njn1fd5eb22005-03-13 05:43:23 +00001982 VG_(message)(Vg_DebugMsg, " (empty?)");
nethercotea70f7352004-04-18 12:08:46 +00001983 }
sewardj92645592005-07-23 09:18:34 +00001984 VG_(close)(fd.val);
sewardj71bc3cb2005-05-19 00:25:45 +00001985# undef BUF_LEN
nethercotea70f7352004-04-18 12:08:46 +00001986 }
sewardjde4a1d02002-03-22 01:27:54 +00001987 }
1988
fitzhardinge98abfc72003-12-16 02:05:15 +00001989 if (VG_(clo_n_suppressions) < VG_CLO_MAX_SFILES-1 &&
njn95ec8702004-11-22 16:46:13 +00001990 (VG_(needs).core_errors || VG_(needs).tool_errors)) {
njn842c26e2005-06-28 02:54:52 +00001991 /* If we haven't reached the max number of suppressions, load
1992 the default one. */
fitzhardinge98abfc72003-12-16 02:05:15 +00001993 static const Char default_supp[] = "default.supp";
1994 Int len = VG_(strlen)(VG_(libdir)) + 1 + sizeof(default_supp);
1995 Char *buf = VG_(arena_malloc)(VG_AR_CORE, len);
1996 VG_(sprintf)(buf, "%s/%s", VG_(libdir), default_supp);
1997 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = buf;
1998 VG_(clo_n_suppressions)++;
sewardjde4a1d02002-03-22 01:27:54 +00001999 }
2000}
2001
nethercotef6a1d502004-08-09 12:21:57 +00002002// Build the string for VALGRINDCLO.
2003Char* VG_(build_child_VALGRINDCLO)( Char* exename )
2004{
2005 /* If we're tracing the children, then we need to start it
2006 with our starter+arguments, which are copied into VALGRINDCLO,
2007 except the --exec= option is changed if present.
2008 */
2009 Int i;
2010 Char *exec;
2011 Char *cp;
2012 Char *optvar;
2013 Int optlen, execlen;
2014
2015 // All these allocated blocks are not free - because we're either
2016 // going to exec, or panic when we fail.
2017
2018 // Create --exec= option: "--exec=<exename>"
2019 exec = VG_(arena_malloc)(VG_AR_CORE,
2020 VG_(strlen)( exename ) + 7/*--exec=*/ + 1/*\0*/);
2021 vg_assert(NULL != exec);
2022 VG_(sprintf)(exec, "--exec=%s", exename);
2023
2024 // Allocate space for optvar (may overestimate by counting --exec twice,
2025 // no matter)
2026 optlen = 1;
2027 for (i = 0; i < vg_argc; i++)
2028 optlen += VG_(strlen)(vg_argv[i]) + 1;
2029 optlen += VG_(strlen)(exec)+1;
2030 optvar = VG_(arena_malloc)(VG_AR_CORE, optlen);
2031
2032 // Copy all valgrind args except the old --exec (if present)
2033 // VG_CLO_SEP is the separator.
2034 cp = optvar;
2035 for (i = 1; i < vg_argc; i++) {
2036 Char *arg = vg_argv[i];
2037
2038 if (VG_(memcmp)(arg, "--exec=", 7) == 0) {
2039 // don't copy existing --exec= arg
2040 } else if (VG_(strcmp)(arg, "--") == 0) {
2041 // stop at "--"
2042 break;
2043 } else {
2044 // copy non "--exec" arg
2045 Int len = VG_(strlen)(arg);
2046 VG_(memcpy)(cp, arg, len);
2047 cp += len;
2048 *cp++ = VG_CLO_SEP;
2049 }
2050 }
2051 // Add the new --exec= option
2052 execlen = VG_(strlen)(exec);
2053 VG_(memcpy)(cp, exec, execlen);
2054 cp += execlen;
2055 *cp++ = VG_CLO_SEP;
2056
2057 *cp = '\0';
2058
2059 return optvar;
2060}
2061
2062// Build "/proc/self/fd/<execfd>".
2063Char* VG_(build_child_exename)( void )
2064{
2065 Char* exename = VG_(arena_malloc)(VG_AR_CORE, 64);
2066 vg_assert(NULL != exename);
2067 VG_(sprintf)(exename, "/proc/self/fd/%d", vgexecfd);
2068 return exename;
2069}
2070
sewardjde4a1d02002-03-22 01:27:54 +00002071
nethercote71980f02004-01-24 18:18:54 +00002072/*====================================================================*/
2073/*=== File descriptor setup ===*/
2074/*====================================================================*/
2075
2076static void setup_file_descriptors(void)
2077{
2078 struct vki_rlimit rl;
2079
2080 /* Get the current file descriptor limits. */
2081 if (VG_(getrlimit)(VKI_RLIMIT_NOFILE, &rl) < 0) {
2082 rl.rlim_cur = 1024;
2083 rl.rlim_max = 1024;
2084 }
2085
2086 /* Work out where to move the soft limit to. */
njn14319cc2005-03-13 06:26:22 +00002087 if (rl.rlim_cur + N_RESERVED_FDS <= rl.rlim_max) {
2088 rl.rlim_cur = rl.rlim_cur + N_RESERVED_FDS;
nethercote71980f02004-01-24 18:18:54 +00002089 } else {
2090 rl.rlim_cur = rl.rlim_max;
2091 }
2092
2093 /* Reserve some file descriptors for our use. */
njn14319cc2005-03-13 06:26:22 +00002094 VG_(fd_soft_limit) = rl.rlim_cur - N_RESERVED_FDS;
2095 VG_(fd_hard_limit) = rl.rlim_cur - N_RESERVED_FDS;
nethercote71980f02004-01-24 18:18:54 +00002096
2097 /* Update the soft limit. */
2098 VG_(setrlimit)(VKI_RLIMIT_NOFILE, &rl);
2099
nethercotef6a1d502004-08-09 12:21:57 +00002100 if (vgexecfd != -1)
2101 vgexecfd = VG_(safe_fd)( vgexecfd );
nethercote71980f02004-01-24 18:18:54 +00002102 if (VG_(clexecfd) != -1)
2103 VG_(clexecfd) = VG_(safe_fd)( VG_(clexecfd) );
2104}
2105
nethercote71980f02004-01-24 18:18:54 +00002106/*====================================================================*/
nethercote71980f02004-01-24 18:18:54 +00002107/*=== Initialise program data/text, etc. ===*/
2108/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +00002109
sewardjb5f6f512005-03-10 23:59:00 +00002110static void build_valgrind_map_callback ( Addr start, SizeT size, UInt prot,
2111 UInt dev, UInt ino, ULong foffset,
2112 const UChar* filename )
sewardjde4a1d02002-03-22 01:27:54 +00002113{
nethercote71980f02004-01-24 18:18:54 +00002114 /* Only record valgrind mappings for now, without loading any
2115 symbols. This is so we know where the free space is before we
2116 start allocating more memory (note: heap is OK, it's just mmap
2117 which is the problem here). */
sewardjb5f6f512005-03-10 23:59:00 +00002118 if (start >= VG_(client_end) && start < VG_(valgrind_last)) {
sewardj8c615892005-04-25 02:38:28 +00002119 VG_(debugLog)(2, "main",
2120 "valgrind-seg: %p-%p prot 0x%x file=%s\n",
njna4469a72005-05-08 02:06:33 +00002121 (void*)start, (void*)(start+size), prot, filename);
sewardjb5f6f512005-03-10 23:59:00 +00002122 VG_(map_file_segment)(start, size, prot,
sewardj8c615892005-04-25 02:38:28 +00002123 SF_MMAP|SF_NOSYMS|SF_VALGRIND,
2124 dev, ino, foffset, filename);
sewardjb5f6f512005-03-10 23:59:00 +00002125 /* update VG_(valgrind_last) if it looks wrong */
2126 if (start+size > VG_(valgrind_last))
sewardj8c615892005-04-25 02:38:28 +00002127 VG_(valgrind_last) = start+size-1;
nethercote71980f02004-01-24 18:18:54 +00002128 }
sewardjde4a1d02002-03-22 01:27:54 +00002129}
2130
nethercote71980f02004-01-24 18:18:54 +00002131// Global var used to pass local data to callback
nethercote4ad74312004-10-26 09:59:49 +00002132Addr sp_at_startup___global_arg = 0;
sewardjde4a1d02002-03-22 01:27:54 +00002133
sewardjb5f6f512005-03-10 23:59:00 +00002134/*
2135 This second pass adds in client mappings, and loads symbol tables
2136 for all interesting mappings. The trouble is that things can
2137 change as we go, because we're calling the Tool to track memory as
2138 we find it.
2139
2140 So for Valgrind mappings, we don't replace any mappings which
2141 aren't still identical (which will include the .so mappings, so we
2142 will load their symtabs)>
2143 */
2144static void build_segment_map_callback ( Addr start, SizeT size, UInt prot,
2145 UInt dev, UInt ino, ULong foffset,
2146 const UChar* filename )
sewardj45b672d2003-07-25 19:58:11 +00002147{
nethercote71980f02004-01-24 18:18:54 +00002148 UInt flags;
2149 Bool is_stack_segment;
2150 Addr r_esp;
sewardj45b672d2003-07-25 19:58:11 +00002151
nethercote71980f02004-01-24 18:18:54 +00002152 is_stack_segment
2153 = (start == VG_(clstk_base) && (start+size) == VG_(clstk_end));
fitzhardinge98abfc72003-12-16 02:05:15 +00002154
sewardj8c615892005-04-25 02:38:28 +00002155 VG_(debugLog)(2, "main",
2156 "any-seg: %p-%p prot 0x%x stack=%d file=%s\n",
njna4469a72005-05-08 02:06:33 +00002157 (void*)start, (void*)(start+size), prot, is_stack_segment,
2158 filename);
fitzhardinge98abfc72003-12-16 02:05:15 +00002159
nethercote71980f02004-01-24 18:18:54 +00002160 if (is_stack_segment)
2161 flags = SF_STACK | SF_GROWDOWN;
2162 else
njn0ae787c2005-06-28 22:14:53 +00002163 flags = SF_MMAP;
fitzhardinge98abfc72003-12-16 02:05:15 +00002164
nethercote71980f02004-01-24 18:18:54 +00002165 if (filename != NULL)
2166 flags |= SF_FILE;
fitzhardinge98abfc72003-12-16 02:05:15 +00002167
sewardjb5f6f512005-03-10 23:59:00 +00002168#if 0
2169 // This needs to be fixed properly. jrs 20050307
2170 if (start >= VG_(client_end) && start < VG_(valgrind_last)) {
2171 Segment *s = VG_(find_segment_before)(start);
fitzhardinge98abfc72003-12-16 02:05:15 +00002172
sewardjb5f6f512005-03-10 23:59:00 +00002173 /* We have to be a bit careful about inserting new mappings into
2174 the Valgrind part of the address space. We're actively
2175 changing things as we parse these mappings, particularly in
2176 shadow memory, and so we don't want to overwrite those
2177 changes. Therefore, we only insert/update a mapping if it is
2178 mapped from a file or it exactly matches an existing mapping.
fitzhardinge98abfc72003-12-16 02:05:15 +00002179
sewardjb5f6f512005-03-10 23:59:00 +00002180 NOTE: we're only talking about the Segment list mapping
2181 metadata; this doesn't actually mmap anything more. */
2182 if (filename || (s && s->addr == start && s->len == size)) {
2183 flags |= SF_VALGRIND;
2184 VG_(map_file_segment)(start, size, prot, flags, dev, ino, foffset, filename);
2185 } else {
2186 /* assert range is already mapped */
2187 vg_assert(VG_(is_addressable)(start, size, VKI_PROT_NONE));
2188 }
2189 } else
2190#endif
2191 VG_(map_file_segment)(start, size, prot, flags, dev, ino, foffset, filename);
2192
2193 if (VG_(is_client_addr)(start) && VG_(is_client_addr)(start+size-1)) {
2194 VG_TRACK( new_mem_startup, start, size,
2195 !!(prot & VKI_PROT_READ),
2196 !!(prot & VKI_PROT_WRITE),
2197 !!(prot & VKI_PROT_EXEC));
2198 }
sewardj3e1eb1f2002-05-18 13:14:17 +00002199
nethercote71980f02004-01-24 18:18:54 +00002200 /* If this is the stack segment mark all below %esp as noaccess. */
nethercote4ad74312004-10-26 09:59:49 +00002201 r_esp = sp_at_startup___global_arg;
nethercote71980f02004-01-24 18:18:54 +00002202 vg_assert(0 != r_esp);
2203 if (is_stack_segment) {
sewardjb5f6f512005-03-10 23:59:00 +00002204 if (0) {
2205 VG_(message)(Vg_DebugMsg, "invalidating stack area: %p .. %p",
nethercote71980f02004-01-24 18:18:54 +00002206 start,r_esp);
sewardjb5f6f512005-03-10 23:59:00 +00002207 VG_(message)(Vg_DebugMsg, " validating stack area: %p .. %p",
2208 r_esp, start+size);
2209 }
nethercote71980f02004-01-24 18:18:54 +00002210 VG_TRACK( die_mem_stack, start, r_esp-start );
sewardjb5f6f512005-03-10 23:59:00 +00002211 // what's this for?
2212 //VG_TRACK( post_mem_write, r_esp, (start+size)-r_esp );
sewardjde4a1d02002-03-22 01:27:54 +00002213 }
sewardjde4a1d02002-03-22 01:27:54 +00002214}
2215
njn2da73352005-06-18 01:35:16 +00002216/*====================================================================*/
2217/*=== Initialise the first thread. ===*/
2218/*====================================================================*/
2219
2220/* Given a pointer to the ThreadArchState for thread 1 (the root
2221 thread), initialise the VEX guest state, and copy in essential
2222 starting values.
2223*/
2224static void init_thread1state ( Addr client_ip,
2225 Addr sp_at_startup,
2226 /*inout*/ ThreadArchState* arch )
2227{
2228#if defined(VGA_x86)
2229 vg_assert(0 == sizeof(VexGuestX86State) % 8);
2230
2231 /* Zero out the initial state, and set up the simulated FPU in a
2232 sane way. */
2233 LibVEX_GuestX86_initialise(&arch->vex);
2234
2235 /* Zero out the shadow area. */
2236 VG_(memset)(&arch->vex_shadow, 0, sizeof(VexGuestX86State));
2237
2238 /* Put essential stuff into the new state. */
2239 arch->vex.guest_ESP = sp_at_startup;
2240 arch->vex.guest_EIP = client_ip;
2241
2242 /* initialise %cs, %ds and %ss to point at the operating systems
2243 default code, data and stack segments */
2244 asm volatile("movw %%cs, %0" : : "m" (arch->vex.guest_CS));
2245 asm volatile("movw %%ds, %0" : : "m" (arch->vex.guest_DS));
2246 asm volatile("movw %%ss, %0" : : "m" (arch->vex.guest_SS));
cerion85665ca2005-06-20 15:51:07 +00002247
njn2da73352005-06-18 01:35:16 +00002248#elif defined(VGA_amd64)
2249 vg_assert(0 == sizeof(VexGuestAMD64State) % 8);
2250
2251 /* Zero out the initial state, and set up the simulated FPU in a
2252 sane way. */
2253 LibVEX_GuestAMD64_initialise(&arch->vex);
2254
2255 /* Zero out the shadow area. */
2256 VG_(memset)(&arch->vex_shadow, 0, sizeof(VexGuestAMD64State));
2257
2258 /* Put essential stuff into the new state. */
2259 arch->vex.guest_RSP = sp_at_startup;
2260 arch->vex.guest_RIP = client_ip;
cerion85665ca2005-06-20 15:51:07 +00002261
2262#elif defined(VGA_ppc32)
2263 vg_assert(0 == sizeof(VexGuestPPC32State) % 8);
2264
2265 /* Zero out the initial state, and set up the simulated FPU in a
2266 sane way. */
2267 LibVEX_GuestPPC32_initialise(&arch->vex);
2268
2269 /* Zero out the shadow area. */
2270 VG_(memset)(&arch->vex_shadow, 0, sizeof(VexGuestPPC32State));
2271
2272 /* Put essential stuff into the new state. */
2273 arch->vex.guest_GPR1 = sp_at_startup;
2274 arch->vex.guest_CIA = client_ip;
2275
njn2da73352005-06-18 01:35:16 +00002276#else
2277# error Unknown arch
2278#endif
2279 // Tell the tool that we just wrote to the registers.
2280 VG_TRACK( post_reg_write, Vg_CoreStartup, /*tid*/1, /*offset*/0,
2281 sizeof(VexGuestArchState));
2282}
2283
sewardjde4a1d02002-03-22 01:27:54 +00002284
nethercote71980f02004-01-24 18:18:54 +00002285/*====================================================================*/
njn2025cf92005-06-26 20:44:48 +00002286/*=== BB profiling ===*/
2287/*====================================================================*/
2288
2289static
2290void show_BB_profile ( BBProfEntry tops[], UInt n_tops, ULong score_total )
2291{
2292 ULong score_cumul, score_here;
2293 Char buf_cumul[10], buf_here[10];
2294 Char name[64];
2295 Int r;
2296
2297 VG_(printf)("\n");
2298 VG_(printf)("-----------------------------------------------------------\n");
2299 VG_(printf)("--- BEGIN BB Profile (summary of scores) ---\n");
2300 VG_(printf)("-----------------------------------------------------------\n");
2301 VG_(printf)("\n");
2302
2303 VG_(printf)("Total score = %lld\n\n", score_total);
2304
2305 score_cumul = 0;
2306 for (r = 0; r < n_tops; r++) {
2307 if (tops[r].addr == 0)
2308 continue;
2309 name[0] = 0;
2310 VG_(get_fnname_w_offset)(tops[r].addr, name, 64);
2311 name[63] = 0;
2312 score_here = tops[r].score;
2313 score_cumul += score_here;
2314 VG_(percentify)(score_cumul, score_total, 2, 6, buf_cumul);
2315 VG_(percentify)(score_here, score_total, 2, 6, buf_here);
2316 VG_(printf)("%3d: (%9lld %s) %9lld %s 0x%llx %s\n",
2317 r,
2318 score_cumul, buf_cumul,
2319 score_here, buf_here, tops[r].addr, name );
2320 }
2321
2322 VG_(printf)("\n");
2323 VG_(printf)("-----------------------------------------------------------\n");
2324 VG_(printf)("--- BB Profile (BB details) ---\n");
2325 VG_(printf)("-----------------------------------------------------------\n");
2326 VG_(printf)("\n");
2327
2328 score_cumul = 0;
2329 for (r = 0; r < n_tops; r++) {
2330 if (tops[r].addr == 0)
2331 continue;
2332 name[0] = 0;
2333 VG_(get_fnname_w_offset)(tops[r].addr, name, 64);
2334 name[63] = 0;
2335 score_here = tops[r].score;
2336 score_cumul += score_here;
2337 VG_(percentify)(score_cumul, score_total, 2, 6, buf_cumul);
2338 VG_(percentify)(score_here, score_total, 2, 6, buf_here);
2339 VG_(printf)("\n");
2340 VG_(printf)("=-=-=-=-=-=-=-=-=-=-=-=-=-= begin BB rank %d "
2341 "=-=-=-=-=-=-=-=-=-=-=-=-=-=\n\n", r);
2342 VG_(printf)("%3d: (%9lld %s) %9lld %s 0x%llx %s\n",
2343 r,
2344 score_cumul, buf_cumul,
2345 score_here, buf_here, tops[r].addr, name );
2346 VG_(printf)("\n");
2347 VG_(translate)(0, tops[r].addr, True, VG_(clo_profile_flags), 0);
2348 VG_(printf)("=-=-=-=-=-=-=-=-=-=-=-=-=-= end BB rank %d "
2349 "=-=-=-=-=-=-=-=-=-=-=-=-=-=\n\n", r);
2350 }
2351
2352 VG_(printf)("\n");
2353 VG_(printf)("-----------------------------------------------------------\n");
2354 VG_(printf)("--- END BB Profile ---\n");
2355 VG_(printf)("-----------------------------------------------------------\n");
2356 VG_(printf)("\n");
2357}
2358
2359
2360/*====================================================================*/
nethercote71980f02004-01-24 18:18:54 +00002361/*=== main() ===*/
2362/*====================================================================*/
2363
nethercotec314eba2004-07-15 12:59:41 +00002364/*
2365 This code decides on the layout of the client and Valgrind address
nethercote996901a2004-08-03 13:29:09 +00002366 spaces, loads valgrind.so and the tool.so into the valgrind part,
nethercotec314eba2004-07-15 12:59:41 +00002367 loads the client executable (and the dynamic linker, if necessary)
2368 into the client part, and calls into Valgrind proper.
2369
2370 The code is careful not to allow spurious mappings to appear in the
2371 wrong parts of the address space. In particular, to make sure
2372 dlopen puts things in the right place, it will pad out the forbidden
2373 chunks of address space so that dlopen is forced to put things where
2374 we want them.
2375
2376 The memory map it creates is:
2377
njn311c5d82005-05-15 21:03:42 +00002378 client_base +-------------------------+
nethercotec314eba2004-07-15 12:59:41 +00002379 | client address space |
2380 : :
2381 : :
2382 | client stack |
2383 client_end +-------------------------+
2384 | redzone |
2385 shadow_base +-------------------------+
2386 | |
nethercote996901a2004-08-03 13:29:09 +00002387 : shadow memory for tools :
nethercotec314eba2004-07-15 12:59:41 +00002388 | (may be 0 sized) |
2389 shadow_end +-------------------------+
nethercotec314eba2004-07-15 12:59:41 +00002390 valgrind_base +-------------------------+
2391 | kickstart executable |
2392 | valgrind heap vvvvvvvvv| (barely used)
2393 - -
2394 | valgrind .so files |
2395 | and mappings |
2396 - -
2397 | valgrind stack ^^^^^^^^^|
nethercote820bd8c2004-09-07 23:04:49 +00002398 valgrind_last +-------------------------+
nethercotec314eba2004-07-15 12:59:41 +00002399 : kernel :
2400
2401 Nb: Before we can do general allocations with VG_(arena_malloc)() and
2402 VG_(mmap)(), we need to build the segment skip-list, so we know where
2403 we can put things. However, building that structure requires
2404 allocating memory. So we need to a bootstrapping process. It's done
2405 by making VG_(arena_malloc)() have a special static superblock that's
2406 used for the first 1MB's worth of allocations. This is enough to
2407 build the segment skip-list.
2408*/
2409
thughes4ad52d02004-06-27 17:37:21 +00002410
sewardj1cf558c2005-04-25 01:36:56 +00002411/* This may be needed before m_mylibc is OK to run. */
2412static Int local_strcmp ( const HChar* s1, const HChar* s2 )
2413{
2414 while (True) {
2415 if (*s1 == 0 && *s2 == 0) return 0;
2416 if (*s1 == 0) return -1;
2417 if (*s2 == 0) return 1;
2418
2419 if (*(UChar*)s1 < *(UChar*)s2) return -1;
2420 if (*(UChar*)s1 > *(UChar*)s2) return 1;
2421
2422 s1++; s2++;
2423 }
2424}
2425
2426
sewardjb5f6f512005-03-10 23:59:00 +00002427int main(int argc, char **argv, char **envp)
nethercote71980f02004-01-24 18:18:54 +00002428{
2429 char **cl_argv;
sewardjb5f6f512005-03-10 23:59:00 +00002430 const char *tool = "memcheck"; // default to Memcheck
nethercote71980f02004-01-24 18:18:54 +00002431 const char *exec = NULL;
2432 char *preload; /* tool-specific LD_PRELOAD .so */
2433 char **env;
nethercote6c999f22004-01-31 22:55:15 +00002434 Int need_help = 0; // 0 = no, 1 = --help, 2 = --help-debug
nethercote71980f02004-01-24 18:18:54 +00002435 struct exeinfo info;
2436 ToolInfo *toolinfo = NULL;
nethercote71980f02004-01-24 18:18:54 +00002437 Addr client_eip;
nethercote4ad74312004-10-26 09:59:49 +00002438 Addr sp_at_startup; /* client's SP at the point we gained control. */
nethercote71980f02004-01-24 18:18:54 +00002439 UInt * client_auxv;
nethercote73b526f2004-10-31 18:48:21 +00002440 struct vki_rlimit zero = { 0, 0 };
sewardj1cf558c2005-04-25 01:36:56 +00002441 Int padfile, loglevel, i;
nethercote71980f02004-01-24 18:18:54 +00002442
2443 //============================================================
2444 // Nb: startup is complex. Prerequisites are shown at every step.
2445 //
2446 // *** Be very careful when messing with the order ***
2447 //============================================================
2448
sewardj1cf558c2005-04-25 01:36:56 +00002449 //--------------------------------------------------------------
2450 // Start up the logging mechanism
2451 // p: none
2452 //--------------------------------------------------------------
2453 /* Start the debugging-log system ASAP. First find out how many
2454 "-d"s were specified. This is a pre-scan of the command line. */
2455 loglevel = 0;
2456 for (i = 1; i < argc; i++) {
sewardj10759312005-05-30 23:52:47 +00002457 if (argv[i][0] != '-')
2458 break;
2459 if (0 == local_strcmp(argv[i], "--"))
2460 break;
2461 if (0 == local_strcmp(argv[i], "-d"))
2462 loglevel++;
sewardj1cf558c2005-04-25 01:36:56 +00002463 }
2464
2465 /* ... and start the debug logger. Now we can safely emit logging
2466 messages all through startup. */
sewardj10759312005-05-30 23:52:47 +00002467 VG_(debugLog_startup)(loglevel, "Stage 2 (main)");
sewardj1cf558c2005-04-25 01:36:56 +00002468
nethercotef4928da2004-06-15 10:54:40 +00002469 //============================================================
2470 // Command line argument handling order:
2471 // * If --help/--help-debug are present, show usage message
sewardjb5f6f512005-03-10 23:59:00 +00002472 // (including the tool-specific usage)
2473 // * (If no --tool option given, default to Memcheck)
nethercotef4928da2004-06-15 10:54:40 +00002474 // * Then, if client is missing, abort with error msg
2475 // * Then, if any cmdline args are bad, abort with error msg
2476 //============================================================
2477
fitzhardingeb50068f2004-02-24 23:42:55 +00002478 // Get the current process datasize rlimit, and set it to zero.
2479 // This prevents any internal uses of brk() from having any effect.
2480 // We remember the old value so we can restore it on exec, so that
2481 // child processes will have a reasonable brk value.
2482 VG_(getrlimit)(VKI_RLIMIT_DATA, &VG_(client_rlimit_data));
2483 zero.rlim_max = VG_(client_rlimit_data).rlim_max;
2484 VG_(setrlimit)(VKI_RLIMIT_DATA, &zero);
thughesc37184f2004-09-11 14:16:57 +00002485
2486 // Get the current process stack rlimit.
2487 VG_(getrlimit)(VKI_RLIMIT_STACK, &VG_(client_rlimit_stack));
2488
nethercote71980f02004-01-24 18:18:54 +00002489 //--------------------------------------------------------------
2490 // Check we were launched by stage1
sewardj51ac0872004-12-21 01:20:49 +00002491 // p: none
nethercote71980f02004-01-24 18:18:54 +00002492 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002493 VG_(debugLog)(1, "main", "Doing scan_auxv()\n");
nethercotec25c4492004-10-18 11:52:17 +00002494 {
sewardj1fbc1a52005-04-25 02:05:54 +00002495 void* init_sp = argv - 1;
2496 padfile = scan_auxv(init_sp);
nethercote71980f02004-01-24 18:18:54 +00002497 }
2498
2499 //--------------------------------------------------------------
2500 // Look for alternative libdir
sewardj51ac0872004-12-21 01:20:49 +00002501 // p: none
nethercote71980f02004-01-24 18:18:54 +00002502 //--------------------------------------------------------------
sewardj51ac0872004-12-21 01:20:49 +00002503 { HChar *cp = getenv(VALGRINDLIB);
nethercote71980f02004-01-24 18:18:54 +00002504 if (cp != NULL)
2505 VG_(libdir) = cp;
2506 }
2507
2508 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002509 // Get valgrind args + client args (inc. from VALGRIND_OPTS/.valgrindrc).
2510 // Pre-process the command line.
sewardj51ac0872004-12-21 01:20:49 +00002511 // p: none
nethercote71980f02004-01-24 18:18:54 +00002512 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002513 VG_(debugLog)(1, "main", "Preprocess command line opts\n");
nethercotef6a1d502004-08-09 12:21:57 +00002514 get_command_line(argc, argv, &vg_argc, &vg_argv, &cl_argv);
nethercote71980f02004-01-24 18:18:54 +00002515 pre_process_cmd_line_options(&need_help, &tool, &exec);
2516
sewardj10759312005-05-30 23:52:47 +00002517 /* If this process was created by exec done by another Valgrind
2518 process, the arguments will only show up at this point. Hence
2519 we need to also snoop around in vg_argv to see if anyone is
2520 asking for debug logging. */
2521 if (loglevel == 0) {
2522 for (i = 1; i < vg_argc; i++) {
2523 if (vg_argv[i][0] != '-')
2524 break;
2525 if (0 == local_strcmp(vg_argv[i], "--"))
2526 break;
2527 if (0 == local_strcmp(vg_argv[i], "-d"))
2528 loglevel++;
2529 }
2530 VG_(debugLog_startup)(loglevel, "Stage 2 (second go)");
2531 }
2532
nethercote71980f02004-01-24 18:18:54 +00002533 //==============================================================
2534 // Nb: once a tool is specified, the tool.so must be loaded even if
2535 // they specified --help or didn't specify a client program.
2536 //==============================================================
2537
2538 //--------------------------------------------------------------
2539 // With client padded out, map in tool
nethercote71980f02004-01-24 18:18:54 +00002540 // p: set-libdir [for VG_(libdir)]
2541 // p: pre_process_cmd_line_options() [for 'tool']
2542 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002543 VG_(debugLog)(1, "main", "Loading tool\n");
njn8a97c6d2005-03-31 04:37:24 +00002544 load_tool(tool, &toolinfo, &preload);
nethercote71980f02004-01-24 18:18:54 +00002545
2546 //==============================================================
2547 // Can use VG_(malloc)() and VG_(arena_malloc)() only after load_tool()
nethercotec314eba2004-07-15 12:59:41 +00002548 // -- redzone size is now set. This is checked by vg_malloc2.c.
nethercote71980f02004-01-24 18:18:54 +00002549 //==============================================================
2550
2551 //--------------------------------------------------------------
2552 // Finalise address space layout
nethercote31779c72004-07-30 21:50:15 +00002553 // p: load_tool() [for 'toolinfo']
nethercote71980f02004-01-24 18:18:54 +00002554 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002555 VG_(debugLog)(1, "main", "Laying out remaining space\n");
nethercote31779c72004-07-30 21:50:15 +00002556 layout_remaining_space( (Addr) & argc, toolinfo->shadow_ratio );
nethercote71980f02004-01-24 18:18:54 +00002557
2558 //--------------------------------------------------------------
2559 // Load client executable, finding in $PATH if necessary
nethercote71980f02004-01-24 18:18:54 +00002560 // p: pre_process_cmd_line_options() [for 'exec', 'need_help']
2561 // p: layout_remaining_space [so there's space]
2562 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002563 VG_(debugLog)(1, "main", "Loading client\n");
nethercotef4928da2004-06-15 10:54:40 +00002564 load_client(cl_argv, exec, need_help, &info, &client_eip);
nethercote71980f02004-01-24 18:18:54 +00002565
2566 //--------------------------------------------------------------
nethercote969ecf12004-10-13 17:29:01 +00002567 // Everything in place, remove padding done by stage1
nethercote71980f02004-01-24 18:18:54 +00002568 // p: layout_remaining_space() [everything must be mapped in before now]
2569 // p: load_client() [ditto]
2570 //--------------------------------------------------------------
nethercote31779c72004-07-30 21:50:15 +00002571 as_unpad((void *)VG_(shadow_end), (void *)~0, padfile);
2572 as_closepadfile(padfile); // no more padding
nethercote71980f02004-01-24 18:18:54 +00002573
2574 //--------------------------------------------------------------
2575 // Set up client's environment
2576 // p: set-libdir [for VG_(libdir)]
2577 // p: load_tool() [for 'preload']
2578 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002579 VG_(debugLog)(1, "main", "Setup client env\n");
sewardjb5f6f512005-03-10 23:59:00 +00002580 env = fix_environment(envp, preload);
nethercote71980f02004-01-24 18:18:54 +00002581
2582 //--------------------------------------------------------------
nethercote5ee67ca2004-06-22 14:00:09 +00002583 // Setup client stack, eip, and VG_(client_arg[cv])
nethercote71980f02004-01-24 18:18:54 +00002584 // p: load_client() [for 'info']
2585 // p: fix_environment() [for 'env']
2586 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002587 VG_(debugLog)(1, "main", "Setup client stack\n");
nethercotec25c4492004-10-18 11:52:17 +00002588 {
sewardj1fbc1a52005-04-25 02:05:54 +00002589 void* init_sp = argv - 1;
sewardjb5f6f512005-03-10 23:59:00 +00002590
sewardj1fbc1a52005-04-25 02:05:54 +00002591 sp_at_startup = setup_client_stack(init_sp, cl_argv, env, &info,
2592 &client_auxv);
2593 free(env);
nethercotec25c4492004-10-18 11:52:17 +00002594 }
nethercote71980f02004-01-24 18:18:54 +00002595
sewardj1fbc1a52005-04-25 02:05:54 +00002596 VG_(debugLog)(2, "main",
2597 "Client info: "
2598 "entry=%p client esp=%p vg_argc=%d brkbase=%p\n",
2599 (void*)client_eip, (void*)sp_at_startup, vg_argc,
2600 (void*)VG_(brk_base) );
nethercote71980f02004-01-24 18:18:54 +00002601
2602 //==============================================================
2603 // Finished setting up operating environment. Now initialise
2604 // Valgrind. (This is where the old VG_(main)() started.)
2605 //==============================================================
2606
2607 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002608 // setup file descriptors
2609 // p: n/a
2610 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002611 VG_(debugLog)(1, "main", "Setup file descriptors\n");
nethercote71980f02004-01-24 18:18:54 +00002612 setup_file_descriptors();
2613
2614 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002615 // Build segment map (Valgrind segments only)
njnd2252832004-11-26 10:53:33 +00002616 // p: tl_pre_clo_init() [to setup new_mem_startup tracker]
nethercotec314eba2004-07-15 12:59:41 +00002617 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002618 VG_(debugLog)(1, "main", "Parse /proc/self/maps (round 1)\n");
nethercotec314eba2004-07-15 12:59:41 +00002619 VG_(parse_procselfmaps) ( build_valgrind_map_callback );
2620
2621 //==============================================================
2622 // Can use VG_(arena_malloc)() with non-CORE arena after segments set up
2623 //==============================================================
2624
2625 //--------------------------------------------------------------
2626 // Init tool: pre_clo_init, process cmd line, post_clo_init
2627 // p: setup_client_stack() [for 'VG_(client_arg[cv]']
njn8a97c6d2005-03-31 04:37:24 +00002628 // p: load_tool() [for 'toolinfo']
nethercotec314eba2004-07-15 12:59:41 +00002629 // p: setup_file_descriptors() [for 'VG_(fd_xxx_limit)']
2630 // p: parse_procselfmaps [so VG segments are setup so tool can
2631 // call VG_(malloc)]
nethercote71980f02004-01-24 18:18:54 +00002632 //--------------------------------------------------------------
njn64c83242005-06-21 01:54:38 +00002633 {
2634 Char* s;
2635 Bool ok;
2636 VG_(debugLog)(1, "main", "Initialise the tool\n");
2637 (*toolinfo->tl_pre_clo_init)();
2638 ok = VG_(sanity_check_needs)( VG_(shadow_base) != VG_(shadow_end), &s );
2639 if (!ok) {
2640 VG_(tool_panic)(s);
2641 }
2642 }
nethercote71980f02004-01-24 18:18:54 +00002643
nethercotef4928da2004-06-15 10:54:40 +00002644 // If --tool and --help/--help-debug was given, now give the core+tool
2645 // help message
nethercotef4928da2004-06-15 10:54:40 +00002646 if (need_help) {
2647 usage(/*--help-debug?*/2 == need_help);
2648 }
nethercotec314eba2004-07-15 12:59:41 +00002649 process_cmd_line_options(client_auxv, tool);
2650
njn51d827b2005-05-09 01:02:08 +00002651 VG_TDICT_CALL(tool_post_clo_init);
nethercotef4928da2004-06-15 10:54:40 +00002652
2653 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002654 // Build segment map (all segments)
sewardjb5f6f512005-03-10 23:59:00 +00002655 // p: shadow/redzone segments
nethercote4ad74312004-10-26 09:59:49 +00002656 // p: setup_client_stack() [for 'sp_at_startup']
nethercotec314eba2004-07-15 12:59:41 +00002657 // p: init tool [for 'new_mem_startup']
nethercote71980f02004-01-24 18:18:54 +00002658 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002659 VG_(debugLog)(1, "main", "Parse /proc/self/maps (round 2)\n");
nethercote4ad74312004-10-26 09:59:49 +00002660 sp_at_startup___global_arg = sp_at_startup;
nethercotec314eba2004-07-15 12:59:41 +00002661 VG_(parse_procselfmaps) ( build_segment_map_callback ); /* everything */
nethercote4ad74312004-10-26 09:59:49 +00002662 sp_at_startup___global_arg = 0;
sewardjb5f6f512005-03-10 23:59:00 +00002663
nethercotec314eba2004-07-15 12:59:41 +00002664 //==============================================================
2665 // Can use VG_(map)() after segments set up
2666 //==============================================================
nethercote71980f02004-01-24 18:18:54 +00002667
2668 //--------------------------------------------------------------
2669 // Allow GDB attach
2670 // p: process_cmd_line_options() [for VG_(clo_wait_for_gdb)]
2671 //--------------------------------------------------------------
2672 /* Hook to delay things long enough so we can get the pid and
2673 attach GDB in another shell. */
2674 if (VG_(clo_wait_for_gdb)) {
sewardj8211a572005-06-23 21:37:47 +00002675 Long q, iters;
sewardj1fbc1a52005-04-25 02:05:54 +00002676 VG_(debugLog)(1, "main", "Wait for GDB\n");
sewardj93ab8572005-02-06 14:10:40 +00002677 VG_(printf)("pid=%d, entering delay loop\n", VG_(getpid)());
2678 /* jrs 20050206: I don't understand why this works on x86. On
2679 amd64 the obvious analogues (jump *$rip or jump *$rcx) don't
2680 work. */
2681 /* do "jump *$eip" to skip this in gdb (x86) */
2682 //VG_(do_syscall0)(__NR_pause);
sewardj8211a572005-06-23 21:37:47 +00002683
2684# if defined(VGP_x86_linux)
2685 iters = 5;
2686# elif defined(VGP_amd64_linux)
2687 iters = 10;
2688# elif defined(VGP_ppc32_linux)
sewardjd714d2e2005-07-08 18:24:04 +00002689 iters = 5;
sewardj8211a572005-06-23 21:37:47 +00002690# else
2691# error "Unknown plat"
2692# endif
2693
2694 iters *= 1000*1000*1000;
2695 for (q = 0; q < iters; q++)
2696 ;
nethercote71980f02004-01-24 18:18:54 +00002697 }
2698
sewardjb5d320c2005-03-13 18:57:15 +00002699 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002700 // Search for file descriptors that are inherited from our parent
2701 // p: process_cmd_line_options [for VG_(clo_track_fds)]
2702 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002703 if (VG_(clo_track_fds)) {
2704 VG_(debugLog)(1, "main", "Init preopened fds\n");
nethercote71980f02004-01-24 18:18:54 +00002705 VG_(init_preopened_fds)();
sewardj1fbc1a52005-04-25 02:05:54 +00002706 }
nethercote71980f02004-01-24 18:18:54 +00002707
2708 //--------------------------------------------------------------
2709 // Initialise the scheduler
nethercote71980f02004-01-24 18:18:54 +00002710 // p: setup_file_descriptors() [else VG_(safe_fd)() breaks]
2711 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002712 VG_(debugLog)(1, "main", "Initialise scheduler\n");
nethercote71980f02004-01-24 18:18:54 +00002713 VG_(scheduler_init)();
2714
2715 //--------------------------------------------------------------
sewardjb5f6f512005-03-10 23:59:00 +00002716 // Initialise the pthread model
2717 // p: ?
sewardj2a99cf62004-11-24 10:44:19 +00002718 // load_client() [for 'client_eip']
2719 // setup_client_stack() [for 'sp_at_startup']
2720 // setup_scheduler() [for the rest of state 1 stuff]
2721 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002722 VG_(debugLog)(1, "main", "Initialise thread 1's state\n");
njn2da73352005-06-18 01:35:16 +00002723 init_thread1state(client_eip, sp_at_startup, &VG_(threads)[1].arch);
njnea4b28c2004-11-30 16:04:58 +00002724
sewardj2a99cf62004-11-24 10:44:19 +00002725 //--------------------------------------------------------------
sewardj39b88fb2005-03-12 15:16:07 +00002726 // Initialise the pthread model
2727 // p: ?
nethercote71980f02004-01-24 18:18:54 +00002728 //--------------------------------------------------------------
sewardjb5f6f512005-03-10 23:59:00 +00002729 //if (VG_(clo_model_pthreads))
2730 // VG_(pthread_init)();
nethercote71980f02004-01-24 18:18:54 +00002731
2732 //--------------------------------------------------------------
2733 // Initialise the signal handling subsystem
sewardjb5f6f512005-03-10 23:59:00 +00002734 // p: n/a
nethercote71980f02004-01-24 18:18:54 +00002735 //--------------------------------------------------------------
2736 // Nb: temporarily parks the saved blocking-mask in saved_sigmask.
sewardj1fbc1a52005-04-25 02:05:54 +00002737 VG_(debugLog)(1, "main", "Initialise signal management\n");
nethercote71980f02004-01-24 18:18:54 +00002738 VG_(sigstartup_actions)();
2739
2740 //--------------------------------------------------------------
2741 // Perhaps we're profiling Valgrind?
2742 // p: process_cmd_line_options() [for VG_(clo_profile)]
2743 // p: others?
2744 //
2745 // XXX: this seems to be broken? It always says the tool wasn't built
2746 // for profiling; vg_profile.c's functions don't seem to be overriding
2747 // vg_dummy_profile.c's?
2748 //
2749 // XXX: want this as early as possible. Looking for --profile
2750 // in pre_process_cmd_line_options() could get it earlier.
2751 //--------------------------------------------------------------
2752 if (VG_(clo_profile))
njn31066fd2005-03-26 00:42:02 +00002753 VG_(init_profiling)();
nethercote71980f02004-01-24 18:18:54 +00002754
2755 VGP_PUSHCC(VgpStartup);
2756
2757 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002758 // Read suppression file
2759 // p: process_cmd_line_options() [for VG_(clo_suppressions)]
2760 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002761 if (VG_(needs).core_errors || VG_(needs).tool_errors) {
2762 VG_(debugLog)(1, "main", "Load suppressions\n");
nethercote71980f02004-01-24 18:18:54 +00002763 VG_(load_suppressions)();
sewardj1fbc1a52005-04-25 02:05:54 +00002764 }
nethercote71980f02004-01-24 18:18:54 +00002765
2766 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002767 // Initialise translation table and translation cache
2768 // p: read_procselfmaps [so the anonymous mmaps for the TT/TC
2769 // aren't identified as part of the client, which would waste
2770 // > 20M of virtual address space.]
2771 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002772 VG_(debugLog)(1, "main", "Initialise TT/TC\n");
nethercote71980f02004-01-24 18:18:54 +00002773 VG_(init_tt_tc)();
2774
2775 //--------------------------------------------------------------
sewardjb9bce632005-06-21 01:41:34 +00002776 // Initialise the redirect table.
sewardjb5d320c2005-03-13 18:57:15 +00002777 // p: parse_procselfmaps? [XXX for debug info?]
2778 // p: init_tt_tc [so it can call VG_(search_transtab) safely]
2779 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002780 VG_(debugLog)(1, "main", "Initialise redirects\n");
sewardjb5d320c2005-03-13 18:57:15 +00002781 VG_(setup_code_redirect_table)();
2782
2783 //--------------------------------------------------------------
sewardjb9bce632005-06-21 01:41:34 +00002784 // Tell the tool about permissions in our handwritten assembly
2785 // helpers.
2786 // p: init tool [for 'new_mem_startup']
2787 //--------------------------------------------------------------
2788 VG_(debugLog)(1, "main", "Tell tool about permissions for asm helpers\n");
2789 VG_TRACK( new_mem_startup,
2790 (Addr)&VG_(trampoline_stuff_start),
2791 &VG_(trampoline_stuff_end) - &VG_(trampoline_stuff_start),
2792 False, /* readable? */
2793 False, /* writable? */
2794 True /* executable? */ );
2795
2796 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002797 // Verbosity message
2798 // p: end_rdtsc_calibration [so startup message is printed first]
2799 //--------------------------------------------------------------
sewardj71bc3cb2005-05-19 00:25:45 +00002800 if (VG_(clo_verbosity) == 1 && !VG_(clo_xml))
nethercote71980f02004-01-24 18:18:54 +00002801 VG_(message)(Vg_UserMsg, "For more details, rerun with: -v");
2802 if (VG_(clo_verbosity) > 0)
2803 VG_(message)(Vg_UserMsg, "");
2804
2805 //--------------------------------------------------------------
2806 // Setup pointercheck
njn04e16982005-05-31 00:23:43 +00002807 // p: layout_remaining_space() [for VG_(client_{base,end})]
nethercote71980f02004-01-24 18:18:54 +00002808 // p: process_cmd_line_options() [for VG_(clo_pointercheck)]
2809 //--------------------------------------------------------------
nethercote775508a2004-09-07 22:38:23 +00002810 if (VG_(clo_pointercheck))
njn04e16982005-05-31 00:23:43 +00002811 VG_(clo_pointercheck) =
njnaf839f52005-06-23 03:27:57 +00002812 VG_(setup_pointercheck)( VG_(client_base), VG_(client_end));
nethercote71980f02004-01-24 18:18:54 +00002813
nethercote71980f02004-01-24 18:18:54 +00002814 //--------------------------------------------------------------
rjwalsh0140af52005-06-04 20:42:33 +00002815 // register client stack
2816 //--------------------------------------------------------------
njn945ed2e2005-06-24 03:28:30 +00002817 VG_(clstk_id) = VG_(register_stack)(VG_(clstk_base), VG_(clstk_end));
rjwalsh0140af52005-06-04 20:42:33 +00002818
2819 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002820 // Run!
2821 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002822 VGP_POPCC(VgpStartup);
nethercote71980f02004-01-24 18:18:54 +00002823
sewardj71bc3cb2005-05-19 00:25:45 +00002824 if (VG_(clo_xml)) {
sewardj68cde6f2005-07-19 12:17:51 +00002825 HChar buf[50];
2826 VG_(ctime)(buf);
sewardj33e60422005-07-24 07:33:15 +00002827 VG_(message)(Vg_UserMsg, "<status> <state>RUNNING</state> "
2828 "<time>%t</time> </status>", buf);
sewardj71bc3cb2005-05-19 00:25:45 +00002829 VG_(message)(Vg_UserMsg, "");
2830 }
2831
sewardj1fbc1a52005-04-25 02:05:54 +00002832 VG_(debugLog)(1, "main", "Running thread 1\n");
sewardj1d887112005-05-30 21:44:08 +00002833 /* As a result of the following call, the last thread standing
2834 eventually winds up running VG_(shutdown_actions_NORETURN) just
2835 below. */
njnaf839f52005-06-23 03:27:57 +00002836 VG_(main_thread_wrapper_NORETURN)(1);
nethercote71980f02004-01-24 18:18:54 +00002837
sewardj1d887112005-05-30 21:44:08 +00002838 /*NOTREACHED*/
2839 vg_assert(0);
sewardjb5f6f512005-03-10 23:59:00 +00002840}
2841
2842
njn9cb54ac2005-06-12 04:19:17 +00002843/* Final clean-up before terminating the process.
2844 Clean up the client by calling __libc_freeres() (if requested)
2845 This is Linux-specific?
2846*/
2847static void final_tidyup(ThreadId tid)
2848{
njnbc6d84d2005-06-19 18:58:03 +00002849 Addr __libc_freeres_wrapper;
2850
njn9cb54ac2005-06-12 04:19:17 +00002851 vg_assert(VG_(is_running_thread)(tid));
2852
njnbc6d84d2005-06-19 18:58:03 +00002853 if ( !VG_(needs).libc_freeres ||
2854 !VG_(clo_run_libc_freeres) ||
2855 0 == (__libc_freeres_wrapper = VG_(get_libc_freeres_wrapper)()) )
njn9cb54ac2005-06-12 04:19:17 +00002856 return; /* can't/won't do it */
2857
2858 if (VG_(clo_verbosity) > 2 ||
2859 VG_(clo_trace_syscalls) ||
2860 VG_(clo_trace_sched))
2861 VG_(message)(Vg_DebugMsg,
2862 "Caught __NR_exit; running __libc_freeres()");
2863
2864 /* point thread context to point to libc_freeres_wrapper */
njnf536bbb2005-06-13 04:21:38 +00002865 VG_(set_IP)(tid, __libc_freeres_wrapper);
njn9cb54ac2005-06-12 04:19:17 +00002866 // XXX should we use a special stack?
2867
2868 /* Block all blockable signals by copying the real block state into
2869 the thread's block state*/
2870 VG_(sigprocmask)(VKI_SIG_BLOCK, NULL, &VG_(threads)[tid].sig_mask);
2871 VG_(threads)[tid].tmp_sig_mask = VG_(threads)[tid].sig_mask;
2872
2873 /* and restore handlers to default */
2874 VG_(set_default_handler)(VKI_SIGSEGV);
2875 VG_(set_default_handler)(VKI_SIGBUS);
2876 VG_(set_default_handler)(VKI_SIGILL);
2877 VG_(set_default_handler)(VKI_SIGFPE);
2878
2879 // We were exiting, so assert that...
2880 vg_assert(VG_(is_exiting)(tid));
2881 // ...but now we're not again
2882 VG_(threads)[tid].exitreason = VgSrc_None;
2883
2884 // run until client thread exits - ideally with LIBC_FREERES_DONE,
2885 // but exit/exitgroup/signal will do
2886 VG_(scheduler)(tid);
2887
2888 vg_assert(VG_(is_exiting)(tid));
2889}
2890
sewardjb5f6f512005-03-10 23:59:00 +00002891/* Do everything which needs doing when the last thread exits */
sewardj1d887112005-05-30 21:44:08 +00002892void VG_(shutdown_actions_NORETURN) ( ThreadId tid,
2893 VgSchedReturnCode tids_schedretcode )
sewardjb5f6f512005-03-10 23:59:00 +00002894{
sewardj1d887112005-05-30 21:44:08 +00002895 VG_(debugLog)(1, "main", "entering VG_(shutdown_actions_NORETURN)\n");
2896
2897 vg_assert( VG_(count_living_threads)() == 1 );
sewardjb5f6f512005-03-10 23:59:00 +00002898 vg_assert(VG_(is_running_thread)(tid));
2899
2900 // Wait for all other threads to exit.
njn7b85dd52005-06-12 17:26:29 +00002901 VG_(reap_threads)(tid);
sewardjb5f6f512005-03-10 23:59:00 +00002902
2903 VG_(clo_model_pthreads) = False;
2904
2905 // Clean the client up before the final report
njn9cb54ac2005-06-12 04:19:17 +00002906 final_tidyup(tid);
sewardjb5f6f512005-03-10 23:59:00 +00002907
2908 // OK, done
2909 VG_(exit_thread)(tid);
2910
2911 /* should be no threads left */
2912 vg_assert(VG_(count_living_threads)() == 0);
2913
2914 VG_(threads)[tid].status = VgTs_Empty;
nethercote71980f02004-01-24 18:18:54 +00002915 //--------------------------------------------------------------
2916 // Finalisation: cleanup, messages, etc. Order no so important, only
2917 // affects what order the messages come.
2918 //--------------------------------------------------------------
2919 if (VG_(clo_verbosity) > 0)
2920 VG_(message)(Vg_UserMsg, "");
2921
sewardj71bc3cb2005-05-19 00:25:45 +00002922 if (VG_(clo_xml)) {
sewardj68cde6f2005-07-19 12:17:51 +00002923 HChar buf[50];
sewardj9f297ca2005-05-20 02:29:52 +00002924 if (VG_(needs).core_errors || VG_(needs).tool_errors) {
2925 VG_(show_error_counts_as_XML)();
2926 VG_(message)(Vg_UserMsg, "");
2927 }
sewardj68cde6f2005-07-19 12:17:51 +00002928 VG_(ctime)(buf);
sewardj33e60422005-07-24 07:33:15 +00002929 VG_(message)(Vg_UserMsg, "<status> <state>FINISHED</state> "
2930 "<time>%t</time> </status>", buf);
sewardj71bc3cb2005-05-19 00:25:45 +00002931 VG_(message)(Vg_UserMsg, "");
2932 }
2933
nethercote71980f02004-01-24 18:18:54 +00002934 /* Print out file descriptor summary and stats. */
2935 if (VG_(clo_track_fds))
nethercote3a42fb82004-08-03 18:08:50 +00002936 VG_(show_open_fds)();
nethercote71980f02004-01-24 18:18:54 +00002937
njn95ec8702004-11-22 16:46:13 +00002938 if (VG_(needs).core_errors || VG_(needs).tool_errors)
nethercote71980f02004-01-24 18:18:54 +00002939 VG_(show_all_errors)();
2940
njn51d827b2005-05-09 01:02:08 +00002941 VG_TDICT_CALL(tool_fini, 0/*exitcode*/);
nethercote71980f02004-01-24 18:18:54 +00002942
sewardj71bc3cb2005-05-19 00:25:45 +00002943 if (VG_(clo_xml)) {
2944 VG_(message)(Vg_UserMsg, "");
2945 VG_(message)(Vg_UserMsg, "</valgrindoutput>");
2946 VG_(message)(Vg_UserMsg, "");
2947 }
2948
nethercote885dd912004-08-03 23:14:00 +00002949 VG_(sanity_check_general)( True /*include expensive checks*/ );
nethercote71980f02004-01-24 18:18:54 +00002950
2951 if (VG_(clo_verbosity) > 1)
nethercote3a42fb82004-08-03 18:08:50 +00002952 print_all_stats();
nethercote71980f02004-01-24 18:18:54 +00002953
nethercote71980f02004-01-24 18:18:54 +00002954 if (VG_(clo_profile))
njn31066fd2005-03-26 00:42:02 +00002955 VG_(done_profiling)();
njn2025cf92005-06-26 20:44:48 +00002956
2957 if (VG_(clo_profile_flags) > 0) {
2958 #define N_MAX 100
2959 BBProfEntry tops[N_MAX];
2960 ULong score_total = VG_(get_BB_profile) (tops, N_MAX);
2961 show_BB_profile(tops, N_MAX, score_total);
2962 }
sewardjfa8ec112005-01-19 11:55:34 +00002963
sewardj8b635a42004-11-22 19:01:47 +00002964 /* Print Vex storage stats */
sewardjbf426512005-01-17 18:35:30 +00002965 if (0)
2966 LibVEX_ShowAllocStats();
sewardj1d887112005-05-30 21:44:08 +00002967
njn8aa35852005-06-10 22:59:56 +00002968 /* Ok, finally exit in the os-specific way, according to the scheduler's
2969 return code. In short, if the (last) thread exited by calling
2970 sys_exit, do likewise; if the (last) thread stopped due to a fatal
2971 signal, terminate the entire system with that same fatal signal. */
2972 VG_(debugLog)(1, "core_os",
njn7b85dd52005-06-12 17:26:29 +00002973 "VG_(terminate_NORETURN)(tid=%lld)\n", (ULong)tid);
njn8aa35852005-06-10 22:59:56 +00002974
2975 vg_assert(VG_(count_living_threads)() == 0);
2976
2977 switch (tids_schedretcode) {
2978 case VgSrc_ExitSyscall: /* the normal way out */
2979 VG_(exit)( VG_(threads)[tid].os_state.exitcode );
2980 /* NOT ALIVE HERE! */
2981 VG_(core_panic)("entered the afterlife in main() -- ExitSyscall");
2982 break; /* what the hell :) */
2983
2984 case VgSrc_FatalSig:
2985 /* We were killed by a fatal signal, so replicate the effect */
2986 vg_assert(VG_(threads)[tid].os_state.fatalsig != 0);
2987 VG_(kill_self)(VG_(threads)[tid].os_state.fatalsig);
2988 VG_(core_panic)("main(): signal was supposed to be fatal");
2989 break;
2990
2991 default:
2992 VG_(core_panic)("main(): unexpected scheduler return code");
2993 }
njne96be672005-05-08 19:08:54 +00002994}
sewardj8b635a42004-11-22 19:01:47 +00002995
sewardjde4a1d02002-03-22 01:27:54 +00002996/*--------------------------------------------------------------------*/
njn04e16982005-05-31 00:23:43 +00002997/*--- end ---*/
sewardjde4a1d02002-03-22 01:27:54 +00002998/*--------------------------------------------------------------------*/