blob: 96131f969fa8d71ceffe2f0e3d4b19327e6ea61f [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"
nethercote2b0793f2003-12-02 10:41:18 +00001266"\n"
1267" uncommon user options for all Valgrind tools:\n"
nethercote0d588502004-06-21 13:27:11 +00001268" --run-libc-freeres=no|yes free up glibc memory at exit? [yes]\n"
sewardjb5f6f512005-03-10 23:59:00 +00001269" --weird-hacks=hack1,hack2,... recognised hacks: lax-ioctls,ioctl-mmap [none]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001270" --pointercheck=no|yes enforce client address space limits [yes]\n"
sewardjb1131a82005-03-19 15:12:21 +00001271" --show-emwarns=no|yes show warnings about emulation limits? [no]\n"
sewardj6c3a2192005-07-24 07:00:45 +00001272" --smc-check=none|stack|all checks for self-modifying code: none,\n"
1273" only for code found in stacks, or all [stack]\n"
njn25e49d8e72002-09-23 09:36:25 +00001274"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001275" user options for Valgrind tools that report errors:\n"
njnc8ec9f82005-07-20 03:03:28 +00001276" --xml=yes all output is in XML (Memcheck only)\n"
1277" --xml-user-comment=STR copy STR verbatim to XML output\n"
nethercotef8548672004-06-21 12:42:35 +00001278" --log-fd=<number> log messages to file descriptor [2=stderr]\n"
1279" --log-file=<file> log messages to <file>.pid<pid>\n"
sewardj603d4102005-01-11 14:01:02 +00001280" --log-file-exactly=<file> log messages to <file>\n"
sewardjad311162005-07-19 11:25:02 +00001281" --log-file-qualifier=<VAR> incorporate $VAR in logfile name [none]\n"
nethercotef8548672004-06-21 12:42:35 +00001282" --log-socket=ipaddr:port log messages to socket ipaddr:port\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"
1300" --single-step=no|yes translate each instr separately? [no]\n"
1301" --optimise=no|yes improve intermediate code? [yes]\n"
nethercote137bc552003-11-14 17:47:54 +00001302" --profile=no|yes profile? (tool must be built for it) [no]\n"
sewardjfa8ec112005-01-19 11:55:34 +00001303" --trace-flags=<XXXXXXXX> show generated code? (X = 0|1) [00000000]\n"
1304" --profile-flags=<XXXXXXXX> ditto, but for profiling (X = 0|1) [00000000]\n"
sewardjc771b292004-11-30 18:55:21 +00001305" --trace-notbelow=<number> only show BBs above <number> [0]\n"
njn25e49d8e72002-09-23 09:36:25 +00001306" --trace-syscalls=no|yes show all system calls? [no]\n"
1307" --trace-signals=no|yes show signal handling details? [no]\n"
1308" --trace-symtab=no|yes show symbol table details? [no]\n"
sewardjce058b02005-05-01 08:55:38 +00001309" --trace-cfi=no|yes show call-frame-info details? [no]\n"
njn25e49d8e72002-09-23 09:36:25 +00001310" --trace-sched=no|yes show thread scheduler details? [no]\n"
jsgf855d93d2003-10-13 22:26:55 +00001311" --wait-for-gdb=yes|no pause on startup to wait for gdb attach\n"
sewardjb5f6f512005-03-10 23:59:00 +00001312#if 0
1313" --model-pthreads=yes|no model the pthreads library [no]\n"
1314#endif
1315" --command-line-only=no|yes only use command line options [no]\n"
njn613812e2005-03-11 04:57:30 +00001316"\n"
1317" --vex-iropt-verbosity 0 .. 9 [0]\n"
1318" --vex-iropt-level 0 .. 2 [2]\n"
1319" --vex-iropt-precise-memory-exns [no]\n"
sewardj8b635a42004-11-22 19:01:47 +00001320" --vex-iropt-unroll-thresh 0 .. 400 [120]\n"
1321" --vex-guest-max-insns 1 .. 100 [50]\n"
1322" --vex-guest-chase-thresh 0 .. 99 [10]\n"
1323"\n"
sewardjfa8ec112005-01-19 11:55:34 +00001324" --trace-flags and --profile-flags values (omit the middle space):\n"
sewardj2a99cf62004-11-24 10:44:19 +00001325" 1000 0000 show conversion into IR\n"
1326" 0100 0000 show after initial opt\n"
1327" 0010 0000 show after instrumentation\n"
1328" 0001 0000 show after second opt\n"
1329" 0000 1000 show after tree building\n"
1330" 0000 0100 show selecting insns\n"
1331" 0000 0010 show after reg-alloc\n"
1332" 0000 0001 show final assembly\n"
1333"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001334" debugging options for Valgrind tools that report errors\n"
1335" --dump-error=<number> show translation for basic block associated\n"
1336" with <number>'th error context [0=show none]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001337"\n";
njn3e884182003-04-15 13:03:23 +00001338
1339 Char* usage3 =
1340"\n"
nethercote71980f02004-01-24 18:18:54 +00001341" Extra options read from ~/.valgrindrc, $VALGRIND_OPTS, ./.valgrindrc\n"
njn25e49d8e72002-09-23 09:36:25 +00001342"\n"
njn53612422005-03-12 16:22:54 +00001343" Valgrind is Copyright (C) 2000-2005 Julian Seward et al.\n"
njn25e49d8e72002-09-23 09:36:25 +00001344" and licensed under the GNU General Public License, version 2.\n"
1345" Bug reports, feedback, admiration, abuse, etc, to: %s.\n"
njnd04b7c62002-10-03 14:05:52 +00001346"\n"
nethercote137bc552003-11-14 17:47:54 +00001347" Tools are copyright and licensed by their authors. See each\n"
1348" tool's start-up message for more information.\n"
njn25e49d8e72002-09-23 09:36:25 +00001349"\n";
njn7cf0bd32002-06-08 13:36:03 +00001350
njnbe9b47b2005-05-15 16:22:58 +00001351 // Ensure the message goes to stdout
1352 VG_(clo_log_fd) = 1;
1353 vg_assert( !VG_(logging_to_socket) );
1354
fitzhardinge98abfc72003-12-16 02:05:15 +00001355 VG_(printf)(usage1);
1356 if (VG_(details).name) {
1357 VG_(printf)(" user options for %s:\n", VG_(details).name);
fitzhardinge98abfc72003-12-16 02:05:15 +00001358 if (VG_(needs).command_line_options)
njn51d827b2005-05-09 01:02:08 +00001359 VG_TDICT_CALL(tool_print_usage);
fitzhardinge98abfc72003-12-16 02:05:15 +00001360 else
1361 VG_(printf)(" (none)\n");
1362 }
nethercote6c999f22004-01-31 22:55:15 +00001363 if (debug_help) {
1364 VG_(printf)(usage2);
fitzhardinge98abfc72003-12-16 02:05:15 +00001365
nethercote6c999f22004-01-31 22:55:15 +00001366 if (VG_(details).name) {
1367 VG_(printf)(" debugging options for %s:\n", VG_(details).name);
1368
1369 if (VG_(needs).command_line_options)
njn51d827b2005-05-09 01:02:08 +00001370 VG_TDICT_CALL(tool_print_debug_usage);
nethercote6c999f22004-01-31 22:55:15 +00001371 else
1372 VG_(printf)(" (none)\n");
1373 }
fitzhardinge98abfc72003-12-16 02:05:15 +00001374 }
nethercote421281e2003-11-20 16:20:55 +00001375 VG_(printf)(usage3, VG_BUGS_TO);
nethercotef4928da2004-06-15 10:54:40 +00001376 VG_(exit)(0);
njn7cf0bd32002-06-08 13:36:03 +00001377}
sewardjde4a1d02002-03-22 01:27:54 +00001378
nethercote71980f02004-01-24 18:18:54 +00001379static void pre_process_cmd_line_options
nethercote6c999f22004-01-31 22:55:15 +00001380 ( Int* need_help, const char** tool, const char** exec )
sewardj1c1b1162003-02-23 01:25:51 +00001381{
nethercote71980f02004-01-24 18:18:54 +00001382 UInt i;
sewardjde4a1d02002-03-22 01:27:54 +00001383
sewardj8b635a42004-11-22 19:01:47 +00001384 LibVEX_default_VexControl(& VG_(clo_vex_control));
1385
nethercote71980f02004-01-24 18:18:54 +00001386 /* parse the options we have (only the options we care about now) */
nethercotef6a1d502004-08-09 12:21:57 +00001387 for (i = 1; i < vg_argc; i++) {
nethercote71980f02004-01-24 18:18:54 +00001388
nethercotef6a1d502004-08-09 12:21:57 +00001389 if (strcmp(vg_argv[i], "--version") == 0) {
nethercote71980f02004-01-24 18:18:54 +00001390 printf("valgrind-" VERSION "\n");
nethercotef4928da2004-06-15 10:54:40 +00001391 exit(0);
nethercote71980f02004-01-24 18:18:54 +00001392
nethercotef6a1d502004-08-09 12:21:57 +00001393 } else if (VG_CLO_STREQ(vg_argv[i], "--help") ||
1394 VG_CLO_STREQ(vg_argv[i], "-h")) {
nethercote6c999f22004-01-31 22:55:15 +00001395 *need_help = 1;
1396
nethercotef6a1d502004-08-09 12:21:57 +00001397 } else if (VG_CLO_STREQ(vg_argv[i], "--help-debug")) {
nethercote6c999f22004-01-31 22:55:15 +00001398 *need_help = 2;
nethercote71980f02004-01-24 18:18:54 +00001399
nethercotef6c99d72004-11-09 14:35:43 +00001400 } else if (VG_CLO_STREQN(7, vg_argv[i], "--tool=")) {
nethercotef6a1d502004-08-09 12:21:57 +00001401 *tool = &vg_argv[i][7];
nethercote71980f02004-01-24 18:18:54 +00001402
nethercotef6a1d502004-08-09 12:21:57 +00001403 } else if (VG_CLO_STREQN(7, vg_argv[i], "--exec=")) {
1404 *exec = &vg_argv[i][7];
nethercote71980f02004-01-24 18:18:54 +00001405 }
1406 }
nethercote71980f02004-01-24 18:18:54 +00001407}
1408
nethercote5ee67ca2004-06-22 14:00:09 +00001409static void process_cmd_line_options( UInt* client_auxv, const char* toolname )
nethercote71980f02004-01-24 18:18:54 +00001410{
sewardj92645592005-07-23 09:18:34 +00001411 SysRes sres;
1412 Int i, eventually_log_fd;
1413 Int toolname_len = VG_(strlen)(toolname);
njnbe9b47b2005-05-15 16:22:58 +00001414 enum {
1415 VgLogTo_Fd,
1416 VgLogTo_File,
1417 VgLogTo_FileExactly,
1418 VgLogTo_Socket
1419 } log_to = VgLogTo_Fd; // Where is logging output to be sent?
sewardjde4a1d02002-03-22 01:27:54 +00001420
nethercotee1730692003-11-20 10:38:07 +00001421 /* log to stderr by default, but usage message goes to stdout */
nethercotef8548672004-06-21 12:42:35 +00001422 eventually_log_fd = 2;
sewardjde4a1d02002-03-22 01:27:54 +00001423
sewardj19d81412002-06-03 01:10:40 +00001424 /* Check for sane path in ./configure --prefix=... */
fitzhardinge98abfc72003-12-16 02:05:15 +00001425 if (VG_LIBDIR[0] != '/')
sewardj19d81412002-06-03 01:10:40 +00001426 config_error("Please use absolute paths in "
1427 "./configure --prefix=... or --libdir=...");
sewardj38170912002-05-10 21:07:22 +00001428
nethercotef6a1d502004-08-09 12:21:57 +00001429 for (i = 1; i < vg_argc; i++) {
nethercote71980f02004-01-24 18:18:54 +00001430
nethercotef6a1d502004-08-09 12:21:57 +00001431 Char* arg = vg_argv[i];
thughes3bfd5a02004-07-18 08:05:44 +00001432 Char* colon = arg;
nethercote71980f02004-01-24 18:18:54 +00001433
thughes3bfd5a02004-07-18 08:05:44 +00001434 /* Look for a colon in the switch name */
1435 while (*colon && *colon != ':' && *colon != '=')
1436 colon++;
nethercote71980f02004-01-24 18:18:54 +00001437
1438 /* Look for matching "--toolname:foo" */
thughes3bfd5a02004-07-18 08:05:44 +00001439 if (*colon == ':') {
nethercote71980f02004-01-24 18:18:54 +00001440 if (VG_CLO_STREQN(2, arg, "--") &&
1441 VG_CLO_STREQN(toolname_len, arg+2, toolname) &&
1442 VG_CLO_STREQN(1, arg+2+toolname_len, ":"))
1443 {
1444 // prefix matches, convert "--toolname:foo" to "--foo"
1445 if (0)
1446 VG_(printf)("tool-specific arg: %s\n", arg);
njn8c0b3bb2005-03-12 21:20:39 +00001447 arg = strdup(arg + toolname_len + 1);
nethercote71980f02004-01-24 18:18:54 +00001448 arg[0] = '-';
1449 arg[1] = '-';
1450
1451 } else {
1452 // prefix doesn't match, skip to next arg
1453 continue;
1454 }
1455 }
1456
fitzhardinge98abfc72003-12-16 02:05:15 +00001457 /* Ignore these options - they've already been handled */
njn45270a22005-03-27 01:00:11 +00001458 if (VG_CLO_STREQN( 7, arg, "--tool=")) goto skip_arg;
1459 if (VG_CLO_STREQN( 7, arg, "--exec=")) goto skip_arg;
1460 if (VG_CLO_STREQN(20, arg, "--command-line-only=")) goto skip_arg;
fitzhardinge98abfc72003-12-16 02:05:15 +00001461
njn45270a22005-03-27 01:00:11 +00001462 if ( VG_CLO_STREQ(arg, "--")) goto skip_arg;
nethercote27fec902004-06-16 21:26:32 +00001463
nethercote71980f02004-01-24 18:18:54 +00001464 else if (VG_CLO_STREQ(arg, "-v") ||
1465 VG_CLO_STREQ(arg, "--verbose"))
sewardjde4a1d02002-03-22 01:27:54 +00001466 VG_(clo_verbosity)++;
nethercote27fec902004-06-16 21:26:32 +00001467
nethercote71980f02004-01-24 18:18:54 +00001468 else if (VG_CLO_STREQ(arg, "-q") ||
1469 VG_CLO_STREQ(arg, "--quiet"))
sewardjde4a1d02002-03-22 01:27:54 +00001470 VG_(clo_verbosity)--;
1471
sewardj1cf558c2005-04-25 01:36:56 +00001472 else if (VG_CLO_STREQ(arg, "-d")) {
1473 /* do nothing */
1474 }
1475
sewardj71bc3cb2005-05-19 00:25:45 +00001476 else VG_BOOL_CLO(arg, "--xml", VG_(clo_xml))
njn45270a22005-03-27 01:00:11 +00001477 else VG_BOOL_CLO(arg, "--db-attach", VG_(clo_db_attach))
1478 else VG_BOOL_CLO(arg, "--demangle", VG_(clo_demangle))
1479 else VG_BOOL_CLO(arg, "--error-limit", VG_(clo_error_limit))
1480 else VG_BOOL_CLO(arg, "--pointercheck", VG_(clo_pointercheck))
njn45270a22005-03-27 01:00:11 +00001481 else VG_BOOL_CLO(arg, "--show-emwarns", VG_(clo_show_emwarns))
sewardj97724e52005-04-02 23:40:59 +00001482 else VG_NUM_CLO (arg, "--max-stackframe", VG_(clo_max_stackframe))
njn45270a22005-03-27 01:00:11 +00001483 else VG_BOOL_CLO(arg, "--profile", VG_(clo_profile))
1484 else VG_BOOL_CLO(arg, "--run-libc-freeres", VG_(clo_run_libc_freeres))
1485 else VG_BOOL_CLO(arg, "--show-below-main", VG_(clo_show_below_main))
1486 else VG_BOOL_CLO(arg, "--time-stamp", VG_(clo_time_stamp))
1487 else VG_BOOL_CLO(arg, "--track-fds", VG_(clo_track_fds))
1488 else VG_BOOL_CLO(arg, "--trace-children", VG_(clo_trace_children))
1489 else VG_BOOL_CLO(arg, "--trace-sched", VG_(clo_trace_sched))
1490 else VG_BOOL_CLO(arg, "--trace-signals", VG_(clo_trace_signals))
1491 else VG_BOOL_CLO(arg, "--trace-symtab", VG_(clo_trace_symtab))
sewardjce058b02005-05-01 08:55:38 +00001492 else VG_BOOL_CLO(arg, "--trace-cfi", VG_(clo_trace_cfi))
njn45270a22005-03-27 01:00:11 +00001493 else VG_BOOL_CLO(arg, "--trace-redir", VG_(clo_trace_redir))
1494 else VG_BOOL_CLO(arg, "--trace-syscalls", VG_(clo_trace_syscalls))
1495 else VG_BOOL_CLO(arg, "--trace-pthreads", VG_(clo_trace_pthreads))
1496 else VG_BOOL_CLO(arg, "--wait-for-gdb", VG_(clo_wait_for_gdb))
1497 else VG_BOOL_CLO(arg, "--model-pthreads", VG_(clo_model_pthreads))
sewardj72f98ff2002-06-13 17:23:38 +00001498
njn45270a22005-03-27 01:00:11 +00001499 else VG_STR_CLO (arg, "--db-command", VG_(clo_db_command))
1500 else VG_STR_CLO (arg, "--weird-hacks", VG_(clo_weird_hacks))
sewardjde4a1d02002-03-22 01:27:54 +00001501
njn45270a22005-03-27 01:00:11 +00001502 else VG_NUM_CLO (arg, "--dump-error", VG_(clo_dump_error))
1503 else VG_NUM_CLO (arg, "--input-fd", VG_(clo_input_fd))
1504 else VG_NUM_CLO (arg, "--sanity-level", VG_(clo_sanity_level))
1505 else VG_BNUM_CLO(arg, "--num-callers", VG_(clo_backtrace_size), 1,
1506 VG_DEEPEST_BACKTRACE)
sewardjde4a1d02002-03-22 01:27:54 +00001507
sewardj6c3a2192005-07-24 07:00:45 +00001508 else if (VG_CLO_STREQ(arg, "--smc-check=none"))
1509 VG_(clo_smc_check) = Vg_SmcNone;
1510 else if (VG_CLO_STREQ(arg, "--smc-check=stack"))
1511 VG_(clo_smc_check) = Vg_SmcStack;
1512 else if (VG_CLO_STREQ(arg, "--smc-check=all"))
1513 VG_(clo_smc_check) = Vg_SmcAll;
sewardj26412bd2005-07-07 10:05:05 +00001514
njn45270a22005-03-27 01:00:11 +00001515 else VG_BNUM_CLO(arg, "--vex-iropt-verbosity",
sewardj8b635a42004-11-22 19:01:47 +00001516 VG_(clo_vex_control).iropt_verbosity, 0, 10)
njn45270a22005-03-27 01:00:11 +00001517 else VG_BNUM_CLO(arg, "--vex-iropt-level",
sewardj8b635a42004-11-22 19:01:47 +00001518 VG_(clo_vex_control).iropt_level, 0, 2)
njn45270a22005-03-27 01:00:11 +00001519 else VG_BOOL_CLO(arg, "--vex-iropt-precise-memory-exns",
sewardj8b635a42004-11-22 19:01:47 +00001520 VG_(clo_vex_control).iropt_precise_memory_exns)
njn45270a22005-03-27 01:00:11 +00001521 else VG_BNUM_CLO(arg, "--vex-iropt-unroll-thresh",
sewardj8b635a42004-11-22 19:01:47 +00001522 VG_(clo_vex_control).iropt_unroll_thresh, 0, 400)
njn45270a22005-03-27 01:00:11 +00001523 else VG_BNUM_CLO(arg, "--vex-guest-max-insns",
sewardj8b635a42004-11-22 19:01:47 +00001524 VG_(clo_vex_control).guest_max_insns, 1, 100)
njn45270a22005-03-27 01:00:11 +00001525 else VG_BNUM_CLO(arg, "--vex-guest-chase-thresh",
sewardj8b635a42004-11-22 19:01:47 +00001526 VG_(clo_vex_control).guest_chase_thresh, 0, 99)
1527
nethercotef8548672004-06-21 12:42:35 +00001528 else if (VG_CLO_STREQN(9, arg, "--log-fd=")) {
njnbe9b47b2005-05-15 16:22:58 +00001529 log_to = VgLogTo_Fd;
nethercotef8548672004-06-21 12:42:35 +00001530 VG_(clo_log_name) = NULL;
1531 eventually_log_fd = (Int)VG_(atoll)(&arg[9]);
sewardj4cf05692002-10-27 20:28:29 +00001532 }
1533
nethercotef8548672004-06-21 12:42:35 +00001534 else if (VG_CLO_STREQN(11, arg, "--log-file=")) {
njnbe9b47b2005-05-15 16:22:58 +00001535 log_to = VgLogTo_File;
nethercotef8548672004-06-21 12:42:35 +00001536 VG_(clo_log_name) = &arg[11];
sewardj4cf05692002-10-27 20:28:29 +00001537 }
njnd6bc3c32005-03-27 00:44:31 +00001538
sewardjad311162005-07-19 11:25:02 +00001539 else if (VG_CLO_STREQN(11, arg, "--log-file=")) {
1540 log_to = VgLogTo_File;
1541 VG_(clo_log_name) = &arg[11];
1542 }
1543
1544 else if (VG_CLO_STREQN(21, arg, "--log-file-qualifier=")) {
1545 VG_(clo_log_file_qualifier) = &arg[21];
1546 }
1547
sewardj603d4102005-01-11 14:01:02 +00001548 else if (VG_CLO_STREQN(19, arg, "--log-file-exactly=")) {
njnbe9b47b2005-05-15 16:22:58 +00001549 log_to = VgLogTo_FileExactly;
sewardj603d4102005-01-11 14:01:02 +00001550 VG_(clo_log_name) = &arg[19];
1551 }
sewardjde4a1d02002-03-22 01:27:54 +00001552
nethercotef8548672004-06-21 12:42:35 +00001553 else if (VG_CLO_STREQN(13, arg, "--log-socket=")) {
njnbe9b47b2005-05-15 16:22:58 +00001554 log_to = VgLogTo_Socket;
nethercotef8548672004-06-21 12:42:35 +00001555 VG_(clo_log_name) = &arg[13];
sewardj73cf3bc2002-11-03 03:20:15 +00001556 }
1557
sewardj768db0e2005-07-19 14:18:56 +00001558 else if (VG_CLO_STREQN(19, arg, "--xml-user-comment=")) {
1559 VG_(clo_xml_user_comment) = &arg[19];
1560 }
1561
nethercote71980f02004-01-24 18:18:54 +00001562 else if (VG_CLO_STREQN(15, arg, "--suppressions=")) {
sewardjde4a1d02002-03-22 01:27:54 +00001563 if (VG_(clo_n_suppressions) >= VG_CLO_MAX_SFILES) {
njn25e49d8e72002-09-23 09:36:25 +00001564 VG_(message)(Vg_UserMsg, "Too many suppression files specified.");
sewardjde4a1d02002-03-22 01:27:54 +00001565 VG_(message)(Vg_UserMsg,
1566 "Increase VG_CLO_MAX_SFILES and recompile.");
nethercote71980f02004-01-24 18:18:54 +00001567 VG_(bad_option)(arg);
sewardjde4a1d02002-03-22 01:27:54 +00001568 }
nethercote71980f02004-01-24 18:18:54 +00001569 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = &arg[15];
sewardjde4a1d02002-03-22 01:27:54 +00001570 VG_(clo_n_suppressions)++;
1571 }
sewardjde4a1d02002-03-22 01:27:54 +00001572
sewardjfa8ec112005-01-19 11:55:34 +00001573 /* "stuvwxyz" --> stuvwxyz (binary) */
1574 else if (VG_CLO_STREQN(14, arg, "--trace-flags=")) {
1575 Int j;
1576 char* opt = & arg[14];
1577
1578 if (8 != VG_(strlen)(opt)) {
1579 VG_(message)(Vg_UserMsg,
1580 "--trace-flags argument must have 8 digits");
1581 VG_(bad_option)(arg);
1582 }
1583 for (j = 0; j < 8; j++) {
1584 if ('0' == opt[j]) { /* do nothing */ }
1585 else if ('1' == opt[j]) VG_(clo_trace_flags) |= (1 << (7-j));
1586 else {
1587 VG_(message)(Vg_UserMsg, "--trace-flags argument can only "
1588 "contain 0s and 1s");
1589 VG_(bad_option)(arg);
1590 }
1591 }
1592 }
1593
1594 /* "stuvwxyz" --> stuvwxyz (binary) */
1595 else if (VG_CLO_STREQN(16, arg, "--profile-flags=")) {
njn25e49d8e72002-09-23 09:36:25 +00001596 Int j;
nethercote71980f02004-01-24 18:18:54 +00001597 char* opt = & arg[16];
njn25e49d8e72002-09-23 09:36:25 +00001598
sewardj2a99cf62004-11-24 10:44:19 +00001599 if (8 != VG_(strlen)(opt)) {
njn25e49d8e72002-09-23 09:36:25 +00001600 VG_(message)(Vg_UserMsg,
sewardjfa8ec112005-01-19 11:55:34 +00001601 "--profile-flags argument must have 8 digits");
nethercote71980f02004-01-24 18:18:54 +00001602 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001603 }
sewardj8b635a42004-11-22 19:01:47 +00001604 for (j = 0; j < 8; j++) {
njn25e49d8e72002-09-23 09:36:25 +00001605 if ('0' == opt[j]) { /* do nothing */ }
sewardjfa8ec112005-01-19 11:55:34 +00001606 else if ('1' == opt[j]) VG_(clo_profile_flags) |= (1 << (7-j));
njn25e49d8e72002-09-23 09:36:25 +00001607 else {
sewardjfa8ec112005-01-19 11:55:34 +00001608 VG_(message)(Vg_UserMsg, "--profile-flags argument can only "
njn25e49d8e72002-09-23 09:36:25 +00001609 "contain 0s and 1s");
nethercote71980f02004-01-24 18:18:54 +00001610 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001611 }
1612 }
1613 }
sewardjde4a1d02002-03-22 01:27:54 +00001614
njn45270a22005-03-27 01:00:11 +00001615 else VG_NUM_CLO (arg, "--trace-notbelow", VG_(clo_trace_notbelow))
sewardjc771b292004-11-30 18:55:21 +00001616
sewardjd153fae2005-01-10 17:24:47 +00001617 else if (VG_CLO_STREQ(arg, "--gen-suppressions=no"))
1618 VG_(clo_gen_suppressions) = 0;
1619 else if (VG_CLO_STREQ(arg, "--gen-suppressions=yes"))
1620 VG_(clo_gen_suppressions) = 1;
1621 else if (VG_CLO_STREQ(arg, "--gen-suppressions=all"))
1622 VG_(clo_gen_suppressions) = 2;
1623
nethercote71980f02004-01-24 18:18:54 +00001624 else if ( ! VG_(needs).command_line_options
njn51d827b2005-05-09 01:02:08 +00001625 || ! VG_TDICT_CALL(tool_process_cmd_line_option, arg) ) {
nethercotef4928da2004-06-15 10:54:40 +00001626 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001627 }
njn8c0b3bb2005-03-12 21:20:39 +00001628 skip_arg:
1629 if (arg != vg_argv[i])
1630 free(arg);
sewardjde4a1d02002-03-22 01:27:54 +00001631 }
1632
sewardj998d40d2004-12-06 14:24:52 +00001633 /* Make VEX control parameters sane */
1634
1635 if (VG_(clo_vex_control).guest_chase_thresh
1636 >= VG_(clo_vex_control).guest_max_insns)
1637 VG_(clo_vex_control).guest_chase_thresh
1638 = VG_(clo_vex_control).guest_max_insns - 1;
1639
1640 if (VG_(clo_vex_control).guest_chase_thresh < 0)
1641 VG_(clo_vex_control).guest_chase_thresh = 0;
1642
1643 /* Check various option values */
nethercote27fec902004-06-16 21:26:32 +00001644
njnf9ebf672003-05-12 21:41:30 +00001645 if (VG_(clo_verbosity) < 0)
sewardjde4a1d02002-03-22 01:27:54 +00001646 VG_(clo_verbosity) = 0;
1647
nethercote04d0fbc2004-01-26 16:48:06 +00001648 if (VG_(clo_db_attach) && VG_(clo_trace_children)) {
sewardjde4a1d02002-03-22 01:27:54 +00001649 VG_(message)(Vg_UserMsg, "");
1650 VG_(message)(Vg_UserMsg,
nethercote04d0fbc2004-01-26 16:48:06 +00001651 "--db-attach=yes conflicts with --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001652 VG_(message)(Vg_UserMsg,
1653 "Please choose one or the other, but not both.");
nethercote04d0fbc2004-01-26 16:48:06 +00001654 VG_(bad_option)("--db-attach=yes and --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001655 }
1656
njnbe9b47b2005-05-15 16:22:58 +00001657 if (VG_(clo_gen_suppressions) > 0 &&
1658 !VG_(needs).core_errors && !VG_(needs).tool_errors) {
1659 VG_(message)(Vg_UserMsg,
1660 "Can't use --gen-suppressions= with this tool,");
1661 VG_(message)(Vg_UserMsg,
1662 "as it doesn't generate errors.");
1663 VG_(bad_option)("--gen-suppressions=");
1664 }
1665
sewardj71bc3cb2005-05-19 00:25:45 +00001666 /* If we've been asked to emit XML, mash around various other
1667 options so as to constrain the output somewhat, and to remove
1668 any need for user input during the run. */
1669 if (VG_(clo_xml)) {
1670 /* Disable suppression generation (requires user input) */
1671 VG_(clo_gen_suppressions) = 0;
1672 /* Disable attaching to GDB (requires user input) */
1673 VG_(clo_db_attach) = False;
1674 /* Set a known verbosity level */
1675 VG_(clo_verbosity) = 1;
1676 /* Disable error limits (this might be a bad idea!) */
1677 VG_(clo_error_limit) = False;
1678 /* Disable emulation warnings */
1679 VG_(clo_show_emwarns) = False;
1680 /* Disable waiting for GDB to debug Valgrind */
1681 VG_(clo_wait_for_gdb) = False;
1682 /* No file-descriptor leak checking yet */
1683 VG_(clo_track_fds) = False;
sewardj21f7f0c2005-07-06 19:46:48 +00001684 /* Disable timestamped output */
1685 VG_(clo_time_stamp) = False;
sewardj71bc3cb2005-05-19 00:25:45 +00001686 /* Also, we want to set options for the leak checker, but that
1687 will have to be done in Memcheck's flag-handling code, not
1688 here. */
1689 }
1690
njnbe9b47b2005-05-15 16:22:58 +00001691 /* All non-logging-related options have been checked. If the logging
1692 option specified is ok, we can switch to it, as we know we won't
1693 have to generate any other command-line-related error messages.
1694 (So far we should be still attached to stderr, so we can show on
1695 the terminal any problems to do with processing command line
1696 opts.)
1697
1698 So set up logging now. After this is done, VG_(clo_log_fd)
sewardj4cf05692002-10-27 20:28:29 +00001699 should be connected to whatever sink has been selected, and we
1700 indiscriminately chuck stuff into it without worrying what the
1701 nature of it is. Oh the wonder of Unix streams. */
1702
njnbe9b47b2005-05-15 16:22:58 +00001703 vg_assert(VG_(clo_log_fd) == 2 /* stderr */);
1704 vg_assert(VG_(logging_to_socket) == False);
sewardj4cf05692002-10-27 20:28:29 +00001705
njnbe9b47b2005-05-15 16:22:58 +00001706 switch (log_to) {
sewardj73cf3bc2002-11-03 03:20:15 +00001707
sewardj4cf05692002-10-27 20:28:29 +00001708 case VgLogTo_Fd:
nethercotef8548672004-06-21 12:42:35 +00001709 vg_assert(VG_(clo_log_name) == NULL);
1710 VG_(clo_log_fd) = eventually_log_fd;
sewardj4cf05692002-10-27 20:28:29 +00001711 break;
sewardj73cf3bc2002-11-03 03:20:15 +00001712
sewardj4cf05692002-10-27 20:28:29 +00001713 case VgLogTo_File: {
sewardjad311162005-07-19 11:25:02 +00001714 HChar logfilename[1000];
1715 Int seq = 0;
1716 Int pid = VG_(getpid)();
1717 HChar* qual = NULL;
jsgff3c3f1a2003-10-14 22:13:28 +00001718
nethercotef8548672004-06-21 12:42:35 +00001719 vg_assert(VG_(clo_log_name) != NULL);
1720 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
jsgff3c3f1a2003-10-14 22:13:28 +00001721
sewardjad311162005-07-19 11:25:02 +00001722 if (VG_(clo_log_file_qualifier)) {
1723 qual = VG_(getenv)(VG_(clo_log_file_qualifier));
1724 }
1725
nethercote71980f02004-01-24 18:18:54 +00001726 for (;;) {
sewardj92645592005-07-23 09:18:34 +00001727 HChar pidtxt[20], seqtxt[20];
1728
1729 VG_(sprintf)(pidtxt, "%d", pid);
1730
1731 if (seq == 0)
1732 seqtxt[0] = 0;
1733 else
1734 VG_(sprintf)(seqtxt, ".%d", seq);
1735
jsgff3c3f1a2003-10-14 22:13:28 +00001736 seq++;
1737
sewardj92645592005-07-23 09:18:34 +00001738 /* Result:
1739 if (qual) base_name ++ "." ++ qual ++ seqtxt
1740 if (not qual) base_name ++ "." ++ pid ++ seqtxt
1741 */
1742 VG_(sprintf)( logfilename,
1743 "%s.%s%s",
1744 VG_(clo_log_name),
1745 qual ? qual : pidtxt,
1746 seqtxt );
1747
njnbe9b47b2005-05-15 16:22:58 +00001748 // EXCL: it will fail with EEXIST if the file already exists.
sewardj92645592005-07-23 09:18:34 +00001749 sres
jsgff3c3f1a2003-10-14 22:13:28 +00001750 = VG_(open)(logfilename,
1751 VKI_O_CREAT|VKI_O_WRONLY|VKI_O_EXCL|VKI_O_TRUNC,
1752 VKI_S_IRUSR|VKI_S_IWUSR);
sewardj92645592005-07-23 09:18:34 +00001753 if (!sres.isError) {
1754 eventually_log_fd = sres.val;
nethercotef8548672004-06-21 12:42:35 +00001755 VG_(clo_log_fd) = VG_(safe_fd)(eventually_log_fd);
sewardj603d4102005-01-11 14:01:02 +00001756 break; /* for (;;) */
jsgff3c3f1a2003-10-14 22:13:28 +00001757 } else {
njnbe9b47b2005-05-15 16:22:58 +00001758 // If the file already existed, we try the next name. If it
1759 // was some other file error, we give up.
sewardj92645592005-07-23 09:18:34 +00001760 if (sres.val != VKI_EEXIST) {
jsgff3c3f1a2003-10-14 22:13:28 +00001761 VG_(message)(Vg_UserMsg,
njn02bc4b82005-05-15 17:28:26 +00001762 "Can't create/open log file '%s.pid%d'; giving up!",
nethercotef8548672004-06-21 12:42:35 +00001763 VG_(clo_log_name), pid);
jsgff3c3f1a2003-10-14 22:13:28 +00001764 VG_(bad_option)(
sewardj603d4102005-01-11 14:01:02 +00001765 "--log-file=<file> (didn't work out for some reason.)");
njnbe9b47b2005-05-15 16:22:58 +00001766 /*NOTREACHED*/
jsgff3c3f1a2003-10-14 22:13:28 +00001767 }
1768 }
1769 }
sewardj603d4102005-01-11 14:01:02 +00001770 break; /* switch (VG_(clo_log_to)) */
1771 }
1772
1773 case VgLogTo_FileExactly: {
sewardj603d4102005-01-11 14:01:02 +00001774 vg_assert(VG_(clo_log_name) != NULL);
1775 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
sewardj603d4102005-01-11 14:01:02 +00001776
sewardj92645592005-07-23 09:18:34 +00001777 sres
njnbe9b47b2005-05-15 16:22:58 +00001778 = VG_(open)(VG_(clo_log_name),
sewardj603d4102005-01-11 14:01:02 +00001779 VKI_O_CREAT|VKI_O_WRONLY|VKI_O_TRUNC,
1780 VKI_S_IRUSR|VKI_S_IWUSR);
sewardj92645592005-07-23 09:18:34 +00001781 if (!sres.isError) {
1782 eventually_log_fd = sres.val;
sewardj603d4102005-01-11 14:01:02 +00001783 VG_(clo_log_fd) = VG_(safe_fd)(eventually_log_fd);
njnbe9b47b2005-05-15 16:22:58 +00001784 } else {
sewardj603d4102005-01-11 14:01:02 +00001785 VG_(message)(Vg_UserMsg,
njn02bc4b82005-05-15 17:28:26 +00001786 "Can't create/open log file '%s'; giving up!",
sewardj603d4102005-01-11 14:01:02 +00001787 VG_(clo_log_name));
1788 VG_(bad_option)(
1789 "--log-file-exactly=<file> (didn't work out for some reason.)");
1790 /*NOTREACHED*/
1791 }
1792 break; /* switch (VG_(clo_log_to)) */
sewardj73cf3bc2002-11-03 03:20:15 +00001793 }
1794
1795 case VgLogTo_Socket: {
nethercotef8548672004-06-21 12:42:35 +00001796 vg_assert(VG_(clo_log_name) != NULL);
1797 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
1798 eventually_log_fd = VG_(connect_via_socket)( VG_(clo_log_name) );
1799 if (eventually_log_fd == -1) {
sewardj73cf3bc2002-11-03 03:20:15 +00001800 VG_(message)(Vg_UserMsg,
nethercotef8548672004-06-21 12:42:35 +00001801 "Invalid --log-socket=ipaddr or --log-socket=ipaddr:port spec");
sewardj73cf3bc2002-11-03 03:20:15 +00001802 VG_(message)(Vg_UserMsg,
njn02bc4b82005-05-15 17:28:26 +00001803 "of '%s'; giving up!", VG_(clo_log_name) );
sewardj73cf3bc2002-11-03 03:20:15 +00001804 VG_(bad_option)(
nethercotef8548672004-06-21 12:42:35 +00001805 "--log-socket=");
njnbe9b47b2005-05-15 16:22:58 +00001806 /*NOTREACHED*/
sewardj4cf05692002-10-27 20:28:29 +00001807 }
nethercotef8548672004-06-21 12:42:35 +00001808 if (eventually_log_fd == -2) {
sewardj73cf3bc2002-11-03 03:20:15 +00001809 VG_(message)(Vg_UserMsg,
njn02bc4b82005-05-15 17:28:26 +00001810 "valgrind: failed to connect to logging server '%s'.",
nethercotef8548672004-06-21 12:42:35 +00001811 VG_(clo_log_name) );
sewardj570f8902002-11-03 11:44:36 +00001812 VG_(message)(Vg_UserMsg,
1813 "Log messages will sent to stderr instead." );
1814 VG_(message)(Vg_UserMsg,
1815 "" );
1816 /* We don't change anything here. */
njnbe9b47b2005-05-15 16:22:58 +00001817 vg_assert(VG_(clo_log_fd) == 2);
sewardj570f8902002-11-03 11:44:36 +00001818 } else {
nethercotef8548672004-06-21 12:42:35 +00001819 vg_assert(eventually_log_fd > 0);
1820 VG_(clo_log_fd) = eventually_log_fd;
njnbe9b47b2005-05-15 16:22:58 +00001821 VG_(logging_to_socket) = True;
sewardj570f8902002-11-03 11:44:36 +00001822 }
sewardj73cf3bc2002-11-03 03:20:15 +00001823 break;
1824 }
sewardj4cf05692002-10-27 20:28:29 +00001825 }
1826
sewardj71bc3cb2005-05-19 00:25:45 +00001827
1828 /* Check that the requested tool actually supports XML output. */
cerion39655202005-07-13 14:18:24 +00001829 if (VG_(clo_xml) && 0 != VG_(strcmp)(toolname, "memcheck")
1830 && 0 != VG_(strcmp)(toolname, "none")) {
sewardj71bc3cb2005-05-19 00:25:45 +00001831 VG_(clo_xml) = False;
1832 VG_(message)(Vg_UserMsg,
cerion39655202005-07-13 14:18:24 +00001833 "Currently only Memcheck|None supports XML output.");
sewardj71bc3cb2005-05-19 00:25:45 +00001834 VG_(bad_option)("--xml=yes");
1835 /*NOTREACHED*/
1836 }
1837
njnbe9b47b2005-05-15 16:22:58 +00001838 // Move log_fd into the safe range, so it doesn't conflict with any app fds.
1839 // XXX: this is more or less duplicating the behaviour of the calls to
1840 // VG_(safe_fd)() above, although this does not close the original fd.
1841 // Perhaps the VG_(safe_fd)() calls above should be removed, and this
1842 // code should be replaced with a call to VG_(safe_fd)(). --njn
thughesad1c9562004-06-26 11:27:52 +00001843 eventually_log_fd = VG_(fcntl)(VG_(clo_log_fd), VKI_F_DUPFD, VG_(fd_hard_limit));
nethercotef8548672004-06-21 12:42:35 +00001844 if (eventually_log_fd < 0)
jsgf855d93d2003-10-13 22:26:55 +00001845 VG_(message)(Vg_UserMsg, "valgrind: failed to move logfile fd into safe range");
1846 else {
nethercotef8548672004-06-21 12:42:35 +00001847 VG_(clo_log_fd) = eventually_log_fd;
1848 VG_(fcntl)(VG_(clo_log_fd), VKI_F_SETFD, VKI_FD_CLOEXEC);
jsgf855d93d2003-10-13 22:26:55 +00001849 }
1850
sewardj4cf05692002-10-27 20:28:29 +00001851 /* Ok, the logging sink is running now. Print a suitable preamble.
1852 If logging to file or a socket, write details of parent PID and
1853 command line args, to help people trying to interpret the
1854 results of a run which encompasses multiple processes. */
sewardjde4a1d02002-03-22 01:27:54 +00001855
sewardj71bc3cb2005-05-19 00:25:45 +00001856 if (VG_(clo_xml)) {
sewardj8665d8e2005-06-01 17:35:23 +00001857 VG_(message)(Vg_UserMsg, "<?xml version=\"1.0\"?>");
1858 VG_(message)(Vg_UserMsg, "");
sewardj71bc3cb2005-05-19 00:25:45 +00001859 VG_(message)(Vg_UserMsg, "<valgrindoutput>");
1860 VG_(message)(Vg_UserMsg, "");
1861 VG_(message)(Vg_UserMsg, "<protocolversion>1</protocolversion>");
1862 VG_(message)(Vg_UserMsg, "");
1863 }
1864
sewardjd7bddad2005-06-13 16:48:32 +00001865 HChar* xpre = VG_(clo_xml) ? " <line>" : "";
1866 HChar* xpost = VG_(clo_xml) ? "</line>" : "";
sewardj71bc3cb2005-05-19 00:25:45 +00001867
sewardj83adf412002-05-01 01:25:45 +00001868 if (VG_(clo_verbosity > 0)) {
sewardjd7bddad2005-06-13 16:48:32 +00001869
1870 if (VG_(clo_xml))
1871 VG_(message)(Vg_UserMsg, "<preamble>");
1872
nethercote996901a2004-08-03 13:29:09 +00001873 /* Tool details */
sewardj71bc3cb2005-05-19 00:25:45 +00001874 VG_(message)(Vg_UserMsg, "%s%s%s%s, %s.%s",
1875 xpre,
njnd04b7c62002-10-03 14:05:52 +00001876 VG_(details).name,
njnb9c427c2004-12-01 14:14:42 +00001877 NULL == VG_(details).version ? "" : "-",
njnd04b7c62002-10-03 14:05:52 +00001878 NULL == VG_(details).version
1879 ? (Char*)"" : VG_(details).version,
sewardj71bc3cb2005-05-19 00:25:45 +00001880 VG_(details).description,
1881 xpost);
1882 VG_(message)(Vg_UserMsg, "%s%s%s",
1883 xpre, VG_(details).copyright_author, xpost);
sewardj3b2736a2002-03-24 12:18:35 +00001884
njnd04b7c62002-10-03 14:05:52 +00001885 /* Core details */
1886 VG_(message)(Vg_UserMsg,
sewardj71bc3cb2005-05-19 00:25:45 +00001887 "%sUsing LibVEX rev %s, a library for dynamic binary translation.%s",
1888 xpre, LibVEX_Version(), xpost );
sewardjc7025332004-12-13 18:30:39 +00001889 VG_(message)(Vg_UserMsg,
sewardj71bc3cb2005-05-19 00:25:45 +00001890 "%sCopyright (C) 2004-2005, and GNU GPL'd, by OpenWorks LLP.%s",
1891 xpre, xpost );
sewardjc7025332004-12-13 18:30:39 +00001892 VG_(message)(Vg_UserMsg,
sewardj71bc3cb2005-05-19 00:25:45 +00001893 "%sUsing valgrind-%s, a dynamic binary instrumentation framework.%s",
1894 xpre, VERSION, xpost);
sewardjde4a1d02002-03-22 01:27:54 +00001895 VG_(message)(Vg_UserMsg,
sewardj71bc3cb2005-05-19 00:25:45 +00001896 "%sCopyright (C) 2000-2005, and GNU GPL'd, by Julian Seward et al.%s",
1897 xpre, xpost );
sewardjd7bddad2005-06-13 16:48:32 +00001898
1899 if (VG_(clo_xml))
1900 VG_(message)(Vg_UserMsg, "</preamble>");
njnd04b7c62002-10-03 14:05:52 +00001901 }
1902
sewardjd94b90a2005-06-29 23:15:56 +00001903 if (!VG_(clo_xml) && VG_(clo_verbosity) > 0 && log_to != VgLogTo_Fd) {
sewardj4cf05692002-10-27 20:28:29 +00001904 VG_(message)(Vg_UserMsg, "");
1905 VG_(message)(Vg_UserMsg,
1906 "My PID = %d, parent PID = %d. Prog and args are:",
1907 VG_(getpid)(), VG_(getppid)() );
1908 for (i = 0; i < VG_(client_argc); i++)
1909 VG_(message)(Vg_UserMsg, " %s", VG_(client_argv)[i]);
1910 }
sewardj71bc3cb2005-05-19 00:25:45 +00001911 else
1912 if (VG_(clo_xml)) {
1913 VG_(message)(Vg_UserMsg, "");
1914 VG_(message)(Vg_UserMsg, "<pid>%d</pid>", VG_(getpid)());
1915 VG_(message)(Vg_UserMsg, "<ppid>%d</ppid>", VG_(getppid)());
sewardj97f7e0c2005-07-19 15:00:25 +00001916 VG_(message)(Vg_UserMsg, "<tool>%t</tool>", toolname);
sewardjad311162005-07-19 11:25:02 +00001917 if (VG_(clo_log_file_qualifier)) {
1918 HChar* val = VG_(getenv)(VG_(clo_log_file_qualifier));
sewardj97f7e0c2005-07-19 15:00:25 +00001919 VG_(message)(Vg_UserMsg, "<logfilequalifier> <var>%t</var> "
1920 "<value>%t</value> </logfilequalifier>",
sewardjad311162005-07-19 11:25:02 +00001921 VG_(clo_log_file_qualifier),
1922 val ? val : "");
1923 }
sewardj768db0e2005-07-19 14:18:56 +00001924 if (VG_(clo_xml_user_comment)) {
1925 /* Note: the user comment itself is XML and is therefore to
1926 be passed through verbatim (%s) rather than escaped
1927 (%t). */
1928 VG_(message)(Vg_UserMsg, "<usercomment>%s</usercomment>",
1929 VG_(clo_xml_user_comment));
1930 }
sewardj71bc3cb2005-05-19 00:25:45 +00001931 VG_(message)(Vg_UserMsg, "");
sewardjb8a3dac2005-07-19 12:39:11 +00001932 VG_(message)(Vg_UserMsg, "<args>");
1933 VG_(message)(Vg_UserMsg, " <vargv>");
1934 for (i = 0; i < vg_argc; i++) {
1935 HChar* tag = i==0 ? "exe" : "arg";
sewardj768db0e2005-07-19 14:18:56 +00001936 VG_(message)(Vg_UserMsg, " <%s>%t</%s>",
sewardjb8a3dac2005-07-19 12:39:11 +00001937 tag, vg_argv[i], tag);
1938 }
1939 VG_(message)(Vg_UserMsg, " </vargv>");
1940 VG_(message)(Vg_UserMsg, " <argv>");
sewardj8665d8e2005-06-01 17:35:23 +00001941 for (i = 0; i < VG_(client_argc); i++) {
1942 HChar* tag = i==0 ? "exe" : "arg";
sewardj97f7e0c2005-07-19 15:00:25 +00001943 VG_(message)(Vg_UserMsg, " <%s>%t</%s>",
sewardj8665d8e2005-06-01 17:35:23 +00001944 tag, VG_(client_argv)[i], tag);
1945 }
sewardjb8a3dac2005-07-19 12:39:11 +00001946 VG_(message)(Vg_UserMsg, " </argv>");
1947 VG_(message)(Vg_UserMsg, "</args>");
sewardj71bc3cb2005-05-19 00:25:45 +00001948 }
sewardj4cf05692002-10-27 20:28:29 +00001949
sewardjde4a1d02002-03-22 01:27:54 +00001950 if (VG_(clo_verbosity) > 1) {
sewardj92645592005-07-23 09:18:34 +00001951 SysRes fd;
njnbe9b47b2005-05-15 16:22:58 +00001952 if (log_to != VgLogTo_Fd)
njn1fd5eb22005-03-13 05:43:23 +00001953 VG_(message)(Vg_DebugMsg, "");
1954 VG_(message)(Vg_DebugMsg, "Valgrind library directory: %s", VG_(libdir));
1955 VG_(message)(Vg_DebugMsg, "Command line");
njn86dc2bc2003-09-09 07:26:21 +00001956 for (i = 0; i < VG_(client_argc); i++)
njn1fd5eb22005-03-13 05:43:23 +00001957 VG_(message)(Vg_DebugMsg, " %s", VG_(client_argv)[i]);
njn86dc2bc2003-09-09 07:26:21 +00001958
njn1fd5eb22005-03-13 05:43:23 +00001959 VG_(message)(Vg_DebugMsg, "Startup, with flags:");
nethercotef6a1d502004-08-09 12:21:57 +00001960 for (i = 1; i < vg_argc; i++) {
njn1fd5eb22005-03-13 05:43:23 +00001961 VG_(message)(Vg_DebugMsg, " %s", vg_argv[i]);
sewardjde4a1d02002-03-22 01:27:54 +00001962 }
nethercotea70f7352004-04-18 12:08:46 +00001963
njn1fd5eb22005-03-13 05:43:23 +00001964 VG_(message)(Vg_DebugMsg, "Contents of /proc/version:");
nethercotea70f7352004-04-18 12:08:46 +00001965 fd = VG_(open) ( "/proc/version", VKI_O_RDONLY, 0 );
sewardj92645592005-07-23 09:18:34 +00001966 if (fd.isError) {
njn1fd5eb22005-03-13 05:43:23 +00001967 VG_(message)(Vg_DebugMsg, " can't open /proc/version");
nethercotea70f7352004-04-18 12:08:46 +00001968 } else {
sewardj71bc3cb2005-05-19 00:25:45 +00001969# define BUF_LEN 256
nethercotea70f7352004-04-18 12:08:46 +00001970 Char version_buf[BUF_LEN];
sewardj92645592005-07-23 09:18:34 +00001971 Int n = VG_(read) ( fd.val, version_buf, BUF_LEN );
njnbe9b47b2005-05-15 16:22:58 +00001972 vg_assert(n <= BUF_LEN);
nethercotea70f7352004-04-18 12:08:46 +00001973 if (n > 0) {
1974 version_buf[n-1] = '\0';
njn1fd5eb22005-03-13 05:43:23 +00001975 VG_(message)(Vg_DebugMsg, " %s", version_buf);
nethercotea70f7352004-04-18 12:08:46 +00001976 } else {
njn1fd5eb22005-03-13 05:43:23 +00001977 VG_(message)(Vg_DebugMsg, " (empty?)");
nethercotea70f7352004-04-18 12:08:46 +00001978 }
sewardj92645592005-07-23 09:18:34 +00001979 VG_(close)(fd.val);
sewardj71bc3cb2005-05-19 00:25:45 +00001980# undef BUF_LEN
nethercotea70f7352004-04-18 12:08:46 +00001981 }
sewardjde4a1d02002-03-22 01:27:54 +00001982 }
1983
fitzhardinge98abfc72003-12-16 02:05:15 +00001984 if (VG_(clo_n_suppressions) < VG_CLO_MAX_SFILES-1 &&
njn95ec8702004-11-22 16:46:13 +00001985 (VG_(needs).core_errors || VG_(needs).tool_errors)) {
njn842c26e2005-06-28 02:54:52 +00001986 /* If we haven't reached the max number of suppressions, load
1987 the default one. */
fitzhardinge98abfc72003-12-16 02:05:15 +00001988 static const Char default_supp[] = "default.supp";
1989 Int len = VG_(strlen)(VG_(libdir)) + 1 + sizeof(default_supp);
1990 Char *buf = VG_(arena_malloc)(VG_AR_CORE, len);
1991 VG_(sprintf)(buf, "%s/%s", VG_(libdir), default_supp);
1992 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = buf;
1993 VG_(clo_n_suppressions)++;
sewardjde4a1d02002-03-22 01:27:54 +00001994 }
1995}
1996
nethercotef6a1d502004-08-09 12:21:57 +00001997// Build the string for VALGRINDCLO.
1998Char* VG_(build_child_VALGRINDCLO)( Char* exename )
1999{
2000 /* If we're tracing the children, then we need to start it
2001 with our starter+arguments, which are copied into VALGRINDCLO,
2002 except the --exec= option is changed if present.
2003 */
2004 Int i;
2005 Char *exec;
2006 Char *cp;
2007 Char *optvar;
2008 Int optlen, execlen;
2009
2010 // All these allocated blocks are not free - because we're either
2011 // going to exec, or panic when we fail.
2012
2013 // Create --exec= option: "--exec=<exename>"
2014 exec = VG_(arena_malloc)(VG_AR_CORE,
2015 VG_(strlen)( exename ) + 7/*--exec=*/ + 1/*\0*/);
2016 vg_assert(NULL != exec);
2017 VG_(sprintf)(exec, "--exec=%s", exename);
2018
2019 // Allocate space for optvar (may overestimate by counting --exec twice,
2020 // no matter)
2021 optlen = 1;
2022 for (i = 0; i < vg_argc; i++)
2023 optlen += VG_(strlen)(vg_argv[i]) + 1;
2024 optlen += VG_(strlen)(exec)+1;
2025 optvar = VG_(arena_malloc)(VG_AR_CORE, optlen);
2026
2027 // Copy all valgrind args except the old --exec (if present)
2028 // VG_CLO_SEP is the separator.
2029 cp = optvar;
2030 for (i = 1; i < vg_argc; i++) {
2031 Char *arg = vg_argv[i];
2032
2033 if (VG_(memcmp)(arg, "--exec=", 7) == 0) {
2034 // don't copy existing --exec= arg
2035 } else if (VG_(strcmp)(arg, "--") == 0) {
2036 // stop at "--"
2037 break;
2038 } else {
2039 // copy non "--exec" arg
2040 Int len = VG_(strlen)(arg);
2041 VG_(memcpy)(cp, arg, len);
2042 cp += len;
2043 *cp++ = VG_CLO_SEP;
2044 }
2045 }
2046 // Add the new --exec= option
2047 execlen = VG_(strlen)(exec);
2048 VG_(memcpy)(cp, exec, execlen);
2049 cp += execlen;
2050 *cp++ = VG_CLO_SEP;
2051
2052 *cp = '\0';
2053
2054 return optvar;
2055}
2056
2057// Build "/proc/self/fd/<execfd>".
2058Char* VG_(build_child_exename)( void )
2059{
2060 Char* exename = VG_(arena_malloc)(VG_AR_CORE, 64);
2061 vg_assert(NULL != exename);
2062 VG_(sprintf)(exename, "/proc/self/fd/%d", vgexecfd);
2063 return exename;
2064}
2065
sewardjde4a1d02002-03-22 01:27:54 +00002066
nethercote71980f02004-01-24 18:18:54 +00002067/*====================================================================*/
2068/*=== File descriptor setup ===*/
2069/*====================================================================*/
2070
2071static void setup_file_descriptors(void)
2072{
2073 struct vki_rlimit rl;
2074
2075 /* Get the current file descriptor limits. */
2076 if (VG_(getrlimit)(VKI_RLIMIT_NOFILE, &rl) < 0) {
2077 rl.rlim_cur = 1024;
2078 rl.rlim_max = 1024;
2079 }
2080
2081 /* Work out where to move the soft limit to. */
njn14319cc2005-03-13 06:26:22 +00002082 if (rl.rlim_cur + N_RESERVED_FDS <= rl.rlim_max) {
2083 rl.rlim_cur = rl.rlim_cur + N_RESERVED_FDS;
nethercote71980f02004-01-24 18:18:54 +00002084 } else {
2085 rl.rlim_cur = rl.rlim_max;
2086 }
2087
2088 /* Reserve some file descriptors for our use. */
njn14319cc2005-03-13 06:26:22 +00002089 VG_(fd_soft_limit) = rl.rlim_cur - N_RESERVED_FDS;
2090 VG_(fd_hard_limit) = rl.rlim_cur - N_RESERVED_FDS;
nethercote71980f02004-01-24 18:18:54 +00002091
2092 /* Update the soft limit. */
2093 VG_(setrlimit)(VKI_RLIMIT_NOFILE, &rl);
2094
nethercotef6a1d502004-08-09 12:21:57 +00002095 if (vgexecfd != -1)
2096 vgexecfd = VG_(safe_fd)( vgexecfd );
nethercote71980f02004-01-24 18:18:54 +00002097 if (VG_(clexecfd) != -1)
2098 VG_(clexecfd) = VG_(safe_fd)( VG_(clexecfd) );
2099}
2100
nethercote71980f02004-01-24 18:18:54 +00002101/*====================================================================*/
nethercote71980f02004-01-24 18:18:54 +00002102/*=== Initialise program data/text, etc. ===*/
2103/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +00002104
sewardjb5f6f512005-03-10 23:59:00 +00002105static void build_valgrind_map_callback ( Addr start, SizeT size, UInt prot,
2106 UInt dev, UInt ino, ULong foffset,
2107 const UChar* filename )
sewardjde4a1d02002-03-22 01:27:54 +00002108{
nethercote71980f02004-01-24 18:18:54 +00002109 /* Only record valgrind mappings for now, without loading any
2110 symbols. This is so we know where the free space is before we
2111 start allocating more memory (note: heap is OK, it's just mmap
2112 which is the problem here). */
sewardjb5f6f512005-03-10 23:59:00 +00002113 if (start >= VG_(client_end) && start < VG_(valgrind_last)) {
sewardj8c615892005-04-25 02:38:28 +00002114 VG_(debugLog)(2, "main",
2115 "valgrind-seg: %p-%p prot 0x%x file=%s\n",
njna4469a72005-05-08 02:06:33 +00002116 (void*)start, (void*)(start+size), prot, filename);
sewardjb5f6f512005-03-10 23:59:00 +00002117 VG_(map_file_segment)(start, size, prot,
sewardj8c615892005-04-25 02:38:28 +00002118 SF_MMAP|SF_NOSYMS|SF_VALGRIND,
2119 dev, ino, foffset, filename);
sewardjb5f6f512005-03-10 23:59:00 +00002120 /* update VG_(valgrind_last) if it looks wrong */
2121 if (start+size > VG_(valgrind_last))
sewardj8c615892005-04-25 02:38:28 +00002122 VG_(valgrind_last) = start+size-1;
nethercote71980f02004-01-24 18:18:54 +00002123 }
sewardjde4a1d02002-03-22 01:27:54 +00002124}
2125
nethercote71980f02004-01-24 18:18:54 +00002126// Global var used to pass local data to callback
nethercote4ad74312004-10-26 09:59:49 +00002127Addr sp_at_startup___global_arg = 0;
sewardjde4a1d02002-03-22 01:27:54 +00002128
sewardjb5f6f512005-03-10 23:59:00 +00002129/*
2130 This second pass adds in client mappings, and loads symbol tables
2131 for all interesting mappings. The trouble is that things can
2132 change as we go, because we're calling the Tool to track memory as
2133 we find it.
2134
2135 So for Valgrind mappings, we don't replace any mappings which
2136 aren't still identical (which will include the .so mappings, so we
2137 will load their symtabs)>
2138 */
2139static void build_segment_map_callback ( Addr start, SizeT size, UInt prot,
2140 UInt dev, UInt ino, ULong foffset,
2141 const UChar* filename )
sewardj45b672d2003-07-25 19:58:11 +00002142{
nethercote71980f02004-01-24 18:18:54 +00002143 UInt flags;
2144 Bool is_stack_segment;
2145 Addr r_esp;
sewardj45b672d2003-07-25 19:58:11 +00002146
nethercote71980f02004-01-24 18:18:54 +00002147 is_stack_segment
2148 = (start == VG_(clstk_base) && (start+size) == VG_(clstk_end));
fitzhardinge98abfc72003-12-16 02:05:15 +00002149
sewardj8c615892005-04-25 02:38:28 +00002150 VG_(debugLog)(2, "main",
2151 "any-seg: %p-%p prot 0x%x stack=%d file=%s\n",
njna4469a72005-05-08 02:06:33 +00002152 (void*)start, (void*)(start+size), prot, is_stack_segment,
2153 filename);
fitzhardinge98abfc72003-12-16 02:05:15 +00002154
nethercote71980f02004-01-24 18:18:54 +00002155 if (is_stack_segment)
2156 flags = SF_STACK | SF_GROWDOWN;
2157 else
njn0ae787c2005-06-28 22:14:53 +00002158 flags = SF_MMAP;
fitzhardinge98abfc72003-12-16 02:05:15 +00002159
nethercote71980f02004-01-24 18:18:54 +00002160 if (filename != NULL)
2161 flags |= SF_FILE;
fitzhardinge98abfc72003-12-16 02:05:15 +00002162
sewardjb5f6f512005-03-10 23:59:00 +00002163#if 0
2164 // This needs to be fixed properly. jrs 20050307
2165 if (start >= VG_(client_end) && start < VG_(valgrind_last)) {
2166 Segment *s = VG_(find_segment_before)(start);
fitzhardinge98abfc72003-12-16 02:05:15 +00002167
sewardjb5f6f512005-03-10 23:59:00 +00002168 /* We have to be a bit careful about inserting new mappings into
2169 the Valgrind part of the address space. We're actively
2170 changing things as we parse these mappings, particularly in
2171 shadow memory, and so we don't want to overwrite those
2172 changes. Therefore, we only insert/update a mapping if it is
2173 mapped from a file or it exactly matches an existing mapping.
fitzhardinge98abfc72003-12-16 02:05:15 +00002174
sewardjb5f6f512005-03-10 23:59:00 +00002175 NOTE: we're only talking about the Segment list mapping
2176 metadata; this doesn't actually mmap anything more. */
2177 if (filename || (s && s->addr == start && s->len == size)) {
2178 flags |= SF_VALGRIND;
2179 VG_(map_file_segment)(start, size, prot, flags, dev, ino, foffset, filename);
2180 } else {
2181 /* assert range is already mapped */
2182 vg_assert(VG_(is_addressable)(start, size, VKI_PROT_NONE));
2183 }
2184 } else
2185#endif
2186 VG_(map_file_segment)(start, size, prot, flags, dev, ino, foffset, filename);
2187
2188 if (VG_(is_client_addr)(start) && VG_(is_client_addr)(start+size-1)) {
2189 VG_TRACK( new_mem_startup, start, size,
2190 !!(prot & VKI_PROT_READ),
2191 !!(prot & VKI_PROT_WRITE),
2192 !!(prot & VKI_PROT_EXEC));
2193 }
sewardj3e1eb1f2002-05-18 13:14:17 +00002194
nethercote71980f02004-01-24 18:18:54 +00002195 /* If this is the stack segment mark all below %esp as noaccess. */
nethercote4ad74312004-10-26 09:59:49 +00002196 r_esp = sp_at_startup___global_arg;
nethercote71980f02004-01-24 18:18:54 +00002197 vg_assert(0 != r_esp);
2198 if (is_stack_segment) {
sewardjb5f6f512005-03-10 23:59:00 +00002199 if (0) {
2200 VG_(message)(Vg_DebugMsg, "invalidating stack area: %p .. %p",
nethercote71980f02004-01-24 18:18:54 +00002201 start,r_esp);
sewardjb5f6f512005-03-10 23:59:00 +00002202 VG_(message)(Vg_DebugMsg, " validating stack area: %p .. %p",
2203 r_esp, start+size);
2204 }
nethercote71980f02004-01-24 18:18:54 +00002205 VG_TRACK( die_mem_stack, start, r_esp-start );
sewardjb5f6f512005-03-10 23:59:00 +00002206 // what's this for?
2207 //VG_TRACK( post_mem_write, r_esp, (start+size)-r_esp );
sewardjde4a1d02002-03-22 01:27:54 +00002208 }
sewardjde4a1d02002-03-22 01:27:54 +00002209}
2210
njn2da73352005-06-18 01:35:16 +00002211/*====================================================================*/
2212/*=== Initialise the first thread. ===*/
2213/*====================================================================*/
2214
2215/* Given a pointer to the ThreadArchState for thread 1 (the root
2216 thread), initialise the VEX guest state, and copy in essential
2217 starting values.
2218*/
2219static void init_thread1state ( Addr client_ip,
2220 Addr sp_at_startup,
2221 /*inout*/ ThreadArchState* arch )
2222{
2223#if defined(VGA_x86)
2224 vg_assert(0 == sizeof(VexGuestX86State) % 8);
2225
2226 /* Zero out the initial state, and set up the simulated FPU in a
2227 sane way. */
2228 LibVEX_GuestX86_initialise(&arch->vex);
2229
2230 /* Zero out the shadow area. */
2231 VG_(memset)(&arch->vex_shadow, 0, sizeof(VexGuestX86State));
2232
2233 /* Put essential stuff into the new state. */
2234 arch->vex.guest_ESP = sp_at_startup;
2235 arch->vex.guest_EIP = client_ip;
2236
2237 /* initialise %cs, %ds and %ss to point at the operating systems
2238 default code, data and stack segments */
2239 asm volatile("movw %%cs, %0" : : "m" (arch->vex.guest_CS));
2240 asm volatile("movw %%ds, %0" : : "m" (arch->vex.guest_DS));
2241 asm volatile("movw %%ss, %0" : : "m" (arch->vex.guest_SS));
cerion85665ca2005-06-20 15:51:07 +00002242
njn2da73352005-06-18 01:35:16 +00002243#elif defined(VGA_amd64)
2244 vg_assert(0 == sizeof(VexGuestAMD64State) % 8);
2245
2246 /* Zero out the initial state, and set up the simulated FPU in a
2247 sane way. */
2248 LibVEX_GuestAMD64_initialise(&arch->vex);
2249
2250 /* Zero out the shadow area. */
2251 VG_(memset)(&arch->vex_shadow, 0, sizeof(VexGuestAMD64State));
2252
2253 /* Put essential stuff into the new state. */
2254 arch->vex.guest_RSP = sp_at_startup;
2255 arch->vex.guest_RIP = client_ip;
cerion85665ca2005-06-20 15:51:07 +00002256
2257#elif defined(VGA_ppc32)
2258 vg_assert(0 == sizeof(VexGuestPPC32State) % 8);
2259
2260 /* Zero out the initial state, and set up the simulated FPU in a
2261 sane way. */
2262 LibVEX_GuestPPC32_initialise(&arch->vex);
2263
2264 /* Zero out the shadow area. */
2265 VG_(memset)(&arch->vex_shadow, 0, sizeof(VexGuestPPC32State));
2266
2267 /* Put essential stuff into the new state. */
2268 arch->vex.guest_GPR1 = sp_at_startup;
2269 arch->vex.guest_CIA = client_ip;
2270
njn2da73352005-06-18 01:35:16 +00002271#else
2272# error Unknown arch
2273#endif
2274 // Tell the tool that we just wrote to the registers.
2275 VG_TRACK( post_reg_write, Vg_CoreStartup, /*tid*/1, /*offset*/0,
2276 sizeof(VexGuestArchState));
2277}
2278
sewardjde4a1d02002-03-22 01:27:54 +00002279
nethercote71980f02004-01-24 18:18:54 +00002280/*====================================================================*/
njn2025cf92005-06-26 20:44:48 +00002281/*=== BB profiling ===*/
2282/*====================================================================*/
2283
2284static
2285void show_BB_profile ( BBProfEntry tops[], UInt n_tops, ULong score_total )
2286{
2287 ULong score_cumul, score_here;
2288 Char buf_cumul[10], buf_here[10];
2289 Char name[64];
2290 Int r;
2291
2292 VG_(printf)("\n");
2293 VG_(printf)("-----------------------------------------------------------\n");
2294 VG_(printf)("--- BEGIN BB Profile (summary of scores) ---\n");
2295 VG_(printf)("-----------------------------------------------------------\n");
2296 VG_(printf)("\n");
2297
2298 VG_(printf)("Total score = %lld\n\n", score_total);
2299
2300 score_cumul = 0;
2301 for (r = 0; r < n_tops; r++) {
2302 if (tops[r].addr == 0)
2303 continue;
2304 name[0] = 0;
2305 VG_(get_fnname_w_offset)(tops[r].addr, name, 64);
2306 name[63] = 0;
2307 score_here = tops[r].score;
2308 score_cumul += score_here;
2309 VG_(percentify)(score_cumul, score_total, 2, 6, buf_cumul);
2310 VG_(percentify)(score_here, score_total, 2, 6, buf_here);
2311 VG_(printf)("%3d: (%9lld %s) %9lld %s 0x%llx %s\n",
2312 r,
2313 score_cumul, buf_cumul,
2314 score_here, buf_here, tops[r].addr, name );
2315 }
2316
2317 VG_(printf)("\n");
2318 VG_(printf)("-----------------------------------------------------------\n");
2319 VG_(printf)("--- BB Profile (BB details) ---\n");
2320 VG_(printf)("-----------------------------------------------------------\n");
2321 VG_(printf)("\n");
2322
2323 score_cumul = 0;
2324 for (r = 0; r < n_tops; r++) {
2325 if (tops[r].addr == 0)
2326 continue;
2327 name[0] = 0;
2328 VG_(get_fnname_w_offset)(tops[r].addr, name, 64);
2329 name[63] = 0;
2330 score_here = tops[r].score;
2331 score_cumul += score_here;
2332 VG_(percentify)(score_cumul, score_total, 2, 6, buf_cumul);
2333 VG_(percentify)(score_here, score_total, 2, 6, buf_here);
2334 VG_(printf)("\n");
2335 VG_(printf)("=-=-=-=-=-=-=-=-=-=-=-=-=-= begin BB rank %d "
2336 "=-=-=-=-=-=-=-=-=-=-=-=-=-=\n\n", r);
2337 VG_(printf)("%3d: (%9lld %s) %9lld %s 0x%llx %s\n",
2338 r,
2339 score_cumul, buf_cumul,
2340 score_here, buf_here, tops[r].addr, name );
2341 VG_(printf)("\n");
2342 VG_(translate)(0, tops[r].addr, True, VG_(clo_profile_flags), 0);
2343 VG_(printf)("=-=-=-=-=-=-=-=-=-=-=-=-=-= end BB rank %d "
2344 "=-=-=-=-=-=-=-=-=-=-=-=-=-=\n\n", r);
2345 }
2346
2347 VG_(printf)("\n");
2348 VG_(printf)("-----------------------------------------------------------\n");
2349 VG_(printf)("--- END BB Profile ---\n");
2350 VG_(printf)("-----------------------------------------------------------\n");
2351 VG_(printf)("\n");
2352}
2353
2354
2355/*====================================================================*/
nethercote71980f02004-01-24 18:18:54 +00002356/*=== main() ===*/
2357/*====================================================================*/
2358
nethercotec314eba2004-07-15 12:59:41 +00002359/*
2360 This code decides on the layout of the client and Valgrind address
nethercote996901a2004-08-03 13:29:09 +00002361 spaces, loads valgrind.so and the tool.so into the valgrind part,
nethercotec314eba2004-07-15 12:59:41 +00002362 loads the client executable (and the dynamic linker, if necessary)
2363 into the client part, and calls into Valgrind proper.
2364
2365 The code is careful not to allow spurious mappings to appear in the
2366 wrong parts of the address space. In particular, to make sure
2367 dlopen puts things in the right place, it will pad out the forbidden
2368 chunks of address space so that dlopen is forced to put things where
2369 we want them.
2370
2371 The memory map it creates is:
2372
njn311c5d82005-05-15 21:03:42 +00002373 client_base +-------------------------+
nethercotec314eba2004-07-15 12:59:41 +00002374 | client address space |
2375 : :
2376 : :
2377 | client stack |
2378 client_end +-------------------------+
2379 | redzone |
2380 shadow_base +-------------------------+
2381 | |
nethercote996901a2004-08-03 13:29:09 +00002382 : shadow memory for tools :
nethercotec314eba2004-07-15 12:59:41 +00002383 | (may be 0 sized) |
2384 shadow_end +-------------------------+
nethercotec314eba2004-07-15 12:59:41 +00002385 valgrind_base +-------------------------+
2386 | kickstart executable |
2387 | valgrind heap vvvvvvvvv| (barely used)
2388 - -
2389 | valgrind .so files |
2390 | and mappings |
2391 - -
2392 | valgrind stack ^^^^^^^^^|
nethercote820bd8c2004-09-07 23:04:49 +00002393 valgrind_last +-------------------------+
nethercotec314eba2004-07-15 12:59:41 +00002394 : kernel :
2395
2396 Nb: Before we can do general allocations with VG_(arena_malloc)() and
2397 VG_(mmap)(), we need to build the segment skip-list, so we know where
2398 we can put things. However, building that structure requires
2399 allocating memory. So we need to a bootstrapping process. It's done
2400 by making VG_(arena_malloc)() have a special static superblock that's
2401 used for the first 1MB's worth of allocations. This is enough to
2402 build the segment skip-list.
2403*/
2404
thughes4ad52d02004-06-27 17:37:21 +00002405
sewardj1cf558c2005-04-25 01:36:56 +00002406/* This may be needed before m_mylibc is OK to run. */
2407static Int local_strcmp ( const HChar* s1, const HChar* s2 )
2408{
2409 while (True) {
2410 if (*s1 == 0 && *s2 == 0) return 0;
2411 if (*s1 == 0) return -1;
2412 if (*s2 == 0) return 1;
2413
2414 if (*(UChar*)s1 < *(UChar*)s2) return -1;
2415 if (*(UChar*)s1 > *(UChar*)s2) return 1;
2416
2417 s1++; s2++;
2418 }
2419}
2420
2421
sewardjb5f6f512005-03-10 23:59:00 +00002422int main(int argc, char **argv, char **envp)
nethercote71980f02004-01-24 18:18:54 +00002423{
2424 char **cl_argv;
sewardjb5f6f512005-03-10 23:59:00 +00002425 const char *tool = "memcheck"; // default to Memcheck
nethercote71980f02004-01-24 18:18:54 +00002426 const char *exec = NULL;
2427 char *preload; /* tool-specific LD_PRELOAD .so */
2428 char **env;
nethercote6c999f22004-01-31 22:55:15 +00002429 Int need_help = 0; // 0 = no, 1 = --help, 2 = --help-debug
nethercote71980f02004-01-24 18:18:54 +00002430 struct exeinfo info;
2431 ToolInfo *toolinfo = NULL;
nethercote71980f02004-01-24 18:18:54 +00002432 Addr client_eip;
nethercote4ad74312004-10-26 09:59:49 +00002433 Addr sp_at_startup; /* client's SP at the point we gained control. */
nethercote71980f02004-01-24 18:18:54 +00002434 UInt * client_auxv;
nethercote73b526f2004-10-31 18:48:21 +00002435 struct vki_rlimit zero = { 0, 0 };
sewardj1cf558c2005-04-25 01:36:56 +00002436 Int padfile, loglevel, i;
nethercote71980f02004-01-24 18:18:54 +00002437
2438 //============================================================
2439 // Nb: startup is complex. Prerequisites are shown at every step.
2440 //
2441 // *** Be very careful when messing with the order ***
2442 //============================================================
2443
sewardj1cf558c2005-04-25 01:36:56 +00002444 //--------------------------------------------------------------
2445 // Start up the logging mechanism
2446 // p: none
2447 //--------------------------------------------------------------
2448 /* Start the debugging-log system ASAP. First find out how many
2449 "-d"s were specified. This is a pre-scan of the command line. */
2450 loglevel = 0;
2451 for (i = 1; i < argc; i++) {
sewardj10759312005-05-30 23:52:47 +00002452 if (argv[i][0] != '-')
2453 break;
2454 if (0 == local_strcmp(argv[i], "--"))
2455 break;
2456 if (0 == local_strcmp(argv[i], "-d"))
2457 loglevel++;
sewardj1cf558c2005-04-25 01:36:56 +00002458 }
2459
2460 /* ... and start the debug logger. Now we can safely emit logging
2461 messages all through startup. */
sewardj10759312005-05-30 23:52:47 +00002462 VG_(debugLog_startup)(loglevel, "Stage 2 (main)");
sewardj1cf558c2005-04-25 01:36:56 +00002463
nethercotef4928da2004-06-15 10:54:40 +00002464 //============================================================
2465 // Command line argument handling order:
2466 // * If --help/--help-debug are present, show usage message
sewardjb5f6f512005-03-10 23:59:00 +00002467 // (including the tool-specific usage)
2468 // * (If no --tool option given, default to Memcheck)
nethercotef4928da2004-06-15 10:54:40 +00002469 // * Then, if client is missing, abort with error msg
2470 // * Then, if any cmdline args are bad, abort with error msg
2471 //============================================================
2472
fitzhardingeb50068f2004-02-24 23:42:55 +00002473 // Get the current process datasize rlimit, and set it to zero.
2474 // This prevents any internal uses of brk() from having any effect.
2475 // We remember the old value so we can restore it on exec, so that
2476 // child processes will have a reasonable brk value.
2477 VG_(getrlimit)(VKI_RLIMIT_DATA, &VG_(client_rlimit_data));
2478 zero.rlim_max = VG_(client_rlimit_data).rlim_max;
2479 VG_(setrlimit)(VKI_RLIMIT_DATA, &zero);
thughesc37184f2004-09-11 14:16:57 +00002480
2481 // Get the current process stack rlimit.
2482 VG_(getrlimit)(VKI_RLIMIT_STACK, &VG_(client_rlimit_stack));
2483
nethercote71980f02004-01-24 18:18:54 +00002484 //--------------------------------------------------------------
2485 // Check we were launched by stage1
sewardj51ac0872004-12-21 01:20:49 +00002486 // p: none
nethercote71980f02004-01-24 18:18:54 +00002487 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002488 VG_(debugLog)(1, "main", "Doing scan_auxv()\n");
nethercotec25c4492004-10-18 11:52:17 +00002489 {
sewardj1fbc1a52005-04-25 02:05:54 +00002490 void* init_sp = argv - 1;
2491 padfile = scan_auxv(init_sp);
nethercote71980f02004-01-24 18:18:54 +00002492 }
2493
2494 //--------------------------------------------------------------
2495 // Look for alternative libdir
sewardj51ac0872004-12-21 01:20:49 +00002496 // p: none
nethercote71980f02004-01-24 18:18:54 +00002497 //--------------------------------------------------------------
sewardj51ac0872004-12-21 01:20:49 +00002498 { HChar *cp = getenv(VALGRINDLIB);
nethercote71980f02004-01-24 18:18:54 +00002499 if (cp != NULL)
2500 VG_(libdir) = cp;
2501 }
2502
2503 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002504 // Get valgrind args + client args (inc. from VALGRIND_OPTS/.valgrindrc).
2505 // Pre-process the command line.
sewardj51ac0872004-12-21 01:20:49 +00002506 // p: none
nethercote71980f02004-01-24 18:18:54 +00002507 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002508 VG_(debugLog)(1, "main", "Preprocess command line opts\n");
nethercotef6a1d502004-08-09 12:21:57 +00002509 get_command_line(argc, argv, &vg_argc, &vg_argv, &cl_argv);
nethercote71980f02004-01-24 18:18:54 +00002510 pre_process_cmd_line_options(&need_help, &tool, &exec);
2511
sewardj10759312005-05-30 23:52:47 +00002512 /* If this process was created by exec done by another Valgrind
2513 process, the arguments will only show up at this point. Hence
2514 we need to also snoop around in vg_argv to see if anyone is
2515 asking for debug logging. */
2516 if (loglevel == 0) {
2517 for (i = 1; i < vg_argc; i++) {
2518 if (vg_argv[i][0] != '-')
2519 break;
2520 if (0 == local_strcmp(vg_argv[i], "--"))
2521 break;
2522 if (0 == local_strcmp(vg_argv[i], "-d"))
2523 loglevel++;
2524 }
2525 VG_(debugLog_startup)(loglevel, "Stage 2 (second go)");
2526 }
2527
nethercote71980f02004-01-24 18:18:54 +00002528 //==============================================================
2529 // Nb: once a tool is specified, the tool.so must be loaded even if
2530 // they specified --help or didn't specify a client program.
2531 //==============================================================
2532
2533 //--------------------------------------------------------------
2534 // With client padded out, map in tool
nethercote71980f02004-01-24 18:18:54 +00002535 // p: set-libdir [for VG_(libdir)]
2536 // p: pre_process_cmd_line_options() [for 'tool']
2537 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002538 VG_(debugLog)(1, "main", "Loading tool\n");
njn8a97c6d2005-03-31 04:37:24 +00002539 load_tool(tool, &toolinfo, &preload);
nethercote71980f02004-01-24 18:18:54 +00002540
2541 //==============================================================
2542 // Can use VG_(malloc)() and VG_(arena_malloc)() only after load_tool()
nethercotec314eba2004-07-15 12:59:41 +00002543 // -- redzone size is now set. This is checked by vg_malloc2.c.
nethercote71980f02004-01-24 18:18:54 +00002544 //==============================================================
2545
2546 //--------------------------------------------------------------
2547 // Finalise address space layout
nethercote31779c72004-07-30 21:50:15 +00002548 // p: load_tool() [for 'toolinfo']
nethercote71980f02004-01-24 18:18:54 +00002549 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002550 VG_(debugLog)(1, "main", "Laying out remaining space\n");
nethercote31779c72004-07-30 21:50:15 +00002551 layout_remaining_space( (Addr) & argc, toolinfo->shadow_ratio );
nethercote71980f02004-01-24 18:18:54 +00002552
2553 //--------------------------------------------------------------
2554 // Load client executable, finding in $PATH if necessary
nethercote71980f02004-01-24 18:18:54 +00002555 // p: pre_process_cmd_line_options() [for 'exec', 'need_help']
2556 // p: layout_remaining_space [so there's space]
2557 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002558 VG_(debugLog)(1, "main", "Loading client\n");
nethercotef4928da2004-06-15 10:54:40 +00002559 load_client(cl_argv, exec, need_help, &info, &client_eip);
nethercote71980f02004-01-24 18:18:54 +00002560
2561 //--------------------------------------------------------------
nethercote969ecf12004-10-13 17:29:01 +00002562 // Everything in place, remove padding done by stage1
nethercote71980f02004-01-24 18:18:54 +00002563 // p: layout_remaining_space() [everything must be mapped in before now]
2564 // p: load_client() [ditto]
2565 //--------------------------------------------------------------
nethercote31779c72004-07-30 21:50:15 +00002566 as_unpad((void *)VG_(shadow_end), (void *)~0, padfile);
2567 as_closepadfile(padfile); // no more padding
nethercote71980f02004-01-24 18:18:54 +00002568
2569 //--------------------------------------------------------------
2570 // Set up client's environment
2571 // p: set-libdir [for VG_(libdir)]
2572 // p: load_tool() [for 'preload']
2573 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002574 VG_(debugLog)(1, "main", "Setup client env\n");
sewardjb5f6f512005-03-10 23:59:00 +00002575 env = fix_environment(envp, preload);
nethercote71980f02004-01-24 18:18:54 +00002576
2577 //--------------------------------------------------------------
nethercote5ee67ca2004-06-22 14:00:09 +00002578 // Setup client stack, eip, and VG_(client_arg[cv])
nethercote71980f02004-01-24 18:18:54 +00002579 // p: load_client() [for 'info']
2580 // p: fix_environment() [for 'env']
2581 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002582 VG_(debugLog)(1, "main", "Setup client stack\n");
nethercotec25c4492004-10-18 11:52:17 +00002583 {
sewardj1fbc1a52005-04-25 02:05:54 +00002584 void* init_sp = argv - 1;
sewardjb5f6f512005-03-10 23:59:00 +00002585
sewardj1fbc1a52005-04-25 02:05:54 +00002586 sp_at_startup = setup_client_stack(init_sp, cl_argv, env, &info,
2587 &client_auxv);
2588 free(env);
nethercotec25c4492004-10-18 11:52:17 +00002589 }
nethercote71980f02004-01-24 18:18:54 +00002590
sewardj1fbc1a52005-04-25 02:05:54 +00002591 VG_(debugLog)(2, "main",
2592 "Client info: "
2593 "entry=%p client esp=%p vg_argc=%d brkbase=%p\n",
2594 (void*)client_eip, (void*)sp_at_startup, vg_argc,
2595 (void*)VG_(brk_base) );
nethercote71980f02004-01-24 18:18:54 +00002596
2597 //==============================================================
2598 // Finished setting up operating environment. Now initialise
2599 // Valgrind. (This is where the old VG_(main)() started.)
2600 //==============================================================
2601
2602 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002603 // setup file descriptors
2604 // p: n/a
2605 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002606 VG_(debugLog)(1, "main", "Setup file descriptors\n");
nethercote71980f02004-01-24 18:18:54 +00002607 setup_file_descriptors();
2608
2609 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002610 // Build segment map (Valgrind segments only)
njnd2252832004-11-26 10:53:33 +00002611 // p: tl_pre_clo_init() [to setup new_mem_startup tracker]
nethercotec314eba2004-07-15 12:59:41 +00002612 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002613 VG_(debugLog)(1, "main", "Parse /proc/self/maps (round 1)\n");
nethercotec314eba2004-07-15 12:59:41 +00002614 VG_(parse_procselfmaps) ( build_valgrind_map_callback );
2615
2616 //==============================================================
2617 // Can use VG_(arena_malloc)() with non-CORE arena after segments set up
2618 //==============================================================
2619
2620 //--------------------------------------------------------------
2621 // Init tool: pre_clo_init, process cmd line, post_clo_init
2622 // p: setup_client_stack() [for 'VG_(client_arg[cv]']
njn8a97c6d2005-03-31 04:37:24 +00002623 // p: load_tool() [for 'toolinfo']
nethercotec314eba2004-07-15 12:59:41 +00002624 // p: setup_file_descriptors() [for 'VG_(fd_xxx_limit)']
2625 // p: parse_procselfmaps [so VG segments are setup so tool can
2626 // call VG_(malloc)]
nethercote71980f02004-01-24 18:18:54 +00002627 //--------------------------------------------------------------
njn64c83242005-06-21 01:54:38 +00002628 {
2629 Char* s;
2630 Bool ok;
2631 VG_(debugLog)(1, "main", "Initialise the tool\n");
2632 (*toolinfo->tl_pre_clo_init)();
2633 ok = VG_(sanity_check_needs)( VG_(shadow_base) != VG_(shadow_end), &s );
2634 if (!ok) {
2635 VG_(tool_panic)(s);
2636 }
2637 }
nethercote71980f02004-01-24 18:18:54 +00002638
nethercotef4928da2004-06-15 10:54:40 +00002639 // If --tool and --help/--help-debug was given, now give the core+tool
2640 // help message
nethercotef4928da2004-06-15 10:54:40 +00002641 if (need_help) {
2642 usage(/*--help-debug?*/2 == need_help);
2643 }
nethercotec314eba2004-07-15 12:59:41 +00002644 process_cmd_line_options(client_auxv, tool);
2645
njn51d827b2005-05-09 01:02:08 +00002646 VG_TDICT_CALL(tool_post_clo_init);
nethercotef4928da2004-06-15 10:54:40 +00002647
2648 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002649 // Build segment map (all segments)
sewardjb5f6f512005-03-10 23:59:00 +00002650 // p: shadow/redzone segments
nethercote4ad74312004-10-26 09:59:49 +00002651 // p: setup_client_stack() [for 'sp_at_startup']
nethercotec314eba2004-07-15 12:59:41 +00002652 // p: init tool [for 'new_mem_startup']
nethercote71980f02004-01-24 18:18:54 +00002653 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002654 VG_(debugLog)(1, "main", "Parse /proc/self/maps (round 2)\n");
nethercote4ad74312004-10-26 09:59:49 +00002655 sp_at_startup___global_arg = sp_at_startup;
nethercotec314eba2004-07-15 12:59:41 +00002656 VG_(parse_procselfmaps) ( build_segment_map_callback ); /* everything */
nethercote4ad74312004-10-26 09:59:49 +00002657 sp_at_startup___global_arg = 0;
sewardjb5f6f512005-03-10 23:59:00 +00002658
nethercotec314eba2004-07-15 12:59:41 +00002659 //==============================================================
2660 // Can use VG_(map)() after segments set up
2661 //==============================================================
nethercote71980f02004-01-24 18:18:54 +00002662
2663 //--------------------------------------------------------------
2664 // Allow GDB attach
2665 // p: process_cmd_line_options() [for VG_(clo_wait_for_gdb)]
2666 //--------------------------------------------------------------
2667 /* Hook to delay things long enough so we can get the pid and
2668 attach GDB in another shell. */
2669 if (VG_(clo_wait_for_gdb)) {
sewardj8211a572005-06-23 21:37:47 +00002670 Long q, iters;
sewardj1fbc1a52005-04-25 02:05:54 +00002671 VG_(debugLog)(1, "main", "Wait for GDB\n");
sewardj93ab8572005-02-06 14:10:40 +00002672 VG_(printf)("pid=%d, entering delay loop\n", VG_(getpid)());
2673 /* jrs 20050206: I don't understand why this works on x86. On
2674 amd64 the obvious analogues (jump *$rip or jump *$rcx) don't
2675 work. */
2676 /* do "jump *$eip" to skip this in gdb (x86) */
2677 //VG_(do_syscall0)(__NR_pause);
sewardj8211a572005-06-23 21:37:47 +00002678
2679# if defined(VGP_x86_linux)
2680 iters = 5;
2681# elif defined(VGP_amd64_linux)
2682 iters = 10;
2683# elif defined(VGP_ppc32_linux)
sewardjd714d2e2005-07-08 18:24:04 +00002684 iters = 5;
sewardj8211a572005-06-23 21:37:47 +00002685# else
2686# error "Unknown plat"
2687# endif
2688
2689 iters *= 1000*1000*1000;
2690 for (q = 0; q < iters; q++)
2691 ;
nethercote71980f02004-01-24 18:18:54 +00002692 }
2693
sewardjb5d320c2005-03-13 18:57:15 +00002694 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002695 // Search for file descriptors that are inherited from our parent
2696 // p: process_cmd_line_options [for VG_(clo_track_fds)]
2697 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002698 if (VG_(clo_track_fds)) {
2699 VG_(debugLog)(1, "main", "Init preopened fds\n");
nethercote71980f02004-01-24 18:18:54 +00002700 VG_(init_preopened_fds)();
sewardj1fbc1a52005-04-25 02:05:54 +00002701 }
nethercote71980f02004-01-24 18:18:54 +00002702
2703 //--------------------------------------------------------------
2704 // Initialise the scheduler
nethercote71980f02004-01-24 18:18:54 +00002705 // p: setup_file_descriptors() [else VG_(safe_fd)() breaks]
2706 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002707 VG_(debugLog)(1, "main", "Initialise scheduler\n");
nethercote71980f02004-01-24 18:18:54 +00002708 VG_(scheduler_init)();
2709
2710 //--------------------------------------------------------------
sewardjb5f6f512005-03-10 23:59:00 +00002711 // Initialise the pthread model
2712 // p: ?
sewardj2a99cf62004-11-24 10:44:19 +00002713 // load_client() [for 'client_eip']
2714 // setup_client_stack() [for 'sp_at_startup']
2715 // setup_scheduler() [for the rest of state 1 stuff]
2716 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002717 VG_(debugLog)(1, "main", "Initialise thread 1's state\n");
njn2da73352005-06-18 01:35:16 +00002718 init_thread1state(client_eip, sp_at_startup, &VG_(threads)[1].arch);
njnea4b28c2004-11-30 16:04:58 +00002719
sewardj2a99cf62004-11-24 10:44:19 +00002720 //--------------------------------------------------------------
sewardj39b88fb2005-03-12 15:16:07 +00002721 // Initialise the pthread model
2722 // p: ?
nethercote71980f02004-01-24 18:18:54 +00002723 //--------------------------------------------------------------
sewardjb5f6f512005-03-10 23:59:00 +00002724 //if (VG_(clo_model_pthreads))
2725 // VG_(pthread_init)();
nethercote71980f02004-01-24 18:18:54 +00002726
2727 //--------------------------------------------------------------
2728 // Initialise the signal handling subsystem
sewardjb5f6f512005-03-10 23:59:00 +00002729 // p: n/a
nethercote71980f02004-01-24 18:18:54 +00002730 //--------------------------------------------------------------
2731 // Nb: temporarily parks the saved blocking-mask in saved_sigmask.
sewardj1fbc1a52005-04-25 02:05:54 +00002732 VG_(debugLog)(1, "main", "Initialise signal management\n");
nethercote71980f02004-01-24 18:18:54 +00002733 VG_(sigstartup_actions)();
2734
2735 //--------------------------------------------------------------
2736 // Perhaps we're profiling Valgrind?
2737 // p: process_cmd_line_options() [for VG_(clo_profile)]
2738 // p: others?
2739 //
2740 // XXX: this seems to be broken? It always says the tool wasn't built
2741 // for profiling; vg_profile.c's functions don't seem to be overriding
2742 // vg_dummy_profile.c's?
2743 //
2744 // XXX: want this as early as possible. Looking for --profile
2745 // in pre_process_cmd_line_options() could get it earlier.
2746 //--------------------------------------------------------------
2747 if (VG_(clo_profile))
njn31066fd2005-03-26 00:42:02 +00002748 VG_(init_profiling)();
nethercote71980f02004-01-24 18:18:54 +00002749
2750 VGP_PUSHCC(VgpStartup);
2751
2752 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002753 // Read suppression file
2754 // p: process_cmd_line_options() [for VG_(clo_suppressions)]
2755 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002756 if (VG_(needs).core_errors || VG_(needs).tool_errors) {
2757 VG_(debugLog)(1, "main", "Load suppressions\n");
nethercote71980f02004-01-24 18:18:54 +00002758 VG_(load_suppressions)();
sewardj1fbc1a52005-04-25 02:05:54 +00002759 }
nethercote71980f02004-01-24 18:18:54 +00002760
2761 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002762 // Initialise translation table and translation cache
2763 // p: read_procselfmaps [so the anonymous mmaps for the TT/TC
2764 // aren't identified as part of the client, which would waste
2765 // > 20M of virtual address space.]
2766 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002767 VG_(debugLog)(1, "main", "Initialise TT/TC\n");
nethercote71980f02004-01-24 18:18:54 +00002768 VG_(init_tt_tc)();
2769
2770 //--------------------------------------------------------------
sewardjb9bce632005-06-21 01:41:34 +00002771 // Initialise the redirect table.
sewardjb5d320c2005-03-13 18:57:15 +00002772 // p: parse_procselfmaps? [XXX for debug info?]
2773 // p: init_tt_tc [so it can call VG_(search_transtab) safely]
2774 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002775 VG_(debugLog)(1, "main", "Initialise redirects\n");
sewardjb5d320c2005-03-13 18:57:15 +00002776 VG_(setup_code_redirect_table)();
2777
2778 //--------------------------------------------------------------
sewardjb9bce632005-06-21 01:41:34 +00002779 // Tell the tool about permissions in our handwritten assembly
2780 // helpers.
2781 // p: init tool [for 'new_mem_startup']
2782 //--------------------------------------------------------------
2783 VG_(debugLog)(1, "main", "Tell tool about permissions for asm helpers\n");
2784 VG_TRACK( new_mem_startup,
2785 (Addr)&VG_(trampoline_stuff_start),
2786 &VG_(trampoline_stuff_end) - &VG_(trampoline_stuff_start),
2787 False, /* readable? */
2788 False, /* writable? */
2789 True /* executable? */ );
2790
2791 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002792 // Verbosity message
2793 // p: end_rdtsc_calibration [so startup message is printed first]
2794 //--------------------------------------------------------------
sewardj71bc3cb2005-05-19 00:25:45 +00002795 if (VG_(clo_verbosity) == 1 && !VG_(clo_xml))
nethercote71980f02004-01-24 18:18:54 +00002796 VG_(message)(Vg_UserMsg, "For more details, rerun with: -v");
2797 if (VG_(clo_verbosity) > 0)
2798 VG_(message)(Vg_UserMsg, "");
2799
2800 //--------------------------------------------------------------
2801 // Setup pointercheck
njn04e16982005-05-31 00:23:43 +00002802 // p: layout_remaining_space() [for VG_(client_{base,end})]
nethercote71980f02004-01-24 18:18:54 +00002803 // p: process_cmd_line_options() [for VG_(clo_pointercheck)]
2804 //--------------------------------------------------------------
nethercote775508a2004-09-07 22:38:23 +00002805 if (VG_(clo_pointercheck))
njn04e16982005-05-31 00:23:43 +00002806 VG_(clo_pointercheck) =
njnaf839f52005-06-23 03:27:57 +00002807 VG_(setup_pointercheck)( VG_(client_base), VG_(client_end));
nethercote71980f02004-01-24 18:18:54 +00002808
nethercote71980f02004-01-24 18:18:54 +00002809 //--------------------------------------------------------------
rjwalsh0140af52005-06-04 20:42:33 +00002810 // register client stack
2811 //--------------------------------------------------------------
njn945ed2e2005-06-24 03:28:30 +00002812 VG_(clstk_id) = VG_(register_stack)(VG_(clstk_base), VG_(clstk_end));
rjwalsh0140af52005-06-04 20:42:33 +00002813
2814 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002815 // Run!
2816 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002817 VGP_POPCC(VgpStartup);
nethercote71980f02004-01-24 18:18:54 +00002818
sewardj71bc3cb2005-05-19 00:25:45 +00002819 if (VG_(clo_xml)) {
sewardj68cde6f2005-07-19 12:17:51 +00002820 HChar buf[50];
2821 VG_(ctime)(buf);
sewardj33e60422005-07-24 07:33:15 +00002822 VG_(message)(Vg_UserMsg, "<status> <state>RUNNING</state> "
2823 "<time>%t</time> </status>", buf);
sewardj71bc3cb2005-05-19 00:25:45 +00002824 VG_(message)(Vg_UserMsg, "");
2825 }
2826
sewardj1fbc1a52005-04-25 02:05:54 +00002827 VG_(debugLog)(1, "main", "Running thread 1\n");
sewardj1d887112005-05-30 21:44:08 +00002828 /* As a result of the following call, the last thread standing
2829 eventually winds up running VG_(shutdown_actions_NORETURN) just
2830 below. */
njnaf839f52005-06-23 03:27:57 +00002831 VG_(main_thread_wrapper_NORETURN)(1);
nethercote71980f02004-01-24 18:18:54 +00002832
sewardj1d887112005-05-30 21:44:08 +00002833 /*NOTREACHED*/
2834 vg_assert(0);
sewardjb5f6f512005-03-10 23:59:00 +00002835}
2836
2837
njn9cb54ac2005-06-12 04:19:17 +00002838/* Final clean-up before terminating the process.
2839 Clean up the client by calling __libc_freeres() (if requested)
2840 This is Linux-specific?
2841*/
2842static void final_tidyup(ThreadId tid)
2843{
njnbc6d84d2005-06-19 18:58:03 +00002844 Addr __libc_freeres_wrapper;
2845
njn9cb54ac2005-06-12 04:19:17 +00002846 vg_assert(VG_(is_running_thread)(tid));
2847
njnbc6d84d2005-06-19 18:58:03 +00002848 if ( !VG_(needs).libc_freeres ||
2849 !VG_(clo_run_libc_freeres) ||
2850 0 == (__libc_freeres_wrapper = VG_(get_libc_freeres_wrapper)()) )
njn9cb54ac2005-06-12 04:19:17 +00002851 return; /* can't/won't do it */
2852
2853 if (VG_(clo_verbosity) > 2 ||
2854 VG_(clo_trace_syscalls) ||
2855 VG_(clo_trace_sched))
2856 VG_(message)(Vg_DebugMsg,
2857 "Caught __NR_exit; running __libc_freeres()");
2858
2859 /* point thread context to point to libc_freeres_wrapper */
njnf536bbb2005-06-13 04:21:38 +00002860 VG_(set_IP)(tid, __libc_freeres_wrapper);
njn9cb54ac2005-06-12 04:19:17 +00002861 // XXX should we use a special stack?
2862
2863 /* Block all blockable signals by copying the real block state into
2864 the thread's block state*/
2865 VG_(sigprocmask)(VKI_SIG_BLOCK, NULL, &VG_(threads)[tid].sig_mask);
2866 VG_(threads)[tid].tmp_sig_mask = VG_(threads)[tid].sig_mask;
2867
2868 /* and restore handlers to default */
2869 VG_(set_default_handler)(VKI_SIGSEGV);
2870 VG_(set_default_handler)(VKI_SIGBUS);
2871 VG_(set_default_handler)(VKI_SIGILL);
2872 VG_(set_default_handler)(VKI_SIGFPE);
2873
2874 // We were exiting, so assert that...
2875 vg_assert(VG_(is_exiting)(tid));
2876 // ...but now we're not again
2877 VG_(threads)[tid].exitreason = VgSrc_None;
2878
2879 // run until client thread exits - ideally with LIBC_FREERES_DONE,
2880 // but exit/exitgroup/signal will do
2881 VG_(scheduler)(tid);
2882
2883 vg_assert(VG_(is_exiting)(tid));
2884}
2885
sewardjb5f6f512005-03-10 23:59:00 +00002886/* Do everything which needs doing when the last thread exits */
sewardj1d887112005-05-30 21:44:08 +00002887void VG_(shutdown_actions_NORETURN) ( ThreadId tid,
2888 VgSchedReturnCode tids_schedretcode )
sewardjb5f6f512005-03-10 23:59:00 +00002889{
sewardj1d887112005-05-30 21:44:08 +00002890 VG_(debugLog)(1, "main", "entering VG_(shutdown_actions_NORETURN)\n");
2891
2892 vg_assert( VG_(count_living_threads)() == 1 );
sewardjb5f6f512005-03-10 23:59:00 +00002893 vg_assert(VG_(is_running_thread)(tid));
2894
2895 // Wait for all other threads to exit.
njn7b85dd52005-06-12 17:26:29 +00002896 VG_(reap_threads)(tid);
sewardjb5f6f512005-03-10 23:59:00 +00002897
2898 VG_(clo_model_pthreads) = False;
2899
2900 // Clean the client up before the final report
njn9cb54ac2005-06-12 04:19:17 +00002901 final_tidyup(tid);
sewardjb5f6f512005-03-10 23:59:00 +00002902
2903 // OK, done
2904 VG_(exit_thread)(tid);
2905
2906 /* should be no threads left */
2907 vg_assert(VG_(count_living_threads)() == 0);
2908
2909 VG_(threads)[tid].status = VgTs_Empty;
nethercote71980f02004-01-24 18:18:54 +00002910 //--------------------------------------------------------------
2911 // Finalisation: cleanup, messages, etc. Order no so important, only
2912 // affects what order the messages come.
2913 //--------------------------------------------------------------
2914 if (VG_(clo_verbosity) > 0)
2915 VG_(message)(Vg_UserMsg, "");
2916
sewardj71bc3cb2005-05-19 00:25:45 +00002917 if (VG_(clo_xml)) {
sewardj68cde6f2005-07-19 12:17:51 +00002918 HChar buf[50];
sewardj9f297ca2005-05-20 02:29:52 +00002919 if (VG_(needs).core_errors || VG_(needs).tool_errors) {
2920 VG_(show_error_counts_as_XML)();
2921 VG_(message)(Vg_UserMsg, "");
2922 }
sewardj68cde6f2005-07-19 12:17:51 +00002923 VG_(ctime)(buf);
sewardj33e60422005-07-24 07:33:15 +00002924 VG_(message)(Vg_UserMsg, "<status> <state>FINISHED</state> "
2925 "<time>%t</time> </status>", buf);
sewardj71bc3cb2005-05-19 00:25:45 +00002926 VG_(message)(Vg_UserMsg, "");
2927 }
2928
nethercote71980f02004-01-24 18:18:54 +00002929 /* Print out file descriptor summary and stats. */
2930 if (VG_(clo_track_fds))
nethercote3a42fb82004-08-03 18:08:50 +00002931 VG_(show_open_fds)();
nethercote71980f02004-01-24 18:18:54 +00002932
njn95ec8702004-11-22 16:46:13 +00002933 if (VG_(needs).core_errors || VG_(needs).tool_errors)
nethercote71980f02004-01-24 18:18:54 +00002934 VG_(show_all_errors)();
2935
njn51d827b2005-05-09 01:02:08 +00002936 VG_TDICT_CALL(tool_fini, 0/*exitcode*/);
nethercote71980f02004-01-24 18:18:54 +00002937
sewardj71bc3cb2005-05-19 00:25:45 +00002938 if (VG_(clo_xml)) {
2939 VG_(message)(Vg_UserMsg, "");
2940 VG_(message)(Vg_UserMsg, "</valgrindoutput>");
2941 VG_(message)(Vg_UserMsg, "");
2942 }
2943
nethercote885dd912004-08-03 23:14:00 +00002944 VG_(sanity_check_general)( True /*include expensive checks*/ );
nethercote71980f02004-01-24 18:18:54 +00002945
2946 if (VG_(clo_verbosity) > 1)
nethercote3a42fb82004-08-03 18:08:50 +00002947 print_all_stats();
nethercote71980f02004-01-24 18:18:54 +00002948
nethercote71980f02004-01-24 18:18:54 +00002949 if (VG_(clo_profile))
njn31066fd2005-03-26 00:42:02 +00002950 VG_(done_profiling)();
njn2025cf92005-06-26 20:44:48 +00002951
2952 if (VG_(clo_profile_flags) > 0) {
2953 #define N_MAX 100
2954 BBProfEntry tops[N_MAX];
2955 ULong score_total = VG_(get_BB_profile) (tops, N_MAX);
2956 show_BB_profile(tops, N_MAX, score_total);
2957 }
sewardjfa8ec112005-01-19 11:55:34 +00002958
sewardj8b635a42004-11-22 19:01:47 +00002959 /* Print Vex storage stats */
sewardjbf426512005-01-17 18:35:30 +00002960 if (0)
2961 LibVEX_ShowAllocStats();
sewardj1d887112005-05-30 21:44:08 +00002962
njn8aa35852005-06-10 22:59:56 +00002963 /* Ok, finally exit in the os-specific way, according to the scheduler's
2964 return code. In short, if the (last) thread exited by calling
2965 sys_exit, do likewise; if the (last) thread stopped due to a fatal
2966 signal, terminate the entire system with that same fatal signal. */
2967 VG_(debugLog)(1, "core_os",
njn7b85dd52005-06-12 17:26:29 +00002968 "VG_(terminate_NORETURN)(tid=%lld)\n", (ULong)tid);
njn8aa35852005-06-10 22:59:56 +00002969
2970 vg_assert(VG_(count_living_threads)() == 0);
2971
2972 switch (tids_schedretcode) {
2973 case VgSrc_ExitSyscall: /* the normal way out */
2974 VG_(exit)( VG_(threads)[tid].os_state.exitcode );
2975 /* NOT ALIVE HERE! */
2976 VG_(core_panic)("entered the afterlife in main() -- ExitSyscall");
2977 break; /* what the hell :) */
2978
2979 case VgSrc_FatalSig:
2980 /* We were killed by a fatal signal, so replicate the effect */
2981 vg_assert(VG_(threads)[tid].os_state.fatalsig != 0);
2982 VG_(kill_self)(VG_(threads)[tid].os_state.fatalsig);
2983 VG_(core_panic)("main(): signal was supposed to be fatal");
2984 break;
2985
2986 default:
2987 VG_(core_panic)("main(): unexpected scheduler return code");
2988 }
njne96be672005-05-08 19:08:54 +00002989}
sewardj8b635a42004-11-22 19:01:47 +00002990
sewardjde4a1d02002-03-22 01:27:54 +00002991/*--------------------------------------------------------------------*/
njn04e16982005-05-31 00:23:43 +00002992/*--- end ---*/
sewardjde4a1d02002-03-22 01:27:54 +00002993/*--------------------------------------------------------------------*/