blob: 71bd0e2e24de62eef5d701ccd9d3a03afd787b6a [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
njn7c555a92005-11-16 17:16:10 +0000660 /* We make the data segment (heap) executable because LinuxThreads on
njn0ddabca2005-11-16 23:54:46 +0000661 ppc32 creates trampolines in this area. Also, on x86/Linux the data
662 segment is RWX natively, at least according to /proc/self/maps.
663 Also, having a non-executable data seg would kill any program which
664 tried to create code in the data seg and then run it. */
sewardj45f4e7c2005-09-27 19:20:21 +0000665 sres = VG_(am_mmap_anon_fixed_client)(
666 anon_start,
667 anon_size,
sewardj33ca9e82005-11-16 17:12:38 +0000668 VKI_PROT_READ|VKI_PROT_WRITE|VKI_PROT_EXEC
sewardj45f4e7c2005-09-27 19:20:21 +0000669 );
670 vg_assert(!sres.isError);
671 vg_assert(sres.val == anon_start);
672}
673
674
nethercote71980f02004-01-24 18:18:54 +0000675/*====================================================================*/
676/*=== Find executable ===*/
677/*====================================================================*/
678
sewardjfdf91b42005-09-28 00:53:09 +0000679/* Scan a colon-separated list, and call a function on each element.
680 The string must be mutable, because we insert a temporary '\0', but
681 the string will end up unmodified. (*func) should return True if it
682 doesn't need to see any more.
683
684 This routine will return True if (*func) returns True and False if
685 it reaches the end of the list without that happening.
686*/
687static Bool scan_colsep(char *colsep, Bool (*func)(const char *))
688{
689 char *cp, *entry;
690 int end;
691
692 if (colsep == NULL ||
693 *colsep == '\0')
694 return False;
695
696 entry = cp = colsep;
697
698 do {
699 end = (*cp == '\0');
700
701 if (*cp == ':' || *cp == '\0') {
702 char save = *cp;
703
704 *cp = '\0';
705 if ((*func)(entry)) {
706 *cp = save;
707 return True;
708 }
709 *cp = save;
710 entry = cp+1;
711 }
712 cp++;
713 } while(!end);
714
715 return False;
716}
717
sewardj45f4e7c2005-09-27 19:20:21 +0000718/* Need a static copy because can't use dynamic mem allocation yet */
njn73750612005-10-14 03:11:30 +0000719static HChar executable_name_in [VKI_PATH_MAX];
720static HChar executable_name_out[VKI_PATH_MAX];
thughes4ad52d02004-06-27 17:37:21 +0000721
sewardj45f4e7c2005-09-27 19:20:21 +0000722static Bool match_executable(const char *entry)
723{
njn73750612005-10-14 03:11:30 +0000724 HChar buf[VG_(strlen)(entry) + VG_(strlen)(executable_name_in) + 3];
thughes4ad52d02004-06-27 17:37:21 +0000725
njn73750612005-10-14 03:11:30 +0000726 /* empty PATH element means '.' */
thughes4ad52d02004-06-27 17:37:21 +0000727 if (*entry == '\0')
728 entry = ".";
729
njn73750612005-10-14 03:11:30 +0000730 VG_(snprintf)(buf, sizeof(buf), "%s/%s", entry, executable_name_in);
731
732 // Don't match directories
733 if (VG_(is_dir)(buf))
734 return False;
735
736 // If we match an executable, we choose that immediately. If we find a
737 // matching non-executable we remember it but keep looking for an
738 // matching executable later in the path.
sewardj45f4e7c2005-09-27 19:20:21 +0000739 if (VG_(access)(buf, True/*r*/, False/*w*/, True/*x*/) == 0) {
njn73750612005-10-14 03:11:30 +0000740 VG_(strncpy)( executable_name_out, buf, VKI_PATH_MAX-1 );
741 executable_name_out[VKI_PATH_MAX-1] = 0;
742 return True; // Stop looking
743 } else if (VG_(access)(buf, True/*r*/, False/*w*/, False/*x*/) == 0
744 && VG_STREQ(executable_name_out, ""))
745 {
746 VG_(strncpy)( executable_name_out, buf, VKI_PATH_MAX-1 );
747 executable_name_out[VKI_PATH_MAX-1] = 0;
748 return False; // Keep looking
749 } else {
750 return False; // Keep looking
thughes4ad52d02004-06-27 17:37:21 +0000751 }
thughes4ad52d02004-06-27 17:37:21 +0000752}
753
njn73750612005-10-14 03:11:30 +0000754// Returns NULL if it wasn't found.
sewardj45f4e7c2005-09-27 19:20:21 +0000755static HChar* find_executable ( HChar* exec )
nethercote71980f02004-01-24 18:18:54 +0000756{
757 vg_assert(NULL != exec);
njn73750612005-10-14 03:11:30 +0000758 if (VG_(strchr)(exec, '/')) {
759 // Has a '/' - use the name as is
760 VG_(strncpy)( executable_name_out, exec, VKI_PATH_MAX-1 );
761 } else {
762 // No '/' - we need to search the path
sewardj03d8aa82005-10-14 11:25:49 +0000763 HChar* path;
njn73750612005-10-14 03:11:30 +0000764 VG_(strncpy)( executable_name_in, exec, VKI_PATH_MAX-1 );
765 VG_(memset) ( executable_name_out, 0, VKI_PATH_MAX );
sewardj03d8aa82005-10-14 11:25:49 +0000766 path = VG_(getenv)("PATH");
thughes4ad52d02004-06-27 17:37:21 +0000767 scan_colsep(path, match_executable);
nethercote71980f02004-01-24 18:18:54 +0000768 }
njn73750612005-10-14 03:11:30 +0000769 return VG_STREQ(executable_name_out, "") ? NULL : executable_name_out;
nethercote71980f02004-01-24 18:18:54 +0000770}
771
772
773/*====================================================================*/
nethercotef4928da2004-06-15 10:54:40 +0000774/*=== Command line errors ===*/
775/*====================================================================*/
776
njnbe9b47b2005-05-15 16:22:58 +0000777static void revert_to_stderr ( void )
nethercotef4928da2004-06-15 10:54:40 +0000778{
njnbe9b47b2005-05-15 16:22:58 +0000779 vg_assert( !VG_(logging_to_socket) );
nethercotef8548672004-06-21 12:42:35 +0000780 VG_(clo_log_fd) = 2; /* stderr */
nethercotef4928da2004-06-15 10:54:40 +0000781}
782
783void VG_(bad_option) ( Char* opt )
784{
njnbe9b47b2005-05-15 16:22:58 +0000785 revert_to_stderr();
njn02bc4b82005-05-15 17:28:26 +0000786 VG_(printf)("valgrind: Bad option '%s'; aborting.\n", opt);
nethercotef4928da2004-06-15 10:54:40 +0000787 VG_(printf)("valgrind: Use --help for more information.\n");
788 VG_(exit)(1);
789}
790
nethercotef4928da2004-06-15 10:54:40 +0000791static void missing_prog ( void )
792{
njnbe9b47b2005-05-15 16:22:58 +0000793 revert_to_stderr();
nethercotef4928da2004-06-15 10:54:40 +0000794 VG_(printf)("valgrind: no program specified\n");
795 VG_(printf)("valgrind: Use --help for more information.\n");
796 VG_(exit)(1);
797}
798
799static void config_error ( Char* msg )
800{
njnbe9b47b2005-05-15 16:22:58 +0000801 revert_to_stderr();
nethercotef4928da2004-06-15 10:54:40 +0000802 VG_(printf)("valgrind: Startup or configuration error:\n %s\n", msg);
803 VG_(printf)("valgrind: Unable to start up properly. Giving up.\n");
804 VG_(exit)(1);
805}
806
807
nethercote71980f02004-01-24 18:18:54 +0000808/*====================================================================*/
809/*=== Loading the client ===*/
810/*====================================================================*/
811
sewardj45f4e7c2005-09-27 19:20:21 +0000812/* Load the client whose name is VG_(argv_the_exename). */
nethercote71980f02004-01-24 18:18:54 +0000813
sewardj45f4e7c2005-09-27 19:20:21 +0000814static void load_client ( /*OUT*/struct exeinfo* info,
815 /*OUT*/Addr* client_eip)
816{
njn73750612005-10-14 03:11:30 +0000817 HChar* exe_name;
sewardj45f4e7c2005-09-27 19:20:21 +0000818 Int ret;
819 SysRes res;
820
821 vg_assert( VG_(args_the_exename) != NULL);
njn73750612005-10-14 03:11:30 +0000822 exe_name = find_executable( VG_(args_the_exename) );
823
824 if (!exe_name) {
825 VG_(printf)("valgrind: %s: command not found\n", VG_(args_the_exename));
826 VG_(exit)(127); // 127 is Posix NOTFOUND
827 }
sewardj45f4e7c2005-09-27 19:20:21 +0000828
829 VG_(memset)(info, 0, sizeof(*info));
nethercote71980f02004-01-24 18:18:54 +0000830 info->exe_base = VG_(client_base);
831 info->exe_end = VG_(client_end);
nethercote71980f02004-01-24 18:18:54 +0000832
njn73750612005-10-14 03:11:30 +0000833 ret = VG_(do_exec)(exe_name, info);
834
835 // The client was successfully loaded! Continue.
nethercote71980f02004-01-24 18:18:54 +0000836
sewardj45f4e7c2005-09-27 19:20:21 +0000837 /* Get hold of a file descriptor which refers to the client
838 executable. This is needed for attaching to GDB. */
njn73750612005-10-14 03:11:30 +0000839 res = VG_(open)(exe_name, VKI_O_RDONLY, VKI_S_IRUSR);
sewardj45f4e7c2005-09-27 19:20:21 +0000840 if (!res.isError)
841 VG_(cl_exec_fd) = res.val;
842
nethercote71980f02004-01-24 18:18:54 +0000843 /* Copy necessary bits of 'info' that were filled in */
844 *client_eip = info->init_eip;
sewardj45f4e7c2005-09-27 19:20:21 +0000845 VG_(brk_base) = VG_(brk_limit) = VG_PGROUNDUP(info->brkbase);
nethercote71980f02004-01-24 18:18:54 +0000846}
847
nethercote969ecf12004-10-13 17:29:01 +0000848
sewardj71bc3cb2005-05-19 00:25:45 +0000849/*====================================================================*/
850/*=== Command-line: variables, processing, etc ===*/
851/*====================================================================*/
852
853// See pub_{core,tool}_options.h for explanations of all these.
854
sewardj45f4e7c2005-09-27 19:20:21 +0000855static void usage_NORETURN ( Bool debug_help )
njn7cf0bd32002-06-08 13:36:03 +0000856{
njn25e49d8e72002-09-23 09:36:25 +0000857 Char* usage1 =
njn00cfcfc2005-11-12 18:53:50 +0000858"usage: valgrind [options] prog-and-args\n"
njn25e49d8e72002-09-23 09:36:25 +0000859"\n"
nethercote2b0793f2003-12-02 10:41:18 +0000860" common user options for all Valgrind tools, with defaults in [ ]:\n"
sewardjb5f6f512005-03-10 23:59:00 +0000861" --tool=<name> use the Valgrind tool named <name> [memcheck]\n"
nethercotea76368b2004-06-16 11:56:29 +0000862" -h --help show this message\n"
nethercote6c999f22004-01-31 22:55:15 +0000863" --help-debug show this message, plus debugging options\n"
njn25e49d8e72002-09-23 09:36:25 +0000864" --version show version\n"
njn25e49d8e72002-09-23 09:36:25 +0000865" -q --quiet run silently; only print error msgs\n"
866" -v --verbose be more verbose, incl counts of errors\n"
nethercote77eba602003-11-13 17:35:04 +0000867" --trace-children=no|yes Valgrind-ise child processes? [no]\n"
nethercote0d588502004-06-21 13:27:11 +0000868" --track-fds=no|yes track open file descriptors? [no]\n"
thughes6233a382004-08-21 11:10:44 +0000869" --time-stamp=no|yes add timestamps to log messages? [no]\n"
njnce545552005-07-25 22:36:52 +0000870" --log-fd=<number> log messages to file descriptor [2=stderr]\n"
tombbe14b12005-11-04 16:49:39 +0000871" --log-file=<file> log messages to <file>.<pid>\n"
njnce545552005-07-25 22:36:52 +0000872" --log-file-exactly=<file> log messages to <file>\n"
873" --log-file-qualifier=<VAR> incorporate $VAR in logfile name [none]\n"
874" --log-socket=ipaddr:port log messages to socket ipaddr:port\n"
nethercote2b0793f2003-12-02 10:41:18 +0000875"\n"
876" uncommon user options for all Valgrind tools:\n"
nethercote0d588502004-06-21 13:27:11 +0000877" --run-libc-freeres=no|yes free up glibc memory at exit? [yes]\n"
njn628add62005-11-12 18:21:40 +0000878" --sim-hints=hint1,hint2,... known hints:\n"
sewardj19617ae2005-10-20 01:09:57 +0000879" lax-ioctls, enable-outer [none]\n"
sewardjb1131a82005-03-19 15:12:21 +0000880" --show-emwarns=no|yes show warnings about emulation limits? [no]\n"
sewardj6c3a2192005-07-24 07:00:45 +0000881" --smc-check=none|stack|all checks for self-modifying code: none,\n"
882" only for code found in stacks, or all [stack]\n"
sewardj3c3f0c12005-11-08 15:52:36 +0000883" --kernel-variant=variant1,variant2,... known variants: bproc [none]\n"
884" handle non-standard kernel variants\n"
njn25e49d8e72002-09-23 09:36:25 +0000885"\n"
nethercote2b0793f2003-12-02 10:41:18 +0000886" user options for Valgrind tools that report errors:\n"
njnce545552005-07-25 22:36:52 +0000887" --xml=yes all output is in XML (Memcheck/Nulgrind only)\n"
njnc8ec9f82005-07-20 03:03:28 +0000888" --xml-user-comment=STR copy STR verbatim to XML output\n"
nethercote2b0793f2003-12-02 10:41:18 +0000889" --demangle=no|yes automatically demangle C++ names? [yes]\n"
njn20b4a152005-10-19 22:39:40 +0000890" --num-callers=<number> show <number> callers in stack traces [12]\n"
nethercote2b0793f2003-12-02 10:41:18 +0000891" --error-limit=no|yes stop showing new errors if too many? [yes]\n"
892" --show-below-main=no|yes continue stack traces below main() [no]\n"
893" --suppressions=<filename> suppress errors described in <filename>\n"
sewardjd153fae2005-01-10 17:24:47 +0000894" --gen-suppressions=no|yes|all print suppressions for errors? [no]\n"
nethercote04d0fbc2004-01-26 16:48:06 +0000895" --db-attach=no|yes start debugger when errors detected? [no]\n"
896" --db-command=<command> command to start debugger [gdb -nw %%f %%p]\n"
897" --input-fd=<number> file descriptor for input [0=stdin]\n"
sewardj97724e52005-04-02 23:40:59 +0000898" --max-stackframe=<number> assume stack switch for SP changes larger\n"
899" than <number> bytes [2000000]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +0000900"\n";
njn7cf0bd32002-06-08 13:36:03 +0000901
njn25e49d8e72002-09-23 09:36:25 +0000902 Char* usage2 =
903"\n"
nethercote2b0793f2003-12-02 10:41:18 +0000904" debugging options for all Valgrind tools:\n"
njn25e49d8e72002-09-23 09:36:25 +0000905" --sanity-level=<number> level of sanity checking to do [1]\n"
nethercote137bc552003-11-14 17:47:54 +0000906" --profile=no|yes profile? (tool must be built for it) [no]\n"
sewardjfa8ec112005-01-19 11:55:34 +0000907" --trace-flags=<XXXXXXXX> show generated code? (X = 0|1) [00000000]\n"
908" --profile-flags=<XXXXXXXX> ditto, but for profiling (X = 0|1) [00000000]\n"
njn20b4a152005-10-19 22:39:40 +0000909" --trace-notbelow=<number> only show BBs above <number> [0]\n"
njn25e49d8e72002-09-23 09:36:25 +0000910" --trace-syscalls=no|yes show all system calls? [no]\n"
911" --trace-signals=no|yes show signal handling details? [no]\n"
912" --trace-symtab=no|yes show symbol table details? [no]\n"
sewardjce058b02005-05-01 08:55:38 +0000913" --trace-cfi=no|yes show call-frame-info details? [no]\n"
njn25e49d8e72002-09-23 09:36:25 +0000914" --trace-sched=no|yes show thread scheduler details? [no]\n"
jsgf855d93d2003-10-13 22:26:55 +0000915" --wait-for-gdb=yes|no pause on startup to wait for gdb attach\n"
sewardjb5f6f512005-03-10 23:59:00 +0000916#if 0
917" --model-pthreads=yes|no model the pthreads library [no]\n"
918#endif
919" --command-line-only=no|yes only use command line options [no]\n"
njn613812e2005-03-11 04:57:30 +0000920"\n"
921" --vex-iropt-verbosity 0 .. 9 [0]\n"
922" --vex-iropt-level 0 .. 2 [2]\n"
923" --vex-iropt-precise-memory-exns [no]\n"
sewardj8b635a42004-11-22 19:01:47 +0000924" --vex-iropt-unroll-thresh 0 .. 400 [120]\n"
925" --vex-guest-max-insns 1 .. 100 [50]\n"
926" --vex-guest-chase-thresh 0 .. 99 [10]\n"
927"\n"
sewardjfa8ec112005-01-19 11:55:34 +0000928" --trace-flags and --profile-flags values (omit the middle space):\n"
sewardj2a99cf62004-11-24 10:44:19 +0000929" 1000 0000 show conversion into IR\n"
930" 0100 0000 show after initial opt\n"
931" 0010 0000 show after instrumentation\n"
932" 0001 0000 show after second opt\n"
933" 0000 1000 show after tree building\n"
934" 0000 0100 show selecting insns\n"
935" 0000 0010 show after reg-alloc\n"
936" 0000 0001 show final assembly\n"
937"\n"
nethercote2b0793f2003-12-02 10:41:18 +0000938" debugging options for Valgrind tools that report errors\n"
939" --dump-error=<number> show translation for basic block associated\n"
940" with <number>'th error context [0=show none]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +0000941"\n";
njn3e884182003-04-15 13:03:23 +0000942
943 Char* usage3 =
944"\n"
nethercote71980f02004-01-24 18:18:54 +0000945" Extra options read from ~/.valgrindrc, $VALGRIND_OPTS, ./.valgrindrc\n"
njn25e49d8e72002-09-23 09:36:25 +0000946"\n"
njn53612422005-03-12 16:22:54 +0000947" Valgrind is Copyright (C) 2000-2005 Julian Seward et al.\n"
njn25e49d8e72002-09-23 09:36:25 +0000948" and licensed under the GNU General Public License, version 2.\n"
949" Bug reports, feedback, admiration, abuse, etc, to: %s.\n"
njnd04b7c62002-10-03 14:05:52 +0000950"\n"
nethercote137bc552003-11-14 17:47:54 +0000951" Tools are copyright and licensed by their authors. See each\n"
952" tool's start-up message for more information.\n"
njn25e49d8e72002-09-23 09:36:25 +0000953"\n";
njn7cf0bd32002-06-08 13:36:03 +0000954
njnbe9b47b2005-05-15 16:22:58 +0000955 // Ensure the message goes to stdout
956 VG_(clo_log_fd) = 1;
957 vg_assert( !VG_(logging_to_socket) );
958
fitzhardinge98abfc72003-12-16 02:05:15 +0000959 VG_(printf)(usage1);
960 if (VG_(details).name) {
961 VG_(printf)(" user options for %s:\n", VG_(details).name);
fitzhardinge98abfc72003-12-16 02:05:15 +0000962 if (VG_(needs).command_line_options)
njn51d827b2005-05-09 01:02:08 +0000963 VG_TDICT_CALL(tool_print_usage);
fitzhardinge98abfc72003-12-16 02:05:15 +0000964 else
965 VG_(printf)(" (none)\n");
966 }
nethercote6c999f22004-01-31 22:55:15 +0000967 if (debug_help) {
968 VG_(printf)(usage2);
fitzhardinge98abfc72003-12-16 02:05:15 +0000969
nethercote6c999f22004-01-31 22:55:15 +0000970 if (VG_(details).name) {
971 VG_(printf)(" debugging options for %s:\n", VG_(details).name);
972
973 if (VG_(needs).command_line_options)
njn51d827b2005-05-09 01:02:08 +0000974 VG_TDICT_CALL(tool_print_debug_usage);
nethercote6c999f22004-01-31 22:55:15 +0000975 else
976 VG_(printf)(" (none)\n");
977 }
fitzhardinge98abfc72003-12-16 02:05:15 +0000978 }
nethercote421281e2003-11-20 16:20:55 +0000979 VG_(printf)(usage3, VG_BUGS_TO);
nethercotef4928da2004-06-15 10:54:40 +0000980 VG_(exit)(0);
njn7cf0bd32002-06-08 13:36:03 +0000981}
sewardjde4a1d02002-03-22 01:27:54 +0000982
sewardjde4a1d02002-03-22 01:27:54 +0000983
sewardj45f4e7c2005-09-27 19:20:21 +0000984/* Peer at previously set up VG_(args_for_valgrind) and extract any
985 request for help and also the tool name. */
986
987static void get_helprequest_and_toolname ( Int* need_help, HChar** tool )
988{
989 UInt i;
990 HChar* str;
sewardj8b635a42004-11-22 19:01:47 +0000991
nethercote71980f02004-01-24 18:18:54 +0000992 /* parse the options we have (only the options we care about now) */
sewardj45f4e7c2005-09-27 19:20:21 +0000993 for (i = 0; i < VG_(args_for_valgrind).used; i++) {
nethercote71980f02004-01-24 18:18:54 +0000994
sewardj45f4e7c2005-09-27 19:20:21 +0000995 str = VG_(args_for_valgrind).strs[i];
996 vg_assert(str);
nethercote71980f02004-01-24 18:18:54 +0000997
sewardj45f4e7c2005-09-27 19:20:21 +0000998 if (VG_STREQ(str, "--version")) {
njn2e9f3f32005-10-26 16:17:46 +0000999 // Ensure the version string goes to stdout
1000 VG_(clo_log_fd) = 1;
sewardj45f4e7c2005-09-27 19:20:21 +00001001 VG_(printf)("valgrind-" VERSION "\n");
1002 VG_(exit)(0);
1003
1004 } else if (VG_CLO_STREQ(str, "--help") ||
1005 VG_CLO_STREQ(str, "-h")) {
nethercote6c999f22004-01-31 22:55:15 +00001006 *need_help = 1;
1007
sewardj45f4e7c2005-09-27 19:20:21 +00001008 } else if (VG_CLO_STREQ(str, "--help-debug")) {
nethercote6c999f22004-01-31 22:55:15 +00001009 *need_help = 2;
nethercote71980f02004-01-24 18:18:54 +00001010
sewardj45f4e7c2005-09-27 19:20:21 +00001011 // The tool has already been determined, but we need to know the name
1012 // here.
1013 } else if (VG_CLO_STREQN(7, str, "--tool=")) {
1014 *tool = &str[7];
nethercote71980f02004-01-24 18:18:54 +00001015 }
1016 }
nethercote71980f02004-01-24 18:18:54 +00001017}
1018
sewardj45f4e7c2005-09-27 19:20:21 +00001019static Bool process_cmd_line_options( UInt* client_auxv, const char* toolname )
nethercote71980f02004-01-24 18:18:54 +00001020{
sewardj92645592005-07-23 09:18:34 +00001021 SysRes sres;
1022 Int i, eventually_log_fd;
1023 Int toolname_len = VG_(strlen)(toolname);
njnbe9b47b2005-05-15 16:22:58 +00001024 enum {
1025 VgLogTo_Fd,
1026 VgLogTo_File,
1027 VgLogTo_FileExactly,
1028 VgLogTo_Socket
1029 } log_to = VgLogTo_Fd; // Where is logging output to be sent?
sewardjde4a1d02002-03-22 01:27:54 +00001030
nethercotee1730692003-11-20 10:38:07 +00001031 /* log to stderr by default, but usage message goes to stdout */
nethercotef8548672004-06-21 12:42:35 +00001032 eventually_log_fd = 2;
sewardjde4a1d02002-03-22 01:27:54 +00001033
sewardj19d81412002-06-03 01:10:40 +00001034 /* Check for sane path in ./configure --prefix=... */
fitzhardinge98abfc72003-12-16 02:05:15 +00001035 if (VG_LIBDIR[0] != '/')
sewardj19d81412002-06-03 01:10:40 +00001036 config_error("Please use absolute paths in "
1037 "./configure --prefix=... or --libdir=...");
sewardj38170912002-05-10 21:07:22 +00001038
sewardj45f4e7c2005-09-27 19:20:21 +00001039 for (i = 0; i < VG_(args_for_valgrind).used; i++) {
nethercote71980f02004-01-24 18:18:54 +00001040
sewardj45f4e7c2005-09-27 19:20:21 +00001041 HChar* arg = VG_(args_for_valgrind).strs[i];
1042 HChar* colon = arg;
nethercote71980f02004-01-24 18:18:54 +00001043
thughes3bfd5a02004-07-18 08:05:44 +00001044 /* Look for a colon in the switch name */
1045 while (*colon && *colon != ':' && *colon != '=')
1046 colon++;
nethercote71980f02004-01-24 18:18:54 +00001047
1048 /* Look for matching "--toolname:foo" */
thughes3bfd5a02004-07-18 08:05:44 +00001049 if (*colon == ':') {
nethercote71980f02004-01-24 18:18:54 +00001050 if (VG_CLO_STREQN(2, arg, "--") &&
1051 VG_CLO_STREQN(toolname_len, arg+2, toolname) &&
1052 VG_CLO_STREQN(1, arg+2+toolname_len, ":"))
1053 {
1054 // prefix matches, convert "--toolname:foo" to "--foo"
1055 if (0)
1056 VG_(printf)("tool-specific arg: %s\n", arg);
sewardj45f4e7c2005-09-27 19:20:21 +00001057 arg = VG_(strdup)(arg + toolname_len + 1);
nethercote71980f02004-01-24 18:18:54 +00001058 arg[0] = '-';
1059 arg[1] = '-';
1060
1061 } else {
1062 // prefix doesn't match, skip to next arg
1063 continue;
1064 }
1065 }
1066
fitzhardinge98abfc72003-12-16 02:05:15 +00001067 /* Ignore these options - they've already been handled */
njn45270a22005-03-27 01:00:11 +00001068 if (VG_CLO_STREQN( 7, arg, "--tool=")) goto skip_arg;
njn45270a22005-03-27 01:00:11 +00001069 if (VG_CLO_STREQN(20, arg, "--command-line-only=")) goto skip_arg;
fitzhardinge98abfc72003-12-16 02:05:15 +00001070
njn45270a22005-03-27 01:00:11 +00001071 if ( VG_CLO_STREQ(arg, "--")) goto skip_arg;
nethercote27fec902004-06-16 21:26:32 +00001072
nethercote71980f02004-01-24 18:18:54 +00001073 else if (VG_CLO_STREQ(arg, "-v") ||
1074 VG_CLO_STREQ(arg, "--verbose"))
sewardjde4a1d02002-03-22 01:27:54 +00001075 VG_(clo_verbosity)++;
nethercote27fec902004-06-16 21:26:32 +00001076
nethercote71980f02004-01-24 18:18:54 +00001077 else if (VG_CLO_STREQ(arg, "-q") ||
1078 VG_CLO_STREQ(arg, "--quiet"))
sewardjde4a1d02002-03-22 01:27:54 +00001079 VG_(clo_verbosity)--;
1080
sewardj1cf558c2005-04-25 01:36:56 +00001081 else if (VG_CLO_STREQ(arg, "-d")) {
1082 /* do nothing */
1083 }
1084
sewardj71bc3cb2005-05-19 00:25:45 +00001085 else VG_BOOL_CLO(arg, "--xml", VG_(clo_xml))
njn45270a22005-03-27 01:00:11 +00001086 else VG_BOOL_CLO(arg, "--db-attach", VG_(clo_db_attach))
1087 else VG_BOOL_CLO(arg, "--demangle", VG_(clo_demangle))
1088 else VG_BOOL_CLO(arg, "--error-limit", VG_(clo_error_limit))
njn45270a22005-03-27 01:00:11 +00001089 else VG_BOOL_CLO(arg, "--show-emwarns", VG_(clo_show_emwarns))
sewardj97724e52005-04-02 23:40:59 +00001090 else VG_NUM_CLO (arg, "--max-stackframe", VG_(clo_max_stackframe))
njn45270a22005-03-27 01:00:11 +00001091 else VG_BOOL_CLO(arg, "--profile", VG_(clo_profile))
1092 else VG_BOOL_CLO(arg, "--run-libc-freeres", VG_(clo_run_libc_freeres))
1093 else VG_BOOL_CLO(arg, "--show-below-main", VG_(clo_show_below_main))
1094 else VG_BOOL_CLO(arg, "--time-stamp", VG_(clo_time_stamp))
1095 else VG_BOOL_CLO(arg, "--track-fds", VG_(clo_track_fds))
1096 else VG_BOOL_CLO(arg, "--trace-children", VG_(clo_trace_children))
1097 else VG_BOOL_CLO(arg, "--trace-sched", VG_(clo_trace_sched))
1098 else VG_BOOL_CLO(arg, "--trace-signals", VG_(clo_trace_signals))
1099 else VG_BOOL_CLO(arg, "--trace-symtab", VG_(clo_trace_symtab))
sewardjce058b02005-05-01 08:55:38 +00001100 else VG_BOOL_CLO(arg, "--trace-cfi", VG_(clo_trace_cfi))
njn45270a22005-03-27 01:00:11 +00001101 else VG_BOOL_CLO(arg, "--trace-redir", VG_(clo_trace_redir))
1102 else VG_BOOL_CLO(arg, "--trace-syscalls", VG_(clo_trace_syscalls))
1103 else VG_BOOL_CLO(arg, "--trace-pthreads", VG_(clo_trace_pthreads))
1104 else VG_BOOL_CLO(arg, "--wait-for-gdb", VG_(clo_wait_for_gdb))
1105 else VG_BOOL_CLO(arg, "--model-pthreads", VG_(clo_model_pthreads))
sewardj72f98ff2002-06-13 17:23:38 +00001106
njn45270a22005-03-27 01:00:11 +00001107 else VG_STR_CLO (arg, "--db-command", VG_(clo_db_command))
njn628add62005-11-12 18:21:40 +00001108 else VG_STR_CLO (arg, "--sim-hints", VG_(clo_sim_hints))
sewardjde4a1d02002-03-22 01:27:54 +00001109
njn45270a22005-03-27 01:00:11 +00001110 else VG_NUM_CLO (arg, "--dump-error", VG_(clo_dump_error))
1111 else VG_NUM_CLO (arg, "--input-fd", VG_(clo_input_fd))
1112 else VG_NUM_CLO (arg, "--sanity-level", VG_(clo_sanity_level))
1113 else VG_BNUM_CLO(arg, "--num-callers", VG_(clo_backtrace_size), 1,
1114 VG_DEEPEST_BACKTRACE)
sewardjde4a1d02002-03-22 01:27:54 +00001115
sewardj6c3a2192005-07-24 07:00:45 +00001116 else if (VG_CLO_STREQ(arg, "--smc-check=none"))
1117 VG_(clo_smc_check) = Vg_SmcNone;
1118 else if (VG_CLO_STREQ(arg, "--smc-check=stack"))
1119 VG_(clo_smc_check) = Vg_SmcStack;
1120 else if (VG_CLO_STREQ(arg, "--smc-check=all"))
1121 VG_(clo_smc_check) = Vg_SmcAll;
sewardj26412bd2005-07-07 10:05:05 +00001122
sewardjce5a5662005-10-06 03:19:49 +00001123 else VG_STR_CLO (arg, "--kernel-variant", VG_(clo_kernel_variant))
1124
njn45270a22005-03-27 01:00:11 +00001125 else VG_BNUM_CLO(arg, "--vex-iropt-verbosity",
sewardj8b635a42004-11-22 19:01:47 +00001126 VG_(clo_vex_control).iropt_verbosity, 0, 10)
njn45270a22005-03-27 01:00:11 +00001127 else VG_BNUM_CLO(arg, "--vex-iropt-level",
sewardj8b635a42004-11-22 19:01:47 +00001128 VG_(clo_vex_control).iropt_level, 0, 2)
njn45270a22005-03-27 01:00:11 +00001129 else VG_BOOL_CLO(arg, "--vex-iropt-precise-memory-exns",
sewardj8b635a42004-11-22 19:01:47 +00001130 VG_(clo_vex_control).iropt_precise_memory_exns)
njn45270a22005-03-27 01:00:11 +00001131 else VG_BNUM_CLO(arg, "--vex-iropt-unroll-thresh",
sewardj8b635a42004-11-22 19:01:47 +00001132 VG_(clo_vex_control).iropt_unroll_thresh, 0, 400)
njn45270a22005-03-27 01:00:11 +00001133 else VG_BNUM_CLO(arg, "--vex-guest-max-insns",
sewardj8b635a42004-11-22 19:01:47 +00001134 VG_(clo_vex_control).guest_max_insns, 1, 100)
njn45270a22005-03-27 01:00:11 +00001135 else VG_BNUM_CLO(arg, "--vex-guest-chase-thresh",
sewardj8b635a42004-11-22 19:01:47 +00001136 VG_(clo_vex_control).guest_chase_thresh, 0, 99)
1137
nethercotef8548672004-06-21 12:42:35 +00001138 else if (VG_CLO_STREQN(9, arg, "--log-fd=")) {
njnbe9b47b2005-05-15 16:22:58 +00001139 log_to = VgLogTo_Fd;
nethercotef8548672004-06-21 12:42:35 +00001140 VG_(clo_log_name) = NULL;
1141 eventually_log_fd = (Int)VG_(atoll)(&arg[9]);
sewardj4cf05692002-10-27 20:28:29 +00001142 }
1143
nethercotef8548672004-06-21 12:42:35 +00001144 else if (VG_CLO_STREQN(11, arg, "--log-file=")) {
njnbe9b47b2005-05-15 16:22:58 +00001145 log_to = VgLogTo_File;
nethercotef8548672004-06-21 12:42:35 +00001146 VG_(clo_log_name) = &arg[11];
sewardj4cf05692002-10-27 20:28:29 +00001147 }
njnd6bc3c32005-03-27 00:44:31 +00001148
sewardjad311162005-07-19 11:25:02 +00001149 else if (VG_CLO_STREQN(21, arg, "--log-file-qualifier=")) {
1150 VG_(clo_log_file_qualifier) = &arg[21];
1151 }
1152
sewardj603d4102005-01-11 14:01:02 +00001153 else if (VG_CLO_STREQN(19, arg, "--log-file-exactly=")) {
njnbe9b47b2005-05-15 16:22:58 +00001154 log_to = VgLogTo_FileExactly;
sewardj603d4102005-01-11 14:01:02 +00001155 VG_(clo_log_name) = &arg[19];
1156 }
sewardjde4a1d02002-03-22 01:27:54 +00001157
nethercotef8548672004-06-21 12:42:35 +00001158 else if (VG_CLO_STREQN(13, arg, "--log-socket=")) {
njnbe9b47b2005-05-15 16:22:58 +00001159 log_to = VgLogTo_Socket;
nethercotef8548672004-06-21 12:42:35 +00001160 VG_(clo_log_name) = &arg[13];
sewardj73cf3bc2002-11-03 03:20:15 +00001161 }
1162
sewardj768db0e2005-07-19 14:18:56 +00001163 else if (VG_CLO_STREQN(19, arg, "--xml-user-comment=")) {
1164 VG_(clo_xml_user_comment) = &arg[19];
1165 }
1166
nethercote71980f02004-01-24 18:18:54 +00001167 else if (VG_CLO_STREQN(15, arg, "--suppressions=")) {
sewardjde4a1d02002-03-22 01:27:54 +00001168 if (VG_(clo_n_suppressions) >= VG_CLO_MAX_SFILES) {
njn25e49d8e72002-09-23 09:36:25 +00001169 VG_(message)(Vg_UserMsg, "Too many suppression files specified.");
sewardjde4a1d02002-03-22 01:27:54 +00001170 VG_(message)(Vg_UserMsg,
1171 "Increase VG_CLO_MAX_SFILES and recompile.");
nethercote71980f02004-01-24 18:18:54 +00001172 VG_(bad_option)(arg);
sewardjde4a1d02002-03-22 01:27:54 +00001173 }
nethercote71980f02004-01-24 18:18:54 +00001174 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = &arg[15];
sewardjde4a1d02002-03-22 01:27:54 +00001175 VG_(clo_n_suppressions)++;
1176 }
sewardjde4a1d02002-03-22 01:27:54 +00001177
sewardjfa8ec112005-01-19 11:55:34 +00001178 /* "stuvwxyz" --> stuvwxyz (binary) */
1179 else if (VG_CLO_STREQN(14, arg, "--trace-flags=")) {
1180 Int j;
1181 char* opt = & arg[14];
1182
1183 if (8 != VG_(strlen)(opt)) {
1184 VG_(message)(Vg_UserMsg,
1185 "--trace-flags argument must have 8 digits");
1186 VG_(bad_option)(arg);
1187 }
1188 for (j = 0; j < 8; j++) {
1189 if ('0' == opt[j]) { /* do nothing */ }
1190 else if ('1' == opt[j]) VG_(clo_trace_flags) |= (1 << (7-j));
1191 else {
1192 VG_(message)(Vg_UserMsg, "--trace-flags argument can only "
1193 "contain 0s and 1s");
1194 VG_(bad_option)(arg);
1195 }
1196 }
1197 }
1198
1199 /* "stuvwxyz" --> stuvwxyz (binary) */
1200 else if (VG_CLO_STREQN(16, arg, "--profile-flags=")) {
njn25e49d8e72002-09-23 09:36:25 +00001201 Int j;
nethercote71980f02004-01-24 18:18:54 +00001202 char* opt = & arg[16];
njn25e49d8e72002-09-23 09:36:25 +00001203
sewardj2a99cf62004-11-24 10:44:19 +00001204 if (8 != VG_(strlen)(opt)) {
njn25e49d8e72002-09-23 09:36:25 +00001205 VG_(message)(Vg_UserMsg,
sewardjfa8ec112005-01-19 11:55:34 +00001206 "--profile-flags argument must have 8 digits");
nethercote71980f02004-01-24 18:18:54 +00001207 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001208 }
sewardj8b635a42004-11-22 19:01:47 +00001209 for (j = 0; j < 8; j++) {
njn25e49d8e72002-09-23 09:36:25 +00001210 if ('0' == opt[j]) { /* do nothing */ }
sewardjfa8ec112005-01-19 11:55:34 +00001211 else if ('1' == opt[j]) VG_(clo_profile_flags) |= (1 << (7-j));
njn25e49d8e72002-09-23 09:36:25 +00001212 else {
sewardjfa8ec112005-01-19 11:55:34 +00001213 VG_(message)(Vg_UserMsg, "--profile-flags argument can only "
njn25e49d8e72002-09-23 09:36:25 +00001214 "contain 0s and 1s");
nethercote71980f02004-01-24 18:18:54 +00001215 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001216 }
1217 }
1218 }
sewardjde4a1d02002-03-22 01:27:54 +00001219
njn45270a22005-03-27 01:00:11 +00001220 else VG_NUM_CLO (arg, "--trace-notbelow", VG_(clo_trace_notbelow))
sewardjc771b292004-11-30 18:55:21 +00001221
sewardjd153fae2005-01-10 17:24:47 +00001222 else if (VG_CLO_STREQ(arg, "--gen-suppressions=no"))
1223 VG_(clo_gen_suppressions) = 0;
1224 else if (VG_CLO_STREQ(arg, "--gen-suppressions=yes"))
1225 VG_(clo_gen_suppressions) = 1;
1226 else if (VG_CLO_STREQ(arg, "--gen-suppressions=all"))
1227 VG_(clo_gen_suppressions) = 2;
1228
nethercote71980f02004-01-24 18:18:54 +00001229 else if ( ! VG_(needs).command_line_options
njn51d827b2005-05-09 01:02:08 +00001230 || ! VG_TDICT_CALL(tool_process_cmd_line_option, arg) ) {
nethercotef4928da2004-06-15 10:54:40 +00001231 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001232 }
njn8c0b3bb2005-03-12 21:20:39 +00001233 skip_arg:
sewardj45f4e7c2005-09-27 19:20:21 +00001234 if (arg != VG_(args_for_valgrind).strs[i]) {
1235 VG_(free)(arg);
1236 }
sewardjde4a1d02002-03-22 01:27:54 +00001237 }
1238
sewardj998d40d2004-12-06 14:24:52 +00001239 /* Make VEX control parameters sane */
1240
1241 if (VG_(clo_vex_control).guest_chase_thresh
1242 >= VG_(clo_vex_control).guest_max_insns)
1243 VG_(clo_vex_control).guest_chase_thresh
1244 = VG_(clo_vex_control).guest_max_insns - 1;
1245
1246 if (VG_(clo_vex_control).guest_chase_thresh < 0)
1247 VG_(clo_vex_control).guest_chase_thresh = 0;
1248
1249 /* Check various option values */
nethercote27fec902004-06-16 21:26:32 +00001250
njnf9ebf672003-05-12 21:41:30 +00001251 if (VG_(clo_verbosity) < 0)
sewardjde4a1d02002-03-22 01:27:54 +00001252 VG_(clo_verbosity) = 0;
1253
nethercote04d0fbc2004-01-26 16:48:06 +00001254 if (VG_(clo_db_attach) && VG_(clo_trace_children)) {
sewardjde4a1d02002-03-22 01:27:54 +00001255 VG_(message)(Vg_UserMsg, "");
1256 VG_(message)(Vg_UserMsg,
nethercote04d0fbc2004-01-26 16:48:06 +00001257 "--db-attach=yes conflicts with --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001258 VG_(message)(Vg_UserMsg,
1259 "Please choose one or the other, but not both.");
nethercote04d0fbc2004-01-26 16:48:06 +00001260 VG_(bad_option)("--db-attach=yes and --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001261 }
1262
njnbe9b47b2005-05-15 16:22:58 +00001263 if (VG_(clo_gen_suppressions) > 0 &&
1264 !VG_(needs).core_errors && !VG_(needs).tool_errors) {
1265 VG_(message)(Vg_UserMsg,
1266 "Can't use --gen-suppressions= with this tool,");
1267 VG_(message)(Vg_UserMsg,
1268 "as it doesn't generate errors.");
1269 VG_(bad_option)("--gen-suppressions=");
1270 }
1271
sewardj71bc3cb2005-05-19 00:25:45 +00001272 /* If we've been asked to emit XML, mash around various other
1273 options so as to constrain the output somewhat, and to remove
1274 any need for user input during the run. */
1275 if (VG_(clo_xml)) {
1276 /* Disable suppression generation (requires user input) */
1277 VG_(clo_gen_suppressions) = 0;
1278 /* Disable attaching to GDB (requires user input) */
1279 VG_(clo_db_attach) = False;
1280 /* Set a known verbosity level */
1281 VG_(clo_verbosity) = 1;
1282 /* Disable error limits (this might be a bad idea!) */
1283 VG_(clo_error_limit) = False;
1284 /* Disable emulation warnings */
1285 VG_(clo_show_emwarns) = False;
1286 /* Disable waiting for GDB to debug Valgrind */
1287 VG_(clo_wait_for_gdb) = False;
1288 /* No file-descriptor leak checking yet */
1289 VG_(clo_track_fds) = False;
sewardj21f7f0c2005-07-06 19:46:48 +00001290 /* Disable timestamped output */
1291 VG_(clo_time_stamp) = False;
sewardj71bc3cb2005-05-19 00:25:45 +00001292 /* Also, we want to set options for the leak checker, but that
1293 will have to be done in Memcheck's flag-handling code, not
1294 here. */
1295 }
1296
njnbe9b47b2005-05-15 16:22:58 +00001297 /* All non-logging-related options have been checked. If the logging
1298 option specified is ok, we can switch to it, as we know we won't
1299 have to generate any other command-line-related error messages.
1300 (So far we should be still attached to stderr, so we can show on
1301 the terminal any problems to do with processing command line
1302 opts.)
1303
1304 So set up logging now. After this is done, VG_(clo_log_fd)
sewardj4cf05692002-10-27 20:28:29 +00001305 should be connected to whatever sink has been selected, and we
1306 indiscriminately chuck stuff into it without worrying what the
1307 nature of it is. Oh the wonder of Unix streams. */
1308
njnbe9b47b2005-05-15 16:22:58 +00001309 vg_assert(VG_(clo_log_fd) == 2 /* stderr */);
1310 vg_assert(VG_(logging_to_socket) == False);
sewardj4cf05692002-10-27 20:28:29 +00001311
njnbe9b47b2005-05-15 16:22:58 +00001312 switch (log_to) {
sewardj73cf3bc2002-11-03 03:20:15 +00001313
sewardj4cf05692002-10-27 20:28:29 +00001314 case VgLogTo_Fd:
nethercotef8548672004-06-21 12:42:35 +00001315 vg_assert(VG_(clo_log_name) == NULL);
1316 VG_(clo_log_fd) = eventually_log_fd;
sewardj4cf05692002-10-27 20:28:29 +00001317 break;
sewardj73cf3bc2002-11-03 03:20:15 +00001318
sewardj4cf05692002-10-27 20:28:29 +00001319 case VgLogTo_File: {
sewardjad311162005-07-19 11:25:02 +00001320 HChar logfilename[1000];
1321 Int seq = 0;
1322 Int pid = VG_(getpid)();
1323 HChar* qual = NULL;
jsgff3c3f1a2003-10-14 22:13:28 +00001324
nethercotef8548672004-06-21 12:42:35 +00001325 vg_assert(VG_(clo_log_name) != NULL);
1326 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
jsgff3c3f1a2003-10-14 22:13:28 +00001327
sewardjad311162005-07-19 11:25:02 +00001328 if (VG_(clo_log_file_qualifier)) {
1329 qual = VG_(getenv)(VG_(clo_log_file_qualifier));
1330 }
1331
nethercote71980f02004-01-24 18:18:54 +00001332 for (;;) {
sewardj92645592005-07-23 09:18:34 +00001333 HChar pidtxt[20], seqtxt[20];
1334
1335 VG_(sprintf)(pidtxt, "%d", pid);
1336
1337 if (seq == 0)
1338 seqtxt[0] = 0;
1339 else
1340 VG_(sprintf)(seqtxt, ".%d", seq);
1341
jsgff3c3f1a2003-10-14 22:13:28 +00001342 seq++;
1343
sewardj92645592005-07-23 09:18:34 +00001344 /* Result:
1345 if (qual) base_name ++ "." ++ qual ++ seqtxt
1346 if (not qual) base_name ++ "." ++ pid ++ seqtxt
1347 */
1348 VG_(sprintf)( logfilename,
1349 "%s.%s%s",
1350 VG_(clo_log_name),
1351 qual ? qual : pidtxt,
1352 seqtxt );
1353
njnbe9b47b2005-05-15 16:22:58 +00001354 // EXCL: it will fail with EEXIST if the file already exists.
sewardj92645592005-07-23 09:18:34 +00001355 sres
jsgff3c3f1a2003-10-14 22:13:28 +00001356 = VG_(open)(logfilename,
1357 VKI_O_CREAT|VKI_O_WRONLY|VKI_O_EXCL|VKI_O_TRUNC,
1358 VKI_S_IRUSR|VKI_S_IWUSR);
sewardj92645592005-07-23 09:18:34 +00001359 if (!sres.isError) {
1360 eventually_log_fd = sres.val;
nethercotef8548672004-06-21 12:42:35 +00001361 VG_(clo_log_fd) = VG_(safe_fd)(eventually_log_fd);
sewardj603d4102005-01-11 14:01:02 +00001362 break; /* for (;;) */
jsgff3c3f1a2003-10-14 22:13:28 +00001363 } else {
njnbe9b47b2005-05-15 16:22:58 +00001364 // If the file already existed, we try the next name. If it
1365 // was some other file error, we give up.
sewardj92645592005-07-23 09:18:34 +00001366 if (sres.val != VKI_EEXIST) {
jsgff3c3f1a2003-10-14 22:13:28 +00001367 VG_(message)(Vg_UserMsg,
tombbe14b12005-11-04 16:49:39 +00001368 "Can't create/open log file '%s.%d'; giving up!",
nethercotef8548672004-06-21 12:42:35 +00001369 VG_(clo_log_name), pid);
jsgff3c3f1a2003-10-14 22:13:28 +00001370 VG_(bad_option)(
sewardj603d4102005-01-11 14:01:02 +00001371 "--log-file=<file> (didn't work out for some reason.)");
njnbe9b47b2005-05-15 16:22:58 +00001372 /*NOTREACHED*/
jsgff3c3f1a2003-10-14 22:13:28 +00001373 }
1374 }
1375 }
sewardj603d4102005-01-11 14:01:02 +00001376 break; /* switch (VG_(clo_log_to)) */
1377 }
1378
1379 case VgLogTo_FileExactly: {
sewardj603d4102005-01-11 14:01:02 +00001380 vg_assert(VG_(clo_log_name) != NULL);
1381 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
sewardj603d4102005-01-11 14:01:02 +00001382
sewardj92645592005-07-23 09:18:34 +00001383 sres
njnbe9b47b2005-05-15 16:22:58 +00001384 = VG_(open)(VG_(clo_log_name),
sewardj603d4102005-01-11 14:01:02 +00001385 VKI_O_CREAT|VKI_O_WRONLY|VKI_O_TRUNC,
1386 VKI_S_IRUSR|VKI_S_IWUSR);
sewardj92645592005-07-23 09:18:34 +00001387 if (!sres.isError) {
1388 eventually_log_fd = sres.val;
sewardj603d4102005-01-11 14:01:02 +00001389 VG_(clo_log_fd) = VG_(safe_fd)(eventually_log_fd);
njnbe9b47b2005-05-15 16:22:58 +00001390 } else {
sewardj603d4102005-01-11 14:01:02 +00001391 VG_(message)(Vg_UserMsg,
njn02bc4b82005-05-15 17:28:26 +00001392 "Can't create/open log file '%s'; giving up!",
sewardj603d4102005-01-11 14:01:02 +00001393 VG_(clo_log_name));
1394 VG_(bad_option)(
1395 "--log-file-exactly=<file> (didn't work out for some reason.)");
1396 /*NOTREACHED*/
1397 }
1398 break; /* switch (VG_(clo_log_to)) */
sewardj73cf3bc2002-11-03 03:20:15 +00001399 }
1400
1401 case VgLogTo_Socket: {
nethercotef8548672004-06-21 12:42:35 +00001402 vg_assert(VG_(clo_log_name) != NULL);
1403 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
1404 eventually_log_fd = VG_(connect_via_socket)( VG_(clo_log_name) );
1405 if (eventually_log_fd == -1) {
sewardj73cf3bc2002-11-03 03:20:15 +00001406 VG_(message)(Vg_UserMsg,
nethercotef8548672004-06-21 12:42:35 +00001407 "Invalid --log-socket=ipaddr or --log-socket=ipaddr:port spec");
sewardj73cf3bc2002-11-03 03:20:15 +00001408 VG_(message)(Vg_UserMsg,
njn02bc4b82005-05-15 17:28:26 +00001409 "of '%s'; giving up!", VG_(clo_log_name) );
sewardj73cf3bc2002-11-03 03:20:15 +00001410 VG_(bad_option)(
nethercotef8548672004-06-21 12:42:35 +00001411 "--log-socket=");
njnbe9b47b2005-05-15 16:22:58 +00001412 /*NOTREACHED*/
sewardj4cf05692002-10-27 20:28:29 +00001413 }
nethercotef8548672004-06-21 12:42:35 +00001414 if (eventually_log_fd == -2) {
sewardj73cf3bc2002-11-03 03:20:15 +00001415 VG_(message)(Vg_UserMsg,
njn02bc4b82005-05-15 17:28:26 +00001416 "valgrind: failed to connect to logging server '%s'.",
nethercotef8548672004-06-21 12:42:35 +00001417 VG_(clo_log_name) );
sewardj570f8902002-11-03 11:44:36 +00001418 VG_(message)(Vg_UserMsg,
1419 "Log messages will sent to stderr instead." );
1420 VG_(message)(Vg_UserMsg,
1421 "" );
1422 /* We don't change anything here. */
njnbe9b47b2005-05-15 16:22:58 +00001423 vg_assert(VG_(clo_log_fd) == 2);
sewardj570f8902002-11-03 11:44:36 +00001424 } else {
nethercotef8548672004-06-21 12:42:35 +00001425 vg_assert(eventually_log_fd > 0);
1426 VG_(clo_log_fd) = eventually_log_fd;
njnbe9b47b2005-05-15 16:22:58 +00001427 VG_(logging_to_socket) = True;
sewardj570f8902002-11-03 11:44:36 +00001428 }
sewardj73cf3bc2002-11-03 03:20:15 +00001429 break;
1430 }
sewardj4cf05692002-10-27 20:28:29 +00001431 }
1432
sewardj71bc3cb2005-05-19 00:25:45 +00001433
1434 /* Check that the requested tool actually supports XML output. */
sewardj45f4e7c2005-09-27 19:20:21 +00001435 if (VG_(clo_xml) && !VG_STREQ(toolname, "memcheck")
1436 && !VG_STREQ(toolname, "none")) {
sewardj71bc3cb2005-05-19 00:25:45 +00001437 VG_(clo_xml) = False;
1438 VG_(message)(Vg_UserMsg,
cerion39655202005-07-13 14:18:24 +00001439 "Currently only Memcheck|None supports XML output.");
sewardj71bc3cb2005-05-19 00:25:45 +00001440 VG_(bad_option)("--xml=yes");
1441 /*NOTREACHED*/
1442 }
1443
njnbe9b47b2005-05-15 16:22:58 +00001444 // Move log_fd into the safe range, so it doesn't conflict with any app fds.
1445 // XXX: this is more or less duplicating the behaviour of the calls to
1446 // VG_(safe_fd)() above, although this does not close the original fd.
1447 // Perhaps the VG_(safe_fd)() calls above should be removed, and this
1448 // code should be replaced with a call to VG_(safe_fd)(). --njn
thughesad1c9562004-06-26 11:27:52 +00001449 eventually_log_fd = VG_(fcntl)(VG_(clo_log_fd), VKI_F_DUPFD, VG_(fd_hard_limit));
nethercotef8548672004-06-21 12:42:35 +00001450 if (eventually_log_fd < 0)
jsgf855d93d2003-10-13 22:26:55 +00001451 VG_(message)(Vg_UserMsg, "valgrind: failed to move logfile fd into safe range");
1452 else {
nethercotef8548672004-06-21 12:42:35 +00001453 VG_(clo_log_fd) = eventually_log_fd;
1454 VG_(fcntl)(VG_(clo_log_fd), VKI_F_SETFD, VKI_FD_CLOEXEC);
jsgf855d93d2003-10-13 22:26:55 +00001455 }
1456
sewardj45f4e7c2005-09-27 19:20:21 +00001457 if (VG_(clo_n_suppressions) < VG_CLO_MAX_SFILES-1 &&
1458 (VG_(needs).core_errors || VG_(needs).tool_errors)) {
1459 /* If we haven't reached the max number of suppressions, load
1460 the default one. */
1461 static const Char default_supp[] = "default.supp";
1462 Int len = VG_(strlen)(VG_(libdir)) + 1 + sizeof(default_supp);
1463 Char *buf = VG_(arena_malloc)(VG_AR_CORE, len);
1464 VG_(sprintf)(buf, "%s/%s", VG_(libdir), default_supp);
1465 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = buf;
1466 VG_(clo_n_suppressions)++;
1467 }
sewardjde4a1d02002-03-22 01:27:54 +00001468
sewardj45f4e7c2005-09-27 19:20:21 +00001469 return (log_to == VgLogTo_Fd);
1470}
1471
1472
1473/*====================================================================*/
1474/*=== Printing the preamble ===*/
1475/*====================================================================*/
1476
1477/* Ok, the logging sink is running now. Print a suitable preamble.
1478 If logging to file or a socket, write details of parent PID and
1479 command line args, to help people trying to interpret the
1480 results of a run which encompasses multiple processes. */
1481static void print_preamble(Bool logging_to_fd, const char* toolname)
1482{
tom60a4b0b2005-10-12 10:45:27 +00001483 HChar* xpre = VG_(clo_xml) ? " <line>" : "";
1484 HChar* xpost = VG_(clo_xml) ? "</line>" : "";
1485 Int i;
1486
sewardj71bc3cb2005-05-19 00:25:45 +00001487 if (VG_(clo_xml)) {
sewardj8665d8e2005-06-01 17:35:23 +00001488 VG_(message)(Vg_UserMsg, "<?xml version=\"1.0\"?>");
1489 VG_(message)(Vg_UserMsg, "");
sewardj71bc3cb2005-05-19 00:25:45 +00001490 VG_(message)(Vg_UserMsg, "<valgrindoutput>");
1491 VG_(message)(Vg_UserMsg, "");
cerion20241ba2005-11-15 19:07:53 +00001492 VG_(message)(Vg_UserMsg, "<protocolversion>2</protocolversion>");
sewardj71bc3cb2005-05-19 00:25:45 +00001493 VG_(message)(Vg_UserMsg, "");
1494 }
1495
sewardj83adf412002-05-01 01:25:45 +00001496 if (VG_(clo_verbosity > 0)) {
sewardjd7bddad2005-06-13 16:48:32 +00001497
1498 if (VG_(clo_xml))
1499 VG_(message)(Vg_UserMsg, "<preamble>");
1500
nethercote996901a2004-08-03 13:29:09 +00001501 /* Tool details */
sewardj71bc3cb2005-05-19 00:25:45 +00001502 VG_(message)(Vg_UserMsg, "%s%s%s%s, %s.%s",
1503 xpre,
njnd04b7c62002-10-03 14:05:52 +00001504 VG_(details).name,
njnb9c427c2004-12-01 14:14:42 +00001505 NULL == VG_(details).version ? "" : "-",
njnd04b7c62002-10-03 14:05:52 +00001506 NULL == VG_(details).version
1507 ? (Char*)"" : VG_(details).version,
sewardj71bc3cb2005-05-19 00:25:45 +00001508 VG_(details).description,
1509 xpost);
1510 VG_(message)(Vg_UserMsg, "%s%s%s",
1511 xpre, VG_(details).copyright_author, xpost);
sewardj3b2736a2002-03-24 12:18:35 +00001512
njnd04b7c62002-10-03 14:05:52 +00001513 /* Core details */
1514 VG_(message)(Vg_UserMsg,
sewardj71bc3cb2005-05-19 00:25:45 +00001515 "%sUsing LibVEX rev %s, a library for dynamic binary translation.%s",
1516 xpre, LibVEX_Version(), xpost );
sewardjc7025332004-12-13 18:30:39 +00001517 VG_(message)(Vg_UserMsg,
sewardj71bc3cb2005-05-19 00:25:45 +00001518 "%sCopyright (C) 2004-2005, and GNU GPL'd, by OpenWorks LLP.%s",
1519 xpre, xpost );
sewardjc7025332004-12-13 18:30:39 +00001520 VG_(message)(Vg_UserMsg,
sewardj71bc3cb2005-05-19 00:25:45 +00001521 "%sUsing valgrind-%s, a dynamic binary instrumentation framework.%s",
1522 xpre, VERSION, xpost);
sewardjde4a1d02002-03-22 01:27:54 +00001523 VG_(message)(Vg_UserMsg,
sewardj71bc3cb2005-05-19 00:25:45 +00001524 "%sCopyright (C) 2000-2005, and GNU GPL'd, by Julian Seward et al.%s",
1525 xpre, xpost );
sewardjd7bddad2005-06-13 16:48:32 +00001526
sewardj45f4e7c2005-09-27 19:20:21 +00001527 if (VG_(clo_verbosity) == 1 && !VG_(clo_xml))
1528 VG_(message)(Vg_UserMsg, "For more details, rerun with: -v");
1529
sewardjd7bddad2005-06-13 16:48:32 +00001530 if (VG_(clo_xml))
1531 VG_(message)(Vg_UserMsg, "</preamble>");
njnd04b7c62002-10-03 14:05:52 +00001532 }
1533
sewardj45f4e7c2005-09-27 19:20:21 +00001534 if (!VG_(clo_xml) && VG_(clo_verbosity) > 0 && !logging_to_fd) {
sewardj4cf05692002-10-27 20:28:29 +00001535 VG_(message)(Vg_UserMsg, "");
1536 VG_(message)(Vg_UserMsg,
1537 "My PID = %d, parent PID = %d. Prog and args are:",
1538 VG_(getpid)(), VG_(getppid)() );
sewardj5e940782005-09-28 19:59:19 +00001539 if (VG_(args_the_exename))
1540 VG_(message)(Vg_UserMsg, " %s", VG_(args_the_exename));
sewardj45f4e7c2005-09-27 19:20:21 +00001541 for (i = 0; i < VG_(args_for_client).used; i++)
1542 VG_(message)(Vg_UserMsg, " %s", VG_(args_for_client).strs[i]);
sewardj5b742c32005-07-26 23:43:26 +00001543 if (VG_(clo_log_file_qualifier)) {
1544 HChar* val = VG_(getenv)(VG_(clo_log_file_qualifier));
1545 VG_(message)(Vg_UserMsg, "");
1546 VG_(message)(Vg_UserMsg, "Log file qualifier: var %s, value %s.",
1547 VG_(clo_log_file_qualifier),
1548 val ? val : "");
1549 }
sewardj4cf05692002-10-27 20:28:29 +00001550 }
sewardj71bc3cb2005-05-19 00:25:45 +00001551 else
1552 if (VG_(clo_xml)) {
1553 VG_(message)(Vg_UserMsg, "");
1554 VG_(message)(Vg_UserMsg, "<pid>%d</pid>", VG_(getpid)());
1555 VG_(message)(Vg_UserMsg, "<ppid>%d</ppid>", VG_(getppid)());
sewardj97f7e0c2005-07-19 15:00:25 +00001556 VG_(message)(Vg_UserMsg, "<tool>%t</tool>", toolname);
sewardjad311162005-07-19 11:25:02 +00001557 if (VG_(clo_log_file_qualifier)) {
1558 HChar* val = VG_(getenv)(VG_(clo_log_file_qualifier));
sewardj97f7e0c2005-07-19 15:00:25 +00001559 VG_(message)(Vg_UserMsg, "<logfilequalifier> <var>%t</var> "
1560 "<value>%t</value> </logfilequalifier>",
sewardjad311162005-07-19 11:25:02 +00001561 VG_(clo_log_file_qualifier),
1562 val ? val : "");
1563 }
sewardj768db0e2005-07-19 14:18:56 +00001564 if (VG_(clo_xml_user_comment)) {
1565 /* Note: the user comment itself is XML and is therefore to
1566 be passed through verbatim (%s) rather than escaped
1567 (%t). */
1568 VG_(message)(Vg_UserMsg, "<usercomment>%s</usercomment>",
1569 VG_(clo_xml_user_comment));
1570 }
sewardj71bc3cb2005-05-19 00:25:45 +00001571 VG_(message)(Vg_UserMsg, "");
sewardjb8a3dac2005-07-19 12:39:11 +00001572 VG_(message)(Vg_UserMsg, "<args>");
sewardj45f4e7c2005-09-27 19:20:21 +00001573
sewardjb8a3dac2005-07-19 12:39:11 +00001574 VG_(message)(Vg_UserMsg, " <vargv>");
sewardj45f4e7c2005-09-27 19:20:21 +00001575 if (VG_(name_of_launcher))
1576 VG_(message)(Vg_UserMsg, " <exe>%t</exe>",
1577 VG_(name_of_launcher));
1578 for (i = 0; i < VG_(args_for_valgrind).used; i++) {
1579 VG_(message)(Vg_UserMsg,
1580 " <arg>%t</arg>",
1581 VG_(args_for_valgrind).strs[i]);
sewardjb8a3dac2005-07-19 12:39:11 +00001582 }
1583 VG_(message)(Vg_UserMsg, " </vargv>");
sewardj45f4e7c2005-09-27 19:20:21 +00001584
sewardjb8a3dac2005-07-19 12:39:11 +00001585 VG_(message)(Vg_UserMsg, " <argv>");
sewardj45f4e7c2005-09-27 19:20:21 +00001586 if (VG_(args_the_exename))
1587 VG_(message)(Vg_UserMsg, " <exe>%t</exe>",
1588 VG_(args_the_exename));
1589 for (i = 0; i < VG_(args_for_client).used; i++) {
1590 VG_(message)(Vg_UserMsg, " <arg>%t</arg>",
1591 VG_(args_for_client).strs[i]);
sewardj8665d8e2005-06-01 17:35:23 +00001592 }
sewardjb8a3dac2005-07-19 12:39:11 +00001593 VG_(message)(Vg_UserMsg, " </argv>");
sewardj45f4e7c2005-09-27 19:20:21 +00001594
sewardjb8a3dac2005-07-19 12:39:11 +00001595 VG_(message)(Vg_UserMsg, "</args>");
sewardj71bc3cb2005-05-19 00:25:45 +00001596 }
sewardj4cf05692002-10-27 20:28:29 +00001597
sewardj45f4e7c2005-09-27 19:20:21 +00001598 // Empty line after the preamble
1599 if (VG_(clo_verbosity) > 0)
1600 VG_(message)(Vg_UserMsg, "");
1601
sewardjde4a1d02002-03-22 01:27:54 +00001602 if (VG_(clo_verbosity) > 1) {
sewardj92645592005-07-23 09:18:34 +00001603 SysRes fd;
sewardj1f0bbc72005-11-16 03:51:02 +00001604 VexArch vex_arch;
1605 VexArchInfo vex_archinfo;
sewardj45f4e7c2005-09-27 19:20:21 +00001606 if (!logging_to_fd)
njn1fd5eb22005-03-13 05:43:23 +00001607 VG_(message)(Vg_DebugMsg, "");
njn1fd5eb22005-03-13 05:43:23 +00001608 VG_(message)(Vg_DebugMsg, "Command line");
sewardj45f4e7c2005-09-27 19:20:21 +00001609 if (VG_(args_the_exename))
1610 VG_(message)(Vg_DebugMsg, " %s", VG_(args_the_exename));
1611 for (i = 0; i < VG_(args_for_client).used; i++)
1612 VG_(message)(Vg_DebugMsg, " %s", VG_(args_for_client).strs[i]);
njn86dc2bc2003-09-09 07:26:21 +00001613
njn1fd5eb22005-03-13 05:43:23 +00001614 VG_(message)(Vg_DebugMsg, "Startup, with flags:");
sewardj45f4e7c2005-09-27 19:20:21 +00001615 for (i = 0; i < VG_(args_for_valgrind).used; i++) {
1616 VG_(message)(Vg_DebugMsg, " %s", VG_(args_for_valgrind).strs[i]);
sewardjde4a1d02002-03-22 01:27:54 +00001617 }
nethercotea70f7352004-04-18 12:08:46 +00001618
njn1fd5eb22005-03-13 05:43:23 +00001619 VG_(message)(Vg_DebugMsg, "Contents of /proc/version:");
nethercotea70f7352004-04-18 12:08:46 +00001620 fd = VG_(open) ( "/proc/version", VKI_O_RDONLY, 0 );
sewardj92645592005-07-23 09:18:34 +00001621 if (fd.isError) {
njn1fd5eb22005-03-13 05:43:23 +00001622 VG_(message)(Vg_DebugMsg, " can't open /proc/version");
nethercotea70f7352004-04-18 12:08:46 +00001623 } else {
sewardj71bc3cb2005-05-19 00:25:45 +00001624# define BUF_LEN 256
nethercotea70f7352004-04-18 12:08:46 +00001625 Char version_buf[BUF_LEN];
sewardj92645592005-07-23 09:18:34 +00001626 Int n = VG_(read) ( fd.val, version_buf, BUF_LEN );
njnbe9b47b2005-05-15 16:22:58 +00001627 vg_assert(n <= BUF_LEN);
nethercotea70f7352004-04-18 12:08:46 +00001628 if (n > 0) {
1629 version_buf[n-1] = '\0';
njn1fd5eb22005-03-13 05:43:23 +00001630 VG_(message)(Vg_DebugMsg, " %s", version_buf);
nethercotea70f7352004-04-18 12:08:46 +00001631 } else {
njn1fd5eb22005-03-13 05:43:23 +00001632 VG_(message)(Vg_DebugMsg, " (empty?)");
nethercotea70f7352004-04-18 12:08:46 +00001633 }
sewardj92645592005-07-23 09:18:34 +00001634 VG_(close)(fd.val);
sewardj71bc3cb2005-05-19 00:25:45 +00001635# undef BUF_LEN
nethercotea70f7352004-04-18 12:08:46 +00001636 }
sewardj1f0bbc72005-11-16 03:51:02 +00001637
1638 VG_(machine_get_VexArchInfo)( &vex_arch, &vex_archinfo );
1639 VG_(message)(Vg_DebugMsg, "Arch and subarch: %s, %s",
1640 LibVEX_ppVexArch ( vex_arch ),
1641 LibVEX_ppVexSubArch( vex_archinfo.subarch ) );
1642 VG_(message)(Vg_DebugMsg, "Valgrind library directory: %s", VG_(libdir));
sewardjde4a1d02002-03-22 01:27:54 +00001643 }
nethercotef6a1d502004-08-09 12:21:57 +00001644}
1645
sewardjde4a1d02002-03-22 01:27:54 +00001646
nethercote71980f02004-01-24 18:18:54 +00001647/*====================================================================*/
1648/*=== File descriptor setup ===*/
1649/*====================================================================*/
1650
sewardj5f229e22005-09-28 01:36:01 +00001651/* Number of file descriptors that Valgrind tries to reserve for
1652 it's own use - just a small constant. */
1653#define N_RESERVED_FDS (10)
1654
nethercote71980f02004-01-24 18:18:54 +00001655static void setup_file_descriptors(void)
1656{
1657 struct vki_rlimit rl;
1658
1659 /* Get the current file descriptor limits. */
1660 if (VG_(getrlimit)(VKI_RLIMIT_NOFILE, &rl) < 0) {
1661 rl.rlim_cur = 1024;
1662 rl.rlim_max = 1024;
1663 }
1664
1665 /* Work out where to move the soft limit to. */
njn14319cc2005-03-13 06:26:22 +00001666 if (rl.rlim_cur + N_RESERVED_FDS <= rl.rlim_max) {
1667 rl.rlim_cur = rl.rlim_cur + N_RESERVED_FDS;
nethercote71980f02004-01-24 18:18:54 +00001668 } else {
1669 rl.rlim_cur = rl.rlim_max;
1670 }
1671
1672 /* Reserve some file descriptors for our use. */
njn14319cc2005-03-13 06:26:22 +00001673 VG_(fd_soft_limit) = rl.rlim_cur - N_RESERVED_FDS;
1674 VG_(fd_hard_limit) = rl.rlim_cur - N_RESERVED_FDS;
nethercote71980f02004-01-24 18:18:54 +00001675
1676 /* Update the soft limit. */
1677 VG_(setrlimit)(VKI_RLIMIT_NOFILE, &rl);
1678
sewardj45f4e7c2005-09-27 19:20:21 +00001679 if (VG_(cl_exec_fd) != -1)
1680 VG_(cl_exec_fd) = VG_(safe_fd)( VG_(cl_exec_fd) );
nethercote71980f02004-01-24 18:18:54 +00001681}
1682
sewardjde4a1d02002-03-22 01:27:54 +00001683
njn2da73352005-06-18 01:35:16 +00001684/*====================================================================*/
1685/*=== Initialise the first thread. ===*/
1686/*====================================================================*/
1687
1688/* Given a pointer to the ThreadArchState for thread 1 (the root
1689 thread), initialise the VEX guest state, and copy in essential
1690 starting values.
1691*/
1692static void init_thread1state ( Addr client_ip,
sewardjfdf91b42005-09-28 00:53:09 +00001693 Addr client_sp,
njn2da73352005-06-18 01:35:16 +00001694 /*inout*/ ThreadArchState* arch )
1695{
1696#if defined(VGA_x86)
1697 vg_assert(0 == sizeof(VexGuestX86State) % 8);
1698
1699 /* Zero out the initial state, and set up the simulated FPU in a
1700 sane way. */
1701 LibVEX_GuestX86_initialise(&arch->vex);
1702
1703 /* Zero out the shadow area. */
1704 VG_(memset)(&arch->vex_shadow, 0, sizeof(VexGuestX86State));
1705
1706 /* Put essential stuff into the new state. */
sewardjfdf91b42005-09-28 00:53:09 +00001707 arch->vex.guest_ESP = client_sp;
njn2da73352005-06-18 01:35:16 +00001708 arch->vex.guest_EIP = client_ip;
1709
1710 /* initialise %cs, %ds and %ss to point at the operating systems
1711 default code, data and stack segments */
1712 asm volatile("movw %%cs, %0" : : "m" (arch->vex.guest_CS));
1713 asm volatile("movw %%ds, %0" : : "m" (arch->vex.guest_DS));
1714 asm volatile("movw %%ss, %0" : : "m" (arch->vex.guest_SS));
cerion85665ca2005-06-20 15:51:07 +00001715
njn2da73352005-06-18 01:35:16 +00001716#elif defined(VGA_amd64)
1717 vg_assert(0 == sizeof(VexGuestAMD64State) % 8);
1718
1719 /* Zero out the initial state, and set up the simulated FPU in a
1720 sane way. */
1721 LibVEX_GuestAMD64_initialise(&arch->vex);
1722
1723 /* Zero out the shadow area. */
1724 VG_(memset)(&arch->vex_shadow, 0, sizeof(VexGuestAMD64State));
1725
1726 /* Put essential stuff into the new state. */
sewardjfdf91b42005-09-28 00:53:09 +00001727 arch->vex.guest_RSP = client_sp;
njn2da73352005-06-18 01:35:16 +00001728 arch->vex.guest_RIP = client_ip;
cerion85665ca2005-06-20 15:51:07 +00001729
1730#elif defined(VGA_ppc32)
1731 vg_assert(0 == sizeof(VexGuestPPC32State) % 8);
1732
1733 /* Zero out the initial state, and set up the simulated FPU in a
1734 sane way. */
1735 LibVEX_GuestPPC32_initialise(&arch->vex);
1736
1737 /* Zero out the shadow area. */
1738 VG_(memset)(&arch->vex_shadow, 0, sizeof(VexGuestPPC32State));
1739
1740 /* Put essential stuff into the new state. */
sewardjfdf91b42005-09-28 00:53:09 +00001741 arch->vex.guest_GPR1 = client_sp;
cerion85665ca2005-06-20 15:51:07 +00001742 arch->vex.guest_CIA = client_ip;
1743
njn2da73352005-06-18 01:35:16 +00001744#else
1745# error Unknown arch
1746#endif
1747 // Tell the tool that we just wrote to the registers.
1748 VG_TRACK( post_reg_write, Vg_CoreStartup, /*tid*/1, /*offset*/0,
1749 sizeof(VexGuestArchState));
1750}
1751
sewardjde4a1d02002-03-22 01:27:54 +00001752
nethercote71980f02004-01-24 18:18:54 +00001753/*====================================================================*/
njn2025cf92005-06-26 20:44:48 +00001754/*=== BB profiling ===*/
1755/*====================================================================*/
1756
1757static
1758void show_BB_profile ( BBProfEntry tops[], UInt n_tops, ULong score_total )
1759{
1760 ULong score_cumul, score_here;
1761 Char buf_cumul[10], buf_here[10];
1762 Char name[64];
1763 Int r;
1764
1765 VG_(printf)("\n");
1766 VG_(printf)("-----------------------------------------------------------\n");
1767 VG_(printf)("--- BEGIN BB Profile (summary of scores) ---\n");
1768 VG_(printf)("-----------------------------------------------------------\n");
1769 VG_(printf)("\n");
1770
1771 VG_(printf)("Total score = %lld\n\n", score_total);
1772
1773 score_cumul = 0;
1774 for (r = 0; r < n_tops; r++) {
1775 if (tops[r].addr == 0)
1776 continue;
1777 name[0] = 0;
1778 VG_(get_fnname_w_offset)(tops[r].addr, name, 64);
1779 name[63] = 0;
1780 score_here = tops[r].score;
1781 score_cumul += score_here;
1782 VG_(percentify)(score_cumul, score_total, 2, 6, buf_cumul);
1783 VG_(percentify)(score_here, score_total, 2, 6, buf_here);
1784 VG_(printf)("%3d: (%9lld %s) %9lld %s 0x%llx %s\n",
1785 r,
1786 score_cumul, buf_cumul,
1787 score_here, buf_here, tops[r].addr, name );
1788 }
1789
1790 VG_(printf)("\n");
1791 VG_(printf)("-----------------------------------------------------------\n");
1792 VG_(printf)("--- BB Profile (BB details) ---\n");
1793 VG_(printf)("-----------------------------------------------------------\n");
1794 VG_(printf)("\n");
1795
1796 score_cumul = 0;
1797 for (r = 0; r < n_tops; r++) {
1798 if (tops[r].addr == 0)
1799 continue;
1800 name[0] = 0;
1801 VG_(get_fnname_w_offset)(tops[r].addr, name, 64);
1802 name[63] = 0;
1803 score_here = tops[r].score;
1804 score_cumul += score_here;
1805 VG_(percentify)(score_cumul, score_total, 2, 6, buf_cumul);
1806 VG_(percentify)(score_here, score_total, 2, 6, buf_here);
1807 VG_(printf)("\n");
1808 VG_(printf)("=-=-=-=-=-=-=-=-=-=-=-=-=-= begin BB rank %d "
1809 "=-=-=-=-=-=-=-=-=-=-=-=-=-=\n\n", r);
1810 VG_(printf)("%3d: (%9lld %s) %9lld %s 0x%llx %s\n",
1811 r,
1812 score_cumul, buf_cumul,
1813 score_here, buf_here, tops[r].addr, name );
1814 VG_(printf)("\n");
1815 VG_(translate)(0, tops[r].addr, True, VG_(clo_profile_flags), 0);
1816 VG_(printf)("=-=-=-=-=-=-=-=-=-=-=-=-=-= end BB rank %d "
1817 "=-=-=-=-=-=-=-=-=-=-=-=-=-=\n\n", r);
1818 }
1819
1820 VG_(printf)("\n");
1821 VG_(printf)("-----------------------------------------------------------\n");
1822 VG_(printf)("--- END BB Profile ---\n");
1823 VG_(printf)("-----------------------------------------------------------\n");
1824 VG_(printf)("\n");
1825}
1826
1827
1828/*====================================================================*/
nethercote71980f02004-01-24 18:18:54 +00001829/*=== main() ===*/
1830/*====================================================================*/
1831
sewardjfdf91b42005-09-28 00:53:09 +00001832/* When main() is entered, we should be on the following stack, not
1833 the one the kernel gave us. We will run on this stack until
1834 simulation of the root thread is started, at which point a transfer
1835 is made to a dynamically allocated stack. This is for the sake of
1836 uniform overflow detection for all Valgrind threads. This is
1837 marked global even though it isn't, because assembly code below
1838 needs to reference the name. */
1839
1840/*static*/ VgStack VG_(interim_stack);
1841
1842/* This should get some address inside the stack on which we gained
1843 control (eg, it could be the SP at startup). It doesn't matter
1844 exactly where in the stack it is. This value is passed to the
1845 address space manager at startup, which uses it to identify the
1846 initial stack segment and hence the upper end of the usable address
1847 space. */
1848
1849static Addr sp_at_startup = 0;
1850
sewardj1ae3f3a2005-09-28 10:47:38 +00001851/* --- Forwards decls to do with shutdown --- */
1852
1853static void final_tidyup(ThreadId tid);
1854
1855/* Do everything which needs doing when the last thread exits */
1856static
1857void shutdown_actions_NORETURN( ThreadId tid,
1858 VgSchedReturnCode tids_schedretcode );
1859
1860/* --- end of Forwards decls to do with shutdown --- */
sewardjfdf91b42005-09-28 00:53:09 +00001861
1862
sewardj45f4e7c2005-09-27 19:20:21 +00001863/* TODO: GIVE THIS A PROPER HOME
1864 TODO: MERGE THIS WITH DUPLICATE IN mac_leakcheck.c
1865 Extract from aspacem a vector of the current segment start
1866 addresses. The vector is dynamically allocated and should be freed
1867 by the caller when done. REQUIRES m_mallocfree to be running.
1868 Writes the number of addresses required into *n_acquired. */
nethercotec314eba2004-07-15 12:59:41 +00001869
sewardj45f4e7c2005-09-27 19:20:21 +00001870static Addr* get_seg_starts ( /*OUT*/Int* n_acquired )
sewardj1cf558c2005-04-25 01:36:56 +00001871{
sewardj45f4e7c2005-09-27 19:20:21 +00001872 Addr* starts;
sewardja48a4932005-09-29 11:09:56 +00001873 Int n_starts, r = 0;
sewardj45f4e7c2005-09-27 19:20:21 +00001874
1875 n_starts = 1;
sewardj1cf558c2005-04-25 01:36:56 +00001876 while (True) {
sewardj45f4e7c2005-09-27 19:20:21 +00001877 starts = VG_(malloc)( n_starts * sizeof(Addr) );
1878 if (starts == NULL)
1879 break;
1880 r = VG_(am_get_segment_starts)( starts, n_starts );
1881 if (r >= 0)
1882 break;
1883 VG_(free)(starts);
1884 n_starts *= 2;
sewardj1cf558c2005-04-25 01:36:56 +00001885 }
sewardj45f4e7c2005-09-27 19:20:21 +00001886
1887 if (starts == NULL) {
1888 *n_acquired = 0;
1889 return NULL;
1890 }
1891
1892 *n_acquired = r;
1893 return starts;
sewardj1cf558c2005-04-25 01:36:56 +00001894}
1895
1896
sewardj45f4e7c2005-09-27 19:20:21 +00001897
sewardj45f4e7c2005-09-27 19:20:21 +00001898Int main(Int argc, HChar **argv, HChar **envp)
nethercote71980f02004-01-24 18:18:54 +00001899{
sewardj45f4e7c2005-09-27 19:20:21 +00001900 HChar* toolname = "memcheck"; // default to Memcheck
1901 HChar** env = NULL;
1902 Int need_help = 0; // 0 = no, 1 = --help, 2 = --help-debug
1903 Addr initial_client_IP = 0;
1904 Addr initial_client_SP = 0;
1905 Addr clstack_top = 0;
1906 SizeT clstack_max_size = 0;
1907 UInt* client_auxv;
1908 Int loglevel, i;
1909 Bool logging_to_fd;
nethercote73b526f2004-10-31 18:48:21 +00001910 struct vki_rlimit zero = { 0, 0 };
sewardj45f4e7c2005-09-27 19:20:21 +00001911 struct exeinfo info;
nethercote71980f02004-01-24 18:18:54 +00001912
1913 //============================================================
nethercote71980f02004-01-24 18:18:54 +00001914 //
sewardj45f4e7c2005-09-27 19:20:21 +00001915 // Nb: startup is complex. Prerequisites are shown at every step.
nethercote71980f02004-01-24 18:18:54 +00001916 // *** Be very careful when messing with the order ***
sewardj45f4e7c2005-09-27 19:20:21 +00001917 //
1918 // The first order of business is to get debug logging, the address
1919 // space manager and the dynamic memory manager up and running.
1920 // Once that's done, we can relax a bit.
1921 //
nethercote71980f02004-01-24 18:18:54 +00001922 //============================================================
sewardj45f4e7c2005-09-27 19:20:21 +00001923
1924 /* This is needed to make VG_(getenv) usable early. */
1925 VG_(client_envp) = (Char**)envp;
nethercote71980f02004-01-24 18:18:54 +00001926
sewardj1cf558c2005-04-25 01:36:56 +00001927 //--------------------------------------------------------------
1928 // Start up the logging mechanism
1929 // p: none
1930 //--------------------------------------------------------------
1931 /* Start the debugging-log system ASAP. First find out how many
1932 "-d"s were specified. This is a pre-scan of the command line. */
1933 loglevel = 0;
1934 for (i = 1; i < argc; i++) {
sewardj10759312005-05-30 23:52:47 +00001935 if (argv[i][0] != '-')
1936 break;
sewardj45f4e7c2005-09-27 19:20:21 +00001937 if (VG_STREQ(argv[i], "--"))
sewardj10759312005-05-30 23:52:47 +00001938 break;
sewardj45f4e7c2005-09-27 19:20:21 +00001939 if (VG_STREQ(argv[i], "-d"))
sewardj10759312005-05-30 23:52:47 +00001940 loglevel++;
sewardj1cf558c2005-04-25 01:36:56 +00001941 }
1942
1943 /* ... and start the debug logger. Now we can safely emit logging
1944 messages all through startup. */
sewardj10759312005-05-30 23:52:47 +00001945 VG_(debugLog_startup)(loglevel, "Stage 2 (main)");
sewardj45f4e7c2005-09-27 19:20:21 +00001946 VG_(debugLog)(1, "main", "Welcome to Valgrind version "
1947 VERSION " debug logging\n");
1948
1949 //--------------------------------------------------------------
1950 // Ensure we're on a plausible stack.
1951 // p: logging
1952 //--------------------------------------------------------------
1953 VG_(debugLog)(1, "main", "Checking current stack is plausible\n");
sewardjfdf91b42005-09-28 00:53:09 +00001954 { HChar* limLo = (HChar*)(&VG_(interim_stack).bytes[0]);
1955 HChar* limHi = limLo + sizeof(VG_(interim_stack));
sewardj45f4e7c2005-09-27 19:20:21 +00001956 HChar* aLocal = (HChar*)&zero; /* any auto local will do */
1957 if (aLocal < limLo || aLocal >= limHi) {
1958 /* something's wrong. Stop. */
1959 VG_(debugLog)(0, "main", "Root stack %p to %p, a local %p\n",
1960 limLo, limHi, aLocal );
1961 VG_(debugLog)(0, "main", "Valgrind: FATAL: "
1962 "Initial stack switched failed.\n");
1963 VG_(debugLog)(0, "main", " Cannot continue. Sorry.\n");
1964 VG_(exit)(1);
1965 }
1966 }
1967
1968 //--------------------------------------------------------------
1969 // Ensure we have a plausible pointer to the stack on which
1970 // we gained control (not the current stack!)
1971 // p: logging
1972 //--------------------------------------------------------------
1973 VG_(debugLog)(1, "main", "Checking initial stack was noted\n");
sewardjfdf91b42005-09-28 00:53:09 +00001974 if (sp_at_startup == 0) {
sewardj45f4e7c2005-09-27 19:20:21 +00001975 VG_(debugLog)(0, "main", "Valgrind: FATAL: "
1976 "Initial stack was not noted.\n");
1977 VG_(debugLog)(0, "main", " Cannot continue. Sorry.\n");
1978 VG_(exit)(1);
1979 }
1980
1981 //--------------------------------------------------------------
1982 // Start up the address space manager, and determine the
1983 // approximate location of the client's stack
1984 // p: logging, plausible-stack
1985 //--------------------------------------------------------------
1986 VG_(debugLog)(1, "main", "Starting the address space manager\n");
sewardjfdf91b42005-09-28 00:53:09 +00001987 clstack_top = VG_(am_startup)( sp_at_startup );
sewardj45f4e7c2005-09-27 19:20:21 +00001988 VG_(debugLog)(1, "main", "Address space manager is running\n");
1989
1990 //--------------------------------------------------------------
1991 // Start up the dynamic memory manager
1992 // p: address space management
1993 // In fact m_mallocfree is self-initialising, so there's no
1994 // initialisation call to do. Instead, try a simple malloc/
1995 // free pair right now to check that nothing is broken.
1996 //--------------------------------------------------------------
1997 VG_(debugLog)(1, "main", "Starting the dynamic memory manager\n");
1998 { void* p = VG_(malloc)( 12345 );
1999 if (p) VG_(free)( p );
2000 }
2001 VG_(debugLog)(1, "main", "Dynamic memory manager is running\n");
sewardj1cf558c2005-04-25 01:36:56 +00002002
nethercotef4928da2004-06-15 10:54:40 +00002003 //============================================================
sewardj45f4e7c2005-09-27 19:20:21 +00002004 //
2005 // Dynamic memory management is now available.
2006 //
nethercotef4928da2004-06-15 10:54:40 +00002007 //============================================================
2008
sewardj45f4e7c2005-09-27 19:20:21 +00002009 //--------------------------------------------------------------
2010 // Look for alternative libdir
2011 { HChar *cp = VG_(getenv)(VALGRIND_LIB);
2012 if (cp != NULL)
2013 VG_(libdir) = cp;
2014 }
2015
2016 //--------------------------------------------------------------
2017 // Extract the launcher name from the environment.
2018 VG_(debugLog)(1, "main", "Getting stage1's name\n");
2019 VG_(name_of_launcher) = VG_(getenv)(VALGRIND_LAUNCHER);
2020 if (VG_(name_of_launcher) == NULL) {
2021 VG_(printf)("valgrind: You cannot run '%s' directly.\n", argv[0]);
2022 VG_(printf)("valgrind: You should use $prefix/bin/valgrind.\n");
2023 VG_(exit)(1);
2024 }
2025
2026 //--------------------------------------------------------------
fitzhardingeb50068f2004-02-24 23:42:55 +00002027 // Get the current process datasize rlimit, and set it to zero.
2028 // This prevents any internal uses of brk() from having any effect.
2029 // We remember the old value so we can restore it on exec, so that
2030 // child processes will have a reasonable brk value.
2031 VG_(getrlimit)(VKI_RLIMIT_DATA, &VG_(client_rlimit_data));
2032 zero.rlim_max = VG_(client_rlimit_data).rlim_max;
2033 VG_(setrlimit)(VKI_RLIMIT_DATA, &zero);
thughesc37184f2004-09-11 14:16:57 +00002034
2035 // Get the current process stack rlimit.
2036 VG_(getrlimit)(VKI_RLIMIT_STACK, &VG_(client_rlimit_stack));
2037
sewardje2d1e672005-11-12 23:10:48 +00002038 //--------------------------------------------------------------
2039 // Figure out what sort of CPU we're on, and whether it is
2040 // able to run V.
2041 VG_(debugLog)(1, "main", "Get hardware capabilities ...\n");
2042 { VexArch vex_arch;
2043 VexArchInfo vex_archinfo;
2044 Bool ok = VG_(machine_get_hwcaps)();
2045 if (!ok) {
2046 VG_(printf)("\n");
2047 VG_(printf)("valgrind: fatal error: unsupported CPU.\n");
2048 VG_(printf)(" Supported CPUs are:\n");
2049 VG_(printf)(" * x86 (practically any; Pentium-I or above), "
2050 "AMD Athlon or above)\n");
2051 VG_(printf)(" * AMD Athlon64/Opteron\n");
2052 VG_(printf)(" * PowerPC (most; ppc405 and above)\n");
2053 VG_(printf)("\n");
2054 VG_(exit)(1);
2055 }
2056 VG_(machine_get_VexArchInfo)( &vex_arch, &vex_archinfo );
2057 VG_(debugLog)(1, "main", "... arch = %s, subarch = %s\n",
2058 LibVEX_ppVexArch ( vex_arch ),
2059 LibVEX_ppVexSubArch( vex_archinfo.subarch ) );
2060 }
2061
sewardj45f4e7c2005-09-27 19:20:21 +00002062 //============================================================
2063 // Command line argument handling order:
2064 // * If --help/--help-debug are present, show usage message
2065 // (including the tool-specific usage)
2066 // * (If no --tool option given, default to Memcheck)
2067 // * Then, if client is missing, abort with error msg
2068 // * Then, if any cmdline args are bad, abort with error msg
2069 //============================================================
2070
2071 //--------------------------------------------------------------
2072 // Split up argv into: C args, V args, V extra args, and exename.
2073 // p: dynamic memory allocation
2074 //--------------------------------------------------------------
2075 VG_(debugLog)(1, "main", "Split up command line\n");
2076 VG_(split_up_argv)( argc, argv );
2077 if (0) {
2078 for (i = 0; i < VG_(args_for_valgrind).used; i++)
2079 VG_(printf)("varg %s\n", VG_(args_for_valgrind).strs[i]);
2080 VG_(printf)(" exe %s\n", VG_(args_the_exename));
2081 for (i = 0; i < VG_(args_for_client).used; i++)
2082 VG_(printf)("carg %s\n", VG_(args_for_client).strs[i]);
nethercote71980f02004-01-24 18:18:54 +00002083 }
2084
2085 //--------------------------------------------------------------
sewardj45f4e7c2005-09-27 19:20:21 +00002086 // Extract tool name and whether help has been requested.
2087 // Note we can't print the help message yet, even if requested,
2088 // because the tool has not been initialised.
2089 // p: split_up_argv [for VG_(args_for_valgrind)]
nethercote71980f02004-01-24 18:18:54 +00002090 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002091 VG_(debugLog)(1, "main", "Preprocess command line opts\n");
sewardj45f4e7c2005-09-27 19:20:21 +00002092 get_helprequest_and_toolname(&need_help, &toolname);
nethercote71980f02004-01-24 18:18:54 +00002093
sewardj45f4e7c2005-09-27 19:20:21 +00002094 // Set default vex control params
2095 LibVEX_default_VexControl(& VG_(clo_vex_control));
nethercote71980f02004-01-24 18:18:54 +00002096
2097 //--------------------------------------------------------------
2098 // Load client executable, finding in $PATH if necessary
sewardj45f4e7c2005-09-27 19:20:21 +00002099 // p: get_helprequest_and_toolname() [for 'exec', 'need_help']
nethercote71980f02004-01-24 18:18:54 +00002100 // p: layout_remaining_space [so there's space]
2101 //--------------------------------------------------------------
sewardj45f4e7c2005-09-27 19:20:21 +00002102 if (!need_help) {
2103 VG_(debugLog)(1, "main", "Loading client\n");
nethercote71980f02004-01-24 18:18:54 +00002104
sewardj45f4e7c2005-09-27 19:20:21 +00002105 if (VG_(args_the_exename) == NULL)
2106 missing_prog();
2107
2108 load_client(&info, &initial_client_IP);
2109 }
nethercote71980f02004-01-24 18:18:54 +00002110
2111 //--------------------------------------------------------------
2112 // Set up client's environment
sewardj45f4e7c2005-09-27 19:20:21 +00002113 // p: set-libdir [for VG_(libdir)]
2114 // p: get_helprequest_and_toolname [for toolname]
nethercote71980f02004-01-24 18:18:54 +00002115 //--------------------------------------------------------------
sewardj45f4e7c2005-09-27 19:20:21 +00002116 if (!need_help) {
2117 VG_(debugLog)(1, "main", "Setup client env\n");
2118 env = setup_client_env(envp, toolname);
2119 }
nethercote71980f02004-01-24 18:18:54 +00002120
2121 //--------------------------------------------------------------
nethercote5ee67ca2004-06-22 14:00:09 +00002122 // Setup client stack, eip, and VG_(client_arg[cv])
nethercote71980f02004-01-24 18:18:54 +00002123 // p: load_client() [for 'info']
2124 // p: fix_environment() [for 'env']
2125 //--------------------------------------------------------------
sewardj45f4e7c2005-09-27 19:20:21 +00002126 if (!need_help) {
2127 void* init_sp = argv - 1;
2128 SizeT m1 = 1024 * 1024;
2129 SizeT m8 = 8 * m1;
2130 VG_(debugLog)(1, "main", "Setup client stack\n");
2131 clstack_max_size = (SizeT)VG_(client_rlimit_stack).rlim_cur;
2132 if (clstack_max_size < m1) clstack_max_size = m1;
2133 if (clstack_max_size > m8) clstack_max_size = m8;
2134 clstack_max_size = VG_PGROUNDUP(clstack_max_size);
sewardjb5f6f512005-03-10 23:59:00 +00002135
sewardj45f4e7c2005-09-27 19:20:21 +00002136 initial_client_SP
2137 = setup_client_stack( init_sp, env,
2138 &info, &client_auxv,
2139 clstack_top, clstack_max_size );
2140
2141 VG_(free)(env);
2142
2143 VG_(debugLog)(2, "main",
2144 "Client info: "
sewardja48a4932005-09-29 11:09:56 +00002145 "initial_IP=%p initial_SP=%p brk_base=%p\n",
sewardj45f4e7c2005-09-27 19:20:21 +00002146 (void*)initial_client_IP,
2147 (void*)initial_client_SP,
2148 (void*)VG_(brk_base) );
nethercotec25c4492004-10-18 11:52:17 +00002149 }
nethercote71980f02004-01-24 18:18:54 +00002150
sewardj45f4e7c2005-09-27 19:20:21 +00002151 //--------------------------------------------------------------
2152 // Setup client data (brk) segment. Initially a 1-page segment
2153 // which abuts a shrinkable reservation.
2154 // p: load_client() [for 'info' and hence VG_(brk_base)]
2155 //--------------------------------------------------------------
2156 if (!need_help) {
2157 SizeT m1 = 1024 * 1024;
2158 SizeT m8 = 8 * m1;
2159 SizeT dseg_max_size = (SizeT)VG_(client_rlimit_data).rlim_cur;
2160 VG_(debugLog)(1, "main", "Setup client data (brk) segment\n");
2161 if (dseg_max_size < m1) dseg_max_size = m1;
2162 if (dseg_max_size > m8) dseg_max_size = m8;
2163 dseg_max_size = VG_PGROUNDUP(dseg_max_size);
2164
2165 setup_client_dataseg( dseg_max_size );
2166 }
nethercote71980f02004-01-24 18:18:54 +00002167
2168 //==============================================================
sewardj45f4e7c2005-09-27 19:20:21 +00002169 //
2170 // Finished loading/setting up the client address space.
2171 //
nethercote71980f02004-01-24 18:18:54 +00002172 //==============================================================
2173
2174 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002175 // setup file descriptors
2176 // p: n/a
2177 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002178 VG_(debugLog)(1, "main", "Setup file descriptors\n");
nethercote71980f02004-01-24 18:18:54 +00002179 setup_file_descriptors();
2180
2181 //--------------------------------------------------------------
sewardj45f4e7c2005-09-27 19:20:21 +00002182 // create the fake /proc/<pid>/cmdline file and then unlink it,
2183 // but hold onto the fd, so we can hand it out to the client
2184 // when it tries to open /proc/<pid>/cmdline for itself.
2185 // p: setup file descriptors
nethercotec314eba2004-07-15 12:59:41 +00002186 //--------------------------------------------------------------
sewardj45f4e7c2005-09-27 19:20:21 +00002187 if (!need_help) {
2188 HChar buf[50], buf2[50+64];
2189 HChar nul[1];
2190 Int fd, r;
2191 HChar* exename;
nethercotec314eba2004-07-15 12:59:41 +00002192
sewardj45f4e7c2005-09-27 19:20:21 +00002193 VG_(debugLog)(1, "main", "Create fake /proc/<pid>/cmdline\n");
2194
2195 VG_(sprintf)(buf, "proc_%d_cmdline", VG_(getpid)());
2196 fd = VG_(mkstemp)( buf, buf2 );
2197 if (fd == -1)
2198 config_error("Can't create client cmdline file in /tmp.");
2199
2200 nul[0] = 0;
2201 exename = VG_(args_the_exename) ? VG_(args_the_exename)
2202 : "unknown_exename";
2203
2204 VG_(write)(fd, VG_(args_the_exename),
2205 VG_(strlen)( VG_(args_the_exename) ));
2206 VG_(write)(fd, nul, 1);
2207
2208 for (i = 0; i < VG_(args_for_client).used; i++) {
2209 VG_(write)(fd, VG_(args_for_client).strs[i],
2210 VG_(strlen)( VG_(args_for_client).strs[i] ));
2211 VG_(write)(fd, nul, 1);
2212 }
2213
2214 /* Don't bother to seek the file back to the start; instead do
2215 it every time a copy of it is given out (by PRE(sys_open)).
2216 That is probably more robust across fork() etc. */
2217
2218 /* Now delete it, but hang on to the fd. */
2219 r = VG_(unlink)( buf2 );
2220 if (r)
2221 config_error("Can't delete client cmdline file in /tmp.");
2222
2223 VG_(cl_cmdline_fd) = fd;
2224 }
nethercotec314eba2004-07-15 12:59:41 +00002225
2226 //--------------------------------------------------------------
sewardj45f4e7c2005-09-27 19:20:21 +00002227 // Init tool part 1: pre_clo_init
nethercotec314eba2004-07-15 12:59:41 +00002228 // p: setup_client_stack() [for 'VG_(client_arg[cv]']
nethercotec314eba2004-07-15 12:59:41 +00002229 // p: setup_file_descriptors() [for 'VG_(fd_xxx_limit)']
nethercote71980f02004-01-24 18:18:54 +00002230 //--------------------------------------------------------------
njn64c83242005-06-21 01:54:38 +00002231 {
2232 Char* s;
2233 Bool ok;
sewardj45f4e7c2005-09-27 19:20:21 +00002234 VG_(debugLog)(1, "main", "Initialise the tool part 1 (pre_clo_init)\n");
2235 (VG_(tool_info).tl_pre_clo_init)();
2236 ok = VG_(sanity_check_needs)( &s );
njn64c83242005-06-21 01:54:38 +00002237 if (!ok) {
2238 VG_(tool_panic)(s);
2239 }
2240 }
nethercote71980f02004-01-24 18:18:54 +00002241
sewardj45f4e7c2005-09-27 19:20:21 +00002242 //--------------------------------------------------------------
nethercotef4928da2004-06-15 10:54:40 +00002243 // If --tool and --help/--help-debug was given, now give the core+tool
2244 // help message
sewardj45f4e7c2005-09-27 19:20:21 +00002245 // p: get_helprequest_and_toolname() [for 'need_help']
2246 // p: tl_pre_clo_init [for 'VG_(tdict).usage']
2247 //--------------------------------------------------------------
2248 VG_(debugLog)(1, "main", "Print help and quit, if requested\n");
nethercotef4928da2004-06-15 10:54:40 +00002249 if (need_help) {
sewardj45f4e7c2005-09-27 19:20:21 +00002250 usage_NORETURN(/*--help-debug?*/2 == need_help);
nethercotef4928da2004-06-15 10:54:40 +00002251 }
nethercotec314eba2004-07-15 12:59:41 +00002252
sewardj45f4e7c2005-09-27 19:20:21 +00002253 //--------------------------------------------------------------
2254 // Process command line options to Valgrind + tool
2255 // p: setup_client_stack() [for 'VG_(client_arg[cv]']
2256 // p: setup_file_descriptors() [for 'VG_(fd_xxx_limit)']
2257 //--------------------------------------------------------------
2258 VG_(debugLog)(1, "main", "Process Valgrind's command line options, "
sewardja48a4932005-09-29 11:09:56 +00002259 "setup logging\n");
sewardj45f4e7c2005-09-27 19:20:21 +00002260 logging_to_fd = process_cmd_line_options(client_auxv, toolname);
2261
2262 //--------------------------------------------------------------
sewardj592ae092005-11-08 19:01:44 +00002263 // Zeroise the millisecond counter by doing a first read of it.
2264 // p: none
2265 //--------------------------------------------------------------
2266 (void) VG_(read_millisecond_timer)();
2267
2268 //--------------------------------------------------------------
sewardj45f4e7c2005-09-27 19:20:21 +00002269 // Print the preamble
2270 // p: tl_pre_clo_init [for 'VG_(details).name' and friends]
2271 // p: process_cmd_line_options() [for VG_(clo_verbosity), VG_(clo_xml),
2272 // VG_(clo_log_file_qualifier),
2273 // logging_to_fd]
2274 //--------------------------------------------------------------
2275 VG_(debugLog)(1, "main", "Print the preamble...\n");
2276 print_preamble(logging_to_fd, toolname);
2277 VG_(debugLog)(1, "main", "...finished the preamble\n");
2278
2279 //--------------------------------------------------------------
2280 // Init tool part 2: post_clo_init
2281 // p: setup_client_stack() [for 'VG_(client_arg[cv]']
2282 // p: setup_file_descriptors() [for 'VG_(fd_xxx_limit)']
2283 // p: print_preamble() [so any warnings printed in post_clo_init
2284 // are shown after the preamble]
2285 //--------------------------------------------------------------
2286 VG_(debugLog)(1, "main", "Initialise the tool part 2 (post_clo_init)\n");
njn51d827b2005-05-09 01:02:08 +00002287 VG_TDICT_CALL(tool_post_clo_init);
nethercotef4928da2004-06-15 10:54:40 +00002288
2289 //--------------------------------------------------------------
sewardj45f4e7c2005-09-27 19:20:21 +00002290 // Initialise translation table and translation cache
2291 // p: aspacem [??]
2292 // p: tl_pre_clo_init [for 'VG_(details).avg_translation_sizeB']
nethercote71980f02004-01-24 18:18:54 +00002293 //--------------------------------------------------------------
sewardj45f4e7c2005-09-27 19:20:21 +00002294 VG_(debugLog)(1, "main", "Initialise TT/TC\n");
2295 VG_(init_tt_tc)();
sewardjb5f6f512005-03-10 23:59:00 +00002296
sewardj45f4e7c2005-09-27 19:20:21 +00002297 //--------------------------------------------------------------
2298 // Initialise the redirect table.
2299 // p: init_tt_tc [so it can call VG_(search_transtab) safely]
2300 // p: aspacem [so can change ownership of sysinfo pages]
2301 //--------------------------------------------------------------
2302 VG_(debugLog)(1, "main", "Initialise redirects\n");
2303 VG_(setup_code_redirect_table)();
nethercote71980f02004-01-24 18:18:54 +00002304
2305 //--------------------------------------------------------------
2306 // Allow GDB attach
2307 // p: process_cmd_line_options() [for VG_(clo_wait_for_gdb)]
2308 //--------------------------------------------------------------
2309 /* Hook to delay things long enough so we can get the pid and
2310 attach GDB in another shell. */
2311 if (VG_(clo_wait_for_gdb)) {
sewardj8211a572005-06-23 21:37:47 +00002312 Long q, iters;
sewardj1fbc1a52005-04-25 02:05:54 +00002313 VG_(debugLog)(1, "main", "Wait for GDB\n");
sewardj93ab8572005-02-06 14:10:40 +00002314 VG_(printf)("pid=%d, entering delay loop\n", VG_(getpid)());
2315 /* jrs 20050206: I don't understand why this works on x86. On
2316 amd64 the obvious analogues (jump *$rip or jump *$rcx) don't
2317 work. */
2318 /* do "jump *$eip" to skip this in gdb (x86) */
2319 //VG_(do_syscall0)(__NR_pause);
sewardj8211a572005-06-23 21:37:47 +00002320
2321# if defined(VGP_x86_linux)
2322 iters = 5;
2323# elif defined(VGP_amd64_linux)
2324 iters = 10;
2325# elif defined(VGP_ppc32_linux)
sewardjd714d2e2005-07-08 18:24:04 +00002326 iters = 5;
sewardj8211a572005-06-23 21:37:47 +00002327# else
2328# error "Unknown plat"
2329# endif
2330
2331 iters *= 1000*1000*1000;
2332 for (q = 0; q < iters; q++)
2333 ;
nethercote71980f02004-01-24 18:18:54 +00002334 }
2335
sewardjb5d320c2005-03-13 18:57:15 +00002336 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002337 // Search for file descriptors that are inherited from our parent
2338 // p: process_cmd_line_options [for VG_(clo_track_fds)]
2339 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002340 if (VG_(clo_track_fds)) {
2341 VG_(debugLog)(1, "main", "Init preopened fds\n");
nethercote71980f02004-01-24 18:18:54 +00002342 VG_(init_preopened_fds)();
sewardj1fbc1a52005-04-25 02:05:54 +00002343 }
nethercote71980f02004-01-24 18:18:54 +00002344
2345 //--------------------------------------------------------------
sewardj45f4e7c2005-09-27 19:20:21 +00002346 // Load debug info for the existing segments.
2347 // p: setup_code_redirect_table [so that redirs can be recorded]
2348 // p: mallocfree
2349 // p: probably: setup fds and process CLOs, so that logging works
2350 //--------------------------------------------------------------
2351 VG_(debugLog)(1, "main", "Load initial debug info\n");
2352 { Addr* seg_starts;
2353 Int n_seg_starts;
2354
2355 seg_starts = get_seg_starts( &n_seg_starts );
2356 vg_assert(seg_starts && n_seg_starts > 0);
2357
sewardjf72cced2005-11-08 00:45:47 +00002358 /* show them all to the debug info reader. allow_SkFileV has to
2359 be True here so that we read info from the valgrind executable
2360 itself. */
sewardj45f4e7c2005-09-27 19:20:21 +00002361 for (i = 0; i < n_seg_starts; i++)
sewardjf72cced2005-11-08 00:45:47 +00002362 VG_(di_notify_mmap)( seg_starts[i], True/*allow_SkFileV*/ );
sewardj45f4e7c2005-09-27 19:20:21 +00002363
2364 VG_(free)( seg_starts );
2365 }
2366
2367 //--------------------------------------------------------------
2368 // Tell aspacem of ownership change of the asm helpers, so that
2369 // m_translate allows them to be translated. However, only do this
2370 // after the initial debug info read, since making a hole in the
2371 // address range for the stage2 binary confuses the debug info reader.
2372 // p: aspacem
2373 //--------------------------------------------------------------
2374 { Bool change_ownership_v_c_OK;
2375 Addr co_start = VG_PGROUNDDN( (Addr)&VG_(trampoline_stuff_start) );
2376 Addr co_endPlus = VG_PGROUNDUP( (Addr)&VG_(trampoline_stuff_end) );
2377 VG_(debugLog)(1,"redir",
2378 "transfer ownership V -> C of 0x%llx .. 0x%llx\n",
2379 (ULong)co_start, (ULong)co_endPlus-1 );
2380
2381 change_ownership_v_c_OK
2382 = VG_(am_change_ownership_v_to_c)( co_start, co_endPlus - co_start );
2383 vg_assert(change_ownership_v_c_OK);
2384 }
2385
2386 //--------------------------------------------------------------
2387 // Tell the tool about the initial client memory permissions
2388 // p: aspacem
2389 // p: mallocfree
2390 // p: setup_client_stack
2391 // p: setup_client_dataseg
2392 //--------------------------------------------------------------
2393 VG_(debugLog)(1, "main", "Tell tool about initial permissions\n");
2394 { Addr* seg_starts;
2395 Int n_seg_starts;
2396 NSegment* seg;
2397
2398 seg_starts = get_seg_starts( &n_seg_starts );
2399 vg_assert(seg_starts && n_seg_starts > 0);
2400
2401 /* show interesting ones to the tool */
2402 for (i = 0; i < n_seg_starts; i++) {
2403 seg = VG_(am_find_nsegment)( seg_starts[i] );
2404 vg_assert(seg);
2405 if (seg->kind == SkFileC || seg->kind == SkAnonC) {
2406 VG_(debugLog)(2, "main",
2407 "tell tool about %010lx-%010lx %c%c%c\n",
2408 seg->start, seg->end,
2409 seg->hasR ? 'r' : '-',
2410 seg->hasW ? 'w' : '-',
2411 seg->hasX ? 'x' : '-' );
2412 VG_TRACK( new_mem_startup, seg->start, seg->end+1-seg->start,
2413 seg->hasR, seg->hasW, seg->hasX );
2414 }
2415 }
2416
2417 VG_(free)( seg_starts );
2418
2419 /* Also do the initial stack permissions. */
2420 seg = VG_(am_find_nsegment)( initial_client_SP );
2421 vg_assert(seg);
2422 vg_assert(seg->kind == SkAnonC);
2423 vg_assert(initial_client_SP >= seg->start);
2424 vg_assert(initial_client_SP <= seg->end);
2425
2426 /* Stuff below the initial SP is unaddressable. */
2427 /* NB: shouldn't this take into account the VG_STACK_REDZONE_SZB
2428 bytes below SP? */
2429 VG_TRACK( die_mem_stack, seg->start, initial_client_SP - seg->start );
2430 VG_(debugLog)(2, "main", "mark stack inaccessible %010lx-%010lx\n",
2431 seg->start, initial_client_SP-1 );
2432
2433 /* Also the assembly helpers. */
2434 VG_TRACK( new_mem_startup,
2435 (Addr)&VG_(trampoline_stuff_start),
tom151a6392005-11-11 12:30:36 +00002436 (Addr)&VG_(trampoline_stuff_end) - (Addr)&VG_(trampoline_stuff_start),
sewardj45f4e7c2005-09-27 19:20:21 +00002437 False, /* readable? */
2438 False, /* writable? */
2439 True /* executable? */ );
2440 }
2441
2442 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002443 // Initialise the scheduler
nethercote71980f02004-01-24 18:18:54 +00002444 // p: setup_file_descriptors() [else VG_(safe_fd)() breaks]
sewardj45f4e7c2005-09-27 19:20:21 +00002445 // p: setup_client_stack
nethercote71980f02004-01-24 18:18:54 +00002446 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002447 VG_(debugLog)(1, "main", "Initialise scheduler\n");
sewardj45f4e7c2005-09-27 19:20:21 +00002448 { NSegment* seg = VG_(am_find_nsegment)( initial_client_SP );
2449 vg_assert(seg);
2450 vg_assert(seg->kind == SkAnonC);
2451 vg_assert(initial_client_SP >= seg->start);
2452 vg_assert(initial_client_SP <= seg->end);
2453 VG_(scheduler_init)( seg->end, clstack_max_size );
2454 }
nethercote71980f02004-01-24 18:18:54 +00002455
2456 //--------------------------------------------------------------
sewardjb5f6f512005-03-10 23:59:00 +00002457 // Initialise the pthread model
2458 // p: ?
sewardj2a99cf62004-11-24 10:44:19 +00002459 // load_client() [for 'client_eip']
2460 // setup_client_stack() [for 'sp_at_startup']
2461 // setup_scheduler() [for the rest of state 1 stuff]
2462 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002463 VG_(debugLog)(1, "main", "Initialise thread 1's state\n");
sewardj45f4e7c2005-09-27 19:20:21 +00002464 init_thread1state( initial_client_IP, initial_client_SP,
2465 &VG_(threads)[1].arch);
njnea4b28c2004-11-30 16:04:58 +00002466
sewardj2a99cf62004-11-24 10:44:19 +00002467 //--------------------------------------------------------------
sewardj39b88fb2005-03-12 15:16:07 +00002468 // Initialise the pthread model
2469 // p: ?
nethercote71980f02004-01-24 18:18:54 +00002470 //--------------------------------------------------------------
sewardjb5f6f512005-03-10 23:59:00 +00002471 //if (VG_(clo_model_pthreads))
2472 // VG_(pthread_init)();
nethercote71980f02004-01-24 18:18:54 +00002473
2474 //--------------------------------------------------------------
2475 // Initialise the signal handling subsystem
sewardjb5f6f512005-03-10 23:59:00 +00002476 // p: n/a
nethercote71980f02004-01-24 18:18:54 +00002477 //--------------------------------------------------------------
2478 // Nb: temporarily parks the saved blocking-mask in saved_sigmask.
sewardj1fbc1a52005-04-25 02:05:54 +00002479 VG_(debugLog)(1, "main", "Initialise signal management\n");
nethercote71980f02004-01-24 18:18:54 +00002480 VG_(sigstartup_actions)();
2481
2482 //--------------------------------------------------------------
2483 // Perhaps we're profiling Valgrind?
2484 // p: process_cmd_line_options() [for VG_(clo_profile)]
2485 // p: others?
2486 //
2487 // XXX: this seems to be broken? It always says the tool wasn't built
2488 // for profiling; vg_profile.c's functions don't seem to be overriding
2489 // vg_dummy_profile.c's?
2490 //
2491 // XXX: want this as early as possible. Looking for --profile
sewardj45f4e7c2005-09-27 19:20:21 +00002492 // in get_helprequest_and_toolname() could get it earlier.
nethercote71980f02004-01-24 18:18:54 +00002493 //--------------------------------------------------------------
2494 if (VG_(clo_profile))
njn31066fd2005-03-26 00:42:02 +00002495 VG_(init_profiling)();
nethercote71980f02004-01-24 18:18:54 +00002496
2497 VGP_PUSHCC(VgpStartup);
2498
2499 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002500 // Read suppression file
2501 // p: process_cmd_line_options() [for VG_(clo_suppressions)]
2502 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002503 if (VG_(needs).core_errors || VG_(needs).tool_errors) {
2504 VG_(debugLog)(1, "main", "Load suppressions\n");
nethercote71980f02004-01-24 18:18:54 +00002505 VG_(load_suppressions)();
sewardj1fbc1a52005-04-25 02:05:54 +00002506 }
nethercote71980f02004-01-24 18:18:54 +00002507
2508 //--------------------------------------------------------------
rjwalsh0140af52005-06-04 20:42:33 +00002509 // register client stack
2510 //--------------------------------------------------------------
njn945ed2e2005-06-24 03:28:30 +00002511 VG_(clstk_id) = VG_(register_stack)(VG_(clstk_base), VG_(clstk_end));
rjwalsh0140af52005-06-04 20:42:33 +00002512
2513 //--------------------------------------------------------------
sewardj45f4e7c2005-09-27 19:20:21 +00002514 // Show the address space state so far
2515 //--------------------------------------------------------------
2516 VG_(debugLog)(1, "main", "\n");
2517 VG_(debugLog)(1, "main", "\n");
2518 VG_(am_show_nsegments)(1,"Memory layout at client startup");
2519 VG_(debugLog)(1, "main", "\n");
2520 VG_(debugLog)(1, "main", "\n");
2521
2522 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002523 // Run!
2524 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002525 VGP_POPCC(VgpStartup);
nethercote71980f02004-01-24 18:18:54 +00002526
sewardj71bc3cb2005-05-19 00:25:45 +00002527 if (VG_(clo_xml)) {
sewardj68cde6f2005-07-19 12:17:51 +00002528 HChar buf[50];
sewardj592ae092005-11-08 19:01:44 +00002529 VG_(elapsed_wallclock_time)(buf);
sewardj753673f2005-08-09 22:03:08 +00002530 VG_(message)(Vg_UserMsg, "<status>\n"
2531 " <state>RUNNING</state>\n"
2532 " <time>%t</time>\n"
2533 "</status>",
2534 buf);
sewardj71bc3cb2005-05-19 00:25:45 +00002535 VG_(message)(Vg_UserMsg, "");
2536 }
2537
sewardj1fbc1a52005-04-25 02:05:54 +00002538 VG_(debugLog)(1, "main", "Running thread 1\n");
sewardj1ae3f3a2005-09-28 10:47:38 +00002539
sewardj1d887112005-05-30 21:44:08 +00002540 /* As a result of the following call, the last thread standing
sewardj1ae3f3a2005-09-28 10:47:38 +00002541 eventually winds up running shutdown_actions_NORETURN
2542 just below. Unfortunately, simply exporting said function
2543 causes m_main to be part of a module cycle, which is pretty
2544 nonsensical. So instead of doing that, the address of said
2545 function is stored in a global variable 'owned' by m_syswrap,
2546 and it uses that function pointer to get back here when it needs
2547 to. */
2548
2549 /* Set continuation address. */
2550 VG_(address_of_m_main_shutdown_actions_NORETURN)
2551 = & shutdown_actions_NORETURN;
2552
2553 /* Run the first thread, eventually ending up at the continuation
2554 address. */
njnaf839f52005-06-23 03:27:57 +00002555 VG_(main_thread_wrapper_NORETURN)(1);
nethercote71980f02004-01-24 18:18:54 +00002556
sewardj1d887112005-05-30 21:44:08 +00002557 /*NOTREACHED*/
2558 vg_assert(0);
sewardjb5f6f512005-03-10 23:59:00 +00002559}
2560
sewardj1ae3f3a2005-09-28 10:47:38 +00002561/* Do everything which needs doing when the last thread exits. */
sewardjb5f6f512005-03-10 23:59:00 +00002562
sewardj1ae3f3a2005-09-28 10:47:38 +00002563static
2564void shutdown_actions_NORETURN( ThreadId tid,
2565 VgSchedReturnCode tids_schedretcode )
sewardjb5f6f512005-03-10 23:59:00 +00002566{
sewardj1d887112005-05-30 21:44:08 +00002567 VG_(debugLog)(1, "main", "entering VG_(shutdown_actions_NORETURN)\n");
2568
2569 vg_assert( VG_(count_living_threads)() == 1 );
sewardjb5f6f512005-03-10 23:59:00 +00002570 vg_assert(VG_(is_running_thread)(tid));
2571
2572 // Wait for all other threads to exit.
njn7b85dd52005-06-12 17:26:29 +00002573 VG_(reap_threads)(tid);
sewardjb5f6f512005-03-10 23:59:00 +00002574
2575 VG_(clo_model_pthreads) = False;
2576
2577 // Clean the client up before the final report
njn9cb54ac2005-06-12 04:19:17 +00002578 final_tidyup(tid);
sewardjb5f6f512005-03-10 23:59:00 +00002579
2580 // OK, done
2581 VG_(exit_thread)(tid);
2582
2583 /* should be no threads left */
2584 vg_assert(VG_(count_living_threads)() == 0);
2585
2586 VG_(threads)[tid].status = VgTs_Empty;
nethercote71980f02004-01-24 18:18:54 +00002587 //--------------------------------------------------------------
2588 // Finalisation: cleanup, messages, etc. Order no so important, only
2589 // affects what order the messages come.
2590 //--------------------------------------------------------------
2591 if (VG_(clo_verbosity) > 0)
2592 VG_(message)(Vg_UserMsg, "");
2593
sewardj71bc3cb2005-05-19 00:25:45 +00002594 if (VG_(clo_xml)) {
sewardj68cde6f2005-07-19 12:17:51 +00002595 HChar buf[50];
sewardj9f297ca2005-05-20 02:29:52 +00002596 if (VG_(needs).core_errors || VG_(needs).tool_errors) {
2597 VG_(show_error_counts_as_XML)();
2598 VG_(message)(Vg_UserMsg, "");
2599 }
sewardj592ae092005-11-08 19:01:44 +00002600 VG_(elapsed_wallclock_time)(buf);
sewardj753673f2005-08-09 22:03:08 +00002601 VG_(message)(Vg_UserMsg, "<status>\n"
2602 " <state>FINISHED</state>\n"
2603 " <time>%t</time>\n"
2604 "</status>",
2605 buf);
sewardj71bc3cb2005-05-19 00:25:45 +00002606 VG_(message)(Vg_UserMsg, "");
2607 }
2608
nethercote71980f02004-01-24 18:18:54 +00002609 /* Print out file descriptor summary and stats. */
2610 if (VG_(clo_track_fds))
nethercote3a42fb82004-08-03 18:08:50 +00002611 VG_(show_open_fds)();
nethercote71980f02004-01-24 18:18:54 +00002612
njn95ec8702004-11-22 16:46:13 +00002613 if (VG_(needs).core_errors || VG_(needs).tool_errors)
nethercote71980f02004-01-24 18:18:54 +00002614 VG_(show_all_errors)();
2615
njn51d827b2005-05-09 01:02:08 +00002616 VG_TDICT_CALL(tool_fini, 0/*exitcode*/);
nethercote71980f02004-01-24 18:18:54 +00002617
sewardj71bc3cb2005-05-19 00:25:45 +00002618 if (VG_(clo_xml)) {
2619 VG_(message)(Vg_UserMsg, "");
2620 VG_(message)(Vg_UserMsg, "</valgrindoutput>");
2621 VG_(message)(Vg_UserMsg, "");
2622 }
2623
nethercote885dd912004-08-03 23:14:00 +00002624 VG_(sanity_check_general)( True /*include expensive checks*/ );
nethercote71980f02004-01-24 18:18:54 +00002625
2626 if (VG_(clo_verbosity) > 1)
nethercote3a42fb82004-08-03 18:08:50 +00002627 print_all_stats();
nethercote71980f02004-01-24 18:18:54 +00002628
nethercote71980f02004-01-24 18:18:54 +00002629 if (VG_(clo_profile))
njn31066fd2005-03-26 00:42:02 +00002630 VG_(done_profiling)();
njn2025cf92005-06-26 20:44:48 +00002631
2632 if (VG_(clo_profile_flags) > 0) {
2633 #define N_MAX 100
2634 BBProfEntry tops[N_MAX];
2635 ULong score_total = VG_(get_BB_profile) (tops, N_MAX);
2636 show_BB_profile(tops, N_MAX, score_total);
2637 }
sewardjfa8ec112005-01-19 11:55:34 +00002638
sewardj8b635a42004-11-22 19:01:47 +00002639 /* Print Vex storage stats */
sewardjbf426512005-01-17 18:35:30 +00002640 if (0)
2641 LibVEX_ShowAllocStats();
sewardj1d887112005-05-30 21:44:08 +00002642
njn8aa35852005-06-10 22:59:56 +00002643 /* Ok, finally exit in the os-specific way, according to the scheduler's
2644 return code. In short, if the (last) thread exited by calling
2645 sys_exit, do likewise; if the (last) thread stopped due to a fatal
2646 signal, terminate the entire system with that same fatal signal. */
2647 VG_(debugLog)(1, "core_os",
njn7b85dd52005-06-12 17:26:29 +00002648 "VG_(terminate_NORETURN)(tid=%lld)\n", (ULong)tid);
njn8aa35852005-06-10 22:59:56 +00002649
2650 vg_assert(VG_(count_living_threads)() == 0);
2651
2652 switch (tids_schedretcode) {
2653 case VgSrc_ExitSyscall: /* the normal way out */
2654 VG_(exit)( VG_(threads)[tid].os_state.exitcode );
2655 /* NOT ALIVE HERE! */
2656 VG_(core_panic)("entered the afterlife in main() -- ExitSyscall");
2657 break; /* what the hell :) */
2658
2659 case VgSrc_FatalSig:
2660 /* We were killed by a fatal signal, so replicate the effect */
2661 vg_assert(VG_(threads)[tid].os_state.fatalsig != 0);
2662 VG_(kill_self)(VG_(threads)[tid].os_state.fatalsig);
2663 VG_(core_panic)("main(): signal was supposed to be fatal");
2664 break;
2665
2666 default:
2667 VG_(core_panic)("main(): unexpected scheduler return code");
2668 }
njne96be672005-05-08 19:08:54 +00002669}
sewardj8b635a42004-11-22 19:01:47 +00002670
sewardj1ae3f3a2005-09-28 10:47:38 +00002671/* -------------------- */
2672
2673/* Final clean-up before terminating the process.
2674 Clean up the client by calling __libc_freeres() (if requested)
2675 This is Linux-specific?
2676*/
2677static void final_tidyup(ThreadId tid)
2678{
2679 Addr __libc_freeres_wrapper;
2680
2681 vg_assert(VG_(is_running_thread)(tid));
2682
2683 if ( !VG_(needs).libc_freeres ||
2684 !VG_(clo_run_libc_freeres) ||
2685 0 == (__libc_freeres_wrapper = VG_(get_libc_freeres_wrapper)()) )
2686 return; /* can't/won't do it */
2687
2688 if (VG_(clo_verbosity) > 2 ||
2689 VG_(clo_trace_syscalls) ||
2690 VG_(clo_trace_sched))
2691 VG_(message)(Vg_DebugMsg,
2692 "Caught __NR_exit; running __libc_freeres()");
2693
2694 /* point thread context to point to libc_freeres_wrapper */
2695 VG_(set_IP)(tid, __libc_freeres_wrapper);
2696 // XXX should we use a special stack?
2697
2698 /* Block all blockable signals by copying the real block state into
2699 the thread's block state*/
2700 VG_(sigprocmask)(VKI_SIG_BLOCK, NULL, &VG_(threads)[tid].sig_mask);
2701 VG_(threads)[tid].tmp_sig_mask = VG_(threads)[tid].sig_mask;
2702
2703 /* and restore handlers to default */
2704 VG_(set_default_handler)(VKI_SIGSEGV);
2705 VG_(set_default_handler)(VKI_SIGBUS);
2706 VG_(set_default_handler)(VKI_SIGILL);
2707 VG_(set_default_handler)(VKI_SIGFPE);
2708
2709 // We were exiting, so assert that...
2710 vg_assert(VG_(is_exiting)(tid));
2711 // ...but now we're not again
2712 VG_(threads)[tid].exitreason = VgSrc_None;
2713
2714 // run until client thread exits - ideally with LIBC_FREERES_DONE,
2715 // but exit/exitgroup/signal will do
2716 VG_(scheduler)(tid);
2717
2718 vg_assert(VG_(is_exiting)(tid));
2719}
2720
sewardj45f4e7c2005-09-27 19:20:21 +00002721
2722/*====================================================================*/
2723/*=== Getting to main() alive ===*/
2724/*====================================================================*/
2725
2726/* If linking of the final executables is done with glibc present,
2727 then Valgrind starts at main() above as usual, and all of the
2728 following code is irrelevant.
2729
2730 However, this is not the intended mode of use. The plan is to
2731 avoid linking against glibc, by giving gcc the flags
2732 -nodefaultlibs -lgcc -nostartfiles at startup.
2733
2734 From this derive two requirements:
2735
2736 1. gcc may emit calls to memcpy and memset to deal with structure
2737 assignments etc. Since we have chosen to ignore all the
2738 "normal" supporting libraries, we have to provide our own
2739 implementations of them. No problem.
2740
2741 2. We have to provide a symbol "_start", to which the kernel
2742 hands control at startup. Hence the code below.
2743*/
2744
2745/* ---------------- Requirement 1 ---------------- */
2746
2747void* memcpy(void *dest, const void *src, size_t n);
2748void* memcpy(void *dest, const void *src, size_t n) {
2749 return VG_(memcpy)(dest,src,n);
2750}
2751void* memset(void *s, int c, size_t n);
2752void* memset(void *s, int c, size_t n) {
2753 return VG_(memset)(s,c,n);
2754}
2755
2756/* ---------------- Requirement 2 ---------------- */
2757
2758/* Glibc's sysdeps/i386/elf/start.S has the following gem of a
2759 comment, which explains how the stack looks right at process start
2760 (when _start is jumped to). Hence _start passes %esp to
2761 _start_in_C, which extracts argc/argv/envp and starts up
2762 correctly. */
2763
2764/* This is the canonical entry point, usually the first thing in the text
2765 segment. The SVR4/i386 ABI (pages 3-31, 3-32) says that when the entry
2766 point runs, most registers' values are unspecified, except for:
2767
2768 %edx Contains a function pointer to be registered with `atexit'.
2769 This is how the dynamic linker arranges to have DT_FINI
2770 functions called for shared libraries that have been loaded
2771 before this code runs.
2772
2773 %esp The stack contains the arguments and environment:
2774 0(%esp) argc
2775 4(%esp) argv[0]
2776 ...
2777 (4*argc)(%esp) NULL
2778 (4*(argc+1))(%esp) envp[0]
2779 ...
2780 NULL
2781*/
2782
2783/* The kernel hands control to _start, which extracts the initial
sewardja48a4932005-09-29 11:09:56 +00002784 stack pointer and calls onwards to _start_in_C. This also switches
2785 the new stack. */
sewardj45f4e7c2005-09-27 19:20:21 +00002786#if defined(VGP_x86_linux)
2787asm("\n"
sewardjd9fc3822005-11-18 23:50:43 +00002788 ".text\n"
sewardj45f4e7c2005-09-27 19:20:21 +00002789 "\t.globl _start\n"
2790 "\t.type _start,@function\n"
2791 "_start:\n"
2792 /* set up the new stack in %eax */
sewardjfdf91b42005-09-28 00:53:09 +00002793 "\tmovl $vgPlain_interim_stack, %eax\n"
sewardj45f4e7c2005-09-27 19:20:21 +00002794 "\taddl $"VG_STRINGIFY(VG_STACK_GUARD_SZB)", %eax\n"
2795 "\taddl $"VG_STRINGIFY(VG_STACK_ACTIVE_SZB)", %eax\n"
2796 "\tsubl $16, %eax\n"
2797 "\tandl $~15, %eax\n"
2798 /* install it, and collect the original one */
2799 "\txchgl %eax, %esp\n"
2800 /* call _start_in_C, passing it the startup %esp */
2801 "\tpushl %eax\n"
2802 "\tcall _start_in_C\n"
2803 "\thlt\n"
2804);
2805#elif defined(VGP_amd64_linux)
2806asm("\n"
sewardjd9fc3822005-11-18 23:50:43 +00002807 ".text\n"
sewardj45f4e7c2005-09-27 19:20:21 +00002808 "\t.globl _start\n"
2809 "\t.type _start,@function\n"
2810 "_start:\n"
2811 /* set up the new stack in %rdi */
sewardjfdf91b42005-09-28 00:53:09 +00002812 "\tmovq $vgPlain_interim_stack, %rdi\n"
sewardj45f4e7c2005-09-27 19:20:21 +00002813 "\taddq $"VG_STRINGIFY(VG_STACK_GUARD_SZB)", %rdi\n"
2814 "\taddq $"VG_STRINGIFY(VG_STACK_ACTIVE_SZB)", %rdi\n"
2815 "\tandq $~15, %rdi\n"
2816 /* install it, and collect the original one */
2817 "\txchgq %rdi, %rsp\n"
2818 /* call _start_in_C, passing it the startup %rsp */
2819 "\tcall _start_in_C\n"
2820 "\thlt\n"
2821);
sewardja48a4932005-09-29 11:09:56 +00002822#elif defined(VGP_ppc32_linux)
2823asm("\n"
sewardjd9fc3822005-11-18 23:50:43 +00002824 ".text\n"
sewardja48a4932005-09-29 11:09:56 +00002825 "\t.globl _start\n"
2826 "\t.type _start,@function\n"
2827 "_start:\n"
2828 /* set up the new stack in r16 */
2829 "\tlis 16,vgPlain_interim_stack@ha\n"
2830 "\tla 16,vgPlain_interim_stack@l(16)\n"
2831 "\tlis 17,("VG_STRINGIFY(VG_STACK_GUARD_SZB)" >> 16)\n"
2832 "\tori 17,17,("VG_STRINGIFY(VG_STACK_GUARD_SZB)" & 0xFFFF)\n"
2833 "\tlis 18,("VG_STRINGIFY(VG_STACK_ACTIVE_SZB)" >> 16)\n"
2834 "\tori 18,18,("VG_STRINGIFY(VG_STACK_ACTIVE_SZB)" & 0xFFFF)\n"
2835 "\tadd 16,17,16\n"
2836 "\tadd 16,18,16\n"
2837 "\trlwinm 16,16,0,0,27\n"
2838 /* now r16 = &vgPlain_interim_stack + VG_STACK_GUARD_SZB +
2839 VG_STACK_ACTIVE_SZB rounded down to the nearest 16-byte
2840 boundary. And r1 is the original SP. Set the SP to r16 and
2841 call _start_in_C, passing it the initial SP. */
2842 "\tmr 3,1\n"
2843 "\tmr 1,16\n"
2844 "\tbl _start_in_C\n"
2845 "\ttrap\n"
2846);
sewardj45f4e7c2005-09-27 19:20:21 +00002847#else
2848#error "_start: needs implementation on this platform"
2849#endif
2850
2851/* Avoid compiler warnings: this fn _is_ used, but labelling it
2852 'static' causes gcc to complain it isn't. */
2853void _start_in_C ( UWord* pArgc );
2854void _start_in_C ( UWord* pArgc )
2855{
2856 Int r;
2857 Word argc = pArgc[0];
2858 HChar** argv = (HChar**)&pArgc[1];
2859 HChar** envp = (HChar**)&pArgc[1+argc+1];
sewardjfdf91b42005-09-28 00:53:09 +00002860 sp_at_startup = (Addr)pArgc;
sewardj45f4e7c2005-09-27 19:20:21 +00002861 r = main( (Int)argc, argv, envp );
2862 VG_(exit)(r);
2863}
2864
sewardjde4a1d02002-03-22 01:27:54 +00002865/*--------------------------------------------------------------------*/
njn04e16982005-05-31 00:23:43 +00002866/*--- end ---*/
sewardjde4a1d02002-03-22 01:27:54 +00002867/*--------------------------------------------------------------------*/