blob: 29273299709d84cee173a0ccf0db29e11751fb6c [file] [log] [blame]
sewardjde4a1d02002-03-22 01:27:54 +00001
2/*--------------------------------------------------------------------*/
njn04e16982005-05-31 00:23:43 +00003/*--- Startup: the real stuff m_main.c ---*/
sewardjde4a1d02002-03-22 01:27:54 +00004/*--------------------------------------------------------------------*/
5
6/*
njnb9c427c2004-12-01 14:14:42 +00007 This file is part of Valgrind, a dynamic binary instrumentation
8 framework.
sewardjde4a1d02002-03-22 01:27:54 +00009
njn53612422005-03-12 16:22:54 +000010 Copyright (C) 2000-2005 Julian Seward
sewardjde4a1d02002-03-22 01:27:54 +000011 jseward@acm.org
sewardjde4a1d02002-03-22 01:27:54 +000012
13 This program is free software; you can redistribute it and/or
14 modify it under the terms of the GNU General Public License as
15 published by the Free Software Foundation; either version 2 of the
16 License, or (at your option) any later version.
17
18 This program is distributed in the hope that it will be useful, but
19 WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 General Public License for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software
25 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
26 02111-1307, USA.
27
njn25e49d8e72002-09-23 09:36:25 +000028 The GNU General Public License is contained in the file COPYING.
sewardjde4a1d02002-03-22 01:27:54 +000029*/
30
njnc7561b92005-06-19 01:24:32 +000031#include "pub_core_basics.h"
32#include "pub_core_threadstate.h"
sewardj45f4e7c2005-09-27 19:20:21 +000033#include "pub_core_clientstate.h"
sewardj55f9d1a2005-04-25 11:11:44 +000034#include "pub_core_aspacemgr.h"
sewardj45f4e7c2005-09-27 19:20:21 +000035#include "pub_core_commandline.h"
njn2521d322005-05-08 14:45:13 +000036#include "pub_core_debuglog.h"
37#include "pub_core_errormgr.h"
38#include "pub_core_execontext.h"
njn97405b22005-06-02 03:39:33 +000039#include "pub_core_libcbase.h"
njn132bfcc2005-06-04 19:16:06 +000040#include "pub_core_libcassert.h"
njneb8896b2005-06-04 20:03:55 +000041#include "pub_core_libcfile.h"
njn36a20fa2005-06-03 03:08:39 +000042#include "pub_core_libcprint.h"
njnf39e9a32005-06-12 02:43:17 +000043#include "pub_core_libcproc.h"
njnde62cbf2005-06-10 22:08:14 +000044#include "pub_core_libcsignal.h"
sewardj45f4e7c2005-09-27 19:20:21 +000045#include "pub_core_syscall.h" // VG_(strerror)
njnf536bbb2005-06-13 04:21:38 +000046#include "pub_core_machine.h"
njnaf1d7df2005-06-11 01:31:52 +000047#include "pub_core_mallocfree.h"
njn20242342005-05-16 23:31:24 +000048#include "pub_core_options.h"
njn31513b42005-06-01 03:09:59 +000049#include "pub_core_profile.h"
sewardjfdf91b42005-09-28 00:53:09 +000050#include "pub_core_debuginfo.h"
njnd1af0032005-05-29 17:01:48 +000051#include "pub_core_redir.h"
njnc7561b92005-06-19 01:24:32 +000052#include "pub_core_scheduler.h"
njn0c246472005-05-31 01:00:08 +000053#include "pub_core_signals.h"
njn2025cf92005-06-26 20:44:48 +000054#include "pub_core_stacks.h" // For VG_(register_stack)
njnc1b01812005-06-17 22:19:06 +000055#include "pub_core_syswrap.h"
sewardjfdf91b42005-09-28 00:53:09 +000056#include "pub_core_translate.h" // For VG_(translate)
njn43b9a8a2005-05-10 04:37:01 +000057#include "pub_core_tooliface.h"
njna7598f62005-06-18 03:27:58 +000058#include "pub_core_trampoline.h"
njn8bddf582005-05-13 23:40:55 +000059#include "pub_core_transtab.h"
njn08a2e172005-06-21 22:47:54 +000060#include "pub_core_ume.h"
nethercote71980f02004-01-24 18:18:54 +000061
sewardjb5f6f512005-03-10 23:59:00 +000062
nethercote71980f02004-01-24 18:18:54 +000063/*====================================================================*/
64/*=== Counters, for profiling purposes only ===*/
65/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +000066
nethercote3a42fb82004-08-03 18:08:50 +000067static void print_all_stats ( void )
nethercote71980f02004-01-24 18:18:54 +000068{
njn42c83552005-12-05 20:45:59 +000069 VG_(print_translation_stats)();
nethercote92e7b7f2004-08-07 17:52:25 +000070 VG_(print_tt_tc_stats)();
nethercote844e7122004-08-02 15:27:22 +000071 VG_(print_scheduler_stats)();
njn9271cbc2005-03-13 05:38:25 +000072 VG_(print_ExeContext_stats)();
73
nethercote3a42fb82004-08-03 18:08:50 +000074 // Memory stats
nethercote885dd912004-08-03 23:14:00 +000075 if (VG_(clo_verbosity) > 2) {
nethercote3a42fb82004-08-03 18:08:50 +000076 VG_(message)(Vg_DebugMsg, "");
77 VG_(message)(Vg_DebugMsg,
78 "------ Valgrind's internal memory use stats follow ------" );
nethercote885dd912004-08-03 23:14:00 +000079 VG_(sanity_check_malloc_all)();
njn11adeb22005-07-03 20:22:39 +000080 VG_(message)(Vg_DebugMsg, "------" );
nethercote3a42fb82004-08-03 18:08:50 +000081 VG_(print_all_arena_stats)();
nethercote885dd912004-08-03 23:14:00 +000082 VG_(message)(Vg_DebugMsg, "");
nethercote3a42fb82004-08-03 18:08:50 +000083 }
nethercote71980f02004-01-24 18:18:54 +000084}
85
86
87/*====================================================================*/
sewardj5f229e22005-09-28 01:36:01 +000088/*=== Setting up the client's environment ===*/
nethercote71980f02004-01-24 18:18:54 +000089/*====================================================================*/
90
nethercote71980f02004-01-24 18:18:54 +000091/* Prepare the client's environment. This is basically a copy of our
92 environment, except:
sewardj45f4e7c2005-09-27 19:20:21 +000093
njn9d5564d2005-09-29 00:25:07 +000094 LD_PRELOAD=$VALGRIND_LIB/vgpreload_core.so:
sewardj45f4e7c2005-09-27 19:20:21 +000095 ($VALGRIND_LIB/vgpreload_TOOL.so:)?
96 $LD_PRELOAD
nethercote71980f02004-01-24 18:18:54 +000097
sewardjb5f6f512005-03-10 23:59:00 +000098 If this is missing, then it is added.
nethercote71980f02004-01-24 18:18:54 +000099
sewardj45f4e7c2005-09-27 19:20:21 +0000100 Also, remove any binding for VALGRIND_LAUNCHER=. The client should
101 not be able to see this.
nethercote71980f02004-01-24 18:18:54 +0000102
103 If this needs to handle any more variables it should be hacked
sewardj45f4e7c2005-09-27 19:20:21 +0000104 into something table driven. The copy is VG_(malloc)'d space.
105*/
106static HChar** setup_client_env ( HChar** origenv, const HChar* toolname)
nethercote71980f02004-01-24 18:18:54 +0000107{
tomfb7bcde2005-11-07 15:24:38 +0000108 HChar* preload_core = "vgpreload_core";
sewardj45f4e7c2005-09-27 19:20:21 +0000109 HChar* ld_preload = "LD_PRELOAD=";
110 HChar* v_launcher = VALGRIND_LAUNCHER "=";
111 Int ld_preload_len = VG_(strlen)( ld_preload );
112 Int v_launcher_len = VG_(strlen)( v_launcher );
113 Bool ld_preload_done = False;
114 Int vglib_len = VG_(strlen)(VG_(libdir));
nethercote71980f02004-01-24 18:18:54 +0000115
sewardj45f4e7c2005-09-27 19:20:21 +0000116 HChar** cpp;
117 HChar** ret;
tom60a4b0b2005-10-12 10:45:27 +0000118 HChar* preload_tool_path;
sewardj45f4e7c2005-09-27 19:20:21 +0000119 Int envc, i;
nethercote71980f02004-01-24 18:18:54 +0000120
sewardj45f4e7c2005-09-27 19:20:21 +0000121 /* Alloc space for the vgpreload_core.so path and vgpreload_<tool>.so
122 paths. We might not need the space for vgpreload_<tool>.so, but it
123 doesn't hurt to over-allocate briefly. The 16s are just cautious
124 slop. */
tomfb7bcde2005-11-07 15:24:38 +0000125 Int preload_core_path_len = vglib_len + sizeof(preload_core) + sizeof(VG_PLATFORM) + 16;
126 Int preload_tool_path_len = vglib_len + VG_(strlen)(toolname) + sizeof(VG_PLATFORM) + 16;
sewardj45f4e7c2005-09-27 19:20:21 +0000127 Int preload_string_len = preload_core_path_len + preload_tool_path_len;
128 HChar* preload_string = VG_(malloc)(preload_string_len);
129 vg_assert(preload_string);
130
131 /* Determine if there's a vgpreload_<tool>.so file, and setup
132 preload_string. */
133 preload_tool_path = VG_(malloc)(preload_tool_path_len);
134 vg_assert(preload_tool_path);
135 VG_(snprintf)(preload_tool_path, preload_tool_path_len,
tomfb7bcde2005-11-07 15:24:38 +0000136 "%s/%s/vgpreload_%s.so", VG_(libdir), VG_PLATFORM, toolname);
sewardj45f4e7c2005-09-27 19:20:21 +0000137 if (VG_(access)(preload_tool_path, True/*r*/, False/*w*/, False/*x*/) == 0) {
tomfb7bcde2005-11-07 15:24:38 +0000138 VG_(snprintf)(preload_string, preload_string_len, "%s/%s/%s.so:%s",
139 VG_(libdir), VG_PLATFORM, preload_core, preload_tool_path);
sewardj45f4e7c2005-09-27 19:20:21 +0000140 } else {
tomfb7bcde2005-11-07 15:24:38 +0000141 VG_(snprintf)(preload_string, preload_string_len, "%s/%s/%s.so",
142 VG_(libdir), VG_PLATFORM, preload_core);
sewardj45f4e7c2005-09-27 19:20:21 +0000143 }
144 VG_(free)(preload_tool_path);
145
sewardja48a4932005-09-29 11:09:56 +0000146 VG_(debugLog)(2, "main", "preload_string:\n");
147 VG_(debugLog)(2, "main", " \"%s\"\n", preload_string);
sewardj45f4e7c2005-09-27 19:20:21 +0000148
nethercote71980f02004-01-24 18:18:54 +0000149 /* Count the original size of the env */
sewardj45f4e7c2005-09-27 19:20:21 +0000150 envc = 0;
nethercote71980f02004-01-24 18:18:54 +0000151 for (cpp = origenv; cpp && *cpp; cpp++)
152 envc++;
153
154 /* Allocate a new space */
sewardj45f4e7c2005-09-27 19:20:21 +0000155 ret = VG_(malloc) (sizeof(HChar *) * (envc+1+1)); /* 1 new entry + NULL */
nethercote7c018f42004-07-17 16:40:50 +0000156 vg_assert(ret);
nethercote71980f02004-01-24 18:18:54 +0000157
158 /* copy it over */
159 for (cpp = ret; *origenv; )
160 *cpp++ = *origenv++;
161 *cpp = NULL;
162
163 vg_assert(envc == (cpp - ret));
164
165 /* Walk over the new environment, mashing as we go */
166 for (cpp = ret; cpp && *cpp; cpp++) {
sewardj45f4e7c2005-09-27 19:20:21 +0000167 if (VG_(memcmp)(*cpp, ld_preload, ld_preload_len) == 0) {
168 Int len = VG_(strlen)(*cpp) + preload_string_len;
169 HChar *cp = VG_(malloc)(len);
nethercote7c018f42004-07-17 16:40:50 +0000170 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000171
sewardj45f4e7c2005-09-27 19:20:21 +0000172 VG_(snprintf)(cp, len, "%s%s:%s",
173 ld_preload, preload_string, (*cpp)+ld_preload_len);
nethercote71980f02004-01-24 18:18:54 +0000174
sewardj45f4e7c2005-09-27 19:20:21 +0000175 *cpp = cp;
176
177 ld_preload_done = True;
nethercote71980f02004-01-24 18:18:54 +0000178 }
179 }
180
181 /* Add the missing bits */
nethercote71980f02004-01-24 18:18:54 +0000182 if (!ld_preload_done) {
sewardj45f4e7c2005-09-27 19:20:21 +0000183 Int len = ld_preload_len + preload_string_len;
184 HChar *cp = VG_(malloc) (len);
nethercote7c018f42004-07-17 16:40:50 +0000185 vg_assert(cp);
sewardj45f4e7c2005-09-27 19:20:21 +0000186
187 VG_(snprintf)(cp, len, "%s%s", ld_preload, preload_string);
188
nethercote71980f02004-01-24 18:18:54 +0000189 ret[envc++] = cp;
190 }
191
sewardj45f4e7c2005-09-27 19:20:21 +0000192 /* ret[0 .. envc-1] is live now. */
193 /* Find and remove a binding for VALGRIND_LAUNCHER. */
194 for (i = 0; i < envc; i++)
195 if (0 == VG_(memcmp(ret[i], v_launcher, v_launcher_len)))
196 break;
197
198 if (i < envc) {
199 for (; i < envc-1; i++)
200 ret[i] = ret[i+1];
201 envc--;
202 }
203
204 VG_(free)(preload_string);
nethercote71980f02004-01-24 18:18:54 +0000205 ret[envc] = NULL;
206
207 return ret;
208}
209
nethercote71980f02004-01-24 18:18:54 +0000210
sewardj5f229e22005-09-28 01:36:01 +0000211/*====================================================================*/
212/*=== Setting up the client's stack ===*/
213/*====================================================================*/
214
215#ifndef AT_DCACHEBSIZE
216#define AT_DCACHEBSIZE 19
217#endif /* AT_DCACHEBSIZE */
218
219#ifndef AT_ICACHEBSIZE
220#define AT_ICACHEBSIZE 20
221#endif /* AT_ICACHEBSIZE */
222
223#ifndef AT_UCACHEBSIZE
224#define AT_UCACHEBSIZE 21
225#endif /* AT_UCACHEBSIZE */
226
227#ifndef AT_SYSINFO
228#define AT_SYSINFO 32
229#endif /* AT_SYSINFO */
230
231#ifndef AT_SYSINFO_EHDR
232#define AT_SYSINFO_EHDR 33
233#endif /* AT_SYSINFO_EHDR */
234
235#ifndef AT_SECURE
236#define AT_SECURE 23 /* secure mode boolean */
237#endif /* AT_SECURE */
238
nethercote71980f02004-01-24 18:18:54 +0000239/* Add a string onto the string table, and return its address */
240static char *copy_str(char **tab, const char *str)
241{
242 char *cp = *tab;
243 char *orig = cp;
244
245 while(*str)
246 *cp++ = *str++;
247 *cp++ = '\0';
248
249 if (0)
sewardj45f4e7c2005-09-27 19:20:21 +0000250 VG_(printf)("copied %p \"%s\" len %lld\n", orig, orig, (Long)(cp-orig));
nethercote71980f02004-01-24 18:18:54 +0000251
252 *tab = cp;
253
254 return orig;
255}
256
sewardj5f229e22005-09-28 01:36:01 +0000257
258/* ----------------------------------------------------------------
259
nethercote71980f02004-01-24 18:18:54 +0000260 This sets up the client's initial stack, containing the args,
261 environment and aux vector.
262
263 The format of the stack is:
264
sewardj45f4e7c2005-09-27 19:20:21 +0000265 higher address +-----------------+ <- clstack_end
nethercote71980f02004-01-24 18:18:54 +0000266 | |
267 : string table :
268 | |
269 +-----------------+
270 | AT_NULL |
271 - -
272 | auxv |
273 +-----------------+
sewardjfdf91b42005-09-28 00:53:09 +0000274 | NULL |
nethercote71980f02004-01-24 18:18:54 +0000275 - -
276 | envp |
277 +-----------------+
sewardjfdf91b42005-09-28 00:53:09 +0000278 | NULL |
nethercote71980f02004-01-24 18:18:54 +0000279 - -
280 | argv |
281 +-----------------+
282 | argc |
nethercote4ad74312004-10-26 09:59:49 +0000283 lower address +-----------------+ <- sp
nethercote71980f02004-01-24 18:18:54 +0000284 | undefined |
285 : :
sewardj45f4e7c2005-09-27 19:20:21 +0000286
sewardjfdf91b42005-09-28 00:53:09 +0000287 Allocate and create the initial client stack. It is allocated down
sewardj45f4e7c2005-09-27 19:20:21 +0000288 from clstack_end, which was previously determined by the address
sewardjfdf91b42005-09-28 00:53:09 +0000289 space manager. The returned value is the SP value for the client.
290
291 The client's auxv is created by copying and modifying our own one.
292 As a side effect of scanning our own auxv, some important bits of
293 info are collected:
294
295 VG_(cache_line_size_ppc32) // ppc32 only -- cache line size
296 VG_(have_altivec_ppc32) // ppc32 only -- is Altivec supported?
sewardj5f229e22005-09-28 01:36:01 +0000297
298 ---------------------------------------------------------------- */
sewardjfdf91b42005-09-28 00:53:09 +0000299
sewardj45f4e7c2005-09-27 19:20:21 +0000300static
301Addr setup_client_stack( void* init_sp,
302 char** orig_envp,
303 const struct exeinfo *info,
304 UInt** client_auxv,
305 Addr clstack_end,
306 SizeT clstack_max_size )
nethercote71980f02004-01-24 18:18:54 +0000307{
njn83407492005-06-19 16:10:47 +0000308 SysRes res;
nethercote71980f02004-01-24 18:18:54 +0000309 char **cpp;
310 char *strtab; /* string table */
311 char *stringbase;
nethercotea3c3cf22004-11-01 18:38:00 +0000312 Addr *ptr;
nethercote71980f02004-01-24 18:18:54 +0000313 struct ume_auxv *auxv;
314 const struct ume_auxv *orig_auxv;
315 const struct ume_auxv *cauxv;
316 unsigned stringsize; /* total size of strings in bytes */
317 unsigned auxsize; /* total size of auxv in bytes */
sewardj45f4e7c2005-09-27 19:20:21 +0000318 Int argc; /* total argc */
319 Int envc; /* total number of env vars */
nethercote71980f02004-01-24 18:18:54 +0000320 unsigned stacksize; /* total client stack size */
sewardj45f4e7c2005-09-27 19:20:21 +0000321 Addr client_SP; /* client stack base (initial SP) */
322 Addr clstack_start;
323 Int i;
324 Bool have_exename;
325
326 vg_assert(VG_IS_PAGE_ALIGNED(clstack_end+1));
nethercote71980f02004-01-24 18:18:54 +0000327
328 /* use our own auxv as a prototype */
njn62ff0f22005-06-21 23:03:36 +0000329 orig_auxv = VG_(find_auxv)(init_sp);
nethercote71980f02004-01-24 18:18:54 +0000330
331 /* ==================== compute sizes ==================== */
332
333 /* first of all, work out how big the client stack will be */
sewardj45f4e7c2005-09-27 19:20:21 +0000334 stringsize = 0;
335 have_exename = VG_(args_the_exename) != NULL;
nethercote71980f02004-01-24 18:18:54 +0000336
337 /* paste on the extra args if the loader needs them (ie, the #!
338 interpreter and its argument) */
339 argc = 0;
nethercoted6a56872004-07-26 15:32:47 +0000340 if (info->interp_name != NULL) {
nethercote71980f02004-01-24 18:18:54 +0000341 argc++;
sewardj45f4e7c2005-09-27 19:20:21 +0000342 stringsize += VG_(strlen)(info->interp_name) + 1;
nethercote71980f02004-01-24 18:18:54 +0000343 }
nethercoted6a56872004-07-26 15:32:47 +0000344 if (info->interp_args != NULL) {
nethercote71980f02004-01-24 18:18:54 +0000345 argc++;
sewardj45f4e7c2005-09-27 19:20:21 +0000346 stringsize += VG_(strlen)(info->interp_args) + 1;
nethercote71980f02004-01-24 18:18:54 +0000347 }
348
349 /* now scan the args we're given... */
sewardj45f4e7c2005-09-27 19:20:21 +0000350 if (have_exename)
351 stringsize += VG_(strlen)( VG_(args_the_exename) ) + 1;
352
353 for (i = 0; i < VG_(args_for_client).used; i++) {
nethercote71980f02004-01-24 18:18:54 +0000354 argc++;
sewardj45f4e7c2005-09-27 19:20:21 +0000355 stringsize += VG_(strlen)( VG_(args_for_client).strs[i] ) + 1;
nethercote71980f02004-01-24 18:18:54 +0000356 }
sewardj45f4e7c2005-09-27 19:20:21 +0000357
nethercote71980f02004-01-24 18:18:54 +0000358 /* ...and the environment */
359 envc = 0;
360 for (cpp = orig_envp; cpp && *cpp; cpp++) {
361 envc++;
sewardj45f4e7c2005-09-27 19:20:21 +0000362 stringsize += VG_(strlen)(*cpp) + 1;
nethercote71980f02004-01-24 18:18:54 +0000363 }
364
365 /* now, how big is the auxv? */
366 auxsize = sizeof(*auxv); /* there's always at least one entry: AT_NULL */
367 for (cauxv = orig_auxv; cauxv->a_type != AT_NULL; cauxv++) {
368 if (cauxv->a_type == AT_PLATFORM)
sewardj45f4e7c2005-09-27 19:20:21 +0000369 stringsize += VG_(strlen)(cauxv->u.a_ptr) + 1;
nethercote71980f02004-01-24 18:18:54 +0000370 auxsize += sizeof(*cauxv);
371 }
372
cerionc7266522005-12-08 03:24:37 +0000373# if defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux)
cerion85665ca2005-06-20 15:51:07 +0000374 auxsize += 2 * sizeof(*cauxv);
sewardjfdf91b42005-09-28 00:53:09 +0000375# endif
cerion85665ca2005-06-20 15:51:07 +0000376
nethercote71980f02004-01-24 18:18:54 +0000377 /* OK, now we know how big the client stack is */
378 stacksize =
sewardj45f4e7c2005-09-27 19:20:21 +0000379 sizeof(Word) + /* argc */
380 (have_exename ? sizeof(char **) : 0) + /* argc[0] == exename */
381 sizeof(char **)*argc + /* argv */
382 sizeof(char **) + /* terminal NULL */
383 sizeof(char **)*envc + /* envp */
384 sizeof(char **) + /* terminal NULL */
385 auxsize + /* auxv */
sewardj90d38542005-09-27 23:53:09 +0000386 VG_ROUNDUP(stringsize, sizeof(Word)); /* strings (aligned) */
nethercote71980f02004-01-24 18:18:54 +0000387
sewardj79048ce2005-02-18 08:28:32 +0000388 if (0) VG_(printf)("stacksize = %d\n", stacksize);
389
sewardj45f4e7c2005-09-27 19:20:21 +0000390 /* client_SP is the client's stack pointer */
391 client_SP = clstack_end - stacksize;
392 client_SP = VG_ROUNDDN(client_SP, 16); /* make stack 16 byte aligned */
nethercote71980f02004-01-24 18:18:54 +0000393
nethercote71980f02004-01-24 18:18:54 +0000394 /* base of the string table (aligned) */
sewardj45f4e7c2005-09-27 19:20:21 +0000395 stringbase = strtab = (char *)clstack_end
396 - VG_ROUNDUP(stringsize, sizeof(int));
nethercote71980f02004-01-24 18:18:54 +0000397
sewardj45f4e7c2005-09-27 19:20:21 +0000398 clstack_start = VG_PGROUNDDN(client_SP);
399
400 /* The max stack size */
401 clstack_max_size = VG_PGROUNDUP(clstack_max_size);
402
403 /* Record stack extent -- needed for stack-change code. */
404 VG_(clstk_base) = clstack_start;
405 VG_(clstk_end) = clstack_end;
nethercote71980f02004-01-24 18:18:54 +0000406
sewardj79048ce2005-02-18 08:28:32 +0000407 if (0)
sewardj45f4e7c2005-09-27 19:20:21 +0000408 VG_(printf)("stringsize=%d auxsize=%d stacksize=%d maxsize=0x%x\n"
409 "clstack_start %p\n"
410 "clstack_end %p\n",
411 stringsize, auxsize, stacksize, (Int)clstack_max_size,
412 (void*)clstack_start, (void*)clstack_end);
nethercote5ee67ca2004-06-22 14:00:09 +0000413
nethercote71980f02004-01-24 18:18:54 +0000414 /* ==================== allocate space ==================== */
415
sewardj45f4e7c2005-09-27 19:20:21 +0000416 { SizeT anon_size = clstack_end - clstack_start + 1;
417 SizeT resvn_size = clstack_max_size - anon_size;
418 Addr anon_start = clstack_start;
419 Addr resvn_start = anon_start - resvn_size;
420 SizeT inner_HACK = 0;
tom60a4b0b2005-10-12 10:45:27 +0000421 Bool ok;
nethercote71980f02004-01-24 18:18:54 +0000422
sewardj45f4e7c2005-09-27 19:20:21 +0000423 vg_assert(VG_IS_PAGE_ALIGNED(anon_size));
424 vg_assert(VG_IS_PAGE_ALIGNED(resvn_size));
425 vg_assert(VG_IS_PAGE_ALIGNED(anon_start));
426 vg_assert(VG_IS_PAGE_ALIGNED(resvn_start));
427 vg_assert(resvn_start == clstack_end + 1 - clstack_max_size);
nethercote71980f02004-01-24 18:18:54 +0000428
sewardj45f4e7c2005-09-27 19:20:21 +0000429# ifdef ENABLE_INNER
430 inner_HACK = 1024*1024; // create 1M non-fault-extending stack
431# endif
nethercote71980f02004-01-24 18:18:54 +0000432
sewardj45f4e7c2005-09-27 19:20:21 +0000433 if (0)
434 VG_(printf)("%p 0x%x %p 0x%x\n",
435 resvn_start, resvn_size, anon_start, anon_size);
nethercote71980f02004-01-24 18:18:54 +0000436
sewardj45f4e7c2005-09-27 19:20:21 +0000437 /* Create a shrinkable reservation followed by an anonymous
438 segment. Together these constitute a growdown stack. */
tom60a4b0b2005-10-12 10:45:27 +0000439 ok = VG_(am_create_reservation)(
440 resvn_start,
441 resvn_size -inner_HACK,
442 SmUpper,
443 anon_size +inner_HACK
444 );
sewardj45f4e7c2005-09-27 19:20:21 +0000445 vg_assert(ok);
446 /* allocate a stack - mmap enough space for the stack */
447 res = VG_(am_mmap_anon_fixed_client)(
448 anon_start -inner_HACK,
449 anon_size +inner_HACK,
450 VKI_PROT_READ|VKI_PROT_WRITE|VKI_PROT_EXEC
451 );
452 vg_assert(!res.isError);
453 }
454
455 /* ==================== create client stack ==================== */
456
457 ptr = (Addr*)client_SP;
458
459 /* --- client argc --- */
460 *ptr++ = argc + (have_exename ? 1 : 0);
461
462 /* --- client argv --- */
nethercoted6a56872004-07-26 15:32:47 +0000463 if (info->interp_name) {
nethercotea3c3cf22004-11-01 18:38:00 +0000464 *ptr++ = (Addr)copy_str(&strtab, info->interp_name);
sewardj45f4e7c2005-09-27 19:20:21 +0000465 VG_(free)(info->interp_name);
nethercote71980f02004-01-24 18:18:54 +0000466 }
nethercoted6a56872004-07-26 15:32:47 +0000467 if (info->interp_args) {
nethercotea3c3cf22004-11-01 18:38:00 +0000468 *ptr++ = (Addr)copy_str(&strtab, info->interp_args);
sewardj45f4e7c2005-09-27 19:20:21 +0000469 VG_(free)(info->interp_args);
nethercote71980f02004-01-24 18:18:54 +0000470 }
sewardj45f4e7c2005-09-27 19:20:21 +0000471
472 if (have_exename)
473 *ptr++ = (Addr)copy_str(&strtab, VG_(args_the_exename));
474
475 for (i = 0; i < VG_(args_for_client).used; i++) {
476 *ptr++ = (Addr)copy_str(&strtab, VG_(args_for_client).strs[i]);
nethercote71980f02004-01-24 18:18:54 +0000477 }
478 *ptr++ = 0;
479
480 /* --- envp --- */
481 VG_(client_envp) = (Char **)ptr;
482 for (cpp = orig_envp; cpp && *cpp; ptr++, cpp++)
nethercotea3c3cf22004-11-01 18:38:00 +0000483 *ptr = (Addr)copy_str(&strtab, *cpp);
nethercote71980f02004-01-24 18:18:54 +0000484 *ptr++ = 0;
485
486 /* --- auxv --- */
487 auxv = (struct ume_auxv *)ptr;
488 *client_auxv = (UInt *)auxv;
489
cerionc7266522005-12-08 03:24:37 +0000490# if defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux)
cerion85665ca2005-06-20 15:51:07 +0000491 auxv[0].a_type = AT_IGNOREPPC;
492 auxv[0].u.a_val = AT_IGNOREPPC;
493 auxv[1].a_type = AT_IGNOREPPC;
494 auxv[1].u.a_val = AT_IGNOREPPC;
495 auxv += 2;
sewardjfdf91b42005-09-28 00:53:09 +0000496# endif
cerion85665ca2005-06-20 15:51:07 +0000497
nethercote71980f02004-01-24 18:18:54 +0000498 for (; orig_auxv->a_type != AT_NULL; auxv++, orig_auxv++) {
sewardjfdf91b42005-09-28 00:53:09 +0000499
nethercote71980f02004-01-24 18:18:54 +0000500 /* copy the entry... */
501 *auxv = *orig_auxv;
502
sewardjfdf91b42005-09-28 00:53:09 +0000503 /* ...and fix up / examine the copy */
nethercote71980f02004-01-24 18:18:54 +0000504 switch(auxv->a_type) {
nethercote71980f02004-01-24 18:18:54 +0000505
sewardjfdf91b42005-09-28 00:53:09 +0000506 case AT_IGNORE:
507 case AT_PHENT:
508 case AT_PAGESZ:
509 case AT_FLAGS:
510 case AT_NOTELF:
511 case AT_UID:
512 case AT_EUID:
513 case AT_GID:
514 case AT_EGID:
515 case AT_CLKTCK:
516 case AT_FPUCW:
sewardjfdf91b42005-09-28 00:53:09 +0000517 /* All these are pointerless, so we don't need to do
518 anything about them. */
519 break;
nethercote71980f02004-01-24 18:18:54 +0000520
sewardjfdf91b42005-09-28 00:53:09 +0000521 case AT_PHDR:
522 if (info->phdr == 0)
523 auxv->a_type = AT_IGNORE;
524 else
525 auxv->u.a_val = info->phdr;
526 break;
nethercote71980f02004-01-24 18:18:54 +0000527
sewardjfdf91b42005-09-28 00:53:09 +0000528 case AT_PHNUM:
529 if (info->phdr == 0)
530 auxv->a_type = AT_IGNORE;
531 else
532 auxv->u.a_val = info->phnum;
533 break;
nethercote71980f02004-01-24 18:18:54 +0000534
sewardjfdf91b42005-09-28 00:53:09 +0000535 case AT_BASE:
536 auxv->u.a_val = info->interp_base;
537 break;
nethercote71980f02004-01-24 18:18:54 +0000538
sewardjfdf91b42005-09-28 00:53:09 +0000539 case AT_PLATFORM:
540 /* points to a platform description string */
541 auxv->u.a_ptr = copy_str(&strtab, orig_auxv->u.a_ptr);
542 break;
nethercote71980f02004-01-24 18:18:54 +0000543
sewardjfdf91b42005-09-28 00:53:09 +0000544 case AT_ENTRY:
545 auxv->u.a_val = info->entry;
546 break;
nethercote71980f02004-01-24 18:18:54 +0000547
sewardjfdf91b42005-09-28 00:53:09 +0000548 case AT_HWCAP:
sewardjfdf91b42005-09-28 00:53:09 +0000549 break;
nethercote71980f02004-01-24 18:18:54 +0000550
sewardjfdf91b42005-09-28 00:53:09 +0000551 case AT_DCACHEBSIZE:
552 case AT_ICACHEBSIZE:
553 case AT_UCACHEBSIZE:
554# if defined(VGP_ppc32_linux)
555 /* acquire cache info */
556 if (auxv->u.a_val > 0) {
sewardje3826cf2005-11-13 00:30:22 +0000557 VG_(machine_ppc32_set_clszB)( auxv->u.a_val );
sewardja48a4932005-09-29 11:09:56 +0000558 VG_(debugLog)(2, "main",
sewardjfdf91b42005-09-28 00:53:09 +0000559 "PPC32 cache line size %u (type %u)\n",
560 (UInt)auxv->u.a_val, (UInt)auxv->a_type );
561 }
cerionc7266522005-12-08 03:24:37 +0000562# elif defined(VGP_ppc64_linux)
563 /* acquire cache info */
564 if (auxv->u.a_val > 0) {
565 VG_(machine_ppc64_set_clszB)( auxv->u.a_val );
566 VG_(debugLog)(2, "main",
567 "PPC64 cache line size %u (type %u)\n",
568 (UInt)auxv->u.a_val, (UInt)auxv->a_type );
569 }
sewardjfdf91b42005-09-28 00:53:09 +0000570# endif
571 break;
nethercote71980f02004-01-24 18:18:54 +0000572
cerionc7266522005-12-08 03:24:37 +0000573# if defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux)
sewardjfdf91b42005-09-28 00:53:09 +0000574 case AT_IGNOREPPC:
575 break;
576# endif
577
578 case AT_SECURE:
579 /* If this is 1, then it means that this program is
580 running suid, and therefore the dynamic linker should
581 be careful about LD_PRELOAD, etc. However, since
582 stage1 (the thing the kernel actually execve's) should
583 never be SUID, and we need LD_PRELOAD to work for the
584 client, we set AT_SECURE to 0. */
585 auxv->u.a_val = 0;
586 break;
587
tom2315d182005-11-11 08:39:34 +0000588 case AT_SYSINFO:
cerionc7266522005-12-08 03:24:37 +0000589# if !defined(VGP_ppc32_linux) && !defined(VGP_ppc64_linux)
sewardjfdf91b42005-09-28 00:53:09 +0000590 case AT_SYSINFO_EHDR:
tom2315d182005-11-11 08:39:34 +0000591# endif
sewardjfdf91b42005-09-28 00:53:09 +0000592 /* Trash this, because we don't reproduce it */
593 auxv->a_type = AT_IGNORE;
594 break;
sewardjfdf91b42005-09-28 00:53:09 +0000595
596 default:
597 /* stomp out anything we don't know about */
598 VG_(debugLog)(2, "main",
599 "stomping auxv entry %lld\n",
600 (ULong)auxv->a_type);
601 auxv->a_type = AT_IGNORE;
602 break;
nethercote71980f02004-01-24 18:18:54 +0000603 }
604 }
605 *auxv = *orig_auxv;
606 vg_assert(auxv->a_type == AT_NULL);
607
608 vg_assert((strtab-stringbase) == stringsize);
609
sewardj45f4e7c2005-09-27 19:20:21 +0000610 /* client_SP is pointing at client's argc/argv */
nethercote5ee67ca2004-06-22 14:00:09 +0000611
sewardj45f4e7c2005-09-27 19:20:21 +0000612 if (0) VG_(printf)("startup SP = %p\n", client_SP);
613 return client_SP;
nethercote71980f02004-01-24 18:18:54 +0000614}
615
sewardj45f4e7c2005-09-27 19:20:21 +0000616
617/* Allocate the client data segment. It is an expandable anonymous
618 mapping abutting a shrinkable reservation of size max_dseg_size.
619 The data segment starts at VG_(brk_base), which is page-aligned,
620 and runs up to VG_(brk_limit), which isn't. */
621
622static void setup_client_dataseg ( SizeT max_size )
623{
624 Bool ok;
625 SysRes sres;
626 Addr anon_start = VG_(brk_base);
627 SizeT anon_size = VKI_PAGE_SIZE;
628 Addr resvn_start = anon_start + anon_size;
629 SizeT resvn_size = max_size - anon_size;
630
631 vg_assert(VG_IS_PAGE_ALIGNED(anon_size));
632 vg_assert(VG_IS_PAGE_ALIGNED(resvn_size));
633 vg_assert(VG_IS_PAGE_ALIGNED(anon_start));
634 vg_assert(VG_IS_PAGE_ALIGNED(resvn_start));
635
636 /* Because there's been no brk activity yet: */
637 vg_assert(VG_(brk_base) == VG_(brk_limit));
638
639 /* Try to create the data seg and associated reservation where
640 VG_(brk_base) says. */
641 ok = VG_(am_create_reservation)(
642 resvn_start,
643 resvn_size,
644 SmLower,
645 anon_size
646 );
647
648 if (!ok) {
649 /* Hmm, that didn't work. Well, let aspacem suggest an address
650 it likes better, and try again with that. */
651 anon_start = VG_(am_get_advisory_client_simple)
652 ( 0/*floating*/, anon_size+resvn_size, &ok );
653 if (ok) {
654 resvn_start = anon_start + anon_size;
655 ok = VG_(am_create_reservation)(
656 resvn_start,
657 resvn_size,
658 SmLower,
659 anon_size
660 );
661 if (ok)
662 VG_(brk_base) = VG_(brk_limit) = anon_start;
663 }
664 /* that too might have failed, but if it has, we're hosed: there
665 is no Plan C. */
666 }
667 vg_assert(ok);
668
njn7c555a92005-11-16 17:16:10 +0000669 /* We make the data segment (heap) executable because LinuxThreads on
njn0ddabca2005-11-16 23:54:46 +0000670 ppc32 creates trampolines in this area. Also, on x86/Linux the data
671 segment is RWX natively, at least according to /proc/self/maps.
672 Also, having a non-executable data seg would kill any program which
673 tried to create code in the data seg and then run it. */
sewardj45f4e7c2005-09-27 19:20:21 +0000674 sres = VG_(am_mmap_anon_fixed_client)(
675 anon_start,
676 anon_size,
sewardj33ca9e82005-11-16 17:12:38 +0000677 VKI_PROT_READ|VKI_PROT_WRITE|VKI_PROT_EXEC
sewardj45f4e7c2005-09-27 19:20:21 +0000678 );
679 vg_assert(!sres.isError);
680 vg_assert(sres.val == anon_start);
681}
682
683
nethercote71980f02004-01-24 18:18:54 +0000684/*====================================================================*/
685/*=== Find executable ===*/
686/*====================================================================*/
687
sewardjfdf91b42005-09-28 00:53:09 +0000688/* Scan a colon-separated list, and call a function on each element.
689 The string must be mutable, because we insert a temporary '\0', but
690 the string will end up unmodified. (*func) should return True if it
691 doesn't need to see any more.
692
693 This routine will return True if (*func) returns True and False if
694 it reaches the end of the list without that happening.
695*/
696static Bool scan_colsep(char *colsep, Bool (*func)(const char *))
697{
698 char *cp, *entry;
699 int end;
700
701 if (colsep == NULL ||
702 *colsep == '\0')
703 return False;
704
705 entry = cp = colsep;
706
707 do {
708 end = (*cp == '\0');
709
710 if (*cp == ':' || *cp == '\0') {
711 char save = *cp;
712
713 *cp = '\0';
714 if ((*func)(entry)) {
715 *cp = save;
716 return True;
717 }
718 *cp = save;
719 entry = cp+1;
720 }
721 cp++;
722 } while(!end);
723
724 return False;
725}
726
sewardj45f4e7c2005-09-27 19:20:21 +0000727/* Need a static copy because can't use dynamic mem allocation yet */
njn73750612005-10-14 03:11:30 +0000728static HChar executable_name_in [VKI_PATH_MAX];
729static HChar executable_name_out[VKI_PATH_MAX];
thughes4ad52d02004-06-27 17:37:21 +0000730
sewardj45f4e7c2005-09-27 19:20:21 +0000731static Bool match_executable(const char *entry)
732{
njn73750612005-10-14 03:11:30 +0000733 HChar buf[VG_(strlen)(entry) + VG_(strlen)(executable_name_in) + 3];
thughes4ad52d02004-06-27 17:37:21 +0000734
njn73750612005-10-14 03:11:30 +0000735 /* empty PATH element means '.' */
thughes4ad52d02004-06-27 17:37:21 +0000736 if (*entry == '\0')
737 entry = ".";
738
njn73750612005-10-14 03:11:30 +0000739 VG_(snprintf)(buf, sizeof(buf), "%s/%s", entry, executable_name_in);
740
741 // Don't match directories
742 if (VG_(is_dir)(buf))
743 return False;
744
745 // If we match an executable, we choose that immediately. If we find a
746 // matching non-executable we remember it but keep looking for an
747 // matching executable later in the path.
sewardj45f4e7c2005-09-27 19:20:21 +0000748 if (VG_(access)(buf, True/*r*/, False/*w*/, True/*x*/) == 0) {
njn73750612005-10-14 03:11:30 +0000749 VG_(strncpy)( executable_name_out, buf, VKI_PATH_MAX-1 );
750 executable_name_out[VKI_PATH_MAX-1] = 0;
751 return True; // Stop looking
752 } else if (VG_(access)(buf, True/*r*/, False/*w*/, False/*x*/) == 0
753 && VG_STREQ(executable_name_out, ""))
754 {
755 VG_(strncpy)( executable_name_out, buf, VKI_PATH_MAX-1 );
756 executable_name_out[VKI_PATH_MAX-1] = 0;
757 return False; // Keep looking
758 } else {
759 return False; // Keep looking
thughes4ad52d02004-06-27 17:37:21 +0000760 }
thughes4ad52d02004-06-27 17:37:21 +0000761}
762
njn73750612005-10-14 03:11:30 +0000763// Returns NULL if it wasn't found.
sewardj45f4e7c2005-09-27 19:20:21 +0000764static HChar* find_executable ( HChar* exec )
nethercote71980f02004-01-24 18:18:54 +0000765{
766 vg_assert(NULL != exec);
njn73750612005-10-14 03:11:30 +0000767 if (VG_(strchr)(exec, '/')) {
768 // Has a '/' - use the name as is
769 VG_(strncpy)( executable_name_out, exec, VKI_PATH_MAX-1 );
770 } else {
771 // No '/' - we need to search the path
sewardj03d8aa82005-10-14 11:25:49 +0000772 HChar* path;
njn73750612005-10-14 03:11:30 +0000773 VG_(strncpy)( executable_name_in, exec, VKI_PATH_MAX-1 );
774 VG_(memset) ( executable_name_out, 0, VKI_PATH_MAX );
sewardj03d8aa82005-10-14 11:25:49 +0000775 path = VG_(getenv)("PATH");
thughes4ad52d02004-06-27 17:37:21 +0000776 scan_colsep(path, match_executable);
nethercote71980f02004-01-24 18:18:54 +0000777 }
njn73750612005-10-14 03:11:30 +0000778 return VG_STREQ(executable_name_out, "") ? NULL : executable_name_out;
nethercote71980f02004-01-24 18:18:54 +0000779}
780
781
782/*====================================================================*/
nethercotef4928da2004-06-15 10:54:40 +0000783/*=== Command line errors ===*/
784/*====================================================================*/
785
njnbe9b47b2005-05-15 16:22:58 +0000786static void revert_to_stderr ( void )
nethercotef4928da2004-06-15 10:54:40 +0000787{
njnbe9b47b2005-05-15 16:22:58 +0000788 vg_assert( !VG_(logging_to_socket) );
nethercotef8548672004-06-21 12:42:35 +0000789 VG_(clo_log_fd) = 2; /* stderr */
nethercotef4928da2004-06-15 10:54:40 +0000790}
791
792void VG_(bad_option) ( Char* opt )
793{
njnbe9b47b2005-05-15 16:22:58 +0000794 revert_to_stderr();
njn02bc4b82005-05-15 17:28:26 +0000795 VG_(printf)("valgrind: Bad option '%s'; aborting.\n", opt);
nethercotef4928da2004-06-15 10:54:40 +0000796 VG_(printf)("valgrind: Use --help for more information.\n");
797 VG_(exit)(1);
798}
799
nethercotef4928da2004-06-15 10:54:40 +0000800static void missing_prog ( void )
801{
njnbe9b47b2005-05-15 16:22:58 +0000802 revert_to_stderr();
nethercotef4928da2004-06-15 10:54:40 +0000803 VG_(printf)("valgrind: no program specified\n");
804 VG_(printf)("valgrind: Use --help for more information.\n");
805 VG_(exit)(1);
806}
807
808static void config_error ( Char* msg )
809{
njnbe9b47b2005-05-15 16:22:58 +0000810 revert_to_stderr();
nethercotef4928da2004-06-15 10:54:40 +0000811 VG_(printf)("valgrind: Startup or configuration error:\n %s\n", msg);
812 VG_(printf)("valgrind: Unable to start up properly. Giving up.\n");
813 VG_(exit)(1);
814}
815
816
nethercote71980f02004-01-24 18:18:54 +0000817/*====================================================================*/
818/*=== Loading the client ===*/
819/*====================================================================*/
820
sewardj45f4e7c2005-09-27 19:20:21 +0000821/* Load the client whose name is VG_(argv_the_exename). */
nethercote71980f02004-01-24 18:18:54 +0000822
sewardj45f4e7c2005-09-27 19:20:21 +0000823static void load_client ( /*OUT*/struct exeinfo* info,
824 /*OUT*/Addr* client_eip)
825{
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 */
853 *client_eip = info->init_eip;
sewardj45f4e7c2005-09-27 19:20:21 +0000854 VG_(brk_base) = VG_(brk_limit) = VG_PGROUNDUP(info->brkbase);
nethercote71980f02004-01-24 18:18:54 +0000855}
856
nethercote969ecf12004-10-13 17:29:01 +0000857
sewardj71bc3cb2005-05-19 00:25:45 +0000858/*====================================================================*/
859/*=== Command-line: variables, processing, etc ===*/
860/*====================================================================*/
861
862// See pub_{core,tool}_options.h for explanations of all these.
863
sewardj45f4e7c2005-09-27 19:20:21 +0000864static void usage_NORETURN ( Bool debug_help )
njn7cf0bd32002-06-08 13:36:03 +0000865{
njn25e49d8e72002-09-23 09:36:25 +0000866 Char* usage1 =
njn00cfcfc2005-11-12 18:53:50 +0000867"usage: valgrind [options] prog-and-args\n"
njn25e49d8e72002-09-23 09:36:25 +0000868"\n"
nethercote2b0793f2003-12-02 10:41:18 +0000869" common user options for all Valgrind tools, with defaults in [ ]:\n"
sewardjb5f6f512005-03-10 23:59:00 +0000870" --tool=<name> use the Valgrind tool named <name> [memcheck]\n"
nethercotea76368b2004-06-16 11:56:29 +0000871" -h --help show this message\n"
nethercote6c999f22004-01-31 22:55:15 +0000872" --help-debug show this message, plus debugging options\n"
njn25e49d8e72002-09-23 09:36:25 +0000873" --version show version\n"
njn25e49d8e72002-09-23 09:36:25 +0000874" -q --quiet run silently; only print error msgs\n"
875" -v --verbose be more verbose, incl counts of errors\n"
nethercote77eba602003-11-13 17:35:04 +0000876" --trace-children=no|yes Valgrind-ise child processes? [no]\n"
nethercote0d588502004-06-21 13:27:11 +0000877" --track-fds=no|yes track open file descriptors? [no]\n"
thughes6233a382004-08-21 11:10:44 +0000878" --time-stamp=no|yes add timestamps to log messages? [no]\n"
njnce545552005-07-25 22:36:52 +0000879" --log-fd=<number> log messages to file descriptor [2=stderr]\n"
tombbe14b12005-11-04 16:49:39 +0000880" --log-file=<file> log messages to <file>.<pid>\n"
njnce545552005-07-25 22:36:52 +0000881" --log-file-exactly=<file> log messages to <file>\n"
882" --log-file-qualifier=<VAR> incorporate $VAR in logfile name [none]\n"
883" --log-socket=ipaddr:port log messages to socket ipaddr:port\n"
nethercote2b0793f2003-12-02 10:41:18 +0000884"\n"
885" uncommon user options for all Valgrind tools:\n"
nethercote0d588502004-06-21 13:27:11 +0000886" --run-libc-freeres=no|yes free up glibc memory at exit? [yes]\n"
njn628add62005-11-12 18:21:40 +0000887" --sim-hints=hint1,hint2,... known hints:\n"
sewardj19617ae2005-10-20 01:09:57 +0000888" lax-ioctls, enable-outer [none]\n"
sewardjb1131a82005-03-19 15:12:21 +0000889" --show-emwarns=no|yes show warnings about emulation limits? [no]\n"
sewardj6c3a2192005-07-24 07:00:45 +0000890" --smc-check=none|stack|all checks for self-modifying code: none,\n"
891" only for code found in stacks, or all [stack]\n"
sewardj3c3f0c12005-11-08 15:52:36 +0000892" --kernel-variant=variant1,variant2,... known variants: bproc [none]\n"
893" handle non-standard kernel variants\n"
njn25e49d8e72002-09-23 09:36:25 +0000894"\n"
nethercote2b0793f2003-12-02 10:41:18 +0000895" user options for Valgrind tools that report errors:\n"
njnce545552005-07-25 22:36:52 +0000896" --xml=yes all output is in XML (Memcheck/Nulgrind only)\n"
njnc8ec9f82005-07-20 03:03:28 +0000897" --xml-user-comment=STR copy STR verbatim to XML output\n"
nethercote2b0793f2003-12-02 10:41:18 +0000898" --demangle=no|yes automatically demangle C++ names? [yes]\n"
njn20b4a152005-10-19 22:39:40 +0000899" --num-callers=<number> show <number> callers in stack traces [12]\n"
nethercote2b0793f2003-12-02 10:41:18 +0000900" --error-limit=no|yes stop showing new errors if too many? [yes]\n"
901" --show-below-main=no|yes continue stack traces below main() [no]\n"
902" --suppressions=<filename> suppress errors described in <filename>\n"
sewardjd153fae2005-01-10 17:24:47 +0000903" --gen-suppressions=no|yes|all print suppressions for errors? [no]\n"
nethercote04d0fbc2004-01-26 16:48:06 +0000904" --db-attach=no|yes start debugger when errors detected? [no]\n"
905" --db-command=<command> command to start debugger [gdb -nw %%f %%p]\n"
906" --input-fd=<number> file descriptor for input [0=stdin]\n"
sewardj97724e52005-04-02 23:40:59 +0000907" --max-stackframe=<number> assume stack switch for SP changes larger\n"
908" than <number> bytes [2000000]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +0000909"\n";
njn7cf0bd32002-06-08 13:36:03 +0000910
njn25e49d8e72002-09-23 09:36:25 +0000911 Char* usage2 =
912"\n"
nethercote2b0793f2003-12-02 10:41:18 +0000913" debugging options for all Valgrind tools:\n"
njn25e49d8e72002-09-23 09:36:25 +0000914" --sanity-level=<number> level of sanity checking to do [1]\n"
nethercote137bc552003-11-14 17:47:54 +0000915" --profile=no|yes profile? (tool must be built for it) [no]\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"
njn20b4a152005-10-19 22:39:40 +0000918" --trace-notbelow=<number> only show BBs above <number> [0]\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"
njn25e49d8e72002-09-23 09:36:25 +0000923" --trace-sched=no|yes show thread scheduler details? [no]\n"
jsgf855d93d2003-10-13 22:26:55 +0000924" --wait-for-gdb=yes|no pause on startup to wait for gdb attach\n"
sewardjb5f6f512005-03-10 23:59:00 +0000925#if 0
926" --model-pthreads=yes|no model the pthreads library [no]\n"
927#endif
928" --command-line-only=no|yes only use command line options [no]\n"
njn613812e2005-03-11 04:57:30 +0000929"\n"
930" --vex-iropt-verbosity 0 .. 9 [0]\n"
931" --vex-iropt-level 0 .. 2 [2]\n"
932" --vex-iropt-precise-memory-exns [no]\n"
sewardj8b635a42004-11-22 19:01:47 +0000933" --vex-iropt-unroll-thresh 0 .. 400 [120]\n"
934" --vex-guest-max-insns 1 .. 100 [50]\n"
935" --vex-guest-chase-thresh 0 .. 99 [10]\n"
936"\n"
sewardjfa8ec112005-01-19 11:55:34 +0000937" --trace-flags and --profile-flags values (omit the middle space):\n"
sewardj2a99cf62004-11-24 10:44:19 +0000938" 1000 0000 show conversion into IR\n"
939" 0100 0000 show after initial opt\n"
940" 0010 0000 show after instrumentation\n"
941" 0001 0000 show after second opt\n"
942" 0000 1000 show after tree building\n"
943" 0000 0100 show selecting insns\n"
944" 0000 0010 show after reg-alloc\n"
945" 0000 0001 show final assembly\n"
946"\n"
nethercote2b0793f2003-12-02 10:41:18 +0000947" debugging options for Valgrind tools that report errors\n"
948" --dump-error=<number> show translation for basic block associated\n"
949" with <number>'th error context [0=show none]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +0000950"\n";
njn3e884182003-04-15 13:03:23 +0000951
952 Char* usage3 =
953"\n"
nethercote71980f02004-01-24 18:18:54 +0000954" Extra options read from ~/.valgrindrc, $VALGRIND_OPTS, ./.valgrindrc\n"
njn25e49d8e72002-09-23 09:36:25 +0000955"\n"
njn53612422005-03-12 16:22:54 +0000956" Valgrind is Copyright (C) 2000-2005 Julian Seward et al.\n"
njn25e49d8e72002-09-23 09:36:25 +0000957" and licensed under the GNU General Public License, version 2.\n"
958" Bug reports, feedback, admiration, abuse, etc, to: %s.\n"
njnd04b7c62002-10-03 14:05:52 +0000959"\n"
nethercote137bc552003-11-14 17:47:54 +0000960" Tools are copyright and licensed by their authors. See each\n"
961" tool's start-up message for more information.\n"
njn25e49d8e72002-09-23 09:36:25 +0000962"\n";
njn7cf0bd32002-06-08 13:36:03 +0000963
njnbe9b47b2005-05-15 16:22:58 +0000964 // Ensure the message goes to stdout
965 VG_(clo_log_fd) = 1;
966 vg_assert( !VG_(logging_to_socket) );
967
fitzhardinge98abfc72003-12-16 02:05:15 +0000968 VG_(printf)(usage1);
969 if (VG_(details).name) {
970 VG_(printf)(" user options for %s:\n", VG_(details).name);
fitzhardinge98abfc72003-12-16 02:05:15 +0000971 if (VG_(needs).command_line_options)
njn51d827b2005-05-09 01:02:08 +0000972 VG_TDICT_CALL(tool_print_usage);
fitzhardinge98abfc72003-12-16 02:05:15 +0000973 else
974 VG_(printf)(" (none)\n");
975 }
nethercote6c999f22004-01-31 22:55:15 +0000976 if (debug_help) {
977 VG_(printf)(usage2);
fitzhardinge98abfc72003-12-16 02:05:15 +0000978
nethercote6c999f22004-01-31 22:55:15 +0000979 if (VG_(details).name) {
980 VG_(printf)(" debugging options for %s:\n", VG_(details).name);
981
982 if (VG_(needs).command_line_options)
njn51d827b2005-05-09 01:02:08 +0000983 VG_TDICT_CALL(tool_print_debug_usage);
nethercote6c999f22004-01-31 22:55:15 +0000984 else
985 VG_(printf)(" (none)\n");
986 }
fitzhardinge98abfc72003-12-16 02:05:15 +0000987 }
nethercote421281e2003-11-20 16:20:55 +0000988 VG_(printf)(usage3, VG_BUGS_TO);
nethercotef4928da2004-06-15 10:54:40 +0000989 VG_(exit)(0);
njn7cf0bd32002-06-08 13:36:03 +0000990}
sewardjde4a1d02002-03-22 01:27:54 +0000991
sewardjde4a1d02002-03-22 01:27:54 +0000992
sewardj45f4e7c2005-09-27 19:20:21 +0000993/* Peer at previously set up VG_(args_for_valgrind) and extract any
994 request for help and also the tool name. */
995
996static void get_helprequest_and_toolname ( Int* need_help, HChar** tool )
997{
998 UInt i;
999 HChar* str;
sewardj8b635a42004-11-22 19:01:47 +00001000
nethercote71980f02004-01-24 18:18:54 +00001001 /* parse the options we have (only the options we care about now) */
sewardj45f4e7c2005-09-27 19:20:21 +00001002 for (i = 0; i < VG_(args_for_valgrind).used; i++) {
nethercote71980f02004-01-24 18:18:54 +00001003
sewardj45f4e7c2005-09-27 19:20:21 +00001004 str = VG_(args_for_valgrind).strs[i];
1005 vg_assert(str);
nethercote71980f02004-01-24 18:18:54 +00001006
sewardj45f4e7c2005-09-27 19:20:21 +00001007 if (VG_STREQ(str, "--version")) {
njn2e9f3f32005-10-26 16:17:46 +00001008 // Ensure the version string goes to stdout
1009 VG_(clo_log_fd) = 1;
sewardj45f4e7c2005-09-27 19:20:21 +00001010 VG_(printf)("valgrind-" VERSION "\n");
1011 VG_(exit)(0);
1012
1013 } else if (VG_CLO_STREQ(str, "--help") ||
1014 VG_CLO_STREQ(str, "-h")) {
nethercote6c999f22004-01-31 22:55:15 +00001015 *need_help = 1;
1016
sewardj45f4e7c2005-09-27 19:20:21 +00001017 } else if (VG_CLO_STREQ(str, "--help-debug")) {
nethercote6c999f22004-01-31 22:55:15 +00001018 *need_help = 2;
nethercote71980f02004-01-24 18:18:54 +00001019
sewardj45f4e7c2005-09-27 19:20:21 +00001020 // The tool has already been determined, but we need to know the name
1021 // here.
1022 } else if (VG_CLO_STREQN(7, str, "--tool=")) {
1023 *tool = &str[7];
nethercote71980f02004-01-24 18:18:54 +00001024 }
1025 }
nethercote71980f02004-01-24 18:18:54 +00001026}
1027
sewardj45f4e7c2005-09-27 19:20:21 +00001028static Bool process_cmd_line_options( UInt* client_auxv, const char* toolname )
nethercote71980f02004-01-24 18:18:54 +00001029{
njnda033f52005-12-19 21:27:58 +00001030 // VG_(clo_log_fd) is used by all the messaging. It starts as 2 (stderr)
1031 // and we cannot change it until we know what we are changing it to is
1032 // ok. So we have tmp_log_fd to hold the tmp fd prior to that point.
sewardj92645592005-07-23 09:18:34 +00001033 SysRes sres;
njnda033f52005-12-19 21:27:58 +00001034 Int i, tmp_log_fd;
sewardj92645592005-07-23 09:18:34 +00001035 Int toolname_len = VG_(strlen)(toolname);
njnbe9b47b2005-05-15 16:22:58 +00001036 enum {
1037 VgLogTo_Fd,
1038 VgLogTo_File,
1039 VgLogTo_FileExactly,
1040 VgLogTo_Socket
1041 } log_to = VgLogTo_Fd; // Where is logging output to be sent?
sewardjde4a1d02002-03-22 01:27:54 +00001042
nethercotee1730692003-11-20 10:38:07 +00001043 /* log to stderr by default, but usage message goes to stdout */
njnda033f52005-12-19 21:27:58 +00001044 tmp_log_fd = 2;
sewardjde4a1d02002-03-22 01:27:54 +00001045
sewardj19d81412002-06-03 01:10:40 +00001046 /* Check for sane path in ./configure --prefix=... */
fitzhardinge98abfc72003-12-16 02:05:15 +00001047 if (VG_LIBDIR[0] != '/')
sewardj19d81412002-06-03 01:10:40 +00001048 config_error("Please use absolute paths in "
1049 "./configure --prefix=... or --libdir=...");
sewardj38170912002-05-10 21:07:22 +00001050
sewardj45f4e7c2005-09-27 19:20:21 +00001051 for (i = 0; i < VG_(args_for_valgrind).used; i++) {
nethercote71980f02004-01-24 18:18:54 +00001052
sewardj45f4e7c2005-09-27 19:20:21 +00001053 HChar* arg = VG_(args_for_valgrind).strs[i];
1054 HChar* colon = arg;
nethercote71980f02004-01-24 18:18:54 +00001055
thughes3bfd5a02004-07-18 08:05:44 +00001056 /* Look for a colon in the switch name */
1057 while (*colon && *colon != ':' && *colon != '=')
1058 colon++;
nethercote71980f02004-01-24 18:18:54 +00001059
1060 /* Look for matching "--toolname:foo" */
thughes3bfd5a02004-07-18 08:05:44 +00001061 if (*colon == ':') {
nethercote71980f02004-01-24 18:18:54 +00001062 if (VG_CLO_STREQN(2, arg, "--") &&
1063 VG_CLO_STREQN(toolname_len, arg+2, toolname) &&
1064 VG_CLO_STREQN(1, arg+2+toolname_len, ":"))
1065 {
1066 // prefix matches, convert "--toolname:foo" to "--foo"
1067 if (0)
1068 VG_(printf)("tool-specific arg: %s\n", arg);
sewardj45f4e7c2005-09-27 19:20:21 +00001069 arg = VG_(strdup)(arg + toolname_len + 1);
nethercote71980f02004-01-24 18:18:54 +00001070 arg[0] = '-';
1071 arg[1] = '-';
1072
1073 } else {
1074 // prefix doesn't match, skip to next arg
1075 continue;
1076 }
1077 }
1078
fitzhardinge98abfc72003-12-16 02:05:15 +00001079 /* Ignore these options - they've already been handled */
njn45270a22005-03-27 01:00:11 +00001080 if (VG_CLO_STREQN( 7, arg, "--tool=")) goto skip_arg;
njn45270a22005-03-27 01:00:11 +00001081 if (VG_CLO_STREQN(20, arg, "--command-line-only=")) goto skip_arg;
fitzhardinge98abfc72003-12-16 02:05:15 +00001082
njn45270a22005-03-27 01:00:11 +00001083 if ( VG_CLO_STREQ(arg, "--")) goto skip_arg;
nethercote27fec902004-06-16 21:26:32 +00001084
nethercote71980f02004-01-24 18:18:54 +00001085 else if (VG_CLO_STREQ(arg, "-v") ||
1086 VG_CLO_STREQ(arg, "--verbose"))
sewardjde4a1d02002-03-22 01:27:54 +00001087 VG_(clo_verbosity)++;
nethercote27fec902004-06-16 21:26:32 +00001088
nethercote71980f02004-01-24 18:18:54 +00001089 else if (VG_CLO_STREQ(arg, "-q") ||
1090 VG_CLO_STREQ(arg, "--quiet"))
sewardjde4a1d02002-03-22 01:27:54 +00001091 VG_(clo_verbosity)--;
1092
sewardj1cf558c2005-04-25 01:36:56 +00001093 else if (VG_CLO_STREQ(arg, "-d")) {
1094 /* do nothing */
1095 }
1096
sewardj71bc3cb2005-05-19 00:25:45 +00001097 else VG_BOOL_CLO(arg, "--xml", VG_(clo_xml))
njn45270a22005-03-27 01:00:11 +00001098 else VG_BOOL_CLO(arg, "--db-attach", VG_(clo_db_attach))
1099 else VG_BOOL_CLO(arg, "--demangle", VG_(clo_demangle))
1100 else VG_BOOL_CLO(arg, "--error-limit", VG_(clo_error_limit))
njn45270a22005-03-27 01:00:11 +00001101 else VG_BOOL_CLO(arg, "--show-emwarns", VG_(clo_show_emwarns))
sewardj97724e52005-04-02 23:40:59 +00001102 else VG_NUM_CLO (arg, "--max-stackframe", VG_(clo_max_stackframe))
njn45270a22005-03-27 01:00:11 +00001103 else VG_BOOL_CLO(arg, "--profile", VG_(clo_profile))
1104 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 );
1649 VG_(message)(Vg_DebugMsg, "Arch and subarch: %s, %s",
1650 LibVEX_ppVexArch ( vex_arch ),
1651 LibVEX_ppVexSubArch( vex_archinfo.subarch ) );
1652 VG_(message)(Vg_DebugMsg, "Valgrind library directory: %s", VG_(libdir));
sewardjde4a1d02002-03-22 01:27:54 +00001653 }
nethercotef6a1d502004-08-09 12:21:57 +00001654}
1655
sewardjde4a1d02002-03-22 01:27:54 +00001656
nethercote71980f02004-01-24 18:18:54 +00001657/*====================================================================*/
1658/*=== File descriptor setup ===*/
1659/*====================================================================*/
1660
sewardj5f229e22005-09-28 01:36:01 +00001661/* Number of file descriptors that Valgrind tries to reserve for
1662 it's own use - just a small constant. */
1663#define N_RESERVED_FDS (10)
1664
nethercote71980f02004-01-24 18:18:54 +00001665static void setup_file_descriptors(void)
1666{
1667 struct vki_rlimit rl;
1668
1669 /* Get the current file descriptor limits. */
1670 if (VG_(getrlimit)(VKI_RLIMIT_NOFILE, &rl) < 0) {
1671 rl.rlim_cur = 1024;
1672 rl.rlim_max = 1024;
1673 }
1674
1675 /* Work out where to move the soft limit to. */
njn14319cc2005-03-13 06:26:22 +00001676 if (rl.rlim_cur + N_RESERVED_FDS <= rl.rlim_max) {
1677 rl.rlim_cur = rl.rlim_cur + N_RESERVED_FDS;
nethercote71980f02004-01-24 18:18:54 +00001678 } else {
1679 rl.rlim_cur = rl.rlim_max;
1680 }
1681
1682 /* Reserve some file descriptors for our use. */
njn14319cc2005-03-13 06:26:22 +00001683 VG_(fd_soft_limit) = rl.rlim_cur - N_RESERVED_FDS;
1684 VG_(fd_hard_limit) = rl.rlim_cur - N_RESERVED_FDS;
nethercote71980f02004-01-24 18:18:54 +00001685
1686 /* Update the soft limit. */
1687 VG_(setrlimit)(VKI_RLIMIT_NOFILE, &rl);
1688
sewardj45f4e7c2005-09-27 19:20:21 +00001689 if (VG_(cl_exec_fd) != -1)
1690 VG_(cl_exec_fd) = VG_(safe_fd)( VG_(cl_exec_fd) );
nethercote71980f02004-01-24 18:18:54 +00001691}
1692
sewardjde4a1d02002-03-22 01:27:54 +00001693
njn2da73352005-06-18 01:35:16 +00001694/*====================================================================*/
1695/*=== Initialise the first thread. ===*/
1696/*====================================================================*/
1697
1698/* Given a pointer to the ThreadArchState for thread 1 (the root
1699 thread), initialise the VEX guest state, and copy in essential
1700 starting values.
1701*/
1702static void init_thread1state ( Addr client_ip,
sewardjfdf91b42005-09-28 00:53:09 +00001703 Addr client_sp,
cerionc7266522005-12-08 03:24:37 +00001704 Addr entry,
njn2da73352005-06-18 01:35:16 +00001705 /*inout*/ ThreadArchState* arch )
1706{
1707#if defined(VGA_x86)
1708 vg_assert(0 == sizeof(VexGuestX86State) % 8);
1709
1710 /* Zero out the initial state, and set up the simulated FPU in a
1711 sane way. */
1712 LibVEX_GuestX86_initialise(&arch->vex);
1713
1714 /* Zero out the shadow area. */
1715 VG_(memset)(&arch->vex_shadow, 0, sizeof(VexGuestX86State));
1716
1717 /* Put essential stuff into the new state. */
sewardjfdf91b42005-09-28 00:53:09 +00001718 arch->vex.guest_ESP = client_sp;
njn2da73352005-06-18 01:35:16 +00001719 arch->vex.guest_EIP = client_ip;
1720
1721 /* initialise %cs, %ds and %ss to point at the operating systems
1722 default code, data and stack segments */
1723 asm volatile("movw %%cs, %0" : : "m" (arch->vex.guest_CS));
1724 asm volatile("movw %%ds, %0" : : "m" (arch->vex.guest_DS));
1725 asm volatile("movw %%ss, %0" : : "m" (arch->vex.guest_SS));
cerion85665ca2005-06-20 15:51:07 +00001726
njn2da73352005-06-18 01:35:16 +00001727#elif defined(VGA_amd64)
1728 vg_assert(0 == sizeof(VexGuestAMD64State) % 8);
1729
1730 /* Zero out the initial state, and set up the simulated FPU in a
1731 sane way. */
1732 LibVEX_GuestAMD64_initialise(&arch->vex);
1733
1734 /* Zero out the shadow area. */
1735 VG_(memset)(&arch->vex_shadow, 0, sizeof(VexGuestAMD64State));
1736
1737 /* Put essential stuff into the new state. */
sewardjfdf91b42005-09-28 00:53:09 +00001738 arch->vex.guest_RSP = client_sp;
njn2da73352005-06-18 01:35:16 +00001739 arch->vex.guest_RIP = client_ip;
cerion85665ca2005-06-20 15:51:07 +00001740
1741#elif defined(VGA_ppc32)
1742 vg_assert(0 == sizeof(VexGuestPPC32State) % 8);
1743
1744 /* Zero out the initial state, and set up the simulated FPU in a
1745 sane way. */
1746 LibVEX_GuestPPC32_initialise(&arch->vex);
1747
1748 /* Zero out the shadow area. */
1749 VG_(memset)(&arch->vex_shadow, 0, sizeof(VexGuestPPC32State));
1750
1751 /* Put essential stuff into the new state. */
sewardjfdf91b42005-09-28 00:53:09 +00001752 arch->vex.guest_GPR1 = client_sp;
cerion85665ca2005-06-20 15:51:07 +00001753 arch->vex.guest_CIA = client_ip;
1754
sewardj2c48c7b2005-11-29 13:05:56 +00001755#elif defined(VGA_ppc64)
cerion21082042005-12-06 19:07:08 +00001756 vg_assert(0 == sizeof(VexGuestPPC64State) % 16);
sewardj2c48c7b2005-11-29 13:05:56 +00001757
1758 /* Zero out the initial state, and set up the simulated FPU in a
1759 sane way. */
1760 LibVEX_GuestPPC64_initialise(&arch->vex);
1761
1762 /* Zero out the shadow area. */
1763 VG_(memset)(&arch->vex_shadow, 0, sizeof(VexGuestPPC64State));
1764
1765 /* Put essential stuff into the new state. */
1766 arch->vex.guest_GPR1 = client_sp;
cerionc7266522005-12-08 03:24:37 +00001767 arch->vex.guest_GPR2 = ((ULong*)entry)[1]; // TOC ptr
sewardj2c48c7b2005-11-29 13:05:56 +00001768 arch->vex.guest_CIA = client_ip;
njn2da73352005-06-18 01:35:16 +00001769#else
1770# error Unknown arch
1771#endif
1772 // Tell the tool that we just wrote to the registers.
1773 VG_TRACK( post_reg_write, Vg_CoreStartup, /*tid*/1, /*offset*/0,
1774 sizeof(VexGuestArchState));
1775}
1776
sewardjde4a1d02002-03-22 01:27:54 +00001777
nethercote71980f02004-01-24 18:18:54 +00001778/*====================================================================*/
njn2025cf92005-06-26 20:44:48 +00001779/*=== BB profiling ===*/
1780/*====================================================================*/
1781
1782static
1783void show_BB_profile ( BBProfEntry tops[], UInt n_tops, ULong score_total )
1784{
1785 ULong score_cumul, score_here;
1786 Char buf_cumul[10], buf_here[10];
1787 Char name[64];
1788 Int r;
1789
1790 VG_(printf)("\n");
1791 VG_(printf)("-----------------------------------------------------------\n");
1792 VG_(printf)("--- BEGIN BB Profile (summary of scores) ---\n");
1793 VG_(printf)("-----------------------------------------------------------\n");
1794 VG_(printf)("\n");
1795
1796 VG_(printf)("Total score = %lld\n\n", score_total);
1797
1798 score_cumul = 0;
1799 for (r = 0; r < n_tops; r++) {
1800 if (tops[r].addr == 0)
1801 continue;
1802 name[0] = 0;
1803 VG_(get_fnname_w_offset)(tops[r].addr, name, 64);
1804 name[63] = 0;
1805 score_here = tops[r].score;
1806 score_cumul += score_here;
1807 VG_(percentify)(score_cumul, score_total, 2, 6, buf_cumul);
1808 VG_(percentify)(score_here, score_total, 2, 6, buf_here);
1809 VG_(printf)("%3d: (%9lld %s) %9lld %s 0x%llx %s\n",
1810 r,
1811 score_cumul, buf_cumul,
1812 score_here, buf_here, tops[r].addr, name );
1813 }
1814
1815 VG_(printf)("\n");
1816 VG_(printf)("-----------------------------------------------------------\n");
1817 VG_(printf)("--- BB Profile (BB details) ---\n");
1818 VG_(printf)("-----------------------------------------------------------\n");
1819 VG_(printf)("\n");
1820
1821 score_cumul = 0;
1822 for (r = 0; r < n_tops; r++) {
1823 if (tops[r].addr == 0)
1824 continue;
1825 name[0] = 0;
1826 VG_(get_fnname_w_offset)(tops[r].addr, name, 64);
1827 name[63] = 0;
1828 score_here = tops[r].score;
1829 score_cumul += score_here;
1830 VG_(percentify)(score_cumul, score_total, 2, 6, buf_cumul);
1831 VG_(percentify)(score_here, score_total, 2, 6, buf_here);
1832 VG_(printf)("\n");
1833 VG_(printf)("=-=-=-=-=-=-=-=-=-=-=-=-=-= begin BB rank %d "
1834 "=-=-=-=-=-=-=-=-=-=-=-=-=-=\n\n", r);
1835 VG_(printf)("%3d: (%9lld %s) %9lld %s 0x%llx %s\n",
1836 r,
1837 score_cumul, buf_cumul,
1838 score_here, buf_here, tops[r].addr, name );
1839 VG_(printf)("\n");
1840 VG_(translate)(0, tops[r].addr, True, VG_(clo_profile_flags), 0);
1841 VG_(printf)("=-=-=-=-=-=-=-=-=-=-=-=-=-= end BB rank %d "
1842 "=-=-=-=-=-=-=-=-=-=-=-=-=-=\n\n", r);
1843 }
1844
1845 VG_(printf)("\n");
1846 VG_(printf)("-----------------------------------------------------------\n");
1847 VG_(printf)("--- END BB Profile ---\n");
1848 VG_(printf)("-----------------------------------------------------------\n");
1849 VG_(printf)("\n");
1850}
1851
1852
1853/*====================================================================*/
nethercote71980f02004-01-24 18:18:54 +00001854/*=== main() ===*/
1855/*====================================================================*/
1856
sewardjfdf91b42005-09-28 00:53:09 +00001857/* When main() is entered, we should be on the following stack, not
1858 the one the kernel gave us. We will run on this stack until
1859 simulation of the root thread is started, at which point a transfer
1860 is made to a dynamically allocated stack. This is for the sake of
1861 uniform overflow detection for all Valgrind threads. This is
1862 marked global even though it isn't, because assembly code below
1863 needs to reference the name. */
1864
1865/*static*/ VgStack VG_(interim_stack);
1866
1867/* This should get some address inside the stack on which we gained
1868 control (eg, it could be the SP at startup). It doesn't matter
1869 exactly where in the stack it is. This value is passed to the
1870 address space manager at startup, which uses it to identify the
1871 initial stack segment and hence the upper end of the usable address
1872 space. */
1873
1874static Addr sp_at_startup = 0;
1875
sewardj1ae3f3a2005-09-28 10:47:38 +00001876/* --- Forwards decls to do with shutdown --- */
1877
1878static void final_tidyup(ThreadId tid);
1879
1880/* Do everything which needs doing when the last thread exits */
1881static
1882void shutdown_actions_NORETURN( ThreadId tid,
1883 VgSchedReturnCode tids_schedretcode );
1884
1885/* --- end of Forwards decls to do with shutdown --- */
sewardjfdf91b42005-09-28 00:53:09 +00001886
1887
sewardj45f4e7c2005-09-27 19:20:21 +00001888/* TODO: GIVE THIS A PROPER HOME
1889 TODO: MERGE THIS WITH DUPLICATE IN mac_leakcheck.c
1890 Extract from aspacem a vector of the current segment start
1891 addresses. The vector is dynamically allocated and should be freed
1892 by the caller when done. REQUIRES m_mallocfree to be running.
1893 Writes the number of addresses required into *n_acquired. */
nethercotec314eba2004-07-15 12:59:41 +00001894
sewardj45f4e7c2005-09-27 19:20:21 +00001895static Addr* get_seg_starts ( /*OUT*/Int* n_acquired )
sewardj1cf558c2005-04-25 01:36:56 +00001896{
sewardj45f4e7c2005-09-27 19:20:21 +00001897 Addr* starts;
sewardja48a4932005-09-29 11:09:56 +00001898 Int n_starts, r = 0;
sewardj45f4e7c2005-09-27 19:20:21 +00001899
1900 n_starts = 1;
sewardj1cf558c2005-04-25 01:36:56 +00001901 while (True) {
sewardj45f4e7c2005-09-27 19:20:21 +00001902 starts = VG_(malloc)( n_starts * sizeof(Addr) );
1903 if (starts == NULL)
1904 break;
1905 r = VG_(am_get_segment_starts)( starts, n_starts );
1906 if (r >= 0)
1907 break;
1908 VG_(free)(starts);
1909 n_starts *= 2;
sewardj1cf558c2005-04-25 01:36:56 +00001910 }
sewardj45f4e7c2005-09-27 19:20:21 +00001911
1912 if (starts == NULL) {
1913 *n_acquired = 0;
1914 return NULL;
1915 }
1916
1917 *n_acquired = r;
1918 return starts;
sewardj1cf558c2005-04-25 01:36:56 +00001919}
1920
1921
sewardj45f4e7c2005-09-27 19:20:21 +00001922
sewardj45f4e7c2005-09-27 19:20:21 +00001923Int main(Int argc, HChar **argv, HChar **envp)
nethercote71980f02004-01-24 18:18:54 +00001924{
sewardj45f4e7c2005-09-27 19:20:21 +00001925 HChar* toolname = "memcheck"; // default to Memcheck
1926 HChar** env = NULL;
1927 Int need_help = 0; // 0 = no, 1 = --help, 2 = --help-debug
1928 Addr initial_client_IP = 0;
1929 Addr initial_client_SP = 0;
1930 Addr clstack_top = 0;
1931 SizeT clstack_max_size = 0;
1932 UInt* client_auxv;
1933 Int loglevel, i;
1934 Bool logging_to_fd;
nethercote73b526f2004-10-31 18:48:21 +00001935 struct vki_rlimit zero = { 0, 0 };
sewardj45f4e7c2005-09-27 19:20:21 +00001936 struct exeinfo info;
nethercote71980f02004-01-24 18:18:54 +00001937
1938 //============================================================
nethercote71980f02004-01-24 18:18:54 +00001939 //
sewardj45f4e7c2005-09-27 19:20:21 +00001940 // Nb: startup is complex. Prerequisites are shown at every step.
nethercote71980f02004-01-24 18:18:54 +00001941 // *** Be very careful when messing with the order ***
sewardj45f4e7c2005-09-27 19:20:21 +00001942 //
1943 // The first order of business is to get debug logging, the address
1944 // space manager and the dynamic memory manager up and running.
1945 // Once that's done, we can relax a bit.
1946 //
nethercote71980f02004-01-24 18:18:54 +00001947 //============================================================
sewardj45f4e7c2005-09-27 19:20:21 +00001948
1949 /* This is needed to make VG_(getenv) usable early. */
1950 VG_(client_envp) = (Char**)envp;
nethercote71980f02004-01-24 18:18:54 +00001951
sewardj1cf558c2005-04-25 01:36:56 +00001952 //--------------------------------------------------------------
1953 // Start up the logging mechanism
1954 // p: none
1955 //--------------------------------------------------------------
1956 /* Start the debugging-log system ASAP. First find out how many
1957 "-d"s were specified. This is a pre-scan of the command line. */
1958 loglevel = 0;
1959 for (i = 1; i < argc; i++) {
sewardj10759312005-05-30 23:52:47 +00001960 if (argv[i][0] != '-')
1961 break;
sewardj45f4e7c2005-09-27 19:20:21 +00001962 if (VG_STREQ(argv[i], "--"))
sewardj10759312005-05-30 23:52:47 +00001963 break;
sewardj45f4e7c2005-09-27 19:20:21 +00001964 if (VG_STREQ(argv[i], "-d"))
sewardj10759312005-05-30 23:52:47 +00001965 loglevel++;
sewardj1cf558c2005-04-25 01:36:56 +00001966 }
1967
1968 /* ... and start the debug logger. Now we can safely emit logging
1969 messages all through startup. */
sewardj10759312005-05-30 23:52:47 +00001970 VG_(debugLog_startup)(loglevel, "Stage 2 (main)");
sewardj45f4e7c2005-09-27 19:20:21 +00001971 VG_(debugLog)(1, "main", "Welcome to Valgrind version "
1972 VERSION " debug logging\n");
1973
1974 //--------------------------------------------------------------
1975 // Ensure we're on a plausible stack.
1976 // p: logging
1977 //--------------------------------------------------------------
1978 VG_(debugLog)(1, "main", "Checking current stack is plausible\n");
sewardjfdf91b42005-09-28 00:53:09 +00001979 { HChar* limLo = (HChar*)(&VG_(interim_stack).bytes[0]);
1980 HChar* limHi = limLo + sizeof(VG_(interim_stack));
sewardj45f4e7c2005-09-27 19:20:21 +00001981 HChar* aLocal = (HChar*)&zero; /* any auto local will do */
1982 if (aLocal < limLo || aLocal >= limHi) {
1983 /* something's wrong. Stop. */
1984 VG_(debugLog)(0, "main", "Root stack %p to %p, a local %p\n",
1985 limLo, limHi, aLocal );
1986 VG_(debugLog)(0, "main", "Valgrind: FATAL: "
1987 "Initial stack switched failed.\n");
1988 VG_(debugLog)(0, "main", " Cannot continue. Sorry.\n");
1989 VG_(exit)(1);
1990 }
1991 }
1992
1993 //--------------------------------------------------------------
1994 // Ensure we have a plausible pointer to the stack on which
1995 // we gained control (not the current stack!)
1996 // p: logging
1997 //--------------------------------------------------------------
1998 VG_(debugLog)(1, "main", "Checking initial stack was noted\n");
sewardjfdf91b42005-09-28 00:53:09 +00001999 if (sp_at_startup == 0) {
sewardj45f4e7c2005-09-27 19:20:21 +00002000 VG_(debugLog)(0, "main", "Valgrind: FATAL: "
2001 "Initial stack was not noted.\n");
2002 VG_(debugLog)(0, "main", " Cannot continue. Sorry.\n");
2003 VG_(exit)(1);
2004 }
2005
2006 //--------------------------------------------------------------
2007 // Start up the address space manager, and determine the
2008 // approximate location of the client's stack
2009 // p: logging, plausible-stack
2010 //--------------------------------------------------------------
2011 VG_(debugLog)(1, "main", "Starting the address space manager\n");
sewardjfdf91b42005-09-28 00:53:09 +00002012 clstack_top = VG_(am_startup)( sp_at_startup );
sewardj45f4e7c2005-09-27 19:20:21 +00002013 VG_(debugLog)(1, "main", "Address space manager is running\n");
2014
2015 //--------------------------------------------------------------
2016 // Start up the dynamic memory manager
2017 // p: address space management
2018 // In fact m_mallocfree is self-initialising, so there's no
2019 // initialisation call to do. Instead, try a simple malloc/
2020 // free pair right now to check that nothing is broken.
2021 //--------------------------------------------------------------
2022 VG_(debugLog)(1, "main", "Starting the dynamic memory manager\n");
2023 { void* p = VG_(malloc)( 12345 );
2024 if (p) VG_(free)( p );
2025 }
2026 VG_(debugLog)(1, "main", "Dynamic memory manager is running\n");
sewardj1cf558c2005-04-25 01:36:56 +00002027
nethercotef4928da2004-06-15 10:54:40 +00002028 //============================================================
sewardj45f4e7c2005-09-27 19:20:21 +00002029 //
2030 // Dynamic memory management is now available.
2031 //
nethercotef4928da2004-06-15 10:54:40 +00002032 //============================================================
2033
sewardj45f4e7c2005-09-27 19:20:21 +00002034 //--------------------------------------------------------------
2035 // Look for alternative libdir
2036 { HChar *cp = VG_(getenv)(VALGRIND_LIB);
2037 if (cp != NULL)
2038 VG_(libdir) = cp;
2039 }
2040
2041 //--------------------------------------------------------------
2042 // Extract the launcher name from the environment.
2043 VG_(debugLog)(1, "main", "Getting stage1's name\n");
2044 VG_(name_of_launcher) = VG_(getenv)(VALGRIND_LAUNCHER);
2045 if (VG_(name_of_launcher) == NULL) {
2046 VG_(printf)("valgrind: You cannot run '%s' directly.\n", argv[0]);
2047 VG_(printf)("valgrind: You should use $prefix/bin/valgrind.\n");
2048 VG_(exit)(1);
2049 }
2050
2051 //--------------------------------------------------------------
fitzhardingeb50068f2004-02-24 23:42:55 +00002052 // Get the current process datasize rlimit, and set it to zero.
2053 // This prevents any internal uses of brk() from having any effect.
2054 // We remember the old value so we can restore it on exec, so that
2055 // child processes will have a reasonable brk value.
2056 VG_(getrlimit)(VKI_RLIMIT_DATA, &VG_(client_rlimit_data));
2057 zero.rlim_max = VG_(client_rlimit_data).rlim_max;
2058 VG_(setrlimit)(VKI_RLIMIT_DATA, &zero);
thughesc37184f2004-09-11 14:16:57 +00002059
2060 // Get the current process stack rlimit.
2061 VG_(getrlimit)(VKI_RLIMIT_STACK, &VG_(client_rlimit_stack));
2062
sewardje2d1e672005-11-12 23:10:48 +00002063 //--------------------------------------------------------------
2064 // Figure out what sort of CPU we're on, and whether it is
2065 // able to run V.
2066 VG_(debugLog)(1, "main", "Get hardware capabilities ...\n");
2067 { VexArch vex_arch;
2068 VexArchInfo vex_archinfo;
2069 Bool ok = VG_(machine_get_hwcaps)();
2070 if (!ok) {
2071 VG_(printf)("\n");
2072 VG_(printf)("valgrind: fatal error: unsupported CPU.\n");
2073 VG_(printf)(" Supported CPUs are:\n");
2074 VG_(printf)(" * x86 (practically any; Pentium-I or above), "
2075 "AMD Athlon or above)\n");
2076 VG_(printf)(" * AMD Athlon64/Opteron\n");
2077 VG_(printf)(" * PowerPC (most; ppc405 and above)\n");
2078 VG_(printf)("\n");
2079 VG_(exit)(1);
2080 }
2081 VG_(machine_get_VexArchInfo)( &vex_arch, &vex_archinfo );
2082 VG_(debugLog)(1, "main", "... arch = %s, subarch = %s\n",
2083 LibVEX_ppVexArch ( vex_arch ),
2084 LibVEX_ppVexSubArch( vex_archinfo.subarch ) );
2085 }
2086
sewardj45f4e7c2005-09-27 19:20:21 +00002087 //============================================================
2088 // Command line argument handling order:
2089 // * If --help/--help-debug are present, show usage message
2090 // (including the tool-specific usage)
2091 // * (If no --tool option given, default to Memcheck)
2092 // * Then, if client is missing, abort with error msg
2093 // * Then, if any cmdline args are bad, abort with error msg
2094 //============================================================
2095
2096 //--------------------------------------------------------------
2097 // Split up argv into: C args, V args, V extra args, and exename.
2098 // p: dynamic memory allocation
2099 //--------------------------------------------------------------
2100 VG_(debugLog)(1, "main", "Split up command line\n");
2101 VG_(split_up_argv)( argc, argv );
2102 if (0) {
2103 for (i = 0; i < VG_(args_for_valgrind).used; i++)
2104 VG_(printf)("varg %s\n", VG_(args_for_valgrind).strs[i]);
2105 VG_(printf)(" exe %s\n", VG_(args_the_exename));
2106 for (i = 0; i < VG_(args_for_client).used; i++)
2107 VG_(printf)("carg %s\n", VG_(args_for_client).strs[i]);
nethercote71980f02004-01-24 18:18:54 +00002108 }
2109
2110 //--------------------------------------------------------------
sewardj45f4e7c2005-09-27 19:20:21 +00002111 // Extract tool name and whether help has been requested.
2112 // Note we can't print the help message yet, even if requested,
2113 // because the tool has not been initialised.
2114 // p: split_up_argv [for VG_(args_for_valgrind)]
nethercote71980f02004-01-24 18:18:54 +00002115 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002116 VG_(debugLog)(1, "main", "Preprocess command line opts\n");
sewardj45f4e7c2005-09-27 19:20:21 +00002117 get_helprequest_and_toolname(&need_help, &toolname);
nethercote71980f02004-01-24 18:18:54 +00002118
sewardj45f4e7c2005-09-27 19:20:21 +00002119 // Set default vex control params
2120 LibVEX_default_VexControl(& VG_(clo_vex_control));
nethercote71980f02004-01-24 18:18:54 +00002121
2122 //--------------------------------------------------------------
2123 // Load client executable, finding in $PATH if necessary
sewardj45f4e7c2005-09-27 19:20:21 +00002124 // p: get_helprequest_and_toolname() [for 'exec', 'need_help']
nethercote71980f02004-01-24 18:18:54 +00002125 // p: layout_remaining_space [so there's space]
2126 //--------------------------------------------------------------
sewardj45f4e7c2005-09-27 19:20:21 +00002127 if (!need_help) {
2128 VG_(debugLog)(1, "main", "Loading client\n");
nethercote71980f02004-01-24 18:18:54 +00002129
sewardj45f4e7c2005-09-27 19:20:21 +00002130 if (VG_(args_the_exename) == NULL)
2131 missing_prog();
2132
2133 load_client(&info, &initial_client_IP);
2134 }
nethercote71980f02004-01-24 18:18:54 +00002135
2136 //--------------------------------------------------------------
2137 // Set up client's environment
sewardj45f4e7c2005-09-27 19:20:21 +00002138 // p: set-libdir [for VG_(libdir)]
2139 // p: get_helprequest_and_toolname [for toolname]
nethercote71980f02004-01-24 18:18:54 +00002140 //--------------------------------------------------------------
sewardj45f4e7c2005-09-27 19:20:21 +00002141 if (!need_help) {
2142 VG_(debugLog)(1, "main", "Setup client env\n");
2143 env = setup_client_env(envp, toolname);
2144 }
nethercote71980f02004-01-24 18:18:54 +00002145
2146 //--------------------------------------------------------------
nethercote5ee67ca2004-06-22 14:00:09 +00002147 // Setup client stack, eip, and VG_(client_arg[cv])
nethercote71980f02004-01-24 18:18:54 +00002148 // p: load_client() [for 'info']
2149 // p: fix_environment() [for 'env']
2150 //--------------------------------------------------------------
sewardj45f4e7c2005-09-27 19:20:21 +00002151 if (!need_help) {
2152 void* init_sp = argv - 1;
2153 SizeT m1 = 1024 * 1024;
2154 SizeT m8 = 8 * m1;
2155 VG_(debugLog)(1, "main", "Setup client stack\n");
2156 clstack_max_size = (SizeT)VG_(client_rlimit_stack).rlim_cur;
2157 if (clstack_max_size < m1) clstack_max_size = m1;
2158 if (clstack_max_size > m8) clstack_max_size = m8;
2159 clstack_max_size = VG_PGROUNDUP(clstack_max_size);
sewardjb5f6f512005-03-10 23:59:00 +00002160
sewardj45f4e7c2005-09-27 19:20:21 +00002161 initial_client_SP
2162 = setup_client_stack( init_sp, env,
2163 &info, &client_auxv,
2164 clstack_top, clstack_max_size );
2165
2166 VG_(free)(env);
2167
2168 VG_(debugLog)(2, "main",
2169 "Client info: "
sewardja48a4932005-09-29 11:09:56 +00002170 "initial_IP=%p initial_SP=%p brk_base=%p\n",
sewardj45f4e7c2005-09-27 19:20:21 +00002171 (void*)initial_client_IP,
2172 (void*)initial_client_SP,
2173 (void*)VG_(brk_base) );
nethercotec25c4492004-10-18 11:52:17 +00002174 }
nethercote71980f02004-01-24 18:18:54 +00002175
sewardj45f4e7c2005-09-27 19:20:21 +00002176 //--------------------------------------------------------------
2177 // Setup client data (brk) segment. Initially a 1-page segment
2178 // which abuts a shrinkable reservation.
2179 // p: load_client() [for 'info' and hence VG_(brk_base)]
2180 //--------------------------------------------------------------
2181 if (!need_help) {
2182 SizeT m1 = 1024 * 1024;
2183 SizeT m8 = 8 * m1;
2184 SizeT dseg_max_size = (SizeT)VG_(client_rlimit_data).rlim_cur;
2185 VG_(debugLog)(1, "main", "Setup client data (brk) segment\n");
2186 if (dseg_max_size < m1) dseg_max_size = m1;
2187 if (dseg_max_size > m8) dseg_max_size = m8;
2188 dseg_max_size = VG_PGROUNDUP(dseg_max_size);
2189
2190 setup_client_dataseg( dseg_max_size );
2191 }
nethercote71980f02004-01-24 18:18:54 +00002192
2193 //==============================================================
sewardj45f4e7c2005-09-27 19:20:21 +00002194 //
2195 // Finished loading/setting up the client address space.
2196 //
nethercote71980f02004-01-24 18:18:54 +00002197 //==============================================================
2198
2199 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002200 // setup file descriptors
2201 // p: n/a
2202 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002203 VG_(debugLog)(1, "main", "Setup file descriptors\n");
nethercote71980f02004-01-24 18:18:54 +00002204 setup_file_descriptors();
2205
2206 //--------------------------------------------------------------
sewardj45f4e7c2005-09-27 19:20:21 +00002207 // create the fake /proc/<pid>/cmdline file and then unlink it,
2208 // but hold onto the fd, so we can hand it out to the client
2209 // when it tries to open /proc/<pid>/cmdline for itself.
2210 // p: setup file descriptors
nethercotec314eba2004-07-15 12:59:41 +00002211 //--------------------------------------------------------------
sewardj45f4e7c2005-09-27 19:20:21 +00002212 if (!need_help) {
2213 HChar buf[50], buf2[50+64];
2214 HChar nul[1];
2215 Int fd, r;
2216 HChar* exename;
nethercotec314eba2004-07-15 12:59:41 +00002217
sewardj45f4e7c2005-09-27 19:20:21 +00002218 VG_(debugLog)(1, "main", "Create fake /proc/<pid>/cmdline\n");
2219
2220 VG_(sprintf)(buf, "proc_%d_cmdline", VG_(getpid)());
2221 fd = VG_(mkstemp)( buf, buf2 );
2222 if (fd == -1)
2223 config_error("Can't create client cmdline file in /tmp.");
2224
2225 nul[0] = 0;
2226 exename = VG_(args_the_exename) ? VG_(args_the_exename)
2227 : "unknown_exename";
2228
2229 VG_(write)(fd, VG_(args_the_exename),
2230 VG_(strlen)( VG_(args_the_exename) ));
2231 VG_(write)(fd, nul, 1);
2232
2233 for (i = 0; i < VG_(args_for_client).used; i++) {
2234 VG_(write)(fd, VG_(args_for_client).strs[i],
2235 VG_(strlen)( VG_(args_for_client).strs[i] ));
2236 VG_(write)(fd, nul, 1);
2237 }
2238
2239 /* Don't bother to seek the file back to the start; instead do
2240 it every time a copy of it is given out (by PRE(sys_open)).
2241 That is probably more robust across fork() etc. */
2242
2243 /* Now delete it, but hang on to the fd. */
2244 r = VG_(unlink)( buf2 );
2245 if (r)
2246 config_error("Can't delete client cmdline file in /tmp.");
2247
2248 VG_(cl_cmdline_fd) = fd;
2249 }
nethercotec314eba2004-07-15 12:59:41 +00002250
2251 //--------------------------------------------------------------
sewardj45f4e7c2005-09-27 19:20:21 +00002252 // Init tool part 1: pre_clo_init
nethercotec314eba2004-07-15 12:59:41 +00002253 // p: setup_client_stack() [for 'VG_(client_arg[cv]']
nethercotec314eba2004-07-15 12:59:41 +00002254 // p: setup_file_descriptors() [for 'VG_(fd_xxx_limit)']
nethercote71980f02004-01-24 18:18:54 +00002255 //--------------------------------------------------------------
njn64c83242005-06-21 01:54:38 +00002256 {
2257 Char* s;
2258 Bool ok;
sewardj45f4e7c2005-09-27 19:20:21 +00002259 VG_(debugLog)(1, "main", "Initialise the tool part 1 (pre_clo_init)\n");
2260 (VG_(tool_info).tl_pre_clo_init)();
2261 ok = VG_(sanity_check_needs)( &s );
njn64c83242005-06-21 01:54:38 +00002262 if (!ok) {
2263 VG_(tool_panic)(s);
2264 }
2265 }
nethercote71980f02004-01-24 18:18:54 +00002266
sewardj45f4e7c2005-09-27 19:20:21 +00002267 //--------------------------------------------------------------
nethercotef4928da2004-06-15 10:54:40 +00002268 // If --tool and --help/--help-debug was given, now give the core+tool
2269 // help message
sewardj45f4e7c2005-09-27 19:20:21 +00002270 // p: get_helprequest_and_toolname() [for 'need_help']
2271 // p: tl_pre_clo_init [for 'VG_(tdict).usage']
2272 //--------------------------------------------------------------
2273 VG_(debugLog)(1, "main", "Print help and quit, if requested\n");
nethercotef4928da2004-06-15 10:54:40 +00002274 if (need_help) {
sewardj45f4e7c2005-09-27 19:20:21 +00002275 usage_NORETURN(/*--help-debug?*/2 == need_help);
nethercotef4928da2004-06-15 10:54:40 +00002276 }
nethercotec314eba2004-07-15 12:59:41 +00002277
sewardj45f4e7c2005-09-27 19:20:21 +00002278 //--------------------------------------------------------------
2279 // Process command line options to Valgrind + tool
2280 // p: setup_client_stack() [for 'VG_(client_arg[cv]']
2281 // p: setup_file_descriptors() [for 'VG_(fd_xxx_limit)']
2282 //--------------------------------------------------------------
2283 VG_(debugLog)(1, "main", "Process Valgrind's command line options, "
sewardja48a4932005-09-29 11:09:56 +00002284 "setup logging\n");
sewardj45f4e7c2005-09-27 19:20:21 +00002285 logging_to_fd = process_cmd_line_options(client_auxv, toolname);
2286
2287 //--------------------------------------------------------------
sewardj592ae092005-11-08 19:01:44 +00002288 // Zeroise the millisecond counter by doing a first read of it.
2289 // p: none
2290 //--------------------------------------------------------------
2291 (void) VG_(read_millisecond_timer)();
2292
2293 //--------------------------------------------------------------
sewardj45f4e7c2005-09-27 19:20:21 +00002294 // Print the preamble
2295 // p: tl_pre_clo_init [for 'VG_(details).name' and friends]
2296 // p: process_cmd_line_options() [for VG_(clo_verbosity), VG_(clo_xml),
2297 // VG_(clo_log_file_qualifier),
2298 // logging_to_fd]
2299 //--------------------------------------------------------------
2300 VG_(debugLog)(1, "main", "Print the preamble...\n");
2301 print_preamble(logging_to_fd, toolname);
2302 VG_(debugLog)(1, "main", "...finished the preamble\n");
2303
2304 //--------------------------------------------------------------
2305 // Init tool part 2: post_clo_init
2306 // p: setup_client_stack() [for 'VG_(client_arg[cv]']
2307 // p: setup_file_descriptors() [for 'VG_(fd_xxx_limit)']
2308 // p: print_preamble() [so any warnings printed in post_clo_init
2309 // are shown after the preamble]
2310 //--------------------------------------------------------------
2311 VG_(debugLog)(1, "main", "Initialise the tool part 2 (post_clo_init)\n");
njn51d827b2005-05-09 01:02:08 +00002312 VG_TDICT_CALL(tool_post_clo_init);
nethercotef4928da2004-06-15 10:54:40 +00002313
2314 //--------------------------------------------------------------
sewardj45f4e7c2005-09-27 19:20:21 +00002315 // Initialise translation table and translation cache
2316 // p: aspacem [??]
2317 // p: tl_pre_clo_init [for 'VG_(details).avg_translation_sizeB']
nethercote71980f02004-01-24 18:18:54 +00002318 //--------------------------------------------------------------
sewardj45f4e7c2005-09-27 19:20:21 +00002319 VG_(debugLog)(1, "main", "Initialise TT/TC\n");
2320 VG_(init_tt_tc)();
sewardjb5f6f512005-03-10 23:59:00 +00002321
sewardj45f4e7c2005-09-27 19:20:21 +00002322 //--------------------------------------------------------------
2323 // Initialise the redirect table.
2324 // p: init_tt_tc [so it can call VG_(search_transtab) safely]
2325 // p: aspacem [so can change ownership of sysinfo pages]
2326 //--------------------------------------------------------------
2327 VG_(debugLog)(1, "main", "Initialise redirects\n");
2328 VG_(setup_code_redirect_table)();
nethercote71980f02004-01-24 18:18:54 +00002329
2330 //--------------------------------------------------------------
2331 // Allow GDB attach
2332 // p: process_cmd_line_options() [for VG_(clo_wait_for_gdb)]
2333 //--------------------------------------------------------------
2334 /* Hook to delay things long enough so we can get the pid and
2335 attach GDB in another shell. */
2336 if (VG_(clo_wait_for_gdb)) {
sewardj8211a572005-06-23 21:37:47 +00002337 Long q, iters;
sewardj1fbc1a52005-04-25 02:05:54 +00002338 VG_(debugLog)(1, "main", "Wait for GDB\n");
sewardj93ab8572005-02-06 14:10:40 +00002339 VG_(printf)("pid=%d, entering delay loop\n", VG_(getpid)());
2340 /* jrs 20050206: I don't understand why this works on x86. On
2341 amd64 the obvious analogues (jump *$rip or jump *$rcx) don't
2342 work. */
2343 /* do "jump *$eip" to skip this in gdb (x86) */
2344 //VG_(do_syscall0)(__NR_pause);
sewardj8211a572005-06-23 21:37:47 +00002345
2346# if defined(VGP_x86_linux)
2347 iters = 5;
sewardj2c48c7b2005-11-29 13:05:56 +00002348# elif defined(VGP_amd64_linux) || defined(VGP_ppc64_linux)
sewardj8211a572005-06-23 21:37:47 +00002349 iters = 10;
2350# elif defined(VGP_ppc32_linux)
sewardjd714d2e2005-07-08 18:24:04 +00002351 iters = 5;
sewardj8211a572005-06-23 21:37:47 +00002352# else
2353# error "Unknown plat"
2354# endif
2355
2356 iters *= 1000*1000*1000;
2357 for (q = 0; q < iters; q++)
2358 ;
nethercote71980f02004-01-24 18:18:54 +00002359 }
2360
sewardjb5d320c2005-03-13 18:57:15 +00002361 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002362 // Search for file descriptors that are inherited from our parent
2363 // p: process_cmd_line_options [for VG_(clo_track_fds)]
2364 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002365 if (VG_(clo_track_fds)) {
2366 VG_(debugLog)(1, "main", "Init preopened fds\n");
nethercote71980f02004-01-24 18:18:54 +00002367 VG_(init_preopened_fds)();
sewardj1fbc1a52005-04-25 02:05:54 +00002368 }
nethercote71980f02004-01-24 18:18:54 +00002369
2370 //--------------------------------------------------------------
sewardj45f4e7c2005-09-27 19:20:21 +00002371 // Load debug info for the existing segments.
2372 // p: setup_code_redirect_table [so that redirs can be recorded]
2373 // p: mallocfree
2374 // p: probably: setup fds and process CLOs, so that logging works
2375 //--------------------------------------------------------------
2376 VG_(debugLog)(1, "main", "Load initial debug info\n");
2377 { Addr* seg_starts;
2378 Int n_seg_starts;
2379
2380 seg_starts = get_seg_starts( &n_seg_starts );
2381 vg_assert(seg_starts && n_seg_starts > 0);
2382
sewardjf72cced2005-11-08 00:45:47 +00002383 /* show them all to the debug info reader. allow_SkFileV has to
2384 be True here so that we read info from the valgrind executable
2385 itself. */
sewardj45f4e7c2005-09-27 19:20:21 +00002386 for (i = 0; i < n_seg_starts; i++)
sewardjf72cced2005-11-08 00:45:47 +00002387 VG_(di_notify_mmap)( seg_starts[i], True/*allow_SkFileV*/ );
sewardj45f4e7c2005-09-27 19:20:21 +00002388
2389 VG_(free)( seg_starts );
2390 }
2391
2392 //--------------------------------------------------------------
2393 // Tell aspacem of ownership change of the asm helpers, so that
2394 // m_translate allows them to be translated. However, only do this
2395 // after the initial debug info read, since making a hole in the
2396 // address range for the stage2 binary confuses the debug info reader.
2397 // p: aspacem
2398 //--------------------------------------------------------------
2399 { Bool change_ownership_v_c_OK;
2400 Addr co_start = VG_PGROUNDDN( (Addr)&VG_(trampoline_stuff_start) );
2401 Addr co_endPlus = VG_PGROUNDUP( (Addr)&VG_(trampoline_stuff_end) );
2402 VG_(debugLog)(1,"redir",
2403 "transfer ownership V -> C of 0x%llx .. 0x%llx\n",
2404 (ULong)co_start, (ULong)co_endPlus-1 );
2405
2406 change_ownership_v_c_OK
2407 = VG_(am_change_ownership_v_to_c)( co_start, co_endPlus - co_start );
2408 vg_assert(change_ownership_v_c_OK);
2409 }
2410
2411 //--------------------------------------------------------------
2412 // Tell the tool about the initial client memory permissions
2413 // p: aspacem
2414 // p: mallocfree
2415 // p: setup_client_stack
2416 // p: setup_client_dataseg
2417 //--------------------------------------------------------------
2418 VG_(debugLog)(1, "main", "Tell tool about initial permissions\n");
2419 { Addr* seg_starts;
2420 Int n_seg_starts;
2421 NSegment* seg;
2422
2423 seg_starts = get_seg_starts( &n_seg_starts );
2424 vg_assert(seg_starts && n_seg_starts > 0);
2425
2426 /* show interesting ones to the tool */
2427 for (i = 0; i < n_seg_starts; i++) {
2428 seg = VG_(am_find_nsegment)( seg_starts[i] );
2429 vg_assert(seg);
2430 if (seg->kind == SkFileC || seg->kind == SkAnonC) {
2431 VG_(debugLog)(2, "main",
2432 "tell tool about %010lx-%010lx %c%c%c\n",
2433 seg->start, seg->end,
2434 seg->hasR ? 'r' : '-',
2435 seg->hasW ? 'w' : '-',
2436 seg->hasX ? 'x' : '-' );
2437 VG_TRACK( new_mem_startup, seg->start, seg->end+1-seg->start,
2438 seg->hasR, seg->hasW, seg->hasX );
2439 }
2440 }
2441
2442 VG_(free)( seg_starts );
2443
2444 /* Also do the initial stack permissions. */
2445 seg = VG_(am_find_nsegment)( initial_client_SP );
2446 vg_assert(seg);
2447 vg_assert(seg->kind == SkAnonC);
2448 vg_assert(initial_client_SP >= seg->start);
2449 vg_assert(initial_client_SP <= seg->end);
2450
2451 /* Stuff below the initial SP is unaddressable. */
2452 /* NB: shouldn't this take into account the VG_STACK_REDZONE_SZB
2453 bytes below SP? */
2454 VG_TRACK( die_mem_stack, seg->start, initial_client_SP - seg->start );
2455 VG_(debugLog)(2, "main", "mark stack inaccessible %010lx-%010lx\n",
2456 seg->start, initial_client_SP-1 );
2457
2458 /* Also the assembly helpers. */
2459 VG_TRACK( new_mem_startup,
2460 (Addr)&VG_(trampoline_stuff_start),
tom151a6392005-11-11 12:30:36 +00002461 (Addr)&VG_(trampoline_stuff_end) - (Addr)&VG_(trampoline_stuff_start),
sewardj45f4e7c2005-09-27 19:20:21 +00002462 False, /* readable? */
2463 False, /* writable? */
2464 True /* executable? */ );
2465 }
2466
2467 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002468 // Initialise the scheduler
nethercote71980f02004-01-24 18:18:54 +00002469 // p: setup_file_descriptors() [else VG_(safe_fd)() breaks]
sewardj45f4e7c2005-09-27 19:20:21 +00002470 // p: setup_client_stack
nethercote71980f02004-01-24 18:18:54 +00002471 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002472 VG_(debugLog)(1, "main", "Initialise scheduler\n");
sewardj45f4e7c2005-09-27 19:20:21 +00002473 { NSegment* seg = VG_(am_find_nsegment)( initial_client_SP );
2474 vg_assert(seg);
2475 vg_assert(seg->kind == SkAnonC);
2476 vg_assert(initial_client_SP >= seg->start);
2477 vg_assert(initial_client_SP <= seg->end);
2478 VG_(scheduler_init)( seg->end, clstack_max_size );
2479 }
nethercote71980f02004-01-24 18:18:54 +00002480
2481 //--------------------------------------------------------------
sewardjb5f6f512005-03-10 23:59:00 +00002482 // Initialise the pthread model
2483 // p: ?
sewardj2a99cf62004-11-24 10:44:19 +00002484 // load_client() [for 'client_eip']
2485 // setup_client_stack() [for 'sp_at_startup']
2486 // setup_scheduler() [for the rest of state 1 stuff]
2487 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002488 VG_(debugLog)(1, "main", "Initialise thread 1's state\n");
sewardj45f4e7c2005-09-27 19:20:21 +00002489 init_thread1state( initial_client_IP, initial_client_SP,
cerionc7266522005-12-08 03:24:37 +00002490 info.entry,
sewardj45f4e7c2005-09-27 19:20:21 +00002491 &VG_(threads)[1].arch);
njnea4b28c2004-11-30 16:04:58 +00002492
sewardj2a99cf62004-11-24 10:44:19 +00002493 //--------------------------------------------------------------
sewardj39b88fb2005-03-12 15:16:07 +00002494 // Initialise the pthread model
2495 // p: ?
nethercote71980f02004-01-24 18:18:54 +00002496 //--------------------------------------------------------------
sewardjb5f6f512005-03-10 23:59:00 +00002497 //if (VG_(clo_model_pthreads))
2498 // VG_(pthread_init)();
nethercote71980f02004-01-24 18:18:54 +00002499
2500 //--------------------------------------------------------------
2501 // Initialise the signal handling subsystem
sewardjb5f6f512005-03-10 23:59:00 +00002502 // p: n/a
nethercote71980f02004-01-24 18:18:54 +00002503 //--------------------------------------------------------------
2504 // Nb: temporarily parks the saved blocking-mask in saved_sigmask.
sewardj1fbc1a52005-04-25 02:05:54 +00002505 VG_(debugLog)(1, "main", "Initialise signal management\n");
nethercote71980f02004-01-24 18:18:54 +00002506 VG_(sigstartup_actions)();
2507
2508 //--------------------------------------------------------------
2509 // Perhaps we're profiling Valgrind?
2510 // p: process_cmd_line_options() [for VG_(clo_profile)]
2511 // p: others?
2512 //
2513 // XXX: this seems to be broken? It always says the tool wasn't built
2514 // for profiling; vg_profile.c's functions don't seem to be overriding
2515 // vg_dummy_profile.c's?
2516 //
2517 // XXX: want this as early as possible. Looking for --profile
sewardj45f4e7c2005-09-27 19:20:21 +00002518 // in get_helprequest_and_toolname() could get it earlier.
nethercote71980f02004-01-24 18:18:54 +00002519 //--------------------------------------------------------------
2520 if (VG_(clo_profile))
njn31066fd2005-03-26 00:42:02 +00002521 VG_(init_profiling)();
nethercote71980f02004-01-24 18:18:54 +00002522
2523 VGP_PUSHCC(VgpStartup);
2524
2525 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002526 // Read suppression file
2527 // p: process_cmd_line_options() [for VG_(clo_suppressions)]
2528 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002529 if (VG_(needs).core_errors || VG_(needs).tool_errors) {
2530 VG_(debugLog)(1, "main", "Load suppressions\n");
nethercote71980f02004-01-24 18:18:54 +00002531 VG_(load_suppressions)();
sewardj1fbc1a52005-04-25 02:05:54 +00002532 }
nethercote71980f02004-01-24 18:18:54 +00002533
2534 //--------------------------------------------------------------
rjwalsh0140af52005-06-04 20:42:33 +00002535 // register client stack
2536 //--------------------------------------------------------------
njn945ed2e2005-06-24 03:28:30 +00002537 VG_(clstk_id) = VG_(register_stack)(VG_(clstk_base), VG_(clstk_end));
rjwalsh0140af52005-06-04 20:42:33 +00002538
2539 //--------------------------------------------------------------
sewardj45f4e7c2005-09-27 19:20:21 +00002540 // Show the address space state so far
2541 //--------------------------------------------------------------
2542 VG_(debugLog)(1, "main", "\n");
2543 VG_(debugLog)(1, "main", "\n");
2544 VG_(am_show_nsegments)(1,"Memory layout at client startup");
2545 VG_(debugLog)(1, "main", "\n");
2546 VG_(debugLog)(1, "main", "\n");
2547
2548 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002549 // Run!
2550 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002551 VGP_POPCC(VgpStartup);
nethercote71980f02004-01-24 18:18:54 +00002552
sewardj71bc3cb2005-05-19 00:25:45 +00002553 if (VG_(clo_xml)) {
sewardj68cde6f2005-07-19 12:17:51 +00002554 HChar buf[50];
sewardj592ae092005-11-08 19:01:44 +00002555 VG_(elapsed_wallclock_time)(buf);
sewardj753673f2005-08-09 22:03:08 +00002556 VG_(message)(Vg_UserMsg, "<status>\n"
2557 " <state>RUNNING</state>\n"
2558 " <time>%t</time>\n"
2559 "</status>",
2560 buf);
sewardj71bc3cb2005-05-19 00:25:45 +00002561 VG_(message)(Vg_UserMsg, "");
2562 }
2563
sewardj1fbc1a52005-04-25 02:05:54 +00002564 VG_(debugLog)(1, "main", "Running thread 1\n");
sewardj1ae3f3a2005-09-28 10:47:38 +00002565
sewardj1d887112005-05-30 21:44:08 +00002566 /* As a result of the following call, the last thread standing
sewardj1ae3f3a2005-09-28 10:47:38 +00002567 eventually winds up running shutdown_actions_NORETURN
2568 just below. Unfortunately, simply exporting said function
2569 causes m_main to be part of a module cycle, which is pretty
2570 nonsensical. So instead of doing that, the address of said
2571 function is stored in a global variable 'owned' by m_syswrap,
2572 and it uses that function pointer to get back here when it needs
2573 to. */
2574
2575 /* Set continuation address. */
2576 VG_(address_of_m_main_shutdown_actions_NORETURN)
2577 = & shutdown_actions_NORETURN;
2578
2579 /* Run the first thread, eventually ending up at the continuation
2580 address. */
njnaf839f52005-06-23 03:27:57 +00002581 VG_(main_thread_wrapper_NORETURN)(1);
nethercote71980f02004-01-24 18:18:54 +00002582
sewardj1d887112005-05-30 21:44:08 +00002583 /*NOTREACHED*/
2584 vg_assert(0);
sewardjb5f6f512005-03-10 23:59:00 +00002585}
2586
sewardj1ae3f3a2005-09-28 10:47:38 +00002587/* Do everything which needs doing when the last thread exits. */
sewardjb5f6f512005-03-10 23:59:00 +00002588
sewardj1ae3f3a2005-09-28 10:47:38 +00002589static
2590void shutdown_actions_NORETURN( ThreadId tid,
2591 VgSchedReturnCode tids_schedretcode )
sewardjb5f6f512005-03-10 23:59:00 +00002592{
sewardj1d887112005-05-30 21:44:08 +00002593 VG_(debugLog)(1, "main", "entering VG_(shutdown_actions_NORETURN)\n");
2594
2595 vg_assert( VG_(count_living_threads)() == 1 );
sewardjb5f6f512005-03-10 23:59:00 +00002596 vg_assert(VG_(is_running_thread)(tid));
2597
2598 // Wait for all other threads to exit.
njn7b85dd52005-06-12 17:26:29 +00002599 VG_(reap_threads)(tid);
sewardjb5f6f512005-03-10 23:59:00 +00002600
2601 VG_(clo_model_pthreads) = False;
2602
2603 // Clean the client up before the final report
njn9cb54ac2005-06-12 04:19:17 +00002604 final_tidyup(tid);
sewardjb5f6f512005-03-10 23:59:00 +00002605
2606 // OK, done
2607 VG_(exit_thread)(tid);
2608
2609 /* should be no threads left */
2610 vg_assert(VG_(count_living_threads)() == 0);
2611
2612 VG_(threads)[tid].status = VgTs_Empty;
nethercote71980f02004-01-24 18:18:54 +00002613 //--------------------------------------------------------------
2614 // Finalisation: cleanup, messages, etc. Order no so important, only
2615 // affects what order the messages come.
2616 //--------------------------------------------------------------
2617 if (VG_(clo_verbosity) > 0)
2618 VG_(message)(Vg_UserMsg, "");
2619
sewardj71bc3cb2005-05-19 00:25:45 +00002620 if (VG_(clo_xml)) {
sewardj68cde6f2005-07-19 12:17:51 +00002621 HChar buf[50];
sewardj9f297ca2005-05-20 02:29:52 +00002622 if (VG_(needs).core_errors || VG_(needs).tool_errors) {
2623 VG_(show_error_counts_as_XML)();
2624 VG_(message)(Vg_UserMsg, "");
2625 }
sewardj592ae092005-11-08 19:01:44 +00002626 VG_(elapsed_wallclock_time)(buf);
sewardj753673f2005-08-09 22:03:08 +00002627 VG_(message)(Vg_UserMsg, "<status>\n"
2628 " <state>FINISHED</state>\n"
2629 " <time>%t</time>\n"
2630 "</status>",
2631 buf);
sewardj71bc3cb2005-05-19 00:25:45 +00002632 VG_(message)(Vg_UserMsg, "");
2633 }
2634
nethercote71980f02004-01-24 18:18:54 +00002635 /* Print out file descriptor summary and stats. */
2636 if (VG_(clo_track_fds))
nethercote3a42fb82004-08-03 18:08:50 +00002637 VG_(show_open_fds)();
nethercote71980f02004-01-24 18:18:54 +00002638
njn95ec8702004-11-22 16:46:13 +00002639 if (VG_(needs).core_errors || VG_(needs).tool_errors)
nethercote71980f02004-01-24 18:18:54 +00002640 VG_(show_all_errors)();
2641
njn51d827b2005-05-09 01:02:08 +00002642 VG_TDICT_CALL(tool_fini, 0/*exitcode*/);
nethercote71980f02004-01-24 18:18:54 +00002643
sewardj71bc3cb2005-05-19 00:25:45 +00002644 if (VG_(clo_xml)) {
2645 VG_(message)(Vg_UserMsg, "");
2646 VG_(message)(Vg_UserMsg, "</valgrindoutput>");
2647 VG_(message)(Vg_UserMsg, "");
2648 }
2649
nethercote885dd912004-08-03 23:14:00 +00002650 VG_(sanity_check_general)( True /*include expensive checks*/ );
nethercote71980f02004-01-24 18:18:54 +00002651
2652 if (VG_(clo_verbosity) > 1)
nethercote3a42fb82004-08-03 18:08:50 +00002653 print_all_stats();
nethercote71980f02004-01-24 18:18:54 +00002654
nethercote71980f02004-01-24 18:18:54 +00002655 if (VG_(clo_profile))
njn31066fd2005-03-26 00:42:02 +00002656 VG_(done_profiling)();
njn2025cf92005-06-26 20:44:48 +00002657
2658 if (VG_(clo_profile_flags) > 0) {
2659 #define N_MAX 100
2660 BBProfEntry tops[N_MAX];
2661 ULong score_total = VG_(get_BB_profile) (tops, N_MAX);
2662 show_BB_profile(tops, N_MAX, score_total);
2663 }
sewardjfa8ec112005-01-19 11:55:34 +00002664
sewardj8b635a42004-11-22 19:01:47 +00002665 /* Print Vex storage stats */
sewardjbf426512005-01-17 18:35:30 +00002666 if (0)
2667 LibVEX_ShowAllocStats();
sewardj1d887112005-05-30 21:44:08 +00002668
njn8aa35852005-06-10 22:59:56 +00002669 /* Ok, finally exit in the os-specific way, according to the scheduler's
2670 return code. In short, if the (last) thread exited by calling
2671 sys_exit, do likewise; if the (last) thread stopped due to a fatal
2672 signal, terminate the entire system with that same fatal signal. */
2673 VG_(debugLog)(1, "core_os",
njn7b85dd52005-06-12 17:26:29 +00002674 "VG_(terminate_NORETURN)(tid=%lld)\n", (ULong)tid);
njn8aa35852005-06-10 22:59:56 +00002675
2676 vg_assert(VG_(count_living_threads)() == 0);
2677
2678 switch (tids_schedretcode) {
2679 case VgSrc_ExitSyscall: /* the normal way out */
2680 VG_(exit)( VG_(threads)[tid].os_state.exitcode );
2681 /* NOT ALIVE HERE! */
2682 VG_(core_panic)("entered the afterlife in main() -- ExitSyscall");
2683 break; /* what the hell :) */
2684
2685 case VgSrc_FatalSig:
2686 /* We were killed by a fatal signal, so replicate the effect */
2687 vg_assert(VG_(threads)[tid].os_state.fatalsig != 0);
2688 VG_(kill_self)(VG_(threads)[tid].os_state.fatalsig);
2689 VG_(core_panic)("main(): signal was supposed to be fatal");
2690 break;
2691
2692 default:
2693 VG_(core_panic)("main(): unexpected scheduler return code");
2694 }
njne96be672005-05-08 19:08:54 +00002695}
sewardj8b635a42004-11-22 19:01:47 +00002696
sewardj1ae3f3a2005-09-28 10:47:38 +00002697/* -------------------- */
2698
2699/* Final clean-up before terminating the process.
2700 Clean up the client by calling __libc_freeres() (if requested)
2701 This is Linux-specific?
2702*/
2703static void final_tidyup(ThreadId tid)
2704{
2705 Addr __libc_freeres_wrapper;
2706
2707 vg_assert(VG_(is_running_thread)(tid));
2708
2709 if ( !VG_(needs).libc_freeres ||
2710 !VG_(clo_run_libc_freeres) ||
2711 0 == (__libc_freeres_wrapper = VG_(get_libc_freeres_wrapper)()) )
2712 return; /* can't/won't do it */
2713
2714 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
2720 /* point thread context to point to libc_freeres_wrapper */
2721 VG_(set_IP)(tid, __libc_freeres_wrapper);
2722 // XXX should we use a special stack?
2723
2724 /* Block all blockable signals by copying the real block state into
2725 the thread's block state*/
2726 VG_(sigprocmask)(VKI_SIG_BLOCK, NULL, &VG_(threads)[tid].sig_mask);
2727 VG_(threads)[tid].tmp_sig_mask = VG_(threads)[tid].sig_mask;
2728
2729 /* and restore handlers to default */
2730 VG_(set_default_handler)(VKI_SIGSEGV);
2731 VG_(set_default_handler)(VKI_SIGBUS);
2732 VG_(set_default_handler)(VKI_SIGILL);
2733 VG_(set_default_handler)(VKI_SIGFPE);
2734
2735 // We were exiting, so assert that...
2736 vg_assert(VG_(is_exiting)(tid));
2737 // ...but now we're not again
2738 VG_(threads)[tid].exitreason = VgSrc_None;
2739
2740 // run until client thread exits - ideally with LIBC_FREERES_DONE,
2741 // but exit/exitgroup/signal will do
2742 VG_(scheduler)(tid);
2743
2744 vg_assert(VG_(is_exiting)(tid));
2745}
2746
sewardj45f4e7c2005-09-27 19:20:21 +00002747
2748/*====================================================================*/
2749/*=== Getting to main() alive ===*/
2750/*====================================================================*/
2751
2752/* If linking of the final executables is done with glibc present,
2753 then Valgrind starts at main() above as usual, and all of the
2754 following code is irrelevant.
2755
2756 However, this is not the intended mode of use. The plan is to
2757 avoid linking against glibc, by giving gcc the flags
2758 -nodefaultlibs -lgcc -nostartfiles at startup.
2759
2760 From this derive two requirements:
2761
2762 1. gcc may emit calls to memcpy and memset to deal with structure
2763 assignments etc. Since we have chosen to ignore all the
2764 "normal" supporting libraries, we have to provide our own
2765 implementations of them. No problem.
2766
2767 2. We have to provide a symbol "_start", to which the kernel
2768 hands control at startup. Hence the code below.
2769*/
2770
2771/* ---------------- Requirement 1 ---------------- */
2772
2773void* memcpy(void *dest, const void *src, size_t n);
2774void* memcpy(void *dest, const void *src, size_t n) {
2775 return VG_(memcpy)(dest,src,n);
2776}
2777void* memset(void *s, int c, size_t n);
2778void* memset(void *s, int c, size_t n) {
2779 return VG_(memset)(s,c,n);
2780}
2781
2782/* ---------------- Requirement 2 ---------------- */
2783
2784/* Glibc's sysdeps/i386/elf/start.S has the following gem of a
2785 comment, which explains how the stack looks right at process start
2786 (when _start is jumped to). Hence _start passes %esp to
2787 _start_in_C, which extracts argc/argv/envp and starts up
2788 correctly. */
2789
2790/* This is the canonical entry point, usually the first thing in the text
2791 segment. The SVR4/i386 ABI (pages 3-31, 3-32) says that when the entry
2792 point runs, most registers' values are unspecified, except for:
2793
2794 %edx Contains a function pointer to be registered with `atexit'.
2795 This is how the dynamic linker arranges to have DT_FINI
2796 functions called for shared libraries that have been loaded
2797 before this code runs.
2798
2799 %esp The stack contains the arguments and environment:
2800 0(%esp) argc
2801 4(%esp) argv[0]
2802 ...
2803 (4*argc)(%esp) NULL
2804 (4*(argc+1))(%esp) envp[0]
2805 ...
2806 NULL
2807*/
2808
2809/* The kernel hands control to _start, which extracts the initial
sewardja48a4932005-09-29 11:09:56 +00002810 stack pointer and calls onwards to _start_in_C. This also switches
2811 the new stack. */
sewardj45f4e7c2005-09-27 19:20:21 +00002812#if defined(VGP_x86_linux)
2813asm("\n"
sewardjd9fc3822005-11-18 23:50:43 +00002814 ".text\n"
sewardj45f4e7c2005-09-27 19:20:21 +00002815 "\t.globl _start\n"
2816 "\t.type _start,@function\n"
2817 "_start:\n"
2818 /* set up the new stack in %eax */
sewardjfdf91b42005-09-28 00:53:09 +00002819 "\tmovl $vgPlain_interim_stack, %eax\n"
sewardj45f4e7c2005-09-27 19:20:21 +00002820 "\taddl $"VG_STRINGIFY(VG_STACK_GUARD_SZB)", %eax\n"
2821 "\taddl $"VG_STRINGIFY(VG_STACK_ACTIVE_SZB)", %eax\n"
2822 "\tsubl $16, %eax\n"
2823 "\tandl $~15, %eax\n"
2824 /* install it, and collect the original one */
2825 "\txchgl %eax, %esp\n"
2826 /* call _start_in_C, passing it the startup %esp */
2827 "\tpushl %eax\n"
2828 "\tcall _start_in_C\n"
2829 "\thlt\n"
sewardj2fedc642005-11-19 02:02:57 +00002830 ".previous\n"
sewardj45f4e7c2005-09-27 19:20:21 +00002831);
2832#elif defined(VGP_amd64_linux)
2833asm("\n"
sewardjd9fc3822005-11-18 23:50:43 +00002834 ".text\n"
sewardj45f4e7c2005-09-27 19:20:21 +00002835 "\t.globl _start\n"
2836 "\t.type _start,@function\n"
2837 "_start:\n"
2838 /* set up the new stack in %rdi */
sewardjfdf91b42005-09-28 00:53:09 +00002839 "\tmovq $vgPlain_interim_stack, %rdi\n"
sewardj45f4e7c2005-09-27 19:20:21 +00002840 "\taddq $"VG_STRINGIFY(VG_STACK_GUARD_SZB)", %rdi\n"
2841 "\taddq $"VG_STRINGIFY(VG_STACK_ACTIVE_SZB)", %rdi\n"
2842 "\tandq $~15, %rdi\n"
2843 /* install it, and collect the original one */
2844 "\txchgq %rdi, %rsp\n"
2845 /* call _start_in_C, passing it the startup %rsp */
2846 "\tcall _start_in_C\n"
2847 "\thlt\n"
sewardj2fedc642005-11-19 02:02:57 +00002848 ".previous\n"
sewardj45f4e7c2005-09-27 19:20:21 +00002849);
sewardja48a4932005-09-29 11:09:56 +00002850#elif defined(VGP_ppc32_linux)
2851asm("\n"
sewardjd9fc3822005-11-18 23:50:43 +00002852 ".text\n"
sewardja48a4932005-09-29 11:09:56 +00002853 "\t.globl _start\n"
2854 "\t.type _start,@function\n"
2855 "_start:\n"
2856 /* set up the new stack in r16 */
2857 "\tlis 16,vgPlain_interim_stack@ha\n"
2858 "\tla 16,vgPlain_interim_stack@l(16)\n"
2859 "\tlis 17,("VG_STRINGIFY(VG_STACK_GUARD_SZB)" >> 16)\n"
2860 "\tori 17,17,("VG_STRINGIFY(VG_STACK_GUARD_SZB)" & 0xFFFF)\n"
2861 "\tlis 18,("VG_STRINGIFY(VG_STACK_ACTIVE_SZB)" >> 16)\n"
2862 "\tori 18,18,("VG_STRINGIFY(VG_STACK_ACTIVE_SZB)" & 0xFFFF)\n"
2863 "\tadd 16,17,16\n"
2864 "\tadd 16,18,16\n"
2865 "\trlwinm 16,16,0,0,27\n"
2866 /* now r16 = &vgPlain_interim_stack + VG_STACK_GUARD_SZB +
2867 VG_STACK_ACTIVE_SZB rounded down to the nearest 16-byte
2868 boundary. And r1 is the original SP. Set the SP to r16 and
2869 call _start_in_C, passing it the initial SP. */
2870 "\tmr 3,1\n"
2871 "\tmr 1,16\n"
2872 "\tbl _start_in_C\n"
2873 "\ttrap\n"
sewardj2fedc642005-11-19 02:02:57 +00002874 ".previous\n"
sewardja48a4932005-09-29 11:09:56 +00002875);
sewardj2c48c7b2005-11-29 13:05:56 +00002876#elif defined(VGP_ppc64_linux)
2877asm("\n"
2878 ".text\n"
cerion21082042005-12-06 19:07:08 +00002879 /* PPC64 ELF ABI says '_start' points to a function descriptor.
2880 So we must have one, and that is what goes into the .opd section. */
2881 "\t.global _start\n"
2882 "\t.section \".opd\",\"aw\"\n"
2883 "\t.align 3\n"
sewardj2c48c7b2005-11-29 13:05:56 +00002884 "_start:\n"
cerion21082042005-12-06 19:07:08 +00002885 "\t.quad ._start,.TOC.@tocbase,0\n"
2886 "\t.previous\n"
2887 "\t.type ._start,@function\n"
2888 "\t.global ._start\n"
2889 "._start:\n"
sewardj2c48c7b2005-11-29 13:05:56 +00002890 /* set up the new stack in r16 */
2891 "\tlis 16, vgPlain_interim_stack@highest\n"
2892 "\tori 16,16,vgPlain_interim_stack@higher\n"
2893 "\tsldi 16,16,32\n"
2894 "\toris 16,16,vgPlain_interim_stack@h\n"
2895 "\tori 16,16,vgPlain_interim_stack@l\n"
2896 "\txor 17,17,17\n"
2897 "\tlis 17,("VG_STRINGIFY(VG_STACK_GUARD_SZB)" >> 16)\n"
2898 "\tori 17,17,("VG_STRINGIFY(VG_STACK_GUARD_SZB)" & 0xFFFF)\n"
2899 "\txor 18,18,18\n"
2900 "\tlis 18,("VG_STRINGIFY(VG_STACK_ACTIVE_SZB)" >> 16)\n"
2901 "\tori 18,18,("VG_STRINGIFY(VG_STACK_ACTIVE_SZB)" & 0xFFFF)\n"
2902 "\tadd 16,17,16\n"
2903 "\tadd 16,18,16\n"
2904 "\trldicr 16,16,0,59\n"
2905 /* now r16 = &vgPlain_interim_stack + VG_STACK_GUARD_SZB +
2906 VG_STACK_ACTIVE_SZB rounded down to the nearest 16-byte
2907 boundary. And r1 is the original SP. Set the SP to r16 and
2908 call _start_in_C, passing it the initial SP. */
2909 "\tmr 3,1\n"
2910 "\tmr 1,16\n"
cerion21082042005-12-06 19:07:08 +00002911 "\tbl ._start_in_C\n"
2912 "\tnop\n"
sewardj2c48c7b2005-11-29 13:05:56 +00002913 "\ttrap\n"
2914 ".previous\n"
2915);
sewardj45f4e7c2005-09-27 19:20:21 +00002916#else
2917#error "_start: needs implementation on this platform"
2918#endif
2919
2920/* Avoid compiler warnings: this fn _is_ used, but labelling it
2921 'static' causes gcc to complain it isn't. */
2922void _start_in_C ( UWord* pArgc );
2923void _start_in_C ( UWord* pArgc )
2924{
2925 Int r;
2926 Word argc = pArgc[0];
2927 HChar** argv = (HChar**)&pArgc[1];
2928 HChar** envp = (HChar**)&pArgc[1+argc+1];
sewardjfdf91b42005-09-28 00:53:09 +00002929 sp_at_startup = (Addr)pArgc;
sewardj45f4e7c2005-09-27 19:20:21 +00002930 r = main( (Int)argc, argv, envp );
2931 VG_(exit)(r);
2932}
2933
sewardjde4a1d02002-03-22 01:27:54 +00002934/*--------------------------------------------------------------------*/
njn04e16982005-05-31 00:23:43 +00002935/*--- end ---*/
sewardjde4a1d02002-03-22 01:27:54 +00002936/*--------------------------------------------------------------------*/