blob: 2d57828a7285bc561d41d156c218ee9ec8cbb71a [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"
njnaf1d7df2005-06-11 01:31:52 +000047#include "pub_core_mallocfree.h"
njn20242342005-05-16 23:31:24 +000048#include "pub_core_options.h"
njn31513b42005-06-01 03:09:59 +000049#include "pub_core_profile.h"
sewardjfdf91b42005-09-28 00:53:09 +000050#include "pub_core_debuginfo.h"
njnd1af0032005-05-29 17:01:48 +000051#include "pub_core_redir.h"
njnc7561b92005-06-19 01:24:32 +000052#include "pub_core_scheduler.h"
njn0c246472005-05-31 01:00:08 +000053#include "pub_core_signals.h"
njn2025cf92005-06-26 20:44:48 +000054#include "pub_core_stacks.h" // For VG_(register_stack)
njnc1b01812005-06-17 22:19:06 +000055#include "pub_core_syswrap.h"
sewardjfdf91b42005-09-28 00:53:09 +000056#include "pub_core_translate.h" // For VG_(translate)
njn43b9a8a2005-05-10 04:37:01 +000057#include "pub_core_tooliface.h"
njna7598f62005-06-18 03:27:58 +000058#include "pub_core_trampoline.h"
njn8bddf582005-05-13 23:40:55 +000059#include "pub_core_transtab.h"
njn08a2e172005-06-21 22:47:54 +000060#include "pub_core_ume.h"
nethercote71980f02004-01-24 18:18:54 +000061
sewardjb5f6f512005-03-10 23:59:00 +000062
nethercote71980f02004-01-24 18:18:54 +000063/*====================================================================*/
64/*=== Counters, for profiling purposes only ===*/
65/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +000066
nethercote3a42fb82004-08-03 18:08:50 +000067static void print_all_stats ( void )
nethercote71980f02004-01-24 18:18:54 +000068{
nethercote92e7b7f2004-08-07 17:52:25 +000069 VG_(print_tt_tc_stats)();
nethercote844e7122004-08-02 15:27:22 +000070 VG_(print_scheduler_stats)();
njn9271cbc2005-03-13 05:38:25 +000071 VG_(print_ExeContext_stats)();
72
nethercote3a42fb82004-08-03 18:08:50 +000073 // Memory stats
nethercote885dd912004-08-03 23:14:00 +000074 if (VG_(clo_verbosity) > 2) {
nethercote3a42fb82004-08-03 18:08:50 +000075 VG_(message)(Vg_DebugMsg, "");
76 VG_(message)(Vg_DebugMsg,
77 "------ Valgrind's internal memory use stats follow ------" );
nethercote885dd912004-08-03 23:14:00 +000078 VG_(sanity_check_malloc_all)();
njn11adeb22005-07-03 20:22:39 +000079 VG_(message)(Vg_DebugMsg, "------" );
nethercote3a42fb82004-08-03 18:08:50 +000080 VG_(print_all_arena_stats)();
nethercote885dd912004-08-03 23:14:00 +000081 VG_(message)(Vg_DebugMsg, "");
nethercote3a42fb82004-08-03 18:08:50 +000082 }
nethercote71980f02004-01-24 18:18:54 +000083}
84
85
86/*====================================================================*/
sewardj5f229e22005-09-28 01:36:01 +000087/*=== Setting up the client's environment ===*/
nethercote71980f02004-01-24 18:18:54 +000088/*====================================================================*/
89
nethercote71980f02004-01-24 18:18:54 +000090/* Prepare the client's environment. This is basically a copy of our
91 environment, except:
sewardj45f4e7c2005-09-27 19:20:21 +000092
njn9d5564d2005-09-29 00:25:07 +000093 LD_PRELOAD=$VALGRIND_LIB/vgpreload_core.so:
sewardj45f4e7c2005-09-27 19:20:21 +000094 ($VALGRIND_LIB/vgpreload_TOOL.so:)?
95 $LD_PRELOAD
nethercote71980f02004-01-24 18:18:54 +000096
sewardjb5f6f512005-03-10 23:59:00 +000097 If this is missing, then it is added.
nethercote71980f02004-01-24 18:18:54 +000098
sewardj45f4e7c2005-09-27 19:20:21 +000099 Also, remove any binding for VALGRIND_LAUNCHER=. The client should
100 not be able to see this.
nethercote71980f02004-01-24 18:18:54 +0000101
102 If this needs to handle any more variables it should be hacked
sewardj45f4e7c2005-09-27 19:20:21 +0000103 into something table driven. The copy is VG_(malloc)'d space.
104*/
105static HChar** setup_client_env ( HChar** origenv, const HChar* toolname)
nethercote71980f02004-01-24 18:18:54 +0000106{
njn9d5564d2005-09-29 00:25:07 +0000107 HChar* preload_core_so = "vgpreload_core.so";
sewardj45f4e7c2005-09-27 19:20:21 +0000108 HChar* ld_preload = "LD_PRELOAD=";
109 HChar* v_launcher = VALGRIND_LAUNCHER "=";
110 Int ld_preload_len = VG_(strlen)( ld_preload );
111 Int v_launcher_len = VG_(strlen)( v_launcher );
112 Bool ld_preload_done = False;
113 Int vglib_len = VG_(strlen)(VG_(libdir));
nethercote71980f02004-01-24 18:18:54 +0000114
sewardj45f4e7c2005-09-27 19:20:21 +0000115 HChar** cpp;
116 HChar** ret;
tom60a4b0b2005-10-12 10:45:27 +0000117 HChar* preload_tool_path;
sewardj45f4e7c2005-09-27 19:20:21 +0000118 Int envc, i;
nethercote71980f02004-01-24 18:18:54 +0000119
sewardj45f4e7c2005-09-27 19:20:21 +0000120 /* Alloc space for the vgpreload_core.so path and vgpreload_<tool>.so
121 paths. We might not need the space for vgpreload_<tool>.so, but it
122 doesn't hurt to over-allocate briefly. The 16s are just cautious
123 slop. */
124 Int preload_core_path_len = vglib_len + sizeof(preload_core_so) + 16;
125 Int preload_tool_path_len = vglib_len + VG_(strlen)(toolname) + 16;
126 Int preload_string_len = preload_core_path_len + preload_tool_path_len;
127 HChar* preload_string = VG_(malloc)(preload_string_len);
128 vg_assert(preload_string);
129
130 /* Determine if there's a vgpreload_<tool>.so file, and setup
131 preload_string. */
132 preload_tool_path = VG_(malloc)(preload_tool_path_len);
133 vg_assert(preload_tool_path);
134 VG_(snprintf)(preload_tool_path, preload_tool_path_len,
135 "%s/vgpreload_%s.so", VG_(libdir), toolname);
136 if (VG_(access)(preload_tool_path, True/*r*/, False/*w*/, False/*x*/) == 0) {
137 VG_(snprintf)(preload_string, preload_string_len, "%s/%s:%s",
138 VG_(libdir), preload_core_so, preload_tool_path);
139 } else {
140 VG_(snprintf)(preload_string, preload_string_len, "%s/%s",
141 VG_(libdir), preload_core_so);
142 }
143 VG_(free)(preload_tool_path);
144
sewardja48a4932005-09-29 11:09:56 +0000145 VG_(debugLog)(2, "main", "preload_string:\n");
146 VG_(debugLog)(2, "main", " \"%s\"\n", preload_string);
sewardj45f4e7c2005-09-27 19:20:21 +0000147
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;
tom60a4b0b2005-10-12 10:45:27 +0000420 Bool ok;
nethercote71980f02004-01-24 18:18:54 +0000421
sewardj45f4e7c2005-09-27 19:20:21 +0000422 vg_assert(VG_IS_PAGE_ALIGNED(anon_size));
423 vg_assert(VG_IS_PAGE_ALIGNED(resvn_size));
424 vg_assert(VG_IS_PAGE_ALIGNED(anon_start));
425 vg_assert(VG_IS_PAGE_ALIGNED(resvn_start));
426 vg_assert(resvn_start == clstack_end + 1 - clstack_max_size);
nethercote71980f02004-01-24 18:18:54 +0000427
sewardj45f4e7c2005-09-27 19:20:21 +0000428# ifdef ENABLE_INNER
429 inner_HACK = 1024*1024; // create 1M non-fault-extending stack
430# endif
nethercote71980f02004-01-24 18:18:54 +0000431
sewardj45f4e7c2005-09-27 19:20:21 +0000432 if (0)
433 VG_(printf)("%p 0x%x %p 0x%x\n",
434 resvn_start, resvn_size, anon_start, anon_size);
nethercote71980f02004-01-24 18:18:54 +0000435
sewardj45f4e7c2005-09-27 19:20:21 +0000436 /* Create a shrinkable reservation followed by an anonymous
437 segment. Together these constitute a growdown stack. */
tom60a4b0b2005-10-12 10:45:27 +0000438 ok = VG_(am_create_reservation)(
439 resvn_start,
440 resvn_size -inner_HACK,
441 SmUpper,
442 anon_size +inner_HACK
443 );
sewardj45f4e7c2005-09-27 19:20:21 +0000444 vg_assert(ok);
445 /* allocate a stack - mmap enough space for the stack */
446 res = VG_(am_mmap_anon_fixed_client)(
447 anon_start -inner_HACK,
448 anon_size +inner_HACK,
449 VKI_PROT_READ|VKI_PROT_WRITE|VKI_PROT_EXEC
450 );
451 vg_assert(!res.isError);
452 }
453
454 /* ==================== create client stack ==================== */
455
456 ptr = (Addr*)client_SP;
457
458 /* --- client argc --- */
459 *ptr++ = argc + (have_exename ? 1 : 0);
460
461 /* --- client argv --- */
nethercoted6a56872004-07-26 15:32:47 +0000462 if (info->interp_name) {
nethercotea3c3cf22004-11-01 18:38:00 +0000463 *ptr++ = (Addr)copy_str(&strtab, info->interp_name);
sewardj45f4e7c2005-09-27 19:20:21 +0000464 VG_(free)(info->interp_name);
nethercote71980f02004-01-24 18:18:54 +0000465 }
nethercoted6a56872004-07-26 15:32:47 +0000466 if (info->interp_args) {
nethercotea3c3cf22004-11-01 18:38:00 +0000467 *ptr++ = (Addr)copy_str(&strtab, info->interp_args);
sewardj45f4e7c2005-09-27 19:20:21 +0000468 VG_(free)(info->interp_args);
nethercote71980f02004-01-24 18:18:54 +0000469 }
sewardj45f4e7c2005-09-27 19:20:21 +0000470
471 if (have_exename)
472 *ptr++ = (Addr)copy_str(&strtab, VG_(args_the_exename));
473
474 for (i = 0; i < VG_(args_for_client).used; i++) {
475 *ptr++ = (Addr)copy_str(&strtab, VG_(args_for_client).strs[i]);
nethercote71980f02004-01-24 18:18:54 +0000476 }
477 *ptr++ = 0;
478
479 /* --- envp --- */
480 VG_(client_envp) = (Char **)ptr;
481 for (cpp = orig_envp; cpp && *cpp; ptr++, cpp++)
nethercotea3c3cf22004-11-01 18:38:00 +0000482 *ptr = (Addr)copy_str(&strtab, *cpp);
nethercote71980f02004-01-24 18:18:54 +0000483 *ptr++ = 0;
484
485 /* --- auxv --- */
486 auxv = (struct ume_auxv *)ptr;
487 *client_auxv = (UInt *)auxv;
488
sewardjfdf91b42005-09-28 00:53:09 +0000489# if defined(VGP_ppc32_linux)
cerion85665ca2005-06-20 15:51:07 +0000490 auxv[0].a_type = AT_IGNOREPPC;
491 auxv[0].u.a_val = AT_IGNOREPPC;
492 auxv[1].a_type = AT_IGNOREPPC;
493 auxv[1].u.a_val = AT_IGNOREPPC;
494 auxv += 2;
sewardjfdf91b42005-09-28 00:53:09 +0000495# endif
cerion85665ca2005-06-20 15:51:07 +0000496
nethercote71980f02004-01-24 18:18:54 +0000497 for (; orig_auxv->a_type != AT_NULL; auxv++, orig_auxv++) {
sewardjfdf91b42005-09-28 00:53:09 +0000498
nethercote71980f02004-01-24 18:18:54 +0000499 /* copy the entry... */
500 *auxv = *orig_auxv;
501
sewardjfdf91b42005-09-28 00:53:09 +0000502 /* ...and fix up / examine the copy */
nethercote71980f02004-01-24 18:18:54 +0000503 switch(auxv->a_type) {
nethercote71980f02004-01-24 18:18:54 +0000504
sewardjfdf91b42005-09-28 00:53:09 +0000505 case AT_IGNORE:
506 case AT_PHENT:
507 case AT_PAGESZ:
508 case AT_FLAGS:
509 case AT_NOTELF:
510 case AT_UID:
511 case AT_EUID:
512 case AT_GID:
513 case AT_EGID:
514 case AT_CLKTCK:
515 case AT_FPUCW:
516 case AT_SYSINFO:
517 /* All these are pointerless, so we don't need to do
518 anything about them. */
519 break;
nethercote71980f02004-01-24 18:18:54 +0000520
sewardjfdf91b42005-09-28 00:53:09 +0000521 case AT_PHDR:
522 if (info->phdr == 0)
523 auxv->a_type = AT_IGNORE;
524 else
525 auxv->u.a_val = info->phdr;
526 break;
nethercote71980f02004-01-24 18:18:54 +0000527
sewardjfdf91b42005-09-28 00:53:09 +0000528 case AT_PHNUM:
529 if (info->phdr == 0)
530 auxv->a_type = AT_IGNORE;
531 else
532 auxv->u.a_val = info->phnum;
533 break;
nethercote71980f02004-01-24 18:18:54 +0000534
sewardjfdf91b42005-09-28 00:53:09 +0000535 case AT_BASE:
536 auxv->u.a_val = info->interp_base;
537 break;
nethercote71980f02004-01-24 18:18:54 +0000538
sewardjfdf91b42005-09-28 00:53:09 +0000539 case AT_PLATFORM:
540 /* points to a platform description string */
541 auxv->u.a_ptr = copy_str(&strtab, orig_auxv->u.a_ptr);
542 break;
nethercote71980f02004-01-24 18:18:54 +0000543
sewardjfdf91b42005-09-28 00:53:09 +0000544 case AT_ENTRY:
545 auxv->u.a_val = info->entry;
546 break;
nethercote71980f02004-01-24 18:18:54 +0000547
sewardjfdf91b42005-09-28 00:53:09 +0000548 case AT_HWCAP:
549# if defined(VGP_ppc32_linux)
550 /* Acquire altivecness info */
sewardja48a4932005-09-29 11:09:56 +0000551 VG_(debugLog)(2, "main", "PPC32 hwcaps: 0x%x\n",
sewardjfdf91b42005-09-28 00:53:09 +0000552 (UInt)auxv->u.a_val);
553 if (auxv->u.a_val & 0x10000000)
554 VG_(have_altivec_ppc32) = 1;
sewardja48a4932005-09-29 11:09:56 +0000555 VG_(debugLog)(2, "main", "PPC32 AltiVec support: %u\n",
sewardjfdf91b42005-09-28 00:53:09 +0000556 VG_(have_altivec_ppc32));
557# endif
558 break;
nethercote71980f02004-01-24 18:18:54 +0000559
sewardjfdf91b42005-09-28 00:53:09 +0000560 case AT_DCACHEBSIZE:
561 case AT_ICACHEBSIZE:
562 case AT_UCACHEBSIZE:
563# if defined(VGP_ppc32_linux)
564 /* acquire cache info */
565 if (auxv->u.a_val > 0) {
566 VG_(cache_line_size_ppc32) = auxv->u.a_val;
sewardja48a4932005-09-29 11:09:56 +0000567 VG_(debugLog)(2, "main",
sewardjfdf91b42005-09-28 00:53:09 +0000568 "PPC32 cache line size %u (type %u)\n",
569 (UInt)auxv->u.a_val, (UInt)auxv->a_type );
570 }
571# endif
572 break;
nethercote71980f02004-01-24 18:18:54 +0000573
sewardjfdf91b42005-09-28 00:53:09 +0000574# if defined(VGP_ppc32_linux)
575 case AT_IGNOREPPC:
576 break;
577# endif
578
579 case AT_SECURE:
580 /* If this is 1, then it means that this program is
581 running suid, and therefore the dynamic linker should
582 be careful about LD_PRELOAD, etc. However, since
583 stage1 (the thing the kernel actually execve's) should
584 never be SUID, and we need LD_PRELOAD to work for the
585 client, we set AT_SECURE to 0. */
586 auxv->u.a_val = 0;
587 break;
588
589# if !defined(VGP_ppc32_linux)
590 case AT_SYSINFO_EHDR:
591 /* Trash this, because we don't reproduce it */
592 auxv->a_type = AT_IGNORE;
593 break;
594# endif
595
596 default:
597 /* stomp out anything we don't know about */
598 VG_(debugLog)(2, "main",
599 "stomping auxv entry %lld\n",
600 (ULong)auxv->a_type);
601 auxv->a_type = AT_IGNORE;
602 break;
nethercote71980f02004-01-24 18:18:54 +0000603 }
604 }
605 *auxv = *orig_auxv;
606 vg_assert(auxv->a_type == AT_NULL);
607
608 vg_assert((strtab-stringbase) == stringsize);
609
sewardj45f4e7c2005-09-27 19:20:21 +0000610 /* client_SP is pointing at client's argc/argv */
nethercote5ee67ca2004-06-22 14:00:09 +0000611
sewardj45f4e7c2005-09-27 19:20:21 +0000612 if (0) VG_(printf)("startup SP = %p\n", client_SP);
613 return client_SP;
nethercote71980f02004-01-24 18:18:54 +0000614}
615
sewardj45f4e7c2005-09-27 19:20:21 +0000616
617/* Allocate the client data segment. It is an expandable anonymous
618 mapping abutting a shrinkable reservation of size max_dseg_size.
619 The data segment starts at VG_(brk_base), which is page-aligned,
620 and runs up to VG_(brk_limit), which isn't. */
621
622static void setup_client_dataseg ( SizeT max_size )
623{
624 Bool ok;
625 SysRes sres;
626 Addr anon_start = VG_(brk_base);
627 SizeT anon_size = VKI_PAGE_SIZE;
628 Addr resvn_start = anon_start + anon_size;
629 SizeT resvn_size = max_size - anon_size;
630
631 vg_assert(VG_IS_PAGE_ALIGNED(anon_size));
632 vg_assert(VG_IS_PAGE_ALIGNED(resvn_size));
633 vg_assert(VG_IS_PAGE_ALIGNED(anon_start));
634 vg_assert(VG_IS_PAGE_ALIGNED(resvn_start));
635
636 /* Because there's been no brk activity yet: */
637 vg_assert(VG_(brk_base) == VG_(brk_limit));
638
639 /* Try to create the data seg and associated reservation where
640 VG_(brk_base) says. */
641 ok = VG_(am_create_reservation)(
642 resvn_start,
643 resvn_size,
644 SmLower,
645 anon_size
646 );
647
648 if (!ok) {
649 /* Hmm, that didn't work. Well, let aspacem suggest an address
650 it likes better, and try again with that. */
651 anon_start = VG_(am_get_advisory_client_simple)
652 ( 0/*floating*/, anon_size+resvn_size, &ok );
653 if (ok) {
654 resvn_start = anon_start + anon_size;
655 ok = VG_(am_create_reservation)(
656 resvn_start,
657 resvn_size,
658 SmLower,
659 anon_size
660 );
661 if (ok)
662 VG_(brk_base) = VG_(brk_limit) = anon_start;
663 }
664 /* that too might have failed, but if it has, we're hosed: there
665 is no Plan C. */
666 }
667 vg_assert(ok);
668
669 sres = VG_(am_mmap_anon_fixed_client)(
670 anon_start,
671 anon_size,
tom0d159442005-11-02 13:02:40 +0000672 VKI_PROT_READ|VKI_PROT_WRITE
sewardj45f4e7c2005-09-27 19:20:21 +0000673 );
674 vg_assert(!sres.isError);
675 vg_assert(sres.val == anon_start);
676}
677
678
nethercote71980f02004-01-24 18:18:54 +0000679/*====================================================================*/
680/*=== Find executable ===*/
681/*====================================================================*/
682
sewardjfdf91b42005-09-28 00:53:09 +0000683/* Scan a colon-separated list, and call a function on each element.
684 The string must be mutable, because we insert a temporary '\0', but
685 the string will end up unmodified. (*func) should return True if it
686 doesn't need to see any more.
687
688 This routine will return True if (*func) returns True and False if
689 it reaches the end of the list without that happening.
690*/
691static Bool scan_colsep(char *colsep, Bool (*func)(const char *))
692{
693 char *cp, *entry;
694 int end;
695
696 if (colsep == NULL ||
697 *colsep == '\0')
698 return False;
699
700 entry = cp = colsep;
701
702 do {
703 end = (*cp == '\0');
704
705 if (*cp == ':' || *cp == '\0') {
706 char save = *cp;
707
708 *cp = '\0';
709 if ((*func)(entry)) {
710 *cp = save;
711 return True;
712 }
713 *cp = save;
714 entry = cp+1;
715 }
716 cp++;
717 } while(!end);
718
719 return False;
720}
721
sewardj45f4e7c2005-09-27 19:20:21 +0000722/* Need a static copy because can't use dynamic mem allocation yet */
njn73750612005-10-14 03:11:30 +0000723static HChar executable_name_in [VKI_PATH_MAX];
724static HChar executable_name_out[VKI_PATH_MAX];
thughes4ad52d02004-06-27 17:37:21 +0000725
sewardj45f4e7c2005-09-27 19:20:21 +0000726static Bool match_executable(const char *entry)
727{
njn73750612005-10-14 03:11:30 +0000728 HChar buf[VG_(strlen)(entry) + VG_(strlen)(executable_name_in) + 3];
thughes4ad52d02004-06-27 17:37:21 +0000729
njn73750612005-10-14 03:11:30 +0000730 /* empty PATH element means '.' */
thughes4ad52d02004-06-27 17:37:21 +0000731 if (*entry == '\0')
732 entry = ".";
733
njn73750612005-10-14 03:11:30 +0000734 VG_(snprintf)(buf, sizeof(buf), "%s/%s", entry, executable_name_in);
735
736 // Don't match directories
737 if (VG_(is_dir)(buf))
738 return False;
739
740 // If we match an executable, we choose that immediately. If we find a
741 // matching non-executable we remember it but keep looking for an
742 // matching executable later in the path.
sewardj45f4e7c2005-09-27 19:20:21 +0000743 if (VG_(access)(buf, True/*r*/, False/*w*/, True/*x*/) == 0) {
njn73750612005-10-14 03:11:30 +0000744 VG_(strncpy)( executable_name_out, buf, VKI_PATH_MAX-1 );
745 executable_name_out[VKI_PATH_MAX-1] = 0;
746 return True; // Stop looking
747 } else if (VG_(access)(buf, True/*r*/, False/*w*/, False/*x*/) == 0
748 && VG_STREQ(executable_name_out, ""))
749 {
750 VG_(strncpy)( executable_name_out, buf, VKI_PATH_MAX-1 );
751 executable_name_out[VKI_PATH_MAX-1] = 0;
752 return False; // Keep looking
753 } else {
754 return False; // Keep looking
thughes4ad52d02004-06-27 17:37:21 +0000755 }
thughes4ad52d02004-06-27 17:37:21 +0000756}
757
njn73750612005-10-14 03:11:30 +0000758// Returns NULL if it wasn't found.
sewardj45f4e7c2005-09-27 19:20:21 +0000759static HChar* find_executable ( HChar* exec )
nethercote71980f02004-01-24 18:18:54 +0000760{
761 vg_assert(NULL != exec);
njn73750612005-10-14 03:11:30 +0000762 if (VG_(strchr)(exec, '/')) {
763 // Has a '/' - use the name as is
764 VG_(strncpy)( executable_name_out, exec, VKI_PATH_MAX-1 );
765 } else {
766 // No '/' - we need to search the path
sewardj03d8aa82005-10-14 11:25:49 +0000767 HChar* path;
njn73750612005-10-14 03:11:30 +0000768 VG_(strncpy)( executable_name_in, exec, VKI_PATH_MAX-1 );
769 VG_(memset) ( executable_name_out, 0, VKI_PATH_MAX );
sewardj03d8aa82005-10-14 11:25:49 +0000770 path = VG_(getenv)("PATH");
thughes4ad52d02004-06-27 17:37:21 +0000771 scan_colsep(path, match_executable);
nethercote71980f02004-01-24 18:18:54 +0000772 }
njn73750612005-10-14 03:11:30 +0000773 return VG_STREQ(executable_name_out, "") ? NULL : executable_name_out;
nethercote71980f02004-01-24 18:18:54 +0000774}
775
776
777/*====================================================================*/
nethercotef4928da2004-06-15 10:54:40 +0000778/*=== Command line errors ===*/
779/*====================================================================*/
780
njnbe9b47b2005-05-15 16:22:58 +0000781static void revert_to_stderr ( void )
nethercotef4928da2004-06-15 10:54:40 +0000782{
njnbe9b47b2005-05-15 16:22:58 +0000783 vg_assert( !VG_(logging_to_socket) );
nethercotef8548672004-06-21 12:42:35 +0000784 VG_(clo_log_fd) = 2; /* stderr */
nethercotef4928da2004-06-15 10:54:40 +0000785}
786
787void VG_(bad_option) ( Char* opt )
788{
njnbe9b47b2005-05-15 16:22:58 +0000789 revert_to_stderr();
njn02bc4b82005-05-15 17:28:26 +0000790 VG_(printf)("valgrind: Bad option '%s'; aborting.\n", opt);
nethercotef4928da2004-06-15 10:54:40 +0000791 VG_(printf)("valgrind: Use --help for more information.\n");
792 VG_(exit)(1);
793}
794
nethercotef4928da2004-06-15 10:54:40 +0000795static void missing_prog ( void )
796{
njnbe9b47b2005-05-15 16:22:58 +0000797 revert_to_stderr();
nethercotef4928da2004-06-15 10:54:40 +0000798 VG_(printf)("valgrind: no program specified\n");
799 VG_(printf)("valgrind: Use --help for more information.\n");
800 VG_(exit)(1);
801}
802
803static void config_error ( Char* msg )
804{
njnbe9b47b2005-05-15 16:22:58 +0000805 revert_to_stderr();
nethercotef4928da2004-06-15 10:54:40 +0000806 VG_(printf)("valgrind: Startup or configuration error:\n %s\n", msg);
807 VG_(printf)("valgrind: Unable to start up properly. Giving up.\n");
808 VG_(exit)(1);
809}
810
811
nethercote71980f02004-01-24 18:18:54 +0000812/*====================================================================*/
813/*=== Loading the client ===*/
814/*====================================================================*/
815
sewardj45f4e7c2005-09-27 19:20:21 +0000816/* Load the client whose name is VG_(argv_the_exename). */
nethercote71980f02004-01-24 18:18:54 +0000817
sewardj45f4e7c2005-09-27 19:20:21 +0000818static void load_client ( /*OUT*/struct exeinfo* info,
819 /*OUT*/Addr* client_eip)
820{
njn73750612005-10-14 03:11:30 +0000821 HChar* exe_name;
sewardj45f4e7c2005-09-27 19:20:21 +0000822 Int ret;
823 SysRes res;
824
825 vg_assert( VG_(args_the_exename) != NULL);
njn73750612005-10-14 03:11:30 +0000826 exe_name = find_executable( VG_(args_the_exename) );
827
828 if (!exe_name) {
829 VG_(printf)("valgrind: %s: command not found\n", VG_(args_the_exename));
830 VG_(exit)(127); // 127 is Posix NOTFOUND
831 }
sewardj45f4e7c2005-09-27 19:20:21 +0000832
833 VG_(memset)(info, 0, sizeof(*info));
nethercote71980f02004-01-24 18:18:54 +0000834 info->exe_base = VG_(client_base);
835 info->exe_end = VG_(client_end);
nethercote71980f02004-01-24 18:18:54 +0000836
njn73750612005-10-14 03:11:30 +0000837 ret = VG_(do_exec)(exe_name, info);
838
839 // The client was successfully loaded! Continue.
nethercote71980f02004-01-24 18:18:54 +0000840
sewardj45f4e7c2005-09-27 19:20:21 +0000841 /* Get hold of a file descriptor which refers to the client
842 executable. This is needed for attaching to GDB. */
njn73750612005-10-14 03:11:30 +0000843 res = VG_(open)(exe_name, VKI_O_RDONLY, VKI_S_IRUSR);
sewardj45f4e7c2005-09-27 19:20:21 +0000844 if (!res.isError)
845 VG_(cl_exec_fd) = res.val;
846
nethercote71980f02004-01-24 18:18:54 +0000847 /* Copy necessary bits of 'info' that were filled in */
848 *client_eip = info->init_eip;
sewardj45f4e7c2005-09-27 19:20:21 +0000849 VG_(brk_base) = VG_(brk_limit) = VG_PGROUNDUP(info->brkbase);
nethercote71980f02004-01-24 18:18:54 +0000850}
851
nethercote969ecf12004-10-13 17:29:01 +0000852
sewardj71bc3cb2005-05-19 00:25:45 +0000853/*====================================================================*/
854/*=== Command-line: variables, processing, etc ===*/
855/*====================================================================*/
856
857// See pub_{core,tool}_options.h for explanations of all these.
858
sewardj45f4e7c2005-09-27 19:20:21 +0000859static void usage_NORETURN ( Bool debug_help )
njn7cf0bd32002-06-08 13:36:03 +0000860{
njn25e49d8e72002-09-23 09:36:25 +0000861 Char* usage1 =
nethercote71980f02004-01-24 18:18:54 +0000862"usage: valgrind --tool=<toolname> [options] prog-and-args\n"
njn25e49d8e72002-09-23 09:36:25 +0000863"\n"
nethercote2b0793f2003-12-02 10:41:18 +0000864" common user options for all Valgrind tools, with defaults in [ ]:\n"
sewardjb5f6f512005-03-10 23:59:00 +0000865" --tool=<name> use the Valgrind tool named <name> [memcheck]\n"
nethercotea76368b2004-06-16 11:56:29 +0000866" -h --help show this message\n"
nethercote6c999f22004-01-31 22:55:15 +0000867" --help-debug show this message, plus debugging options\n"
njn25e49d8e72002-09-23 09:36:25 +0000868" --version show version\n"
njn25e49d8e72002-09-23 09:36:25 +0000869" -q --quiet run silently; only print error msgs\n"
870" -v --verbose be more verbose, incl counts of errors\n"
nethercote77eba602003-11-13 17:35:04 +0000871" --trace-children=no|yes Valgrind-ise child processes? [no]\n"
nethercote0d588502004-06-21 13:27:11 +0000872" --track-fds=no|yes track open file descriptors? [no]\n"
thughes6233a382004-08-21 11:10:44 +0000873" --time-stamp=no|yes add timestamps to log messages? [no]\n"
njnce545552005-07-25 22:36:52 +0000874" --log-fd=<number> log messages to file descriptor [2=stderr]\n"
875" --log-file=<file> log messages to <file>.pid<pid>\n"
876" --log-file-exactly=<file> log messages to <file>\n"
877" --log-file-qualifier=<VAR> incorporate $VAR in logfile name [none]\n"
878" --log-socket=ipaddr:port log messages to socket ipaddr:port\n"
nethercote2b0793f2003-12-02 10:41:18 +0000879"\n"
880" uncommon user options for all Valgrind tools:\n"
nethercote0d588502004-06-21 13:27:11 +0000881" --run-libc-freeres=no|yes free up glibc memory at exit? [yes]\n"
sewardj19617ae2005-10-20 01:09:57 +0000882" --simulation-hints=hint1,hint2,... known hints:\n"
883" lax-ioctls, enable-outer [none]\n"
sewardjb1131a82005-03-19 15:12:21 +0000884" --show-emwarns=no|yes show warnings about emulation limits? [no]\n"
sewardj6c3a2192005-07-24 07:00:45 +0000885" --smc-check=none|stack|all checks for self-modifying code: none,\n"
886" only for code found in stacks, or all [stack]\n"
njn25e49d8e72002-09-23 09:36:25 +0000887"\n"
nethercote2b0793f2003-12-02 10:41:18 +0000888" user options for Valgrind tools that report errors:\n"
njnce545552005-07-25 22:36:52 +0000889" --xml=yes all output is in XML (Memcheck/Nulgrind only)\n"
njnc8ec9f82005-07-20 03:03:28 +0000890" --xml-user-comment=STR copy STR verbatim to XML output\n"
nethercote2b0793f2003-12-02 10:41:18 +0000891" --demangle=no|yes automatically demangle C++ names? [yes]\n"
njn20b4a152005-10-19 22:39:40 +0000892" --num-callers=<number> show <number> callers in stack traces [12]\n"
nethercote2b0793f2003-12-02 10:41:18 +0000893" --error-limit=no|yes stop showing new errors if too many? [yes]\n"
894" --show-below-main=no|yes continue stack traces below main() [no]\n"
895" --suppressions=<filename> suppress errors described in <filename>\n"
sewardjd153fae2005-01-10 17:24:47 +0000896" --gen-suppressions=no|yes|all print suppressions for errors? [no]\n"
nethercote04d0fbc2004-01-26 16:48:06 +0000897" --db-attach=no|yes start debugger when errors detected? [no]\n"
898" --db-command=<command> command to start debugger [gdb -nw %%f %%p]\n"
899" --input-fd=<number> file descriptor for input [0=stdin]\n"
sewardj97724e52005-04-02 23:40:59 +0000900" --max-stackframe=<number> assume stack switch for SP changes larger\n"
901" than <number> bytes [2000000]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +0000902"\n";
njn7cf0bd32002-06-08 13:36:03 +0000903
njn25e49d8e72002-09-23 09:36:25 +0000904 Char* usage2 =
905"\n"
nethercote2b0793f2003-12-02 10:41:18 +0000906" debugging options for all Valgrind tools:\n"
njn25e49d8e72002-09-23 09:36:25 +0000907" --sanity-level=<number> level of sanity checking to do [1]\n"
nethercote137bc552003-11-14 17:47:54 +0000908" --profile=no|yes profile? (tool must be built for it) [no]\n"
sewardjfa8ec112005-01-19 11:55:34 +0000909" --trace-flags=<XXXXXXXX> show generated code? (X = 0|1) [00000000]\n"
910" --profile-flags=<XXXXXXXX> ditto, but for profiling (X = 0|1) [00000000]\n"
njn20b4a152005-10-19 22:39:40 +0000911" --trace-notbelow=<number> only show BBs above <number> [0]\n"
njn25e49d8e72002-09-23 09:36:25 +0000912" --trace-syscalls=no|yes show all system calls? [no]\n"
913" --trace-signals=no|yes show signal handling details? [no]\n"
914" --trace-symtab=no|yes show symbol table details? [no]\n"
sewardjce058b02005-05-01 08:55:38 +0000915" --trace-cfi=no|yes show call-frame-info details? [no]\n"
njn25e49d8e72002-09-23 09:36:25 +0000916" --trace-sched=no|yes show thread scheduler details? [no]\n"
jsgf855d93d2003-10-13 22:26:55 +0000917" --wait-for-gdb=yes|no pause on startup to wait for gdb attach\n"
sewardjb5f6f512005-03-10 23:59:00 +0000918#if 0
919" --model-pthreads=yes|no model the pthreads library [no]\n"
920#endif
921" --command-line-only=no|yes only use command line options [no]\n"
njn613812e2005-03-11 04:57:30 +0000922"\n"
923" --vex-iropt-verbosity 0 .. 9 [0]\n"
924" --vex-iropt-level 0 .. 2 [2]\n"
925" --vex-iropt-precise-memory-exns [no]\n"
sewardj8b635a42004-11-22 19:01:47 +0000926" --vex-iropt-unroll-thresh 0 .. 400 [120]\n"
927" --vex-guest-max-insns 1 .. 100 [50]\n"
928" --vex-guest-chase-thresh 0 .. 99 [10]\n"
929"\n"
sewardjfa8ec112005-01-19 11:55:34 +0000930" --trace-flags and --profile-flags values (omit the middle space):\n"
sewardj2a99cf62004-11-24 10:44:19 +0000931" 1000 0000 show conversion into IR\n"
932" 0100 0000 show after initial opt\n"
933" 0010 0000 show after instrumentation\n"
934" 0001 0000 show after second opt\n"
935" 0000 1000 show after tree building\n"
936" 0000 0100 show selecting insns\n"
937" 0000 0010 show after reg-alloc\n"
938" 0000 0001 show final assembly\n"
939"\n"
nethercote2b0793f2003-12-02 10:41:18 +0000940" debugging options for Valgrind tools that report errors\n"
941" --dump-error=<number> show translation for basic block associated\n"
942" with <number>'th error context [0=show none]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +0000943"\n";
njn3e884182003-04-15 13:03:23 +0000944
945 Char* usage3 =
946"\n"
nethercote71980f02004-01-24 18:18:54 +0000947" Extra options read from ~/.valgrindrc, $VALGRIND_OPTS, ./.valgrindrc\n"
njn25e49d8e72002-09-23 09:36:25 +0000948"\n"
njn53612422005-03-12 16:22:54 +0000949" Valgrind is Copyright (C) 2000-2005 Julian Seward et al.\n"
njn25e49d8e72002-09-23 09:36:25 +0000950" and licensed under the GNU General Public License, version 2.\n"
951" Bug reports, feedback, admiration, abuse, etc, to: %s.\n"
njnd04b7c62002-10-03 14:05:52 +0000952"\n"
nethercote137bc552003-11-14 17:47:54 +0000953" Tools are copyright and licensed by their authors. See each\n"
954" tool's start-up message for more information.\n"
njn25e49d8e72002-09-23 09:36:25 +0000955"\n";
njn7cf0bd32002-06-08 13:36:03 +0000956
njnbe9b47b2005-05-15 16:22:58 +0000957 // Ensure the message goes to stdout
958 VG_(clo_log_fd) = 1;
959 vg_assert( !VG_(logging_to_socket) );
960
fitzhardinge98abfc72003-12-16 02:05:15 +0000961 VG_(printf)(usage1);
962 if (VG_(details).name) {
963 VG_(printf)(" user options for %s:\n", VG_(details).name);
fitzhardinge98abfc72003-12-16 02:05:15 +0000964 if (VG_(needs).command_line_options)
njn51d827b2005-05-09 01:02:08 +0000965 VG_TDICT_CALL(tool_print_usage);
fitzhardinge98abfc72003-12-16 02:05:15 +0000966 else
967 VG_(printf)(" (none)\n");
968 }
nethercote6c999f22004-01-31 22:55:15 +0000969 if (debug_help) {
970 VG_(printf)(usage2);
fitzhardinge98abfc72003-12-16 02:05:15 +0000971
nethercote6c999f22004-01-31 22:55:15 +0000972 if (VG_(details).name) {
973 VG_(printf)(" debugging options for %s:\n", VG_(details).name);
974
975 if (VG_(needs).command_line_options)
njn51d827b2005-05-09 01:02:08 +0000976 VG_TDICT_CALL(tool_print_debug_usage);
nethercote6c999f22004-01-31 22:55:15 +0000977 else
978 VG_(printf)(" (none)\n");
979 }
fitzhardinge98abfc72003-12-16 02:05:15 +0000980 }
nethercote421281e2003-11-20 16:20:55 +0000981 VG_(printf)(usage3, VG_BUGS_TO);
nethercotef4928da2004-06-15 10:54:40 +0000982 VG_(exit)(0);
njn7cf0bd32002-06-08 13:36:03 +0000983}
sewardjde4a1d02002-03-22 01:27:54 +0000984
sewardjde4a1d02002-03-22 01:27:54 +0000985
sewardj45f4e7c2005-09-27 19:20:21 +0000986/* Peer at previously set up VG_(args_for_valgrind) and extract any
987 request for help and also the tool name. */
988
989static void get_helprequest_and_toolname ( Int* need_help, HChar** tool )
990{
991 UInt i;
992 HChar* str;
sewardj8b635a42004-11-22 19:01:47 +0000993
nethercote71980f02004-01-24 18:18:54 +0000994 /* parse the options we have (only the options we care about now) */
sewardj45f4e7c2005-09-27 19:20:21 +0000995 for (i = 0; i < VG_(args_for_valgrind).used; i++) {
nethercote71980f02004-01-24 18:18:54 +0000996
sewardj45f4e7c2005-09-27 19:20:21 +0000997 str = VG_(args_for_valgrind).strs[i];
998 vg_assert(str);
nethercote71980f02004-01-24 18:18:54 +0000999
sewardj45f4e7c2005-09-27 19:20:21 +00001000 if (VG_STREQ(str, "--version")) {
njn2e9f3f32005-10-26 16:17:46 +00001001 // Ensure the version string goes to stdout
1002 VG_(clo_log_fd) = 1;
sewardj45f4e7c2005-09-27 19:20:21 +00001003 VG_(printf)("valgrind-" VERSION "\n");
1004 VG_(exit)(0);
1005
1006 } else if (VG_CLO_STREQ(str, "--help") ||
1007 VG_CLO_STREQ(str, "-h")) {
nethercote6c999f22004-01-31 22:55:15 +00001008 *need_help = 1;
1009
sewardj45f4e7c2005-09-27 19:20:21 +00001010 } else if (VG_CLO_STREQ(str, "--help-debug")) {
nethercote6c999f22004-01-31 22:55:15 +00001011 *need_help = 2;
nethercote71980f02004-01-24 18:18:54 +00001012
sewardj45f4e7c2005-09-27 19:20:21 +00001013 // The tool has already been determined, but we need to know the name
1014 // here.
1015 } else if (VG_CLO_STREQN(7, str, "--tool=")) {
1016 *tool = &str[7];
nethercote71980f02004-01-24 18:18:54 +00001017 }
1018 }
nethercote71980f02004-01-24 18:18:54 +00001019}
1020
sewardj45f4e7c2005-09-27 19:20:21 +00001021static Bool process_cmd_line_options( UInt* client_auxv, const char* toolname )
nethercote71980f02004-01-24 18:18:54 +00001022{
sewardj92645592005-07-23 09:18:34 +00001023 SysRes sres;
1024 Int i, eventually_log_fd;
1025 Int toolname_len = VG_(strlen)(toolname);
njnbe9b47b2005-05-15 16:22:58 +00001026 enum {
1027 VgLogTo_Fd,
1028 VgLogTo_File,
1029 VgLogTo_FileExactly,
1030 VgLogTo_Socket
1031 } log_to = VgLogTo_Fd; // Where is logging output to be sent?
sewardjde4a1d02002-03-22 01:27:54 +00001032
nethercotee1730692003-11-20 10:38:07 +00001033 /* log to stderr by default, but usage message goes to stdout */
nethercotef8548672004-06-21 12:42:35 +00001034 eventually_log_fd = 2;
sewardjde4a1d02002-03-22 01:27:54 +00001035
sewardj19d81412002-06-03 01:10:40 +00001036 /* Check for sane path in ./configure --prefix=... */
fitzhardinge98abfc72003-12-16 02:05:15 +00001037 if (VG_LIBDIR[0] != '/')
sewardj19d81412002-06-03 01:10:40 +00001038 config_error("Please use absolute paths in "
1039 "./configure --prefix=... or --libdir=...");
sewardj38170912002-05-10 21:07:22 +00001040
sewardj45f4e7c2005-09-27 19:20:21 +00001041 for (i = 0; i < VG_(args_for_valgrind).used; i++) {
nethercote71980f02004-01-24 18:18:54 +00001042
sewardj45f4e7c2005-09-27 19:20:21 +00001043 HChar* arg = VG_(args_for_valgrind).strs[i];
1044 HChar* colon = arg;
nethercote71980f02004-01-24 18:18:54 +00001045
thughes3bfd5a02004-07-18 08:05:44 +00001046 /* Look for a colon in the switch name */
1047 while (*colon && *colon != ':' && *colon != '=')
1048 colon++;
nethercote71980f02004-01-24 18:18:54 +00001049
1050 /* Look for matching "--toolname:foo" */
thughes3bfd5a02004-07-18 08:05:44 +00001051 if (*colon == ':') {
nethercote71980f02004-01-24 18:18:54 +00001052 if (VG_CLO_STREQN(2, arg, "--") &&
1053 VG_CLO_STREQN(toolname_len, arg+2, toolname) &&
1054 VG_CLO_STREQN(1, arg+2+toolname_len, ":"))
1055 {
1056 // prefix matches, convert "--toolname:foo" to "--foo"
1057 if (0)
1058 VG_(printf)("tool-specific arg: %s\n", arg);
sewardj45f4e7c2005-09-27 19:20:21 +00001059 arg = VG_(strdup)(arg + toolname_len + 1);
nethercote71980f02004-01-24 18:18:54 +00001060 arg[0] = '-';
1061 arg[1] = '-';
1062
1063 } else {
1064 // prefix doesn't match, skip to next arg
1065 continue;
1066 }
1067 }
1068
fitzhardinge98abfc72003-12-16 02:05:15 +00001069 /* Ignore these options - they've already been handled */
njn45270a22005-03-27 01:00:11 +00001070 if (VG_CLO_STREQN( 7, arg, "--tool=")) goto skip_arg;
njn45270a22005-03-27 01:00:11 +00001071 if (VG_CLO_STREQN(20, arg, "--command-line-only=")) goto skip_arg;
fitzhardinge98abfc72003-12-16 02:05:15 +00001072
njn45270a22005-03-27 01:00:11 +00001073 if ( VG_CLO_STREQ(arg, "--")) goto skip_arg;
nethercote27fec902004-06-16 21:26:32 +00001074
nethercote71980f02004-01-24 18:18:54 +00001075 else if (VG_CLO_STREQ(arg, "-v") ||
1076 VG_CLO_STREQ(arg, "--verbose"))
sewardjde4a1d02002-03-22 01:27:54 +00001077 VG_(clo_verbosity)++;
nethercote27fec902004-06-16 21:26:32 +00001078
nethercote71980f02004-01-24 18:18:54 +00001079 else if (VG_CLO_STREQ(arg, "-q") ||
1080 VG_CLO_STREQ(arg, "--quiet"))
sewardjde4a1d02002-03-22 01:27:54 +00001081 VG_(clo_verbosity)--;
1082
sewardj1cf558c2005-04-25 01:36:56 +00001083 else if (VG_CLO_STREQ(arg, "-d")) {
1084 /* do nothing */
1085 }
1086
sewardj71bc3cb2005-05-19 00:25:45 +00001087 else VG_BOOL_CLO(arg, "--xml", VG_(clo_xml))
njn45270a22005-03-27 01:00:11 +00001088 else VG_BOOL_CLO(arg, "--db-attach", VG_(clo_db_attach))
1089 else VG_BOOL_CLO(arg, "--demangle", VG_(clo_demangle))
1090 else VG_BOOL_CLO(arg, "--error-limit", VG_(clo_error_limit))
njn45270a22005-03-27 01:00:11 +00001091 else VG_BOOL_CLO(arg, "--show-emwarns", VG_(clo_show_emwarns))
sewardj97724e52005-04-02 23:40:59 +00001092 else VG_NUM_CLO (arg, "--max-stackframe", VG_(clo_max_stackframe))
njn45270a22005-03-27 01:00:11 +00001093 else VG_BOOL_CLO(arg, "--profile", VG_(clo_profile))
1094 else VG_BOOL_CLO(arg, "--run-libc-freeres", VG_(clo_run_libc_freeres))
1095 else VG_BOOL_CLO(arg, "--show-below-main", VG_(clo_show_below_main))
1096 else VG_BOOL_CLO(arg, "--time-stamp", VG_(clo_time_stamp))
1097 else VG_BOOL_CLO(arg, "--track-fds", VG_(clo_track_fds))
1098 else VG_BOOL_CLO(arg, "--trace-children", VG_(clo_trace_children))
1099 else VG_BOOL_CLO(arg, "--trace-sched", VG_(clo_trace_sched))
1100 else VG_BOOL_CLO(arg, "--trace-signals", VG_(clo_trace_signals))
1101 else VG_BOOL_CLO(arg, "--trace-symtab", VG_(clo_trace_symtab))
sewardjce058b02005-05-01 08:55:38 +00001102 else VG_BOOL_CLO(arg, "--trace-cfi", VG_(clo_trace_cfi))
njn45270a22005-03-27 01:00:11 +00001103 else VG_BOOL_CLO(arg, "--trace-redir", VG_(clo_trace_redir))
1104 else VG_BOOL_CLO(arg, "--trace-syscalls", VG_(clo_trace_syscalls))
1105 else VG_BOOL_CLO(arg, "--trace-pthreads", VG_(clo_trace_pthreads))
1106 else VG_BOOL_CLO(arg, "--wait-for-gdb", VG_(clo_wait_for_gdb))
1107 else VG_BOOL_CLO(arg, "--model-pthreads", VG_(clo_model_pthreads))
sewardj72f98ff2002-06-13 17:23:38 +00001108
njn45270a22005-03-27 01:00:11 +00001109 else VG_STR_CLO (arg, "--db-command", VG_(clo_db_command))
sewardj19617ae2005-10-20 01:09:57 +00001110 else VG_STR_CLO (arg, "--simulation-hints", VG_(clo_simulation_hints))
sewardjde4a1d02002-03-22 01:27:54 +00001111
njn45270a22005-03-27 01:00:11 +00001112 else VG_NUM_CLO (arg, "--dump-error", VG_(clo_dump_error))
1113 else VG_NUM_CLO (arg, "--input-fd", VG_(clo_input_fd))
1114 else VG_NUM_CLO (arg, "--sanity-level", VG_(clo_sanity_level))
1115 else VG_BNUM_CLO(arg, "--num-callers", VG_(clo_backtrace_size), 1,
1116 VG_DEEPEST_BACKTRACE)
sewardjde4a1d02002-03-22 01:27:54 +00001117
sewardj6c3a2192005-07-24 07:00:45 +00001118 else if (VG_CLO_STREQ(arg, "--smc-check=none"))
1119 VG_(clo_smc_check) = Vg_SmcNone;
1120 else if (VG_CLO_STREQ(arg, "--smc-check=stack"))
1121 VG_(clo_smc_check) = Vg_SmcStack;
1122 else if (VG_CLO_STREQ(arg, "--smc-check=all"))
1123 VG_(clo_smc_check) = Vg_SmcAll;
sewardj26412bd2005-07-07 10:05:05 +00001124
sewardjce5a5662005-10-06 03:19:49 +00001125 else VG_STR_CLO (arg, "--kernel-variant", VG_(clo_kernel_variant))
1126
njn45270a22005-03-27 01:00:11 +00001127 else VG_BNUM_CLO(arg, "--vex-iropt-verbosity",
sewardj8b635a42004-11-22 19:01:47 +00001128 VG_(clo_vex_control).iropt_verbosity, 0, 10)
njn45270a22005-03-27 01:00:11 +00001129 else VG_BNUM_CLO(arg, "--vex-iropt-level",
sewardj8b635a42004-11-22 19:01:47 +00001130 VG_(clo_vex_control).iropt_level, 0, 2)
njn45270a22005-03-27 01:00:11 +00001131 else VG_BOOL_CLO(arg, "--vex-iropt-precise-memory-exns",
sewardj8b635a42004-11-22 19:01:47 +00001132 VG_(clo_vex_control).iropt_precise_memory_exns)
njn45270a22005-03-27 01:00:11 +00001133 else VG_BNUM_CLO(arg, "--vex-iropt-unroll-thresh",
sewardj8b635a42004-11-22 19:01:47 +00001134 VG_(clo_vex_control).iropt_unroll_thresh, 0, 400)
njn45270a22005-03-27 01:00:11 +00001135 else VG_BNUM_CLO(arg, "--vex-guest-max-insns",
sewardj8b635a42004-11-22 19:01:47 +00001136 VG_(clo_vex_control).guest_max_insns, 1, 100)
njn45270a22005-03-27 01:00:11 +00001137 else VG_BNUM_CLO(arg, "--vex-guest-chase-thresh",
sewardj8b635a42004-11-22 19:01:47 +00001138 VG_(clo_vex_control).guest_chase_thresh, 0, 99)
1139
nethercotef8548672004-06-21 12:42:35 +00001140 else if (VG_CLO_STREQN(9, arg, "--log-fd=")) {
njnbe9b47b2005-05-15 16:22:58 +00001141 log_to = VgLogTo_Fd;
nethercotef8548672004-06-21 12:42:35 +00001142 VG_(clo_log_name) = NULL;
1143 eventually_log_fd = (Int)VG_(atoll)(&arg[9]);
sewardj4cf05692002-10-27 20:28:29 +00001144 }
1145
nethercotef8548672004-06-21 12:42:35 +00001146 else if (VG_CLO_STREQN(11, arg, "--log-file=")) {
njnbe9b47b2005-05-15 16:22:58 +00001147 log_to = VgLogTo_File;
nethercotef8548672004-06-21 12:42:35 +00001148 VG_(clo_log_name) = &arg[11];
sewardj4cf05692002-10-27 20:28:29 +00001149 }
njnd6bc3c32005-03-27 00:44:31 +00001150
sewardjad311162005-07-19 11:25:02 +00001151 else if (VG_CLO_STREQN(11, arg, "--log-file=")) {
1152 log_to = VgLogTo_File;
1153 VG_(clo_log_name) = &arg[11];
1154 }
1155
1156 else if (VG_CLO_STREQN(21, arg, "--log-file-qualifier=")) {
1157 VG_(clo_log_file_qualifier) = &arg[21];
1158 }
1159
sewardj603d4102005-01-11 14:01:02 +00001160 else if (VG_CLO_STREQN(19, arg, "--log-file-exactly=")) {
njnbe9b47b2005-05-15 16:22:58 +00001161 log_to = VgLogTo_FileExactly;
sewardj603d4102005-01-11 14:01:02 +00001162 VG_(clo_log_name) = &arg[19];
1163 }
sewardjde4a1d02002-03-22 01:27:54 +00001164
nethercotef8548672004-06-21 12:42:35 +00001165 else if (VG_CLO_STREQN(13, arg, "--log-socket=")) {
njnbe9b47b2005-05-15 16:22:58 +00001166 log_to = VgLogTo_Socket;
nethercotef8548672004-06-21 12:42:35 +00001167 VG_(clo_log_name) = &arg[13];
sewardj73cf3bc2002-11-03 03:20:15 +00001168 }
1169
sewardj768db0e2005-07-19 14:18:56 +00001170 else if (VG_CLO_STREQN(19, arg, "--xml-user-comment=")) {
1171 VG_(clo_xml_user_comment) = &arg[19];
1172 }
1173
nethercote71980f02004-01-24 18:18:54 +00001174 else if (VG_CLO_STREQN(15, arg, "--suppressions=")) {
sewardjde4a1d02002-03-22 01:27:54 +00001175 if (VG_(clo_n_suppressions) >= VG_CLO_MAX_SFILES) {
njn25e49d8e72002-09-23 09:36:25 +00001176 VG_(message)(Vg_UserMsg, "Too many suppression files specified.");
sewardjde4a1d02002-03-22 01:27:54 +00001177 VG_(message)(Vg_UserMsg,
1178 "Increase VG_CLO_MAX_SFILES and recompile.");
nethercote71980f02004-01-24 18:18:54 +00001179 VG_(bad_option)(arg);
sewardjde4a1d02002-03-22 01:27:54 +00001180 }
nethercote71980f02004-01-24 18:18:54 +00001181 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = &arg[15];
sewardjde4a1d02002-03-22 01:27:54 +00001182 VG_(clo_n_suppressions)++;
1183 }
sewardjde4a1d02002-03-22 01:27:54 +00001184
sewardjfa8ec112005-01-19 11:55:34 +00001185 /* "stuvwxyz" --> stuvwxyz (binary) */
1186 else if (VG_CLO_STREQN(14, arg, "--trace-flags=")) {
1187 Int j;
1188 char* opt = & arg[14];
1189
1190 if (8 != VG_(strlen)(opt)) {
1191 VG_(message)(Vg_UserMsg,
1192 "--trace-flags argument must have 8 digits");
1193 VG_(bad_option)(arg);
1194 }
1195 for (j = 0; j < 8; j++) {
1196 if ('0' == opt[j]) { /* do nothing */ }
1197 else if ('1' == opt[j]) VG_(clo_trace_flags) |= (1 << (7-j));
1198 else {
1199 VG_(message)(Vg_UserMsg, "--trace-flags argument can only "
1200 "contain 0s and 1s");
1201 VG_(bad_option)(arg);
1202 }
1203 }
1204 }
1205
1206 /* "stuvwxyz" --> stuvwxyz (binary) */
1207 else if (VG_CLO_STREQN(16, arg, "--profile-flags=")) {
njn25e49d8e72002-09-23 09:36:25 +00001208 Int j;
nethercote71980f02004-01-24 18:18:54 +00001209 char* opt = & arg[16];
njn25e49d8e72002-09-23 09:36:25 +00001210
sewardj2a99cf62004-11-24 10:44:19 +00001211 if (8 != VG_(strlen)(opt)) {
njn25e49d8e72002-09-23 09:36:25 +00001212 VG_(message)(Vg_UserMsg,
sewardjfa8ec112005-01-19 11:55:34 +00001213 "--profile-flags argument must have 8 digits");
nethercote71980f02004-01-24 18:18:54 +00001214 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001215 }
sewardj8b635a42004-11-22 19:01:47 +00001216 for (j = 0; j < 8; j++) {
njn25e49d8e72002-09-23 09:36:25 +00001217 if ('0' == opt[j]) { /* do nothing */ }
sewardjfa8ec112005-01-19 11:55:34 +00001218 else if ('1' == opt[j]) VG_(clo_profile_flags) |= (1 << (7-j));
njn25e49d8e72002-09-23 09:36:25 +00001219 else {
sewardjfa8ec112005-01-19 11:55:34 +00001220 VG_(message)(Vg_UserMsg, "--profile-flags argument can only "
njn25e49d8e72002-09-23 09:36:25 +00001221 "contain 0s and 1s");
nethercote71980f02004-01-24 18:18:54 +00001222 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001223 }
1224 }
1225 }
sewardjde4a1d02002-03-22 01:27:54 +00001226
njn45270a22005-03-27 01:00:11 +00001227 else VG_NUM_CLO (arg, "--trace-notbelow", VG_(clo_trace_notbelow))
sewardjc771b292004-11-30 18:55:21 +00001228
sewardjd153fae2005-01-10 17:24:47 +00001229 else if (VG_CLO_STREQ(arg, "--gen-suppressions=no"))
1230 VG_(clo_gen_suppressions) = 0;
1231 else if (VG_CLO_STREQ(arg, "--gen-suppressions=yes"))
1232 VG_(clo_gen_suppressions) = 1;
1233 else if (VG_CLO_STREQ(arg, "--gen-suppressions=all"))
1234 VG_(clo_gen_suppressions) = 2;
1235
nethercote71980f02004-01-24 18:18:54 +00001236 else if ( ! VG_(needs).command_line_options
njn51d827b2005-05-09 01:02:08 +00001237 || ! VG_TDICT_CALL(tool_process_cmd_line_option, arg) ) {
nethercotef4928da2004-06-15 10:54:40 +00001238 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001239 }
njn8c0b3bb2005-03-12 21:20:39 +00001240 skip_arg:
sewardj45f4e7c2005-09-27 19:20:21 +00001241 if (arg != VG_(args_for_valgrind).strs[i]) {
1242 VG_(free)(arg);
1243 }
sewardjde4a1d02002-03-22 01:27:54 +00001244 }
1245
sewardj998d40d2004-12-06 14:24:52 +00001246 /* Make VEX control parameters sane */
1247
1248 if (VG_(clo_vex_control).guest_chase_thresh
1249 >= VG_(clo_vex_control).guest_max_insns)
1250 VG_(clo_vex_control).guest_chase_thresh
1251 = VG_(clo_vex_control).guest_max_insns - 1;
1252
1253 if (VG_(clo_vex_control).guest_chase_thresh < 0)
1254 VG_(clo_vex_control).guest_chase_thresh = 0;
1255
1256 /* Check various option values */
nethercote27fec902004-06-16 21:26:32 +00001257
njnf9ebf672003-05-12 21:41:30 +00001258 if (VG_(clo_verbosity) < 0)
sewardjde4a1d02002-03-22 01:27:54 +00001259 VG_(clo_verbosity) = 0;
1260
nethercote04d0fbc2004-01-26 16:48:06 +00001261 if (VG_(clo_db_attach) && VG_(clo_trace_children)) {
sewardjde4a1d02002-03-22 01:27:54 +00001262 VG_(message)(Vg_UserMsg, "");
1263 VG_(message)(Vg_UserMsg,
nethercote04d0fbc2004-01-26 16:48:06 +00001264 "--db-attach=yes conflicts with --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001265 VG_(message)(Vg_UserMsg,
1266 "Please choose one or the other, but not both.");
nethercote04d0fbc2004-01-26 16:48:06 +00001267 VG_(bad_option)("--db-attach=yes and --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001268 }
1269
njnbe9b47b2005-05-15 16:22:58 +00001270 if (VG_(clo_gen_suppressions) > 0 &&
1271 !VG_(needs).core_errors && !VG_(needs).tool_errors) {
1272 VG_(message)(Vg_UserMsg,
1273 "Can't use --gen-suppressions= with this tool,");
1274 VG_(message)(Vg_UserMsg,
1275 "as it doesn't generate errors.");
1276 VG_(bad_option)("--gen-suppressions=");
1277 }
1278
sewardj71bc3cb2005-05-19 00:25:45 +00001279 /* If we've been asked to emit XML, mash around various other
1280 options so as to constrain the output somewhat, and to remove
1281 any need for user input during the run. */
1282 if (VG_(clo_xml)) {
1283 /* Disable suppression generation (requires user input) */
1284 VG_(clo_gen_suppressions) = 0;
1285 /* Disable attaching to GDB (requires user input) */
1286 VG_(clo_db_attach) = False;
1287 /* Set a known verbosity level */
1288 VG_(clo_verbosity) = 1;
1289 /* Disable error limits (this might be a bad idea!) */
1290 VG_(clo_error_limit) = False;
1291 /* Disable emulation warnings */
1292 VG_(clo_show_emwarns) = False;
1293 /* Disable waiting for GDB to debug Valgrind */
1294 VG_(clo_wait_for_gdb) = False;
1295 /* No file-descriptor leak checking yet */
1296 VG_(clo_track_fds) = False;
sewardj21f7f0c2005-07-06 19:46:48 +00001297 /* Disable timestamped output */
1298 VG_(clo_time_stamp) = False;
sewardj71bc3cb2005-05-19 00:25:45 +00001299 /* Also, we want to set options for the leak checker, but that
1300 will have to be done in Memcheck's flag-handling code, not
1301 here. */
1302 }
1303
njnbe9b47b2005-05-15 16:22:58 +00001304 /* All non-logging-related options have been checked. If the logging
1305 option specified is ok, we can switch to it, as we know we won't
1306 have to generate any other command-line-related error messages.
1307 (So far we should be still attached to stderr, so we can show on
1308 the terminal any problems to do with processing command line
1309 opts.)
1310
1311 So set up logging now. After this is done, VG_(clo_log_fd)
sewardj4cf05692002-10-27 20:28:29 +00001312 should be connected to whatever sink has been selected, and we
1313 indiscriminately chuck stuff into it without worrying what the
1314 nature of it is. Oh the wonder of Unix streams. */
1315
njnbe9b47b2005-05-15 16:22:58 +00001316 vg_assert(VG_(clo_log_fd) == 2 /* stderr */);
1317 vg_assert(VG_(logging_to_socket) == False);
sewardj4cf05692002-10-27 20:28:29 +00001318
njnbe9b47b2005-05-15 16:22:58 +00001319 switch (log_to) {
sewardj73cf3bc2002-11-03 03:20:15 +00001320
sewardj4cf05692002-10-27 20:28:29 +00001321 case VgLogTo_Fd:
nethercotef8548672004-06-21 12:42:35 +00001322 vg_assert(VG_(clo_log_name) == NULL);
1323 VG_(clo_log_fd) = eventually_log_fd;
sewardj4cf05692002-10-27 20:28:29 +00001324 break;
sewardj73cf3bc2002-11-03 03:20:15 +00001325
sewardj4cf05692002-10-27 20:28:29 +00001326 case VgLogTo_File: {
sewardjad311162005-07-19 11:25:02 +00001327 HChar logfilename[1000];
1328 Int seq = 0;
1329 Int pid = VG_(getpid)();
1330 HChar* qual = NULL;
jsgff3c3f1a2003-10-14 22:13:28 +00001331
nethercotef8548672004-06-21 12:42:35 +00001332 vg_assert(VG_(clo_log_name) != NULL);
1333 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
jsgff3c3f1a2003-10-14 22:13:28 +00001334
sewardjad311162005-07-19 11:25:02 +00001335 if (VG_(clo_log_file_qualifier)) {
1336 qual = VG_(getenv)(VG_(clo_log_file_qualifier));
1337 }
1338
nethercote71980f02004-01-24 18:18:54 +00001339 for (;;) {
sewardj92645592005-07-23 09:18:34 +00001340 HChar pidtxt[20], seqtxt[20];
1341
1342 VG_(sprintf)(pidtxt, "%d", pid);
1343
1344 if (seq == 0)
1345 seqtxt[0] = 0;
1346 else
1347 VG_(sprintf)(seqtxt, ".%d", seq);
1348
jsgff3c3f1a2003-10-14 22:13:28 +00001349 seq++;
1350
sewardj92645592005-07-23 09:18:34 +00001351 /* Result:
1352 if (qual) base_name ++ "." ++ qual ++ seqtxt
1353 if (not qual) base_name ++ "." ++ pid ++ seqtxt
1354 */
1355 VG_(sprintf)( logfilename,
1356 "%s.%s%s",
1357 VG_(clo_log_name),
1358 qual ? qual : pidtxt,
1359 seqtxt );
1360
njnbe9b47b2005-05-15 16:22:58 +00001361 // EXCL: it will fail with EEXIST if the file already exists.
sewardj92645592005-07-23 09:18:34 +00001362 sres
jsgff3c3f1a2003-10-14 22:13:28 +00001363 = VG_(open)(logfilename,
1364 VKI_O_CREAT|VKI_O_WRONLY|VKI_O_EXCL|VKI_O_TRUNC,
1365 VKI_S_IRUSR|VKI_S_IWUSR);
sewardj92645592005-07-23 09:18:34 +00001366 if (!sres.isError) {
1367 eventually_log_fd = sres.val;
nethercotef8548672004-06-21 12:42:35 +00001368 VG_(clo_log_fd) = VG_(safe_fd)(eventually_log_fd);
sewardj603d4102005-01-11 14:01:02 +00001369 break; /* for (;;) */
jsgff3c3f1a2003-10-14 22:13:28 +00001370 } else {
njnbe9b47b2005-05-15 16:22:58 +00001371 // If the file already existed, we try the next name. If it
1372 // was some other file error, we give up.
sewardj92645592005-07-23 09:18:34 +00001373 if (sres.val != VKI_EEXIST) {
jsgff3c3f1a2003-10-14 22:13:28 +00001374 VG_(message)(Vg_UserMsg,
njn02bc4b82005-05-15 17:28:26 +00001375 "Can't create/open log file '%s.pid%d'; giving up!",
nethercotef8548672004-06-21 12:42:35 +00001376 VG_(clo_log_name), pid);
jsgff3c3f1a2003-10-14 22:13:28 +00001377 VG_(bad_option)(
sewardj603d4102005-01-11 14:01:02 +00001378 "--log-file=<file> (didn't work out for some reason.)");
njnbe9b47b2005-05-15 16:22:58 +00001379 /*NOTREACHED*/
jsgff3c3f1a2003-10-14 22:13:28 +00001380 }
1381 }
1382 }
sewardj603d4102005-01-11 14:01:02 +00001383 break; /* switch (VG_(clo_log_to)) */
1384 }
1385
1386 case VgLogTo_FileExactly: {
sewardj603d4102005-01-11 14:01:02 +00001387 vg_assert(VG_(clo_log_name) != NULL);
1388 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
sewardj603d4102005-01-11 14:01:02 +00001389
sewardj92645592005-07-23 09:18:34 +00001390 sres
njnbe9b47b2005-05-15 16:22:58 +00001391 = VG_(open)(VG_(clo_log_name),
sewardj603d4102005-01-11 14:01:02 +00001392 VKI_O_CREAT|VKI_O_WRONLY|VKI_O_TRUNC,
1393 VKI_S_IRUSR|VKI_S_IWUSR);
sewardj92645592005-07-23 09:18:34 +00001394 if (!sres.isError) {
1395 eventually_log_fd = sres.val;
sewardj603d4102005-01-11 14:01:02 +00001396 VG_(clo_log_fd) = VG_(safe_fd)(eventually_log_fd);
njnbe9b47b2005-05-15 16:22:58 +00001397 } else {
sewardj603d4102005-01-11 14:01:02 +00001398 VG_(message)(Vg_UserMsg,
njn02bc4b82005-05-15 17:28:26 +00001399 "Can't create/open log file '%s'; giving up!",
sewardj603d4102005-01-11 14:01:02 +00001400 VG_(clo_log_name));
1401 VG_(bad_option)(
1402 "--log-file-exactly=<file> (didn't work out for some reason.)");
1403 /*NOTREACHED*/
1404 }
1405 break; /* switch (VG_(clo_log_to)) */
sewardj73cf3bc2002-11-03 03:20:15 +00001406 }
1407
1408 case VgLogTo_Socket: {
nethercotef8548672004-06-21 12:42:35 +00001409 vg_assert(VG_(clo_log_name) != NULL);
1410 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
1411 eventually_log_fd = VG_(connect_via_socket)( VG_(clo_log_name) );
1412 if (eventually_log_fd == -1) {
sewardj73cf3bc2002-11-03 03:20:15 +00001413 VG_(message)(Vg_UserMsg,
nethercotef8548672004-06-21 12:42:35 +00001414 "Invalid --log-socket=ipaddr or --log-socket=ipaddr:port spec");
sewardj73cf3bc2002-11-03 03:20:15 +00001415 VG_(message)(Vg_UserMsg,
njn02bc4b82005-05-15 17:28:26 +00001416 "of '%s'; giving up!", VG_(clo_log_name) );
sewardj73cf3bc2002-11-03 03:20:15 +00001417 VG_(bad_option)(
nethercotef8548672004-06-21 12:42:35 +00001418 "--log-socket=");
njnbe9b47b2005-05-15 16:22:58 +00001419 /*NOTREACHED*/
sewardj4cf05692002-10-27 20:28:29 +00001420 }
nethercotef8548672004-06-21 12:42:35 +00001421 if (eventually_log_fd == -2) {
sewardj73cf3bc2002-11-03 03:20:15 +00001422 VG_(message)(Vg_UserMsg,
njn02bc4b82005-05-15 17:28:26 +00001423 "valgrind: failed to connect to logging server '%s'.",
nethercotef8548672004-06-21 12:42:35 +00001424 VG_(clo_log_name) );
sewardj570f8902002-11-03 11:44:36 +00001425 VG_(message)(Vg_UserMsg,
1426 "Log messages will sent to stderr instead." );
1427 VG_(message)(Vg_UserMsg,
1428 "" );
1429 /* We don't change anything here. */
njnbe9b47b2005-05-15 16:22:58 +00001430 vg_assert(VG_(clo_log_fd) == 2);
sewardj570f8902002-11-03 11:44:36 +00001431 } else {
nethercotef8548672004-06-21 12:42:35 +00001432 vg_assert(eventually_log_fd > 0);
1433 VG_(clo_log_fd) = eventually_log_fd;
njnbe9b47b2005-05-15 16:22:58 +00001434 VG_(logging_to_socket) = True;
sewardj570f8902002-11-03 11:44:36 +00001435 }
sewardj73cf3bc2002-11-03 03:20:15 +00001436 break;
1437 }
sewardj4cf05692002-10-27 20:28:29 +00001438 }
1439
sewardj71bc3cb2005-05-19 00:25:45 +00001440
1441 /* Check that the requested tool actually supports XML output. */
sewardj45f4e7c2005-09-27 19:20:21 +00001442 if (VG_(clo_xml) && !VG_STREQ(toolname, "memcheck")
1443 && !VG_STREQ(toolname, "none")) {
sewardj71bc3cb2005-05-19 00:25:45 +00001444 VG_(clo_xml) = False;
1445 VG_(message)(Vg_UserMsg,
cerion39655202005-07-13 14:18:24 +00001446 "Currently only Memcheck|None supports XML output.");
sewardj71bc3cb2005-05-19 00:25:45 +00001447 VG_(bad_option)("--xml=yes");
1448 /*NOTREACHED*/
1449 }
1450
njnbe9b47b2005-05-15 16:22:58 +00001451 // Move log_fd into the safe range, so it doesn't conflict with any app fds.
1452 // XXX: this is more or less duplicating the behaviour of the calls to
1453 // VG_(safe_fd)() above, although this does not close the original fd.
1454 // Perhaps the VG_(safe_fd)() calls above should be removed, and this
1455 // code should be replaced with a call to VG_(safe_fd)(). --njn
thughesad1c9562004-06-26 11:27:52 +00001456 eventually_log_fd = VG_(fcntl)(VG_(clo_log_fd), VKI_F_DUPFD, VG_(fd_hard_limit));
nethercotef8548672004-06-21 12:42:35 +00001457 if (eventually_log_fd < 0)
jsgf855d93d2003-10-13 22:26:55 +00001458 VG_(message)(Vg_UserMsg, "valgrind: failed to move logfile fd into safe range");
1459 else {
nethercotef8548672004-06-21 12:42:35 +00001460 VG_(clo_log_fd) = eventually_log_fd;
1461 VG_(fcntl)(VG_(clo_log_fd), VKI_F_SETFD, VKI_FD_CLOEXEC);
jsgf855d93d2003-10-13 22:26:55 +00001462 }
1463
sewardj45f4e7c2005-09-27 19:20:21 +00001464 if (VG_(clo_n_suppressions) < VG_CLO_MAX_SFILES-1 &&
1465 (VG_(needs).core_errors || VG_(needs).tool_errors)) {
1466 /* If we haven't reached the max number of suppressions, load
1467 the default one. */
1468 static const Char default_supp[] = "default.supp";
1469 Int len = VG_(strlen)(VG_(libdir)) + 1 + sizeof(default_supp);
1470 Char *buf = VG_(arena_malloc)(VG_AR_CORE, len);
1471 VG_(sprintf)(buf, "%s/%s", VG_(libdir), default_supp);
1472 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = buf;
1473 VG_(clo_n_suppressions)++;
1474 }
sewardjde4a1d02002-03-22 01:27:54 +00001475
sewardj45f4e7c2005-09-27 19:20:21 +00001476 return (log_to == VgLogTo_Fd);
1477}
1478
1479
1480/*====================================================================*/
1481/*=== Printing the preamble ===*/
1482/*====================================================================*/
1483
1484/* Ok, the logging sink is running now. Print a suitable preamble.
1485 If logging to file or a socket, write details of parent PID and
1486 command line args, to help people trying to interpret the
1487 results of a run which encompasses multiple processes. */
1488static void print_preamble(Bool logging_to_fd, const char* toolname)
1489{
tom60a4b0b2005-10-12 10:45:27 +00001490 HChar* xpre = VG_(clo_xml) ? " <line>" : "";
1491 HChar* xpost = VG_(clo_xml) ? "</line>" : "";
1492 Int i;
1493
sewardj71bc3cb2005-05-19 00:25:45 +00001494 if (VG_(clo_xml)) {
sewardj8665d8e2005-06-01 17:35:23 +00001495 VG_(message)(Vg_UserMsg, "<?xml version=\"1.0\"?>");
1496 VG_(message)(Vg_UserMsg, "");
sewardj71bc3cb2005-05-19 00:25:45 +00001497 VG_(message)(Vg_UserMsg, "<valgrindoutput>");
1498 VG_(message)(Vg_UserMsg, "");
1499 VG_(message)(Vg_UserMsg, "<protocolversion>1</protocolversion>");
1500 VG_(message)(Vg_UserMsg, "");
1501 }
1502
sewardj83adf412002-05-01 01:25:45 +00001503 if (VG_(clo_verbosity > 0)) {
sewardjd7bddad2005-06-13 16:48:32 +00001504
1505 if (VG_(clo_xml))
1506 VG_(message)(Vg_UserMsg, "<preamble>");
1507
nethercote996901a2004-08-03 13:29:09 +00001508 /* Tool details */
sewardj71bc3cb2005-05-19 00:25:45 +00001509 VG_(message)(Vg_UserMsg, "%s%s%s%s, %s.%s",
1510 xpre,
njnd04b7c62002-10-03 14:05:52 +00001511 VG_(details).name,
njnb9c427c2004-12-01 14:14:42 +00001512 NULL == VG_(details).version ? "" : "-",
njnd04b7c62002-10-03 14:05:52 +00001513 NULL == VG_(details).version
1514 ? (Char*)"" : VG_(details).version,
sewardj71bc3cb2005-05-19 00:25:45 +00001515 VG_(details).description,
1516 xpost);
1517 VG_(message)(Vg_UserMsg, "%s%s%s",
1518 xpre, VG_(details).copyright_author, xpost);
sewardj3b2736a2002-03-24 12:18:35 +00001519
njnd04b7c62002-10-03 14:05:52 +00001520 /* Core details */
1521 VG_(message)(Vg_UserMsg,
sewardj71bc3cb2005-05-19 00:25:45 +00001522 "%sUsing LibVEX rev %s, a library for dynamic binary translation.%s",
1523 xpre, LibVEX_Version(), xpost );
sewardjc7025332004-12-13 18:30:39 +00001524 VG_(message)(Vg_UserMsg,
sewardj71bc3cb2005-05-19 00:25:45 +00001525 "%sCopyright (C) 2004-2005, and GNU GPL'd, by OpenWorks LLP.%s",
1526 xpre, xpost );
sewardjc7025332004-12-13 18:30:39 +00001527 VG_(message)(Vg_UserMsg,
sewardj71bc3cb2005-05-19 00:25:45 +00001528 "%sUsing valgrind-%s, a dynamic binary instrumentation framework.%s",
1529 xpre, VERSION, xpost);
sewardjde4a1d02002-03-22 01:27:54 +00001530 VG_(message)(Vg_UserMsg,
sewardj71bc3cb2005-05-19 00:25:45 +00001531 "%sCopyright (C) 2000-2005, and GNU GPL'd, by Julian Seward et al.%s",
1532 xpre, xpost );
sewardjd7bddad2005-06-13 16:48:32 +00001533
sewardj45f4e7c2005-09-27 19:20:21 +00001534 if (VG_(clo_verbosity) == 1 && !VG_(clo_xml))
1535 VG_(message)(Vg_UserMsg, "For more details, rerun with: -v");
1536
sewardjd7bddad2005-06-13 16:48:32 +00001537 if (VG_(clo_xml))
1538 VG_(message)(Vg_UserMsg, "</preamble>");
njnd04b7c62002-10-03 14:05:52 +00001539 }
1540
sewardj45f4e7c2005-09-27 19:20:21 +00001541 if (!VG_(clo_xml) && VG_(clo_verbosity) > 0 && !logging_to_fd) {
sewardj4cf05692002-10-27 20:28:29 +00001542 VG_(message)(Vg_UserMsg, "");
1543 VG_(message)(Vg_UserMsg,
1544 "My PID = %d, parent PID = %d. Prog and args are:",
1545 VG_(getpid)(), VG_(getppid)() );
sewardj5e940782005-09-28 19:59:19 +00001546 if (VG_(args_the_exename))
1547 VG_(message)(Vg_UserMsg, " %s", VG_(args_the_exename));
sewardj45f4e7c2005-09-27 19:20:21 +00001548 for (i = 0; i < VG_(args_for_client).used; i++)
1549 VG_(message)(Vg_UserMsg, " %s", VG_(args_for_client).strs[i]);
sewardj5b742c32005-07-26 23:43:26 +00001550 if (VG_(clo_log_file_qualifier)) {
1551 HChar* val = VG_(getenv)(VG_(clo_log_file_qualifier));
1552 VG_(message)(Vg_UserMsg, "");
1553 VG_(message)(Vg_UserMsg, "Log file qualifier: var %s, value %s.",
1554 VG_(clo_log_file_qualifier),
1555 val ? val : "");
1556 }
sewardj4cf05692002-10-27 20:28:29 +00001557 }
sewardj71bc3cb2005-05-19 00:25:45 +00001558 else
1559 if (VG_(clo_xml)) {
1560 VG_(message)(Vg_UserMsg, "");
1561 VG_(message)(Vg_UserMsg, "<pid>%d</pid>", VG_(getpid)());
1562 VG_(message)(Vg_UserMsg, "<ppid>%d</ppid>", VG_(getppid)());
sewardj97f7e0c2005-07-19 15:00:25 +00001563 VG_(message)(Vg_UserMsg, "<tool>%t</tool>", toolname);
sewardjad311162005-07-19 11:25:02 +00001564 if (VG_(clo_log_file_qualifier)) {
1565 HChar* val = VG_(getenv)(VG_(clo_log_file_qualifier));
sewardj97f7e0c2005-07-19 15:00:25 +00001566 VG_(message)(Vg_UserMsg, "<logfilequalifier> <var>%t</var> "
1567 "<value>%t</value> </logfilequalifier>",
sewardjad311162005-07-19 11:25:02 +00001568 VG_(clo_log_file_qualifier),
1569 val ? val : "");
1570 }
sewardj768db0e2005-07-19 14:18:56 +00001571 if (VG_(clo_xml_user_comment)) {
1572 /* Note: the user comment itself is XML and is therefore to
1573 be passed through verbatim (%s) rather than escaped
1574 (%t). */
1575 VG_(message)(Vg_UserMsg, "<usercomment>%s</usercomment>",
1576 VG_(clo_xml_user_comment));
1577 }
sewardj71bc3cb2005-05-19 00:25:45 +00001578 VG_(message)(Vg_UserMsg, "");
sewardjb8a3dac2005-07-19 12:39:11 +00001579 VG_(message)(Vg_UserMsg, "<args>");
sewardj45f4e7c2005-09-27 19:20:21 +00001580
sewardjb8a3dac2005-07-19 12:39:11 +00001581 VG_(message)(Vg_UserMsg, " <vargv>");
sewardj45f4e7c2005-09-27 19:20:21 +00001582 if (VG_(name_of_launcher))
1583 VG_(message)(Vg_UserMsg, " <exe>%t</exe>",
1584 VG_(name_of_launcher));
1585 for (i = 0; i < VG_(args_for_valgrind).used; i++) {
1586 VG_(message)(Vg_UserMsg,
1587 " <arg>%t</arg>",
1588 VG_(args_for_valgrind).strs[i]);
sewardjb8a3dac2005-07-19 12:39:11 +00001589 }
1590 VG_(message)(Vg_UserMsg, " </vargv>");
sewardj45f4e7c2005-09-27 19:20:21 +00001591
sewardjb8a3dac2005-07-19 12:39:11 +00001592 VG_(message)(Vg_UserMsg, " <argv>");
sewardj45f4e7c2005-09-27 19:20:21 +00001593 if (VG_(args_the_exename))
1594 VG_(message)(Vg_UserMsg, " <exe>%t</exe>",
1595 VG_(args_the_exename));
1596 for (i = 0; i < VG_(args_for_client).used; i++) {
1597 VG_(message)(Vg_UserMsg, " <arg>%t</arg>",
1598 VG_(args_for_client).strs[i]);
sewardj8665d8e2005-06-01 17:35:23 +00001599 }
sewardjb8a3dac2005-07-19 12:39:11 +00001600 VG_(message)(Vg_UserMsg, " </argv>");
sewardj45f4e7c2005-09-27 19:20:21 +00001601
sewardjb8a3dac2005-07-19 12:39:11 +00001602 VG_(message)(Vg_UserMsg, "</args>");
sewardj71bc3cb2005-05-19 00:25:45 +00001603 }
sewardj4cf05692002-10-27 20:28:29 +00001604
sewardj45f4e7c2005-09-27 19:20:21 +00001605 // Empty line after the preamble
1606 if (VG_(clo_verbosity) > 0)
1607 VG_(message)(Vg_UserMsg, "");
1608
sewardjde4a1d02002-03-22 01:27:54 +00001609 if (VG_(clo_verbosity) > 1) {
sewardj92645592005-07-23 09:18:34 +00001610 SysRes fd;
sewardj45f4e7c2005-09-27 19:20:21 +00001611 if (!logging_to_fd)
njn1fd5eb22005-03-13 05:43:23 +00001612 VG_(message)(Vg_DebugMsg, "");
1613 VG_(message)(Vg_DebugMsg, "Valgrind library directory: %s", VG_(libdir));
sewardj45f4e7c2005-09-27 19:20:21 +00001614
njn1fd5eb22005-03-13 05:43:23 +00001615 VG_(message)(Vg_DebugMsg, "Command line");
sewardj45f4e7c2005-09-27 19:20:21 +00001616 if (VG_(args_the_exename))
1617 VG_(message)(Vg_DebugMsg, " %s", VG_(args_the_exename));
1618 for (i = 0; i < VG_(args_for_client).used; i++)
1619 VG_(message)(Vg_DebugMsg, " %s", VG_(args_for_client).strs[i]);
njn86dc2bc2003-09-09 07:26:21 +00001620
njn1fd5eb22005-03-13 05:43:23 +00001621 VG_(message)(Vg_DebugMsg, "Startup, with flags:");
sewardj45f4e7c2005-09-27 19:20:21 +00001622 for (i = 0; i < VG_(args_for_valgrind).used; i++) {
1623 VG_(message)(Vg_DebugMsg, " %s", VG_(args_for_valgrind).strs[i]);
sewardjde4a1d02002-03-22 01:27:54 +00001624 }
nethercotea70f7352004-04-18 12:08:46 +00001625
njn1fd5eb22005-03-13 05:43:23 +00001626 VG_(message)(Vg_DebugMsg, "Contents of /proc/version:");
nethercotea70f7352004-04-18 12:08:46 +00001627 fd = VG_(open) ( "/proc/version", VKI_O_RDONLY, 0 );
sewardj92645592005-07-23 09:18:34 +00001628 if (fd.isError) {
njn1fd5eb22005-03-13 05:43:23 +00001629 VG_(message)(Vg_DebugMsg, " can't open /proc/version");
nethercotea70f7352004-04-18 12:08:46 +00001630 } else {
sewardj71bc3cb2005-05-19 00:25:45 +00001631# define BUF_LEN 256
nethercotea70f7352004-04-18 12:08:46 +00001632 Char version_buf[BUF_LEN];
sewardj92645592005-07-23 09:18:34 +00001633 Int n = VG_(read) ( fd.val, version_buf, BUF_LEN );
njnbe9b47b2005-05-15 16:22:58 +00001634 vg_assert(n <= BUF_LEN);
nethercotea70f7352004-04-18 12:08:46 +00001635 if (n > 0) {
1636 version_buf[n-1] = '\0';
njn1fd5eb22005-03-13 05:43:23 +00001637 VG_(message)(Vg_DebugMsg, " %s", version_buf);
nethercotea70f7352004-04-18 12:08:46 +00001638 } else {
njn1fd5eb22005-03-13 05:43:23 +00001639 VG_(message)(Vg_DebugMsg, " (empty?)");
nethercotea70f7352004-04-18 12:08:46 +00001640 }
sewardj92645592005-07-23 09:18:34 +00001641 VG_(close)(fd.val);
sewardj71bc3cb2005-05-19 00:25:45 +00001642# undef BUF_LEN
nethercotea70f7352004-04-18 12:08:46 +00001643 }
sewardjde4a1d02002-03-22 01:27:54 +00001644 }
nethercotef6a1d502004-08-09 12:21:57 +00001645}
1646
sewardjde4a1d02002-03-22 01:27:54 +00001647
nethercote71980f02004-01-24 18:18:54 +00001648/*====================================================================*/
1649/*=== File descriptor setup ===*/
1650/*====================================================================*/
1651
sewardj5f229e22005-09-28 01:36:01 +00001652/* Number of file descriptors that Valgrind tries to reserve for
1653 it's own use - just a small constant. */
1654#define N_RESERVED_FDS (10)
1655
nethercote71980f02004-01-24 18:18:54 +00001656static void setup_file_descriptors(void)
1657{
1658 struct vki_rlimit rl;
1659
1660 /* Get the current file descriptor limits. */
1661 if (VG_(getrlimit)(VKI_RLIMIT_NOFILE, &rl) < 0) {
1662 rl.rlim_cur = 1024;
1663 rl.rlim_max = 1024;
1664 }
1665
1666 /* Work out where to move the soft limit to. */
njn14319cc2005-03-13 06:26:22 +00001667 if (rl.rlim_cur + N_RESERVED_FDS <= rl.rlim_max) {
1668 rl.rlim_cur = rl.rlim_cur + N_RESERVED_FDS;
nethercote71980f02004-01-24 18:18:54 +00001669 } else {
1670 rl.rlim_cur = rl.rlim_max;
1671 }
1672
1673 /* Reserve some file descriptors for our use. */
njn14319cc2005-03-13 06:26:22 +00001674 VG_(fd_soft_limit) = rl.rlim_cur - N_RESERVED_FDS;
1675 VG_(fd_hard_limit) = rl.rlim_cur - N_RESERVED_FDS;
nethercote71980f02004-01-24 18:18:54 +00001676
1677 /* Update the soft limit. */
1678 VG_(setrlimit)(VKI_RLIMIT_NOFILE, &rl);
1679
sewardj45f4e7c2005-09-27 19:20:21 +00001680 if (VG_(cl_exec_fd) != -1)
1681 VG_(cl_exec_fd) = VG_(safe_fd)( VG_(cl_exec_fd) );
nethercote71980f02004-01-24 18:18:54 +00001682}
1683
sewardjde4a1d02002-03-22 01:27:54 +00001684
njn2da73352005-06-18 01:35:16 +00001685/*====================================================================*/
1686/*=== Initialise the first thread. ===*/
1687/*====================================================================*/
1688
1689/* Given a pointer to the ThreadArchState for thread 1 (the root
1690 thread), initialise the VEX guest state, and copy in essential
1691 starting values.
1692*/
1693static void init_thread1state ( Addr client_ip,
sewardjfdf91b42005-09-28 00:53:09 +00001694 Addr client_sp,
njn2da73352005-06-18 01:35:16 +00001695 /*inout*/ ThreadArchState* arch )
1696{
1697#if defined(VGA_x86)
1698 vg_assert(0 == sizeof(VexGuestX86State) % 8);
1699
1700 /* Zero out the initial state, and set up the simulated FPU in a
1701 sane way. */
1702 LibVEX_GuestX86_initialise(&arch->vex);
1703
1704 /* Zero out the shadow area. */
1705 VG_(memset)(&arch->vex_shadow, 0, sizeof(VexGuestX86State));
1706
1707 /* Put essential stuff into the new state. */
sewardjfdf91b42005-09-28 00:53:09 +00001708 arch->vex.guest_ESP = client_sp;
njn2da73352005-06-18 01:35:16 +00001709 arch->vex.guest_EIP = client_ip;
1710
1711 /* initialise %cs, %ds and %ss to point at the operating systems
1712 default code, data and stack segments */
1713 asm volatile("movw %%cs, %0" : : "m" (arch->vex.guest_CS));
1714 asm volatile("movw %%ds, %0" : : "m" (arch->vex.guest_DS));
1715 asm volatile("movw %%ss, %0" : : "m" (arch->vex.guest_SS));
cerion85665ca2005-06-20 15:51:07 +00001716
njn2da73352005-06-18 01:35:16 +00001717#elif defined(VGA_amd64)
1718 vg_assert(0 == sizeof(VexGuestAMD64State) % 8);
1719
1720 /* Zero out the initial state, and set up the simulated FPU in a
1721 sane way. */
1722 LibVEX_GuestAMD64_initialise(&arch->vex);
1723
1724 /* Zero out the shadow area. */
1725 VG_(memset)(&arch->vex_shadow, 0, sizeof(VexGuestAMD64State));
1726
1727 /* Put essential stuff into the new state. */
sewardjfdf91b42005-09-28 00:53:09 +00001728 arch->vex.guest_RSP = client_sp;
njn2da73352005-06-18 01:35:16 +00001729 arch->vex.guest_RIP = client_ip;
cerion85665ca2005-06-20 15:51:07 +00001730
1731#elif defined(VGA_ppc32)
1732 vg_assert(0 == sizeof(VexGuestPPC32State) % 8);
1733
1734 /* Zero out the initial state, and set up the simulated FPU in a
1735 sane way. */
1736 LibVEX_GuestPPC32_initialise(&arch->vex);
1737
1738 /* Zero out the shadow area. */
1739 VG_(memset)(&arch->vex_shadow, 0, sizeof(VexGuestPPC32State));
1740
1741 /* Put essential stuff into the new state. */
sewardjfdf91b42005-09-28 00:53:09 +00001742 arch->vex.guest_GPR1 = client_sp;
cerion85665ca2005-06-20 15:51:07 +00001743 arch->vex.guest_CIA = client_ip;
1744
njn2da73352005-06-18 01:35:16 +00001745#else
1746# error Unknown arch
1747#endif
1748 // Tell the tool that we just wrote to the registers.
1749 VG_TRACK( post_reg_write, Vg_CoreStartup, /*tid*/1, /*offset*/0,
1750 sizeof(VexGuestArchState));
1751}
1752
sewardjde4a1d02002-03-22 01:27:54 +00001753
nethercote71980f02004-01-24 18:18:54 +00001754/*====================================================================*/
njn2025cf92005-06-26 20:44:48 +00001755/*=== BB profiling ===*/
1756/*====================================================================*/
1757
1758static
1759void show_BB_profile ( BBProfEntry tops[], UInt n_tops, ULong score_total )
1760{
1761 ULong score_cumul, score_here;
1762 Char buf_cumul[10], buf_here[10];
1763 Char name[64];
1764 Int r;
1765
1766 VG_(printf)("\n");
1767 VG_(printf)("-----------------------------------------------------------\n");
1768 VG_(printf)("--- BEGIN BB Profile (summary of scores) ---\n");
1769 VG_(printf)("-----------------------------------------------------------\n");
1770 VG_(printf)("\n");
1771
1772 VG_(printf)("Total score = %lld\n\n", score_total);
1773
1774 score_cumul = 0;
1775 for (r = 0; r < n_tops; r++) {
1776 if (tops[r].addr == 0)
1777 continue;
1778 name[0] = 0;
1779 VG_(get_fnname_w_offset)(tops[r].addr, name, 64);
1780 name[63] = 0;
1781 score_here = tops[r].score;
1782 score_cumul += score_here;
1783 VG_(percentify)(score_cumul, score_total, 2, 6, buf_cumul);
1784 VG_(percentify)(score_here, score_total, 2, 6, buf_here);
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 }
1790
1791 VG_(printf)("\n");
1792 VG_(printf)("-----------------------------------------------------------\n");
1793 VG_(printf)("--- BB Profile (BB details) ---\n");
1794 VG_(printf)("-----------------------------------------------------------\n");
1795 VG_(printf)("\n");
1796
1797 score_cumul = 0;
1798 for (r = 0; r < n_tops; r++) {
1799 if (tops[r].addr == 0)
1800 continue;
1801 name[0] = 0;
1802 VG_(get_fnname_w_offset)(tops[r].addr, name, 64);
1803 name[63] = 0;
1804 score_here = tops[r].score;
1805 score_cumul += score_here;
1806 VG_(percentify)(score_cumul, score_total, 2, 6, buf_cumul);
1807 VG_(percentify)(score_here, score_total, 2, 6, buf_here);
1808 VG_(printf)("\n");
1809 VG_(printf)("=-=-=-=-=-=-=-=-=-=-=-=-=-= begin BB rank %d "
1810 "=-=-=-=-=-=-=-=-=-=-=-=-=-=\n\n", r);
1811 VG_(printf)("%3d: (%9lld %s) %9lld %s 0x%llx %s\n",
1812 r,
1813 score_cumul, buf_cumul,
1814 score_here, buf_here, tops[r].addr, name );
1815 VG_(printf)("\n");
1816 VG_(translate)(0, tops[r].addr, True, VG_(clo_profile_flags), 0);
1817 VG_(printf)("=-=-=-=-=-=-=-=-=-=-=-=-=-= end BB rank %d "
1818 "=-=-=-=-=-=-=-=-=-=-=-=-=-=\n\n", r);
1819 }
1820
1821 VG_(printf)("\n");
1822 VG_(printf)("-----------------------------------------------------------\n");
1823 VG_(printf)("--- END BB Profile ---\n");
1824 VG_(printf)("-----------------------------------------------------------\n");
1825 VG_(printf)("\n");
1826}
1827
1828
1829/*====================================================================*/
nethercote71980f02004-01-24 18:18:54 +00001830/*=== main() ===*/
1831/*====================================================================*/
1832
sewardjfdf91b42005-09-28 00:53:09 +00001833/* When main() is entered, we should be on the following stack, not
1834 the one the kernel gave us. We will run on this stack until
1835 simulation of the root thread is started, at which point a transfer
1836 is made to a dynamically allocated stack. This is for the sake of
1837 uniform overflow detection for all Valgrind threads. This is
1838 marked global even though it isn't, because assembly code below
1839 needs to reference the name. */
1840
1841/*static*/ VgStack VG_(interim_stack);
1842
1843/* This should get some address inside the stack on which we gained
1844 control (eg, it could be the SP at startup). It doesn't matter
1845 exactly where in the stack it is. This value is passed to the
1846 address space manager at startup, which uses it to identify the
1847 initial stack segment and hence the upper end of the usable address
1848 space. */
1849
1850static Addr sp_at_startup = 0;
1851
sewardj1ae3f3a2005-09-28 10:47:38 +00001852/* --- Forwards decls to do with shutdown --- */
1853
1854static void final_tidyup(ThreadId tid);
1855
1856/* Do everything which needs doing when the last thread exits */
1857static
1858void shutdown_actions_NORETURN( ThreadId tid,
1859 VgSchedReturnCode tids_schedretcode );
1860
1861/* --- end of Forwards decls to do with shutdown --- */
sewardjfdf91b42005-09-28 00:53:09 +00001862
1863
sewardj45f4e7c2005-09-27 19:20:21 +00001864/* TODO: GIVE THIS A PROPER HOME
1865 TODO: MERGE THIS WITH DUPLICATE IN mac_leakcheck.c
1866 Extract from aspacem a vector of the current segment start
1867 addresses. The vector is dynamically allocated and should be freed
1868 by the caller when done. REQUIRES m_mallocfree to be running.
1869 Writes the number of addresses required into *n_acquired. */
nethercotec314eba2004-07-15 12:59:41 +00001870
sewardj45f4e7c2005-09-27 19:20:21 +00001871static Addr* get_seg_starts ( /*OUT*/Int* n_acquired )
sewardj1cf558c2005-04-25 01:36:56 +00001872{
sewardj45f4e7c2005-09-27 19:20:21 +00001873 Addr* starts;
sewardja48a4932005-09-29 11:09:56 +00001874 Int n_starts, r = 0;
sewardj45f4e7c2005-09-27 19:20:21 +00001875
1876 n_starts = 1;
sewardj1cf558c2005-04-25 01:36:56 +00001877 while (True) {
sewardj45f4e7c2005-09-27 19:20:21 +00001878 starts = VG_(malloc)( n_starts * sizeof(Addr) );
1879 if (starts == NULL)
1880 break;
1881 r = VG_(am_get_segment_starts)( starts, n_starts );
1882 if (r >= 0)
1883 break;
1884 VG_(free)(starts);
1885 n_starts *= 2;
sewardj1cf558c2005-04-25 01:36:56 +00001886 }
sewardj45f4e7c2005-09-27 19:20:21 +00001887
1888 if (starts == NULL) {
1889 *n_acquired = 0;
1890 return NULL;
1891 }
1892
1893 *n_acquired = r;
1894 return starts;
sewardj1cf558c2005-04-25 01:36:56 +00001895}
1896
1897
sewardj45f4e7c2005-09-27 19:20:21 +00001898
sewardj45f4e7c2005-09-27 19:20:21 +00001899Int main(Int argc, HChar **argv, HChar **envp)
nethercote71980f02004-01-24 18:18:54 +00001900{
sewardj45f4e7c2005-09-27 19:20:21 +00001901 HChar* toolname = "memcheck"; // default to Memcheck
1902 HChar** env = NULL;
1903 Int need_help = 0; // 0 = no, 1 = --help, 2 = --help-debug
1904 Addr initial_client_IP = 0;
1905 Addr initial_client_SP = 0;
1906 Addr clstack_top = 0;
1907 SizeT clstack_max_size = 0;
1908 UInt* client_auxv;
1909 Int loglevel, i;
1910 Bool logging_to_fd;
nethercote73b526f2004-10-31 18:48:21 +00001911 struct vki_rlimit zero = { 0, 0 };
sewardj45f4e7c2005-09-27 19:20:21 +00001912 struct exeinfo info;
nethercote71980f02004-01-24 18:18:54 +00001913
1914 //============================================================
nethercote71980f02004-01-24 18:18:54 +00001915 //
sewardj45f4e7c2005-09-27 19:20:21 +00001916 // Nb: startup is complex. Prerequisites are shown at every step.
nethercote71980f02004-01-24 18:18:54 +00001917 // *** Be very careful when messing with the order ***
sewardj45f4e7c2005-09-27 19:20:21 +00001918 //
1919 // The first order of business is to get debug logging, the address
1920 // space manager and the dynamic memory manager up and running.
1921 // Once that's done, we can relax a bit.
1922 //
nethercote71980f02004-01-24 18:18:54 +00001923 //============================================================
sewardj45f4e7c2005-09-27 19:20:21 +00001924
1925 /* This is needed to make VG_(getenv) usable early. */
1926 VG_(client_envp) = (Char**)envp;
nethercote71980f02004-01-24 18:18:54 +00001927
sewardj1cf558c2005-04-25 01:36:56 +00001928 //--------------------------------------------------------------
1929 // Start up the logging mechanism
1930 // p: none
1931 //--------------------------------------------------------------
1932 /* Start the debugging-log system ASAP. First find out how many
1933 "-d"s were specified. This is a pre-scan of the command line. */
1934 loglevel = 0;
1935 for (i = 1; i < argc; i++) {
sewardj10759312005-05-30 23:52:47 +00001936 if (argv[i][0] != '-')
1937 break;
sewardj45f4e7c2005-09-27 19:20:21 +00001938 if (VG_STREQ(argv[i], "--"))
sewardj10759312005-05-30 23:52:47 +00001939 break;
sewardj45f4e7c2005-09-27 19:20:21 +00001940 if (VG_STREQ(argv[i], "-d"))
sewardj10759312005-05-30 23:52:47 +00001941 loglevel++;
sewardj1cf558c2005-04-25 01:36:56 +00001942 }
1943
1944 /* ... and start the debug logger. Now we can safely emit logging
1945 messages all through startup. */
sewardj10759312005-05-30 23:52:47 +00001946 VG_(debugLog_startup)(loglevel, "Stage 2 (main)");
sewardj45f4e7c2005-09-27 19:20:21 +00001947 VG_(debugLog)(1, "main", "Welcome to Valgrind version "
1948 VERSION " debug logging\n");
1949
1950 //--------------------------------------------------------------
1951 // Ensure we're on a plausible stack.
1952 // p: logging
1953 //--------------------------------------------------------------
1954 VG_(debugLog)(1, "main", "Checking current stack is plausible\n");
sewardjfdf91b42005-09-28 00:53:09 +00001955 { HChar* limLo = (HChar*)(&VG_(interim_stack).bytes[0]);
1956 HChar* limHi = limLo + sizeof(VG_(interim_stack));
sewardj45f4e7c2005-09-27 19:20:21 +00001957 HChar* aLocal = (HChar*)&zero; /* any auto local will do */
1958 if (aLocal < limLo || aLocal >= limHi) {
1959 /* something's wrong. Stop. */
1960 VG_(debugLog)(0, "main", "Root stack %p to %p, a local %p\n",
1961 limLo, limHi, aLocal );
1962 VG_(debugLog)(0, "main", "Valgrind: FATAL: "
1963 "Initial stack switched failed.\n");
1964 VG_(debugLog)(0, "main", " Cannot continue. Sorry.\n");
1965 VG_(exit)(1);
1966 }
1967 }
1968
1969 //--------------------------------------------------------------
1970 // Ensure we have a plausible pointer to the stack on which
1971 // we gained control (not the current stack!)
1972 // p: logging
1973 //--------------------------------------------------------------
1974 VG_(debugLog)(1, "main", "Checking initial stack was noted\n");
sewardjfdf91b42005-09-28 00:53:09 +00001975 if (sp_at_startup == 0) {
sewardj45f4e7c2005-09-27 19:20:21 +00001976 VG_(debugLog)(0, "main", "Valgrind: FATAL: "
1977 "Initial stack was not noted.\n");
1978 VG_(debugLog)(0, "main", " Cannot continue. Sorry.\n");
1979 VG_(exit)(1);
1980 }
1981
1982 //--------------------------------------------------------------
1983 // Start up the address space manager, and determine the
1984 // approximate location of the client's stack
1985 // p: logging, plausible-stack
1986 //--------------------------------------------------------------
1987 VG_(debugLog)(1, "main", "Starting the address space manager\n");
sewardjfdf91b42005-09-28 00:53:09 +00001988 clstack_top = VG_(am_startup)( sp_at_startup );
sewardj45f4e7c2005-09-27 19:20:21 +00001989 VG_(debugLog)(1, "main", "Address space manager is running\n");
1990
1991 //--------------------------------------------------------------
1992 // Start up the dynamic memory manager
1993 // p: address space management
1994 // In fact m_mallocfree is self-initialising, so there's no
1995 // initialisation call to do. Instead, try a simple malloc/
1996 // free pair right now to check that nothing is broken.
1997 //--------------------------------------------------------------
1998 VG_(debugLog)(1, "main", "Starting the dynamic memory manager\n");
1999 { void* p = VG_(malloc)( 12345 );
2000 if (p) VG_(free)( p );
2001 }
2002 VG_(debugLog)(1, "main", "Dynamic memory manager is running\n");
sewardj1cf558c2005-04-25 01:36:56 +00002003
nethercotef4928da2004-06-15 10:54:40 +00002004 //============================================================
sewardj45f4e7c2005-09-27 19:20:21 +00002005 //
2006 // Dynamic memory management is now available.
2007 //
nethercotef4928da2004-06-15 10:54:40 +00002008 //============================================================
2009
sewardj45f4e7c2005-09-27 19:20:21 +00002010 //--------------------------------------------------------------
2011 // Look for alternative libdir
2012 { HChar *cp = VG_(getenv)(VALGRIND_LIB);
2013 if (cp != NULL)
2014 VG_(libdir) = cp;
2015 }
2016
2017 //--------------------------------------------------------------
2018 // Extract the launcher name from the environment.
2019 VG_(debugLog)(1, "main", "Getting stage1's name\n");
2020 VG_(name_of_launcher) = VG_(getenv)(VALGRIND_LAUNCHER);
2021 if (VG_(name_of_launcher) == NULL) {
2022 VG_(printf)("valgrind: You cannot run '%s' directly.\n", argv[0]);
2023 VG_(printf)("valgrind: You should use $prefix/bin/valgrind.\n");
2024 VG_(exit)(1);
2025 }
2026
2027 //--------------------------------------------------------------
fitzhardingeb50068f2004-02-24 23:42:55 +00002028 // Get the current process datasize rlimit, and set it to zero.
2029 // This prevents any internal uses of brk() from having any effect.
2030 // We remember the old value so we can restore it on exec, so that
2031 // child processes will have a reasonable brk value.
2032 VG_(getrlimit)(VKI_RLIMIT_DATA, &VG_(client_rlimit_data));
2033 zero.rlim_max = VG_(client_rlimit_data).rlim_max;
2034 VG_(setrlimit)(VKI_RLIMIT_DATA, &zero);
thughesc37184f2004-09-11 14:16:57 +00002035
2036 // Get the current process stack rlimit.
2037 VG_(getrlimit)(VKI_RLIMIT_STACK, &VG_(client_rlimit_stack));
2038
sewardj45f4e7c2005-09-27 19:20:21 +00002039 //============================================================
2040 // Command line argument handling order:
2041 // * If --help/--help-debug are present, show usage message
2042 // (including the tool-specific usage)
2043 // * (If no --tool option given, default to Memcheck)
2044 // * Then, if client is missing, abort with error msg
2045 // * Then, if any cmdline args are bad, abort with error msg
2046 //============================================================
2047
2048 //--------------------------------------------------------------
2049 // Split up argv into: C args, V args, V extra args, and exename.
2050 // p: dynamic memory allocation
2051 //--------------------------------------------------------------
2052 VG_(debugLog)(1, "main", "Split up command line\n");
2053 VG_(split_up_argv)( argc, argv );
2054 if (0) {
2055 for (i = 0; i < VG_(args_for_valgrind).used; i++)
2056 VG_(printf)("varg %s\n", VG_(args_for_valgrind).strs[i]);
2057 VG_(printf)(" exe %s\n", VG_(args_the_exename));
2058 for (i = 0; i < VG_(args_for_client).used; i++)
2059 VG_(printf)("carg %s\n", VG_(args_for_client).strs[i]);
nethercote71980f02004-01-24 18:18:54 +00002060 }
2061
2062 //--------------------------------------------------------------
sewardj45f4e7c2005-09-27 19:20:21 +00002063 // Extract tool name and whether help has been requested.
2064 // Note we can't print the help message yet, even if requested,
2065 // because the tool has not been initialised.
2066 // p: split_up_argv [for VG_(args_for_valgrind)]
nethercote71980f02004-01-24 18:18:54 +00002067 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002068 VG_(debugLog)(1, "main", "Preprocess command line opts\n");
sewardj45f4e7c2005-09-27 19:20:21 +00002069 get_helprequest_and_toolname(&need_help, &toolname);
nethercote71980f02004-01-24 18:18:54 +00002070
sewardj45f4e7c2005-09-27 19:20:21 +00002071 // Set default vex control params
2072 LibVEX_default_VexControl(& VG_(clo_vex_control));
nethercote71980f02004-01-24 18:18:54 +00002073
2074 //--------------------------------------------------------------
2075 // Load client executable, finding in $PATH if necessary
sewardj45f4e7c2005-09-27 19:20:21 +00002076 // p: get_helprequest_and_toolname() [for 'exec', 'need_help']
nethercote71980f02004-01-24 18:18:54 +00002077 // p: layout_remaining_space [so there's space]
2078 //--------------------------------------------------------------
sewardj45f4e7c2005-09-27 19:20:21 +00002079 if (!need_help) {
2080 VG_(debugLog)(1, "main", "Loading client\n");
nethercote71980f02004-01-24 18:18:54 +00002081
sewardj45f4e7c2005-09-27 19:20:21 +00002082 if (VG_(args_the_exename) == NULL)
2083 missing_prog();
2084
2085 load_client(&info, &initial_client_IP);
2086 }
nethercote71980f02004-01-24 18:18:54 +00002087
2088 //--------------------------------------------------------------
2089 // Set up client's environment
sewardj45f4e7c2005-09-27 19:20:21 +00002090 // p: set-libdir [for VG_(libdir)]
2091 // p: get_helprequest_and_toolname [for toolname]
nethercote71980f02004-01-24 18:18:54 +00002092 //--------------------------------------------------------------
sewardj45f4e7c2005-09-27 19:20:21 +00002093 if (!need_help) {
2094 VG_(debugLog)(1, "main", "Setup client env\n");
2095 env = setup_client_env(envp, toolname);
2096 }
nethercote71980f02004-01-24 18:18:54 +00002097
2098 //--------------------------------------------------------------
nethercote5ee67ca2004-06-22 14:00:09 +00002099 // Setup client stack, eip, and VG_(client_arg[cv])
nethercote71980f02004-01-24 18:18:54 +00002100 // p: load_client() [for 'info']
2101 // p: fix_environment() [for 'env']
2102 //--------------------------------------------------------------
sewardj45f4e7c2005-09-27 19:20:21 +00002103 if (!need_help) {
2104 void* init_sp = argv - 1;
2105 SizeT m1 = 1024 * 1024;
2106 SizeT m8 = 8 * m1;
2107 VG_(debugLog)(1, "main", "Setup client stack\n");
2108 clstack_max_size = (SizeT)VG_(client_rlimit_stack).rlim_cur;
2109 if (clstack_max_size < m1) clstack_max_size = m1;
2110 if (clstack_max_size > m8) clstack_max_size = m8;
2111 clstack_max_size = VG_PGROUNDUP(clstack_max_size);
sewardjb5f6f512005-03-10 23:59:00 +00002112
sewardj45f4e7c2005-09-27 19:20:21 +00002113 initial_client_SP
2114 = setup_client_stack( init_sp, env,
2115 &info, &client_auxv,
2116 clstack_top, clstack_max_size );
2117
2118 VG_(free)(env);
2119
2120 VG_(debugLog)(2, "main",
2121 "Client info: "
sewardja48a4932005-09-29 11:09:56 +00002122 "initial_IP=%p initial_SP=%p brk_base=%p\n",
sewardj45f4e7c2005-09-27 19:20:21 +00002123 (void*)initial_client_IP,
2124 (void*)initial_client_SP,
2125 (void*)VG_(brk_base) );
nethercotec25c4492004-10-18 11:52:17 +00002126 }
nethercote71980f02004-01-24 18:18:54 +00002127
sewardj45f4e7c2005-09-27 19:20:21 +00002128 //--------------------------------------------------------------
2129 // Setup client data (brk) segment. Initially a 1-page segment
2130 // which abuts a shrinkable reservation.
2131 // p: load_client() [for 'info' and hence VG_(brk_base)]
2132 //--------------------------------------------------------------
2133 if (!need_help) {
2134 SizeT m1 = 1024 * 1024;
2135 SizeT m8 = 8 * m1;
2136 SizeT dseg_max_size = (SizeT)VG_(client_rlimit_data).rlim_cur;
2137 VG_(debugLog)(1, "main", "Setup client data (brk) segment\n");
2138 if (dseg_max_size < m1) dseg_max_size = m1;
2139 if (dseg_max_size > m8) dseg_max_size = m8;
2140 dseg_max_size = VG_PGROUNDUP(dseg_max_size);
2141
2142 setup_client_dataseg( dseg_max_size );
2143 }
nethercote71980f02004-01-24 18:18:54 +00002144
2145 //==============================================================
sewardj45f4e7c2005-09-27 19:20:21 +00002146 //
2147 // Finished loading/setting up the client address space.
2148 //
nethercote71980f02004-01-24 18:18:54 +00002149 //==============================================================
2150
2151 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002152 // setup file descriptors
2153 // p: n/a
2154 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002155 VG_(debugLog)(1, "main", "Setup file descriptors\n");
nethercote71980f02004-01-24 18:18:54 +00002156 setup_file_descriptors();
2157
2158 //--------------------------------------------------------------
sewardj45f4e7c2005-09-27 19:20:21 +00002159 // create the fake /proc/<pid>/cmdline file and then unlink it,
2160 // but hold onto the fd, so we can hand it out to the client
2161 // when it tries to open /proc/<pid>/cmdline for itself.
2162 // p: setup file descriptors
nethercotec314eba2004-07-15 12:59:41 +00002163 //--------------------------------------------------------------
sewardj45f4e7c2005-09-27 19:20:21 +00002164 if (!need_help) {
2165 HChar buf[50], buf2[50+64];
2166 HChar nul[1];
2167 Int fd, r;
2168 HChar* exename;
nethercotec314eba2004-07-15 12:59:41 +00002169
sewardj45f4e7c2005-09-27 19:20:21 +00002170 VG_(debugLog)(1, "main", "Create fake /proc/<pid>/cmdline\n");
2171
2172 VG_(sprintf)(buf, "proc_%d_cmdline", VG_(getpid)());
2173 fd = VG_(mkstemp)( buf, buf2 );
2174 if (fd == -1)
2175 config_error("Can't create client cmdline file in /tmp.");
2176
2177 nul[0] = 0;
2178 exename = VG_(args_the_exename) ? VG_(args_the_exename)
2179 : "unknown_exename";
2180
2181 VG_(write)(fd, VG_(args_the_exename),
2182 VG_(strlen)( VG_(args_the_exename) ));
2183 VG_(write)(fd, nul, 1);
2184
2185 for (i = 0; i < VG_(args_for_client).used; i++) {
2186 VG_(write)(fd, VG_(args_for_client).strs[i],
2187 VG_(strlen)( VG_(args_for_client).strs[i] ));
2188 VG_(write)(fd, nul, 1);
2189 }
2190
2191 /* Don't bother to seek the file back to the start; instead do
2192 it every time a copy of it is given out (by PRE(sys_open)).
2193 That is probably more robust across fork() etc. */
2194
2195 /* Now delete it, but hang on to the fd. */
2196 r = VG_(unlink)( buf2 );
2197 if (r)
2198 config_error("Can't delete client cmdline file in /tmp.");
2199
2200 VG_(cl_cmdline_fd) = fd;
2201 }
nethercotec314eba2004-07-15 12:59:41 +00002202
2203 //--------------------------------------------------------------
sewardj45f4e7c2005-09-27 19:20:21 +00002204 // Init tool part 1: pre_clo_init
nethercotec314eba2004-07-15 12:59:41 +00002205 // p: setup_client_stack() [for 'VG_(client_arg[cv]']
nethercotec314eba2004-07-15 12:59:41 +00002206 // p: setup_file_descriptors() [for 'VG_(fd_xxx_limit)']
nethercote71980f02004-01-24 18:18:54 +00002207 //--------------------------------------------------------------
njn64c83242005-06-21 01:54:38 +00002208 {
2209 Char* s;
2210 Bool ok;
sewardj45f4e7c2005-09-27 19:20:21 +00002211 VG_(debugLog)(1, "main", "Initialise the tool part 1 (pre_clo_init)\n");
2212 (VG_(tool_info).tl_pre_clo_init)();
2213 ok = VG_(sanity_check_needs)( &s );
njn64c83242005-06-21 01:54:38 +00002214 if (!ok) {
2215 VG_(tool_panic)(s);
2216 }
2217 }
nethercote71980f02004-01-24 18:18:54 +00002218
sewardj45f4e7c2005-09-27 19:20:21 +00002219 //--------------------------------------------------------------
nethercotef4928da2004-06-15 10:54:40 +00002220 // If --tool and --help/--help-debug was given, now give the core+tool
2221 // help message
sewardj45f4e7c2005-09-27 19:20:21 +00002222 // p: get_helprequest_and_toolname() [for 'need_help']
2223 // p: tl_pre_clo_init [for 'VG_(tdict).usage']
2224 //--------------------------------------------------------------
2225 VG_(debugLog)(1, "main", "Print help and quit, if requested\n");
nethercotef4928da2004-06-15 10:54:40 +00002226 if (need_help) {
sewardj45f4e7c2005-09-27 19:20:21 +00002227 usage_NORETURN(/*--help-debug?*/2 == need_help);
nethercotef4928da2004-06-15 10:54:40 +00002228 }
nethercotec314eba2004-07-15 12:59:41 +00002229
sewardj45f4e7c2005-09-27 19:20:21 +00002230 //--------------------------------------------------------------
2231 // Process command line options to Valgrind + tool
2232 // p: setup_client_stack() [for 'VG_(client_arg[cv]']
2233 // p: setup_file_descriptors() [for 'VG_(fd_xxx_limit)']
2234 //--------------------------------------------------------------
2235 VG_(debugLog)(1, "main", "Process Valgrind's command line options, "
sewardja48a4932005-09-29 11:09:56 +00002236 "setup logging\n");
sewardj45f4e7c2005-09-27 19:20:21 +00002237 logging_to_fd = process_cmd_line_options(client_auxv, toolname);
2238
2239 //--------------------------------------------------------------
2240 // Print the preamble
2241 // p: tl_pre_clo_init [for 'VG_(details).name' and friends]
2242 // p: process_cmd_line_options() [for VG_(clo_verbosity), VG_(clo_xml),
2243 // VG_(clo_log_file_qualifier),
2244 // logging_to_fd]
2245 //--------------------------------------------------------------
2246 VG_(debugLog)(1, "main", "Print the preamble...\n");
2247 print_preamble(logging_to_fd, toolname);
2248 VG_(debugLog)(1, "main", "...finished the preamble\n");
2249
2250 //--------------------------------------------------------------
2251 // Init tool part 2: post_clo_init
2252 // p: setup_client_stack() [for 'VG_(client_arg[cv]']
2253 // p: setup_file_descriptors() [for 'VG_(fd_xxx_limit)']
2254 // p: print_preamble() [so any warnings printed in post_clo_init
2255 // are shown after the preamble]
2256 //--------------------------------------------------------------
2257 VG_(debugLog)(1, "main", "Initialise the tool part 2 (post_clo_init)\n");
njn51d827b2005-05-09 01:02:08 +00002258 VG_TDICT_CALL(tool_post_clo_init);
nethercotef4928da2004-06-15 10:54:40 +00002259
2260 //--------------------------------------------------------------
sewardj45f4e7c2005-09-27 19:20:21 +00002261 // Initialise translation table and translation cache
2262 // p: aspacem [??]
2263 // p: tl_pre_clo_init [for 'VG_(details).avg_translation_sizeB']
nethercote71980f02004-01-24 18:18:54 +00002264 //--------------------------------------------------------------
sewardj45f4e7c2005-09-27 19:20:21 +00002265 VG_(debugLog)(1, "main", "Initialise TT/TC\n");
2266 VG_(init_tt_tc)();
sewardjb5f6f512005-03-10 23:59:00 +00002267
sewardj45f4e7c2005-09-27 19:20:21 +00002268 //--------------------------------------------------------------
2269 // Initialise the redirect table.
2270 // p: init_tt_tc [so it can call VG_(search_transtab) safely]
2271 // p: aspacem [so can change ownership of sysinfo pages]
2272 //--------------------------------------------------------------
2273 VG_(debugLog)(1, "main", "Initialise redirects\n");
2274 VG_(setup_code_redirect_table)();
nethercote71980f02004-01-24 18:18:54 +00002275
2276 //--------------------------------------------------------------
2277 // Allow GDB attach
2278 // p: process_cmd_line_options() [for VG_(clo_wait_for_gdb)]
2279 //--------------------------------------------------------------
2280 /* Hook to delay things long enough so we can get the pid and
2281 attach GDB in another shell. */
2282 if (VG_(clo_wait_for_gdb)) {
sewardj8211a572005-06-23 21:37:47 +00002283 Long q, iters;
sewardj1fbc1a52005-04-25 02:05:54 +00002284 VG_(debugLog)(1, "main", "Wait for GDB\n");
sewardj93ab8572005-02-06 14:10:40 +00002285 VG_(printf)("pid=%d, entering delay loop\n", VG_(getpid)());
2286 /* jrs 20050206: I don't understand why this works on x86. On
2287 amd64 the obvious analogues (jump *$rip or jump *$rcx) don't
2288 work. */
2289 /* do "jump *$eip" to skip this in gdb (x86) */
2290 //VG_(do_syscall0)(__NR_pause);
sewardj8211a572005-06-23 21:37:47 +00002291
2292# if defined(VGP_x86_linux)
2293 iters = 5;
2294# elif defined(VGP_amd64_linux)
2295 iters = 10;
2296# elif defined(VGP_ppc32_linux)
sewardjd714d2e2005-07-08 18:24:04 +00002297 iters = 5;
sewardj8211a572005-06-23 21:37:47 +00002298# else
2299# error "Unknown plat"
2300# endif
2301
2302 iters *= 1000*1000*1000;
2303 for (q = 0; q < iters; q++)
2304 ;
nethercote71980f02004-01-24 18:18:54 +00002305 }
2306
sewardjb5d320c2005-03-13 18:57:15 +00002307 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002308 // Search for file descriptors that are inherited from our parent
2309 // p: process_cmd_line_options [for VG_(clo_track_fds)]
2310 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002311 if (VG_(clo_track_fds)) {
2312 VG_(debugLog)(1, "main", "Init preopened fds\n");
nethercote71980f02004-01-24 18:18:54 +00002313 VG_(init_preopened_fds)();
sewardj1fbc1a52005-04-25 02:05:54 +00002314 }
nethercote71980f02004-01-24 18:18:54 +00002315
2316 //--------------------------------------------------------------
sewardj45f4e7c2005-09-27 19:20:21 +00002317 // Load debug info for the existing segments.
2318 // p: setup_code_redirect_table [so that redirs can be recorded]
2319 // p: mallocfree
2320 // p: probably: setup fds and process CLOs, so that logging works
2321 //--------------------------------------------------------------
2322 VG_(debugLog)(1, "main", "Load initial debug info\n");
2323 { Addr* seg_starts;
2324 Int n_seg_starts;
2325
2326 seg_starts = get_seg_starts( &n_seg_starts );
2327 vg_assert(seg_starts && n_seg_starts > 0);
2328
2329 /* show them all to the debug info reader */
2330 for (i = 0; i < n_seg_starts; i++)
2331 VG_(di_notify_mmap)( seg_starts[i] );
2332
2333 VG_(free)( seg_starts );
2334 }
2335
2336 //--------------------------------------------------------------
2337 // Tell aspacem of ownership change of the asm helpers, so that
2338 // m_translate allows them to be translated. However, only do this
2339 // after the initial debug info read, since making a hole in the
2340 // address range for the stage2 binary confuses the debug info reader.
2341 // p: aspacem
2342 //--------------------------------------------------------------
2343 { Bool change_ownership_v_c_OK;
2344 Addr co_start = VG_PGROUNDDN( (Addr)&VG_(trampoline_stuff_start) );
2345 Addr co_endPlus = VG_PGROUNDUP( (Addr)&VG_(trampoline_stuff_end) );
2346 VG_(debugLog)(1,"redir",
2347 "transfer ownership V -> C of 0x%llx .. 0x%llx\n",
2348 (ULong)co_start, (ULong)co_endPlus-1 );
2349
2350 change_ownership_v_c_OK
2351 = VG_(am_change_ownership_v_to_c)( co_start, co_endPlus - co_start );
2352 vg_assert(change_ownership_v_c_OK);
2353 }
2354
2355 //--------------------------------------------------------------
2356 // Tell the tool about the initial client memory permissions
2357 // p: aspacem
2358 // p: mallocfree
2359 // p: setup_client_stack
2360 // p: setup_client_dataseg
2361 //--------------------------------------------------------------
2362 VG_(debugLog)(1, "main", "Tell tool about initial permissions\n");
2363 { Addr* seg_starts;
2364 Int n_seg_starts;
2365 NSegment* seg;
2366
2367 seg_starts = get_seg_starts( &n_seg_starts );
2368 vg_assert(seg_starts && n_seg_starts > 0);
2369
2370 /* show interesting ones to the tool */
2371 for (i = 0; i < n_seg_starts; i++) {
2372 seg = VG_(am_find_nsegment)( seg_starts[i] );
2373 vg_assert(seg);
2374 if (seg->kind == SkFileC || seg->kind == SkAnonC) {
2375 VG_(debugLog)(2, "main",
2376 "tell tool about %010lx-%010lx %c%c%c\n",
2377 seg->start, seg->end,
2378 seg->hasR ? 'r' : '-',
2379 seg->hasW ? 'w' : '-',
2380 seg->hasX ? 'x' : '-' );
2381 VG_TRACK( new_mem_startup, seg->start, seg->end+1-seg->start,
2382 seg->hasR, seg->hasW, seg->hasX );
2383 }
2384 }
2385
2386 VG_(free)( seg_starts );
2387
2388 /* Also do the initial stack permissions. */
2389 seg = VG_(am_find_nsegment)( initial_client_SP );
2390 vg_assert(seg);
2391 vg_assert(seg->kind == SkAnonC);
2392 vg_assert(initial_client_SP >= seg->start);
2393 vg_assert(initial_client_SP <= seg->end);
2394
2395 /* Stuff below the initial SP is unaddressable. */
2396 /* NB: shouldn't this take into account the VG_STACK_REDZONE_SZB
2397 bytes below SP? */
2398 VG_TRACK( die_mem_stack, seg->start, initial_client_SP - seg->start );
2399 VG_(debugLog)(2, "main", "mark stack inaccessible %010lx-%010lx\n",
2400 seg->start, initial_client_SP-1 );
2401
2402 /* Also the assembly helpers. */
2403 VG_TRACK( new_mem_startup,
2404 (Addr)&VG_(trampoline_stuff_start),
2405 &VG_(trampoline_stuff_end) - &VG_(trampoline_stuff_start),
2406 False, /* readable? */
2407 False, /* writable? */
2408 True /* executable? */ );
2409 }
2410
2411 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002412 // Initialise the scheduler
nethercote71980f02004-01-24 18:18:54 +00002413 // p: setup_file_descriptors() [else VG_(safe_fd)() breaks]
sewardj45f4e7c2005-09-27 19:20:21 +00002414 // p: setup_client_stack
nethercote71980f02004-01-24 18:18:54 +00002415 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002416 VG_(debugLog)(1, "main", "Initialise scheduler\n");
sewardj45f4e7c2005-09-27 19:20:21 +00002417 { NSegment* seg = VG_(am_find_nsegment)( initial_client_SP );
2418 vg_assert(seg);
2419 vg_assert(seg->kind == SkAnonC);
2420 vg_assert(initial_client_SP >= seg->start);
2421 vg_assert(initial_client_SP <= seg->end);
2422 VG_(scheduler_init)( seg->end, clstack_max_size );
2423 }
nethercote71980f02004-01-24 18:18:54 +00002424
2425 //--------------------------------------------------------------
sewardjb5f6f512005-03-10 23:59:00 +00002426 // Initialise the pthread model
2427 // p: ?
sewardj2a99cf62004-11-24 10:44:19 +00002428 // load_client() [for 'client_eip']
2429 // setup_client_stack() [for 'sp_at_startup']
2430 // setup_scheduler() [for the rest of state 1 stuff]
2431 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002432 VG_(debugLog)(1, "main", "Initialise thread 1's state\n");
sewardj45f4e7c2005-09-27 19:20:21 +00002433 init_thread1state( initial_client_IP, initial_client_SP,
2434 &VG_(threads)[1].arch);
njnea4b28c2004-11-30 16:04:58 +00002435
sewardj2a99cf62004-11-24 10:44:19 +00002436 //--------------------------------------------------------------
sewardj39b88fb2005-03-12 15:16:07 +00002437 // Initialise the pthread model
2438 // p: ?
nethercote71980f02004-01-24 18:18:54 +00002439 //--------------------------------------------------------------
sewardjb5f6f512005-03-10 23:59:00 +00002440 //if (VG_(clo_model_pthreads))
2441 // VG_(pthread_init)();
nethercote71980f02004-01-24 18:18:54 +00002442
2443 //--------------------------------------------------------------
2444 // Initialise the signal handling subsystem
sewardjb5f6f512005-03-10 23:59:00 +00002445 // p: n/a
nethercote71980f02004-01-24 18:18:54 +00002446 //--------------------------------------------------------------
2447 // Nb: temporarily parks the saved blocking-mask in saved_sigmask.
sewardj1fbc1a52005-04-25 02:05:54 +00002448 VG_(debugLog)(1, "main", "Initialise signal management\n");
nethercote71980f02004-01-24 18:18:54 +00002449 VG_(sigstartup_actions)();
2450
2451 //--------------------------------------------------------------
2452 // Perhaps we're profiling Valgrind?
2453 // p: process_cmd_line_options() [for VG_(clo_profile)]
2454 // p: others?
2455 //
2456 // XXX: this seems to be broken? It always says the tool wasn't built
2457 // for profiling; vg_profile.c's functions don't seem to be overriding
2458 // vg_dummy_profile.c's?
2459 //
2460 // XXX: want this as early as possible. Looking for --profile
sewardj45f4e7c2005-09-27 19:20:21 +00002461 // in get_helprequest_and_toolname() could get it earlier.
nethercote71980f02004-01-24 18:18:54 +00002462 //--------------------------------------------------------------
2463 if (VG_(clo_profile))
njn31066fd2005-03-26 00:42:02 +00002464 VG_(init_profiling)();
nethercote71980f02004-01-24 18:18:54 +00002465
2466 VGP_PUSHCC(VgpStartup);
2467
2468 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002469 // Read suppression file
2470 // p: process_cmd_line_options() [for VG_(clo_suppressions)]
2471 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002472 if (VG_(needs).core_errors || VG_(needs).tool_errors) {
2473 VG_(debugLog)(1, "main", "Load suppressions\n");
nethercote71980f02004-01-24 18:18:54 +00002474 VG_(load_suppressions)();
sewardj1fbc1a52005-04-25 02:05:54 +00002475 }
nethercote71980f02004-01-24 18:18:54 +00002476
2477 //--------------------------------------------------------------
rjwalsh0140af52005-06-04 20:42:33 +00002478 // register client stack
2479 //--------------------------------------------------------------
njn945ed2e2005-06-24 03:28:30 +00002480 VG_(clstk_id) = VG_(register_stack)(VG_(clstk_base), VG_(clstk_end));
rjwalsh0140af52005-06-04 20:42:33 +00002481
2482 //--------------------------------------------------------------
sewardj45f4e7c2005-09-27 19:20:21 +00002483 // Show the address space state so far
2484 //--------------------------------------------------------------
2485 VG_(debugLog)(1, "main", "\n");
2486 VG_(debugLog)(1, "main", "\n");
2487 VG_(am_show_nsegments)(1,"Memory layout at client startup");
2488 VG_(debugLog)(1, "main", "\n");
2489 VG_(debugLog)(1, "main", "\n");
2490
2491 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002492 // Run!
2493 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002494 VGP_POPCC(VgpStartup);
nethercote71980f02004-01-24 18:18:54 +00002495
sewardj71bc3cb2005-05-19 00:25:45 +00002496 if (VG_(clo_xml)) {
sewardj68cde6f2005-07-19 12:17:51 +00002497 HChar buf[50];
2498 VG_(ctime)(buf);
sewardj753673f2005-08-09 22:03:08 +00002499 VG_(message)(Vg_UserMsg, "<status>\n"
2500 " <state>RUNNING</state>\n"
2501 " <time>%t</time>\n"
2502 "</status>",
2503 buf);
sewardj71bc3cb2005-05-19 00:25:45 +00002504 VG_(message)(Vg_UserMsg, "");
2505 }
2506
sewardj1fbc1a52005-04-25 02:05:54 +00002507 VG_(debugLog)(1, "main", "Running thread 1\n");
sewardj1ae3f3a2005-09-28 10:47:38 +00002508
sewardj1d887112005-05-30 21:44:08 +00002509 /* As a result of the following call, the last thread standing
sewardj1ae3f3a2005-09-28 10:47:38 +00002510 eventually winds up running shutdown_actions_NORETURN
2511 just below. Unfortunately, simply exporting said function
2512 causes m_main to be part of a module cycle, which is pretty
2513 nonsensical. So instead of doing that, the address of said
2514 function is stored in a global variable 'owned' by m_syswrap,
2515 and it uses that function pointer to get back here when it needs
2516 to. */
2517
2518 /* Set continuation address. */
2519 VG_(address_of_m_main_shutdown_actions_NORETURN)
2520 = & shutdown_actions_NORETURN;
2521
2522 /* Run the first thread, eventually ending up at the continuation
2523 address. */
njnaf839f52005-06-23 03:27:57 +00002524 VG_(main_thread_wrapper_NORETURN)(1);
nethercote71980f02004-01-24 18:18:54 +00002525
sewardj1d887112005-05-30 21:44:08 +00002526 /*NOTREACHED*/
2527 vg_assert(0);
sewardjb5f6f512005-03-10 23:59:00 +00002528}
2529
sewardj1ae3f3a2005-09-28 10:47:38 +00002530/* Do everything which needs doing when the last thread exits. */
sewardjb5f6f512005-03-10 23:59:00 +00002531
sewardj1ae3f3a2005-09-28 10:47:38 +00002532static
2533void shutdown_actions_NORETURN( ThreadId tid,
2534 VgSchedReturnCode tids_schedretcode )
sewardjb5f6f512005-03-10 23:59:00 +00002535{
sewardj1d887112005-05-30 21:44:08 +00002536 VG_(debugLog)(1, "main", "entering VG_(shutdown_actions_NORETURN)\n");
2537
2538 vg_assert( VG_(count_living_threads)() == 1 );
sewardjb5f6f512005-03-10 23:59:00 +00002539 vg_assert(VG_(is_running_thread)(tid));
2540
2541 // Wait for all other threads to exit.
njn7b85dd52005-06-12 17:26:29 +00002542 VG_(reap_threads)(tid);
sewardjb5f6f512005-03-10 23:59:00 +00002543
2544 VG_(clo_model_pthreads) = False;
2545
2546 // Clean the client up before the final report
njn9cb54ac2005-06-12 04:19:17 +00002547 final_tidyup(tid);
sewardjb5f6f512005-03-10 23:59:00 +00002548
2549 // OK, done
2550 VG_(exit_thread)(tid);
2551
2552 /* should be no threads left */
2553 vg_assert(VG_(count_living_threads)() == 0);
2554
2555 VG_(threads)[tid].status = VgTs_Empty;
nethercote71980f02004-01-24 18:18:54 +00002556 //--------------------------------------------------------------
2557 // Finalisation: cleanup, messages, etc. Order no so important, only
2558 // affects what order the messages come.
2559 //--------------------------------------------------------------
2560 if (VG_(clo_verbosity) > 0)
2561 VG_(message)(Vg_UserMsg, "");
2562
sewardj71bc3cb2005-05-19 00:25:45 +00002563 if (VG_(clo_xml)) {
sewardj68cde6f2005-07-19 12:17:51 +00002564 HChar buf[50];
sewardj9f297ca2005-05-20 02:29:52 +00002565 if (VG_(needs).core_errors || VG_(needs).tool_errors) {
2566 VG_(show_error_counts_as_XML)();
2567 VG_(message)(Vg_UserMsg, "");
2568 }
sewardj68cde6f2005-07-19 12:17:51 +00002569 VG_(ctime)(buf);
sewardj753673f2005-08-09 22:03:08 +00002570 VG_(message)(Vg_UserMsg, "<status>\n"
2571 " <state>FINISHED</state>\n"
2572 " <time>%t</time>\n"
2573 "</status>",
2574 buf);
sewardj71bc3cb2005-05-19 00:25:45 +00002575 VG_(message)(Vg_UserMsg, "");
2576 }
2577
nethercote71980f02004-01-24 18:18:54 +00002578 /* Print out file descriptor summary and stats. */
2579 if (VG_(clo_track_fds))
nethercote3a42fb82004-08-03 18:08:50 +00002580 VG_(show_open_fds)();
nethercote71980f02004-01-24 18:18:54 +00002581
njn95ec8702004-11-22 16:46:13 +00002582 if (VG_(needs).core_errors || VG_(needs).tool_errors)
nethercote71980f02004-01-24 18:18:54 +00002583 VG_(show_all_errors)();
2584
njn51d827b2005-05-09 01:02:08 +00002585 VG_TDICT_CALL(tool_fini, 0/*exitcode*/);
nethercote71980f02004-01-24 18:18:54 +00002586
sewardj71bc3cb2005-05-19 00:25:45 +00002587 if (VG_(clo_xml)) {
2588 VG_(message)(Vg_UserMsg, "");
2589 VG_(message)(Vg_UserMsg, "</valgrindoutput>");
2590 VG_(message)(Vg_UserMsg, "");
2591 }
2592
nethercote885dd912004-08-03 23:14:00 +00002593 VG_(sanity_check_general)( True /*include expensive checks*/ );
nethercote71980f02004-01-24 18:18:54 +00002594
2595 if (VG_(clo_verbosity) > 1)
nethercote3a42fb82004-08-03 18:08:50 +00002596 print_all_stats();
nethercote71980f02004-01-24 18:18:54 +00002597
nethercote71980f02004-01-24 18:18:54 +00002598 if (VG_(clo_profile))
njn31066fd2005-03-26 00:42:02 +00002599 VG_(done_profiling)();
njn2025cf92005-06-26 20:44:48 +00002600
2601 if (VG_(clo_profile_flags) > 0) {
2602 #define N_MAX 100
2603 BBProfEntry tops[N_MAX];
2604 ULong score_total = VG_(get_BB_profile) (tops, N_MAX);
2605 show_BB_profile(tops, N_MAX, score_total);
2606 }
sewardjfa8ec112005-01-19 11:55:34 +00002607
sewardj8b635a42004-11-22 19:01:47 +00002608 /* Print Vex storage stats */
sewardjbf426512005-01-17 18:35:30 +00002609 if (0)
2610 LibVEX_ShowAllocStats();
sewardj1d887112005-05-30 21:44:08 +00002611
njn8aa35852005-06-10 22:59:56 +00002612 /* Ok, finally exit in the os-specific way, according to the scheduler's
2613 return code. In short, if the (last) thread exited by calling
2614 sys_exit, do likewise; if the (last) thread stopped due to a fatal
2615 signal, terminate the entire system with that same fatal signal. */
2616 VG_(debugLog)(1, "core_os",
njn7b85dd52005-06-12 17:26:29 +00002617 "VG_(terminate_NORETURN)(tid=%lld)\n", (ULong)tid);
njn8aa35852005-06-10 22:59:56 +00002618
2619 vg_assert(VG_(count_living_threads)() == 0);
2620
2621 switch (tids_schedretcode) {
2622 case VgSrc_ExitSyscall: /* the normal way out */
2623 VG_(exit)( VG_(threads)[tid].os_state.exitcode );
2624 /* NOT ALIVE HERE! */
2625 VG_(core_panic)("entered the afterlife in main() -- ExitSyscall");
2626 break; /* what the hell :) */
2627
2628 case VgSrc_FatalSig:
2629 /* We were killed by a fatal signal, so replicate the effect */
2630 vg_assert(VG_(threads)[tid].os_state.fatalsig != 0);
2631 VG_(kill_self)(VG_(threads)[tid].os_state.fatalsig);
2632 VG_(core_panic)("main(): signal was supposed to be fatal");
2633 break;
2634
2635 default:
2636 VG_(core_panic)("main(): unexpected scheduler return code");
2637 }
njne96be672005-05-08 19:08:54 +00002638}
sewardj8b635a42004-11-22 19:01:47 +00002639
sewardj1ae3f3a2005-09-28 10:47:38 +00002640/* -------------------- */
2641
2642/* Final clean-up before terminating the process.
2643 Clean up the client by calling __libc_freeres() (if requested)
2644 This is Linux-specific?
2645*/
2646static void final_tidyup(ThreadId tid)
2647{
2648 Addr __libc_freeres_wrapper;
2649
2650 vg_assert(VG_(is_running_thread)(tid));
2651
2652 if ( !VG_(needs).libc_freeres ||
2653 !VG_(clo_run_libc_freeres) ||
2654 0 == (__libc_freeres_wrapper = VG_(get_libc_freeres_wrapper)()) )
2655 return; /* can't/won't do it */
2656
2657 if (VG_(clo_verbosity) > 2 ||
2658 VG_(clo_trace_syscalls) ||
2659 VG_(clo_trace_sched))
2660 VG_(message)(Vg_DebugMsg,
2661 "Caught __NR_exit; running __libc_freeres()");
2662
2663 /* point thread context to point to libc_freeres_wrapper */
2664 VG_(set_IP)(tid, __libc_freeres_wrapper);
2665 // XXX should we use a special stack?
2666
2667 /* Block all blockable signals by copying the real block state into
2668 the thread's block state*/
2669 VG_(sigprocmask)(VKI_SIG_BLOCK, NULL, &VG_(threads)[tid].sig_mask);
2670 VG_(threads)[tid].tmp_sig_mask = VG_(threads)[tid].sig_mask;
2671
2672 /* and restore handlers to default */
2673 VG_(set_default_handler)(VKI_SIGSEGV);
2674 VG_(set_default_handler)(VKI_SIGBUS);
2675 VG_(set_default_handler)(VKI_SIGILL);
2676 VG_(set_default_handler)(VKI_SIGFPE);
2677
2678 // We were exiting, so assert that...
2679 vg_assert(VG_(is_exiting)(tid));
2680 // ...but now we're not again
2681 VG_(threads)[tid].exitreason = VgSrc_None;
2682
2683 // run until client thread exits - ideally with LIBC_FREERES_DONE,
2684 // but exit/exitgroup/signal will do
2685 VG_(scheduler)(tid);
2686
2687 vg_assert(VG_(is_exiting)(tid));
2688}
2689
sewardj45f4e7c2005-09-27 19:20:21 +00002690
2691/*====================================================================*/
2692/*=== Getting to main() alive ===*/
2693/*====================================================================*/
2694
2695/* If linking of the final executables is done with glibc present,
2696 then Valgrind starts at main() above as usual, and all of the
2697 following code is irrelevant.
2698
2699 However, this is not the intended mode of use. The plan is to
2700 avoid linking against glibc, by giving gcc the flags
2701 -nodefaultlibs -lgcc -nostartfiles at startup.
2702
2703 From this derive two requirements:
2704
2705 1. gcc may emit calls to memcpy and memset to deal with structure
2706 assignments etc. Since we have chosen to ignore all the
2707 "normal" supporting libraries, we have to provide our own
2708 implementations of them. No problem.
2709
2710 2. We have to provide a symbol "_start", to which the kernel
2711 hands control at startup. Hence the code below.
2712*/
2713
2714/* ---------------- Requirement 1 ---------------- */
2715
2716void* memcpy(void *dest, const void *src, size_t n);
2717void* memcpy(void *dest, const void *src, size_t n) {
2718 return VG_(memcpy)(dest,src,n);
2719}
2720void* memset(void *s, int c, size_t n);
2721void* memset(void *s, int c, size_t n) {
2722 return VG_(memset)(s,c,n);
2723}
2724
2725/* ---------------- Requirement 2 ---------------- */
2726
2727/* Glibc's sysdeps/i386/elf/start.S has the following gem of a
2728 comment, which explains how the stack looks right at process start
2729 (when _start is jumped to). Hence _start passes %esp to
2730 _start_in_C, which extracts argc/argv/envp and starts up
2731 correctly. */
2732
2733/* This is the canonical entry point, usually the first thing in the text
2734 segment. The SVR4/i386 ABI (pages 3-31, 3-32) says that when the entry
2735 point runs, most registers' values are unspecified, except for:
2736
2737 %edx Contains a function pointer to be registered with `atexit'.
2738 This is how the dynamic linker arranges to have DT_FINI
2739 functions called for shared libraries that have been loaded
2740 before this code runs.
2741
2742 %esp The stack contains the arguments and environment:
2743 0(%esp) argc
2744 4(%esp) argv[0]
2745 ...
2746 (4*argc)(%esp) NULL
2747 (4*(argc+1))(%esp) envp[0]
2748 ...
2749 NULL
2750*/
2751
2752/* The kernel hands control to _start, which extracts the initial
sewardja48a4932005-09-29 11:09:56 +00002753 stack pointer and calls onwards to _start_in_C. This also switches
2754 the new stack. */
sewardj45f4e7c2005-09-27 19:20:21 +00002755#if defined(VGP_x86_linux)
2756asm("\n"
2757 "\t.globl _start\n"
2758 "\t.type _start,@function\n"
2759 "_start:\n"
2760 /* set up the new stack in %eax */
sewardjfdf91b42005-09-28 00:53:09 +00002761 "\tmovl $vgPlain_interim_stack, %eax\n"
sewardj45f4e7c2005-09-27 19:20:21 +00002762 "\taddl $"VG_STRINGIFY(VG_STACK_GUARD_SZB)", %eax\n"
2763 "\taddl $"VG_STRINGIFY(VG_STACK_ACTIVE_SZB)", %eax\n"
2764 "\tsubl $16, %eax\n"
2765 "\tandl $~15, %eax\n"
2766 /* install it, and collect the original one */
2767 "\txchgl %eax, %esp\n"
2768 /* call _start_in_C, passing it the startup %esp */
2769 "\tpushl %eax\n"
2770 "\tcall _start_in_C\n"
2771 "\thlt\n"
2772);
2773#elif defined(VGP_amd64_linux)
2774asm("\n"
2775 "\t.globl _start\n"
2776 "\t.type _start,@function\n"
2777 "_start:\n"
2778 /* set up the new stack in %rdi */
sewardjfdf91b42005-09-28 00:53:09 +00002779 "\tmovq $vgPlain_interim_stack, %rdi\n"
sewardj45f4e7c2005-09-27 19:20:21 +00002780 "\taddq $"VG_STRINGIFY(VG_STACK_GUARD_SZB)", %rdi\n"
2781 "\taddq $"VG_STRINGIFY(VG_STACK_ACTIVE_SZB)", %rdi\n"
2782 "\tandq $~15, %rdi\n"
2783 /* install it, and collect the original one */
2784 "\txchgq %rdi, %rsp\n"
2785 /* call _start_in_C, passing it the startup %rsp */
2786 "\tcall _start_in_C\n"
2787 "\thlt\n"
2788);
sewardja48a4932005-09-29 11:09:56 +00002789#elif defined(VGP_ppc32_linux)
2790asm("\n"
2791 "\t.globl _start\n"
2792 "\t.type _start,@function\n"
2793 "_start:\n"
2794 /* set up the new stack in r16 */
2795 "\tlis 16,vgPlain_interim_stack@ha\n"
2796 "\tla 16,vgPlain_interim_stack@l(16)\n"
2797 "\tlis 17,("VG_STRINGIFY(VG_STACK_GUARD_SZB)" >> 16)\n"
2798 "\tori 17,17,("VG_STRINGIFY(VG_STACK_GUARD_SZB)" & 0xFFFF)\n"
2799 "\tlis 18,("VG_STRINGIFY(VG_STACK_ACTIVE_SZB)" >> 16)\n"
2800 "\tori 18,18,("VG_STRINGIFY(VG_STACK_ACTIVE_SZB)" & 0xFFFF)\n"
2801 "\tadd 16,17,16\n"
2802 "\tadd 16,18,16\n"
2803 "\trlwinm 16,16,0,0,27\n"
2804 /* now r16 = &vgPlain_interim_stack + VG_STACK_GUARD_SZB +
2805 VG_STACK_ACTIVE_SZB rounded down to the nearest 16-byte
2806 boundary. And r1 is the original SP. Set the SP to r16 and
2807 call _start_in_C, passing it the initial SP. */
2808 "\tmr 3,1\n"
2809 "\tmr 1,16\n"
2810 "\tbl _start_in_C\n"
2811 "\ttrap\n"
2812);
sewardj45f4e7c2005-09-27 19:20:21 +00002813#else
2814#error "_start: needs implementation on this platform"
2815#endif
2816
2817/* Avoid compiler warnings: this fn _is_ used, but labelling it
2818 'static' causes gcc to complain it isn't. */
2819void _start_in_C ( UWord* pArgc );
2820void _start_in_C ( UWord* pArgc )
2821{
2822 Int r;
2823 Word argc = pArgc[0];
2824 HChar** argv = (HChar**)&pArgc[1];
2825 HChar** envp = (HChar**)&pArgc[1+argc+1];
sewardjfdf91b42005-09-28 00:53:09 +00002826 sp_at_startup = (Addr)pArgc;
sewardj45f4e7c2005-09-27 19:20:21 +00002827 r = main( (Int)argc, argv, envp );
2828 VG_(exit)(r);
2829}
2830
sewardjde4a1d02002-03-22 01:27:54 +00002831/*--------------------------------------------------------------------*/
njn04e16982005-05-31 00:23:43 +00002832/*--- end ---*/
sewardjde4a1d02002-03-22 01:27:54 +00002833/*--------------------------------------------------------------------*/