blob: a0886059f939ffbde9429b607a7510f8c5b2afe2 [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
njnc7561b92005-06-19 01:24:32 +000031#include "pub_core_basics.h"
32#include "pub_core_threadstate.h"
sewardj45f4e7c2005-09-27 19:20:21 +000033#include "pub_core_clientstate.h"
sewardj55f9d1a2005-04-25 11:11:44 +000034#include "pub_core_aspacemgr.h"
sewardj45f4e7c2005-09-27 19:20:21 +000035#include "pub_core_commandline.h"
njn2521d322005-05-08 14:45:13 +000036#include "pub_core_debuglog.h"
37#include "pub_core_errormgr.h"
38#include "pub_core_execontext.h"
njn97405b22005-06-02 03:39:33 +000039#include "pub_core_libcbase.h"
njn132bfcc2005-06-04 19:16:06 +000040#include "pub_core_libcassert.h"
njneb8896b2005-06-04 20:03:55 +000041#include "pub_core_libcfile.h"
njn36a20fa2005-06-03 03:08:39 +000042#include "pub_core_libcprint.h"
njnf39e9a32005-06-12 02:43:17 +000043#include "pub_core_libcproc.h"
njnde62cbf2005-06-10 22:08:14 +000044#include "pub_core_libcsignal.h"
sewardj45f4e7c2005-09-27 19:20:21 +000045#include "pub_core_syscall.h" // VG_(strerror)
njnf536bbb2005-06-13 04:21:38 +000046#include "pub_core_machine.h"
njn04e16982005-05-31 00:23:43 +000047#include "pub_core_main.h"
njnaf1d7df2005-06-11 01:31:52 +000048#include "pub_core_mallocfree.h"
njn20242342005-05-16 23:31:24 +000049#include "pub_core_options.h"
njn31513b42005-06-01 03:09:59 +000050#include "pub_core_profile.h"
sewardjfdf91b42005-09-28 00:53:09 +000051#include "pub_core_debuginfo.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"
sewardjfdf91b42005-09-28 00:53:09 +000057#include "pub_core_translate.h" // For VG_(translate)
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
sewardjb5f6f512005-03-10 23:59:00 +000063
nethercote71980f02004-01-24 18:18:54 +000064/*====================================================================*/
65/*=== Counters, for profiling purposes only ===*/
66/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +000067
nethercote3a42fb82004-08-03 18:08:50 +000068static void print_all_stats ( void )
nethercote71980f02004-01-24 18:18:54 +000069{
nethercote92e7b7f2004-08-07 17:52:25 +000070 VG_(print_tt_tc_stats)();
nethercote844e7122004-08-02 15:27:22 +000071 VG_(print_scheduler_stats)();
njn9271cbc2005-03-13 05:38:25 +000072 VG_(print_ExeContext_stats)();
73
nethercote3a42fb82004-08-03 18:08:50 +000074 // Memory stats
nethercote885dd912004-08-03 23:14:00 +000075 if (VG_(clo_verbosity) > 2) {
nethercote3a42fb82004-08-03 18:08:50 +000076 VG_(message)(Vg_DebugMsg, "");
77 VG_(message)(Vg_DebugMsg,
78 "------ Valgrind's internal memory use stats follow ------" );
nethercote885dd912004-08-03 23:14:00 +000079 VG_(sanity_check_malloc_all)();
njn11adeb22005-07-03 20:22:39 +000080 VG_(message)(Vg_DebugMsg, "------" );
nethercote3a42fb82004-08-03 18:08:50 +000081 VG_(print_all_arena_stats)();
nethercote885dd912004-08-03 23:14:00 +000082 VG_(message)(Vg_DebugMsg, "");
nethercote3a42fb82004-08-03 18:08:50 +000083 }
nethercote71980f02004-01-24 18:18:54 +000084}
85
86
87/*====================================================================*/
sewardj5f229e22005-09-28 01:36:01 +000088/*=== Setting up the client's environment ===*/
nethercote71980f02004-01-24 18:18:54 +000089/*====================================================================*/
90
nethercote71980f02004-01-24 18:18:54 +000091/* Prepare the client's environment. This is basically a copy of our
92 environment, except:
sewardj45f4e7c2005-09-27 19:20:21 +000093
94 LD_PRELOAD=$VALGRIND_LIB/vg_preload_core.so:
95 ($VALGRIND_LIB/vgpreload_TOOL.so:)?
96 $LD_PRELOAD
nethercote71980f02004-01-24 18:18:54 +000097
sewardjb5f6f512005-03-10 23:59:00 +000098 If this is missing, then it is added.
nethercote71980f02004-01-24 18:18:54 +000099
sewardj45f4e7c2005-09-27 19:20:21 +0000100 Also, remove any binding for VALGRIND_LAUNCHER=. The client should
101 not be able to see this.
nethercote71980f02004-01-24 18:18:54 +0000102
103 If this needs to handle any more variables it should be hacked
sewardj45f4e7c2005-09-27 19:20:21 +0000104 into something table driven. The copy is VG_(malloc)'d space.
105*/
106static HChar** setup_client_env ( HChar** origenv, const HChar* toolname)
nethercote71980f02004-01-24 18:18:54 +0000107{
sewardj45f4e7c2005-09-27 19:20:21 +0000108 HChar* preload_core_so = "vg_preload_core.so";
109 HChar* ld_preload = "LD_PRELOAD=";
110 HChar* v_launcher = VALGRIND_LAUNCHER "=";
111 Int ld_preload_len = VG_(strlen)( ld_preload );
112 Int v_launcher_len = VG_(strlen)( v_launcher );
113 Bool ld_preload_done = False;
114 Int vglib_len = VG_(strlen)(VG_(libdir));
nethercote71980f02004-01-24 18:18:54 +0000115
sewardj45f4e7c2005-09-27 19:20:21 +0000116 HChar** cpp;
117 HChar** ret;
118 HChar* preload_tool_path;;
119 Int envc, i;
nethercote71980f02004-01-24 18:18:54 +0000120
sewardj45f4e7c2005-09-27 19:20:21 +0000121 /* Alloc space for the vgpreload_core.so path and vgpreload_<tool>.so
122 paths. We might not need the space for vgpreload_<tool>.so, but it
123 doesn't hurt to over-allocate briefly. The 16s are just cautious
124 slop. */
125 Int preload_core_path_len = vglib_len + sizeof(preload_core_so) + 16;
126 Int preload_tool_path_len = vglib_len + VG_(strlen)(toolname) + 16;
127 Int preload_string_len = preload_core_path_len + preload_tool_path_len;
128 HChar* preload_string = VG_(malloc)(preload_string_len);
129 vg_assert(preload_string);
130
131 /* Determine if there's a vgpreload_<tool>.so file, and setup
132 preload_string. */
133 preload_tool_path = VG_(malloc)(preload_tool_path_len);
134 vg_assert(preload_tool_path);
135 VG_(snprintf)(preload_tool_path, preload_tool_path_len,
136 "%s/vgpreload_%s.so", VG_(libdir), toolname);
137 if (VG_(access)(preload_tool_path, True/*r*/, False/*w*/, False/*x*/) == 0) {
138 VG_(snprintf)(preload_string, preload_string_len, "%s/%s:%s",
139 VG_(libdir), preload_core_so, preload_tool_path);
140 } else {
141 VG_(snprintf)(preload_string, preload_string_len, "%s/%s",
142 VG_(libdir), preload_core_so);
143 }
144 VG_(free)(preload_tool_path);
145
146 VG_(debugLog)(1, "main", "preload_string = %s\n", preload_string);
147
nethercote71980f02004-01-24 18:18:54 +0000148 /* Count the original size of the env */
sewardj45f4e7c2005-09-27 19:20:21 +0000149 envc = 0;
nethercote71980f02004-01-24 18:18:54 +0000150 for (cpp = origenv; cpp && *cpp; cpp++)
151 envc++;
152
153 /* Allocate a new space */
sewardj45f4e7c2005-09-27 19:20:21 +0000154 ret = VG_(malloc) (sizeof(HChar *) * (envc+1+1)); /* 1 new entry + NULL */
nethercote7c018f42004-07-17 16:40:50 +0000155 vg_assert(ret);
nethercote71980f02004-01-24 18:18:54 +0000156
157 /* copy it over */
158 for (cpp = ret; *origenv; )
159 *cpp++ = *origenv++;
160 *cpp = NULL;
161
162 vg_assert(envc == (cpp - ret));
163
164 /* Walk over the new environment, mashing as we go */
165 for (cpp = ret; cpp && *cpp; cpp++) {
sewardj45f4e7c2005-09-27 19:20:21 +0000166 if (VG_(memcmp)(*cpp, ld_preload, ld_preload_len) == 0) {
167 Int len = VG_(strlen)(*cpp) + preload_string_len;
168 HChar *cp = VG_(malloc)(len);
nethercote7c018f42004-07-17 16:40:50 +0000169 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000170
sewardj45f4e7c2005-09-27 19:20:21 +0000171 VG_(snprintf)(cp, len, "%s%s:%s",
172 ld_preload, preload_string, (*cpp)+ld_preload_len);
nethercote71980f02004-01-24 18:18:54 +0000173
sewardj45f4e7c2005-09-27 19:20:21 +0000174 *cpp = cp;
175
176 ld_preload_done = True;
nethercote71980f02004-01-24 18:18:54 +0000177 }
178 }
179
180 /* Add the missing bits */
nethercote71980f02004-01-24 18:18:54 +0000181 if (!ld_preload_done) {
sewardj45f4e7c2005-09-27 19:20:21 +0000182 Int len = ld_preload_len + preload_string_len;
183 HChar *cp = VG_(malloc) (len);
nethercote7c018f42004-07-17 16:40:50 +0000184 vg_assert(cp);
sewardj45f4e7c2005-09-27 19:20:21 +0000185
186 VG_(snprintf)(cp, len, "%s%s", ld_preload, preload_string);
187
nethercote71980f02004-01-24 18:18:54 +0000188 ret[envc++] = cp;
189 }
190
sewardj45f4e7c2005-09-27 19:20:21 +0000191 /* ret[0 .. envc-1] is live now. */
192 /* Find and remove a binding for VALGRIND_LAUNCHER. */
193 for (i = 0; i < envc; i++)
194 if (0 == VG_(memcmp(ret[i], v_launcher, v_launcher_len)))
195 break;
196
197 if (i < envc) {
198 for (; i < envc-1; i++)
199 ret[i] = ret[i+1];
200 envc--;
201 }
202
203 VG_(free)(preload_string);
nethercote71980f02004-01-24 18:18:54 +0000204 ret[envc] = NULL;
205
206 return ret;
207}
208
nethercote71980f02004-01-24 18:18:54 +0000209
sewardj5f229e22005-09-28 01:36:01 +0000210/*====================================================================*/
211/*=== Setting up the client's stack ===*/
212/*====================================================================*/
213
214#ifndef AT_DCACHEBSIZE
215#define AT_DCACHEBSIZE 19
216#endif /* AT_DCACHEBSIZE */
217
218#ifndef AT_ICACHEBSIZE
219#define AT_ICACHEBSIZE 20
220#endif /* AT_ICACHEBSIZE */
221
222#ifndef AT_UCACHEBSIZE
223#define AT_UCACHEBSIZE 21
224#endif /* AT_UCACHEBSIZE */
225
226#ifndef AT_SYSINFO
227#define AT_SYSINFO 32
228#endif /* AT_SYSINFO */
229
230#ifndef AT_SYSINFO_EHDR
231#define AT_SYSINFO_EHDR 33
232#endif /* AT_SYSINFO_EHDR */
233
234#ifndef AT_SECURE
235#define AT_SECURE 23 /* secure mode boolean */
236#endif /* AT_SECURE */
237
nethercote71980f02004-01-24 18:18:54 +0000238/* Add a string onto the string table, and return its address */
239static char *copy_str(char **tab, const char *str)
240{
241 char *cp = *tab;
242 char *orig = cp;
243
244 while(*str)
245 *cp++ = *str++;
246 *cp++ = '\0';
247
248 if (0)
sewardj45f4e7c2005-09-27 19:20:21 +0000249 VG_(printf)("copied %p \"%s\" len %lld\n", orig, orig, (Long)(cp-orig));
nethercote71980f02004-01-24 18:18:54 +0000250
251 *tab = cp;
252
253 return orig;
254}
255
sewardj5f229e22005-09-28 01:36:01 +0000256
257/* ----------------------------------------------------------------
258
nethercote71980f02004-01-24 18:18:54 +0000259 This sets up the client's initial stack, containing the args,
260 environment and aux vector.
261
262 The format of the stack is:
263
sewardj45f4e7c2005-09-27 19:20:21 +0000264 higher address +-----------------+ <- clstack_end
nethercote71980f02004-01-24 18:18:54 +0000265 | |
266 : string table :
267 | |
268 +-----------------+
269 | AT_NULL |
270 - -
271 | auxv |
272 +-----------------+
sewardjfdf91b42005-09-28 00:53:09 +0000273 | NULL |
nethercote71980f02004-01-24 18:18:54 +0000274 - -
275 | envp |
276 +-----------------+
sewardjfdf91b42005-09-28 00:53:09 +0000277 | NULL |
nethercote71980f02004-01-24 18:18:54 +0000278 - -
279 | argv |
280 +-----------------+
281 | argc |
nethercote4ad74312004-10-26 09:59:49 +0000282 lower address +-----------------+ <- sp
nethercote71980f02004-01-24 18:18:54 +0000283 | undefined |
284 : :
sewardj45f4e7c2005-09-27 19:20:21 +0000285
sewardjfdf91b42005-09-28 00:53:09 +0000286 Allocate and create the initial client stack. It is allocated down
sewardj45f4e7c2005-09-27 19:20:21 +0000287 from clstack_end, which was previously determined by the address
sewardjfdf91b42005-09-28 00:53:09 +0000288 space manager. The returned value is the SP value for the client.
289
290 The client's auxv is created by copying and modifying our own one.
291 As a side effect of scanning our own auxv, some important bits of
292 info are collected:
293
294 VG_(cache_line_size_ppc32) // ppc32 only -- cache line size
295 VG_(have_altivec_ppc32) // ppc32 only -- is Altivec supported?
sewardj5f229e22005-09-28 01:36:01 +0000296
297 ---------------------------------------------------------------- */
sewardjfdf91b42005-09-28 00:53:09 +0000298
sewardj45f4e7c2005-09-27 19:20:21 +0000299static
300Addr setup_client_stack( void* init_sp,
301 char** orig_envp,
302 const struct exeinfo *info,
303 UInt** client_auxv,
304 Addr clstack_end,
305 SizeT clstack_max_size )
nethercote71980f02004-01-24 18:18:54 +0000306{
njn83407492005-06-19 16:10:47 +0000307 SysRes res;
nethercote71980f02004-01-24 18:18:54 +0000308 char **cpp;
309 char *strtab; /* string table */
310 char *stringbase;
nethercotea3c3cf22004-11-01 18:38:00 +0000311 Addr *ptr;
nethercote71980f02004-01-24 18:18:54 +0000312 struct ume_auxv *auxv;
313 const struct ume_auxv *orig_auxv;
314 const struct ume_auxv *cauxv;
315 unsigned stringsize; /* total size of strings in bytes */
316 unsigned auxsize; /* total size of auxv in bytes */
sewardj45f4e7c2005-09-27 19:20:21 +0000317 Int argc; /* total argc */
318 Int envc; /* total number of env vars */
nethercote71980f02004-01-24 18:18:54 +0000319 unsigned stacksize; /* total client stack size */
sewardj45f4e7c2005-09-27 19:20:21 +0000320 Addr client_SP; /* client stack base (initial SP) */
321 Addr clstack_start;
322 Int i;
323 Bool have_exename;
324
325 vg_assert(VG_IS_PAGE_ALIGNED(clstack_end+1));
nethercote71980f02004-01-24 18:18:54 +0000326
327 /* use our own auxv as a prototype */
njn62ff0f22005-06-21 23:03:36 +0000328 orig_auxv = VG_(find_auxv)(init_sp);
nethercote71980f02004-01-24 18:18:54 +0000329
330 /* ==================== compute sizes ==================== */
331
332 /* first of all, work out how big the client stack will be */
sewardj45f4e7c2005-09-27 19:20:21 +0000333 stringsize = 0;
334 have_exename = VG_(args_the_exename) != NULL;
nethercote71980f02004-01-24 18:18:54 +0000335
336 /* paste on the extra args if the loader needs them (ie, the #!
337 interpreter and its argument) */
338 argc = 0;
nethercoted6a56872004-07-26 15:32:47 +0000339 if (info->interp_name != NULL) {
nethercote71980f02004-01-24 18:18:54 +0000340 argc++;
sewardj45f4e7c2005-09-27 19:20:21 +0000341 stringsize += VG_(strlen)(info->interp_name) + 1;
nethercote71980f02004-01-24 18:18:54 +0000342 }
nethercoted6a56872004-07-26 15:32:47 +0000343 if (info->interp_args != NULL) {
nethercote71980f02004-01-24 18:18:54 +0000344 argc++;
sewardj45f4e7c2005-09-27 19:20:21 +0000345 stringsize += VG_(strlen)(info->interp_args) + 1;
nethercote71980f02004-01-24 18:18:54 +0000346 }
347
348 /* now scan the args we're given... */
sewardj45f4e7c2005-09-27 19:20:21 +0000349 if (have_exename)
350 stringsize += VG_(strlen)( VG_(args_the_exename) ) + 1;
351
352 for (i = 0; i < VG_(args_for_client).used; i++) {
nethercote71980f02004-01-24 18:18:54 +0000353 argc++;
sewardj45f4e7c2005-09-27 19:20:21 +0000354 stringsize += VG_(strlen)( VG_(args_for_client).strs[i] ) + 1;
nethercote71980f02004-01-24 18:18:54 +0000355 }
sewardj45f4e7c2005-09-27 19:20:21 +0000356
nethercote71980f02004-01-24 18:18:54 +0000357 /* ...and the environment */
358 envc = 0;
359 for (cpp = orig_envp; cpp && *cpp; cpp++) {
360 envc++;
sewardj45f4e7c2005-09-27 19:20:21 +0000361 stringsize += VG_(strlen)(*cpp) + 1;
nethercote71980f02004-01-24 18:18:54 +0000362 }
363
364 /* now, how big is the auxv? */
365 auxsize = sizeof(*auxv); /* there's always at least one entry: AT_NULL */
366 for (cauxv = orig_auxv; cauxv->a_type != AT_NULL; cauxv++) {
367 if (cauxv->a_type == AT_PLATFORM)
sewardj45f4e7c2005-09-27 19:20:21 +0000368 stringsize += VG_(strlen)(cauxv->u.a_ptr) + 1;
nethercote71980f02004-01-24 18:18:54 +0000369 auxsize += sizeof(*cauxv);
370 }
371
sewardjfdf91b42005-09-28 00:53:09 +0000372# if defined(VGP_ppc32_linux)
cerion85665ca2005-06-20 15:51:07 +0000373 auxsize += 2 * sizeof(*cauxv);
sewardjfdf91b42005-09-28 00:53:09 +0000374# endif
cerion85665ca2005-06-20 15:51:07 +0000375
nethercote71980f02004-01-24 18:18:54 +0000376 /* OK, now we know how big the client stack is */
377 stacksize =
sewardj45f4e7c2005-09-27 19:20:21 +0000378 sizeof(Word) + /* argc */
379 (have_exename ? sizeof(char **) : 0) + /* argc[0] == exename */
380 sizeof(char **)*argc + /* argv */
381 sizeof(char **) + /* terminal NULL */
382 sizeof(char **)*envc + /* envp */
383 sizeof(char **) + /* terminal NULL */
384 auxsize + /* auxv */
sewardj90d38542005-09-27 23:53:09 +0000385 VG_ROUNDUP(stringsize, sizeof(Word)); /* strings (aligned) */
nethercote71980f02004-01-24 18:18:54 +0000386
sewardj79048ce2005-02-18 08:28:32 +0000387 if (0) VG_(printf)("stacksize = %d\n", stacksize);
388
sewardj45f4e7c2005-09-27 19:20:21 +0000389 /* client_SP is the client's stack pointer */
390 client_SP = clstack_end - stacksize;
391 client_SP = VG_ROUNDDN(client_SP, 16); /* make stack 16 byte aligned */
nethercote71980f02004-01-24 18:18:54 +0000392
nethercote71980f02004-01-24 18:18:54 +0000393 /* base of the string table (aligned) */
sewardj45f4e7c2005-09-27 19:20:21 +0000394 stringbase = strtab = (char *)clstack_end
395 - VG_ROUNDUP(stringsize, sizeof(int));
nethercote71980f02004-01-24 18:18:54 +0000396
sewardj45f4e7c2005-09-27 19:20:21 +0000397 clstack_start = VG_PGROUNDDN(client_SP);
398
399 /* The max stack size */
400 clstack_max_size = VG_PGROUNDUP(clstack_max_size);
401
402 /* Record stack extent -- needed for stack-change code. */
403 VG_(clstk_base) = clstack_start;
404 VG_(clstk_end) = clstack_end;
nethercote71980f02004-01-24 18:18:54 +0000405
sewardj79048ce2005-02-18 08:28:32 +0000406 if (0)
sewardj45f4e7c2005-09-27 19:20:21 +0000407 VG_(printf)("stringsize=%d auxsize=%d stacksize=%d maxsize=0x%x\n"
408 "clstack_start %p\n"
409 "clstack_end %p\n",
410 stringsize, auxsize, stacksize, (Int)clstack_max_size,
411 (void*)clstack_start, (void*)clstack_end);
nethercote5ee67ca2004-06-22 14:00:09 +0000412
nethercote71980f02004-01-24 18:18:54 +0000413 /* ==================== allocate space ==================== */
414
sewardj45f4e7c2005-09-27 19:20:21 +0000415 { SizeT anon_size = clstack_end - clstack_start + 1;
416 SizeT resvn_size = clstack_max_size - anon_size;
417 Addr anon_start = clstack_start;
418 Addr resvn_start = anon_start - resvn_size;
419 SizeT inner_HACK = 0;
nethercote71980f02004-01-24 18:18:54 +0000420
sewardj45f4e7c2005-09-27 19:20:21 +0000421 vg_assert(VG_IS_PAGE_ALIGNED(anon_size));
422 vg_assert(VG_IS_PAGE_ALIGNED(resvn_size));
423 vg_assert(VG_IS_PAGE_ALIGNED(anon_start));
424 vg_assert(VG_IS_PAGE_ALIGNED(resvn_start));
425 vg_assert(resvn_start == clstack_end + 1 - clstack_max_size);
nethercote71980f02004-01-24 18:18:54 +0000426
sewardj45f4e7c2005-09-27 19:20:21 +0000427# ifdef ENABLE_INNER
428 inner_HACK = 1024*1024; // create 1M non-fault-extending stack
429# endif
nethercote71980f02004-01-24 18:18:54 +0000430
sewardj45f4e7c2005-09-27 19:20:21 +0000431 if (0)
432 VG_(printf)("%p 0x%x %p 0x%x\n",
433 resvn_start, resvn_size, anon_start, anon_size);
nethercote71980f02004-01-24 18:18:54 +0000434
sewardj45f4e7c2005-09-27 19:20:21 +0000435 /* Create a shrinkable reservation followed by an anonymous
436 segment. Together these constitute a growdown stack. */
437 Bool ok = VG_(am_create_reservation)(
438 resvn_start,
439 resvn_size -inner_HACK,
440 SmUpper,
441 anon_size +inner_HACK
442 );
443 vg_assert(ok);
444 /* allocate a stack - mmap enough space for the stack */
445 res = VG_(am_mmap_anon_fixed_client)(
446 anon_start -inner_HACK,
447 anon_size +inner_HACK,
448 VKI_PROT_READ|VKI_PROT_WRITE|VKI_PROT_EXEC
449 );
450 vg_assert(!res.isError);
451 }
452
453 /* ==================== create client stack ==================== */
454
455 ptr = (Addr*)client_SP;
456
457 /* --- client argc --- */
458 *ptr++ = argc + (have_exename ? 1 : 0);
459
460 /* --- client argv --- */
nethercoted6a56872004-07-26 15:32:47 +0000461 if (info->interp_name) {
nethercotea3c3cf22004-11-01 18:38:00 +0000462 *ptr++ = (Addr)copy_str(&strtab, info->interp_name);
sewardj45f4e7c2005-09-27 19:20:21 +0000463 VG_(free)(info->interp_name);
nethercote71980f02004-01-24 18:18:54 +0000464 }
nethercoted6a56872004-07-26 15:32:47 +0000465 if (info->interp_args) {
nethercotea3c3cf22004-11-01 18:38:00 +0000466 *ptr++ = (Addr)copy_str(&strtab, info->interp_args);
sewardj45f4e7c2005-09-27 19:20:21 +0000467 VG_(free)(info->interp_args);
nethercote71980f02004-01-24 18:18:54 +0000468 }
sewardj45f4e7c2005-09-27 19:20:21 +0000469
470 if (have_exename)
471 *ptr++ = (Addr)copy_str(&strtab, VG_(args_the_exename));
472
473 for (i = 0; i < VG_(args_for_client).used; i++) {
474 *ptr++ = (Addr)copy_str(&strtab, VG_(args_for_client).strs[i]);
nethercote71980f02004-01-24 18:18:54 +0000475 }
476 *ptr++ = 0;
477
478 /* --- envp --- */
479 VG_(client_envp) = (Char **)ptr;
480 for (cpp = orig_envp; cpp && *cpp; ptr++, cpp++)
nethercotea3c3cf22004-11-01 18:38:00 +0000481 *ptr = (Addr)copy_str(&strtab, *cpp);
nethercote71980f02004-01-24 18:18:54 +0000482 *ptr++ = 0;
483
484 /* --- auxv --- */
485 auxv = (struct ume_auxv *)ptr;
486 *client_auxv = (UInt *)auxv;
487
sewardjfdf91b42005-09-28 00:53:09 +0000488# if defined(VGP_ppc32_linux)
cerion85665ca2005-06-20 15:51:07 +0000489 auxv[0].a_type = AT_IGNOREPPC;
490 auxv[0].u.a_val = AT_IGNOREPPC;
491 auxv[1].a_type = AT_IGNOREPPC;
492 auxv[1].u.a_val = AT_IGNOREPPC;
493 auxv += 2;
sewardjfdf91b42005-09-28 00:53:09 +0000494# endif
cerion85665ca2005-06-20 15:51:07 +0000495
nethercote71980f02004-01-24 18:18:54 +0000496 for (; orig_auxv->a_type != AT_NULL; auxv++, orig_auxv++) {
sewardjfdf91b42005-09-28 00:53:09 +0000497
nethercote71980f02004-01-24 18:18:54 +0000498 /* copy the entry... */
499 *auxv = *orig_auxv;
500
sewardjfdf91b42005-09-28 00:53:09 +0000501 /* ...and fix up / examine the copy */
nethercote71980f02004-01-24 18:18:54 +0000502 switch(auxv->a_type) {
nethercote71980f02004-01-24 18:18:54 +0000503
sewardjfdf91b42005-09-28 00:53:09 +0000504 case AT_IGNORE:
505 case AT_PHENT:
506 case AT_PAGESZ:
507 case AT_FLAGS:
508 case AT_NOTELF:
509 case AT_UID:
510 case AT_EUID:
511 case AT_GID:
512 case AT_EGID:
513 case AT_CLKTCK:
514 case AT_FPUCW:
515 case AT_SYSINFO:
516 /* All these are pointerless, so we don't need to do
517 anything about them. */
518 break;
nethercote71980f02004-01-24 18:18:54 +0000519
sewardjfdf91b42005-09-28 00:53:09 +0000520 case AT_PHDR:
521 if (info->phdr == 0)
522 auxv->a_type = AT_IGNORE;
523 else
524 auxv->u.a_val = info->phdr;
525 break;
nethercote71980f02004-01-24 18:18:54 +0000526
sewardjfdf91b42005-09-28 00:53:09 +0000527 case AT_PHNUM:
528 if (info->phdr == 0)
529 auxv->a_type = AT_IGNORE;
530 else
531 auxv->u.a_val = info->phnum;
532 break;
nethercote71980f02004-01-24 18:18:54 +0000533
sewardjfdf91b42005-09-28 00:53:09 +0000534 case AT_BASE:
535 auxv->u.a_val = info->interp_base;
536 break;
nethercote71980f02004-01-24 18:18:54 +0000537
sewardjfdf91b42005-09-28 00:53:09 +0000538 case AT_PLATFORM:
539 /* points to a platform description string */
540 auxv->u.a_ptr = copy_str(&strtab, orig_auxv->u.a_ptr);
541 break;
nethercote71980f02004-01-24 18:18:54 +0000542
sewardjfdf91b42005-09-28 00:53:09 +0000543 case AT_ENTRY:
544 auxv->u.a_val = info->entry;
545 break;
nethercote71980f02004-01-24 18:18:54 +0000546
sewardjfdf91b42005-09-28 00:53:09 +0000547 case AT_HWCAP:
548# if defined(VGP_ppc32_linux)
549 /* Acquire altivecness info */
550 VG_(debugLog)(1, "main", "PPC32 hwcaps: 0x%x\n",
551 (UInt)auxv->u.a_val);
552 if (auxv->u.a_val & 0x10000000)
553 VG_(have_altivec_ppc32) = 1;
554 VG_(debugLog)(1, "main", "PPC32 AltiVec support: %u\n",
555 VG_(have_altivec_ppc32));
556# endif
557 break;
nethercote71980f02004-01-24 18:18:54 +0000558
sewardjfdf91b42005-09-28 00:53:09 +0000559 case AT_DCACHEBSIZE:
560 case AT_ICACHEBSIZE:
561 case AT_UCACHEBSIZE:
562# if defined(VGP_ppc32_linux)
563 /* acquire cache info */
564 if (auxv->u.a_val > 0) {
565 VG_(cache_line_size_ppc32) = auxv->u.a_val;
566 VG_(debugLog)(1, "main",
567 "PPC32 cache line size %u (type %u)\n",
568 (UInt)auxv->u.a_val, (UInt)auxv->a_type );
569 }
570# endif
571 break;
nethercote71980f02004-01-24 18:18:54 +0000572
sewardjfdf91b42005-09-28 00:53:09 +0000573# if defined(VGP_ppc32_linux)
574 case AT_IGNOREPPC:
575 break;
576# endif
577
578 case AT_SECURE:
579 /* If this is 1, then it means that this program is
580 running suid, and therefore the dynamic linker should
581 be careful about LD_PRELOAD, etc. However, since
582 stage1 (the thing the kernel actually execve's) should
583 never be SUID, and we need LD_PRELOAD to work for the
584 client, we set AT_SECURE to 0. */
585 auxv->u.a_val = 0;
586 break;
587
588# if !defined(VGP_ppc32_linux)
589 case AT_SYSINFO_EHDR:
590 /* Trash this, because we don't reproduce it */
591 auxv->a_type = AT_IGNORE;
592 break;
593# endif
594
595 default:
596 /* stomp out anything we don't know about */
597 VG_(debugLog)(2, "main",
598 "stomping auxv entry %lld\n",
599 (ULong)auxv->a_type);
600 auxv->a_type = AT_IGNORE;
601 break;
nethercote71980f02004-01-24 18:18:54 +0000602 }
603 }
604 *auxv = *orig_auxv;
605 vg_assert(auxv->a_type == AT_NULL);
606
607 vg_assert((strtab-stringbase) == stringsize);
608
sewardj45f4e7c2005-09-27 19:20:21 +0000609 /* client_SP is pointing at client's argc/argv */
nethercote5ee67ca2004-06-22 14:00:09 +0000610
sewardj45f4e7c2005-09-27 19:20:21 +0000611 if (0) VG_(printf)("startup SP = %p\n", client_SP);
612 return client_SP;
nethercote71980f02004-01-24 18:18:54 +0000613}
614
sewardj45f4e7c2005-09-27 19:20:21 +0000615
616/* Allocate the client data segment. It is an expandable anonymous
617 mapping abutting a shrinkable reservation of size max_dseg_size.
618 The data segment starts at VG_(brk_base), which is page-aligned,
619 and runs up to VG_(brk_limit), which isn't. */
620
621static void setup_client_dataseg ( SizeT max_size )
622{
623 Bool ok;
624 SysRes sres;
625 Addr anon_start = VG_(brk_base);
626 SizeT anon_size = VKI_PAGE_SIZE;
627 Addr resvn_start = anon_start + anon_size;
628 SizeT resvn_size = max_size - anon_size;
629
630 vg_assert(VG_IS_PAGE_ALIGNED(anon_size));
631 vg_assert(VG_IS_PAGE_ALIGNED(resvn_size));
632 vg_assert(VG_IS_PAGE_ALIGNED(anon_start));
633 vg_assert(VG_IS_PAGE_ALIGNED(resvn_start));
634
635 /* Because there's been no brk activity yet: */
636 vg_assert(VG_(brk_base) == VG_(brk_limit));
637
638 /* Try to create the data seg and associated reservation where
639 VG_(brk_base) says. */
640 ok = VG_(am_create_reservation)(
641 resvn_start,
642 resvn_size,
643 SmLower,
644 anon_size
645 );
646
647 if (!ok) {
648 /* Hmm, that didn't work. Well, let aspacem suggest an address
649 it likes better, and try again with that. */
650 anon_start = VG_(am_get_advisory_client_simple)
651 ( 0/*floating*/, anon_size+resvn_size, &ok );
652 if (ok) {
653 resvn_start = anon_start + anon_size;
654 ok = VG_(am_create_reservation)(
655 resvn_start,
656 resvn_size,
657 SmLower,
658 anon_size
659 );
660 if (ok)
661 VG_(brk_base) = VG_(brk_limit) = anon_start;
662 }
663 /* that too might have failed, but if it has, we're hosed: there
664 is no Plan C. */
665 }
666 vg_assert(ok);
667
668 sres = VG_(am_mmap_anon_fixed_client)(
669 anon_start,
670 anon_size,
671 VKI_PROT_READ|VKI_PROT_WRITE|VKI_PROT_EXEC
672 );
673 vg_assert(!sres.isError);
674 vg_assert(sres.val == anon_start);
675}
676
677
nethercote71980f02004-01-24 18:18:54 +0000678/*====================================================================*/
679/*=== Find executable ===*/
680/*====================================================================*/
681
sewardjfdf91b42005-09-28 00:53:09 +0000682/* Scan a colon-separated list, and call a function on each element.
683 The string must be mutable, because we insert a temporary '\0', but
684 the string will end up unmodified. (*func) should return True if it
685 doesn't need to see any more.
686
687 This routine will return True if (*func) returns True and False if
688 it reaches the end of the list without that happening.
689*/
690static Bool scan_colsep(char *colsep, Bool (*func)(const char *))
691{
692 char *cp, *entry;
693 int end;
694
695 if (colsep == NULL ||
696 *colsep == '\0')
697 return False;
698
699 entry = cp = colsep;
700
701 do {
702 end = (*cp == '\0');
703
704 if (*cp == ':' || *cp == '\0') {
705 char save = *cp;
706
707 *cp = '\0';
708 if ((*func)(entry)) {
709 *cp = save;
710 return True;
711 }
712 *cp = save;
713 entry = cp+1;
714 }
715 cp++;
716 } while(!end);
717
718 return False;
719}
720
sewardj45f4e7c2005-09-27 19:20:21 +0000721/* Need a static copy because can't use dynamic mem allocation yet */
722static HChar executable_name[VKI_PATH_MAX];
thughes4ad52d02004-06-27 17:37:21 +0000723
sewardj45f4e7c2005-09-27 19:20:21 +0000724static Bool match_executable(const char *entry)
725{
726 HChar buf[VG_(strlen)(entry) + VG_(strlen)(executable_name) + 3];
thughes4ad52d02004-06-27 17:37:21 +0000727
728 /* empty PATH element means . */
729 if (*entry == '\0')
730 entry = ".";
731
sewardj45f4e7c2005-09-27 19:20:21 +0000732 VG_(snprintf)(buf, sizeof(buf), "%s/%s", entry, executable_name);
733 if (VG_(access)(buf, True/*r*/, False/*w*/, True/*x*/) == 0) {
734 VG_(strncpy)( executable_name, buf, VKI_PATH_MAX-1 );
735 executable_name[VKI_PATH_MAX-1] = 0;
thughes4ad52d02004-06-27 17:37:21 +0000736 return True;
737 }
738 return False;
739}
740
sewardj45f4e7c2005-09-27 19:20:21 +0000741static HChar* find_executable ( HChar* exec )
nethercote71980f02004-01-24 18:18:54 +0000742{
743 vg_assert(NULL != exec);
sewardj45f4e7c2005-09-27 19:20:21 +0000744 VG_(strncpy)( executable_name, exec, VKI_PATH_MAX-1 );
745 executable_name[VKI_PATH_MAX-1] = 0;
746
747 if (VG_(strchr)(executable_name, '/') == NULL) {
nethercote71980f02004-01-24 18:18:54 +0000748 /* no '/' - we need to search the path */
sewardj45f4e7c2005-09-27 19:20:21 +0000749 HChar *path = VG_(getenv)("PATH");
thughes4ad52d02004-06-27 17:37:21 +0000750 scan_colsep(path, match_executable);
nethercote71980f02004-01-24 18:18:54 +0000751 }
thughes4ad52d02004-06-27 17:37:21 +0000752 return executable_name;
nethercote71980f02004-01-24 18:18:54 +0000753}
754
755
756/*====================================================================*/
nethercotef4928da2004-06-15 10:54:40 +0000757/*=== Command line errors ===*/
758/*====================================================================*/
759
njnbe9b47b2005-05-15 16:22:58 +0000760static void revert_to_stderr ( void )
nethercotef4928da2004-06-15 10:54:40 +0000761{
njnbe9b47b2005-05-15 16:22:58 +0000762 vg_assert( !VG_(logging_to_socket) );
nethercotef8548672004-06-21 12:42:35 +0000763 VG_(clo_log_fd) = 2; /* stderr */
nethercotef4928da2004-06-15 10:54:40 +0000764}
765
766void VG_(bad_option) ( Char* opt )
767{
njnbe9b47b2005-05-15 16:22:58 +0000768 revert_to_stderr();
njn02bc4b82005-05-15 17:28:26 +0000769 VG_(printf)("valgrind: Bad option '%s'; aborting.\n", opt);
nethercotef4928da2004-06-15 10:54:40 +0000770 VG_(printf)("valgrind: Use --help for more information.\n");
771 VG_(exit)(1);
772}
773
nethercotef4928da2004-06-15 10:54:40 +0000774static void missing_prog ( void )
775{
njnbe9b47b2005-05-15 16:22:58 +0000776 revert_to_stderr();
nethercotef4928da2004-06-15 10:54:40 +0000777 VG_(printf)("valgrind: no program specified\n");
778 VG_(printf)("valgrind: Use --help for more information.\n");
779 VG_(exit)(1);
780}
781
782static void config_error ( Char* msg )
783{
njnbe9b47b2005-05-15 16:22:58 +0000784 revert_to_stderr();
nethercotef4928da2004-06-15 10:54:40 +0000785 VG_(printf)("valgrind: Startup or configuration error:\n %s\n", msg);
786 VG_(printf)("valgrind: Unable to start up properly. Giving up.\n");
787 VG_(exit)(1);
788}
789
790
nethercote71980f02004-01-24 18:18:54 +0000791/*====================================================================*/
792/*=== Loading the client ===*/
793/*====================================================================*/
794
sewardj45f4e7c2005-09-27 19:20:21 +0000795/* Load the client whose name is VG_(argv_the_exename). */
nethercote71980f02004-01-24 18:18:54 +0000796
sewardj45f4e7c2005-09-27 19:20:21 +0000797static void load_client ( /*OUT*/struct exeinfo* info,
798 /*OUT*/Addr* client_eip)
799{
800 HChar* exec;
801 Int ret;
802 SysRes res;
803
804 vg_assert( VG_(args_the_exename) != NULL);
805 exec = find_executable( VG_(args_the_exename) );
806
807 VG_(memset)(info, 0, sizeof(*info));
nethercote71980f02004-01-24 18:18:54 +0000808 info->exe_base = VG_(client_base);
809 info->exe_end = VG_(client_end);
nethercote71980f02004-01-24 18:18:54 +0000810
sewardj45f4e7c2005-09-27 19:20:21 +0000811 ret = VG_(do_exec)(exec, info);
812 if (ret != 0) {
813 VG_(printf)("valgrind: do_exec(%s) failed: %s\n",
814 exec, VG_(strerror)(ret));
815 VG_(exit)(127);
nethercote71980f02004-01-24 18:18:54 +0000816 }
817
sewardj45f4e7c2005-09-27 19:20:21 +0000818 /* Get hold of a file descriptor which refers to the client
819 executable. This is needed for attaching to GDB. */
820 res = VG_(open)(exec, VKI_O_RDONLY, VKI_S_IRUSR);
821 if (!res.isError)
822 VG_(cl_exec_fd) = res.val;
823
nethercote71980f02004-01-24 18:18:54 +0000824 /* Copy necessary bits of 'info' that were filled in */
825 *client_eip = info->init_eip;
sewardj45f4e7c2005-09-27 19:20:21 +0000826 VG_(brk_base) = VG_(brk_limit) = VG_PGROUNDUP(info->brkbase);
nethercote71980f02004-01-24 18:18:54 +0000827}
828
nethercote969ecf12004-10-13 17:29:01 +0000829
sewardj71bc3cb2005-05-19 00:25:45 +0000830/*====================================================================*/
831/*=== Command-line: variables, processing, etc ===*/
832/*====================================================================*/
833
834// See pub_{core,tool}_options.h for explanations of all these.
835
sewardj45f4e7c2005-09-27 19:20:21 +0000836static void usage_NORETURN ( Bool debug_help )
njn7cf0bd32002-06-08 13:36:03 +0000837{
njn25e49d8e72002-09-23 09:36:25 +0000838 Char* usage1 =
nethercote71980f02004-01-24 18:18:54 +0000839"usage: valgrind --tool=<toolname> [options] prog-and-args\n"
njn25e49d8e72002-09-23 09:36:25 +0000840"\n"
nethercote2b0793f2003-12-02 10:41:18 +0000841" common user options for all Valgrind tools, with defaults in [ ]:\n"
sewardjb5f6f512005-03-10 23:59:00 +0000842" --tool=<name> use the Valgrind tool named <name> [memcheck]\n"
nethercotea76368b2004-06-16 11:56:29 +0000843" -h --help show this message\n"
nethercote6c999f22004-01-31 22:55:15 +0000844" --help-debug show this message, plus debugging options\n"
njn25e49d8e72002-09-23 09:36:25 +0000845" --version show version\n"
njn25e49d8e72002-09-23 09:36:25 +0000846" -q --quiet run silently; only print error msgs\n"
847" -v --verbose be more verbose, incl counts of errors\n"
nethercote77eba602003-11-13 17:35:04 +0000848" --trace-children=no|yes Valgrind-ise child processes? [no]\n"
nethercote0d588502004-06-21 13:27:11 +0000849" --track-fds=no|yes track open file descriptors? [no]\n"
thughes6233a382004-08-21 11:10:44 +0000850" --time-stamp=no|yes add timestamps to log messages? [no]\n"
njnce545552005-07-25 22:36:52 +0000851" --log-fd=<number> log messages to file descriptor [2=stderr]\n"
852" --log-file=<file> log messages to <file>.pid<pid>\n"
853" --log-file-exactly=<file> log messages to <file>\n"
854" --log-file-qualifier=<VAR> incorporate $VAR in logfile name [none]\n"
855" --log-socket=ipaddr:port log messages to socket ipaddr:port\n"
nethercote2b0793f2003-12-02 10:41:18 +0000856"\n"
857" uncommon user options for all Valgrind tools:\n"
nethercote0d588502004-06-21 13:27:11 +0000858" --run-libc-freeres=no|yes free up glibc memory at exit? [yes]\n"
sewardja0461a62005-09-28 01:14:32 +0000859" --weird-hacks=hack1,hack2,... known hacks: lax-ioctls\n"
sewardj45f4e7c2005-09-27 19:20:21 +0000860" enable-outer [none]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +0000861" --pointercheck=no|yes enforce client address space limits [yes]\n"
sewardjb1131a82005-03-19 15:12:21 +0000862" --show-emwarns=no|yes show warnings about emulation limits? [no]\n"
sewardj6c3a2192005-07-24 07:00:45 +0000863" --smc-check=none|stack|all checks for self-modifying code: none,\n"
864" only for code found in stacks, or all [stack]\n"
njn25e49d8e72002-09-23 09:36:25 +0000865"\n"
nethercote2b0793f2003-12-02 10:41:18 +0000866" user options for Valgrind tools that report errors:\n"
njnce545552005-07-25 22:36:52 +0000867" --xml=yes all output is in XML (Memcheck/Nulgrind only)\n"
njnc8ec9f82005-07-20 03:03:28 +0000868" --xml-user-comment=STR copy STR verbatim to XML output\n"
nethercote2b0793f2003-12-02 10:41:18 +0000869" --demangle=no|yes automatically demangle C++ names? [yes]\n"
njncc6cc142005-03-12 20:59:29 +0000870" --num-callers=<number> show <num> callers in stack traces [12]\n"
nethercote2b0793f2003-12-02 10:41:18 +0000871" --error-limit=no|yes stop showing new errors if too many? [yes]\n"
872" --show-below-main=no|yes continue stack traces below main() [no]\n"
873" --suppressions=<filename> suppress errors described in <filename>\n"
sewardjd153fae2005-01-10 17:24:47 +0000874" --gen-suppressions=no|yes|all print suppressions for errors? [no]\n"
nethercote04d0fbc2004-01-26 16:48:06 +0000875" --db-attach=no|yes start debugger when errors detected? [no]\n"
876" --db-command=<command> command to start debugger [gdb -nw %%f %%p]\n"
877" --input-fd=<number> file descriptor for input [0=stdin]\n"
sewardj97724e52005-04-02 23:40:59 +0000878" --max-stackframe=<number> assume stack switch for SP changes larger\n"
879" than <number> bytes [2000000]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +0000880"\n";
njn7cf0bd32002-06-08 13:36:03 +0000881
njn25e49d8e72002-09-23 09:36:25 +0000882 Char* usage2 =
883"\n"
nethercote2b0793f2003-12-02 10:41:18 +0000884" debugging options for all Valgrind tools:\n"
njn25e49d8e72002-09-23 09:36:25 +0000885" --sanity-level=<number> level of sanity checking to do [1]\n"
nethercote137bc552003-11-14 17:47:54 +0000886" --profile=no|yes profile? (tool must be built for it) [no]\n"
sewardjfa8ec112005-01-19 11:55:34 +0000887" --trace-flags=<XXXXXXXX> show generated code? (X = 0|1) [00000000]\n"
888" --profile-flags=<XXXXXXXX> ditto, but for profiling (X = 0|1) [00000000]\n"
sewardjc771b292004-11-30 18:55:21 +0000889" --trace-notbelow=<number> only show BBs above <number> [0]\n"
njn25e49d8e72002-09-23 09:36:25 +0000890" --trace-syscalls=no|yes show all system calls? [no]\n"
891" --trace-signals=no|yes show signal handling details? [no]\n"
892" --trace-symtab=no|yes show symbol table details? [no]\n"
sewardjce058b02005-05-01 08:55:38 +0000893" --trace-cfi=no|yes show call-frame-info details? [no]\n"
njn25e49d8e72002-09-23 09:36:25 +0000894" --trace-sched=no|yes show thread scheduler details? [no]\n"
jsgf855d93d2003-10-13 22:26:55 +0000895" --wait-for-gdb=yes|no pause on startup to wait for gdb attach\n"
sewardjb5f6f512005-03-10 23:59:00 +0000896#if 0
897" --model-pthreads=yes|no model the pthreads library [no]\n"
898#endif
899" --command-line-only=no|yes only use command line options [no]\n"
njn613812e2005-03-11 04:57:30 +0000900"\n"
901" --vex-iropt-verbosity 0 .. 9 [0]\n"
902" --vex-iropt-level 0 .. 2 [2]\n"
903" --vex-iropt-precise-memory-exns [no]\n"
sewardj8b635a42004-11-22 19:01:47 +0000904" --vex-iropt-unroll-thresh 0 .. 400 [120]\n"
905" --vex-guest-max-insns 1 .. 100 [50]\n"
906" --vex-guest-chase-thresh 0 .. 99 [10]\n"
907"\n"
sewardjfa8ec112005-01-19 11:55:34 +0000908" --trace-flags and --profile-flags values (omit the middle space):\n"
sewardj2a99cf62004-11-24 10:44:19 +0000909" 1000 0000 show conversion into IR\n"
910" 0100 0000 show after initial opt\n"
911" 0010 0000 show after instrumentation\n"
912" 0001 0000 show after second opt\n"
913" 0000 1000 show after tree building\n"
914" 0000 0100 show selecting insns\n"
915" 0000 0010 show after reg-alloc\n"
916" 0000 0001 show final assembly\n"
917"\n"
nethercote2b0793f2003-12-02 10:41:18 +0000918" debugging options for Valgrind tools that report errors\n"
919" --dump-error=<number> show translation for basic block associated\n"
920" with <number>'th error context [0=show none]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +0000921"\n";
njn3e884182003-04-15 13:03:23 +0000922
923 Char* usage3 =
924"\n"
nethercote71980f02004-01-24 18:18:54 +0000925" Extra options read from ~/.valgrindrc, $VALGRIND_OPTS, ./.valgrindrc\n"
njn25e49d8e72002-09-23 09:36:25 +0000926"\n"
njn53612422005-03-12 16:22:54 +0000927" Valgrind is Copyright (C) 2000-2005 Julian Seward et al.\n"
njn25e49d8e72002-09-23 09:36:25 +0000928" and licensed under the GNU General Public License, version 2.\n"
929" Bug reports, feedback, admiration, abuse, etc, to: %s.\n"
njnd04b7c62002-10-03 14:05:52 +0000930"\n"
nethercote137bc552003-11-14 17:47:54 +0000931" Tools are copyright and licensed by their authors. See each\n"
932" tool's start-up message for more information.\n"
njn25e49d8e72002-09-23 09:36:25 +0000933"\n";
njn7cf0bd32002-06-08 13:36:03 +0000934
njnbe9b47b2005-05-15 16:22:58 +0000935 // Ensure the message goes to stdout
936 VG_(clo_log_fd) = 1;
937 vg_assert( !VG_(logging_to_socket) );
938
fitzhardinge98abfc72003-12-16 02:05:15 +0000939 VG_(printf)(usage1);
940 if (VG_(details).name) {
941 VG_(printf)(" user options for %s:\n", VG_(details).name);
fitzhardinge98abfc72003-12-16 02:05:15 +0000942 if (VG_(needs).command_line_options)
njn51d827b2005-05-09 01:02:08 +0000943 VG_TDICT_CALL(tool_print_usage);
fitzhardinge98abfc72003-12-16 02:05:15 +0000944 else
945 VG_(printf)(" (none)\n");
946 }
nethercote6c999f22004-01-31 22:55:15 +0000947 if (debug_help) {
948 VG_(printf)(usage2);
fitzhardinge98abfc72003-12-16 02:05:15 +0000949
nethercote6c999f22004-01-31 22:55:15 +0000950 if (VG_(details).name) {
951 VG_(printf)(" debugging options for %s:\n", VG_(details).name);
952
953 if (VG_(needs).command_line_options)
njn51d827b2005-05-09 01:02:08 +0000954 VG_TDICT_CALL(tool_print_debug_usage);
nethercote6c999f22004-01-31 22:55:15 +0000955 else
956 VG_(printf)(" (none)\n");
957 }
fitzhardinge98abfc72003-12-16 02:05:15 +0000958 }
nethercote421281e2003-11-20 16:20:55 +0000959 VG_(printf)(usage3, VG_BUGS_TO);
nethercotef4928da2004-06-15 10:54:40 +0000960 VG_(exit)(0);
njn7cf0bd32002-06-08 13:36:03 +0000961}
sewardjde4a1d02002-03-22 01:27:54 +0000962
sewardjde4a1d02002-03-22 01:27:54 +0000963
sewardj45f4e7c2005-09-27 19:20:21 +0000964/* Peer at previously set up VG_(args_for_valgrind) and extract any
965 request for help and also the tool name. */
966
967static void get_helprequest_and_toolname ( Int* need_help, HChar** tool )
968{
969 UInt i;
970 HChar* str;
sewardj8b635a42004-11-22 19:01:47 +0000971
nethercote71980f02004-01-24 18:18:54 +0000972 /* parse the options we have (only the options we care about now) */
sewardj45f4e7c2005-09-27 19:20:21 +0000973 for (i = 0; i < VG_(args_for_valgrind).used; i++) {
nethercote71980f02004-01-24 18:18:54 +0000974
sewardj45f4e7c2005-09-27 19:20:21 +0000975 str = VG_(args_for_valgrind).strs[i];
976 vg_assert(str);
nethercote71980f02004-01-24 18:18:54 +0000977
sewardj45f4e7c2005-09-27 19:20:21 +0000978 if (VG_STREQ(str, "--version")) {
979 VG_(printf)("valgrind-" VERSION "\n");
980 VG_(exit)(0);
981
982 } else if (VG_CLO_STREQ(str, "--help") ||
983 VG_CLO_STREQ(str, "-h")) {
nethercote6c999f22004-01-31 22:55:15 +0000984 *need_help = 1;
985
sewardj45f4e7c2005-09-27 19:20:21 +0000986 } else if (VG_CLO_STREQ(str, "--help-debug")) {
nethercote6c999f22004-01-31 22:55:15 +0000987 *need_help = 2;
nethercote71980f02004-01-24 18:18:54 +0000988
sewardj45f4e7c2005-09-27 19:20:21 +0000989 // The tool has already been determined, but we need to know the name
990 // here.
991 } else if (VG_CLO_STREQN(7, str, "--tool=")) {
992 *tool = &str[7];
nethercote71980f02004-01-24 18:18:54 +0000993 }
994 }
nethercote71980f02004-01-24 18:18:54 +0000995}
996
sewardj45f4e7c2005-09-27 19:20:21 +0000997static Bool process_cmd_line_options( UInt* client_auxv, const char* toolname )
nethercote71980f02004-01-24 18:18:54 +0000998{
sewardj92645592005-07-23 09:18:34 +0000999 SysRes sres;
1000 Int i, eventually_log_fd;
1001 Int toolname_len = VG_(strlen)(toolname);
njnbe9b47b2005-05-15 16:22:58 +00001002 enum {
1003 VgLogTo_Fd,
1004 VgLogTo_File,
1005 VgLogTo_FileExactly,
1006 VgLogTo_Socket
1007 } log_to = VgLogTo_Fd; // Where is logging output to be sent?
sewardjde4a1d02002-03-22 01:27:54 +00001008
nethercotee1730692003-11-20 10:38:07 +00001009 /* log to stderr by default, but usage message goes to stdout */
nethercotef8548672004-06-21 12:42:35 +00001010 eventually_log_fd = 2;
sewardjde4a1d02002-03-22 01:27:54 +00001011
sewardj19d81412002-06-03 01:10:40 +00001012 /* Check for sane path in ./configure --prefix=... */
fitzhardinge98abfc72003-12-16 02:05:15 +00001013 if (VG_LIBDIR[0] != '/')
sewardj19d81412002-06-03 01:10:40 +00001014 config_error("Please use absolute paths in "
1015 "./configure --prefix=... or --libdir=...");
sewardj38170912002-05-10 21:07:22 +00001016
sewardj45f4e7c2005-09-27 19:20:21 +00001017 for (i = 0; i < VG_(args_for_valgrind).used; i++) {
nethercote71980f02004-01-24 18:18:54 +00001018
sewardj45f4e7c2005-09-27 19:20:21 +00001019 HChar* arg = VG_(args_for_valgrind).strs[i];
1020 HChar* colon = arg;
nethercote71980f02004-01-24 18:18:54 +00001021
thughes3bfd5a02004-07-18 08:05:44 +00001022 /* Look for a colon in the switch name */
1023 while (*colon && *colon != ':' && *colon != '=')
1024 colon++;
nethercote71980f02004-01-24 18:18:54 +00001025
1026 /* Look for matching "--toolname:foo" */
thughes3bfd5a02004-07-18 08:05:44 +00001027 if (*colon == ':') {
nethercote71980f02004-01-24 18:18:54 +00001028 if (VG_CLO_STREQN(2, arg, "--") &&
1029 VG_CLO_STREQN(toolname_len, arg+2, toolname) &&
1030 VG_CLO_STREQN(1, arg+2+toolname_len, ":"))
1031 {
1032 // prefix matches, convert "--toolname:foo" to "--foo"
1033 if (0)
1034 VG_(printf)("tool-specific arg: %s\n", arg);
sewardj45f4e7c2005-09-27 19:20:21 +00001035 arg = VG_(strdup)(arg + toolname_len + 1);
nethercote71980f02004-01-24 18:18:54 +00001036 arg[0] = '-';
1037 arg[1] = '-';
1038
1039 } else {
1040 // prefix doesn't match, skip to next arg
1041 continue;
1042 }
1043 }
1044
fitzhardinge98abfc72003-12-16 02:05:15 +00001045 /* Ignore these options - they've already been handled */
njn45270a22005-03-27 01:00:11 +00001046 if (VG_CLO_STREQN( 7, arg, "--tool=")) goto skip_arg;
njn45270a22005-03-27 01:00:11 +00001047 if (VG_CLO_STREQN(20, arg, "--command-line-only=")) goto skip_arg;
fitzhardinge98abfc72003-12-16 02:05:15 +00001048
njn45270a22005-03-27 01:00:11 +00001049 if ( VG_CLO_STREQ(arg, "--")) goto skip_arg;
nethercote27fec902004-06-16 21:26:32 +00001050
nethercote71980f02004-01-24 18:18:54 +00001051 else if (VG_CLO_STREQ(arg, "-v") ||
1052 VG_CLO_STREQ(arg, "--verbose"))
sewardjde4a1d02002-03-22 01:27:54 +00001053 VG_(clo_verbosity)++;
nethercote27fec902004-06-16 21:26:32 +00001054
nethercote71980f02004-01-24 18:18:54 +00001055 else if (VG_CLO_STREQ(arg, "-q") ||
1056 VG_CLO_STREQ(arg, "--quiet"))
sewardjde4a1d02002-03-22 01:27:54 +00001057 VG_(clo_verbosity)--;
1058
sewardj1cf558c2005-04-25 01:36:56 +00001059 else if (VG_CLO_STREQ(arg, "-d")) {
1060 /* do nothing */
1061 }
1062
sewardj71bc3cb2005-05-19 00:25:45 +00001063 else VG_BOOL_CLO(arg, "--xml", VG_(clo_xml))
njn45270a22005-03-27 01:00:11 +00001064 else VG_BOOL_CLO(arg, "--db-attach", VG_(clo_db_attach))
1065 else VG_BOOL_CLO(arg, "--demangle", VG_(clo_demangle))
1066 else VG_BOOL_CLO(arg, "--error-limit", VG_(clo_error_limit))
1067 else VG_BOOL_CLO(arg, "--pointercheck", VG_(clo_pointercheck))
njn45270a22005-03-27 01:00:11 +00001068 else VG_BOOL_CLO(arg, "--show-emwarns", VG_(clo_show_emwarns))
sewardj97724e52005-04-02 23:40:59 +00001069 else VG_NUM_CLO (arg, "--max-stackframe", VG_(clo_max_stackframe))
njn45270a22005-03-27 01:00:11 +00001070 else VG_BOOL_CLO(arg, "--profile", VG_(clo_profile))
1071 else VG_BOOL_CLO(arg, "--run-libc-freeres", VG_(clo_run_libc_freeres))
1072 else VG_BOOL_CLO(arg, "--show-below-main", VG_(clo_show_below_main))
1073 else VG_BOOL_CLO(arg, "--time-stamp", VG_(clo_time_stamp))
1074 else VG_BOOL_CLO(arg, "--track-fds", VG_(clo_track_fds))
1075 else VG_BOOL_CLO(arg, "--trace-children", VG_(clo_trace_children))
1076 else VG_BOOL_CLO(arg, "--trace-sched", VG_(clo_trace_sched))
1077 else VG_BOOL_CLO(arg, "--trace-signals", VG_(clo_trace_signals))
1078 else VG_BOOL_CLO(arg, "--trace-symtab", VG_(clo_trace_symtab))
sewardjce058b02005-05-01 08:55:38 +00001079 else VG_BOOL_CLO(arg, "--trace-cfi", VG_(clo_trace_cfi))
njn45270a22005-03-27 01:00:11 +00001080 else VG_BOOL_CLO(arg, "--trace-redir", VG_(clo_trace_redir))
1081 else VG_BOOL_CLO(arg, "--trace-syscalls", VG_(clo_trace_syscalls))
1082 else VG_BOOL_CLO(arg, "--trace-pthreads", VG_(clo_trace_pthreads))
1083 else VG_BOOL_CLO(arg, "--wait-for-gdb", VG_(clo_wait_for_gdb))
1084 else VG_BOOL_CLO(arg, "--model-pthreads", VG_(clo_model_pthreads))
sewardj72f98ff2002-06-13 17:23:38 +00001085
njn45270a22005-03-27 01:00:11 +00001086 else VG_STR_CLO (arg, "--db-command", VG_(clo_db_command))
1087 else VG_STR_CLO (arg, "--weird-hacks", VG_(clo_weird_hacks))
sewardjde4a1d02002-03-22 01:27:54 +00001088
njn45270a22005-03-27 01:00:11 +00001089 else VG_NUM_CLO (arg, "--dump-error", VG_(clo_dump_error))
1090 else VG_NUM_CLO (arg, "--input-fd", VG_(clo_input_fd))
1091 else VG_NUM_CLO (arg, "--sanity-level", VG_(clo_sanity_level))
1092 else VG_BNUM_CLO(arg, "--num-callers", VG_(clo_backtrace_size), 1,
1093 VG_DEEPEST_BACKTRACE)
sewardjde4a1d02002-03-22 01:27:54 +00001094
sewardj6c3a2192005-07-24 07:00:45 +00001095 else if (VG_CLO_STREQ(arg, "--smc-check=none"))
1096 VG_(clo_smc_check) = Vg_SmcNone;
1097 else if (VG_CLO_STREQ(arg, "--smc-check=stack"))
1098 VG_(clo_smc_check) = Vg_SmcStack;
1099 else if (VG_CLO_STREQ(arg, "--smc-check=all"))
1100 VG_(clo_smc_check) = Vg_SmcAll;
sewardj26412bd2005-07-07 10:05:05 +00001101
njn45270a22005-03-27 01:00:11 +00001102 else VG_BNUM_CLO(arg, "--vex-iropt-verbosity",
sewardj8b635a42004-11-22 19:01:47 +00001103 VG_(clo_vex_control).iropt_verbosity, 0, 10)
njn45270a22005-03-27 01:00:11 +00001104 else VG_BNUM_CLO(arg, "--vex-iropt-level",
sewardj8b635a42004-11-22 19:01:47 +00001105 VG_(clo_vex_control).iropt_level, 0, 2)
njn45270a22005-03-27 01:00:11 +00001106 else VG_BOOL_CLO(arg, "--vex-iropt-precise-memory-exns",
sewardj8b635a42004-11-22 19:01:47 +00001107 VG_(clo_vex_control).iropt_precise_memory_exns)
njn45270a22005-03-27 01:00:11 +00001108 else VG_BNUM_CLO(arg, "--vex-iropt-unroll-thresh",
sewardj8b635a42004-11-22 19:01:47 +00001109 VG_(clo_vex_control).iropt_unroll_thresh, 0, 400)
njn45270a22005-03-27 01:00:11 +00001110 else VG_BNUM_CLO(arg, "--vex-guest-max-insns",
sewardj8b635a42004-11-22 19:01:47 +00001111 VG_(clo_vex_control).guest_max_insns, 1, 100)
njn45270a22005-03-27 01:00:11 +00001112 else VG_BNUM_CLO(arg, "--vex-guest-chase-thresh",
sewardj8b635a42004-11-22 19:01:47 +00001113 VG_(clo_vex_control).guest_chase_thresh, 0, 99)
1114
nethercotef8548672004-06-21 12:42:35 +00001115 else if (VG_CLO_STREQN(9, arg, "--log-fd=")) {
njnbe9b47b2005-05-15 16:22:58 +00001116 log_to = VgLogTo_Fd;
nethercotef8548672004-06-21 12:42:35 +00001117 VG_(clo_log_name) = NULL;
1118 eventually_log_fd = (Int)VG_(atoll)(&arg[9]);
sewardj4cf05692002-10-27 20:28:29 +00001119 }
1120
nethercotef8548672004-06-21 12:42:35 +00001121 else if (VG_CLO_STREQN(11, arg, "--log-file=")) {
njnbe9b47b2005-05-15 16:22:58 +00001122 log_to = VgLogTo_File;
nethercotef8548672004-06-21 12:42:35 +00001123 VG_(clo_log_name) = &arg[11];
sewardj4cf05692002-10-27 20:28:29 +00001124 }
njnd6bc3c32005-03-27 00:44:31 +00001125
sewardjad311162005-07-19 11:25:02 +00001126 else if (VG_CLO_STREQN(11, arg, "--log-file=")) {
1127 log_to = VgLogTo_File;
1128 VG_(clo_log_name) = &arg[11];
1129 }
1130
1131 else if (VG_CLO_STREQN(21, arg, "--log-file-qualifier=")) {
1132 VG_(clo_log_file_qualifier) = &arg[21];
1133 }
1134
sewardj603d4102005-01-11 14:01:02 +00001135 else if (VG_CLO_STREQN(19, arg, "--log-file-exactly=")) {
njnbe9b47b2005-05-15 16:22:58 +00001136 log_to = VgLogTo_FileExactly;
sewardj603d4102005-01-11 14:01:02 +00001137 VG_(clo_log_name) = &arg[19];
1138 }
sewardjde4a1d02002-03-22 01:27:54 +00001139
nethercotef8548672004-06-21 12:42:35 +00001140 else if (VG_CLO_STREQN(13, arg, "--log-socket=")) {
njnbe9b47b2005-05-15 16:22:58 +00001141 log_to = VgLogTo_Socket;
nethercotef8548672004-06-21 12:42:35 +00001142 VG_(clo_log_name) = &arg[13];
sewardj73cf3bc2002-11-03 03:20:15 +00001143 }
1144
sewardj768db0e2005-07-19 14:18:56 +00001145 else if (VG_CLO_STREQN(19, arg, "--xml-user-comment=")) {
1146 VG_(clo_xml_user_comment) = &arg[19];
1147 }
1148
nethercote71980f02004-01-24 18:18:54 +00001149 else if (VG_CLO_STREQN(15, arg, "--suppressions=")) {
sewardjde4a1d02002-03-22 01:27:54 +00001150 if (VG_(clo_n_suppressions) >= VG_CLO_MAX_SFILES) {
njn25e49d8e72002-09-23 09:36:25 +00001151 VG_(message)(Vg_UserMsg, "Too many suppression files specified.");
sewardjde4a1d02002-03-22 01:27:54 +00001152 VG_(message)(Vg_UserMsg,
1153 "Increase VG_CLO_MAX_SFILES and recompile.");
nethercote71980f02004-01-24 18:18:54 +00001154 VG_(bad_option)(arg);
sewardjde4a1d02002-03-22 01:27:54 +00001155 }
nethercote71980f02004-01-24 18:18:54 +00001156 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = &arg[15];
sewardjde4a1d02002-03-22 01:27:54 +00001157 VG_(clo_n_suppressions)++;
1158 }
sewardjde4a1d02002-03-22 01:27:54 +00001159
sewardjfa8ec112005-01-19 11:55:34 +00001160 /* "stuvwxyz" --> stuvwxyz (binary) */
1161 else if (VG_CLO_STREQN(14, arg, "--trace-flags=")) {
1162 Int j;
1163 char* opt = & arg[14];
1164
1165 if (8 != VG_(strlen)(opt)) {
1166 VG_(message)(Vg_UserMsg,
1167 "--trace-flags argument must have 8 digits");
1168 VG_(bad_option)(arg);
1169 }
1170 for (j = 0; j < 8; j++) {
1171 if ('0' == opt[j]) { /* do nothing */ }
1172 else if ('1' == opt[j]) VG_(clo_trace_flags) |= (1 << (7-j));
1173 else {
1174 VG_(message)(Vg_UserMsg, "--trace-flags argument can only "
1175 "contain 0s and 1s");
1176 VG_(bad_option)(arg);
1177 }
1178 }
1179 }
1180
1181 /* "stuvwxyz" --> stuvwxyz (binary) */
1182 else if (VG_CLO_STREQN(16, arg, "--profile-flags=")) {
njn25e49d8e72002-09-23 09:36:25 +00001183 Int j;
nethercote71980f02004-01-24 18:18:54 +00001184 char* opt = & arg[16];
njn25e49d8e72002-09-23 09:36:25 +00001185
sewardj2a99cf62004-11-24 10:44:19 +00001186 if (8 != VG_(strlen)(opt)) {
njn25e49d8e72002-09-23 09:36:25 +00001187 VG_(message)(Vg_UserMsg,
sewardjfa8ec112005-01-19 11:55:34 +00001188 "--profile-flags argument must have 8 digits");
nethercote71980f02004-01-24 18:18:54 +00001189 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001190 }
sewardj8b635a42004-11-22 19:01:47 +00001191 for (j = 0; j < 8; j++) {
njn25e49d8e72002-09-23 09:36:25 +00001192 if ('0' == opt[j]) { /* do nothing */ }
sewardjfa8ec112005-01-19 11:55:34 +00001193 else if ('1' == opt[j]) VG_(clo_profile_flags) |= (1 << (7-j));
njn25e49d8e72002-09-23 09:36:25 +00001194 else {
sewardjfa8ec112005-01-19 11:55:34 +00001195 VG_(message)(Vg_UserMsg, "--profile-flags argument can only "
njn25e49d8e72002-09-23 09:36:25 +00001196 "contain 0s and 1s");
nethercote71980f02004-01-24 18:18:54 +00001197 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001198 }
1199 }
1200 }
sewardjde4a1d02002-03-22 01:27:54 +00001201
njn45270a22005-03-27 01:00:11 +00001202 else VG_NUM_CLO (arg, "--trace-notbelow", VG_(clo_trace_notbelow))
sewardjc771b292004-11-30 18:55:21 +00001203
sewardjd153fae2005-01-10 17:24:47 +00001204 else if (VG_CLO_STREQ(arg, "--gen-suppressions=no"))
1205 VG_(clo_gen_suppressions) = 0;
1206 else if (VG_CLO_STREQ(arg, "--gen-suppressions=yes"))
1207 VG_(clo_gen_suppressions) = 1;
1208 else if (VG_CLO_STREQ(arg, "--gen-suppressions=all"))
1209 VG_(clo_gen_suppressions) = 2;
1210
nethercote71980f02004-01-24 18:18:54 +00001211 else if ( ! VG_(needs).command_line_options
njn51d827b2005-05-09 01:02:08 +00001212 || ! VG_TDICT_CALL(tool_process_cmd_line_option, arg) ) {
nethercotef4928da2004-06-15 10:54:40 +00001213 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001214 }
njn8c0b3bb2005-03-12 21:20:39 +00001215 skip_arg:
sewardj45f4e7c2005-09-27 19:20:21 +00001216 if (arg != VG_(args_for_valgrind).strs[i]) {
1217 VG_(free)(arg);
1218 }
sewardjde4a1d02002-03-22 01:27:54 +00001219 }
1220
sewardj998d40d2004-12-06 14:24:52 +00001221 /* Make VEX control parameters sane */
1222
1223 if (VG_(clo_vex_control).guest_chase_thresh
1224 >= VG_(clo_vex_control).guest_max_insns)
1225 VG_(clo_vex_control).guest_chase_thresh
1226 = VG_(clo_vex_control).guest_max_insns - 1;
1227
1228 if (VG_(clo_vex_control).guest_chase_thresh < 0)
1229 VG_(clo_vex_control).guest_chase_thresh = 0;
1230
1231 /* Check various option values */
nethercote27fec902004-06-16 21:26:32 +00001232
njnf9ebf672003-05-12 21:41:30 +00001233 if (VG_(clo_verbosity) < 0)
sewardjde4a1d02002-03-22 01:27:54 +00001234 VG_(clo_verbosity) = 0;
1235
nethercote04d0fbc2004-01-26 16:48:06 +00001236 if (VG_(clo_db_attach) && VG_(clo_trace_children)) {
sewardjde4a1d02002-03-22 01:27:54 +00001237 VG_(message)(Vg_UserMsg, "");
1238 VG_(message)(Vg_UserMsg,
nethercote04d0fbc2004-01-26 16:48:06 +00001239 "--db-attach=yes conflicts with --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001240 VG_(message)(Vg_UserMsg,
1241 "Please choose one or the other, but not both.");
nethercote04d0fbc2004-01-26 16:48:06 +00001242 VG_(bad_option)("--db-attach=yes and --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001243 }
1244
njnbe9b47b2005-05-15 16:22:58 +00001245 if (VG_(clo_gen_suppressions) > 0 &&
1246 !VG_(needs).core_errors && !VG_(needs).tool_errors) {
1247 VG_(message)(Vg_UserMsg,
1248 "Can't use --gen-suppressions= with this tool,");
1249 VG_(message)(Vg_UserMsg,
1250 "as it doesn't generate errors.");
1251 VG_(bad_option)("--gen-suppressions=");
1252 }
1253
sewardj71bc3cb2005-05-19 00:25:45 +00001254 /* If we've been asked to emit XML, mash around various other
1255 options so as to constrain the output somewhat, and to remove
1256 any need for user input during the run. */
1257 if (VG_(clo_xml)) {
1258 /* Disable suppression generation (requires user input) */
1259 VG_(clo_gen_suppressions) = 0;
1260 /* Disable attaching to GDB (requires user input) */
1261 VG_(clo_db_attach) = False;
1262 /* Set a known verbosity level */
1263 VG_(clo_verbosity) = 1;
1264 /* Disable error limits (this might be a bad idea!) */
1265 VG_(clo_error_limit) = False;
1266 /* Disable emulation warnings */
1267 VG_(clo_show_emwarns) = False;
1268 /* Disable waiting for GDB to debug Valgrind */
1269 VG_(clo_wait_for_gdb) = False;
1270 /* No file-descriptor leak checking yet */
1271 VG_(clo_track_fds) = False;
sewardj21f7f0c2005-07-06 19:46:48 +00001272 /* Disable timestamped output */
1273 VG_(clo_time_stamp) = False;
sewardj71bc3cb2005-05-19 00:25:45 +00001274 /* Also, we want to set options for the leak checker, but that
1275 will have to be done in Memcheck's flag-handling code, not
1276 here. */
1277 }
1278
njnbe9b47b2005-05-15 16:22:58 +00001279 /* All non-logging-related options have been checked. If the logging
1280 option specified is ok, we can switch to it, as we know we won't
1281 have to generate any other command-line-related error messages.
1282 (So far we should be still attached to stderr, so we can show on
1283 the terminal any problems to do with processing command line
1284 opts.)
1285
1286 So set up logging now. After this is done, VG_(clo_log_fd)
sewardj4cf05692002-10-27 20:28:29 +00001287 should be connected to whatever sink has been selected, and we
1288 indiscriminately chuck stuff into it without worrying what the
1289 nature of it is. Oh the wonder of Unix streams. */
1290
njnbe9b47b2005-05-15 16:22:58 +00001291 vg_assert(VG_(clo_log_fd) == 2 /* stderr */);
1292 vg_assert(VG_(logging_to_socket) == False);
sewardj4cf05692002-10-27 20:28:29 +00001293
njnbe9b47b2005-05-15 16:22:58 +00001294 switch (log_to) {
sewardj73cf3bc2002-11-03 03:20:15 +00001295
sewardj4cf05692002-10-27 20:28:29 +00001296 case VgLogTo_Fd:
nethercotef8548672004-06-21 12:42:35 +00001297 vg_assert(VG_(clo_log_name) == NULL);
1298 VG_(clo_log_fd) = eventually_log_fd;
sewardj4cf05692002-10-27 20:28:29 +00001299 break;
sewardj73cf3bc2002-11-03 03:20:15 +00001300
sewardj4cf05692002-10-27 20:28:29 +00001301 case VgLogTo_File: {
sewardjad311162005-07-19 11:25:02 +00001302 HChar logfilename[1000];
1303 Int seq = 0;
1304 Int pid = VG_(getpid)();
1305 HChar* qual = NULL;
jsgff3c3f1a2003-10-14 22:13:28 +00001306
nethercotef8548672004-06-21 12:42:35 +00001307 vg_assert(VG_(clo_log_name) != NULL);
1308 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
jsgff3c3f1a2003-10-14 22:13:28 +00001309
sewardjad311162005-07-19 11:25:02 +00001310 if (VG_(clo_log_file_qualifier)) {
1311 qual = VG_(getenv)(VG_(clo_log_file_qualifier));
1312 }
1313
nethercote71980f02004-01-24 18:18:54 +00001314 for (;;) {
sewardj92645592005-07-23 09:18:34 +00001315 HChar pidtxt[20], seqtxt[20];
1316
1317 VG_(sprintf)(pidtxt, "%d", pid);
1318
1319 if (seq == 0)
1320 seqtxt[0] = 0;
1321 else
1322 VG_(sprintf)(seqtxt, ".%d", seq);
1323
jsgff3c3f1a2003-10-14 22:13:28 +00001324 seq++;
1325
sewardj92645592005-07-23 09:18:34 +00001326 /* Result:
1327 if (qual) base_name ++ "." ++ qual ++ seqtxt
1328 if (not qual) base_name ++ "." ++ pid ++ seqtxt
1329 */
1330 VG_(sprintf)( logfilename,
1331 "%s.%s%s",
1332 VG_(clo_log_name),
1333 qual ? qual : pidtxt,
1334 seqtxt );
1335
njnbe9b47b2005-05-15 16:22:58 +00001336 // EXCL: it will fail with EEXIST if the file already exists.
sewardj92645592005-07-23 09:18:34 +00001337 sres
jsgff3c3f1a2003-10-14 22:13:28 +00001338 = VG_(open)(logfilename,
1339 VKI_O_CREAT|VKI_O_WRONLY|VKI_O_EXCL|VKI_O_TRUNC,
1340 VKI_S_IRUSR|VKI_S_IWUSR);
sewardj92645592005-07-23 09:18:34 +00001341 if (!sres.isError) {
1342 eventually_log_fd = sres.val;
nethercotef8548672004-06-21 12:42:35 +00001343 VG_(clo_log_fd) = VG_(safe_fd)(eventually_log_fd);
sewardj603d4102005-01-11 14:01:02 +00001344 break; /* for (;;) */
jsgff3c3f1a2003-10-14 22:13:28 +00001345 } else {
njnbe9b47b2005-05-15 16:22:58 +00001346 // If the file already existed, we try the next name. If it
1347 // was some other file error, we give up.
sewardj92645592005-07-23 09:18:34 +00001348 if (sres.val != VKI_EEXIST) {
jsgff3c3f1a2003-10-14 22:13:28 +00001349 VG_(message)(Vg_UserMsg,
njn02bc4b82005-05-15 17:28:26 +00001350 "Can't create/open log file '%s.pid%d'; giving up!",
nethercotef8548672004-06-21 12:42:35 +00001351 VG_(clo_log_name), pid);
jsgff3c3f1a2003-10-14 22:13:28 +00001352 VG_(bad_option)(
sewardj603d4102005-01-11 14:01:02 +00001353 "--log-file=<file> (didn't work out for some reason.)");
njnbe9b47b2005-05-15 16:22:58 +00001354 /*NOTREACHED*/
jsgff3c3f1a2003-10-14 22:13:28 +00001355 }
1356 }
1357 }
sewardj603d4102005-01-11 14:01:02 +00001358 break; /* switch (VG_(clo_log_to)) */
1359 }
1360
1361 case VgLogTo_FileExactly: {
sewardj603d4102005-01-11 14:01:02 +00001362 vg_assert(VG_(clo_log_name) != NULL);
1363 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
sewardj603d4102005-01-11 14:01:02 +00001364
sewardj92645592005-07-23 09:18:34 +00001365 sres
njnbe9b47b2005-05-15 16:22:58 +00001366 = VG_(open)(VG_(clo_log_name),
sewardj603d4102005-01-11 14:01:02 +00001367 VKI_O_CREAT|VKI_O_WRONLY|VKI_O_TRUNC,
1368 VKI_S_IRUSR|VKI_S_IWUSR);
sewardj92645592005-07-23 09:18:34 +00001369 if (!sres.isError) {
1370 eventually_log_fd = sres.val;
sewardj603d4102005-01-11 14:01:02 +00001371 VG_(clo_log_fd) = VG_(safe_fd)(eventually_log_fd);
njnbe9b47b2005-05-15 16:22:58 +00001372 } else {
sewardj603d4102005-01-11 14:01:02 +00001373 VG_(message)(Vg_UserMsg,
njn02bc4b82005-05-15 17:28:26 +00001374 "Can't create/open log file '%s'; giving up!",
sewardj603d4102005-01-11 14:01:02 +00001375 VG_(clo_log_name));
1376 VG_(bad_option)(
1377 "--log-file-exactly=<file> (didn't work out for some reason.)");
1378 /*NOTREACHED*/
1379 }
1380 break; /* switch (VG_(clo_log_to)) */
sewardj73cf3bc2002-11-03 03:20:15 +00001381 }
1382
1383 case VgLogTo_Socket: {
nethercotef8548672004-06-21 12:42:35 +00001384 vg_assert(VG_(clo_log_name) != NULL);
1385 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
1386 eventually_log_fd = VG_(connect_via_socket)( VG_(clo_log_name) );
1387 if (eventually_log_fd == -1) {
sewardj73cf3bc2002-11-03 03:20:15 +00001388 VG_(message)(Vg_UserMsg,
nethercotef8548672004-06-21 12:42:35 +00001389 "Invalid --log-socket=ipaddr or --log-socket=ipaddr:port spec");
sewardj73cf3bc2002-11-03 03:20:15 +00001390 VG_(message)(Vg_UserMsg,
njn02bc4b82005-05-15 17:28:26 +00001391 "of '%s'; giving up!", VG_(clo_log_name) );
sewardj73cf3bc2002-11-03 03:20:15 +00001392 VG_(bad_option)(
nethercotef8548672004-06-21 12:42:35 +00001393 "--log-socket=");
njnbe9b47b2005-05-15 16:22:58 +00001394 /*NOTREACHED*/
sewardj4cf05692002-10-27 20:28:29 +00001395 }
nethercotef8548672004-06-21 12:42:35 +00001396 if (eventually_log_fd == -2) {
sewardj73cf3bc2002-11-03 03:20:15 +00001397 VG_(message)(Vg_UserMsg,
njn02bc4b82005-05-15 17:28:26 +00001398 "valgrind: failed to connect to logging server '%s'.",
nethercotef8548672004-06-21 12:42:35 +00001399 VG_(clo_log_name) );
sewardj570f8902002-11-03 11:44:36 +00001400 VG_(message)(Vg_UserMsg,
1401 "Log messages will sent to stderr instead." );
1402 VG_(message)(Vg_UserMsg,
1403 "" );
1404 /* We don't change anything here. */
njnbe9b47b2005-05-15 16:22:58 +00001405 vg_assert(VG_(clo_log_fd) == 2);
sewardj570f8902002-11-03 11:44:36 +00001406 } else {
nethercotef8548672004-06-21 12:42:35 +00001407 vg_assert(eventually_log_fd > 0);
1408 VG_(clo_log_fd) = eventually_log_fd;
njnbe9b47b2005-05-15 16:22:58 +00001409 VG_(logging_to_socket) = True;
sewardj570f8902002-11-03 11:44:36 +00001410 }
sewardj73cf3bc2002-11-03 03:20:15 +00001411 break;
1412 }
sewardj4cf05692002-10-27 20:28:29 +00001413 }
1414
sewardj71bc3cb2005-05-19 00:25:45 +00001415
1416 /* Check that the requested tool actually supports XML output. */
sewardj45f4e7c2005-09-27 19:20:21 +00001417 if (VG_(clo_xml) && !VG_STREQ(toolname, "memcheck")
1418 && !VG_STREQ(toolname, "none")) {
sewardj71bc3cb2005-05-19 00:25:45 +00001419 VG_(clo_xml) = False;
1420 VG_(message)(Vg_UserMsg,
cerion39655202005-07-13 14:18:24 +00001421 "Currently only Memcheck|None supports XML output.");
sewardj71bc3cb2005-05-19 00:25:45 +00001422 VG_(bad_option)("--xml=yes");
1423 /*NOTREACHED*/
1424 }
1425
njnbe9b47b2005-05-15 16:22:58 +00001426 // Move log_fd into the safe range, so it doesn't conflict with any app fds.
1427 // XXX: this is more or less duplicating the behaviour of the calls to
1428 // VG_(safe_fd)() above, although this does not close the original fd.
1429 // Perhaps the VG_(safe_fd)() calls above should be removed, and this
1430 // code should be replaced with a call to VG_(safe_fd)(). --njn
thughesad1c9562004-06-26 11:27:52 +00001431 eventually_log_fd = VG_(fcntl)(VG_(clo_log_fd), VKI_F_DUPFD, VG_(fd_hard_limit));
nethercotef8548672004-06-21 12:42:35 +00001432 if (eventually_log_fd < 0)
jsgf855d93d2003-10-13 22:26:55 +00001433 VG_(message)(Vg_UserMsg, "valgrind: failed to move logfile fd into safe range");
1434 else {
nethercotef8548672004-06-21 12:42:35 +00001435 VG_(clo_log_fd) = eventually_log_fd;
1436 VG_(fcntl)(VG_(clo_log_fd), VKI_F_SETFD, VKI_FD_CLOEXEC);
jsgf855d93d2003-10-13 22:26:55 +00001437 }
1438
sewardj45f4e7c2005-09-27 19:20:21 +00001439 if (VG_(clo_n_suppressions) < VG_CLO_MAX_SFILES-1 &&
1440 (VG_(needs).core_errors || VG_(needs).tool_errors)) {
1441 /* If we haven't reached the max number of suppressions, load
1442 the default one. */
1443 static const Char default_supp[] = "default.supp";
1444 Int len = VG_(strlen)(VG_(libdir)) + 1 + sizeof(default_supp);
1445 Char *buf = VG_(arena_malloc)(VG_AR_CORE, len);
1446 VG_(sprintf)(buf, "%s/%s", VG_(libdir), default_supp);
1447 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = buf;
1448 VG_(clo_n_suppressions)++;
1449 }
sewardjde4a1d02002-03-22 01:27:54 +00001450
sewardj45f4e7c2005-09-27 19:20:21 +00001451 return (log_to == VgLogTo_Fd);
1452}
1453
1454
1455/*====================================================================*/
1456/*=== Printing the preamble ===*/
1457/*====================================================================*/
1458
1459/* Ok, the logging sink is running now. Print a suitable preamble.
1460 If logging to file or a socket, write details of parent PID and
1461 command line args, to help people trying to interpret the
1462 results of a run which encompasses multiple processes. */
1463static void print_preamble(Bool logging_to_fd, const char* toolname)
1464{
1465 Int i;
1466
sewardj71bc3cb2005-05-19 00:25:45 +00001467 if (VG_(clo_xml)) {
sewardj8665d8e2005-06-01 17:35:23 +00001468 VG_(message)(Vg_UserMsg, "<?xml version=\"1.0\"?>");
1469 VG_(message)(Vg_UserMsg, "");
sewardj71bc3cb2005-05-19 00:25:45 +00001470 VG_(message)(Vg_UserMsg, "<valgrindoutput>");
1471 VG_(message)(Vg_UserMsg, "");
1472 VG_(message)(Vg_UserMsg, "<protocolversion>1</protocolversion>");
1473 VG_(message)(Vg_UserMsg, "");
1474 }
1475
sewardjd7bddad2005-06-13 16:48:32 +00001476 HChar* xpre = VG_(clo_xml) ? " <line>" : "";
1477 HChar* xpost = VG_(clo_xml) ? "</line>" : "";
sewardj71bc3cb2005-05-19 00:25:45 +00001478
sewardj83adf412002-05-01 01:25:45 +00001479 if (VG_(clo_verbosity > 0)) {
sewardjd7bddad2005-06-13 16:48:32 +00001480
1481 if (VG_(clo_xml))
1482 VG_(message)(Vg_UserMsg, "<preamble>");
1483
nethercote996901a2004-08-03 13:29:09 +00001484 /* Tool details */
sewardj71bc3cb2005-05-19 00:25:45 +00001485 VG_(message)(Vg_UserMsg, "%s%s%s%s, %s.%s",
1486 xpre,
njnd04b7c62002-10-03 14:05:52 +00001487 VG_(details).name,
njnb9c427c2004-12-01 14:14:42 +00001488 NULL == VG_(details).version ? "" : "-",
njnd04b7c62002-10-03 14:05:52 +00001489 NULL == VG_(details).version
1490 ? (Char*)"" : VG_(details).version,
sewardj71bc3cb2005-05-19 00:25:45 +00001491 VG_(details).description,
1492 xpost);
1493 VG_(message)(Vg_UserMsg, "%s%s%s",
1494 xpre, VG_(details).copyright_author, xpost);
sewardj3b2736a2002-03-24 12:18:35 +00001495
njnd04b7c62002-10-03 14:05:52 +00001496 /* Core details */
1497 VG_(message)(Vg_UserMsg,
sewardj71bc3cb2005-05-19 00:25:45 +00001498 "%sUsing LibVEX rev %s, a library for dynamic binary translation.%s",
1499 xpre, LibVEX_Version(), xpost );
sewardjc7025332004-12-13 18:30:39 +00001500 VG_(message)(Vg_UserMsg,
sewardj71bc3cb2005-05-19 00:25:45 +00001501 "%sCopyright (C) 2004-2005, and GNU GPL'd, by OpenWorks LLP.%s",
1502 xpre, xpost );
sewardjc7025332004-12-13 18:30:39 +00001503 VG_(message)(Vg_UserMsg,
sewardj71bc3cb2005-05-19 00:25:45 +00001504 "%sUsing valgrind-%s, a dynamic binary instrumentation framework.%s",
1505 xpre, VERSION, xpost);
sewardjde4a1d02002-03-22 01:27:54 +00001506 VG_(message)(Vg_UserMsg,
sewardj71bc3cb2005-05-19 00:25:45 +00001507 "%sCopyright (C) 2000-2005, and GNU GPL'd, by Julian Seward et al.%s",
1508 xpre, xpost );
sewardjd7bddad2005-06-13 16:48:32 +00001509
sewardj45f4e7c2005-09-27 19:20:21 +00001510 if (VG_(clo_verbosity) == 1 && !VG_(clo_xml))
1511 VG_(message)(Vg_UserMsg, "For more details, rerun with: -v");
1512
sewardjd7bddad2005-06-13 16:48:32 +00001513 if (VG_(clo_xml))
1514 VG_(message)(Vg_UserMsg, "</preamble>");
njnd04b7c62002-10-03 14:05:52 +00001515 }
1516
sewardj45f4e7c2005-09-27 19:20:21 +00001517 if (!VG_(clo_xml) && VG_(clo_verbosity) > 0 && !logging_to_fd) {
sewardj4cf05692002-10-27 20:28:29 +00001518 VG_(message)(Vg_UserMsg, "");
1519 VG_(message)(Vg_UserMsg,
1520 "My PID = %d, parent PID = %d. Prog and args are:",
1521 VG_(getpid)(), VG_(getppid)() );
sewardj45f4e7c2005-09-27 19:20:21 +00001522 for (i = 0; i < VG_(args_for_client).used; i++)
1523 VG_(message)(Vg_UserMsg, " %s", VG_(args_for_client).strs[i]);
sewardj5b742c32005-07-26 23:43:26 +00001524 if (VG_(clo_log_file_qualifier)) {
1525 HChar* val = VG_(getenv)(VG_(clo_log_file_qualifier));
1526 VG_(message)(Vg_UserMsg, "");
1527 VG_(message)(Vg_UserMsg, "Log file qualifier: var %s, value %s.",
1528 VG_(clo_log_file_qualifier),
1529 val ? val : "");
1530 }
sewardj4cf05692002-10-27 20:28:29 +00001531 }
sewardj71bc3cb2005-05-19 00:25:45 +00001532 else
1533 if (VG_(clo_xml)) {
1534 VG_(message)(Vg_UserMsg, "");
1535 VG_(message)(Vg_UserMsg, "<pid>%d</pid>", VG_(getpid)());
1536 VG_(message)(Vg_UserMsg, "<ppid>%d</ppid>", VG_(getppid)());
sewardj97f7e0c2005-07-19 15:00:25 +00001537 VG_(message)(Vg_UserMsg, "<tool>%t</tool>", toolname);
sewardjad311162005-07-19 11:25:02 +00001538 if (VG_(clo_log_file_qualifier)) {
1539 HChar* val = VG_(getenv)(VG_(clo_log_file_qualifier));
sewardj97f7e0c2005-07-19 15:00:25 +00001540 VG_(message)(Vg_UserMsg, "<logfilequalifier> <var>%t</var> "
1541 "<value>%t</value> </logfilequalifier>",
sewardjad311162005-07-19 11:25:02 +00001542 VG_(clo_log_file_qualifier),
1543 val ? val : "");
1544 }
sewardj768db0e2005-07-19 14:18:56 +00001545 if (VG_(clo_xml_user_comment)) {
1546 /* Note: the user comment itself is XML and is therefore to
1547 be passed through verbatim (%s) rather than escaped
1548 (%t). */
1549 VG_(message)(Vg_UserMsg, "<usercomment>%s</usercomment>",
1550 VG_(clo_xml_user_comment));
1551 }
sewardj71bc3cb2005-05-19 00:25:45 +00001552 VG_(message)(Vg_UserMsg, "");
sewardjb8a3dac2005-07-19 12:39:11 +00001553 VG_(message)(Vg_UserMsg, "<args>");
sewardj45f4e7c2005-09-27 19:20:21 +00001554
sewardjb8a3dac2005-07-19 12:39:11 +00001555 VG_(message)(Vg_UserMsg, " <vargv>");
sewardj45f4e7c2005-09-27 19:20:21 +00001556 if (VG_(name_of_launcher))
1557 VG_(message)(Vg_UserMsg, " <exe>%t</exe>",
1558 VG_(name_of_launcher));
1559 for (i = 0; i < VG_(args_for_valgrind).used; i++) {
1560 VG_(message)(Vg_UserMsg,
1561 " <arg>%t</arg>",
1562 VG_(args_for_valgrind).strs[i]);
sewardjb8a3dac2005-07-19 12:39:11 +00001563 }
1564 VG_(message)(Vg_UserMsg, " </vargv>");
sewardj45f4e7c2005-09-27 19:20:21 +00001565
sewardjb8a3dac2005-07-19 12:39:11 +00001566 VG_(message)(Vg_UserMsg, " <argv>");
sewardj45f4e7c2005-09-27 19:20:21 +00001567 if (VG_(args_the_exename))
1568 VG_(message)(Vg_UserMsg, " <exe>%t</exe>",
1569 VG_(args_the_exename));
1570 for (i = 0; i < VG_(args_for_client).used; i++) {
1571 VG_(message)(Vg_UserMsg, " <arg>%t</arg>",
1572 VG_(args_for_client).strs[i]);
sewardj8665d8e2005-06-01 17:35:23 +00001573 }
sewardjb8a3dac2005-07-19 12:39:11 +00001574 VG_(message)(Vg_UserMsg, " </argv>");
sewardj45f4e7c2005-09-27 19:20:21 +00001575
sewardjb8a3dac2005-07-19 12:39:11 +00001576 VG_(message)(Vg_UserMsg, "</args>");
sewardj71bc3cb2005-05-19 00:25:45 +00001577 }
sewardj4cf05692002-10-27 20:28:29 +00001578
sewardj45f4e7c2005-09-27 19:20:21 +00001579 // Empty line after the preamble
1580 if (VG_(clo_verbosity) > 0)
1581 VG_(message)(Vg_UserMsg, "");
1582
sewardjde4a1d02002-03-22 01:27:54 +00001583 if (VG_(clo_verbosity) > 1) {
sewardj92645592005-07-23 09:18:34 +00001584 SysRes fd;
sewardj45f4e7c2005-09-27 19:20:21 +00001585 if (!logging_to_fd)
njn1fd5eb22005-03-13 05:43:23 +00001586 VG_(message)(Vg_DebugMsg, "");
1587 VG_(message)(Vg_DebugMsg, "Valgrind library directory: %s", VG_(libdir));
sewardj45f4e7c2005-09-27 19:20:21 +00001588
njn1fd5eb22005-03-13 05:43:23 +00001589 VG_(message)(Vg_DebugMsg, "Command line");
sewardj45f4e7c2005-09-27 19:20:21 +00001590 if (VG_(args_the_exename))
1591 VG_(message)(Vg_DebugMsg, " %s", VG_(args_the_exename));
1592 for (i = 0; i < VG_(args_for_client).used; i++)
1593 VG_(message)(Vg_DebugMsg, " %s", VG_(args_for_client).strs[i]);
njn86dc2bc2003-09-09 07:26:21 +00001594
njn1fd5eb22005-03-13 05:43:23 +00001595 VG_(message)(Vg_DebugMsg, "Startup, with flags:");
sewardj45f4e7c2005-09-27 19:20:21 +00001596 for (i = 0; i < VG_(args_for_valgrind).used; i++) {
1597 VG_(message)(Vg_DebugMsg, " %s", VG_(args_for_valgrind).strs[i]);
sewardjde4a1d02002-03-22 01:27:54 +00001598 }
nethercotea70f7352004-04-18 12:08:46 +00001599
njn1fd5eb22005-03-13 05:43:23 +00001600 VG_(message)(Vg_DebugMsg, "Contents of /proc/version:");
nethercotea70f7352004-04-18 12:08:46 +00001601 fd = VG_(open) ( "/proc/version", VKI_O_RDONLY, 0 );
sewardj92645592005-07-23 09:18:34 +00001602 if (fd.isError) {
njn1fd5eb22005-03-13 05:43:23 +00001603 VG_(message)(Vg_DebugMsg, " can't open /proc/version");
nethercotea70f7352004-04-18 12:08:46 +00001604 } else {
sewardj71bc3cb2005-05-19 00:25:45 +00001605# define BUF_LEN 256
nethercotea70f7352004-04-18 12:08:46 +00001606 Char version_buf[BUF_LEN];
sewardj92645592005-07-23 09:18:34 +00001607 Int n = VG_(read) ( fd.val, version_buf, BUF_LEN );
njnbe9b47b2005-05-15 16:22:58 +00001608 vg_assert(n <= BUF_LEN);
nethercotea70f7352004-04-18 12:08:46 +00001609 if (n > 0) {
1610 version_buf[n-1] = '\0';
njn1fd5eb22005-03-13 05:43:23 +00001611 VG_(message)(Vg_DebugMsg, " %s", version_buf);
nethercotea70f7352004-04-18 12:08:46 +00001612 } else {
njn1fd5eb22005-03-13 05:43:23 +00001613 VG_(message)(Vg_DebugMsg, " (empty?)");
nethercotea70f7352004-04-18 12:08:46 +00001614 }
sewardj92645592005-07-23 09:18:34 +00001615 VG_(close)(fd.val);
sewardj71bc3cb2005-05-19 00:25:45 +00001616# undef BUF_LEN
nethercotea70f7352004-04-18 12:08:46 +00001617 }
sewardjde4a1d02002-03-22 01:27:54 +00001618 }
nethercotef6a1d502004-08-09 12:21:57 +00001619}
1620
sewardjde4a1d02002-03-22 01:27:54 +00001621
nethercote71980f02004-01-24 18:18:54 +00001622/*====================================================================*/
1623/*=== File descriptor setup ===*/
1624/*====================================================================*/
1625
sewardj5f229e22005-09-28 01:36:01 +00001626/* Number of file descriptors that Valgrind tries to reserve for
1627 it's own use - just a small constant. */
1628#define N_RESERVED_FDS (10)
1629
nethercote71980f02004-01-24 18:18:54 +00001630static void setup_file_descriptors(void)
1631{
1632 struct vki_rlimit rl;
1633
1634 /* Get the current file descriptor limits. */
1635 if (VG_(getrlimit)(VKI_RLIMIT_NOFILE, &rl) < 0) {
1636 rl.rlim_cur = 1024;
1637 rl.rlim_max = 1024;
1638 }
1639
1640 /* Work out where to move the soft limit to. */
njn14319cc2005-03-13 06:26:22 +00001641 if (rl.rlim_cur + N_RESERVED_FDS <= rl.rlim_max) {
1642 rl.rlim_cur = rl.rlim_cur + N_RESERVED_FDS;
nethercote71980f02004-01-24 18:18:54 +00001643 } else {
1644 rl.rlim_cur = rl.rlim_max;
1645 }
1646
1647 /* Reserve some file descriptors for our use. */
njn14319cc2005-03-13 06:26:22 +00001648 VG_(fd_soft_limit) = rl.rlim_cur - N_RESERVED_FDS;
1649 VG_(fd_hard_limit) = rl.rlim_cur - N_RESERVED_FDS;
nethercote71980f02004-01-24 18:18:54 +00001650
1651 /* Update the soft limit. */
1652 VG_(setrlimit)(VKI_RLIMIT_NOFILE, &rl);
1653
sewardj45f4e7c2005-09-27 19:20:21 +00001654 if (VG_(cl_exec_fd) != -1)
1655 VG_(cl_exec_fd) = VG_(safe_fd)( VG_(cl_exec_fd) );
nethercote71980f02004-01-24 18:18:54 +00001656}
1657
sewardjde4a1d02002-03-22 01:27:54 +00001658
njn2da73352005-06-18 01:35:16 +00001659/*====================================================================*/
1660/*=== Initialise the first thread. ===*/
1661/*====================================================================*/
1662
1663/* Given a pointer to the ThreadArchState for thread 1 (the root
1664 thread), initialise the VEX guest state, and copy in essential
1665 starting values.
1666*/
1667static void init_thread1state ( Addr client_ip,
sewardjfdf91b42005-09-28 00:53:09 +00001668 Addr client_sp,
njn2da73352005-06-18 01:35:16 +00001669 /*inout*/ ThreadArchState* arch )
1670{
1671#if defined(VGA_x86)
1672 vg_assert(0 == sizeof(VexGuestX86State) % 8);
1673
1674 /* Zero out the initial state, and set up the simulated FPU in a
1675 sane way. */
1676 LibVEX_GuestX86_initialise(&arch->vex);
1677
1678 /* Zero out the shadow area. */
1679 VG_(memset)(&arch->vex_shadow, 0, sizeof(VexGuestX86State));
1680
1681 /* Put essential stuff into the new state. */
sewardjfdf91b42005-09-28 00:53:09 +00001682 arch->vex.guest_ESP = client_sp;
njn2da73352005-06-18 01:35:16 +00001683 arch->vex.guest_EIP = client_ip;
1684
1685 /* initialise %cs, %ds and %ss to point at the operating systems
1686 default code, data and stack segments */
1687 asm volatile("movw %%cs, %0" : : "m" (arch->vex.guest_CS));
1688 asm volatile("movw %%ds, %0" : : "m" (arch->vex.guest_DS));
1689 asm volatile("movw %%ss, %0" : : "m" (arch->vex.guest_SS));
cerion85665ca2005-06-20 15:51:07 +00001690
njn2da73352005-06-18 01:35:16 +00001691#elif defined(VGA_amd64)
1692 vg_assert(0 == sizeof(VexGuestAMD64State) % 8);
1693
1694 /* Zero out the initial state, and set up the simulated FPU in a
1695 sane way. */
1696 LibVEX_GuestAMD64_initialise(&arch->vex);
1697
1698 /* Zero out the shadow area. */
1699 VG_(memset)(&arch->vex_shadow, 0, sizeof(VexGuestAMD64State));
1700
1701 /* Put essential stuff into the new state. */
sewardjfdf91b42005-09-28 00:53:09 +00001702 arch->vex.guest_RSP = client_sp;
njn2da73352005-06-18 01:35:16 +00001703 arch->vex.guest_RIP = client_ip;
cerion85665ca2005-06-20 15:51:07 +00001704
1705#elif defined(VGA_ppc32)
1706 vg_assert(0 == sizeof(VexGuestPPC32State) % 8);
1707
1708 /* Zero out the initial state, and set up the simulated FPU in a
1709 sane way. */
1710 LibVEX_GuestPPC32_initialise(&arch->vex);
1711
1712 /* Zero out the shadow area. */
1713 VG_(memset)(&arch->vex_shadow, 0, sizeof(VexGuestPPC32State));
1714
1715 /* Put essential stuff into the new state. */
sewardjfdf91b42005-09-28 00:53:09 +00001716 arch->vex.guest_GPR1 = client_sp;
cerion85665ca2005-06-20 15:51:07 +00001717 arch->vex.guest_CIA = client_ip;
1718
njn2da73352005-06-18 01:35:16 +00001719#else
1720# error Unknown arch
1721#endif
1722 // Tell the tool that we just wrote to the registers.
1723 VG_TRACK( post_reg_write, Vg_CoreStartup, /*tid*/1, /*offset*/0,
1724 sizeof(VexGuestArchState));
1725}
1726
sewardjde4a1d02002-03-22 01:27:54 +00001727
nethercote71980f02004-01-24 18:18:54 +00001728/*====================================================================*/
njn2025cf92005-06-26 20:44:48 +00001729/*=== BB profiling ===*/
1730/*====================================================================*/
1731
1732static
1733void show_BB_profile ( BBProfEntry tops[], UInt n_tops, ULong score_total )
1734{
1735 ULong score_cumul, score_here;
1736 Char buf_cumul[10], buf_here[10];
1737 Char name[64];
1738 Int r;
1739
1740 VG_(printf)("\n");
1741 VG_(printf)("-----------------------------------------------------------\n");
1742 VG_(printf)("--- BEGIN BB Profile (summary of scores) ---\n");
1743 VG_(printf)("-----------------------------------------------------------\n");
1744 VG_(printf)("\n");
1745
1746 VG_(printf)("Total score = %lld\n\n", score_total);
1747
1748 score_cumul = 0;
1749 for (r = 0; r < n_tops; r++) {
1750 if (tops[r].addr == 0)
1751 continue;
1752 name[0] = 0;
1753 VG_(get_fnname_w_offset)(tops[r].addr, name, 64);
1754 name[63] = 0;
1755 score_here = tops[r].score;
1756 score_cumul += score_here;
1757 VG_(percentify)(score_cumul, score_total, 2, 6, buf_cumul);
1758 VG_(percentify)(score_here, score_total, 2, 6, buf_here);
1759 VG_(printf)("%3d: (%9lld %s) %9lld %s 0x%llx %s\n",
1760 r,
1761 score_cumul, buf_cumul,
1762 score_here, buf_here, tops[r].addr, name );
1763 }
1764
1765 VG_(printf)("\n");
1766 VG_(printf)("-----------------------------------------------------------\n");
1767 VG_(printf)("--- BB Profile (BB details) ---\n");
1768 VG_(printf)("-----------------------------------------------------------\n");
1769 VG_(printf)("\n");
1770
1771 score_cumul = 0;
1772 for (r = 0; r < n_tops; r++) {
1773 if (tops[r].addr == 0)
1774 continue;
1775 name[0] = 0;
1776 VG_(get_fnname_w_offset)(tops[r].addr, name, 64);
1777 name[63] = 0;
1778 score_here = tops[r].score;
1779 score_cumul += score_here;
1780 VG_(percentify)(score_cumul, score_total, 2, 6, buf_cumul);
1781 VG_(percentify)(score_here, score_total, 2, 6, buf_here);
1782 VG_(printf)("\n");
1783 VG_(printf)("=-=-=-=-=-=-=-=-=-=-=-=-=-= begin BB rank %d "
1784 "=-=-=-=-=-=-=-=-=-=-=-=-=-=\n\n", r);
1785 VG_(printf)("%3d: (%9lld %s) %9lld %s 0x%llx %s\n",
1786 r,
1787 score_cumul, buf_cumul,
1788 score_here, buf_here, tops[r].addr, name );
1789 VG_(printf)("\n");
1790 VG_(translate)(0, tops[r].addr, True, VG_(clo_profile_flags), 0);
1791 VG_(printf)("=-=-=-=-=-=-=-=-=-=-=-=-=-= end BB rank %d "
1792 "=-=-=-=-=-=-=-=-=-=-=-=-=-=\n\n", r);
1793 }
1794
1795 VG_(printf)("\n");
1796 VG_(printf)("-----------------------------------------------------------\n");
1797 VG_(printf)("--- END BB Profile ---\n");
1798 VG_(printf)("-----------------------------------------------------------\n");
1799 VG_(printf)("\n");
1800}
1801
1802
1803/*====================================================================*/
nethercote71980f02004-01-24 18:18:54 +00001804/*=== main() ===*/
1805/*====================================================================*/
1806
sewardjfdf91b42005-09-28 00:53:09 +00001807/* When main() is entered, we should be on the following stack, not
1808 the one the kernel gave us. We will run on this stack until
1809 simulation of the root thread is started, at which point a transfer
1810 is made to a dynamically allocated stack. This is for the sake of
1811 uniform overflow detection for all Valgrind threads. This is
1812 marked global even though it isn't, because assembly code below
1813 needs to reference the name. */
1814
1815/*static*/ VgStack VG_(interim_stack);
1816
1817/* This should get some address inside the stack on which we gained
1818 control (eg, it could be the SP at startup). It doesn't matter
1819 exactly where in the stack it is. This value is passed to the
1820 address space manager at startup, which uses it to identify the
1821 initial stack segment and hence the upper end of the usable address
1822 space. */
1823
1824static Addr sp_at_startup = 0;
1825
1826
1827
sewardj45f4e7c2005-09-27 19:20:21 +00001828/* TODO: GIVE THIS A PROPER HOME
1829 TODO: MERGE THIS WITH DUPLICATE IN mac_leakcheck.c
1830 Extract from aspacem a vector of the current segment start
1831 addresses. The vector is dynamically allocated and should be freed
1832 by the caller when done. REQUIRES m_mallocfree to be running.
1833 Writes the number of addresses required into *n_acquired. */
nethercotec314eba2004-07-15 12:59:41 +00001834
sewardj45f4e7c2005-09-27 19:20:21 +00001835static Addr* get_seg_starts ( /*OUT*/Int* n_acquired )
sewardj1cf558c2005-04-25 01:36:56 +00001836{
sewardj45f4e7c2005-09-27 19:20:21 +00001837 Addr* starts;
1838 Int n_starts, r;
1839
1840 n_starts = 1;
sewardj1cf558c2005-04-25 01:36:56 +00001841 while (True) {
sewardj45f4e7c2005-09-27 19:20:21 +00001842 starts = VG_(malloc)( n_starts * sizeof(Addr) );
1843 if (starts == NULL)
1844 break;
1845 r = VG_(am_get_segment_starts)( starts, n_starts );
1846 if (r >= 0)
1847 break;
1848 VG_(free)(starts);
1849 n_starts *= 2;
sewardj1cf558c2005-04-25 01:36:56 +00001850 }
sewardj45f4e7c2005-09-27 19:20:21 +00001851
1852 if (starts == NULL) {
1853 *n_acquired = 0;
1854 return NULL;
1855 }
1856
1857 *n_acquired = r;
1858 return starts;
sewardj1cf558c2005-04-25 01:36:56 +00001859}
1860
1861
sewardj45f4e7c2005-09-27 19:20:21 +00001862
sewardj45f4e7c2005-09-27 19:20:21 +00001863
1864
1865Int main(Int argc, HChar **argv, HChar **envp)
nethercote71980f02004-01-24 18:18:54 +00001866{
sewardj45f4e7c2005-09-27 19:20:21 +00001867 HChar* toolname = "memcheck"; // default to Memcheck
1868 HChar** env = NULL;
1869 Int need_help = 0; // 0 = no, 1 = --help, 2 = --help-debug
1870 Addr initial_client_IP = 0;
1871 Addr initial_client_SP = 0;
1872 Addr clstack_top = 0;
1873 SizeT clstack_max_size = 0;
1874 UInt* client_auxv;
1875 Int loglevel, i;
1876 Bool logging_to_fd;
nethercote73b526f2004-10-31 18:48:21 +00001877 struct vki_rlimit zero = { 0, 0 };
sewardj45f4e7c2005-09-27 19:20:21 +00001878 struct exeinfo info;
nethercote71980f02004-01-24 18:18:54 +00001879
1880 //============================================================
nethercote71980f02004-01-24 18:18:54 +00001881 //
sewardj45f4e7c2005-09-27 19:20:21 +00001882 // Nb: startup is complex. Prerequisites are shown at every step.
nethercote71980f02004-01-24 18:18:54 +00001883 // *** Be very careful when messing with the order ***
sewardj45f4e7c2005-09-27 19:20:21 +00001884 //
1885 // The first order of business is to get debug logging, the address
1886 // space manager and the dynamic memory manager up and running.
1887 // Once that's done, we can relax a bit.
1888 //
nethercote71980f02004-01-24 18:18:54 +00001889 //============================================================
sewardj45f4e7c2005-09-27 19:20:21 +00001890
1891 /* This is needed to make VG_(getenv) usable early. */
1892 VG_(client_envp) = (Char**)envp;
nethercote71980f02004-01-24 18:18:54 +00001893
sewardj1cf558c2005-04-25 01:36:56 +00001894 //--------------------------------------------------------------
1895 // Start up the logging mechanism
1896 // p: none
1897 //--------------------------------------------------------------
1898 /* Start the debugging-log system ASAP. First find out how many
1899 "-d"s were specified. This is a pre-scan of the command line. */
1900 loglevel = 0;
1901 for (i = 1; i < argc; i++) {
sewardj10759312005-05-30 23:52:47 +00001902 if (argv[i][0] != '-')
1903 break;
sewardj45f4e7c2005-09-27 19:20:21 +00001904 if (VG_STREQ(argv[i], "--"))
sewardj10759312005-05-30 23:52:47 +00001905 break;
sewardj45f4e7c2005-09-27 19:20:21 +00001906 if (VG_STREQ(argv[i], "-d"))
sewardj10759312005-05-30 23:52:47 +00001907 loglevel++;
sewardj1cf558c2005-04-25 01:36:56 +00001908 }
1909
1910 /* ... and start the debug logger. Now we can safely emit logging
1911 messages all through startup. */
sewardj10759312005-05-30 23:52:47 +00001912 VG_(debugLog_startup)(loglevel, "Stage 2 (main)");
sewardj45f4e7c2005-09-27 19:20:21 +00001913 VG_(debugLog)(1, "main", "Welcome to Valgrind version "
1914 VERSION " debug logging\n");
1915
1916 //--------------------------------------------------------------
1917 // Ensure we're on a plausible stack.
1918 // p: logging
1919 //--------------------------------------------------------------
1920 VG_(debugLog)(1, "main", "Checking current stack is plausible\n");
sewardjfdf91b42005-09-28 00:53:09 +00001921 { HChar* limLo = (HChar*)(&VG_(interim_stack).bytes[0]);
1922 HChar* limHi = limLo + sizeof(VG_(interim_stack));
sewardj45f4e7c2005-09-27 19:20:21 +00001923 HChar* aLocal = (HChar*)&zero; /* any auto local will do */
1924 if (aLocal < limLo || aLocal >= limHi) {
1925 /* something's wrong. Stop. */
1926 VG_(debugLog)(0, "main", "Root stack %p to %p, a local %p\n",
1927 limLo, limHi, aLocal );
1928 VG_(debugLog)(0, "main", "Valgrind: FATAL: "
1929 "Initial stack switched failed.\n");
1930 VG_(debugLog)(0, "main", " Cannot continue. Sorry.\n");
1931 VG_(exit)(1);
1932 }
1933 }
1934
1935 //--------------------------------------------------------------
1936 // Ensure we have a plausible pointer to the stack on which
1937 // we gained control (not the current stack!)
1938 // p: logging
1939 //--------------------------------------------------------------
1940 VG_(debugLog)(1, "main", "Checking initial stack was noted\n");
sewardjfdf91b42005-09-28 00:53:09 +00001941 if (sp_at_startup == 0) {
sewardj45f4e7c2005-09-27 19:20:21 +00001942 VG_(debugLog)(0, "main", "Valgrind: FATAL: "
1943 "Initial stack was not noted.\n");
1944 VG_(debugLog)(0, "main", " Cannot continue. Sorry.\n");
1945 VG_(exit)(1);
1946 }
1947
1948 //--------------------------------------------------------------
1949 // Start up the address space manager, and determine the
1950 // approximate location of the client's stack
1951 // p: logging, plausible-stack
1952 //--------------------------------------------------------------
1953 VG_(debugLog)(1, "main", "Starting the address space manager\n");
sewardjfdf91b42005-09-28 00:53:09 +00001954 clstack_top = VG_(am_startup)( sp_at_startup );
sewardj45f4e7c2005-09-27 19:20:21 +00001955 VG_(debugLog)(1, "main", "Address space manager is running\n");
1956
1957 //--------------------------------------------------------------
1958 // Start up the dynamic memory manager
1959 // p: address space management
1960 // In fact m_mallocfree is self-initialising, so there's no
1961 // initialisation call to do. Instead, try a simple malloc/
1962 // free pair right now to check that nothing is broken.
1963 //--------------------------------------------------------------
1964 VG_(debugLog)(1, "main", "Starting the dynamic memory manager\n");
1965 { void* p = VG_(malloc)( 12345 );
1966 if (p) VG_(free)( p );
1967 }
1968 VG_(debugLog)(1, "main", "Dynamic memory manager is running\n");
sewardj1cf558c2005-04-25 01:36:56 +00001969
nethercotef4928da2004-06-15 10:54:40 +00001970 //============================================================
sewardj45f4e7c2005-09-27 19:20:21 +00001971 //
1972 // Dynamic memory management is now available.
1973 //
nethercotef4928da2004-06-15 10:54:40 +00001974 //============================================================
1975
sewardj45f4e7c2005-09-27 19:20:21 +00001976 //--------------------------------------------------------------
1977 // Look for alternative libdir
1978 { HChar *cp = VG_(getenv)(VALGRIND_LIB);
1979 if (cp != NULL)
1980 VG_(libdir) = cp;
1981 }
1982
1983 //--------------------------------------------------------------
1984 // Extract the launcher name from the environment.
1985 VG_(debugLog)(1, "main", "Getting stage1's name\n");
1986 VG_(name_of_launcher) = VG_(getenv)(VALGRIND_LAUNCHER);
1987 if (VG_(name_of_launcher) == NULL) {
1988 VG_(printf)("valgrind: You cannot run '%s' directly.\n", argv[0]);
1989 VG_(printf)("valgrind: You should use $prefix/bin/valgrind.\n");
1990 VG_(exit)(1);
1991 }
1992
1993 //--------------------------------------------------------------
fitzhardingeb50068f2004-02-24 23:42:55 +00001994 // Get the current process datasize rlimit, and set it to zero.
1995 // This prevents any internal uses of brk() from having any effect.
1996 // We remember the old value so we can restore it on exec, so that
1997 // child processes will have a reasonable brk value.
1998 VG_(getrlimit)(VKI_RLIMIT_DATA, &VG_(client_rlimit_data));
1999 zero.rlim_max = VG_(client_rlimit_data).rlim_max;
2000 VG_(setrlimit)(VKI_RLIMIT_DATA, &zero);
thughesc37184f2004-09-11 14:16:57 +00002001
2002 // Get the current process stack rlimit.
2003 VG_(getrlimit)(VKI_RLIMIT_STACK, &VG_(client_rlimit_stack));
2004
sewardj45f4e7c2005-09-27 19:20:21 +00002005 //============================================================
2006 // Command line argument handling order:
2007 // * If --help/--help-debug are present, show usage message
2008 // (including the tool-specific usage)
2009 // * (If no --tool option given, default to Memcheck)
2010 // * Then, if client is missing, abort with error msg
2011 // * Then, if any cmdline args are bad, abort with error msg
2012 //============================================================
2013
2014 //--------------------------------------------------------------
2015 // Split up argv into: C args, V args, V extra args, and exename.
2016 // p: dynamic memory allocation
2017 //--------------------------------------------------------------
2018 VG_(debugLog)(1, "main", "Split up command line\n");
2019 VG_(split_up_argv)( argc, argv );
2020 if (0) {
2021 for (i = 0; i < VG_(args_for_valgrind).used; i++)
2022 VG_(printf)("varg %s\n", VG_(args_for_valgrind).strs[i]);
2023 VG_(printf)(" exe %s\n", VG_(args_the_exename));
2024 for (i = 0; i < VG_(args_for_client).used; i++)
2025 VG_(printf)("carg %s\n", VG_(args_for_client).strs[i]);
nethercote71980f02004-01-24 18:18:54 +00002026 }
2027
2028 //--------------------------------------------------------------
sewardj45f4e7c2005-09-27 19:20:21 +00002029 // Extract tool name and whether help has been requested.
2030 // Note we can't print the help message yet, even if requested,
2031 // because the tool has not been initialised.
2032 // p: split_up_argv [for VG_(args_for_valgrind)]
nethercote71980f02004-01-24 18:18:54 +00002033 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002034 VG_(debugLog)(1, "main", "Preprocess command line opts\n");
sewardj45f4e7c2005-09-27 19:20:21 +00002035 get_helprequest_and_toolname(&need_help, &toolname);
nethercote71980f02004-01-24 18:18:54 +00002036
sewardj45f4e7c2005-09-27 19:20:21 +00002037 // Set default vex control params
2038 LibVEX_default_VexControl(& VG_(clo_vex_control));
nethercote71980f02004-01-24 18:18:54 +00002039
2040 //--------------------------------------------------------------
2041 // Load client executable, finding in $PATH if necessary
sewardj45f4e7c2005-09-27 19:20:21 +00002042 // p: get_helprequest_and_toolname() [for 'exec', 'need_help']
nethercote71980f02004-01-24 18:18:54 +00002043 // p: layout_remaining_space [so there's space]
2044 //--------------------------------------------------------------
sewardj45f4e7c2005-09-27 19:20:21 +00002045 if (!need_help) {
2046 VG_(debugLog)(1, "main", "Loading client\n");
nethercote71980f02004-01-24 18:18:54 +00002047
sewardj45f4e7c2005-09-27 19:20:21 +00002048 if (VG_(args_the_exename) == NULL)
2049 missing_prog();
2050
2051 load_client(&info, &initial_client_IP);
2052 }
nethercote71980f02004-01-24 18:18:54 +00002053
2054 //--------------------------------------------------------------
2055 // Set up client's environment
sewardj45f4e7c2005-09-27 19:20:21 +00002056 // p: set-libdir [for VG_(libdir)]
2057 // p: get_helprequest_and_toolname [for toolname]
nethercote71980f02004-01-24 18:18:54 +00002058 //--------------------------------------------------------------
sewardj45f4e7c2005-09-27 19:20:21 +00002059 if (!need_help) {
2060 VG_(debugLog)(1, "main", "Setup client env\n");
2061 env = setup_client_env(envp, toolname);
2062 }
nethercote71980f02004-01-24 18:18:54 +00002063
2064 //--------------------------------------------------------------
nethercote5ee67ca2004-06-22 14:00:09 +00002065 // Setup client stack, eip, and VG_(client_arg[cv])
nethercote71980f02004-01-24 18:18:54 +00002066 // p: load_client() [for 'info']
2067 // p: fix_environment() [for 'env']
2068 //--------------------------------------------------------------
sewardj45f4e7c2005-09-27 19:20:21 +00002069 if (!need_help) {
2070 void* init_sp = argv - 1;
2071 SizeT m1 = 1024 * 1024;
2072 SizeT m8 = 8 * m1;
2073 VG_(debugLog)(1, "main", "Setup client stack\n");
2074 clstack_max_size = (SizeT)VG_(client_rlimit_stack).rlim_cur;
2075 if (clstack_max_size < m1) clstack_max_size = m1;
2076 if (clstack_max_size > m8) clstack_max_size = m8;
2077 clstack_max_size = VG_PGROUNDUP(clstack_max_size);
sewardjb5f6f512005-03-10 23:59:00 +00002078
sewardj45f4e7c2005-09-27 19:20:21 +00002079 initial_client_SP
2080 = setup_client_stack( init_sp, env,
2081 &info, &client_auxv,
2082 clstack_top, clstack_max_size );
2083
2084 VG_(free)(env);
2085
2086 VG_(debugLog)(2, "main",
2087 "Client info: "
2088 "entry=%p client_SP=%p brkbase=%p\n",
2089 (void*)initial_client_IP,
2090 (void*)initial_client_SP,
2091 (void*)VG_(brk_base) );
nethercotec25c4492004-10-18 11:52:17 +00002092 }
nethercote71980f02004-01-24 18:18:54 +00002093
sewardj45f4e7c2005-09-27 19:20:21 +00002094 //--------------------------------------------------------------
2095 // Setup client data (brk) segment. Initially a 1-page segment
2096 // which abuts a shrinkable reservation.
2097 // p: load_client() [for 'info' and hence VG_(brk_base)]
2098 //--------------------------------------------------------------
2099 if (!need_help) {
2100 SizeT m1 = 1024 * 1024;
2101 SizeT m8 = 8 * m1;
2102 SizeT dseg_max_size = (SizeT)VG_(client_rlimit_data).rlim_cur;
2103 VG_(debugLog)(1, "main", "Setup client data (brk) segment\n");
2104 if (dseg_max_size < m1) dseg_max_size = m1;
2105 if (dseg_max_size > m8) dseg_max_size = m8;
2106 dseg_max_size = VG_PGROUNDUP(dseg_max_size);
2107
2108 setup_client_dataseg( dseg_max_size );
2109 }
nethercote71980f02004-01-24 18:18:54 +00002110
2111 //==============================================================
sewardj45f4e7c2005-09-27 19:20:21 +00002112 //
2113 // Finished loading/setting up the client address space.
2114 //
nethercote71980f02004-01-24 18:18:54 +00002115 //==============================================================
2116
2117 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002118 // setup file descriptors
2119 // p: n/a
2120 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002121 VG_(debugLog)(1, "main", "Setup file descriptors\n");
nethercote71980f02004-01-24 18:18:54 +00002122 setup_file_descriptors();
2123
2124 //--------------------------------------------------------------
sewardj45f4e7c2005-09-27 19:20:21 +00002125 // create the fake /proc/<pid>/cmdline file and then unlink it,
2126 // but hold onto the fd, so we can hand it out to the client
2127 // when it tries to open /proc/<pid>/cmdline for itself.
2128 // p: setup file descriptors
nethercotec314eba2004-07-15 12:59:41 +00002129 //--------------------------------------------------------------
sewardj45f4e7c2005-09-27 19:20:21 +00002130 if (!need_help) {
2131 HChar buf[50], buf2[50+64];
2132 HChar nul[1];
2133 Int fd, r;
2134 HChar* exename;
nethercotec314eba2004-07-15 12:59:41 +00002135
sewardj45f4e7c2005-09-27 19:20:21 +00002136 VG_(debugLog)(1, "main", "Create fake /proc/<pid>/cmdline\n");
2137
2138 VG_(sprintf)(buf, "proc_%d_cmdline", VG_(getpid)());
2139 fd = VG_(mkstemp)( buf, buf2 );
2140 if (fd == -1)
2141 config_error("Can't create client cmdline file in /tmp.");
2142
2143 nul[0] = 0;
2144 exename = VG_(args_the_exename) ? VG_(args_the_exename)
2145 : "unknown_exename";
2146
2147 VG_(write)(fd, VG_(args_the_exename),
2148 VG_(strlen)( VG_(args_the_exename) ));
2149 VG_(write)(fd, nul, 1);
2150
2151 for (i = 0; i < VG_(args_for_client).used; i++) {
2152 VG_(write)(fd, VG_(args_for_client).strs[i],
2153 VG_(strlen)( VG_(args_for_client).strs[i] ));
2154 VG_(write)(fd, nul, 1);
2155 }
2156
2157 /* Don't bother to seek the file back to the start; instead do
2158 it every time a copy of it is given out (by PRE(sys_open)).
2159 That is probably more robust across fork() etc. */
2160
2161 /* Now delete it, but hang on to the fd. */
2162 r = VG_(unlink)( buf2 );
2163 if (r)
2164 config_error("Can't delete client cmdline file in /tmp.");
2165
2166 VG_(cl_cmdline_fd) = fd;
2167 }
nethercotec314eba2004-07-15 12:59:41 +00002168
2169 //--------------------------------------------------------------
sewardj45f4e7c2005-09-27 19:20:21 +00002170 // Init tool part 1: pre_clo_init
nethercotec314eba2004-07-15 12:59:41 +00002171 // p: setup_client_stack() [for 'VG_(client_arg[cv]']
nethercotec314eba2004-07-15 12:59:41 +00002172 // p: setup_file_descriptors() [for 'VG_(fd_xxx_limit)']
nethercote71980f02004-01-24 18:18:54 +00002173 //--------------------------------------------------------------
njn64c83242005-06-21 01:54:38 +00002174 {
2175 Char* s;
2176 Bool ok;
sewardj45f4e7c2005-09-27 19:20:21 +00002177 VG_(debugLog)(1, "main", "Initialise the tool part 1 (pre_clo_init)\n");
2178 (VG_(tool_info).tl_pre_clo_init)();
2179 ok = VG_(sanity_check_needs)( &s );
njn64c83242005-06-21 01:54:38 +00002180 if (!ok) {
2181 VG_(tool_panic)(s);
2182 }
2183 }
nethercote71980f02004-01-24 18:18:54 +00002184
sewardj45f4e7c2005-09-27 19:20:21 +00002185 //--------------------------------------------------------------
nethercotef4928da2004-06-15 10:54:40 +00002186 // If --tool and --help/--help-debug was given, now give the core+tool
2187 // help message
sewardj45f4e7c2005-09-27 19:20:21 +00002188 // p: get_helprequest_and_toolname() [for 'need_help']
2189 // p: tl_pre_clo_init [for 'VG_(tdict).usage']
2190 //--------------------------------------------------------------
2191 VG_(debugLog)(1, "main", "Print help and quit, if requested\n");
nethercotef4928da2004-06-15 10:54:40 +00002192 if (need_help) {
sewardj45f4e7c2005-09-27 19:20:21 +00002193 usage_NORETURN(/*--help-debug?*/2 == need_help);
nethercotef4928da2004-06-15 10:54:40 +00002194 }
nethercotec314eba2004-07-15 12:59:41 +00002195
sewardj45f4e7c2005-09-27 19:20:21 +00002196 //--------------------------------------------------------------
2197 // Process command line options to Valgrind + tool
2198 // p: setup_client_stack() [for 'VG_(client_arg[cv]']
2199 // p: setup_file_descriptors() [for 'VG_(fd_xxx_limit)']
2200 //--------------------------------------------------------------
2201 VG_(debugLog)(1, "main", "Process Valgrind's command line options, "
2202 " setup logging\n");
2203 logging_to_fd = process_cmd_line_options(client_auxv, toolname);
2204
2205 //--------------------------------------------------------------
2206 // Print the preamble
2207 // p: tl_pre_clo_init [for 'VG_(details).name' and friends]
2208 // p: process_cmd_line_options() [for VG_(clo_verbosity), VG_(clo_xml),
2209 // VG_(clo_log_file_qualifier),
2210 // logging_to_fd]
2211 //--------------------------------------------------------------
2212 VG_(debugLog)(1, "main", "Print the preamble...\n");
2213 print_preamble(logging_to_fd, toolname);
2214 VG_(debugLog)(1, "main", "...finished the preamble\n");
2215
2216 //--------------------------------------------------------------
2217 // Init tool part 2: post_clo_init
2218 // p: setup_client_stack() [for 'VG_(client_arg[cv]']
2219 // p: setup_file_descriptors() [for 'VG_(fd_xxx_limit)']
2220 // p: print_preamble() [so any warnings printed in post_clo_init
2221 // are shown after the preamble]
2222 //--------------------------------------------------------------
2223 VG_(debugLog)(1, "main", "Initialise the tool part 2 (post_clo_init)\n");
njn51d827b2005-05-09 01:02:08 +00002224 VG_TDICT_CALL(tool_post_clo_init);
nethercotef4928da2004-06-15 10:54:40 +00002225
2226 //--------------------------------------------------------------
sewardj45f4e7c2005-09-27 19:20:21 +00002227 // Initialise translation table and translation cache
2228 // p: aspacem [??]
2229 // p: tl_pre_clo_init [for 'VG_(details).avg_translation_sizeB']
nethercote71980f02004-01-24 18:18:54 +00002230 //--------------------------------------------------------------
sewardj45f4e7c2005-09-27 19:20:21 +00002231 VG_(debugLog)(1, "main", "Initialise TT/TC\n");
2232 VG_(init_tt_tc)();
sewardjb5f6f512005-03-10 23:59:00 +00002233
sewardj45f4e7c2005-09-27 19:20:21 +00002234 //--------------------------------------------------------------
2235 // Initialise the redirect table.
2236 // p: init_tt_tc [so it can call VG_(search_transtab) safely]
2237 // p: aspacem [so can change ownership of sysinfo pages]
2238 //--------------------------------------------------------------
2239 VG_(debugLog)(1, "main", "Initialise redirects\n");
2240 VG_(setup_code_redirect_table)();
nethercote71980f02004-01-24 18:18:54 +00002241
2242 //--------------------------------------------------------------
2243 // Allow GDB attach
2244 // p: process_cmd_line_options() [for VG_(clo_wait_for_gdb)]
2245 //--------------------------------------------------------------
2246 /* Hook to delay things long enough so we can get the pid and
2247 attach GDB in another shell. */
2248 if (VG_(clo_wait_for_gdb)) {
sewardj8211a572005-06-23 21:37:47 +00002249 Long q, iters;
sewardj1fbc1a52005-04-25 02:05:54 +00002250 VG_(debugLog)(1, "main", "Wait for GDB\n");
sewardj93ab8572005-02-06 14:10:40 +00002251 VG_(printf)("pid=%d, entering delay loop\n", VG_(getpid)());
2252 /* jrs 20050206: I don't understand why this works on x86. On
2253 amd64 the obvious analogues (jump *$rip or jump *$rcx) don't
2254 work. */
2255 /* do "jump *$eip" to skip this in gdb (x86) */
2256 //VG_(do_syscall0)(__NR_pause);
sewardj8211a572005-06-23 21:37:47 +00002257
2258# if defined(VGP_x86_linux)
2259 iters = 5;
2260# elif defined(VGP_amd64_linux)
2261 iters = 10;
2262# elif defined(VGP_ppc32_linux)
sewardjd714d2e2005-07-08 18:24:04 +00002263 iters = 5;
sewardj8211a572005-06-23 21:37:47 +00002264# else
2265# error "Unknown plat"
2266# endif
2267
2268 iters *= 1000*1000*1000;
2269 for (q = 0; q < iters; q++)
2270 ;
nethercote71980f02004-01-24 18:18:54 +00002271 }
2272
sewardjb5d320c2005-03-13 18:57:15 +00002273 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002274 // Search for file descriptors that are inherited from our parent
2275 // p: process_cmd_line_options [for VG_(clo_track_fds)]
2276 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002277 if (VG_(clo_track_fds)) {
2278 VG_(debugLog)(1, "main", "Init preopened fds\n");
nethercote71980f02004-01-24 18:18:54 +00002279 VG_(init_preopened_fds)();
sewardj1fbc1a52005-04-25 02:05:54 +00002280 }
nethercote71980f02004-01-24 18:18:54 +00002281
2282 //--------------------------------------------------------------
sewardj45f4e7c2005-09-27 19:20:21 +00002283 // Load debug info for the existing segments.
2284 // p: setup_code_redirect_table [so that redirs can be recorded]
2285 // p: mallocfree
2286 // p: probably: setup fds and process CLOs, so that logging works
2287 //--------------------------------------------------------------
2288 VG_(debugLog)(1, "main", "Load initial debug info\n");
2289 { Addr* seg_starts;
2290 Int n_seg_starts;
2291
2292 seg_starts = get_seg_starts( &n_seg_starts );
2293 vg_assert(seg_starts && n_seg_starts > 0);
2294
2295 /* show them all to the debug info reader */
2296 for (i = 0; i < n_seg_starts; i++)
2297 VG_(di_notify_mmap)( seg_starts[i] );
2298
2299 VG_(free)( seg_starts );
2300 }
2301
2302 //--------------------------------------------------------------
2303 // Tell aspacem of ownership change of the asm helpers, so that
2304 // m_translate allows them to be translated. However, only do this
2305 // after the initial debug info read, since making a hole in the
2306 // address range for the stage2 binary confuses the debug info reader.
2307 // p: aspacem
2308 //--------------------------------------------------------------
2309 { Bool change_ownership_v_c_OK;
2310 Addr co_start = VG_PGROUNDDN( (Addr)&VG_(trampoline_stuff_start) );
2311 Addr co_endPlus = VG_PGROUNDUP( (Addr)&VG_(trampoline_stuff_end) );
2312 VG_(debugLog)(1,"redir",
2313 "transfer ownership V -> C of 0x%llx .. 0x%llx\n",
2314 (ULong)co_start, (ULong)co_endPlus-1 );
2315
2316 change_ownership_v_c_OK
2317 = VG_(am_change_ownership_v_to_c)( co_start, co_endPlus - co_start );
2318 vg_assert(change_ownership_v_c_OK);
2319 }
2320
2321 //--------------------------------------------------------------
2322 // Tell the tool about the initial client memory permissions
2323 // p: aspacem
2324 // p: mallocfree
2325 // p: setup_client_stack
2326 // p: setup_client_dataseg
2327 //--------------------------------------------------------------
2328 VG_(debugLog)(1, "main", "Tell tool about initial permissions\n");
2329 { Addr* seg_starts;
2330 Int n_seg_starts;
2331 NSegment* seg;
2332
2333 seg_starts = get_seg_starts( &n_seg_starts );
2334 vg_assert(seg_starts && n_seg_starts > 0);
2335
2336 /* show interesting ones to the tool */
2337 for (i = 0; i < n_seg_starts; i++) {
2338 seg = VG_(am_find_nsegment)( seg_starts[i] );
2339 vg_assert(seg);
2340 if (seg->kind == SkFileC || seg->kind == SkAnonC) {
2341 VG_(debugLog)(2, "main",
2342 "tell tool about %010lx-%010lx %c%c%c\n",
2343 seg->start, seg->end,
2344 seg->hasR ? 'r' : '-',
2345 seg->hasW ? 'w' : '-',
2346 seg->hasX ? 'x' : '-' );
2347 VG_TRACK( new_mem_startup, seg->start, seg->end+1-seg->start,
2348 seg->hasR, seg->hasW, seg->hasX );
2349 }
2350 }
2351
2352 VG_(free)( seg_starts );
2353
2354 /* Also do the initial stack permissions. */
2355 seg = VG_(am_find_nsegment)( initial_client_SP );
2356 vg_assert(seg);
2357 vg_assert(seg->kind == SkAnonC);
2358 vg_assert(initial_client_SP >= seg->start);
2359 vg_assert(initial_client_SP <= seg->end);
2360
2361 /* Stuff below the initial SP is unaddressable. */
2362 /* NB: shouldn't this take into account the VG_STACK_REDZONE_SZB
2363 bytes below SP? */
2364 VG_TRACK( die_mem_stack, seg->start, initial_client_SP - seg->start );
2365 VG_(debugLog)(2, "main", "mark stack inaccessible %010lx-%010lx\n",
2366 seg->start, initial_client_SP-1 );
2367
2368 /* Also the assembly helpers. */
2369 VG_TRACK( new_mem_startup,
2370 (Addr)&VG_(trampoline_stuff_start),
2371 &VG_(trampoline_stuff_end) - &VG_(trampoline_stuff_start),
2372 False, /* readable? */
2373 False, /* writable? */
2374 True /* executable? */ );
2375 }
2376
2377 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002378 // Initialise the scheduler
nethercote71980f02004-01-24 18:18:54 +00002379 // p: setup_file_descriptors() [else VG_(safe_fd)() breaks]
sewardj45f4e7c2005-09-27 19:20:21 +00002380 // p: setup_client_stack
nethercote71980f02004-01-24 18:18:54 +00002381 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002382 VG_(debugLog)(1, "main", "Initialise scheduler\n");
sewardj45f4e7c2005-09-27 19:20:21 +00002383 { NSegment* seg = VG_(am_find_nsegment)( initial_client_SP );
2384 vg_assert(seg);
2385 vg_assert(seg->kind == SkAnonC);
2386 vg_assert(initial_client_SP >= seg->start);
2387 vg_assert(initial_client_SP <= seg->end);
2388 VG_(scheduler_init)( seg->end, clstack_max_size );
2389 }
nethercote71980f02004-01-24 18:18:54 +00002390
2391 //--------------------------------------------------------------
sewardjb5f6f512005-03-10 23:59:00 +00002392 // Initialise the pthread model
2393 // p: ?
sewardj2a99cf62004-11-24 10:44:19 +00002394 // load_client() [for 'client_eip']
2395 // setup_client_stack() [for 'sp_at_startup']
2396 // setup_scheduler() [for the rest of state 1 stuff]
2397 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002398 VG_(debugLog)(1, "main", "Initialise thread 1's state\n");
sewardj45f4e7c2005-09-27 19:20:21 +00002399 init_thread1state( initial_client_IP, initial_client_SP,
2400 &VG_(threads)[1].arch);
njnea4b28c2004-11-30 16:04:58 +00002401
sewardj2a99cf62004-11-24 10:44:19 +00002402 //--------------------------------------------------------------
sewardj39b88fb2005-03-12 15:16:07 +00002403 // Initialise the pthread model
2404 // p: ?
nethercote71980f02004-01-24 18:18:54 +00002405 //--------------------------------------------------------------
sewardjb5f6f512005-03-10 23:59:00 +00002406 //if (VG_(clo_model_pthreads))
2407 // VG_(pthread_init)();
nethercote71980f02004-01-24 18:18:54 +00002408
2409 //--------------------------------------------------------------
2410 // Initialise the signal handling subsystem
sewardjb5f6f512005-03-10 23:59:00 +00002411 // p: n/a
nethercote71980f02004-01-24 18:18:54 +00002412 //--------------------------------------------------------------
2413 // Nb: temporarily parks the saved blocking-mask in saved_sigmask.
sewardj1fbc1a52005-04-25 02:05:54 +00002414 VG_(debugLog)(1, "main", "Initialise signal management\n");
nethercote71980f02004-01-24 18:18:54 +00002415 VG_(sigstartup_actions)();
2416
2417 //--------------------------------------------------------------
2418 // Perhaps we're profiling Valgrind?
2419 // p: process_cmd_line_options() [for VG_(clo_profile)]
2420 // p: others?
2421 //
2422 // XXX: this seems to be broken? It always says the tool wasn't built
2423 // for profiling; vg_profile.c's functions don't seem to be overriding
2424 // vg_dummy_profile.c's?
2425 //
2426 // XXX: want this as early as possible. Looking for --profile
sewardj45f4e7c2005-09-27 19:20:21 +00002427 // in get_helprequest_and_toolname() could get it earlier.
nethercote71980f02004-01-24 18:18:54 +00002428 //--------------------------------------------------------------
2429 if (VG_(clo_profile))
njn31066fd2005-03-26 00:42:02 +00002430 VG_(init_profiling)();
nethercote71980f02004-01-24 18:18:54 +00002431
2432 VGP_PUSHCC(VgpStartup);
2433
2434 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002435 // Read suppression file
2436 // p: process_cmd_line_options() [for VG_(clo_suppressions)]
2437 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002438 if (VG_(needs).core_errors || VG_(needs).tool_errors) {
2439 VG_(debugLog)(1, "main", "Load suppressions\n");
nethercote71980f02004-01-24 18:18:54 +00002440 VG_(load_suppressions)();
sewardj1fbc1a52005-04-25 02:05:54 +00002441 }
nethercote71980f02004-01-24 18:18:54 +00002442
2443 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002444 // Setup pointercheck
njn04e16982005-05-31 00:23:43 +00002445 // p: layout_remaining_space() [for VG_(client_{base,end})]
nethercote71980f02004-01-24 18:18:54 +00002446 // p: process_cmd_line_options() [for VG_(clo_pointercheck)]
2447 //--------------------------------------------------------------
sewardj45f4e7c2005-09-27 19:20:21 +00002448 //if (VG_(clo_pointercheck))
2449 // VG_(clo_pointercheck) =
2450 // VG_(setup_pointercheck)( VG_(client_base), VG_(client_end));
nethercote71980f02004-01-24 18:18:54 +00002451
nethercote71980f02004-01-24 18:18:54 +00002452 //--------------------------------------------------------------
rjwalsh0140af52005-06-04 20:42:33 +00002453 // register client stack
2454 //--------------------------------------------------------------
njn945ed2e2005-06-24 03:28:30 +00002455 VG_(clstk_id) = VG_(register_stack)(VG_(clstk_base), VG_(clstk_end));
rjwalsh0140af52005-06-04 20:42:33 +00002456
2457 //--------------------------------------------------------------
sewardj45f4e7c2005-09-27 19:20:21 +00002458 // Show the address space state so far
2459 //--------------------------------------------------------------
2460 VG_(debugLog)(1, "main", "\n");
2461 VG_(debugLog)(1, "main", "\n");
2462 VG_(am_show_nsegments)(1,"Memory layout at client startup");
2463 VG_(debugLog)(1, "main", "\n");
2464 VG_(debugLog)(1, "main", "\n");
2465
2466 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002467 // Run!
2468 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002469 VGP_POPCC(VgpStartup);
nethercote71980f02004-01-24 18:18:54 +00002470
sewardj71bc3cb2005-05-19 00:25:45 +00002471 if (VG_(clo_xml)) {
sewardj68cde6f2005-07-19 12:17:51 +00002472 HChar buf[50];
2473 VG_(ctime)(buf);
sewardj753673f2005-08-09 22:03:08 +00002474 VG_(message)(Vg_UserMsg, "<status>\n"
2475 " <state>RUNNING</state>\n"
2476 " <time>%t</time>\n"
2477 "</status>",
2478 buf);
sewardj71bc3cb2005-05-19 00:25:45 +00002479 VG_(message)(Vg_UserMsg, "");
2480 }
2481
sewardj1fbc1a52005-04-25 02:05:54 +00002482 VG_(debugLog)(1, "main", "Running thread 1\n");
sewardj1d887112005-05-30 21:44:08 +00002483 /* As a result of the following call, the last thread standing
2484 eventually winds up running VG_(shutdown_actions_NORETURN) just
2485 below. */
njnaf839f52005-06-23 03:27:57 +00002486 VG_(main_thread_wrapper_NORETURN)(1);
nethercote71980f02004-01-24 18:18:54 +00002487
sewardj1d887112005-05-30 21:44:08 +00002488 /*NOTREACHED*/
2489 vg_assert(0);
sewardjb5f6f512005-03-10 23:59:00 +00002490}
2491
2492
njn9cb54ac2005-06-12 04:19:17 +00002493/* Final clean-up before terminating the process.
2494 Clean up the client by calling __libc_freeres() (if requested)
2495 This is Linux-specific?
2496*/
2497static void final_tidyup(ThreadId tid)
2498{
njnbc6d84d2005-06-19 18:58:03 +00002499 Addr __libc_freeres_wrapper;
2500
njn9cb54ac2005-06-12 04:19:17 +00002501 vg_assert(VG_(is_running_thread)(tid));
2502
njnbc6d84d2005-06-19 18:58:03 +00002503 if ( !VG_(needs).libc_freeres ||
2504 !VG_(clo_run_libc_freeres) ||
2505 0 == (__libc_freeres_wrapper = VG_(get_libc_freeres_wrapper)()) )
njn9cb54ac2005-06-12 04:19:17 +00002506 return; /* can't/won't do it */
2507
2508 if (VG_(clo_verbosity) > 2 ||
2509 VG_(clo_trace_syscalls) ||
2510 VG_(clo_trace_sched))
2511 VG_(message)(Vg_DebugMsg,
2512 "Caught __NR_exit; running __libc_freeres()");
2513
2514 /* point thread context to point to libc_freeres_wrapper */
njnf536bbb2005-06-13 04:21:38 +00002515 VG_(set_IP)(tid, __libc_freeres_wrapper);
njn9cb54ac2005-06-12 04:19:17 +00002516 // XXX should we use a special stack?
2517
2518 /* Block all blockable signals by copying the real block state into
2519 the thread's block state*/
2520 VG_(sigprocmask)(VKI_SIG_BLOCK, NULL, &VG_(threads)[tid].sig_mask);
2521 VG_(threads)[tid].tmp_sig_mask = VG_(threads)[tid].sig_mask;
2522
2523 /* and restore handlers to default */
2524 VG_(set_default_handler)(VKI_SIGSEGV);
2525 VG_(set_default_handler)(VKI_SIGBUS);
2526 VG_(set_default_handler)(VKI_SIGILL);
2527 VG_(set_default_handler)(VKI_SIGFPE);
2528
2529 // We were exiting, so assert that...
2530 vg_assert(VG_(is_exiting)(tid));
2531 // ...but now we're not again
2532 VG_(threads)[tid].exitreason = VgSrc_None;
2533
2534 // run until client thread exits - ideally with LIBC_FREERES_DONE,
2535 // but exit/exitgroup/signal will do
2536 VG_(scheduler)(tid);
2537
2538 vg_assert(VG_(is_exiting)(tid));
2539}
2540
sewardjb5f6f512005-03-10 23:59:00 +00002541/* Do everything which needs doing when the last thread exits */
sewardj1d887112005-05-30 21:44:08 +00002542void VG_(shutdown_actions_NORETURN) ( ThreadId tid,
2543 VgSchedReturnCode tids_schedretcode )
sewardjb5f6f512005-03-10 23:59:00 +00002544{
sewardj1d887112005-05-30 21:44:08 +00002545 VG_(debugLog)(1, "main", "entering VG_(shutdown_actions_NORETURN)\n");
2546
2547 vg_assert( VG_(count_living_threads)() == 1 );
sewardjb5f6f512005-03-10 23:59:00 +00002548 vg_assert(VG_(is_running_thread)(tid));
2549
2550 // Wait for all other threads to exit.
njn7b85dd52005-06-12 17:26:29 +00002551 VG_(reap_threads)(tid);
sewardjb5f6f512005-03-10 23:59:00 +00002552
2553 VG_(clo_model_pthreads) = False;
2554
2555 // Clean the client up before the final report
njn9cb54ac2005-06-12 04:19:17 +00002556 final_tidyup(tid);
sewardjb5f6f512005-03-10 23:59:00 +00002557
2558 // OK, done
2559 VG_(exit_thread)(tid);
2560
2561 /* should be no threads left */
2562 vg_assert(VG_(count_living_threads)() == 0);
2563
2564 VG_(threads)[tid].status = VgTs_Empty;
nethercote71980f02004-01-24 18:18:54 +00002565 //--------------------------------------------------------------
2566 // Finalisation: cleanup, messages, etc. Order no so important, only
2567 // affects what order the messages come.
2568 //--------------------------------------------------------------
2569 if (VG_(clo_verbosity) > 0)
2570 VG_(message)(Vg_UserMsg, "");
2571
sewardj71bc3cb2005-05-19 00:25:45 +00002572 if (VG_(clo_xml)) {
sewardj68cde6f2005-07-19 12:17:51 +00002573 HChar buf[50];
sewardj9f297ca2005-05-20 02:29:52 +00002574 if (VG_(needs).core_errors || VG_(needs).tool_errors) {
2575 VG_(show_error_counts_as_XML)();
2576 VG_(message)(Vg_UserMsg, "");
2577 }
sewardj68cde6f2005-07-19 12:17:51 +00002578 VG_(ctime)(buf);
sewardj753673f2005-08-09 22:03:08 +00002579 VG_(message)(Vg_UserMsg, "<status>\n"
2580 " <state>FINISHED</state>\n"
2581 " <time>%t</time>\n"
2582 "</status>",
2583 buf);
sewardj71bc3cb2005-05-19 00:25:45 +00002584 VG_(message)(Vg_UserMsg, "");
2585 }
2586
nethercote71980f02004-01-24 18:18:54 +00002587 /* Print out file descriptor summary and stats. */
2588 if (VG_(clo_track_fds))
nethercote3a42fb82004-08-03 18:08:50 +00002589 VG_(show_open_fds)();
nethercote71980f02004-01-24 18:18:54 +00002590
njn95ec8702004-11-22 16:46:13 +00002591 if (VG_(needs).core_errors || VG_(needs).tool_errors)
nethercote71980f02004-01-24 18:18:54 +00002592 VG_(show_all_errors)();
2593
njn51d827b2005-05-09 01:02:08 +00002594 VG_TDICT_CALL(tool_fini, 0/*exitcode*/);
nethercote71980f02004-01-24 18:18:54 +00002595
sewardj71bc3cb2005-05-19 00:25:45 +00002596 if (VG_(clo_xml)) {
2597 VG_(message)(Vg_UserMsg, "");
2598 VG_(message)(Vg_UserMsg, "</valgrindoutput>");
2599 VG_(message)(Vg_UserMsg, "");
2600 }
2601
nethercote885dd912004-08-03 23:14:00 +00002602 VG_(sanity_check_general)( True /*include expensive checks*/ );
nethercote71980f02004-01-24 18:18:54 +00002603
2604 if (VG_(clo_verbosity) > 1)
nethercote3a42fb82004-08-03 18:08:50 +00002605 print_all_stats();
nethercote71980f02004-01-24 18:18:54 +00002606
nethercote71980f02004-01-24 18:18:54 +00002607 if (VG_(clo_profile))
njn31066fd2005-03-26 00:42:02 +00002608 VG_(done_profiling)();
njn2025cf92005-06-26 20:44:48 +00002609
2610 if (VG_(clo_profile_flags) > 0) {
2611 #define N_MAX 100
2612 BBProfEntry tops[N_MAX];
2613 ULong score_total = VG_(get_BB_profile) (tops, N_MAX);
2614 show_BB_profile(tops, N_MAX, score_total);
2615 }
sewardjfa8ec112005-01-19 11:55:34 +00002616
sewardj8b635a42004-11-22 19:01:47 +00002617 /* Print Vex storage stats */
sewardjbf426512005-01-17 18:35:30 +00002618 if (0)
2619 LibVEX_ShowAllocStats();
sewardj1d887112005-05-30 21:44:08 +00002620
njn8aa35852005-06-10 22:59:56 +00002621 /* Ok, finally exit in the os-specific way, according to the scheduler's
2622 return code. In short, if the (last) thread exited by calling
2623 sys_exit, do likewise; if the (last) thread stopped due to a fatal
2624 signal, terminate the entire system with that same fatal signal. */
2625 VG_(debugLog)(1, "core_os",
njn7b85dd52005-06-12 17:26:29 +00002626 "VG_(terminate_NORETURN)(tid=%lld)\n", (ULong)tid);
njn8aa35852005-06-10 22:59:56 +00002627
2628 vg_assert(VG_(count_living_threads)() == 0);
2629
2630 switch (tids_schedretcode) {
2631 case VgSrc_ExitSyscall: /* the normal way out */
2632 VG_(exit)( VG_(threads)[tid].os_state.exitcode );
2633 /* NOT ALIVE HERE! */
2634 VG_(core_panic)("entered the afterlife in main() -- ExitSyscall");
2635 break; /* what the hell :) */
2636
2637 case VgSrc_FatalSig:
2638 /* We were killed by a fatal signal, so replicate the effect */
2639 vg_assert(VG_(threads)[tid].os_state.fatalsig != 0);
2640 VG_(kill_self)(VG_(threads)[tid].os_state.fatalsig);
2641 VG_(core_panic)("main(): signal was supposed to be fatal");
2642 break;
2643
2644 default:
2645 VG_(core_panic)("main(): unexpected scheduler return code");
2646 }
njne96be672005-05-08 19:08:54 +00002647}
sewardj8b635a42004-11-22 19:01:47 +00002648
sewardj45f4e7c2005-09-27 19:20:21 +00002649
2650/*====================================================================*/
2651/*=== Getting to main() alive ===*/
2652/*====================================================================*/
2653
2654/* If linking of the final executables is done with glibc present,
2655 then Valgrind starts at main() above as usual, and all of the
2656 following code is irrelevant.
2657
2658 However, this is not the intended mode of use. The plan is to
2659 avoid linking against glibc, by giving gcc the flags
2660 -nodefaultlibs -lgcc -nostartfiles at startup.
2661
2662 From this derive two requirements:
2663
2664 1. gcc may emit calls to memcpy and memset to deal with structure
2665 assignments etc. Since we have chosen to ignore all the
2666 "normal" supporting libraries, we have to provide our own
2667 implementations of them. No problem.
2668
2669 2. We have to provide a symbol "_start", to which the kernel
2670 hands control at startup. Hence the code below.
2671*/
2672
2673/* ---------------- Requirement 1 ---------------- */
2674
2675void* memcpy(void *dest, const void *src, size_t n);
2676void* memcpy(void *dest, const void *src, size_t n) {
2677 return VG_(memcpy)(dest,src,n);
2678}
2679void* memset(void *s, int c, size_t n);
2680void* memset(void *s, int c, size_t n) {
2681 return VG_(memset)(s,c,n);
2682}
2683
2684/* ---------------- Requirement 2 ---------------- */
2685
2686/* Glibc's sysdeps/i386/elf/start.S has the following gem of a
2687 comment, which explains how the stack looks right at process start
2688 (when _start is jumped to). Hence _start passes %esp to
2689 _start_in_C, which extracts argc/argv/envp and starts up
2690 correctly. */
2691
2692/* This is the canonical entry point, usually the first thing in the text
2693 segment. The SVR4/i386 ABI (pages 3-31, 3-32) says that when the entry
2694 point runs, most registers' values are unspecified, except for:
2695
2696 %edx Contains a function pointer to be registered with `atexit'.
2697 This is how the dynamic linker arranges to have DT_FINI
2698 functions called for shared libraries that have been loaded
2699 before this code runs.
2700
2701 %esp The stack contains the arguments and environment:
2702 0(%esp) argc
2703 4(%esp) argv[0]
2704 ...
2705 (4*argc)(%esp) NULL
2706 (4*(argc+1))(%esp) envp[0]
2707 ...
2708 NULL
2709*/
2710
2711/* The kernel hands control to _start, which extracts the initial
2712 stack pointer and calls onwards to _start_in_C. This also switches the new stack. */
2713#if defined(VGP_x86_linux)
2714asm("\n"
2715 "\t.globl _start\n"
2716 "\t.type _start,@function\n"
2717 "_start:\n"
2718 /* set up the new stack in %eax */
sewardjfdf91b42005-09-28 00:53:09 +00002719 "\tmovl $vgPlain_interim_stack, %eax\n"
sewardj45f4e7c2005-09-27 19:20:21 +00002720 "\taddl $"VG_STRINGIFY(VG_STACK_GUARD_SZB)", %eax\n"
2721 "\taddl $"VG_STRINGIFY(VG_STACK_ACTIVE_SZB)", %eax\n"
2722 "\tsubl $16, %eax\n"
2723 "\tandl $~15, %eax\n"
2724 /* install it, and collect the original one */
2725 "\txchgl %eax, %esp\n"
2726 /* call _start_in_C, passing it the startup %esp */
2727 "\tpushl %eax\n"
2728 "\tcall _start_in_C\n"
2729 "\thlt\n"
2730);
2731#elif defined(VGP_amd64_linux)
2732asm("\n"
2733 "\t.globl _start\n"
2734 "\t.type _start,@function\n"
2735 "_start:\n"
2736 /* set up the new stack in %rdi */
sewardjfdf91b42005-09-28 00:53:09 +00002737 "\tmovq $vgPlain_interim_stack, %rdi\n"
sewardj45f4e7c2005-09-27 19:20:21 +00002738 "\taddq $"VG_STRINGIFY(VG_STACK_GUARD_SZB)", %rdi\n"
2739 "\taddq $"VG_STRINGIFY(VG_STACK_ACTIVE_SZB)", %rdi\n"
2740 "\tandq $~15, %rdi\n"
2741 /* install it, and collect the original one */
2742 "\txchgq %rdi, %rsp\n"
2743 /* call _start_in_C, passing it the startup %rsp */
2744 "\tcall _start_in_C\n"
2745 "\thlt\n"
2746);
2747#else
2748#error "_start: needs implementation on this platform"
2749#endif
2750
2751/* Avoid compiler warnings: this fn _is_ used, but labelling it
2752 'static' causes gcc to complain it isn't. */
2753void _start_in_C ( UWord* pArgc );
2754void _start_in_C ( UWord* pArgc )
2755{
2756 Int r;
2757 Word argc = pArgc[0];
2758 HChar** argv = (HChar**)&pArgc[1];
2759 HChar** envp = (HChar**)&pArgc[1+argc+1];
sewardjfdf91b42005-09-28 00:53:09 +00002760 sp_at_startup = (Addr)pArgc;
sewardj45f4e7c2005-09-27 19:20:21 +00002761 r = main( (Int)argc, argv, envp );
2762 VG_(exit)(r);
2763}
2764
sewardjde4a1d02002-03-22 01:27:54 +00002765/*--------------------------------------------------------------------*/
njn04e16982005-05-31 00:23:43 +00002766/*--- end ---*/
sewardjde4a1d02002-03-22 01:27:54 +00002767/*--------------------------------------------------------------------*/