blob: ebf216feeb8a5e1789a826a8dbd41bbb292dfafb [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{
tomfb7bcde2005-11-07 15:24:38 +0000107 HChar* preload_core = "vgpreload_core";
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. */
tomfb7bcde2005-11-07 15:24:38 +0000124 Int preload_core_path_len = vglib_len + sizeof(preload_core) + sizeof(VG_PLATFORM) + 16;
125 Int preload_tool_path_len = vglib_len + VG_(strlen)(toolname) + sizeof(VG_PLATFORM) + 16;
sewardj45f4e7c2005-09-27 19:20:21 +0000126 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,
tomfb7bcde2005-11-07 15:24:38 +0000135 "%s/%s/vgpreload_%s.so", VG_(libdir), VG_PLATFORM, toolname);
sewardj45f4e7c2005-09-27 19:20:21 +0000136 if (VG_(access)(preload_tool_path, True/*r*/, False/*w*/, False/*x*/) == 0) {
tomfb7bcde2005-11-07 15:24:38 +0000137 VG_(snprintf)(preload_string, preload_string_len, "%s/%s/%s.so:%s",
138 VG_(libdir), VG_PLATFORM, preload_core, preload_tool_path);
sewardj45f4e7c2005-09-27 19:20:21 +0000139 } else {
tomfb7bcde2005-11-07 15:24:38 +0000140 VG_(snprintf)(preload_string, preload_string_len, "%s/%s/%s.so",
141 VG_(libdir), VG_PLATFORM, preload_core);
sewardj45f4e7c2005-09-27 19:20:21 +0000142 }
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:
sewardjfdf91b42005-09-28 00:53:09 +0000516 /* All these are pointerless, so we don't need to do
517 anything about them. */
518 break;
nethercote71980f02004-01-24 18:18:54 +0000519
sewardjfdf91b42005-09-28 00:53:09 +0000520 case AT_PHDR:
521 if (info->phdr == 0)
522 auxv->a_type = AT_IGNORE;
523 else
524 auxv->u.a_val = info->phdr;
525 break;
nethercote71980f02004-01-24 18:18:54 +0000526
sewardjfdf91b42005-09-28 00:53:09 +0000527 case AT_PHNUM:
528 if (info->phdr == 0)
529 auxv->a_type = AT_IGNORE;
530 else
531 auxv->u.a_val = info->phnum;
532 break;
nethercote71980f02004-01-24 18:18:54 +0000533
sewardjfdf91b42005-09-28 00:53:09 +0000534 case AT_BASE:
535 auxv->u.a_val = info->interp_base;
536 break;
nethercote71980f02004-01-24 18:18:54 +0000537
sewardjfdf91b42005-09-28 00:53:09 +0000538 case AT_PLATFORM:
539 /* points to a platform description string */
540 auxv->u.a_ptr = copy_str(&strtab, orig_auxv->u.a_ptr);
541 break;
nethercote71980f02004-01-24 18:18:54 +0000542
sewardjfdf91b42005-09-28 00:53:09 +0000543 case AT_ENTRY:
544 auxv->u.a_val = info->entry;
545 break;
nethercote71980f02004-01-24 18:18:54 +0000546
sewardjfdf91b42005-09-28 00:53:09 +0000547 case AT_HWCAP:
sewardjfdf91b42005-09-28 00:53:09 +0000548 break;
nethercote71980f02004-01-24 18:18:54 +0000549
sewardjfdf91b42005-09-28 00:53:09 +0000550 case AT_DCACHEBSIZE:
551 case AT_ICACHEBSIZE:
552 case AT_UCACHEBSIZE:
553# if defined(VGP_ppc32_linux)
554 /* acquire cache info */
555 if (auxv->u.a_val > 0) {
sewardje3826cf2005-11-13 00:30:22 +0000556 VG_(machine_ppc32_set_clszB)( auxv->u.a_val );
sewardja48a4932005-09-29 11:09:56 +0000557 VG_(debugLog)(2, "main",
sewardjfdf91b42005-09-28 00:53:09 +0000558 "PPC32 cache line size %u (type %u)\n",
559 (UInt)auxv->u.a_val, (UInt)auxv->a_type );
560 }
561# endif
562 break;
nethercote71980f02004-01-24 18:18:54 +0000563
sewardjfdf91b42005-09-28 00:53:09 +0000564# if defined(VGP_ppc32_linux)
565 case AT_IGNOREPPC:
566 break;
567# endif
568
569 case AT_SECURE:
570 /* If this is 1, then it means that this program is
571 running suid, and therefore the dynamic linker should
572 be careful about LD_PRELOAD, etc. However, since
573 stage1 (the thing the kernel actually execve's) should
574 never be SUID, and we need LD_PRELOAD to work for the
575 client, we set AT_SECURE to 0. */
576 auxv->u.a_val = 0;
577 break;
578
tom2315d182005-11-11 08:39:34 +0000579 case AT_SYSINFO:
sewardjfdf91b42005-09-28 00:53:09 +0000580# if !defined(VGP_ppc32_linux)
581 case AT_SYSINFO_EHDR:
tom2315d182005-11-11 08:39:34 +0000582# endif
sewardjfdf91b42005-09-28 00:53:09 +0000583 /* Trash this, because we don't reproduce it */
584 auxv->a_type = AT_IGNORE;
585 break;
sewardjfdf91b42005-09-28 00:53:09 +0000586
587 default:
588 /* stomp out anything we don't know about */
589 VG_(debugLog)(2, "main",
590 "stomping auxv entry %lld\n",
591 (ULong)auxv->a_type);
592 auxv->a_type = AT_IGNORE;
593 break;
nethercote71980f02004-01-24 18:18:54 +0000594 }
595 }
596 *auxv = *orig_auxv;
597 vg_assert(auxv->a_type == AT_NULL);
598
599 vg_assert((strtab-stringbase) == stringsize);
600
sewardj45f4e7c2005-09-27 19:20:21 +0000601 /* client_SP is pointing at client's argc/argv */
nethercote5ee67ca2004-06-22 14:00:09 +0000602
sewardj45f4e7c2005-09-27 19:20:21 +0000603 if (0) VG_(printf)("startup SP = %p\n", client_SP);
604 return client_SP;
nethercote71980f02004-01-24 18:18:54 +0000605}
606
sewardj45f4e7c2005-09-27 19:20:21 +0000607
608/* Allocate the client data segment. It is an expandable anonymous
609 mapping abutting a shrinkable reservation of size max_dseg_size.
610 The data segment starts at VG_(brk_base), which is page-aligned,
611 and runs up to VG_(brk_limit), which isn't. */
612
613static void setup_client_dataseg ( SizeT max_size )
614{
615 Bool ok;
616 SysRes sres;
617 Addr anon_start = VG_(brk_base);
618 SizeT anon_size = VKI_PAGE_SIZE;
619 Addr resvn_start = anon_start + anon_size;
620 SizeT resvn_size = max_size - anon_size;
621
622 vg_assert(VG_IS_PAGE_ALIGNED(anon_size));
623 vg_assert(VG_IS_PAGE_ALIGNED(resvn_size));
624 vg_assert(VG_IS_PAGE_ALIGNED(anon_start));
625 vg_assert(VG_IS_PAGE_ALIGNED(resvn_start));
626
627 /* Because there's been no brk activity yet: */
628 vg_assert(VG_(brk_base) == VG_(brk_limit));
629
630 /* Try to create the data seg and associated reservation where
631 VG_(brk_base) says. */
632 ok = VG_(am_create_reservation)(
633 resvn_start,
634 resvn_size,
635 SmLower,
636 anon_size
637 );
638
639 if (!ok) {
640 /* Hmm, that didn't work. Well, let aspacem suggest an address
641 it likes better, and try again with that. */
642 anon_start = VG_(am_get_advisory_client_simple)
643 ( 0/*floating*/, anon_size+resvn_size, &ok );
644 if (ok) {
645 resvn_start = anon_start + anon_size;
646 ok = VG_(am_create_reservation)(
647 resvn_start,
648 resvn_size,
649 SmLower,
650 anon_size
651 );
652 if (ok)
653 VG_(brk_base) = VG_(brk_limit) = anon_start;
654 }
655 /* that too might have failed, but if it has, we're hosed: there
656 is no Plan C. */
657 }
658 vg_assert(ok);
659
660 sres = VG_(am_mmap_anon_fixed_client)(
661 anon_start,
662 anon_size,
sewardj33ca9e82005-11-16 17:12:38 +0000663 VKI_PROT_READ|VKI_PROT_WRITE|VKI_PROT_EXEC
sewardj45f4e7c2005-09-27 19:20:21 +0000664 );
665 vg_assert(!sres.isError);
666 vg_assert(sres.val == anon_start);
667}
668
669
nethercote71980f02004-01-24 18:18:54 +0000670/*====================================================================*/
671/*=== Find executable ===*/
672/*====================================================================*/
673
sewardjfdf91b42005-09-28 00:53:09 +0000674/* Scan a colon-separated list, and call a function on each element.
675 The string must be mutable, because we insert a temporary '\0', but
676 the string will end up unmodified. (*func) should return True if it
677 doesn't need to see any more.
678
679 This routine will return True if (*func) returns True and False if
680 it reaches the end of the list without that happening.
681*/
682static Bool scan_colsep(char *colsep, Bool (*func)(const char *))
683{
684 char *cp, *entry;
685 int end;
686
687 if (colsep == NULL ||
688 *colsep == '\0')
689 return False;
690
691 entry = cp = colsep;
692
693 do {
694 end = (*cp == '\0');
695
696 if (*cp == ':' || *cp == '\0') {
697 char save = *cp;
698
699 *cp = '\0';
700 if ((*func)(entry)) {
701 *cp = save;
702 return True;
703 }
704 *cp = save;
705 entry = cp+1;
706 }
707 cp++;
708 } while(!end);
709
710 return False;
711}
712
sewardj45f4e7c2005-09-27 19:20:21 +0000713/* Need a static copy because can't use dynamic mem allocation yet */
njn73750612005-10-14 03:11:30 +0000714static HChar executable_name_in [VKI_PATH_MAX];
715static HChar executable_name_out[VKI_PATH_MAX];
thughes4ad52d02004-06-27 17:37:21 +0000716
sewardj45f4e7c2005-09-27 19:20:21 +0000717static Bool match_executable(const char *entry)
718{
njn73750612005-10-14 03:11:30 +0000719 HChar buf[VG_(strlen)(entry) + VG_(strlen)(executable_name_in) + 3];
thughes4ad52d02004-06-27 17:37:21 +0000720
njn73750612005-10-14 03:11:30 +0000721 /* empty PATH element means '.' */
thughes4ad52d02004-06-27 17:37:21 +0000722 if (*entry == '\0')
723 entry = ".";
724
njn73750612005-10-14 03:11:30 +0000725 VG_(snprintf)(buf, sizeof(buf), "%s/%s", entry, executable_name_in);
726
727 // Don't match directories
728 if (VG_(is_dir)(buf))
729 return False;
730
731 // If we match an executable, we choose that immediately. If we find a
732 // matching non-executable we remember it but keep looking for an
733 // matching executable later in the path.
sewardj45f4e7c2005-09-27 19:20:21 +0000734 if (VG_(access)(buf, True/*r*/, False/*w*/, True/*x*/) == 0) {
njn73750612005-10-14 03:11:30 +0000735 VG_(strncpy)( executable_name_out, buf, VKI_PATH_MAX-1 );
736 executable_name_out[VKI_PATH_MAX-1] = 0;
737 return True; // Stop looking
738 } else if (VG_(access)(buf, True/*r*/, False/*w*/, False/*x*/) == 0
739 && VG_STREQ(executable_name_out, ""))
740 {
741 VG_(strncpy)( executable_name_out, buf, VKI_PATH_MAX-1 );
742 executable_name_out[VKI_PATH_MAX-1] = 0;
743 return False; // Keep looking
744 } else {
745 return False; // Keep looking
thughes4ad52d02004-06-27 17:37:21 +0000746 }
thughes4ad52d02004-06-27 17:37:21 +0000747}
748
njn73750612005-10-14 03:11:30 +0000749// Returns NULL if it wasn't found.
sewardj45f4e7c2005-09-27 19:20:21 +0000750static HChar* find_executable ( HChar* exec )
nethercote71980f02004-01-24 18:18:54 +0000751{
752 vg_assert(NULL != exec);
njn73750612005-10-14 03:11:30 +0000753 if (VG_(strchr)(exec, '/')) {
754 // Has a '/' - use the name as is
755 VG_(strncpy)( executable_name_out, exec, VKI_PATH_MAX-1 );
756 } else {
757 // No '/' - we need to search the path
sewardj03d8aa82005-10-14 11:25:49 +0000758 HChar* path;
njn73750612005-10-14 03:11:30 +0000759 VG_(strncpy)( executable_name_in, exec, VKI_PATH_MAX-1 );
760 VG_(memset) ( executable_name_out, 0, VKI_PATH_MAX );
sewardj03d8aa82005-10-14 11:25:49 +0000761 path = VG_(getenv)("PATH");
thughes4ad52d02004-06-27 17:37:21 +0000762 scan_colsep(path, match_executable);
nethercote71980f02004-01-24 18:18:54 +0000763 }
njn73750612005-10-14 03:11:30 +0000764 return VG_STREQ(executable_name_out, "") ? NULL : executable_name_out;
nethercote71980f02004-01-24 18:18:54 +0000765}
766
767
768/*====================================================================*/
nethercotef4928da2004-06-15 10:54:40 +0000769/*=== Command line errors ===*/
770/*====================================================================*/
771
njnbe9b47b2005-05-15 16:22:58 +0000772static void revert_to_stderr ( void )
nethercotef4928da2004-06-15 10:54:40 +0000773{
njnbe9b47b2005-05-15 16:22:58 +0000774 vg_assert( !VG_(logging_to_socket) );
nethercotef8548672004-06-21 12:42:35 +0000775 VG_(clo_log_fd) = 2; /* stderr */
nethercotef4928da2004-06-15 10:54:40 +0000776}
777
778void VG_(bad_option) ( Char* opt )
779{
njnbe9b47b2005-05-15 16:22:58 +0000780 revert_to_stderr();
njn02bc4b82005-05-15 17:28:26 +0000781 VG_(printf)("valgrind: Bad option '%s'; aborting.\n", opt);
nethercotef4928da2004-06-15 10:54:40 +0000782 VG_(printf)("valgrind: Use --help for more information.\n");
783 VG_(exit)(1);
784}
785
nethercotef4928da2004-06-15 10:54:40 +0000786static void missing_prog ( void )
787{
njnbe9b47b2005-05-15 16:22:58 +0000788 revert_to_stderr();
nethercotef4928da2004-06-15 10:54:40 +0000789 VG_(printf)("valgrind: no program specified\n");
790 VG_(printf)("valgrind: Use --help for more information.\n");
791 VG_(exit)(1);
792}
793
794static void config_error ( Char* msg )
795{
njnbe9b47b2005-05-15 16:22:58 +0000796 revert_to_stderr();
nethercotef4928da2004-06-15 10:54:40 +0000797 VG_(printf)("valgrind: Startup or configuration error:\n %s\n", msg);
798 VG_(printf)("valgrind: Unable to start up properly. Giving up.\n");
799 VG_(exit)(1);
800}
801
802
nethercote71980f02004-01-24 18:18:54 +0000803/*====================================================================*/
804/*=== Loading the client ===*/
805/*====================================================================*/
806
sewardj45f4e7c2005-09-27 19:20:21 +0000807/* Load the client whose name is VG_(argv_the_exename). */
nethercote71980f02004-01-24 18:18:54 +0000808
sewardj45f4e7c2005-09-27 19:20:21 +0000809static void load_client ( /*OUT*/struct exeinfo* info,
810 /*OUT*/Addr* client_eip)
811{
njn73750612005-10-14 03:11:30 +0000812 HChar* exe_name;
sewardj45f4e7c2005-09-27 19:20:21 +0000813 Int ret;
814 SysRes res;
815
816 vg_assert( VG_(args_the_exename) != NULL);
njn73750612005-10-14 03:11:30 +0000817 exe_name = find_executable( VG_(args_the_exename) );
818
819 if (!exe_name) {
820 VG_(printf)("valgrind: %s: command not found\n", VG_(args_the_exename));
821 VG_(exit)(127); // 127 is Posix NOTFOUND
822 }
sewardj45f4e7c2005-09-27 19:20:21 +0000823
824 VG_(memset)(info, 0, sizeof(*info));
nethercote71980f02004-01-24 18:18:54 +0000825 info->exe_base = VG_(client_base);
826 info->exe_end = VG_(client_end);
nethercote71980f02004-01-24 18:18:54 +0000827
njn73750612005-10-14 03:11:30 +0000828 ret = VG_(do_exec)(exe_name, info);
829
830 // The client was successfully loaded! Continue.
nethercote71980f02004-01-24 18:18:54 +0000831
sewardj45f4e7c2005-09-27 19:20:21 +0000832 /* Get hold of a file descriptor which refers to the client
833 executable. This is needed for attaching to GDB. */
njn73750612005-10-14 03:11:30 +0000834 res = VG_(open)(exe_name, VKI_O_RDONLY, VKI_S_IRUSR);
sewardj45f4e7c2005-09-27 19:20:21 +0000835 if (!res.isError)
836 VG_(cl_exec_fd) = res.val;
837
nethercote71980f02004-01-24 18:18:54 +0000838 /* Copy necessary bits of 'info' that were filled in */
839 *client_eip = info->init_eip;
sewardj45f4e7c2005-09-27 19:20:21 +0000840 VG_(brk_base) = VG_(brk_limit) = VG_PGROUNDUP(info->brkbase);
nethercote71980f02004-01-24 18:18:54 +0000841}
842
nethercote969ecf12004-10-13 17:29:01 +0000843
sewardj71bc3cb2005-05-19 00:25:45 +0000844/*====================================================================*/
845/*=== Command-line: variables, processing, etc ===*/
846/*====================================================================*/
847
848// See pub_{core,tool}_options.h for explanations of all these.
849
sewardj45f4e7c2005-09-27 19:20:21 +0000850static void usage_NORETURN ( Bool debug_help )
njn7cf0bd32002-06-08 13:36:03 +0000851{
njn25e49d8e72002-09-23 09:36:25 +0000852 Char* usage1 =
njn00cfcfc2005-11-12 18:53:50 +0000853"usage: valgrind [options] prog-and-args\n"
njn25e49d8e72002-09-23 09:36:25 +0000854"\n"
nethercote2b0793f2003-12-02 10:41:18 +0000855" common user options for all Valgrind tools, with defaults in [ ]:\n"
sewardjb5f6f512005-03-10 23:59:00 +0000856" --tool=<name> use the Valgrind tool named <name> [memcheck]\n"
nethercotea76368b2004-06-16 11:56:29 +0000857" -h --help show this message\n"
nethercote6c999f22004-01-31 22:55:15 +0000858" --help-debug show this message, plus debugging options\n"
njn25e49d8e72002-09-23 09:36:25 +0000859" --version show version\n"
njn25e49d8e72002-09-23 09:36:25 +0000860" -q --quiet run silently; only print error msgs\n"
861" -v --verbose be more verbose, incl counts of errors\n"
nethercote77eba602003-11-13 17:35:04 +0000862" --trace-children=no|yes Valgrind-ise child processes? [no]\n"
nethercote0d588502004-06-21 13:27:11 +0000863" --track-fds=no|yes track open file descriptors? [no]\n"
thughes6233a382004-08-21 11:10:44 +0000864" --time-stamp=no|yes add timestamps to log messages? [no]\n"
njnce545552005-07-25 22:36:52 +0000865" --log-fd=<number> log messages to file descriptor [2=stderr]\n"
tombbe14b12005-11-04 16:49:39 +0000866" --log-file=<file> log messages to <file>.<pid>\n"
njnce545552005-07-25 22:36:52 +0000867" --log-file-exactly=<file> log messages to <file>\n"
868" --log-file-qualifier=<VAR> incorporate $VAR in logfile name [none]\n"
869" --log-socket=ipaddr:port log messages to socket ipaddr:port\n"
nethercote2b0793f2003-12-02 10:41:18 +0000870"\n"
871" uncommon user options for all Valgrind tools:\n"
nethercote0d588502004-06-21 13:27:11 +0000872" --run-libc-freeres=no|yes free up glibc memory at exit? [yes]\n"
njn628add62005-11-12 18:21:40 +0000873" --sim-hints=hint1,hint2,... known hints:\n"
sewardj19617ae2005-10-20 01:09:57 +0000874" lax-ioctls, enable-outer [none]\n"
sewardjb1131a82005-03-19 15:12:21 +0000875" --show-emwarns=no|yes show warnings about emulation limits? [no]\n"
sewardj6c3a2192005-07-24 07:00:45 +0000876" --smc-check=none|stack|all checks for self-modifying code: none,\n"
877" only for code found in stacks, or all [stack]\n"
sewardj3c3f0c12005-11-08 15:52:36 +0000878" --kernel-variant=variant1,variant2,... known variants: bproc [none]\n"
879" handle non-standard kernel variants\n"
njn25e49d8e72002-09-23 09:36:25 +0000880"\n"
nethercote2b0793f2003-12-02 10:41:18 +0000881" user options for Valgrind tools that report errors:\n"
njnce545552005-07-25 22:36:52 +0000882" --xml=yes all output is in XML (Memcheck/Nulgrind only)\n"
njnc8ec9f82005-07-20 03:03:28 +0000883" --xml-user-comment=STR copy STR verbatim to XML output\n"
nethercote2b0793f2003-12-02 10:41:18 +0000884" --demangle=no|yes automatically demangle C++ names? [yes]\n"
njn20b4a152005-10-19 22:39:40 +0000885" --num-callers=<number> show <number> callers in stack traces [12]\n"
nethercote2b0793f2003-12-02 10:41:18 +0000886" --error-limit=no|yes stop showing new errors if too many? [yes]\n"
887" --show-below-main=no|yes continue stack traces below main() [no]\n"
888" --suppressions=<filename> suppress errors described in <filename>\n"
sewardjd153fae2005-01-10 17:24:47 +0000889" --gen-suppressions=no|yes|all print suppressions for errors? [no]\n"
nethercote04d0fbc2004-01-26 16:48:06 +0000890" --db-attach=no|yes start debugger when errors detected? [no]\n"
891" --db-command=<command> command to start debugger [gdb -nw %%f %%p]\n"
892" --input-fd=<number> file descriptor for input [0=stdin]\n"
sewardj97724e52005-04-02 23:40:59 +0000893" --max-stackframe=<number> assume stack switch for SP changes larger\n"
894" than <number> bytes [2000000]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +0000895"\n";
njn7cf0bd32002-06-08 13:36:03 +0000896
njn25e49d8e72002-09-23 09:36:25 +0000897 Char* usage2 =
898"\n"
nethercote2b0793f2003-12-02 10:41:18 +0000899" debugging options for all Valgrind tools:\n"
njn25e49d8e72002-09-23 09:36:25 +0000900" --sanity-level=<number> level of sanity checking to do [1]\n"
nethercote137bc552003-11-14 17:47:54 +0000901" --profile=no|yes profile? (tool must be built for it) [no]\n"
sewardjfa8ec112005-01-19 11:55:34 +0000902" --trace-flags=<XXXXXXXX> show generated code? (X = 0|1) [00000000]\n"
903" --profile-flags=<XXXXXXXX> ditto, but for profiling (X = 0|1) [00000000]\n"
njn20b4a152005-10-19 22:39:40 +0000904" --trace-notbelow=<number> only show BBs above <number> [0]\n"
njn25e49d8e72002-09-23 09:36:25 +0000905" --trace-syscalls=no|yes show all system calls? [no]\n"
906" --trace-signals=no|yes show signal handling details? [no]\n"
907" --trace-symtab=no|yes show symbol table details? [no]\n"
sewardjce058b02005-05-01 08:55:38 +0000908" --trace-cfi=no|yes show call-frame-info details? [no]\n"
njn25e49d8e72002-09-23 09:36:25 +0000909" --trace-sched=no|yes show thread scheduler details? [no]\n"
jsgf855d93d2003-10-13 22:26:55 +0000910" --wait-for-gdb=yes|no pause on startup to wait for gdb attach\n"
sewardjb5f6f512005-03-10 23:59:00 +0000911#if 0
912" --model-pthreads=yes|no model the pthreads library [no]\n"
913#endif
914" --command-line-only=no|yes only use command line options [no]\n"
njn613812e2005-03-11 04:57:30 +0000915"\n"
916" --vex-iropt-verbosity 0 .. 9 [0]\n"
917" --vex-iropt-level 0 .. 2 [2]\n"
918" --vex-iropt-precise-memory-exns [no]\n"
sewardj8b635a42004-11-22 19:01:47 +0000919" --vex-iropt-unroll-thresh 0 .. 400 [120]\n"
920" --vex-guest-max-insns 1 .. 100 [50]\n"
921" --vex-guest-chase-thresh 0 .. 99 [10]\n"
922"\n"
sewardjfa8ec112005-01-19 11:55:34 +0000923" --trace-flags and --profile-flags values (omit the middle space):\n"
sewardj2a99cf62004-11-24 10:44:19 +0000924" 1000 0000 show conversion into IR\n"
925" 0100 0000 show after initial opt\n"
926" 0010 0000 show after instrumentation\n"
927" 0001 0000 show after second opt\n"
928" 0000 1000 show after tree building\n"
929" 0000 0100 show selecting insns\n"
930" 0000 0010 show after reg-alloc\n"
931" 0000 0001 show final assembly\n"
932"\n"
nethercote2b0793f2003-12-02 10:41:18 +0000933" debugging options for Valgrind tools that report errors\n"
934" --dump-error=<number> show translation for basic block associated\n"
935" with <number>'th error context [0=show none]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +0000936"\n";
njn3e884182003-04-15 13:03:23 +0000937
938 Char* usage3 =
939"\n"
nethercote71980f02004-01-24 18:18:54 +0000940" Extra options read from ~/.valgrindrc, $VALGRIND_OPTS, ./.valgrindrc\n"
njn25e49d8e72002-09-23 09:36:25 +0000941"\n"
njn53612422005-03-12 16:22:54 +0000942" Valgrind is Copyright (C) 2000-2005 Julian Seward et al.\n"
njn25e49d8e72002-09-23 09:36:25 +0000943" and licensed under the GNU General Public License, version 2.\n"
944" Bug reports, feedback, admiration, abuse, etc, to: %s.\n"
njnd04b7c62002-10-03 14:05:52 +0000945"\n"
nethercote137bc552003-11-14 17:47:54 +0000946" Tools are copyright and licensed by their authors. See each\n"
947" tool's start-up message for more information.\n"
njn25e49d8e72002-09-23 09:36:25 +0000948"\n";
njn7cf0bd32002-06-08 13:36:03 +0000949
njnbe9b47b2005-05-15 16:22:58 +0000950 // Ensure the message goes to stdout
951 VG_(clo_log_fd) = 1;
952 vg_assert( !VG_(logging_to_socket) );
953
fitzhardinge98abfc72003-12-16 02:05:15 +0000954 VG_(printf)(usage1);
955 if (VG_(details).name) {
956 VG_(printf)(" user options for %s:\n", VG_(details).name);
fitzhardinge98abfc72003-12-16 02:05:15 +0000957 if (VG_(needs).command_line_options)
njn51d827b2005-05-09 01:02:08 +0000958 VG_TDICT_CALL(tool_print_usage);
fitzhardinge98abfc72003-12-16 02:05:15 +0000959 else
960 VG_(printf)(" (none)\n");
961 }
nethercote6c999f22004-01-31 22:55:15 +0000962 if (debug_help) {
963 VG_(printf)(usage2);
fitzhardinge98abfc72003-12-16 02:05:15 +0000964
nethercote6c999f22004-01-31 22:55:15 +0000965 if (VG_(details).name) {
966 VG_(printf)(" debugging options for %s:\n", VG_(details).name);
967
968 if (VG_(needs).command_line_options)
njn51d827b2005-05-09 01:02:08 +0000969 VG_TDICT_CALL(tool_print_debug_usage);
nethercote6c999f22004-01-31 22:55:15 +0000970 else
971 VG_(printf)(" (none)\n");
972 }
fitzhardinge98abfc72003-12-16 02:05:15 +0000973 }
nethercote421281e2003-11-20 16:20:55 +0000974 VG_(printf)(usage3, VG_BUGS_TO);
nethercotef4928da2004-06-15 10:54:40 +0000975 VG_(exit)(0);
njn7cf0bd32002-06-08 13:36:03 +0000976}
sewardjde4a1d02002-03-22 01:27:54 +0000977
sewardjde4a1d02002-03-22 01:27:54 +0000978
sewardj45f4e7c2005-09-27 19:20:21 +0000979/* Peer at previously set up VG_(args_for_valgrind) and extract any
980 request for help and also the tool name. */
981
982static void get_helprequest_and_toolname ( Int* need_help, HChar** tool )
983{
984 UInt i;
985 HChar* str;
sewardj8b635a42004-11-22 19:01:47 +0000986
nethercote71980f02004-01-24 18:18:54 +0000987 /* parse the options we have (only the options we care about now) */
sewardj45f4e7c2005-09-27 19:20:21 +0000988 for (i = 0; i < VG_(args_for_valgrind).used; i++) {
nethercote71980f02004-01-24 18:18:54 +0000989
sewardj45f4e7c2005-09-27 19:20:21 +0000990 str = VG_(args_for_valgrind).strs[i];
991 vg_assert(str);
nethercote71980f02004-01-24 18:18:54 +0000992
sewardj45f4e7c2005-09-27 19:20:21 +0000993 if (VG_STREQ(str, "--version")) {
njn2e9f3f32005-10-26 16:17:46 +0000994 // Ensure the version string goes to stdout
995 VG_(clo_log_fd) = 1;
sewardj45f4e7c2005-09-27 19:20:21 +0000996 VG_(printf)("valgrind-" VERSION "\n");
997 VG_(exit)(0);
998
999 } else if (VG_CLO_STREQ(str, "--help") ||
1000 VG_CLO_STREQ(str, "-h")) {
nethercote6c999f22004-01-31 22:55:15 +00001001 *need_help = 1;
1002
sewardj45f4e7c2005-09-27 19:20:21 +00001003 } else if (VG_CLO_STREQ(str, "--help-debug")) {
nethercote6c999f22004-01-31 22:55:15 +00001004 *need_help = 2;
nethercote71980f02004-01-24 18:18:54 +00001005
sewardj45f4e7c2005-09-27 19:20:21 +00001006 // The tool has already been determined, but we need to know the name
1007 // here.
1008 } else if (VG_CLO_STREQN(7, str, "--tool=")) {
1009 *tool = &str[7];
nethercote71980f02004-01-24 18:18:54 +00001010 }
1011 }
nethercote71980f02004-01-24 18:18:54 +00001012}
1013
sewardj45f4e7c2005-09-27 19:20:21 +00001014static Bool process_cmd_line_options( UInt* client_auxv, const char* toolname )
nethercote71980f02004-01-24 18:18:54 +00001015{
sewardj92645592005-07-23 09:18:34 +00001016 SysRes sres;
1017 Int i, eventually_log_fd;
1018 Int toolname_len = VG_(strlen)(toolname);
njnbe9b47b2005-05-15 16:22:58 +00001019 enum {
1020 VgLogTo_Fd,
1021 VgLogTo_File,
1022 VgLogTo_FileExactly,
1023 VgLogTo_Socket
1024 } log_to = VgLogTo_Fd; // Where is logging output to be sent?
sewardjde4a1d02002-03-22 01:27:54 +00001025
nethercotee1730692003-11-20 10:38:07 +00001026 /* log to stderr by default, but usage message goes to stdout */
nethercotef8548672004-06-21 12:42:35 +00001027 eventually_log_fd = 2;
sewardjde4a1d02002-03-22 01:27:54 +00001028
sewardj19d81412002-06-03 01:10:40 +00001029 /* Check for sane path in ./configure --prefix=... */
fitzhardinge98abfc72003-12-16 02:05:15 +00001030 if (VG_LIBDIR[0] != '/')
sewardj19d81412002-06-03 01:10:40 +00001031 config_error("Please use absolute paths in "
1032 "./configure --prefix=... or --libdir=...");
sewardj38170912002-05-10 21:07:22 +00001033
sewardj45f4e7c2005-09-27 19:20:21 +00001034 for (i = 0; i < VG_(args_for_valgrind).used; i++) {
nethercote71980f02004-01-24 18:18:54 +00001035
sewardj45f4e7c2005-09-27 19:20:21 +00001036 HChar* arg = VG_(args_for_valgrind).strs[i];
1037 HChar* colon = arg;
nethercote71980f02004-01-24 18:18:54 +00001038
thughes3bfd5a02004-07-18 08:05:44 +00001039 /* Look for a colon in the switch name */
1040 while (*colon && *colon != ':' && *colon != '=')
1041 colon++;
nethercote71980f02004-01-24 18:18:54 +00001042
1043 /* Look for matching "--toolname:foo" */
thughes3bfd5a02004-07-18 08:05:44 +00001044 if (*colon == ':') {
nethercote71980f02004-01-24 18:18:54 +00001045 if (VG_CLO_STREQN(2, arg, "--") &&
1046 VG_CLO_STREQN(toolname_len, arg+2, toolname) &&
1047 VG_CLO_STREQN(1, arg+2+toolname_len, ":"))
1048 {
1049 // prefix matches, convert "--toolname:foo" to "--foo"
1050 if (0)
1051 VG_(printf)("tool-specific arg: %s\n", arg);
sewardj45f4e7c2005-09-27 19:20:21 +00001052 arg = VG_(strdup)(arg + toolname_len + 1);
nethercote71980f02004-01-24 18:18:54 +00001053 arg[0] = '-';
1054 arg[1] = '-';
1055
1056 } else {
1057 // prefix doesn't match, skip to next arg
1058 continue;
1059 }
1060 }
1061
fitzhardinge98abfc72003-12-16 02:05:15 +00001062 /* Ignore these options - they've already been handled */
njn45270a22005-03-27 01:00:11 +00001063 if (VG_CLO_STREQN( 7, arg, "--tool=")) goto skip_arg;
njn45270a22005-03-27 01:00:11 +00001064 if (VG_CLO_STREQN(20, arg, "--command-line-only=")) goto skip_arg;
fitzhardinge98abfc72003-12-16 02:05:15 +00001065
njn45270a22005-03-27 01:00:11 +00001066 if ( VG_CLO_STREQ(arg, "--")) goto skip_arg;
nethercote27fec902004-06-16 21:26:32 +00001067
nethercote71980f02004-01-24 18:18:54 +00001068 else if (VG_CLO_STREQ(arg, "-v") ||
1069 VG_CLO_STREQ(arg, "--verbose"))
sewardjde4a1d02002-03-22 01:27:54 +00001070 VG_(clo_verbosity)++;
nethercote27fec902004-06-16 21:26:32 +00001071
nethercote71980f02004-01-24 18:18:54 +00001072 else if (VG_CLO_STREQ(arg, "-q") ||
1073 VG_CLO_STREQ(arg, "--quiet"))
sewardjde4a1d02002-03-22 01:27:54 +00001074 VG_(clo_verbosity)--;
1075
sewardj1cf558c2005-04-25 01:36:56 +00001076 else if (VG_CLO_STREQ(arg, "-d")) {
1077 /* do nothing */
1078 }
1079
sewardj71bc3cb2005-05-19 00:25:45 +00001080 else VG_BOOL_CLO(arg, "--xml", VG_(clo_xml))
njn45270a22005-03-27 01:00:11 +00001081 else VG_BOOL_CLO(arg, "--db-attach", VG_(clo_db_attach))
1082 else VG_BOOL_CLO(arg, "--demangle", VG_(clo_demangle))
1083 else VG_BOOL_CLO(arg, "--error-limit", VG_(clo_error_limit))
njn45270a22005-03-27 01:00:11 +00001084 else VG_BOOL_CLO(arg, "--show-emwarns", VG_(clo_show_emwarns))
sewardj97724e52005-04-02 23:40:59 +00001085 else VG_NUM_CLO (arg, "--max-stackframe", VG_(clo_max_stackframe))
njn45270a22005-03-27 01:00:11 +00001086 else VG_BOOL_CLO(arg, "--profile", VG_(clo_profile))
1087 else VG_BOOL_CLO(arg, "--run-libc-freeres", VG_(clo_run_libc_freeres))
1088 else VG_BOOL_CLO(arg, "--show-below-main", VG_(clo_show_below_main))
1089 else VG_BOOL_CLO(arg, "--time-stamp", VG_(clo_time_stamp))
1090 else VG_BOOL_CLO(arg, "--track-fds", VG_(clo_track_fds))
1091 else VG_BOOL_CLO(arg, "--trace-children", VG_(clo_trace_children))
1092 else VG_BOOL_CLO(arg, "--trace-sched", VG_(clo_trace_sched))
1093 else VG_BOOL_CLO(arg, "--trace-signals", VG_(clo_trace_signals))
1094 else VG_BOOL_CLO(arg, "--trace-symtab", VG_(clo_trace_symtab))
sewardjce058b02005-05-01 08:55:38 +00001095 else VG_BOOL_CLO(arg, "--trace-cfi", VG_(clo_trace_cfi))
njn45270a22005-03-27 01:00:11 +00001096 else VG_BOOL_CLO(arg, "--trace-redir", VG_(clo_trace_redir))
1097 else VG_BOOL_CLO(arg, "--trace-syscalls", VG_(clo_trace_syscalls))
1098 else VG_BOOL_CLO(arg, "--trace-pthreads", VG_(clo_trace_pthreads))
1099 else VG_BOOL_CLO(arg, "--wait-for-gdb", VG_(clo_wait_for_gdb))
1100 else VG_BOOL_CLO(arg, "--model-pthreads", VG_(clo_model_pthreads))
sewardj72f98ff2002-06-13 17:23:38 +00001101
njn45270a22005-03-27 01:00:11 +00001102 else VG_STR_CLO (arg, "--db-command", VG_(clo_db_command))
njn628add62005-11-12 18:21:40 +00001103 else VG_STR_CLO (arg, "--sim-hints", VG_(clo_sim_hints))
sewardjde4a1d02002-03-22 01:27:54 +00001104
njn45270a22005-03-27 01:00:11 +00001105 else VG_NUM_CLO (arg, "--dump-error", VG_(clo_dump_error))
1106 else VG_NUM_CLO (arg, "--input-fd", VG_(clo_input_fd))
1107 else VG_NUM_CLO (arg, "--sanity-level", VG_(clo_sanity_level))
1108 else VG_BNUM_CLO(arg, "--num-callers", VG_(clo_backtrace_size), 1,
1109 VG_DEEPEST_BACKTRACE)
sewardjde4a1d02002-03-22 01:27:54 +00001110
sewardj6c3a2192005-07-24 07:00:45 +00001111 else if (VG_CLO_STREQ(arg, "--smc-check=none"))
1112 VG_(clo_smc_check) = Vg_SmcNone;
1113 else if (VG_CLO_STREQ(arg, "--smc-check=stack"))
1114 VG_(clo_smc_check) = Vg_SmcStack;
1115 else if (VG_CLO_STREQ(arg, "--smc-check=all"))
1116 VG_(clo_smc_check) = Vg_SmcAll;
sewardj26412bd2005-07-07 10:05:05 +00001117
sewardjce5a5662005-10-06 03:19:49 +00001118 else VG_STR_CLO (arg, "--kernel-variant", VG_(clo_kernel_variant))
1119
njn45270a22005-03-27 01:00:11 +00001120 else VG_BNUM_CLO(arg, "--vex-iropt-verbosity",
sewardj8b635a42004-11-22 19:01:47 +00001121 VG_(clo_vex_control).iropt_verbosity, 0, 10)
njn45270a22005-03-27 01:00:11 +00001122 else VG_BNUM_CLO(arg, "--vex-iropt-level",
sewardj8b635a42004-11-22 19:01:47 +00001123 VG_(clo_vex_control).iropt_level, 0, 2)
njn45270a22005-03-27 01:00:11 +00001124 else VG_BOOL_CLO(arg, "--vex-iropt-precise-memory-exns",
sewardj8b635a42004-11-22 19:01:47 +00001125 VG_(clo_vex_control).iropt_precise_memory_exns)
njn45270a22005-03-27 01:00:11 +00001126 else VG_BNUM_CLO(arg, "--vex-iropt-unroll-thresh",
sewardj8b635a42004-11-22 19:01:47 +00001127 VG_(clo_vex_control).iropt_unroll_thresh, 0, 400)
njn45270a22005-03-27 01:00:11 +00001128 else VG_BNUM_CLO(arg, "--vex-guest-max-insns",
sewardj8b635a42004-11-22 19:01:47 +00001129 VG_(clo_vex_control).guest_max_insns, 1, 100)
njn45270a22005-03-27 01:00:11 +00001130 else VG_BNUM_CLO(arg, "--vex-guest-chase-thresh",
sewardj8b635a42004-11-22 19:01:47 +00001131 VG_(clo_vex_control).guest_chase_thresh, 0, 99)
1132
nethercotef8548672004-06-21 12:42:35 +00001133 else if (VG_CLO_STREQN(9, arg, "--log-fd=")) {
njnbe9b47b2005-05-15 16:22:58 +00001134 log_to = VgLogTo_Fd;
nethercotef8548672004-06-21 12:42:35 +00001135 VG_(clo_log_name) = NULL;
1136 eventually_log_fd = (Int)VG_(atoll)(&arg[9]);
sewardj4cf05692002-10-27 20:28:29 +00001137 }
1138
nethercotef8548672004-06-21 12:42:35 +00001139 else if (VG_CLO_STREQN(11, arg, "--log-file=")) {
njnbe9b47b2005-05-15 16:22:58 +00001140 log_to = VgLogTo_File;
nethercotef8548672004-06-21 12:42:35 +00001141 VG_(clo_log_name) = &arg[11];
sewardj4cf05692002-10-27 20:28:29 +00001142 }
njnd6bc3c32005-03-27 00:44:31 +00001143
sewardjad311162005-07-19 11:25:02 +00001144 else if (VG_CLO_STREQN(21, arg, "--log-file-qualifier=")) {
1145 VG_(clo_log_file_qualifier) = &arg[21];
1146 }
1147
sewardj603d4102005-01-11 14:01:02 +00001148 else if (VG_CLO_STREQN(19, arg, "--log-file-exactly=")) {
njnbe9b47b2005-05-15 16:22:58 +00001149 log_to = VgLogTo_FileExactly;
sewardj603d4102005-01-11 14:01:02 +00001150 VG_(clo_log_name) = &arg[19];
1151 }
sewardjde4a1d02002-03-22 01:27:54 +00001152
nethercotef8548672004-06-21 12:42:35 +00001153 else if (VG_CLO_STREQN(13, arg, "--log-socket=")) {
njnbe9b47b2005-05-15 16:22:58 +00001154 log_to = VgLogTo_Socket;
nethercotef8548672004-06-21 12:42:35 +00001155 VG_(clo_log_name) = &arg[13];
sewardj73cf3bc2002-11-03 03:20:15 +00001156 }
1157
sewardj768db0e2005-07-19 14:18:56 +00001158 else if (VG_CLO_STREQN(19, arg, "--xml-user-comment=")) {
1159 VG_(clo_xml_user_comment) = &arg[19];
1160 }
1161
nethercote71980f02004-01-24 18:18:54 +00001162 else if (VG_CLO_STREQN(15, arg, "--suppressions=")) {
sewardjde4a1d02002-03-22 01:27:54 +00001163 if (VG_(clo_n_suppressions) >= VG_CLO_MAX_SFILES) {
njn25e49d8e72002-09-23 09:36:25 +00001164 VG_(message)(Vg_UserMsg, "Too many suppression files specified.");
sewardjde4a1d02002-03-22 01:27:54 +00001165 VG_(message)(Vg_UserMsg,
1166 "Increase VG_CLO_MAX_SFILES and recompile.");
nethercote71980f02004-01-24 18:18:54 +00001167 VG_(bad_option)(arg);
sewardjde4a1d02002-03-22 01:27:54 +00001168 }
nethercote71980f02004-01-24 18:18:54 +00001169 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = &arg[15];
sewardjde4a1d02002-03-22 01:27:54 +00001170 VG_(clo_n_suppressions)++;
1171 }
sewardjde4a1d02002-03-22 01:27:54 +00001172
sewardjfa8ec112005-01-19 11:55:34 +00001173 /* "stuvwxyz" --> stuvwxyz (binary) */
1174 else if (VG_CLO_STREQN(14, arg, "--trace-flags=")) {
1175 Int j;
1176 char* opt = & arg[14];
1177
1178 if (8 != VG_(strlen)(opt)) {
1179 VG_(message)(Vg_UserMsg,
1180 "--trace-flags argument must have 8 digits");
1181 VG_(bad_option)(arg);
1182 }
1183 for (j = 0; j < 8; j++) {
1184 if ('0' == opt[j]) { /* do nothing */ }
1185 else if ('1' == opt[j]) VG_(clo_trace_flags) |= (1 << (7-j));
1186 else {
1187 VG_(message)(Vg_UserMsg, "--trace-flags argument can only "
1188 "contain 0s and 1s");
1189 VG_(bad_option)(arg);
1190 }
1191 }
1192 }
1193
1194 /* "stuvwxyz" --> stuvwxyz (binary) */
1195 else if (VG_CLO_STREQN(16, arg, "--profile-flags=")) {
njn25e49d8e72002-09-23 09:36:25 +00001196 Int j;
nethercote71980f02004-01-24 18:18:54 +00001197 char* opt = & arg[16];
njn25e49d8e72002-09-23 09:36:25 +00001198
sewardj2a99cf62004-11-24 10:44:19 +00001199 if (8 != VG_(strlen)(opt)) {
njn25e49d8e72002-09-23 09:36:25 +00001200 VG_(message)(Vg_UserMsg,
sewardjfa8ec112005-01-19 11:55:34 +00001201 "--profile-flags argument must have 8 digits");
nethercote71980f02004-01-24 18:18:54 +00001202 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001203 }
sewardj8b635a42004-11-22 19:01:47 +00001204 for (j = 0; j < 8; j++) {
njn25e49d8e72002-09-23 09:36:25 +00001205 if ('0' == opt[j]) { /* do nothing */ }
sewardjfa8ec112005-01-19 11:55:34 +00001206 else if ('1' == opt[j]) VG_(clo_profile_flags) |= (1 << (7-j));
njn25e49d8e72002-09-23 09:36:25 +00001207 else {
sewardjfa8ec112005-01-19 11:55:34 +00001208 VG_(message)(Vg_UserMsg, "--profile-flags argument can only "
njn25e49d8e72002-09-23 09:36:25 +00001209 "contain 0s and 1s");
nethercote71980f02004-01-24 18:18:54 +00001210 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001211 }
1212 }
1213 }
sewardjde4a1d02002-03-22 01:27:54 +00001214
njn45270a22005-03-27 01:00:11 +00001215 else VG_NUM_CLO (arg, "--trace-notbelow", VG_(clo_trace_notbelow))
sewardjc771b292004-11-30 18:55:21 +00001216
sewardjd153fae2005-01-10 17:24:47 +00001217 else if (VG_CLO_STREQ(arg, "--gen-suppressions=no"))
1218 VG_(clo_gen_suppressions) = 0;
1219 else if (VG_CLO_STREQ(arg, "--gen-suppressions=yes"))
1220 VG_(clo_gen_suppressions) = 1;
1221 else if (VG_CLO_STREQ(arg, "--gen-suppressions=all"))
1222 VG_(clo_gen_suppressions) = 2;
1223
nethercote71980f02004-01-24 18:18:54 +00001224 else if ( ! VG_(needs).command_line_options
njn51d827b2005-05-09 01:02:08 +00001225 || ! VG_TDICT_CALL(tool_process_cmd_line_option, arg) ) {
nethercotef4928da2004-06-15 10:54:40 +00001226 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001227 }
njn8c0b3bb2005-03-12 21:20:39 +00001228 skip_arg:
sewardj45f4e7c2005-09-27 19:20:21 +00001229 if (arg != VG_(args_for_valgrind).strs[i]) {
1230 VG_(free)(arg);
1231 }
sewardjde4a1d02002-03-22 01:27:54 +00001232 }
1233
sewardj998d40d2004-12-06 14:24:52 +00001234 /* Make VEX control parameters sane */
1235
1236 if (VG_(clo_vex_control).guest_chase_thresh
1237 >= VG_(clo_vex_control).guest_max_insns)
1238 VG_(clo_vex_control).guest_chase_thresh
1239 = VG_(clo_vex_control).guest_max_insns - 1;
1240
1241 if (VG_(clo_vex_control).guest_chase_thresh < 0)
1242 VG_(clo_vex_control).guest_chase_thresh = 0;
1243
1244 /* Check various option values */
nethercote27fec902004-06-16 21:26:32 +00001245
njnf9ebf672003-05-12 21:41:30 +00001246 if (VG_(clo_verbosity) < 0)
sewardjde4a1d02002-03-22 01:27:54 +00001247 VG_(clo_verbosity) = 0;
1248
nethercote04d0fbc2004-01-26 16:48:06 +00001249 if (VG_(clo_db_attach) && VG_(clo_trace_children)) {
sewardjde4a1d02002-03-22 01:27:54 +00001250 VG_(message)(Vg_UserMsg, "");
1251 VG_(message)(Vg_UserMsg,
nethercote04d0fbc2004-01-26 16:48:06 +00001252 "--db-attach=yes conflicts with --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001253 VG_(message)(Vg_UserMsg,
1254 "Please choose one or the other, but not both.");
nethercote04d0fbc2004-01-26 16:48:06 +00001255 VG_(bad_option)("--db-attach=yes and --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001256 }
1257
njnbe9b47b2005-05-15 16:22:58 +00001258 if (VG_(clo_gen_suppressions) > 0 &&
1259 !VG_(needs).core_errors && !VG_(needs).tool_errors) {
1260 VG_(message)(Vg_UserMsg,
1261 "Can't use --gen-suppressions= with this tool,");
1262 VG_(message)(Vg_UserMsg,
1263 "as it doesn't generate errors.");
1264 VG_(bad_option)("--gen-suppressions=");
1265 }
1266
sewardj71bc3cb2005-05-19 00:25:45 +00001267 /* If we've been asked to emit XML, mash around various other
1268 options so as to constrain the output somewhat, and to remove
1269 any need for user input during the run. */
1270 if (VG_(clo_xml)) {
1271 /* Disable suppression generation (requires user input) */
1272 VG_(clo_gen_suppressions) = 0;
1273 /* Disable attaching to GDB (requires user input) */
1274 VG_(clo_db_attach) = False;
1275 /* Set a known verbosity level */
1276 VG_(clo_verbosity) = 1;
1277 /* Disable error limits (this might be a bad idea!) */
1278 VG_(clo_error_limit) = False;
1279 /* Disable emulation warnings */
1280 VG_(clo_show_emwarns) = False;
1281 /* Disable waiting for GDB to debug Valgrind */
1282 VG_(clo_wait_for_gdb) = False;
1283 /* No file-descriptor leak checking yet */
1284 VG_(clo_track_fds) = False;
sewardj21f7f0c2005-07-06 19:46:48 +00001285 /* Disable timestamped output */
1286 VG_(clo_time_stamp) = False;
sewardj71bc3cb2005-05-19 00:25:45 +00001287 /* Also, we want to set options for the leak checker, but that
1288 will have to be done in Memcheck's flag-handling code, not
1289 here. */
1290 }
1291
njnbe9b47b2005-05-15 16:22:58 +00001292 /* All non-logging-related options have been checked. If the logging
1293 option specified is ok, we can switch to it, as we know we won't
1294 have to generate any other command-line-related error messages.
1295 (So far we should be still attached to stderr, so we can show on
1296 the terminal any problems to do with processing command line
1297 opts.)
1298
1299 So set up logging now. After this is done, VG_(clo_log_fd)
sewardj4cf05692002-10-27 20:28:29 +00001300 should be connected to whatever sink has been selected, and we
1301 indiscriminately chuck stuff into it without worrying what the
1302 nature of it is. Oh the wonder of Unix streams. */
1303
njnbe9b47b2005-05-15 16:22:58 +00001304 vg_assert(VG_(clo_log_fd) == 2 /* stderr */);
1305 vg_assert(VG_(logging_to_socket) == False);
sewardj4cf05692002-10-27 20:28:29 +00001306
njnbe9b47b2005-05-15 16:22:58 +00001307 switch (log_to) {
sewardj73cf3bc2002-11-03 03:20:15 +00001308
sewardj4cf05692002-10-27 20:28:29 +00001309 case VgLogTo_Fd:
nethercotef8548672004-06-21 12:42:35 +00001310 vg_assert(VG_(clo_log_name) == NULL);
1311 VG_(clo_log_fd) = eventually_log_fd;
sewardj4cf05692002-10-27 20:28:29 +00001312 break;
sewardj73cf3bc2002-11-03 03:20:15 +00001313
sewardj4cf05692002-10-27 20:28:29 +00001314 case VgLogTo_File: {
sewardjad311162005-07-19 11:25:02 +00001315 HChar logfilename[1000];
1316 Int seq = 0;
1317 Int pid = VG_(getpid)();
1318 HChar* qual = NULL;
jsgff3c3f1a2003-10-14 22:13:28 +00001319
nethercotef8548672004-06-21 12:42:35 +00001320 vg_assert(VG_(clo_log_name) != NULL);
1321 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
jsgff3c3f1a2003-10-14 22:13:28 +00001322
sewardjad311162005-07-19 11:25:02 +00001323 if (VG_(clo_log_file_qualifier)) {
1324 qual = VG_(getenv)(VG_(clo_log_file_qualifier));
1325 }
1326
nethercote71980f02004-01-24 18:18:54 +00001327 for (;;) {
sewardj92645592005-07-23 09:18:34 +00001328 HChar pidtxt[20], seqtxt[20];
1329
1330 VG_(sprintf)(pidtxt, "%d", pid);
1331
1332 if (seq == 0)
1333 seqtxt[0] = 0;
1334 else
1335 VG_(sprintf)(seqtxt, ".%d", seq);
1336
jsgff3c3f1a2003-10-14 22:13:28 +00001337 seq++;
1338
sewardj92645592005-07-23 09:18:34 +00001339 /* Result:
1340 if (qual) base_name ++ "." ++ qual ++ seqtxt
1341 if (not qual) base_name ++ "." ++ pid ++ seqtxt
1342 */
1343 VG_(sprintf)( logfilename,
1344 "%s.%s%s",
1345 VG_(clo_log_name),
1346 qual ? qual : pidtxt,
1347 seqtxt );
1348
njnbe9b47b2005-05-15 16:22:58 +00001349 // EXCL: it will fail with EEXIST if the file already exists.
sewardj92645592005-07-23 09:18:34 +00001350 sres
jsgff3c3f1a2003-10-14 22:13:28 +00001351 = VG_(open)(logfilename,
1352 VKI_O_CREAT|VKI_O_WRONLY|VKI_O_EXCL|VKI_O_TRUNC,
1353 VKI_S_IRUSR|VKI_S_IWUSR);
sewardj92645592005-07-23 09:18:34 +00001354 if (!sres.isError) {
1355 eventually_log_fd = sres.val;
nethercotef8548672004-06-21 12:42:35 +00001356 VG_(clo_log_fd) = VG_(safe_fd)(eventually_log_fd);
sewardj603d4102005-01-11 14:01:02 +00001357 break; /* for (;;) */
jsgff3c3f1a2003-10-14 22:13:28 +00001358 } else {
njnbe9b47b2005-05-15 16:22:58 +00001359 // If the file already existed, we try the next name. If it
1360 // was some other file error, we give up.
sewardj92645592005-07-23 09:18:34 +00001361 if (sres.val != VKI_EEXIST) {
jsgff3c3f1a2003-10-14 22:13:28 +00001362 VG_(message)(Vg_UserMsg,
tombbe14b12005-11-04 16:49:39 +00001363 "Can't create/open log file '%s.%d'; giving up!",
nethercotef8548672004-06-21 12:42:35 +00001364 VG_(clo_log_name), pid);
jsgff3c3f1a2003-10-14 22:13:28 +00001365 VG_(bad_option)(
sewardj603d4102005-01-11 14:01:02 +00001366 "--log-file=<file> (didn't work out for some reason.)");
njnbe9b47b2005-05-15 16:22:58 +00001367 /*NOTREACHED*/
jsgff3c3f1a2003-10-14 22:13:28 +00001368 }
1369 }
1370 }
sewardj603d4102005-01-11 14:01:02 +00001371 break; /* switch (VG_(clo_log_to)) */
1372 }
1373
1374 case VgLogTo_FileExactly: {
sewardj603d4102005-01-11 14:01:02 +00001375 vg_assert(VG_(clo_log_name) != NULL);
1376 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
sewardj603d4102005-01-11 14:01:02 +00001377
sewardj92645592005-07-23 09:18:34 +00001378 sres
njnbe9b47b2005-05-15 16:22:58 +00001379 = VG_(open)(VG_(clo_log_name),
sewardj603d4102005-01-11 14:01:02 +00001380 VKI_O_CREAT|VKI_O_WRONLY|VKI_O_TRUNC,
1381 VKI_S_IRUSR|VKI_S_IWUSR);
sewardj92645592005-07-23 09:18:34 +00001382 if (!sres.isError) {
1383 eventually_log_fd = sres.val;
sewardj603d4102005-01-11 14:01:02 +00001384 VG_(clo_log_fd) = VG_(safe_fd)(eventually_log_fd);
njnbe9b47b2005-05-15 16:22:58 +00001385 } else {
sewardj603d4102005-01-11 14:01:02 +00001386 VG_(message)(Vg_UserMsg,
njn02bc4b82005-05-15 17:28:26 +00001387 "Can't create/open log file '%s'; giving up!",
sewardj603d4102005-01-11 14:01:02 +00001388 VG_(clo_log_name));
1389 VG_(bad_option)(
1390 "--log-file-exactly=<file> (didn't work out for some reason.)");
1391 /*NOTREACHED*/
1392 }
1393 break; /* switch (VG_(clo_log_to)) */
sewardj73cf3bc2002-11-03 03:20:15 +00001394 }
1395
1396 case VgLogTo_Socket: {
nethercotef8548672004-06-21 12:42:35 +00001397 vg_assert(VG_(clo_log_name) != NULL);
1398 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
1399 eventually_log_fd = VG_(connect_via_socket)( VG_(clo_log_name) );
1400 if (eventually_log_fd == -1) {
sewardj73cf3bc2002-11-03 03:20:15 +00001401 VG_(message)(Vg_UserMsg,
nethercotef8548672004-06-21 12:42:35 +00001402 "Invalid --log-socket=ipaddr or --log-socket=ipaddr:port spec");
sewardj73cf3bc2002-11-03 03:20:15 +00001403 VG_(message)(Vg_UserMsg,
njn02bc4b82005-05-15 17:28:26 +00001404 "of '%s'; giving up!", VG_(clo_log_name) );
sewardj73cf3bc2002-11-03 03:20:15 +00001405 VG_(bad_option)(
nethercotef8548672004-06-21 12:42:35 +00001406 "--log-socket=");
njnbe9b47b2005-05-15 16:22:58 +00001407 /*NOTREACHED*/
sewardj4cf05692002-10-27 20:28:29 +00001408 }
nethercotef8548672004-06-21 12:42:35 +00001409 if (eventually_log_fd == -2) {
sewardj73cf3bc2002-11-03 03:20:15 +00001410 VG_(message)(Vg_UserMsg,
njn02bc4b82005-05-15 17:28:26 +00001411 "valgrind: failed to connect to logging server '%s'.",
nethercotef8548672004-06-21 12:42:35 +00001412 VG_(clo_log_name) );
sewardj570f8902002-11-03 11:44:36 +00001413 VG_(message)(Vg_UserMsg,
1414 "Log messages will sent to stderr instead." );
1415 VG_(message)(Vg_UserMsg,
1416 "" );
1417 /* We don't change anything here. */
njnbe9b47b2005-05-15 16:22:58 +00001418 vg_assert(VG_(clo_log_fd) == 2);
sewardj570f8902002-11-03 11:44:36 +00001419 } else {
nethercotef8548672004-06-21 12:42:35 +00001420 vg_assert(eventually_log_fd > 0);
1421 VG_(clo_log_fd) = eventually_log_fd;
njnbe9b47b2005-05-15 16:22:58 +00001422 VG_(logging_to_socket) = True;
sewardj570f8902002-11-03 11:44:36 +00001423 }
sewardj73cf3bc2002-11-03 03:20:15 +00001424 break;
1425 }
sewardj4cf05692002-10-27 20:28:29 +00001426 }
1427
sewardj71bc3cb2005-05-19 00:25:45 +00001428
1429 /* Check that the requested tool actually supports XML output. */
sewardj45f4e7c2005-09-27 19:20:21 +00001430 if (VG_(clo_xml) && !VG_STREQ(toolname, "memcheck")
1431 && !VG_STREQ(toolname, "none")) {
sewardj71bc3cb2005-05-19 00:25:45 +00001432 VG_(clo_xml) = False;
1433 VG_(message)(Vg_UserMsg,
cerion39655202005-07-13 14:18:24 +00001434 "Currently only Memcheck|None supports XML output.");
sewardj71bc3cb2005-05-19 00:25:45 +00001435 VG_(bad_option)("--xml=yes");
1436 /*NOTREACHED*/
1437 }
1438
njnbe9b47b2005-05-15 16:22:58 +00001439 // Move log_fd into the safe range, so it doesn't conflict with any app fds.
1440 // XXX: this is more or less duplicating the behaviour of the calls to
1441 // VG_(safe_fd)() above, although this does not close the original fd.
1442 // Perhaps the VG_(safe_fd)() calls above should be removed, and this
1443 // code should be replaced with a call to VG_(safe_fd)(). --njn
thughesad1c9562004-06-26 11:27:52 +00001444 eventually_log_fd = VG_(fcntl)(VG_(clo_log_fd), VKI_F_DUPFD, VG_(fd_hard_limit));
nethercotef8548672004-06-21 12:42:35 +00001445 if (eventually_log_fd < 0)
jsgf855d93d2003-10-13 22:26:55 +00001446 VG_(message)(Vg_UserMsg, "valgrind: failed to move logfile fd into safe range");
1447 else {
nethercotef8548672004-06-21 12:42:35 +00001448 VG_(clo_log_fd) = eventually_log_fd;
1449 VG_(fcntl)(VG_(clo_log_fd), VKI_F_SETFD, VKI_FD_CLOEXEC);
jsgf855d93d2003-10-13 22:26:55 +00001450 }
1451
sewardj45f4e7c2005-09-27 19:20:21 +00001452 if (VG_(clo_n_suppressions) < VG_CLO_MAX_SFILES-1 &&
1453 (VG_(needs).core_errors || VG_(needs).tool_errors)) {
1454 /* If we haven't reached the max number of suppressions, load
1455 the default one. */
1456 static const Char default_supp[] = "default.supp";
1457 Int len = VG_(strlen)(VG_(libdir)) + 1 + sizeof(default_supp);
1458 Char *buf = VG_(arena_malloc)(VG_AR_CORE, len);
1459 VG_(sprintf)(buf, "%s/%s", VG_(libdir), default_supp);
1460 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = buf;
1461 VG_(clo_n_suppressions)++;
1462 }
sewardjde4a1d02002-03-22 01:27:54 +00001463
sewardj45f4e7c2005-09-27 19:20:21 +00001464 return (log_to == VgLogTo_Fd);
1465}
1466
1467
1468/*====================================================================*/
1469/*=== Printing the preamble ===*/
1470/*====================================================================*/
1471
1472/* Ok, the logging sink is running now. Print a suitable preamble.
1473 If logging to file or a socket, write details of parent PID and
1474 command line args, to help people trying to interpret the
1475 results of a run which encompasses multiple processes. */
1476static void print_preamble(Bool logging_to_fd, const char* toolname)
1477{
tom60a4b0b2005-10-12 10:45:27 +00001478 HChar* xpre = VG_(clo_xml) ? " <line>" : "";
1479 HChar* xpost = VG_(clo_xml) ? "</line>" : "";
1480 Int i;
1481
sewardj71bc3cb2005-05-19 00:25:45 +00001482 if (VG_(clo_xml)) {
sewardj8665d8e2005-06-01 17:35:23 +00001483 VG_(message)(Vg_UserMsg, "<?xml version=\"1.0\"?>");
1484 VG_(message)(Vg_UserMsg, "");
sewardj71bc3cb2005-05-19 00:25:45 +00001485 VG_(message)(Vg_UserMsg, "<valgrindoutput>");
1486 VG_(message)(Vg_UserMsg, "");
cerion20241ba2005-11-15 19:07:53 +00001487 VG_(message)(Vg_UserMsg, "<protocolversion>2</protocolversion>");
sewardj71bc3cb2005-05-19 00:25:45 +00001488 VG_(message)(Vg_UserMsg, "");
1489 }
1490
sewardj83adf412002-05-01 01:25:45 +00001491 if (VG_(clo_verbosity > 0)) {
sewardjd7bddad2005-06-13 16:48:32 +00001492
1493 if (VG_(clo_xml))
1494 VG_(message)(Vg_UserMsg, "<preamble>");
1495
nethercote996901a2004-08-03 13:29:09 +00001496 /* Tool details */
sewardj71bc3cb2005-05-19 00:25:45 +00001497 VG_(message)(Vg_UserMsg, "%s%s%s%s, %s.%s",
1498 xpre,
njnd04b7c62002-10-03 14:05:52 +00001499 VG_(details).name,
njnb9c427c2004-12-01 14:14:42 +00001500 NULL == VG_(details).version ? "" : "-",
njnd04b7c62002-10-03 14:05:52 +00001501 NULL == VG_(details).version
1502 ? (Char*)"" : VG_(details).version,
sewardj71bc3cb2005-05-19 00:25:45 +00001503 VG_(details).description,
1504 xpost);
1505 VG_(message)(Vg_UserMsg, "%s%s%s",
1506 xpre, VG_(details).copyright_author, xpost);
sewardj3b2736a2002-03-24 12:18:35 +00001507
njnd04b7c62002-10-03 14:05:52 +00001508 /* Core details */
1509 VG_(message)(Vg_UserMsg,
sewardj71bc3cb2005-05-19 00:25:45 +00001510 "%sUsing LibVEX rev %s, a library for dynamic binary translation.%s",
1511 xpre, LibVEX_Version(), xpost );
sewardjc7025332004-12-13 18:30:39 +00001512 VG_(message)(Vg_UserMsg,
sewardj71bc3cb2005-05-19 00:25:45 +00001513 "%sCopyright (C) 2004-2005, and GNU GPL'd, by OpenWorks LLP.%s",
1514 xpre, xpost );
sewardjc7025332004-12-13 18:30:39 +00001515 VG_(message)(Vg_UserMsg,
sewardj71bc3cb2005-05-19 00:25:45 +00001516 "%sUsing valgrind-%s, a dynamic binary instrumentation framework.%s",
1517 xpre, VERSION, xpost);
sewardjde4a1d02002-03-22 01:27:54 +00001518 VG_(message)(Vg_UserMsg,
sewardj71bc3cb2005-05-19 00:25:45 +00001519 "%sCopyright (C) 2000-2005, and GNU GPL'd, by Julian Seward et al.%s",
1520 xpre, xpost );
sewardjd7bddad2005-06-13 16:48:32 +00001521
sewardj45f4e7c2005-09-27 19:20:21 +00001522 if (VG_(clo_verbosity) == 1 && !VG_(clo_xml))
1523 VG_(message)(Vg_UserMsg, "For more details, rerun with: -v");
1524
sewardjd7bddad2005-06-13 16:48:32 +00001525 if (VG_(clo_xml))
1526 VG_(message)(Vg_UserMsg, "</preamble>");
njnd04b7c62002-10-03 14:05:52 +00001527 }
1528
sewardj45f4e7c2005-09-27 19:20:21 +00001529 if (!VG_(clo_xml) && VG_(clo_verbosity) > 0 && !logging_to_fd) {
sewardj4cf05692002-10-27 20:28:29 +00001530 VG_(message)(Vg_UserMsg, "");
1531 VG_(message)(Vg_UserMsg,
1532 "My PID = %d, parent PID = %d. Prog and args are:",
1533 VG_(getpid)(), VG_(getppid)() );
sewardj5e940782005-09-28 19:59:19 +00001534 if (VG_(args_the_exename))
1535 VG_(message)(Vg_UserMsg, " %s", VG_(args_the_exename));
sewardj45f4e7c2005-09-27 19:20:21 +00001536 for (i = 0; i < VG_(args_for_client).used; i++)
1537 VG_(message)(Vg_UserMsg, " %s", VG_(args_for_client).strs[i]);
sewardj5b742c32005-07-26 23:43:26 +00001538 if (VG_(clo_log_file_qualifier)) {
1539 HChar* val = VG_(getenv)(VG_(clo_log_file_qualifier));
1540 VG_(message)(Vg_UserMsg, "");
1541 VG_(message)(Vg_UserMsg, "Log file qualifier: var %s, value %s.",
1542 VG_(clo_log_file_qualifier),
1543 val ? val : "");
1544 }
sewardj4cf05692002-10-27 20:28:29 +00001545 }
sewardj71bc3cb2005-05-19 00:25:45 +00001546 else
1547 if (VG_(clo_xml)) {
1548 VG_(message)(Vg_UserMsg, "");
1549 VG_(message)(Vg_UserMsg, "<pid>%d</pid>", VG_(getpid)());
1550 VG_(message)(Vg_UserMsg, "<ppid>%d</ppid>", VG_(getppid)());
sewardj97f7e0c2005-07-19 15:00:25 +00001551 VG_(message)(Vg_UserMsg, "<tool>%t</tool>", toolname);
sewardjad311162005-07-19 11:25:02 +00001552 if (VG_(clo_log_file_qualifier)) {
1553 HChar* val = VG_(getenv)(VG_(clo_log_file_qualifier));
sewardj97f7e0c2005-07-19 15:00:25 +00001554 VG_(message)(Vg_UserMsg, "<logfilequalifier> <var>%t</var> "
1555 "<value>%t</value> </logfilequalifier>",
sewardjad311162005-07-19 11:25:02 +00001556 VG_(clo_log_file_qualifier),
1557 val ? val : "");
1558 }
sewardj768db0e2005-07-19 14:18:56 +00001559 if (VG_(clo_xml_user_comment)) {
1560 /* Note: the user comment itself is XML and is therefore to
1561 be passed through verbatim (%s) rather than escaped
1562 (%t). */
1563 VG_(message)(Vg_UserMsg, "<usercomment>%s</usercomment>",
1564 VG_(clo_xml_user_comment));
1565 }
sewardj71bc3cb2005-05-19 00:25:45 +00001566 VG_(message)(Vg_UserMsg, "");
sewardjb8a3dac2005-07-19 12:39:11 +00001567 VG_(message)(Vg_UserMsg, "<args>");
sewardj45f4e7c2005-09-27 19:20:21 +00001568
sewardjb8a3dac2005-07-19 12:39:11 +00001569 VG_(message)(Vg_UserMsg, " <vargv>");
sewardj45f4e7c2005-09-27 19:20:21 +00001570 if (VG_(name_of_launcher))
1571 VG_(message)(Vg_UserMsg, " <exe>%t</exe>",
1572 VG_(name_of_launcher));
1573 for (i = 0; i < VG_(args_for_valgrind).used; i++) {
1574 VG_(message)(Vg_UserMsg,
1575 " <arg>%t</arg>",
1576 VG_(args_for_valgrind).strs[i]);
sewardjb8a3dac2005-07-19 12:39:11 +00001577 }
1578 VG_(message)(Vg_UserMsg, " </vargv>");
sewardj45f4e7c2005-09-27 19:20:21 +00001579
sewardjb8a3dac2005-07-19 12:39:11 +00001580 VG_(message)(Vg_UserMsg, " <argv>");
sewardj45f4e7c2005-09-27 19:20:21 +00001581 if (VG_(args_the_exename))
1582 VG_(message)(Vg_UserMsg, " <exe>%t</exe>",
1583 VG_(args_the_exename));
1584 for (i = 0; i < VG_(args_for_client).used; i++) {
1585 VG_(message)(Vg_UserMsg, " <arg>%t</arg>",
1586 VG_(args_for_client).strs[i]);
sewardj8665d8e2005-06-01 17:35:23 +00001587 }
sewardjb8a3dac2005-07-19 12:39:11 +00001588 VG_(message)(Vg_UserMsg, " </argv>");
sewardj45f4e7c2005-09-27 19:20:21 +00001589
sewardjb8a3dac2005-07-19 12:39:11 +00001590 VG_(message)(Vg_UserMsg, "</args>");
sewardj71bc3cb2005-05-19 00:25:45 +00001591 }
sewardj4cf05692002-10-27 20:28:29 +00001592
sewardj45f4e7c2005-09-27 19:20:21 +00001593 // Empty line after the preamble
1594 if (VG_(clo_verbosity) > 0)
1595 VG_(message)(Vg_UserMsg, "");
1596
sewardjde4a1d02002-03-22 01:27:54 +00001597 if (VG_(clo_verbosity) > 1) {
sewardj92645592005-07-23 09:18:34 +00001598 SysRes fd;
sewardj1f0bbc72005-11-16 03:51:02 +00001599 VexArch vex_arch;
1600 VexArchInfo vex_archinfo;
sewardj45f4e7c2005-09-27 19:20:21 +00001601 if (!logging_to_fd)
njn1fd5eb22005-03-13 05:43:23 +00001602 VG_(message)(Vg_DebugMsg, "");
njn1fd5eb22005-03-13 05:43:23 +00001603 VG_(message)(Vg_DebugMsg, "Command line");
sewardj45f4e7c2005-09-27 19:20:21 +00001604 if (VG_(args_the_exename))
1605 VG_(message)(Vg_DebugMsg, " %s", VG_(args_the_exename));
1606 for (i = 0; i < VG_(args_for_client).used; i++)
1607 VG_(message)(Vg_DebugMsg, " %s", VG_(args_for_client).strs[i]);
njn86dc2bc2003-09-09 07:26:21 +00001608
njn1fd5eb22005-03-13 05:43:23 +00001609 VG_(message)(Vg_DebugMsg, "Startup, with flags:");
sewardj45f4e7c2005-09-27 19:20:21 +00001610 for (i = 0; i < VG_(args_for_valgrind).used; i++) {
1611 VG_(message)(Vg_DebugMsg, " %s", VG_(args_for_valgrind).strs[i]);
sewardjde4a1d02002-03-22 01:27:54 +00001612 }
nethercotea70f7352004-04-18 12:08:46 +00001613
njn1fd5eb22005-03-13 05:43:23 +00001614 VG_(message)(Vg_DebugMsg, "Contents of /proc/version:");
nethercotea70f7352004-04-18 12:08:46 +00001615 fd = VG_(open) ( "/proc/version", VKI_O_RDONLY, 0 );
sewardj92645592005-07-23 09:18:34 +00001616 if (fd.isError) {
njn1fd5eb22005-03-13 05:43:23 +00001617 VG_(message)(Vg_DebugMsg, " can't open /proc/version");
nethercotea70f7352004-04-18 12:08:46 +00001618 } else {
sewardj71bc3cb2005-05-19 00:25:45 +00001619# define BUF_LEN 256
nethercotea70f7352004-04-18 12:08:46 +00001620 Char version_buf[BUF_LEN];
sewardj92645592005-07-23 09:18:34 +00001621 Int n = VG_(read) ( fd.val, version_buf, BUF_LEN );
njnbe9b47b2005-05-15 16:22:58 +00001622 vg_assert(n <= BUF_LEN);
nethercotea70f7352004-04-18 12:08:46 +00001623 if (n > 0) {
1624 version_buf[n-1] = '\0';
njn1fd5eb22005-03-13 05:43:23 +00001625 VG_(message)(Vg_DebugMsg, " %s", version_buf);
nethercotea70f7352004-04-18 12:08:46 +00001626 } else {
njn1fd5eb22005-03-13 05:43:23 +00001627 VG_(message)(Vg_DebugMsg, " (empty?)");
nethercotea70f7352004-04-18 12:08:46 +00001628 }
sewardj92645592005-07-23 09:18:34 +00001629 VG_(close)(fd.val);
sewardj71bc3cb2005-05-19 00:25:45 +00001630# undef BUF_LEN
nethercotea70f7352004-04-18 12:08:46 +00001631 }
sewardj1f0bbc72005-11-16 03:51:02 +00001632
1633 VG_(machine_get_VexArchInfo)( &vex_arch, &vex_archinfo );
1634 VG_(message)(Vg_DebugMsg, "Arch and subarch: %s, %s",
1635 LibVEX_ppVexArch ( vex_arch ),
1636 LibVEX_ppVexSubArch( vex_archinfo.subarch ) );
1637 VG_(message)(Vg_DebugMsg, "Valgrind library directory: %s", VG_(libdir));
sewardjde4a1d02002-03-22 01:27:54 +00001638 }
nethercotef6a1d502004-08-09 12:21:57 +00001639}
1640
sewardjde4a1d02002-03-22 01:27:54 +00001641
nethercote71980f02004-01-24 18:18:54 +00001642/*====================================================================*/
1643/*=== File descriptor setup ===*/
1644/*====================================================================*/
1645
sewardj5f229e22005-09-28 01:36:01 +00001646/* Number of file descriptors that Valgrind tries to reserve for
1647 it's own use - just a small constant. */
1648#define N_RESERVED_FDS (10)
1649
nethercote71980f02004-01-24 18:18:54 +00001650static void setup_file_descriptors(void)
1651{
1652 struct vki_rlimit rl;
1653
1654 /* Get the current file descriptor limits. */
1655 if (VG_(getrlimit)(VKI_RLIMIT_NOFILE, &rl) < 0) {
1656 rl.rlim_cur = 1024;
1657 rl.rlim_max = 1024;
1658 }
1659
1660 /* Work out where to move the soft limit to. */
njn14319cc2005-03-13 06:26:22 +00001661 if (rl.rlim_cur + N_RESERVED_FDS <= rl.rlim_max) {
1662 rl.rlim_cur = rl.rlim_cur + N_RESERVED_FDS;
nethercote71980f02004-01-24 18:18:54 +00001663 } else {
1664 rl.rlim_cur = rl.rlim_max;
1665 }
1666
1667 /* Reserve some file descriptors for our use. */
njn14319cc2005-03-13 06:26:22 +00001668 VG_(fd_soft_limit) = rl.rlim_cur - N_RESERVED_FDS;
1669 VG_(fd_hard_limit) = rl.rlim_cur - N_RESERVED_FDS;
nethercote71980f02004-01-24 18:18:54 +00001670
1671 /* Update the soft limit. */
1672 VG_(setrlimit)(VKI_RLIMIT_NOFILE, &rl);
1673
sewardj45f4e7c2005-09-27 19:20:21 +00001674 if (VG_(cl_exec_fd) != -1)
1675 VG_(cl_exec_fd) = VG_(safe_fd)( VG_(cl_exec_fd) );
nethercote71980f02004-01-24 18:18:54 +00001676}
1677
sewardjde4a1d02002-03-22 01:27:54 +00001678
njn2da73352005-06-18 01:35:16 +00001679/*====================================================================*/
1680/*=== Initialise the first thread. ===*/
1681/*====================================================================*/
1682
1683/* Given a pointer to the ThreadArchState for thread 1 (the root
1684 thread), initialise the VEX guest state, and copy in essential
1685 starting values.
1686*/
1687static void init_thread1state ( Addr client_ip,
sewardjfdf91b42005-09-28 00:53:09 +00001688 Addr client_sp,
njn2da73352005-06-18 01:35:16 +00001689 /*inout*/ ThreadArchState* arch )
1690{
1691#if defined(VGA_x86)
1692 vg_assert(0 == sizeof(VexGuestX86State) % 8);
1693
1694 /* Zero out the initial state, and set up the simulated FPU in a
1695 sane way. */
1696 LibVEX_GuestX86_initialise(&arch->vex);
1697
1698 /* Zero out the shadow area. */
1699 VG_(memset)(&arch->vex_shadow, 0, sizeof(VexGuestX86State));
1700
1701 /* Put essential stuff into the new state. */
sewardjfdf91b42005-09-28 00:53:09 +00001702 arch->vex.guest_ESP = client_sp;
njn2da73352005-06-18 01:35:16 +00001703 arch->vex.guest_EIP = client_ip;
1704
1705 /* initialise %cs, %ds and %ss to point at the operating systems
1706 default code, data and stack segments */
1707 asm volatile("movw %%cs, %0" : : "m" (arch->vex.guest_CS));
1708 asm volatile("movw %%ds, %0" : : "m" (arch->vex.guest_DS));
1709 asm volatile("movw %%ss, %0" : : "m" (arch->vex.guest_SS));
cerion85665ca2005-06-20 15:51:07 +00001710
njn2da73352005-06-18 01:35:16 +00001711#elif defined(VGA_amd64)
1712 vg_assert(0 == sizeof(VexGuestAMD64State) % 8);
1713
1714 /* Zero out the initial state, and set up the simulated FPU in a
1715 sane way. */
1716 LibVEX_GuestAMD64_initialise(&arch->vex);
1717
1718 /* Zero out the shadow area. */
1719 VG_(memset)(&arch->vex_shadow, 0, sizeof(VexGuestAMD64State));
1720
1721 /* Put essential stuff into the new state. */
sewardjfdf91b42005-09-28 00:53:09 +00001722 arch->vex.guest_RSP = client_sp;
njn2da73352005-06-18 01:35:16 +00001723 arch->vex.guest_RIP = client_ip;
cerion85665ca2005-06-20 15:51:07 +00001724
1725#elif defined(VGA_ppc32)
1726 vg_assert(0 == sizeof(VexGuestPPC32State) % 8);
1727
1728 /* Zero out the initial state, and set up the simulated FPU in a
1729 sane way. */
1730 LibVEX_GuestPPC32_initialise(&arch->vex);
1731
1732 /* Zero out the shadow area. */
1733 VG_(memset)(&arch->vex_shadow, 0, sizeof(VexGuestPPC32State));
1734
1735 /* Put essential stuff into the new state. */
sewardjfdf91b42005-09-28 00:53:09 +00001736 arch->vex.guest_GPR1 = client_sp;
cerion85665ca2005-06-20 15:51:07 +00001737 arch->vex.guest_CIA = client_ip;
1738
njn2da73352005-06-18 01:35:16 +00001739#else
1740# error Unknown arch
1741#endif
1742 // Tell the tool that we just wrote to the registers.
1743 VG_TRACK( post_reg_write, Vg_CoreStartup, /*tid*/1, /*offset*/0,
1744 sizeof(VexGuestArchState));
1745}
1746
sewardjde4a1d02002-03-22 01:27:54 +00001747
nethercote71980f02004-01-24 18:18:54 +00001748/*====================================================================*/
njn2025cf92005-06-26 20:44:48 +00001749/*=== BB profiling ===*/
1750/*====================================================================*/
1751
1752static
1753void show_BB_profile ( BBProfEntry tops[], UInt n_tops, ULong score_total )
1754{
1755 ULong score_cumul, score_here;
1756 Char buf_cumul[10], buf_here[10];
1757 Char name[64];
1758 Int r;
1759
1760 VG_(printf)("\n");
1761 VG_(printf)("-----------------------------------------------------------\n");
1762 VG_(printf)("--- BEGIN BB Profile (summary of scores) ---\n");
1763 VG_(printf)("-----------------------------------------------------------\n");
1764 VG_(printf)("\n");
1765
1766 VG_(printf)("Total score = %lld\n\n", score_total);
1767
1768 score_cumul = 0;
1769 for (r = 0; r < n_tops; r++) {
1770 if (tops[r].addr == 0)
1771 continue;
1772 name[0] = 0;
1773 VG_(get_fnname_w_offset)(tops[r].addr, name, 64);
1774 name[63] = 0;
1775 score_here = tops[r].score;
1776 score_cumul += score_here;
1777 VG_(percentify)(score_cumul, score_total, 2, 6, buf_cumul);
1778 VG_(percentify)(score_here, score_total, 2, 6, buf_here);
1779 VG_(printf)("%3d: (%9lld %s) %9lld %s 0x%llx %s\n",
1780 r,
1781 score_cumul, buf_cumul,
1782 score_here, buf_here, tops[r].addr, name );
1783 }
1784
1785 VG_(printf)("\n");
1786 VG_(printf)("-----------------------------------------------------------\n");
1787 VG_(printf)("--- BB Profile (BB details) ---\n");
1788 VG_(printf)("-----------------------------------------------------------\n");
1789 VG_(printf)("\n");
1790
1791 score_cumul = 0;
1792 for (r = 0; r < n_tops; r++) {
1793 if (tops[r].addr == 0)
1794 continue;
1795 name[0] = 0;
1796 VG_(get_fnname_w_offset)(tops[r].addr, name, 64);
1797 name[63] = 0;
1798 score_here = tops[r].score;
1799 score_cumul += score_here;
1800 VG_(percentify)(score_cumul, score_total, 2, 6, buf_cumul);
1801 VG_(percentify)(score_here, score_total, 2, 6, buf_here);
1802 VG_(printf)("\n");
1803 VG_(printf)("=-=-=-=-=-=-=-=-=-=-=-=-=-= begin BB rank %d "
1804 "=-=-=-=-=-=-=-=-=-=-=-=-=-=\n\n", r);
1805 VG_(printf)("%3d: (%9lld %s) %9lld %s 0x%llx %s\n",
1806 r,
1807 score_cumul, buf_cumul,
1808 score_here, buf_here, tops[r].addr, name );
1809 VG_(printf)("\n");
1810 VG_(translate)(0, tops[r].addr, True, VG_(clo_profile_flags), 0);
1811 VG_(printf)("=-=-=-=-=-=-=-=-=-=-=-=-=-= end BB rank %d "
1812 "=-=-=-=-=-=-=-=-=-=-=-=-=-=\n\n", r);
1813 }
1814
1815 VG_(printf)("\n");
1816 VG_(printf)("-----------------------------------------------------------\n");
1817 VG_(printf)("--- END BB Profile ---\n");
1818 VG_(printf)("-----------------------------------------------------------\n");
1819 VG_(printf)("\n");
1820}
1821
1822
1823/*====================================================================*/
nethercote71980f02004-01-24 18:18:54 +00001824/*=== main() ===*/
1825/*====================================================================*/
1826
sewardjfdf91b42005-09-28 00:53:09 +00001827/* When main() is entered, we should be on the following stack, not
1828 the one the kernel gave us. We will run on this stack until
1829 simulation of the root thread is started, at which point a transfer
1830 is made to a dynamically allocated stack. This is for the sake of
1831 uniform overflow detection for all Valgrind threads. This is
1832 marked global even though it isn't, because assembly code below
1833 needs to reference the name. */
1834
1835/*static*/ VgStack VG_(interim_stack);
1836
1837/* This should get some address inside the stack on which we gained
1838 control (eg, it could be the SP at startup). It doesn't matter
1839 exactly where in the stack it is. This value is passed to the
1840 address space manager at startup, which uses it to identify the
1841 initial stack segment and hence the upper end of the usable address
1842 space. */
1843
1844static Addr sp_at_startup = 0;
1845
sewardj1ae3f3a2005-09-28 10:47:38 +00001846/* --- Forwards decls to do with shutdown --- */
1847
1848static void final_tidyup(ThreadId tid);
1849
1850/* Do everything which needs doing when the last thread exits */
1851static
1852void shutdown_actions_NORETURN( ThreadId tid,
1853 VgSchedReturnCode tids_schedretcode );
1854
1855/* --- end of Forwards decls to do with shutdown --- */
sewardjfdf91b42005-09-28 00:53:09 +00001856
1857
sewardj45f4e7c2005-09-27 19:20:21 +00001858/* TODO: GIVE THIS A PROPER HOME
1859 TODO: MERGE THIS WITH DUPLICATE IN mac_leakcheck.c
1860 Extract from aspacem a vector of the current segment start
1861 addresses. The vector is dynamically allocated and should be freed
1862 by the caller when done. REQUIRES m_mallocfree to be running.
1863 Writes the number of addresses required into *n_acquired. */
nethercotec314eba2004-07-15 12:59:41 +00001864
sewardj45f4e7c2005-09-27 19:20:21 +00001865static Addr* get_seg_starts ( /*OUT*/Int* n_acquired )
sewardj1cf558c2005-04-25 01:36:56 +00001866{
sewardj45f4e7c2005-09-27 19:20:21 +00001867 Addr* starts;
sewardja48a4932005-09-29 11:09:56 +00001868 Int n_starts, r = 0;
sewardj45f4e7c2005-09-27 19:20:21 +00001869
1870 n_starts = 1;
sewardj1cf558c2005-04-25 01:36:56 +00001871 while (True) {
sewardj45f4e7c2005-09-27 19:20:21 +00001872 starts = VG_(malloc)( n_starts * sizeof(Addr) );
1873 if (starts == NULL)
1874 break;
1875 r = VG_(am_get_segment_starts)( starts, n_starts );
1876 if (r >= 0)
1877 break;
1878 VG_(free)(starts);
1879 n_starts *= 2;
sewardj1cf558c2005-04-25 01:36:56 +00001880 }
sewardj45f4e7c2005-09-27 19:20:21 +00001881
1882 if (starts == NULL) {
1883 *n_acquired = 0;
1884 return NULL;
1885 }
1886
1887 *n_acquired = r;
1888 return starts;
sewardj1cf558c2005-04-25 01:36:56 +00001889}
1890
1891
sewardj45f4e7c2005-09-27 19:20:21 +00001892
sewardj45f4e7c2005-09-27 19:20:21 +00001893Int main(Int argc, HChar **argv, HChar **envp)
nethercote71980f02004-01-24 18:18:54 +00001894{
sewardj45f4e7c2005-09-27 19:20:21 +00001895 HChar* toolname = "memcheck"; // default to Memcheck
1896 HChar** env = NULL;
1897 Int need_help = 0; // 0 = no, 1 = --help, 2 = --help-debug
1898 Addr initial_client_IP = 0;
1899 Addr initial_client_SP = 0;
1900 Addr clstack_top = 0;
1901 SizeT clstack_max_size = 0;
1902 UInt* client_auxv;
1903 Int loglevel, i;
1904 Bool logging_to_fd;
nethercote73b526f2004-10-31 18:48:21 +00001905 struct vki_rlimit zero = { 0, 0 };
sewardj45f4e7c2005-09-27 19:20:21 +00001906 struct exeinfo info;
nethercote71980f02004-01-24 18:18:54 +00001907
1908 //============================================================
nethercote71980f02004-01-24 18:18:54 +00001909 //
sewardj45f4e7c2005-09-27 19:20:21 +00001910 // Nb: startup is complex. Prerequisites are shown at every step.
nethercote71980f02004-01-24 18:18:54 +00001911 // *** Be very careful when messing with the order ***
sewardj45f4e7c2005-09-27 19:20:21 +00001912 //
1913 // The first order of business is to get debug logging, the address
1914 // space manager and the dynamic memory manager up and running.
1915 // Once that's done, we can relax a bit.
1916 //
nethercote71980f02004-01-24 18:18:54 +00001917 //============================================================
sewardj45f4e7c2005-09-27 19:20:21 +00001918
1919 /* This is needed to make VG_(getenv) usable early. */
1920 VG_(client_envp) = (Char**)envp;
nethercote71980f02004-01-24 18:18:54 +00001921
sewardj1cf558c2005-04-25 01:36:56 +00001922 //--------------------------------------------------------------
1923 // Start up the logging mechanism
1924 // p: none
1925 //--------------------------------------------------------------
1926 /* Start the debugging-log system ASAP. First find out how many
1927 "-d"s were specified. This is a pre-scan of the command line. */
1928 loglevel = 0;
1929 for (i = 1; i < argc; i++) {
sewardj10759312005-05-30 23:52:47 +00001930 if (argv[i][0] != '-')
1931 break;
sewardj45f4e7c2005-09-27 19:20:21 +00001932 if (VG_STREQ(argv[i], "--"))
sewardj10759312005-05-30 23:52:47 +00001933 break;
sewardj45f4e7c2005-09-27 19:20:21 +00001934 if (VG_STREQ(argv[i], "-d"))
sewardj10759312005-05-30 23:52:47 +00001935 loglevel++;
sewardj1cf558c2005-04-25 01:36:56 +00001936 }
1937
1938 /* ... and start the debug logger. Now we can safely emit logging
1939 messages all through startup. */
sewardj10759312005-05-30 23:52:47 +00001940 VG_(debugLog_startup)(loglevel, "Stage 2 (main)");
sewardj45f4e7c2005-09-27 19:20:21 +00001941 VG_(debugLog)(1, "main", "Welcome to Valgrind version "
1942 VERSION " debug logging\n");
1943
1944 //--------------------------------------------------------------
1945 // Ensure we're on a plausible stack.
1946 // p: logging
1947 //--------------------------------------------------------------
1948 VG_(debugLog)(1, "main", "Checking current stack is plausible\n");
sewardjfdf91b42005-09-28 00:53:09 +00001949 { HChar* limLo = (HChar*)(&VG_(interim_stack).bytes[0]);
1950 HChar* limHi = limLo + sizeof(VG_(interim_stack));
sewardj45f4e7c2005-09-27 19:20:21 +00001951 HChar* aLocal = (HChar*)&zero; /* any auto local will do */
1952 if (aLocal < limLo || aLocal >= limHi) {
1953 /* something's wrong. Stop. */
1954 VG_(debugLog)(0, "main", "Root stack %p to %p, a local %p\n",
1955 limLo, limHi, aLocal );
1956 VG_(debugLog)(0, "main", "Valgrind: FATAL: "
1957 "Initial stack switched failed.\n");
1958 VG_(debugLog)(0, "main", " Cannot continue. Sorry.\n");
1959 VG_(exit)(1);
1960 }
1961 }
1962
1963 //--------------------------------------------------------------
1964 // Ensure we have a plausible pointer to the stack on which
1965 // we gained control (not the current stack!)
1966 // p: logging
1967 //--------------------------------------------------------------
1968 VG_(debugLog)(1, "main", "Checking initial stack was noted\n");
sewardjfdf91b42005-09-28 00:53:09 +00001969 if (sp_at_startup == 0) {
sewardj45f4e7c2005-09-27 19:20:21 +00001970 VG_(debugLog)(0, "main", "Valgrind: FATAL: "
1971 "Initial stack was not noted.\n");
1972 VG_(debugLog)(0, "main", " Cannot continue. Sorry.\n");
1973 VG_(exit)(1);
1974 }
1975
1976 //--------------------------------------------------------------
1977 // Start up the address space manager, and determine the
1978 // approximate location of the client's stack
1979 // p: logging, plausible-stack
1980 //--------------------------------------------------------------
1981 VG_(debugLog)(1, "main", "Starting the address space manager\n");
sewardjfdf91b42005-09-28 00:53:09 +00001982 clstack_top = VG_(am_startup)( sp_at_startup );
sewardj45f4e7c2005-09-27 19:20:21 +00001983 VG_(debugLog)(1, "main", "Address space manager is running\n");
1984
1985 //--------------------------------------------------------------
1986 // Start up the dynamic memory manager
1987 // p: address space management
1988 // In fact m_mallocfree is self-initialising, so there's no
1989 // initialisation call to do. Instead, try a simple malloc/
1990 // free pair right now to check that nothing is broken.
1991 //--------------------------------------------------------------
1992 VG_(debugLog)(1, "main", "Starting the dynamic memory manager\n");
1993 { void* p = VG_(malloc)( 12345 );
1994 if (p) VG_(free)( p );
1995 }
1996 VG_(debugLog)(1, "main", "Dynamic memory manager is running\n");
sewardj1cf558c2005-04-25 01:36:56 +00001997
nethercotef4928da2004-06-15 10:54:40 +00001998 //============================================================
sewardj45f4e7c2005-09-27 19:20:21 +00001999 //
2000 // Dynamic memory management is now available.
2001 //
nethercotef4928da2004-06-15 10:54:40 +00002002 //============================================================
2003
sewardj45f4e7c2005-09-27 19:20:21 +00002004 //--------------------------------------------------------------
2005 // Look for alternative libdir
2006 { HChar *cp = VG_(getenv)(VALGRIND_LIB);
2007 if (cp != NULL)
2008 VG_(libdir) = cp;
2009 }
2010
2011 //--------------------------------------------------------------
2012 // Extract the launcher name from the environment.
2013 VG_(debugLog)(1, "main", "Getting stage1's name\n");
2014 VG_(name_of_launcher) = VG_(getenv)(VALGRIND_LAUNCHER);
2015 if (VG_(name_of_launcher) == NULL) {
2016 VG_(printf)("valgrind: You cannot run '%s' directly.\n", argv[0]);
2017 VG_(printf)("valgrind: You should use $prefix/bin/valgrind.\n");
2018 VG_(exit)(1);
2019 }
2020
2021 //--------------------------------------------------------------
fitzhardingeb50068f2004-02-24 23:42:55 +00002022 // Get the current process datasize rlimit, and set it to zero.
2023 // This prevents any internal uses of brk() from having any effect.
2024 // We remember the old value so we can restore it on exec, so that
2025 // child processes will have a reasonable brk value.
2026 VG_(getrlimit)(VKI_RLIMIT_DATA, &VG_(client_rlimit_data));
2027 zero.rlim_max = VG_(client_rlimit_data).rlim_max;
2028 VG_(setrlimit)(VKI_RLIMIT_DATA, &zero);
thughesc37184f2004-09-11 14:16:57 +00002029
2030 // Get the current process stack rlimit.
2031 VG_(getrlimit)(VKI_RLIMIT_STACK, &VG_(client_rlimit_stack));
2032
sewardje2d1e672005-11-12 23:10:48 +00002033 //--------------------------------------------------------------
2034 // Figure out what sort of CPU we're on, and whether it is
2035 // able to run V.
2036 VG_(debugLog)(1, "main", "Get hardware capabilities ...\n");
2037 { VexArch vex_arch;
2038 VexArchInfo vex_archinfo;
2039 Bool ok = VG_(machine_get_hwcaps)();
2040 if (!ok) {
2041 VG_(printf)("\n");
2042 VG_(printf)("valgrind: fatal error: unsupported CPU.\n");
2043 VG_(printf)(" Supported CPUs are:\n");
2044 VG_(printf)(" * x86 (practically any; Pentium-I or above), "
2045 "AMD Athlon or above)\n");
2046 VG_(printf)(" * AMD Athlon64/Opteron\n");
2047 VG_(printf)(" * PowerPC (most; ppc405 and above)\n");
2048 VG_(printf)("\n");
2049 VG_(exit)(1);
2050 }
2051 VG_(machine_get_VexArchInfo)( &vex_arch, &vex_archinfo );
2052 VG_(debugLog)(1, "main", "... arch = %s, subarch = %s\n",
2053 LibVEX_ppVexArch ( vex_arch ),
2054 LibVEX_ppVexSubArch( vex_archinfo.subarch ) );
2055 }
2056
sewardj45f4e7c2005-09-27 19:20:21 +00002057 //============================================================
2058 // Command line argument handling order:
2059 // * If --help/--help-debug are present, show usage message
2060 // (including the tool-specific usage)
2061 // * (If no --tool option given, default to Memcheck)
2062 // * Then, if client is missing, abort with error msg
2063 // * Then, if any cmdline args are bad, abort with error msg
2064 //============================================================
2065
2066 //--------------------------------------------------------------
2067 // Split up argv into: C args, V args, V extra args, and exename.
2068 // p: dynamic memory allocation
2069 //--------------------------------------------------------------
2070 VG_(debugLog)(1, "main", "Split up command line\n");
2071 VG_(split_up_argv)( argc, argv );
2072 if (0) {
2073 for (i = 0; i < VG_(args_for_valgrind).used; i++)
2074 VG_(printf)("varg %s\n", VG_(args_for_valgrind).strs[i]);
2075 VG_(printf)(" exe %s\n", VG_(args_the_exename));
2076 for (i = 0; i < VG_(args_for_client).used; i++)
2077 VG_(printf)("carg %s\n", VG_(args_for_client).strs[i]);
nethercote71980f02004-01-24 18:18:54 +00002078 }
2079
2080 //--------------------------------------------------------------
sewardj45f4e7c2005-09-27 19:20:21 +00002081 // Extract tool name and whether help has been requested.
2082 // Note we can't print the help message yet, even if requested,
2083 // because the tool has not been initialised.
2084 // p: split_up_argv [for VG_(args_for_valgrind)]
nethercote71980f02004-01-24 18:18:54 +00002085 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002086 VG_(debugLog)(1, "main", "Preprocess command line opts\n");
sewardj45f4e7c2005-09-27 19:20:21 +00002087 get_helprequest_and_toolname(&need_help, &toolname);
nethercote71980f02004-01-24 18:18:54 +00002088
sewardj45f4e7c2005-09-27 19:20:21 +00002089 // Set default vex control params
2090 LibVEX_default_VexControl(& VG_(clo_vex_control));
nethercote71980f02004-01-24 18:18:54 +00002091
2092 //--------------------------------------------------------------
2093 // Load client executable, finding in $PATH if necessary
sewardj45f4e7c2005-09-27 19:20:21 +00002094 // p: get_helprequest_and_toolname() [for 'exec', 'need_help']
nethercote71980f02004-01-24 18:18:54 +00002095 // p: layout_remaining_space [so there's space]
2096 //--------------------------------------------------------------
sewardj45f4e7c2005-09-27 19:20:21 +00002097 if (!need_help) {
2098 VG_(debugLog)(1, "main", "Loading client\n");
nethercote71980f02004-01-24 18:18:54 +00002099
sewardj45f4e7c2005-09-27 19:20:21 +00002100 if (VG_(args_the_exename) == NULL)
2101 missing_prog();
2102
2103 load_client(&info, &initial_client_IP);
2104 }
nethercote71980f02004-01-24 18:18:54 +00002105
2106 //--------------------------------------------------------------
2107 // Set up client's environment
sewardj45f4e7c2005-09-27 19:20:21 +00002108 // p: set-libdir [for VG_(libdir)]
2109 // p: get_helprequest_and_toolname [for toolname]
nethercote71980f02004-01-24 18:18:54 +00002110 //--------------------------------------------------------------
sewardj45f4e7c2005-09-27 19:20:21 +00002111 if (!need_help) {
2112 VG_(debugLog)(1, "main", "Setup client env\n");
2113 env = setup_client_env(envp, toolname);
2114 }
nethercote71980f02004-01-24 18:18:54 +00002115
2116 //--------------------------------------------------------------
nethercote5ee67ca2004-06-22 14:00:09 +00002117 // Setup client stack, eip, and VG_(client_arg[cv])
nethercote71980f02004-01-24 18:18:54 +00002118 // p: load_client() [for 'info']
2119 // p: fix_environment() [for 'env']
2120 //--------------------------------------------------------------
sewardj45f4e7c2005-09-27 19:20:21 +00002121 if (!need_help) {
2122 void* init_sp = argv - 1;
2123 SizeT m1 = 1024 * 1024;
2124 SizeT m8 = 8 * m1;
2125 VG_(debugLog)(1, "main", "Setup client stack\n");
2126 clstack_max_size = (SizeT)VG_(client_rlimit_stack).rlim_cur;
2127 if (clstack_max_size < m1) clstack_max_size = m1;
2128 if (clstack_max_size > m8) clstack_max_size = m8;
2129 clstack_max_size = VG_PGROUNDUP(clstack_max_size);
sewardjb5f6f512005-03-10 23:59:00 +00002130
sewardj45f4e7c2005-09-27 19:20:21 +00002131 initial_client_SP
2132 = setup_client_stack( init_sp, env,
2133 &info, &client_auxv,
2134 clstack_top, clstack_max_size );
2135
2136 VG_(free)(env);
2137
2138 VG_(debugLog)(2, "main",
2139 "Client info: "
sewardja48a4932005-09-29 11:09:56 +00002140 "initial_IP=%p initial_SP=%p brk_base=%p\n",
sewardj45f4e7c2005-09-27 19:20:21 +00002141 (void*)initial_client_IP,
2142 (void*)initial_client_SP,
2143 (void*)VG_(brk_base) );
nethercotec25c4492004-10-18 11:52:17 +00002144 }
nethercote71980f02004-01-24 18:18:54 +00002145
sewardj45f4e7c2005-09-27 19:20:21 +00002146 //--------------------------------------------------------------
2147 // Setup client data (brk) segment. Initially a 1-page segment
2148 // which abuts a shrinkable reservation.
2149 // p: load_client() [for 'info' and hence VG_(brk_base)]
2150 //--------------------------------------------------------------
2151 if (!need_help) {
2152 SizeT m1 = 1024 * 1024;
2153 SizeT m8 = 8 * m1;
2154 SizeT dseg_max_size = (SizeT)VG_(client_rlimit_data).rlim_cur;
2155 VG_(debugLog)(1, "main", "Setup client data (brk) segment\n");
2156 if (dseg_max_size < m1) dseg_max_size = m1;
2157 if (dseg_max_size > m8) dseg_max_size = m8;
2158 dseg_max_size = VG_PGROUNDUP(dseg_max_size);
2159
2160 setup_client_dataseg( dseg_max_size );
2161 }
nethercote71980f02004-01-24 18:18:54 +00002162
2163 //==============================================================
sewardj45f4e7c2005-09-27 19:20:21 +00002164 //
2165 // Finished loading/setting up the client address space.
2166 //
nethercote71980f02004-01-24 18:18:54 +00002167 //==============================================================
2168
2169 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002170 // setup file descriptors
2171 // p: n/a
2172 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002173 VG_(debugLog)(1, "main", "Setup file descriptors\n");
nethercote71980f02004-01-24 18:18:54 +00002174 setup_file_descriptors();
2175
2176 //--------------------------------------------------------------
sewardj45f4e7c2005-09-27 19:20:21 +00002177 // create the fake /proc/<pid>/cmdline file and then unlink it,
2178 // but hold onto the fd, so we can hand it out to the client
2179 // when it tries to open /proc/<pid>/cmdline for itself.
2180 // p: setup file descriptors
nethercotec314eba2004-07-15 12:59:41 +00002181 //--------------------------------------------------------------
sewardj45f4e7c2005-09-27 19:20:21 +00002182 if (!need_help) {
2183 HChar buf[50], buf2[50+64];
2184 HChar nul[1];
2185 Int fd, r;
2186 HChar* exename;
nethercotec314eba2004-07-15 12:59:41 +00002187
sewardj45f4e7c2005-09-27 19:20:21 +00002188 VG_(debugLog)(1, "main", "Create fake /proc/<pid>/cmdline\n");
2189
2190 VG_(sprintf)(buf, "proc_%d_cmdline", VG_(getpid)());
2191 fd = VG_(mkstemp)( buf, buf2 );
2192 if (fd == -1)
2193 config_error("Can't create client cmdline file in /tmp.");
2194
2195 nul[0] = 0;
2196 exename = VG_(args_the_exename) ? VG_(args_the_exename)
2197 : "unknown_exename";
2198
2199 VG_(write)(fd, VG_(args_the_exename),
2200 VG_(strlen)( VG_(args_the_exename) ));
2201 VG_(write)(fd, nul, 1);
2202
2203 for (i = 0; i < VG_(args_for_client).used; i++) {
2204 VG_(write)(fd, VG_(args_for_client).strs[i],
2205 VG_(strlen)( VG_(args_for_client).strs[i] ));
2206 VG_(write)(fd, nul, 1);
2207 }
2208
2209 /* Don't bother to seek the file back to the start; instead do
2210 it every time a copy of it is given out (by PRE(sys_open)).
2211 That is probably more robust across fork() etc. */
2212
2213 /* Now delete it, but hang on to the fd. */
2214 r = VG_(unlink)( buf2 );
2215 if (r)
2216 config_error("Can't delete client cmdline file in /tmp.");
2217
2218 VG_(cl_cmdline_fd) = fd;
2219 }
nethercotec314eba2004-07-15 12:59:41 +00002220
2221 //--------------------------------------------------------------
sewardj45f4e7c2005-09-27 19:20:21 +00002222 // Init tool part 1: pre_clo_init
nethercotec314eba2004-07-15 12:59:41 +00002223 // p: setup_client_stack() [for 'VG_(client_arg[cv]']
nethercotec314eba2004-07-15 12:59:41 +00002224 // p: setup_file_descriptors() [for 'VG_(fd_xxx_limit)']
nethercote71980f02004-01-24 18:18:54 +00002225 //--------------------------------------------------------------
njn64c83242005-06-21 01:54:38 +00002226 {
2227 Char* s;
2228 Bool ok;
sewardj45f4e7c2005-09-27 19:20:21 +00002229 VG_(debugLog)(1, "main", "Initialise the tool part 1 (pre_clo_init)\n");
2230 (VG_(tool_info).tl_pre_clo_init)();
2231 ok = VG_(sanity_check_needs)( &s );
njn64c83242005-06-21 01:54:38 +00002232 if (!ok) {
2233 VG_(tool_panic)(s);
2234 }
2235 }
nethercote71980f02004-01-24 18:18:54 +00002236
sewardj45f4e7c2005-09-27 19:20:21 +00002237 //--------------------------------------------------------------
nethercotef4928da2004-06-15 10:54:40 +00002238 // If --tool and --help/--help-debug was given, now give the core+tool
2239 // help message
sewardj45f4e7c2005-09-27 19:20:21 +00002240 // p: get_helprequest_and_toolname() [for 'need_help']
2241 // p: tl_pre_clo_init [for 'VG_(tdict).usage']
2242 //--------------------------------------------------------------
2243 VG_(debugLog)(1, "main", "Print help and quit, if requested\n");
nethercotef4928da2004-06-15 10:54:40 +00002244 if (need_help) {
sewardj45f4e7c2005-09-27 19:20:21 +00002245 usage_NORETURN(/*--help-debug?*/2 == need_help);
nethercotef4928da2004-06-15 10:54:40 +00002246 }
nethercotec314eba2004-07-15 12:59:41 +00002247
sewardj45f4e7c2005-09-27 19:20:21 +00002248 //--------------------------------------------------------------
2249 // Process command line options to Valgrind + tool
2250 // p: setup_client_stack() [for 'VG_(client_arg[cv]']
2251 // p: setup_file_descriptors() [for 'VG_(fd_xxx_limit)']
2252 //--------------------------------------------------------------
2253 VG_(debugLog)(1, "main", "Process Valgrind's command line options, "
sewardja48a4932005-09-29 11:09:56 +00002254 "setup logging\n");
sewardj45f4e7c2005-09-27 19:20:21 +00002255 logging_to_fd = process_cmd_line_options(client_auxv, toolname);
2256
2257 //--------------------------------------------------------------
sewardj592ae092005-11-08 19:01:44 +00002258 // Zeroise the millisecond counter by doing a first read of it.
2259 // p: none
2260 //--------------------------------------------------------------
2261 (void) VG_(read_millisecond_timer)();
2262
2263 //--------------------------------------------------------------
sewardj45f4e7c2005-09-27 19:20:21 +00002264 // Print the preamble
2265 // p: tl_pre_clo_init [for 'VG_(details).name' and friends]
2266 // p: process_cmd_line_options() [for VG_(clo_verbosity), VG_(clo_xml),
2267 // VG_(clo_log_file_qualifier),
2268 // logging_to_fd]
2269 //--------------------------------------------------------------
2270 VG_(debugLog)(1, "main", "Print the preamble...\n");
2271 print_preamble(logging_to_fd, toolname);
2272 VG_(debugLog)(1, "main", "...finished the preamble\n");
2273
2274 //--------------------------------------------------------------
2275 // Init tool part 2: post_clo_init
2276 // p: setup_client_stack() [for 'VG_(client_arg[cv]']
2277 // p: setup_file_descriptors() [for 'VG_(fd_xxx_limit)']
2278 // p: print_preamble() [so any warnings printed in post_clo_init
2279 // are shown after the preamble]
2280 //--------------------------------------------------------------
2281 VG_(debugLog)(1, "main", "Initialise the tool part 2 (post_clo_init)\n");
njn51d827b2005-05-09 01:02:08 +00002282 VG_TDICT_CALL(tool_post_clo_init);
nethercotef4928da2004-06-15 10:54:40 +00002283
2284 //--------------------------------------------------------------
sewardj45f4e7c2005-09-27 19:20:21 +00002285 // Initialise translation table and translation cache
2286 // p: aspacem [??]
2287 // p: tl_pre_clo_init [for 'VG_(details).avg_translation_sizeB']
nethercote71980f02004-01-24 18:18:54 +00002288 //--------------------------------------------------------------
sewardj45f4e7c2005-09-27 19:20:21 +00002289 VG_(debugLog)(1, "main", "Initialise TT/TC\n");
2290 VG_(init_tt_tc)();
sewardjb5f6f512005-03-10 23:59:00 +00002291
sewardj45f4e7c2005-09-27 19:20:21 +00002292 //--------------------------------------------------------------
2293 // Initialise the redirect table.
2294 // p: init_tt_tc [so it can call VG_(search_transtab) safely]
2295 // p: aspacem [so can change ownership of sysinfo pages]
2296 //--------------------------------------------------------------
2297 VG_(debugLog)(1, "main", "Initialise redirects\n");
2298 VG_(setup_code_redirect_table)();
nethercote71980f02004-01-24 18:18:54 +00002299
2300 //--------------------------------------------------------------
2301 // Allow GDB attach
2302 // p: process_cmd_line_options() [for VG_(clo_wait_for_gdb)]
2303 //--------------------------------------------------------------
2304 /* Hook to delay things long enough so we can get the pid and
2305 attach GDB in another shell. */
2306 if (VG_(clo_wait_for_gdb)) {
sewardj8211a572005-06-23 21:37:47 +00002307 Long q, iters;
sewardj1fbc1a52005-04-25 02:05:54 +00002308 VG_(debugLog)(1, "main", "Wait for GDB\n");
sewardj93ab8572005-02-06 14:10:40 +00002309 VG_(printf)("pid=%d, entering delay loop\n", VG_(getpid)());
2310 /* jrs 20050206: I don't understand why this works on x86. On
2311 amd64 the obvious analogues (jump *$rip or jump *$rcx) don't
2312 work. */
2313 /* do "jump *$eip" to skip this in gdb (x86) */
2314 //VG_(do_syscall0)(__NR_pause);
sewardj8211a572005-06-23 21:37:47 +00002315
2316# if defined(VGP_x86_linux)
2317 iters = 5;
2318# elif defined(VGP_amd64_linux)
2319 iters = 10;
2320# elif defined(VGP_ppc32_linux)
sewardjd714d2e2005-07-08 18:24:04 +00002321 iters = 5;
sewardj8211a572005-06-23 21:37:47 +00002322# else
2323# error "Unknown plat"
2324# endif
2325
2326 iters *= 1000*1000*1000;
2327 for (q = 0; q < iters; q++)
2328 ;
nethercote71980f02004-01-24 18:18:54 +00002329 }
2330
sewardjb5d320c2005-03-13 18:57:15 +00002331 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002332 // Search for file descriptors that are inherited from our parent
2333 // p: process_cmd_line_options [for VG_(clo_track_fds)]
2334 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002335 if (VG_(clo_track_fds)) {
2336 VG_(debugLog)(1, "main", "Init preopened fds\n");
nethercote71980f02004-01-24 18:18:54 +00002337 VG_(init_preopened_fds)();
sewardj1fbc1a52005-04-25 02:05:54 +00002338 }
nethercote71980f02004-01-24 18:18:54 +00002339
2340 //--------------------------------------------------------------
sewardj45f4e7c2005-09-27 19:20:21 +00002341 // Load debug info for the existing segments.
2342 // p: setup_code_redirect_table [so that redirs can be recorded]
2343 // p: mallocfree
2344 // p: probably: setup fds and process CLOs, so that logging works
2345 //--------------------------------------------------------------
2346 VG_(debugLog)(1, "main", "Load initial debug info\n");
2347 { Addr* seg_starts;
2348 Int n_seg_starts;
2349
2350 seg_starts = get_seg_starts( &n_seg_starts );
2351 vg_assert(seg_starts && n_seg_starts > 0);
2352
sewardjf72cced2005-11-08 00:45:47 +00002353 /* show them all to the debug info reader. allow_SkFileV has to
2354 be True here so that we read info from the valgrind executable
2355 itself. */
sewardj45f4e7c2005-09-27 19:20:21 +00002356 for (i = 0; i < n_seg_starts; i++)
sewardjf72cced2005-11-08 00:45:47 +00002357 VG_(di_notify_mmap)( seg_starts[i], True/*allow_SkFileV*/ );
sewardj45f4e7c2005-09-27 19:20:21 +00002358
2359 VG_(free)( seg_starts );
2360 }
2361
2362 //--------------------------------------------------------------
2363 // Tell aspacem of ownership change of the asm helpers, so that
2364 // m_translate allows them to be translated. However, only do this
2365 // after the initial debug info read, since making a hole in the
2366 // address range for the stage2 binary confuses the debug info reader.
2367 // p: aspacem
2368 //--------------------------------------------------------------
2369 { Bool change_ownership_v_c_OK;
2370 Addr co_start = VG_PGROUNDDN( (Addr)&VG_(trampoline_stuff_start) );
2371 Addr co_endPlus = VG_PGROUNDUP( (Addr)&VG_(trampoline_stuff_end) );
2372 VG_(debugLog)(1,"redir",
2373 "transfer ownership V -> C of 0x%llx .. 0x%llx\n",
2374 (ULong)co_start, (ULong)co_endPlus-1 );
2375
2376 change_ownership_v_c_OK
2377 = VG_(am_change_ownership_v_to_c)( co_start, co_endPlus - co_start );
2378 vg_assert(change_ownership_v_c_OK);
2379 }
2380
2381 //--------------------------------------------------------------
2382 // Tell the tool about the initial client memory permissions
2383 // p: aspacem
2384 // p: mallocfree
2385 // p: setup_client_stack
2386 // p: setup_client_dataseg
2387 //--------------------------------------------------------------
2388 VG_(debugLog)(1, "main", "Tell tool about initial permissions\n");
2389 { Addr* seg_starts;
2390 Int n_seg_starts;
2391 NSegment* seg;
2392
2393 seg_starts = get_seg_starts( &n_seg_starts );
2394 vg_assert(seg_starts && n_seg_starts > 0);
2395
2396 /* show interesting ones to the tool */
2397 for (i = 0; i < n_seg_starts; i++) {
2398 seg = VG_(am_find_nsegment)( seg_starts[i] );
2399 vg_assert(seg);
2400 if (seg->kind == SkFileC || seg->kind == SkAnonC) {
2401 VG_(debugLog)(2, "main",
2402 "tell tool about %010lx-%010lx %c%c%c\n",
2403 seg->start, seg->end,
2404 seg->hasR ? 'r' : '-',
2405 seg->hasW ? 'w' : '-',
2406 seg->hasX ? 'x' : '-' );
2407 VG_TRACK( new_mem_startup, seg->start, seg->end+1-seg->start,
2408 seg->hasR, seg->hasW, seg->hasX );
2409 }
2410 }
2411
2412 VG_(free)( seg_starts );
2413
2414 /* Also do the initial stack permissions. */
2415 seg = VG_(am_find_nsegment)( initial_client_SP );
2416 vg_assert(seg);
2417 vg_assert(seg->kind == SkAnonC);
2418 vg_assert(initial_client_SP >= seg->start);
2419 vg_assert(initial_client_SP <= seg->end);
2420
2421 /* Stuff below the initial SP is unaddressable. */
2422 /* NB: shouldn't this take into account the VG_STACK_REDZONE_SZB
2423 bytes below SP? */
2424 VG_TRACK( die_mem_stack, seg->start, initial_client_SP - seg->start );
2425 VG_(debugLog)(2, "main", "mark stack inaccessible %010lx-%010lx\n",
2426 seg->start, initial_client_SP-1 );
2427
2428 /* Also the assembly helpers. */
2429 VG_TRACK( new_mem_startup,
2430 (Addr)&VG_(trampoline_stuff_start),
tom151a6392005-11-11 12:30:36 +00002431 (Addr)&VG_(trampoline_stuff_end) - (Addr)&VG_(trampoline_stuff_start),
sewardj45f4e7c2005-09-27 19:20:21 +00002432 False, /* readable? */
2433 False, /* writable? */
2434 True /* executable? */ );
2435 }
2436
2437 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002438 // Initialise the scheduler
nethercote71980f02004-01-24 18:18:54 +00002439 // p: setup_file_descriptors() [else VG_(safe_fd)() breaks]
sewardj45f4e7c2005-09-27 19:20:21 +00002440 // p: setup_client_stack
nethercote71980f02004-01-24 18:18:54 +00002441 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002442 VG_(debugLog)(1, "main", "Initialise scheduler\n");
sewardj45f4e7c2005-09-27 19:20:21 +00002443 { NSegment* seg = VG_(am_find_nsegment)( initial_client_SP );
2444 vg_assert(seg);
2445 vg_assert(seg->kind == SkAnonC);
2446 vg_assert(initial_client_SP >= seg->start);
2447 vg_assert(initial_client_SP <= seg->end);
2448 VG_(scheduler_init)( seg->end, clstack_max_size );
2449 }
nethercote71980f02004-01-24 18:18:54 +00002450
2451 //--------------------------------------------------------------
sewardjb5f6f512005-03-10 23:59:00 +00002452 // Initialise the pthread model
2453 // p: ?
sewardj2a99cf62004-11-24 10:44:19 +00002454 // load_client() [for 'client_eip']
2455 // setup_client_stack() [for 'sp_at_startup']
2456 // setup_scheduler() [for the rest of state 1 stuff]
2457 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002458 VG_(debugLog)(1, "main", "Initialise thread 1's state\n");
sewardj45f4e7c2005-09-27 19:20:21 +00002459 init_thread1state( initial_client_IP, initial_client_SP,
2460 &VG_(threads)[1].arch);
njnea4b28c2004-11-30 16:04:58 +00002461
sewardj2a99cf62004-11-24 10:44:19 +00002462 //--------------------------------------------------------------
sewardj39b88fb2005-03-12 15:16:07 +00002463 // Initialise the pthread model
2464 // p: ?
nethercote71980f02004-01-24 18:18:54 +00002465 //--------------------------------------------------------------
sewardjb5f6f512005-03-10 23:59:00 +00002466 //if (VG_(clo_model_pthreads))
2467 // VG_(pthread_init)();
nethercote71980f02004-01-24 18:18:54 +00002468
2469 //--------------------------------------------------------------
2470 // Initialise the signal handling subsystem
sewardjb5f6f512005-03-10 23:59:00 +00002471 // p: n/a
nethercote71980f02004-01-24 18:18:54 +00002472 //--------------------------------------------------------------
2473 // Nb: temporarily parks the saved blocking-mask in saved_sigmask.
sewardj1fbc1a52005-04-25 02:05:54 +00002474 VG_(debugLog)(1, "main", "Initialise signal management\n");
nethercote71980f02004-01-24 18:18:54 +00002475 VG_(sigstartup_actions)();
2476
2477 //--------------------------------------------------------------
2478 // Perhaps we're profiling Valgrind?
2479 // p: process_cmd_line_options() [for VG_(clo_profile)]
2480 // p: others?
2481 //
2482 // XXX: this seems to be broken? It always says the tool wasn't built
2483 // for profiling; vg_profile.c's functions don't seem to be overriding
2484 // vg_dummy_profile.c's?
2485 //
2486 // XXX: want this as early as possible. Looking for --profile
sewardj45f4e7c2005-09-27 19:20:21 +00002487 // in get_helprequest_and_toolname() could get it earlier.
nethercote71980f02004-01-24 18:18:54 +00002488 //--------------------------------------------------------------
2489 if (VG_(clo_profile))
njn31066fd2005-03-26 00:42:02 +00002490 VG_(init_profiling)();
nethercote71980f02004-01-24 18:18:54 +00002491
2492 VGP_PUSHCC(VgpStartup);
2493
2494 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002495 // Read suppression file
2496 // p: process_cmd_line_options() [for VG_(clo_suppressions)]
2497 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002498 if (VG_(needs).core_errors || VG_(needs).tool_errors) {
2499 VG_(debugLog)(1, "main", "Load suppressions\n");
nethercote71980f02004-01-24 18:18:54 +00002500 VG_(load_suppressions)();
sewardj1fbc1a52005-04-25 02:05:54 +00002501 }
nethercote71980f02004-01-24 18:18:54 +00002502
2503 //--------------------------------------------------------------
rjwalsh0140af52005-06-04 20:42:33 +00002504 // register client stack
2505 //--------------------------------------------------------------
njn945ed2e2005-06-24 03:28:30 +00002506 VG_(clstk_id) = VG_(register_stack)(VG_(clstk_base), VG_(clstk_end));
rjwalsh0140af52005-06-04 20:42:33 +00002507
2508 //--------------------------------------------------------------
sewardj45f4e7c2005-09-27 19:20:21 +00002509 // Show the address space state so far
2510 //--------------------------------------------------------------
2511 VG_(debugLog)(1, "main", "\n");
2512 VG_(debugLog)(1, "main", "\n");
2513 VG_(am_show_nsegments)(1,"Memory layout at client startup");
2514 VG_(debugLog)(1, "main", "\n");
2515 VG_(debugLog)(1, "main", "\n");
2516
2517 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002518 // Run!
2519 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002520 VGP_POPCC(VgpStartup);
nethercote71980f02004-01-24 18:18:54 +00002521
sewardj71bc3cb2005-05-19 00:25:45 +00002522 if (VG_(clo_xml)) {
sewardj68cde6f2005-07-19 12:17:51 +00002523 HChar buf[50];
sewardj592ae092005-11-08 19:01:44 +00002524 VG_(elapsed_wallclock_time)(buf);
sewardj753673f2005-08-09 22:03:08 +00002525 VG_(message)(Vg_UserMsg, "<status>\n"
2526 " <state>RUNNING</state>\n"
2527 " <time>%t</time>\n"
2528 "</status>",
2529 buf);
sewardj71bc3cb2005-05-19 00:25:45 +00002530 VG_(message)(Vg_UserMsg, "");
2531 }
2532
sewardj1fbc1a52005-04-25 02:05:54 +00002533 VG_(debugLog)(1, "main", "Running thread 1\n");
sewardj1ae3f3a2005-09-28 10:47:38 +00002534
sewardj1d887112005-05-30 21:44:08 +00002535 /* As a result of the following call, the last thread standing
sewardj1ae3f3a2005-09-28 10:47:38 +00002536 eventually winds up running shutdown_actions_NORETURN
2537 just below. Unfortunately, simply exporting said function
2538 causes m_main to be part of a module cycle, which is pretty
2539 nonsensical. So instead of doing that, the address of said
2540 function is stored in a global variable 'owned' by m_syswrap,
2541 and it uses that function pointer to get back here when it needs
2542 to. */
2543
2544 /* Set continuation address. */
2545 VG_(address_of_m_main_shutdown_actions_NORETURN)
2546 = & shutdown_actions_NORETURN;
2547
2548 /* Run the first thread, eventually ending up at the continuation
2549 address. */
njnaf839f52005-06-23 03:27:57 +00002550 VG_(main_thread_wrapper_NORETURN)(1);
nethercote71980f02004-01-24 18:18:54 +00002551
sewardj1d887112005-05-30 21:44:08 +00002552 /*NOTREACHED*/
2553 vg_assert(0);
sewardjb5f6f512005-03-10 23:59:00 +00002554}
2555
sewardj1ae3f3a2005-09-28 10:47:38 +00002556/* Do everything which needs doing when the last thread exits. */
sewardjb5f6f512005-03-10 23:59:00 +00002557
sewardj1ae3f3a2005-09-28 10:47:38 +00002558static
2559void shutdown_actions_NORETURN( ThreadId tid,
2560 VgSchedReturnCode tids_schedretcode )
sewardjb5f6f512005-03-10 23:59:00 +00002561{
sewardj1d887112005-05-30 21:44:08 +00002562 VG_(debugLog)(1, "main", "entering VG_(shutdown_actions_NORETURN)\n");
2563
2564 vg_assert( VG_(count_living_threads)() == 1 );
sewardjb5f6f512005-03-10 23:59:00 +00002565 vg_assert(VG_(is_running_thread)(tid));
2566
2567 // Wait for all other threads to exit.
njn7b85dd52005-06-12 17:26:29 +00002568 VG_(reap_threads)(tid);
sewardjb5f6f512005-03-10 23:59:00 +00002569
2570 VG_(clo_model_pthreads) = False;
2571
2572 // Clean the client up before the final report
njn9cb54ac2005-06-12 04:19:17 +00002573 final_tidyup(tid);
sewardjb5f6f512005-03-10 23:59:00 +00002574
2575 // OK, done
2576 VG_(exit_thread)(tid);
2577
2578 /* should be no threads left */
2579 vg_assert(VG_(count_living_threads)() == 0);
2580
2581 VG_(threads)[tid].status = VgTs_Empty;
nethercote71980f02004-01-24 18:18:54 +00002582 //--------------------------------------------------------------
2583 // Finalisation: cleanup, messages, etc. Order no so important, only
2584 // affects what order the messages come.
2585 //--------------------------------------------------------------
2586 if (VG_(clo_verbosity) > 0)
2587 VG_(message)(Vg_UserMsg, "");
2588
sewardj71bc3cb2005-05-19 00:25:45 +00002589 if (VG_(clo_xml)) {
sewardj68cde6f2005-07-19 12:17:51 +00002590 HChar buf[50];
sewardj9f297ca2005-05-20 02:29:52 +00002591 if (VG_(needs).core_errors || VG_(needs).tool_errors) {
2592 VG_(show_error_counts_as_XML)();
2593 VG_(message)(Vg_UserMsg, "");
2594 }
sewardj592ae092005-11-08 19:01:44 +00002595 VG_(elapsed_wallclock_time)(buf);
sewardj753673f2005-08-09 22:03:08 +00002596 VG_(message)(Vg_UserMsg, "<status>\n"
2597 " <state>FINISHED</state>\n"
2598 " <time>%t</time>\n"
2599 "</status>",
2600 buf);
sewardj71bc3cb2005-05-19 00:25:45 +00002601 VG_(message)(Vg_UserMsg, "");
2602 }
2603
nethercote71980f02004-01-24 18:18:54 +00002604 /* Print out file descriptor summary and stats. */
2605 if (VG_(clo_track_fds))
nethercote3a42fb82004-08-03 18:08:50 +00002606 VG_(show_open_fds)();
nethercote71980f02004-01-24 18:18:54 +00002607
njn95ec8702004-11-22 16:46:13 +00002608 if (VG_(needs).core_errors || VG_(needs).tool_errors)
nethercote71980f02004-01-24 18:18:54 +00002609 VG_(show_all_errors)();
2610
njn51d827b2005-05-09 01:02:08 +00002611 VG_TDICT_CALL(tool_fini, 0/*exitcode*/);
nethercote71980f02004-01-24 18:18:54 +00002612
sewardj71bc3cb2005-05-19 00:25:45 +00002613 if (VG_(clo_xml)) {
2614 VG_(message)(Vg_UserMsg, "");
2615 VG_(message)(Vg_UserMsg, "</valgrindoutput>");
2616 VG_(message)(Vg_UserMsg, "");
2617 }
2618
nethercote885dd912004-08-03 23:14:00 +00002619 VG_(sanity_check_general)( True /*include expensive checks*/ );
nethercote71980f02004-01-24 18:18:54 +00002620
2621 if (VG_(clo_verbosity) > 1)
nethercote3a42fb82004-08-03 18:08:50 +00002622 print_all_stats();
nethercote71980f02004-01-24 18:18:54 +00002623
nethercote71980f02004-01-24 18:18:54 +00002624 if (VG_(clo_profile))
njn31066fd2005-03-26 00:42:02 +00002625 VG_(done_profiling)();
njn2025cf92005-06-26 20:44:48 +00002626
2627 if (VG_(clo_profile_flags) > 0) {
2628 #define N_MAX 100
2629 BBProfEntry tops[N_MAX];
2630 ULong score_total = VG_(get_BB_profile) (tops, N_MAX);
2631 show_BB_profile(tops, N_MAX, score_total);
2632 }
sewardjfa8ec112005-01-19 11:55:34 +00002633
sewardj8b635a42004-11-22 19:01:47 +00002634 /* Print Vex storage stats */
sewardjbf426512005-01-17 18:35:30 +00002635 if (0)
2636 LibVEX_ShowAllocStats();
sewardj1d887112005-05-30 21:44:08 +00002637
njn8aa35852005-06-10 22:59:56 +00002638 /* Ok, finally exit in the os-specific way, according to the scheduler's
2639 return code. In short, if the (last) thread exited by calling
2640 sys_exit, do likewise; if the (last) thread stopped due to a fatal
2641 signal, terminate the entire system with that same fatal signal. */
2642 VG_(debugLog)(1, "core_os",
njn7b85dd52005-06-12 17:26:29 +00002643 "VG_(terminate_NORETURN)(tid=%lld)\n", (ULong)tid);
njn8aa35852005-06-10 22:59:56 +00002644
2645 vg_assert(VG_(count_living_threads)() == 0);
2646
2647 switch (tids_schedretcode) {
2648 case VgSrc_ExitSyscall: /* the normal way out */
2649 VG_(exit)( VG_(threads)[tid].os_state.exitcode );
2650 /* NOT ALIVE HERE! */
2651 VG_(core_panic)("entered the afterlife in main() -- ExitSyscall");
2652 break; /* what the hell :) */
2653
2654 case VgSrc_FatalSig:
2655 /* We were killed by a fatal signal, so replicate the effect */
2656 vg_assert(VG_(threads)[tid].os_state.fatalsig != 0);
2657 VG_(kill_self)(VG_(threads)[tid].os_state.fatalsig);
2658 VG_(core_panic)("main(): signal was supposed to be fatal");
2659 break;
2660
2661 default:
2662 VG_(core_panic)("main(): unexpected scheduler return code");
2663 }
njne96be672005-05-08 19:08:54 +00002664}
sewardj8b635a42004-11-22 19:01:47 +00002665
sewardj1ae3f3a2005-09-28 10:47:38 +00002666/* -------------------- */
2667
2668/* Final clean-up before terminating the process.
2669 Clean up the client by calling __libc_freeres() (if requested)
2670 This is Linux-specific?
2671*/
2672static void final_tidyup(ThreadId tid)
2673{
2674 Addr __libc_freeres_wrapper;
2675
2676 vg_assert(VG_(is_running_thread)(tid));
2677
2678 if ( !VG_(needs).libc_freeres ||
2679 !VG_(clo_run_libc_freeres) ||
2680 0 == (__libc_freeres_wrapper = VG_(get_libc_freeres_wrapper)()) )
2681 return; /* can't/won't do it */
2682
2683 if (VG_(clo_verbosity) > 2 ||
2684 VG_(clo_trace_syscalls) ||
2685 VG_(clo_trace_sched))
2686 VG_(message)(Vg_DebugMsg,
2687 "Caught __NR_exit; running __libc_freeres()");
2688
2689 /* point thread context to point to libc_freeres_wrapper */
2690 VG_(set_IP)(tid, __libc_freeres_wrapper);
2691 // XXX should we use a special stack?
2692
2693 /* Block all blockable signals by copying the real block state into
2694 the thread's block state*/
2695 VG_(sigprocmask)(VKI_SIG_BLOCK, NULL, &VG_(threads)[tid].sig_mask);
2696 VG_(threads)[tid].tmp_sig_mask = VG_(threads)[tid].sig_mask;
2697
2698 /* and restore handlers to default */
2699 VG_(set_default_handler)(VKI_SIGSEGV);
2700 VG_(set_default_handler)(VKI_SIGBUS);
2701 VG_(set_default_handler)(VKI_SIGILL);
2702 VG_(set_default_handler)(VKI_SIGFPE);
2703
2704 // We were exiting, so assert that...
2705 vg_assert(VG_(is_exiting)(tid));
2706 // ...but now we're not again
2707 VG_(threads)[tid].exitreason = VgSrc_None;
2708
2709 // run until client thread exits - ideally with LIBC_FREERES_DONE,
2710 // but exit/exitgroup/signal will do
2711 VG_(scheduler)(tid);
2712
2713 vg_assert(VG_(is_exiting)(tid));
2714}
2715
sewardj45f4e7c2005-09-27 19:20:21 +00002716
2717/*====================================================================*/
2718/*=== Getting to main() alive ===*/
2719/*====================================================================*/
2720
2721/* If linking of the final executables is done with glibc present,
2722 then Valgrind starts at main() above as usual, and all of the
2723 following code is irrelevant.
2724
2725 However, this is not the intended mode of use. The plan is to
2726 avoid linking against glibc, by giving gcc the flags
2727 -nodefaultlibs -lgcc -nostartfiles at startup.
2728
2729 From this derive two requirements:
2730
2731 1. gcc may emit calls to memcpy and memset to deal with structure
2732 assignments etc. Since we have chosen to ignore all the
2733 "normal" supporting libraries, we have to provide our own
2734 implementations of them. No problem.
2735
2736 2. We have to provide a symbol "_start", to which the kernel
2737 hands control at startup. Hence the code below.
2738*/
2739
2740/* ---------------- Requirement 1 ---------------- */
2741
2742void* memcpy(void *dest, const void *src, size_t n);
2743void* memcpy(void *dest, const void *src, size_t n) {
2744 return VG_(memcpy)(dest,src,n);
2745}
2746void* memset(void *s, int c, size_t n);
2747void* memset(void *s, int c, size_t n) {
2748 return VG_(memset)(s,c,n);
2749}
2750
2751/* ---------------- Requirement 2 ---------------- */
2752
2753/* Glibc's sysdeps/i386/elf/start.S has the following gem of a
2754 comment, which explains how the stack looks right at process start
2755 (when _start is jumped to). Hence _start passes %esp to
2756 _start_in_C, which extracts argc/argv/envp and starts up
2757 correctly. */
2758
2759/* This is the canonical entry point, usually the first thing in the text
2760 segment. The SVR4/i386 ABI (pages 3-31, 3-32) says that when the entry
2761 point runs, most registers' values are unspecified, except for:
2762
2763 %edx Contains a function pointer to be registered with `atexit'.
2764 This is how the dynamic linker arranges to have DT_FINI
2765 functions called for shared libraries that have been loaded
2766 before this code runs.
2767
2768 %esp The stack contains the arguments and environment:
2769 0(%esp) argc
2770 4(%esp) argv[0]
2771 ...
2772 (4*argc)(%esp) NULL
2773 (4*(argc+1))(%esp) envp[0]
2774 ...
2775 NULL
2776*/
2777
2778/* The kernel hands control to _start, which extracts the initial
sewardja48a4932005-09-29 11:09:56 +00002779 stack pointer and calls onwards to _start_in_C. This also switches
2780 the new stack. */
sewardj45f4e7c2005-09-27 19:20:21 +00002781#if defined(VGP_x86_linux)
2782asm("\n"
2783 "\t.globl _start\n"
2784 "\t.type _start,@function\n"
2785 "_start:\n"
2786 /* set up the new stack in %eax */
sewardjfdf91b42005-09-28 00:53:09 +00002787 "\tmovl $vgPlain_interim_stack, %eax\n"
sewardj45f4e7c2005-09-27 19:20:21 +00002788 "\taddl $"VG_STRINGIFY(VG_STACK_GUARD_SZB)", %eax\n"
2789 "\taddl $"VG_STRINGIFY(VG_STACK_ACTIVE_SZB)", %eax\n"
2790 "\tsubl $16, %eax\n"
2791 "\tandl $~15, %eax\n"
2792 /* install it, and collect the original one */
2793 "\txchgl %eax, %esp\n"
2794 /* call _start_in_C, passing it the startup %esp */
2795 "\tpushl %eax\n"
2796 "\tcall _start_in_C\n"
2797 "\thlt\n"
2798);
2799#elif defined(VGP_amd64_linux)
2800asm("\n"
2801 "\t.globl _start\n"
2802 "\t.type _start,@function\n"
2803 "_start:\n"
2804 /* set up the new stack in %rdi */
sewardjfdf91b42005-09-28 00:53:09 +00002805 "\tmovq $vgPlain_interim_stack, %rdi\n"
sewardj45f4e7c2005-09-27 19:20:21 +00002806 "\taddq $"VG_STRINGIFY(VG_STACK_GUARD_SZB)", %rdi\n"
2807 "\taddq $"VG_STRINGIFY(VG_STACK_ACTIVE_SZB)", %rdi\n"
2808 "\tandq $~15, %rdi\n"
2809 /* install it, and collect the original one */
2810 "\txchgq %rdi, %rsp\n"
2811 /* call _start_in_C, passing it the startup %rsp */
2812 "\tcall _start_in_C\n"
2813 "\thlt\n"
2814);
sewardja48a4932005-09-29 11:09:56 +00002815#elif defined(VGP_ppc32_linux)
2816asm("\n"
2817 "\t.globl _start\n"
2818 "\t.type _start,@function\n"
2819 "_start:\n"
2820 /* set up the new stack in r16 */
2821 "\tlis 16,vgPlain_interim_stack@ha\n"
2822 "\tla 16,vgPlain_interim_stack@l(16)\n"
2823 "\tlis 17,("VG_STRINGIFY(VG_STACK_GUARD_SZB)" >> 16)\n"
2824 "\tori 17,17,("VG_STRINGIFY(VG_STACK_GUARD_SZB)" & 0xFFFF)\n"
2825 "\tlis 18,("VG_STRINGIFY(VG_STACK_ACTIVE_SZB)" >> 16)\n"
2826 "\tori 18,18,("VG_STRINGIFY(VG_STACK_ACTIVE_SZB)" & 0xFFFF)\n"
2827 "\tadd 16,17,16\n"
2828 "\tadd 16,18,16\n"
2829 "\trlwinm 16,16,0,0,27\n"
2830 /* now r16 = &vgPlain_interim_stack + VG_STACK_GUARD_SZB +
2831 VG_STACK_ACTIVE_SZB rounded down to the nearest 16-byte
2832 boundary. And r1 is the original SP. Set the SP to r16 and
2833 call _start_in_C, passing it the initial SP. */
2834 "\tmr 3,1\n"
2835 "\tmr 1,16\n"
2836 "\tbl _start_in_C\n"
2837 "\ttrap\n"
2838);
sewardj45f4e7c2005-09-27 19:20:21 +00002839#else
2840#error "_start: needs implementation on this platform"
2841#endif
2842
2843/* Avoid compiler warnings: this fn _is_ used, but labelling it
2844 'static' causes gcc to complain it isn't. */
2845void _start_in_C ( UWord* pArgc );
2846void _start_in_C ( UWord* pArgc )
2847{
2848 Int r;
2849 Word argc = pArgc[0];
2850 HChar** argv = (HChar**)&pArgc[1];
2851 HChar** envp = (HChar**)&pArgc[1+argc+1];
sewardjfdf91b42005-09-28 00:53:09 +00002852 sp_at_startup = (Addr)pArgc;
sewardj45f4e7c2005-09-27 19:20:21 +00002853 r = main( (Int)argc, argv, envp );
2854 VG_(exit)(r);
2855}
2856
sewardjde4a1d02002-03-22 01:27:54 +00002857/*--------------------------------------------------------------------*/
njn04e16982005-05-31 00:23:43 +00002858/*--- end ---*/
sewardjde4a1d02002-03-22 01:27:54 +00002859/*--------------------------------------------------------------------*/