blob: ee6fde2e3c9e44928258018215f6d25f42d6b98f [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)();
nethercote3a42fb82004-08-03 18:08:50 +0000142 VG_(print_all_arena_stats)();
nethercote885dd912004-08-03 23:14:00 +0000143 VG_(message)(Vg_DebugMsg, "");
nethercote3a42fb82004-08-03 18:08:50 +0000144 }
nethercote71980f02004-01-24 18:18:54 +0000145}
146
147
148/*====================================================================*/
nethercote71980f02004-01-24 18:18:54 +0000149/*=== Check we were launched by stage 1 ===*/
150/*====================================================================*/
151
152/* Look for our AUXV table */
sewardjb5f6f512005-03-10 23:59:00 +0000153static int scan_auxv(void* init_sp)
nethercote71980f02004-01-24 18:18:54 +0000154{
njn62ff0f22005-06-21 23:03:36 +0000155 struct ume_auxv *auxv = VG_(find_auxv)((UWord*)init_sp);
nethercote31779c72004-07-30 21:50:15 +0000156 int padfile = -1, found = 0;
nethercote71980f02004-01-24 18:18:54 +0000157
158 for (; auxv->a_type != AT_NULL; auxv++)
159 switch(auxv->a_type) {
160 case AT_UME_PADFD:
nethercote31779c72004-07-30 21:50:15 +0000161 padfile = auxv->u.a_val;
nethercote71980f02004-01-24 18:18:54 +0000162 found |= 1;
163 break;
164
165 case AT_UME_EXECFD:
nethercotef6a1d502004-08-09 12:21:57 +0000166 vgexecfd = auxv->u.a_val;
nethercote71980f02004-01-24 18:18:54 +0000167 found |= 2;
168 break;
nethercote7f390022004-10-25 17:18:24 +0000169
sewardj10f08cf2005-06-29 10:16:14 +0000170# if defined(VGP_ppc32_linux)
cerion85665ca2005-06-20 15:51:07 +0000171 case AT_DCACHEBSIZE:
172 case AT_ICACHEBSIZE:
173 case AT_UCACHEBSIZE:
sewardj10f08cf2005-06-29 10:16:14 +0000174 if (auxv->u.a_val > 0) {
175 VG_(cache_line_size_ppc32) = auxv->u.a_val;
176 VG_(debugLog)(1, "main",
177 "PPC32 cache line size %u (type %u)\n",
178 (UInt)auxv->u.a_val, (UInt)auxv->a_type );
179 }
180 /* HACK: Tell glibc we don't know what the line size is.
181 This stops it using dcbz. */
182 auxv->u.a_val = 0;
cerion85665ca2005-06-20 15:51:07 +0000183 break;
sewardj10f08cf2005-06-29 10:16:14 +0000184# endif
cerion85665ca2005-06-20 15:51:07 +0000185
nethercote7f390022004-10-25 17:18:24 +0000186 case AT_PHDR:
njn13bfd852005-06-02 03:52:53 +0000187 VG_(valgrind_base) = VG_PGROUNDDN(auxv->u.a_val);
nethercote7f390022004-10-25 17:18:24 +0000188 break;
cerion85665ca2005-06-20 15:51:07 +0000189
sewardj10f08cf2005-06-29 10:16:14 +0000190 default:
191 break;
nethercote71980f02004-01-24 18:18:54 +0000192 }
193
nethercote361a14e2004-07-26 11:11:56 +0000194 if ( found != (1|2) ) {
195 fprintf(stderr, "valgrind: stage2 must be launched by stage1\n");
nethercote71980f02004-01-24 18:18:54 +0000196 exit(127);
197 }
nethercote31779c72004-07-30 21:50:15 +0000198 vg_assert(padfile >= 0);
199 return padfile;
nethercote71980f02004-01-24 18:18:54 +0000200}
201
202
203/*====================================================================*/
204/*=== Address space determination ===*/
205/*====================================================================*/
206
nethercote7f390022004-10-25 17:18:24 +0000207extern char _start[];
208
nethercote31779c72004-07-30 21:50:15 +0000209static void layout_remaining_space(Addr argc_addr, float ratio)
nethercote71980f02004-01-24 18:18:54 +0000210{
njn83407492005-06-19 16:10:47 +0000211 SysRes res;
212 Addr client_size, shadow_size;
nethercote71980f02004-01-24 18:18:54 +0000213
nethercote7f390022004-10-25 17:18:24 +0000214 // VG_(valgrind_base) should have been set by scan_auxv, but if not,
215 // this is a workable approximation
216 if (VG_(valgrind_base) == 0) {
njn13bfd852005-06-02 03:52:53 +0000217 VG_(valgrind_base) = VG_PGROUNDDN(&_start);
nethercote7f390022004-10-25 17:18:24 +0000218 }
219
njn13bfd852005-06-02 03:52:53 +0000220 VG_(valgrind_last) = VG_ROUNDUP(argc_addr, 0x10000) - 1; // stack
nethercote71980f02004-01-24 18:18:54 +0000221
nethercote31779c72004-07-30 21:50:15 +0000222 // This gives the client the largest possible address space while
223 // taking into account the tool's shadow needs.
njn13bfd852005-06-02 03:52:53 +0000224 client_size = VG_ROUNDDN((VG_(valgrind_base)-REDZONE_SIZE) / (1.+ratio),
nethercote71980f02004-01-24 18:18:54 +0000225 CLIENT_SIZE_MULTIPLE);
njn311c5d82005-05-15 21:03:42 +0000226 VG_(client_base) = 0;
nethercote71980f02004-01-24 18:18:54 +0000227 VG_(client_end) = VG_(client_base) + client_size;
nethercotee2097312004-06-27 12:29:56 +0000228 /* where !FIXED mmap goes */
nethercotebc7b4f42004-07-26 12:44:35 +0000229 VG_(client_mapbase) = VG_(client_base) +
njn13bfd852005-06-02 03:52:53 +0000230 VG_PGROUNDDN((Addr)(client_size * CLIENT_HEAP_PROPORTION));
nethercote71980f02004-01-24 18:18:54 +0000231
nethercote31779c72004-07-30 21:50:15 +0000232 VG_(shadow_base) = VG_(client_end) + REDZONE_SIZE;
nethercote410bfe62004-09-04 15:53:35 +0000233 VG_(shadow_end) = VG_(valgrind_base);
234 shadow_size = VG_(shadow_end) - VG_(shadow_base);
nethercote71980f02004-01-24 18:18:54 +0000235
nethercotee2097312004-06-27 12:29:56 +0000236#define SEGSIZE(a,b) ((VG_(b) - VG_(a))/(1024*1024))
237
nethercote71980f02004-01-24 18:18:54 +0000238 if (0)
nethercotee2097312004-06-27 12:29:56 +0000239 VG_(printf)(
tomb1d43182005-03-29 09:00:12 +0000240 "client_base %p (%dMB)\n"
241 "client_mapbase %p (%dMB)\n"
242 "client_end %p (%dMB)\n"
243 "shadow_base %p (%dMB)\n"
244 "shadow_end %p\n"
245 "valgrind_base %p (%dMB)\n"
246 "valgrind_last %p\n",
nethercotee2097312004-06-27 12:29:56 +0000247 VG_(client_base), SEGSIZE(client_base, client_mapbase),
248 VG_(client_mapbase), SEGSIZE(client_mapbase, client_end),
249 VG_(client_end), SEGSIZE(client_end, shadow_base),
250 VG_(shadow_base), SEGSIZE(shadow_base, shadow_end),
nethercote410bfe62004-09-04 15:53:35 +0000251 VG_(shadow_end),
nethercote820bd8c2004-09-07 23:04:49 +0000252 VG_(valgrind_base), SEGSIZE(valgrind_base, valgrind_last),
253 VG_(valgrind_last)
nethercotee2097312004-06-27 12:29:56 +0000254 );
255
256#undef SEGSIZE
nethercote71980f02004-01-24 18:18:54 +0000257
258 // Ban redzone
njn83407492005-06-19 16:10:47 +0000259 res = VG_(mmap_native)((void *)VG_(client_end), REDZONE_SIZE, VKI_PROT_NONE,
260 VKI_MAP_FIXED|VKI_MAP_ANONYMOUS|VKI_MAP_PRIVATE|VKI_MAP_NORESERVE,
261 -1, 0);
262 vg_assert(!res.isError);
nethercote71980f02004-01-24 18:18:54 +0000263
264 // Make client hole
njn83407492005-06-19 16:10:47 +0000265 res = VG_(munmap_native)((void*)VG_(client_base), client_size);
266 vg_assert(!res.isError);
nethercote71980f02004-01-24 18:18:54 +0000267
268 // Map shadow memory.
269 // Initially all inaccessible, incrementally initialized as it is used
nethercotee567e702004-07-10 17:49:17 +0000270 if (shadow_size != 0) {
njn83407492005-06-19 16:10:47 +0000271 res = VG_(mmap_native)((char *)VG_(shadow_base), shadow_size,
272 VKI_PROT_NONE,
273 VKI_MAP_PRIVATE|VKI_MAP_ANONYMOUS|VKI_MAP_FIXED|VKI_MAP_NORESERVE,
274 -1, 0);
275 if (res.isError) {
nethercoted4722622004-08-30 19:36:42 +0000276 fprintf(stderr,
nethercote8c1ce432004-10-08 14:01:14 +0000277 "valgrind: Could not allocate address space (%p bytes)\n"
278 "valgrind: for shadow memory\n"
279 "valgrind: Possible causes:\n"
280 "valgrind: - For some systems (especially under RedHat 8), Valgrind\n"
281 "valgrind: needs at least 1.5GB swap space.\n"
282 "valgrind: - Or, your virtual memory size may be limited (check\n"
283 "valgrind: with 'ulimit -v').\n"
284 "valgrind: - Or, your system may use a kernel that provides only a\n"
285 "valgrind: too-small (eg. 2GB) user address space.\n"
286 , (void*)shadow_size
287 );
nethercoted4722622004-08-30 19:36:42 +0000288 exit(1);
289 }
nethercotee567e702004-07-10 17:49:17 +0000290 }
nethercote71980f02004-01-24 18:18:54 +0000291}
292
293/*====================================================================*/
294/*=== Command line setup ===*/
295/*====================================================================*/
296
njndcc99d32005-06-19 15:34:59 +0000297// Note that we deliberately don't free the malloc'd memory. See comment
298// at call site.
nethercote71980f02004-01-24 18:18:54 +0000299static char* get_file_clo(char* dir)
300{
301# define FLEN 512
302 Int fd, n;
njn909c3192005-06-19 15:46:27 +0000303 struct vki_stat s1;
nethercote71980f02004-01-24 18:18:54 +0000304 char* f_clo = NULL;
305 char filename[FLEN];
306
307 snprintf(filename, FLEN, "%s/.valgrindrc", ( NULL == dir ? "" : dir ) );
308 fd = VG_(open)(filename, 0, VKI_S_IRUSR);
309 if ( fd > 0 ) {
njn909c3192005-06-19 15:46:27 +0000310 if ( 0 == VG_(fstat)(fd, &s1) ) {
nethercote71980f02004-01-24 18:18:54 +0000311 f_clo = malloc(s1.st_size+1);
312 vg_assert(f_clo);
njn909c3192005-06-19 15:46:27 +0000313 n = VG_(read)(fd, f_clo, s1.st_size);
nethercote71980f02004-01-24 18:18:54 +0000314 if (n == -1) n = 0;
315 f_clo[n] = '\0';
316 }
njn909c3192005-06-19 15:46:27 +0000317 VG_(close)(fd);
nethercote71980f02004-01-24 18:18:54 +0000318 }
319 return f_clo;
320# undef FLEN
321}
322
323static Int count_args(char* s)
324{
325 Int n = 0;
326 if (s) {
327 char* cp = s;
328 while (True) {
329 // We have alternating sequences: blanks, non-blanks, blanks...
330 // count the non-blanks sequences.
njn0c0f32a2005-03-26 04:14:01 +0000331 while ( VG_(isspace)(*cp) ) cp++;
nethercote71980f02004-01-24 18:18:54 +0000332 if ( !*cp ) break;
333 n++;
njn0c0f32a2005-03-26 04:14:01 +0000334 while ( !VG_(isspace)(*cp) && *cp ) cp++;
nethercote71980f02004-01-24 18:18:54 +0000335 }
336 }
337 return n;
338}
339
njndcc99d32005-06-19 15:34:59 +0000340// Add args out of environment, skipping multiple spaces and "--" args.
341// We split 's' into multiple strings by replacing whitespace with nuls,
342// eg. "--aa --bb --cc" --> "--aa\0--bb\0--cc". And for each new string
343// carved out of 's', we put a pointer to it in 'to'.
nethercote71980f02004-01-24 18:18:54 +0000344static char** copy_args( char* s, char** to )
345{
346 if (s) {
347 char* cp = s;
348 while (True) {
349 // We have alternating sequences: blanks, non-blanks, blanks...
350 // copy the non-blanks sequences, and add terminating '\0'
njn0c0f32a2005-03-26 04:14:01 +0000351 while ( VG_(isspace)(*cp) ) cp++;
nethercote71980f02004-01-24 18:18:54 +0000352 if ( !*cp ) break;
353 *to++ = cp;
njn0c0f32a2005-03-26 04:14:01 +0000354 while ( !VG_(isspace)(*cp) && *cp ) cp++;
njndcc99d32005-06-19 15:34:59 +0000355 if ( *cp ) *cp++ = '\0'; // terminate if not the last
nethercote71980f02004-01-24 18:18:54 +0000356 if (VG_STREQ(to[-1], "--")) to--; // undo any '--' arg
357 }
358 }
359 return to;
360}
361
362// Augment command line with arguments from environment and .valgrindrc
363// files.
364static void augment_command_line(Int* vg_argc_inout, char*** vg_argv_inout)
365{
nethercotef6a1d502004-08-09 12:21:57 +0000366 int vg_argc0 = *vg_argc_inout;
367 char** vg_argv0 = *vg_argv_inout;
nethercote71980f02004-01-24 18:18:54 +0000368
njndcc99d32005-06-19 15:34:59 +0000369 // get_file_clo() allocates the return value with malloc(). We do not
370 // free f1_clo and f2_clo as they get put into vg_argv[] which must persist.
nethercote71980f02004-01-24 18:18:54 +0000371 char* env_clo = getenv(VALGRINDOPTS);
372 char* f1_clo = get_file_clo( getenv("HOME") );
373 char* f2_clo = get_file_clo(".");
374
375 /* copy any extra args from file or environment, if present */
376 if ( (env_clo && *env_clo) || (f1_clo && *f1_clo) || (f2_clo && *f2_clo) ) {
377 /* ' ' separated extra options */
378 char **from;
379 char **to;
thughescaca0022004-09-13 10:20:34 +0000380 int orig_arg_count, env_arg_count, f1_arg_count, f2_arg_count;
381
382 for ( orig_arg_count = 0; vg_argv0[orig_arg_count]; orig_arg_count++ );
383
nethercote71980f02004-01-24 18:18:54 +0000384 env_arg_count = count_args(env_clo);
385 f1_arg_count = count_args(f1_clo);
386 f2_arg_count = count_args(f2_clo);
387
388 if (0)
389 printf("extra-argc=%d %d %d\n",
390 env_arg_count, f1_arg_count, f2_arg_count);
391
392 /* +2: +1 for null-termination, +1 for added '--' */
nethercotef6a1d502004-08-09 12:21:57 +0000393 from = vg_argv0;
thughescaca0022004-09-13 10:20:34 +0000394 vg_argv0 = malloc( (orig_arg_count + env_arg_count + f1_arg_count
nethercote71980f02004-01-24 18:18:54 +0000395 + f2_arg_count + 2) * sizeof(char **));
nethercotef6a1d502004-08-09 12:21:57 +0000396 vg_assert(vg_argv0);
397 to = vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000398
399 /* copy argv[0] */
400 *to++ = *from++;
401
402 /* Copy extra args from env var and file, in the order: ~/.valgrindrc,
403 * $VALGRIND_OPTS, ./.valgrindrc -- more local options are put later
404 * to override less local ones. */
405 to = copy_args(f1_clo, to);
406 to = copy_args(env_clo, to);
407 to = copy_args(f2_clo, to);
njna96e15a2005-05-24 21:36:32 +0000408
nethercote71980f02004-01-24 18:18:54 +0000409 /* copy original arguments, stopping at command or -- */
410 while (*from) {
411 if (**from != '-')
412 break;
413 if (VG_STREQ(*from, "--")) {
414 from++; /* skip -- */
415 break;
416 }
417 *to++ = *from++;
418 }
419
420 /* add -- */
421 *to++ = "--";
422
nethercotef6a1d502004-08-09 12:21:57 +0000423 vg_argc0 = to - vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000424
425 /* copy rest of original command line, then NULL */
426 while (*from) *to++ = *from++;
427 *to = NULL;
428 }
429
nethercotef6a1d502004-08-09 12:21:57 +0000430 *vg_argc_inout = vg_argc0;
431 *vg_argv_inout = vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000432}
433
nethercotef6a1d502004-08-09 12:21:57 +0000434#define VG_CLO_SEP '\01'
435
nethercote71980f02004-01-24 18:18:54 +0000436static void get_command_line( int argc, char** argv,
437 Int* vg_argc_out, Char*** vg_argv_out,
438 char*** cl_argv_out )
439{
nethercotef6a1d502004-08-09 12:21:57 +0000440 int vg_argc0;
441 char** vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000442 char** cl_argv;
443 char* env_clo = getenv(VALGRINDCLO);
444
445 if (env_clo != NULL && *env_clo != '\0') {
446 char *cp;
447 char **cpp;
448
nethercotef6a1d502004-08-09 12:21:57 +0000449 /* OK, VALGRINDCLO is set, which means we must be a child of another
450 Valgrind process using --trace-children, so we're getting all our
451 arguments from VALGRINDCLO, and the entire command line belongs to
452 the client (including argv[0]) */
453 vg_argc0 = 1; /* argv[0] */
nethercote71980f02004-01-24 18:18:54 +0000454 for (cp = env_clo; *cp; cp++)
nethercotef6a1d502004-08-09 12:21:57 +0000455 if (*cp == VG_CLO_SEP)
456 vg_argc0++;
nethercote71980f02004-01-24 18:18:54 +0000457
nethercotef6a1d502004-08-09 12:21:57 +0000458 vg_argv0 = malloc(sizeof(char **) * (vg_argc0 + 1));
459 vg_assert(vg_argv0);
nethercote71980f02004-01-24 18:18:54 +0000460
nethercotef6a1d502004-08-09 12:21:57 +0000461 cpp = vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000462
463 *cpp++ = "valgrind"; /* nominal argv[0] */
464 *cpp++ = env_clo;
465
nethercotef6a1d502004-08-09 12:21:57 +0000466 // Replace the VG_CLO_SEP args separator with '\0'
nethercote71980f02004-01-24 18:18:54 +0000467 for (cp = env_clo; *cp; cp++) {
nethercotef6a1d502004-08-09 12:21:57 +0000468 if (*cp == VG_CLO_SEP) {
nethercote71980f02004-01-24 18:18:54 +0000469 *cp++ = '\0'; /* chop it up in place */
470 *cpp++ = cp;
471 }
472 }
473 *cpp = NULL;
474 cl_argv = argv;
475
476 } else {
sewardjb5f6f512005-03-10 23:59:00 +0000477 Bool noaugment = False;
478
nethercote71980f02004-01-24 18:18:54 +0000479 /* Count the arguments on the command line. */
nethercotef6a1d502004-08-09 12:21:57 +0000480 vg_argv0 = argv;
nethercote71980f02004-01-24 18:18:54 +0000481
nethercotef6a1d502004-08-09 12:21:57 +0000482 for (vg_argc0 = 1; vg_argc0 < argc; vg_argc0++) {
sewardjb5f6f512005-03-10 23:59:00 +0000483 Char* arg = argv[vg_argc0];
484 if (arg[0] != '-') /* exe name */
nethercote71980f02004-01-24 18:18:54 +0000485 break;
sewardjb5f6f512005-03-10 23:59:00 +0000486 if (VG_STREQ(arg, "--")) { /* dummy arg */
nethercotef6a1d502004-08-09 12:21:57 +0000487 vg_argc0++;
nethercote71980f02004-01-24 18:18:54 +0000488 break;
489 }
njn45270a22005-03-27 01:00:11 +0000490 VG_BOOL_CLO(arg, "--command-line-only", noaugment)
nethercote71980f02004-01-24 18:18:54 +0000491 }
nethercotef6a1d502004-08-09 12:21:57 +0000492 cl_argv = &argv[vg_argc0];
nethercote71980f02004-01-24 18:18:54 +0000493
494 /* Get extra args from VALGRIND_OPTS and .valgrindrc files.
nethercotef6a1d502004-08-09 12:21:57 +0000495 Note we don't do this if getting args from VALGRINDCLO, as
sewardjb5f6f512005-03-10 23:59:00 +0000496 those extra args will already be present in VALGRINDCLO.
497 (We also don't do it when --command-line-only=yes.) */
498 if (!noaugment)
499 augment_command_line(&vg_argc0, &vg_argv0);
nethercote71980f02004-01-24 18:18:54 +0000500 }
501
502 if (0) {
503 Int i;
nethercotef6a1d502004-08-09 12:21:57 +0000504 for (i = 0; i < vg_argc0; i++)
505 printf("vg_argv0[%d]=\"%s\"\n", i, vg_argv0[i]);
nethercote71980f02004-01-24 18:18:54 +0000506 }
507
nethercotef6a1d502004-08-09 12:21:57 +0000508 *vg_argc_out = vg_argc0;
509 *vg_argv_out = (Char**)vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000510 *cl_argv_out = cl_argv;
511}
512
513
514/*====================================================================*/
515/*=== Environment and stack setup ===*/
516/*====================================================================*/
517
518/* Scan a colon-separated list, and call a function on each element.
519 The string must be mutable, because we insert a temporary '\0', but
thughes4ad52d02004-06-27 17:37:21 +0000520 the string will end up unmodified. (*func) should return True if it
nethercote71980f02004-01-24 18:18:54 +0000521 doesn't need to see any more.
thughes4ad52d02004-06-27 17:37:21 +0000522
523 This routine will return True if (*func) returns True and False if
524 it reaches the end of the list without that happening.
nethercote71980f02004-01-24 18:18:54 +0000525*/
thughes4ad52d02004-06-27 17:37:21 +0000526static Bool scan_colsep(char *colsep, Bool (*func)(const char *))
nethercote71980f02004-01-24 18:18:54 +0000527{
528 char *cp, *entry;
529 int end;
530
531 if (colsep == NULL ||
532 *colsep == '\0')
thughes4ad52d02004-06-27 17:37:21 +0000533 return False;
nethercote71980f02004-01-24 18:18:54 +0000534
535 entry = cp = colsep;
536
537 do {
538 end = (*cp == '\0');
539
540 if (*cp == ':' || *cp == '\0') {
541 char save = *cp;
542
543 *cp = '\0';
thughes21942d92004-07-12 09:35:37 +0000544 if ((*func)(entry)) {
545 *cp = save;
thughes4ad52d02004-06-27 17:37:21 +0000546 return True;
thughes21942d92004-07-12 09:35:37 +0000547 }
nethercote71980f02004-01-24 18:18:54 +0000548 *cp = save;
549 entry = cp+1;
550 }
551 cp++;
552 } while(!end);
thughes4ad52d02004-06-27 17:37:21 +0000553
554 return False;
555}
556
nethercote71980f02004-01-24 18:18:54 +0000557/* Prepare the client's environment. This is basically a copy of our
558 environment, except:
njn16eeb4e2005-06-16 03:56:58 +0000559 LD_PRELOAD=$VALGRINDLIB/vg_preload_core.so:($VALGRINDLIB/vgpreload_TOOL.so:)?$LD_PRELOAD
nethercote71980f02004-01-24 18:18:54 +0000560
sewardjb5f6f512005-03-10 23:59:00 +0000561 If this is missing, then it is added.
nethercote71980f02004-01-24 18:18:54 +0000562
563 Yummy. String hacking in C.
564
565 If this needs to handle any more variables it should be hacked
566 into something table driven.
567 */
568static char **fix_environment(char **origenv, const char *preload)
569{
njn16eeb4e2005-06-16 03:56:58 +0000570 static const char preload_core_so[] = "vg_preload_core.so";
nethercote71980f02004-01-24 18:18:54 +0000571 static const char ld_preload[] = "LD_PRELOAD=";
572 static const char valgrind_clo[] = VALGRINDCLO "=";
nethercote71980f02004-01-24 18:18:54 +0000573 static const int ld_preload_len = sizeof(ld_preload)-1;
574 static const int valgrind_clo_len = sizeof(valgrind_clo)-1;
575 int ld_preload_done = 0;
njn16eeb4e2005-06-16 03:56:58 +0000576 char *preload_core_path;
577 int preload_core_path_len;
nethercote71980f02004-01-24 18:18:54 +0000578 int vgliblen = strlen(VG_(libdir));
579 char **cpp;
580 char **ret;
581 int envc;
582 const int preloadlen = (preload == NULL) ? 0 : strlen(preload);
583
njn16eeb4e2005-06-16 03:56:58 +0000584 /* Find the vg_preload_core.so; also make room for the tool preload
nethercote71980f02004-01-24 18:18:54 +0000585 library */
njn16eeb4e2005-06-16 03:56:58 +0000586 preload_core_path_len = sizeof(preload_core_so) + vgliblen + preloadlen + 16;
587 preload_core_path = malloc(preload_core_path_len);
588 vg_assert(preload_core_path);
nethercote71980f02004-01-24 18:18:54 +0000589
590 if (preload)
njn16eeb4e2005-06-16 03:56:58 +0000591 snprintf(preload_core_path, preload_core_path_len, "%s/%s:%s",
592 VG_(libdir), preload_core_so, preload);
nethercote71980f02004-01-24 18:18:54 +0000593 else
njn16eeb4e2005-06-16 03:56:58 +0000594 snprintf(preload_core_path, preload_core_path_len, "%s/%s",
595 VG_(libdir), preload_core_so);
nethercote71980f02004-01-24 18:18:54 +0000596
597 /* Count the original size of the env */
598 envc = 0; /* trailing NULL */
599 for (cpp = origenv; cpp && *cpp; cpp++)
600 envc++;
601
602 /* Allocate a new space */
sewardjb5f6f512005-03-10 23:59:00 +0000603 ret = malloc(sizeof(char *) * (envc+1+1)); /* 1 new entry + NULL */
nethercote7c018f42004-07-17 16:40:50 +0000604 vg_assert(ret);
nethercote71980f02004-01-24 18:18:54 +0000605
606 /* copy it over */
607 for (cpp = ret; *origenv; )
608 *cpp++ = *origenv++;
609 *cpp = NULL;
610
611 vg_assert(envc == (cpp - ret));
612
613 /* Walk over the new environment, mashing as we go */
614 for (cpp = ret; cpp && *cpp; cpp++) {
sewardjb5f6f512005-03-10 23:59:00 +0000615 if (memcmp(*cpp, ld_preload, ld_preload_len) == 0) {
njn16eeb4e2005-06-16 03:56:58 +0000616 int len = strlen(*cpp) + preload_core_path_len;
nethercote71980f02004-01-24 18:18:54 +0000617 char *cp = malloc(len);
nethercote7c018f42004-07-17 16:40:50 +0000618 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000619
620 snprintf(cp, len, "%s%s:%s",
njn16eeb4e2005-06-16 03:56:58 +0000621 ld_preload, preload_core_path, (*cpp)+ld_preload_len);
nethercote71980f02004-01-24 18:18:54 +0000622
623 *cpp = cp;
624
625 ld_preload_done = 1;
626 } else if (memcmp(*cpp, valgrind_clo, valgrind_clo_len) == 0) {
627 *cpp = "";
628 }
629 }
630
631 /* Add the missing bits */
nethercote71980f02004-01-24 18:18:54 +0000632 if (!ld_preload_done) {
njn16eeb4e2005-06-16 03:56:58 +0000633 int len = ld_preload_len + preload_core_path_len;
nethercote71980f02004-01-24 18:18:54 +0000634 char *cp = malloc(len);
nethercote7c018f42004-07-17 16:40:50 +0000635 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000636
njn16eeb4e2005-06-16 03:56:58 +0000637 snprintf(cp, len, "%s%s", ld_preload, preload_core_path);
nethercote71980f02004-01-24 18:18:54 +0000638
639 ret[envc++] = cp;
640 }
641
njn16eeb4e2005-06-16 03:56:58 +0000642 free(preload_core_path);
nethercote71980f02004-01-24 18:18:54 +0000643 ret[envc] = NULL;
644
645 return ret;
646}
647
648extern char **environ; /* our environment */
nethercote71980f02004-01-24 18:18:54 +0000649
650/* Add a string onto the string table, and return its address */
651static char *copy_str(char **tab, const char *str)
652{
653 char *cp = *tab;
654 char *orig = cp;
655
656 while(*str)
657 *cp++ = *str++;
658 *cp++ = '\0';
659
660 if (0)
nethercote545fe672004-11-01 16:52:43 +0000661 printf("copied %p \"%s\" len %lld\n", orig, orig, (Long)(cp-orig));
nethercote71980f02004-01-24 18:18:54 +0000662
663 *tab = cp;
664
665 return orig;
666}
667
668/*
669 This sets up the client's initial stack, containing the args,
670 environment and aux vector.
671
672 The format of the stack is:
673
674 higher address +-----------------+
675 | Trampoline code |
676 +-----------------+
677 | |
678 : string table :
679 | |
680 +-----------------+
681 | AT_NULL |
682 - -
683 | auxv |
684 +-----------------+
685 | NULL |
686 - -
687 | envp |
688 +-----------------+
689 | NULL |
690 - -
691 | argv |
692 +-----------------+
693 | argc |
nethercote4ad74312004-10-26 09:59:49 +0000694 lower address +-----------------+ <- sp
nethercote71980f02004-01-24 18:18:54 +0000695 | undefined |
696 : :
697 */
nethercotec25c4492004-10-18 11:52:17 +0000698static Addr setup_client_stack(void* init_sp,
699 char **orig_argv, char **orig_envp,
nethercote71980f02004-01-24 18:18:54 +0000700 const struct exeinfo *info,
701 UInt** client_auxv)
702{
njn83407492005-06-19 16:10:47 +0000703 SysRes res;
nethercote71980f02004-01-24 18:18:54 +0000704 char **cpp;
705 char *strtab; /* string table */
706 char *stringbase;
nethercotea3c3cf22004-11-01 18:38:00 +0000707 Addr *ptr;
nethercote71980f02004-01-24 18:18:54 +0000708 struct ume_auxv *auxv;
709 const struct ume_auxv *orig_auxv;
710 const struct ume_auxv *cauxv;
711 unsigned stringsize; /* total size of strings in bytes */
712 unsigned auxsize; /* total size of auxv in bytes */
713 int argc; /* total argc */
714 int envc; /* total number of env vars */
715 unsigned stacksize; /* total client stack size */
nethercotea3c3cf22004-11-01 18:38:00 +0000716 Addr cl_esp; /* client stack base (initial esp) */
nethercote71980f02004-01-24 18:18:54 +0000717
718 /* use our own auxv as a prototype */
njn62ff0f22005-06-21 23:03:36 +0000719 orig_auxv = VG_(find_auxv)(init_sp);
nethercote71980f02004-01-24 18:18:54 +0000720
721 /* ==================== compute sizes ==================== */
722
723 /* first of all, work out how big the client stack will be */
724 stringsize = 0;
725
726 /* paste on the extra args if the loader needs them (ie, the #!
727 interpreter and its argument) */
728 argc = 0;
nethercoted6a56872004-07-26 15:32:47 +0000729 if (info->interp_name != NULL) {
nethercote71980f02004-01-24 18:18:54 +0000730 argc++;
nethercoted6a56872004-07-26 15:32:47 +0000731 stringsize += strlen(info->interp_name) + 1;
nethercote71980f02004-01-24 18:18:54 +0000732 }
nethercoted6a56872004-07-26 15:32:47 +0000733 if (info->interp_args != NULL) {
nethercote71980f02004-01-24 18:18:54 +0000734 argc++;
nethercoted6a56872004-07-26 15:32:47 +0000735 stringsize += strlen(info->interp_args) + 1;
nethercote71980f02004-01-24 18:18:54 +0000736 }
737
738 /* now scan the args we're given... */
739 for (cpp = orig_argv; *cpp; cpp++) {
740 argc++;
741 stringsize += strlen(*cpp) + 1;
742 }
743
744 /* ...and the environment */
745 envc = 0;
746 for (cpp = orig_envp; cpp && *cpp; cpp++) {
747 envc++;
748 stringsize += strlen(*cpp) + 1;
749 }
750
751 /* now, how big is the auxv? */
752 auxsize = sizeof(*auxv); /* there's always at least one entry: AT_NULL */
753 for (cauxv = orig_auxv; cauxv->a_type != AT_NULL; cauxv++) {
754 if (cauxv->a_type == AT_PLATFORM)
755 stringsize += strlen(cauxv->u.a_ptr) + 1;
756 auxsize += sizeof(*cauxv);
757 }
758
cerion85665ca2005-06-20 15:51:07 +0000759#if defined(VGP_ppc32_linux)
760 auxsize += 2 * sizeof(*cauxv);
761#endif
762
nethercote71980f02004-01-24 18:18:54 +0000763 /* OK, now we know how big the client stack is */
764 stacksize =
sewardj9d9cdea2005-03-23 03:06:30 +0000765 sizeof(Word) + /* argc */
nethercote71980f02004-01-24 18:18:54 +0000766 sizeof(char **)*argc + /* argv */
767 sizeof(char **) + /* terminal NULL */
768 sizeof(char **)*envc + /* envp */
769 sizeof(char **) + /* terminal NULL */
770 auxsize + /* auxv */
njn13bfd852005-06-02 03:52:53 +0000771 VG_ROUNDUP(stringsize, sizeof(Word)) +/* strings (aligned) */
nethercote5fd72bb2004-11-04 19:28:38 +0000772 VKI_PAGE_SIZE; /* page for trampoline code */
nethercote71980f02004-01-24 18:18:54 +0000773
sewardj79048ce2005-02-18 08:28:32 +0000774 if (0) VG_(printf)("stacksize = %d\n", stacksize);
775
nethercotef84f6952004-07-15 14:58:33 +0000776 // decide where stack goes!
777 VG_(clstk_end) = VG_(client_end);
778
nethercote71980f02004-01-24 18:18:54 +0000779 /* cl_esp is the client's stack pointer */
nethercotef84f6952004-07-15 14:58:33 +0000780 cl_esp = VG_(clstk_end) - stacksize;
njn13bfd852005-06-02 03:52:53 +0000781 cl_esp = VG_ROUNDDN(cl_esp, 16); /* make stack 16 byte aligned */
nethercote71980f02004-01-24 18:18:54 +0000782
nethercote71980f02004-01-24 18:18:54 +0000783 /* base of the string table (aligned) */
sewardjb9bce632005-06-21 01:41:34 +0000784 stringbase = strtab = (char *)(VG_(clstk_end)
njn13bfd852005-06-02 03:52:53 +0000785 - VG_ROUNDUP(stringsize, sizeof(int)));
nethercote71980f02004-01-24 18:18:54 +0000786
njn13bfd852005-06-02 03:52:53 +0000787 VG_(clstk_base) = VG_PGROUNDDN(cl_esp);
nethercote71980f02004-01-24 18:18:54 +0000788
sewardj79048ce2005-02-18 08:28:32 +0000789 if (0)
nethercote5ee67ca2004-06-22 14:00:09 +0000790 printf("stringsize=%d auxsize=%d stacksize=%d\n"
nethercote6a27d832004-09-07 10:17:02 +0000791 "clstk_base %p\n"
792 "clstk_end %p\n",
793 stringsize, auxsize, stacksize,
794 (void*)VG_(clstk_base), (void*)VG_(clstk_end));
nethercote5ee67ca2004-06-22 14:00:09 +0000795
nethercote71980f02004-01-24 18:18:54 +0000796 /* ==================== allocate space ==================== */
797
798 /* allocate a stack - mmap enough space for the stack */
njn83407492005-06-19 16:10:47 +0000799 res = VG_(mmap_native)((void *)VG_PGROUNDDN(cl_esp),
njn13bfd852005-06-02 03:52:53 +0000800 VG_(clstk_end) - VG_PGROUNDDN(cl_esp),
njn83407492005-06-19 16:10:47 +0000801 VKI_PROT_READ|VKI_PROT_WRITE|VKI_PROT_EXEC,
802 VKI_MAP_PRIVATE|VKI_MAP_ANONYMOUS|VKI_MAP_FIXED, -1, 0);
803 vg_assert(!res.isError);
nethercote71980f02004-01-24 18:18:54 +0000804
805 /* ==================== copy client stack ==================== */
806
nethercotea3c3cf22004-11-01 18:38:00 +0000807 ptr = (Addr*)cl_esp;
nethercote71980f02004-01-24 18:18:54 +0000808
809 /* --- argc --- */
810 *ptr++ = argc; /* client argc */
811
812 /* --- argv --- */
nethercoted6a56872004-07-26 15:32:47 +0000813 if (info->interp_name) {
nethercotea3c3cf22004-11-01 18:38:00 +0000814 *ptr++ = (Addr)copy_str(&strtab, info->interp_name);
nethercoted6a56872004-07-26 15:32:47 +0000815 free(info->interp_name);
nethercote71980f02004-01-24 18:18:54 +0000816 }
nethercoted6a56872004-07-26 15:32:47 +0000817 if (info->interp_args) {
nethercotea3c3cf22004-11-01 18:38:00 +0000818 *ptr++ = (Addr)copy_str(&strtab, info->interp_args);
nethercoted6a56872004-07-26 15:32:47 +0000819 free(info->interp_args);
nethercote71980f02004-01-24 18:18:54 +0000820 }
821 for (cpp = orig_argv; *cpp; ptr++, cpp++) {
nethercotea3c3cf22004-11-01 18:38:00 +0000822 *ptr = (Addr)copy_str(&strtab, *cpp);
nethercote71980f02004-01-24 18:18:54 +0000823 }
824 *ptr++ = 0;
825
826 /* --- envp --- */
827 VG_(client_envp) = (Char **)ptr;
828 for (cpp = orig_envp; cpp && *cpp; ptr++, cpp++)
nethercotea3c3cf22004-11-01 18:38:00 +0000829 *ptr = (Addr)copy_str(&strtab, *cpp);
nethercote71980f02004-01-24 18:18:54 +0000830 *ptr++ = 0;
831
832 /* --- auxv --- */
833 auxv = (struct ume_auxv *)ptr;
834 *client_auxv = (UInt *)auxv;
835
cerion85665ca2005-06-20 15:51:07 +0000836#if defined(VGP_ppc32_linux)
837 auxv[0].a_type = AT_IGNOREPPC;
838 auxv[0].u.a_val = AT_IGNOREPPC;
839 auxv[1].a_type = AT_IGNOREPPC;
840 auxv[1].u.a_val = AT_IGNOREPPC;
841 auxv += 2;
842#endif
843
nethercote71980f02004-01-24 18:18:54 +0000844 for (; orig_auxv->a_type != AT_NULL; auxv++, orig_auxv++) {
845 /* copy the entry... */
846 *auxv = *orig_auxv;
847
848 /* ...and fix up the copy */
849 switch(auxv->a_type) {
850 case AT_PHDR:
851 if (info->phdr == 0)
852 auxv->a_type = AT_IGNORE;
853 else
854 auxv->u.a_val = info->phdr;
855 break;
856
857 case AT_PHNUM:
858 if (info->phdr == 0)
859 auxv->a_type = AT_IGNORE;
860 else
861 auxv->u.a_val = info->phnum;
862 break;
863
864 case AT_BASE:
sewardjb5f6f512005-03-10 23:59:00 +0000865 auxv->u.a_val = info->interp_base;
nethercote71980f02004-01-24 18:18:54 +0000866 break;
867
868 case AT_PLATFORM: /* points to a platform description string */
869 auxv->u.a_ptr = copy_str(&strtab, orig_auxv->u.a_ptr);
870 break;
871
872 case AT_ENTRY:
873 auxv->u.a_val = info->entry;
874 break;
875
876 case AT_IGNORE:
877 case AT_EXECFD:
878 case AT_PHENT:
879 case AT_PAGESZ:
880 case AT_FLAGS:
881 case AT_NOTELF:
882 case AT_UID:
883 case AT_EUID:
884 case AT_GID:
885 case AT_EGID:
886 case AT_CLKTCK:
887 case AT_HWCAP:
888 case AT_FPUCW:
889 case AT_DCACHEBSIZE:
890 case AT_ICACHEBSIZE:
891 case AT_UCACHEBSIZE:
cerion85665ca2005-06-20 15:51:07 +0000892#if defined(VGP_ppc32_linux)
893 case AT_IGNOREPPC:
894#endif
nethercote71980f02004-01-24 18:18:54 +0000895 /* All these are pointerless, so we don't need to do anything
896 about them. */
897 break;
898
899 case AT_SECURE:
900 /* If this is 1, then it means that this program is running
901 suid, and therefore the dynamic linker should be careful
902 about LD_PRELOAD, etc. However, since stage1 (the thing
903 the kernel actually execve's) should never be SUID, and we
sewardjb5f6f512005-03-10 23:59:00 +0000904 need LD_PRELOAD to work for the client, we
nethercote71980f02004-01-24 18:18:54 +0000905 set AT_SECURE to 0. */
906 auxv->u.a_val = 0;
907 break;
908
909 case AT_SYSINFO:
910 /* Leave this unmolested for now, but we'll update it later
911 when we set up the client trampoline code page */
912 break;
913
cerion85665ca2005-06-20 15:51:07 +0000914#if !defined(VGP_ppc32_linux)
nethercote71980f02004-01-24 18:18:54 +0000915 case AT_SYSINFO_EHDR:
916 /* Trash this, because we don't reproduce it */
917 auxv->a_type = AT_IGNORE;
918 break;
cerion85665ca2005-06-20 15:51:07 +0000919#endif
nethercote71980f02004-01-24 18:18:54 +0000920
921 default:
922 /* stomp out anything we don't know about */
njn37569252005-06-21 00:28:43 +0000923 if (0)
nethercote545fe672004-11-01 16:52:43 +0000924 printf("stomping auxv entry %lld\n", (ULong)auxv->a_type);
nethercote71980f02004-01-24 18:18:54 +0000925 auxv->a_type = AT_IGNORE;
926 break;
927
928 }
929 }
930 *auxv = *orig_auxv;
931 vg_assert(auxv->a_type == AT_NULL);
932
933 vg_assert((strtab-stringbase) == stringsize);
934
nethercote5ee67ca2004-06-22 14:00:09 +0000935 /* We know the initial ESP is pointing at argc/argv */
936 VG_(client_argc) = *(Int*)cl_esp;
sewardj45f02c42005-02-05 18:27:14 +0000937 VG_(client_argv) = (Char**)(cl_esp + sizeof(HWord));
nethercote5ee67ca2004-06-22 14:00:09 +0000938
sewardj79048ce2005-02-18 08:28:32 +0000939 if (0) VG_(printf)("startup SP = %p\n", cl_esp);
nethercote71980f02004-01-24 18:18:54 +0000940 return cl_esp;
941}
942
943/*====================================================================*/
944/*=== Find executable ===*/
945/*====================================================================*/
946
thughes4ad52d02004-06-27 17:37:21 +0000947static const char* executable_name;
948
949static Bool match_executable(const char *entry) {
950 char buf[strlen(entry) + strlen(executable_name) + 2];
951
952 /* empty PATH element means . */
953 if (*entry == '\0')
954 entry = ".";
955
956 snprintf(buf, sizeof(buf), "%s/%s", entry, executable_name);
957
958 if (access(buf, R_OK|X_OK) == 0) {
959 executable_name = strdup(buf);
960 vg_assert(NULL != executable_name);
961 return True;
962 }
963 return False;
964}
965
nethercote71980f02004-01-24 18:18:54 +0000966static const char* find_executable(const char* exec)
967{
968 vg_assert(NULL != exec);
thughes4ad52d02004-06-27 17:37:21 +0000969 executable_name = exec;
970 if (strchr(executable_name, '/') == NULL) {
nethercote71980f02004-01-24 18:18:54 +0000971 /* no '/' - we need to search the path */
972 char *path = getenv("PATH");
thughes4ad52d02004-06-27 17:37:21 +0000973 scan_colsep(path, match_executable);
nethercote71980f02004-01-24 18:18:54 +0000974 }
thughes4ad52d02004-06-27 17:37:21 +0000975 return executable_name;
nethercote71980f02004-01-24 18:18:54 +0000976}
977
978
979/*====================================================================*/
980/*=== Loading tools ===*/
981/*====================================================================*/
982
983static void list_tools(void)
984{
985 DIR *dir = opendir(VG_(libdir));
986 struct dirent *de;
987 int first = 1;
988
989 if (dir == NULL) {
990 fprintf(stderr, "Can't open %s: %s (installation problem?)\n",
nethercotef4928da2004-06-15 10:54:40 +0000991 VG_(libdir), strerror(errno));
nethercote71980f02004-01-24 18:18:54 +0000992 return;
993 }
994
nethercotef4928da2004-06-15 10:54:40 +0000995 while ((de = readdir(dir)) != NULL) {
nethercote71980f02004-01-24 18:18:54 +0000996 int len = strlen(de->d_name);
997
njn063c5402004-11-22 16:58:05 +0000998 /* look for vgtool_TOOL.so names */
999 if (len > (7+1+3) && /* "vgtool_" + at least 1-char toolname + ".so" */
1000 strncmp(de->d_name, "vgtool_", 7) == 0 &&
nethercotef4928da2004-06-15 10:54:40 +00001001 VG_STREQ(de->d_name + len - 3, ".so")) {
1002 if (first) {
1003 fprintf(stderr, "Available tools:\n");
1004 first = 0;
1005 }
1006 de->d_name[len-3] = '\0';
1007 fprintf(stderr, "\t%s\n", de->d_name+7);
nethercote71980f02004-01-24 18:18:54 +00001008 }
1009 }
1010
1011 closedir(dir);
1012
1013 if (first)
nethercotef4928da2004-06-15 10:54:40 +00001014 fprintf(stderr, "No tools available in \"%s\" (installation problem?)\n",
1015 VG_(libdir));
nethercote71980f02004-01-24 18:18:54 +00001016}
1017
1018
1019/* Find and load a tool, and check it looks ok. Also looks to see if there's
1020 * a matching vgpreload_*.so file, and returns its name in *preloadpath. */
njn8a97c6d2005-03-31 04:37:24 +00001021static void load_tool( const char *toolname,
nethercote71980f02004-01-24 18:18:54 +00001022 ToolInfo** toolinfo_out, char **preloadpath_out )
1023{
1024 Bool ok;
sewardjb5f6f512005-03-10 23:59:00 +00001025 int len = strlen(VG_(libdir)) + strlen(toolname) + 16;
nethercote71980f02004-01-24 18:18:54 +00001026 char buf[len];
1027 void* handle;
1028 ToolInfo* toolinfo;
1029 char* preloadpath = NULL;
nethercote71980f02004-01-24 18:18:54 +00001030
1031 // XXX: allowing full paths for --tool option -- does it make sense?
1032 // Doesn't allow for vgpreload_<tool>.so.
1033
1034 if (strchr(toolname, '/') != 0) {
1035 /* toolname contains '/', and so must be a pathname */
1036 handle = dlopen(toolname, RTLD_NOW);
1037 } else {
1038 /* just try in the libdir */
njn063c5402004-11-22 16:58:05 +00001039 snprintf(buf, len, "%s/vgtool_%s.so", VG_(libdir), toolname);
nethercote71980f02004-01-24 18:18:54 +00001040 handle = dlopen(buf, RTLD_NOW);
1041
1042 if (handle != NULL) {
1043 snprintf(buf, len, "%s/vgpreload_%s.so", VG_(libdir), toolname);
1044 if (access(buf, R_OK) == 0) {
1045 preloadpath = strdup(buf);
1046 vg_assert(NULL != preloadpath);
1047 }
1048 }
1049 }
1050
1051 ok = (NULL != handle);
1052 if (!ok) {
1053 fprintf(stderr, "Can't open tool \"%s\": %s\n", toolname, dlerror());
1054 goto bad_load;
1055 }
1056
njn51d827b2005-05-09 01:02:08 +00001057 toolinfo = dlsym(handle, "vgPlain_tool_info");
nethercote71980f02004-01-24 18:18:54 +00001058 ok = (NULL != toolinfo);
1059 if (!ok) {
njn51d827b2005-05-09 01:02:08 +00001060 fprintf(stderr, "Tool \"%s\" doesn't define its ToolInfo - "
nethercote71980f02004-01-24 18:18:54 +00001061 "add VG_DETERMINE_INTERFACE_VERSION?\n", toolname);
1062 goto bad_load;
1063 }
1064
1065 ok = (toolinfo->sizeof_ToolInfo == sizeof(*toolinfo) &&
njn51d827b2005-05-09 01:02:08 +00001066 toolinfo->interface_version == VG_CORE_INTERFACE_VERSION &&
1067 toolinfo->tl_pre_clo_init != NULL);
nethercote71980f02004-01-24 18:18:54 +00001068 if (!ok) {
1069 fprintf(stderr, "Error:\n"
1070 " Tool and core interface versions do not match.\n"
njn51d827b2005-05-09 01:02:08 +00001071 " Interface version used by core is: %d (size %d)\n"
1072 " Interface version used by tool is: %d (size %d)\n"
1073 " The version numbers must match.\n",
1074 VG_CORE_INTERFACE_VERSION,
nethercote545fe672004-11-01 16:52:43 +00001075 (Int)sizeof(*toolinfo),
njn51d827b2005-05-09 01:02:08 +00001076 toolinfo->interface_version,
nethercote71980f02004-01-24 18:18:54 +00001077 toolinfo->sizeof_ToolInfo);
1078 fprintf(stderr, " You need to at least recompile, and possibly update,\n");
njn51d827b2005-05-09 01:02:08 +00001079 if (VG_CORE_INTERFACE_VERSION > toolinfo->interface_version)
nethercote996901a2004-08-03 13:29:09 +00001080 fprintf(stderr, " your tool to work with this version of Valgrind.\n");
nethercote71980f02004-01-24 18:18:54 +00001081 else
nethercote996901a2004-08-03 13:29:09 +00001082 fprintf(stderr, " your version of Valgrind to work with this tool.\n");
nethercote71980f02004-01-24 18:18:54 +00001083 goto bad_load;
1084 }
1085
njn8a97c6d2005-03-31 04:37:24 +00001086 vg_assert(NULL != toolinfo);
nethercote71980f02004-01-24 18:18:54 +00001087 *toolinfo_out = toolinfo;
1088 *preloadpath_out = preloadpath;
1089 return;
1090
1091
1092 bad_load:
1093 if (handle != NULL)
1094 dlclose(handle);
1095
nethercotef4928da2004-06-15 10:54:40 +00001096 fprintf(stderr, "valgrind: couldn't load tool\n");
nethercote71980f02004-01-24 18:18:54 +00001097 list_tools();
1098 exit(127);
1099}
1100
nethercotef4928da2004-06-15 10:54:40 +00001101
1102/*====================================================================*/
1103/*=== Command line errors ===*/
1104/*====================================================================*/
1105
njnbe9b47b2005-05-15 16:22:58 +00001106static void revert_to_stderr ( void )
nethercotef4928da2004-06-15 10:54:40 +00001107{
njnbe9b47b2005-05-15 16:22:58 +00001108 vg_assert( !VG_(logging_to_socket) );
nethercotef8548672004-06-21 12:42:35 +00001109 VG_(clo_log_fd) = 2; /* stderr */
nethercotef4928da2004-06-15 10:54:40 +00001110}
1111
1112void VG_(bad_option) ( Char* opt )
1113{
njnbe9b47b2005-05-15 16:22:58 +00001114 revert_to_stderr();
njn02bc4b82005-05-15 17:28:26 +00001115 VG_(printf)("valgrind: Bad option '%s'; aborting.\n", opt);
nethercotef4928da2004-06-15 10:54:40 +00001116 VG_(printf)("valgrind: Use --help for more information.\n");
1117 VG_(exit)(1);
1118}
1119
nethercotef4928da2004-06-15 10:54:40 +00001120static void missing_prog ( void )
1121{
njnbe9b47b2005-05-15 16:22:58 +00001122 revert_to_stderr();
nethercotef4928da2004-06-15 10:54:40 +00001123 VG_(printf)("valgrind: no program specified\n");
1124 VG_(printf)("valgrind: Use --help for more information.\n");
1125 VG_(exit)(1);
1126}
1127
1128static void config_error ( Char* msg )
1129{
njnbe9b47b2005-05-15 16:22:58 +00001130 revert_to_stderr();
nethercotef4928da2004-06-15 10:54:40 +00001131 VG_(printf)("valgrind: Startup or configuration error:\n %s\n", msg);
1132 VG_(printf)("valgrind: Unable to start up properly. Giving up.\n");
1133 VG_(exit)(1);
1134}
1135
1136
nethercote71980f02004-01-24 18:18:54 +00001137/*====================================================================*/
1138/*=== Loading the client ===*/
1139/*====================================================================*/
1140
nethercotef4928da2004-06-15 10:54:40 +00001141static void load_client(char* cl_argv[], const char* exec, Int need_help,
nethercote71980f02004-01-24 18:18:54 +00001142 /*out*/struct exeinfo* info, /*out*/Addr* client_eip)
1143{
1144 // If they didn't specify an executable with --exec, and didn't specify
1145 // --help, then use client argv[0] (searching $PATH if necessary).
nethercotef4928da2004-06-15 10:54:40 +00001146 if (NULL == exec && !need_help) {
nethercote71980f02004-01-24 18:18:54 +00001147 if (cl_argv[0] == NULL ||
1148 ( NULL == (exec = find_executable(cl_argv[0])) ) )
1149 {
nethercotef4928da2004-06-15 10:54:40 +00001150 missing_prog();
nethercote71980f02004-01-24 18:18:54 +00001151 }
1152 }
1153
1154 info->map_base = VG_(client_mapbase);
nethercote71980f02004-01-24 18:18:54 +00001155 info->exe_base = VG_(client_base);
1156 info->exe_end = VG_(client_end);
1157 info->argv = cl_argv;
1158
nethercotef4928da2004-06-15 10:54:40 +00001159 if (need_help) {
nethercote71980f02004-01-24 18:18:54 +00001160 VG_(clexecfd) = -1;
njnc8c93282004-11-29 16:05:54 +00001161 // Totally zero 'info' before continuing.
1162 VG_(memset)(info, 0, sizeof(*info));
nethercote71980f02004-01-24 18:18:54 +00001163 } else {
1164 Int ret;
nethercote4ec0af42004-10-16 15:31:49 +00001165 VG_(clexecfd) = VG_(open)(exec, VKI_O_RDONLY, VKI_S_IRUSR);
njn62ff0f22005-06-21 23:03:36 +00001166 ret = VG_(do_exec)(exec, info);
nethercote71980f02004-01-24 18:18:54 +00001167 if (ret != 0) {
nethercoteea147e72004-07-26 15:43:57 +00001168 fprintf(stderr, "valgrind: do_exec(%s) failed: %s\n",
1169 exec, strerror(ret));
nethercote71980f02004-01-24 18:18:54 +00001170 exit(127);
1171 }
1172 }
1173
1174 /* Copy necessary bits of 'info' that were filled in */
1175 *client_eip = info->init_eip;
1176 VG_(brk_base) = VG_(brk_limit) = info->brkbase;
1177}
1178
nethercote969ecf12004-10-13 17:29:01 +00001179/*====================================================================*/
1180/*=== Address space unpadding ===*/
1181/*====================================================================*/
1182
1183typedef struct {
njn909c3192005-06-19 15:46:27 +00001184 char* killpad_start;
1185 char* killpad_end;
1186 struct vki_stat* killpad_padstat;
nethercote969ecf12004-10-13 17:29:01 +00001187} killpad_extra;
1188
1189static int killpad(char *segstart, char *segend, const char *perm, off_t off,
1190 int maj, int min, int ino, void* ex)
1191{
1192 killpad_extra* extra = ex;
1193 void *b, *e;
njn83407492005-06-19 16:10:47 +00001194 SysRes res;
nethercote969ecf12004-10-13 17:29:01 +00001195
1196 vg_assert(NULL != extra->killpad_padstat);
1197
1198 if (extra->killpad_padstat->st_dev != makedev(maj, min) ||
1199 extra->killpad_padstat->st_ino != ino)
1200 return 1;
1201
1202 if (segend <= extra->killpad_start || segstart >= extra->killpad_end)
1203 return 1;
1204
1205 if (segstart <= extra->killpad_start)
1206 b = extra->killpad_start;
1207 else
1208 b = segstart;
1209
1210 if (segend >= extra->killpad_end)
1211 e = extra->killpad_end;
1212 else
1213 e = segend;
1214
njn83407492005-06-19 16:10:47 +00001215 res = VG_(munmap_native)(b, (char *)e-(char *)b);
1216 vg_assert(!res.isError);
nethercote969ecf12004-10-13 17:29:01 +00001217
1218 return 1;
1219}
1220
1221// Remove padding of 'padfile' from a range of address space.
sewardj2c5ffbe2005-03-12 13:32:06 +00001222static void as_unpad(void *start, void *end, int padfile)
nethercote969ecf12004-10-13 17:29:01 +00001223{
njn909c3192005-06-19 15:46:27 +00001224 static struct vki_stat padstat;
nethercote969ecf12004-10-13 17:29:01 +00001225 killpad_extra extra;
1226 int res;
1227
sewardjb5f6f512005-03-10 23:59:00 +00001228 vg_assert(padfile >= 0);
nethercote969ecf12004-10-13 17:29:01 +00001229
njn909c3192005-06-19 15:46:27 +00001230 res = VG_(fstat)(padfile, &padstat);
nethercote969ecf12004-10-13 17:29:01 +00001231 vg_assert(0 == res);
1232 extra.killpad_padstat = &padstat;
1233 extra.killpad_start = start;
1234 extra.killpad_end = end;
njn62ff0f22005-06-21 23:03:36 +00001235 VG_(foreach_map)(killpad, &extra);
nethercote969ecf12004-10-13 17:29:01 +00001236}
1237
sewardj2c5ffbe2005-03-12 13:32:06 +00001238static void as_closepadfile(int padfile)
nethercote969ecf12004-10-13 17:29:01 +00001239{
1240 int res = close(padfile);
1241 vg_assert(0 == res);
1242}
1243
sewardj71bc3cb2005-05-19 00:25:45 +00001244/*====================================================================*/
1245/*=== Command-line: variables, processing, etc ===*/
1246/*====================================================================*/
1247
1248// See pub_{core,tool}_options.h for explanations of all these.
1249
sewardj2c5ffbe2005-03-12 13:32:06 +00001250static void usage ( Bool debug_help )
njn7cf0bd32002-06-08 13:36:03 +00001251{
njn25e49d8e72002-09-23 09:36:25 +00001252 Char* usage1 =
nethercote71980f02004-01-24 18:18:54 +00001253"usage: valgrind --tool=<toolname> [options] prog-and-args\n"
njn25e49d8e72002-09-23 09:36:25 +00001254"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001255" common user options for all Valgrind tools, with defaults in [ ]:\n"
sewardjb5f6f512005-03-10 23:59:00 +00001256" --tool=<name> use the Valgrind tool named <name> [memcheck]\n"
nethercotea76368b2004-06-16 11:56:29 +00001257" -h --help show this message\n"
nethercote6c999f22004-01-31 22:55:15 +00001258" --help-debug show this message, plus debugging options\n"
njn25e49d8e72002-09-23 09:36:25 +00001259" --version show version\n"
njn25e49d8e72002-09-23 09:36:25 +00001260" -q --quiet run silently; only print error msgs\n"
1261" -v --verbose be more verbose, incl counts of errors\n"
sewardjf178c302005-05-20 02:02:10 +00001262" --xml=yes all output is in XML (Memcheck only)\n"
nethercote77eba602003-11-13 17:35:04 +00001263" --trace-children=no|yes Valgrind-ise child processes? [no]\n"
nethercote0d588502004-06-21 13:27:11 +00001264" --track-fds=no|yes track open file descriptors? [no]\n"
thughes6233a382004-08-21 11:10:44 +00001265" --time-stamp=no|yes add timestamps to log messages? [no]\n"
nethercote2b0793f2003-12-02 10:41:18 +00001266"\n"
1267" uncommon user options for all Valgrind tools:\n"
nethercote0d588502004-06-21 13:27:11 +00001268" --run-libc-freeres=no|yes free up glibc memory at exit? [yes]\n"
sewardjb5f6f512005-03-10 23:59:00 +00001269" --weird-hacks=hack1,hack2,... recognised hacks: lax-ioctls,ioctl-mmap [none]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001270" --pointercheck=no|yes enforce client address space limits [yes]\n"
sewardj062f3552005-01-06 16:13:40 +00001271" --support-elan3=no|yes hacks for Quadrics Elan3 support [no]\n"
sewardjb1131a82005-03-19 15:12:21 +00001272" --show-emwarns=no|yes show warnings about emulation limits? [no]\n"
njn25e49d8e72002-09-23 09:36:25 +00001273"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001274" user options for Valgrind tools that report errors:\n"
nethercotef8548672004-06-21 12:42:35 +00001275" --log-fd=<number> log messages to file descriptor [2=stderr]\n"
1276" --log-file=<file> log messages to <file>.pid<pid>\n"
sewardj603d4102005-01-11 14:01:02 +00001277" --log-file-exactly=<file> log messages to <file>\n"
nethercotef8548672004-06-21 12:42:35 +00001278" --log-socket=ipaddr:port log messages to socket ipaddr:port\n"
nethercote2b0793f2003-12-02 10:41:18 +00001279" --demangle=no|yes automatically demangle C++ names? [yes]\n"
njncc6cc142005-03-12 20:59:29 +00001280" --num-callers=<number> show <num> callers in stack traces [12]\n"
nethercote2b0793f2003-12-02 10:41:18 +00001281" --error-limit=no|yes stop showing new errors if too many? [yes]\n"
1282" --show-below-main=no|yes continue stack traces below main() [no]\n"
1283" --suppressions=<filename> suppress errors described in <filename>\n"
sewardjd153fae2005-01-10 17:24:47 +00001284" --gen-suppressions=no|yes|all print suppressions for errors? [no]\n"
nethercote04d0fbc2004-01-26 16:48:06 +00001285" --db-attach=no|yes start debugger when errors detected? [no]\n"
1286" --db-command=<command> command to start debugger [gdb -nw %%f %%p]\n"
1287" --input-fd=<number> file descriptor for input [0=stdin]\n"
sewardj97724e52005-04-02 23:40:59 +00001288" --max-stackframe=<number> assume stack switch for SP changes larger\n"
1289" than <number> bytes [2000000]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001290"\n";
njn7cf0bd32002-06-08 13:36:03 +00001291
njn25e49d8e72002-09-23 09:36:25 +00001292 Char* usage2 =
1293"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001294" debugging options for all Valgrind tools:\n"
njn25e49d8e72002-09-23 09:36:25 +00001295" --sanity-level=<number> level of sanity checking to do [1]\n"
1296" --single-step=no|yes translate each instr separately? [no]\n"
1297" --optimise=no|yes improve intermediate code? [yes]\n"
nethercote137bc552003-11-14 17:47:54 +00001298" --profile=no|yes profile? (tool must be built for it) [no]\n"
fitzhardinge462f4f92003-12-18 02:10:54 +00001299" --branchpred=yes|no generate branch prediction hints [no]\n"
sewardjfa8ec112005-01-19 11:55:34 +00001300" --trace-flags=<XXXXXXXX> show generated code? (X = 0|1) [00000000]\n"
1301" --profile-flags=<XXXXXXXX> ditto, but for profiling (X = 0|1) [00000000]\n"
sewardjc771b292004-11-30 18:55:21 +00001302" --trace-notbelow=<number> only show BBs above <number> [0]\n"
njn25e49d8e72002-09-23 09:36:25 +00001303" --trace-syscalls=no|yes show all system calls? [no]\n"
1304" --trace-signals=no|yes show signal handling details? [no]\n"
1305" --trace-symtab=no|yes show symbol table details? [no]\n"
sewardjce058b02005-05-01 08:55:38 +00001306" --trace-cfi=no|yes show call-frame-info details? [no]\n"
njn25e49d8e72002-09-23 09:36:25 +00001307" --trace-sched=no|yes show thread scheduler details? [no]\n"
jsgf855d93d2003-10-13 22:26:55 +00001308" --wait-for-gdb=yes|no pause on startup to wait for gdb attach\n"
sewardjb5f6f512005-03-10 23:59:00 +00001309#if 0
1310" --model-pthreads=yes|no model the pthreads library [no]\n"
1311#endif
1312" --command-line-only=no|yes only use command line options [no]\n"
njn613812e2005-03-11 04:57:30 +00001313"\n"
1314" --vex-iropt-verbosity 0 .. 9 [0]\n"
1315" --vex-iropt-level 0 .. 2 [2]\n"
1316" --vex-iropt-precise-memory-exns [no]\n"
sewardj8b635a42004-11-22 19:01:47 +00001317" --vex-iropt-unroll-thresh 0 .. 400 [120]\n"
1318" --vex-guest-max-insns 1 .. 100 [50]\n"
1319" --vex-guest-chase-thresh 0 .. 99 [10]\n"
1320"\n"
sewardjfa8ec112005-01-19 11:55:34 +00001321" --trace-flags and --profile-flags values (omit the middle space):\n"
sewardj2a99cf62004-11-24 10:44:19 +00001322" 1000 0000 show conversion into IR\n"
1323" 0100 0000 show after initial opt\n"
1324" 0010 0000 show after instrumentation\n"
1325" 0001 0000 show after second opt\n"
1326" 0000 1000 show after tree building\n"
1327" 0000 0100 show selecting insns\n"
1328" 0000 0010 show after reg-alloc\n"
1329" 0000 0001 show final assembly\n"
1330"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001331" debugging options for Valgrind tools that report errors\n"
1332" --dump-error=<number> show translation for basic block associated\n"
1333" with <number>'th error context [0=show none]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001334"\n";
njn3e884182003-04-15 13:03:23 +00001335
1336 Char* usage3 =
1337"\n"
nethercote71980f02004-01-24 18:18:54 +00001338" Extra options read from ~/.valgrindrc, $VALGRIND_OPTS, ./.valgrindrc\n"
njn25e49d8e72002-09-23 09:36:25 +00001339"\n"
njn53612422005-03-12 16:22:54 +00001340" Valgrind is Copyright (C) 2000-2005 Julian Seward et al.\n"
njn25e49d8e72002-09-23 09:36:25 +00001341" and licensed under the GNU General Public License, version 2.\n"
1342" Bug reports, feedback, admiration, abuse, etc, to: %s.\n"
njnd04b7c62002-10-03 14:05:52 +00001343"\n"
nethercote137bc552003-11-14 17:47:54 +00001344" Tools are copyright and licensed by their authors. See each\n"
1345" tool's start-up message for more information.\n"
njn25e49d8e72002-09-23 09:36:25 +00001346"\n";
njn7cf0bd32002-06-08 13:36:03 +00001347
njnbe9b47b2005-05-15 16:22:58 +00001348 // Ensure the message goes to stdout
1349 VG_(clo_log_fd) = 1;
1350 vg_assert( !VG_(logging_to_socket) );
1351
fitzhardinge98abfc72003-12-16 02:05:15 +00001352 VG_(printf)(usage1);
1353 if (VG_(details).name) {
1354 VG_(printf)(" user options for %s:\n", VG_(details).name);
fitzhardinge98abfc72003-12-16 02:05:15 +00001355 if (VG_(needs).command_line_options)
njn51d827b2005-05-09 01:02:08 +00001356 VG_TDICT_CALL(tool_print_usage);
fitzhardinge98abfc72003-12-16 02:05:15 +00001357 else
1358 VG_(printf)(" (none)\n");
1359 }
nethercote6c999f22004-01-31 22:55:15 +00001360 if (debug_help) {
1361 VG_(printf)(usage2);
fitzhardinge98abfc72003-12-16 02:05:15 +00001362
nethercote6c999f22004-01-31 22:55:15 +00001363 if (VG_(details).name) {
1364 VG_(printf)(" debugging options for %s:\n", VG_(details).name);
1365
1366 if (VG_(needs).command_line_options)
njn51d827b2005-05-09 01:02:08 +00001367 VG_TDICT_CALL(tool_print_debug_usage);
nethercote6c999f22004-01-31 22:55:15 +00001368 else
1369 VG_(printf)(" (none)\n");
1370 }
fitzhardinge98abfc72003-12-16 02:05:15 +00001371 }
nethercote421281e2003-11-20 16:20:55 +00001372 VG_(printf)(usage3, VG_BUGS_TO);
nethercotef4928da2004-06-15 10:54:40 +00001373 VG_(exit)(0);
njn7cf0bd32002-06-08 13:36:03 +00001374}
sewardjde4a1d02002-03-22 01:27:54 +00001375
nethercote71980f02004-01-24 18:18:54 +00001376static void pre_process_cmd_line_options
nethercote6c999f22004-01-31 22:55:15 +00001377 ( Int* need_help, const char** tool, const char** exec )
sewardj1c1b1162003-02-23 01:25:51 +00001378{
nethercote71980f02004-01-24 18:18:54 +00001379 UInt i;
sewardjde4a1d02002-03-22 01:27:54 +00001380
sewardj8b635a42004-11-22 19:01:47 +00001381 LibVEX_default_VexControl(& VG_(clo_vex_control));
1382
nethercote71980f02004-01-24 18:18:54 +00001383 /* parse the options we have (only the options we care about now) */
nethercotef6a1d502004-08-09 12:21:57 +00001384 for (i = 1; i < vg_argc; i++) {
nethercote71980f02004-01-24 18:18:54 +00001385
nethercotef6a1d502004-08-09 12:21:57 +00001386 if (strcmp(vg_argv[i], "--version") == 0) {
nethercote71980f02004-01-24 18:18:54 +00001387 printf("valgrind-" VERSION "\n");
nethercotef4928da2004-06-15 10:54:40 +00001388 exit(0);
nethercote71980f02004-01-24 18:18:54 +00001389
nethercotef6a1d502004-08-09 12:21:57 +00001390 } else if (VG_CLO_STREQ(vg_argv[i], "--help") ||
1391 VG_CLO_STREQ(vg_argv[i], "-h")) {
nethercote6c999f22004-01-31 22:55:15 +00001392 *need_help = 1;
1393
nethercotef6a1d502004-08-09 12:21:57 +00001394 } else if (VG_CLO_STREQ(vg_argv[i], "--help-debug")) {
nethercote6c999f22004-01-31 22:55:15 +00001395 *need_help = 2;
nethercote71980f02004-01-24 18:18:54 +00001396
nethercotef6c99d72004-11-09 14:35:43 +00001397 } else if (VG_CLO_STREQN(7, vg_argv[i], "--tool=")) {
nethercotef6a1d502004-08-09 12:21:57 +00001398 *tool = &vg_argv[i][7];
nethercote71980f02004-01-24 18:18:54 +00001399
nethercotef6a1d502004-08-09 12:21:57 +00001400 } else if (VG_CLO_STREQN(7, vg_argv[i], "--exec=")) {
1401 *exec = &vg_argv[i][7];
nethercote71980f02004-01-24 18:18:54 +00001402 }
1403 }
nethercote71980f02004-01-24 18:18:54 +00001404}
1405
nethercote5ee67ca2004-06-22 14:00:09 +00001406static void process_cmd_line_options( UInt* client_auxv, const char* toolname )
nethercote71980f02004-01-24 18:18:54 +00001407{
nethercotef8548672004-06-21 12:42:35 +00001408 Int i, eventually_log_fd;
nethercote71980f02004-01-24 18:18:54 +00001409 Int toolname_len = VG_(strlen)(toolname);
njnbe9b47b2005-05-15 16:22:58 +00001410 enum {
1411 VgLogTo_Fd,
1412 VgLogTo_File,
1413 VgLogTo_FileExactly,
1414 VgLogTo_Socket
1415 } log_to = VgLogTo_Fd; // Where is logging output to be sent?
sewardjde4a1d02002-03-22 01:27:54 +00001416
nethercotee1730692003-11-20 10:38:07 +00001417 /* log to stderr by default, but usage message goes to stdout */
nethercotef8548672004-06-21 12:42:35 +00001418 eventually_log_fd = 2;
sewardjde4a1d02002-03-22 01:27:54 +00001419
sewardj19d81412002-06-03 01:10:40 +00001420 /* Check for sane path in ./configure --prefix=... */
fitzhardinge98abfc72003-12-16 02:05:15 +00001421 if (VG_LIBDIR[0] != '/')
sewardj19d81412002-06-03 01:10:40 +00001422 config_error("Please use absolute paths in "
1423 "./configure --prefix=... or --libdir=...");
sewardj38170912002-05-10 21:07:22 +00001424
nethercotef6a1d502004-08-09 12:21:57 +00001425 for (i = 1; i < vg_argc; i++) {
nethercote71980f02004-01-24 18:18:54 +00001426
nethercotef6a1d502004-08-09 12:21:57 +00001427 Char* arg = vg_argv[i];
thughes3bfd5a02004-07-18 08:05:44 +00001428 Char* colon = arg;
nethercote71980f02004-01-24 18:18:54 +00001429
thughes3bfd5a02004-07-18 08:05:44 +00001430 /* Look for a colon in the switch name */
1431 while (*colon && *colon != ':' && *colon != '=')
1432 colon++;
nethercote71980f02004-01-24 18:18:54 +00001433
1434 /* Look for matching "--toolname:foo" */
thughes3bfd5a02004-07-18 08:05:44 +00001435 if (*colon == ':') {
nethercote71980f02004-01-24 18:18:54 +00001436 if (VG_CLO_STREQN(2, arg, "--") &&
1437 VG_CLO_STREQN(toolname_len, arg+2, toolname) &&
1438 VG_CLO_STREQN(1, arg+2+toolname_len, ":"))
1439 {
1440 // prefix matches, convert "--toolname:foo" to "--foo"
1441 if (0)
1442 VG_(printf)("tool-specific arg: %s\n", arg);
njn8c0b3bb2005-03-12 21:20:39 +00001443 arg = strdup(arg + toolname_len + 1);
nethercote71980f02004-01-24 18:18:54 +00001444 arg[0] = '-';
1445 arg[1] = '-';
1446
1447 } else {
1448 // prefix doesn't match, skip to next arg
1449 continue;
1450 }
1451 }
1452
fitzhardinge98abfc72003-12-16 02:05:15 +00001453 /* Ignore these options - they've already been handled */
njn45270a22005-03-27 01:00:11 +00001454 if (VG_CLO_STREQN( 7, arg, "--tool=")) goto skip_arg;
1455 if (VG_CLO_STREQN( 7, arg, "--exec=")) goto skip_arg;
1456 if (VG_CLO_STREQN(20, arg, "--command-line-only=")) goto skip_arg;
fitzhardinge98abfc72003-12-16 02:05:15 +00001457
njn45270a22005-03-27 01:00:11 +00001458 if ( VG_CLO_STREQ(arg, "--")) goto skip_arg;
nethercote27fec902004-06-16 21:26:32 +00001459
nethercote71980f02004-01-24 18:18:54 +00001460 else if (VG_CLO_STREQ(arg, "-v") ||
1461 VG_CLO_STREQ(arg, "--verbose"))
sewardjde4a1d02002-03-22 01:27:54 +00001462 VG_(clo_verbosity)++;
nethercote27fec902004-06-16 21:26:32 +00001463
nethercote71980f02004-01-24 18:18:54 +00001464 else if (VG_CLO_STREQ(arg, "-q") ||
1465 VG_CLO_STREQ(arg, "--quiet"))
sewardjde4a1d02002-03-22 01:27:54 +00001466 VG_(clo_verbosity)--;
1467
sewardj1cf558c2005-04-25 01:36:56 +00001468 else if (VG_CLO_STREQ(arg, "-d")) {
1469 /* do nothing */
1470 }
1471
sewardj71bc3cb2005-05-19 00:25:45 +00001472 else VG_BOOL_CLO(arg, "--xml", VG_(clo_xml))
njn45270a22005-03-27 01:00:11 +00001473 else VG_BOOL_CLO(arg, "--branchpred", VG_(clo_branchpred))
1474 else VG_BOOL_CLO(arg, "--db-attach", VG_(clo_db_attach))
1475 else VG_BOOL_CLO(arg, "--demangle", VG_(clo_demangle))
1476 else VG_BOOL_CLO(arg, "--error-limit", VG_(clo_error_limit))
1477 else VG_BOOL_CLO(arg, "--pointercheck", VG_(clo_pointercheck))
1478 else VG_BOOL_CLO(arg, "--support-elan3", VG_(clo_support_elan3))
1479 else VG_BOOL_CLO(arg, "--show-emwarns", VG_(clo_show_emwarns))
sewardj97724e52005-04-02 23:40:59 +00001480 else VG_NUM_CLO (arg, "--max-stackframe", VG_(clo_max_stackframe))
njn45270a22005-03-27 01:00:11 +00001481 else VG_BOOL_CLO(arg, "--profile", VG_(clo_profile))
1482 else VG_BOOL_CLO(arg, "--run-libc-freeres", VG_(clo_run_libc_freeres))
1483 else VG_BOOL_CLO(arg, "--show-below-main", VG_(clo_show_below_main))
1484 else VG_BOOL_CLO(arg, "--time-stamp", VG_(clo_time_stamp))
1485 else VG_BOOL_CLO(arg, "--track-fds", VG_(clo_track_fds))
1486 else VG_BOOL_CLO(arg, "--trace-children", VG_(clo_trace_children))
1487 else VG_BOOL_CLO(arg, "--trace-sched", VG_(clo_trace_sched))
1488 else VG_BOOL_CLO(arg, "--trace-signals", VG_(clo_trace_signals))
1489 else VG_BOOL_CLO(arg, "--trace-symtab", VG_(clo_trace_symtab))
sewardjce058b02005-05-01 08:55:38 +00001490 else VG_BOOL_CLO(arg, "--trace-cfi", VG_(clo_trace_cfi))
njn45270a22005-03-27 01:00:11 +00001491 else VG_BOOL_CLO(arg, "--trace-redir", VG_(clo_trace_redir))
1492 else VG_BOOL_CLO(arg, "--trace-syscalls", VG_(clo_trace_syscalls))
1493 else VG_BOOL_CLO(arg, "--trace-pthreads", VG_(clo_trace_pthreads))
1494 else VG_BOOL_CLO(arg, "--wait-for-gdb", VG_(clo_wait_for_gdb))
1495 else VG_BOOL_CLO(arg, "--model-pthreads", VG_(clo_model_pthreads))
sewardj72f98ff2002-06-13 17:23:38 +00001496
njn45270a22005-03-27 01:00:11 +00001497 else VG_STR_CLO (arg, "--db-command", VG_(clo_db_command))
1498 else VG_STR_CLO (arg, "--weird-hacks", VG_(clo_weird_hacks))
sewardjde4a1d02002-03-22 01:27:54 +00001499
njn45270a22005-03-27 01:00:11 +00001500 else VG_NUM_CLO (arg, "--dump-error", VG_(clo_dump_error))
1501 else VG_NUM_CLO (arg, "--input-fd", VG_(clo_input_fd))
1502 else VG_NUM_CLO (arg, "--sanity-level", VG_(clo_sanity_level))
1503 else VG_BNUM_CLO(arg, "--num-callers", VG_(clo_backtrace_size), 1,
1504 VG_DEEPEST_BACKTRACE)
sewardjde4a1d02002-03-22 01:27:54 +00001505
njn45270a22005-03-27 01:00:11 +00001506 else VG_BNUM_CLO(arg, "--vex-iropt-verbosity",
sewardj8b635a42004-11-22 19:01:47 +00001507 VG_(clo_vex_control).iropt_verbosity, 0, 10)
njn45270a22005-03-27 01:00:11 +00001508 else VG_BNUM_CLO(arg, "--vex-iropt-level",
sewardj8b635a42004-11-22 19:01:47 +00001509 VG_(clo_vex_control).iropt_level, 0, 2)
njn45270a22005-03-27 01:00:11 +00001510 else VG_BOOL_CLO(arg, "--vex-iropt-precise-memory-exns",
sewardj8b635a42004-11-22 19:01:47 +00001511 VG_(clo_vex_control).iropt_precise_memory_exns)
njn45270a22005-03-27 01:00:11 +00001512 else VG_BNUM_CLO(arg, "--vex-iropt-unroll-thresh",
sewardj8b635a42004-11-22 19:01:47 +00001513 VG_(clo_vex_control).iropt_unroll_thresh, 0, 400)
njn45270a22005-03-27 01:00:11 +00001514 else VG_BNUM_CLO(arg, "--vex-guest-max-insns",
sewardj8b635a42004-11-22 19:01:47 +00001515 VG_(clo_vex_control).guest_max_insns, 1, 100)
njn45270a22005-03-27 01:00:11 +00001516 else VG_BNUM_CLO(arg, "--vex-guest-chase-thresh",
sewardj8b635a42004-11-22 19:01:47 +00001517 VG_(clo_vex_control).guest_chase_thresh, 0, 99)
1518
nethercotef8548672004-06-21 12:42:35 +00001519 else if (VG_CLO_STREQN(9, arg, "--log-fd=")) {
njnbe9b47b2005-05-15 16:22:58 +00001520 log_to = VgLogTo_Fd;
nethercotef8548672004-06-21 12:42:35 +00001521 VG_(clo_log_name) = NULL;
1522 eventually_log_fd = (Int)VG_(atoll)(&arg[9]);
sewardj4cf05692002-10-27 20:28:29 +00001523 }
1524
nethercotef8548672004-06-21 12:42:35 +00001525 else if (VG_CLO_STREQN(11, arg, "--log-file=")) {
njnbe9b47b2005-05-15 16:22:58 +00001526 log_to = VgLogTo_File;
nethercotef8548672004-06-21 12:42:35 +00001527 VG_(clo_log_name) = &arg[11];
sewardj4cf05692002-10-27 20:28:29 +00001528 }
njnd6bc3c32005-03-27 00:44:31 +00001529
sewardj603d4102005-01-11 14:01:02 +00001530 else if (VG_CLO_STREQN(19, arg, "--log-file-exactly=")) {
njnbe9b47b2005-05-15 16:22:58 +00001531 log_to = VgLogTo_FileExactly;
sewardj603d4102005-01-11 14:01:02 +00001532 VG_(clo_log_name) = &arg[19];
1533 }
sewardjde4a1d02002-03-22 01:27:54 +00001534
nethercotef8548672004-06-21 12:42:35 +00001535 else if (VG_CLO_STREQN(13, arg, "--log-socket=")) {
njnbe9b47b2005-05-15 16:22:58 +00001536 log_to = VgLogTo_Socket;
nethercotef8548672004-06-21 12:42:35 +00001537 VG_(clo_log_name) = &arg[13];
sewardj73cf3bc2002-11-03 03:20:15 +00001538 }
1539
nethercote71980f02004-01-24 18:18:54 +00001540 else if (VG_CLO_STREQN(15, arg, "--suppressions=")) {
sewardjde4a1d02002-03-22 01:27:54 +00001541 if (VG_(clo_n_suppressions) >= VG_CLO_MAX_SFILES) {
njn25e49d8e72002-09-23 09:36:25 +00001542 VG_(message)(Vg_UserMsg, "Too many suppression files specified.");
sewardjde4a1d02002-03-22 01:27:54 +00001543 VG_(message)(Vg_UserMsg,
1544 "Increase VG_CLO_MAX_SFILES and recompile.");
nethercote71980f02004-01-24 18:18:54 +00001545 VG_(bad_option)(arg);
sewardjde4a1d02002-03-22 01:27:54 +00001546 }
nethercote71980f02004-01-24 18:18:54 +00001547 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = &arg[15];
sewardjde4a1d02002-03-22 01:27:54 +00001548 VG_(clo_n_suppressions)++;
1549 }
sewardjde4a1d02002-03-22 01:27:54 +00001550
sewardjfa8ec112005-01-19 11:55:34 +00001551 /* "stuvwxyz" --> stuvwxyz (binary) */
1552 else if (VG_CLO_STREQN(14, arg, "--trace-flags=")) {
1553 Int j;
1554 char* opt = & arg[14];
1555
1556 if (8 != VG_(strlen)(opt)) {
1557 VG_(message)(Vg_UserMsg,
1558 "--trace-flags argument must have 8 digits");
1559 VG_(bad_option)(arg);
1560 }
1561 for (j = 0; j < 8; j++) {
1562 if ('0' == opt[j]) { /* do nothing */ }
1563 else if ('1' == opt[j]) VG_(clo_trace_flags) |= (1 << (7-j));
1564 else {
1565 VG_(message)(Vg_UserMsg, "--trace-flags argument can only "
1566 "contain 0s and 1s");
1567 VG_(bad_option)(arg);
1568 }
1569 }
1570 }
1571
1572 /* "stuvwxyz" --> stuvwxyz (binary) */
1573 else if (VG_CLO_STREQN(16, arg, "--profile-flags=")) {
njn25e49d8e72002-09-23 09:36:25 +00001574 Int j;
nethercote71980f02004-01-24 18:18:54 +00001575 char* opt = & arg[16];
njn25e49d8e72002-09-23 09:36:25 +00001576
sewardj2a99cf62004-11-24 10:44:19 +00001577 if (8 != VG_(strlen)(opt)) {
njn25e49d8e72002-09-23 09:36:25 +00001578 VG_(message)(Vg_UserMsg,
sewardjfa8ec112005-01-19 11:55:34 +00001579 "--profile-flags argument must have 8 digits");
nethercote71980f02004-01-24 18:18:54 +00001580 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001581 }
sewardj8b635a42004-11-22 19:01:47 +00001582 for (j = 0; j < 8; j++) {
njn25e49d8e72002-09-23 09:36:25 +00001583 if ('0' == opt[j]) { /* do nothing */ }
sewardjfa8ec112005-01-19 11:55:34 +00001584 else if ('1' == opt[j]) VG_(clo_profile_flags) |= (1 << (7-j));
njn25e49d8e72002-09-23 09:36:25 +00001585 else {
sewardjfa8ec112005-01-19 11:55:34 +00001586 VG_(message)(Vg_UserMsg, "--profile-flags argument can only "
njn25e49d8e72002-09-23 09:36:25 +00001587 "contain 0s and 1s");
nethercote71980f02004-01-24 18:18:54 +00001588 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001589 }
1590 }
1591 }
sewardjde4a1d02002-03-22 01:27:54 +00001592
njn45270a22005-03-27 01:00:11 +00001593 else VG_NUM_CLO (arg, "--trace-notbelow", VG_(clo_trace_notbelow))
sewardjc771b292004-11-30 18:55:21 +00001594
sewardjd153fae2005-01-10 17:24:47 +00001595 else if (VG_CLO_STREQ(arg, "--gen-suppressions=no"))
1596 VG_(clo_gen_suppressions) = 0;
1597 else if (VG_CLO_STREQ(arg, "--gen-suppressions=yes"))
1598 VG_(clo_gen_suppressions) = 1;
1599 else if (VG_CLO_STREQ(arg, "--gen-suppressions=all"))
1600 VG_(clo_gen_suppressions) = 2;
1601
nethercote71980f02004-01-24 18:18:54 +00001602 else if ( ! VG_(needs).command_line_options
njn51d827b2005-05-09 01:02:08 +00001603 || ! VG_TDICT_CALL(tool_process_cmd_line_option, arg) ) {
nethercotef4928da2004-06-15 10:54:40 +00001604 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001605 }
njn8c0b3bb2005-03-12 21:20:39 +00001606 skip_arg:
1607 if (arg != vg_argv[i])
1608 free(arg);
sewardjde4a1d02002-03-22 01:27:54 +00001609 }
1610
sewardj998d40d2004-12-06 14:24:52 +00001611 /* Make VEX control parameters sane */
1612
1613 if (VG_(clo_vex_control).guest_chase_thresh
1614 >= VG_(clo_vex_control).guest_max_insns)
1615 VG_(clo_vex_control).guest_chase_thresh
1616 = VG_(clo_vex_control).guest_max_insns - 1;
1617
1618 if (VG_(clo_vex_control).guest_chase_thresh < 0)
1619 VG_(clo_vex_control).guest_chase_thresh = 0;
1620
1621 /* Check various option values */
nethercote27fec902004-06-16 21:26:32 +00001622
njnf9ebf672003-05-12 21:41:30 +00001623 if (VG_(clo_verbosity) < 0)
sewardjde4a1d02002-03-22 01:27:54 +00001624 VG_(clo_verbosity) = 0;
1625
nethercote04d0fbc2004-01-26 16:48:06 +00001626 if (VG_(clo_db_attach) && VG_(clo_trace_children)) {
sewardjde4a1d02002-03-22 01:27:54 +00001627 VG_(message)(Vg_UserMsg, "");
1628 VG_(message)(Vg_UserMsg,
nethercote04d0fbc2004-01-26 16:48:06 +00001629 "--db-attach=yes conflicts with --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001630 VG_(message)(Vg_UserMsg,
1631 "Please choose one or the other, but not both.");
nethercote04d0fbc2004-01-26 16:48:06 +00001632 VG_(bad_option)("--db-attach=yes and --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001633 }
1634
njnbe9b47b2005-05-15 16:22:58 +00001635 if (VG_(clo_gen_suppressions) > 0 &&
1636 !VG_(needs).core_errors && !VG_(needs).tool_errors) {
1637 VG_(message)(Vg_UserMsg,
1638 "Can't use --gen-suppressions= with this tool,");
1639 VG_(message)(Vg_UserMsg,
1640 "as it doesn't generate errors.");
1641 VG_(bad_option)("--gen-suppressions=");
1642 }
1643
sewardj71bc3cb2005-05-19 00:25:45 +00001644 /* If we've been asked to emit XML, mash around various other
1645 options so as to constrain the output somewhat, and to remove
1646 any need for user input during the run. */
1647 if (VG_(clo_xml)) {
1648 /* Disable suppression generation (requires user input) */
1649 VG_(clo_gen_suppressions) = 0;
1650 /* Disable attaching to GDB (requires user input) */
1651 VG_(clo_db_attach) = False;
1652 /* Set a known verbosity level */
1653 VG_(clo_verbosity) = 1;
1654 /* Disable error limits (this might be a bad idea!) */
1655 VG_(clo_error_limit) = False;
1656 /* Disable emulation warnings */
1657 VG_(clo_show_emwarns) = False;
1658 /* Disable waiting for GDB to debug Valgrind */
1659 VG_(clo_wait_for_gdb) = False;
1660 /* No file-descriptor leak checking yet */
1661 VG_(clo_track_fds) = False;
1662 /* Also, we want to set options for the leak checker, but that
1663 will have to be done in Memcheck's flag-handling code, not
1664 here. */
1665 }
1666
njnbe9b47b2005-05-15 16:22:58 +00001667 /* All non-logging-related options have been checked. If the logging
1668 option specified is ok, we can switch to it, as we know we won't
1669 have to generate any other command-line-related error messages.
1670 (So far we should be still attached to stderr, so we can show on
1671 the terminal any problems to do with processing command line
1672 opts.)
1673
1674 So set up logging now. After this is done, VG_(clo_log_fd)
sewardj4cf05692002-10-27 20:28:29 +00001675 should be connected to whatever sink has been selected, and we
1676 indiscriminately chuck stuff into it without worrying what the
1677 nature of it is. Oh the wonder of Unix streams. */
1678
njnbe9b47b2005-05-15 16:22:58 +00001679 vg_assert(VG_(clo_log_fd) == 2 /* stderr */);
1680 vg_assert(VG_(logging_to_socket) == False);
sewardj4cf05692002-10-27 20:28:29 +00001681
njnbe9b47b2005-05-15 16:22:58 +00001682 switch (log_to) {
sewardj73cf3bc2002-11-03 03:20:15 +00001683
sewardj4cf05692002-10-27 20:28:29 +00001684 case VgLogTo_Fd:
nethercotef8548672004-06-21 12:42:35 +00001685 vg_assert(VG_(clo_log_name) == NULL);
1686 VG_(clo_log_fd) = eventually_log_fd;
sewardj4cf05692002-10-27 20:28:29 +00001687 break;
sewardj73cf3bc2002-11-03 03:20:15 +00001688
sewardj4cf05692002-10-27 20:28:29 +00001689 case VgLogTo_File: {
1690 Char logfilename[1000];
jsgff3c3f1a2003-10-14 22:13:28 +00001691 Int seq = 0;
1692 Int pid = VG_(getpid)();
1693
nethercotef8548672004-06-21 12:42:35 +00001694 vg_assert(VG_(clo_log_name) != NULL);
1695 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
jsgff3c3f1a2003-10-14 22:13:28 +00001696
nethercote71980f02004-01-24 18:18:54 +00001697 for (;;) {
jsgff3c3f1a2003-10-14 22:13:28 +00001698 if (seq == 0)
1699 VG_(sprintf)(logfilename, "%s.pid%d",
nethercotef8548672004-06-21 12:42:35 +00001700 VG_(clo_log_name), pid );
jsgff3c3f1a2003-10-14 22:13:28 +00001701 else
1702 VG_(sprintf)(logfilename, "%s.pid%d.%d",
nethercotef8548672004-06-21 12:42:35 +00001703 VG_(clo_log_name), pid, seq );
jsgff3c3f1a2003-10-14 22:13:28 +00001704 seq++;
1705
njnbe9b47b2005-05-15 16:22:58 +00001706 // EXCL: it will fail with EEXIST if the file already exists.
nethercotef8548672004-06-21 12:42:35 +00001707 eventually_log_fd
jsgff3c3f1a2003-10-14 22:13:28 +00001708 = VG_(open)(logfilename,
1709 VKI_O_CREAT|VKI_O_WRONLY|VKI_O_EXCL|VKI_O_TRUNC,
1710 VKI_S_IRUSR|VKI_S_IWUSR);
nethercotef8548672004-06-21 12:42:35 +00001711 if (eventually_log_fd >= 0) {
1712 VG_(clo_log_fd) = VG_(safe_fd)(eventually_log_fd);
sewardj603d4102005-01-11 14:01:02 +00001713 break; /* for (;;) */
jsgff3c3f1a2003-10-14 22:13:28 +00001714 } else {
njnbe9b47b2005-05-15 16:22:58 +00001715 // If the file already existed, we try the next name. If it
1716 // was some other file error, we give up.
nethercotef8548672004-06-21 12:42:35 +00001717 if (eventually_log_fd != -VKI_EEXIST) {
jsgff3c3f1a2003-10-14 22:13:28 +00001718 VG_(message)(Vg_UserMsg,
njn02bc4b82005-05-15 17:28:26 +00001719 "Can't create/open log file '%s.pid%d'; giving up!",
nethercotef8548672004-06-21 12:42:35 +00001720 VG_(clo_log_name), pid);
jsgff3c3f1a2003-10-14 22:13:28 +00001721 VG_(bad_option)(
sewardj603d4102005-01-11 14:01:02 +00001722 "--log-file=<file> (didn't work out for some reason.)");
njnbe9b47b2005-05-15 16:22:58 +00001723 /*NOTREACHED*/
jsgff3c3f1a2003-10-14 22:13:28 +00001724 }
1725 }
1726 }
sewardj603d4102005-01-11 14:01:02 +00001727 break; /* switch (VG_(clo_log_to)) */
1728 }
1729
1730 case VgLogTo_FileExactly: {
sewardj603d4102005-01-11 14:01:02 +00001731 vg_assert(VG_(clo_log_name) != NULL);
1732 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
sewardj603d4102005-01-11 14:01:02 +00001733
1734 eventually_log_fd
njnbe9b47b2005-05-15 16:22:58 +00001735 = VG_(open)(VG_(clo_log_name),
sewardj603d4102005-01-11 14:01:02 +00001736 VKI_O_CREAT|VKI_O_WRONLY|VKI_O_TRUNC,
1737 VKI_S_IRUSR|VKI_S_IWUSR);
1738 if (eventually_log_fd >= 0) {
1739 VG_(clo_log_fd) = VG_(safe_fd)(eventually_log_fd);
njnbe9b47b2005-05-15 16:22:58 +00001740 } else {
sewardj603d4102005-01-11 14:01:02 +00001741 VG_(message)(Vg_UserMsg,
njn02bc4b82005-05-15 17:28:26 +00001742 "Can't create/open log file '%s'; giving up!",
sewardj603d4102005-01-11 14:01:02 +00001743 VG_(clo_log_name));
1744 VG_(bad_option)(
1745 "--log-file-exactly=<file> (didn't work out for some reason.)");
1746 /*NOTREACHED*/
1747 }
1748 break; /* switch (VG_(clo_log_to)) */
sewardj73cf3bc2002-11-03 03:20:15 +00001749 }
1750
1751 case VgLogTo_Socket: {
nethercotef8548672004-06-21 12:42:35 +00001752 vg_assert(VG_(clo_log_name) != NULL);
1753 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
1754 eventually_log_fd = VG_(connect_via_socket)( VG_(clo_log_name) );
1755 if (eventually_log_fd == -1) {
sewardj73cf3bc2002-11-03 03:20:15 +00001756 VG_(message)(Vg_UserMsg,
nethercotef8548672004-06-21 12:42:35 +00001757 "Invalid --log-socket=ipaddr or --log-socket=ipaddr:port spec");
sewardj73cf3bc2002-11-03 03:20:15 +00001758 VG_(message)(Vg_UserMsg,
njn02bc4b82005-05-15 17:28:26 +00001759 "of '%s'; giving up!", VG_(clo_log_name) );
sewardj73cf3bc2002-11-03 03:20:15 +00001760 VG_(bad_option)(
nethercotef8548672004-06-21 12:42:35 +00001761 "--log-socket=");
njnbe9b47b2005-05-15 16:22:58 +00001762 /*NOTREACHED*/
sewardj4cf05692002-10-27 20:28:29 +00001763 }
nethercotef8548672004-06-21 12:42:35 +00001764 if (eventually_log_fd == -2) {
sewardj73cf3bc2002-11-03 03:20:15 +00001765 VG_(message)(Vg_UserMsg,
njn02bc4b82005-05-15 17:28:26 +00001766 "valgrind: failed to connect to logging server '%s'.",
nethercotef8548672004-06-21 12:42:35 +00001767 VG_(clo_log_name) );
sewardj570f8902002-11-03 11:44:36 +00001768 VG_(message)(Vg_UserMsg,
1769 "Log messages will sent to stderr instead." );
1770 VG_(message)(Vg_UserMsg,
1771 "" );
1772 /* We don't change anything here. */
njnbe9b47b2005-05-15 16:22:58 +00001773 vg_assert(VG_(clo_log_fd) == 2);
sewardj570f8902002-11-03 11:44:36 +00001774 } else {
nethercotef8548672004-06-21 12:42:35 +00001775 vg_assert(eventually_log_fd > 0);
1776 VG_(clo_log_fd) = eventually_log_fd;
njnbe9b47b2005-05-15 16:22:58 +00001777 VG_(logging_to_socket) = True;
sewardj570f8902002-11-03 11:44:36 +00001778 }
sewardj73cf3bc2002-11-03 03:20:15 +00001779 break;
1780 }
sewardj4cf05692002-10-27 20:28:29 +00001781 }
1782
sewardj71bc3cb2005-05-19 00:25:45 +00001783
1784 /* Check that the requested tool actually supports XML output. */
1785 if (VG_(clo_xml) && 0 != VG_(strcmp)(toolname, "memcheck")) {
1786 VG_(clo_xml) = False;
1787 VG_(message)(Vg_UserMsg,
1788 "Currently only Memcheck supports XML output.");
1789 VG_(bad_option)("--xml=yes");
1790 /*NOTREACHED*/
1791 }
1792
njnbe9b47b2005-05-15 16:22:58 +00001793 // Move log_fd into the safe range, so it doesn't conflict with any app fds.
1794 // XXX: this is more or less duplicating the behaviour of the calls to
1795 // VG_(safe_fd)() above, although this does not close the original fd.
1796 // Perhaps the VG_(safe_fd)() calls above should be removed, and this
1797 // code should be replaced with a call to VG_(safe_fd)(). --njn
thughesad1c9562004-06-26 11:27:52 +00001798 eventually_log_fd = VG_(fcntl)(VG_(clo_log_fd), VKI_F_DUPFD, VG_(fd_hard_limit));
nethercotef8548672004-06-21 12:42:35 +00001799 if (eventually_log_fd < 0)
jsgf855d93d2003-10-13 22:26:55 +00001800 VG_(message)(Vg_UserMsg, "valgrind: failed to move logfile fd into safe range");
1801 else {
nethercotef8548672004-06-21 12:42:35 +00001802 VG_(clo_log_fd) = eventually_log_fd;
1803 VG_(fcntl)(VG_(clo_log_fd), VKI_F_SETFD, VKI_FD_CLOEXEC);
jsgf855d93d2003-10-13 22:26:55 +00001804 }
1805
sewardj4cf05692002-10-27 20:28:29 +00001806 /* Ok, the logging sink is running now. Print a suitable preamble.
1807 If logging to file or a socket, write details of parent PID and
1808 command line args, to help people trying to interpret the
1809 results of a run which encompasses multiple processes. */
sewardjde4a1d02002-03-22 01:27:54 +00001810
sewardj71bc3cb2005-05-19 00:25:45 +00001811 if (VG_(clo_xml)) {
sewardj8665d8e2005-06-01 17:35:23 +00001812 VG_(message)(Vg_UserMsg, "<?xml version=\"1.0\"?>");
1813 VG_(message)(Vg_UserMsg, "");
sewardj71bc3cb2005-05-19 00:25:45 +00001814 VG_(message)(Vg_UserMsg, "<valgrindoutput>");
1815 VG_(message)(Vg_UserMsg, "");
1816 VG_(message)(Vg_UserMsg, "<protocolversion>1</protocolversion>");
1817 VG_(message)(Vg_UserMsg, "");
1818 }
1819
sewardjd7bddad2005-06-13 16:48:32 +00001820 HChar* xpre = VG_(clo_xml) ? " <line>" : "";
1821 HChar* xpost = VG_(clo_xml) ? "</line>" : "";
sewardj71bc3cb2005-05-19 00:25:45 +00001822
sewardj83adf412002-05-01 01:25:45 +00001823 if (VG_(clo_verbosity > 0)) {
sewardjd7bddad2005-06-13 16:48:32 +00001824
1825 if (VG_(clo_xml))
1826 VG_(message)(Vg_UserMsg, "<preamble>");
1827
nethercote996901a2004-08-03 13:29:09 +00001828 /* Tool details */
sewardj71bc3cb2005-05-19 00:25:45 +00001829 VG_(message)(Vg_UserMsg, "%s%s%s%s, %s.%s",
1830 xpre,
njnd04b7c62002-10-03 14:05:52 +00001831 VG_(details).name,
njnb9c427c2004-12-01 14:14:42 +00001832 NULL == VG_(details).version ? "" : "-",
njnd04b7c62002-10-03 14:05:52 +00001833 NULL == VG_(details).version
1834 ? (Char*)"" : VG_(details).version,
sewardj71bc3cb2005-05-19 00:25:45 +00001835 VG_(details).description,
1836 xpost);
1837 VG_(message)(Vg_UserMsg, "%s%s%s",
1838 xpre, VG_(details).copyright_author, xpost);
sewardj3b2736a2002-03-24 12:18:35 +00001839
njnd04b7c62002-10-03 14:05:52 +00001840 /* Core details */
1841 VG_(message)(Vg_UserMsg,
sewardj71bc3cb2005-05-19 00:25:45 +00001842 "%sUsing LibVEX rev %s, a library for dynamic binary translation.%s",
1843 xpre, LibVEX_Version(), xpost );
sewardjc7025332004-12-13 18:30:39 +00001844 VG_(message)(Vg_UserMsg,
sewardj71bc3cb2005-05-19 00:25:45 +00001845 "%sCopyright (C) 2004-2005, and GNU GPL'd, by OpenWorks LLP.%s",
1846 xpre, xpost );
sewardjc7025332004-12-13 18:30:39 +00001847 VG_(message)(Vg_UserMsg,
sewardj71bc3cb2005-05-19 00:25:45 +00001848 "%sUsing valgrind-%s, a dynamic binary instrumentation framework.%s",
1849 xpre, VERSION, xpost);
sewardjde4a1d02002-03-22 01:27:54 +00001850 VG_(message)(Vg_UserMsg,
sewardj71bc3cb2005-05-19 00:25:45 +00001851 "%sCopyright (C) 2000-2005, and GNU GPL'd, by Julian Seward et al.%s",
1852 xpre, xpost );
sewardjd7bddad2005-06-13 16:48:32 +00001853
1854 if (VG_(clo_xml))
1855 VG_(message)(Vg_UserMsg, "</preamble>");
njnd04b7c62002-10-03 14:05:52 +00001856 }
1857
njnbe9b47b2005-05-15 16:22:58 +00001858 if (VG_(clo_verbosity) > 0 && log_to != VgLogTo_Fd) {
sewardj4cf05692002-10-27 20:28:29 +00001859 VG_(message)(Vg_UserMsg, "");
1860 VG_(message)(Vg_UserMsg,
1861 "My PID = %d, parent PID = %d. Prog and args are:",
1862 VG_(getpid)(), VG_(getppid)() );
1863 for (i = 0; i < VG_(client_argc); i++)
1864 VG_(message)(Vg_UserMsg, " %s", VG_(client_argv)[i]);
1865 }
sewardj71bc3cb2005-05-19 00:25:45 +00001866 else
1867 if (VG_(clo_xml)) {
1868 VG_(message)(Vg_UserMsg, "");
1869 VG_(message)(Vg_UserMsg, "<pid>%d</pid>", VG_(getpid)());
1870 VG_(message)(Vg_UserMsg, "<ppid>%d</ppid>", VG_(getppid)());
sewardj7c9e57c2005-05-24 14:21:45 +00001871 VG_(message)(Vg_UserMsg, "<tool>%s</tool>", toolname);
sewardj71bc3cb2005-05-19 00:25:45 +00001872 VG_(message)(Vg_UserMsg, "");
1873 VG_(message)(Vg_UserMsg, "<argv>");
sewardj8665d8e2005-06-01 17:35:23 +00001874 for (i = 0; i < VG_(client_argc); i++) {
1875 HChar* tag = i==0 ? "exe" : "arg";
1876 VG_(message)(Vg_UserMsg, " <%s>%s</%s>",
1877 tag, VG_(client_argv)[i], tag);
1878 }
sewardj71bc3cb2005-05-19 00:25:45 +00001879 VG_(message)(Vg_UserMsg, "</argv>");
1880 }
sewardj4cf05692002-10-27 20:28:29 +00001881
sewardjde4a1d02002-03-22 01:27:54 +00001882 if (VG_(clo_verbosity) > 1) {
nethercotea70f7352004-04-18 12:08:46 +00001883 Int fd;
njnbe9b47b2005-05-15 16:22:58 +00001884 if (log_to != VgLogTo_Fd)
njn1fd5eb22005-03-13 05:43:23 +00001885 VG_(message)(Vg_DebugMsg, "");
1886 VG_(message)(Vg_DebugMsg, "Valgrind library directory: %s", VG_(libdir));
1887 VG_(message)(Vg_DebugMsg, "Command line");
njn86dc2bc2003-09-09 07:26:21 +00001888 for (i = 0; i < VG_(client_argc); i++)
njn1fd5eb22005-03-13 05:43:23 +00001889 VG_(message)(Vg_DebugMsg, " %s", VG_(client_argv)[i]);
njn86dc2bc2003-09-09 07:26:21 +00001890
njn1fd5eb22005-03-13 05:43:23 +00001891 VG_(message)(Vg_DebugMsg, "Startup, with flags:");
nethercotef6a1d502004-08-09 12:21:57 +00001892 for (i = 1; i < vg_argc; i++) {
njn1fd5eb22005-03-13 05:43:23 +00001893 VG_(message)(Vg_DebugMsg, " %s", vg_argv[i]);
sewardjde4a1d02002-03-22 01:27:54 +00001894 }
nethercotea70f7352004-04-18 12:08:46 +00001895
njn1fd5eb22005-03-13 05:43:23 +00001896 VG_(message)(Vg_DebugMsg, "Contents of /proc/version:");
nethercotea70f7352004-04-18 12:08:46 +00001897 fd = VG_(open) ( "/proc/version", VKI_O_RDONLY, 0 );
1898 if (fd < 0) {
njn1fd5eb22005-03-13 05:43:23 +00001899 VG_(message)(Vg_DebugMsg, " can't open /proc/version");
nethercotea70f7352004-04-18 12:08:46 +00001900 } else {
sewardj71bc3cb2005-05-19 00:25:45 +00001901# define BUF_LEN 256
nethercotea70f7352004-04-18 12:08:46 +00001902 Char version_buf[BUF_LEN];
1903 Int n = VG_(read) ( fd, version_buf, BUF_LEN );
njnbe9b47b2005-05-15 16:22:58 +00001904 vg_assert(n <= BUF_LEN);
nethercotea70f7352004-04-18 12:08:46 +00001905 if (n > 0) {
1906 version_buf[n-1] = '\0';
njn1fd5eb22005-03-13 05:43:23 +00001907 VG_(message)(Vg_DebugMsg, " %s", version_buf);
nethercotea70f7352004-04-18 12:08:46 +00001908 } else {
njn1fd5eb22005-03-13 05:43:23 +00001909 VG_(message)(Vg_DebugMsg, " (empty?)");
nethercotea70f7352004-04-18 12:08:46 +00001910 }
1911 VG_(close)(fd);
sewardj71bc3cb2005-05-19 00:25:45 +00001912# undef BUF_LEN
nethercotea70f7352004-04-18 12:08:46 +00001913 }
sewardjde4a1d02002-03-22 01:27:54 +00001914 }
1915
fitzhardinge98abfc72003-12-16 02:05:15 +00001916 if (VG_(clo_n_suppressions) < VG_CLO_MAX_SFILES-1 &&
njn95ec8702004-11-22 16:46:13 +00001917 (VG_(needs).core_errors || VG_(needs).tool_errors)) {
njn842c26e2005-06-28 02:54:52 +00001918 /* If we haven't reached the max number of suppressions, load
1919 the default one. */
fitzhardinge98abfc72003-12-16 02:05:15 +00001920 static const Char default_supp[] = "default.supp";
1921 Int len = VG_(strlen)(VG_(libdir)) + 1 + sizeof(default_supp);
1922 Char *buf = VG_(arena_malloc)(VG_AR_CORE, len);
1923 VG_(sprintf)(buf, "%s/%s", VG_(libdir), default_supp);
1924 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = buf;
1925 VG_(clo_n_suppressions)++;
sewardjde4a1d02002-03-22 01:27:54 +00001926 }
1927}
1928
nethercotef6a1d502004-08-09 12:21:57 +00001929// Build the string for VALGRINDCLO.
1930Char* VG_(build_child_VALGRINDCLO)( Char* exename )
1931{
1932 /* If we're tracing the children, then we need to start it
1933 with our starter+arguments, which are copied into VALGRINDCLO,
1934 except the --exec= option is changed if present.
1935 */
1936 Int i;
1937 Char *exec;
1938 Char *cp;
1939 Char *optvar;
1940 Int optlen, execlen;
1941
1942 // All these allocated blocks are not free - because we're either
1943 // going to exec, or panic when we fail.
1944
1945 // Create --exec= option: "--exec=<exename>"
1946 exec = VG_(arena_malloc)(VG_AR_CORE,
1947 VG_(strlen)( exename ) + 7/*--exec=*/ + 1/*\0*/);
1948 vg_assert(NULL != exec);
1949 VG_(sprintf)(exec, "--exec=%s", exename);
1950
1951 // Allocate space for optvar (may overestimate by counting --exec twice,
1952 // no matter)
1953 optlen = 1;
1954 for (i = 0; i < vg_argc; i++)
1955 optlen += VG_(strlen)(vg_argv[i]) + 1;
1956 optlen += VG_(strlen)(exec)+1;
1957 optvar = VG_(arena_malloc)(VG_AR_CORE, optlen);
1958
1959 // Copy all valgrind args except the old --exec (if present)
1960 // VG_CLO_SEP is the separator.
1961 cp = optvar;
1962 for (i = 1; i < vg_argc; i++) {
1963 Char *arg = vg_argv[i];
1964
1965 if (VG_(memcmp)(arg, "--exec=", 7) == 0) {
1966 // don't copy existing --exec= arg
1967 } else if (VG_(strcmp)(arg, "--") == 0) {
1968 // stop at "--"
1969 break;
1970 } else {
1971 // copy non "--exec" arg
1972 Int len = VG_(strlen)(arg);
1973 VG_(memcpy)(cp, arg, len);
1974 cp += len;
1975 *cp++ = VG_CLO_SEP;
1976 }
1977 }
1978 // Add the new --exec= option
1979 execlen = VG_(strlen)(exec);
1980 VG_(memcpy)(cp, exec, execlen);
1981 cp += execlen;
1982 *cp++ = VG_CLO_SEP;
1983
1984 *cp = '\0';
1985
1986 return optvar;
1987}
1988
1989// Build "/proc/self/fd/<execfd>".
1990Char* VG_(build_child_exename)( void )
1991{
1992 Char* exename = VG_(arena_malloc)(VG_AR_CORE, 64);
1993 vg_assert(NULL != exename);
1994 VG_(sprintf)(exename, "/proc/self/fd/%d", vgexecfd);
1995 return exename;
1996}
1997
sewardjde4a1d02002-03-22 01:27:54 +00001998
nethercote71980f02004-01-24 18:18:54 +00001999/*====================================================================*/
2000/*=== File descriptor setup ===*/
2001/*====================================================================*/
2002
2003static void setup_file_descriptors(void)
2004{
2005 struct vki_rlimit rl;
2006
2007 /* Get the current file descriptor limits. */
2008 if (VG_(getrlimit)(VKI_RLIMIT_NOFILE, &rl) < 0) {
2009 rl.rlim_cur = 1024;
2010 rl.rlim_max = 1024;
2011 }
2012
2013 /* Work out where to move the soft limit to. */
njn14319cc2005-03-13 06:26:22 +00002014 if (rl.rlim_cur + N_RESERVED_FDS <= rl.rlim_max) {
2015 rl.rlim_cur = rl.rlim_cur + N_RESERVED_FDS;
nethercote71980f02004-01-24 18:18:54 +00002016 } else {
2017 rl.rlim_cur = rl.rlim_max;
2018 }
2019
2020 /* Reserve some file descriptors for our use. */
njn14319cc2005-03-13 06:26:22 +00002021 VG_(fd_soft_limit) = rl.rlim_cur - N_RESERVED_FDS;
2022 VG_(fd_hard_limit) = rl.rlim_cur - N_RESERVED_FDS;
nethercote71980f02004-01-24 18:18:54 +00002023
2024 /* Update the soft limit. */
2025 VG_(setrlimit)(VKI_RLIMIT_NOFILE, &rl);
2026
nethercotef6a1d502004-08-09 12:21:57 +00002027 if (vgexecfd != -1)
2028 vgexecfd = VG_(safe_fd)( vgexecfd );
nethercote71980f02004-01-24 18:18:54 +00002029 if (VG_(clexecfd) != -1)
2030 VG_(clexecfd) = VG_(safe_fd)( VG_(clexecfd) );
2031}
2032
nethercote71980f02004-01-24 18:18:54 +00002033/*====================================================================*/
nethercote71980f02004-01-24 18:18:54 +00002034/*=== Initialise program data/text, etc. ===*/
2035/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +00002036
sewardjb5f6f512005-03-10 23:59:00 +00002037static void build_valgrind_map_callback ( Addr start, SizeT size, UInt prot,
2038 UInt dev, UInt ino, ULong foffset,
2039 const UChar* filename )
sewardjde4a1d02002-03-22 01:27:54 +00002040{
nethercote71980f02004-01-24 18:18:54 +00002041 /* Only record valgrind mappings for now, without loading any
2042 symbols. This is so we know where the free space is before we
2043 start allocating more memory (note: heap is OK, it's just mmap
2044 which is the problem here). */
sewardjb5f6f512005-03-10 23:59:00 +00002045 if (start >= VG_(client_end) && start < VG_(valgrind_last)) {
sewardj8c615892005-04-25 02:38:28 +00002046 VG_(debugLog)(2, "main",
2047 "valgrind-seg: %p-%p prot 0x%x file=%s\n",
njna4469a72005-05-08 02:06:33 +00002048 (void*)start, (void*)(start+size), prot, filename);
sewardjb5f6f512005-03-10 23:59:00 +00002049 VG_(map_file_segment)(start, size, prot,
sewardj8c615892005-04-25 02:38:28 +00002050 SF_MMAP|SF_NOSYMS|SF_VALGRIND,
2051 dev, ino, foffset, filename);
sewardjb5f6f512005-03-10 23:59:00 +00002052 /* update VG_(valgrind_last) if it looks wrong */
2053 if (start+size > VG_(valgrind_last))
sewardj8c615892005-04-25 02:38:28 +00002054 VG_(valgrind_last) = start+size-1;
nethercote71980f02004-01-24 18:18:54 +00002055 }
sewardjde4a1d02002-03-22 01:27:54 +00002056}
2057
nethercote71980f02004-01-24 18:18:54 +00002058// Global var used to pass local data to callback
nethercote4ad74312004-10-26 09:59:49 +00002059Addr sp_at_startup___global_arg = 0;
sewardjde4a1d02002-03-22 01:27:54 +00002060
sewardjb5f6f512005-03-10 23:59:00 +00002061/*
2062 This second pass adds in client mappings, and loads symbol tables
2063 for all interesting mappings. The trouble is that things can
2064 change as we go, because we're calling the Tool to track memory as
2065 we find it.
2066
2067 So for Valgrind mappings, we don't replace any mappings which
2068 aren't still identical (which will include the .so mappings, so we
2069 will load their symtabs)>
2070 */
2071static void build_segment_map_callback ( Addr start, SizeT size, UInt prot,
2072 UInt dev, UInt ino, ULong foffset,
2073 const UChar* filename )
sewardj45b672d2003-07-25 19:58:11 +00002074{
nethercote71980f02004-01-24 18:18:54 +00002075 UInt flags;
2076 Bool is_stack_segment;
2077 Addr r_esp;
sewardj45b672d2003-07-25 19:58:11 +00002078
nethercote71980f02004-01-24 18:18:54 +00002079 is_stack_segment
2080 = (start == VG_(clstk_base) && (start+size) == VG_(clstk_end));
fitzhardinge98abfc72003-12-16 02:05:15 +00002081
sewardj8c615892005-04-25 02:38:28 +00002082 VG_(debugLog)(2, "main",
2083 "any-seg: %p-%p prot 0x%x stack=%d file=%s\n",
njna4469a72005-05-08 02:06:33 +00002084 (void*)start, (void*)(start+size), prot, is_stack_segment,
2085 filename);
fitzhardinge98abfc72003-12-16 02:05:15 +00002086
nethercote71980f02004-01-24 18:18:54 +00002087 if (is_stack_segment)
2088 flags = SF_STACK | SF_GROWDOWN;
2089 else
njn0ae787c2005-06-28 22:14:53 +00002090 flags = SF_MMAP;
fitzhardinge98abfc72003-12-16 02:05:15 +00002091
nethercote71980f02004-01-24 18:18:54 +00002092 if (filename != NULL)
2093 flags |= SF_FILE;
fitzhardinge98abfc72003-12-16 02:05:15 +00002094
sewardjb5f6f512005-03-10 23:59:00 +00002095#if 0
2096 // This needs to be fixed properly. jrs 20050307
2097 if (start >= VG_(client_end) && start < VG_(valgrind_last)) {
2098 Segment *s = VG_(find_segment_before)(start);
fitzhardinge98abfc72003-12-16 02:05:15 +00002099
sewardjb5f6f512005-03-10 23:59:00 +00002100 /* We have to be a bit careful about inserting new mappings into
2101 the Valgrind part of the address space. We're actively
2102 changing things as we parse these mappings, particularly in
2103 shadow memory, and so we don't want to overwrite those
2104 changes. Therefore, we only insert/update a mapping if it is
2105 mapped from a file or it exactly matches an existing mapping.
fitzhardinge98abfc72003-12-16 02:05:15 +00002106
sewardjb5f6f512005-03-10 23:59:00 +00002107 NOTE: we're only talking about the Segment list mapping
2108 metadata; this doesn't actually mmap anything more. */
2109 if (filename || (s && s->addr == start && s->len == size)) {
2110 flags |= SF_VALGRIND;
2111 VG_(map_file_segment)(start, size, prot, flags, dev, ino, foffset, filename);
2112 } else {
2113 /* assert range is already mapped */
2114 vg_assert(VG_(is_addressable)(start, size, VKI_PROT_NONE));
2115 }
2116 } else
2117#endif
2118 VG_(map_file_segment)(start, size, prot, flags, dev, ino, foffset, filename);
2119
2120 if (VG_(is_client_addr)(start) && VG_(is_client_addr)(start+size-1)) {
2121 VG_TRACK( new_mem_startup, start, size,
2122 !!(prot & VKI_PROT_READ),
2123 !!(prot & VKI_PROT_WRITE),
2124 !!(prot & VKI_PROT_EXEC));
2125 }
sewardj3e1eb1f2002-05-18 13:14:17 +00002126
nethercote71980f02004-01-24 18:18:54 +00002127 /* If this is the stack segment mark all below %esp as noaccess. */
nethercote4ad74312004-10-26 09:59:49 +00002128 r_esp = sp_at_startup___global_arg;
nethercote71980f02004-01-24 18:18:54 +00002129 vg_assert(0 != r_esp);
2130 if (is_stack_segment) {
sewardjb5f6f512005-03-10 23:59:00 +00002131 if (0) {
2132 VG_(message)(Vg_DebugMsg, "invalidating stack area: %p .. %p",
nethercote71980f02004-01-24 18:18:54 +00002133 start,r_esp);
sewardjb5f6f512005-03-10 23:59:00 +00002134 VG_(message)(Vg_DebugMsg, " validating stack area: %p .. %p",
2135 r_esp, start+size);
2136 }
nethercote71980f02004-01-24 18:18:54 +00002137 VG_TRACK( die_mem_stack, start, r_esp-start );
sewardjb5f6f512005-03-10 23:59:00 +00002138 // what's this for?
2139 //VG_TRACK( post_mem_write, r_esp, (start+size)-r_esp );
sewardjde4a1d02002-03-22 01:27:54 +00002140 }
sewardjde4a1d02002-03-22 01:27:54 +00002141}
2142
njn2da73352005-06-18 01:35:16 +00002143/*====================================================================*/
2144/*=== Initialise the first thread. ===*/
2145/*====================================================================*/
2146
2147/* Given a pointer to the ThreadArchState for thread 1 (the root
2148 thread), initialise the VEX guest state, and copy in essential
2149 starting values.
2150*/
2151static void init_thread1state ( Addr client_ip,
2152 Addr sp_at_startup,
2153 /*inout*/ ThreadArchState* arch )
2154{
2155#if defined(VGA_x86)
2156 vg_assert(0 == sizeof(VexGuestX86State) % 8);
2157
2158 /* Zero out the initial state, and set up the simulated FPU in a
2159 sane way. */
2160 LibVEX_GuestX86_initialise(&arch->vex);
2161
2162 /* Zero out the shadow area. */
2163 VG_(memset)(&arch->vex_shadow, 0, sizeof(VexGuestX86State));
2164
2165 /* Put essential stuff into the new state. */
2166 arch->vex.guest_ESP = sp_at_startup;
2167 arch->vex.guest_EIP = client_ip;
2168
2169 /* initialise %cs, %ds and %ss to point at the operating systems
2170 default code, data and stack segments */
2171 asm volatile("movw %%cs, %0" : : "m" (arch->vex.guest_CS));
2172 asm volatile("movw %%ds, %0" : : "m" (arch->vex.guest_DS));
2173 asm volatile("movw %%ss, %0" : : "m" (arch->vex.guest_SS));
cerion85665ca2005-06-20 15:51:07 +00002174
njn2da73352005-06-18 01:35:16 +00002175#elif defined(VGA_amd64)
2176 vg_assert(0 == sizeof(VexGuestAMD64State) % 8);
2177
2178 /* Zero out the initial state, and set up the simulated FPU in a
2179 sane way. */
2180 LibVEX_GuestAMD64_initialise(&arch->vex);
2181
2182 /* Zero out the shadow area. */
2183 VG_(memset)(&arch->vex_shadow, 0, sizeof(VexGuestAMD64State));
2184
2185 /* Put essential stuff into the new state. */
2186 arch->vex.guest_RSP = sp_at_startup;
2187 arch->vex.guest_RIP = client_ip;
cerion85665ca2005-06-20 15:51:07 +00002188
2189#elif defined(VGA_ppc32)
2190 vg_assert(0 == sizeof(VexGuestPPC32State) % 8);
2191
2192 /* Zero out the initial state, and set up the simulated FPU in a
2193 sane way. */
2194 LibVEX_GuestPPC32_initialise(&arch->vex);
2195
2196 /* Zero out the shadow area. */
2197 VG_(memset)(&arch->vex_shadow, 0, sizeof(VexGuestPPC32State));
2198
2199 /* Put essential stuff into the new state. */
2200 arch->vex.guest_GPR1 = sp_at_startup;
2201 arch->vex.guest_CIA = client_ip;
2202
njn2da73352005-06-18 01:35:16 +00002203#else
2204# error Unknown arch
2205#endif
2206 // Tell the tool that we just wrote to the registers.
2207 VG_TRACK( post_reg_write, Vg_CoreStartup, /*tid*/1, /*offset*/0,
2208 sizeof(VexGuestArchState));
2209}
2210
sewardjde4a1d02002-03-22 01:27:54 +00002211
nethercote71980f02004-01-24 18:18:54 +00002212/*====================================================================*/
njn2025cf92005-06-26 20:44:48 +00002213/*=== BB profiling ===*/
2214/*====================================================================*/
2215
2216static
2217void show_BB_profile ( BBProfEntry tops[], UInt n_tops, ULong score_total )
2218{
2219 ULong score_cumul, score_here;
2220 Char buf_cumul[10], buf_here[10];
2221 Char name[64];
2222 Int r;
2223
2224 VG_(printf)("\n");
2225 VG_(printf)("-----------------------------------------------------------\n");
2226 VG_(printf)("--- BEGIN BB Profile (summary of scores) ---\n");
2227 VG_(printf)("-----------------------------------------------------------\n");
2228 VG_(printf)("\n");
2229
2230 VG_(printf)("Total score = %lld\n\n", score_total);
2231
2232 score_cumul = 0;
2233 for (r = 0; r < n_tops; r++) {
2234 if (tops[r].addr == 0)
2235 continue;
2236 name[0] = 0;
2237 VG_(get_fnname_w_offset)(tops[r].addr, name, 64);
2238 name[63] = 0;
2239 score_here = tops[r].score;
2240 score_cumul += score_here;
2241 VG_(percentify)(score_cumul, score_total, 2, 6, buf_cumul);
2242 VG_(percentify)(score_here, score_total, 2, 6, buf_here);
2243 VG_(printf)("%3d: (%9lld %s) %9lld %s 0x%llx %s\n",
2244 r,
2245 score_cumul, buf_cumul,
2246 score_here, buf_here, tops[r].addr, name );
2247 }
2248
2249 VG_(printf)("\n");
2250 VG_(printf)("-----------------------------------------------------------\n");
2251 VG_(printf)("--- BB Profile (BB details) ---\n");
2252 VG_(printf)("-----------------------------------------------------------\n");
2253 VG_(printf)("\n");
2254
2255 score_cumul = 0;
2256 for (r = 0; r < n_tops; r++) {
2257 if (tops[r].addr == 0)
2258 continue;
2259 name[0] = 0;
2260 VG_(get_fnname_w_offset)(tops[r].addr, name, 64);
2261 name[63] = 0;
2262 score_here = tops[r].score;
2263 score_cumul += score_here;
2264 VG_(percentify)(score_cumul, score_total, 2, 6, buf_cumul);
2265 VG_(percentify)(score_here, score_total, 2, 6, buf_here);
2266 VG_(printf)("\n");
2267 VG_(printf)("=-=-=-=-=-=-=-=-=-=-=-=-=-= begin BB rank %d "
2268 "=-=-=-=-=-=-=-=-=-=-=-=-=-=\n\n", r);
2269 VG_(printf)("%3d: (%9lld %s) %9lld %s 0x%llx %s\n",
2270 r,
2271 score_cumul, buf_cumul,
2272 score_here, buf_here, tops[r].addr, name );
2273 VG_(printf)("\n");
2274 VG_(translate)(0, tops[r].addr, True, VG_(clo_profile_flags), 0);
2275 VG_(printf)("=-=-=-=-=-=-=-=-=-=-=-=-=-= end BB rank %d "
2276 "=-=-=-=-=-=-=-=-=-=-=-=-=-=\n\n", r);
2277 }
2278
2279 VG_(printf)("\n");
2280 VG_(printf)("-----------------------------------------------------------\n");
2281 VG_(printf)("--- END BB Profile ---\n");
2282 VG_(printf)("-----------------------------------------------------------\n");
2283 VG_(printf)("\n");
2284}
2285
2286
2287/*====================================================================*/
nethercote71980f02004-01-24 18:18:54 +00002288/*=== main() ===*/
2289/*====================================================================*/
2290
nethercotec314eba2004-07-15 12:59:41 +00002291/*
2292 This code decides on the layout of the client and Valgrind address
nethercote996901a2004-08-03 13:29:09 +00002293 spaces, loads valgrind.so and the tool.so into the valgrind part,
nethercotec314eba2004-07-15 12:59:41 +00002294 loads the client executable (and the dynamic linker, if necessary)
2295 into the client part, and calls into Valgrind proper.
2296
2297 The code is careful not to allow spurious mappings to appear in the
2298 wrong parts of the address space. In particular, to make sure
2299 dlopen puts things in the right place, it will pad out the forbidden
2300 chunks of address space so that dlopen is forced to put things where
2301 we want them.
2302
2303 The memory map it creates is:
2304
njn311c5d82005-05-15 21:03:42 +00002305 client_base +-------------------------+
nethercotec314eba2004-07-15 12:59:41 +00002306 | client address space |
2307 : :
2308 : :
2309 | client stack |
2310 client_end +-------------------------+
2311 | redzone |
2312 shadow_base +-------------------------+
2313 | |
nethercote996901a2004-08-03 13:29:09 +00002314 : shadow memory for tools :
nethercotec314eba2004-07-15 12:59:41 +00002315 | (may be 0 sized) |
2316 shadow_end +-------------------------+
nethercotec314eba2004-07-15 12:59:41 +00002317 valgrind_base +-------------------------+
2318 | kickstart executable |
2319 | valgrind heap vvvvvvvvv| (barely used)
2320 - -
2321 | valgrind .so files |
2322 | and mappings |
2323 - -
2324 | valgrind stack ^^^^^^^^^|
nethercote820bd8c2004-09-07 23:04:49 +00002325 valgrind_last +-------------------------+
nethercotec314eba2004-07-15 12:59:41 +00002326 : kernel :
2327
2328 Nb: Before we can do general allocations with VG_(arena_malloc)() and
2329 VG_(mmap)(), we need to build the segment skip-list, so we know where
2330 we can put things. However, building that structure requires
2331 allocating memory. So we need to a bootstrapping process. It's done
2332 by making VG_(arena_malloc)() have a special static superblock that's
2333 used for the first 1MB's worth of allocations. This is enough to
2334 build the segment skip-list.
2335*/
2336
thughes4ad52d02004-06-27 17:37:21 +00002337
sewardj1cf558c2005-04-25 01:36:56 +00002338/* This may be needed before m_mylibc is OK to run. */
2339static Int local_strcmp ( const HChar* s1, const HChar* s2 )
2340{
2341 while (True) {
2342 if (*s1 == 0 && *s2 == 0) return 0;
2343 if (*s1 == 0) return -1;
2344 if (*s2 == 0) return 1;
2345
2346 if (*(UChar*)s1 < *(UChar*)s2) return -1;
2347 if (*(UChar*)s1 > *(UChar*)s2) return 1;
2348
2349 s1++; s2++;
2350 }
2351}
2352
2353
sewardjb5f6f512005-03-10 23:59:00 +00002354int main(int argc, char **argv, char **envp)
nethercote71980f02004-01-24 18:18:54 +00002355{
2356 char **cl_argv;
sewardjb5f6f512005-03-10 23:59:00 +00002357 const char *tool = "memcheck"; // default to Memcheck
nethercote71980f02004-01-24 18:18:54 +00002358 const char *exec = NULL;
2359 char *preload; /* tool-specific LD_PRELOAD .so */
2360 char **env;
nethercote6c999f22004-01-31 22:55:15 +00002361 Int need_help = 0; // 0 = no, 1 = --help, 2 = --help-debug
nethercote71980f02004-01-24 18:18:54 +00002362 struct exeinfo info;
2363 ToolInfo *toolinfo = NULL;
nethercote71980f02004-01-24 18:18:54 +00002364 Addr client_eip;
nethercote4ad74312004-10-26 09:59:49 +00002365 Addr sp_at_startup; /* client's SP at the point we gained control. */
nethercote71980f02004-01-24 18:18:54 +00002366 UInt * client_auxv;
nethercote73b526f2004-10-31 18:48:21 +00002367 struct vki_rlimit zero = { 0, 0 };
sewardj1cf558c2005-04-25 01:36:56 +00002368 Int padfile, loglevel, i;
nethercote71980f02004-01-24 18:18:54 +00002369
2370 //============================================================
2371 // Nb: startup is complex. Prerequisites are shown at every step.
2372 //
2373 // *** Be very careful when messing with the order ***
2374 //============================================================
2375
sewardj1cf558c2005-04-25 01:36:56 +00002376 //--------------------------------------------------------------
2377 // Start up the logging mechanism
2378 // p: none
2379 //--------------------------------------------------------------
2380 /* Start the debugging-log system ASAP. First find out how many
2381 "-d"s were specified. This is a pre-scan of the command line. */
2382 loglevel = 0;
2383 for (i = 1; i < argc; i++) {
sewardj10759312005-05-30 23:52:47 +00002384 if (argv[i][0] != '-')
2385 break;
2386 if (0 == local_strcmp(argv[i], "--"))
2387 break;
2388 if (0 == local_strcmp(argv[i], "-d"))
2389 loglevel++;
sewardj1cf558c2005-04-25 01:36:56 +00002390 }
2391
2392 /* ... and start the debug logger. Now we can safely emit logging
2393 messages all through startup. */
sewardj10759312005-05-30 23:52:47 +00002394 VG_(debugLog_startup)(loglevel, "Stage 2 (main)");
sewardj1cf558c2005-04-25 01:36:56 +00002395
nethercotef4928da2004-06-15 10:54:40 +00002396 //============================================================
2397 // Command line argument handling order:
2398 // * If --help/--help-debug are present, show usage message
sewardjb5f6f512005-03-10 23:59:00 +00002399 // (including the tool-specific usage)
2400 // * (If no --tool option given, default to Memcheck)
nethercotef4928da2004-06-15 10:54:40 +00002401 // * Then, if client is missing, abort with error msg
2402 // * Then, if any cmdline args are bad, abort with error msg
2403 //============================================================
2404
fitzhardingeb50068f2004-02-24 23:42:55 +00002405 // Get the current process datasize rlimit, and set it to zero.
2406 // This prevents any internal uses of brk() from having any effect.
2407 // We remember the old value so we can restore it on exec, so that
2408 // child processes will have a reasonable brk value.
2409 VG_(getrlimit)(VKI_RLIMIT_DATA, &VG_(client_rlimit_data));
2410 zero.rlim_max = VG_(client_rlimit_data).rlim_max;
2411 VG_(setrlimit)(VKI_RLIMIT_DATA, &zero);
thughesc37184f2004-09-11 14:16:57 +00002412
2413 // Get the current process stack rlimit.
2414 VG_(getrlimit)(VKI_RLIMIT_STACK, &VG_(client_rlimit_stack));
2415
nethercote71980f02004-01-24 18:18:54 +00002416 //--------------------------------------------------------------
2417 // Check we were launched by stage1
sewardj51ac0872004-12-21 01:20:49 +00002418 // p: none
nethercote71980f02004-01-24 18:18:54 +00002419 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002420 VG_(debugLog)(1, "main", "Doing scan_auxv()\n");
nethercotec25c4492004-10-18 11:52:17 +00002421 {
sewardj1fbc1a52005-04-25 02:05:54 +00002422 void* init_sp = argv - 1;
2423 padfile = scan_auxv(init_sp);
nethercote71980f02004-01-24 18:18:54 +00002424 }
2425
2426 //--------------------------------------------------------------
2427 // Look for alternative libdir
sewardj51ac0872004-12-21 01:20:49 +00002428 // p: none
nethercote71980f02004-01-24 18:18:54 +00002429 //--------------------------------------------------------------
sewardj51ac0872004-12-21 01:20:49 +00002430 { HChar *cp = getenv(VALGRINDLIB);
nethercote71980f02004-01-24 18:18:54 +00002431 if (cp != NULL)
2432 VG_(libdir) = cp;
2433 }
2434
2435 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002436 // Get valgrind args + client args (inc. from VALGRIND_OPTS/.valgrindrc).
2437 // Pre-process the command line.
sewardj51ac0872004-12-21 01:20:49 +00002438 // p: none
nethercote71980f02004-01-24 18:18:54 +00002439 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002440 VG_(debugLog)(1, "main", "Preprocess command line opts\n");
nethercotef6a1d502004-08-09 12:21:57 +00002441 get_command_line(argc, argv, &vg_argc, &vg_argv, &cl_argv);
nethercote71980f02004-01-24 18:18:54 +00002442 pre_process_cmd_line_options(&need_help, &tool, &exec);
2443
sewardj10759312005-05-30 23:52:47 +00002444 /* If this process was created by exec done by another Valgrind
2445 process, the arguments will only show up at this point. Hence
2446 we need to also snoop around in vg_argv to see if anyone is
2447 asking for debug logging. */
2448 if (loglevel == 0) {
2449 for (i = 1; i < vg_argc; i++) {
2450 if (vg_argv[i][0] != '-')
2451 break;
2452 if (0 == local_strcmp(vg_argv[i], "--"))
2453 break;
2454 if (0 == local_strcmp(vg_argv[i], "-d"))
2455 loglevel++;
2456 }
2457 VG_(debugLog_startup)(loglevel, "Stage 2 (second go)");
2458 }
2459
nethercote71980f02004-01-24 18:18:54 +00002460 //==============================================================
2461 // Nb: once a tool is specified, the tool.so must be loaded even if
2462 // they specified --help or didn't specify a client program.
2463 //==============================================================
2464
2465 //--------------------------------------------------------------
2466 // With client padded out, map in tool
nethercote71980f02004-01-24 18:18:54 +00002467 // p: set-libdir [for VG_(libdir)]
2468 // p: pre_process_cmd_line_options() [for 'tool']
2469 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002470 VG_(debugLog)(1, "main", "Loading tool\n");
njn8a97c6d2005-03-31 04:37:24 +00002471 load_tool(tool, &toolinfo, &preload);
nethercote71980f02004-01-24 18:18:54 +00002472
2473 //==============================================================
2474 // Can use VG_(malloc)() and VG_(arena_malloc)() only after load_tool()
nethercotec314eba2004-07-15 12:59:41 +00002475 // -- redzone size is now set. This is checked by vg_malloc2.c.
nethercote71980f02004-01-24 18:18:54 +00002476 //==============================================================
2477
2478 //--------------------------------------------------------------
2479 // Finalise address space layout
nethercote31779c72004-07-30 21:50:15 +00002480 // p: load_tool() [for 'toolinfo']
nethercote71980f02004-01-24 18:18:54 +00002481 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002482 VG_(debugLog)(1, "main", "Laying out remaining space\n");
nethercote31779c72004-07-30 21:50:15 +00002483 layout_remaining_space( (Addr) & argc, toolinfo->shadow_ratio );
nethercote71980f02004-01-24 18:18:54 +00002484
2485 //--------------------------------------------------------------
2486 // Load client executable, finding in $PATH if necessary
nethercote71980f02004-01-24 18:18:54 +00002487 // p: pre_process_cmd_line_options() [for 'exec', 'need_help']
2488 // p: layout_remaining_space [so there's space]
2489 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002490 VG_(debugLog)(1, "main", "Loading client\n");
nethercotef4928da2004-06-15 10:54:40 +00002491 load_client(cl_argv, exec, need_help, &info, &client_eip);
nethercote71980f02004-01-24 18:18:54 +00002492
2493 //--------------------------------------------------------------
nethercote969ecf12004-10-13 17:29:01 +00002494 // Everything in place, remove padding done by stage1
nethercote71980f02004-01-24 18:18:54 +00002495 // p: layout_remaining_space() [everything must be mapped in before now]
2496 // p: load_client() [ditto]
2497 //--------------------------------------------------------------
nethercote31779c72004-07-30 21:50:15 +00002498 as_unpad((void *)VG_(shadow_end), (void *)~0, padfile);
2499 as_closepadfile(padfile); // no more padding
nethercote71980f02004-01-24 18:18:54 +00002500
2501 //--------------------------------------------------------------
2502 // Set up client's environment
2503 // p: set-libdir [for VG_(libdir)]
2504 // p: load_tool() [for 'preload']
2505 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002506 VG_(debugLog)(1, "main", "Setup client env\n");
sewardjb5f6f512005-03-10 23:59:00 +00002507 env = fix_environment(envp, preload);
nethercote71980f02004-01-24 18:18:54 +00002508
2509 //--------------------------------------------------------------
nethercote5ee67ca2004-06-22 14:00:09 +00002510 // Setup client stack, eip, and VG_(client_arg[cv])
nethercote71980f02004-01-24 18:18:54 +00002511 // p: load_client() [for 'info']
2512 // p: fix_environment() [for 'env']
2513 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002514 VG_(debugLog)(1, "main", "Setup client stack\n");
nethercotec25c4492004-10-18 11:52:17 +00002515 {
sewardj1fbc1a52005-04-25 02:05:54 +00002516 void* init_sp = argv - 1;
sewardjb5f6f512005-03-10 23:59:00 +00002517
sewardj1fbc1a52005-04-25 02:05:54 +00002518 sp_at_startup = setup_client_stack(init_sp, cl_argv, env, &info,
2519 &client_auxv);
2520 free(env);
nethercotec25c4492004-10-18 11:52:17 +00002521 }
nethercote71980f02004-01-24 18:18:54 +00002522
sewardj1fbc1a52005-04-25 02:05:54 +00002523 VG_(debugLog)(2, "main",
2524 "Client info: "
2525 "entry=%p client esp=%p vg_argc=%d brkbase=%p\n",
2526 (void*)client_eip, (void*)sp_at_startup, vg_argc,
2527 (void*)VG_(brk_base) );
nethercote71980f02004-01-24 18:18:54 +00002528
2529 //==============================================================
2530 // Finished setting up operating environment. Now initialise
2531 // Valgrind. (This is where the old VG_(main)() started.)
2532 //==============================================================
2533
2534 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002535 // setup file descriptors
2536 // p: n/a
2537 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002538 VG_(debugLog)(1, "main", "Setup file descriptors\n");
nethercote71980f02004-01-24 18:18:54 +00002539 setup_file_descriptors();
2540
2541 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002542 // Build segment map (Valgrind segments only)
njnd2252832004-11-26 10:53:33 +00002543 // p: tl_pre_clo_init() [to setup new_mem_startup tracker]
nethercotec314eba2004-07-15 12:59:41 +00002544 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002545 VG_(debugLog)(1, "main", "Parse /proc/self/maps (round 1)\n");
nethercotec314eba2004-07-15 12:59:41 +00002546 VG_(parse_procselfmaps) ( build_valgrind_map_callback );
2547
2548 //==============================================================
2549 // Can use VG_(arena_malloc)() with non-CORE arena after segments set up
2550 //==============================================================
2551
2552 //--------------------------------------------------------------
2553 // Init tool: pre_clo_init, process cmd line, post_clo_init
2554 // p: setup_client_stack() [for 'VG_(client_arg[cv]']
njn8a97c6d2005-03-31 04:37:24 +00002555 // p: load_tool() [for 'toolinfo']
nethercotec314eba2004-07-15 12:59:41 +00002556 // p: setup_file_descriptors() [for 'VG_(fd_xxx_limit)']
2557 // p: parse_procselfmaps [so VG segments are setup so tool can
2558 // call VG_(malloc)]
nethercote71980f02004-01-24 18:18:54 +00002559 //--------------------------------------------------------------
njn64c83242005-06-21 01:54:38 +00002560 {
2561 Char* s;
2562 Bool ok;
2563 VG_(debugLog)(1, "main", "Initialise the tool\n");
2564 (*toolinfo->tl_pre_clo_init)();
2565 ok = VG_(sanity_check_needs)( VG_(shadow_base) != VG_(shadow_end), &s );
2566 if (!ok) {
2567 VG_(tool_panic)(s);
2568 }
2569 }
nethercote71980f02004-01-24 18:18:54 +00002570
nethercotef4928da2004-06-15 10:54:40 +00002571 // If --tool and --help/--help-debug was given, now give the core+tool
2572 // help message
nethercotef4928da2004-06-15 10:54:40 +00002573 if (need_help) {
2574 usage(/*--help-debug?*/2 == need_help);
2575 }
nethercotec314eba2004-07-15 12:59:41 +00002576 process_cmd_line_options(client_auxv, tool);
2577
njn51d827b2005-05-09 01:02:08 +00002578 VG_TDICT_CALL(tool_post_clo_init);
nethercotef4928da2004-06-15 10:54:40 +00002579
2580 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002581 // Build segment map (all segments)
sewardjb5f6f512005-03-10 23:59:00 +00002582 // p: shadow/redzone segments
nethercote4ad74312004-10-26 09:59:49 +00002583 // p: setup_client_stack() [for 'sp_at_startup']
nethercotec314eba2004-07-15 12:59:41 +00002584 // p: init tool [for 'new_mem_startup']
nethercote71980f02004-01-24 18:18:54 +00002585 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002586 VG_(debugLog)(1, "main", "Parse /proc/self/maps (round 2)\n");
nethercote4ad74312004-10-26 09:59:49 +00002587 sp_at_startup___global_arg = sp_at_startup;
nethercotec314eba2004-07-15 12:59:41 +00002588 VG_(parse_procselfmaps) ( build_segment_map_callback ); /* everything */
nethercote4ad74312004-10-26 09:59:49 +00002589 sp_at_startup___global_arg = 0;
sewardjb5f6f512005-03-10 23:59:00 +00002590
nethercotec314eba2004-07-15 12:59:41 +00002591 //==============================================================
2592 // Can use VG_(map)() after segments set up
2593 //==============================================================
nethercote71980f02004-01-24 18:18:54 +00002594
2595 //--------------------------------------------------------------
2596 // Allow GDB attach
2597 // p: process_cmd_line_options() [for VG_(clo_wait_for_gdb)]
2598 //--------------------------------------------------------------
2599 /* Hook to delay things long enough so we can get the pid and
2600 attach GDB in another shell. */
2601 if (VG_(clo_wait_for_gdb)) {
sewardj8211a572005-06-23 21:37:47 +00002602 Long q, iters;
sewardj1fbc1a52005-04-25 02:05:54 +00002603 VG_(debugLog)(1, "main", "Wait for GDB\n");
sewardj93ab8572005-02-06 14:10:40 +00002604 VG_(printf)("pid=%d, entering delay loop\n", VG_(getpid)());
2605 /* jrs 20050206: I don't understand why this works on x86. On
2606 amd64 the obvious analogues (jump *$rip or jump *$rcx) don't
2607 work. */
2608 /* do "jump *$eip" to skip this in gdb (x86) */
2609 //VG_(do_syscall0)(__NR_pause);
sewardj8211a572005-06-23 21:37:47 +00002610
2611# if defined(VGP_x86_linux)
2612 iters = 5;
2613# elif defined(VGP_amd64_linux)
2614 iters = 10;
2615# elif defined(VGP_ppc32_linux)
2616 iters = 1;
2617# else
2618# error "Unknown plat"
2619# endif
2620
2621 iters *= 1000*1000*1000;
2622 for (q = 0; q < iters; q++)
2623 ;
nethercote71980f02004-01-24 18:18:54 +00002624 }
2625
sewardjb5d320c2005-03-13 18:57:15 +00002626 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002627 // Search for file descriptors that are inherited from our parent
2628 // p: process_cmd_line_options [for VG_(clo_track_fds)]
2629 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002630 if (VG_(clo_track_fds)) {
2631 VG_(debugLog)(1, "main", "Init preopened fds\n");
nethercote71980f02004-01-24 18:18:54 +00002632 VG_(init_preopened_fds)();
sewardj1fbc1a52005-04-25 02:05:54 +00002633 }
nethercote71980f02004-01-24 18:18:54 +00002634
2635 //--------------------------------------------------------------
2636 // Initialise the scheduler
nethercote71980f02004-01-24 18:18:54 +00002637 // p: setup_file_descriptors() [else VG_(safe_fd)() breaks]
2638 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002639 VG_(debugLog)(1, "main", "Initialise scheduler\n");
nethercote71980f02004-01-24 18:18:54 +00002640 VG_(scheduler_init)();
2641
2642 //--------------------------------------------------------------
sewardjb5f6f512005-03-10 23:59:00 +00002643 // Initialise the pthread model
2644 // p: ?
sewardj2a99cf62004-11-24 10:44:19 +00002645 // load_client() [for 'client_eip']
2646 // setup_client_stack() [for 'sp_at_startup']
2647 // setup_scheduler() [for the rest of state 1 stuff]
2648 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002649 VG_(debugLog)(1, "main", "Initialise thread 1's state\n");
njn2da73352005-06-18 01:35:16 +00002650 init_thread1state(client_eip, sp_at_startup, &VG_(threads)[1].arch);
njnea4b28c2004-11-30 16:04:58 +00002651
sewardj2a99cf62004-11-24 10:44:19 +00002652 //--------------------------------------------------------------
sewardj39b88fb2005-03-12 15:16:07 +00002653 // Initialise the pthread model
2654 // p: ?
nethercote71980f02004-01-24 18:18:54 +00002655 //--------------------------------------------------------------
sewardjb5f6f512005-03-10 23:59:00 +00002656 //if (VG_(clo_model_pthreads))
2657 // VG_(pthread_init)();
nethercote71980f02004-01-24 18:18:54 +00002658
2659 //--------------------------------------------------------------
2660 // Initialise the signal handling subsystem
sewardjb5f6f512005-03-10 23:59:00 +00002661 // p: n/a
nethercote71980f02004-01-24 18:18:54 +00002662 //--------------------------------------------------------------
2663 // Nb: temporarily parks the saved blocking-mask in saved_sigmask.
sewardj1fbc1a52005-04-25 02:05:54 +00002664 VG_(debugLog)(1, "main", "Initialise signal management\n");
nethercote71980f02004-01-24 18:18:54 +00002665 VG_(sigstartup_actions)();
2666
2667 //--------------------------------------------------------------
2668 // Perhaps we're profiling Valgrind?
2669 // p: process_cmd_line_options() [for VG_(clo_profile)]
2670 // p: others?
2671 //
2672 // XXX: this seems to be broken? It always says the tool wasn't built
2673 // for profiling; vg_profile.c's functions don't seem to be overriding
2674 // vg_dummy_profile.c's?
2675 //
2676 // XXX: want this as early as possible. Looking for --profile
2677 // in pre_process_cmd_line_options() could get it earlier.
2678 //--------------------------------------------------------------
2679 if (VG_(clo_profile))
njn31066fd2005-03-26 00:42:02 +00002680 VG_(init_profiling)();
nethercote71980f02004-01-24 18:18:54 +00002681
2682 VGP_PUSHCC(VgpStartup);
2683
2684 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002685 // Read suppression file
2686 // p: process_cmd_line_options() [for VG_(clo_suppressions)]
2687 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002688 if (VG_(needs).core_errors || VG_(needs).tool_errors) {
2689 VG_(debugLog)(1, "main", "Load suppressions\n");
nethercote71980f02004-01-24 18:18:54 +00002690 VG_(load_suppressions)();
sewardj1fbc1a52005-04-25 02:05:54 +00002691 }
nethercote71980f02004-01-24 18:18:54 +00002692
2693 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002694 // Initialise translation table and translation cache
2695 // p: read_procselfmaps [so the anonymous mmaps for the TT/TC
2696 // aren't identified as part of the client, which would waste
2697 // > 20M of virtual address space.]
2698 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002699 VG_(debugLog)(1, "main", "Initialise TT/TC\n");
nethercote71980f02004-01-24 18:18:54 +00002700 VG_(init_tt_tc)();
2701
2702 //--------------------------------------------------------------
sewardjb9bce632005-06-21 01:41:34 +00002703 // Initialise the redirect table.
sewardjb5d320c2005-03-13 18:57:15 +00002704 // p: parse_procselfmaps? [XXX for debug info?]
2705 // p: init_tt_tc [so it can call VG_(search_transtab) safely]
2706 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002707 VG_(debugLog)(1, "main", "Initialise redirects\n");
sewardjb5d320c2005-03-13 18:57:15 +00002708 VG_(setup_code_redirect_table)();
2709
2710 //--------------------------------------------------------------
sewardjb9bce632005-06-21 01:41:34 +00002711 // Tell the tool about permissions in our handwritten assembly
2712 // helpers.
2713 // p: init tool [for 'new_mem_startup']
2714 //--------------------------------------------------------------
2715 VG_(debugLog)(1, "main", "Tell tool about permissions for asm helpers\n");
2716 VG_TRACK( new_mem_startup,
2717 (Addr)&VG_(trampoline_stuff_start),
2718 &VG_(trampoline_stuff_end) - &VG_(trampoline_stuff_start),
2719 False, /* readable? */
2720 False, /* writable? */
2721 True /* executable? */ );
2722
2723 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002724 // Verbosity message
2725 // p: end_rdtsc_calibration [so startup message is printed first]
2726 //--------------------------------------------------------------
sewardj71bc3cb2005-05-19 00:25:45 +00002727 if (VG_(clo_verbosity) == 1 && !VG_(clo_xml))
nethercote71980f02004-01-24 18:18:54 +00002728 VG_(message)(Vg_UserMsg, "For more details, rerun with: -v");
2729 if (VG_(clo_verbosity) > 0)
2730 VG_(message)(Vg_UserMsg, "");
2731
2732 //--------------------------------------------------------------
2733 // Setup pointercheck
njn04e16982005-05-31 00:23:43 +00002734 // p: layout_remaining_space() [for VG_(client_{base,end})]
nethercote71980f02004-01-24 18:18:54 +00002735 // p: process_cmd_line_options() [for VG_(clo_pointercheck)]
2736 //--------------------------------------------------------------
nethercote775508a2004-09-07 22:38:23 +00002737 if (VG_(clo_pointercheck))
njn04e16982005-05-31 00:23:43 +00002738 VG_(clo_pointercheck) =
njnaf839f52005-06-23 03:27:57 +00002739 VG_(setup_pointercheck)( VG_(client_base), VG_(client_end));
nethercote71980f02004-01-24 18:18:54 +00002740
nethercote71980f02004-01-24 18:18:54 +00002741 //--------------------------------------------------------------
rjwalsh0140af52005-06-04 20:42:33 +00002742 // register client stack
2743 //--------------------------------------------------------------
njn945ed2e2005-06-24 03:28:30 +00002744 VG_(clstk_id) = VG_(register_stack)(VG_(clstk_base), VG_(clstk_end));
rjwalsh0140af52005-06-04 20:42:33 +00002745
2746 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002747 // Run!
2748 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002749 VGP_POPCC(VgpStartup);
nethercote71980f02004-01-24 18:18:54 +00002750
sewardj71bc3cb2005-05-19 00:25:45 +00002751 if (VG_(clo_xml)) {
2752 VG_(message)(Vg_UserMsg, "<status>RUNNING</status>");
2753 VG_(message)(Vg_UserMsg, "");
2754 }
2755
sewardj1fbc1a52005-04-25 02:05:54 +00002756 VG_(debugLog)(1, "main", "Running thread 1\n");
sewardj1d887112005-05-30 21:44:08 +00002757 /* As a result of the following call, the last thread standing
2758 eventually winds up running VG_(shutdown_actions_NORETURN) just
2759 below. */
njnaf839f52005-06-23 03:27:57 +00002760 VG_(main_thread_wrapper_NORETURN)(1);
nethercote71980f02004-01-24 18:18:54 +00002761
sewardj1d887112005-05-30 21:44:08 +00002762 /*NOTREACHED*/
2763 vg_assert(0);
sewardjb5f6f512005-03-10 23:59:00 +00002764}
2765
2766
njn9cb54ac2005-06-12 04:19:17 +00002767/* Final clean-up before terminating the process.
2768 Clean up the client by calling __libc_freeres() (if requested)
2769 This is Linux-specific?
2770*/
2771static void final_tidyup(ThreadId tid)
2772{
njnbc6d84d2005-06-19 18:58:03 +00002773 Addr __libc_freeres_wrapper;
2774
njn9cb54ac2005-06-12 04:19:17 +00002775 vg_assert(VG_(is_running_thread)(tid));
2776
njnbc6d84d2005-06-19 18:58:03 +00002777 if ( !VG_(needs).libc_freeres ||
2778 !VG_(clo_run_libc_freeres) ||
2779 0 == (__libc_freeres_wrapper = VG_(get_libc_freeres_wrapper)()) )
njn9cb54ac2005-06-12 04:19:17 +00002780 return; /* can't/won't do it */
2781
2782 if (VG_(clo_verbosity) > 2 ||
2783 VG_(clo_trace_syscalls) ||
2784 VG_(clo_trace_sched))
2785 VG_(message)(Vg_DebugMsg,
2786 "Caught __NR_exit; running __libc_freeres()");
2787
2788 /* point thread context to point to libc_freeres_wrapper */
njnf536bbb2005-06-13 04:21:38 +00002789 VG_(set_IP)(tid, __libc_freeres_wrapper);
njn9cb54ac2005-06-12 04:19:17 +00002790 // XXX should we use a special stack?
2791
2792 /* Block all blockable signals by copying the real block state into
2793 the thread's block state*/
2794 VG_(sigprocmask)(VKI_SIG_BLOCK, NULL, &VG_(threads)[tid].sig_mask);
2795 VG_(threads)[tid].tmp_sig_mask = VG_(threads)[tid].sig_mask;
2796
2797 /* and restore handlers to default */
2798 VG_(set_default_handler)(VKI_SIGSEGV);
2799 VG_(set_default_handler)(VKI_SIGBUS);
2800 VG_(set_default_handler)(VKI_SIGILL);
2801 VG_(set_default_handler)(VKI_SIGFPE);
2802
2803 // We were exiting, so assert that...
2804 vg_assert(VG_(is_exiting)(tid));
2805 // ...but now we're not again
2806 VG_(threads)[tid].exitreason = VgSrc_None;
2807
2808 // run until client thread exits - ideally with LIBC_FREERES_DONE,
2809 // but exit/exitgroup/signal will do
2810 VG_(scheduler)(tid);
2811
2812 vg_assert(VG_(is_exiting)(tid));
2813}
2814
sewardjb5f6f512005-03-10 23:59:00 +00002815/* Do everything which needs doing when the last thread exits */
sewardj1d887112005-05-30 21:44:08 +00002816void VG_(shutdown_actions_NORETURN) ( ThreadId tid,
2817 VgSchedReturnCode tids_schedretcode )
sewardjb5f6f512005-03-10 23:59:00 +00002818{
sewardj1d887112005-05-30 21:44:08 +00002819 VG_(debugLog)(1, "main", "entering VG_(shutdown_actions_NORETURN)\n");
2820
2821 vg_assert( VG_(count_living_threads)() == 1 );
sewardjb5f6f512005-03-10 23:59:00 +00002822 vg_assert(VG_(is_running_thread)(tid));
2823
2824 // Wait for all other threads to exit.
njn7b85dd52005-06-12 17:26:29 +00002825 VG_(reap_threads)(tid);
sewardjb5f6f512005-03-10 23:59:00 +00002826
2827 VG_(clo_model_pthreads) = False;
2828
2829 // Clean the client up before the final report
njn9cb54ac2005-06-12 04:19:17 +00002830 final_tidyup(tid);
sewardjb5f6f512005-03-10 23:59:00 +00002831
2832 // OK, done
2833 VG_(exit_thread)(tid);
2834
2835 /* should be no threads left */
2836 vg_assert(VG_(count_living_threads)() == 0);
2837
2838 VG_(threads)[tid].status = VgTs_Empty;
nethercote71980f02004-01-24 18:18:54 +00002839 //--------------------------------------------------------------
2840 // Finalisation: cleanup, messages, etc. Order no so important, only
2841 // affects what order the messages come.
2842 //--------------------------------------------------------------
2843 if (VG_(clo_verbosity) > 0)
2844 VG_(message)(Vg_UserMsg, "");
2845
sewardj71bc3cb2005-05-19 00:25:45 +00002846 if (VG_(clo_xml)) {
sewardj9f297ca2005-05-20 02:29:52 +00002847 if (VG_(needs).core_errors || VG_(needs).tool_errors) {
2848 VG_(show_error_counts_as_XML)();
2849 VG_(message)(Vg_UserMsg, "");
2850 }
sewardj71bc3cb2005-05-19 00:25:45 +00002851 VG_(message)(Vg_UserMsg, "<status>FINISHED</status>");
2852 VG_(message)(Vg_UserMsg, "");
2853 }
2854
nethercote71980f02004-01-24 18:18:54 +00002855 /* Print out file descriptor summary and stats. */
2856 if (VG_(clo_track_fds))
nethercote3a42fb82004-08-03 18:08:50 +00002857 VG_(show_open_fds)();
nethercote71980f02004-01-24 18:18:54 +00002858
njn95ec8702004-11-22 16:46:13 +00002859 if (VG_(needs).core_errors || VG_(needs).tool_errors)
nethercote71980f02004-01-24 18:18:54 +00002860 VG_(show_all_errors)();
2861
njn51d827b2005-05-09 01:02:08 +00002862 VG_TDICT_CALL(tool_fini, 0/*exitcode*/);
nethercote71980f02004-01-24 18:18:54 +00002863
sewardj71bc3cb2005-05-19 00:25:45 +00002864 if (VG_(clo_xml)) {
2865 VG_(message)(Vg_UserMsg, "");
2866 VG_(message)(Vg_UserMsg, "</valgrindoutput>");
2867 VG_(message)(Vg_UserMsg, "");
2868 }
2869
nethercote885dd912004-08-03 23:14:00 +00002870 VG_(sanity_check_general)( True /*include expensive checks*/ );
nethercote71980f02004-01-24 18:18:54 +00002871
2872 if (VG_(clo_verbosity) > 1)
nethercote3a42fb82004-08-03 18:08:50 +00002873 print_all_stats();
nethercote71980f02004-01-24 18:18:54 +00002874
nethercote71980f02004-01-24 18:18:54 +00002875 if (VG_(clo_profile))
njn31066fd2005-03-26 00:42:02 +00002876 VG_(done_profiling)();
njn2025cf92005-06-26 20:44:48 +00002877
2878 if (VG_(clo_profile_flags) > 0) {
2879 #define N_MAX 100
2880 BBProfEntry tops[N_MAX];
2881 ULong score_total = VG_(get_BB_profile) (tops, N_MAX);
2882 show_BB_profile(tops, N_MAX, score_total);
2883 }
sewardjfa8ec112005-01-19 11:55:34 +00002884
sewardj8b635a42004-11-22 19:01:47 +00002885 /* Print Vex storage stats */
sewardjbf426512005-01-17 18:35:30 +00002886 if (0)
2887 LibVEX_ShowAllocStats();
sewardj1d887112005-05-30 21:44:08 +00002888
njn8aa35852005-06-10 22:59:56 +00002889 /* Ok, finally exit in the os-specific way, according to the scheduler's
2890 return code. In short, if the (last) thread exited by calling
2891 sys_exit, do likewise; if the (last) thread stopped due to a fatal
2892 signal, terminate the entire system with that same fatal signal. */
2893 VG_(debugLog)(1, "core_os",
njn7b85dd52005-06-12 17:26:29 +00002894 "VG_(terminate_NORETURN)(tid=%lld)\n", (ULong)tid);
njn8aa35852005-06-10 22:59:56 +00002895
2896 vg_assert(VG_(count_living_threads)() == 0);
2897
2898 switch (tids_schedretcode) {
2899 case VgSrc_ExitSyscall: /* the normal way out */
2900 VG_(exit)( VG_(threads)[tid].os_state.exitcode );
2901 /* NOT ALIVE HERE! */
2902 VG_(core_panic)("entered the afterlife in main() -- ExitSyscall");
2903 break; /* what the hell :) */
2904
2905 case VgSrc_FatalSig:
2906 /* We were killed by a fatal signal, so replicate the effect */
2907 vg_assert(VG_(threads)[tid].os_state.fatalsig != 0);
2908 VG_(kill_self)(VG_(threads)[tid].os_state.fatalsig);
2909 VG_(core_panic)("main(): signal was supposed to be fatal");
2910 break;
2911
2912 default:
2913 VG_(core_panic)("main(): unexpected scheduler return code");
2914 }
njne96be672005-05-08 19:08:54 +00002915}
sewardj8b635a42004-11-22 19:01:47 +00002916
sewardjde4a1d02002-03-22 01:27:54 +00002917/*--------------------------------------------------------------------*/
njn04e16982005-05-31 00:23:43 +00002918/*--- end ---*/
sewardjde4a1d02002-03-22 01:27:54 +00002919/*--------------------------------------------------------------------*/