blob: cb6892ec6561be3ffc3435e6e5215a26c6f5321b [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
sewardjfdf91b42005-09-28 00:53:09 +0000373# if defined(VGP_ppc32_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
sewardjfdf91b42005-09-28 00:53:09 +0000490# if defined(VGP_ppc32_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 }
562# endif
563 break;
nethercote71980f02004-01-24 18:18:54 +0000564
sewardjfdf91b42005-09-28 00:53:09 +0000565# if defined(VGP_ppc32_linux)
566 case AT_IGNOREPPC:
567 break;
568# endif
569
570 case AT_SECURE:
571 /* If this is 1, then it means that this program is
572 running suid, and therefore the dynamic linker should
573 be careful about LD_PRELOAD, etc. However, since
574 stage1 (the thing the kernel actually execve's) should
575 never be SUID, and we need LD_PRELOAD to work for the
576 client, we set AT_SECURE to 0. */
577 auxv->u.a_val = 0;
578 break;
579
tom2315d182005-11-11 08:39:34 +0000580 case AT_SYSINFO:
sewardjfdf91b42005-09-28 00:53:09 +0000581# if !defined(VGP_ppc32_linux)
582 case AT_SYSINFO_EHDR:
tom2315d182005-11-11 08:39:34 +0000583# endif
sewardjfdf91b42005-09-28 00:53:09 +0000584 /* Trash this, because we don't reproduce it */
585 auxv->a_type = AT_IGNORE;
586 break;
sewardjfdf91b42005-09-28 00:53:09 +0000587
588 default:
589 /* stomp out anything we don't know about */
590 VG_(debugLog)(2, "main",
591 "stomping auxv entry %lld\n",
592 (ULong)auxv->a_type);
593 auxv->a_type = AT_IGNORE;
594 break;
nethercote71980f02004-01-24 18:18:54 +0000595 }
596 }
597 *auxv = *orig_auxv;
598 vg_assert(auxv->a_type == AT_NULL);
599
600 vg_assert((strtab-stringbase) == stringsize);
601
sewardj45f4e7c2005-09-27 19:20:21 +0000602 /* client_SP is pointing at client's argc/argv */
nethercote5ee67ca2004-06-22 14:00:09 +0000603
sewardj45f4e7c2005-09-27 19:20:21 +0000604 if (0) VG_(printf)("startup SP = %p\n", client_SP);
605 return client_SP;
nethercote71980f02004-01-24 18:18:54 +0000606}
607
sewardj45f4e7c2005-09-27 19:20:21 +0000608
609/* Allocate the client data segment. It is an expandable anonymous
610 mapping abutting a shrinkable reservation of size max_dseg_size.
611 The data segment starts at VG_(brk_base), which is page-aligned,
612 and runs up to VG_(brk_limit), which isn't. */
613
614static void setup_client_dataseg ( SizeT max_size )
615{
616 Bool ok;
617 SysRes sres;
618 Addr anon_start = VG_(brk_base);
619 SizeT anon_size = VKI_PAGE_SIZE;
620 Addr resvn_start = anon_start + anon_size;
621 SizeT resvn_size = max_size - anon_size;
622
623 vg_assert(VG_IS_PAGE_ALIGNED(anon_size));
624 vg_assert(VG_IS_PAGE_ALIGNED(resvn_size));
625 vg_assert(VG_IS_PAGE_ALIGNED(anon_start));
626 vg_assert(VG_IS_PAGE_ALIGNED(resvn_start));
627
628 /* Because there's been no brk activity yet: */
629 vg_assert(VG_(brk_base) == VG_(brk_limit));
630
631 /* Try to create the data seg and associated reservation where
632 VG_(brk_base) says. */
633 ok = VG_(am_create_reservation)(
634 resvn_start,
635 resvn_size,
636 SmLower,
637 anon_size
638 );
639
640 if (!ok) {
641 /* Hmm, that didn't work. Well, let aspacem suggest an address
642 it likes better, and try again with that. */
643 anon_start = VG_(am_get_advisory_client_simple)
644 ( 0/*floating*/, anon_size+resvn_size, &ok );
645 if (ok) {
646 resvn_start = anon_start + anon_size;
647 ok = VG_(am_create_reservation)(
648 resvn_start,
649 resvn_size,
650 SmLower,
651 anon_size
652 );
653 if (ok)
654 VG_(brk_base) = VG_(brk_limit) = anon_start;
655 }
656 /* that too might have failed, but if it has, we're hosed: there
657 is no Plan C. */
658 }
659 vg_assert(ok);
660
njn7c555a92005-11-16 17:16:10 +0000661 /* We make the data segment (heap) executable because LinuxThreads on
njn0ddabca2005-11-16 23:54:46 +0000662 ppc32 creates trampolines in this area. Also, on x86/Linux the data
663 segment is RWX natively, at least according to /proc/self/maps.
664 Also, having a non-executable data seg would kill any program which
665 tried to create code in the data seg and then run it. */
sewardj45f4e7c2005-09-27 19:20:21 +0000666 sres = VG_(am_mmap_anon_fixed_client)(
667 anon_start,
668 anon_size,
sewardj33ca9e82005-11-16 17:12:38 +0000669 VKI_PROT_READ|VKI_PROT_WRITE|VKI_PROT_EXEC
sewardj45f4e7c2005-09-27 19:20:21 +0000670 );
671 vg_assert(!sres.isError);
672 vg_assert(sres.val == anon_start);
673}
674
675
nethercote71980f02004-01-24 18:18:54 +0000676/*====================================================================*/
677/*=== Find executable ===*/
678/*====================================================================*/
679
sewardjfdf91b42005-09-28 00:53:09 +0000680/* Scan a colon-separated list, and call a function on each element.
681 The string must be mutable, because we insert a temporary '\0', but
682 the string will end up unmodified. (*func) should return True if it
683 doesn't need to see any more.
684
685 This routine will return True if (*func) returns True and False if
686 it reaches the end of the list without that happening.
687*/
688static Bool scan_colsep(char *colsep, Bool (*func)(const char *))
689{
690 char *cp, *entry;
691 int end;
692
693 if (colsep == NULL ||
694 *colsep == '\0')
695 return False;
696
697 entry = cp = colsep;
698
699 do {
700 end = (*cp == '\0');
701
702 if (*cp == ':' || *cp == '\0') {
703 char save = *cp;
704
705 *cp = '\0';
706 if ((*func)(entry)) {
707 *cp = save;
708 return True;
709 }
710 *cp = save;
711 entry = cp+1;
712 }
713 cp++;
714 } while(!end);
715
716 return False;
717}
718
sewardj45f4e7c2005-09-27 19:20:21 +0000719/* Need a static copy because can't use dynamic mem allocation yet */
njn73750612005-10-14 03:11:30 +0000720static HChar executable_name_in [VKI_PATH_MAX];
721static HChar executable_name_out[VKI_PATH_MAX];
thughes4ad52d02004-06-27 17:37:21 +0000722
sewardj45f4e7c2005-09-27 19:20:21 +0000723static Bool match_executable(const char *entry)
724{
njn73750612005-10-14 03:11:30 +0000725 HChar buf[VG_(strlen)(entry) + VG_(strlen)(executable_name_in) + 3];
thughes4ad52d02004-06-27 17:37:21 +0000726
njn73750612005-10-14 03:11:30 +0000727 /* empty PATH element means '.' */
thughes4ad52d02004-06-27 17:37:21 +0000728 if (*entry == '\0')
729 entry = ".";
730
njn73750612005-10-14 03:11:30 +0000731 VG_(snprintf)(buf, sizeof(buf), "%s/%s", entry, executable_name_in);
732
733 // Don't match directories
734 if (VG_(is_dir)(buf))
735 return False;
736
737 // If we match an executable, we choose that immediately. If we find a
738 // matching non-executable we remember it but keep looking for an
739 // matching executable later in the path.
sewardj45f4e7c2005-09-27 19:20:21 +0000740 if (VG_(access)(buf, True/*r*/, False/*w*/, True/*x*/) == 0) {
njn73750612005-10-14 03:11:30 +0000741 VG_(strncpy)( executable_name_out, buf, VKI_PATH_MAX-1 );
742 executable_name_out[VKI_PATH_MAX-1] = 0;
743 return True; // Stop looking
744 } else if (VG_(access)(buf, True/*r*/, False/*w*/, False/*x*/) == 0
745 && VG_STREQ(executable_name_out, ""))
746 {
747 VG_(strncpy)( executable_name_out, buf, VKI_PATH_MAX-1 );
748 executable_name_out[VKI_PATH_MAX-1] = 0;
749 return False; // Keep looking
750 } else {
751 return False; // Keep looking
thughes4ad52d02004-06-27 17:37:21 +0000752 }
thughes4ad52d02004-06-27 17:37:21 +0000753}
754
njn73750612005-10-14 03:11:30 +0000755// Returns NULL if it wasn't found.
sewardj45f4e7c2005-09-27 19:20:21 +0000756static HChar* find_executable ( HChar* exec )
nethercote71980f02004-01-24 18:18:54 +0000757{
758 vg_assert(NULL != exec);
njn73750612005-10-14 03:11:30 +0000759 if (VG_(strchr)(exec, '/')) {
760 // Has a '/' - use the name as is
761 VG_(strncpy)( executable_name_out, exec, VKI_PATH_MAX-1 );
762 } else {
763 // No '/' - we need to search the path
sewardj03d8aa82005-10-14 11:25:49 +0000764 HChar* path;
njn73750612005-10-14 03:11:30 +0000765 VG_(strncpy)( executable_name_in, exec, VKI_PATH_MAX-1 );
766 VG_(memset) ( executable_name_out, 0, VKI_PATH_MAX );
sewardj03d8aa82005-10-14 11:25:49 +0000767 path = VG_(getenv)("PATH");
thughes4ad52d02004-06-27 17:37:21 +0000768 scan_colsep(path, match_executable);
nethercote71980f02004-01-24 18:18:54 +0000769 }
njn73750612005-10-14 03:11:30 +0000770 return VG_STREQ(executable_name_out, "") ? NULL : executable_name_out;
nethercote71980f02004-01-24 18:18:54 +0000771}
772
773
774/*====================================================================*/
nethercotef4928da2004-06-15 10:54:40 +0000775/*=== Command line errors ===*/
776/*====================================================================*/
777
njnbe9b47b2005-05-15 16:22:58 +0000778static void revert_to_stderr ( void )
nethercotef4928da2004-06-15 10:54:40 +0000779{
njnbe9b47b2005-05-15 16:22:58 +0000780 vg_assert( !VG_(logging_to_socket) );
nethercotef8548672004-06-21 12:42:35 +0000781 VG_(clo_log_fd) = 2; /* stderr */
nethercotef4928da2004-06-15 10:54:40 +0000782}
783
784void VG_(bad_option) ( Char* opt )
785{
njnbe9b47b2005-05-15 16:22:58 +0000786 revert_to_stderr();
njn02bc4b82005-05-15 17:28:26 +0000787 VG_(printf)("valgrind: Bad option '%s'; aborting.\n", opt);
nethercotef4928da2004-06-15 10:54:40 +0000788 VG_(printf)("valgrind: Use --help for more information.\n");
789 VG_(exit)(1);
790}
791
nethercotef4928da2004-06-15 10:54:40 +0000792static void missing_prog ( void )
793{
njnbe9b47b2005-05-15 16:22:58 +0000794 revert_to_stderr();
nethercotef4928da2004-06-15 10:54:40 +0000795 VG_(printf)("valgrind: no program specified\n");
796 VG_(printf)("valgrind: Use --help for more information.\n");
797 VG_(exit)(1);
798}
799
800static void config_error ( Char* msg )
801{
njnbe9b47b2005-05-15 16:22:58 +0000802 revert_to_stderr();
nethercotef4928da2004-06-15 10:54:40 +0000803 VG_(printf)("valgrind: Startup or configuration error:\n %s\n", msg);
804 VG_(printf)("valgrind: Unable to start up properly. Giving up.\n");
805 VG_(exit)(1);
806}
807
808
nethercote71980f02004-01-24 18:18:54 +0000809/*====================================================================*/
810/*=== Loading the client ===*/
811/*====================================================================*/
812
sewardj45f4e7c2005-09-27 19:20:21 +0000813/* Load the client whose name is VG_(argv_the_exename). */
nethercote71980f02004-01-24 18:18:54 +0000814
sewardj45f4e7c2005-09-27 19:20:21 +0000815static void load_client ( /*OUT*/struct exeinfo* info,
816 /*OUT*/Addr* client_eip)
817{
njn73750612005-10-14 03:11:30 +0000818 HChar* exe_name;
sewardj45f4e7c2005-09-27 19:20:21 +0000819 Int ret;
820 SysRes res;
821
822 vg_assert( VG_(args_the_exename) != NULL);
njn73750612005-10-14 03:11:30 +0000823 exe_name = find_executable( VG_(args_the_exename) );
824
825 if (!exe_name) {
826 VG_(printf)("valgrind: %s: command not found\n", VG_(args_the_exename));
827 VG_(exit)(127); // 127 is Posix NOTFOUND
828 }
sewardj45f4e7c2005-09-27 19:20:21 +0000829
830 VG_(memset)(info, 0, sizeof(*info));
nethercote71980f02004-01-24 18:18:54 +0000831 info->exe_base = VG_(client_base);
832 info->exe_end = VG_(client_end);
nethercote71980f02004-01-24 18:18:54 +0000833
njn73750612005-10-14 03:11:30 +0000834 ret = VG_(do_exec)(exe_name, info);
835
836 // The client was successfully loaded! Continue.
nethercote71980f02004-01-24 18:18:54 +0000837
sewardj45f4e7c2005-09-27 19:20:21 +0000838 /* Get hold of a file descriptor which refers to the client
839 executable. This is needed for attaching to GDB. */
njn73750612005-10-14 03:11:30 +0000840 res = VG_(open)(exe_name, VKI_O_RDONLY, VKI_S_IRUSR);
sewardj45f4e7c2005-09-27 19:20:21 +0000841 if (!res.isError)
842 VG_(cl_exec_fd) = res.val;
843
nethercote71980f02004-01-24 18:18:54 +0000844 /* Copy necessary bits of 'info' that were filled in */
845 *client_eip = info->init_eip;
sewardj45f4e7c2005-09-27 19:20:21 +0000846 VG_(brk_base) = VG_(brk_limit) = VG_PGROUNDUP(info->brkbase);
nethercote71980f02004-01-24 18:18:54 +0000847}
848
nethercote969ecf12004-10-13 17:29:01 +0000849
sewardj71bc3cb2005-05-19 00:25:45 +0000850/*====================================================================*/
851/*=== Command-line: variables, processing, etc ===*/
852/*====================================================================*/
853
854// See pub_{core,tool}_options.h for explanations of all these.
855
sewardj45f4e7c2005-09-27 19:20:21 +0000856static void usage_NORETURN ( Bool debug_help )
njn7cf0bd32002-06-08 13:36:03 +0000857{
njn25e49d8e72002-09-23 09:36:25 +0000858 Char* usage1 =
njn00cfcfc2005-11-12 18:53:50 +0000859"usage: valgrind [options] prog-and-args\n"
njn25e49d8e72002-09-23 09:36:25 +0000860"\n"
nethercote2b0793f2003-12-02 10:41:18 +0000861" common user options for all Valgrind tools, with defaults in [ ]:\n"
sewardjb5f6f512005-03-10 23:59:00 +0000862" --tool=<name> use the Valgrind tool named <name> [memcheck]\n"
nethercotea76368b2004-06-16 11:56:29 +0000863" -h --help show this message\n"
nethercote6c999f22004-01-31 22:55:15 +0000864" --help-debug show this message, plus debugging options\n"
njn25e49d8e72002-09-23 09:36:25 +0000865" --version show version\n"
njn25e49d8e72002-09-23 09:36:25 +0000866" -q --quiet run silently; only print error msgs\n"
867" -v --verbose be more verbose, incl counts of errors\n"
nethercote77eba602003-11-13 17:35:04 +0000868" --trace-children=no|yes Valgrind-ise child processes? [no]\n"
nethercote0d588502004-06-21 13:27:11 +0000869" --track-fds=no|yes track open file descriptors? [no]\n"
thughes6233a382004-08-21 11:10:44 +0000870" --time-stamp=no|yes add timestamps to log messages? [no]\n"
njnce545552005-07-25 22:36:52 +0000871" --log-fd=<number> log messages to file descriptor [2=stderr]\n"
tombbe14b12005-11-04 16:49:39 +0000872" --log-file=<file> log messages to <file>.<pid>\n"
njnce545552005-07-25 22:36:52 +0000873" --log-file-exactly=<file> log messages to <file>\n"
874" --log-file-qualifier=<VAR> incorporate $VAR in logfile name [none]\n"
875" --log-socket=ipaddr:port log messages to socket ipaddr:port\n"
nethercote2b0793f2003-12-02 10:41:18 +0000876"\n"
877" uncommon user options for all Valgrind tools:\n"
nethercote0d588502004-06-21 13:27:11 +0000878" --run-libc-freeres=no|yes free up glibc memory at exit? [yes]\n"
njn628add62005-11-12 18:21:40 +0000879" --sim-hints=hint1,hint2,... known hints:\n"
sewardj19617ae2005-10-20 01:09:57 +0000880" lax-ioctls, enable-outer [none]\n"
sewardjb1131a82005-03-19 15:12:21 +0000881" --show-emwarns=no|yes show warnings about emulation limits? [no]\n"
sewardj6c3a2192005-07-24 07:00:45 +0000882" --smc-check=none|stack|all checks for self-modifying code: none,\n"
883" only for code found in stacks, or all [stack]\n"
sewardj3c3f0c12005-11-08 15:52:36 +0000884" --kernel-variant=variant1,variant2,... known variants: bproc [none]\n"
885" handle non-standard kernel variants\n"
njn25e49d8e72002-09-23 09:36:25 +0000886"\n"
nethercote2b0793f2003-12-02 10:41:18 +0000887" user options for Valgrind tools that report errors:\n"
njnce545552005-07-25 22:36:52 +0000888" --xml=yes all output is in XML (Memcheck/Nulgrind only)\n"
njnc8ec9f82005-07-20 03:03:28 +0000889" --xml-user-comment=STR copy STR verbatim to XML output\n"
nethercote2b0793f2003-12-02 10:41:18 +0000890" --demangle=no|yes automatically demangle C++ names? [yes]\n"
njn20b4a152005-10-19 22:39:40 +0000891" --num-callers=<number> show <number> callers in stack traces [12]\n"
nethercote2b0793f2003-12-02 10:41:18 +0000892" --error-limit=no|yes stop showing new errors if too many? [yes]\n"
893" --show-below-main=no|yes continue stack traces below main() [no]\n"
894" --suppressions=<filename> suppress errors described in <filename>\n"
sewardjd153fae2005-01-10 17:24:47 +0000895" --gen-suppressions=no|yes|all print suppressions for errors? [no]\n"
nethercote04d0fbc2004-01-26 16:48:06 +0000896" --db-attach=no|yes start debugger when errors detected? [no]\n"
897" --db-command=<command> command to start debugger [gdb -nw %%f %%p]\n"
898" --input-fd=<number> file descriptor for input [0=stdin]\n"
sewardj97724e52005-04-02 23:40:59 +0000899" --max-stackframe=<number> assume stack switch for SP changes larger\n"
900" than <number> bytes [2000000]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +0000901"\n";
njn7cf0bd32002-06-08 13:36:03 +0000902
njn25e49d8e72002-09-23 09:36:25 +0000903 Char* usage2 =
904"\n"
nethercote2b0793f2003-12-02 10:41:18 +0000905" debugging options for all Valgrind tools:\n"
njn25e49d8e72002-09-23 09:36:25 +0000906" --sanity-level=<number> level of sanity checking to do [1]\n"
nethercote137bc552003-11-14 17:47:54 +0000907" --profile=no|yes profile? (tool must be built for it) [no]\n"
sewardjfa8ec112005-01-19 11:55:34 +0000908" --trace-flags=<XXXXXXXX> show generated code? (X = 0|1) [00000000]\n"
909" --profile-flags=<XXXXXXXX> ditto, but for profiling (X = 0|1) [00000000]\n"
njn20b4a152005-10-19 22:39:40 +0000910" --trace-notbelow=<number> only show BBs above <number> [0]\n"
njn25e49d8e72002-09-23 09:36:25 +0000911" --trace-syscalls=no|yes show all system calls? [no]\n"
912" --trace-signals=no|yes show signal handling details? [no]\n"
913" --trace-symtab=no|yes show symbol table details? [no]\n"
sewardjce058b02005-05-01 08:55:38 +0000914" --trace-cfi=no|yes show call-frame-info details? [no]\n"
njn25e49d8e72002-09-23 09:36:25 +0000915" --trace-sched=no|yes show thread scheduler details? [no]\n"
jsgf855d93d2003-10-13 22:26:55 +0000916" --wait-for-gdb=yes|no pause on startup to wait for gdb attach\n"
sewardjb5f6f512005-03-10 23:59:00 +0000917#if 0
918" --model-pthreads=yes|no model the pthreads library [no]\n"
919#endif
920" --command-line-only=no|yes only use command line options [no]\n"
njn613812e2005-03-11 04:57:30 +0000921"\n"
922" --vex-iropt-verbosity 0 .. 9 [0]\n"
923" --vex-iropt-level 0 .. 2 [2]\n"
924" --vex-iropt-precise-memory-exns [no]\n"
sewardj8b635a42004-11-22 19:01:47 +0000925" --vex-iropt-unroll-thresh 0 .. 400 [120]\n"
926" --vex-guest-max-insns 1 .. 100 [50]\n"
927" --vex-guest-chase-thresh 0 .. 99 [10]\n"
928"\n"
sewardjfa8ec112005-01-19 11:55:34 +0000929" --trace-flags and --profile-flags values (omit the middle space):\n"
sewardj2a99cf62004-11-24 10:44:19 +0000930" 1000 0000 show conversion into IR\n"
931" 0100 0000 show after initial opt\n"
932" 0010 0000 show after instrumentation\n"
933" 0001 0000 show after second opt\n"
934" 0000 1000 show after tree building\n"
935" 0000 0100 show selecting insns\n"
936" 0000 0010 show after reg-alloc\n"
937" 0000 0001 show final assembly\n"
938"\n"
nethercote2b0793f2003-12-02 10:41:18 +0000939" debugging options for Valgrind tools that report errors\n"
940" --dump-error=<number> show translation for basic block associated\n"
941" with <number>'th error context [0=show none]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +0000942"\n";
njn3e884182003-04-15 13:03:23 +0000943
944 Char* usage3 =
945"\n"
nethercote71980f02004-01-24 18:18:54 +0000946" Extra options read from ~/.valgrindrc, $VALGRIND_OPTS, ./.valgrindrc\n"
njn25e49d8e72002-09-23 09:36:25 +0000947"\n"
njn53612422005-03-12 16:22:54 +0000948" Valgrind is Copyright (C) 2000-2005 Julian Seward et al.\n"
njn25e49d8e72002-09-23 09:36:25 +0000949" and licensed under the GNU General Public License, version 2.\n"
950" Bug reports, feedback, admiration, abuse, etc, to: %s.\n"
njnd04b7c62002-10-03 14:05:52 +0000951"\n"
nethercote137bc552003-11-14 17:47:54 +0000952" Tools are copyright and licensed by their authors. See each\n"
953" tool's start-up message for more information.\n"
njn25e49d8e72002-09-23 09:36:25 +0000954"\n";
njn7cf0bd32002-06-08 13:36:03 +0000955
njnbe9b47b2005-05-15 16:22:58 +0000956 // Ensure the message goes to stdout
957 VG_(clo_log_fd) = 1;
958 vg_assert( !VG_(logging_to_socket) );
959
fitzhardinge98abfc72003-12-16 02:05:15 +0000960 VG_(printf)(usage1);
961 if (VG_(details).name) {
962 VG_(printf)(" user options for %s:\n", VG_(details).name);
fitzhardinge98abfc72003-12-16 02:05:15 +0000963 if (VG_(needs).command_line_options)
njn51d827b2005-05-09 01:02:08 +0000964 VG_TDICT_CALL(tool_print_usage);
fitzhardinge98abfc72003-12-16 02:05:15 +0000965 else
966 VG_(printf)(" (none)\n");
967 }
nethercote6c999f22004-01-31 22:55:15 +0000968 if (debug_help) {
969 VG_(printf)(usage2);
fitzhardinge98abfc72003-12-16 02:05:15 +0000970
nethercote6c999f22004-01-31 22:55:15 +0000971 if (VG_(details).name) {
972 VG_(printf)(" debugging options for %s:\n", VG_(details).name);
973
974 if (VG_(needs).command_line_options)
njn51d827b2005-05-09 01:02:08 +0000975 VG_TDICT_CALL(tool_print_debug_usage);
nethercote6c999f22004-01-31 22:55:15 +0000976 else
977 VG_(printf)(" (none)\n");
978 }
fitzhardinge98abfc72003-12-16 02:05:15 +0000979 }
nethercote421281e2003-11-20 16:20:55 +0000980 VG_(printf)(usage3, VG_BUGS_TO);
nethercotef4928da2004-06-15 10:54:40 +0000981 VG_(exit)(0);
njn7cf0bd32002-06-08 13:36:03 +0000982}
sewardjde4a1d02002-03-22 01:27:54 +0000983
sewardjde4a1d02002-03-22 01:27:54 +0000984
sewardj45f4e7c2005-09-27 19:20:21 +0000985/* Peer at previously set up VG_(args_for_valgrind) and extract any
986 request for help and also the tool name. */
987
988static void get_helprequest_and_toolname ( Int* need_help, HChar** tool )
989{
990 UInt i;
991 HChar* str;
sewardj8b635a42004-11-22 19:01:47 +0000992
nethercote71980f02004-01-24 18:18:54 +0000993 /* parse the options we have (only the options we care about now) */
sewardj45f4e7c2005-09-27 19:20:21 +0000994 for (i = 0; i < VG_(args_for_valgrind).used; i++) {
nethercote71980f02004-01-24 18:18:54 +0000995
sewardj45f4e7c2005-09-27 19:20:21 +0000996 str = VG_(args_for_valgrind).strs[i];
997 vg_assert(str);
nethercote71980f02004-01-24 18:18:54 +0000998
sewardj45f4e7c2005-09-27 19:20:21 +0000999 if (VG_STREQ(str, "--version")) {
njn2e9f3f32005-10-26 16:17:46 +00001000 // Ensure the version string goes to stdout
1001 VG_(clo_log_fd) = 1;
sewardj45f4e7c2005-09-27 19:20:21 +00001002 VG_(printf)("valgrind-" VERSION "\n");
1003 VG_(exit)(0);
1004
1005 } else if (VG_CLO_STREQ(str, "--help") ||
1006 VG_CLO_STREQ(str, "-h")) {
nethercote6c999f22004-01-31 22:55:15 +00001007 *need_help = 1;
1008
sewardj45f4e7c2005-09-27 19:20:21 +00001009 } else if (VG_CLO_STREQ(str, "--help-debug")) {
nethercote6c999f22004-01-31 22:55:15 +00001010 *need_help = 2;
nethercote71980f02004-01-24 18:18:54 +00001011
sewardj45f4e7c2005-09-27 19:20:21 +00001012 // The tool has already been determined, but we need to know the name
1013 // here.
1014 } else if (VG_CLO_STREQN(7, str, "--tool=")) {
1015 *tool = &str[7];
nethercote71980f02004-01-24 18:18:54 +00001016 }
1017 }
nethercote71980f02004-01-24 18:18:54 +00001018}
1019
sewardj45f4e7c2005-09-27 19:20:21 +00001020static Bool process_cmd_line_options( UInt* client_auxv, const char* toolname )
nethercote71980f02004-01-24 18:18:54 +00001021{
sewardj92645592005-07-23 09:18:34 +00001022 SysRes sres;
1023 Int i, eventually_log_fd;
1024 Int toolname_len = VG_(strlen)(toolname);
njnbe9b47b2005-05-15 16:22:58 +00001025 enum {
1026 VgLogTo_Fd,
1027 VgLogTo_File,
1028 VgLogTo_FileExactly,
1029 VgLogTo_Socket
1030 } log_to = VgLogTo_Fd; // Where is logging output to be sent?
sewardjde4a1d02002-03-22 01:27:54 +00001031
nethercotee1730692003-11-20 10:38:07 +00001032 /* log to stderr by default, but usage message goes to stdout */
nethercotef8548672004-06-21 12:42:35 +00001033 eventually_log_fd = 2;
sewardjde4a1d02002-03-22 01:27:54 +00001034
sewardj19d81412002-06-03 01:10:40 +00001035 /* Check for sane path in ./configure --prefix=... */
fitzhardinge98abfc72003-12-16 02:05:15 +00001036 if (VG_LIBDIR[0] != '/')
sewardj19d81412002-06-03 01:10:40 +00001037 config_error("Please use absolute paths in "
1038 "./configure --prefix=... or --libdir=...");
sewardj38170912002-05-10 21:07:22 +00001039
sewardj45f4e7c2005-09-27 19:20:21 +00001040 for (i = 0; i < VG_(args_for_valgrind).used; i++) {
nethercote71980f02004-01-24 18:18:54 +00001041
sewardj45f4e7c2005-09-27 19:20:21 +00001042 HChar* arg = VG_(args_for_valgrind).strs[i];
1043 HChar* colon = arg;
nethercote71980f02004-01-24 18:18:54 +00001044
thughes3bfd5a02004-07-18 08:05:44 +00001045 /* Look for a colon in the switch name */
1046 while (*colon && *colon != ':' && *colon != '=')
1047 colon++;
nethercote71980f02004-01-24 18:18:54 +00001048
1049 /* Look for matching "--toolname:foo" */
thughes3bfd5a02004-07-18 08:05:44 +00001050 if (*colon == ':') {
nethercote71980f02004-01-24 18:18:54 +00001051 if (VG_CLO_STREQN(2, arg, "--") &&
1052 VG_CLO_STREQN(toolname_len, arg+2, toolname) &&
1053 VG_CLO_STREQN(1, arg+2+toolname_len, ":"))
1054 {
1055 // prefix matches, convert "--toolname:foo" to "--foo"
1056 if (0)
1057 VG_(printf)("tool-specific arg: %s\n", arg);
sewardj45f4e7c2005-09-27 19:20:21 +00001058 arg = VG_(strdup)(arg + toolname_len + 1);
nethercote71980f02004-01-24 18:18:54 +00001059 arg[0] = '-';
1060 arg[1] = '-';
1061
1062 } else {
1063 // prefix doesn't match, skip to next arg
1064 continue;
1065 }
1066 }
1067
fitzhardinge98abfc72003-12-16 02:05:15 +00001068 /* Ignore these options - they've already been handled */
njn45270a22005-03-27 01:00:11 +00001069 if (VG_CLO_STREQN( 7, arg, "--tool=")) goto skip_arg;
njn45270a22005-03-27 01:00:11 +00001070 if (VG_CLO_STREQN(20, arg, "--command-line-only=")) goto skip_arg;
fitzhardinge98abfc72003-12-16 02:05:15 +00001071
njn45270a22005-03-27 01:00:11 +00001072 if ( VG_CLO_STREQ(arg, "--")) goto skip_arg;
nethercote27fec902004-06-16 21:26:32 +00001073
nethercote71980f02004-01-24 18:18:54 +00001074 else if (VG_CLO_STREQ(arg, "-v") ||
1075 VG_CLO_STREQ(arg, "--verbose"))
sewardjde4a1d02002-03-22 01:27:54 +00001076 VG_(clo_verbosity)++;
nethercote27fec902004-06-16 21:26:32 +00001077
nethercote71980f02004-01-24 18:18:54 +00001078 else if (VG_CLO_STREQ(arg, "-q") ||
1079 VG_CLO_STREQ(arg, "--quiet"))
sewardjde4a1d02002-03-22 01:27:54 +00001080 VG_(clo_verbosity)--;
1081
sewardj1cf558c2005-04-25 01:36:56 +00001082 else if (VG_CLO_STREQ(arg, "-d")) {
1083 /* do nothing */
1084 }
1085
sewardj71bc3cb2005-05-19 00:25:45 +00001086 else VG_BOOL_CLO(arg, "--xml", VG_(clo_xml))
njn45270a22005-03-27 01:00:11 +00001087 else VG_BOOL_CLO(arg, "--db-attach", VG_(clo_db_attach))
1088 else VG_BOOL_CLO(arg, "--demangle", VG_(clo_demangle))
1089 else VG_BOOL_CLO(arg, "--error-limit", VG_(clo_error_limit))
njn45270a22005-03-27 01:00:11 +00001090 else VG_BOOL_CLO(arg, "--show-emwarns", VG_(clo_show_emwarns))
sewardj97724e52005-04-02 23:40:59 +00001091 else VG_NUM_CLO (arg, "--max-stackframe", VG_(clo_max_stackframe))
njn45270a22005-03-27 01:00:11 +00001092 else VG_BOOL_CLO(arg, "--profile", VG_(clo_profile))
1093 else VG_BOOL_CLO(arg, "--run-libc-freeres", VG_(clo_run_libc_freeres))
1094 else VG_BOOL_CLO(arg, "--show-below-main", VG_(clo_show_below_main))
1095 else VG_BOOL_CLO(arg, "--time-stamp", VG_(clo_time_stamp))
1096 else VG_BOOL_CLO(arg, "--track-fds", VG_(clo_track_fds))
1097 else VG_BOOL_CLO(arg, "--trace-children", VG_(clo_trace_children))
1098 else VG_BOOL_CLO(arg, "--trace-sched", VG_(clo_trace_sched))
1099 else VG_BOOL_CLO(arg, "--trace-signals", VG_(clo_trace_signals))
1100 else VG_BOOL_CLO(arg, "--trace-symtab", VG_(clo_trace_symtab))
sewardjce058b02005-05-01 08:55:38 +00001101 else VG_BOOL_CLO(arg, "--trace-cfi", VG_(clo_trace_cfi))
njn45270a22005-03-27 01:00:11 +00001102 else VG_BOOL_CLO(arg, "--trace-redir", VG_(clo_trace_redir))
1103 else VG_BOOL_CLO(arg, "--trace-syscalls", VG_(clo_trace_syscalls))
1104 else VG_BOOL_CLO(arg, "--trace-pthreads", VG_(clo_trace_pthreads))
1105 else VG_BOOL_CLO(arg, "--wait-for-gdb", VG_(clo_wait_for_gdb))
1106 else VG_BOOL_CLO(arg, "--model-pthreads", VG_(clo_model_pthreads))
sewardj72f98ff2002-06-13 17:23:38 +00001107
njn45270a22005-03-27 01:00:11 +00001108 else VG_STR_CLO (arg, "--db-command", VG_(clo_db_command))
njn628add62005-11-12 18:21:40 +00001109 else VG_STR_CLO (arg, "--sim-hints", VG_(clo_sim_hints))
sewardjde4a1d02002-03-22 01:27:54 +00001110
njn45270a22005-03-27 01:00:11 +00001111 else VG_NUM_CLO (arg, "--dump-error", VG_(clo_dump_error))
1112 else VG_NUM_CLO (arg, "--input-fd", VG_(clo_input_fd))
1113 else VG_NUM_CLO (arg, "--sanity-level", VG_(clo_sanity_level))
1114 else VG_BNUM_CLO(arg, "--num-callers", VG_(clo_backtrace_size), 1,
1115 VG_DEEPEST_BACKTRACE)
sewardjde4a1d02002-03-22 01:27:54 +00001116
sewardj6c3a2192005-07-24 07:00:45 +00001117 else if (VG_CLO_STREQ(arg, "--smc-check=none"))
1118 VG_(clo_smc_check) = Vg_SmcNone;
1119 else if (VG_CLO_STREQ(arg, "--smc-check=stack"))
1120 VG_(clo_smc_check) = Vg_SmcStack;
1121 else if (VG_CLO_STREQ(arg, "--smc-check=all"))
1122 VG_(clo_smc_check) = Vg_SmcAll;
sewardj26412bd2005-07-07 10:05:05 +00001123
sewardjce5a5662005-10-06 03:19:49 +00001124 else VG_STR_CLO (arg, "--kernel-variant", VG_(clo_kernel_variant))
1125
njn45270a22005-03-27 01:00:11 +00001126 else VG_BNUM_CLO(arg, "--vex-iropt-verbosity",
sewardj8b635a42004-11-22 19:01:47 +00001127 VG_(clo_vex_control).iropt_verbosity, 0, 10)
njn45270a22005-03-27 01:00:11 +00001128 else VG_BNUM_CLO(arg, "--vex-iropt-level",
sewardj8b635a42004-11-22 19:01:47 +00001129 VG_(clo_vex_control).iropt_level, 0, 2)
njn45270a22005-03-27 01:00:11 +00001130 else VG_BOOL_CLO(arg, "--vex-iropt-precise-memory-exns",
sewardj8b635a42004-11-22 19:01:47 +00001131 VG_(clo_vex_control).iropt_precise_memory_exns)
njn45270a22005-03-27 01:00:11 +00001132 else VG_BNUM_CLO(arg, "--vex-iropt-unroll-thresh",
sewardj8b635a42004-11-22 19:01:47 +00001133 VG_(clo_vex_control).iropt_unroll_thresh, 0, 400)
njn45270a22005-03-27 01:00:11 +00001134 else VG_BNUM_CLO(arg, "--vex-guest-max-insns",
sewardj8b635a42004-11-22 19:01:47 +00001135 VG_(clo_vex_control).guest_max_insns, 1, 100)
njn45270a22005-03-27 01:00:11 +00001136 else VG_BNUM_CLO(arg, "--vex-guest-chase-thresh",
sewardj8b635a42004-11-22 19:01:47 +00001137 VG_(clo_vex_control).guest_chase_thresh, 0, 99)
1138
nethercotef8548672004-06-21 12:42:35 +00001139 else if (VG_CLO_STREQN(9, arg, "--log-fd=")) {
njnbe9b47b2005-05-15 16:22:58 +00001140 log_to = VgLogTo_Fd;
nethercotef8548672004-06-21 12:42:35 +00001141 VG_(clo_log_name) = NULL;
1142 eventually_log_fd = (Int)VG_(atoll)(&arg[9]);
sewardj4cf05692002-10-27 20:28:29 +00001143 }
1144
nethercotef8548672004-06-21 12:42:35 +00001145 else if (VG_CLO_STREQN(11, arg, "--log-file=")) {
njnbe9b47b2005-05-15 16:22:58 +00001146 log_to = VgLogTo_File;
nethercotef8548672004-06-21 12:42:35 +00001147 VG_(clo_log_name) = &arg[11];
sewardj4cf05692002-10-27 20:28:29 +00001148 }
njnd6bc3c32005-03-27 00:44:31 +00001149
sewardjad311162005-07-19 11:25:02 +00001150 else if (VG_CLO_STREQN(21, arg, "--log-file-qualifier=")) {
1151 VG_(clo_log_file_qualifier) = &arg[21];
1152 }
1153
sewardj603d4102005-01-11 14:01:02 +00001154 else if (VG_CLO_STREQN(19, arg, "--log-file-exactly=")) {
njnbe9b47b2005-05-15 16:22:58 +00001155 log_to = VgLogTo_FileExactly;
sewardj603d4102005-01-11 14:01:02 +00001156 VG_(clo_log_name) = &arg[19];
1157 }
sewardjde4a1d02002-03-22 01:27:54 +00001158
nethercotef8548672004-06-21 12:42:35 +00001159 else if (VG_CLO_STREQN(13, arg, "--log-socket=")) {
njnbe9b47b2005-05-15 16:22:58 +00001160 log_to = VgLogTo_Socket;
nethercotef8548672004-06-21 12:42:35 +00001161 VG_(clo_log_name) = &arg[13];
sewardj73cf3bc2002-11-03 03:20:15 +00001162 }
1163
sewardj768db0e2005-07-19 14:18:56 +00001164 else if (VG_CLO_STREQN(19, arg, "--xml-user-comment=")) {
1165 VG_(clo_xml_user_comment) = &arg[19];
1166 }
1167
nethercote71980f02004-01-24 18:18:54 +00001168 else if (VG_CLO_STREQN(15, arg, "--suppressions=")) {
sewardjde4a1d02002-03-22 01:27:54 +00001169 if (VG_(clo_n_suppressions) >= VG_CLO_MAX_SFILES) {
njn25e49d8e72002-09-23 09:36:25 +00001170 VG_(message)(Vg_UserMsg, "Too many suppression files specified.");
sewardjde4a1d02002-03-22 01:27:54 +00001171 VG_(message)(Vg_UserMsg,
1172 "Increase VG_CLO_MAX_SFILES and recompile.");
nethercote71980f02004-01-24 18:18:54 +00001173 VG_(bad_option)(arg);
sewardjde4a1d02002-03-22 01:27:54 +00001174 }
nethercote71980f02004-01-24 18:18:54 +00001175 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = &arg[15];
sewardjde4a1d02002-03-22 01:27:54 +00001176 VG_(clo_n_suppressions)++;
1177 }
sewardjde4a1d02002-03-22 01:27:54 +00001178
sewardjfa8ec112005-01-19 11:55:34 +00001179 /* "stuvwxyz" --> stuvwxyz (binary) */
1180 else if (VG_CLO_STREQN(14, arg, "--trace-flags=")) {
1181 Int j;
1182 char* opt = & arg[14];
1183
1184 if (8 != VG_(strlen)(opt)) {
1185 VG_(message)(Vg_UserMsg,
1186 "--trace-flags argument must have 8 digits");
1187 VG_(bad_option)(arg);
1188 }
1189 for (j = 0; j < 8; j++) {
1190 if ('0' == opt[j]) { /* do nothing */ }
1191 else if ('1' == opt[j]) VG_(clo_trace_flags) |= (1 << (7-j));
1192 else {
1193 VG_(message)(Vg_UserMsg, "--trace-flags argument can only "
1194 "contain 0s and 1s");
1195 VG_(bad_option)(arg);
1196 }
1197 }
1198 }
1199
1200 /* "stuvwxyz" --> stuvwxyz (binary) */
1201 else if (VG_CLO_STREQN(16, arg, "--profile-flags=")) {
njn25e49d8e72002-09-23 09:36:25 +00001202 Int j;
nethercote71980f02004-01-24 18:18:54 +00001203 char* opt = & arg[16];
njn25e49d8e72002-09-23 09:36:25 +00001204
sewardj2a99cf62004-11-24 10:44:19 +00001205 if (8 != VG_(strlen)(opt)) {
njn25e49d8e72002-09-23 09:36:25 +00001206 VG_(message)(Vg_UserMsg,
sewardjfa8ec112005-01-19 11:55:34 +00001207 "--profile-flags argument must have 8 digits");
nethercote71980f02004-01-24 18:18:54 +00001208 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001209 }
sewardj8b635a42004-11-22 19:01:47 +00001210 for (j = 0; j < 8; j++) {
njn25e49d8e72002-09-23 09:36:25 +00001211 if ('0' == opt[j]) { /* do nothing */ }
sewardjfa8ec112005-01-19 11:55:34 +00001212 else if ('1' == opt[j]) VG_(clo_profile_flags) |= (1 << (7-j));
njn25e49d8e72002-09-23 09:36:25 +00001213 else {
sewardjfa8ec112005-01-19 11:55:34 +00001214 VG_(message)(Vg_UserMsg, "--profile-flags argument can only "
njn25e49d8e72002-09-23 09:36:25 +00001215 "contain 0s and 1s");
nethercote71980f02004-01-24 18:18:54 +00001216 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001217 }
1218 }
1219 }
sewardjde4a1d02002-03-22 01:27:54 +00001220
njn45270a22005-03-27 01:00:11 +00001221 else VG_NUM_CLO (arg, "--trace-notbelow", VG_(clo_trace_notbelow))
sewardjc771b292004-11-30 18:55:21 +00001222
sewardjd153fae2005-01-10 17:24:47 +00001223 else if (VG_CLO_STREQ(arg, "--gen-suppressions=no"))
1224 VG_(clo_gen_suppressions) = 0;
1225 else if (VG_CLO_STREQ(arg, "--gen-suppressions=yes"))
1226 VG_(clo_gen_suppressions) = 1;
1227 else if (VG_CLO_STREQ(arg, "--gen-suppressions=all"))
1228 VG_(clo_gen_suppressions) = 2;
1229
nethercote71980f02004-01-24 18:18:54 +00001230 else if ( ! VG_(needs).command_line_options
njn51d827b2005-05-09 01:02:08 +00001231 || ! VG_TDICT_CALL(tool_process_cmd_line_option, arg) ) {
nethercotef4928da2004-06-15 10:54:40 +00001232 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001233 }
njn8c0b3bb2005-03-12 21:20:39 +00001234 skip_arg:
sewardj45f4e7c2005-09-27 19:20:21 +00001235 if (arg != VG_(args_for_valgrind).strs[i]) {
1236 VG_(free)(arg);
1237 }
sewardjde4a1d02002-03-22 01:27:54 +00001238 }
1239
sewardj998d40d2004-12-06 14:24:52 +00001240 /* Make VEX control parameters sane */
1241
1242 if (VG_(clo_vex_control).guest_chase_thresh
1243 >= VG_(clo_vex_control).guest_max_insns)
1244 VG_(clo_vex_control).guest_chase_thresh
1245 = VG_(clo_vex_control).guest_max_insns - 1;
1246
1247 if (VG_(clo_vex_control).guest_chase_thresh < 0)
1248 VG_(clo_vex_control).guest_chase_thresh = 0;
1249
1250 /* Check various option values */
nethercote27fec902004-06-16 21:26:32 +00001251
njnf9ebf672003-05-12 21:41:30 +00001252 if (VG_(clo_verbosity) < 0)
sewardjde4a1d02002-03-22 01:27:54 +00001253 VG_(clo_verbosity) = 0;
1254
nethercote04d0fbc2004-01-26 16:48:06 +00001255 if (VG_(clo_db_attach) && VG_(clo_trace_children)) {
sewardjde4a1d02002-03-22 01:27:54 +00001256 VG_(message)(Vg_UserMsg, "");
1257 VG_(message)(Vg_UserMsg,
nethercote04d0fbc2004-01-26 16:48:06 +00001258 "--db-attach=yes conflicts with --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001259 VG_(message)(Vg_UserMsg,
1260 "Please choose one or the other, but not both.");
nethercote04d0fbc2004-01-26 16:48:06 +00001261 VG_(bad_option)("--db-attach=yes and --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001262 }
1263
njnbe9b47b2005-05-15 16:22:58 +00001264 if (VG_(clo_gen_suppressions) > 0 &&
1265 !VG_(needs).core_errors && !VG_(needs).tool_errors) {
1266 VG_(message)(Vg_UserMsg,
1267 "Can't use --gen-suppressions= with this tool,");
1268 VG_(message)(Vg_UserMsg,
1269 "as it doesn't generate errors.");
1270 VG_(bad_option)("--gen-suppressions=");
1271 }
1272
sewardj71bc3cb2005-05-19 00:25:45 +00001273 /* If we've been asked to emit XML, mash around various other
1274 options so as to constrain the output somewhat, and to remove
1275 any need for user input during the run. */
1276 if (VG_(clo_xml)) {
1277 /* Disable suppression generation (requires user input) */
1278 VG_(clo_gen_suppressions) = 0;
1279 /* Disable attaching to GDB (requires user input) */
1280 VG_(clo_db_attach) = False;
1281 /* Set a known verbosity level */
1282 VG_(clo_verbosity) = 1;
1283 /* Disable error limits (this might be a bad idea!) */
1284 VG_(clo_error_limit) = False;
1285 /* Disable emulation warnings */
1286 VG_(clo_show_emwarns) = False;
1287 /* Disable waiting for GDB to debug Valgrind */
1288 VG_(clo_wait_for_gdb) = False;
1289 /* No file-descriptor leak checking yet */
1290 VG_(clo_track_fds) = False;
sewardj21f7f0c2005-07-06 19:46:48 +00001291 /* Disable timestamped output */
1292 VG_(clo_time_stamp) = False;
sewardj71bc3cb2005-05-19 00:25:45 +00001293 /* Also, we want to set options for the leak checker, but that
1294 will have to be done in Memcheck's flag-handling code, not
1295 here. */
1296 }
1297
njnbe9b47b2005-05-15 16:22:58 +00001298 /* All non-logging-related options have been checked. If the logging
1299 option specified is ok, we can switch to it, as we know we won't
1300 have to generate any other command-line-related error messages.
1301 (So far we should be still attached to stderr, so we can show on
1302 the terminal any problems to do with processing command line
1303 opts.)
1304
1305 So set up logging now. After this is done, VG_(clo_log_fd)
sewardj4cf05692002-10-27 20:28:29 +00001306 should be connected to whatever sink has been selected, and we
1307 indiscriminately chuck stuff into it without worrying what the
1308 nature of it is. Oh the wonder of Unix streams. */
1309
njnbe9b47b2005-05-15 16:22:58 +00001310 vg_assert(VG_(clo_log_fd) == 2 /* stderr */);
1311 vg_assert(VG_(logging_to_socket) == False);
sewardj4cf05692002-10-27 20:28:29 +00001312
njnbe9b47b2005-05-15 16:22:58 +00001313 switch (log_to) {
sewardj73cf3bc2002-11-03 03:20:15 +00001314
sewardj4cf05692002-10-27 20:28:29 +00001315 case VgLogTo_Fd:
nethercotef8548672004-06-21 12:42:35 +00001316 vg_assert(VG_(clo_log_name) == NULL);
1317 VG_(clo_log_fd) = eventually_log_fd;
sewardj4cf05692002-10-27 20:28:29 +00001318 break;
sewardj73cf3bc2002-11-03 03:20:15 +00001319
sewardj4cf05692002-10-27 20:28:29 +00001320 case VgLogTo_File: {
sewardjad311162005-07-19 11:25:02 +00001321 HChar logfilename[1000];
1322 Int seq = 0;
1323 Int pid = VG_(getpid)();
1324 HChar* qual = NULL;
jsgff3c3f1a2003-10-14 22:13:28 +00001325
nethercotef8548672004-06-21 12:42:35 +00001326 vg_assert(VG_(clo_log_name) != NULL);
1327 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
jsgff3c3f1a2003-10-14 22:13:28 +00001328
sewardjad311162005-07-19 11:25:02 +00001329 if (VG_(clo_log_file_qualifier)) {
1330 qual = VG_(getenv)(VG_(clo_log_file_qualifier));
1331 }
1332
nethercote71980f02004-01-24 18:18:54 +00001333 for (;;) {
sewardj92645592005-07-23 09:18:34 +00001334 HChar pidtxt[20], seqtxt[20];
1335
1336 VG_(sprintf)(pidtxt, "%d", pid);
1337
1338 if (seq == 0)
1339 seqtxt[0] = 0;
1340 else
1341 VG_(sprintf)(seqtxt, ".%d", seq);
1342
jsgff3c3f1a2003-10-14 22:13:28 +00001343 seq++;
1344
sewardj92645592005-07-23 09:18:34 +00001345 /* Result:
1346 if (qual) base_name ++ "." ++ qual ++ seqtxt
1347 if (not qual) base_name ++ "." ++ pid ++ seqtxt
1348 */
1349 VG_(sprintf)( logfilename,
1350 "%s.%s%s",
1351 VG_(clo_log_name),
1352 qual ? qual : pidtxt,
1353 seqtxt );
1354
njnbe9b47b2005-05-15 16:22:58 +00001355 // EXCL: it will fail with EEXIST if the file already exists.
sewardj92645592005-07-23 09:18:34 +00001356 sres
jsgff3c3f1a2003-10-14 22:13:28 +00001357 = VG_(open)(logfilename,
1358 VKI_O_CREAT|VKI_O_WRONLY|VKI_O_EXCL|VKI_O_TRUNC,
1359 VKI_S_IRUSR|VKI_S_IWUSR);
sewardj92645592005-07-23 09:18:34 +00001360 if (!sres.isError) {
1361 eventually_log_fd = sres.val;
nethercotef8548672004-06-21 12:42:35 +00001362 VG_(clo_log_fd) = VG_(safe_fd)(eventually_log_fd);
sewardj603d4102005-01-11 14:01:02 +00001363 break; /* for (;;) */
jsgff3c3f1a2003-10-14 22:13:28 +00001364 } else {
njnbe9b47b2005-05-15 16:22:58 +00001365 // If the file already existed, we try the next name. If it
1366 // was some other file error, we give up.
sewardj92645592005-07-23 09:18:34 +00001367 if (sres.val != VKI_EEXIST) {
jsgff3c3f1a2003-10-14 22:13:28 +00001368 VG_(message)(Vg_UserMsg,
tombbe14b12005-11-04 16:49:39 +00001369 "Can't create/open log file '%s.%d'; giving up!",
nethercotef8548672004-06-21 12:42:35 +00001370 VG_(clo_log_name), pid);
jsgff3c3f1a2003-10-14 22:13:28 +00001371 VG_(bad_option)(
sewardj603d4102005-01-11 14:01:02 +00001372 "--log-file=<file> (didn't work out for some reason.)");
njnbe9b47b2005-05-15 16:22:58 +00001373 /*NOTREACHED*/
jsgff3c3f1a2003-10-14 22:13:28 +00001374 }
1375 }
1376 }
sewardj603d4102005-01-11 14:01:02 +00001377 break; /* switch (VG_(clo_log_to)) */
1378 }
1379
1380 case VgLogTo_FileExactly: {
sewardj603d4102005-01-11 14:01:02 +00001381 vg_assert(VG_(clo_log_name) != NULL);
1382 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
sewardj603d4102005-01-11 14:01:02 +00001383
sewardj92645592005-07-23 09:18:34 +00001384 sres
njnbe9b47b2005-05-15 16:22:58 +00001385 = VG_(open)(VG_(clo_log_name),
sewardj603d4102005-01-11 14:01:02 +00001386 VKI_O_CREAT|VKI_O_WRONLY|VKI_O_TRUNC,
1387 VKI_S_IRUSR|VKI_S_IWUSR);
sewardj92645592005-07-23 09:18:34 +00001388 if (!sres.isError) {
1389 eventually_log_fd = sres.val;
sewardj603d4102005-01-11 14:01:02 +00001390 VG_(clo_log_fd) = VG_(safe_fd)(eventually_log_fd);
njnbe9b47b2005-05-15 16:22:58 +00001391 } else {
sewardj603d4102005-01-11 14:01:02 +00001392 VG_(message)(Vg_UserMsg,
njn02bc4b82005-05-15 17:28:26 +00001393 "Can't create/open log file '%s'; giving up!",
sewardj603d4102005-01-11 14:01:02 +00001394 VG_(clo_log_name));
1395 VG_(bad_option)(
1396 "--log-file-exactly=<file> (didn't work out for some reason.)");
1397 /*NOTREACHED*/
1398 }
1399 break; /* switch (VG_(clo_log_to)) */
sewardj73cf3bc2002-11-03 03:20:15 +00001400 }
1401
1402 case VgLogTo_Socket: {
nethercotef8548672004-06-21 12:42:35 +00001403 vg_assert(VG_(clo_log_name) != NULL);
1404 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
1405 eventually_log_fd = VG_(connect_via_socket)( VG_(clo_log_name) );
1406 if (eventually_log_fd == -1) {
sewardj73cf3bc2002-11-03 03:20:15 +00001407 VG_(message)(Vg_UserMsg,
nethercotef8548672004-06-21 12:42:35 +00001408 "Invalid --log-socket=ipaddr or --log-socket=ipaddr:port spec");
sewardj73cf3bc2002-11-03 03:20:15 +00001409 VG_(message)(Vg_UserMsg,
njn02bc4b82005-05-15 17:28:26 +00001410 "of '%s'; giving up!", VG_(clo_log_name) );
sewardj73cf3bc2002-11-03 03:20:15 +00001411 VG_(bad_option)(
nethercotef8548672004-06-21 12:42:35 +00001412 "--log-socket=");
njnbe9b47b2005-05-15 16:22:58 +00001413 /*NOTREACHED*/
sewardj4cf05692002-10-27 20:28:29 +00001414 }
nethercotef8548672004-06-21 12:42:35 +00001415 if (eventually_log_fd == -2) {
sewardj73cf3bc2002-11-03 03:20:15 +00001416 VG_(message)(Vg_UserMsg,
njn02bc4b82005-05-15 17:28:26 +00001417 "valgrind: failed to connect to logging server '%s'.",
nethercotef8548672004-06-21 12:42:35 +00001418 VG_(clo_log_name) );
sewardj570f8902002-11-03 11:44:36 +00001419 VG_(message)(Vg_UserMsg,
1420 "Log messages will sent to stderr instead." );
1421 VG_(message)(Vg_UserMsg,
1422 "" );
1423 /* We don't change anything here. */
njnbe9b47b2005-05-15 16:22:58 +00001424 vg_assert(VG_(clo_log_fd) == 2);
sewardj570f8902002-11-03 11:44:36 +00001425 } else {
nethercotef8548672004-06-21 12:42:35 +00001426 vg_assert(eventually_log_fd > 0);
1427 VG_(clo_log_fd) = eventually_log_fd;
njnbe9b47b2005-05-15 16:22:58 +00001428 VG_(logging_to_socket) = True;
sewardj570f8902002-11-03 11:44:36 +00001429 }
sewardj73cf3bc2002-11-03 03:20:15 +00001430 break;
1431 }
sewardj4cf05692002-10-27 20:28:29 +00001432 }
1433
sewardj71bc3cb2005-05-19 00:25:45 +00001434
1435 /* Check that the requested tool actually supports XML output. */
sewardj45f4e7c2005-09-27 19:20:21 +00001436 if (VG_(clo_xml) && !VG_STREQ(toolname, "memcheck")
1437 && !VG_STREQ(toolname, "none")) {
sewardj71bc3cb2005-05-19 00:25:45 +00001438 VG_(clo_xml) = False;
1439 VG_(message)(Vg_UserMsg,
cerion39655202005-07-13 14:18:24 +00001440 "Currently only Memcheck|None supports XML output.");
sewardj71bc3cb2005-05-19 00:25:45 +00001441 VG_(bad_option)("--xml=yes");
1442 /*NOTREACHED*/
1443 }
1444
njnbe9b47b2005-05-15 16:22:58 +00001445 // Move log_fd into the safe range, so it doesn't conflict with any app fds.
1446 // XXX: this is more or less duplicating the behaviour of the calls to
1447 // VG_(safe_fd)() above, although this does not close the original fd.
1448 // Perhaps the VG_(safe_fd)() calls above should be removed, and this
1449 // code should be replaced with a call to VG_(safe_fd)(). --njn
thughesad1c9562004-06-26 11:27:52 +00001450 eventually_log_fd = VG_(fcntl)(VG_(clo_log_fd), VKI_F_DUPFD, VG_(fd_hard_limit));
nethercotef8548672004-06-21 12:42:35 +00001451 if (eventually_log_fd < 0)
jsgf855d93d2003-10-13 22:26:55 +00001452 VG_(message)(Vg_UserMsg, "valgrind: failed to move logfile fd into safe range");
1453 else {
nethercotef8548672004-06-21 12:42:35 +00001454 VG_(clo_log_fd) = eventually_log_fd;
1455 VG_(fcntl)(VG_(clo_log_fd), VKI_F_SETFD, VKI_FD_CLOEXEC);
jsgf855d93d2003-10-13 22:26:55 +00001456 }
1457
sewardj45f4e7c2005-09-27 19:20:21 +00001458 if (VG_(clo_n_suppressions) < VG_CLO_MAX_SFILES-1 &&
1459 (VG_(needs).core_errors || VG_(needs).tool_errors)) {
1460 /* If we haven't reached the max number of suppressions, load
1461 the default one. */
1462 static const Char default_supp[] = "default.supp";
1463 Int len = VG_(strlen)(VG_(libdir)) + 1 + sizeof(default_supp);
1464 Char *buf = VG_(arena_malloc)(VG_AR_CORE, len);
1465 VG_(sprintf)(buf, "%s/%s", VG_(libdir), default_supp);
1466 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = buf;
1467 VG_(clo_n_suppressions)++;
1468 }
sewardjde4a1d02002-03-22 01:27:54 +00001469
sewardj45f4e7c2005-09-27 19:20:21 +00001470 return (log_to == VgLogTo_Fd);
1471}
1472
1473
1474/*====================================================================*/
1475/*=== Printing the preamble ===*/
1476/*====================================================================*/
1477
1478/* Ok, the logging sink is running now. Print a suitable preamble.
1479 If logging to file or a socket, write details of parent PID and
1480 command line args, to help people trying to interpret the
1481 results of a run which encompasses multiple processes. */
1482static void print_preamble(Bool logging_to_fd, const char* toolname)
1483{
tom60a4b0b2005-10-12 10:45:27 +00001484 HChar* xpre = VG_(clo_xml) ? " <line>" : "";
1485 HChar* xpost = VG_(clo_xml) ? "</line>" : "";
1486 Int i;
1487
sewardj71bc3cb2005-05-19 00:25:45 +00001488 if (VG_(clo_xml)) {
sewardj8665d8e2005-06-01 17:35:23 +00001489 VG_(message)(Vg_UserMsg, "<?xml version=\"1.0\"?>");
1490 VG_(message)(Vg_UserMsg, "");
sewardj71bc3cb2005-05-19 00:25:45 +00001491 VG_(message)(Vg_UserMsg, "<valgrindoutput>");
1492 VG_(message)(Vg_UserMsg, "");
cerion20241ba2005-11-15 19:07:53 +00001493 VG_(message)(Vg_UserMsg, "<protocolversion>2</protocolversion>");
sewardj71bc3cb2005-05-19 00:25:45 +00001494 VG_(message)(Vg_UserMsg, "");
1495 }
1496
sewardj83adf412002-05-01 01:25:45 +00001497 if (VG_(clo_verbosity > 0)) {
sewardjd7bddad2005-06-13 16:48:32 +00001498
1499 if (VG_(clo_xml))
1500 VG_(message)(Vg_UserMsg, "<preamble>");
1501
nethercote996901a2004-08-03 13:29:09 +00001502 /* Tool details */
sewardj71bc3cb2005-05-19 00:25:45 +00001503 VG_(message)(Vg_UserMsg, "%s%s%s%s, %s.%s",
1504 xpre,
njnd04b7c62002-10-03 14:05:52 +00001505 VG_(details).name,
njnb9c427c2004-12-01 14:14:42 +00001506 NULL == VG_(details).version ? "" : "-",
njnd04b7c62002-10-03 14:05:52 +00001507 NULL == VG_(details).version
1508 ? (Char*)"" : VG_(details).version,
sewardj71bc3cb2005-05-19 00:25:45 +00001509 VG_(details).description,
1510 xpost);
1511 VG_(message)(Vg_UserMsg, "%s%s%s",
1512 xpre, VG_(details).copyright_author, xpost);
sewardj3b2736a2002-03-24 12:18:35 +00001513
njnd04b7c62002-10-03 14:05:52 +00001514 /* Core details */
1515 VG_(message)(Vg_UserMsg,
sewardj71bc3cb2005-05-19 00:25:45 +00001516 "%sUsing LibVEX rev %s, a library for dynamic binary translation.%s",
1517 xpre, LibVEX_Version(), xpost );
sewardjc7025332004-12-13 18:30:39 +00001518 VG_(message)(Vg_UserMsg,
sewardj71bc3cb2005-05-19 00:25:45 +00001519 "%sCopyright (C) 2004-2005, and GNU GPL'd, by OpenWorks LLP.%s",
1520 xpre, xpost );
sewardjc7025332004-12-13 18:30:39 +00001521 VG_(message)(Vg_UserMsg,
sewardj71bc3cb2005-05-19 00:25:45 +00001522 "%sUsing valgrind-%s, a dynamic binary instrumentation framework.%s",
1523 xpre, VERSION, xpost);
sewardjde4a1d02002-03-22 01:27:54 +00001524 VG_(message)(Vg_UserMsg,
sewardj71bc3cb2005-05-19 00:25:45 +00001525 "%sCopyright (C) 2000-2005, and GNU GPL'd, by Julian Seward et al.%s",
1526 xpre, xpost );
sewardjd7bddad2005-06-13 16:48:32 +00001527
sewardj45f4e7c2005-09-27 19:20:21 +00001528 if (VG_(clo_verbosity) == 1 && !VG_(clo_xml))
1529 VG_(message)(Vg_UserMsg, "For more details, rerun with: -v");
1530
sewardjd7bddad2005-06-13 16:48:32 +00001531 if (VG_(clo_xml))
1532 VG_(message)(Vg_UserMsg, "</preamble>");
njnd04b7c62002-10-03 14:05:52 +00001533 }
1534
sewardj45f4e7c2005-09-27 19:20:21 +00001535 if (!VG_(clo_xml) && VG_(clo_verbosity) > 0 && !logging_to_fd) {
sewardj4cf05692002-10-27 20:28:29 +00001536 VG_(message)(Vg_UserMsg, "");
1537 VG_(message)(Vg_UserMsg,
1538 "My PID = %d, parent PID = %d. Prog and args are:",
1539 VG_(getpid)(), VG_(getppid)() );
sewardj5e940782005-09-28 19:59:19 +00001540 if (VG_(args_the_exename))
1541 VG_(message)(Vg_UserMsg, " %s", VG_(args_the_exename));
sewardj45f4e7c2005-09-27 19:20:21 +00001542 for (i = 0; i < VG_(args_for_client).used; i++)
1543 VG_(message)(Vg_UserMsg, " %s", VG_(args_for_client).strs[i]);
sewardj5b742c32005-07-26 23:43:26 +00001544 if (VG_(clo_log_file_qualifier)) {
1545 HChar* val = VG_(getenv)(VG_(clo_log_file_qualifier));
1546 VG_(message)(Vg_UserMsg, "");
1547 VG_(message)(Vg_UserMsg, "Log file qualifier: var %s, value %s.",
1548 VG_(clo_log_file_qualifier),
1549 val ? val : "");
1550 }
sewardj4cf05692002-10-27 20:28:29 +00001551 }
sewardj71bc3cb2005-05-19 00:25:45 +00001552 else
1553 if (VG_(clo_xml)) {
1554 VG_(message)(Vg_UserMsg, "");
1555 VG_(message)(Vg_UserMsg, "<pid>%d</pid>", VG_(getpid)());
1556 VG_(message)(Vg_UserMsg, "<ppid>%d</ppid>", VG_(getppid)());
sewardj97f7e0c2005-07-19 15:00:25 +00001557 VG_(message)(Vg_UserMsg, "<tool>%t</tool>", toolname);
sewardjad311162005-07-19 11:25:02 +00001558 if (VG_(clo_log_file_qualifier)) {
1559 HChar* val = VG_(getenv)(VG_(clo_log_file_qualifier));
sewardj97f7e0c2005-07-19 15:00:25 +00001560 VG_(message)(Vg_UserMsg, "<logfilequalifier> <var>%t</var> "
1561 "<value>%t</value> </logfilequalifier>",
sewardjad311162005-07-19 11:25:02 +00001562 VG_(clo_log_file_qualifier),
1563 val ? val : "");
1564 }
sewardj768db0e2005-07-19 14:18:56 +00001565 if (VG_(clo_xml_user_comment)) {
1566 /* Note: the user comment itself is XML and is therefore to
1567 be passed through verbatim (%s) rather than escaped
1568 (%t). */
1569 VG_(message)(Vg_UserMsg, "<usercomment>%s</usercomment>",
1570 VG_(clo_xml_user_comment));
1571 }
sewardj71bc3cb2005-05-19 00:25:45 +00001572 VG_(message)(Vg_UserMsg, "");
sewardjb8a3dac2005-07-19 12:39:11 +00001573 VG_(message)(Vg_UserMsg, "<args>");
sewardj45f4e7c2005-09-27 19:20:21 +00001574
sewardjb8a3dac2005-07-19 12:39:11 +00001575 VG_(message)(Vg_UserMsg, " <vargv>");
sewardj45f4e7c2005-09-27 19:20:21 +00001576 if (VG_(name_of_launcher))
1577 VG_(message)(Vg_UserMsg, " <exe>%t</exe>",
1578 VG_(name_of_launcher));
1579 for (i = 0; i < VG_(args_for_valgrind).used; i++) {
1580 VG_(message)(Vg_UserMsg,
1581 " <arg>%t</arg>",
1582 VG_(args_for_valgrind).strs[i]);
sewardjb8a3dac2005-07-19 12:39:11 +00001583 }
1584 VG_(message)(Vg_UserMsg, " </vargv>");
sewardj45f4e7c2005-09-27 19:20:21 +00001585
sewardjb8a3dac2005-07-19 12:39:11 +00001586 VG_(message)(Vg_UserMsg, " <argv>");
sewardj45f4e7c2005-09-27 19:20:21 +00001587 if (VG_(args_the_exename))
1588 VG_(message)(Vg_UserMsg, " <exe>%t</exe>",
1589 VG_(args_the_exename));
1590 for (i = 0; i < VG_(args_for_client).used; i++) {
1591 VG_(message)(Vg_UserMsg, " <arg>%t</arg>",
1592 VG_(args_for_client).strs[i]);
sewardj8665d8e2005-06-01 17:35:23 +00001593 }
sewardjb8a3dac2005-07-19 12:39:11 +00001594 VG_(message)(Vg_UserMsg, " </argv>");
sewardj45f4e7c2005-09-27 19:20:21 +00001595
sewardjb8a3dac2005-07-19 12:39:11 +00001596 VG_(message)(Vg_UserMsg, "</args>");
sewardj71bc3cb2005-05-19 00:25:45 +00001597 }
sewardj4cf05692002-10-27 20:28:29 +00001598
sewardj45f4e7c2005-09-27 19:20:21 +00001599 // Empty line after the preamble
1600 if (VG_(clo_verbosity) > 0)
1601 VG_(message)(Vg_UserMsg, "");
1602
sewardjde4a1d02002-03-22 01:27:54 +00001603 if (VG_(clo_verbosity) > 1) {
sewardj92645592005-07-23 09:18:34 +00001604 SysRes fd;
sewardj1f0bbc72005-11-16 03:51:02 +00001605 VexArch vex_arch;
1606 VexArchInfo vex_archinfo;
sewardj45f4e7c2005-09-27 19:20:21 +00001607 if (!logging_to_fd)
njn1fd5eb22005-03-13 05:43:23 +00001608 VG_(message)(Vg_DebugMsg, "");
njn1fd5eb22005-03-13 05:43:23 +00001609 VG_(message)(Vg_DebugMsg, "Command line");
sewardj45f4e7c2005-09-27 19:20:21 +00001610 if (VG_(args_the_exename))
1611 VG_(message)(Vg_DebugMsg, " %s", VG_(args_the_exename));
1612 for (i = 0; i < VG_(args_for_client).used; i++)
1613 VG_(message)(Vg_DebugMsg, " %s", VG_(args_for_client).strs[i]);
njn86dc2bc2003-09-09 07:26:21 +00001614
njn1fd5eb22005-03-13 05:43:23 +00001615 VG_(message)(Vg_DebugMsg, "Startup, with flags:");
sewardj45f4e7c2005-09-27 19:20:21 +00001616 for (i = 0; i < VG_(args_for_valgrind).used; i++) {
1617 VG_(message)(Vg_DebugMsg, " %s", VG_(args_for_valgrind).strs[i]);
sewardjde4a1d02002-03-22 01:27:54 +00001618 }
nethercotea70f7352004-04-18 12:08:46 +00001619
njn1fd5eb22005-03-13 05:43:23 +00001620 VG_(message)(Vg_DebugMsg, "Contents of /proc/version:");
nethercotea70f7352004-04-18 12:08:46 +00001621 fd = VG_(open) ( "/proc/version", VKI_O_RDONLY, 0 );
sewardj92645592005-07-23 09:18:34 +00001622 if (fd.isError) {
njn1fd5eb22005-03-13 05:43:23 +00001623 VG_(message)(Vg_DebugMsg, " can't open /proc/version");
nethercotea70f7352004-04-18 12:08:46 +00001624 } else {
sewardj71bc3cb2005-05-19 00:25:45 +00001625# define BUF_LEN 256
nethercotea70f7352004-04-18 12:08:46 +00001626 Char version_buf[BUF_LEN];
sewardj92645592005-07-23 09:18:34 +00001627 Int n = VG_(read) ( fd.val, version_buf, BUF_LEN );
njnbe9b47b2005-05-15 16:22:58 +00001628 vg_assert(n <= BUF_LEN);
nethercotea70f7352004-04-18 12:08:46 +00001629 if (n > 0) {
1630 version_buf[n-1] = '\0';
njn1fd5eb22005-03-13 05:43:23 +00001631 VG_(message)(Vg_DebugMsg, " %s", version_buf);
nethercotea70f7352004-04-18 12:08:46 +00001632 } else {
njn1fd5eb22005-03-13 05:43:23 +00001633 VG_(message)(Vg_DebugMsg, " (empty?)");
nethercotea70f7352004-04-18 12:08:46 +00001634 }
sewardj92645592005-07-23 09:18:34 +00001635 VG_(close)(fd.val);
sewardj71bc3cb2005-05-19 00:25:45 +00001636# undef BUF_LEN
nethercotea70f7352004-04-18 12:08:46 +00001637 }
sewardj1f0bbc72005-11-16 03:51:02 +00001638
1639 VG_(machine_get_VexArchInfo)( &vex_arch, &vex_archinfo );
1640 VG_(message)(Vg_DebugMsg, "Arch and subarch: %s, %s",
1641 LibVEX_ppVexArch ( vex_arch ),
1642 LibVEX_ppVexSubArch( vex_archinfo.subarch ) );
1643 VG_(message)(Vg_DebugMsg, "Valgrind library directory: %s", VG_(libdir));
sewardjde4a1d02002-03-22 01:27:54 +00001644 }
nethercotef6a1d502004-08-09 12:21:57 +00001645}
1646
sewardjde4a1d02002-03-22 01:27:54 +00001647
nethercote71980f02004-01-24 18:18:54 +00001648/*====================================================================*/
1649/*=== File descriptor setup ===*/
1650/*====================================================================*/
1651
sewardj5f229e22005-09-28 01:36:01 +00001652/* Number of file descriptors that Valgrind tries to reserve for
1653 it's own use - just a small constant. */
1654#define N_RESERVED_FDS (10)
1655
nethercote71980f02004-01-24 18:18:54 +00001656static void setup_file_descriptors(void)
1657{
1658 struct vki_rlimit rl;
1659
1660 /* Get the current file descriptor limits. */
1661 if (VG_(getrlimit)(VKI_RLIMIT_NOFILE, &rl) < 0) {
1662 rl.rlim_cur = 1024;
1663 rl.rlim_max = 1024;
1664 }
1665
1666 /* Work out where to move the soft limit to. */
njn14319cc2005-03-13 06:26:22 +00001667 if (rl.rlim_cur + N_RESERVED_FDS <= rl.rlim_max) {
1668 rl.rlim_cur = rl.rlim_cur + N_RESERVED_FDS;
nethercote71980f02004-01-24 18:18:54 +00001669 } else {
1670 rl.rlim_cur = rl.rlim_max;
1671 }
1672
1673 /* Reserve some file descriptors for our use. */
njn14319cc2005-03-13 06:26:22 +00001674 VG_(fd_soft_limit) = rl.rlim_cur - N_RESERVED_FDS;
1675 VG_(fd_hard_limit) = rl.rlim_cur - N_RESERVED_FDS;
nethercote71980f02004-01-24 18:18:54 +00001676
1677 /* Update the soft limit. */
1678 VG_(setrlimit)(VKI_RLIMIT_NOFILE, &rl);
1679
sewardj45f4e7c2005-09-27 19:20:21 +00001680 if (VG_(cl_exec_fd) != -1)
1681 VG_(cl_exec_fd) = VG_(safe_fd)( VG_(cl_exec_fd) );
nethercote71980f02004-01-24 18:18:54 +00001682}
1683
sewardjde4a1d02002-03-22 01:27:54 +00001684
njn2da73352005-06-18 01:35:16 +00001685/*====================================================================*/
1686/*=== Initialise the first thread. ===*/
1687/*====================================================================*/
1688
1689/* Given a pointer to the ThreadArchState for thread 1 (the root
1690 thread), initialise the VEX guest state, and copy in essential
1691 starting values.
1692*/
1693static void init_thread1state ( Addr client_ip,
sewardjfdf91b42005-09-28 00:53:09 +00001694 Addr client_sp,
njn2da73352005-06-18 01:35:16 +00001695 /*inout*/ ThreadArchState* arch )
1696{
1697#if defined(VGA_x86)
1698 vg_assert(0 == sizeof(VexGuestX86State) % 8);
1699
1700 /* Zero out the initial state, and set up the simulated FPU in a
1701 sane way. */
1702 LibVEX_GuestX86_initialise(&arch->vex);
1703
1704 /* Zero out the shadow area. */
1705 VG_(memset)(&arch->vex_shadow, 0, sizeof(VexGuestX86State));
1706
1707 /* Put essential stuff into the new state. */
sewardjfdf91b42005-09-28 00:53:09 +00001708 arch->vex.guest_ESP = client_sp;
njn2da73352005-06-18 01:35:16 +00001709 arch->vex.guest_EIP = client_ip;
1710
1711 /* initialise %cs, %ds and %ss to point at the operating systems
1712 default code, data and stack segments */
1713 asm volatile("movw %%cs, %0" : : "m" (arch->vex.guest_CS));
1714 asm volatile("movw %%ds, %0" : : "m" (arch->vex.guest_DS));
1715 asm volatile("movw %%ss, %0" : : "m" (arch->vex.guest_SS));
cerion85665ca2005-06-20 15:51:07 +00001716
njn2da73352005-06-18 01:35:16 +00001717#elif defined(VGA_amd64)
1718 vg_assert(0 == sizeof(VexGuestAMD64State) % 8);
1719
1720 /* Zero out the initial state, and set up the simulated FPU in a
1721 sane way. */
1722 LibVEX_GuestAMD64_initialise(&arch->vex);
1723
1724 /* Zero out the shadow area. */
1725 VG_(memset)(&arch->vex_shadow, 0, sizeof(VexGuestAMD64State));
1726
1727 /* Put essential stuff into the new state. */
sewardjfdf91b42005-09-28 00:53:09 +00001728 arch->vex.guest_RSP = client_sp;
njn2da73352005-06-18 01:35:16 +00001729 arch->vex.guest_RIP = client_ip;
cerion85665ca2005-06-20 15:51:07 +00001730
1731#elif defined(VGA_ppc32)
1732 vg_assert(0 == sizeof(VexGuestPPC32State) % 8);
1733
1734 /* Zero out the initial state, and set up the simulated FPU in a
1735 sane way. */
1736 LibVEX_GuestPPC32_initialise(&arch->vex);
1737
1738 /* Zero out the shadow area. */
1739 VG_(memset)(&arch->vex_shadow, 0, sizeof(VexGuestPPC32State));
1740
1741 /* Put essential stuff into the new state. */
sewardjfdf91b42005-09-28 00:53:09 +00001742 arch->vex.guest_GPR1 = client_sp;
cerion85665ca2005-06-20 15:51:07 +00001743 arch->vex.guest_CIA = client_ip;
1744
sewardj2c48c7b2005-11-29 13:05:56 +00001745#elif defined(VGA_ppc64)
cerion21082042005-12-06 19:07:08 +00001746 vg_assert(0 == sizeof(VexGuestPPC64State) % 16);
sewardj2c48c7b2005-11-29 13:05:56 +00001747
1748 /* Zero out the initial state, and set up the simulated FPU in a
1749 sane way. */
1750 LibVEX_GuestPPC64_initialise(&arch->vex);
1751
1752 /* Zero out the shadow area. */
1753 VG_(memset)(&arch->vex_shadow, 0, sizeof(VexGuestPPC64State));
1754
1755 /* Put essential stuff into the new state. */
1756 arch->vex.guest_GPR1 = client_sp;
1757 arch->vex.guest_CIA = client_ip;
1758
njn2da73352005-06-18 01:35:16 +00001759#else
1760# error Unknown arch
1761#endif
1762 // Tell the tool that we just wrote to the registers.
1763 VG_TRACK( post_reg_write, Vg_CoreStartup, /*tid*/1, /*offset*/0,
1764 sizeof(VexGuestArchState));
1765}
1766
sewardjde4a1d02002-03-22 01:27:54 +00001767
nethercote71980f02004-01-24 18:18:54 +00001768/*====================================================================*/
njn2025cf92005-06-26 20:44:48 +00001769/*=== BB profiling ===*/
1770/*====================================================================*/
1771
1772static
1773void show_BB_profile ( BBProfEntry tops[], UInt n_tops, ULong score_total )
1774{
1775 ULong score_cumul, score_here;
1776 Char buf_cumul[10], buf_here[10];
1777 Char name[64];
1778 Int r;
1779
1780 VG_(printf)("\n");
1781 VG_(printf)("-----------------------------------------------------------\n");
1782 VG_(printf)("--- BEGIN BB Profile (summary of scores) ---\n");
1783 VG_(printf)("-----------------------------------------------------------\n");
1784 VG_(printf)("\n");
1785
1786 VG_(printf)("Total score = %lld\n\n", score_total);
1787
1788 score_cumul = 0;
1789 for (r = 0; r < n_tops; r++) {
1790 if (tops[r].addr == 0)
1791 continue;
1792 name[0] = 0;
1793 VG_(get_fnname_w_offset)(tops[r].addr, name, 64);
1794 name[63] = 0;
1795 score_here = tops[r].score;
1796 score_cumul += score_here;
1797 VG_(percentify)(score_cumul, score_total, 2, 6, buf_cumul);
1798 VG_(percentify)(score_here, score_total, 2, 6, buf_here);
1799 VG_(printf)("%3d: (%9lld %s) %9lld %s 0x%llx %s\n",
1800 r,
1801 score_cumul, buf_cumul,
1802 score_here, buf_here, tops[r].addr, name );
1803 }
1804
1805 VG_(printf)("\n");
1806 VG_(printf)("-----------------------------------------------------------\n");
1807 VG_(printf)("--- BB Profile (BB details) ---\n");
1808 VG_(printf)("-----------------------------------------------------------\n");
1809 VG_(printf)("\n");
1810
1811 score_cumul = 0;
1812 for (r = 0; r < n_tops; r++) {
1813 if (tops[r].addr == 0)
1814 continue;
1815 name[0] = 0;
1816 VG_(get_fnname_w_offset)(tops[r].addr, name, 64);
1817 name[63] = 0;
1818 score_here = tops[r].score;
1819 score_cumul += score_here;
1820 VG_(percentify)(score_cumul, score_total, 2, 6, buf_cumul);
1821 VG_(percentify)(score_here, score_total, 2, 6, buf_here);
1822 VG_(printf)("\n");
1823 VG_(printf)("=-=-=-=-=-=-=-=-=-=-=-=-=-= begin BB rank %d "
1824 "=-=-=-=-=-=-=-=-=-=-=-=-=-=\n\n", r);
1825 VG_(printf)("%3d: (%9lld %s) %9lld %s 0x%llx %s\n",
1826 r,
1827 score_cumul, buf_cumul,
1828 score_here, buf_here, tops[r].addr, name );
1829 VG_(printf)("\n");
1830 VG_(translate)(0, tops[r].addr, True, VG_(clo_profile_flags), 0);
1831 VG_(printf)("=-=-=-=-=-=-=-=-=-=-=-=-=-= end BB rank %d "
1832 "=-=-=-=-=-=-=-=-=-=-=-=-=-=\n\n", r);
1833 }
1834
1835 VG_(printf)("\n");
1836 VG_(printf)("-----------------------------------------------------------\n");
1837 VG_(printf)("--- END BB Profile ---\n");
1838 VG_(printf)("-----------------------------------------------------------\n");
1839 VG_(printf)("\n");
1840}
1841
1842
1843/*====================================================================*/
nethercote71980f02004-01-24 18:18:54 +00001844/*=== main() ===*/
1845/*====================================================================*/
1846
sewardjfdf91b42005-09-28 00:53:09 +00001847/* When main() is entered, we should be on the following stack, not
1848 the one the kernel gave us. We will run on this stack until
1849 simulation of the root thread is started, at which point a transfer
1850 is made to a dynamically allocated stack. This is for the sake of
1851 uniform overflow detection for all Valgrind threads. This is
1852 marked global even though it isn't, because assembly code below
1853 needs to reference the name. */
1854
1855/*static*/ VgStack VG_(interim_stack);
1856
1857/* This should get some address inside the stack on which we gained
1858 control (eg, it could be the SP at startup). It doesn't matter
1859 exactly where in the stack it is. This value is passed to the
1860 address space manager at startup, which uses it to identify the
1861 initial stack segment and hence the upper end of the usable address
1862 space. */
1863
1864static Addr sp_at_startup = 0;
1865
sewardj1ae3f3a2005-09-28 10:47:38 +00001866/* --- Forwards decls to do with shutdown --- */
1867
1868static void final_tidyup(ThreadId tid);
1869
1870/* Do everything which needs doing when the last thread exits */
1871static
1872void shutdown_actions_NORETURN( ThreadId tid,
1873 VgSchedReturnCode tids_schedretcode );
1874
1875/* --- end of Forwards decls to do with shutdown --- */
sewardjfdf91b42005-09-28 00:53:09 +00001876
1877
sewardj45f4e7c2005-09-27 19:20:21 +00001878/* TODO: GIVE THIS A PROPER HOME
1879 TODO: MERGE THIS WITH DUPLICATE IN mac_leakcheck.c
1880 Extract from aspacem a vector of the current segment start
1881 addresses. The vector is dynamically allocated and should be freed
1882 by the caller when done. REQUIRES m_mallocfree to be running.
1883 Writes the number of addresses required into *n_acquired. */
nethercotec314eba2004-07-15 12:59:41 +00001884
sewardj45f4e7c2005-09-27 19:20:21 +00001885static Addr* get_seg_starts ( /*OUT*/Int* n_acquired )
sewardj1cf558c2005-04-25 01:36:56 +00001886{
sewardj45f4e7c2005-09-27 19:20:21 +00001887 Addr* starts;
sewardja48a4932005-09-29 11:09:56 +00001888 Int n_starts, r = 0;
sewardj45f4e7c2005-09-27 19:20:21 +00001889
1890 n_starts = 1;
sewardj1cf558c2005-04-25 01:36:56 +00001891 while (True) {
sewardj45f4e7c2005-09-27 19:20:21 +00001892 starts = VG_(malloc)( n_starts * sizeof(Addr) );
1893 if (starts == NULL)
1894 break;
1895 r = VG_(am_get_segment_starts)( starts, n_starts );
1896 if (r >= 0)
1897 break;
1898 VG_(free)(starts);
1899 n_starts *= 2;
sewardj1cf558c2005-04-25 01:36:56 +00001900 }
sewardj45f4e7c2005-09-27 19:20:21 +00001901
1902 if (starts == NULL) {
1903 *n_acquired = 0;
1904 return NULL;
1905 }
1906
1907 *n_acquired = r;
1908 return starts;
sewardj1cf558c2005-04-25 01:36:56 +00001909}
1910
1911
sewardj45f4e7c2005-09-27 19:20:21 +00001912
sewardj45f4e7c2005-09-27 19:20:21 +00001913Int main(Int argc, HChar **argv, HChar **envp)
nethercote71980f02004-01-24 18:18:54 +00001914{
sewardj45f4e7c2005-09-27 19:20:21 +00001915 HChar* toolname = "memcheck"; // default to Memcheck
1916 HChar** env = NULL;
1917 Int need_help = 0; // 0 = no, 1 = --help, 2 = --help-debug
1918 Addr initial_client_IP = 0;
1919 Addr initial_client_SP = 0;
1920 Addr clstack_top = 0;
1921 SizeT clstack_max_size = 0;
1922 UInt* client_auxv;
1923 Int loglevel, i;
1924 Bool logging_to_fd;
nethercote73b526f2004-10-31 18:48:21 +00001925 struct vki_rlimit zero = { 0, 0 };
sewardj45f4e7c2005-09-27 19:20:21 +00001926 struct exeinfo info;
nethercote71980f02004-01-24 18:18:54 +00001927
1928 //============================================================
nethercote71980f02004-01-24 18:18:54 +00001929 //
sewardj45f4e7c2005-09-27 19:20:21 +00001930 // Nb: startup is complex. Prerequisites are shown at every step.
nethercote71980f02004-01-24 18:18:54 +00001931 // *** Be very careful when messing with the order ***
sewardj45f4e7c2005-09-27 19:20:21 +00001932 //
1933 // The first order of business is to get debug logging, the address
1934 // space manager and the dynamic memory manager up and running.
1935 // Once that's done, we can relax a bit.
1936 //
nethercote71980f02004-01-24 18:18:54 +00001937 //============================================================
sewardj45f4e7c2005-09-27 19:20:21 +00001938
1939 /* This is needed to make VG_(getenv) usable early. */
1940 VG_(client_envp) = (Char**)envp;
nethercote71980f02004-01-24 18:18:54 +00001941
sewardj1cf558c2005-04-25 01:36:56 +00001942 //--------------------------------------------------------------
1943 // Start up the logging mechanism
1944 // p: none
1945 //--------------------------------------------------------------
1946 /* Start the debugging-log system ASAP. First find out how many
1947 "-d"s were specified. This is a pre-scan of the command line. */
1948 loglevel = 0;
1949 for (i = 1; i < argc; i++) {
sewardj10759312005-05-30 23:52:47 +00001950 if (argv[i][0] != '-')
1951 break;
sewardj45f4e7c2005-09-27 19:20:21 +00001952 if (VG_STREQ(argv[i], "--"))
sewardj10759312005-05-30 23:52:47 +00001953 break;
sewardj45f4e7c2005-09-27 19:20:21 +00001954 if (VG_STREQ(argv[i], "-d"))
sewardj10759312005-05-30 23:52:47 +00001955 loglevel++;
sewardj1cf558c2005-04-25 01:36:56 +00001956 }
1957
1958 /* ... and start the debug logger. Now we can safely emit logging
1959 messages all through startup. */
sewardj10759312005-05-30 23:52:47 +00001960 VG_(debugLog_startup)(loglevel, "Stage 2 (main)");
sewardj45f4e7c2005-09-27 19:20:21 +00001961 VG_(debugLog)(1, "main", "Welcome to Valgrind version "
1962 VERSION " debug logging\n");
1963
1964 //--------------------------------------------------------------
1965 // Ensure we're on a plausible stack.
1966 // p: logging
1967 //--------------------------------------------------------------
1968 VG_(debugLog)(1, "main", "Checking current stack is plausible\n");
sewardjfdf91b42005-09-28 00:53:09 +00001969 { HChar* limLo = (HChar*)(&VG_(interim_stack).bytes[0]);
1970 HChar* limHi = limLo + sizeof(VG_(interim_stack));
sewardj45f4e7c2005-09-27 19:20:21 +00001971 HChar* aLocal = (HChar*)&zero; /* any auto local will do */
1972 if (aLocal < limLo || aLocal >= limHi) {
1973 /* something's wrong. Stop. */
1974 VG_(debugLog)(0, "main", "Root stack %p to %p, a local %p\n",
1975 limLo, limHi, aLocal );
1976 VG_(debugLog)(0, "main", "Valgrind: FATAL: "
1977 "Initial stack switched failed.\n");
1978 VG_(debugLog)(0, "main", " Cannot continue. Sorry.\n");
1979 VG_(exit)(1);
1980 }
1981 }
1982
1983 //--------------------------------------------------------------
1984 // Ensure we have a plausible pointer to the stack on which
1985 // we gained control (not the current stack!)
1986 // p: logging
1987 //--------------------------------------------------------------
1988 VG_(debugLog)(1, "main", "Checking initial stack was noted\n");
sewardjfdf91b42005-09-28 00:53:09 +00001989 if (sp_at_startup == 0) {
sewardj45f4e7c2005-09-27 19:20:21 +00001990 VG_(debugLog)(0, "main", "Valgrind: FATAL: "
1991 "Initial stack was not noted.\n");
1992 VG_(debugLog)(0, "main", " Cannot continue. Sorry.\n");
1993 VG_(exit)(1);
1994 }
1995
1996 //--------------------------------------------------------------
1997 // Start up the address space manager, and determine the
1998 // approximate location of the client's stack
1999 // p: logging, plausible-stack
2000 //--------------------------------------------------------------
2001 VG_(debugLog)(1, "main", "Starting the address space manager\n");
sewardjfdf91b42005-09-28 00:53:09 +00002002 clstack_top = VG_(am_startup)( sp_at_startup );
sewardj45f4e7c2005-09-27 19:20:21 +00002003 VG_(debugLog)(1, "main", "Address space manager is running\n");
2004
2005 //--------------------------------------------------------------
2006 // Start up the dynamic memory manager
2007 // p: address space management
2008 // In fact m_mallocfree is self-initialising, so there's no
2009 // initialisation call to do. Instead, try a simple malloc/
2010 // free pair right now to check that nothing is broken.
2011 //--------------------------------------------------------------
2012 VG_(debugLog)(1, "main", "Starting the dynamic memory manager\n");
2013 { void* p = VG_(malloc)( 12345 );
2014 if (p) VG_(free)( p );
2015 }
2016 VG_(debugLog)(1, "main", "Dynamic memory manager is running\n");
sewardj1cf558c2005-04-25 01:36:56 +00002017
nethercotef4928da2004-06-15 10:54:40 +00002018 //============================================================
sewardj45f4e7c2005-09-27 19:20:21 +00002019 //
2020 // Dynamic memory management is now available.
2021 //
nethercotef4928da2004-06-15 10:54:40 +00002022 //============================================================
2023
sewardj45f4e7c2005-09-27 19:20:21 +00002024 //--------------------------------------------------------------
2025 // Look for alternative libdir
2026 { HChar *cp = VG_(getenv)(VALGRIND_LIB);
2027 if (cp != NULL)
2028 VG_(libdir) = cp;
2029 }
2030
2031 //--------------------------------------------------------------
2032 // Extract the launcher name from the environment.
2033 VG_(debugLog)(1, "main", "Getting stage1's name\n");
2034 VG_(name_of_launcher) = VG_(getenv)(VALGRIND_LAUNCHER);
2035 if (VG_(name_of_launcher) == NULL) {
2036 VG_(printf)("valgrind: You cannot run '%s' directly.\n", argv[0]);
2037 VG_(printf)("valgrind: You should use $prefix/bin/valgrind.\n");
2038 VG_(exit)(1);
2039 }
2040
2041 //--------------------------------------------------------------
fitzhardingeb50068f2004-02-24 23:42:55 +00002042 // Get the current process datasize rlimit, and set it to zero.
2043 // This prevents any internal uses of brk() from having any effect.
2044 // We remember the old value so we can restore it on exec, so that
2045 // child processes will have a reasonable brk value.
2046 VG_(getrlimit)(VKI_RLIMIT_DATA, &VG_(client_rlimit_data));
2047 zero.rlim_max = VG_(client_rlimit_data).rlim_max;
2048 VG_(setrlimit)(VKI_RLIMIT_DATA, &zero);
thughesc37184f2004-09-11 14:16:57 +00002049
2050 // Get the current process stack rlimit.
2051 VG_(getrlimit)(VKI_RLIMIT_STACK, &VG_(client_rlimit_stack));
2052
sewardje2d1e672005-11-12 23:10:48 +00002053 //--------------------------------------------------------------
2054 // Figure out what sort of CPU we're on, and whether it is
2055 // able to run V.
2056 VG_(debugLog)(1, "main", "Get hardware capabilities ...\n");
2057 { VexArch vex_arch;
2058 VexArchInfo vex_archinfo;
2059 Bool ok = VG_(machine_get_hwcaps)();
2060 if (!ok) {
2061 VG_(printf)("\n");
2062 VG_(printf)("valgrind: fatal error: unsupported CPU.\n");
2063 VG_(printf)(" Supported CPUs are:\n");
2064 VG_(printf)(" * x86 (practically any; Pentium-I or above), "
2065 "AMD Athlon or above)\n");
2066 VG_(printf)(" * AMD Athlon64/Opteron\n");
2067 VG_(printf)(" * PowerPC (most; ppc405 and above)\n");
2068 VG_(printf)("\n");
2069 VG_(exit)(1);
2070 }
2071 VG_(machine_get_VexArchInfo)( &vex_arch, &vex_archinfo );
2072 VG_(debugLog)(1, "main", "... arch = %s, subarch = %s\n",
2073 LibVEX_ppVexArch ( vex_arch ),
2074 LibVEX_ppVexSubArch( vex_archinfo.subarch ) );
2075 }
2076
sewardj45f4e7c2005-09-27 19:20:21 +00002077 //============================================================
2078 // Command line argument handling order:
2079 // * If --help/--help-debug are present, show usage message
2080 // (including the tool-specific usage)
2081 // * (If no --tool option given, default to Memcheck)
2082 // * Then, if client is missing, abort with error msg
2083 // * Then, if any cmdline args are bad, abort with error msg
2084 //============================================================
2085
2086 //--------------------------------------------------------------
2087 // Split up argv into: C args, V args, V extra args, and exename.
2088 // p: dynamic memory allocation
2089 //--------------------------------------------------------------
2090 VG_(debugLog)(1, "main", "Split up command line\n");
2091 VG_(split_up_argv)( argc, argv );
2092 if (0) {
2093 for (i = 0; i < VG_(args_for_valgrind).used; i++)
2094 VG_(printf)("varg %s\n", VG_(args_for_valgrind).strs[i]);
2095 VG_(printf)(" exe %s\n", VG_(args_the_exename));
2096 for (i = 0; i < VG_(args_for_client).used; i++)
2097 VG_(printf)("carg %s\n", VG_(args_for_client).strs[i]);
nethercote71980f02004-01-24 18:18:54 +00002098 }
2099
2100 //--------------------------------------------------------------
sewardj45f4e7c2005-09-27 19:20:21 +00002101 // Extract tool name and whether help has been requested.
2102 // Note we can't print the help message yet, even if requested,
2103 // because the tool has not been initialised.
2104 // p: split_up_argv [for VG_(args_for_valgrind)]
nethercote71980f02004-01-24 18:18:54 +00002105 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002106 VG_(debugLog)(1, "main", "Preprocess command line opts\n");
sewardj45f4e7c2005-09-27 19:20:21 +00002107 get_helprequest_and_toolname(&need_help, &toolname);
nethercote71980f02004-01-24 18:18:54 +00002108
sewardj45f4e7c2005-09-27 19:20:21 +00002109 // Set default vex control params
2110 LibVEX_default_VexControl(& VG_(clo_vex_control));
nethercote71980f02004-01-24 18:18:54 +00002111
2112 //--------------------------------------------------------------
2113 // Load client executable, finding in $PATH if necessary
sewardj45f4e7c2005-09-27 19:20:21 +00002114 // p: get_helprequest_and_toolname() [for 'exec', 'need_help']
nethercote71980f02004-01-24 18:18:54 +00002115 // p: layout_remaining_space [so there's space]
2116 //--------------------------------------------------------------
sewardj45f4e7c2005-09-27 19:20:21 +00002117 if (!need_help) {
2118 VG_(debugLog)(1, "main", "Loading client\n");
nethercote71980f02004-01-24 18:18:54 +00002119
sewardj45f4e7c2005-09-27 19:20:21 +00002120 if (VG_(args_the_exename) == NULL)
2121 missing_prog();
2122
2123 load_client(&info, &initial_client_IP);
2124 }
nethercote71980f02004-01-24 18:18:54 +00002125
2126 //--------------------------------------------------------------
2127 // Set up client's environment
sewardj45f4e7c2005-09-27 19:20:21 +00002128 // p: set-libdir [for VG_(libdir)]
2129 // p: get_helprequest_and_toolname [for toolname]
nethercote71980f02004-01-24 18:18:54 +00002130 //--------------------------------------------------------------
sewardj45f4e7c2005-09-27 19:20:21 +00002131 if (!need_help) {
2132 VG_(debugLog)(1, "main", "Setup client env\n");
2133 env = setup_client_env(envp, toolname);
2134 }
nethercote71980f02004-01-24 18:18:54 +00002135
2136 //--------------------------------------------------------------
nethercote5ee67ca2004-06-22 14:00:09 +00002137 // Setup client stack, eip, and VG_(client_arg[cv])
nethercote71980f02004-01-24 18:18:54 +00002138 // p: load_client() [for 'info']
2139 // p: fix_environment() [for 'env']
2140 //--------------------------------------------------------------
sewardj45f4e7c2005-09-27 19:20:21 +00002141 if (!need_help) {
2142 void* init_sp = argv - 1;
2143 SizeT m1 = 1024 * 1024;
2144 SizeT m8 = 8 * m1;
2145 VG_(debugLog)(1, "main", "Setup client stack\n");
2146 clstack_max_size = (SizeT)VG_(client_rlimit_stack).rlim_cur;
2147 if (clstack_max_size < m1) clstack_max_size = m1;
2148 if (clstack_max_size > m8) clstack_max_size = m8;
2149 clstack_max_size = VG_PGROUNDUP(clstack_max_size);
sewardjb5f6f512005-03-10 23:59:00 +00002150
sewardj45f4e7c2005-09-27 19:20:21 +00002151 initial_client_SP
2152 = setup_client_stack( init_sp, env,
2153 &info, &client_auxv,
2154 clstack_top, clstack_max_size );
2155
2156 VG_(free)(env);
2157
2158 VG_(debugLog)(2, "main",
2159 "Client info: "
sewardja48a4932005-09-29 11:09:56 +00002160 "initial_IP=%p initial_SP=%p brk_base=%p\n",
sewardj45f4e7c2005-09-27 19:20:21 +00002161 (void*)initial_client_IP,
2162 (void*)initial_client_SP,
2163 (void*)VG_(brk_base) );
nethercotec25c4492004-10-18 11:52:17 +00002164 }
nethercote71980f02004-01-24 18:18:54 +00002165
sewardj45f4e7c2005-09-27 19:20:21 +00002166 //--------------------------------------------------------------
2167 // Setup client data (brk) segment. Initially a 1-page segment
2168 // which abuts a shrinkable reservation.
2169 // p: load_client() [for 'info' and hence VG_(brk_base)]
2170 //--------------------------------------------------------------
2171 if (!need_help) {
2172 SizeT m1 = 1024 * 1024;
2173 SizeT m8 = 8 * m1;
2174 SizeT dseg_max_size = (SizeT)VG_(client_rlimit_data).rlim_cur;
2175 VG_(debugLog)(1, "main", "Setup client data (brk) segment\n");
2176 if (dseg_max_size < m1) dseg_max_size = m1;
2177 if (dseg_max_size > m8) dseg_max_size = m8;
2178 dseg_max_size = VG_PGROUNDUP(dseg_max_size);
2179
2180 setup_client_dataseg( dseg_max_size );
2181 }
nethercote71980f02004-01-24 18:18:54 +00002182
2183 //==============================================================
sewardj45f4e7c2005-09-27 19:20:21 +00002184 //
2185 // Finished loading/setting up the client address space.
2186 //
nethercote71980f02004-01-24 18:18:54 +00002187 //==============================================================
2188
2189 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002190 // setup file descriptors
2191 // p: n/a
2192 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002193 VG_(debugLog)(1, "main", "Setup file descriptors\n");
nethercote71980f02004-01-24 18:18:54 +00002194 setup_file_descriptors();
2195
2196 //--------------------------------------------------------------
sewardj45f4e7c2005-09-27 19:20:21 +00002197 // create the fake /proc/<pid>/cmdline file and then unlink it,
2198 // but hold onto the fd, so we can hand it out to the client
2199 // when it tries to open /proc/<pid>/cmdline for itself.
2200 // p: setup file descriptors
nethercotec314eba2004-07-15 12:59:41 +00002201 //--------------------------------------------------------------
sewardj45f4e7c2005-09-27 19:20:21 +00002202 if (!need_help) {
2203 HChar buf[50], buf2[50+64];
2204 HChar nul[1];
2205 Int fd, r;
2206 HChar* exename;
nethercotec314eba2004-07-15 12:59:41 +00002207
sewardj45f4e7c2005-09-27 19:20:21 +00002208 VG_(debugLog)(1, "main", "Create fake /proc/<pid>/cmdline\n");
2209
2210 VG_(sprintf)(buf, "proc_%d_cmdline", VG_(getpid)());
2211 fd = VG_(mkstemp)( buf, buf2 );
2212 if (fd == -1)
2213 config_error("Can't create client cmdline file in /tmp.");
2214
2215 nul[0] = 0;
2216 exename = VG_(args_the_exename) ? VG_(args_the_exename)
2217 : "unknown_exename";
2218
2219 VG_(write)(fd, VG_(args_the_exename),
2220 VG_(strlen)( VG_(args_the_exename) ));
2221 VG_(write)(fd, nul, 1);
2222
2223 for (i = 0; i < VG_(args_for_client).used; i++) {
2224 VG_(write)(fd, VG_(args_for_client).strs[i],
2225 VG_(strlen)( VG_(args_for_client).strs[i] ));
2226 VG_(write)(fd, nul, 1);
2227 }
2228
2229 /* Don't bother to seek the file back to the start; instead do
2230 it every time a copy of it is given out (by PRE(sys_open)).
2231 That is probably more robust across fork() etc. */
2232
2233 /* Now delete it, but hang on to the fd. */
2234 r = VG_(unlink)( buf2 );
2235 if (r)
2236 config_error("Can't delete client cmdline file in /tmp.");
2237
2238 VG_(cl_cmdline_fd) = fd;
2239 }
nethercotec314eba2004-07-15 12:59:41 +00002240
2241 //--------------------------------------------------------------
sewardj45f4e7c2005-09-27 19:20:21 +00002242 // Init tool part 1: pre_clo_init
nethercotec314eba2004-07-15 12:59:41 +00002243 // p: setup_client_stack() [for 'VG_(client_arg[cv]']
nethercotec314eba2004-07-15 12:59:41 +00002244 // p: setup_file_descriptors() [for 'VG_(fd_xxx_limit)']
nethercote71980f02004-01-24 18:18:54 +00002245 //--------------------------------------------------------------
njn64c83242005-06-21 01:54:38 +00002246 {
2247 Char* s;
2248 Bool ok;
sewardj45f4e7c2005-09-27 19:20:21 +00002249 VG_(debugLog)(1, "main", "Initialise the tool part 1 (pre_clo_init)\n");
2250 (VG_(tool_info).tl_pre_clo_init)();
2251 ok = VG_(sanity_check_needs)( &s );
njn64c83242005-06-21 01:54:38 +00002252 if (!ok) {
2253 VG_(tool_panic)(s);
2254 }
2255 }
nethercote71980f02004-01-24 18:18:54 +00002256
sewardj45f4e7c2005-09-27 19:20:21 +00002257 //--------------------------------------------------------------
nethercotef4928da2004-06-15 10:54:40 +00002258 // If --tool and --help/--help-debug was given, now give the core+tool
2259 // help message
sewardj45f4e7c2005-09-27 19:20:21 +00002260 // p: get_helprequest_and_toolname() [for 'need_help']
2261 // p: tl_pre_clo_init [for 'VG_(tdict).usage']
2262 //--------------------------------------------------------------
2263 VG_(debugLog)(1, "main", "Print help and quit, if requested\n");
nethercotef4928da2004-06-15 10:54:40 +00002264 if (need_help) {
sewardj45f4e7c2005-09-27 19:20:21 +00002265 usage_NORETURN(/*--help-debug?*/2 == need_help);
nethercotef4928da2004-06-15 10:54:40 +00002266 }
nethercotec314eba2004-07-15 12:59:41 +00002267
sewardj45f4e7c2005-09-27 19:20:21 +00002268 //--------------------------------------------------------------
2269 // Process command line options to Valgrind + tool
2270 // p: setup_client_stack() [for 'VG_(client_arg[cv]']
2271 // p: setup_file_descriptors() [for 'VG_(fd_xxx_limit)']
2272 //--------------------------------------------------------------
2273 VG_(debugLog)(1, "main", "Process Valgrind's command line options, "
sewardja48a4932005-09-29 11:09:56 +00002274 "setup logging\n");
sewardj45f4e7c2005-09-27 19:20:21 +00002275 logging_to_fd = process_cmd_line_options(client_auxv, toolname);
2276
2277 //--------------------------------------------------------------
sewardj592ae092005-11-08 19:01:44 +00002278 // Zeroise the millisecond counter by doing a first read of it.
2279 // p: none
2280 //--------------------------------------------------------------
2281 (void) VG_(read_millisecond_timer)();
2282
2283 //--------------------------------------------------------------
sewardj45f4e7c2005-09-27 19:20:21 +00002284 // Print the preamble
2285 // p: tl_pre_clo_init [for 'VG_(details).name' and friends]
2286 // p: process_cmd_line_options() [for VG_(clo_verbosity), VG_(clo_xml),
2287 // VG_(clo_log_file_qualifier),
2288 // logging_to_fd]
2289 //--------------------------------------------------------------
2290 VG_(debugLog)(1, "main", "Print the preamble...\n");
2291 print_preamble(logging_to_fd, toolname);
2292 VG_(debugLog)(1, "main", "...finished the preamble\n");
2293
2294 //--------------------------------------------------------------
2295 // Init tool part 2: post_clo_init
2296 // p: setup_client_stack() [for 'VG_(client_arg[cv]']
2297 // p: setup_file_descriptors() [for 'VG_(fd_xxx_limit)']
2298 // p: print_preamble() [so any warnings printed in post_clo_init
2299 // are shown after the preamble]
2300 //--------------------------------------------------------------
2301 VG_(debugLog)(1, "main", "Initialise the tool part 2 (post_clo_init)\n");
njn51d827b2005-05-09 01:02:08 +00002302 VG_TDICT_CALL(tool_post_clo_init);
nethercotef4928da2004-06-15 10:54:40 +00002303
2304 //--------------------------------------------------------------
sewardj45f4e7c2005-09-27 19:20:21 +00002305 // Initialise translation table and translation cache
2306 // p: aspacem [??]
2307 // p: tl_pre_clo_init [for 'VG_(details).avg_translation_sizeB']
nethercote71980f02004-01-24 18:18:54 +00002308 //--------------------------------------------------------------
sewardj45f4e7c2005-09-27 19:20:21 +00002309 VG_(debugLog)(1, "main", "Initialise TT/TC\n");
2310 VG_(init_tt_tc)();
sewardjb5f6f512005-03-10 23:59:00 +00002311
sewardj45f4e7c2005-09-27 19:20:21 +00002312 //--------------------------------------------------------------
2313 // Initialise the redirect table.
2314 // p: init_tt_tc [so it can call VG_(search_transtab) safely]
2315 // p: aspacem [so can change ownership of sysinfo pages]
2316 //--------------------------------------------------------------
2317 VG_(debugLog)(1, "main", "Initialise redirects\n");
2318 VG_(setup_code_redirect_table)();
nethercote71980f02004-01-24 18:18:54 +00002319
2320 //--------------------------------------------------------------
2321 // Allow GDB attach
2322 // p: process_cmd_line_options() [for VG_(clo_wait_for_gdb)]
2323 //--------------------------------------------------------------
2324 /* Hook to delay things long enough so we can get the pid and
2325 attach GDB in another shell. */
2326 if (VG_(clo_wait_for_gdb)) {
sewardj8211a572005-06-23 21:37:47 +00002327 Long q, iters;
sewardj1fbc1a52005-04-25 02:05:54 +00002328 VG_(debugLog)(1, "main", "Wait for GDB\n");
sewardj93ab8572005-02-06 14:10:40 +00002329 VG_(printf)("pid=%d, entering delay loop\n", VG_(getpid)());
2330 /* jrs 20050206: I don't understand why this works on x86. On
2331 amd64 the obvious analogues (jump *$rip or jump *$rcx) don't
2332 work. */
2333 /* do "jump *$eip" to skip this in gdb (x86) */
2334 //VG_(do_syscall0)(__NR_pause);
sewardj8211a572005-06-23 21:37:47 +00002335
2336# if defined(VGP_x86_linux)
2337 iters = 5;
sewardj2c48c7b2005-11-29 13:05:56 +00002338# elif defined(VGP_amd64_linux) || defined(VGP_ppc64_linux)
sewardj8211a572005-06-23 21:37:47 +00002339 iters = 10;
2340# elif defined(VGP_ppc32_linux)
sewardjd714d2e2005-07-08 18:24:04 +00002341 iters = 5;
sewardj8211a572005-06-23 21:37:47 +00002342# else
2343# error "Unknown plat"
2344# endif
2345
2346 iters *= 1000*1000*1000;
2347 for (q = 0; q < iters; q++)
2348 ;
nethercote71980f02004-01-24 18:18:54 +00002349 }
2350
sewardjb5d320c2005-03-13 18:57:15 +00002351 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002352 // Search for file descriptors that are inherited from our parent
2353 // p: process_cmd_line_options [for VG_(clo_track_fds)]
2354 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002355 if (VG_(clo_track_fds)) {
2356 VG_(debugLog)(1, "main", "Init preopened fds\n");
nethercote71980f02004-01-24 18:18:54 +00002357 VG_(init_preopened_fds)();
sewardj1fbc1a52005-04-25 02:05:54 +00002358 }
nethercote71980f02004-01-24 18:18:54 +00002359
2360 //--------------------------------------------------------------
sewardj45f4e7c2005-09-27 19:20:21 +00002361 // Load debug info for the existing segments.
2362 // p: setup_code_redirect_table [so that redirs can be recorded]
2363 // p: mallocfree
2364 // p: probably: setup fds and process CLOs, so that logging works
2365 //--------------------------------------------------------------
2366 VG_(debugLog)(1, "main", "Load initial debug info\n");
2367 { Addr* seg_starts;
2368 Int n_seg_starts;
2369
2370 seg_starts = get_seg_starts( &n_seg_starts );
2371 vg_assert(seg_starts && n_seg_starts > 0);
2372
sewardjf72cced2005-11-08 00:45:47 +00002373 /* show them all to the debug info reader. allow_SkFileV has to
2374 be True here so that we read info from the valgrind executable
2375 itself. */
sewardj45f4e7c2005-09-27 19:20:21 +00002376 for (i = 0; i < n_seg_starts; i++)
sewardjf72cced2005-11-08 00:45:47 +00002377 VG_(di_notify_mmap)( seg_starts[i], True/*allow_SkFileV*/ );
sewardj45f4e7c2005-09-27 19:20:21 +00002378
2379 VG_(free)( seg_starts );
2380 }
2381
2382 //--------------------------------------------------------------
2383 // Tell aspacem of ownership change of the asm helpers, so that
2384 // m_translate allows them to be translated. However, only do this
2385 // after the initial debug info read, since making a hole in the
2386 // address range for the stage2 binary confuses the debug info reader.
2387 // p: aspacem
2388 //--------------------------------------------------------------
2389 { Bool change_ownership_v_c_OK;
2390 Addr co_start = VG_PGROUNDDN( (Addr)&VG_(trampoline_stuff_start) );
2391 Addr co_endPlus = VG_PGROUNDUP( (Addr)&VG_(trampoline_stuff_end) );
2392 VG_(debugLog)(1,"redir",
2393 "transfer ownership V -> C of 0x%llx .. 0x%llx\n",
2394 (ULong)co_start, (ULong)co_endPlus-1 );
2395
2396 change_ownership_v_c_OK
2397 = VG_(am_change_ownership_v_to_c)( co_start, co_endPlus - co_start );
2398 vg_assert(change_ownership_v_c_OK);
2399 }
2400
2401 //--------------------------------------------------------------
2402 // Tell the tool about the initial client memory permissions
2403 // p: aspacem
2404 // p: mallocfree
2405 // p: setup_client_stack
2406 // p: setup_client_dataseg
2407 //--------------------------------------------------------------
2408 VG_(debugLog)(1, "main", "Tell tool about initial permissions\n");
2409 { Addr* seg_starts;
2410 Int n_seg_starts;
2411 NSegment* seg;
2412
2413 seg_starts = get_seg_starts( &n_seg_starts );
2414 vg_assert(seg_starts && n_seg_starts > 0);
2415
2416 /* show interesting ones to the tool */
2417 for (i = 0; i < n_seg_starts; i++) {
2418 seg = VG_(am_find_nsegment)( seg_starts[i] );
2419 vg_assert(seg);
2420 if (seg->kind == SkFileC || seg->kind == SkAnonC) {
2421 VG_(debugLog)(2, "main",
2422 "tell tool about %010lx-%010lx %c%c%c\n",
2423 seg->start, seg->end,
2424 seg->hasR ? 'r' : '-',
2425 seg->hasW ? 'w' : '-',
2426 seg->hasX ? 'x' : '-' );
2427 VG_TRACK( new_mem_startup, seg->start, seg->end+1-seg->start,
2428 seg->hasR, seg->hasW, seg->hasX );
2429 }
2430 }
2431
2432 VG_(free)( seg_starts );
2433
2434 /* Also do the initial stack permissions. */
2435 seg = VG_(am_find_nsegment)( initial_client_SP );
2436 vg_assert(seg);
2437 vg_assert(seg->kind == SkAnonC);
2438 vg_assert(initial_client_SP >= seg->start);
2439 vg_assert(initial_client_SP <= seg->end);
2440
2441 /* Stuff below the initial SP is unaddressable. */
2442 /* NB: shouldn't this take into account the VG_STACK_REDZONE_SZB
2443 bytes below SP? */
2444 VG_TRACK( die_mem_stack, seg->start, initial_client_SP - seg->start );
2445 VG_(debugLog)(2, "main", "mark stack inaccessible %010lx-%010lx\n",
2446 seg->start, initial_client_SP-1 );
2447
2448 /* Also the assembly helpers. */
2449 VG_TRACK( new_mem_startup,
2450 (Addr)&VG_(trampoline_stuff_start),
tom151a6392005-11-11 12:30:36 +00002451 (Addr)&VG_(trampoline_stuff_end) - (Addr)&VG_(trampoline_stuff_start),
sewardj45f4e7c2005-09-27 19:20:21 +00002452 False, /* readable? */
2453 False, /* writable? */
2454 True /* executable? */ );
2455 }
2456
2457 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002458 // Initialise the scheduler
nethercote71980f02004-01-24 18:18:54 +00002459 // p: setup_file_descriptors() [else VG_(safe_fd)() breaks]
sewardj45f4e7c2005-09-27 19:20:21 +00002460 // p: setup_client_stack
nethercote71980f02004-01-24 18:18:54 +00002461 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002462 VG_(debugLog)(1, "main", "Initialise scheduler\n");
sewardj45f4e7c2005-09-27 19:20:21 +00002463 { NSegment* seg = VG_(am_find_nsegment)( initial_client_SP );
2464 vg_assert(seg);
2465 vg_assert(seg->kind == SkAnonC);
2466 vg_assert(initial_client_SP >= seg->start);
2467 vg_assert(initial_client_SP <= seg->end);
2468 VG_(scheduler_init)( seg->end, clstack_max_size );
2469 }
nethercote71980f02004-01-24 18:18:54 +00002470
2471 //--------------------------------------------------------------
sewardjb5f6f512005-03-10 23:59:00 +00002472 // Initialise the pthread model
2473 // p: ?
sewardj2a99cf62004-11-24 10:44:19 +00002474 // load_client() [for 'client_eip']
2475 // setup_client_stack() [for 'sp_at_startup']
2476 // setup_scheduler() [for the rest of state 1 stuff]
2477 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002478 VG_(debugLog)(1, "main", "Initialise thread 1's state\n");
sewardj45f4e7c2005-09-27 19:20:21 +00002479 init_thread1state( initial_client_IP, initial_client_SP,
2480 &VG_(threads)[1].arch);
njnea4b28c2004-11-30 16:04:58 +00002481
sewardj2a99cf62004-11-24 10:44:19 +00002482 //--------------------------------------------------------------
sewardj39b88fb2005-03-12 15:16:07 +00002483 // Initialise the pthread model
2484 // p: ?
nethercote71980f02004-01-24 18:18:54 +00002485 //--------------------------------------------------------------
sewardjb5f6f512005-03-10 23:59:00 +00002486 //if (VG_(clo_model_pthreads))
2487 // VG_(pthread_init)();
nethercote71980f02004-01-24 18:18:54 +00002488
2489 //--------------------------------------------------------------
2490 // Initialise the signal handling subsystem
sewardjb5f6f512005-03-10 23:59:00 +00002491 // p: n/a
nethercote71980f02004-01-24 18:18:54 +00002492 //--------------------------------------------------------------
2493 // Nb: temporarily parks the saved blocking-mask in saved_sigmask.
sewardj1fbc1a52005-04-25 02:05:54 +00002494 VG_(debugLog)(1, "main", "Initialise signal management\n");
nethercote71980f02004-01-24 18:18:54 +00002495 VG_(sigstartup_actions)();
2496
2497 //--------------------------------------------------------------
2498 // Perhaps we're profiling Valgrind?
2499 // p: process_cmd_line_options() [for VG_(clo_profile)]
2500 // p: others?
2501 //
2502 // XXX: this seems to be broken? It always says the tool wasn't built
2503 // for profiling; vg_profile.c's functions don't seem to be overriding
2504 // vg_dummy_profile.c's?
2505 //
2506 // XXX: want this as early as possible. Looking for --profile
sewardj45f4e7c2005-09-27 19:20:21 +00002507 // in get_helprequest_and_toolname() could get it earlier.
nethercote71980f02004-01-24 18:18:54 +00002508 //--------------------------------------------------------------
2509 if (VG_(clo_profile))
njn31066fd2005-03-26 00:42:02 +00002510 VG_(init_profiling)();
nethercote71980f02004-01-24 18:18:54 +00002511
2512 VGP_PUSHCC(VgpStartup);
2513
2514 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002515 // Read suppression file
2516 // p: process_cmd_line_options() [for VG_(clo_suppressions)]
2517 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002518 if (VG_(needs).core_errors || VG_(needs).tool_errors) {
2519 VG_(debugLog)(1, "main", "Load suppressions\n");
nethercote71980f02004-01-24 18:18:54 +00002520 VG_(load_suppressions)();
sewardj1fbc1a52005-04-25 02:05:54 +00002521 }
nethercote71980f02004-01-24 18:18:54 +00002522
2523 //--------------------------------------------------------------
rjwalsh0140af52005-06-04 20:42:33 +00002524 // register client stack
2525 //--------------------------------------------------------------
njn945ed2e2005-06-24 03:28:30 +00002526 VG_(clstk_id) = VG_(register_stack)(VG_(clstk_base), VG_(clstk_end));
rjwalsh0140af52005-06-04 20:42:33 +00002527
2528 //--------------------------------------------------------------
sewardj45f4e7c2005-09-27 19:20:21 +00002529 // Show the address space state so far
2530 //--------------------------------------------------------------
2531 VG_(debugLog)(1, "main", "\n");
2532 VG_(debugLog)(1, "main", "\n");
2533 VG_(am_show_nsegments)(1,"Memory layout at client startup");
2534 VG_(debugLog)(1, "main", "\n");
2535 VG_(debugLog)(1, "main", "\n");
2536
2537 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002538 // Run!
2539 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002540 VGP_POPCC(VgpStartup);
nethercote71980f02004-01-24 18:18:54 +00002541
sewardj71bc3cb2005-05-19 00:25:45 +00002542 if (VG_(clo_xml)) {
sewardj68cde6f2005-07-19 12:17:51 +00002543 HChar buf[50];
sewardj592ae092005-11-08 19:01:44 +00002544 VG_(elapsed_wallclock_time)(buf);
sewardj753673f2005-08-09 22:03:08 +00002545 VG_(message)(Vg_UserMsg, "<status>\n"
2546 " <state>RUNNING</state>\n"
2547 " <time>%t</time>\n"
2548 "</status>",
2549 buf);
sewardj71bc3cb2005-05-19 00:25:45 +00002550 VG_(message)(Vg_UserMsg, "");
2551 }
2552
sewardj1fbc1a52005-04-25 02:05:54 +00002553 VG_(debugLog)(1, "main", "Running thread 1\n");
sewardj1ae3f3a2005-09-28 10:47:38 +00002554
sewardj1d887112005-05-30 21:44:08 +00002555 /* As a result of the following call, the last thread standing
sewardj1ae3f3a2005-09-28 10:47:38 +00002556 eventually winds up running shutdown_actions_NORETURN
2557 just below. Unfortunately, simply exporting said function
2558 causes m_main to be part of a module cycle, which is pretty
2559 nonsensical. So instead of doing that, the address of said
2560 function is stored in a global variable 'owned' by m_syswrap,
2561 and it uses that function pointer to get back here when it needs
2562 to. */
2563
2564 /* Set continuation address. */
2565 VG_(address_of_m_main_shutdown_actions_NORETURN)
2566 = & shutdown_actions_NORETURN;
2567
2568 /* Run the first thread, eventually ending up at the continuation
2569 address. */
njnaf839f52005-06-23 03:27:57 +00002570 VG_(main_thread_wrapper_NORETURN)(1);
nethercote71980f02004-01-24 18:18:54 +00002571
sewardj1d887112005-05-30 21:44:08 +00002572 /*NOTREACHED*/
2573 vg_assert(0);
sewardjb5f6f512005-03-10 23:59:00 +00002574}
2575
sewardj1ae3f3a2005-09-28 10:47:38 +00002576/* Do everything which needs doing when the last thread exits. */
sewardjb5f6f512005-03-10 23:59:00 +00002577
sewardj1ae3f3a2005-09-28 10:47:38 +00002578static
2579void shutdown_actions_NORETURN( ThreadId tid,
2580 VgSchedReturnCode tids_schedretcode )
sewardjb5f6f512005-03-10 23:59:00 +00002581{
sewardj1d887112005-05-30 21:44:08 +00002582 VG_(debugLog)(1, "main", "entering VG_(shutdown_actions_NORETURN)\n");
2583
2584 vg_assert( VG_(count_living_threads)() == 1 );
sewardjb5f6f512005-03-10 23:59:00 +00002585 vg_assert(VG_(is_running_thread)(tid));
2586
2587 // Wait for all other threads to exit.
njn7b85dd52005-06-12 17:26:29 +00002588 VG_(reap_threads)(tid);
sewardjb5f6f512005-03-10 23:59:00 +00002589
2590 VG_(clo_model_pthreads) = False;
2591
2592 // Clean the client up before the final report
njn9cb54ac2005-06-12 04:19:17 +00002593 final_tidyup(tid);
sewardjb5f6f512005-03-10 23:59:00 +00002594
2595 // OK, done
2596 VG_(exit_thread)(tid);
2597
2598 /* should be no threads left */
2599 vg_assert(VG_(count_living_threads)() == 0);
2600
2601 VG_(threads)[tid].status = VgTs_Empty;
nethercote71980f02004-01-24 18:18:54 +00002602 //--------------------------------------------------------------
2603 // Finalisation: cleanup, messages, etc. Order no so important, only
2604 // affects what order the messages come.
2605 //--------------------------------------------------------------
2606 if (VG_(clo_verbosity) > 0)
2607 VG_(message)(Vg_UserMsg, "");
2608
sewardj71bc3cb2005-05-19 00:25:45 +00002609 if (VG_(clo_xml)) {
sewardj68cde6f2005-07-19 12:17:51 +00002610 HChar buf[50];
sewardj9f297ca2005-05-20 02:29:52 +00002611 if (VG_(needs).core_errors || VG_(needs).tool_errors) {
2612 VG_(show_error_counts_as_XML)();
2613 VG_(message)(Vg_UserMsg, "");
2614 }
sewardj592ae092005-11-08 19:01:44 +00002615 VG_(elapsed_wallclock_time)(buf);
sewardj753673f2005-08-09 22:03:08 +00002616 VG_(message)(Vg_UserMsg, "<status>\n"
2617 " <state>FINISHED</state>\n"
2618 " <time>%t</time>\n"
2619 "</status>",
2620 buf);
sewardj71bc3cb2005-05-19 00:25:45 +00002621 VG_(message)(Vg_UserMsg, "");
2622 }
2623
nethercote71980f02004-01-24 18:18:54 +00002624 /* Print out file descriptor summary and stats. */
2625 if (VG_(clo_track_fds))
nethercote3a42fb82004-08-03 18:08:50 +00002626 VG_(show_open_fds)();
nethercote71980f02004-01-24 18:18:54 +00002627
njn95ec8702004-11-22 16:46:13 +00002628 if (VG_(needs).core_errors || VG_(needs).tool_errors)
nethercote71980f02004-01-24 18:18:54 +00002629 VG_(show_all_errors)();
2630
njn51d827b2005-05-09 01:02:08 +00002631 VG_TDICT_CALL(tool_fini, 0/*exitcode*/);
nethercote71980f02004-01-24 18:18:54 +00002632
sewardj71bc3cb2005-05-19 00:25:45 +00002633 if (VG_(clo_xml)) {
2634 VG_(message)(Vg_UserMsg, "");
2635 VG_(message)(Vg_UserMsg, "</valgrindoutput>");
2636 VG_(message)(Vg_UserMsg, "");
2637 }
2638
nethercote885dd912004-08-03 23:14:00 +00002639 VG_(sanity_check_general)( True /*include expensive checks*/ );
nethercote71980f02004-01-24 18:18:54 +00002640
2641 if (VG_(clo_verbosity) > 1)
nethercote3a42fb82004-08-03 18:08:50 +00002642 print_all_stats();
nethercote71980f02004-01-24 18:18:54 +00002643
nethercote71980f02004-01-24 18:18:54 +00002644 if (VG_(clo_profile))
njn31066fd2005-03-26 00:42:02 +00002645 VG_(done_profiling)();
njn2025cf92005-06-26 20:44:48 +00002646
2647 if (VG_(clo_profile_flags) > 0) {
2648 #define N_MAX 100
2649 BBProfEntry tops[N_MAX];
2650 ULong score_total = VG_(get_BB_profile) (tops, N_MAX);
2651 show_BB_profile(tops, N_MAX, score_total);
2652 }
sewardjfa8ec112005-01-19 11:55:34 +00002653
sewardj8b635a42004-11-22 19:01:47 +00002654 /* Print Vex storage stats */
sewardjbf426512005-01-17 18:35:30 +00002655 if (0)
2656 LibVEX_ShowAllocStats();
sewardj1d887112005-05-30 21:44:08 +00002657
njn8aa35852005-06-10 22:59:56 +00002658 /* Ok, finally exit in the os-specific way, according to the scheduler's
2659 return code. In short, if the (last) thread exited by calling
2660 sys_exit, do likewise; if the (last) thread stopped due to a fatal
2661 signal, terminate the entire system with that same fatal signal. */
2662 VG_(debugLog)(1, "core_os",
njn7b85dd52005-06-12 17:26:29 +00002663 "VG_(terminate_NORETURN)(tid=%lld)\n", (ULong)tid);
njn8aa35852005-06-10 22:59:56 +00002664
2665 vg_assert(VG_(count_living_threads)() == 0);
2666
2667 switch (tids_schedretcode) {
2668 case VgSrc_ExitSyscall: /* the normal way out */
2669 VG_(exit)( VG_(threads)[tid].os_state.exitcode );
2670 /* NOT ALIVE HERE! */
2671 VG_(core_panic)("entered the afterlife in main() -- ExitSyscall");
2672 break; /* what the hell :) */
2673
2674 case VgSrc_FatalSig:
2675 /* We were killed by a fatal signal, so replicate the effect */
2676 vg_assert(VG_(threads)[tid].os_state.fatalsig != 0);
2677 VG_(kill_self)(VG_(threads)[tid].os_state.fatalsig);
2678 VG_(core_panic)("main(): signal was supposed to be fatal");
2679 break;
2680
2681 default:
2682 VG_(core_panic)("main(): unexpected scheduler return code");
2683 }
njne96be672005-05-08 19:08:54 +00002684}
sewardj8b635a42004-11-22 19:01:47 +00002685
sewardj1ae3f3a2005-09-28 10:47:38 +00002686/* -------------------- */
2687
2688/* Final clean-up before terminating the process.
2689 Clean up the client by calling __libc_freeres() (if requested)
2690 This is Linux-specific?
2691*/
2692static void final_tidyup(ThreadId tid)
2693{
2694 Addr __libc_freeres_wrapper;
2695
2696 vg_assert(VG_(is_running_thread)(tid));
2697
2698 if ( !VG_(needs).libc_freeres ||
2699 !VG_(clo_run_libc_freeres) ||
2700 0 == (__libc_freeres_wrapper = VG_(get_libc_freeres_wrapper)()) )
2701 return; /* can't/won't do it */
2702
2703 if (VG_(clo_verbosity) > 2 ||
2704 VG_(clo_trace_syscalls) ||
2705 VG_(clo_trace_sched))
2706 VG_(message)(Vg_DebugMsg,
2707 "Caught __NR_exit; running __libc_freeres()");
2708
2709 /* point thread context to point to libc_freeres_wrapper */
2710 VG_(set_IP)(tid, __libc_freeres_wrapper);
2711 // XXX should we use a special stack?
2712
2713 /* Block all blockable signals by copying the real block state into
2714 the thread's block state*/
2715 VG_(sigprocmask)(VKI_SIG_BLOCK, NULL, &VG_(threads)[tid].sig_mask);
2716 VG_(threads)[tid].tmp_sig_mask = VG_(threads)[tid].sig_mask;
2717
2718 /* and restore handlers to default */
2719 VG_(set_default_handler)(VKI_SIGSEGV);
2720 VG_(set_default_handler)(VKI_SIGBUS);
2721 VG_(set_default_handler)(VKI_SIGILL);
2722 VG_(set_default_handler)(VKI_SIGFPE);
2723
2724 // We were exiting, so assert that...
2725 vg_assert(VG_(is_exiting)(tid));
2726 // ...but now we're not again
2727 VG_(threads)[tid].exitreason = VgSrc_None;
2728
2729 // run until client thread exits - ideally with LIBC_FREERES_DONE,
2730 // but exit/exitgroup/signal will do
2731 VG_(scheduler)(tid);
2732
2733 vg_assert(VG_(is_exiting)(tid));
2734}
2735
sewardj45f4e7c2005-09-27 19:20:21 +00002736
2737/*====================================================================*/
2738/*=== Getting to main() alive ===*/
2739/*====================================================================*/
2740
2741/* If linking of the final executables is done with glibc present,
2742 then Valgrind starts at main() above as usual, and all of the
2743 following code is irrelevant.
2744
2745 However, this is not the intended mode of use. The plan is to
2746 avoid linking against glibc, by giving gcc the flags
2747 -nodefaultlibs -lgcc -nostartfiles at startup.
2748
2749 From this derive two requirements:
2750
2751 1. gcc may emit calls to memcpy and memset to deal with structure
2752 assignments etc. Since we have chosen to ignore all the
2753 "normal" supporting libraries, we have to provide our own
2754 implementations of them. No problem.
2755
2756 2. We have to provide a symbol "_start", to which the kernel
2757 hands control at startup. Hence the code below.
2758*/
2759
2760/* ---------------- Requirement 1 ---------------- */
2761
2762void* memcpy(void *dest, const void *src, size_t n);
2763void* memcpy(void *dest, const void *src, size_t n) {
2764 return VG_(memcpy)(dest,src,n);
2765}
2766void* memset(void *s, int c, size_t n);
2767void* memset(void *s, int c, size_t n) {
2768 return VG_(memset)(s,c,n);
2769}
2770
2771/* ---------------- Requirement 2 ---------------- */
2772
2773/* Glibc's sysdeps/i386/elf/start.S has the following gem of a
2774 comment, which explains how the stack looks right at process start
2775 (when _start is jumped to). Hence _start passes %esp to
2776 _start_in_C, which extracts argc/argv/envp and starts up
2777 correctly. */
2778
2779/* This is the canonical entry point, usually the first thing in the text
2780 segment. The SVR4/i386 ABI (pages 3-31, 3-32) says that when the entry
2781 point runs, most registers' values are unspecified, except for:
2782
2783 %edx Contains a function pointer to be registered with `atexit'.
2784 This is how the dynamic linker arranges to have DT_FINI
2785 functions called for shared libraries that have been loaded
2786 before this code runs.
2787
2788 %esp The stack contains the arguments and environment:
2789 0(%esp) argc
2790 4(%esp) argv[0]
2791 ...
2792 (4*argc)(%esp) NULL
2793 (4*(argc+1))(%esp) envp[0]
2794 ...
2795 NULL
2796*/
2797
2798/* The kernel hands control to _start, which extracts the initial
sewardja48a4932005-09-29 11:09:56 +00002799 stack pointer and calls onwards to _start_in_C. This also switches
2800 the new stack. */
sewardj45f4e7c2005-09-27 19:20:21 +00002801#if defined(VGP_x86_linux)
2802asm("\n"
sewardjd9fc3822005-11-18 23:50:43 +00002803 ".text\n"
sewardj45f4e7c2005-09-27 19:20:21 +00002804 "\t.globl _start\n"
2805 "\t.type _start,@function\n"
2806 "_start:\n"
2807 /* set up the new stack in %eax */
sewardjfdf91b42005-09-28 00:53:09 +00002808 "\tmovl $vgPlain_interim_stack, %eax\n"
sewardj45f4e7c2005-09-27 19:20:21 +00002809 "\taddl $"VG_STRINGIFY(VG_STACK_GUARD_SZB)", %eax\n"
2810 "\taddl $"VG_STRINGIFY(VG_STACK_ACTIVE_SZB)", %eax\n"
2811 "\tsubl $16, %eax\n"
2812 "\tandl $~15, %eax\n"
2813 /* install it, and collect the original one */
2814 "\txchgl %eax, %esp\n"
2815 /* call _start_in_C, passing it the startup %esp */
2816 "\tpushl %eax\n"
2817 "\tcall _start_in_C\n"
2818 "\thlt\n"
sewardj2fedc642005-11-19 02:02:57 +00002819 ".previous\n"
sewardj45f4e7c2005-09-27 19:20:21 +00002820);
2821#elif defined(VGP_amd64_linux)
2822asm("\n"
sewardjd9fc3822005-11-18 23:50:43 +00002823 ".text\n"
sewardj45f4e7c2005-09-27 19:20:21 +00002824 "\t.globl _start\n"
2825 "\t.type _start,@function\n"
2826 "_start:\n"
2827 /* set up the new stack in %rdi */
sewardjfdf91b42005-09-28 00:53:09 +00002828 "\tmovq $vgPlain_interim_stack, %rdi\n"
sewardj45f4e7c2005-09-27 19:20:21 +00002829 "\taddq $"VG_STRINGIFY(VG_STACK_GUARD_SZB)", %rdi\n"
2830 "\taddq $"VG_STRINGIFY(VG_STACK_ACTIVE_SZB)", %rdi\n"
2831 "\tandq $~15, %rdi\n"
2832 /* install it, and collect the original one */
2833 "\txchgq %rdi, %rsp\n"
2834 /* call _start_in_C, passing it the startup %rsp */
2835 "\tcall _start_in_C\n"
2836 "\thlt\n"
sewardj2fedc642005-11-19 02:02:57 +00002837 ".previous\n"
sewardj45f4e7c2005-09-27 19:20:21 +00002838);
sewardja48a4932005-09-29 11:09:56 +00002839#elif defined(VGP_ppc32_linux)
2840asm("\n"
sewardjd9fc3822005-11-18 23:50:43 +00002841 ".text\n"
sewardja48a4932005-09-29 11:09:56 +00002842 "\t.globl _start\n"
2843 "\t.type _start,@function\n"
2844 "_start:\n"
2845 /* set up the new stack in r16 */
2846 "\tlis 16,vgPlain_interim_stack@ha\n"
2847 "\tla 16,vgPlain_interim_stack@l(16)\n"
2848 "\tlis 17,("VG_STRINGIFY(VG_STACK_GUARD_SZB)" >> 16)\n"
2849 "\tori 17,17,("VG_STRINGIFY(VG_STACK_GUARD_SZB)" & 0xFFFF)\n"
2850 "\tlis 18,("VG_STRINGIFY(VG_STACK_ACTIVE_SZB)" >> 16)\n"
2851 "\tori 18,18,("VG_STRINGIFY(VG_STACK_ACTIVE_SZB)" & 0xFFFF)\n"
2852 "\tadd 16,17,16\n"
2853 "\tadd 16,18,16\n"
2854 "\trlwinm 16,16,0,0,27\n"
2855 /* now r16 = &vgPlain_interim_stack + VG_STACK_GUARD_SZB +
2856 VG_STACK_ACTIVE_SZB rounded down to the nearest 16-byte
2857 boundary. And r1 is the original SP. Set the SP to r16 and
2858 call _start_in_C, passing it the initial SP. */
2859 "\tmr 3,1\n"
2860 "\tmr 1,16\n"
2861 "\tbl _start_in_C\n"
2862 "\ttrap\n"
sewardj2fedc642005-11-19 02:02:57 +00002863 ".previous\n"
sewardja48a4932005-09-29 11:09:56 +00002864);
sewardj2c48c7b2005-11-29 13:05:56 +00002865#elif defined(VGP_ppc64_linux)
2866asm("\n"
2867 ".text\n"
cerion21082042005-12-06 19:07:08 +00002868 /* PPC64 ELF ABI says '_start' points to a function descriptor.
2869 So we must have one, and that is what goes into the .opd section. */
2870 "\t.global _start\n"
2871 "\t.section \".opd\",\"aw\"\n"
2872 "\t.align 3\n"
sewardj2c48c7b2005-11-29 13:05:56 +00002873 "_start:\n"
cerion21082042005-12-06 19:07:08 +00002874 "\t.quad ._start,.TOC.@tocbase,0\n"
2875 "\t.previous\n"
2876 "\t.type ._start,@function\n"
2877 "\t.global ._start\n"
2878 "._start:\n"
sewardj2c48c7b2005-11-29 13:05:56 +00002879 /* set up the new stack in r16 */
2880 "\tlis 16, vgPlain_interim_stack@highest\n"
2881 "\tori 16,16,vgPlain_interim_stack@higher\n"
2882 "\tsldi 16,16,32\n"
2883 "\toris 16,16,vgPlain_interim_stack@h\n"
2884 "\tori 16,16,vgPlain_interim_stack@l\n"
2885 "\txor 17,17,17\n"
2886 "\tlis 17,("VG_STRINGIFY(VG_STACK_GUARD_SZB)" >> 16)\n"
2887 "\tori 17,17,("VG_STRINGIFY(VG_STACK_GUARD_SZB)" & 0xFFFF)\n"
2888 "\txor 18,18,18\n"
2889 "\tlis 18,("VG_STRINGIFY(VG_STACK_ACTIVE_SZB)" >> 16)\n"
2890 "\tori 18,18,("VG_STRINGIFY(VG_STACK_ACTIVE_SZB)" & 0xFFFF)\n"
2891 "\tadd 16,17,16\n"
2892 "\tadd 16,18,16\n"
2893 "\trldicr 16,16,0,59\n"
2894 /* now r16 = &vgPlain_interim_stack + VG_STACK_GUARD_SZB +
2895 VG_STACK_ACTIVE_SZB rounded down to the nearest 16-byte
2896 boundary. And r1 is the original SP. Set the SP to r16 and
2897 call _start_in_C, passing it the initial SP. */
2898 "\tmr 3,1\n"
2899 "\tmr 1,16\n"
cerion21082042005-12-06 19:07:08 +00002900 "\tbl ._start_in_C\n"
2901 "\tnop\n"
sewardj2c48c7b2005-11-29 13:05:56 +00002902 "\ttrap\n"
2903 ".previous\n"
2904);
sewardj45f4e7c2005-09-27 19:20:21 +00002905#else
2906#error "_start: needs implementation on this platform"
2907#endif
2908
2909/* Avoid compiler warnings: this fn _is_ used, but labelling it
2910 'static' causes gcc to complain it isn't. */
2911void _start_in_C ( UWord* pArgc );
2912void _start_in_C ( UWord* pArgc )
2913{
2914 Int r;
2915 Word argc = pArgc[0];
2916 HChar** argv = (HChar**)&pArgc[1];
2917 HChar** envp = (HChar**)&pArgc[1+argc+1];
sewardjfdf91b42005-09-28 00:53:09 +00002918 sp_at_startup = (Addr)pArgc;
sewardj45f4e7c2005-09-27 19:20:21 +00002919 r = main( (Int)argc, argv, envp );
2920 VG_(exit)(r);
2921}
2922
sewardjde4a1d02002-03-22 01:27:54 +00002923/*--------------------------------------------------------------------*/
njn04e16982005-05-31 00:23:43 +00002924/*--- end ---*/
sewardjde4a1d02002-03-22 01:27:54 +00002925/*--------------------------------------------------------------------*/