blob: 214e541395accddeee0d7ceb4fab9833d7777a5f [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"
sewardjfdf91b42005-09-28 00:53:09 +000049#include "pub_core_debuginfo.h"
njnd1af0032005-05-29 17:01:48 +000050#include "pub_core_redir.h"
njnc7561b92005-06-19 01:24:32 +000051#include "pub_core_scheduler.h"
njn0c246472005-05-31 01:00:08 +000052#include "pub_core_signals.h"
njn2025cf92005-06-26 20:44:48 +000053#include "pub_core_stacks.h" // For VG_(register_stack)
njnc1b01812005-06-17 22:19:06 +000054#include "pub_core_syswrap.h"
sewardjfdf91b42005-09-28 00:53:09 +000055#include "pub_core_translate.h" // For VG_(translate)
njn43b9a8a2005-05-10 04:37:01 +000056#include "pub_core_tooliface.h"
njna7598f62005-06-18 03:27:58 +000057#include "pub_core_trampoline.h"
njn8bddf582005-05-13 23:40:55 +000058#include "pub_core_transtab.h"
njn08a2e172005-06-21 22:47:54 +000059#include "pub_core_ume.h"
nethercote71980f02004-01-24 18:18:54 +000060
sewardjb5f6f512005-03-10 23:59:00 +000061
nethercote71980f02004-01-24 18:18:54 +000062/*====================================================================*/
63/*=== Counters, for profiling purposes only ===*/
64/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +000065
nethercote3a42fb82004-08-03 18:08:50 +000066static void print_all_stats ( void )
nethercote71980f02004-01-24 18:18:54 +000067{
njn42c83552005-12-05 20:45:59 +000068 VG_(print_translation_stats)();
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,
sewardj13247ca2005-12-30 22:52:20 +0000302 const ExeInfo* info,
sewardj45f4e7c2005-09-27 19:20:21 +0000303 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
cerionc7266522005-12-08 03:24:37 +0000372# if defined(VGP_ppc32_linux) || defined(VGP_ppc64_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
cerionc7266522005-12-08 03:24:37 +0000489# if defined(VGP_ppc32_linux) || defined(VGP_ppc64_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 }
cerionc7266522005-12-08 03:24:37 +0000561# elif defined(VGP_ppc64_linux)
562 /* acquire cache info */
563 if (auxv->u.a_val > 0) {
564 VG_(machine_ppc64_set_clszB)( auxv->u.a_val );
565 VG_(debugLog)(2, "main",
566 "PPC64 cache line size %u (type %u)\n",
567 (UInt)auxv->u.a_val, (UInt)auxv->a_type );
568 }
sewardjfdf91b42005-09-28 00:53:09 +0000569# endif
570 break;
nethercote71980f02004-01-24 18:18:54 +0000571
cerionc7266522005-12-08 03:24:37 +0000572# if defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux)
sewardjfdf91b42005-09-28 00:53:09 +0000573 case AT_IGNOREPPC:
574 break;
575# endif
576
577 case AT_SECURE:
578 /* If this is 1, then it means that this program is
579 running suid, and therefore the dynamic linker should
580 be careful about LD_PRELOAD, etc. However, since
581 stage1 (the thing the kernel actually execve's) should
582 never be SUID, and we need LD_PRELOAD to work for the
583 client, we set AT_SECURE to 0. */
584 auxv->u.a_val = 0;
585 break;
586
tom2315d182005-11-11 08:39:34 +0000587 case AT_SYSINFO:
cerionc7266522005-12-08 03:24:37 +0000588# if !defined(VGP_ppc32_linux) && !defined(VGP_ppc64_linux)
sewardjfdf91b42005-09-28 00:53:09 +0000589 case AT_SYSINFO_EHDR:
tom2315d182005-11-11 08:39:34 +0000590# endif
sewardjfdf91b42005-09-28 00:53:09 +0000591 /* Trash this, because we don't reproduce it */
592 auxv->a_type = AT_IGNORE;
593 break;
sewardjfdf91b42005-09-28 00:53:09 +0000594
595 default:
596 /* stomp out anything we don't know about */
597 VG_(debugLog)(2, "main",
598 "stomping auxv entry %lld\n",
599 (ULong)auxv->a_type);
600 auxv->a_type = AT_IGNORE;
601 break;
nethercote71980f02004-01-24 18:18:54 +0000602 }
603 }
604 *auxv = *orig_auxv;
605 vg_assert(auxv->a_type == AT_NULL);
606
607 vg_assert((strtab-stringbase) == stringsize);
608
sewardj45f4e7c2005-09-27 19:20:21 +0000609 /* client_SP is pointing at client's argc/argv */
nethercote5ee67ca2004-06-22 14:00:09 +0000610
sewardj45f4e7c2005-09-27 19:20:21 +0000611 if (0) VG_(printf)("startup SP = %p\n", client_SP);
612 return client_SP;
nethercote71980f02004-01-24 18:18:54 +0000613}
614
sewardj45f4e7c2005-09-27 19:20:21 +0000615
616/* Allocate the client data segment. It is an expandable anonymous
617 mapping abutting a shrinkable reservation of size max_dseg_size.
618 The data segment starts at VG_(brk_base), which is page-aligned,
619 and runs up to VG_(brk_limit), which isn't. */
620
621static void setup_client_dataseg ( SizeT max_size )
622{
623 Bool ok;
624 SysRes sres;
625 Addr anon_start = VG_(brk_base);
626 SizeT anon_size = VKI_PAGE_SIZE;
627 Addr resvn_start = anon_start + anon_size;
628 SizeT resvn_size = max_size - anon_size;
629
630 vg_assert(VG_IS_PAGE_ALIGNED(anon_size));
631 vg_assert(VG_IS_PAGE_ALIGNED(resvn_size));
632 vg_assert(VG_IS_PAGE_ALIGNED(anon_start));
633 vg_assert(VG_IS_PAGE_ALIGNED(resvn_start));
634
635 /* Because there's been no brk activity yet: */
636 vg_assert(VG_(brk_base) == VG_(brk_limit));
637
638 /* Try to create the data seg and associated reservation where
639 VG_(brk_base) says. */
640 ok = VG_(am_create_reservation)(
641 resvn_start,
642 resvn_size,
643 SmLower,
644 anon_size
645 );
646
647 if (!ok) {
648 /* Hmm, that didn't work. Well, let aspacem suggest an address
649 it likes better, and try again with that. */
650 anon_start = VG_(am_get_advisory_client_simple)
651 ( 0/*floating*/, anon_size+resvn_size, &ok );
652 if (ok) {
653 resvn_start = anon_start + anon_size;
654 ok = VG_(am_create_reservation)(
655 resvn_start,
656 resvn_size,
657 SmLower,
658 anon_size
659 );
660 if (ok)
661 VG_(brk_base) = VG_(brk_limit) = anon_start;
662 }
663 /* that too might have failed, but if it has, we're hosed: there
664 is no Plan C. */
665 }
666 vg_assert(ok);
667
njn7c555a92005-11-16 17:16:10 +0000668 /* We make the data segment (heap) executable because LinuxThreads on
njn0ddabca2005-11-16 23:54:46 +0000669 ppc32 creates trampolines in this area. Also, on x86/Linux the data
670 segment is RWX natively, at least according to /proc/self/maps.
671 Also, having a non-executable data seg would kill any program which
672 tried to create code in the data seg and then run it. */
sewardj45f4e7c2005-09-27 19:20:21 +0000673 sres = VG_(am_mmap_anon_fixed_client)(
674 anon_start,
675 anon_size,
sewardj33ca9e82005-11-16 17:12:38 +0000676 VKI_PROT_READ|VKI_PROT_WRITE|VKI_PROT_EXEC
sewardj45f4e7c2005-09-27 19:20:21 +0000677 );
678 vg_assert(!sres.isError);
679 vg_assert(sres.val == anon_start);
680}
681
682
nethercote71980f02004-01-24 18:18:54 +0000683/*====================================================================*/
684/*=== Find executable ===*/
685/*====================================================================*/
686
sewardjfdf91b42005-09-28 00:53:09 +0000687/* Scan a colon-separated list, and call a function on each element.
688 The string must be mutable, because we insert a temporary '\0', but
689 the string will end up unmodified. (*func) should return True if it
690 doesn't need to see any more.
691
692 This routine will return True if (*func) returns True and False if
693 it reaches the end of the list without that happening.
694*/
695static Bool scan_colsep(char *colsep, Bool (*func)(const char *))
696{
697 char *cp, *entry;
698 int end;
699
700 if (colsep == NULL ||
701 *colsep == '\0')
702 return False;
703
704 entry = cp = colsep;
705
706 do {
707 end = (*cp == '\0');
708
709 if (*cp == ':' || *cp == '\0') {
710 char save = *cp;
711
712 *cp = '\0';
713 if ((*func)(entry)) {
714 *cp = save;
715 return True;
716 }
717 *cp = save;
718 entry = cp+1;
719 }
720 cp++;
721 } while(!end);
722
723 return False;
724}
725
sewardj45f4e7c2005-09-27 19:20:21 +0000726/* Need a static copy because can't use dynamic mem allocation yet */
njn73750612005-10-14 03:11:30 +0000727static HChar executable_name_in [VKI_PATH_MAX];
728static HChar executable_name_out[VKI_PATH_MAX];
thughes4ad52d02004-06-27 17:37:21 +0000729
sewardj45f4e7c2005-09-27 19:20:21 +0000730static Bool match_executable(const char *entry)
731{
njn73750612005-10-14 03:11:30 +0000732 HChar buf[VG_(strlen)(entry) + VG_(strlen)(executable_name_in) + 3];
thughes4ad52d02004-06-27 17:37:21 +0000733
njn73750612005-10-14 03:11:30 +0000734 /* empty PATH element means '.' */
thughes4ad52d02004-06-27 17:37:21 +0000735 if (*entry == '\0')
736 entry = ".";
737
njn73750612005-10-14 03:11:30 +0000738 VG_(snprintf)(buf, sizeof(buf), "%s/%s", entry, executable_name_in);
739
740 // Don't match directories
741 if (VG_(is_dir)(buf))
742 return False;
743
744 // If we match an executable, we choose that immediately. If we find a
745 // matching non-executable we remember it but keep looking for an
746 // matching executable later in the path.
sewardj45f4e7c2005-09-27 19:20:21 +0000747 if (VG_(access)(buf, True/*r*/, False/*w*/, True/*x*/) == 0) {
njn73750612005-10-14 03:11:30 +0000748 VG_(strncpy)( executable_name_out, buf, VKI_PATH_MAX-1 );
749 executable_name_out[VKI_PATH_MAX-1] = 0;
750 return True; // Stop looking
751 } else if (VG_(access)(buf, True/*r*/, False/*w*/, False/*x*/) == 0
752 && VG_STREQ(executable_name_out, ""))
753 {
754 VG_(strncpy)( executable_name_out, buf, VKI_PATH_MAX-1 );
755 executable_name_out[VKI_PATH_MAX-1] = 0;
756 return False; // Keep looking
757 } else {
758 return False; // Keep looking
thughes4ad52d02004-06-27 17:37:21 +0000759 }
thughes4ad52d02004-06-27 17:37:21 +0000760}
761
njn73750612005-10-14 03:11:30 +0000762// Returns NULL if it wasn't found.
sewardj45f4e7c2005-09-27 19:20:21 +0000763static HChar* find_executable ( HChar* exec )
nethercote71980f02004-01-24 18:18:54 +0000764{
765 vg_assert(NULL != exec);
njn73750612005-10-14 03:11:30 +0000766 if (VG_(strchr)(exec, '/')) {
767 // Has a '/' - use the name as is
768 VG_(strncpy)( executable_name_out, exec, VKI_PATH_MAX-1 );
769 } else {
770 // No '/' - we need to search the path
sewardj03d8aa82005-10-14 11:25:49 +0000771 HChar* path;
njn73750612005-10-14 03:11:30 +0000772 VG_(strncpy)( executable_name_in, exec, VKI_PATH_MAX-1 );
773 VG_(memset) ( executable_name_out, 0, VKI_PATH_MAX );
sewardj03d8aa82005-10-14 11:25:49 +0000774 path = VG_(getenv)("PATH");
thughes4ad52d02004-06-27 17:37:21 +0000775 scan_colsep(path, match_executable);
nethercote71980f02004-01-24 18:18:54 +0000776 }
njn73750612005-10-14 03:11:30 +0000777 return VG_STREQ(executable_name_out, "") ? NULL : executable_name_out;
nethercote71980f02004-01-24 18:18:54 +0000778}
779
780
781/*====================================================================*/
nethercotef4928da2004-06-15 10:54:40 +0000782/*=== Command line errors ===*/
783/*====================================================================*/
784
njnbe9b47b2005-05-15 16:22:58 +0000785static void revert_to_stderr ( void )
nethercotef4928da2004-06-15 10:54:40 +0000786{
njnbe9b47b2005-05-15 16:22:58 +0000787 vg_assert( !VG_(logging_to_socket) );
nethercotef8548672004-06-21 12:42:35 +0000788 VG_(clo_log_fd) = 2; /* stderr */
nethercotef4928da2004-06-15 10:54:40 +0000789}
790
791void VG_(bad_option) ( Char* opt )
792{
njnbe9b47b2005-05-15 16:22:58 +0000793 revert_to_stderr();
njn02bc4b82005-05-15 17:28:26 +0000794 VG_(printf)("valgrind: Bad option '%s'; aborting.\n", opt);
nethercotef4928da2004-06-15 10:54:40 +0000795 VG_(printf)("valgrind: Use --help for more information.\n");
796 VG_(exit)(1);
797}
798
nethercotef4928da2004-06-15 10:54:40 +0000799static void missing_prog ( void )
800{
njnbe9b47b2005-05-15 16:22:58 +0000801 revert_to_stderr();
nethercotef4928da2004-06-15 10:54:40 +0000802 VG_(printf)("valgrind: no program specified\n");
803 VG_(printf)("valgrind: Use --help for more information.\n");
804 VG_(exit)(1);
805}
806
807static void config_error ( Char* msg )
808{
njnbe9b47b2005-05-15 16:22:58 +0000809 revert_to_stderr();
nethercotef4928da2004-06-15 10:54:40 +0000810 VG_(printf)("valgrind: Startup or configuration error:\n %s\n", msg);
811 VG_(printf)("valgrind: Unable to start up properly. Giving up.\n");
812 VG_(exit)(1);
813}
814
815
nethercote71980f02004-01-24 18:18:54 +0000816/*====================================================================*/
817/*=== Loading the client ===*/
818/*====================================================================*/
819
sewardj45f4e7c2005-09-27 19:20:21 +0000820/* Load the client whose name is VG_(argv_the_exename). */
nethercote71980f02004-01-24 18:18:54 +0000821
sewardj13247ca2005-12-30 22:52:20 +0000822static void load_client ( /*OUT*/ExeInfo* info,
823 /*OUT*/Addr* client_ip,
824 /*OUT*/Addr* client_toc)
sewardj45f4e7c2005-09-27 19:20:21 +0000825{
njn73750612005-10-14 03:11:30 +0000826 HChar* exe_name;
sewardj45f4e7c2005-09-27 19:20:21 +0000827 Int ret;
828 SysRes res;
829
830 vg_assert( VG_(args_the_exename) != NULL);
njn73750612005-10-14 03:11:30 +0000831 exe_name = find_executable( VG_(args_the_exename) );
832
833 if (!exe_name) {
834 VG_(printf)("valgrind: %s: command not found\n", VG_(args_the_exename));
835 VG_(exit)(127); // 127 is Posix NOTFOUND
836 }
sewardj45f4e7c2005-09-27 19:20:21 +0000837
838 VG_(memset)(info, 0, sizeof(*info));
nethercote71980f02004-01-24 18:18:54 +0000839 info->exe_base = VG_(client_base);
840 info->exe_end = VG_(client_end);
nethercote71980f02004-01-24 18:18:54 +0000841
njn73750612005-10-14 03:11:30 +0000842 ret = VG_(do_exec)(exe_name, info);
843
844 // The client was successfully loaded! Continue.
nethercote71980f02004-01-24 18:18:54 +0000845
sewardj45f4e7c2005-09-27 19:20:21 +0000846 /* Get hold of a file descriptor which refers to the client
847 executable. This is needed for attaching to GDB. */
njn73750612005-10-14 03:11:30 +0000848 res = VG_(open)(exe_name, VKI_O_RDONLY, VKI_S_IRUSR);
sewardj45f4e7c2005-09-27 19:20:21 +0000849 if (!res.isError)
850 VG_(cl_exec_fd) = res.val;
851
nethercote71980f02004-01-24 18:18:54 +0000852 /* Copy necessary bits of 'info' that were filled in */
sewardj13247ca2005-12-30 22:52:20 +0000853 *client_ip = info->init_ip;
854 *client_toc = info->init_toc;
sewardj45f4e7c2005-09-27 19:20:21 +0000855 VG_(brk_base) = VG_(brk_limit) = VG_PGROUNDUP(info->brkbase);
nethercote71980f02004-01-24 18:18:54 +0000856}
857
nethercote969ecf12004-10-13 17:29:01 +0000858
sewardj71bc3cb2005-05-19 00:25:45 +0000859/*====================================================================*/
860/*=== Command-line: variables, processing, etc ===*/
861/*====================================================================*/
862
863// See pub_{core,tool}_options.h for explanations of all these.
864
sewardj45f4e7c2005-09-27 19:20:21 +0000865static void usage_NORETURN ( Bool debug_help )
njn7cf0bd32002-06-08 13:36:03 +0000866{
njn25e49d8e72002-09-23 09:36:25 +0000867 Char* usage1 =
njn00cfcfc2005-11-12 18:53:50 +0000868"usage: valgrind [options] prog-and-args\n"
njn25e49d8e72002-09-23 09:36:25 +0000869"\n"
nethercote2b0793f2003-12-02 10:41:18 +0000870" common user options for all Valgrind tools, with defaults in [ ]:\n"
sewardjb5f6f512005-03-10 23:59:00 +0000871" --tool=<name> use the Valgrind tool named <name> [memcheck]\n"
nethercotea76368b2004-06-16 11:56:29 +0000872" -h --help show this message\n"
nethercote6c999f22004-01-31 22:55:15 +0000873" --help-debug show this message, plus debugging options\n"
njn25e49d8e72002-09-23 09:36:25 +0000874" --version show version\n"
njn25e49d8e72002-09-23 09:36:25 +0000875" -q --quiet run silently; only print error msgs\n"
876" -v --verbose be more verbose, incl counts of errors\n"
nethercote77eba602003-11-13 17:35:04 +0000877" --trace-children=no|yes Valgrind-ise child processes? [no]\n"
nethercote0d588502004-06-21 13:27:11 +0000878" --track-fds=no|yes track open file descriptors? [no]\n"
thughes6233a382004-08-21 11:10:44 +0000879" --time-stamp=no|yes add timestamps to log messages? [no]\n"
njnce545552005-07-25 22:36:52 +0000880" --log-fd=<number> log messages to file descriptor [2=stderr]\n"
tombbe14b12005-11-04 16:49:39 +0000881" --log-file=<file> log messages to <file>.<pid>\n"
njnce545552005-07-25 22:36:52 +0000882" --log-file-exactly=<file> log messages to <file>\n"
883" --log-file-qualifier=<VAR> incorporate $VAR in logfile name [none]\n"
884" --log-socket=ipaddr:port log messages to socket ipaddr:port\n"
nethercote2b0793f2003-12-02 10:41:18 +0000885"\n"
886" uncommon user options for all Valgrind tools:\n"
nethercote0d588502004-06-21 13:27:11 +0000887" --run-libc-freeres=no|yes free up glibc memory at exit? [yes]\n"
njn628add62005-11-12 18:21:40 +0000888" --sim-hints=hint1,hint2,... known hints:\n"
sewardj19617ae2005-10-20 01:09:57 +0000889" lax-ioctls, enable-outer [none]\n"
sewardjb1131a82005-03-19 15:12:21 +0000890" --show-emwarns=no|yes show warnings about emulation limits? [no]\n"
sewardj6c3a2192005-07-24 07:00:45 +0000891" --smc-check=none|stack|all checks for self-modifying code: none,\n"
892" only for code found in stacks, or all [stack]\n"
sewardj3c3f0c12005-11-08 15:52:36 +0000893" --kernel-variant=variant1,variant2,... known variants: bproc [none]\n"
894" handle non-standard kernel variants\n"
njn25e49d8e72002-09-23 09:36:25 +0000895"\n"
nethercote2b0793f2003-12-02 10:41:18 +0000896" user options for Valgrind tools that report errors:\n"
njnce545552005-07-25 22:36:52 +0000897" --xml=yes all output is in XML (Memcheck/Nulgrind only)\n"
njnc8ec9f82005-07-20 03:03:28 +0000898" --xml-user-comment=STR copy STR verbatim to XML output\n"
nethercote2b0793f2003-12-02 10:41:18 +0000899" --demangle=no|yes automatically demangle C++ names? [yes]\n"
njn20b4a152005-10-19 22:39:40 +0000900" --num-callers=<number> show <number> callers in stack traces [12]\n"
nethercote2b0793f2003-12-02 10:41:18 +0000901" --error-limit=no|yes stop showing new errors if too many? [yes]\n"
902" --show-below-main=no|yes continue stack traces below main() [no]\n"
903" --suppressions=<filename> suppress errors described in <filename>\n"
sewardjd153fae2005-01-10 17:24:47 +0000904" --gen-suppressions=no|yes|all print suppressions for errors? [no]\n"
nethercote04d0fbc2004-01-26 16:48:06 +0000905" --db-attach=no|yes start debugger when errors detected? [no]\n"
906" --db-command=<command> command to start debugger [gdb -nw %%f %%p]\n"
907" --input-fd=<number> file descriptor for input [0=stdin]\n"
sewardj97724e52005-04-02 23:40:59 +0000908" --max-stackframe=<number> assume stack switch for SP changes larger\n"
909" than <number> bytes [2000000]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +0000910"\n";
njn7cf0bd32002-06-08 13:36:03 +0000911
njn25e49d8e72002-09-23 09:36:25 +0000912 Char* usage2 =
913"\n"
nethercote2b0793f2003-12-02 10:41:18 +0000914" debugging options for all Valgrind tools:\n"
njn25e49d8e72002-09-23 09:36:25 +0000915" --sanity-level=<number> level of sanity checking to do [1]\n"
sewardjfa8ec112005-01-19 11:55:34 +0000916" --trace-flags=<XXXXXXXX> show generated code? (X = 0|1) [00000000]\n"
917" --profile-flags=<XXXXXXXX> ditto, but for profiling (X = 0|1) [00000000]\n"
sewardj33afdb52006-01-17 02:36:40 +0000918" --trace-notbelow=<number> only show BBs above <number> [999999999]\n"
njn25e49d8e72002-09-23 09:36:25 +0000919" --trace-syscalls=no|yes show all system calls? [no]\n"
920" --trace-signals=no|yes show signal handling details? [no]\n"
921" --trace-symtab=no|yes show symbol table details? [no]\n"
sewardjce058b02005-05-01 08:55:38 +0000922" --trace-cfi=no|yes show call-frame-info details? [no]\n"
sewardj0ec07f32006-01-12 12:32:32 +0000923" --trace-redir=no|yes show redirection details? [no]\n"
njn25e49d8e72002-09-23 09:36:25 +0000924" --trace-sched=no|yes show thread scheduler details? [no]\n"
jsgf855d93d2003-10-13 22:26:55 +0000925" --wait-for-gdb=yes|no pause on startup to wait for gdb attach\n"
sewardjb5f6f512005-03-10 23:59:00 +0000926#if 0
927" --model-pthreads=yes|no model the pthreads library [no]\n"
928#endif
929" --command-line-only=no|yes only use command line options [no]\n"
njn613812e2005-03-11 04:57:30 +0000930"\n"
931" --vex-iropt-verbosity 0 .. 9 [0]\n"
932" --vex-iropt-level 0 .. 2 [2]\n"
933" --vex-iropt-precise-memory-exns [no]\n"
sewardj8b635a42004-11-22 19:01:47 +0000934" --vex-iropt-unroll-thresh 0 .. 400 [120]\n"
935" --vex-guest-max-insns 1 .. 100 [50]\n"
936" --vex-guest-chase-thresh 0 .. 99 [10]\n"
937"\n"
sewardjfa8ec112005-01-19 11:55:34 +0000938" --trace-flags and --profile-flags values (omit the middle space):\n"
sewardj2a99cf62004-11-24 10:44:19 +0000939" 1000 0000 show conversion into IR\n"
940" 0100 0000 show after initial opt\n"
941" 0010 0000 show after instrumentation\n"
942" 0001 0000 show after second opt\n"
943" 0000 1000 show after tree building\n"
944" 0000 0100 show selecting insns\n"
945" 0000 0010 show after reg-alloc\n"
946" 0000 0001 show final assembly\n"
947"\n"
nethercote2b0793f2003-12-02 10:41:18 +0000948" debugging options for Valgrind tools that report errors\n"
949" --dump-error=<number> show translation for basic block associated\n"
950" with <number>'th error context [0=show none]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +0000951"\n";
njn3e884182003-04-15 13:03:23 +0000952
953 Char* usage3 =
954"\n"
nethercote71980f02004-01-24 18:18:54 +0000955" Extra options read from ~/.valgrindrc, $VALGRIND_OPTS, ./.valgrindrc\n"
njn25e49d8e72002-09-23 09:36:25 +0000956"\n"
njn53612422005-03-12 16:22:54 +0000957" Valgrind is Copyright (C) 2000-2005 Julian Seward et al.\n"
njn25e49d8e72002-09-23 09:36:25 +0000958" and licensed under the GNU General Public License, version 2.\n"
959" Bug reports, feedback, admiration, abuse, etc, to: %s.\n"
njnd04b7c62002-10-03 14:05:52 +0000960"\n"
nethercote137bc552003-11-14 17:47:54 +0000961" Tools are copyright and licensed by their authors. See each\n"
962" tool's start-up message for more information.\n"
njn25e49d8e72002-09-23 09:36:25 +0000963"\n";
njn7cf0bd32002-06-08 13:36:03 +0000964
njnbe9b47b2005-05-15 16:22:58 +0000965 // Ensure the message goes to stdout
966 VG_(clo_log_fd) = 1;
967 vg_assert( !VG_(logging_to_socket) );
968
fitzhardinge98abfc72003-12-16 02:05:15 +0000969 VG_(printf)(usage1);
970 if (VG_(details).name) {
971 VG_(printf)(" user options for %s:\n", VG_(details).name);
fitzhardinge98abfc72003-12-16 02:05:15 +0000972 if (VG_(needs).command_line_options)
njn51d827b2005-05-09 01:02:08 +0000973 VG_TDICT_CALL(tool_print_usage);
fitzhardinge98abfc72003-12-16 02:05:15 +0000974 else
975 VG_(printf)(" (none)\n");
976 }
nethercote6c999f22004-01-31 22:55:15 +0000977 if (debug_help) {
978 VG_(printf)(usage2);
fitzhardinge98abfc72003-12-16 02:05:15 +0000979
nethercote6c999f22004-01-31 22:55:15 +0000980 if (VG_(details).name) {
981 VG_(printf)(" debugging options for %s:\n", VG_(details).name);
982
983 if (VG_(needs).command_line_options)
njn51d827b2005-05-09 01:02:08 +0000984 VG_TDICT_CALL(tool_print_debug_usage);
nethercote6c999f22004-01-31 22:55:15 +0000985 else
986 VG_(printf)(" (none)\n");
987 }
fitzhardinge98abfc72003-12-16 02:05:15 +0000988 }
nethercote421281e2003-11-20 16:20:55 +0000989 VG_(printf)(usage3, VG_BUGS_TO);
nethercotef4928da2004-06-15 10:54:40 +0000990 VG_(exit)(0);
njn7cf0bd32002-06-08 13:36:03 +0000991}
sewardjde4a1d02002-03-22 01:27:54 +0000992
sewardjde4a1d02002-03-22 01:27:54 +0000993
sewardj45f4e7c2005-09-27 19:20:21 +0000994/* Peer at previously set up VG_(args_for_valgrind) and extract any
995 request for help and also the tool name. */
996
997static void get_helprequest_and_toolname ( Int* need_help, HChar** tool )
998{
999 UInt i;
1000 HChar* str;
sewardj8b635a42004-11-22 19:01:47 +00001001
nethercote71980f02004-01-24 18:18:54 +00001002 /* parse the options we have (only the options we care about now) */
sewardj45f4e7c2005-09-27 19:20:21 +00001003 for (i = 0; i < VG_(args_for_valgrind).used; i++) {
nethercote71980f02004-01-24 18:18:54 +00001004
sewardj45f4e7c2005-09-27 19:20:21 +00001005 str = VG_(args_for_valgrind).strs[i];
1006 vg_assert(str);
nethercote71980f02004-01-24 18:18:54 +00001007
sewardj45f4e7c2005-09-27 19:20:21 +00001008 if (VG_STREQ(str, "--version")) {
njn2e9f3f32005-10-26 16:17:46 +00001009 // Ensure the version string goes to stdout
1010 VG_(clo_log_fd) = 1;
sewardj45f4e7c2005-09-27 19:20:21 +00001011 VG_(printf)("valgrind-" VERSION "\n");
1012 VG_(exit)(0);
1013
1014 } else if (VG_CLO_STREQ(str, "--help") ||
1015 VG_CLO_STREQ(str, "-h")) {
nethercote6c999f22004-01-31 22:55:15 +00001016 *need_help = 1;
1017
sewardj45f4e7c2005-09-27 19:20:21 +00001018 } else if (VG_CLO_STREQ(str, "--help-debug")) {
nethercote6c999f22004-01-31 22:55:15 +00001019 *need_help = 2;
nethercote71980f02004-01-24 18:18:54 +00001020
sewardj45f4e7c2005-09-27 19:20:21 +00001021 // The tool has already been determined, but we need to know the name
1022 // here.
1023 } else if (VG_CLO_STREQN(7, str, "--tool=")) {
1024 *tool = &str[7];
nethercote71980f02004-01-24 18:18:54 +00001025 }
1026 }
nethercote71980f02004-01-24 18:18:54 +00001027}
1028
sewardj45f4e7c2005-09-27 19:20:21 +00001029static Bool process_cmd_line_options( UInt* client_auxv, const char* toolname )
nethercote71980f02004-01-24 18:18:54 +00001030{
njnda033f52005-12-19 21:27:58 +00001031 // VG_(clo_log_fd) is used by all the messaging. It starts as 2 (stderr)
1032 // and we cannot change it until we know what we are changing it to is
1033 // ok. So we have tmp_log_fd to hold the tmp fd prior to that point.
sewardj92645592005-07-23 09:18:34 +00001034 SysRes sres;
njnda033f52005-12-19 21:27:58 +00001035 Int i, tmp_log_fd;
sewardj92645592005-07-23 09:18:34 +00001036 Int toolname_len = VG_(strlen)(toolname);
njnbe9b47b2005-05-15 16:22:58 +00001037 enum {
1038 VgLogTo_Fd,
1039 VgLogTo_File,
1040 VgLogTo_FileExactly,
1041 VgLogTo_Socket
1042 } log_to = VgLogTo_Fd; // Where is logging output to be sent?
sewardjde4a1d02002-03-22 01:27:54 +00001043
nethercotee1730692003-11-20 10:38:07 +00001044 /* log to stderr by default, but usage message goes to stdout */
njnda033f52005-12-19 21:27:58 +00001045 tmp_log_fd = 2;
sewardjde4a1d02002-03-22 01:27:54 +00001046
sewardj19d81412002-06-03 01:10:40 +00001047 /* Check for sane path in ./configure --prefix=... */
fitzhardinge98abfc72003-12-16 02:05:15 +00001048 if (VG_LIBDIR[0] != '/')
sewardj19d81412002-06-03 01:10:40 +00001049 config_error("Please use absolute paths in "
1050 "./configure --prefix=... or --libdir=...");
sewardj38170912002-05-10 21:07:22 +00001051
sewardj45f4e7c2005-09-27 19:20:21 +00001052 for (i = 0; i < VG_(args_for_valgrind).used; i++) {
nethercote71980f02004-01-24 18:18:54 +00001053
sewardj45f4e7c2005-09-27 19:20:21 +00001054 HChar* arg = VG_(args_for_valgrind).strs[i];
1055 HChar* colon = arg;
nethercote71980f02004-01-24 18:18:54 +00001056
thughes3bfd5a02004-07-18 08:05:44 +00001057 /* Look for a colon in the switch name */
1058 while (*colon && *colon != ':' && *colon != '=')
1059 colon++;
nethercote71980f02004-01-24 18:18:54 +00001060
1061 /* Look for matching "--toolname:foo" */
thughes3bfd5a02004-07-18 08:05:44 +00001062 if (*colon == ':') {
nethercote71980f02004-01-24 18:18:54 +00001063 if (VG_CLO_STREQN(2, arg, "--") &&
1064 VG_CLO_STREQN(toolname_len, arg+2, toolname) &&
1065 VG_CLO_STREQN(1, arg+2+toolname_len, ":"))
1066 {
1067 // prefix matches, convert "--toolname:foo" to "--foo"
1068 if (0)
1069 VG_(printf)("tool-specific arg: %s\n", arg);
sewardj45f4e7c2005-09-27 19:20:21 +00001070 arg = VG_(strdup)(arg + toolname_len + 1);
nethercote71980f02004-01-24 18:18:54 +00001071 arg[0] = '-';
1072 arg[1] = '-';
1073
1074 } else {
1075 // prefix doesn't match, skip to next arg
1076 continue;
1077 }
1078 }
1079
fitzhardinge98abfc72003-12-16 02:05:15 +00001080 /* Ignore these options - they've already been handled */
njn45270a22005-03-27 01:00:11 +00001081 if (VG_CLO_STREQN( 7, arg, "--tool=")) goto skip_arg;
njn45270a22005-03-27 01:00:11 +00001082 if (VG_CLO_STREQN(20, arg, "--command-line-only=")) goto skip_arg;
fitzhardinge98abfc72003-12-16 02:05:15 +00001083
njn45270a22005-03-27 01:00:11 +00001084 if ( VG_CLO_STREQ(arg, "--")) goto skip_arg;
nethercote27fec902004-06-16 21:26:32 +00001085
nethercote71980f02004-01-24 18:18:54 +00001086 else if (VG_CLO_STREQ(arg, "-v") ||
1087 VG_CLO_STREQ(arg, "--verbose"))
sewardjde4a1d02002-03-22 01:27:54 +00001088 VG_(clo_verbosity)++;
nethercote27fec902004-06-16 21:26:32 +00001089
nethercote71980f02004-01-24 18:18:54 +00001090 else if (VG_CLO_STREQ(arg, "-q") ||
1091 VG_CLO_STREQ(arg, "--quiet"))
sewardjde4a1d02002-03-22 01:27:54 +00001092 VG_(clo_verbosity)--;
1093
sewardj1cf558c2005-04-25 01:36:56 +00001094 else if (VG_CLO_STREQ(arg, "-d")) {
1095 /* do nothing */
1096 }
1097
sewardj71bc3cb2005-05-19 00:25:45 +00001098 else VG_BOOL_CLO(arg, "--xml", VG_(clo_xml))
njn45270a22005-03-27 01:00:11 +00001099 else VG_BOOL_CLO(arg, "--db-attach", VG_(clo_db_attach))
1100 else VG_BOOL_CLO(arg, "--demangle", VG_(clo_demangle))
1101 else VG_BOOL_CLO(arg, "--error-limit", VG_(clo_error_limit))
njn45270a22005-03-27 01:00:11 +00001102 else VG_BOOL_CLO(arg, "--show-emwarns", VG_(clo_show_emwarns))
sewardj97724e52005-04-02 23:40:59 +00001103 else VG_NUM_CLO (arg, "--max-stackframe", VG_(clo_max_stackframe))
njn45270a22005-03-27 01:00:11 +00001104 else VG_BOOL_CLO(arg, "--run-libc-freeres", VG_(clo_run_libc_freeres))
1105 else VG_BOOL_CLO(arg, "--show-below-main", VG_(clo_show_below_main))
1106 else VG_BOOL_CLO(arg, "--time-stamp", VG_(clo_time_stamp))
1107 else VG_BOOL_CLO(arg, "--track-fds", VG_(clo_track_fds))
1108 else VG_BOOL_CLO(arg, "--trace-children", VG_(clo_trace_children))
1109 else VG_BOOL_CLO(arg, "--trace-sched", VG_(clo_trace_sched))
1110 else VG_BOOL_CLO(arg, "--trace-signals", VG_(clo_trace_signals))
1111 else VG_BOOL_CLO(arg, "--trace-symtab", VG_(clo_trace_symtab))
sewardjce058b02005-05-01 08:55:38 +00001112 else VG_BOOL_CLO(arg, "--trace-cfi", VG_(clo_trace_cfi))
njn45270a22005-03-27 01:00:11 +00001113 else VG_BOOL_CLO(arg, "--trace-redir", VG_(clo_trace_redir))
1114 else VG_BOOL_CLO(arg, "--trace-syscalls", VG_(clo_trace_syscalls))
1115 else VG_BOOL_CLO(arg, "--trace-pthreads", VG_(clo_trace_pthreads))
1116 else VG_BOOL_CLO(arg, "--wait-for-gdb", VG_(clo_wait_for_gdb))
1117 else VG_BOOL_CLO(arg, "--model-pthreads", VG_(clo_model_pthreads))
sewardj72f98ff2002-06-13 17:23:38 +00001118
njn45270a22005-03-27 01:00:11 +00001119 else VG_STR_CLO (arg, "--db-command", VG_(clo_db_command))
njn628add62005-11-12 18:21:40 +00001120 else VG_STR_CLO (arg, "--sim-hints", VG_(clo_sim_hints))
sewardjde4a1d02002-03-22 01:27:54 +00001121
njn45270a22005-03-27 01:00:11 +00001122 else VG_NUM_CLO (arg, "--dump-error", VG_(clo_dump_error))
1123 else VG_NUM_CLO (arg, "--input-fd", VG_(clo_input_fd))
1124 else VG_NUM_CLO (arg, "--sanity-level", VG_(clo_sanity_level))
1125 else VG_BNUM_CLO(arg, "--num-callers", VG_(clo_backtrace_size), 1,
1126 VG_DEEPEST_BACKTRACE)
sewardjde4a1d02002-03-22 01:27:54 +00001127
sewardj6c3a2192005-07-24 07:00:45 +00001128 else if (VG_CLO_STREQ(arg, "--smc-check=none"))
1129 VG_(clo_smc_check) = Vg_SmcNone;
1130 else if (VG_CLO_STREQ(arg, "--smc-check=stack"))
1131 VG_(clo_smc_check) = Vg_SmcStack;
1132 else if (VG_CLO_STREQ(arg, "--smc-check=all"))
1133 VG_(clo_smc_check) = Vg_SmcAll;
sewardj26412bd2005-07-07 10:05:05 +00001134
sewardjce5a5662005-10-06 03:19:49 +00001135 else VG_STR_CLO (arg, "--kernel-variant", VG_(clo_kernel_variant))
1136
njn45270a22005-03-27 01:00:11 +00001137 else VG_BNUM_CLO(arg, "--vex-iropt-verbosity",
sewardj8b635a42004-11-22 19:01:47 +00001138 VG_(clo_vex_control).iropt_verbosity, 0, 10)
njn45270a22005-03-27 01:00:11 +00001139 else VG_BNUM_CLO(arg, "--vex-iropt-level",
sewardj8b635a42004-11-22 19:01:47 +00001140 VG_(clo_vex_control).iropt_level, 0, 2)
njn45270a22005-03-27 01:00:11 +00001141 else VG_BOOL_CLO(arg, "--vex-iropt-precise-memory-exns",
sewardj8b635a42004-11-22 19:01:47 +00001142 VG_(clo_vex_control).iropt_precise_memory_exns)
njn45270a22005-03-27 01:00:11 +00001143 else VG_BNUM_CLO(arg, "--vex-iropt-unroll-thresh",
sewardj8b635a42004-11-22 19:01:47 +00001144 VG_(clo_vex_control).iropt_unroll_thresh, 0, 400)
njn45270a22005-03-27 01:00:11 +00001145 else VG_BNUM_CLO(arg, "--vex-guest-max-insns",
sewardj8b635a42004-11-22 19:01:47 +00001146 VG_(clo_vex_control).guest_max_insns, 1, 100)
njn45270a22005-03-27 01:00:11 +00001147 else VG_BNUM_CLO(arg, "--vex-guest-chase-thresh",
sewardj8b635a42004-11-22 19:01:47 +00001148 VG_(clo_vex_control).guest_chase_thresh, 0, 99)
1149
nethercotef8548672004-06-21 12:42:35 +00001150 else if (VG_CLO_STREQN(9, arg, "--log-fd=")) {
njnbe9b47b2005-05-15 16:22:58 +00001151 log_to = VgLogTo_Fd;
nethercotef8548672004-06-21 12:42:35 +00001152 VG_(clo_log_name) = NULL;
njnda033f52005-12-19 21:27:58 +00001153 tmp_log_fd = (Int)VG_(atoll)(&arg[9]);
sewardj4cf05692002-10-27 20:28:29 +00001154 }
1155
nethercotef8548672004-06-21 12:42:35 +00001156 else if (VG_CLO_STREQN(11, arg, "--log-file=")) {
njnbe9b47b2005-05-15 16:22:58 +00001157 log_to = VgLogTo_File;
nethercotef8548672004-06-21 12:42:35 +00001158 VG_(clo_log_name) = &arg[11];
sewardj4cf05692002-10-27 20:28:29 +00001159 }
njnd6bc3c32005-03-27 00:44:31 +00001160
sewardjad311162005-07-19 11:25:02 +00001161 else if (VG_CLO_STREQN(21, arg, "--log-file-qualifier=")) {
1162 VG_(clo_log_file_qualifier) = &arg[21];
1163 }
1164
sewardj603d4102005-01-11 14:01:02 +00001165 else if (VG_CLO_STREQN(19, arg, "--log-file-exactly=")) {
njnbe9b47b2005-05-15 16:22:58 +00001166 log_to = VgLogTo_FileExactly;
sewardj603d4102005-01-11 14:01:02 +00001167 VG_(clo_log_name) = &arg[19];
1168 }
sewardjde4a1d02002-03-22 01:27:54 +00001169
nethercotef8548672004-06-21 12:42:35 +00001170 else if (VG_CLO_STREQN(13, arg, "--log-socket=")) {
njnbe9b47b2005-05-15 16:22:58 +00001171 log_to = VgLogTo_Socket;
nethercotef8548672004-06-21 12:42:35 +00001172 VG_(clo_log_name) = &arg[13];
sewardj73cf3bc2002-11-03 03:20:15 +00001173 }
1174
sewardj768db0e2005-07-19 14:18:56 +00001175 else if (VG_CLO_STREQN(19, arg, "--xml-user-comment=")) {
1176 VG_(clo_xml_user_comment) = &arg[19];
1177 }
1178
nethercote71980f02004-01-24 18:18:54 +00001179 else if (VG_CLO_STREQN(15, arg, "--suppressions=")) {
sewardjde4a1d02002-03-22 01:27:54 +00001180 if (VG_(clo_n_suppressions) >= VG_CLO_MAX_SFILES) {
njn25e49d8e72002-09-23 09:36:25 +00001181 VG_(message)(Vg_UserMsg, "Too many suppression files specified.");
sewardjde4a1d02002-03-22 01:27:54 +00001182 VG_(message)(Vg_UserMsg,
1183 "Increase VG_CLO_MAX_SFILES and recompile.");
nethercote71980f02004-01-24 18:18:54 +00001184 VG_(bad_option)(arg);
sewardjde4a1d02002-03-22 01:27:54 +00001185 }
nethercote71980f02004-01-24 18:18:54 +00001186 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = &arg[15];
sewardjde4a1d02002-03-22 01:27:54 +00001187 VG_(clo_n_suppressions)++;
1188 }
sewardjde4a1d02002-03-22 01:27:54 +00001189
sewardjfa8ec112005-01-19 11:55:34 +00001190 /* "stuvwxyz" --> stuvwxyz (binary) */
1191 else if (VG_CLO_STREQN(14, arg, "--trace-flags=")) {
1192 Int j;
1193 char* opt = & arg[14];
1194
1195 if (8 != VG_(strlen)(opt)) {
1196 VG_(message)(Vg_UserMsg,
1197 "--trace-flags argument must have 8 digits");
1198 VG_(bad_option)(arg);
1199 }
1200 for (j = 0; j < 8; j++) {
1201 if ('0' == opt[j]) { /* do nothing */ }
1202 else if ('1' == opt[j]) VG_(clo_trace_flags) |= (1 << (7-j));
1203 else {
1204 VG_(message)(Vg_UserMsg, "--trace-flags argument can only "
1205 "contain 0s and 1s");
1206 VG_(bad_option)(arg);
1207 }
1208 }
1209 }
1210
1211 /* "stuvwxyz" --> stuvwxyz (binary) */
1212 else if (VG_CLO_STREQN(16, arg, "--profile-flags=")) {
njn25e49d8e72002-09-23 09:36:25 +00001213 Int j;
nethercote71980f02004-01-24 18:18:54 +00001214 char* opt = & arg[16];
njn25e49d8e72002-09-23 09:36:25 +00001215
sewardj2a99cf62004-11-24 10:44:19 +00001216 if (8 != VG_(strlen)(opt)) {
njn25e49d8e72002-09-23 09:36:25 +00001217 VG_(message)(Vg_UserMsg,
sewardjfa8ec112005-01-19 11:55:34 +00001218 "--profile-flags argument must have 8 digits");
nethercote71980f02004-01-24 18:18:54 +00001219 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001220 }
sewardj8b635a42004-11-22 19:01:47 +00001221 for (j = 0; j < 8; j++) {
njn25e49d8e72002-09-23 09:36:25 +00001222 if ('0' == opt[j]) { /* do nothing */ }
sewardjfa8ec112005-01-19 11:55:34 +00001223 else if ('1' == opt[j]) VG_(clo_profile_flags) |= (1 << (7-j));
njn25e49d8e72002-09-23 09:36:25 +00001224 else {
sewardjfa8ec112005-01-19 11:55:34 +00001225 VG_(message)(Vg_UserMsg, "--profile-flags argument can only "
njn25e49d8e72002-09-23 09:36:25 +00001226 "contain 0s and 1s");
nethercote71980f02004-01-24 18:18:54 +00001227 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001228 }
1229 }
1230 }
sewardjde4a1d02002-03-22 01:27:54 +00001231
njn45270a22005-03-27 01:00:11 +00001232 else VG_NUM_CLO (arg, "--trace-notbelow", VG_(clo_trace_notbelow))
sewardjc771b292004-11-30 18:55:21 +00001233
sewardjd153fae2005-01-10 17:24:47 +00001234 else if (VG_CLO_STREQ(arg, "--gen-suppressions=no"))
1235 VG_(clo_gen_suppressions) = 0;
1236 else if (VG_CLO_STREQ(arg, "--gen-suppressions=yes"))
1237 VG_(clo_gen_suppressions) = 1;
1238 else if (VG_CLO_STREQ(arg, "--gen-suppressions=all"))
1239 VG_(clo_gen_suppressions) = 2;
1240
nethercote71980f02004-01-24 18:18:54 +00001241 else if ( ! VG_(needs).command_line_options
njn51d827b2005-05-09 01:02:08 +00001242 || ! VG_TDICT_CALL(tool_process_cmd_line_option, arg) ) {
nethercotef4928da2004-06-15 10:54:40 +00001243 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001244 }
njn8c0b3bb2005-03-12 21:20:39 +00001245 skip_arg:
sewardj45f4e7c2005-09-27 19:20:21 +00001246 if (arg != VG_(args_for_valgrind).strs[i]) {
1247 VG_(free)(arg);
1248 }
sewardjde4a1d02002-03-22 01:27:54 +00001249 }
1250
sewardj998d40d2004-12-06 14:24:52 +00001251 /* Make VEX control parameters sane */
1252
1253 if (VG_(clo_vex_control).guest_chase_thresh
1254 >= VG_(clo_vex_control).guest_max_insns)
1255 VG_(clo_vex_control).guest_chase_thresh
1256 = VG_(clo_vex_control).guest_max_insns - 1;
1257
1258 if (VG_(clo_vex_control).guest_chase_thresh < 0)
1259 VG_(clo_vex_control).guest_chase_thresh = 0;
1260
1261 /* Check various option values */
nethercote27fec902004-06-16 21:26:32 +00001262
njnf9ebf672003-05-12 21:41:30 +00001263 if (VG_(clo_verbosity) < 0)
sewardjde4a1d02002-03-22 01:27:54 +00001264 VG_(clo_verbosity) = 0;
1265
nethercote04d0fbc2004-01-26 16:48:06 +00001266 if (VG_(clo_db_attach) && VG_(clo_trace_children)) {
sewardjde4a1d02002-03-22 01:27:54 +00001267 VG_(message)(Vg_UserMsg, "");
1268 VG_(message)(Vg_UserMsg,
nethercote04d0fbc2004-01-26 16:48:06 +00001269 "--db-attach=yes conflicts with --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001270 VG_(message)(Vg_UserMsg,
1271 "Please choose one or the other, but not both.");
nethercote04d0fbc2004-01-26 16:48:06 +00001272 VG_(bad_option)("--db-attach=yes and --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001273 }
1274
njnbe9b47b2005-05-15 16:22:58 +00001275 if (VG_(clo_gen_suppressions) > 0 &&
1276 !VG_(needs).core_errors && !VG_(needs).tool_errors) {
1277 VG_(message)(Vg_UserMsg,
1278 "Can't use --gen-suppressions= with this tool,");
1279 VG_(message)(Vg_UserMsg,
1280 "as it doesn't generate errors.");
1281 VG_(bad_option)("--gen-suppressions=");
1282 }
1283
sewardj71bc3cb2005-05-19 00:25:45 +00001284 /* If we've been asked to emit XML, mash around various other
1285 options so as to constrain the output somewhat, and to remove
1286 any need for user input during the run. */
1287 if (VG_(clo_xml)) {
1288 /* Disable suppression generation (requires user input) */
1289 VG_(clo_gen_suppressions) = 0;
1290 /* Disable attaching to GDB (requires user input) */
1291 VG_(clo_db_attach) = False;
1292 /* Set a known verbosity level */
1293 VG_(clo_verbosity) = 1;
1294 /* Disable error limits (this might be a bad idea!) */
1295 VG_(clo_error_limit) = False;
1296 /* Disable emulation warnings */
1297 VG_(clo_show_emwarns) = False;
1298 /* Disable waiting for GDB to debug Valgrind */
1299 VG_(clo_wait_for_gdb) = False;
1300 /* No file-descriptor leak checking yet */
1301 VG_(clo_track_fds) = False;
sewardj21f7f0c2005-07-06 19:46:48 +00001302 /* Disable timestamped output */
1303 VG_(clo_time_stamp) = False;
sewardj71bc3cb2005-05-19 00:25:45 +00001304 /* Also, we want to set options for the leak checker, but that
1305 will have to be done in Memcheck's flag-handling code, not
1306 here. */
1307 }
1308
njnbe9b47b2005-05-15 16:22:58 +00001309 /* All non-logging-related options have been checked. If the logging
1310 option specified is ok, we can switch to it, as we know we won't
1311 have to generate any other command-line-related error messages.
1312 (So far we should be still attached to stderr, so we can show on
1313 the terminal any problems to do with processing command line
1314 opts.)
1315
1316 So set up logging now. After this is done, VG_(clo_log_fd)
sewardj4cf05692002-10-27 20:28:29 +00001317 should be connected to whatever sink has been selected, and we
1318 indiscriminately chuck stuff into it without worrying what the
1319 nature of it is. Oh the wonder of Unix streams. */
1320
njnbe9b47b2005-05-15 16:22:58 +00001321 vg_assert(VG_(clo_log_fd) == 2 /* stderr */);
1322 vg_assert(VG_(logging_to_socket) == False);
sewardj4cf05692002-10-27 20:28:29 +00001323
njnbe9b47b2005-05-15 16:22:58 +00001324 switch (log_to) {
sewardj73cf3bc2002-11-03 03:20:15 +00001325
sewardj4cf05692002-10-27 20:28:29 +00001326 case VgLogTo_Fd:
nethercotef8548672004-06-21 12:42:35 +00001327 vg_assert(VG_(clo_log_name) == NULL);
sewardj4cf05692002-10-27 20:28:29 +00001328 break;
sewardj73cf3bc2002-11-03 03:20:15 +00001329
sewardj4cf05692002-10-27 20:28:29 +00001330 case VgLogTo_File: {
sewardjad311162005-07-19 11:25:02 +00001331 HChar logfilename[1000];
1332 Int seq = 0;
1333 Int pid = VG_(getpid)();
1334 HChar* qual = NULL;
jsgff3c3f1a2003-10-14 22:13:28 +00001335
nethercotef8548672004-06-21 12:42:35 +00001336 vg_assert(VG_(clo_log_name) != NULL);
1337 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
jsgff3c3f1a2003-10-14 22:13:28 +00001338
sewardjad311162005-07-19 11:25:02 +00001339 if (VG_(clo_log_file_qualifier)) {
1340 qual = VG_(getenv)(VG_(clo_log_file_qualifier));
1341 }
1342
nethercote71980f02004-01-24 18:18:54 +00001343 for (;;) {
sewardj92645592005-07-23 09:18:34 +00001344 HChar pidtxt[20], seqtxt[20];
1345
1346 VG_(sprintf)(pidtxt, "%d", pid);
1347
1348 if (seq == 0)
1349 seqtxt[0] = 0;
1350 else
1351 VG_(sprintf)(seqtxt, ".%d", seq);
1352
jsgff3c3f1a2003-10-14 22:13:28 +00001353 seq++;
1354
sewardj92645592005-07-23 09:18:34 +00001355 /* Result:
1356 if (qual) base_name ++ "." ++ qual ++ seqtxt
1357 if (not qual) base_name ++ "." ++ pid ++ seqtxt
1358 */
1359 VG_(sprintf)( logfilename,
1360 "%s.%s%s",
1361 VG_(clo_log_name),
1362 qual ? qual : pidtxt,
1363 seqtxt );
1364
njnbe9b47b2005-05-15 16:22:58 +00001365 // EXCL: it will fail with EEXIST if the file already exists.
njnda033f52005-12-19 21:27:58 +00001366 sres = VG_(open)(logfilename,
1367 VKI_O_CREAT|VKI_O_WRONLY|VKI_O_EXCL|VKI_O_TRUNC,
1368 VKI_S_IRUSR|VKI_S_IWUSR);
sewardj92645592005-07-23 09:18:34 +00001369 if (!sres.isError) {
njnda033f52005-12-19 21:27:58 +00001370 tmp_log_fd = sres.val;
sewardj603d4102005-01-11 14:01:02 +00001371 break; /* for (;;) */
jsgff3c3f1a2003-10-14 22:13:28 +00001372 } else {
njnbe9b47b2005-05-15 16:22:58 +00001373 // If the file already existed, we try the next name. If it
1374 // was some other file error, we give up.
sewardj92645592005-07-23 09:18:34 +00001375 if (sres.val != VKI_EEXIST) {
jsgff3c3f1a2003-10-14 22:13:28 +00001376 VG_(message)(Vg_UserMsg,
tombbe14b12005-11-04 16:49:39 +00001377 "Can't create/open log file '%s.%d'; giving up!",
nethercotef8548672004-06-21 12:42:35 +00001378 VG_(clo_log_name), pid);
jsgff3c3f1a2003-10-14 22:13:28 +00001379 VG_(bad_option)(
sewardj603d4102005-01-11 14:01:02 +00001380 "--log-file=<file> (didn't work out for some reason.)");
njnbe9b47b2005-05-15 16:22:58 +00001381 /*NOTREACHED*/
jsgff3c3f1a2003-10-14 22:13:28 +00001382 }
1383 }
1384 }
sewardj603d4102005-01-11 14:01:02 +00001385 break; /* switch (VG_(clo_log_to)) */
1386 }
1387
1388 case VgLogTo_FileExactly: {
sewardj603d4102005-01-11 14:01:02 +00001389 vg_assert(VG_(clo_log_name) != NULL);
1390 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
sewardj603d4102005-01-11 14:01:02 +00001391
njnda033f52005-12-19 21:27:58 +00001392 sres = VG_(open)(VG_(clo_log_name),
1393 VKI_O_CREAT|VKI_O_WRONLY|VKI_O_TRUNC,
1394 VKI_S_IRUSR|VKI_S_IWUSR);
sewardj92645592005-07-23 09:18:34 +00001395 if (!sres.isError) {
njnda033f52005-12-19 21:27:58 +00001396 tmp_log_fd = sres.val;
njnbe9b47b2005-05-15 16:22:58 +00001397 } else {
sewardj603d4102005-01-11 14:01:02 +00001398 VG_(message)(Vg_UserMsg,
njn02bc4b82005-05-15 17:28:26 +00001399 "Can't create/open log file '%s'; giving up!",
sewardj603d4102005-01-11 14:01:02 +00001400 VG_(clo_log_name));
1401 VG_(bad_option)(
1402 "--log-file-exactly=<file> (didn't work out for some reason.)");
1403 /*NOTREACHED*/
1404 }
1405 break; /* switch (VG_(clo_log_to)) */
sewardj73cf3bc2002-11-03 03:20:15 +00001406 }
1407
1408 case VgLogTo_Socket: {
nethercotef8548672004-06-21 12:42:35 +00001409 vg_assert(VG_(clo_log_name) != NULL);
1410 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
njnda033f52005-12-19 21:27:58 +00001411 tmp_log_fd = VG_(connect_via_socket)( VG_(clo_log_name) );
1412 if (tmp_log_fd == -1) {
sewardj73cf3bc2002-11-03 03:20:15 +00001413 VG_(message)(Vg_UserMsg,
nethercotef8548672004-06-21 12:42:35 +00001414 "Invalid --log-socket=ipaddr or --log-socket=ipaddr:port spec");
sewardj73cf3bc2002-11-03 03:20:15 +00001415 VG_(message)(Vg_UserMsg,
njn02bc4b82005-05-15 17:28:26 +00001416 "of '%s'; giving up!", VG_(clo_log_name) );
sewardj73cf3bc2002-11-03 03:20:15 +00001417 VG_(bad_option)(
nethercotef8548672004-06-21 12:42:35 +00001418 "--log-socket=");
njnbe9b47b2005-05-15 16:22:58 +00001419 /*NOTREACHED*/
sewardj4cf05692002-10-27 20:28:29 +00001420 }
njnda033f52005-12-19 21:27:58 +00001421 if (tmp_log_fd == -2) {
sewardj73cf3bc2002-11-03 03:20:15 +00001422 VG_(message)(Vg_UserMsg,
njn02bc4b82005-05-15 17:28:26 +00001423 "valgrind: failed to connect to logging server '%s'.",
nethercotef8548672004-06-21 12:42:35 +00001424 VG_(clo_log_name) );
sewardj570f8902002-11-03 11:44:36 +00001425 VG_(message)(Vg_UserMsg,
1426 "Log messages will sent to stderr instead." );
1427 VG_(message)(Vg_UserMsg,
1428 "" );
1429 /* We don't change anything here. */
njnbe9b47b2005-05-15 16:22:58 +00001430 vg_assert(VG_(clo_log_fd) == 2);
njnda033f52005-12-19 21:27:58 +00001431 tmp_log_fd = 2;
sewardj570f8902002-11-03 11:44:36 +00001432 } else {
njnda033f52005-12-19 21:27:58 +00001433 vg_assert(tmp_log_fd > 0);
njnbe9b47b2005-05-15 16:22:58 +00001434 VG_(logging_to_socket) = True;
sewardj570f8902002-11-03 11:44:36 +00001435 }
sewardj73cf3bc2002-11-03 03:20:15 +00001436 break;
1437 }
sewardj4cf05692002-10-27 20:28:29 +00001438 }
1439
sewardj71bc3cb2005-05-19 00:25:45 +00001440
1441 /* Check that the requested tool actually supports XML output. */
sewardj45f4e7c2005-09-27 19:20:21 +00001442 if (VG_(clo_xml) && !VG_STREQ(toolname, "memcheck")
1443 && !VG_STREQ(toolname, "none")) {
sewardj71bc3cb2005-05-19 00:25:45 +00001444 VG_(clo_xml) = False;
1445 VG_(message)(Vg_UserMsg,
cerion39655202005-07-13 14:18:24 +00001446 "Currently only Memcheck|None supports XML output.");
sewardj71bc3cb2005-05-19 00:25:45 +00001447 VG_(bad_option)("--xml=yes");
1448 /*NOTREACHED*/
1449 }
1450
njnda033f52005-12-19 21:27:58 +00001451 if (tmp_log_fd >= 0) {
1452 // Move log_fd into the safe range, so it doesn't conflict with any app fds.
1453 tmp_log_fd = VG_(fcntl)(tmp_log_fd, VKI_F_DUPFD, VG_(fd_hard_limit));
1454 if (tmp_log_fd < 0) {
1455 VG_(message)(Vg_UserMsg, "valgrind: failed to move logfile fd into safe range, using stderr");
1456 VG_(clo_log_fd) = 2; // stderr
1457 } else {
1458 VG_(clo_log_fd) = tmp_log_fd;
1459 VG_(fcntl)(VG_(clo_log_fd), VKI_F_SETFD, VKI_FD_CLOEXEC);
1460 }
1461 } else {
1462 // If they said --log-fd=-1, don't print anything. Plausible for use in
1463 // regression testing suites that use client requests to count errors.
1464 VG_(clo_log_fd) = tmp_log_fd;
jsgf855d93d2003-10-13 22:26:55 +00001465 }
1466
sewardj45f4e7c2005-09-27 19:20:21 +00001467 if (VG_(clo_n_suppressions) < VG_CLO_MAX_SFILES-1 &&
1468 (VG_(needs).core_errors || VG_(needs).tool_errors)) {
1469 /* If we haven't reached the max number of suppressions, load
1470 the default one. */
1471 static const Char default_supp[] = "default.supp";
1472 Int len = VG_(strlen)(VG_(libdir)) + 1 + sizeof(default_supp);
1473 Char *buf = VG_(arena_malloc)(VG_AR_CORE, len);
1474 VG_(sprintf)(buf, "%s/%s", VG_(libdir), default_supp);
1475 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = buf;
1476 VG_(clo_n_suppressions)++;
1477 }
sewardjde4a1d02002-03-22 01:27:54 +00001478
sewardj45f4e7c2005-09-27 19:20:21 +00001479 return (log_to == VgLogTo_Fd);
1480}
1481
1482
1483/*====================================================================*/
1484/*=== Printing the preamble ===*/
1485/*====================================================================*/
1486
1487/* Ok, the logging sink is running now. Print a suitable preamble.
1488 If logging to file or a socket, write details of parent PID and
1489 command line args, to help people trying to interpret the
1490 results of a run which encompasses multiple processes. */
1491static void print_preamble(Bool logging_to_fd, const char* toolname)
1492{
tom60a4b0b2005-10-12 10:45:27 +00001493 HChar* xpre = VG_(clo_xml) ? " <line>" : "";
1494 HChar* xpost = VG_(clo_xml) ? "</line>" : "";
1495 Int i;
1496
sewardj71bc3cb2005-05-19 00:25:45 +00001497 if (VG_(clo_xml)) {
sewardj8665d8e2005-06-01 17:35:23 +00001498 VG_(message)(Vg_UserMsg, "<?xml version=\"1.0\"?>");
1499 VG_(message)(Vg_UserMsg, "");
sewardj71bc3cb2005-05-19 00:25:45 +00001500 VG_(message)(Vg_UserMsg, "<valgrindoutput>");
1501 VG_(message)(Vg_UserMsg, "");
cerion20241ba2005-11-15 19:07:53 +00001502 VG_(message)(Vg_UserMsg, "<protocolversion>2</protocolversion>");
sewardj71bc3cb2005-05-19 00:25:45 +00001503 VG_(message)(Vg_UserMsg, "");
1504 }
1505
sewardj83adf412002-05-01 01:25:45 +00001506 if (VG_(clo_verbosity > 0)) {
sewardjd7bddad2005-06-13 16:48:32 +00001507
1508 if (VG_(clo_xml))
1509 VG_(message)(Vg_UserMsg, "<preamble>");
1510
nethercote996901a2004-08-03 13:29:09 +00001511 /* Tool details */
sewardj71bc3cb2005-05-19 00:25:45 +00001512 VG_(message)(Vg_UserMsg, "%s%s%s%s, %s.%s",
1513 xpre,
njnd04b7c62002-10-03 14:05:52 +00001514 VG_(details).name,
njnb9c427c2004-12-01 14:14:42 +00001515 NULL == VG_(details).version ? "" : "-",
njnd04b7c62002-10-03 14:05:52 +00001516 NULL == VG_(details).version
1517 ? (Char*)"" : VG_(details).version,
sewardj71bc3cb2005-05-19 00:25:45 +00001518 VG_(details).description,
1519 xpost);
1520 VG_(message)(Vg_UserMsg, "%s%s%s",
1521 xpre, VG_(details).copyright_author, xpost);
sewardj3b2736a2002-03-24 12:18:35 +00001522
njnd04b7c62002-10-03 14:05:52 +00001523 /* Core details */
1524 VG_(message)(Vg_UserMsg,
sewardj71bc3cb2005-05-19 00:25:45 +00001525 "%sUsing LibVEX rev %s, a library for dynamic binary translation.%s",
1526 xpre, LibVEX_Version(), xpost );
sewardjc7025332004-12-13 18:30:39 +00001527 VG_(message)(Vg_UserMsg,
sewardj71bc3cb2005-05-19 00:25:45 +00001528 "%sCopyright (C) 2004-2005, and GNU GPL'd, by OpenWorks LLP.%s",
1529 xpre, xpost );
sewardjc7025332004-12-13 18:30:39 +00001530 VG_(message)(Vg_UserMsg,
sewardj71bc3cb2005-05-19 00:25:45 +00001531 "%sUsing valgrind-%s, a dynamic binary instrumentation framework.%s",
1532 xpre, VERSION, xpost);
sewardjde4a1d02002-03-22 01:27:54 +00001533 VG_(message)(Vg_UserMsg,
sewardj71bc3cb2005-05-19 00:25:45 +00001534 "%sCopyright (C) 2000-2005, and GNU GPL'd, by Julian Seward et al.%s",
1535 xpre, xpost );
sewardjd7bddad2005-06-13 16:48:32 +00001536
sewardj45f4e7c2005-09-27 19:20:21 +00001537 if (VG_(clo_verbosity) == 1 && !VG_(clo_xml))
1538 VG_(message)(Vg_UserMsg, "For more details, rerun with: -v");
1539
sewardjd7bddad2005-06-13 16:48:32 +00001540 if (VG_(clo_xml))
1541 VG_(message)(Vg_UserMsg, "</preamble>");
njnd04b7c62002-10-03 14:05:52 +00001542 }
1543
sewardj45f4e7c2005-09-27 19:20:21 +00001544 if (!VG_(clo_xml) && VG_(clo_verbosity) > 0 && !logging_to_fd) {
sewardj4cf05692002-10-27 20:28:29 +00001545 VG_(message)(Vg_UserMsg, "");
1546 VG_(message)(Vg_UserMsg,
1547 "My PID = %d, parent PID = %d. Prog and args are:",
1548 VG_(getpid)(), VG_(getppid)() );
sewardj5e940782005-09-28 19:59:19 +00001549 if (VG_(args_the_exename))
1550 VG_(message)(Vg_UserMsg, " %s", VG_(args_the_exename));
sewardj45f4e7c2005-09-27 19:20:21 +00001551 for (i = 0; i < VG_(args_for_client).used; i++)
1552 VG_(message)(Vg_UserMsg, " %s", VG_(args_for_client).strs[i]);
sewardj5b742c32005-07-26 23:43:26 +00001553 if (VG_(clo_log_file_qualifier)) {
1554 HChar* val = VG_(getenv)(VG_(clo_log_file_qualifier));
1555 VG_(message)(Vg_UserMsg, "");
1556 VG_(message)(Vg_UserMsg, "Log file qualifier: var %s, value %s.",
1557 VG_(clo_log_file_qualifier),
1558 val ? val : "");
1559 }
sewardj4cf05692002-10-27 20:28:29 +00001560 }
sewardj71bc3cb2005-05-19 00:25:45 +00001561 else
1562 if (VG_(clo_xml)) {
1563 VG_(message)(Vg_UserMsg, "");
1564 VG_(message)(Vg_UserMsg, "<pid>%d</pid>", VG_(getpid)());
1565 VG_(message)(Vg_UserMsg, "<ppid>%d</ppid>", VG_(getppid)());
sewardj97f7e0c2005-07-19 15:00:25 +00001566 VG_(message)(Vg_UserMsg, "<tool>%t</tool>", toolname);
sewardjad311162005-07-19 11:25:02 +00001567 if (VG_(clo_log_file_qualifier)) {
1568 HChar* val = VG_(getenv)(VG_(clo_log_file_qualifier));
sewardj97f7e0c2005-07-19 15:00:25 +00001569 VG_(message)(Vg_UserMsg, "<logfilequalifier> <var>%t</var> "
1570 "<value>%t</value> </logfilequalifier>",
sewardjad311162005-07-19 11:25:02 +00001571 VG_(clo_log_file_qualifier),
1572 val ? val : "");
1573 }
sewardj768db0e2005-07-19 14:18:56 +00001574 if (VG_(clo_xml_user_comment)) {
1575 /* Note: the user comment itself is XML and is therefore to
1576 be passed through verbatim (%s) rather than escaped
1577 (%t). */
1578 VG_(message)(Vg_UserMsg, "<usercomment>%s</usercomment>",
1579 VG_(clo_xml_user_comment));
1580 }
sewardj71bc3cb2005-05-19 00:25:45 +00001581 VG_(message)(Vg_UserMsg, "");
sewardjb8a3dac2005-07-19 12:39:11 +00001582 VG_(message)(Vg_UserMsg, "<args>");
sewardj45f4e7c2005-09-27 19:20:21 +00001583
sewardjb8a3dac2005-07-19 12:39:11 +00001584 VG_(message)(Vg_UserMsg, " <vargv>");
sewardj45f4e7c2005-09-27 19:20:21 +00001585 if (VG_(name_of_launcher))
1586 VG_(message)(Vg_UserMsg, " <exe>%t</exe>",
1587 VG_(name_of_launcher));
1588 for (i = 0; i < VG_(args_for_valgrind).used; i++) {
1589 VG_(message)(Vg_UserMsg,
1590 " <arg>%t</arg>",
1591 VG_(args_for_valgrind).strs[i]);
sewardjb8a3dac2005-07-19 12:39:11 +00001592 }
1593 VG_(message)(Vg_UserMsg, " </vargv>");
sewardj45f4e7c2005-09-27 19:20:21 +00001594
sewardjb8a3dac2005-07-19 12:39:11 +00001595 VG_(message)(Vg_UserMsg, " <argv>");
sewardj45f4e7c2005-09-27 19:20:21 +00001596 if (VG_(args_the_exename))
1597 VG_(message)(Vg_UserMsg, " <exe>%t</exe>",
1598 VG_(args_the_exename));
1599 for (i = 0; i < VG_(args_for_client).used; i++) {
1600 VG_(message)(Vg_UserMsg, " <arg>%t</arg>",
1601 VG_(args_for_client).strs[i]);
sewardj8665d8e2005-06-01 17:35:23 +00001602 }
sewardjb8a3dac2005-07-19 12:39:11 +00001603 VG_(message)(Vg_UserMsg, " </argv>");
sewardj45f4e7c2005-09-27 19:20:21 +00001604
sewardjb8a3dac2005-07-19 12:39:11 +00001605 VG_(message)(Vg_UserMsg, "</args>");
sewardj71bc3cb2005-05-19 00:25:45 +00001606 }
sewardj4cf05692002-10-27 20:28:29 +00001607
sewardj45f4e7c2005-09-27 19:20:21 +00001608 // Empty line after the preamble
1609 if (VG_(clo_verbosity) > 0)
1610 VG_(message)(Vg_UserMsg, "");
1611
sewardjde4a1d02002-03-22 01:27:54 +00001612 if (VG_(clo_verbosity) > 1) {
sewardj92645592005-07-23 09:18:34 +00001613 SysRes fd;
sewardj1f0bbc72005-11-16 03:51:02 +00001614 VexArch vex_arch;
1615 VexArchInfo vex_archinfo;
sewardj45f4e7c2005-09-27 19:20:21 +00001616 if (!logging_to_fd)
njn1fd5eb22005-03-13 05:43:23 +00001617 VG_(message)(Vg_DebugMsg, "");
njn1fd5eb22005-03-13 05:43:23 +00001618 VG_(message)(Vg_DebugMsg, "Command line");
sewardj45f4e7c2005-09-27 19:20:21 +00001619 if (VG_(args_the_exename))
1620 VG_(message)(Vg_DebugMsg, " %s", VG_(args_the_exename));
1621 for (i = 0; i < VG_(args_for_client).used; i++)
1622 VG_(message)(Vg_DebugMsg, " %s", VG_(args_for_client).strs[i]);
njn86dc2bc2003-09-09 07:26:21 +00001623
njn1fd5eb22005-03-13 05:43:23 +00001624 VG_(message)(Vg_DebugMsg, "Startup, with flags:");
sewardj45f4e7c2005-09-27 19:20:21 +00001625 for (i = 0; i < VG_(args_for_valgrind).used; i++) {
1626 VG_(message)(Vg_DebugMsg, " %s", VG_(args_for_valgrind).strs[i]);
sewardjde4a1d02002-03-22 01:27:54 +00001627 }
nethercotea70f7352004-04-18 12:08:46 +00001628
njn1fd5eb22005-03-13 05:43:23 +00001629 VG_(message)(Vg_DebugMsg, "Contents of /proc/version:");
nethercotea70f7352004-04-18 12:08:46 +00001630 fd = VG_(open) ( "/proc/version", VKI_O_RDONLY, 0 );
sewardj92645592005-07-23 09:18:34 +00001631 if (fd.isError) {
njn1fd5eb22005-03-13 05:43:23 +00001632 VG_(message)(Vg_DebugMsg, " can't open /proc/version");
nethercotea70f7352004-04-18 12:08:46 +00001633 } else {
sewardj71bc3cb2005-05-19 00:25:45 +00001634# define BUF_LEN 256
nethercotea70f7352004-04-18 12:08:46 +00001635 Char version_buf[BUF_LEN];
sewardj92645592005-07-23 09:18:34 +00001636 Int n = VG_(read) ( fd.val, version_buf, BUF_LEN );
njnbe9b47b2005-05-15 16:22:58 +00001637 vg_assert(n <= BUF_LEN);
nethercotea70f7352004-04-18 12:08:46 +00001638 if (n > 0) {
1639 version_buf[n-1] = '\0';
njn1fd5eb22005-03-13 05:43:23 +00001640 VG_(message)(Vg_DebugMsg, " %s", version_buf);
nethercotea70f7352004-04-18 12:08:46 +00001641 } else {
njn1fd5eb22005-03-13 05:43:23 +00001642 VG_(message)(Vg_DebugMsg, " (empty?)");
nethercotea70f7352004-04-18 12:08:46 +00001643 }
sewardj92645592005-07-23 09:18:34 +00001644 VG_(close)(fd.val);
sewardj71bc3cb2005-05-19 00:25:45 +00001645# undef BUF_LEN
nethercotea70f7352004-04-18 12:08:46 +00001646 }
sewardj1f0bbc72005-11-16 03:51:02 +00001647
1648 VG_(machine_get_VexArchInfo)( &vex_arch, &vex_archinfo );
sewardje3121f32006-01-27 21:23:23 +00001649 VG_(message)(
1650 Vg_DebugMsg,
1651 "Arch and hwcaps: %s, %s",
1652 LibVEX_ppVexArch ( vex_arch ),
1653 LibVEX_ppVexHwCaps ( vex_arch, vex_archinfo.hwcaps )
1654 );
sewardj1f0bbc72005-11-16 03:51:02 +00001655 VG_(message)(Vg_DebugMsg, "Valgrind library directory: %s", VG_(libdir));
sewardjde4a1d02002-03-22 01:27:54 +00001656 }
nethercotef6a1d502004-08-09 12:21:57 +00001657}
1658
sewardjde4a1d02002-03-22 01:27:54 +00001659
nethercote71980f02004-01-24 18:18:54 +00001660/*====================================================================*/
1661/*=== File descriptor setup ===*/
1662/*====================================================================*/
1663
sewardj5f229e22005-09-28 01:36:01 +00001664/* Number of file descriptors that Valgrind tries to reserve for
1665 it's own use - just a small constant. */
1666#define N_RESERVED_FDS (10)
1667
nethercote71980f02004-01-24 18:18:54 +00001668static void setup_file_descriptors(void)
1669{
1670 struct vki_rlimit rl;
1671
1672 /* Get the current file descriptor limits. */
1673 if (VG_(getrlimit)(VKI_RLIMIT_NOFILE, &rl) < 0) {
1674 rl.rlim_cur = 1024;
1675 rl.rlim_max = 1024;
1676 }
1677
1678 /* Work out where to move the soft limit to. */
njn14319cc2005-03-13 06:26:22 +00001679 if (rl.rlim_cur + N_RESERVED_FDS <= rl.rlim_max) {
1680 rl.rlim_cur = rl.rlim_cur + N_RESERVED_FDS;
nethercote71980f02004-01-24 18:18:54 +00001681 } else {
1682 rl.rlim_cur = rl.rlim_max;
1683 }
1684
1685 /* Reserve some file descriptors for our use. */
njn14319cc2005-03-13 06:26:22 +00001686 VG_(fd_soft_limit) = rl.rlim_cur - N_RESERVED_FDS;
1687 VG_(fd_hard_limit) = rl.rlim_cur - N_RESERVED_FDS;
nethercote71980f02004-01-24 18:18:54 +00001688
1689 /* Update the soft limit. */
1690 VG_(setrlimit)(VKI_RLIMIT_NOFILE, &rl);
1691
sewardj45f4e7c2005-09-27 19:20:21 +00001692 if (VG_(cl_exec_fd) != -1)
1693 VG_(cl_exec_fd) = VG_(safe_fd)( VG_(cl_exec_fd) );
nethercote71980f02004-01-24 18:18:54 +00001694}
1695
sewardjde4a1d02002-03-22 01:27:54 +00001696
njn2da73352005-06-18 01:35:16 +00001697/*====================================================================*/
1698/*=== Initialise the first thread. ===*/
1699/*====================================================================*/
1700
1701/* Given a pointer to the ThreadArchState for thread 1 (the root
1702 thread), initialise the VEX guest state, and copy in essential
1703 starting values.
1704*/
1705static void init_thread1state ( Addr client_ip,
sewardjfdf91b42005-09-28 00:53:09 +00001706 Addr client_sp,
sewardj13247ca2005-12-30 22:52:20 +00001707 Addr client_toc,
njn2da73352005-06-18 01:35:16 +00001708 /*inout*/ ThreadArchState* arch )
1709{
1710#if defined(VGA_x86)
1711 vg_assert(0 == sizeof(VexGuestX86State) % 8);
1712
1713 /* Zero out the initial state, and set up the simulated FPU in a
1714 sane way. */
1715 LibVEX_GuestX86_initialise(&arch->vex);
1716
1717 /* Zero out the shadow area. */
1718 VG_(memset)(&arch->vex_shadow, 0, sizeof(VexGuestX86State));
1719
1720 /* Put essential stuff into the new state. */
sewardjfdf91b42005-09-28 00:53:09 +00001721 arch->vex.guest_ESP = client_sp;
njn2da73352005-06-18 01:35:16 +00001722 arch->vex.guest_EIP = client_ip;
1723
1724 /* initialise %cs, %ds and %ss to point at the operating systems
1725 default code, data and stack segments */
1726 asm volatile("movw %%cs, %0" : : "m" (arch->vex.guest_CS));
1727 asm volatile("movw %%ds, %0" : : "m" (arch->vex.guest_DS));
1728 asm volatile("movw %%ss, %0" : : "m" (arch->vex.guest_SS));
cerion85665ca2005-06-20 15:51:07 +00001729
njn2da73352005-06-18 01:35:16 +00001730#elif defined(VGA_amd64)
1731 vg_assert(0 == sizeof(VexGuestAMD64State) % 8);
1732
1733 /* Zero out the initial state, and set up the simulated FPU in a
1734 sane way. */
1735 LibVEX_GuestAMD64_initialise(&arch->vex);
1736
1737 /* Zero out the shadow area. */
1738 VG_(memset)(&arch->vex_shadow, 0, sizeof(VexGuestAMD64State));
1739
1740 /* Put essential stuff into the new state. */
sewardjfdf91b42005-09-28 00:53:09 +00001741 arch->vex.guest_RSP = client_sp;
njn2da73352005-06-18 01:35:16 +00001742 arch->vex.guest_RIP = client_ip;
cerion85665ca2005-06-20 15:51:07 +00001743
1744#elif defined(VGA_ppc32)
1745 vg_assert(0 == sizeof(VexGuestPPC32State) % 8);
1746
1747 /* Zero out the initial state, and set up the simulated FPU in a
1748 sane way. */
1749 LibVEX_GuestPPC32_initialise(&arch->vex);
1750
1751 /* Zero out the shadow area. */
1752 VG_(memset)(&arch->vex_shadow, 0, sizeof(VexGuestPPC32State));
1753
1754 /* Put essential stuff into the new state. */
sewardjfdf91b42005-09-28 00:53:09 +00001755 arch->vex.guest_GPR1 = client_sp;
cerion85665ca2005-06-20 15:51:07 +00001756 arch->vex.guest_CIA = client_ip;
1757
sewardj2c48c7b2005-11-29 13:05:56 +00001758#elif defined(VGA_ppc64)
cerion21082042005-12-06 19:07:08 +00001759 vg_assert(0 == sizeof(VexGuestPPC64State) % 16);
sewardj2c48c7b2005-11-29 13:05:56 +00001760
1761 /* Zero out the initial state, and set up the simulated FPU in a
1762 sane way. */
1763 LibVEX_GuestPPC64_initialise(&arch->vex);
1764
1765 /* Zero out the shadow area. */
1766 VG_(memset)(&arch->vex_shadow, 0, sizeof(VexGuestPPC64State));
1767
1768 /* Put essential stuff into the new state. */
1769 arch->vex.guest_GPR1 = client_sp;
sewardj13247ca2005-12-30 22:52:20 +00001770 arch->vex.guest_GPR2 = client_toc;
sewardj2c48c7b2005-11-29 13:05:56 +00001771 arch->vex.guest_CIA = client_ip;
njn2da73352005-06-18 01:35:16 +00001772#else
1773# error Unknown arch
1774#endif
1775 // Tell the tool that we just wrote to the registers.
1776 VG_TRACK( post_reg_write, Vg_CoreStartup, /*tid*/1, /*offset*/0,
1777 sizeof(VexGuestArchState));
1778}
1779
sewardjde4a1d02002-03-22 01:27:54 +00001780
nethercote71980f02004-01-24 18:18:54 +00001781/*====================================================================*/
njn2025cf92005-06-26 20:44:48 +00001782/*=== BB profiling ===*/
1783/*====================================================================*/
1784
1785static
1786void show_BB_profile ( BBProfEntry tops[], UInt n_tops, ULong score_total )
1787{
1788 ULong score_cumul, score_here;
1789 Char buf_cumul[10], buf_here[10];
1790 Char name[64];
1791 Int r;
1792
1793 VG_(printf)("\n");
1794 VG_(printf)("-----------------------------------------------------------\n");
1795 VG_(printf)("--- BEGIN BB Profile (summary of scores) ---\n");
1796 VG_(printf)("-----------------------------------------------------------\n");
1797 VG_(printf)("\n");
1798
1799 VG_(printf)("Total score = %lld\n\n", score_total);
1800
1801 score_cumul = 0;
1802 for (r = 0; r < n_tops; r++) {
1803 if (tops[r].addr == 0)
1804 continue;
1805 name[0] = 0;
1806 VG_(get_fnname_w_offset)(tops[r].addr, name, 64);
1807 name[63] = 0;
1808 score_here = tops[r].score;
1809 score_cumul += score_here;
1810 VG_(percentify)(score_cumul, score_total, 2, 6, buf_cumul);
1811 VG_(percentify)(score_here, score_total, 2, 6, buf_here);
1812 VG_(printf)("%3d: (%9lld %s) %9lld %s 0x%llx %s\n",
1813 r,
1814 score_cumul, buf_cumul,
1815 score_here, buf_here, tops[r].addr, name );
1816 }
1817
1818 VG_(printf)("\n");
1819 VG_(printf)("-----------------------------------------------------------\n");
1820 VG_(printf)("--- BB Profile (BB details) ---\n");
1821 VG_(printf)("-----------------------------------------------------------\n");
1822 VG_(printf)("\n");
1823
1824 score_cumul = 0;
1825 for (r = 0; r < n_tops; r++) {
1826 if (tops[r].addr == 0)
1827 continue;
1828 name[0] = 0;
1829 VG_(get_fnname_w_offset)(tops[r].addr, name, 64);
1830 name[63] = 0;
1831 score_here = tops[r].score;
1832 score_cumul += score_here;
1833 VG_(percentify)(score_cumul, score_total, 2, 6, buf_cumul);
1834 VG_(percentify)(score_here, score_total, 2, 6, buf_here);
1835 VG_(printf)("\n");
1836 VG_(printf)("=-=-=-=-=-=-=-=-=-=-=-=-=-= begin BB rank %d "
1837 "=-=-=-=-=-=-=-=-=-=-=-=-=-=\n\n", r);
1838 VG_(printf)("%3d: (%9lld %s) %9lld %s 0x%llx %s\n",
1839 r,
1840 score_cumul, buf_cumul,
1841 score_here, buf_here, tops[r].addr, name );
1842 VG_(printf)("\n");
sewardj0ec07f32006-01-12 12:32:32 +00001843 VG_(translate)(0, tops[r].addr, True, VG_(clo_profile_flags), 0, True);
njn2025cf92005-06-26 20:44:48 +00001844 VG_(printf)("=-=-=-=-=-=-=-=-=-=-=-=-=-= end BB rank %d "
1845 "=-=-=-=-=-=-=-=-=-=-=-=-=-=\n\n", r);
1846 }
1847
1848 VG_(printf)("\n");
1849 VG_(printf)("-----------------------------------------------------------\n");
1850 VG_(printf)("--- END BB Profile ---\n");
1851 VG_(printf)("-----------------------------------------------------------\n");
1852 VG_(printf)("\n");
1853}
1854
1855
1856/*====================================================================*/
nethercote71980f02004-01-24 18:18:54 +00001857/*=== main() ===*/
1858/*====================================================================*/
1859
sewardjfdf91b42005-09-28 00:53:09 +00001860/* When main() is entered, we should be on the following stack, not
1861 the one the kernel gave us. We will run on this stack until
1862 simulation of the root thread is started, at which point a transfer
1863 is made to a dynamically allocated stack. This is for the sake of
1864 uniform overflow detection for all Valgrind threads. This is
1865 marked global even though it isn't, because assembly code below
1866 needs to reference the name. */
1867
1868/*static*/ VgStack VG_(interim_stack);
1869
1870/* This should get some address inside the stack on which we gained
1871 control (eg, it could be the SP at startup). It doesn't matter
1872 exactly where in the stack it is. This value is passed to the
1873 address space manager at startup, which uses it to identify the
1874 initial stack segment and hence the upper end of the usable address
1875 space. */
1876
1877static Addr sp_at_startup = 0;
1878
sewardj1ae3f3a2005-09-28 10:47:38 +00001879/* --- Forwards decls to do with shutdown --- */
1880
1881static void final_tidyup(ThreadId tid);
1882
1883/* Do everything which needs doing when the last thread exits */
1884static
1885void shutdown_actions_NORETURN( ThreadId tid,
1886 VgSchedReturnCode tids_schedretcode );
1887
1888/* --- end of Forwards decls to do with shutdown --- */
sewardjfdf91b42005-09-28 00:53:09 +00001889
1890
sewardj45f4e7c2005-09-27 19:20:21 +00001891/* TODO: GIVE THIS A PROPER HOME
1892 TODO: MERGE THIS WITH DUPLICATE IN mac_leakcheck.c
1893 Extract from aspacem a vector of the current segment start
1894 addresses. The vector is dynamically allocated and should be freed
1895 by the caller when done. REQUIRES m_mallocfree to be running.
1896 Writes the number of addresses required into *n_acquired. */
nethercotec314eba2004-07-15 12:59:41 +00001897
sewardj45f4e7c2005-09-27 19:20:21 +00001898static Addr* get_seg_starts ( /*OUT*/Int* n_acquired )
sewardj1cf558c2005-04-25 01:36:56 +00001899{
sewardj45f4e7c2005-09-27 19:20:21 +00001900 Addr* starts;
sewardja48a4932005-09-29 11:09:56 +00001901 Int n_starts, r = 0;
sewardj45f4e7c2005-09-27 19:20:21 +00001902
1903 n_starts = 1;
sewardj1cf558c2005-04-25 01:36:56 +00001904 while (True) {
sewardj45f4e7c2005-09-27 19:20:21 +00001905 starts = VG_(malloc)( n_starts * sizeof(Addr) );
1906 if (starts == NULL)
1907 break;
1908 r = VG_(am_get_segment_starts)( starts, n_starts );
1909 if (r >= 0)
1910 break;
1911 VG_(free)(starts);
1912 n_starts *= 2;
sewardj1cf558c2005-04-25 01:36:56 +00001913 }
sewardj45f4e7c2005-09-27 19:20:21 +00001914
1915 if (starts == NULL) {
1916 *n_acquired = 0;
1917 return NULL;
1918 }
1919
1920 *n_acquired = r;
1921 return starts;
sewardj1cf558c2005-04-25 01:36:56 +00001922}
1923
1924
sewardj45f4e7c2005-09-27 19:20:21 +00001925
sewardj45f4e7c2005-09-27 19:20:21 +00001926Int main(Int argc, HChar **argv, HChar **envp)
nethercote71980f02004-01-24 18:18:54 +00001927{
sewardj13247ca2005-12-30 22:52:20 +00001928 HChar* toolname = "memcheck"; // default to Memcheck
1929 HChar** env = NULL;
1930 Int need_help = 0; // 0 = no, 1 = --help, 2 = --help-debug
1931 Addr initial_client_IP = 0;
1932 Addr initial_client_SP = 0;
1933 Addr initial_client_TOC = 0;
1934 Addr clstack_top = 0;
1935 SizeT clstack_max_size = 0;
sewardj45f4e7c2005-09-27 19:20:21 +00001936 UInt* client_auxv;
1937 Int loglevel, i;
1938 Bool logging_to_fd;
nethercote73b526f2004-10-31 18:48:21 +00001939 struct vki_rlimit zero = { 0, 0 };
sewardj13247ca2005-12-30 22:52:20 +00001940 ExeInfo info;
nethercote71980f02004-01-24 18:18:54 +00001941
1942 //============================================================
nethercote71980f02004-01-24 18:18:54 +00001943 //
sewardj45f4e7c2005-09-27 19:20:21 +00001944 // Nb: startup is complex. Prerequisites are shown at every step.
nethercote71980f02004-01-24 18:18:54 +00001945 // *** Be very careful when messing with the order ***
sewardj45f4e7c2005-09-27 19:20:21 +00001946 //
1947 // The first order of business is to get debug logging, the address
1948 // space manager and the dynamic memory manager up and running.
1949 // Once that's done, we can relax a bit.
1950 //
nethercote71980f02004-01-24 18:18:54 +00001951 //============================================================
sewardj45f4e7c2005-09-27 19:20:21 +00001952
1953 /* This is needed to make VG_(getenv) usable early. */
1954 VG_(client_envp) = (Char**)envp;
nethercote71980f02004-01-24 18:18:54 +00001955
sewardj1cf558c2005-04-25 01:36:56 +00001956 //--------------------------------------------------------------
1957 // Start up the logging mechanism
1958 // p: none
1959 //--------------------------------------------------------------
1960 /* Start the debugging-log system ASAP. First find out how many
1961 "-d"s were specified. This is a pre-scan of the command line. */
1962 loglevel = 0;
1963 for (i = 1; i < argc; i++) {
sewardj10759312005-05-30 23:52:47 +00001964 if (argv[i][0] != '-')
1965 break;
sewardj45f4e7c2005-09-27 19:20:21 +00001966 if (VG_STREQ(argv[i], "--"))
sewardj10759312005-05-30 23:52:47 +00001967 break;
sewardj45f4e7c2005-09-27 19:20:21 +00001968 if (VG_STREQ(argv[i], "-d"))
sewardj10759312005-05-30 23:52:47 +00001969 loglevel++;
sewardj1cf558c2005-04-25 01:36:56 +00001970 }
1971
1972 /* ... and start the debug logger. Now we can safely emit logging
1973 messages all through startup. */
sewardj10759312005-05-30 23:52:47 +00001974 VG_(debugLog_startup)(loglevel, "Stage 2 (main)");
sewardj45f4e7c2005-09-27 19:20:21 +00001975 VG_(debugLog)(1, "main", "Welcome to Valgrind version "
1976 VERSION " debug logging\n");
1977
1978 //--------------------------------------------------------------
1979 // Ensure we're on a plausible stack.
1980 // p: logging
1981 //--------------------------------------------------------------
1982 VG_(debugLog)(1, "main", "Checking current stack is plausible\n");
sewardjfdf91b42005-09-28 00:53:09 +00001983 { HChar* limLo = (HChar*)(&VG_(interim_stack).bytes[0]);
1984 HChar* limHi = limLo + sizeof(VG_(interim_stack));
sewardj45f4e7c2005-09-27 19:20:21 +00001985 HChar* aLocal = (HChar*)&zero; /* any auto local will do */
1986 if (aLocal < limLo || aLocal >= limHi) {
1987 /* something's wrong. Stop. */
1988 VG_(debugLog)(0, "main", "Root stack %p to %p, a local %p\n",
1989 limLo, limHi, aLocal );
1990 VG_(debugLog)(0, "main", "Valgrind: FATAL: "
1991 "Initial stack switched failed.\n");
1992 VG_(debugLog)(0, "main", " Cannot continue. Sorry.\n");
1993 VG_(exit)(1);
1994 }
1995 }
1996
1997 //--------------------------------------------------------------
1998 // Ensure we have a plausible pointer to the stack on which
1999 // we gained control (not the current stack!)
2000 // p: logging
2001 //--------------------------------------------------------------
2002 VG_(debugLog)(1, "main", "Checking initial stack was noted\n");
sewardjfdf91b42005-09-28 00:53:09 +00002003 if (sp_at_startup == 0) {
sewardj45f4e7c2005-09-27 19:20:21 +00002004 VG_(debugLog)(0, "main", "Valgrind: FATAL: "
2005 "Initial stack was not noted.\n");
2006 VG_(debugLog)(0, "main", " Cannot continue. Sorry.\n");
2007 VG_(exit)(1);
2008 }
2009
2010 //--------------------------------------------------------------
2011 // Start up the address space manager, and determine the
2012 // approximate location of the client's stack
2013 // p: logging, plausible-stack
2014 //--------------------------------------------------------------
2015 VG_(debugLog)(1, "main", "Starting the address space manager\n");
sewardjfdf91b42005-09-28 00:53:09 +00002016 clstack_top = VG_(am_startup)( sp_at_startup );
sewardj45f4e7c2005-09-27 19:20:21 +00002017 VG_(debugLog)(1, "main", "Address space manager is running\n");
2018
2019 //--------------------------------------------------------------
2020 // Start up the dynamic memory manager
2021 // p: address space management
2022 // In fact m_mallocfree is self-initialising, so there's no
2023 // initialisation call to do. Instead, try a simple malloc/
2024 // free pair right now to check that nothing is broken.
2025 //--------------------------------------------------------------
2026 VG_(debugLog)(1, "main", "Starting the dynamic memory manager\n");
2027 { void* p = VG_(malloc)( 12345 );
2028 if (p) VG_(free)( p );
2029 }
2030 VG_(debugLog)(1, "main", "Dynamic memory manager is running\n");
sewardj1cf558c2005-04-25 01:36:56 +00002031
nethercotef4928da2004-06-15 10:54:40 +00002032 //============================================================
sewardj45f4e7c2005-09-27 19:20:21 +00002033 //
2034 // Dynamic memory management is now available.
2035 //
nethercotef4928da2004-06-15 10:54:40 +00002036 //============================================================
2037
sewardj45f4e7c2005-09-27 19:20:21 +00002038 //--------------------------------------------------------------
2039 // Look for alternative libdir
2040 { HChar *cp = VG_(getenv)(VALGRIND_LIB);
2041 if (cp != NULL)
2042 VG_(libdir) = cp;
2043 }
2044
2045 //--------------------------------------------------------------
2046 // Extract the launcher name from the environment.
2047 VG_(debugLog)(1, "main", "Getting stage1's name\n");
2048 VG_(name_of_launcher) = VG_(getenv)(VALGRIND_LAUNCHER);
2049 if (VG_(name_of_launcher) == NULL) {
2050 VG_(printf)("valgrind: You cannot run '%s' directly.\n", argv[0]);
2051 VG_(printf)("valgrind: You should use $prefix/bin/valgrind.\n");
2052 VG_(exit)(1);
2053 }
2054
2055 //--------------------------------------------------------------
fitzhardingeb50068f2004-02-24 23:42:55 +00002056 // Get the current process datasize rlimit, and set it to zero.
2057 // This prevents any internal uses of brk() from having any effect.
2058 // We remember the old value so we can restore it on exec, so that
2059 // child processes will have a reasonable brk value.
2060 VG_(getrlimit)(VKI_RLIMIT_DATA, &VG_(client_rlimit_data));
2061 zero.rlim_max = VG_(client_rlimit_data).rlim_max;
2062 VG_(setrlimit)(VKI_RLIMIT_DATA, &zero);
thughesc37184f2004-09-11 14:16:57 +00002063
2064 // Get the current process stack rlimit.
2065 VG_(getrlimit)(VKI_RLIMIT_STACK, &VG_(client_rlimit_stack));
2066
sewardje2d1e672005-11-12 23:10:48 +00002067 //--------------------------------------------------------------
2068 // Figure out what sort of CPU we're on, and whether it is
2069 // able to run V.
2070 VG_(debugLog)(1, "main", "Get hardware capabilities ...\n");
2071 { VexArch vex_arch;
2072 VexArchInfo vex_archinfo;
2073 Bool ok = VG_(machine_get_hwcaps)();
2074 if (!ok) {
2075 VG_(printf)("\n");
2076 VG_(printf)("valgrind: fatal error: unsupported CPU.\n");
2077 VG_(printf)(" Supported CPUs are:\n");
2078 VG_(printf)(" * x86 (practically any; Pentium-I or above), "
2079 "AMD Athlon or above)\n");
2080 VG_(printf)(" * AMD Athlon64/Opteron\n");
2081 VG_(printf)(" * PowerPC (most; ppc405 and above)\n");
2082 VG_(printf)("\n");
2083 VG_(exit)(1);
2084 }
2085 VG_(machine_get_VexArchInfo)( &vex_arch, &vex_archinfo );
sewardje3121f32006-01-27 21:23:23 +00002086 VG_(debugLog)(
2087 1, "main", "... arch = %s, hwcaps = %s\n",
2088 LibVEX_ppVexArch ( vex_arch ),
2089 LibVEX_ppVexHwCaps ( vex_arch, vex_archinfo.hwcaps )
2090 );
sewardje2d1e672005-11-12 23:10:48 +00002091 }
2092
sewardj45f4e7c2005-09-27 19:20:21 +00002093 //============================================================
2094 // Command line argument handling order:
2095 // * If --help/--help-debug are present, show usage message
2096 // (including the tool-specific usage)
2097 // * (If no --tool option given, default to Memcheck)
2098 // * Then, if client is missing, abort with error msg
2099 // * Then, if any cmdline args are bad, abort with error msg
2100 //============================================================
2101
2102 //--------------------------------------------------------------
2103 // Split up argv into: C args, V args, V extra args, and exename.
2104 // p: dynamic memory allocation
2105 //--------------------------------------------------------------
2106 VG_(debugLog)(1, "main", "Split up command line\n");
2107 VG_(split_up_argv)( argc, argv );
2108 if (0) {
2109 for (i = 0; i < VG_(args_for_valgrind).used; i++)
2110 VG_(printf)("varg %s\n", VG_(args_for_valgrind).strs[i]);
2111 VG_(printf)(" exe %s\n", VG_(args_the_exename));
2112 for (i = 0; i < VG_(args_for_client).used; i++)
2113 VG_(printf)("carg %s\n", VG_(args_for_client).strs[i]);
nethercote71980f02004-01-24 18:18:54 +00002114 }
2115
2116 //--------------------------------------------------------------
sewardj45f4e7c2005-09-27 19:20:21 +00002117 // Extract tool name and whether help has been requested.
2118 // Note we can't print the help message yet, even if requested,
2119 // because the tool has not been initialised.
2120 // p: split_up_argv [for VG_(args_for_valgrind)]
nethercote71980f02004-01-24 18:18:54 +00002121 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002122 VG_(debugLog)(1, "main", "Preprocess command line opts\n");
sewardj45f4e7c2005-09-27 19:20:21 +00002123 get_helprequest_and_toolname(&need_help, &toolname);
nethercote71980f02004-01-24 18:18:54 +00002124
sewardj45f4e7c2005-09-27 19:20:21 +00002125 // Set default vex control params
2126 LibVEX_default_VexControl(& VG_(clo_vex_control));
nethercote71980f02004-01-24 18:18:54 +00002127
2128 //--------------------------------------------------------------
2129 // Load client executable, finding in $PATH if necessary
sewardj45f4e7c2005-09-27 19:20:21 +00002130 // p: get_helprequest_and_toolname() [for 'exec', 'need_help']
nethercote71980f02004-01-24 18:18:54 +00002131 // p: layout_remaining_space [so there's space]
2132 //--------------------------------------------------------------
sewardj45f4e7c2005-09-27 19:20:21 +00002133 if (!need_help) {
2134 VG_(debugLog)(1, "main", "Loading client\n");
nethercote71980f02004-01-24 18:18:54 +00002135
sewardj45f4e7c2005-09-27 19:20:21 +00002136 if (VG_(args_the_exename) == NULL)
2137 missing_prog();
2138
sewardj13247ca2005-12-30 22:52:20 +00002139 load_client(&info, &initial_client_IP, &initial_client_TOC);
sewardj45f4e7c2005-09-27 19:20:21 +00002140 }
nethercote71980f02004-01-24 18:18:54 +00002141
2142 //--------------------------------------------------------------
2143 // Set up client's environment
sewardj45f4e7c2005-09-27 19:20:21 +00002144 // p: set-libdir [for VG_(libdir)]
2145 // p: get_helprequest_and_toolname [for toolname]
nethercote71980f02004-01-24 18:18:54 +00002146 //--------------------------------------------------------------
sewardj45f4e7c2005-09-27 19:20:21 +00002147 if (!need_help) {
2148 VG_(debugLog)(1, "main", "Setup client env\n");
2149 env = setup_client_env(envp, toolname);
2150 }
nethercote71980f02004-01-24 18:18:54 +00002151
2152 //--------------------------------------------------------------
nethercote5ee67ca2004-06-22 14:00:09 +00002153 // Setup client stack, eip, and VG_(client_arg[cv])
nethercote71980f02004-01-24 18:18:54 +00002154 // p: load_client() [for 'info']
2155 // p: fix_environment() [for 'env']
2156 //--------------------------------------------------------------
sewardj45f4e7c2005-09-27 19:20:21 +00002157 if (!need_help) {
2158 void* init_sp = argv - 1;
2159 SizeT m1 = 1024 * 1024;
2160 SizeT m8 = 8 * m1;
2161 VG_(debugLog)(1, "main", "Setup client stack\n");
2162 clstack_max_size = (SizeT)VG_(client_rlimit_stack).rlim_cur;
2163 if (clstack_max_size < m1) clstack_max_size = m1;
2164 if (clstack_max_size > m8) clstack_max_size = m8;
2165 clstack_max_size = VG_PGROUNDUP(clstack_max_size);
sewardjb5f6f512005-03-10 23:59:00 +00002166
sewardj45f4e7c2005-09-27 19:20:21 +00002167 initial_client_SP
2168 = setup_client_stack( init_sp, env,
2169 &info, &client_auxv,
2170 clstack_top, clstack_max_size );
2171
2172 VG_(free)(env);
2173
2174 VG_(debugLog)(2, "main",
2175 "Client info: "
sewardj13247ca2005-12-30 22:52:20 +00002176 "initial_IP=%p initial_SP=%p initial_TOC=%p brk_base=%p\n",
sewardj45f4e7c2005-09-27 19:20:21 +00002177 (void*)initial_client_IP,
2178 (void*)initial_client_SP,
sewardj13247ca2005-12-30 22:52:20 +00002179 (void*)initial_client_TOC,
sewardj45f4e7c2005-09-27 19:20:21 +00002180 (void*)VG_(brk_base) );
nethercotec25c4492004-10-18 11:52:17 +00002181 }
nethercote71980f02004-01-24 18:18:54 +00002182
sewardj45f4e7c2005-09-27 19:20:21 +00002183 //--------------------------------------------------------------
2184 // Setup client data (brk) segment. Initially a 1-page segment
2185 // which abuts a shrinkable reservation.
2186 // p: load_client() [for 'info' and hence VG_(brk_base)]
2187 //--------------------------------------------------------------
2188 if (!need_help) {
2189 SizeT m1 = 1024 * 1024;
2190 SizeT m8 = 8 * m1;
2191 SizeT dseg_max_size = (SizeT)VG_(client_rlimit_data).rlim_cur;
2192 VG_(debugLog)(1, "main", "Setup client data (brk) segment\n");
2193 if (dseg_max_size < m1) dseg_max_size = m1;
2194 if (dseg_max_size > m8) dseg_max_size = m8;
2195 dseg_max_size = VG_PGROUNDUP(dseg_max_size);
2196
2197 setup_client_dataseg( dseg_max_size );
2198 }
nethercote71980f02004-01-24 18:18:54 +00002199
2200 //==============================================================
sewardj45f4e7c2005-09-27 19:20:21 +00002201 //
2202 // Finished loading/setting up the client address space.
2203 //
nethercote71980f02004-01-24 18:18:54 +00002204 //==============================================================
2205
2206 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002207 // setup file descriptors
2208 // p: n/a
2209 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002210 VG_(debugLog)(1, "main", "Setup file descriptors\n");
nethercote71980f02004-01-24 18:18:54 +00002211 setup_file_descriptors();
2212
2213 //--------------------------------------------------------------
sewardj45f4e7c2005-09-27 19:20:21 +00002214 // create the fake /proc/<pid>/cmdline file and then unlink it,
2215 // but hold onto the fd, so we can hand it out to the client
2216 // when it tries to open /proc/<pid>/cmdline for itself.
2217 // p: setup file descriptors
nethercotec314eba2004-07-15 12:59:41 +00002218 //--------------------------------------------------------------
sewardj45f4e7c2005-09-27 19:20:21 +00002219 if (!need_help) {
2220 HChar buf[50], buf2[50+64];
2221 HChar nul[1];
2222 Int fd, r;
2223 HChar* exename;
nethercotec314eba2004-07-15 12:59:41 +00002224
sewardj45f4e7c2005-09-27 19:20:21 +00002225 VG_(debugLog)(1, "main", "Create fake /proc/<pid>/cmdline\n");
2226
2227 VG_(sprintf)(buf, "proc_%d_cmdline", VG_(getpid)());
2228 fd = VG_(mkstemp)( buf, buf2 );
2229 if (fd == -1)
2230 config_error("Can't create client cmdline file in /tmp.");
2231
2232 nul[0] = 0;
2233 exename = VG_(args_the_exename) ? VG_(args_the_exename)
2234 : "unknown_exename";
2235
2236 VG_(write)(fd, VG_(args_the_exename),
2237 VG_(strlen)( VG_(args_the_exename) ));
2238 VG_(write)(fd, nul, 1);
2239
2240 for (i = 0; i < VG_(args_for_client).used; i++) {
2241 VG_(write)(fd, VG_(args_for_client).strs[i],
2242 VG_(strlen)( VG_(args_for_client).strs[i] ));
2243 VG_(write)(fd, nul, 1);
2244 }
2245
2246 /* Don't bother to seek the file back to the start; instead do
2247 it every time a copy of it is given out (by PRE(sys_open)).
2248 That is probably more robust across fork() etc. */
2249
2250 /* Now delete it, but hang on to the fd. */
2251 r = VG_(unlink)( buf2 );
2252 if (r)
2253 config_error("Can't delete client cmdline file in /tmp.");
2254
2255 VG_(cl_cmdline_fd) = fd;
2256 }
nethercotec314eba2004-07-15 12:59:41 +00002257
2258 //--------------------------------------------------------------
sewardj45f4e7c2005-09-27 19:20:21 +00002259 // Init tool part 1: pre_clo_init
nethercotec314eba2004-07-15 12:59:41 +00002260 // p: setup_client_stack() [for 'VG_(client_arg[cv]']
nethercotec314eba2004-07-15 12:59:41 +00002261 // p: setup_file_descriptors() [for 'VG_(fd_xxx_limit)']
nethercote71980f02004-01-24 18:18:54 +00002262 //--------------------------------------------------------------
njn64c83242005-06-21 01:54:38 +00002263 {
2264 Char* s;
2265 Bool ok;
sewardj45f4e7c2005-09-27 19:20:21 +00002266 VG_(debugLog)(1, "main", "Initialise the tool part 1 (pre_clo_init)\n");
2267 (VG_(tool_info).tl_pre_clo_init)();
2268 ok = VG_(sanity_check_needs)( &s );
njn64c83242005-06-21 01:54:38 +00002269 if (!ok) {
2270 VG_(tool_panic)(s);
2271 }
2272 }
nethercote71980f02004-01-24 18:18:54 +00002273
sewardj45f4e7c2005-09-27 19:20:21 +00002274 //--------------------------------------------------------------
nethercotef4928da2004-06-15 10:54:40 +00002275 // If --tool and --help/--help-debug was given, now give the core+tool
2276 // help message
sewardj45f4e7c2005-09-27 19:20:21 +00002277 // p: get_helprequest_and_toolname() [for 'need_help']
2278 // p: tl_pre_clo_init [for 'VG_(tdict).usage']
2279 //--------------------------------------------------------------
2280 VG_(debugLog)(1, "main", "Print help and quit, if requested\n");
nethercotef4928da2004-06-15 10:54:40 +00002281 if (need_help) {
sewardj45f4e7c2005-09-27 19:20:21 +00002282 usage_NORETURN(/*--help-debug?*/2 == need_help);
nethercotef4928da2004-06-15 10:54:40 +00002283 }
nethercotec314eba2004-07-15 12:59:41 +00002284
sewardj45f4e7c2005-09-27 19:20:21 +00002285 //--------------------------------------------------------------
2286 // Process command line options to Valgrind + tool
2287 // p: setup_client_stack() [for 'VG_(client_arg[cv]']
2288 // p: setup_file_descriptors() [for 'VG_(fd_xxx_limit)']
2289 //--------------------------------------------------------------
2290 VG_(debugLog)(1, "main", "Process Valgrind's command line options, "
sewardja48a4932005-09-29 11:09:56 +00002291 "setup logging\n");
sewardj45f4e7c2005-09-27 19:20:21 +00002292 logging_to_fd = process_cmd_line_options(client_auxv, toolname);
2293
2294 //--------------------------------------------------------------
sewardj592ae092005-11-08 19:01:44 +00002295 // Zeroise the millisecond counter by doing a first read of it.
2296 // p: none
2297 //--------------------------------------------------------------
2298 (void) VG_(read_millisecond_timer)();
2299
2300 //--------------------------------------------------------------
sewardj45f4e7c2005-09-27 19:20:21 +00002301 // Print the preamble
2302 // p: tl_pre_clo_init [for 'VG_(details).name' and friends]
2303 // p: process_cmd_line_options() [for VG_(clo_verbosity), VG_(clo_xml),
2304 // VG_(clo_log_file_qualifier),
2305 // logging_to_fd]
2306 //--------------------------------------------------------------
2307 VG_(debugLog)(1, "main", "Print the preamble...\n");
2308 print_preamble(logging_to_fd, toolname);
2309 VG_(debugLog)(1, "main", "...finished the preamble\n");
2310
2311 //--------------------------------------------------------------
2312 // Init tool part 2: post_clo_init
2313 // p: setup_client_stack() [for 'VG_(client_arg[cv]']
2314 // p: setup_file_descriptors() [for 'VG_(fd_xxx_limit)']
2315 // p: print_preamble() [so any warnings printed in post_clo_init
2316 // are shown after the preamble]
2317 //--------------------------------------------------------------
2318 VG_(debugLog)(1, "main", "Initialise the tool part 2 (post_clo_init)\n");
njn51d827b2005-05-09 01:02:08 +00002319 VG_TDICT_CALL(tool_post_clo_init);
nethercotef4928da2004-06-15 10:54:40 +00002320
2321 //--------------------------------------------------------------
sewardj45f4e7c2005-09-27 19:20:21 +00002322 // Initialise translation table and translation cache
2323 // p: aspacem [??]
2324 // p: tl_pre_clo_init [for 'VG_(details).avg_translation_sizeB']
nethercote71980f02004-01-24 18:18:54 +00002325 //--------------------------------------------------------------
sewardj45f4e7c2005-09-27 19:20:21 +00002326 VG_(debugLog)(1, "main", "Initialise TT/TC\n");
2327 VG_(init_tt_tc)();
sewardjb5f6f512005-03-10 23:59:00 +00002328
sewardj45f4e7c2005-09-27 19:20:21 +00002329 //--------------------------------------------------------------
2330 // Initialise the redirect table.
2331 // p: init_tt_tc [so it can call VG_(search_transtab) safely]
2332 // p: aspacem [so can change ownership of sysinfo pages]
2333 //--------------------------------------------------------------
2334 VG_(debugLog)(1, "main", "Initialise redirects\n");
sewardj0ec07f32006-01-12 12:32:32 +00002335 VG_(redir_initialise)();
nethercote71980f02004-01-24 18:18:54 +00002336
2337 //--------------------------------------------------------------
2338 // Allow GDB attach
2339 // p: process_cmd_line_options() [for VG_(clo_wait_for_gdb)]
2340 //--------------------------------------------------------------
2341 /* Hook to delay things long enough so we can get the pid and
2342 attach GDB in another shell. */
2343 if (VG_(clo_wait_for_gdb)) {
sewardj8211a572005-06-23 21:37:47 +00002344 Long q, iters;
sewardj1fbc1a52005-04-25 02:05:54 +00002345 VG_(debugLog)(1, "main", "Wait for GDB\n");
sewardj93ab8572005-02-06 14:10:40 +00002346 VG_(printf)("pid=%d, entering delay loop\n", VG_(getpid)());
2347 /* jrs 20050206: I don't understand why this works on x86. On
2348 amd64 the obvious analogues (jump *$rip or jump *$rcx) don't
2349 work. */
2350 /* do "jump *$eip" to skip this in gdb (x86) */
2351 //VG_(do_syscall0)(__NR_pause);
sewardj8211a572005-06-23 21:37:47 +00002352
2353# if defined(VGP_x86_linux)
2354 iters = 5;
sewardj2c48c7b2005-11-29 13:05:56 +00002355# elif defined(VGP_amd64_linux) || defined(VGP_ppc64_linux)
sewardj8211a572005-06-23 21:37:47 +00002356 iters = 10;
2357# elif defined(VGP_ppc32_linux)
sewardjd714d2e2005-07-08 18:24:04 +00002358 iters = 5;
sewardj8211a572005-06-23 21:37:47 +00002359# else
2360# error "Unknown plat"
2361# endif
2362
2363 iters *= 1000*1000*1000;
2364 for (q = 0; q < iters; q++)
2365 ;
nethercote71980f02004-01-24 18:18:54 +00002366 }
2367
sewardjb5d320c2005-03-13 18:57:15 +00002368 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002369 // Search for file descriptors that are inherited from our parent
2370 // p: process_cmd_line_options [for VG_(clo_track_fds)]
2371 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002372 if (VG_(clo_track_fds)) {
2373 VG_(debugLog)(1, "main", "Init preopened fds\n");
nethercote71980f02004-01-24 18:18:54 +00002374 VG_(init_preopened_fds)();
sewardj1fbc1a52005-04-25 02:05:54 +00002375 }
nethercote71980f02004-01-24 18:18:54 +00002376
2377 //--------------------------------------------------------------
sewardj45f4e7c2005-09-27 19:20:21 +00002378 // Load debug info for the existing segments.
2379 // p: setup_code_redirect_table [so that redirs can be recorded]
2380 // p: mallocfree
2381 // p: probably: setup fds and process CLOs, so that logging works
2382 //--------------------------------------------------------------
2383 VG_(debugLog)(1, "main", "Load initial debug info\n");
2384 { Addr* seg_starts;
2385 Int n_seg_starts;
2386
2387 seg_starts = get_seg_starts( &n_seg_starts );
2388 vg_assert(seg_starts && n_seg_starts > 0);
2389
sewardjf72cced2005-11-08 00:45:47 +00002390 /* show them all to the debug info reader. allow_SkFileV has to
2391 be True here so that we read info from the valgrind executable
2392 itself. */
sewardj45f4e7c2005-09-27 19:20:21 +00002393 for (i = 0; i < n_seg_starts; i++)
sewardjf72cced2005-11-08 00:45:47 +00002394 VG_(di_notify_mmap)( seg_starts[i], True/*allow_SkFileV*/ );
sewardj45f4e7c2005-09-27 19:20:21 +00002395
2396 VG_(free)( seg_starts );
2397 }
2398
2399 //--------------------------------------------------------------
2400 // Tell aspacem of ownership change of the asm helpers, so that
2401 // m_translate allows them to be translated. However, only do this
2402 // after the initial debug info read, since making a hole in the
2403 // address range for the stage2 binary confuses the debug info reader.
2404 // p: aspacem
2405 //--------------------------------------------------------------
2406 { Bool change_ownership_v_c_OK;
sewardj1a85f4f2006-01-12 21:15:35 +00002407 Addr co_start = VG_PGROUNDDN( (Addr)&VG_(trampoline_stuff_start) );
2408 Addr co_endPlus = VG_PGROUNDUP( (Addr)&VG_(trampoline_stuff_end) );
sewardj45f4e7c2005-09-27 19:20:21 +00002409 VG_(debugLog)(1,"redir",
2410 "transfer ownership V -> C of 0x%llx .. 0x%llx\n",
2411 (ULong)co_start, (ULong)co_endPlus-1 );
2412
2413 change_ownership_v_c_OK
2414 = VG_(am_change_ownership_v_to_c)( co_start, co_endPlus - co_start );
2415 vg_assert(change_ownership_v_c_OK);
2416 }
2417
2418 //--------------------------------------------------------------
2419 // Tell the tool about the initial client memory permissions
2420 // p: aspacem
2421 // p: mallocfree
2422 // p: setup_client_stack
2423 // p: setup_client_dataseg
2424 //--------------------------------------------------------------
2425 VG_(debugLog)(1, "main", "Tell tool about initial permissions\n");
2426 { Addr* seg_starts;
2427 Int n_seg_starts;
2428 NSegment* seg;
2429
2430 seg_starts = get_seg_starts( &n_seg_starts );
2431 vg_assert(seg_starts && n_seg_starts > 0);
2432
2433 /* show interesting ones to the tool */
2434 for (i = 0; i < n_seg_starts; i++) {
2435 seg = VG_(am_find_nsegment)( seg_starts[i] );
2436 vg_assert(seg);
2437 if (seg->kind == SkFileC || seg->kind == SkAnonC) {
2438 VG_(debugLog)(2, "main",
2439 "tell tool about %010lx-%010lx %c%c%c\n",
2440 seg->start, seg->end,
2441 seg->hasR ? 'r' : '-',
2442 seg->hasW ? 'w' : '-',
2443 seg->hasX ? 'x' : '-' );
2444 VG_TRACK( new_mem_startup, seg->start, seg->end+1-seg->start,
2445 seg->hasR, seg->hasW, seg->hasX );
2446 }
2447 }
2448
2449 VG_(free)( seg_starts );
2450
2451 /* Also do the initial stack permissions. */
2452 seg = VG_(am_find_nsegment)( initial_client_SP );
2453 vg_assert(seg);
2454 vg_assert(seg->kind == SkAnonC);
2455 vg_assert(initial_client_SP >= seg->start);
2456 vg_assert(initial_client_SP <= seg->end);
2457
2458 /* Stuff below the initial SP is unaddressable. */
2459 /* NB: shouldn't this take into account the VG_STACK_REDZONE_SZB
2460 bytes below SP? */
2461 VG_TRACK( die_mem_stack, seg->start, initial_client_SP - seg->start );
2462 VG_(debugLog)(2, "main", "mark stack inaccessible %010lx-%010lx\n",
2463 seg->start, initial_client_SP-1 );
2464
2465 /* Also the assembly helpers. */
2466 VG_TRACK( new_mem_startup,
2467 (Addr)&VG_(trampoline_stuff_start),
tom151a6392005-11-11 12:30:36 +00002468 (Addr)&VG_(trampoline_stuff_end) - (Addr)&VG_(trampoline_stuff_start),
sewardj45f4e7c2005-09-27 19:20:21 +00002469 False, /* readable? */
2470 False, /* writable? */
2471 True /* executable? */ );
2472 }
2473
2474 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002475 // Initialise the scheduler
nethercote71980f02004-01-24 18:18:54 +00002476 // p: setup_file_descriptors() [else VG_(safe_fd)() breaks]
sewardj45f4e7c2005-09-27 19:20:21 +00002477 // p: setup_client_stack
nethercote71980f02004-01-24 18:18:54 +00002478 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002479 VG_(debugLog)(1, "main", "Initialise scheduler\n");
sewardj45f4e7c2005-09-27 19:20:21 +00002480 { NSegment* seg = VG_(am_find_nsegment)( initial_client_SP );
2481 vg_assert(seg);
2482 vg_assert(seg->kind == SkAnonC);
2483 vg_assert(initial_client_SP >= seg->start);
2484 vg_assert(initial_client_SP <= seg->end);
2485 VG_(scheduler_init)( seg->end, clstack_max_size );
2486 }
nethercote71980f02004-01-24 18:18:54 +00002487
2488 //--------------------------------------------------------------
sewardjb5f6f512005-03-10 23:59:00 +00002489 // Initialise the pthread model
2490 // p: ?
sewardj2a99cf62004-11-24 10:44:19 +00002491 // load_client() [for 'client_eip']
2492 // setup_client_stack() [for 'sp_at_startup']
2493 // setup_scheduler() [for the rest of state 1 stuff]
2494 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002495 VG_(debugLog)(1, "main", "Initialise thread 1's state\n");
sewardj13247ca2005-12-30 22:52:20 +00002496 init_thread1state( initial_client_IP,
2497 initial_client_SP,
2498 initial_client_TOC,
sewardj45f4e7c2005-09-27 19:20:21 +00002499 &VG_(threads)[1].arch);
njnea4b28c2004-11-30 16:04:58 +00002500
sewardj2a99cf62004-11-24 10:44:19 +00002501 //--------------------------------------------------------------
sewardj39b88fb2005-03-12 15:16:07 +00002502 // Initialise the pthread model
2503 // p: ?
nethercote71980f02004-01-24 18:18:54 +00002504 //--------------------------------------------------------------
sewardjb5f6f512005-03-10 23:59:00 +00002505 //if (VG_(clo_model_pthreads))
2506 // VG_(pthread_init)();
nethercote71980f02004-01-24 18:18:54 +00002507
2508 //--------------------------------------------------------------
2509 // Initialise the signal handling subsystem
sewardjb5f6f512005-03-10 23:59:00 +00002510 // p: n/a
nethercote71980f02004-01-24 18:18:54 +00002511 //--------------------------------------------------------------
2512 // Nb: temporarily parks the saved blocking-mask in saved_sigmask.
sewardj1fbc1a52005-04-25 02:05:54 +00002513 VG_(debugLog)(1, "main", "Initialise signal management\n");
nethercote71980f02004-01-24 18:18:54 +00002514 VG_(sigstartup_actions)();
2515
2516 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002517 // Read suppression file
2518 // p: process_cmd_line_options() [for VG_(clo_suppressions)]
2519 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002520 if (VG_(needs).core_errors || VG_(needs).tool_errors) {
2521 VG_(debugLog)(1, "main", "Load suppressions\n");
nethercote71980f02004-01-24 18:18:54 +00002522 VG_(load_suppressions)();
sewardj1fbc1a52005-04-25 02:05:54 +00002523 }
nethercote71980f02004-01-24 18:18:54 +00002524
2525 //--------------------------------------------------------------
rjwalsh0140af52005-06-04 20:42:33 +00002526 // register client stack
2527 //--------------------------------------------------------------
njn945ed2e2005-06-24 03:28:30 +00002528 VG_(clstk_id) = VG_(register_stack)(VG_(clstk_base), VG_(clstk_end));
rjwalsh0140af52005-06-04 20:42:33 +00002529
2530 //--------------------------------------------------------------
sewardj45f4e7c2005-09-27 19:20:21 +00002531 // Show the address space state so far
2532 //--------------------------------------------------------------
2533 VG_(debugLog)(1, "main", "\n");
2534 VG_(debugLog)(1, "main", "\n");
2535 VG_(am_show_nsegments)(1,"Memory layout at client startup");
2536 VG_(debugLog)(1, "main", "\n");
2537 VG_(debugLog)(1, "main", "\n");
2538
2539 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002540 // Run!
2541 //--------------------------------------------------------------
sewardj71bc3cb2005-05-19 00:25:45 +00002542 if (VG_(clo_xml)) {
sewardj68cde6f2005-07-19 12:17:51 +00002543 HChar buf[50];
sewardj592ae092005-11-08 19:01:44 +00002544 VG_(elapsed_wallclock_time)(buf);
sewardj753673f2005-08-09 22:03:08 +00002545 VG_(message)(Vg_UserMsg, "<status>\n"
2546 " <state>RUNNING</state>\n"
2547 " <time>%t</time>\n"
2548 "</status>",
2549 buf);
sewardj71bc3cb2005-05-19 00:25:45 +00002550 VG_(message)(Vg_UserMsg, "");
2551 }
2552
sewardj1fbc1a52005-04-25 02:05:54 +00002553 VG_(debugLog)(1, "main", "Running thread 1\n");
sewardj1ae3f3a2005-09-28 10:47:38 +00002554
sewardj1d887112005-05-30 21:44:08 +00002555 /* As a result of the following call, the last thread standing
sewardj1ae3f3a2005-09-28 10:47:38 +00002556 eventually winds up running shutdown_actions_NORETURN
2557 just below. Unfortunately, simply exporting said function
2558 causes m_main to be part of a module cycle, which is pretty
2559 nonsensical. So instead of doing that, the address of said
2560 function is stored in a global variable 'owned' by m_syswrap,
2561 and it uses that function pointer to get back here when it needs
2562 to. */
2563
2564 /* Set continuation address. */
2565 VG_(address_of_m_main_shutdown_actions_NORETURN)
2566 = & shutdown_actions_NORETURN;
2567
2568 /* Run the first thread, eventually ending up at the continuation
2569 address. */
njnaf839f52005-06-23 03:27:57 +00002570 VG_(main_thread_wrapper_NORETURN)(1);
nethercote71980f02004-01-24 18:18:54 +00002571
sewardj1d887112005-05-30 21:44:08 +00002572 /*NOTREACHED*/
2573 vg_assert(0);
sewardjb5f6f512005-03-10 23:59:00 +00002574}
2575
sewardj1ae3f3a2005-09-28 10:47:38 +00002576/* Do everything which needs doing when the last thread exits. */
sewardjb5f6f512005-03-10 23:59:00 +00002577
sewardj1ae3f3a2005-09-28 10:47:38 +00002578static
2579void shutdown_actions_NORETURN( ThreadId tid,
2580 VgSchedReturnCode tids_schedretcode )
sewardjb5f6f512005-03-10 23:59:00 +00002581{
sewardj1d887112005-05-30 21:44:08 +00002582 VG_(debugLog)(1, "main", "entering VG_(shutdown_actions_NORETURN)\n");
2583
2584 vg_assert( VG_(count_living_threads)() == 1 );
sewardjb5f6f512005-03-10 23:59:00 +00002585 vg_assert(VG_(is_running_thread)(tid));
2586
2587 // Wait for all other threads to exit.
njn7b85dd52005-06-12 17:26:29 +00002588 VG_(reap_threads)(tid);
sewardjb5f6f512005-03-10 23:59:00 +00002589
2590 VG_(clo_model_pthreads) = False;
2591
2592 // Clean the client up before the final report
njn9cb54ac2005-06-12 04:19:17 +00002593 final_tidyup(tid);
sewardjb5f6f512005-03-10 23:59:00 +00002594
2595 // OK, done
2596 VG_(exit_thread)(tid);
2597
2598 /* should be no threads left */
2599 vg_assert(VG_(count_living_threads)() == 0);
2600
2601 VG_(threads)[tid].status = VgTs_Empty;
nethercote71980f02004-01-24 18:18:54 +00002602 //--------------------------------------------------------------
2603 // Finalisation: cleanup, messages, etc. Order no so important, only
2604 // affects what order the messages come.
2605 //--------------------------------------------------------------
2606 if (VG_(clo_verbosity) > 0)
2607 VG_(message)(Vg_UserMsg, "");
2608
sewardj71bc3cb2005-05-19 00:25:45 +00002609 if (VG_(clo_xml)) {
sewardj68cde6f2005-07-19 12:17:51 +00002610 HChar buf[50];
sewardj9f297ca2005-05-20 02:29:52 +00002611 if (VG_(needs).core_errors || VG_(needs).tool_errors) {
2612 VG_(show_error_counts_as_XML)();
2613 VG_(message)(Vg_UserMsg, "");
2614 }
sewardj592ae092005-11-08 19:01:44 +00002615 VG_(elapsed_wallclock_time)(buf);
sewardj753673f2005-08-09 22:03:08 +00002616 VG_(message)(Vg_UserMsg, "<status>\n"
2617 " <state>FINISHED</state>\n"
2618 " <time>%t</time>\n"
2619 "</status>",
2620 buf);
sewardj71bc3cb2005-05-19 00:25:45 +00002621 VG_(message)(Vg_UserMsg, "");
2622 }
2623
nethercote71980f02004-01-24 18:18:54 +00002624 /* Print out file descriptor summary and stats. */
2625 if (VG_(clo_track_fds))
nethercote3a42fb82004-08-03 18:08:50 +00002626 VG_(show_open_fds)();
nethercote71980f02004-01-24 18:18:54 +00002627
njn95ec8702004-11-22 16:46:13 +00002628 if (VG_(needs).core_errors || VG_(needs).tool_errors)
nethercote71980f02004-01-24 18:18:54 +00002629 VG_(show_all_errors)();
2630
njn51d827b2005-05-09 01:02:08 +00002631 VG_TDICT_CALL(tool_fini, 0/*exitcode*/);
nethercote71980f02004-01-24 18:18:54 +00002632
sewardj71bc3cb2005-05-19 00:25:45 +00002633 if (VG_(clo_xml)) {
2634 VG_(message)(Vg_UserMsg, "");
2635 VG_(message)(Vg_UserMsg, "</valgrindoutput>");
2636 VG_(message)(Vg_UserMsg, "");
2637 }
2638
nethercote885dd912004-08-03 23:14:00 +00002639 VG_(sanity_check_general)( True /*include expensive checks*/ );
nethercote71980f02004-01-24 18:18:54 +00002640
2641 if (VG_(clo_verbosity) > 1)
nethercote3a42fb82004-08-03 18:08:50 +00002642 print_all_stats();
nethercote71980f02004-01-24 18:18:54 +00002643
njn2025cf92005-06-26 20:44:48 +00002644 if (VG_(clo_profile_flags) > 0) {
2645 #define N_MAX 100
2646 BBProfEntry tops[N_MAX];
2647 ULong score_total = VG_(get_BB_profile) (tops, N_MAX);
2648 show_BB_profile(tops, N_MAX, score_total);
2649 }
sewardjfa8ec112005-01-19 11:55:34 +00002650
sewardj8b635a42004-11-22 19:01:47 +00002651 /* Print Vex storage stats */
sewardjbf426512005-01-17 18:35:30 +00002652 if (0)
2653 LibVEX_ShowAllocStats();
sewardj1d887112005-05-30 21:44:08 +00002654
njn8aa35852005-06-10 22:59:56 +00002655 /* Ok, finally exit in the os-specific way, according to the scheduler's
2656 return code. In short, if the (last) thread exited by calling
2657 sys_exit, do likewise; if the (last) thread stopped due to a fatal
2658 signal, terminate the entire system with that same fatal signal. */
2659 VG_(debugLog)(1, "core_os",
njn7b85dd52005-06-12 17:26:29 +00002660 "VG_(terminate_NORETURN)(tid=%lld)\n", (ULong)tid);
njn8aa35852005-06-10 22:59:56 +00002661
2662 vg_assert(VG_(count_living_threads)() == 0);
2663
2664 switch (tids_schedretcode) {
2665 case VgSrc_ExitSyscall: /* the normal way out */
2666 VG_(exit)( VG_(threads)[tid].os_state.exitcode );
2667 /* NOT ALIVE HERE! */
2668 VG_(core_panic)("entered the afterlife in main() -- ExitSyscall");
2669 break; /* what the hell :) */
2670
2671 case VgSrc_FatalSig:
2672 /* We were killed by a fatal signal, so replicate the effect */
2673 vg_assert(VG_(threads)[tid].os_state.fatalsig != 0);
2674 VG_(kill_self)(VG_(threads)[tid].os_state.fatalsig);
2675 VG_(core_panic)("main(): signal was supposed to be fatal");
2676 break;
2677
2678 default:
2679 VG_(core_panic)("main(): unexpected scheduler return code");
2680 }
njne96be672005-05-08 19:08:54 +00002681}
sewardj8b635a42004-11-22 19:01:47 +00002682
sewardj1ae3f3a2005-09-28 10:47:38 +00002683/* -------------------- */
2684
2685/* Final clean-up before terminating the process.
2686 Clean up the client by calling __libc_freeres() (if requested)
2687 This is Linux-specific?
2688*/
2689static void final_tidyup(ThreadId tid)
2690{
sewardjcf951812006-01-17 02:22:21 +00002691# if defined(VGP_ppc64_linux)
2692 Addr r2;
2693# endif
sewardj0ec07f32006-01-12 12:32:32 +00002694 Addr __libc_freeres_wrapper = VG_(client___libc_freeres_wrapper);
sewardj1ae3f3a2005-09-28 10:47:38 +00002695
2696 vg_assert(VG_(is_running_thread)(tid));
2697
2698 if ( !VG_(needs).libc_freeres ||
2699 !VG_(clo_run_libc_freeres) ||
sewardj0ec07f32006-01-12 12:32:32 +00002700 0 == __libc_freeres_wrapper )
sewardj1ae3f3a2005-09-28 10:47:38 +00002701 return; /* can't/won't do it */
2702
sewardjcf951812006-01-17 02:22:21 +00002703# if defined(VGP_ppc64_linux)
2704 r2 = VG_(get_tocptr)( __libc_freeres_wrapper );
2705 if (r2 == 0) {
2706 VG_(message)(Vg_UserMsg,
2707 "Caught __NR_exit, but can't run __libc_freeres()");
2708 VG_(message)(Vg_UserMsg,
2709 " since cannot establish TOC pointer for it.");
2710 return;
2711 }
2712# endif
2713
sewardj1ae3f3a2005-09-28 10:47:38 +00002714 if (VG_(clo_verbosity) > 2 ||
2715 VG_(clo_trace_syscalls) ||
2716 VG_(clo_trace_sched))
2717 VG_(message)(Vg_DebugMsg,
2718 "Caught __NR_exit; running __libc_freeres()");
2719
sewardj0ec07f32006-01-12 12:32:32 +00002720 /* set thread context to point to libc_freeres_wrapper */
sewardj1a85f4f2006-01-12 21:15:35 +00002721 /* ppc64-linux note: __libc_freeres_wrapper gives us the real
2722 function entry point, not a fn descriptor, so can use it
2723 directly. However, we need to set R2 (the toc pointer)
2724 appropriately. */
sewardj1ae3f3a2005-09-28 10:47:38 +00002725 VG_(set_IP)(tid, __libc_freeres_wrapper);
sewardjcf951812006-01-17 02:22:21 +00002726# if defined(VGP_ppc64_linux)
2727 VG_(threads)[tid].arch.vex.guest_GPR2 = r2;
2728# endif
sewardj1ae3f3a2005-09-28 10:47:38 +00002729
2730 /* Block all blockable signals by copying the real block state into
2731 the thread's block state*/
2732 VG_(sigprocmask)(VKI_SIG_BLOCK, NULL, &VG_(threads)[tid].sig_mask);
2733 VG_(threads)[tid].tmp_sig_mask = VG_(threads)[tid].sig_mask;
2734
2735 /* and restore handlers to default */
2736 VG_(set_default_handler)(VKI_SIGSEGV);
2737 VG_(set_default_handler)(VKI_SIGBUS);
2738 VG_(set_default_handler)(VKI_SIGILL);
2739 VG_(set_default_handler)(VKI_SIGFPE);
2740
2741 // We were exiting, so assert that...
2742 vg_assert(VG_(is_exiting)(tid));
2743 // ...but now we're not again
2744 VG_(threads)[tid].exitreason = VgSrc_None;
2745
2746 // run until client thread exits - ideally with LIBC_FREERES_DONE,
2747 // but exit/exitgroup/signal will do
2748 VG_(scheduler)(tid);
2749
2750 vg_assert(VG_(is_exiting)(tid));
2751}
2752
sewardj45f4e7c2005-09-27 19:20:21 +00002753
2754/*====================================================================*/
2755/*=== Getting to main() alive ===*/
2756/*====================================================================*/
2757
2758/* If linking of the final executables is done with glibc present,
2759 then Valgrind starts at main() above as usual, and all of the
2760 following code is irrelevant.
2761
2762 However, this is not the intended mode of use. The plan is to
2763 avoid linking against glibc, by giving gcc the flags
2764 -nodefaultlibs -lgcc -nostartfiles at startup.
2765
2766 From this derive two requirements:
2767
2768 1. gcc may emit calls to memcpy and memset to deal with structure
2769 assignments etc. Since we have chosen to ignore all the
2770 "normal" supporting libraries, we have to provide our own
2771 implementations of them. No problem.
2772
2773 2. We have to provide a symbol "_start", to which the kernel
2774 hands control at startup. Hence the code below.
2775*/
2776
2777/* ---------------- Requirement 1 ---------------- */
2778
2779void* memcpy(void *dest, const void *src, size_t n);
2780void* memcpy(void *dest, const void *src, size_t n) {
2781 return VG_(memcpy)(dest,src,n);
2782}
2783void* memset(void *s, int c, size_t n);
2784void* memset(void *s, int c, size_t n) {
2785 return VG_(memset)(s,c,n);
2786}
2787
2788/* ---------------- Requirement 2 ---------------- */
2789
2790/* Glibc's sysdeps/i386/elf/start.S has the following gem of a
2791 comment, which explains how the stack looks right at process start
2792 (when _start is jumped to). Hence _start passes %esp to
2793 _start_in_C, which extracts argc/argv/envp and starts up
2794 correctly. */
2795
2796/* This is the canonical entry point, usually the first thing in the text
2797 segment. The SVR4/i386 ABI (pages 3-31, 3-32) says that when the entry
2798 point runs, most registers' values are unspecified, except for:
2799
2800 %edx Contains a function pointer to be registered with `atexit'.
2801 This is how the dynamic linker arranges to have DT_FINI
2802 functions called for shared libraries that have been loaded
2803 before this code runs.
2804
2805 %esp The stack contains the arguments and environment:
2806 0(%esp) argc
2807 4(%esp) argv[0]
2808 ...
2809 (4*argc)(%esp) NULL
2810 (4*(argc+1))(%esp) envp[0]
2811 ...
2812 NULL
2813*/
2814
2815/* The kernel hands control to _start, which extracts the initial
sewardja48a4932005-09-29 11:09:56 +00002816 stack pointer and calls onwards to _start_in_C. This also switches
2817 the new stack. */
sewardj45f4e7c2005-09-27 19:20:21 +00002818#if defined(VGP_x86_linux)
2819asm("\n"
sewardjd9fc3822005-11-18 23:50:43 +00002820 ".text\n"
sewardj45f4e7c2005-09-27 19:20:21 +00002821 "\t.globl _start\n"
2822 "\t.type _start,@function\n"
2823 "_start:\n"
2824 /* set up the new stack in %eax */
sewardjfdf91b42005-09-28 00:53:09 +00002825 "\tmovl $vgPlain_interim_stack, %eax\n"
sewardj45f4e7c2005-09-27 19:20:21 +00002826 "\taddl $"VG_STRINGIFY(VG_STACK_GUARD_SZB)", %eax\n"
2827 "\taddl $"VG_STRINGIFY(VG_STACK_ACTIVE_SZB)", %eax\n"
2828 "\tsubl $16, %eax\n"
2829 "\tandl $~15, %eax\n"
2830 /* install it, and collect the original one */
2831 "\txchgl %eax, %esp\n"
2832 /* call _start_in_C, passing it the startup %esp */
2833 "\tpushl %eax\n"
2834 "\tcall _start_in_C\n"
2835 "\thlt\n"
sewardj2fedc642005-11-19 02:02:57 +00002836 ".previous\n"
sewardj45f4e7c2005-09-27 19:20:21 +00002837);
2838#elif defined(VGP_amd64_linux)
2839asm("\n"
sewardjd9fc3822005-11-18 23:50:43 +00002840 ".text\n"
sewardj45f4e7c2005-09-27 19:20:21 +00002841 "\t.globl _start\n"
2842 "\t.type _start,@function\n"
2843 "_start:\n"
2844 /* set up the new stack in %rdi */
sewardjfdf91b42005-09-28 00:53:09 +00002845 "\tmovq $vgPlain_interim_stack, %rdi\n"
sewardj45f4e7c2005-09-27 19:20:21 +00002846 "\taddq $"VG_STRINGIFY(VG_STACK_GUARD_SZB)", %rdi\n"
2847 "\taddq $"VG_STRINGIFY(VG_STACK_ACTIVE_SZB)", %rdi\n"
2848 "\tandq $~15, %rdi\n"
2849 /* install it, and collect the original one */
2850 "\txchgq %rdi, %rsp\n"
2851 /* call _start_in_C, passing it the startup %rsp */
2852 "\tcall _start_in_C\n"
2853 "\thlt\n"
sewardj2fedc642005-11-19 02:02:57 +00002854 ".previous\n"
sewardj45f4e7c2005-09-27 19:20:21 +00002855);
sewardja48a4932005-09-29 11:09:56 +00002856#elif defined(VGP_ppc32_linux)
2857asm("\n"
sewardjd9fc3822005-11-18 23:50:43 +00002858 ".text\n"
sewardja48a4932005-09-29 11:09:56 +00002859 "\t.globl _start\n"
2860 "\t.type _start,@function\n"
2861 "_start:\n"
2862 /* set up the new stack in r16 */
2863 "\tlis 16,vgPlain_interim_stack@ha\n"
2864 "\tla 16,vgPlain_interim_stack@l(16)\n"
2865 "\tlis 17,("VG_STRINGIFY(VG_STACK_GUARD_SZB)" >> 16)\n"
2866 "\tori 17,17,("VG_STRINGIFY(VG_STACK_GUARD_SZB)" & 0xFFFF)\n"
2867 "\tlis 18,("VG_STRINGIFY(VG_STACK_ACTIVE_SZB)" >> 16)\n"
2868 "\tori 18,18,("VG_STRINGIFY(VG_STACK_ACTIVE_SZB)" & 0xFFFF)\n"
2869 "\tadd 16,17,16\n"
2870 "\tadd 16,18,16\n"
2871 "\trlwinm 16,16,0,0,27\n"
2872 /* now r16 = &vgPlain_interim_stack + VG_STACK_GUARD_SZB +
2873 VG_STACK_ACTIVE_SZB rounded down to the nearest 16-byte
2874 boundary. And r1 is the original SP. Set the SP to r16 and
2875 call _start_in_C, passing it the initial SP. */
2876 "\tmr 3,1\n"
2877 "\tmr 1,16\n"
2878 "\tbl _start_in_C\n"
2879 "\ttrap\n"
sewardj2fedc642005-11-19 02:02:57 +00002880 ".previous\n"
sewardja48a4932005-09-29 11:09:56 +00002881);
sewardj2c48c7b2005-11-29 13:05:56 +00002882#elif defined(VGP_ppc64_linux)
2883asm("\n"
cerion21082042005-12-06 19:07:08 +00002884 /* PPC64 ELF ABI says '_start' points to a function descriptor.
2885 So we must have one, and that is what goes into the .opd section. */
cerion297c88f2005-12-22 15:53:12 +00002886 "\t.align 2\n"
cerion21082042005-12-06 19:07:08 +00002887 "\t.global _start\n"
2888 "\t.section \".opd\",\"aw\"\n"
2889 "\t.align 3\n"
sewardj2c48c7b2005-11-29 13:05:56 +00002890 "_start:\n"
cerion21082042005-12-06 19:07:08 +00002891 "\t.quad ._start,.TOC.@tocbase,0\n"
2892 "\t.previous\n"
2893 "\t.type ._start,@function\n"
2894 "\t.global ._start\n"
2895 "._start:\n"
sewardj2c48c7b2005-11-29 13:05:56 +00002896 /* set up the new stack in r16 */
2897 "\tlis 16, vgPlain_interim_stack@highest\n"
2898 "\tori 16,16,vgPlain_interim_stack@higher\n"
2899 "\tsldi 16,16,32\n"
2900 "\toris 16,16,vgPlain_interim_stack@h\n"
2901 "\tori 16,16,vgPlain_interim_stack@l\n"
2902 "\txor 17,17,17\n"
2903 "\tlis 17,("VG_STRINGIFY(VG_STACK_GUARD_SZB)" >> 16)\n"
2904 "\tori 17,17,("VG_STRINGIFY(VG_STACK_GUARD_SZB)" & 0xFFFF)\n"
2905 "\txor 18,18,18\n"
2906 "\tlis 18,("VG_STRINGIFY(VG_STACK_ACTIVE_SZB)" >> 16)\n"
2907 "\tori 18,18,("VG_STRINGIFY(VG_STACK_ACTIVE_SZB)" & 0xFFFF)\n"
2908 "\tadd 16,17,16\n"
2909 "\tadd 16,18,16\n"
2910 "\trldicr 16,16,0,59\n"
2911 /* now r16 = &vgPlain_interim_stack + VG_STACK_GUARD_SZB +
2912 VG_STACK_ACTIVE_SZB rounded down to the nearest 16-byte
2913 boundary. And r1 is the original SP. Set the SP to r16 and
2914 call _start_in_C, passing it the initial SP. */
2915 "\tmr 3,1\n"
2916 "\tmr 1,16\n"
cerion21082042005-12-06 19:07:08 +00002917 "\tbl ._start_in_C\n"
2918 "\tnop\n"
sewardj2c48c7b2005-11-29 13:05:56 +00002919 "\ttrap\n"
sewardj2c48c7b2005-11-29 13:05:56 +00002920);
sewardj45f4e7c2005-09-27 19:20:21 +00002921#else
2922#error "_start: needs implementation on this platform"
2923#endif
2924
2925/* Avoid compiler warnings: this fn _is_ used, but labelling it
2926 'static' causes gcc to complain it isn't. */
2927void _start_in_C ( UWord* pArgc );
2928void _start_in_C ( UWord* pArgc )
2929{
2930 Int r;
2931 Word argc = pArgc[0];
2932 HChar** argv = (HChar**)&pArgc[1];
2933 HChar** envp = (HChar**)&pArgc[1+argc+1];
sewardjfdf91b42005-09-28 00:53:09 +00002934 sp_at_startup = (Addr)pArgc;
sewardj45f4e7c2005-09-27 19:20:21 +00002935 r = main( (Int)argc, argv, envp );
2936 VG_(exit)(r);
2937}
2938
sewardjde4a1d02002-03-22 01:27:54 +00002939/*--------------------------------------------------------------------*/
njn04e16982005-05-31 00:23:43 +00002940/*--- end ---*/
sewardjde4a1d02002-03-22 01:27:54 +00002941/*--------------------------------------------------------------------*/