blob: bd2dd2a8a5bd4d65009142880ac2d5f698efab7a [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
300 Int fd, n;
njn909c3192005-06-19 15:46:27 +0000301 struct vki_stat s1;
nethercote71980f02004-01-24 18:18:54 +0000302 char* f_clo = NULL;
303 char filename[FLEN];
304
305 snprintf(filename, FLEN, "%s/.valgrindrc", ( NULL == dir ? "" : dir ) );
306 fd = VG_(open)(filename, 0, VKI_S_IRUSR);
307 if ( fd > 0 ) {
njn909c3192005-06-19 15:46:27 +0000308 if ( 0 == VG_(fstat)(fd, &s1) ) {
nethercote71980f02004-01-24 18:18:54 +0000309 f_clo = malloc(s1.st_size+1);
310 vg_assert(f_clo);
njn909c3192005-06-19 15:46:27 +0000311 n = VG_(read)(fd, f_clo, s1.st_size);
nethercote71980f02004-01-24 18:18:54 +0000312 if (n == -1) n = 0;
313 f_clo[n] = '\0';
314 }
njn909c3192005-06-19 15:46:27 +0000315 VG_(close)(fd);
nethercote71980f02004-01-24 18:18:54 +0000316 }
317 return f_clo;
318# undef FLEN
319}
320
321static Int count_args(char* s)
322{
323 Int n = 0;
324 if (s) {
325 char* cp = s;
326 while (True) {
327 // We have alternating sequences: blanks, non-blanks, blanks...
328 // count the non-blanks sequences.
njn0c0f32a2005-03-26 04:14:01 +0000329 while ( VG_(isspace)(*cp) ) cp++;
nethercote71980f02004-01-24 18:18:54 +0000330 if ( !*cp ) break;
331 n++;
njn0c0f32a2005-03-26 04:14:01 +0000332 while ( !VG_(isspace)(*cp) && *cp ) cp++;
nethercote71980f02004-01-24 18:18:54 +0000333 }
334 }
335 return n;
336}
337
njndcc99d32005-06-19 15:34:59 +0000338// Add args out of environment, skipping multiple spaces and "--" args.
339// We split 's' into multiple strings by replacing whitespace with nuls,
340// eg. "--aa --bb --cc" --> "--aa\0--bb\0--cc". And for each new string
341// carved out of 's', we put a pointer to it in 'to'.
nethercote71980f02004-01-24 18:18:54 +0000342static char** copy_args( char* s, char** to )
343{
344 if (s) {
345 char* cp = s;
346 while (True) {
347 // We have alternating sequences: blanks, non-blanks, blanks...
348 // copy the non-blanks sequences, and add terminating '\0'
njn0c0f32a2005-03-26 04:14:01 +0000349 while ( VG_(isspace)(*cp) ) cp++;
nethercote71980f02004-01-24 18:18:54 +0000350 if ( !*cp ) break;
351 *to++ = cp;
njn0c0f32a2005-03-26 04:14:01 +0000352 while ( !VG_(isspace)(*cp) && *cp ) cp++;
njndcc99d32005-06-19 15:34:59 +0000353 if ( *cp ) *cp++ = '\0'; // terminate if not the last
nethercote71980f02004-01-24 18:18:54 +0000354 if (VG_STREQ(to[-1], "--")) to--; // undo any '--' arg
355 }
356 }
357 return to;
358}
359
360// Augment command line with arguments from environment and .valgrindrc
361// files.
362static void augment_command_line(Int* vg_argc_inout, char*** vg_argv_inout)
363{
nethercotef6a1d502004-08-09 12:21:57 +0000364 int vg_argc0 = *vg_argc_inout;
365 char** vg_argv0 = *vg_argv_inout;
nethercote71980f02004-01-24 18:18:54 +0000366
njndcc99d32005-06-19 15:34:59 +0000367 // get_file_clo() allocates the return value with malloc(). We do not
368 // free f1_clo and f2_clo as they get put into vg_argv[] which must persist.
nethercote71980f02004-01-24 18:18:54 +0000369 char* env_clo = getenv(VALGRINDOPTS);
370 char* f1_clo = get_file_clo( getenv("HOME") );
371 char* f2_clo = get_file_clo(".");
372
373 /* copy any extra args from file or environment, if present */
374 if ( (env_clo && *env_clo) || (f1_clo && *f1_clo) || (f2_clo && *f2_clo) ) {
375 /* ' ' separated extra options */
376 char **from;
377 char **to;
thughescaca0022004-09-13 10:20:34 +0000378 int orig_arg_count, env_arg_count, f1_arg_count, f2_arg_count;
379
380 for ( orig_arg_count = 0; vg_argv0[orig_arg_count]; orig_arg_count++ );
381
nethercote71980f02004-01-24 18:18:54 +0000382 env_arg_count = count_args(env_clo);
383 f1_arg_count = count_args(f1_clo);
384 f2_arg_count = count_args(f2_clo);
385
386 if (0)
387 printf("extra-argc=%d %d %d\n",
388 env_arg_count, f1_arg_count, f2_arg_count);
389
390 /* +2: +1 for null-termination, +1 for added '--' */
nethercotef6a1d502004-08-09 12:21:57 +0000391 from = vg_argv0;
thughescaca0022004-09-13 10:20:34 +0000392 vg_argv0 = malloc( (orig_arg_count + env_arg_count + f1_arg_count
nethercote71980f02004-01-24 18:18:54 +0000393 + f2_arg_count + 2) * sizeof(char **));
nethercotef6a1d502004-08-09 12:21:57 +0000394 vg_assert(vg_argv0);
395 to = vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000396
397 /* copy argv[0] */
398 *to++ = *from++;
399
400 /* Copy extra args from env var and file, in the order: ~/.valgrindrc,
401 * $VALGRIND_OPTS, ./.valgrindrc -- more local options are put later
402 * to override less local ones. */
403 to = copy_args(f1_clo, to);
404 to = copy_args(env_clo, to);
405 to = copy_args(f2_clo, to);
njna96e15a2005-05-24 21:36:32 +0000406
nethercote71980f02004-01-24 18:18:54 +0000407 /* copy original arguments, stopping at command or -- */
408 while (*from) {
409 if (**from != '-')
410 break;
411 if (VG_STREQ(*from, "--")) {
412 from++; /* skip -- */
413 break;
414 }
415 *to++ = *from++;
416 }
417
418 /* add -- */
419 *to++ = "--";
420
nethercotef6a1d502004-08-09 12:21:57 +0000421 vg_argc0 = to - vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000422
423 /* copy rest of original command line, then NULL */
424 while (*from) *to++ = *from++;
425 *to = NULL;
426 }
427
nethercotef6a1d502004-08-09 12:21:57 +0000428 *vg_argc_inout = vg_argc0;
429 *vg_argv_inout = vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000430}
431
nethercotef6a1d502004-08-09 12:21:57 +0000432#define VG_CLO_SEP '\01'
433
nethercote71980f02004-01-24 18:18:54 +0000434static void get_command_line( int argc, char** argv,
435 Int* vg_argc_out, Char*** vg_argv_out,
436 char*** cl_argv_out )
437{
nethercotef6a1d502004-08-09 12:21:57 +0000438 int vg_argc0;
439 char** vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000440 char** cl_argv;
441 char* env_clo = getenv(VALGRINDCLO);
442
443 if (env_clo != NULL && *env_clo != '\0') {
444 char *cp;
445 char **cpp;
446
nethercotef6a1d502004-08-09 12:21:57 +0000447 /* OK, VALGRINDCLO is set, which means we must be a child of another
448 Valgrind process using --trace-children, so we're getting all our
449 arguments from VALGRINDCLO, and the entire command line belongs to
450 the client (including argv[0]) */
451 vg_argc0 = 1; /* argv[0] */
nethercote71980f02004-01-24 18:18:54 +0000452 for (cp = env_clo; *cp; cp++)
nethercotef6a1d502004-08-09 12:21:57 +0000453 if (*cp == VG_CLO_SEP)
454 vg_argc0++;
nethercote71980f02004-01-24 18:18:54 +0000455
nethercotef6a1d502004-08-09 12:21:57 +0000456 vg_argv0 = malloc(sizeof(char **) * (vg_argc0 + 1));
457 vg_assert(vg_argv0);
nethercote71980f02004-01-24 18:18:54 +0000458
nethercotef6a1d502004-08-09 12:21:57 +0000459 cpp = vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000460
461 *cpp++ = "valgrind"; /* nominal argv[0] */
462 *cpp++ = env_clo;
463
nethercotef6a1d502004-08-09 12:21:57 +0000464 // Replace the VG_CLO_SEP args separator with '\0'
nethercote71980f02004-01-24 18:18:54 +0000465 for (cp = env_clo; *cp; cp++) {
nethercotef6a1d502004-08-09 12:21:57 +0000466 if (*cp == VG_CLO_SEP) {
nethercote71980f02004-01-24 18:18:54 +0000467 *cp++ = '\0'; /* chop it up in place */
468 *cpp++ = cp;
469 }
470 }
471 *cpp = NULL;
472 cl_argv = argv;
473
474 } else {
sewardjb5f6f512005-03-10 23:59:00 +0000475 Bool noaugment = False;
476
nethercote71980f02004-01-24 18:18:54 +0000477 /* Count the arguments on the command line. */
nethercotef6a1d502004-08-09 12:21:57 +0000478 vg_argv0 = argv;
nethercote71980f02004-01-24 18:18:54 +0000479
nethercotef6a1d502004-08-09 12:21:57 +0000480 for (vg_argc0 = 1; vg_argc0 < argc; vg_argc0++) {
sewardjb5f6f512005-03-10 23:59:00 +0000481 Char* arg = argv[vg_argc0];
482 if (arg[0] != '-') /* exe name */
nethercote71980f02004-01-24 18:18:54 +0000483 break;
sewardjb5f6f512005-03-10 23:59:00 +0000484 if (VG_STREQ(arg, "--")) { /* dummy arg */
nethercotef6a1d502004-08-09 12:21:57 +0000485 vg_argc0++;
nethercote71980f02004-01-24 18:18:54 +0000486 break;
487 }
njn45270a22005-03-27 01:00:11 +0000488 VG_BOOL_CLO(arg, "--command-line-only", noaugment)
nethercote71980f02004-01-24 18:18:54 +0000489 }
nethercotef6a1d502004-08-09 12:21:57 +0000490 cl_argv = &argv[vg_argc0];
nethercote71980f02004-01-24 18:18:54 +0000491
492 /* Get extra args from VALGRIND_OPTS and .valgrindrc files.
nethercotef6a1d502004-08-09 12:21:57 +0000493 Note we don't do this if getting args from VALGRINDCLO, as
sewardjb5f6f512005-03-10 23:59:00 +0000494 those extra args will already be present in VALGRINDCLO.
495 (We also don't do it when --command-line-only=yes.) */
496 if (!noaugment)
497 augment_command_line(&vg_argc0, &vg_argv0);
nethercote71980f02004-01-24 18:18:54 +0000498 }
499
500 if (0) {
501 Int i;
nethercotef6a1d502004-08-09 12:21:57 +0000502 for (i = 0; i < vg_argc0; i++)
503 printf("vg_argv0[%d]=\"%s\"\n", i, vg_argv0[i]);
nethercote71980f02004-01-24 18:18:54 +0000504 }
505
nethercotef6a1d502004-08-09 12:21:57 +0000506 *vg_argc_out = vg_argc0;
507 *vg_argv_out = (Char**)vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000508 *cl_argv_out = cl_argv;
509}
510
511
512/*====================================================================*/
513/*=== Environment and stack setup ===*/
514/*====================================================================*/
515
516/* Scan a colon-separated list, and call a function on each element.
517 The string must be mutable, because we insert a temporary '\0', but
thughes4ad52d02004-06-27 17:37:21 +0000518 the string will end up unmodified. (*func) should return True if it
nethercote71980f02004-01-24 18:18:54 +0000519 doesn't need to see any more.
thughes4ad52d02004-06-27 17:37:21 +0000520
521 This routine will return True if (*func) returns True and False if
522 it reaches the end of the list without that happening.
nethercote71980f02004-01-24 18:18:54 +0000523*/
thughes4ad52d02004-06-27 17:37:21 +0000524static Bool scan_colsep(char *colsep, Bool (*func)(const char *))
nethercote71980f02004-01-24 18:18:54 +0000525{
526 char *cp, *entry;
527 int end;
528
529 if (colsep == NULL ||
530 *colsep == '\0')
thughes4ad52d02004-06-27 17:37:21 +0000531 return False;
nethercote71980f02004-01-24 18:18:54 +0000532
533 entry = cp = colsep;
534
535 do {
536 end = (*cp == '\0');
537
538 if (*cp == ':' || *cp == '\0') {
539 char save = *cp;
540
541 *cp = '\0';
thughes21942d92004-07-12 09:35:37 +0000542 if ((*func)(entry)) {
543 *cp = save;
thughes4ad52d02004-06-27 17:37:21 +0000544 return True;
thughes21942d92004-07-12 09:35:37 +0000545 }
nethercote71980f02004-01-24 18:18:54 +0000546 *cp = save;
547 entry = cp+1;
548 }
549 cp++;
550 } while(!end);
thughes4ad52d02004-06-27 17:37:21 +0000551
552 return False;
553}
554
nethercote71980f02004-01-24 18:18:54 +0000555/* Prepare the client's environment. This is basically a copy of our
556 environment, except:
njn16eeb4e2005-06-16 03:56:58 +0000557 LD_PRELOAD=$VALGRINDLIB/vg_preload_core.so:($VALGRINDLIB/vgpreload_TOOL.so:)?$LD_PRELOAD
nethercote71980f02004-01-24 18:18:54 +0000558
sewardjb5f6f512005-03-10 23:59:00 +0000559 If this is missing, then it is added.
nethercote71980f02004-01-24 18:18:54 +0000560
561 Yummy. String hacking in C.
562
563 If this needs to handle any more variables it should be hacked
564 into something table driven.
565 */
566static char **fix_environment(char **origenv, const char *preload)
567{
njn16eeb4e2005-06-16 03:56:58 +0000568 static const char preload_core_so[] = "vg_preload_core.so";
nethercote71980f02004-01-24 18:18:54 +0000569 static const char ld_preload[] = "LD_PRELOAD=";
570 static const char valgrind_clo[] = VALGRINDCLO "=";
nethercote71980f02004-01-24 18:18:54 +0000571 static const int ld_preload_len = sizeof(ld_preload)-1;
572 static const int valgrind_clo_len = sizeof(valgrind_clo)-1;
573 int ld_preload_done = 0;
njn16eeb4e2005-06-16 03:56:58 +0000574 char *preload_core_path;
575 int preload_core_path_len;
nethercote71980f02004-01-24 18:18:54 +0000576 int vgliblen = strlen(VG_(libdir));
577 char **cpp;
578 char **ret;
579 int envc;
580 const int preloadlen = (preload == NULL) ? 0 : strlen(preload);
581
njn16eeb4e2005-06-16 03:56:58 +0000582 /* Find the vg_preload_core.so; also make room for the tool preload
nethercote71980f02004-01-24 18:18:54 +0000583 library */
njn16eeb4e2005-06-16 03:56:58 +0000584 preload_core_path_len = sizeof(preload_core_so) + vgliblen + preloadlen + 16;
585 preload_core_path = malloc(preload_core_path_len);
586 vg_assert(preload_core_path);
nethercote71980f02004-01-24 18:18:54 +0000587
588 if (preload)
njn16eeb4e2005-06-16 03:56:58 +0000589 snprintf(preload_core_path, preload_core_path_len, "%s/%s:%s",
590 VG_(libdir), preload_core_so, preload);
nethercote71980f02004-01-24 18:18:54 +0000591 else
njn16eeb4e2005-06-16 03:56:58 +0000592 snprintf(preload_core_path, preload_core_path_len, "%s/%s",
593 VG_(libdir), preload_core_so);
nethercote71980f02004-01-24 18:18:54 +0000594
595 /* Count the original size of the env */
596 envc = 0; /* trailing NULL */
597 for (cpp = origenv; cpp && *cpp; cpp++)
598 envc++;
599
600 /* Allocate a new space */
sewardjb5f6f512005-03-10 23:59:00 +0000601 ret = malloc(sizeof(char *) * (envc+1+1)); /* 1 new entry + NULL */
nethercote7c018f42004-07-17 16:40:50 +0000602 vg_assert(ret);
nethercote71980f02004-01-24 18:18:54 +0000603
604 /* copy it over */
605 for (cpp = ret; *origenv; )
606 *cpp++ = *origenv++;
607 *cpp = NULL;
608
609 vg_assert(envc == (cpp - ret));
610
611 /* Walk over the new environment, mashing as we go */
612 for (cpp = ret; cpp && *cpp; cpp++) {
sewardjb5f6f512005-03-10 23:59:00 +0000613 if (memcmp(*cpp, ld_preload, ld_preload_len) == 0) {
njn16eeb4e2005-06-16 03:56:58 +0000614 int len = strlen(*cpp) + preload_core_path_len;
nethercote71980f02004-01-24 18:18:54 +0000615 char *cp = malloc(len);
nethercote7c018f42004-07-17 16:40:50 +0000616 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000617
618 snprintf(cp, len, "%s%s:%s",
njn16eeb4e2005-06-16 03:56:58 +0000619 ld_preload, preload_core_path, (*cpp)+ld_preload_len);
nethercote71980f02004-01-24 18:18:54 +0000620
621 *cpp = cp;
622
623 ld_preload_done = 1;
624 } else if (memcmp(*cpp, valgrind_clo, valgrind_clo_len) == 0) {
625 *cpp = "";
626 }
627 }
628
629 /* Add the missing bits */
nethercote71980f02004-01-24 18:18:54 +0000630 if (!ld_preload_done) {
njn16eeb4e2005-06-16 03:56:58 +0000631 int len = ld_preload_len + preload_core_path_len;
nethercote71980f02004-01-24 18:18:54 +0000632 char *cp = malloc(len);
nethercote7c018f42004-07-17 16:40:50 +0000633 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000634
njn16eeb4e2005-06-16 03:56:58 +0000635 snprintf(cp, len, "%s%s", ld_preload, preload_core_path);
nethercote71980f02004-01-24 18:18:54 +0000636
637 ret[envc++] = cp;
638 }
639
njn16eeb4e2005-06-16 03:56:58 +0000640 free(preload_core_path);
nethercote71980f02004-01-24 18:18:54 +0000641 ret[envc] = NULL;
642
643 return ret;
644}
645
646extern char **environ; /* our environment */
nethercote71980f02004-01-24 18:18:54 +0000647
648/* Add a string onto the string table, and return its address */
649static char *copy_str(char **tab, const char *str)
650{
651 char *cp = *tab;
652 char *orig = cp;
653
654 while(*str)
655 *cp++ = *str++;
656 *cp++ = '\0';
657
658 if (0)
nethercote545fe672004-11-01 16:52:43 +0000659 printf("copied %p \"%s\" len %lld\n", orig, orig, (Long)(cp-orig));
nethercote71980f02004-01-24 18:18:54 +0000660
661 *tab = cp;
662
663 return orig;
664}
665
666/*
667 This sets up the client's initial stack, containing the args,
668 environment and aux vector.
669
670 The format of the stack is:
671
672 higher address +-----------------+
673 | Trampoline code |
674 +-----------------+
675 | |
676 : string table :
677 | |
678 +-----------------+
679 | AT_NULL |
680 - -
681 | auxv |
682 +-----------------+
683 | NULL |
684 - -
685 | envp |
686 +-----------------+
687 | NULL |
688 - -
689 | argv |
690 +-----------------+
691 | argc |
nethercote4ad74312004-10-26 09:59:49 +0000692 lower address +-----------------+ <- sp
nethercote71980f02004-01-24 18:18:54 +0000693 | undefined |
694 : :
695 */
nethercotec25c4492004-10-18 11:52:17 +0000696static Addr setup_client_stack(void* init_sp,
697 char **orig_argv, char **orig_envp,
nethercote71980f02004-01-24 18:18:54 +0000698 const struct exeinfo *info,
699 UInt** client_auxv)
700{
njn83407492005-06-19 16:10:47 +0000701 SysRes res;
nethercote71980f02004-01-24 18:18:54 +0000702 char **cpp;
703 char *strtab; /* string table */
704 char *stringbase;
nethercotea3c3cf22004-11-01 18:38:00 +0000705 Addr *ptr;
nethercote71980f02004-01-24 18:18:54 +0000706 struct ume_auxv *auxv;
707 const struct ume_auxv *orig_auxv;
708 const struct ume_auxv *cauxv;
709 unsigned stringsize; /* total size of strings in bytes */
710 unsigned auxsize; /* total size of auxv in bytes */
711 int argc; /* total argc */
712 int envc; /* total number of env vars */
713 unsigned stacksize; /* total client stack size */
nethercotea3c3cf22004-11-01 18:38:00 +0000714 Addr cl_esp; /* client stack base (initial esp) */
nethercote71980f02004-01-24 18:18:54 +0000715
716 /* use our own auxv as a prototype */
njn62ff0f22005-06-21 23:03:36 +0000717 orig_auxv = VG_(find_auxv)(init_sp);
nethercote71980f02004-01-24 18:18:54 +0000718
719 /* ==================== compute sizes ==================== */
720
721 /* first of all, work out how big the client stack will be */
722 stringsize = 0;
723
724 /* paste on the extra args if the loader needs them (ie, the #!
725 interpreter and its argument) */
726 argc = 0;
nethercoted6a56872004-07-26 15:32:47 +0000727 if (info->interp_name != NULL) {
nethercote71980f02004-01-24 18:18:54 +0000728 argc++;
nethercoted6a56872004-07-26 15:32:47 +0000729 stringsize += strlen(info->interp_name) + 1;
nethercote71980f02004-01-24 18:18:54 +0000730 }
nethercoted6a56872004-07-26 15:32:47 +0000731 if (info->interp_args != NULL) {
nethercote71980f02004-01-24 18:18:54 +0000732 argc++;
nethercoted6a56872004-07-26 15:32:47 +0000733 stringsize += strlen(info->interp_args) + 1;
nethercote71980f02004-01-24 18:18:54 +0000734 }
735
736 /* now scan the args we're given... */
737 for (cpp = orig_argv; *cpp; cpp++) {
738 argc++;
739 stringsize += strlen(*cpp) + 1;
740 }
741
742 /* ...and the environment */
743 envc = 0;
744 for (cpp = orig_envp; cpp && *cpp; cpp++) {
745 envc++;
746 stringsize += strlen(*cpp) + 1;
747 }
748
749 /* now, how big is the auxv? */
750 auxsize = sizeof(*auxv); /* there's always at least one entry: AT_NULL */
751 for (cauxv = orig_auxv; cauxv->a_type != AT_NULL; cauxv++) {
752 if (cauxv->a_type == AT_PLATFORM)
753 stringsize += strlen(cauxv->u.a_ptr) + 1;
754 auxsize += sizeof(*cauxv);
755 }
756
cerion85665ca2005-06-20 15:51:07 +0000757#if defined(VGP_ppc32_linux)
758 auxsize += 2 * sizeof(*cauxv);
759#endif
760
nethercote71980f02004-01-24 18:18:54 +0000761 /* OK, now we know how big the client stack is */
762 stacksize =
sewardj9d9cdea2005-03-23 03:06:30 +0000763 sizeof(Word) + /* argc */
nethercote71980f02004-01-24 18:18:54 +0000764 sizeof(char **)*argc + /* argv */
765 sizeof(char **) + /* terminal NULL */
766 sizeof(char **)*envc + /* envp */
767 sizeof(char **) + /* terminal NULL */
768 auxsize + /* auxv */
njn13bfd852005-06-02 03:52:53 +0000769 VG_ROUNDUP(stringsize, sizeof(Word)) +/* strings (aligned) */
nethercote5fd72bb2004-11-04 19:28:38 +0000770 VKI_PAGE_SIZE; /* page for trampoline code */
nethercote71980f02004-01-24 18:18:54 +0000771
sewardj79048ce2005-02-18 08:28:32 +0000772 if (0) VG_(printf)("stacksize = %d\n", stacksize);
773
nethercotef84f6952004-07-15 14:58:33 +0000774 // decide where stack goes!
775 VG_(clstk_end) = VG_(client_end);
776
nethercote71980f02004-01-24 18:18:54 +0000777 /* cl_esp is the client's stack pointer */
nethercotef84f6952004-07-15 14:58:33 +0000778 cl_esp = VG_(clstk_end) - stacksize;
njn13bfd852005-06-02 03:52:53 +0000779 cl_esp = VG_ROUNDDN(cl_esp, 16); /* make stack 16 byte aligned */
nethercote71980f02004-01-24 18:18:54 +0000780
nethercote71980f02004-01-24 18:18:54 +0000781 /* base of the string table (aligned) */
sewardjb9bce632005-06-21 01:41:34 +0000782 stringbase = strtab = (char *)(VG_(clstk_end)
njn13bfd852005-06-02 03:52:53 +0000783 - VG_ROUNDUP(stringsize, sizeof(int)));
nethercote71980f02004-01-24 18:18:54 +0000784
njn13bfd852005-06-02 03:52:53 +0000785 VG_(clstk_base) = VG_PGROUNDDN(cl_esp);
nethercote71980f02004-01-24 18:18:54 +0000786
sewardj79048ce2005-02-18 08:28:32 +0000787 if (0)
nethercote5ee67ca2004-06-22 14:00:09 +0000788 printf("stringsize=%d auxsize=%d stacksize=%d\n"
nethercote6a27d832004-09-07 10:17:02 +0000789 "clstk_base %p\n"
790 "clstk_end %p\n",
791 stringsize, auxsize, stacksize,
792 (void*)VG_(clstk_base), (void*)VG_(clstk_end));
nethercote5ee67ca2004-06-22 14:00:09 +0000793
nethercote71980f02004-01-24 18:18:54 +0000794 /* ==================== allocate space ==================== */
795
796 /* allocate a stack - mmap enough space for the stack */
njn83407492005-06-19 16:10:47 +0000797 res = VG_(mmap_native)((void *)VG_PGROUNDDN(cl_esp),
njn13bfd852005-06-02 03:52:53 +0000798 VG_(clstk_end) - VG_PGROUNDDN(cl_esp),
njn83407492005-06-19 16:10:47 +0000799 VKI_PROT_READ|VKI_PROT_WRITE|VKI_PROT_EXEC,
800 VKI_MAP_PRIVATE|VKI_MAP_ANONYMOUS|VKI_MAP_FIXED, -1, 0);
801 vg_assert(!res.isError);
nethercote71980f02004-01-24 18:18:54 +0000802
803 /* ==================== copy client stack ==================== */
804
nethercotea3c3cf22004-11-01 18:38:00 +0000805 ptr = (Addr*)cl_esp;
nethercote71980f02004-01-24 18:18:54 +0000806
807 /* --- argc --- */
808 *ptr++ = argc; /* client argc */
809
810 /* --- argv --- */
nethercoted6a56872004-07-26 15:32:47 +0000811 if (info->interp_name) {
nethercotea3c3cf22004-11-01 18:38:00 +0000812 *ptr++ = (Addr)copy_str(&strtab, info->interp_name);
nethercoted6a56872004-07-26 15:32:47 +0000813 free(info->interp_name);
nethercote71980f02004-01-24 18:18:54 +0000814 }
nethercoted6a56872004-07-26 15:32:47 +0000815 if (info->interp_args) {
nethercotea3c3cf22004-11-01 18:38:00 +0000816 *ptr++ = (Addr)copy_str(&strtab, info->interp_args);
nethercoted6a56872004-07-26 15:32:47 +0000817 free(info->interp_args);
nethercote71980f02004-01-24 18:18:54 +0000818 }
819 for (cpp = orig_argv; *cpp; ptr++, cpp++) {
nethercotea3c3cf22004-11-01 18:38:00 +0000820 *ptr = (Addr)copy_str(&strtab, *cpp);
nethercote71980f02004-01-24 18:18:54 +0000821 }
822 *ptr++ = 0;
823
824 /* --- envp --- */
825 VG_(client_envp) = (Char **)ptr;
826 for (cpp = orig_envp; cpp && *cpp; ptr++, cpp++)
nethercotea3c3cf22004-11-01 18:38:00 +0000827 *ptr = (Addr)copy_str(&strtab, *cpp);
nethercote71980f02004-01-24 18:18:54 +0000828 *ptr++ = 0;
829
830 /* --- auxv --- */
831 auxv = (struct ume_auxv *)ptr;
832 *client_auxv = (UInt *)auxv;
833
cerion85665ca2005-06-20 15:51:07 +0000834#if defined(VGP_ppc32_linux)
835 auxv[0].a_type = AT_IGNOREPPC;
836 auxv[0].u.a_val = AT_IGNOREPPC;
837 auxv[1].a_type = AT_IGNOREPPC;
838 auxv[1].u.a_val = AT_IGNOREPPC;
839 auxv += 2;
840#endif
841
nethercote71980f02004-01-24 18:18:54 +0000842 for (; orig_auxv->a_type != AT_NULL; auxv++, orig_auxv++) {
843 /* copy the entry... */
844 *auxv = *orig_auxv;
845
846 /* ...and fix up the copy */
847 switch(auxv->a_type) {
848 case AT_PHDR:
849 if (info->phdr == 0)
850 auxv->a_type = AT_IGNORE;
851 else
852 auxv->u.a_val = info->phdr;
853 break;
854
855 case AT_PHNUM:
856 if (info->phdr == 0)
857 auxv->a_type = AT_IGNORE;
858 else
859 auxv->u.a_val = info->phnum;
860 break;
861
862 case AT_BASE:
sewardjb5f6f512005-03-10 23:59:00 +0000863 auxv->u.a_val = info->interp_base;
nethercote71980f02004-01-24 18:18:54 +0000864 break;
865
866 case AT_PLATFORM: /* points to a platform description string */
867 auxv->u.a_ptr = copy_str(&strtab, orig_auxv->u.a_ptr);
868 break;
869
870 case AT_ENTRY:
871 auxv->u.a_val = info->entry;
872 break;
873
874 case AT_IGNORE:
875 case AT_EXECFD:
876 case AT_PHENT:
877 case AT_PAGESZ:
878 case AT_FLAGS:
879 case AT_NOTELF:
880 case AT_UID:
881 case AT_EUID:
882 case AT_GID:
883 case AT_EGID:
884 case AT_CLKTCK:
885 case AT_HWCAP:
886 case AT_FPUCW:
887 case AT_DCACHEBSIZE:
888 case AT_ICACHEBSIZE:
889 case AT_UCACHEBSIZE:
cerion85665ca2005-06-20 15:51:07 +0000890#if defined(VGP_ppc32_linux)
891 case AT_IGNOREPPC:
892#endif
nethercote71980f02004-01-24 18:18:54 +0000893 /* All these are pointerless, so we don't need to do anything
894 about them. */
895 break;
896
897 case AT_SECURE:
898 /* If this is 1, then it means that this program is running
899 suid, and therefore the dynamic linker should be careful
900 about LD_PRELOAD, etc. However, since stage1 (the thing
901 the kernel actually execve's) should never be SUID, and we
sewardjb5f6f512005-03-10 23:59:00 +0000902 need LD_PRELOAD to work for the client, we
nethercote71980f02004-01-24 18:18:54 +0000903 set AT_SECURE to 0. */
904 auxv->u.a_val = 0;
905 break;
906
907 case AT_SYSINFO:
908 /* Leave this unmolested for now, but we'll update it later
909 when we set up the client trampoline code page */
910 break;
911
cerion85665ca2005-06-20 15:51:07 +0000912#if !defined(VGP_ppc32_linux)
nethercote71980f02004-01-24 18:18:54 +0000913 case AT_SYSINFO_EHDR:
914 /* Trash this, because we don't reproduce it */
915 auxv->a_type = AT_IGNORE;
916 break;
cerion85665ca2005-06-20 15:51:07 +0000917#endif
nethercote71980f02004-01-24 18:18:54 +0000918
919 default:
920 /* stomp out anything we don't know about */
njn37569252005-06-21 00:28:43 +0000921 if (0)
nethercote545fe672004-11-01 16:52:43 +0000922 printf("stomping auxv entry %lld\n", (ULong)auxv->a_type);
nethercote71980f02004-01-24 18:18:54 +0000923 auxv->a_type = AT_IGNORE;
924 break;
925
926 }
927 }
928 *auxv = *orig_auxv;
929 vg_assert(auxv->a_type == AT_NULL);
930
931 vg_assert((strtab-stringbase) == stringsize);
932
nethercote5ee67ca2004-06-22 14:00:09 +0000933 /* We know the initial ESP is pointing at argc/argv */
934 VG_(client_argc) = *(Int*)cl_esp;
sewardj45f02c42005-02-05 18:27:14 +0000935 VG_(client_argv) = (Char**)(cl_esp + sizeof(HWord));
nethercote5ee67ca2004-06-22 14:00:09 +0000936
sewardj79048ce2005-02-18 08:28:32 +0000937 if (0) VG_(printf)("startup SP = %p\n", cl_esp);
nethercote71980f02004-01-24 18:18:54 +0000938 return cl_esp;
939}
940
941/*====================================================================*/
942/*=== Find executable ===*/
943/*====================================================================*/
944
thughes4ad52d02004-06-27 17:37:21 +0000945static const char* executable_name;
946
947static Bool match_executable(const char *entry) {
948 char buf[strlen(entry) + strlen(executable_name) + 2];
949
950 /* empty PATH element means . */
951 if (*entry == '\0')
952 entry = ".";
953
954 snprintf(buf, sizeof(buf), "%s/%s", entry, executable_name);
955
956 if (access(buf, R_OK|X_OK) == 0) {
957 executable_name = strdup(buf);
958 vg_assert(NULL != executable_name);
959 return True;
960 }
961 return False;
962}
963
nethercote71980f02004-01-24 18:18:54 +0000964static const char* find_executable(const char* exec)
965{
966 vg_assert(NULL != exec);
thughes4ad52d02004-06-27 17:37:21 +0000967 executable_name = exec;
968 if (strchr(executable_name, '/') == NULL) {
nethercote71980f02004-01-24 18:18:54 +0000969 /* no '/' - we need to search the path */
970 char *path = getenv("PATH");
thughes4ad52d02004-06-27 17:37:21 +0000971 scan_colsep(path, match_executable);
nethercote71980f02004-01-24 18:18:54 +0000972 }
thughes4ad52d02004-06-27 17:37:21 +0000973 return executable_name;
nethercote71980f02004-01-24 18:18:54 +0000974}
975
976
977/*====================================================================*/
978/*=== Loading tools ===*/
979/*====================================================================*/
980
981static void list_tools(void)
982{
983 DIR *dir = opendir(VG_(libdir));
984 struct dirent *de;
985 int first = 1;
986
987 if (dir == NULL) {
988 fprintf(stderr, "Can't open %s: %s (installation problem?)\n",
nethercotef4928da2004-06-15 10:54:40 +0000989 VG_(libdir), strerror(errno));
nethercote71980f02004-01-24 18:18:54 +0000990 return;
991 }
992
nethercotef4928da2004-06-15 10:54:40 +0000993 while ((de = readdir(dir)) != NULL) {
nethercote71980f02004-01-24 18:18:54 +0000994 int len = strlen(de->d_name);
995
njn063c5402004-11-22 16:58:05 +0000996 /* look for vgtool_TOOL.so names */
997 if (len > (7+1+3) && /* "vgtool_" + at least 1-char toolname + ".so" */
998 strncmp(de->d_name, "vgtool_", 7) == 0 &&
nethercotef4928da2004-06-15 10:54:40 +0000999 VG_STREQ(de->d_name + len - 3, ".so")) {
1000 if (first) {
1001 fprintf(stderr, "Available tools:\n");
1002 first = 0;
1003 }
1004 de->d_name[len-3] = '\0';
1005 fprintf(stderr, "\t%s\n", de->d_name+7);
nethercote71980f02004-01-24 18:18:54 +00001006 }
1007 }
1008
1009 closedir(dir);
1010
1011 if (first)
nethercotef4928da2004-06-15 10:54:40 +00001012 fprintf(stderr, "No tools available in \"%s\" (installation problem?)\n",
1013 VG_(libdir));
nethercote71980f02004-01-24 18:18:54 +00001014}
1015
1016
1017/* Find and load a tool, and check it looks ok. Also looks to see if there's
1018 * a matching vgpreload_*.so file, and returns its name in *preloadpath. */
njn8a97c6d2005-03-31 04:37:24 +00001019static void load_tool( const char *toolname,
nethercote71980f02004-01-24 18:18:54 +00001020 ToolInfo** toolinfo_out, char **preloadpath_out )
1021{
1022 Bool ok;
sewardjb5f6f512005-03-10 23:59:00 +00001023 int len = strlen(VG_(libdir)) + strlen(toolname) + 16;
nethercote71980f02004-01-24 18:18:54 +00001024 char buf[len];
1025 void* handle;
1026 ToolInfo* toolinfo;
1027 char* preloadpath = NULL;
nethercote71980f02004-01-24 18:18:54 +00001028
1029 // XXX: allowing full paths for --tool option -- does it make sense?
1030 // Doesn't allow for vgpreload_<tool>.so.
1031
1032 if (strchr(toolname, '/') != 0) {
1033 /* toolname contains '/', and so must be a pathname */
1034 handle = dlopen(toolname, RTLD_NOW);
1035 } else {
1036 /* just try in the libdir */
njn063c5402004-11-22 16:58:05 +00001037 snprintf(buf, len, "%s/vgtool_%s.so", VG_(libdir), toolname);
nethercote71980f02004-01-24 18:18:54 +00001038 handle = dlopen(buf, RTLD_NOW);
1039
1040 if (handle != NULL) {
1041 snprintf(buf, len, "%s/vgpreload_%s.so", VG_(libdir), toolname);
1042 if (access(buf, R_OK) == 0) {
1043 preloadpath = strdup(buf);
1044 vg_assert(NULL != preloadpath);
1045 }
1046 }
1047 }
1048
1049 ok = (NULL != handle);
1050 if (!ok) {
1051 fprintf(stderr, "Can't open tool \"%s\": %s\n", toolname, dlerror());
1052 goto bad_load;
1053 }
1054
njn51d827b2005-05-09 01:02:08 +00001055 toolinfo = dlsym(handle, "vgPlain_tool_info");
nethercote71980f02004-01-24 18:18:54 +00001056 ok = (NULL != toolinfo);
1057 if (!ok) {
njn51d827b2005-05-09 01:02:08 +00001058 fprintf(stderr, "Tool \"%s\" doesn't define its ToolInfo - "
nethercote71980f02004-01-24 18:18:54 +00001059 "add VG_DETERMINE_INTERFACE_VERSION?\n", toolname);
1060 goto bad_load;
1061 }
1062
1063 ok = (toolinfo->sizeof_ToolInfo == sizeof(*toolinfo) &&
njn51d827b2005-05-09 01:02:08 +00001064 toolinfo->interface_version == VG_CORE_INTERFACE_VERSION &&
1065 toolinfo->tl_pre_clo_init != NULL);
nethercote71980f02004-01-24 18:18:54 +00001066 if (!ok) {
1067 fprintf(stderr, "Error:\n"
1068 " Tool and core interface versions do not match.\n"
njn51d827b2005-05-09 01:02:08 +00001069 " Interface version used by core is: %d (size %d)\n"
1070 " Interface version used by tool is: %d (size %d)\n"
1071 " The version numbers must match.\n",
1072 VG_CORE_INTERFACE_VERSION,
nethercote545fe672004-11-01 16:52:43 +00001073 (Int)sizeof(*toolinfo),
njn51d827b2005-05-09 01:02:08 +00001074 toolinfo->interface_version,
nethercote71980f02004-01-24 18:18:54 +00001075 toolinfo->sizeof_ToolInfo);
1076 fprintf(stderr, " You need to at least recompile, and possibly update,\n");
njn51d827b2005-05-09 01:02:08 +00001077 if (VG_CORE_INTERFACE_VERSION > toolinfo->interface_version)
nethercote996901a2004-08-03 13:29:09 +00001078 fprintf(stderr, " your tool to work with this version of Valgrind.\n");
nethercote71980f02004-01-24 18:18:54 +00001079 else
nethercote996901a2004-08-03 13:29:09 +00001080 fprintf(stderr, " your version of Valgrind to work with this tool.\n");
nethercote71980f02004-01-24 18:18:54 +00001081 goto bad_load;
1082 }
1083
njn8a97c6d2005-03-31 04:37:24 +00001084 vg_assert(NULL != toolinfo);
nethercote71980f02004-01-24 18:18:54 +00001085 *toolinfo_out = toolinfo;
1086 *preloadpath_out = preloadpath;
1087 return;
1088
1089
1090 bad_load:
1091 if (handle != NULL)
1092 dlclose(handle);
1093
nethercotef4928da2004-06-15 10:54:40 +00001094 fprintf(stderr, "valgrind: couldn't load tool\n");
nethercote71980f02004-01-24 18:18:54 +00001095 list_tools();
1096 exit(127);
1097}
1098
nethercotef4928da2004-06-15 10:54:40 +00001099
1100/*====================================================================*/
1101/*=== Command line errors ===*/
1102/*====================================================================*/
1103
njnbe9b47b2005-05-15 16:22:58 +00001104static void revert_to_stderr ( void )
nethercotef4928da2004-06-15 10:54:40 +00001105{
njnbe9b47b2005-05-15 16:22:58 +00001106 vg_assert( !VG_(logging_to_socket) );
nethercotef8548672004-06-21 12:42:35 +00001107 VG_(clo_log_fd) = 2; /* stderr */
nethercotef4928da2004-06-15 10:54:40 +00001108}
1109
1110void VG_(bad_option) ( Char* opt )
1111{
njnbe9b47b2005-05-15 16:22:58 +00001112 revert_to_stderr();
njn02bc4b82005-05-15 17:28:26 +00001113 VG_(printf)("valgrind: Bad option '%s'; aborting.\n", opt);
nethercotef4928da2004-06-15 10:54:40 +00001114 VG_(printf)("valgrind: Use --help for more information.\n");
1115 VG_(exit)(1);
1116}
1117
nethercotef4928da2004-06-15 10:54:40 +00001118static void missing_prog ( void )
1119{
njnbe9b47b2005-05-15 16:22:58 +00001120 revert_to_stderr();
nethercotef4928da2004-06-15 10:54:40 +00001121 VG_(printf)("valgrind: no program specified\n");
1122 VG_(printf)("valgrind: Use --help for more information.\n");
1123 VG_(exit)(1);
1124}
1125
1126static void config_error ( Char* msg )
1127{
njnbe9b47b2005-05-15 16:22:58 +00001128 revert_to_stderr();
nethercotef4928da2004-06-15 10:54:40 +00001129 VG_(printf)("valgrind: Startup or configuration error:\n %s\n", msg);
1130 VG_(printf)("valgrind: Unable to start up properly. Giving up.\n");
1131 VG_(exit)(1);
1132}
1133
1134
nethercote71980f02004-01-24 18:18:54 +00001135/*====================================================================*/
1136/*=== Loading the client ===*/
1137/*====================================================================*/
1138
nethercotef4928da2004-06-15 10:54:40 +00001139static void load_client(char* cl_argv[], const char* exec, Int need_help,
nethercote71980f02004-01-24 18:18:54 +00001140 /*out*/struct exeinfo* info, /*out*/Addr* client_eip)
1141{
1142 // If they didn't specify an executable with --exec, and didn't specify
1143 // --help, then use client argv[0] (searching $PATH if necessary).
nethercotef4928da2004-06-15 10:54:40 +00001144 if (NULL == exec && !need_help) {
nethercote71980f02004-01-24 18:18:54 +00001145 if (cl_argv[0] == NULL ||
1146 ( NULL == (exec = find_executable(cl_argv[0])) ) )
1147 {
nethercotef4928da2004-06-15 10:54:40 +00001148 missing_prog();
nethercote71980f02004-01-24 18:18:54 +00001149 }
1150 }
1151
1152 info->map_base = VG_(client_mapbase);
nethercote71980f02004-01-24 18:18:54 +00001153 info->exe_base = VG_(client_base);
1154 info->exe_end = VG_(client_end);
1155 info->argv = cl_argv;
1156
nethercotef4928da2004-06-15 10:54:40 +00001157 if (need_help) {
nethercote71980f02004-01-24 18:18:54 +00001158 VG_(clexecfd) = -1;
njnc8c93282004-11-29 16:05:54 +00001159 // Totally zero 'info' before continuing.
1160 VG_(memset)(info, 0, sizeof(*info));
nethercote71980f02004-01-24 18:18:54 +00001161 } else {
1162 Int ret;
nethercote4ec0af42004-10-16 15:31:49 +00001163 VG_(clexecfd) = VG_(open)(exec, VKI_O_RDONLY, VKI_S_IRUSR);
njn62ff0f22005-06-21 23:03:36 +00001164 ret = VG_(do_exec)(exec, info);
nethercote71980f02004-01-24 18:18:54 +00001165 if (ret != 0) {
nethercoteea147e72004-07-26 15:43:57 +00001166 fprintf(stderr, "valgrind: do_exec(%s) failed: %s\n",
1167 exec, strerror(ret));
nethercote71980f02004-01-24 18:18:54 +00001168 exit(127);
1169 }
1170 }
1171
1172 /* Copy necessary bits of 'info' that were filled in */
1173 *client_eip = info->init_eip;
1174 VG_(brk_base) = VG_(brk_limit) = info->brkbase;
1175}
1176
nethercote969ecf12004-10-13 17:29:01 +00001177/*====================================================================*/
1178/*=== Address space unpadding ===*/
1179/*====================================================================*/
1180
1181typedef struct {
njn909c3192005-06-19 15:46:27 +00001182 char* killpad_start;
1183 char* killpad_end;
1184 struct vki_stat* killpad_padstat;
nethercote969ecf12004-10-13 17:29:01 +00001185} killpad_extra;
1186
1187static int killpad(char *segstart, char *segend, const char *perm, off_t off,
1188 int maj, int min, int ino, void* ex)
1189{
1190 killpad_extra* extra = ex;
1191 void *b, *e;
njn83407492005-06-19 16:10:47 +00001192 SysRes res;
nethercote969ecf12004-10-13 17:29:01 +00001193
1194 vg_assert(NULL != extra->killpad_padstat);
1195
1196 if (extra->killpad_padstat->st_dev != makedev(maj, min) ||
1197 extra->killpad_padstat->st_ino != ino)
1198 return 1;
1199
1200 if (segend <= extra->killpad_start || segstart >= extra->killpad_end)
1201 return 1;
1202
1203 if (segstart <= extra->killpad_start)
1204 b = extra->killpad_start;
1205 else
1206 b = segstart;
1207
1208 if (segend >= extra->killpad_end)
1209 e = extra->killpad_end;
1210 else
1211 e = segend;
1212
njn83407492005-06-19 16:10:47 +00001213 res = VG_(munmap_native)(b, (char *)e-(char *)b);
1214 vg_assert(!res.isError);
nethercote969ecf12004-10-13 17:29:01 +00001215
1216 return 1;
1217}
1218
1219// Remove padding of 'padfile' from a range of address space.
sewardj2c5ffbe2005-03-12 13:32:06 +00001220static void as_unpad(void *start, void *end, int padfile)
nethercote969ecf12004-10-13 17:29:01 +00001221{
njn909c3192005-06-19 15:46:27 +00001222 static struct vki_stat padstat;
nethercote969ecf12004-10-13 17:29:01 +00001223 killpad_extra extra;
1224 int res;
1225
sewardjb5f6f512005-03-10 23:59:00 +00001226 vg_assert(padfile >= 0);
nethercote969ecf12004-10-13 17:29:01 +00001227
njn909c3192005-06-19 15:46:27 +00001228 res = VG_(fstat)(padfile, &padstat);
nethercote969ecf12004-10-13 17:29:01 +00001229 vg_assert(0 == res);
1230 extra.killpad_padstat = &padstat;
1231 extra.killpad_start = start;
1232 extra.killpad_end = end;
njn62ff0f22005-06-21 23:03:36 +00001233 VG_(foreach_map)(killpad, &extra);
nethercote969ecf12004-10-13 17:29:01 +00001234}
1235
sewardj2c5ffbe2005-03-12 13:32:06 +00001236static void as_closepadfile(int padfile)
nethercote969ecf12004-10-13 17:29:01 +00001237{
1238 int res = close(padfile);
1239 vg_assert(0 == res);
1240}
1241
sewardj71bc3cb2005-05-19 00:25:45 +00001242/*====================================================================*/
1243/*=== Command-line: variables, processing, etc ===*/
1244/*====================================================================*/
1245
1246// See pub_{core,tool}_options.h for explanations of all these.
1247
sewardj2c5ffbe2005-03-12 13:32:06 +00001248static void usage ( Bool debug_help )
njn7cf0bd32002-06-08 13:36:03 +00001249{
njn25e49d8e72002-09-23 09:36:25 +00001250 Char* usage1 =
nethercote71980f02004-01-24 18:18:54 +00001251"usage: valgrind --tool=<toolname> [options] prog-and-args\n"
njn25e49d8e72002-09-23 09:36:25 +00001252"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001253" common user options for all Valgrind tools, with defaults in [ ]:\n"
sewardjb5f6f512005-03-10 23:59:00 +00001254" --tool=<name> use the Valgrind tool named <name> [memcheck]\n"
nethercotea76368b2004-06-16 11:56:29 +00001255" -h --help show this message\n"
nethercote6c999f22004-01-31 22:55:15 +00001256" --help-debug show this message, plus debugging options\n"
njn25e49d8e72002-09-23 09:36:25 +00001257" --version show version\n"
njn25e49d8e72002-09-23 09:36:25 +00001258" -q --quiet run silently; only print error msgs\n"
1259" -v --verbose be more verbose, incl counts of errors\n"
sewardjf178c302005-05-20 02:02:10 +00001260" --xml=yes all output is in XML (Memcheck only)\n"
nethercote77eba602003-11-13 17:35:04 +00001261" --trace-children=no|yes Valgrind-ise child processes? [no]\n"
nethercote0d588502004-06-21 13:27:11 +00001262" --track-fds=no|yes track open file descriptors? [no]\n"
thughes6233a382004-08-21 11:10:44 +00001263" --time-stamp=no|yes add timestamps to log messages? [no]\n"
nethercote2b0793f2003-12-02 10:41:18 +00001264"\n"
1265" uncommon user options for all Valgrind tools:\n"
nethercote0d588502004-06-21 13:27:11 +00001266" --run-libc-freeres=no|yes free up glibc memory at exit? [yes]\n"
sewardjb5f6f512005-03-10 23:59:00 +00001267" --weird-hacks=hack1,hack2,... recognised hacks: lax-ioctls,ioctl-mmap [none]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001268" --pointercheck=no|yes enforce client address space limits [yes]\n"
sewardj062f3552005-01-06 16:13:40 +00001269" --support-elan3=no|yes hacks for Quadrics Elan3 support [no]\n"
sewardjb1131a82005-03-19 15:12:21 +00001270" --show-emwarns=no|yes show warnings about emulation limits? [no]\n"
sewardj26412bd2005-07-07 10:05:05 +00001271" --smc-support=none|stack|all support for self-modifying code:\n"
1272" none, for code found in stacks, or all [stack]\n"
sewardj768db0e2005-07-19 14:18:56 +00001273" --xml-user-comment=STR copy STR verbatim to XML output\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"
nethercotef8548672004-06-21 12:42:35 +00001276" --log-fd=<number> log messages to file descriptor [2=stderr]\n"
1277" --log-file=<file> log messages to <file>.pid<pid>\n"
sewardj603d4102005-01-11 14:01:02 +00001278" --log-file-exactly=<file> log messages to <file>\n"
sewardjad311162005-07-19 11:25:02 +00001279" --log-file-qualifier=<VAR> incorporate $VAR in logfile name [none]\n"
nethercotef8548672004-06-21 12:42:35 +00001280" --log-socket=ipaddr:port log messages to socket ipaddr:port\n"
nethercote2b0793f2003-12-02 10:41:18 +00001281" --demangle=no|yes automatically demangle C++ names? [yes]\n"
njncc6cc142005-03-12 20:59:29 +00001282" --num-callers=<number> show <num> callers in stack traces [12]\n"
nethercote2b0793f2003-12-02 10:41:18 +00001283" --error-limit=no|yes stop showing new errors if too many? [yes]\n"
1284" --show-below-main=no|yes continue stack traces below main() [no]\n"
1285" --suppressions=<filename> suppress errors described in <filename>\n"
sewardjd153fae2005-01-10 17:24:47 +00001286" --gen-suppressions=no|yes|all print suppressions for errors? [no]\n"
nethercote04d0fbc2004-01-26 16:48:06 +00001287" --db-attach=no|yes start debugger when errors detected? [no]\n"
1288" --db-command=<command> command to start debugger [gdb -nw %%f %%p]\n"
1289" --input-fd=<number> file descriptor for input [0=stdin]\n"
sewardj97724e52005-04-02 23:40:59 +00001290" --max-stackframe=<number> assume stack switch for SP changes larger\n"
1291" than <number> bytes [2000000]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001292"\n";
njn7cf0bd32002-06-08 13:36:03 +00001293
njn25e49d8e72002-09-23 09:36:25 +00001294 Char* usage2 =
1295"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001296" debugging options for all Valgrind tools:\n"
njn25e49d8e72002-09-23 09:36:25 +00001297" --sanity-level=<number> level of sanity checking to do [1]\n"
1298" --single-step=no|yes translate each instr separately? [no]\n"
1299" --optimise=no|yes improve intermediate code? [yes]\n"
nethercote137bc552003-11-14 17:47:54 +00001300" --profile=no|yes profile? (tool must be built for it) [no]\n"
fitzhardinge462f4f92003-12-18 02:10:54 +00001301" --branchpred=yes|no generate branch prediction hints [no]\n"
sewardjfa8ec112005-01-19 11:55:34 +00001302" --trace-flags=<XXXXXXXX> show generated code? (X = 0|1) [00000000]\n"
1303" --profile-flags=<XXXXXXXX> ditto, but for profiling (X = 0|1) [00000000]\n"
sewardjc771b292004-11-30 18:55:21 +00001304" --trace-notbelow=<number> only show BBs above <number> [0]\n"
njn25e49d8e72002-09-23 09:36:25 +00001305" --trace-syscalls=no|yes show all system calls? [no]\n"
1306" --trace-signals=no|yes show signal handling details? [no]\n"
1307" --trace-symtab=no|yes show symbol table details? [no]\n"
sewardjce058b02005-05-01 08:55:38 +00001308" --trace-cfi=no|yes show call-frame-info details? [no]\n"
njn25e49d8e72002-09-23 09:36:25 +00001309" --trace-sched=no|yes show thread scheduler details? [no]\n"
jsgf855d93d2003-10-13 22:26:55 +00001310" --wait-for-gdb=yes|no pause on startup to wait for gdb attach\n"
sewardjb5f6f512005-03-10 23:59:00 +00001311#if 0
1312" --model-pthreads=yes|no model the pthreads library [no]\n"
1313#endif
1314" --command-line-only=no|yes only use command line options [no]\n"
njn613812e2005-03-11 04:57:30 +00001315"\n"
1316" --vex-iropt-verbosity 0 .. 9 [0]\n"
1317" --vex-iropt-level 0 .. 2 [2]\n"
1318" --vex-iropt-precise-memory-exns [no]\n"
sewardj8b635a42004-11-22 19:01:47 +00001319" --vex-iropt-unroll-thresh 0 .. 400 [120]\n"
1320" --vex-guest-max-insns 1 .. 100 [50]\n"
1321" --vex-guest-chase-thresh 0 .. 99 [10]\n"
1322"\n"
sewardjfa8ec112005-01-19 11:55:34 +00001323" --trace-flags and --profile-flags values (omit the middle space):\n"
sewardj2a99cf62004-11-24 10:44:19 +00001324" 1000 0000 show conversion into IR\n"
1325" 0100 0000 show after initial opt\n"
1326" 0010 0000 show after instrumentation\n"
1327" 0001 0000 show after second opt\n"
1328" 0000 1000 show after tree building\n"
1329" 0000 0100 show selecting insns\n"
1330" 0000 0010 show after reg-alloc\n"
1331" 0000 0001 show final assembly\n"
1332"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001333" debugging options for Valgrind tools that report errors\n"
1334" --dump-error=<number> show translation for basic block associated\n"
1335" with <number>'th error context [0=show none]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001336"\n";
njn3e884182003-04-15 13:03:23 +00001337
1338 Char* usage3 =
1339"\n"
nethercote71980f02004-01-24 18:18:54 +00001340" Extra options read from ~/.valgrindrc, $VALGRIND_OPTS, ./.valgrindrc\n"
njn25e49d8e72002-09-23 09:36:25 +00001341"\n"
njn53612422005-03-12 16:22:54 +00001342" Valgrind is Copyright (C) 2000-2005 Julian Seward et al.\n"
njn25e49d8e72002-09-23 09:36:25 +00001343" and licensed under the GNU General Public License, version 2.\n"
1344" Bug reports, feedback, admiration, abuse, etc, to: %s.\n"
njnd04b7c62002-10-03 14:05:52 +00001345"\n"
nethercote137bc552003-11-14 17:47:54 +00001346" Tools are copyright and licensed by their authors. See each\n"
1347" tool's start-up message for more information.\n"
njn25e49d8e72002-09-23 09:36:25 +00001348"\n";
njn7cf0bd32002-06-08 13:36:03 +00001349
njnbe9b47b2005-05-15 16:22:58 +00001350 // Ensure the message goes to stdout
1351 VG_(clo_log_fd) = 1;
1352 vg_assert( !VG_(logging_to_socket) );
1353
fitzhardinge98abfc72003-12-16 02:05:15 +00001354 VG_(printf)(usage1);
1355 if (VG_(details).name) {
1356 VG_(printf)(" user options for %s:\n", VG_(details).name);
fitzhardinge98abfc72003-12-16 02:05:15 +00001357 if (VG_(needs).command_line_options)
njn51d827b2005-05-09 01:02:08 +00001358 VG_TDICT_CALL(tool_print_usage);
fitzhardinge98abfc72003-12-16 02:05:15 +00001359 else
1360 VG_(printf)(" (none)\n");
1361 }
nethercote6c999f22004-01-31 22:55:15 +00001362 if (debug_help) {
1363 VG_(printf)(usage2);
fitzhardinge98abfc72003-12-16 02:05:15 +00001364
nethercote6c999f22004-01-31 22:55:15 +00001365 if (VG_(details).name) {
1366 VG_(printf)(" debugging options for %s:\n", VG_(details).name);
1367
1368 if (VG_(needs).command_line_options)
njn51d827b2005-05-09 01:02:08 +00001369 VG_TDICT_CALL(tool_print_debug_usage);
nethercote6c999f22004-01-31 22:55:15 +00001370 else
1371 VG_(printf)(" (none)\n");
1372 }
fitzhardinge98abfc72003-12-16 02:05:15 +00001373 }
nethercote421281e2003-11-20 16:20:55 +00001374 VG_(printf)(usage3, VG_BUGS_TO);
nethercotef4928da2004-06-15 10:54:40 +00001375 VG_(exit)(0);
njn7cf0bd32002-06-08 13:36:03 +00001376}
sewardjde4a1d02002-03-22 01:27:54 +00001377
nethercote71980f02004-01-24 18:18:54 +00001378static void pre_process_cmd_line_options
nethercote6c999f22004-01-31 22:55:15 +00001379 ( Int* need_help, const char** tool, const char** exec )
sewardj1c1b1162003-02-23 01:25:51 +00001380{
nethercote71980f02004-01-24 18:18:54 +00001381 UInt i;
sewardjde4a1d02002-03-22 01:27:54 +00001382
sewardj8b635a42004-11-22 19:01:47 +00001383 LibVEX_default_VexControl(& VG_(clo_vex_control));
1384
nethercote71980f02004-01-24 18:18:54 +00001385 /* parse the options we have (only the options we care about now) */
nethercotef6a1d502004-08-09 12:21:57 +00001386 for (i = 1; i < vg_argc; i++) {
nethercote71980f02004-01-24 18:18:54 +00001387
nethercotef6a1d502004-08-09 12:21:57 +00001388 if (strcmp(vg_argv[i], "--version") == 0) {
nethercote71980f02004-01-24 18:18:54 +00001389 printf("valgrind-" VERSION "\n");
nethercotef4928da2004-06-15 10:54:40 +00001390 exit(0);
nethercote71980f02004-01-24 18:18:54 +00001391
nethercotef6a1d502004-08-09 12:21:57 +00001392 } else if (VG_CLO_STREQ(vg_argv[i], "--help") ||
1393 VG_CLO_STREQ(vg_argv[i], "-h")) {
nethercote6c999f22004-01-31 22:55:15 +00001394 *need_help = 1;
1395
nethercotef6a1d502004-08-09 12:21:57 +00001396 } else if (VG_CLO_STREQ(vg_argv[i], "--help-debug")) {
nethercote6c999f22004-01-31 22:55:15 +00001397 *need_help = 2;
nethercote71980f02004-01-24 18:18:54 +00001398
nethercotef6c99d72004-11-09 14:35:43 +00001399 } else if (VG_CLO_STREQN(7, vg_argv[i], "--tool=")) {
nethercotef6a1d502004-08-09 12:21:57 +00001400 *tool = &vg_argv[i][7];
nethercote71980f02004-01-24 18:18:54 +00001401
nethercotef6a1d502004-08-09 12:21:57 +00001402 } else if (VG_CLO_STREQN(7, vg_argv[i], "--exec=")) {
1403 *exec = &vg_argv[i][7];
nethercote71980f02004-01-24 18:18:54 +00001404 }
1405 }
nethercote71980f02004-01-24 18:18:54 +00001406}
1407
nethercote5ee67ca2004-06-22 14:00:09 +00001408static void process_cmd_line_options( UInt* client_auxv, const char* toolname )
nethercote71980f02004-01-24 18:18:54 +00001409{
nethercotef8548672004-06-21 12:42:35 +00001410 Int i, eventually_log_fd;
nethercote71980f02004-01-24 18:18:54 +00001411 Int toolname_len = VG_(strlen)(toolname);
njnbe9b47b2005-05-15 16:22:58 +00001412 enum {
1413 VgLogTo_Fd,
1414 VgLogTo_File,
1415 VgLogTo_FileExactly,
1416 VgLogTo_Socket
1417 } log_to = VgLogTo_Fd; // Where is logging output to be sent?
sewardjde4a1d02002-03-22 01:27:54 +00001418
nethercotee1730692003-11-20 10:38:07 +00001419 /* log to stderr by default, but usage message goes to stdout */
nethercotef8548672004-06-21 12:42:35 +00001420 eventually_log_fd = 2;
sewardjde4a1d02002-03-22 01:27:54 +00001421
sewardj19d81412002-06-03 01:10:40 +00001422 /* Check for sane path in ./configure --prefix=... */
fitzhardinge98abfc72003-12-16 02:05:15 +00001423 if (VG_LIBDIR[0] != '/')
sewardj19d81412002-06-03 01:10:40 +00001424 config_error("Please use absolute paths in "
1425 "./configure --prefix=... or --libdir=...");
sewardj38170912002-05-10 21:07:22 +00001426
nethercotef6a1d502004-08-09 12:21:57 +00001427 for (i = 1; i < vg_argc; i++) {
nethercote71980f02004-01-24 18:18:54 +00001428
nethercotef6a1d502004-08-09 12:21:57 +00001429 Char* arg = vg_argv[i];
thughes3bfd5a02004-07-18 08:05:44 +00001430 Char* colon = arg;
nethercote71980f02004-01-24 18:18:54 +00001431
thughes3bfd5a02004-07-18 08:05:44 +00001432 /* Look for a colon in the switch name */
1433 while (*colon && *colon != ':' && *colon != '=')
1434 colon++;
nethercote71980f02004-01-24 18:18:54 +00001435
1436 /* Look for matching "--toolname:foo" */
thughes3bfd5a02004-07-18 08:05:44 +00001437 if (*colon == ':') {
nethercote71980f02004-01-24 18:18:54 +00001438 if (VG_CLO_STREQN(2, arg, "--") &&
1439 VG_CLO_STREQN(toolname_len, arg+2, toolname) &&
1440 VG_CLO_STREQN(1, arg+2+toolname_len, ":"))
1441 {
1442 // prefix matches, convert "--toolname:foo" to "--foo"
1443 if (0)
1444 VG_(printf)("tool-specific arg: %s\n", arg);
njn8c0b3bb2005-03-12 21:20:39 +00001445 arg = strdup(arg + toolname_len + 1);
nethercote71980f02004-01-24 18:18:54 +00001446 arg[0] = '-';
1447 arg[1] = '-';
1448
1449 } else {
1450 // prefix doesn't match, skip to next arg
1451 continue;
1452 }
1453 }
1454
fitzhardinge98abfc72003-12-16 02:05:15 +00001455 /* Ignore these options - they've already been handled */
njn45270a22005-03-27 01:00:11 +00001456 if (VG_CLO_STREQN( 7, arg, "--tool=")) goto skip_arg;
1457 if (VG_CLO_STREQN( 7, arg, "--exec=")) goto skip_arg;
1458 if (VG_CLO_STREQN(20, arg, "--command-line-only=")) goto skip_arg;
fitzhardinge98abfc72003-12-16 02:05:15 +00001459
njn45270a22005-03-27 01:00:11 +00001460 if ( VG_CLO_STREQ(arg, "--")) goto skip_arg;
nethercote27fec902004-06-16 21:26:32 +00001461
nethercote71980f02004-01-24 18:18:54 +00001462 else if (VG_CLO_STREQ(arg, "-v") ||
1463 VG_CLO_STREQ(arg, "--verbose"))
sewardjde4a1d02002-03-22 01:27:54 +00001464 VG_(clo_verbosity)++;
nethercote27fec902004-06-16 21:26:32 +00001465
nethercote71980f02004-01-24 18:18:54 +00001466 else if (VG_CLO_STREQ(arg, "-q") ||
1467 VG_CLO_STREQ(arg, "--quiet"))
sewardjde4a1d02002-03-22 01:27:54 +00001468 VG_(clo_verbosity)--;
1469
sewardj1cf558c2005-04-25 01:36:56 +00001470 else if (VG_CLO_STREQ(arg, "-d")) {
1471 /* do nothing */
1472 }
1473
sewardj71bc3cb2005-05-19 00:25:45 +00001474 else VG_BOOL_CLO(arg, "--xml", VG_(clo_xml))
njn45270a22005-03-27 01:00:11 +00001475 else VG_BOOL_CLO(arg, "--branchpred", VG_(clo_branchpred))
1476 else VG_BOOL_CLO(arg, "--db-attach", VG_(clo_db_attach))
1477 else VG_BOOL_CLO(arg, "--demangle", VG_(clo_demangle))
1478 else VG_BOOL_CLO(arg, "--error-limit", VG_(clo_error_limit))
1479 else VG_BOOL_CLO(arg, "--pointercheck", VG_(clo_pointercheck))
1480 else VG_BOOL_CLO(arg, "--support-elan3", VG_(clo_support_elan3))
1481 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
sewardj26412bd2005-07-07 10:05:05 +00001508 else if (VG_CLO_STREQ(arg, "--smc-support=none"))
1509 VG_(clo_smc_support) = Vg_SmcNone;
1510 else if (VG_CLO_STREQ(arg, "--smc-support=stack"))
1511 VG_(clo_smc_support) = Vg_SmcStack;
1512 else if (VG_CLO_STREQ(arg, "--smc-support=all"))
1513 VG_(clo_smc_support) = Vg_SmcAll;
1514
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 (;;) {
jsgff3c3f1a2003-10-14 22:13:28 +00001727 if (seq == 0)
sewardjad311162005-07-19 11:25:02 +00001728 VG_(sprintf)( logfilename, "%s%s%s.pid%d",
1729 VG_(clo_log_name),
1730 qual ? "." : "", qual ? qual : "",
1731 pid );
jsgff3c3f1a2003-10-14 22:13:28 +00001732 else
sewardjad311162005-07-19 11:25:02 +00001733 VG_(sprintf)( logfilename, "%s%s%s.pid%d.%d",
1734 VG_(clo_log_name),
1735 qual ? "." : "", qual ? qual : "",
1736 pid, seq );
jsgff3c3f1a2003-10-14 22:13:28 +00001737 seq++;
1738
njnbe9b47b2005-05-15 16:22:58 +00001739 // EXCL: it will fail with EEXIST if the file already exists.
nethercotef8548672004-06-21 12:42:35 +00001740 eventually_log_fd
jsgff3c3f1a2003-10-14 22:13:28 +00001741 = VG_(open)(logfilename,
1742 VKI_O_CREAT|VKI_O_WRONLY|VKI_O_EXCL|VKI_O_TRUNC,
1743 VKI_S_IRUSR|VKI_S_IWUSR);
nethercotef8548672004-06-21 12:42:35 +00001744 if (eventually_log_fd >= 0) {
1745 VG_(clo_log_fd) = VG_(safe_fd)(eventually_log_fd);
sewardj603d4102005-01-11 14:01:02 +00001746 break; /* for (;;) */
jsgff3c3f1a2003-10-14 22:13:28 +00001747 } else {
njnbe9b47b2005-05-15 16:22:58 +00001748 // If the file already existed, we try the next name. If it
1749 // was some other file error, we give up.
nethercotef8548672004-06-21 12:42:35 +00001750 if (eventually_log_fd != -VKI_EEXIST) {
jsgff3c3f1a2003-10-14 22:13:28 +00001751 VG_(message)(Vg_UserMsg,
njn02bc4b82005-05-15 17:28:26 +00001752 "Can't create/open log file '%s.pid%d'; giving up!",
nethercotef8548672004-06-21 12:42:35 +00001753 VG_(clo_log_name), pid);
jsgff3c3f1a2003-10-14 22:13:28 +00001754 VG_(bad_option)(
sewardj603d4102005-01-11 14:01:02 +00001755 "--log-file=<file> (didn't work out for some reason.)");
njnbe9b47b2005-05-15 16:22:58 +00001756 /*NOTREACHED*/
jsgff3c3f1a2003-10-14 22:13:28 +00001757 }
1758 }
1759 }
sewardj603d4102005-01-11 14:01:02 +00001760 break; /* switch (VG_(clo_log_to)) */
1761 }
1762
1763 case VgLogTo_FileExactly: {
sewardj603d4102005-01-11 14:01:02 +00001764 vg_assert(VG_(clo_log_name) != NULL);
1765 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
sewardj603d4102005-01-11 14:01:02 +00001766
1767 eventually_log_fd
njnbe9b47b2005-05-15 16:22:58 +00001768 = VG_(open)(VG_(clo_log_name),
sewardj603d4102005-01-11 14:01:02 +00001769 VKI_O_CREAT|VKI_O_WRONLY|VKI_O_TRUNC,
1770 VKI_S_IRUSR|VKI_S_IWUSR);
1771 if (eventually_log_fd >= 0) {
1772 VG_(clo_log_fd) = VG_(safe_fd)(eventually_log_fd);
njnbe9b47b2005-05-15 16:22:58 +00001773 } else {
sewardj603d4102005-01-11 14:01:02 +00001774 VG_(message)(Vg_UserMsg,
njn02bc4b82005-05-15 17:28:26 +00001775 "Can't create/open log file '%s'; giving up!",
sewardj603d4102005-01-11 14:01:02 +00001776 VG_(clo_log_name));
1777 VG_(bad_option)(
1778 "--log-file-exactly=<file> (didn't work out for some reason.)");
1779 /*NOTREACHED*/
1780 }
1781 break; /* switch (VG_(clo_log_to)) */
sewardj73cf3bc2002-11-03 03:20:15 +00001782 }
1783
1784 case VgLogTo_Socket: {
nethercotef8548672004-06-21 12:42:35 +00001785 vg_assert(VG_(clo_log_name) != NULL);
1786 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
1787 eventually_log_fd = VG_(connect_via_socket)( VG_(clo_log_name) );
1788 if (eventually_log_fd == -1) {
sewardj73cf3bc2002-11-03 03:20:15 +00001789 VG_(message)(Vg_UserMsg,
nethercotef8548672004-06-21 12:42:35 +00001790 "Invalid --log-socket=ipaddr or --log-socket=ipaddr:port spec");
sewardj73cf3bc2002-11-03 03:20:15 +00001791 VG_(message)(Vg_UserMsg,
njn02bc4b82005-05-15 17:28:26 +00001792 "of '%s'; giving up!", VG_(clo_log_name) );
sewardj73cf3bc2002-11-03 03:20:15 +00001793 VG_(bad_option)(
nethercotef8548672004-06-21 12:42:35 +00001794 "--log-socket=");
njnbe9b47b2005-05-15 16:22:58 +00001795 /*NOTREACHED*/
sewardj4cf05692002-10-27 20:28:29 +00001796 }
nethercotef8548672004-06-21 12:42:35 +00001797 if (eventually_log_fd == -2) {
sewardj73cf3bc2002-11-03 03:20:15 +00001798 VG_(message)(Vg_UserMsg,
njn02bc4b82005-05-15 17:28:26 +00001799 "valgrind: failed to connect to logging server '%s'.",
nethercotef8548672004-06-21 12:42:35 +00001800 VG_(clo_log_name) );
sewardj570f8902002-11-03 11:44:36 +00001801 VG_(message)(Vg_UserMsg,
1802 "Log messages will sent to stderr instead." );
1803 VG_(message)(Vg_UserMsg,
1804 "" );
1805 /* We don't change anything here. */
njnbe9b47b2005-05-15 16:22:58 +00001806 vg_assert(VG_(clo_log_fd) == 2);
sewardj570f8902002-11-03 11:44:36 +00001807 } else {
nethercotef8548672004-06-21 12:42:35 +00001808 vg_assert(eventually_log_fd > 0);
1809 VG_(clo_log_fd) = eventually_log_fd;
njnbe9b47b2005-05-15 16:22:58 +00001810 VG_(logging_to_socket) = True;
sewardj570f8902002-11-03 11:44:36 +00001811 }
sewardj73cf3bc2002-11-03 03:20:15 +00001812 break;
1813 }
sewardj4cf05692002-10-27 20:28:29 +00001814 }
1815
sewardj71bc3cb2005-05-19 00:25:45 +00001816
1817 /* Check that the requested tool actually supports XML output. */
cerion39655202005-07-13 14:18:24 +00001818 if (VG_(clo_xml) && 0 != VG_(strcmp)(toolname, "memcheck")
1819 && 0 != VG_(strcmp)(toolname, "none")) {
sewardj71bc3cb2005-05-19 00:25:45 +00001820 VG_(clo_xml) = False;
1821 VG_(message)(Vg_UserMsg,
cerion39655202005-07-13 14:18:24 +00001822 "Currently only Memcheck|None supports XML output.");
sewardj71bc3cb2005-05-19 00:25:45 +00001823 VG_(bad_option)("--xml=yes");
1824 /*NOTREACHED*/
1825 }
1826
njnbe9b47b2005-05-15 16:22:58 +00001827 // Move log_fd into the safe range, so it doesn't conflict with any app fds.
1828 // XXX: this is more or less duplicating the behaviour of the calls to
1829 // VG_(safe_fd)() above, although this does not close the original fd.
1830 // Perhaps the VG_(safe_fd)() calls above should be removed, and this
1831 // code should be replaced with a call to VG_(safe_fd)(). --njn
thughesad1c9562004-06-26 11:27:52 +00001832 eventually_log_fd = VG_(fcntl)(VG_(clo_log_fd), VKI_F_DUPFD, VG_(fd_hard_limit));
nethercotef8548672004-06-21 12:42:35 +00001833 if (eventually_log_fd < 0)
jsgf855d93d2003-10-13 22:26:55 +00001834 VG_(message)(Vg_UserMsg, "valgrind: failed to move logfile fd into safe range");
1835 else {
nethercotef8548672004-06-21 12:42:35 +00001836 VG_(clo_log_fd) = eventually_log_fd;
1837 VG_(fcntl)(VG_(clo_log_fd), VKI_F_SETFD, VKI_FD_CLOEXEC);
jsgf855d93d2003-10-13 22:26:55 +00001838 }
1839
sewardj4cf05692002-10-27 20:28:29 +00001840 /* Ok, the logging sink is running now. Print a suitable preamble.
1841 If logging to file or a socket, write details of parent PID and
1842 command line args, to help people trying to interpret the
1843 results of a run which encompasses multiple processes. */
sewardjde4a1d02002-03-22 01:27:54 +00001844
sewardj71bc3cb2005-05-19 00:25:45 +00001845 if (VG_(clo_xml)) {
sewardj8665d8e2005-06-01 17:35:23 +00001846 VG_(message)(Vg_UserMsg, "<?xml version=\"1.0\"?>");
1847 VG_(message)(Vg_UserMsg, "");
sewardj71bc3cb2005-05-19 00:25:45 +00001848 VG_(message)(Vg_UserMsg, "<valgrindoutput>");
1849 VG_(message)(Vg_UserMsg, "");
1850 VG_(message)(Vg_UserMsg, "<protocolversion>1</protocolversion>");
1851 VG_(message)(Vg_UserMsg, "");
1852 }
1853
sewardjd7bddad2005-06-13 16:48:32 +00001854 HChar* xpre = VG_(clo_xml) ? " <line>" : "";
1855 HChar* xpost = VG_(clo_xml) ? "</line>" : "";
sewardj71bc3cb2005-05-19 00:25:45 +00001856
sewardj83adf412002-05-01 01:25:45 +00001857 if (VG_(clo_verbosity > 0)) {
sewardjd7bddad2005-06-13 16:48:32 +00001858
1859 if (VG_(clo_xml))
1860 VG_(message)(Vg_UserMsg, "<preamble>");
1861
nethercote996901a2004-08-03 13:29:09 +00001862 /* Tool details */
sewardj71bc3cb2005-05-19 00:25:45 +00001863 VG_(message)(Vg_UserMsg, "%s%s%s%s, %s.%s",
1864 xpre,
njnd04b7c62002-10-03 14:05:52 +00001865 VG_(details).name,
njnb9c427c2004-12-01 14:14:42 +00001866 NULL == VG_(details).version ? "" : "-",
njnd04b7c62002-10-03 14:05:52 +00001867 NULL == VG_(details).version
1868 ? (Char*)"" : VG_(details).version,
sewardj71bc3cb2005-05-19 00:25:45 +00001869 VG_(details).description,
1870 xpost);
1871 VG_(message)(Vg_UserMsg, "%s%s%s",
1872 xpre, VG_(details).copyright_author, xpost);
sewardj3b2736a2002-03-24 12:18:35 +00001873
njnd04b7c62002-10-03 14:05:52 +00001874 /* Core details */
1875 VG_(message)(Vg_UserMsg,
sewardj71bc3cb2005-05-19 00:25:45 +00001876 "%sUsing LibVEX rev %s, a library for dynamic binary translation.%s",
1877 xpre, LibVEX_Version(), xpost );
sewardjc7025332004-12-13 18:30:39 +00001878 VG_(message)(Vg_UserMsg,
sewardj71bc3cb2005-05-19 00:25:45 +00001879 "%sCopyright (C) 2004-2005, and GNU GPL'd, by OpenWorks LLP.%s",
1880 xpre, xpost );
sewardjc7025332004-12-13 18:30:39 +00001881 VG_(message)(Vg_UserMsg,
sewardj71bc3cb2005-05-19 00:25:45 +00001882 "%sUsing valgrind-%s, a dynamic binary instrumentation framework.%s",
1883 xpre, VERSION, xpost);
sewardjde4a1d02002-03-22 01:27:54 +00001884 VG_(message)(Vg_UserMsg,
sewardj71bc3cb2005-05-19 00:25:45 +00001885 "%sCopyright (C) 2000-2005, and GNU GPL'd, by Julian Seward et al.%s",
1886 xpre, xpost );
sewardjd7bddad2005-06-13 16:48:32 +00001887
1888 if (VG_(clo_xml))
1889 VG_(message)(Vg_UserMsg, "</preamble>");
njnd04b7c62002-10-03 14:05:52 +00001890 }
1891
sewardjd94b90a2005-06-29 23:15:56 +00001892 if (!VG_(clo_xml) && VG_(clo_verbosity) > 0 && log_to != VgLogTo_Fd) {
sewardj4cf05692002-10-27 20:28:29 +00001893 VG_(message)(Vg_UserMsg, "");
1894 VG_(message)(Vg_UserMsg,
1895 "My PID = %d, parent PID = %d. Prog and args are:",
1896 VG_(getpid)(), VG_(getppid)() );
1897 for (i = 0; i < VG_(client_argc); i++)
1898 VG_(message)(Vg_UserMsg, " %s", VG_(client_argv)[i]);
1899 }
sewardj71bc3cb2005-05-19 00:25:45 +00001900 else
1901 if (VG_(clo_xml)) {
1902 VG_(message)(Vg_UserMsg, "");
1903 VG_(message)(Vg_UserMsg, "<pid>%d</pid>", VG_(getpid)());
1904 VG_(message)(Vg_UserMsg, "<ppid>%d</ppid>", VG_(getppid)());
sewardj97f7e0c2005-07-19 15:00:25 +00001905 VG_(message)(Vg_UserMsg, "<tool>%t</tool>", toolname);
sewardjad311162005-07-19 11:25:02 +00001906 if (VG_(clo_log_file_qualifier)) {
1907 HChar* val = VG_(getenv)(VG_(clo_log_file_qualifier));
sewardj97f7e0c2005-07-19 15:00:25 +00001908 VG_(message)(Vg_UserMsg, "<logfilequalifier> <var>%t</var> "
1909 "<value>%t</value> </logfilequalifier>",
sewardjad311162005-07-19 11:25:02 +00001910 VG_(clo_log_file_qualifier),
1911 val ? val : "");
1912 }
sewardj768db0e2005-07-19 14:18:56 +00001913 if (VG_(clo_xml_user_comment)) {
1914 /* Note: the user comment itself is XML and is therefore to
1915 be passed through verbatim (%s) rather than escaped
1916 (%t). */
1917 VG_(message)(Vg_UserMsg, "<usercomment>%s</usercomment>",
1918 VG_(clo_xml_user_comment));
1919 }
sewardj71bc3cb2005-05-19 00:25:45 +00001920 VG_(message)(Vg_UserMsg, "");
sewardjb8a3dac2005-07-19 12:39:11 +00001921 VG_(message)(Vg_UserMsg, "<args>");
1922 VG_(message)(Vg_UserMsg, " <vargv>");
1923 for (i = 0; i < vg_argc; i++) {
1924 HChar* tag = i==0 ? "exe" : "arg";
sewardj768db0e2005-07-19 14:18:56 +00001925 VG_(message)(Vg_UserMsg, " <%s>%t</%s>",
sewardjb8a3dac2005-07-19 12:39:11 +00001926 tag, vg_argv[i], tag);
1927 }
1928 VG_(message)(Vg_UserMsg, " </vargv>");
1929 VG_(message)(Vg_UserMsg, " <argv>");
sewardj8665d8e2005-06-01 17:35:23 +00001930 for (i = 0; i < VG_(client_argc); i++) {
1931 HChar* tag = i==0 ? "exe" : "arg";
sewardj97f7e0c2005-07-19 15:00:25 +00001932 VG_(message)(Vg_UserMsg, " <%s>%t</%s>",
sewardj8665d8e2005-06-01 17:35:23 +00001933 tag, VG_(client_argv)[i], tag);
1934 }
sewardjb8a3dac2005-07-19 12:39:11 +00001935 VG_(message)(Vg_UserMsg, " </argv>");
1936 VG_(message)(Vg_UserMsg, "</args>");
sewardj71bc3cb2005-05-19 00:25:45 +00001937 }
sewardj4cf05692002-10-27 20:28:29 +00001938
sewardjde4a1d02002-03-22 01:27:54 +00001939 if (VG_(clo_verbosity) > 1) {
nethercotea70f7352004-04-18 12:08:46 +00001940 Int fd;
njnbe9b47b2005-05-15 16:22:58 +00001941 if (log_to != VgLogTo_Fd)
njn1fd5eb22005-03-13 05:43:23 +00001942 VG_(message)(Vg_DebugMsg, "");
1943 VG_(message)(Vg_DebugMsg, "Valgrind library directory: %s", VG_(libdir));
1944 VG_(message)(Vg_DebugMsg, "Command line");
njn86dc2bc2003-09-09 07:26:21 +00001945 for (i = 0; i < VG_(client_argc); i++)
njn1fd5eb22005-03-13 05:43:23 +00001946 VG_(message)(Vg_DebugMsg, " %s", VG_(client_argv)[i]);
njn86dc2bc2003-09-09 07:26:21 +00001947
njn1fd5eb22005-03-13 05:43:23 +00001948 VG_(message)(Vg_DebugMsg, "Startup, with flags:");
nethercotef6a1d502004-08-09 12:21:57 +00001949 for (i = 1; i < vg_argc; i++) {
njn1fd5eb22005-03-13 05:43:23 +00001950 VG_(message)(Vg_DebugMsg, " %s", vg_argv[i]);
sewardjde4a1d02002-03-22 01:27:54 +00001951 }
nethercotea70f7352004-04-18 12:08:46 +00001952
njn1fd5eb22005-03-13 05:43:23 +00001953 VG_(message)(Vg_DebugMsg, "Contents of /proc/version:");
nethercotea70f7352004-04-18 12:08:46 +00001954 fd = VG_(open) ( "/proc/version", VKI_O_RDONLY, 0 );
1955 if (fd < 0) {
njn1fd5eb22005-03-13 05:43:23 +00001956 VG_(message)(Vg_DebugMsg, " can't open /proc/version");
nethercotea70f7352004-04-18 12:08:46 +00001957 } else {
sewardj71bc3cb2005-05-19 00:25:45 +00001958# define BUF_LEN 256
nethercotea70f7352004-04-18 12:08:46 +00001959 Char version_buf[BUF_LEN];
1960 Int n = VG_(read) ( fd, version_buf, BUF_LEN );
njnbe9b47b2005-05-15 16:22:58 +00001961 vg_assert(n <= BUF_LEN);
nethercotea70f7352004-04-18 12:08:46 +00001962 if (n > 0) {
1963 version_buf[n-1] = '\0';
njn1fd5eb22005-03-13 05:43:23 +00001964 VG_(message)(Vg_DebugMsg, " %s", version_buf);
nethercotea70f7352004-04-18 12:08:46 +00001965 } else {
njn1fd5eb22005-03-13 05:43:23 +00001966 VG_(message)(Vg_DebugMsg, " (empty?)");
nethercotea70f7352004-04-18 12:08:46 +00001967 }
1968 VG_(close)(fd);
sewardj71bc3cb2005-05-19 00:25:45 +00001969# undef BUF_LEN
nethercotea70f7352004-04-18 12:08:46 +00001970 }
sewardjde4a1d02002-03-22 01:27:54 +00001971 }
1972
fitzhardinge98abfc72003-12-16 02:05:15 +00001973 if (VG_(clo_n_suppressions) < VG_CLO_MAX_SFILES-1 &&
njn95ec8702004-11-22 16:46:13 +00001974 (VG_(needs).core_errors || VG_(needs).tool_errors)) {
njn842c26e2005-06-28 02:54:52 +00001975 /* If we haven't reached the max number of suppressions, load
1976 the default one. */
fitzhardinge98abfc72003-12-16 02:05:15 +00001977 static const Char default_supp[] = "default.supp";
1978 Int len = VG_(strlen)(VG_(libdir)) + 1 + sizeof(default_supp);
1979 Char *buf = VG_(arena_malloc)(VG_AR_CORE, len);
1980 VG_(sprintf)(buf, "%s/%s", VG_(libdir), default_supp);
1981 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = buf;
1982 VG_(clo_n_suppressions)++;
sewardjde4a1d02002-03-22 01:27:54 +00001983 }
1984}
1985
nethercotef6a1d502004-08-09 12:21:57 +00001986// Build the string for VALGRINDCLO.
1987Char* VG_(build_child_VALGRINDCLO)( Char* exename )
1988{
1989 /* If we're tracing the children, then we need to start it
1990 with our starter+arguments, which are copied into VALGRINDCLO,
1991 except the --exec= option is changed if present.
1992 */
1993 Int i;
1994 Char *exec;
1995 Char *cp;
1996 Char *optvar;
1997 Int optlen, execlen;
1998
1999 // All these allocated blocks are not free - because we're either
2000 // going to exec, or panic when we fail.
2001
2002 // Create --exec= option: "--exec=<exename>"
2003 exec = VG_(arena_malloc)(VG_AR_CORE,
2004 VG_(strlen)( exename ) + 7/*--exec=*/ + 1/*\0*/);
2005 vg_assert(NULL != exec);
2006 VG_(sprintf)(exec, "--exec=%s", exename);
2007
2008 // Allocate space for optvar (may overestimate by counting --exec twice,
2009 // no matter)
2010 optlen = 1;
2011 for (i = 0; i < vg_argc; i++)
2012 optlen += VG_(strlen)(vg_argv[i]) + 1;
2013 optlen += VG_(strlen)(exec)+1;
2014 optvar = VG_(arena_malloc)(VG_AR_CORE, optlen);
2015
2016 // Copy all valgrind args except the old --exec (if present)
2017 // VG_CLO_SEP is the separator.
2018 cp = optvar;
2019 for (i = 1; i < vg_argc; i++) {
2020 Char *arg = vg_argv[i];
2021
2022 if (VG_(memcmp)(arg, "--exec=", 7) == 0) {
2023 // don't copy existing --exec= arg
2024 } else if (VG_(strcmp)(arg, "--") == 0) {
2025 // stop at "--"
2026 break;
2027 } else {
2028 // copy non "--exec" arg
2029 Int len = VG_(strlen)(arg);
2030 VG_(memcpy)(cp, arg, len);
2031 cp += len;
2032 *cp++ = VG_CLO_SEP;
2033 }
2034 }
2035 // Add the new --exec= option
2036 execlen = VG_(strlen)(exec);
2037 VG_(memcpy)(cp, exec, execlen);
2038 cp += execlen;
2039 *cp++ = VG_CLO_SEP;
2040
2041 *cp = '\0';
2042
2043 return optvar;
2044}
2045
2046// Build "/proc/self/fd/<execfd>".
2047Char* VG_(build_child_exename)( void )
2048{
2049 Char* exename = VG_(arena_malloc)(VG_AR_CORE, 64);
2050 vg_assert(NULL != exename);
2051 VG_(sprintf)(exename, "/proc/self/fd/%d", vgexecfd);
2052 return exename;
2053}
2054
sewardjde4a1d02002-03-22 01:27:54 +00002055
nethercote71980f02004-01-24 18:18:54 +00002056/*====================================================================*/
2057/*=== File descriptor setup ===*/
2058/*====================================================================*/
2059
2060static void setup_file_descriptors(void)
2061{
2062 struct vki_rlimit rl;
2063
2064 /* Get the current file descriptor limits. */
2065 if (VG_(getrlimit)(VKI_RLIMIT_NOFILE, &rl) < 0) {
2066 rl.rlim_cur = 1024;
2067 rl.rlim_max = 1024;
2068 }
2069
2070 /* Work out where to move the soft limit to. */
njn14319cc2005-03-13 06:26:22 +00002071 if (rl.rlim_cur + N_RESERVED_FDS <= rl.rlim_max) {
2072 rl.rlim_cur = rl.rlim_cur + N_RESERVED_FDS;
nethercote71980f02004-01-24 18:18:54 +00002073 } else {
2074 rl.rlim_cur = rl.rlim_max;
2075 }
2076
2077 /* Reserve some file descriptors for our use. */
njn14319cc2005-03-13 06:26:22 +00002078 VG_(fd_soft_limit) = rl.rlim_cur - N_RESERVED_FDS;
2079 VG_(fd_hard_limit) = rl.rlim_cur - N_RESERVED_FDS;
nethercote71980f02004-01-24 18:18:54 +00002080
2081 /* Update the soft limit. */
2082 VG_(setrlimit)(VKI_RLIMIT_NOFILE, &rl);
2083
nethercotef6a1d502004-08-09 12:21:57 +00002084 if (vgexecfd != -1)
2085 vgexecfd = VG_(safe_fd)( vgexecfd );
nethercote71980f02004-01-24 18:18:54 +00002086 if (VG_(clexecfd) != -1)
2087 VG_(clexecfd) = VG_(safe_fd)( VG_(clexecfd) );
2088}
2089
nethercote71980f02004-01-24 18:18:54 +00002090/*====================================================================*/
nethercote71980f02004-01-24 18:18:54 +00002091/*=== Initialise program data/text, etc. ===*/
2092/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +00002093
sewardjb5f6f512005-03-10 23:59:00 +00002094static void build_valgrind_map_callback ( Addr start, SizeT size, UInt prot,
2095 UInt dev, UInt ino, ULong foffset,
2096 const UChar* filename )
sewardjde4a1d02002-03-22 01:27:54 +00002097{
nethercote71980f02004-01-24 18:18:54 +00002098 /* Only record valgrind mappings for now, without loading any
2099 symbols. This is so we know where the free space is before we
2100 start allocating more memory (note: heap is OK, it's just mmap
2101 which is the problem here). */
sewardjb5f6f512005-03-10 23:59:00 +00002102 if (start >= VG_(client_end) && start < VG_(valgrind_last)) {
sewardj8c615892005-04-25 02:38:28 +00002103 VG_(debugLog)(2, "main",
2104 "valgrind-seg: %p-%p prot 0x%x file=%s\n",
njna4469a72005-05-08 02:06:33 +00002105 (void*)start, (void*)(start+size), prot, filename);
sewardjb5f6f512005-03-10 23:59:00 +00002106 VG_(map_file_segment)(start, size, prot,
sewardj8c615892005-04-25 02:38:28 +00002107 SF_MMAP|SF_NOSYMS|SF_VALGRIND,
2108 dev, ino, foffset, filename);
sewardjb5f6f512005-03-10 23:59:00 +00002109 /* update VG_(valgrind_last) if it looks wrong */
2110 if (start+size > VG_(valgrind_last))
sewardj8c615892005-04-25 02:38:28 +00002111 VG_(valgrind_last) = start+size-1;
nethercote71980f02004-01-24 18:18:54 +00002112 }
sewardjde4a1d02002-03-22 01:27:54 +00002113}
2114
nethercote71980f02004-01-24 18:18:54 +00002115// Global var used to pass local data to callback
nethercote4ad74312004-10-26 09:59:49 +00002116Addr sp_at_startup___global_arg = 0;
sewardjde4a1d02002-03-22 01:27:54 +00002117
sewardjb5f6f512005-03-10 23:59:00 +00002118/*
2119 This second pass adds in client mappings, and loads symbol tables
2120 for all interesting mappings. The trouble is that things can
2121 change as we go, because we're calling the Tool to track memory as
2122 we find it.
2123
2124 So for Valgrind mappings, we don't replace any mappings which
2125 aren't still identical (which will include the .so mappings, so we
2126 will load their symtabs)>
2127 */
2128static void build_segment_map_callback ( Addr start, SizeT size, UInt prot,
2129 UInt dev, UInt ino, ULong foffset,
2130 const UChar* filename )
sewardj45b672d2003-07-25 19:58:11 +00002131{
nethercote71980f02004-01-24 18:18:54 +00002132 UInt flags;
2133 Bool is_stack_segment;
2134 Addr r_esp;
sewardj45b672d2003-07-25 19:58:11 +00002135
nethercote71980f02004-01-24 18:18:54 +00002136 is_stack_segment
2137 = (start == VG_(clstk_base) && (start+size) == VG_(clstk_end));
fitzhardinge98abfc72003-12-16 02:05:15 +00002138
sewardj8c615892005-04-25 02:38:28 +00002139 VG_(debugLog)(2, "main",
2140 "any-seg: %p-%p prot 0x%x stack=%d file=%s\n",
njna4469a72005-05-08 02:06:33 +00002141 (void*)start, (void*)(start+size), prot, is_stack_segment,
2142 filename);
fitzhardinge98abfc72003-12-16 02:05:15 +00002143
nethercote71980f02004-01-24 18:18:54 +00002144 if (is_stack_segment)
2145 flags = SF_STACK | SF_GROWDOWN;
2146 else
njn0ae787c2005-06-28 22:14:53 +00002147 flags = SF_MMAP;
fitzhardinge98abfc72003-12-16 02:05:15 +00002148
nethercote71980f02004-01-24 18:18:54 +00002149 if (filename != NULL)
2150 flags |= SF_FILE;
fitzhardinge98abfc72003-12-16 02:05:15 +00002151
sewardjb5f6f512005-03-10 23:59:00 +00002152#if 0
2153 // This needs to be fixed properly. jrs 20050307
2154 if (start >= VG_(client_end) && start < VG_(valgrind_last)) {
2155 Segment *s = VG_(find_segment_before)(start);
fitzhardinge98abfc72003-12-16 02:05:15 +00002156
sewardjb5f6f512005-03-10 23:59:00 +00002157 /* We have to be a bit careful about inserting new mappings into
2158 the Valgrind part of the address space. We're actively
2159 changing things as we parse these mappings, particularly in
2160 shadow memory, and so we don't want to overwrite those
2161 changes. Therefore, we only insert/update a mapping if it is
2162 mapped from a file or it exactly matches an existing mapping.
fitzhardinge98abfc72003-12-16 02:05:15 +00002163
sewardjb5f6f512005-03-10 23:59:00 +00002164 NOTE: we're only talking about the Segment list mapping
2165 metadata; this doesn't actually mmap anything more. */
2166 if (filename || (s && s->addr == start && s->len == size)) {
2167 flags |= SF_VALGRIND;
2168 VG_(map_file_segment)(start, size, prot, flags, dev, ino, foffset, filename);
2169 } else {
2170 /* assert range is already mapped */
2171 vg_assert(VG_(is_addressable)(start, size, VKI_PROT_NONE));
2172 }
2173 } else
2174#endif
2175 VG_(map_file_segment)(start, size, prot, flags, dev, ino, foffset, filename);
2176
2177 if (VG_(is_client_addr)(start) && VG_(is_client_addr)(start+size-1)) {
2178 VG_TRACK( new_mem_startup, start, size,
2179 !!(prot & VKI_PROT_READ),
2180 !!(prot & VKI_PROT_WRITE),
2181 !!(prot & VKI_PROT_EXEC));
2182 }
sewardj3e1eb1f2002-05-18 13:14:17 +00002183
nethercote71980f02004-01-24 18:18:54 +00002184 /* If this is the stack segment mark all below %esp as noaccess. */
nethercote4ad74312004-10-26 09:59:49 +00002185 r_esp = sp_at_startup___global_arg;
nethercote71980f02004-01-24 18:18:54 +00002186 vg_assert(0 != r_esp);
2187 if (is_stack_segment) {
sewardjb5f6f512005-03-10 23:59:00 +00002188 if (0) {
2189 VG_(message)(Vg_DebugMsg, "invalidating stack area: %p .. %p",
nethercote71980f02004-01-24 18:18:54 +00002190 start,r_esp);
sewardjb5f6f512005-03-10 23:59:00 +00002191 VG_(message)(Vg_DebugMsg, " validating stack area: %p .. %p",
2192 r_esp, start+size);
2193 }
nethercote71980f02004-01-24 18:18:54 +00002194 VG_TRACK( die_mem_stack, start, r_esp-start );
sewardjb5f6f512005-03-10 23:59:00 +00002195 // what's this for?
2196 //VG_TRACK( post_mem_write, r_esp, (start+size)-r_esp );
sewardjde4a1d02002-03-22 01:27:54 +00002197 }
sewardjde4a1d02002-03-22 01:27:54 +00002198}
2199
njn2da73352005-06-18 01:35:16 +00002200/*====================================================================*/
2201/*=== Initialise the first thread. ===*/
2202/*====================================================================*/
2203
2204/* Given a pointer to the ThreadArchState for thread 1 (the root
2205 thread), initialise the VEX guest state, and copy in essential
2206 starting values.
2207*/
2208static void init_thread1state ( Addr client_ip,
2209 Addr sp_at_startup,
2210 /*inout*/ ThreadArchState* arch )
2211{
2212#if defined(VGA_x86)
2213 vg_assert(0 == sizeof(VexGuestX86State) % 8);
2214
2215 /* Zero out the initial state, and set up the simulated FPU in a
2216 sane way. */
2217 LibVEX_GuestX86_initialise(&arch->vex);
2218
2219 /* Zero out the shadow area. */
2220 VG_(memset)(&arch->vex_shadow, 0, sizeof(VexGuestX86State));
2221
2222 /* Put essential stuff into the new state. */
2223 arch->vex.guest_ESP = sp_at_startup;
2224 arch->vex.guest_EIP = client_ip;
2225
2226 /* initialise %cs, %ds and %ss to point at the operating systems
2227 default code, data and stack segments */
2228 asm volatile("movw %%cs, %0" : : "m" (arch->vex.guest_CS));
2229 asm volatile("movw %%ds, %0" : : "m" (arch->vex.guest_DS));
2230 asm volatile("movw %%ss, %0" : : "m" (arch->vex.guest_SS));
cerion85665ca2005-06-20 15:51:07 +00002231
njn2da73352005-06-18 01:35:16 +00002232#elif defined(VGA_amd64)
2233 vg_assert(0 == sizeof(VexGuestAMD64State) % 8);
2234
2235 /* Zero out the initial state, and set up the simulated FPU in a
2236 sane way. */
2237 LibVEX_GuestAMD64_initialise(&arch->vex);
2238
2239 /* Zero out the shadow area. */
2240 VG_(memset)(&arch->vex_shadow, 0, sizeof(VexGuestAMD64State));
2241
2242 /* Put essential stuff into the new state. */
2243 arch->vex.guest_RSP = sp_at_startup;
2244 arch->vex.guest_RIP = client_ip;
cerion85665ca2005-06-20 15:51:07 +00002245
2246#elif defined(VGA_ppc32)
2247 vg_assert(0 == sizeof(VexGuestPPC32State) % 8);
2248
2249 /* Zero out the initial state, and set up the simulated FPU in a
2250 sane way. */
2251 LibVEX_GuestPPC32_initialise(&arch->vex);
2252
2253 /* Zero out the shadow area. */
2254 VG_(memset)(&arch->vex_shadow, 0, sizeof(VexGuestPPC32State));
2255
2256 /* Put essential stuff into the new state. */
2257 arch->vex.guest_GPR1 = sp_at_startup;
2258 arch->vex.guest_CIA = client_ip;
2259
njn2da73352005-06-18 01:35:16 +00002260#else
2261# error Unknown arch
2262#endif
2263 // Tell the tool that we just wrote to the registers.
2264 VG_TRACK( post_reg_write, Vg_CoreStartup, /*tid*/1, /*offset*/0,
2265 sizeof(VexGuestArchState));
2266}
2267
sewardjde4a1d02002-03-22 01:27:54 +00002268
nethercote71980f02004-01-24 18:18:54 +00002269/*====================================================================*/
njn2025cf92005-06-26 20:44:48 +00002270/*=== BB profiling ===*/
2271/*====================================================================*/
2272
2273static
2274void show_BB_profile ( BBProfEntry tops[], UInt n_tops, ULong score_total )
2275{
2276 ULong score_cumul, score_here;
2277 Char buf_cumul[10], buf_here[10];
2278 Char name[64];
2279 Int r;
2280
2281 VG_(printf)("\n");
2282 VG_(printf)("-----------------------------------------------------------\n");
2283 VG_(printf)("--- BEGIN BB Profile (summary of scores) ---\n");
2284 VG_(printf)("-----------------------------------------------------------\n");
2285 VG_(printf)("\n");
2286
2287 VG_(printf)("Total score = %lld\n\n", score_total);
2288
2289 score_cumul = 0;
2290 for (r = 0; r < n_tops; r++) {
2291 if (tops[r].addr == 0)
2292 continue;
2293 name[0] = 0;
2294 VG_(get_fnname_w_offset)(tops[r].addr, name, 64);
2295 name[63] = 0;
2296 score_here = tops[r].score;
2297 score_cumul += score_here;
2298 VG_(percentify)(score_cumul, score_total, 2, 6, buf_cumul);
2299 VG_(percentify)(score_here, score_total, 2, 6, buf_here);
2300 VG_(printf)("%3d: (%9lld %s) %9lld %s 0x%llx %s\n",
2301 r,
2302 score_cumul, buf_cumul,
2303 score_here, buf_here, tops[r].addr, name );
2304 }
2305
2306 VG_(printf)("\n");
2307 VG_(printf)("-----------------------------------------------------------\n");
2308 VG_(printf)("--- BB Profile (BB details) ---\n");
2309 VG_(printf)("-----------------------------------------------------------\n");
2310 VG_(printf)("\n");
2311
2312 score_cumul = 0;
2313 for (r = 0; r < n_tops; r++) {
2314 if (tops[r].addr == 0)
2315 continue;
2316 name[0] = 0;
2317 VG_(get_fnname_w_offset)(tops[r].addr, name, 64);
2318 name[63] = 0;
2319 score_here = tops[r].score;
2320 score_cumul += score_here;
2321 VG_(percentify)(score_cumul, score_total, 2, 6, buf_cumul);
2322 VG_(percentify)(score_here, score_total, 2, 6, buf_here);
2323 VG_(printf)("\n");
2324 VG_(printf)("=-=-=-=-=-=-=-=-=-=-=-=-=-= begin BB rank %d "
2325 "=-=-=-=-=-=-=-=-=-=-=-=-=-=\n\n", r);
2326 VG_(printf)("%3d: (%9lld %s) %9lld %s 0x%llx %s\n",
2327 r,
2328 score_cumul, buf_cumul,
2329 score_here, buf_here, tops[r].addr, name );
2330 VG_(printf)("\n");
2331 VG_(translate)(0, tops[r].addr, True, VG_(clo_profile_flags), 0);
2332 VG_(printf)("=-=-=-=-=-=-=-=-=-=-=-=-=-= end BB rank %d "
2333 "=-=-=-=-=-=-=-=-=-=-=-=-=-=\n\n", r);
2334 }
2335
2336 VG_(printf)("\n");
2337 VG_(printf)("-----------------------------------------------------------\n");
2338 VG_(printf)("--- END BB Profile ---\n");
2339 VG_(printf)("-----------------------------------------------------------\n");
2340 VG_(printf)("\n");
2341}
2342
2343
2344/*====================================================================*/
nethercote71980f02004-01-24 18:18:54 +00002345/*=== main() ===*/
2346/*====================================================================*/
2347
nethercotec314eba2004-07-15 12:59:41 +00002348/*
2349 This code decides on the layout of the client and Valgrind address
nethercote996901a2004-08-03 13:29:09 +00002350 spaces, loads valgrind.so and the tool.so into the valgrind part,
nethercotec314eba2004-07-15 12:59:41 +00002351 loads the client executable (and the dynamic linker, if necessary)
2352 into the client part, and calls into Valgrind proper.
2353
2354 The code is careful not to allow spurious mappings to appear in the
2355 wrong parts of the address space. In particular, to make sure
2356 dlopen puts things in the right place, it will pad out the forbidden
2357 chunks of address space so that dlopen is forced to put things where
2358 we want them.
2359
2360 The memory map it creates is:
2361
njn311c5d82005-05-15 21:03:42 +00002362 client_base +-------------------------+
nethercotec314eba2004-07-15 12:59:41 +00002363 | client address space |
2364 : :
2365 : :
2366 | client stack |
2367 client_end +-------------------------+
2368 | redzone |
2369 shadow_base +-------------------------+
2370 | |
nethercote996901a2004-08-03 13:29:09 +00002371 : shadow memory for tools :
nethercotec314eba2004-07-15 12:59:41 +00002372 | (may be 0 sized) |
2373 shadow_end +-------------------------+
nethercotec314eba2004-07-15 12:59:41 +00002374 valgrind_base +-------------------------+
2375 | kickstart executable |
2376 | valgrind heap vvvvvvvvv| (barely used)
2377 - -
2378 | valgrind .so files |
2379 | and mappings |
2380 - -
2381 | valgrind stack ^^^^^^^^^|
nethercote820bd8c2004-09-07 23:04:49 +00002382 valgrind_last +-------------------------+
nethercotec314eba2004-07-15 12:59:41 +00002383 : kernel :
2384
2385 Nb: Before we can do general allocations with VG_(arena_malloc)() and
2386 VG_(mmap)(), we need to build the segment skip-list, so we know where
2387 we can put things. However, building that structure requires
2388 allocating memory. So we need to a bootstrapping process. It's done
2389 by making VG_(arena_malloc)() have a special static superblock that's
2390 used for the first 1MB's worth of allocations. This is enough to
2391 build the segment skip-list.
2392*/
2393
thughes4ad52d02004-06-27 17:37:21 +00002394
sewardj1cf558c2005-04-25 01:36:56 +00002395/* This may be needed before m_mylibc is OK to run. */
2396static Int local_strcmp ( const HChar* s1, const HChar* s2 )
2397{
2398 while (True) {
2399 if (*s1 == 0 && *s2 == 0) return 0;
2400 if (*s1 == 0) return -1;
2401 if (*s2 == 0) return 1;
2402
2403 if (*(UChar*)s1 < *(UChar*)s2) return -1;
2404 if (*(UChar*)s1 > *(UChar*)s2) return 1;
2405
2406 s1++; s2++;
2407 }
2408}
2409
2410
sewardjb5f6f512005-03-10 23:59:00 +00002411int main(int argc, char **argv, char **envp)
nethercote71980f02004-01-24 18:18:54 +00002412{
2413 char **cl_argv;
sewardjb5f6f512005-03-10 23:59:00 +00002414 const char *tool = "memcheck"; // default to Memcheck
nethercote71980f02004-01-24 18:18:54 +00002415 const char *exec = NULL;
2416 char *preload; /* tool-specific LD_PRELOAD .so */
2417 char **env;
nethercote6c999f22004-01-31 22:55:15 +00002418 Int need_help = 0; // 0 = no, 1 = --help, 2 = --help-debug
nethercote71980f02004-01-24 18:18:54 +00002419 struct exeinfo info;
2420 ToolInfo *toolinfo = NULL;
nethercote71980f02004-01-24 18:18:54 +00002421 Addr client_eip;
nethercote4ad74312004-10-26 09:59:49 +00002422 Addr sp_at_startup; /* client's SP at the point we gained control. */
nethercote71980f02004-01-24 18:18:54 +00002423 UInt * client_auxv;
nethercote73b526f2004-10-31 18:48:21 +00002424 struct vki_rlimit zero = { 0, 0 };
sewardj1cf558c2005-04-25 01:36:56 +00002425 Int padfile, loglevel, i;
nethercote71980f02004-01-24 18:18:54 +00002426
2427 //============================================================
2428 // Nb: startup is complex. Prerequisites are shown at every step.
2429 //
2430 // *** Be very careful when messing with the order ***
2431 //============================================================
2432
sewardj1cf558c2005-04-25 01:36:56 +00002433 //--------------------------------------------------------------
2434 // Start up the logging mechanism
2435 // p: none
2436 //--------------------------------------------------------------
2437 /* Start the debugging-log system ASAP. First find out how many
2438 "-d"s were specified. This is a pre-scan of the command line. */
2439 loglevel = 0;
2440 for (i = 1; i < argc; i++) {
sewardj10759312005-05-30 23:52:47 +00002441 if (argv[i][0] != '-')
2442 break;
2443 if (0 == local_strcmp(argv[i], "--"))
2444 break;
2445 if (0 == local_strcmp(argv[i], "-d"))
2446 loglevel++;
sewardj1cf558c2005-04-25 01:36:56 +00002447 }
2448
2449 /* ... and start the debug logger. Now we can safely emit logging
2450 messages all through startup. */
sewardj10759312005-05-30 23:52:47 +00002451 VG_(debugLog_startup)(loglevel, "Stage 2 (main)");
sewardj1cf558c2005-04-25 01:36:56 +00002452
nethercotef4928da2004-06-15 10:54:40 +00002453 //============================================================
2454 // Command line argument handling order:
2455 // * If --help/--help-debug are present, show usage message
sewardjb5f6f512005-03-10 23:59:00 +00002456 // (including the tool-specific usage)
2457 // * (If no --tool option given, default to Memcheck)
nethercotef4928da2004-06-15 10:54:40 +00002458 // * Then, if client is missing, abort with error msg
2459 // * Then, if any cmdline args are bad, abort with error msg
2460 //============================================================
2461
fitzhardingeb50068f2004-02-24 23:42:55 +00002462 // Get the current process datasize rlimit, and set it to zero.
2463 // This prevents any internal uses of brk() from having any effect.
2464 // We remember the old value so we can restore it on exec, so that
2465 // child processes will have a reasonable brk value.
2466 VG_(getrlimit)(VKI_RLIMIT_DATA, &VG_(client_rlimit_data));
2467 zero.rlim_max = VG_(client_rlimit_data).rlim_max;
2468 VG_(setrlimit)(VKI_RLIMIT_DATA, &zero);
thughesc37184f2004-09-11 14:16:57 +00002469
2470 // Get the current process stack rlimit.
2471 VG_(getrlimit)(VKI_RLIMIT_STACK, &VG_(client_rlimit_stack));
2472
nethercote71980f02004-01-24 18:18:54 +00002473 //--------------------------------------------------------------
2474 // Check we were launched by stage1
sewardj51ac0872004-12-21 01:20:49 +00002475 // p: none
nethercote71980f02004-01-24 18:18:54 +00002476 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002477 VG_(debugLog)(1, "main", "Doing scan_auxv()\n");
nethercotec25c4492004-10-18 11:52:17 +00002478 {
sewardj1fbc1a52005-04-25 02:05:54 +00002479 void* init_sp = argv - 1;
2480 padfile = scan_auxv(init_sp);
nethercote71980f02004-01-24 18:18:54 +00002481 }
2482
2483 //--------------------------------------------------------------
2484 // Look for alternative libdir
sewardj51ac0872004-12-21 01:20:49 +00002485 // p: none
nethercote71980f02004-01-24 18:18:54 +00002486 //--------------------------------------------------------------
sewardj51ac0872004-12-21 01:20:49 +00002487 { HChar *cp = getenv(VALGRINDLIB);
nethercote71980f02004-01-24 18:18:54 +00002488 if (cp != NULL)
2489 VG_(libdir) = cp;
2490 }
2491
2492 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002493 // Get valgrind args + client args (inc. from VALGRIND_OPTS/.valgrindrc).
2494 // Pre-process the command line.
sewardj51ac0872004-12-21 01:20:49 +00002495 // p: none
nethercote71980f02004-01-24 18:18:54 +00002496 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002497 VG_(debugLog)(1, "main", "Preprocess command line opts\n");
nethercotef6a1d502004-08-09 12:21:57 +00002498 get_command_line(argc, argv, &vg_argc, &vg_argv, &cl_argv);
nethercote71980f02004-01-24 18:18:54 +00002499 pre_process_cmd_line_options(&need_help, &tool, &exec);
2500
sewardj10759312005-05-30 23:52:47 +00002501 /* If this process was created by exec done by another Valgrind
2502 process, the arguments will only show up at this point. Hence
2503 we need to also snoop around in vg_argv to see if anyone is
2504 asking for debug logging. */
2505 if (loglevel == 0) {
2506 for (i = 1; i < vg_argc; i++) {
2507 if (vg_argv[i][0] != '-')
2508 break;
2509 if (0 == local_strcmp(vg_argv[i], "--"))
2510 break;
2511 if (0 == local_strcmp(vg_argv[i], "-d"))
2512 loglevel++;
2513 }
2514 VG_(debugLog_startup)(loglevel, "Stage 2 (second go)");
2515 }
2516
nethercote71980f02004-01-24 18:18:54 +00002517 //==============================================================
2518 // Nb: once a tool is specified, the tool.so must be loaded even if
2519 // they specified --help or didn't specify a client program.
2520 //==============================================================
2521
2522 //--------------------------------------------------------------
2523 // With client padded out, map in tool
nethercote71980f02004-01-24 18:18:54 +00002524 // p: set-libdir [for VG_(libdir)]
2525 // p: pre_process_cmd_line_options() [for 'tool']
2526 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002527 VG_(debugLog)(1, "main", "Loading tool\n");
njn8a97c6d2005-03-31 04:37:24 +00002528 load_tool(tool, &toolinfo, &preload);
nethercote71980f02004-01-24 18:18:54 +00002529
2530 //==============================================================
2531 // Can use VG_(malloc)() and VG_(arena_malloc)() only after load_tool()
nethercotec314eba2004-07-15 12:59:41 +00002532 // -- redzone size is now set. This is checked by vg_malloc2.c.
nethercote71980f02004-01-24 18:18:54 +00002533 //==============================================================
2534
2535 //--------------------------------------------------------------
2536 // Finalise address space layout
nethercote31779c72004-07-30 21:50:15 +00002537 // p: load_tool() [for 'toolinfo']
nethercote71980f02004-01-24 18:18:54 +00002538 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002539 VG_(debugLog)(1, "main", "Laying out remaining space\n");
nethercote31779c72004-07-30 21:50:15 +00002540 layout_remaining_space( (Addr) & argc, toolinfo->shadow_ratio );
nethercote71980f02004-01-24 18:18:54 +00002541
2542 //--------------------------------------------------------------
2543 // Load client executable, finding in $PATH if necessary
nethercote71980f02004-01-24 18:18:54 +00002544 // p: pre_process_cmd_line_options() [for 'exec', 'need_help']
2545 // p: layout_remaining_space [so there's space]
2546 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002547 VG_(debugLog)(1, "main", "Loading client\n");
nethercotef4928da2004-06-15 10:54:40 +00002548 load_client(cl_argv, exec, need_help, &info, &client_eip);
nethercote71980f02004-01-24 18:18:54 +00002549
2550 //--------------------------------------------------------------
nethercote969ecf12004-10-13 17:29:01 +00002551 // Everything in place, remove padding done by stage1
nethercote71980f02004-01-24 18:18:54 +00002552 // p: layout_remaining_space() [everything must be mapped in before now]
2553 // p: load_client() [ditto]
2554 //--------------------------------------------------------------
nethercote31779c72004-07-30 21:50:15 +00002555 as_unpad((void *)VG_(shadow_end), (void *)~0, padfile);
2556 as_closepadfile(padfile); // no more padding
nethercote71980f02004-01-24 18:18:54 +00002557
2558 //--------------------------------------------------------------
2559 // Set up client's environment
2560 // p: set-libdir [for VG_(libdir)]
2561 // p: load_tool() [for 'preload']
2562 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002563 VG_(debugLog)(1, "main", "Setup client env\n");
sewardjb5f6f512005-03-10 23:59:00 +00002564 env = fix_environment(envp, preload);
nethercote71980f02004-01-24 18:18:54 +00002565
2566 //--------------------------------------------------------------
nethercote5ee67ca2004-06-22 14:00:09 +00002567 // Setup client stack, eip, and VG_(client_arg[cv])
nethercote71980f02004-01-24 18:18:54 +00002568 // p: load_client() [for 'info']
2569 // p: fix_environment() [for 'env']
2570 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002571 VG_(debugLog)(1, "main", "Setup client stack\n");
nethercotec25c4492004-10-18 11:52:17 +00002572 {
sewardj1fbc1a52005-04-25 02:05:54 +00002573 void* init_sp = argv - 1;
sewardjb5f6f512005-03-10 23:59:00 +00002574
sewardj1fbc1a52005-04-25 02:05:54 +00002575 sp_at_startup = setup_client_stack(init_sp, cl_argv, env, &info,
2576 &client_auxv);
2577 free(env);
nethercotec25c4492004-10-18 11:52:17 +00002578 }
nethercote71980f02004-01-24 18:18:54 +00002579
sewardj1fbc1a52005-04-25 02:05:54 +00002580 VG_(debugLog)(2, "main",
2581 "Client info: "
2582 "entry=%p client esp=%p vg_argc=%d brkbase=%p\n",
2583 (void*)client_eip, (void*)sp_at_startup, vg_argc,
2584 (void*)VG_(brk_base) );
nethercote71980f02004-01-24 18:18:54 +00002585
2586 //==============================================================
2587 // Finished setting up operating environment. Now initialise
2588 // Valgrind. (This is where the old VG_(main)() started.)
2589 //==============================================================
2590
2591 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002592 // setup file descriptors
2593 // p: n/a
2594 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002595 VG_(debugLog)(1, "main", "Setup file descriptors\n");
nethercote71980f02004-01-24 18:18:54 +00002596 setup_file_descriptors();
2597
2598 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002599 // Build segment map (Valgrind segments only)
njnd2252832004-11-26 10:53:33 +00002600 // p: tl_pre_clo_init() [to setup new_mem_startup tracker]
nethercotec314eba2004-07-15 12:59:41 +00002601 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002602 VG_(debugLog)(1, "main", "Parse /proc/self/maps (round 1)\n");
nethercotec314eba2004-07-15 12:59:41 +00002603 VG_(parse_procselfmaps) ( build_valgrind_map_callback );
2604
2605 //==============================================================
2606 // Can use VG_(arena_malloc)() with non-CORE arena after segments set up
2607 //==============================================================
2608
2609 //--------------------------------------------------------------
2610 // Init tool: pre_clo_init, process cmd line, post_clo_init
2611 // p: setup_client_stack() [for 'VG_(client_arg[cv]']
njn8a97c6d2005-03-31 04:37:24 +00002612 // p: load_tool() [for 'toolinfo']
nethercotec314eba2004-07-15 12:59:41 +00002613 // p: setup_file_descriptors() [for 'VG_(fd_xxx_limit)']
2614 // p: parse_procselfmaps [so VG segments are setup so tool can
2615 // call VG_(malloc)]
nethercote71980f02004-01-24 18:18:54 +00002616 //--------------------------------------------------------------
njn64c83242005-06-21 01:54:38 +00002617 {
2618 Char* s;
2619 Bool ok;
2620 VG_(debugLog)(1, "main", "Initialise the tool\n");
2621 (*toolinfo->tl_pre_clo_init)();
2622 ok = VG_(sanity_check_needs)( VG_(shadow_base) != VG_(shadow_end), &s );
2623 if (!ok) {
2624 VG_(tool_panic)(s);
2625 }
2626 }
nethercote71980f02004-01-24 18:18:54 +00002627
nethercotef4928da2004-06-15 10:54:40 +00002628 // If --tool and --help/--help-debug was given, now give the core+tool
2629 // help message
nethercotef4928da2004-06-15 10:54:40 +00002630 if (need_help) {
2631 usage(/*--help-debug?*/2 == need_help);
2632 }
nethercotec314eba2004-07-15 12:59:41 +00002633 process_cmd_line_options(client_auxv, tool);
2634
njn51d827b2005-05-09 01:02:08 +00002635 VG_TDICT_CALL(tool_post_clo_init);
nethercotef4928da2004-06-15 10:54:40 +00002636
2637 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002638 // Build segment map (all segments)
sewardjb5f6f512005-03-10 23:59:00 +00002639 // p: shadow/redzone segments
nethercote4ad74312004-10-26 09:59:49 +00002640 // p: setup_client_stack() [for 'sp_at_startup']
nethercotec314eba2004-07-15 12:59:41 +00002641 // p: init tool [for 'new_mem_startup']
nethercote71980f02004-01-24 18:18:54 +00002642 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002643 VG_(debugLog)(1, "main", "Parse /proc/self/maps (round 2)\n");
nethercote4ad74312004-10-26 09:59:49 +00002644 sp_at_startup___global_arg = sp_at_startup;
nethercotec314eba2004-07-15 12:59:41 +00002645 VG_(parse_procselfmaps) ( build_segment_map_callback ); /* everything */
nethercote4ad74312004-10-26 09:59:49 +00002646 sp_at_startup___global_arg = 0;
sewardjb5f6f512005-03-10 23:59:00 +00002647
nethercotec314eba2004-07-15 12:59:41 +00002648 //==============================================================
2649 // Can use VG_(map)() after segments set up
2650 //==============================================================
nethercote71980f02004-01-24 18:18:54 +00002651
2652 //--------------------------------------------------------------
2653 // Allow GDB attach
2654 // p: process_cmd_line_options() [for VG_(clo_wait_for_gdb)]
2655 //--------------------------------------------------------------
2656 /* Hook to delay things long enough so we can get the pid and
2657 attach GDB in another shell. */
2658 if (VG_(clo_wait_for_gdb)) {
sewardj8211a572005-06-23 21:37:47 +00002659 Long q, iters;
sewardj1fbc1a52005-04-25 02:05:54 +00002660 VG_(debugLog)(1, "main", "Wait for GDB\n");
sewardj93ab8572005-02-06 14:10:40 +00002661 VG_(printf)("pid=%d, entering delay loop\n", VG_(getpid)());
2662 /* jrs 20050206: I don't understand why this works on x86. On
2663 amd64 the obvious analogues (jump *$rip or jump *$rcx) don't
2664 work. */
2665 /* do "jump *$eip" to skip this in gdb (x86) */
2666 //VG_(do_syscall0)(__NR_pause);
sewardj8211a572005-06-23 21:37:47 +00002667
2668# if defined(VGP_x86_linux)
2669 iters = 5;
2670# elif defined(VGP_amd64_linux)
2671 iters = 10;
2672# elif defined(VGP_ppc32_linux)
sewardjd714d2e2005-07-08 18:24:04 +00002673 iters = 5;
sewardj8211a572005-06-23 21:37:47 +00002674# else
2675# error "Unknown plat"
2676# endif
2677
2678 iters *= 1000*1000*1000;
2679 for (q = 0; q < iters; q++)
2680 ;
nethercote71980f02004-01-24 18:18:54 +00002681 }
2682
sewardjb5d320c2005-03-13 18:57:15 +00002683 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002684 // Search for file descriptors that are inherited from our parent
2685 // p: process_cmd_line_options [for VG_(clo_track_fds)]
2686 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002687 if (VG_(clo_track_fds)) {
2688 VG_(debugLog)(1, "main", "Init preopened fds\n");
nethercote71980f02004-01-24 18:18:54 +00002689 VG_(init_preopened_fds)();
sewardj1fbc1a52005-04-25 02:05:54 +00002690 }
nethercote71980f02004-01-24 18:18:54 +00002691
2692 //--------------------------------------------------------------
2693 // Initialise the scheduler
nethercote71980f02004-01-24 18:18:54 +00002694 // p: setup_file_descriptors() [else VG_(safe_fd)() breaks]
2695 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002696 VG_(debugLog)(1, "main", "Initialise scheduler\n");
nethercote71980f02004-01-24 18:18:54 +00002697 VG_(scheduler_init)();
2698
2699 //--------------------------------------------------------------
sewardjb5f6f512005-03-10 23:59:00 +00002700 // Initialise the pthread model
2701 // p: ?
sewardj2a99cf62004-11-24 10:44:19 +00002702 // load_client() [for 'client_eip']
2703 // setup_client_stack() [for 'sp_at_startup']
2704 // setup_scheduler() [for the rest of state 1 stuff]
2705 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002706 VG_(debugLog)(1, "main", "Initialise thread 1's state\n");
njn2da73352005-06-18 01:35:16 +00002707 init_thread1state(client_eip, sp_at_startup, &VG_(threads)[1].arch);
njnea4b28c2004-11-30 16:04:58 +00002708
sewardj2a99cf62004-11-24 10:44:19 +00002709 //--------------------------------------------------------------
sewardj39b88fb2005-03-12 15:16:07 +00002710 // Initialise the pthread model
2711 // p: ?
nethercote71980f02004-01-24 18:18:54 +00002712 //--------------------------------------------------------------
sewardjb5f6f512005-03-10 23:59:00 +00002713 //if (VG_(clo_model_pthreads))
2714 // VG_(pthread_init)();
nethercote71980f02004-01-24 18:18:54 +00002715
2716 //--------------------------------------------------------------
2717 // Initialise the signal handling subsystem
sewardjb5f6f512005-03-10 23:59:00 +00002718 // p: n/a
nethercote71980f02004-01-24 18:18:54 +00002719 //--------------------------------------------------------------
2720 // Nb: temporarily parks the saved blocking-mask in saved_sigmask.
sewardj1fbc1a52005-04-25 02:05:54 +00002721 VG_(debugLog)(1, "main", "Initialise signal management\n");
nethercote71980f02004-01-24 18:18:54 +00002722 VG_(sigstartup_actions)();
2723
2724 //--------------------------------------------------------------
2725 // Perhaps we're profiling Valgrind?
2726 // p: process_cmd_line_options() [for VG_(clo_profile)]
2727 // p: others?
2728 //
2729 // XXX: this seems to be broken? It always says the tool wasn't built
2730 // for profiling; vg_profile.c's functions don't seem to be overriding
2731 // vg_dummy_profile.c's?
2732 //
2733 // XXX: want this as early as possible. Looking for --profile
2734 // in pre_process_cmd_line_options() could get it earlier.
2735 //--------------------------------------------------------------
2736 if (VG_(clo_profile))
njn31066fd2005-03-26 00:42:02 +00002737 VG_(init_profiling)();
nethercote71980f02004-01-24 18:18:54 +00002738
2739 VGP_PUSHCC(VgpStartup);
2740
2741 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002742 // Read suppression file
2743 // p: process_cmd_line_options() [for VG_(clo_suppressions)]
2744 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002745 if (VG_(needs).core_errors || VG_(needs).tool_errors) {
2746 VG_(debugLog)(1, "main", "Load suppressions\n");
nethercote71980f02004-01-24 18:18:54 +00002747 VG_(load_suppressions)();
sewardj1fbc1a52005-04-25 02:05:54 +00002748 }
nethercote71980f02004-01-24 18:18:54 +00002749
2750 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002751 // Initialise translation table and translation cache
2752 // p: read_procselfmaps [so the anonymous mmaps for the TT/TC
2753 // aren't identified as part of the client, which would waste
2754 // > 20M of virtual address space.]
2755 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002756 VG_(debugLog)(1, "main", "Initialise TT/TC\n");
nethercote71980f02004-01-24 18:18:54 +00002757 VG_(init_tt_tc)();
2758
2759 //--------------------------------------------------------------
sewardjb9bce632005-06-21 01:41:34 +00002760 // Initialise the redirect table.
sewardjb5d320c2005-03-13 18:57:15 +00002761 // p: parse_procselfmaps? [XXX for debug info?]
2762 // p: init_tt_tc [so it can call VG_(search_transtab) safely]
2763 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002764 VG_(debugLog)(1, "main", "Initialise redirects\n");
sewardjb5d320c2005-03-13 18:57:15 +00002765 VG_(setup_code_redirect_table)();
2766
2767 //--------------------------------------------------------------
sewardjb9bce632005-06-21 01:41:34 +00002768 // Tell the tool about permissions in our handwritten assembly
2769 // helpers.
2770 // p: init tool [for 'new_mem_startup']
2771 //--------------------------------------------------------------
2772 VG_(debugLog)(1, "main", "Tell tool about permissions for asm helpers\n");
2773 VG_TRACK( new_mem_startup,
2774 (Addr)&VG_(trampoline_stuff_start),
2775 &VG_(trampoline_stuff_end) - &VG_(trampoline_stuff_start),
2776 False, /* readable? */
2777 False, /* writable? */
2778 True /* executable? */ );
2779
2780 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002781 // Verbosity message
2782 // p: end_rdtsc_calibration [so startup message is printed first]
2783 //--------------------------------------------------------------
sewardj71bc3cb2005-05-19 00:25:45 +00002784 if (VG_(clo_verbosity) == 1 && !VG_(clo_xml))
nethercote71980f02004-01-24 18:18:54 +00002785 VG_(message)(Vg_UserMsg, "For more details, rerun with: -v");
2786 if (VG_(clo_verbosity) > 0)
2787 VG_(message)(Vg_UserMsg, "");
2788
2789 //--------------------------------------------------------------
2790 // Setup pointercheck
njn04e16982005-05-31 00:23:43 +00002791 // p: layout_remaining_space() [for VG_(client_{base,end})]
nethercote71980f02004-01-24 18:18:54 +00002792 // p: process_cmd_line_options() [for VG_(clo_pointercheck)]
2793 //--------------------------------------------------------------
nethercote775508a2004-09-07 22:38:23 +00002794 if (VG_(clo_pointercheck))
njn04e16982005-05-31 00:23:43 +00002795 VG_(clo_pointercheck) =
njnaf839f52005-06-23 03:27:57 +00002796 VG_(setup_pointercheck)( VG_(client_base), VG_(client_end));
nethercote71980f02004-01-24 18:18:54 +00002797
nethercote71980f02004-01-24 18:18:54 +00002798 //--------------------------------------------------------------
rjwalsh0140af52005-06-04 20:42:33 +00002799 // register client stack
2800 //--------------------------------------------------------------
njn945ed2e2005-06-24 03:28:30 +00002801 VG_(clstk_id) = VG_(register_stack)(VG_(clstk_base), VG_(clstk_end));
rjwalsh0140af52005-06-04 20:42:33 +00002802
2803 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002804 // Run!
2805 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002806 VGP_POPCC(VgpStartup);
nethercote71980f02004-01-24 18:18:54 +00002807
sewardj71bc3cb2005-05-19 00:25:45 +00002808 if (VG_(clo_xml)) {
sewardj68cde6f2005-07-19 12:17:51 +00002809 HChar buf[50];
2810 VG_(ctime)(buf);
2811 VG_(message)(Vg_UserMsg, "<status> <what>RUNNING</what> "
sewardj97f7e0c2005-07-19 15:00:25 +00002812 "<when>%t</when> </status>", buf);
sewardj71bc3cb2005-05-19 00:25:45 +00002813 VG_(message)(Vg_UserMsg, "");
2814 }
2815
sewardj1fbc1a52005-04-25 02:05:54 +00002816 VG_(debugLog)(1, "main", "Running thread 1\n");
sewardj1d887112005-05-30 21:44:08 +00002817 /* As a result of the following call, the last thread standing
2818 eventually winds up running VG_(shutdown_actions_NORETURN) just
2819 below. */
njnaf839f52005-06-23 03:27:57 +00002820 VG_(main_thread_wrapper_NORETURN)(1);
nethercote71980f02004-01-24 18:18:54 +00002821
sewardj1d887112005-05-30 21:44:08 +00002822 /*NOTREACHED*/
2823 vg_assert(0);
sewardjb5f6f512005-03-10 23:59:00 +00002824}
2825
2826
njn9cb54ac2005-06-12 04:19:17 +00002827/* Final clean-up before terminating the process.
2828 Clean up the client by calling __libc_freeres() (if requested)
2829 This is Linux-specific?
2830*/
2831static void final_tidyup(ThreadId tid)
2832{
njnbc6d84d2005-06-19 18:58:03 +00002833 Addr __libc_freeres_wrapper;
2834
njn9cb54ac2005-06-12 04:19:17 +00002835 vg_assert(VG_(is_running_thread)(tid));
2836
njnbc6d84d2005-06-19 18:58:03 +00002837 if ( !VG_(needs).libc_freeres ||
2838 !VG_(clo_run_libc_freeres) ||
2839 0 == (__libc_freeres_wrapper = VG_(get_libc_freeres_wrapper)()) )
njn9cb54ac2005-06-12 04:19:17 +00002840 return; /* can't/won't do it */
2841
2842 if (VG_(clo_verbosity) > 2 ||
2843 VG_(clo_trace_syscalls) ||
2844 VG_(clo_trace_sched))
2845 VG_(message)(Vg_DebugMsg,
2846 "Caught __NR_exit; running __libc_freeres()");
2847
2848 /* point thread context to point to libc_freeres_wrapper */
njnf536bbb2005-06-13 04:21:38 +00002849 VG_(set_IP)(tid, __libc_freeres_wrapper);
njn9cb54ac2005-06-12 04:19:17 +00002850 // XXX should we use a special stack?
2851
2852 /* Block all blockable signals by copying the real block state into
2853 the thread's block state*/
2854 VG_(sigprocmask)(VKI_SIG_BLOCK, NULL, &VG_(threads)[tid].sig_mask);
2855 VG_(threads)[tid].tmp_sig_mask = VG_(threads)[tid].sig_mask;
2856
2857 /* and restore handlers to default */
2858 VG_(set_default_handler)(VKI_SIGSEGV);
2859 VG_(set_default_handler)(VKI_SIGBUS);
2860 VG_(set_default_handler)(VKI_SIGILL);
2861 VG_(set_default_handler)(VKI_SIGFPE);
2862
2863 // We were exiting, so assert that...
2864 vg_assert(VG_(is_exiting)(tid));
2865 // ...but now we're not again
2866 VG_(threads)[tid].exitreason = VgSrc_None;
2867
2868 // run until client thread exits - ideally with LIBC_FREERES_DONE,
2869 // but exit/exitgroup/signal will do
2870 VG_(scheduler)(tid);
2871
2872 vg_assert(VG_(is_exiting)(tid));
2873}
2874
sewardjb5f6f512005-03-10 23:59:00 +00002875/* Do everything which needs doing when the last thread exits */
sewardj1d887112005-05-30 21:44:08 +00002876void VG_(shutdown_actions_NORETURN) ( ThreadId tid,
2877 VgSchedReturnCode tids_schedretcode )
sewardjb5f6f512005-03-10 23:59:00 +00002878{
sewardj1d887112005-05-30 21:44:08 +00002879 VG_(debugLog)(1, "main", "entering VG_(shutdown_actions_NORETURN)\n");
2880
2881 vg_assert( VG_(count_living_threads)() == 1 );
sewardjb5f6f512005-03-10 23:59:00 +00002882 vg_assert(VG_(is_running_thread)(tid));
2883
2884 // Wait for all other threads to exit.
njn7b85dd52005-06-12 17:26:29 +00002885 VG_(reap_threads)(tid);
sewardjb5f6f512005-03-10 23:59:00 +00002886
2887 VG_(clo_model_pthreads) = False;
2888
2889 // Clean the client up before the final report
njn9cb54ac2005-06-12 04:19:17 +00002890 final_tidyup(tid);
sewardjb5f6f512005-03-10 23:59:00 +00002891
2892 // OK, done
2893 VG_(exit_thread)(tid);
2894
2895 /* should be no threads left */
2896 vg_assert(VG_(count_living_threads)() == 0);
2897
2898 VG_(threads)[tid].status = VgTs_Empty;
nethercote71980f02004-01-24 18:18:54 +00002899 //--------------------------------------------------------------
2900 // Finalisation: cleanup, messages, etc. Order no so important, only
2901 // affects what order the messages come.
2902 //--------------------------------------------------------------
2903 if (VG_(clo_verbosity) > 0)
2904 VG_(message)(Vg_UserMsg, "");
2905
sewardj71bc3cb2005-05-19 00:25:45 +00002906 if (VG_(clo_xml)) {
sewardj68cde6f2005-07-19 12:17:51 +00002907 HChar buf[50];
sewardj9f297ca2005-05-20 02:29:52 +00002908 if (VG_(needs).core_errors || VG_(needs).tool_errors) {
2909 VG_(show_error_counts_as_XML)();
2910 VG_(message)(Vg_UserMsg, "");
2911 }
sewardj68cde6f2005-07-19 12:17:51 +00002912 VG_(ctime)(buf);
2913 VG_(message)(Vg_UserMsg, "<status> <what>FINISHED</what> "
sewardj97f7e0c2005-07-19 15:00:25 +00002914 "<when>%t</when> </status>", buf);
sewardj71bc3cb2005-05-19 00:25:45 +00002915 VG_(message)(Vg_UserMsg, "");
2916 }
2917
nethercote71980f02004-01-24 18:18:54 +00002918 /* Print out file descriptor summary and stats. */
2919 if (VG_(clo_track_fds))
nethercote3a42fb82004-08-03 18:08:50 +00002920 VG_(show_open_fds)();
nethercote71980f02004-01-24 18:18:54 +00002921
njn95ec8702004-11-22 16:46:13 +00002922 if (VG_(needs).core_errors || VG_(needs).tool_errors)
nethercote71980f02004-01-24 18:18:54 +00002923 VG_(show_all_errors)();
2924
njn51d827b2005-05-09 01:02:08 +00002925 VG_TDICT_CALL(tool_fini, 0/*exitcode*/);
nethercote71980f02004-01-24 18:18:54 +00002926
sewardj71bc3cb2005-05-19 00:25:45 +00002927 if (VG_(clo_xml)) {
2928 VG_(message)(Vg_UserMsg, "");
2929 VG_(message)(Vg_UserMsg, "</valgrindoutput>");
2930 VG_(message)(Vg_UserMsg, "");
2931 }
2932
nethercote885dd912004-08-03 23:14:00 +00002933 VG_(sanity_check_general)( True /*include expensive checks*/ );
nethercote71980f02004-01-24 18:18:54 +00002934
2935 if (VG_(clo_verbosity) > 1)
nethercote3a42fb82004-08-03 18:08:50 +00002936 print_all_stats();
nethercote71980f02004-01-24 18:18:54 +00002937
nethercote71980f02004-01-24 18:18:54 +00002938 if (VG_(clo_profile))
njn31066fd2005-03-26 00:42:02 +00002939 VG_(done_profiling)();
njn2025cf92005-06-26 20:44:48 +00002940
2941 if (VG_(clo_profile_flags) > 0) {
2942 #define N_MAX 100
2943 BBProfEntry tops[N_MAX];
2944 ULong score_total = VG_(get_BB_profile) (tops, N_MAX);
2945 show_BB_profile(tops, N_MAX, score_total);
2946 }
sewardjfa8ec112005-01-19 11:55:34 +00002947
sewardj8b635a42004-11-22 19:01:47 +00002948 /* Print Vex storage stats */
sewardjbf426512005-01-17 18:35:30 +00002949 if (0)
2950 LibVEX_ShowAllocStats();
sewardj1d887112005-05-30 21:44:08 +00002951
njn8aa35852005-06-10 22:59:56 +00002952 /* Ok, finally exit in the os-specific way, according to the scheduler's
2953 return code. In short, if the (last) thread exited by calling
2954 sys_exit, do likewise; if the (last) thread stopped due to a fatal
2955 signal, terminate the entire system with that same fatal signal. */
2956 VG_(debugLog)(1, "core_os",
njn7b85dd52005-06-12 17:26:29 +00002957 "VG_(terminate_NORETURN)(tid=%lld)\n", (ULong)tid);
njn8aa35852005-06-10 22:59:56 +00002958
2959 vg_assert(VG_(count_living_threads)() == 0);
2960
2961 switch (tids_schedretcode) {
2962 case VgSrc_ExitSyscall: /* the normal way out */
2963 VG_(exit)( VG_(threads)[tid].os_state.exitcode );
2964 /* NOT ALIVE HERE! */
2965 VG_(core_panic)("entered the afterlife in main() -- ExitSyscall");
2966 break; /* what the hell :) */
2967
2968 case VgSrc_FatalSig:
2969 /* We were killed by a fatal signal, so replicate the effect */
2970 vg_assert(VG_(threads)[tid].os_state.fatalsig != 0);
2971 VG_(kill_self)(VG_(threads)[tid].os_state.fatalsig);
2972 VG_(core_panic)("main(): signal was supposed to be fatal");
2973 break;
2974
2975 default:
2976 VG_(core_panic)("main(): unexpected scheduler return code");
2977 }
njne96be672005-05-08 19:08:54 +00002978}
sewardj8b635a42004-11-22 19:01:47 +00002979
sewardjde4a1d02002-03-22 01:27:54 +00002980/*--------------------------------------------------------------------*/
njn04e16982005-05-31 00:23:43 +00002981/*--- end ---*/
sewardjde4a1d02002-03-22 01:27:54 +00002982/*--------------------------------------------------------------------*/