blob: 9faf0c5540095ffaa4f0a0d47ec43cc5f266a247 [file] [log] [blame]
sewardjde4a1d02002-03-22 01:27:54 +00001
2/*--------------------------------------------------------------------*/
njn04e16982005-05-31 00:23:43 +00003/*--- Startup: the real stuff m_main.c ---*/
sewardjde4a1d02002-03-22 01:27:54 +00004/*--------------------------------------------------------------------*/
5
6/*
njnb9c427c2004-12-01 14:14:42 +00007 This file is part of Valgrind, a dynamic binary instrumentation
8 framework.
sewardjde4a1d02002-03-22 01:27:54 +00009
njn53612422005-03-12 16:22:54 +000010 Copyright (C) 2000-2005 Julian Seward
sewardjde4a1d02002-03-22 01:27:54 +000011 jseward@acm.org
sewardjde4a1d02002-03-22 01:27:54 +000012
13 This program is free software; you can redistribute it and/or
14 modify it under the terms of the GNU General Public License as
15 published by the Free Software Foundation; either version 2 of the
16 License, or (at your option) any later version.
17
18 This program is distributed in the hope that it will be useful, but
19 WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 General Public License for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software
25 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
26 02111-1307, USA.
27
njn25e49d8e72002-09-23 09:36:25 +000028 The GNU General Public License is contained in the file COPYING.
sewardjde4a1d02002-03-22 01:27:54 +000029*/
30
njnc7561b92005-06-19 01:24:32 +000031#include "pub_core_basics.h"
32#include "pub_core_threadstate.h"
sewardj45f4e7c2005-09-27 19:20:21 +000033#include "pub_core_clientstate.h"
sewardj55f9d1a2005-04-25 11:11:44 +000034#include "pub_core_aspacemgr.h"
sewardj45f4e7c2005-09-27 19:20:21 +000035#include "pub_core_commandline.h"
njn2521d322005-05-08 14:45:13 +000036#include "pub_core_debuglog.h"
37#include "pub_core_errormgr.h"
38#include "pub_core_execontext.h"
njn97405b22005-06-02 03:39:33 +000039#include "pub_core_libcbase.h"
njn132bfcc2005-06-04 19:16:06 +000040#include "pub_core_libcassert.h"
njneb8896b2005-06-04 20:03:55 +000041#include "pub_core_libcfile.h"
njn36a20fa2005-06-03 03:08:39 +000042#include "pub_core_libcprint.h"
njnf39e9a32005-06-12 02:43:17 +000043#include "pub_core_libcproc.h"
njnde62cbf2005-06-10 22:08:14 +000044#include "pub_core_libcsignal.h"
sewardj45f4e7c2005-09-27 19:20:21 +000045#include "pub_core_syscall.h" // VG_(strerror)
njnf536bbb2005-06-13 04:21:38 +000046#include "pub_core_machine.h"
njnaf1d7df2005-06-11 01:31:52 +000047#include "pub_core_mallocfree.h"
njn20242342005-05-16 23:31:24 +000048#include "pub_core_options.h"
sewardjfdf91b42005-09-28 00:53:09 +000049#include "pub_core_debuginfo.h"
njnd1af0032005-05-29 17:01:48 +000050#include "pub_core_redir.h"
njnc7561b92005-06-19 01:24:32 +000051#include "pub_core_scheduler.h"
njn0c246472005-05-31 01:00:08 +000052#include "pub_core_signals.h"
njn2025cf92005-06-26 20:44:48 +000053#include "pub_core_stacks.h" // For VG_(register_stack)
njnc1b01812005-06-17 22:19:06 +000054#include "pub_core_syswrap.h"
sewardjfdf91b42005-09-28 00:53:09 +000055#include "pub_core_translate.h" // For VG_(translate)
njn43b9a8a2005-05-10 04:37:01 +000056#include "pub_core_tooliface.h"
njna7598f62005-06-18 03:27:58 +000057#include "pub_core_trampoline.h"
njn8bddf582005-05-13 23:40:55 +000058#include "pub_core_transtab.h"
njn08a2e172005-06-21 22:47:54 +000059#include "pub_core_ume.h"
nethercote71980f02004-01-24 18:18:54 +000060
sewardjb5f6f512005-03-10 23:59:00 +000061
nethercote71980f02004-01-24 18:18:54 +000062/*====================================================================*/
63/*=== Counters, for profiling purposes only ===*/
64/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +000065
nethercote3a42fb82004-08-03 18:08:50 +000066static void print_all_stats ( void )
nethercote71980f02004-01-24 18:18:54 +000067{
njn42c83552005-12-05 20:45:59 +000068 VG_(print_translation_stats)();
nethercote92e7b7f2004-08-07 17:52:25 +000069 VG_(print_tt_tc_stats)();
nethercote844e7122004-08-02 15:27:22 +000070 VG_(print_scheduler_stats)();
njn9271cbc2005-03-13 05:38:25 +000071 VG_(print_ExeContext_stats)();
72
nethercote3a42fb82004-08-03 18:08:50 +000073 // Memory stats
nethercote885dd912004-08-03 23:14:00 +000074 if (VG_(clo_verbosity) > 2) {
nethercote3a42fb82004-08-03 18:08:50 +000075 VG_(message)(Vg_DebugMsg, "");
76 VG_(message)(Vg_DebugMsg,
77 "------ Valgrind's internal memory use stats follow ------" );
nethercote885dd912004-08-03 23:14:00 +000078 VG_(sanity_check_malloc_all)();
njn11adeb22005-07-03 20:22:39 +000079 VG_(message)(Vg_DebugMsg, "------" );
nethercote3a42fb82004-08-03 18:08:50 +000080 VG_(print_all_arena_stats)();
nethercote885dd912004-08-03 23:14:00 +000081 VG_(message)(Vg_DebugMsg, "");
nethercote3a42fb82004-08-03 18:08:50 +000082 }
nethercote71980f02004-01-24 18:18:54 +000083}
84
85
86/*====================================================================*/
sewardj5f229e22005-09-28 01:36:01 +000087/*=== Setting up the client's environment ===*/
nethercote71980f02004-01-24 18:18:54 +000088/*====================================================================*/
89
nethercote71980f02004-01-24 18:18:54 +000090/* Prepare the client's environment. This is basically a copy of our
91 environment, except:
sewardj45f4e7c2005-09-27 19:20:21 +000092
njn9d5564d2005-09-29 00:25:07 +000093 LD_PRELOAD=$VALGRIND_LIB/vgpreload_core.so:
sewardj45f4e7c2005-09-27 19:20:21 +000094 ($VALGRIND_LIB/vgpreload_TOOL.so:)?
95 $LD_PRELOAD
nethercote71980f02004-01-24 18:18:54 +000096
sewardjb5f6f512005-03-10 23:59:00 +000097 If this is missing, then it is added.
nethercote71980f02004-01-24 18:18:54 +000098
sewardj45f4e7c2005-09-27 19:20:21 +000099 Also, remove any binding for VALGRIND_LAUNCHER=. The client should
100 not be able to see this.
nethercote71980f02004-01-24 18:18:54 +0000101
102 If this needs to handle any more variables it should be hacked
sewardj45f4e7c2005-09-27 19:20:21 +0000103 into something table driven. The copy is VG_(malloc)'d space.
104*/
105static HChar** setup_client_env ( HChar** origenv, const HChar* toolname)
nethercote71980f02004-01-24 18:18:54 +0000106{
tomfb7bcde2005-11-07 15:24:38 +0000107 HChar* preload_core = "vgpreload_core";
sewardj45f4e7c2005-09-27 19:20:21 +0000108 HChar* ld_preload = "LD_PRELOAD=";
109 HChar* v_launcher = VALGRIND_LAUNCHER "=";
110 Int ld_preload_len = VG_(strlen)( ld_preload );
111 Int v_launcher_len = VG_(strlen)( v_launcher );
112 Bool ld_preload_done = False;
113 Int vglib_len = VG_(strlen)(VG_(libdir));
nethercote71980f02004-01-24 18:18:54 +0000114
sewardj45f4e7c2005-09-27 19:20:21 +0000115 HChar** cpp;
116 HChar** ret;
tom60a4b0b2005-10-12 10:45:27 +0000117 HChar* preload_tool_path;
sewardj45f4e7c2005-09-27 19:20:21 +0000118 Int envc, i;
nethercote71980f02004-01-24 18:18:54 +0000119
sewardj45f4e7c2005-09-27 19:20:21 +0000120 /* Alloc space for the vgpreload_core.so path and vgpreload_<tool>.so
121 paths. We might not need the space for vgpreload_<tool>.so, but it
122 doesn't hurt to over-allocate briefly. The 16s are just cautious
123 slop. */
tomfb7bcde2005-11-07 15:24:38 +0000124 Int preload_core_path_len = vglib_len + sizeof(preload_core) + sizeof(VG_PLATFORM) + 16;
125 Int preload_tool_path_len = vglib_len + VG_(strlen)(toolname) + sizeof(VG_PLATFORM) + 16;
sewardj45f4e7c2005-09-27 19:20:21 +0000126 Int preload_string_len = preload_core_path_len + preload_tool_path_len;
127 HChar* preload_string = VG_(malloc)(preload_string_len);
128 vg_assert(preload_string);
129
130 /* Determine if there's a vgpreload_<tool>.so file, and setup
131 preload_string. */
132 preload_tool_path = VG_(malloc)(preload_tool_path_len);
133 vg_assert(preload_tool_path);
134 VG_(snprintf)(preload_tool_path, preload_tool_path_len,
tomfb7bcde2005-11-07 15:24:38 +0000135 "%s/%s/vgpreload_%s.so", VG_(libdir), VG_PLATFORM, toolname);
sewardj45f4e7c2005-09-27 19:20:21 +0000136 if (VG_(access)(preload_tool_path, True/*r*/, False/*w*/, False/*x*/) == 0) {
tomfb7bcde2005-11-07 15:24:38 +0000137 VG_(snprintf)(preload_string, preload_string_len, "%s/%s/%s.so:%s",
138 VG_(libdir), VG_PLATFORM, preload_core, preload_tool_path);
sewardj45f4e7c2005-09-27 19:20:21 +0000139 } else {
tomfb7bcde2005-11-07 15:24:38 +0000140 VG_(snprintf)(preload_string, preload_string_len, "%s/%s/%s.so",
141 VG_(libdir), VG_PLATFORM, preload_core);
sewardj45f4e7c2005-09-27 19:20:21 +0000142 }
143 VG_(free)(preload_tool_path);
144
sewardja48a4932005-09-29 11:09:56 +0000145 VG_(debugLog)(2, "main", "preload_string:\n");
146 VG_(debugLog)(2, "main", " \"%s\"\n", preload_string);
sewardj45f4e7c2005-09-27 19:20:21 +0000147
nethercote71980f02004-01-24 18:18:54 +0000148 /* Count the original size of the env */
sewardj45f4e7c2005-09-27 19:20:21 +0000149 envc = 0;
nethercote71980f02004-01-24 18:18:54 +0000150 for (cpp = origenv; cpp && *cpp; cpp++)
151 envc++;
152
153 /* Allocate a new space */
sewardj45f4e7c2005-09-27 19:20:21 +0000154 ret = VG_(malloc) (sizeof(HChar *) * (envc+1+1)); /* 1 new entry + NULL */
nethercote7c018f42004-07-17 16:40:50 +0000155 vg_assert(ret);
nethercote71980f02004-01-24 18:18:54 +0000156
157 /* copy it over */
158 for (cpp = ret; *origenv; )
159 *cpp++ = *origenv++;
160 *cpp = NULL;
161
162 vg_assert(envc == (cpp - ret));
163
164 /* Walk over the new environment, mashing as we go */
165 for (cpp = ret; cpp && *cpp; cpp++) {
sewardj45f4e7c2005-09-27 19:20:21 +0000166 if (VG_(memcmp)(*cpp, ld_preload, ld_preload_len) == 0) {
167 Int len = VG_(strlen)(*cpp) + preload_string_len;
168 HChar *cp = VG_(malloc)(len);
nethercote7c018f42004-07-17 16:40:50 +0000169 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000170
sewardj45f4e7c2005-09-27 19:20:21 +0000171 VG_(snprintf)(cp, len, "%s%s:%s",
172 ld_preload, preload_string, (*cpp)+ld_preload_len);
nethercote71980f02004-01-24 18:18:54 +0000173
sewardj45f4e7c2005-09-27 19:20:21 +0000174 *cpp = cp;
175
176 ld_preload_done = True;
nethercote71980f02004-01-24 18:18:54 +0000177 }
178 }
179
180 /* Add the missing bits */
nethercote71980f02004-01-24 18:18:54 +0000181 if (!ld_preload_done) {
sewardj45f4e7c2005-09-27 19:20:21 +0000182 Int len = ld_preload_len + preload_string_len;
183 HChar *cp = VG_(malloc) (len);
nethercote7c018f42004-07-17 16:40:50 +0000184 vg_assert(cp);
sewardj45f4e7c2005-09-27 19:20:21 +0000185
186 VG_(snprintf)(cp, len, "%s%s", ld_preload, preload_string);
187
nethercote71980f02004-01-24 18:18:54 +0000188 ret[envc++] = cp;
189 }
190
sewardj45f4e7c2005-09-27 19:20:21 +0000191 /* ret[0 .. envc-1] is live now. */
192 /* Find and remove a binding for VALGRIND_LAUNCHER. */
193 for (i = 0; i < envc; i++)
194 if (0 == VG_(memcmp(ret[i], v_launcher, v_launcher_len)))
195 break;
196
197 if (i < envc) {
198 for (; i < envc-1; i++)
199 ret[i] = ret[i+1];
200 envc--;
201 }
202
203 VG_(free)(preload_string);
nethercote71980f02004-01-24 18:18:54 +0000204 ret[envc] = NULL;
205
206 return ret;
207}
208
nethercote71980f02004-01-24 18:18:54 +0000209
sewardj5f229e22005-09-28 01:36:01 +0000210/*====================================================================*/
211/*=== Setting up the client's stack ===*/
212/*====================================================================*/
213
214#ifndef AT_DCACHEBSIZE
215#define AT_DCACHEBSIZE 19
216#endif /* AT_DCACHEBSIZE */
217
218#ifndef AT_ICACHEBSIZE
219#define AT_ICACHEBSIZE 20
220#endif /* AT_ICACHEBSIZE */
221
222#ifndef AT_UCACHEBSIZE
223#define AT_UCACHEBSIZE 21
224#endif /* AT_UCACHEBSIZE */
225
226#ifndef AT_SYSINFO
227#define AT_SYSINFO 32
228#endif /* AT_SYSINFO */
229
230#ifndef AT_SYSINFO_EHDR
231#define AT_SYSINFO_EHDR 33
232#endif /* AT_SYSINFO_EHDR */
233
234#ifndef AT_SECURE
235#define AT_SECURE 23 /* secure mode boolean */
236#endif /* AT_SECURE */
237
nethercote71980f02004-01-24 18:18:54 +0000238/* Add a string onto the string table, and return its address */
239static char *copy_str(char **tab, const char *str)
240{
241 char *cp = *tab;
242 char *orig = cp;
243
244 while(*str)
245 *cp++ = *str++;
246 *cp++ = '\0';
247
248 if (0)
sewardj45f4e7c2005-09-27 19:20:21 +0000249 VG_(printf)("copied %p \"%s\" len %lld\n", orig, orig, (Long)(cp-orig));
nethercote71980f02004-01-24 18:18:54 +0000250
251 *tab = cp;
252
253 return orig;
254}
255
sewardj5f229e22005-09-28 01:36:01 +0000256
257/* ----------------------------------------------------------------
258
nethercote71980f02004-01-24 18:18:54 +0000259 This sets up the client's initial stack, containing the args,
260 environment and aux vector.
261
262 The format of the stack is:
263
sewardj45f4e7c2005-09-27 19:20:21 +0000264 higher address +-----------------+ <- clstack_end
nethercote71980f02004-01-24 18:18:54 +0000265 | |
266 : string table :
267 | |
268 +-----------------+
269 | AT_NULL |
270 - -
271 | auxv |
272 +-----------------+
sewardjfdf91b42005-09-28 00:53:09 +0000273 | NULL |
nethercote71980f02004-01-24 18:18:54 +0000274 - -
275 | envp |
276 +-----------------+
sewardjfdf91b42005-09-28 00:53:09 +0000277 | NULL |
nethercote71980f02004-01-24 18:18:54 +0000278 - -
279 | argv |
280 +-----------------+
281 | argc |
nethercote4ad74312004-10-26 09:59:49 +0000282 lower address +-----------------+ <- sp
nethercote71980f02004-01-24 18:18:54 +0000283 | undefined |
284 : :
sewardj45f4e7c2005-09-27 19:20:21 +0000285
sewardjfdf91b42005-09-28 00:53:09 +0000286 Allocate and create the initial client stack. It is allocated down
sewardj45f4e7c2005-09-27 19:20:21 +0000287 from clstack_end, which was previously determined by the address
sewardjfdf91b42005-09-28 00:53:09 +0000288 space manager. The returned value is the SP value for the client.
289
290 The client's auxv is created by copying and modifying our own one.
291 As a side effect of scanning our own auxv, some important bits of
292 info are collected:
293
294 VG_(cache_line_size_ppc32) // ppc32 only -- cache line size
295 VG_(have_altivec_ppc32) // ppc32 only -- is Altivec supported?
sewardj5f229e22005-09-28 01:36:01 +0000296
297 ---------------------------------------------------------------- */
sewardjfdf91b42005-09-28 00:53:09 +0000298
sewardj45f4e7c2005-09-27 19:20:21 +0000299static
300Addr setup_client_stack( void* init_sp,
301 char** orig_envp,
sewardj13247ca2005-12-30 22:52:20 +0000302 const ExeInfo* info,
sewardj45f4e7c2005-09-27 19:20:21 +0000303 UInt** client_auxv,
304 Addr clstack_end,
305 SizeT clstack_max_size )
nethercote71980f02004-01-24 18:18:54 +0000306{
njn83407492005-06-19 16:10:47 +0000307 SysRes res;
nethercote71980f02004-01-24 18:18:54 +0000308 char **cpp;
309 char *strtab; /* string table */
310 char *stringbase;
nethercotea3c3cf22004-11-01 18:38:00 +0000311 Addr *ptr;
nethercote71980f02004-01-24 18:18:54 +0000312 struct ume_auxv *auxv;
313 const struct ume_auxv *orig_auxv;
314 const struct ume_auxv *cauxv;
315 unsigned stringsize; /* total size of strings in bytes */
316 unsigned auxsize; /* total size of auxv in bytes */
sewardj45f4e7c2005-09-27 19:20:21 +0000317 Int argc; /* total argc */
318 Int envc; /* total number of env vars */
nethercote71980f02004-01-24 18:18:54 +0000319 unsigned stacksize; /* total client stack size */
sewardj45f4e7c2005-09-27 19:20:21 +0000320 Addr client_SP; /* client stack base (initial SP) */
321 Addr clstack_start;
322 Int i;
323 Bool have_exename;
324
325 vg_assert(VG_IS_PAGE_ALIGNED(clstack_end+1));
nethercote71980f02004-01-24 18:18:54 +0000326
327 /* use our own auxv as a prototype */
njn62ff0f22005-06-21 23:03:36 +0000328 orig_auxv = VG_(find_auxv)(init_sp);
nethercote71980f02004-01-24 18:18:54 +0000329
330 /* ==================== compute sizes ==================== */
331
332 /* first of all, work out how big the client stack will be */
sewardj45f4e7c2005-09-27 19:20:21 +0000333 stringsize = 0;
334 have_exename = VG_(args_the_exename) != NULL;
nethercote71980f02004-01-24 18:18:54 +0000335
336 /* paste on the extra args if the loader needs them (ie, the #!
337 interpreter and its argument) */
338 argc = 0;
nethercoted6a56872004-07-26 15:32:47 +0000339 if (info->interp_name != NULL) {
nethercote71980f02004-01-24 18:18:54 +0000340 argc++;
sewardj45f4e7c2005-09-27 19:20:21 +0000341 stringsize += VG_(strlen)(info->interp_name) + 1;
nethercote71980f02004-01-24 18:18:54 +0000342 }
nethercoted6a56872004-07-26 15:32:47 +0000343 if (info->interp_args != NULL) {
nethercote71980f02004-01-24 18:18:54 +0000344 argc++;
sewardj45f4e7c2005-09-27 19:20:21 +0000345 stringsize += VG_(strlen)(info->interp_args) + 1;
nethercote71980f02004-01-24 18:18:54 +0000346 }
347
348 /* now scan the args we're given... */
sewardj45f4e7c2005-09-27 19:20:21 +0000349 if (have_exename)
350 stringsize += VG_(strlen)( VG_(args_the_exename) ) + 1;
351
352 for (i = 0; i < VG_(args_for_client).used; i++) {
nethercote71980f02004-01-24 18:18:54 +0000353 argc++;
sewardj45f4e7c2005-09-27 19:20:21 +0000354 stringsize += VG_(strlen)( VG_(args_for_client).strs[i] ) + 1;
nethercote71980f02004-01-24 18:18:54 +0000355 }
sewardj45f4e7c2005-09-27 19:20:21 +0000356
nethercote71980f02004-01-24 18:18:54 +0000357 /* ...and the environment */
358 envc = 0;
359 for (cpp = orig_envp; cpp && *cpp; cpp++) {
360 envc++;
sewardj45f4e7c2005-09-27 19:20:21 +0000361 stringsize += VG_(strlen)(*cpp) + 1;
nethercote71980f02004-01-24 18:18:54 +0000362 }
363
364 /* now, how big is the auxv? */
365 auxsize = sizeof(*auxv); /* there's always at least one entry: AT_NULL */
366 for (cauxv = orig_auxv; cauxv->a_type != AT_NULL; cauxv++) {
367 if (cauxv->a_type == AT_PLATFORM)
sewardj45f4e7c2005-09-27 19:20:21 +0000368 stringsize += VG_(strlen)(cauxv->u.a_ptr) + 1;
nethercote71980f02004-01-24 18:18:54 +0000369 auxsize += sizeof(*cauxv);
370 }
371
cerionc7266522005-12-08 03:24:37 +0000372# if defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux)
cerion85665ca2005-06-20 15:51:07 +0000373 auxsize += 2 * sizeof(*cauxv);
sewardjfdf91b42005-09-28 00:53:09 +0000374# endif
cerion85665ca2005-06-20 15:51:07 +0000375
nethercote71980f02004-01-24 18:18:54 +0000376 /* OK, now we know how big the client stack is */
377 stacksize =
sewardj45f4e7c2005-09-27 19:20:21 +0000378 sizeof(Word) + /* argc */
379 (have_exename ? sizeof(char **) : 0) + /* argc[0] == exename */
380 sizeof(char **)*argc + /* argv */
381 sizeof(char **) + /* terminal NULL */
382 sizeof(char **)*envc + /* envp */
383 sizeof(char **) + /* terminal NULL */
384 auxsize + /* auxv */
sewardj90d38542005-09-27 23:53:09 +0000385 VG_ROUNDUP(stringsize, sizeof(Word)); /* strings (aligned) */
nethercote71980f02004-01-24 18:18:54 +0000386
sewardj79048ce2005-02-18 08:28:32 +0000387 if (0) VG_(printf)("stacksize = %d\n", stacksize);
388
sewardj45f4e7c2005-09-27 19:20:21 +0000389 /* client_SP is the client's stack pointer */
390 client_SP = clstack_end - stacksize;
391 client_SP = VG_ROUNDDN(client_SP, 16); /* make stack 16 byte aligned */
nethercote71980f02004-01-24 18:18:54 +0000392
nethercote71980f02004-01-24 18:18:54 +0000393 /* base of the string table (aligned) */
sewardj45f4e7c2005-09-27 19:20:21 +0000394 stringbase = strtab = (char *)clstack_end
395 - VG_ROUNDUP(stringsize, sizeof(int));
nethercote71980f02004-01-24 18:18:54 +0000396
sewardj45f4e7c2005-09-27 19:20:21 +0000397 clstack_start = VG_PGROUNDDN(client_SP);
398
399 /* The max stack size */
400 clstack_max_size = VG_PGROUNDUP(clstack_max_size);
401
402 /* Record stack extent -- needed for stack-change code. */
403 VG_(clstk_base) = clstack_start;
404 VG_(clstk_end) = clstack_end;
nethercote71980f02004-01-24 18:18:54 +0000405
sewardj79048ce2005-02-18 08:28:32 +0000406 if (0)
sewardj45f4e7c2005-09-27 19:20:21 +0000407 VG_(printf)("stringsize=%d auxsize=%d stacksize=%d maxsize=0x%x\n"
408 "clstack_start %p\n"
409 "clstack_end %p\n",
410 stringsize, auxsize, stacksize, (Int)clstack_max_size,
411 (void*)clstack_start, (void*)clstack_end);
nethercote5ee67ca2004-06-22 14:00:09 +0000412
nethercote71980f02004-01-24 18:18:54 +0000413 /* ==================== allocate space ==================== */
414
sewardj45f4e7c2005-09-27 19:20:21 +0000415 { SizeT anon_size = clstack_end - clstack_start + 1;
416 SizeT resvn_size = clstack_max_size - anon_size;
417 Addr anon_start = clstack_start;
418 Addr resvn_start = anon_start - resvn_size;
419 SizeT inner_HACK = 0;
tom60a4b0b2005-10-12 10:45:27 +0000420 Bool ok;
nethercote71980f02004-01-24 18:18:54 +0000421
sewardjc6527d62006-02-13 17:54:31 +0000422 /* So far we've only accounted for space requirements down to the
423 stack pointer. If this target's ABI requires a redzone below
424 the stack pointer, we need to allocate an extra page, to
425 handle the worst case in which the stack pointer is almost at
426 the bottom of a page, and so there is insufficient room left
427 over to put the redzone in. In this case the simple thing to
428 do is allocate an extra page, by shrinking the reservation by
429 one page and growing the anonymous area by a corresponding
430 page. */
431 vg_assert(VG_STACK_REDZONE_SZB >= 0);
432 vg_assert(VG_STACK_REDZONE_SZB < VKI_PAGE_SIZE);
433 if (VG_STACK_REDZONE_SZB > 0) {
434 vg_assert(resvn_size > VKI_PAGE_SIZE);
435 resvn_size -= VKI_PAGE_SIZE;
436 anon_start -= VKI_PAGE_SIZE;
437 anon_size += VKI_PAGE_SIZE;
438 }
439
sewardj45f4e7c2005-09-27 19:20:21 +0000440 vg_assert(VG_IS_PAGE_ALIGNED(anon_size));
441 vg_assert(VG_IS_PAGE_ALIGNED(resvn_size));
442 vg_assert(VG_IS_PAGE_ALIGNED(anon_start));
443 vg_assert(VG_IS_PAGE_ALIGNED(resvn_start));
444 vg_assert(resvn_start == clstack_end + 1 - clstack_max_size);
nethercote71980f02004-01-24 18:18:54 +0000445
sewardj45f4e7c2005-09-27 19:20:21 +0000446# ifdef ENABLE_INNER
447 inner_HACK = 1024*1024; // create 1M non-fault-extending stack
448# endif
nethercote71980f02004-01-24 18:18:54 +0000449
sewardj45f4e7c2005-09-27 19:20:21 +0000450 if (0)
451 VG_(printf)("%p 0x%x %p 0x%x\n",
452 resvn_start, resvn_size, anon_start, anon_size);
nethercote71980f02004-01-24 18:18:54 +0000453
sewardj45f4e7c2005-09-27 19:20:21 +0000454 /* Create a shrinkable reservation followed by an anonymous
455 segment. Together these constitute a growdown stack. */
tom60a4b0b2005-10-12 10:45:27 +0000456 ok = VG_(am_create_reservation)(
457 resvn_start,
458 resvn_size -inner_HACK,
459 SmUpper,
460 anon_size +inner_HACK
461 );
sewardj45f4e7c2005-09-27 19:20:21 +0000462 vg_assert(ok);
463 /* allocate a stack - mmap enough space for the stack */
464 res = VG_(am_mmap_anon_fixed_client)(
465 anon_start -inner_HACK,
466 anon_size +inner_HACK,
467 VKI_PROT_READ|VKI_PROT_WRITE|VKI_PROT_EXEC
468 );
469 vg_assert(!res.isError);
470 }
471
472 /* ==================== create client stack ==================== */
473
474 ptr = (Addr*)client_SP;
475
476 /* --- client argc --- */
477 *ptr++ = argc + (have_exename ? 1 : 0);
478
479 /* --- client argv --- */
nethercoted6a56872004-07-26 15:32:47 +0000480 if (info->interp_name) {
nethercotea3c3cf22004-11-01 18:38:00 +0000481 *ptr++ = (Addr)copy_str(&strtab, info->interp_name);
sewardj45f4e7c2005-09-27 19:20:21 +0000482 VG_(free)(info->interp_name);
nethercote71980f02004-01-24 18:18:54 +0000483 }
nethercoted6a56872004-07-26 15:32:47 +0000484 if (info->interp_args) {
nethercotea3c3cf22004-11-01 18:38:00 +0000485 *ptr++ = (Addr)copy_str(&strtab, info->interp_args);
sewardj45f4e7c2005-09-27 19:20:21 +0000486 VG_(free)(info->interp_args);
nethercote71980f02004-01-24 18:18:54 +0000487 }
sewardj45f4e7c2005-09-27 19:20:21 +0000488
489 if (have_exename)
490 *ptr++ = (Addr)copy_str(&strtab, VG_(args_the_exename));
491
492 for (i = 0; i < VG_(args_for_client).used; i++) {
493 *ptr++ = (Addr)copy_str(&strtab, VG_(args_for_client).strs[i]);
nethercote71980f02004-01-24 18:18:54 +0000494 }
495 *ptr++ = 0;
496
497 /* --- envp --- */
498 VG_(client_envp) = (Char **)ptr;
499 for (cpp = orig_envp; cpp && *cpp; ptr++, cpp++)
nethercotea3c3cf22004-11-01 18:38:00 +0000500 *ptr = (Addr)copy_str(&strtab, *cpp);
nethercote71980f02004-01-24 18:18:54 +0000501 *ptr++ = 0;
502
503 /* --- auxv --- */
504 auxv = (struct ume_auxv *)ptr;
505 *client_auxv = (UInt *)auxv;
506
cerionc7266522005-12-08 03:24:37 +0000507# if defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux)
cerion85665ca2005-06-20 15:51:07 +0000508 auxv[0].a_type = AT_IGNOREPPC;
509 auxv[0].u.a_val = AT_IGNOREPPC;
510 auxv[1].a_type = AT_IGNOREPPC;
511 auxv[1].u.a_val = AT_IGNOREPPC;
512 auxv += 2;
sewardjfdf91b42005-09-28 00:53:09 +0000513# endif
cerion85665ca2005-06-20 15:51:07 +0000514
nethercote71980f02004-01-24 18:18:54 +0000515 for (; orig_auxv->a_type != AT_NULL; auxv++, orig_auxv++) {
sewardjfdf91b42005-09-28 00:53:09 +0000516
nethercote71980f02004-01-24 18:18:54 +0000517 /* copy the entry... */
518 *auxv = *orig_auxv;
519
sewardjfdf91b42005-09-28 00:53:09 +0000520 /* ...and fix up / examine the copy */
nethercote71980f02004-01-24 18:18:54 +0000521 switch(auxv->a_type) {
nethercote71980f02004-01-24 18:18:54 +0000522
sewardjfdf91b42005-09-28 00:53:09 +0000523 case AT_IGNORE:
524 case AT_PHENT:
525 case AT_PAGESZ:
526 case AT_FLAGS:
527 case AT_NOTELF:
528 case AT_UID:
529 case AT_EUID:
530 case AT_GID:
531 case AT_EGID:
532 case AT_CLKTCK:
533 case AT_FPUCW:
sewardjfdf91b42005-09-28 00:53:09 +0000534 /* All these are pointerless, so we don't need to do
535 anything about them. */
536 break;
nethercote71980f02004-01-24 18:18:54 +0000537
sewardjfdf91b42005-09-28 00:53:09 +0000538 case AT_PHDR:
539 if (info->phdr == 0)
540 auxv->a_type = AT_IGNORE;
541 else
542 auxv->u.a_val = info->phdr;
543 break;
nethercote71980f02004-01-24 18:18:54 +0000544
sewardjfdf91b42005-09-28 00:53:09 +0000545 case AT_PHNUM:
546 if (info->phdr == 0)
547 auxv->a_type = AT_IGNORE;
548 else
549 auxv->u.a_val = info->phnum;
550 break;
nethercote71980f02004-01-24 18:18:54 +0000551
sewardjfdf91b42005-09-28 00:53:09 +0000552 case AT_BASE:
553 auxv->u.a_val = info->interp_base;
554 break;
nethercote71980f02004-01-24 18:18:54 +0000555
sewardjfdf91b42005-09-28 00:53:09 +0000556 case AT_PLATFORM:
557 /* points to a platform description string */
558 auxv->u.a_ptr = copy_str(&strtab, orig_auxv->u.a_ptr);
559 break;
nethercote71980f02004-01-24 18:18:54 +0000560
sewardjfdf91b42005-09-28 00:53:09 +0000561 case AT_ENTRY:
562 auxv->u.a_val = info->entry;
563 break;
nethercote71980f02004-01-24 18:18:54 +0000564
sewardjfdf91b42005-09-28 00:53:09 +0000565 case AT_HWCAP:
sewardjfdf91b42005-09-28 00:53:09 +0000566 break;
nethercote71980f02004-01-24 18:18:54 +0000567
sewardjfdf91b42005-09-28 00:53:09 +0000568 case AT_DCACHEBSIZE:
569 case AT_ICACHEBSIZE:
570 case AT_UCACHEBSIZE:
571# if defined(VGP_ppc32_linux)
572 /* acquire cache info */
573 if (auxv->u.a_val > 0) {
sewardje3826cf2005-11-13 00:30:22 +0000574 VG_(machine_ppc32_set_clszB)( auxv->u.a_val );
sewardja48a4932005-09-29 11:09:56 +0000575 VG_(debugLog)(2, "main",
sewardjfdf91b42005-09-28 00:53:09 +0000576 "PPC32 cache line size %u (type %u)\n",
577 (UInt)auxv->u.a_val, (UInt)auxv->a_type );
578 }
cerionc7266522005-12-08 03:24:37 +0000579# elif defined(VGP_ppc64_linux)
580 /* acquire cache info */
581 if (auxv->u.a_val > 0) {
582 VG_(machine_ppc64_set_clszB)( auxv->u.a_val );
583 VG_(debugLog)(2, "main",
584 "PPC64 cache line size %u (type %u)\n",
585 (UInt)auxv->u.a_val, (UInt)auxv->a_type );
586 }
sewardjfdf91b42005-09-28 00:53:09 +0000587# endif
588 break;
nethercote71980f02004-01-24 18:18:54 +0000589
cerionc7266522005-12-08 03:24:37 +0000590# if defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux)
sewardjfdf91b42005-09-28 00:53:09 +0000591 case AT_IGNOREPPC:
592 break;
593# endif
594
595 case AT_SECURE:
596 /* If this is 1, then it means that this program is
597 running suid, and therefore the dynamic linker should
598 be careful about LD_PRELOAD, etc. However, since
599 stage1 (the thing the kernel actually execve's) should
600 never be SUID, and we need LD_PRELOAD to work for the
601 client, we set AT_SECURE to 0. */
602 auxv->u.a_val = 0;
603 break;
604
tom2315d182005-11-11 08:39:34 +0000605 case AT_SYSINFO:
cerionc7266522005-12-08 03:24:37 +0000606# if !defined(VGP_ppc32_linux) && !defined(VGP_ppc64_linux)
sewardjfdf91b42005-09-28 00:53:09 +0000607 case AT_SYSINFO_EHDR:
tom2315d182005-11-11 08:39:34 +0000608# endif
sewardjfdf91b42005-09-28 00:53:09 +0000609 /* Trash this, because we don't reproduce it */
610 auxv->a_type = AT_IGNORE;
611 break;
sewardjfdf91b42005-09-28 00:53:09 +0000612
613 default:
614 /* stomp out anything we don't know about */
615 VG_(debugLog)(2, "main",
616 "stomping auxv entry %lld\n",
617 (ULong)auxv->a_type);
618 auxv->a_type = AT_IGNORE;
619 break;
nethercote71980f02004-01-24 18:18:54 +0000620 }
621 }
622 *auxv = *orig_auxv;
623 vg_assert(auxv->a_type == AT_NULL);
624
625 vg_assert((strtab-stringbase) == stringsize);
626
sewardj45f4e7c2005-09-27 19:20:21 +0000627 /* client_SP is pointing at client's argc/argv */
nethercote5ee67ca2004-06-22 14:00:09 +0000628
sewardj45f4e7c2005-09-27 19:20:21 +0000629 if (0) VG_(printf)("startup SP = %p\n", client_SP);
630 return client_SP;
nethercote71980f02004-01-24 18:18:54 +0000631}
632
sewardj45f4e7c2005-09-27 19:20:21 +0000633
634/* Allocate the client data segment. It is an expandable anonymous
635 mapping abutting a shrinkable reservation of size max_dseg_size.
636 The data segment starts at VG_(brk_base), which is page-aligned,
637 and runs up to VG_(brk_limit), which isn't. */
638
639static void setup_client_dataseg ( SizeT max_size )
640{
641 Bool ok;
642 SysRes sres;
643 Addr anon_start = VG_(brk_base);
644 SizeT anon_size = VKI_PAGE_SIZE;
645 Addr resvn_start = anon_start + anon_size;
646 SizeT resvn_size = max_size - anon_size;
647
648 vg_assert(VG_IS_PAGE_ALIGNED(anon_size));
649 vg_assert(VG_IS_PAGE_ALIGNED(resvn_size));
650 vg_assert(VG_IS_PAGE_ALIGNED(anon_start));
651 vg_assert(VG_IS_PAGE_ALIGNED(resvn_start));
652
653 /* Because there's been no brk activity yet: */
654 vg_assert(VG_(brk_base) == VG_(brk_limit));
655
656 /* Try to create the data seg and associated reservation where
657 VG_(brk_base) says. */
658 ok = VG_(am_create_reservation)(
659 resvn_start,
660 resvn_size,
661 SmLower,
662 anon_size
663 );
664
665 if (!ok) {
666 /* Hmm, that didn't work. Well, let aspacem suggest an address
667 it likes better, and try again with that. */
668 anon_start = VG_(am_get_advisory_client_simple)
669 ( 0/*floating*/, anon_size+resvn_size, &ok );
670 if (ok) {
671 resvn_start = anon_start + anon_size;
672 ok = VG_(am_create_reservation)(
673 resvn_start,
674 resvn_size,
675 SmLower,
676 anon_size
677 );
678 if (ok)
679 VG_(brk_base) = VG_(brk_limit) = anon_start;
680 }
681 /* that too might have failed, but if it has, we're hosed: there
682 is no Plan C. */
683 }
684 vg_assert(ok);
685
njn7c555a92005-11-16 17:16:10 +0000686 /* We make the data segment (heap) executable because LinuxThreads on
njn0ddabca2005-11-16 23:54:46 +0000687 ppc32 creates trampolines in this area. Also, on x86/Linux the data
688 segment is RWX natively, at least according to /proc/self/maps.
689 Also, having a non-executable data seg would kill any program which
690 tried to create code in the data seg and then run it. */
sewardj45f4e7c2005-09-27 19:20:21 +0000691 sres = VG_(am_mmap_anon_fixed_client)(
692 anon_start,
693 anon_size,
sewardj33ca9e82005-11-16 17:12:38 +0000694 VKI_PROT_READ|VKI_PROT_WRITE|VKI_PROT_EXEC
sewardj45f4e7c2005-09-27 19:20:21 +0000695 );
696 vg_assert(!sres.isError);
697 vg_assert(sres.val == anon_start);
698}
699
700
nethercote71980f02004-01-24 18:18:54 +0000701/*====================================================================*/
702/*=== Find executable ===*/
703/*====================================================================*/
704
sewardjfdf91b42005-09-28 00:53:09 +0000705/* Scan a colon-separated list, and call a function on each element.
706 The string must be mutable, because we insert a temporary '\0', but
707 the string will end up unmodified. (*func) should return True if it
708 doesn't need to see any more.
709
710 This routine will return True if (*func) returns True and False if
711 it reaches the end of the list without that happening.
712*/
713static Bool scan_colsep(char *colsep, Bool (*func)(const char *))
714{
715 char *cp, *entry;
716 int end;
717
718 if (colsep == NULL ||
719 *colsep == '\0')
720 return False;
721
722 entry = cp = colsep;
723
724 do {
725 end = (*cp == '\0');
726
727 if (*cp == ':' || *cp == '\0') {
728 char save = *cp;
729
730 *cp = '\0';
731 if ((*func)(entry)) {
732 *cp = save;
733 return True;
734 }
735 *cp = save;
736 entry = cp+1;
737 }
738 cp++;
739 } while(!end);
740
741 return False;
742}
743
sewardj45f4e7c2005-09-27 19:20:21 +0000744/* Need a static copy because can't use dynamic mem allocation yet */
njn73750612005-10-14 03:11:30 +0000745static HChar executable_name_in [VKI_PATH_MAX];
746static HChar executable_name_out[VKI_PATH_MAX];
thughes4ad52d02004-06-27 17:37:21 +0000747
sewardj45f4e7c2005-09-27 19:20:21 +0000748static Bool match_executable(const char *entry)
749{
njn73750612005-10-14 03:11:30 +0000750 HChar buf[VG_(strlen)(entry) + VG_(strlen)(executable_name_in) + 3];
thughes4ad52d02004-06-27 17:37:21 +0000751
njn73750612005-10-14 03:11:30 +0000752 /* empty PATH element means '.' */
thughes4ad52d02004-06-27 17:37:21 +0000753 if (*entry == '\0')
754 entry = ".";
755
njn73750612005-10-14 03:11:30 +0000756 VG_(snprintf)(buf, sizeof(buf), "%s/%s", entry, executable_name_in);
757
758 // Don't match directories
759 if (VG_(is_dir)(buf))
760 return False;
761
762 // If we match an executable, we choose that immediately. If we find a
763 // matching non-executable we remember it but keep looking for an
764 // matching executable later in the path.
sewardj45f4e7c2005-09-27 19:20:21 +0000765 if (VG_(access)(buf, True/*r*/, False/*w*/, True/*x*/) == 0) {
njn73750612005-10-14 03:11:30 +0000766 VG_(strncpy)( executable_name_out, buf, VKI_PATH_MAX-1 );
767 executable_name_out[VKI_PATH_MAX-1] = 0;
768 return True; // Stop looking
769 } else if (VG_(access)(buf, True/*r*/, False/*w*/, False/*x*/) == 0
770 && VG_STREQ(executable_name_out, ""))
771 {
772 VG_(strncpy)( executable_name_out, buf, VKI_PATH_MAX-1 );
773 executable_name_out[VKI_PATH_MAX-1] = 0;
774 return False; // Keep looking
775 } else {
776 return False; // Keep looking
thughes4ad52d02004-06-27 17:37:21 +0000777 }
thughes4ad52d02004-06-27 17:37:21 +0000778}
779
njn73750612005-10-14 03:11:30 +0000780// Returns NULL if it wasn't found.
sewardj45f4e7c2005-09-27 19:20:21 +0000781static HChar* find_executable ( HChar* exec )
nethercote71980f02004-01-24 18:18:54 +0000782{
783 vg_assert(NULL != exec);
njn73750612005-10-14 03:11:30 +0000784 if (VG_(strchr)(exec, '/')) {
785 // Has a '/' - use the name as is
786 VG_(strncpy)( executable_name_out, exec, VKI_PATH_MAX-1 );
787 } else {
788 // No '/' - we need to search the path
sewardj03d8aa82005-10-14 11:25:49 +0000789 HChar* path;
njn73750612005-10-14 03:11:30 +0000790 VG_(strncpy)( executable_name_in, exec, VKI_PATH_MAX-1 );
791 VG_(memset) ( executable_name_out, 0, VKI_PATH_MAX );
sewardj03d8aa82005-10-14 11:25:49 +0000792 path = VG_(getenv)("PATH");
thughes4ad52d02004-06-27 17:37:21 +0000793 scan_colsep(path, match_executable);
nethercote71980f02004-01-24 18:18:54 +0000794 }
njn73750612005-10-14 03:11:30 +0000795 return VG_STREQ(executable_name_out, "") ? NULL : executable_name_out;
nethercote71980f02004-01-24 18:18:54 +0000796}
797
798
799/*====================================================================*/
nethercotef4928da2004-06-15 10:54:40 +0000800/*=== Command line errors ===*/
801/*====================================================================*/
802
njnbe9b47b2005-05-15 16:22:58 +0000803static void revert_to_stderr ( void )
nethercotef4928da2004-06-15 10:54:40 +0000804{
njnbe9b47b2005-05-15 16:22:58 +0000805 vg_assert( !VG_(logging_to_socket) );
nethercotef8548672004-06-21 12:42:35 +0000806 VG_(clo_log_fd) = 2; /* stderr */
nethercotef4928da2004-06-15 10:54:40 +0000807}
808
809void VG_(bad_option) ( Char* opt )
810{
njnbe9b47b2005-05-15 16:22:58 +0000811 revert_to_stderr();
njn02bc4b82005-05-15 17:28:26 +0000812 VG_(printf)("valgrind: Bad option '%s'; aborting.\n", opt);
nethercotef4928da2004-06-15 10:54:40 +0000813 VG_(printf)("valgrind: Use --help for more information.\n");
814 VG_(exit)(1);
815}
816
nethercotef4928da2004-06-15 10:54:40 +0000817static void missing_prog ( void )
818{
njnbe9b47b2005-05-15 16:22:58 +0000819 revert_to_stderr();
nethercotef4928da2004-06-15 10:54:40 +0000820 VG_(printf)("valgrind: no program specified\n");
821 VG_(printf)("valgrind: Use --help for more information.\n");
822 VG_(exit)(1);
823}
824
825static void config_error ( Char* msg )
826{
njnbe9b47b2005-05-15 16:22:58 +0000827 revert_to_stderr();
nethercotef4928da2004-06-15 10:54:40 +0000828 VG_(printf)("valgrind: Startup or configuration error:\n %s\n", msg);
829 VG_(printf)("valgrind: Unable to start up properly. Giving up.\n");
830 VG_(exit)(1);
831}
832
833
nethercote71980f02004-01-24 18:18:54 +0000834/*====================================================================*/
835/*=== Loading the client ===*/
836/*====================================================================*/
837
sewardj45f4e7c2005-09-27 19:20:21 +0000838/* Load the client whose name is VG_(argv_the_exename). */
nethercote71980f02004-01-24 18:18:54 +0000839
sewardj13247ca2005-12-30 22:52:20 +0000840static void load_client ( /*OUT*/ExeInfo* info,
841 /*OUT*/Addr* client_ip,
842 /*OUT*/Addr* client_toc)
sewardj45f4e7c2005-09-27 19:20:21 +0000843{
njn73750612005-10-14 03:11:30 +0000844 HChar* exe_name;
sewardj45f4e7c2005-09-27 19:20:21 +0000845 Int ret;
846 SysRes res;
847
848 vg_assert( VG_(args_the_exename) != NULL);
njn73750612005-10-14 03:11:30 +0000849 exe_name = find_executable( VG_(args_the_exename) );
850
851 if (!exe_name) {
852 VG_(printf)("valgrind: %s: command not found\n", VG_(args_the_exename));
853 VG_(exit)(127); // 127 is Posix NOTFOUND
854 }
sewardj45f4e7c2005-09-27 19:20:21 +0000855
856 VG_(memset)(info, 0, sizeof(*info));
nethercote71980f02004-01-24 18:18:54 +0000857 info->exe_base = VG_(client_base);
858 info->exe_end = VG_(client_end);
nethercote71980f02004-01-24 18:18:54 +0000859
njn73750612005-10-14 03:11:30 +0000860 ret = VG_(do_exec)(exe_name, info);
861
862 // The client was successfully loaded! Continue.
nethercote71980f02004-01-24 18:18:54 +0000863
sewardj45f4e7c2005-09-27 19:20:21 +0000864 /* Get hold of a file descriptor which refers to the client
865 executable. This is needed for attaching to GDB. */
njn73750612005-10-14 03:11:30 +0000866 res = VG_(open)(exe_name, VKI_O_RDONLY, VKI_S_IRUSR);
sewardj45f4e7c2005-09-27 19:20:21 +0000867 if (!res.isError)
868 VG_(cl_exec_fd) = res.val;
869
nethercote71980f02004-01-24 18:18:54 +0000870 /* Copy necessary bits of 'info' that were filled in */
sewardj13247ca2005-12-30 22:52:20 +0000871 *client_ip = info->init_ip;
872 *client_toc = info->init_toc;
sewardj45f4e7c2005-09-27 19:20:21 +0000873 VG_(brk_base) = VG_(brk_limit) = VG_PGROUNDUP(info->brkbase);
nethercote71980f02004-01-24 18:18:54 +0000874}
875
nethercote969ecf12004-10-13 17:29:01 +0000876
sewardj71bc3cb2005-05-19 00:25:45 +0000877/*====================================================================*/
878/*=== Command-line: variables, processing, etc ===*/
879/*====================================================================*/
880
881// See pub_{core,tool}_options.h for explanations of all these.
882
sewardj45f4e7c2005-09-27 19:20:21 +0000883static void usage_NORETURN ( Bool debug_help )
njn7cf0bd32002-06-08 13:36:03 +0000884{
njn25e49d8e72002-09-23 09:36:25 +0000885 Char* usage1 =
njn00cfcfc2005-11-12 18:53:50 +0000886"usage: valgrind [options] prog-and-args\n"
njn25e49d8e72002-09-23 09:36:25 +0000887"\n"
nethercote2b0793f2003-12-02 10:41:18 +0000888" common user options for all Valgrind tools, with defaults in [ ]:\n"
sewardjb5f6f512005-03-10 23:59:00 +0000889" --tool=<name> use the Valgrind tool named <name> [memcheck]\n"
nethercotea76368b2004-06-16 11:56:29 +0000890" -h --help show this message\n"
nethercote6c999f22004-01-31 22:55:15 +0000891" --help-debug show this message, plus debugging options\n"
njn25e49d8e72002-09-23 09:36:25 +0000892" --version show version\n"
njn25e49d8e72002-09-23 09:36:25 +0000893" -q --quiet run silently; only print error msgs\n"
894" -v --verbose be more verbose, incl counts of errors\n"
nethercote77eba602003-11-13 17:35:04 +0000895" --trace-children=no|yes Valgrind-ise child processes? [no]\n"
nethercote0d588502004-06-21 13:27:11 +0000896" --track-fds=no|yes track open file descriptors? [no]\n"
thughes6233a382004-08-21 11:10:44 +0000897" --time-stamp=no|yes add timestamps to log messages? [no]\n"
njnce545552005-07-25 22:36:52 +0000898" --log-fd=<number> log messages to file descriptor [2=stderr]\n"
tombbe14b12005-11-04 16:49:39 +0000899" --log-file=<file> log messages to <file>.<pid>\n"
njnce545552005-07-25 22:36:52 +0000900" --log-file-exactly=<file> log messages to <file>\n"
901" --log-file-qualifier=<VAR> incorporate $VAR in logfile name [none]\n"
902" --log-socket=ipaddr:port log messages to socket ipaddr:port\n"
nethercote2b0793f2003-12-02 10:41:18 +0000903"\n"
904" uncommon user options for all Valgrind tools:\n"
nethercote0d588502004-06-21 13:27:11 +0000905" --run-libc-freeres=no|yes free up glibc memory at exit? [yes]\n"
njn628add62005-11-12 18:21:40 +0000906" --sim-hints=hint1,hint2,... known hints:\n"
sewardj19617ae2005-10-20 01:09:57 +0000907" lax-ioctls, enable-outer [none]\n"
sewardjb1131a82005-03-19 15:12:21 +0000908" --show-emwarns=no|yes show warnings about emulation limits? [no]\n"
sewardj6c3a2192005-07-24 07:00:45 +0000909" --smc-check=none|stack|all checks for self-modifying code: none,\n"
910" only for code found in stacks, or all [stack]\n"
sewardj3c3f0c12005-11-08 15:52:36 +0000911" --kernel-variant=variant1,variant2,... known variants: bproc [none]\n"
912" handle non-standard kernel variants\n"
njn25e49d8e72002-09-23 09:36:25 +0000913"\n"
nethercote2b0793f2003-12-02 10:41:18 +0000914" user options for Valgrind tools that report errors:\n"
njnce545552005-07-25 22:36:52 +0000915" --xml=yes all output is in XML (Memcheck/Nulgrind only)\n"
njnc8ec9f82005-07-20 03:03:28 +0000916" --xml-user-comment=STR copy STR verbatim to XML output\n"
nethercote2b0793f2003-12-02 10:41:18 +0000917" --demangle=no|yes automatically demangle C++ names? [yes]\n"
njn20b4a152005-10-19 22:39:40 +0000918" --num-callers=<number> show <number> callers in stack traces [12]\n"
nethercote2b0793f2003-12-02 10:41:18 +0000919" --error-limit=no|yes stop showing new errors if too many? [yes]\n"
920" --show-below-main=no|yes continue stack traces below main() [no]\n"
921" --suppressions=<filename> suppress errors described in <filename>\n"
sewardjd153fae2005-01-10 17:24:47 +0000922" --gen-suppressions=no|yes|all print suppressions for errors? [no]\n"
nethercote04d0fbc2004-01-26 16:48:06 +0000923" --db-attach=no|yes start debugger when errors detected? [no]\n"
924" --db-command=<command> command to start debugger [gdb -nw %%f %%p]\n"
925" --input-fd=<number> file descriptor for input [0=stdin]\n"
sewardj97724e52005-04-02 23:40:59 +0000926" --max-stackframe=<number> assume stack switch for SP changes larger\n"
927" than <number> bytes [2000000]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +0000928"\n";
njn7cf0bd32002-06-08 13:36:03 +0000929
njn25e49d8e72002-09-23 09:36:25 +0000930 Char* usage2 =
931"\n"
nethercote2b0793f2003-12-02 10:41:18 +0000932" debugging options for all Valgrind tools:\n"
njn25e49d8e72002-09-23 09:36:25 +0000933" --sanity-level=<number> level of sanity checking to do [1]\n"
sewardjfa8ec112005-01-19 11:55:34 +0000934" --trace-flags=<XXXXXXXX> show generated code? (X = 0|1) [00000000]\n"
935" --profile-flags=<XXXXXXXX> ditto, but for profiling (X = 0|1) [00000000]\n"
sewardj33afdb52006-01-17 02:36:40 +0000936" --trace-notbelow=<number> only show BBs above <number> [999999999]\n"
njn25e49d8e72002-09-23 09:36:25 +0000937" --trace-syscalls=no|yes show all system calls? [no]\n"
938" --trace-signals=no|yes show signal handling details? [no]\n"
939" --trace-symtab=no|yes show symbol table details? [no]\n"
sewardjce058b02005-05-01 08:55:38 +0000940" --trace-cfi=no|yes show call-frame-info details? [no]\n"
sewardj0ec07f32006-01-12 12:32:32 +0000941" --trace-redir=no|yes show redirection details? [no]\n"
njn25e49d8e72002-09-23 09:36:25 +0000942" --trace-sched=no|yes show thread scheduler details? [no]\n"
jsgf855d93d2003-10-13 22:26:55 +0000943" --wait-for-gdb=yes|no pause on startup to wait for gdb attach\n"
sewardjb5f6f512005-03-10 23:59:00 +0000944#if 0
945" --model-pthreads=yes|no model the pthreads library [no]\n"
946#endif
947" --command-line-only=no|yes only use command line options [no]\n"
njn613812e2005-03-11 04:57:30 +0000948"\n"
949" --vex-iropt-verbosity 0 .. 9 [0]\n"
950" --vex-iropt-level 0 .. 2 [2]\n"
951" --vex-iropt-precise-memory-exns [no]\n"
sewardj8b635a42004-11-22 19:01:47 +0000952" --vex-iropt-unroll-thresh 0 .. 400 [120]\n"
953" --vex-guest-max-insns 1 .. 100 [50]\n"
954" --vex-guest-chase-thresh 0 .. 99 [10]\n"
955"\n"
sewardjfa8ec112005-01-19 11:55:34 +0000956" --trace-flags and --profile-flags values (omit the middle space):\n"
sewardj2a99cf62004-11-24 10:44:19 +0000957" 1000 0000 show conversion into IR\n"
958" 0100 0000 show after initial opt\n"
959" 0010 0000 show after instrumentation\n"
960" 0001 0000 show after second opt\n"
961" 0000 1000 show after tree building\n"
962" 0000 0100 show selecting insns\n"
963" 0000 0010 show after reg-alloc\n"
964" 0000 0001 show final assembly\n"
965"\n"
nethercote2b0793f2003-12-02 10:41:18 +0000966" debugging options for Valgrind tools that report errors\n"
967" --dump-error=<number> show translation for basic block associated\n"
968" with <number>'th error context [0=show none]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +0000969"\n";
njn3e884182003-04-15 13:03:23 +0000970
971 Char* usage3 =
972"\n"
nethercote71980f02004-01-24 18:18:54 +0000973" Extra options read from ~/.valgrindrc, $VALGRIND_OPTS, ./.valgrindrc\n"
njn25e49d8e72002-09-23 09:36:25 +0000974"\n"
njn53612422005-03-12 16:22:54 +0000975" Valgrind is Copyright (C) 2000-2005 Julian Seward et al.\n"
njn25e49d8e72002-09-23 09:36:25 +0000976" and licensed under the GNU General Public License, version 2.\n"
977" Bug reports, feedback, admiration, abuse, etc, to: %s.\n"
njnd04b7c62002-10-03 14:05:52 +0000978"\n"
nethercote137bc552003-11-14 17:47:54 +0000979" Tools are copyright and licensed by their authors. See each\n"
980" tool's start-up message for more information.\n"
njn25e49d8e72002-09-23 09:36:25 +0000981"\n";
njn7cf0bd32002-06-08 13:36:03 +0000982
njnbe9b47b2005-05-15 16:22:58 +0000983 // Ensure the message goes to stdout
984 VG_(clo_log_fd) = 1;
985 vg_assert( !VG_(logging_to_socket) );
986
fitzhardinge98abfc72003-12-16 02:05:15 +0000987 VG_(printf)(usage1);
988 if (VG_(details).name) {
989 VG_(printf)(" user options for %s:\n", VG_(details).name);
fitzhardinge98abfc72003-12-16 02:05:15 +0000990 if (VG_(needs).command_line_options)
njn51d827b2005-05-09 01:02:08 +0000991 VG_TDICT_CALL(tool_print_usage);
fitzhardinge98abfc72003-12-16 02:05:15 +0000992 else
993 VG_(printf)(" (none)\n");
994 }
nethercote6c999f22004-01-31 22:55:15 +0000995 if (debug_help) {
996 VG_(printf)(usage2);
fitzhardinge98abfc72003-12-16 02:05:15 +0000997
nethercote6c999f22004-01-31 22:55:15 +0000998 if (VG_(details).name) {
999 VG_(printf)(" debugging options for %s:\n", VG_(details).name);
1000
1001 if (VG_(needs).command_line_options)
njn51d827b2005-05-09 01:02:08 +00001002 VG_TDICT_CALL(tool_print_debug_usage);
nethercote6c999f22004-01-31 22:55:15 +00001003 else
1004 VG_(printf)(" (none)\n");
1005 }
fitzhardinge98abfc72003-12-16 02:05:15 +00001006 }
nethercote421281e2003-11-20 16:20:55 +00001007 VG_(printf)(usage3, VG_BUGS_TO);
nethercotef4928da2004-06-15 10:54:40 +00001008 VG_(exit)(0);
njn7cf0bd32002-06-08 13:36:03 +00001009}
sewardjde4a1d02002-03-22 01:27:54 +00001010
sewardjde4a1d02002-03-22 01:27:54 +00001011
sewardj45f4e7c2005-09-27 19:20:21 +00001012/* Peer at previously set up VG_(args_for_valgrind) and extract any
1013 request for help and also the tool name. */
1014
1015static void get_helprequest_and_toolname ( Int* need_help, HChar** tool )
1016{
1017 UInt i;
1018 HChar* str;
sewardj8b635a42004-11-22 19:01:47 +00001019
nethercote71980f02004-01-24 18:18:54 +00001020 /* parse the options we have (only the options we care about now) */
sewardj45f4e7c2005-09-27 19:20:21 +00001021 for (i = 0; i < VG_(args_for_valgrind).used; i++) {
nethercote71980f02004-01-24 18:18:54 +00001022
sewardj45f4e7c2005-09-27 19:20:21 +00001023 str = VG_(args_for_valgrind).strs[i];
1024 vg_assert(str);
nethercote71980f02004-01-24 18:18:54 +00001025
sewardj45f4e7c2005-09-27 19:20:21 +00001026 if (VG_STREQ(str, "--version")) {
njn2e9f3f32005-10-26 16:17:46 +00001027 // Ensure the version string goes to stdout
1028 VG_(clo_log_fd) = 1;
sewardj45f4e7c2005-09-27 19:20:21 +00001029 VG_(printf)("valgrind-" VERSION "\n");
1030 VG_(exit)(0);
1031
1032 } else if (VG_CLO_STREQ(str, "--help") ||
1033 VG_CLO_STREQ(str, "-h")) {
nethercote6c999f22004-01-31 22:55:15 +00001034 *need_help = 1;
1035
sewardj45f4e7c2005-09-27 19:20:21 +00001036 } else if (VG_CLO_STREQ(str, "--help-debug")) {
nethercote6c999f22004-01-31 22:55:15 +00001037 *need_help = 2;
nethercote71980f02004-01-24 18:18:54 +00001038
sewardj45f4e7c2005-09-27 19:20:21 +00001039 // The tool has already been determined, but we need to know the name
1040 // here.
1041 } else if (VG_CLO_STREQN(7, str, "--tool=")) {
1042 *tool = &str[7];
nethercote71980f02004-01-24 18:18:54 +00001043 }
1044 }
nethercote71980f02004-01-24 18:18:54 +00001045}
1046
sewardj45f4e7c2005-09-27 19:20:21 +00001047static Bool process_cmd_line_options( UInt* client_auxv, const char* toolname )
nethercote71980f02004-01-24 18:18:54 +00001048{
njnda033f52005-12-19 21:27:58 +00001049 // VG_(clo_log_fd) is used by all the messaging. It starts as 2 (stderr)
1050 // and we cannot change it until we know what we are changing it to is
1051 // ok. So we have tmp_log_fd to hold the tmp fd prior to that point.
sewardj92645592005-07-23 09:18:34 +00001052 SysRes sres;
njnda033f52005-12-19 21:27:58 +00001053 Int i, tmp_log_fd;
sewardj92645592005-07-23 09:18:34 +00001054 Int toolname_len = VG_(strlen)(toolname);
njnbe9b47b2005-05-15 16:22:58 +00001055 enum {
1056 VgLogTo_Fd,
1057 VgLogTo_File,
1058 VgLogTo_FileExactly,
1059 VgLogTo_Socket
1060 } log_to = VgLogTo_Fd; // Where is logging output to be sent?
sewardjde4a1d02002-03-22 01:27:54 +00001061
nethercotee1730692003-11-20 10:38:07 +00001062 /* log to stderr by default, but usage message goes to stdout */
njnda033f52005-12-19 21:27:58 +00001063 tmp_log_fd = 2;
sewardjde4a1d02002-03-22 01:27:54 +00001064
sewardj19d81412002-06-03 01:10:40 +00001065 /* Check for sane path in ./configure --prefix=... */
fitzhardinge98abfc72003-12-16 02:05:15 +00001066 if (VG_LIBDIR[0] != '/')
sewardj19d81412002-06-03 01:10:40 +00001067 config_error("Please use absolute paths in "
1068 "./configure --prefix=... or --libdir=...");
sewardj38170912002-05-10 21:07:22 +00001069
sewardj45f4e7c2005-09-27 19:20:21 +00001070 for (i = 0; i < VG_(args_for_valgrind).used; i++) {
nethercote71980f02004-01-24 18:18:54 +00001071
sewardj45f4e7c2005-09-27 19:20:21 +00001072 HChar* arg = VG_(args_for_valgrind).strs[i];
1073 HChar* colon = arg;
nethercote71980f02004-01-24 18:18:54 +00001074
thughes3bfd5a02004-07-18 08:05:44 +00001075 /* Look for a colon in the switch name */
1076 while (*colon && *colon != ':' && *colon != '=')
1077 colon++;
nethercote71980f02004-01-24 18:18:54 +00001078
1079 /* Look for matching "--toolname:foo" */
thughes3bfd5a02004-07-18 08:05:44 +00001080 if (*colon == ':') {
nethercote71980f02004-01-24 18:18:54 +00001081 if (VG_CLO_STREQN(2, arg, "--") &&
1082 VG_CLO_STREQN(toolname_len, arg+2, toolname) &&
1083 VG_CLO_STREQN(1, arg+2+toolname_len, ":"))
1084 {
1085 // prefix matches, convert "--toolname:foo" to "--foo"
1086 if (0)
1087 VG_(printf)("tool-specific arg: %s\n", arg);
sewardj45f4e7c2005-09-27 19:20:21 +00001088 arg = VG_(strdup)(arg + toolname_len + 1);
nethercote71980f02004-01-24 18:18:54 +00001089 arg[0] = '-';
1090 arg[1] = '-';
1091
1092 } else {
1093 // prefix doesn't match, skip to next arg
1094 continue;
1095 }
1096 }
1097
fitzhardinge98abfc72003-12-16 02:05:15 +00001098 /* Ignore these options - they've already been handled */
njn45270a22005-03-27 01:00:11 +00001099 if (VG_CLO_STREQN( 7, arg, "--tool=")) goto skip_arg;
njn45270a22005-03-27 01:00:11 +00001100 if (VG_CLO_STREQN(20, arg, "--command-line-only=")) goto skip_arg;
fitzhardinge98abfc72003-12-16 02:05:15 +00001101
njn45270a22005-03-27 01:00:11 +00001102 if ( VG_CLO_STREQ(arg, "--")) goto skip_arg;
nethercote27fec902004-06-16 21:26:32 +00001103
nethercote71980f02004-01-24 18:18:54 +00001104 else if (VG_CLO_STREQ(arg, "-v") ||
1105 VG_CLO_STREQ(arg, "--verbose"))
sewardjde4a1d02002-03-22 01:27:54 +00001106 VG_(clo_verbosity)++;
nethercote27fec902004-06-16 21:26:32 +00001107
nethercote71980f02004-01-24 18:18:54 +00001108 else if (VG_CLO_STREQ(arg, "-q") ||
1109 VG_CLO_STREQ(arg, "--quiet"))
sewardjde4a1d02002-03-22 01:27:54 +00001110 VG_(clo_verbosity)--;
1111
sewardj1cf558c2005-04-25 01:36:56 +00001112 else if (VG_CLO_STREQ(arg, "-d")) {
1113 /* do nothing */
1114 }
1115
sewardj71bc3cb2005-05-19 00:25:45 +00001116 else VG_BOOL_CLO(arg, "--xml", VG_(clo_xml))
njn45270a22005-03-27 01:00:11 +00001117 else VG_BOOL_CLO(arg, "--db-attach", VG_(clo_db_attach))
1118 else VG_BOOL_CLO(arg, "--demangle", VG_(clo_demangle))
1119 else VG_BOOL_CLO(arg, "--error-limit", VG_(clo_error_limit))
njn45270a22005-03-27 01:00:11 +00001120 else VG_BOOL_CLO(arg, "--show-emwarns", VG_(clo_show_emwarns))
sewardj97724e52005-04-02 23:40:59 +00001121 else VG_NUM_CLO (arg, "--max-stackframe", VG_(clo_max_stackframe))
njn45270a22005-03-27 01:00:11 +00001122 else VG_BOOL_CLO(arg, "--run-libc-freeres", VG_(clo_run_libc_freeres))
1123 else VG_BOOL_CLO(arg, "--show-below-main", VG_(clo_show_below_main))
1124 else VG_BOOL_CLO(arg, "--time-stamp", VG_(clo_time_stamp))
1125 else VG_BOOL_CLO(arg, "--track-fds", VG_(clo_track_fds))
1126 else VG_BOOL_CLO(arg, "--trace-children", VG_(clo_trace_children))
1127 else VG_BOOL_CLO(arg, "--trace-sched", VG_(clo_trace_sched))
1128 else VG_BOOL_CLO(arg, "--trace-signals", VG_(clo_trace_signals))
1129 else VG_BOOL_CLO(arg, "--trace-symtab", VG_(clo_trace_symtab))
sewardjce058b02005-05-01 08:55:38 +00001130 else VG_BOOL_CLO(arg, "--trace-cfi", VG_(clo_trace_cfi))
njn45270a22005-03-27 01:00:11 +00001131 else VG_BOOL_CLO(arg, "--trace-redir", VG_(clo_trace_redir))
1132 else VG_BOOL_CLO(arg, "--trace-syscalls", VG_(clo_trace_syscalls))
1133 else VG_BOOL_CLO(arg, "--trace-pthreads", VG_(clo_trace_pthreads))
1134 else VG_BOOL_CLO(arg, "--wait-for-gdb", VG_(clo_wait_for_gdb))
1135 else VG_BOOL_CLO(arg, "--model-pthreads", VG_(clo_model_pthreads))
sewardj72f98ff2002-06-13 17:23:38 +00001136
njn45270a22005-03-27 01:00:11 +00001137 else VG_STR_CLO (arg, "--db-command", VG_(clo_db_command))
njn628add62005-11-12 18:21:40 +00001138 else VG_STR_CLO (arg, "--sim-hints", VG_(clo_sim_hints))
sewardjde4a1d02002-03-22 01:27:54 +00001139
njn45270a22005-03-27 01:00:11 +00001140 else VG_NUM_CLO (arg, "--dump-error", VG_(clo_dump_error))
1141 else VG_NUM_CLO (arg, "--input-fd", VG_(clo_input_fd))
1142 else VG_NUM_CLO (arg, "--sanity-level", VG_(clo_sanity_level))
1143 else VG_BNUM_CLO(arg, "--num-callers", VG_(clo_backtrace_size), 1,
1144 VG_DEEPEST_BACKTRACE)
sewardjde4a1d02002-03-22 01:27:54 +00001145
sewardj6c3a2192005-07-24 07:00:45 +00001146 else if (VG_CLO_STREQ(arg, "--smc-check=none"))
1147 VG_(clo_smc_check) = Vg_SmcNone;
1148 else if (VG_CLO_STREQ(arg, "--smc-check=stack"))
1149 VG_(clo_smc_check) = Vg_SmcStack;
1150 else if (VG_CLO_STREQ(arg, "--smc-check=all"))
1151 VG_(clo_smc_check) = Vg_SmcAll;
sewardj26412bd2005-07-07 10:05:05 +00001152
sewardjce5a5662005-10-06 03:19:49 +00001153 else VG_STR_CLO (arg, "--kernel-variant", VG_(clo_kernel_variant))
1154
njn45270a22005-03-27 01:00:11 +00001155 else VG_BNUM_CLO(arg, "--vex-iropt-verbosity",
sewardj8b635a42004-11-22 19:01:47 +00001156 VG_(clo_vex_control).iropt_verbosity, 0, 10)
njn45270a22005-03-27 01:00:11 +00001157 else VG_BNUM_CLO(arg, "--vex-iropt-level",
sewardj8b635a42004-11-22 19:01:47 +00001158 VG_(clo_vex_control).iropt_level, 0, 2)
njn45270a22005-03-27 01:00:11 +00001159 else VG_BOOL_CLO(arg, "--vex-iropt-precise-memory-exns",
sewardj8b635a42004-11-22 19:01:47 +00001160 VG_(clo_vex_control).iropt_precise_memory_exns)
njn45270a22005-03-27 01:00:11 +00001161 else VG_BNUM_CLO(arg, "--vex-iropt-unroll-thresh",
sewardj8b635a42004-11-22 19:01:47 +00001162 VG_(clo_vex_control).iropt_unroll_thresh, 0, 400)
njn45270a22005-03-27 01:00:11 +00001163 else VG_BNUM_CLO(arg, "--vex-guest-max-insns",
sewardj8b635a42004-11-22 19:01:47 +00001164 VG_(clo_vex_control).guest_max_insns, 1, 100)
njn45270a22005-03-27 01:00:11 +00001165 else VG_BNUM_CLO(arg, "--vex-guest-chase-thresh",
sewardj8b635a42004-11-22 19:01:47 +00001166 VG_(clo_vex_control).guest_chase_thresh, 0, 99)
1167
nethercotef8548672004-06-21 12:42:35 +00001168 else if (VG_CLO_STREQN(9, arg, "--log-fd=")) {
njnbe9b47b2005-05-15 16:22:58 +00001169 log_to = VgLogTo_Fd;
nethercotef8548672004-06-21 12:42:35 +00001170 VG_(clo_log_name) = NULL;
njnda033f52005-12-19 21:27:58 +00001171 tmp_log_fd = (Int)VG_(atoll)(&arg[9]);
sewardj4cf05692002-10-27 20:28:29 +00001172 }
1173
nethercotef8548672004-06-21 12:42:35 +00001174 else if (VG_CLO_STREQN(11, arg, "--log-file=")) {
njnbe9b47b2005-05-15 16:22:58 +00001175 log_to = VgLogTo_File;
nethercotef8548672004-06-21 12:42:35 +00001176 VG_(clo_log_name) = &arg[11];
sewardj4cf05692002-10-27 20:28:29 +00001177 }
njnd6bc3c32005-03-27 00:44:31 +00001178
sewardjad311162005-07-19 11:25:02 +00001179 else if (VG_CLO_STREQN(21, arg, "--log-file-qualifier=")) {
1180 VG_(clo_log_file_qualifier) = &arg[21];
1181 }
1182
sewardj603d4102005-01-11 14:01:02 +00001183 else if (VG_CLO_STREQN(19, arg, "--log-file-exactly=")) {
njnbe9b47b2005-05-15 16:22:58 +00001184 log_to = VgLogTo_FileExactly;
sewardj603d4102005-01-11 14:01:02 +00001185 VG_(clo_log_name) = &arg[19];
1186 }
sewardjde4a1d02002-03-22 01:27:54 +00001187
nethercotef8548672004-06-21 12:42:35 +00001188 else if (VG_CLO_STREQN(13, arg, "--log-socket=")) {
njnbe9b47b2005-05-15 16:22:58 +00001189 log_to = VgLogTo_Socket;
nethercotef8548672004-06-21 12:42:35 +00001190 VG_(clo_log_name) = &arg[13];
sewardj73cf3bc2002-11-03 03:20:15 +00001191 }
1192
sewardj768db0e2005-07-19 14:18:56 +00001193 else if (VG_CLO_STREQN(19, arg, "--xml-user-comment=")) {
1194 VG_(clo_xml_user_comment) = &arg[19];
1195 }
1196
nethercote71980f02004-01-24 18:18:54 +00001197 else if (VG_CLO_STREQN(15, arg, "--suppressions=")) {
sewardjde4a1d02002-03-22 01:27:54 +00001198 if (VG_(clo_n_suppressions) >= VG_CLO_MAX_SFILES) {
njn25e49d8e72002-09-23 09:36:25 +00001199 VG_(message)(Vg_UserMsg, "Too many suppression files specified.");
sewardjde4a1d02002-03-22 01:27:54 +00001200 VG_(message)(Vg_UserMsg,
1201 "Increase VG_CLO_MAX_SFILES and recompile.");
nethercote71980f02004-01-24 18:18:54 +00001202 VG_(bad_option)(arg);
sewardjde4a1d02002-03-22 01:27:54 +00001203 }
nethercote71980f02004-01-24 18:18:54 +00001204 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = &arg[15];
sewardjde4a1d02002-03-22 01:27:54 +00001205 VG_(clo_n_suppressions)++;
1206 }
sewardjde4a1d02002-03-22 01:27:54 +00001207
sewardjfa8ec112005-01-19 11:55:34 +00001208 /* "stuvwxyz" --> stuvwxyz (binary) */
1209 else if (VG_CLO_STREQN(14, arg, "--trace-flags=")) {
1210 Int j;
1211 char* opt = & arg[14];
1212
1213 if (8 != VG_(strlen)(opt)) {
1214 VG_(message)(Vg_UserMsg,
1215 "--trace-flags argument must have 8 digits");
1216 VG_(bad_option)(arg);
1217 }
1218 for (j = 0; j < 8; j++) {
1219 if ('0' == opt[j]) { /* do nothing */ }
1220 else if ('1' == opt[j]) VG_(clo_trace_flags) |= (1 << (7-j));
1221 else {
1222 VG_(message)(Vg_UserMsg, "--trace-flags argument can only "
1223 "contain 0s and 1s");
1224 VG_(bad_option)(arg);
1225 }
1226 }
1227 }
1228
1229 /* "stuvwxyz" --> stuvwxyz (binary) */
1230 else if (VG_CLO_STREQN(16, arg, "--profile-flags=")) {
njn25e49d8e72002-09-23 09:36:25 +00001231 Int j;
nethercote71980f02004-01-24 18:18:54 +00001232 char* opt = & arg[16];
njn25e49d8e72002-09-23 09:36:25 +00001233
sewardj2a99cf62004-11-24 10:44:19 +00001234 if (8 != VG_(strlen)(opt)) {
njn25e49d8e72002-09-23 09:36:25 +00001235 VG_(message)(Vg_UserMsg,
sewardjfa8ec112005-01-19 11:55:34 +00001236 "--profile-flags argument must have 8 digits");
nethercote71980f02004-01-24 18:18:54 +00001237 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001238 }
sewardj8b635a42004-11-22 19:01:47 +00001239 for (j = 0; j < 8; j++) {
njn25e49d8e72002-09-23 09:36:25 +00001240 if ('0' == opt[j]) { /* do nothing */ }
sewardjfa8ec112005-01-19 11:55:34 +00001241 else if ('1' == opt[j]) VG_(clo_profile_flags) |= (1 << (7-j));
njn25e49d8e72002-09-23 09:36:25 +00001242 else {
sewardjfa8ec112005-01-19 11:55:34 +00001243 VG_(message)(Vg_UserMsg, "--profile-flags argument can only "
njn25e49d8e72002-09-23 09:36:25 +00001244 "contain 0s and 1s");
nethercote71980f02004-01-24 18:18:54 +00001245 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001246 }
1247 }
1248 }
sewardjde4a1d02002-03-22 01:27:54 +00001249
njn45270a22005-03-27 01:00:11 +00001250 else VG_NUM_CLO (arg, "--trace-notbelow", VG_(clo_trace_notbelow))
sewardjc771b292004-11-30 18:55:21 +00001251
sewardjd153fae2005-01-10 17:24:47 +00001252 else if (VG_CLO_STREQ(arg, "--gen-suppressions=no"))
1253 VG_(clo_gen_suppressions) = 0;
1254 else if (VG_CLO_STREQ(arg, "--gen-suppressions=yes"))
1255 VG_(clo_gen_suppressions) = 1;
1256 else if (VG_CLO_STREQ(arg, "--gen-suppressions=all"))
1257 VG_(clo_gen_suppressions) = 2;
1258
nethercote71980f02004-01-24 18:18:54 +00001259 else if ( ! VG_(needs).command_line_options
njn51d827b2005-05-09 01:02:08 +00001260 || ! VG_TDICT_CALL(tool_process_cmd_line_option, arg) ) {
nethercotef4928da2004-06-15 10:54:40 +00001261 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001262 }
njn8c0b3bb2005-03-12 21:20:39 +00001263 skip_arg:
sewardj45f4e7c2005-09-27 19:20:21 +00001264 if (arg != VG_(args_for_valgrind).strs[i]) {
1265 VG_(free)(arg);
1266 }
sewardjde4a1d02002-03-22 01:27:54 +00001267 }
1268
sewardj998d40d2004-12-06 14:24:52 +00001269 /* Make VEX control parameters sane */
1270
1271 if (VG_(clo_vex_control).guest_chase_thresh
1272 >= VG_(clo_vex_control).guest_max_insns)
1273 VG_(clo_vex_control).guest_chase_thresh
1274 = VG_(clo_vex_control).guest_max_insns - 1;
1275
1276 if (VG_(clo_vex_control).guest_chase_thresh < 0)
1277 VG_(clo_vex_control).guest_chase_thresh = 0;
1278
1279 /* Check various option values */
nethercote27fec902004-06-16 21:26:32 +00001280
njnf9ebf672003-05-12 21:41:30 +00001281 if (VG_(clo_verbosity) < 0)
sewardjde4a1d02002-03-22 01:27:54 +00001282 VG_(clo_verbosity) = 0;
1283
nethercote04d0fbc2004-01-26 16:48:06 +00001284 if (VG_(clo_db_attach) && VG_(clo_trace_children)) {
sewardjde4a1d02002-03-22 01:27:54 +00001285 VG_(message)(Vg_UserMsg, "");
1286 VG_(message)(Vg_UserMsg,
nethercote04d0fbc2004-01-26 16:48:06 +00001287 "--db-attach=yes conflicts with --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001288 VG_(message)(Vg_UserMsg,
1289 "Please choose one or the other, but not both.");
nethercote04d0fbc2004-01-26 16:48:06 +00001290 VG_(bad_option)("--db-attach=yes and --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001291 }
1292
njnbe9b47b2005-05-15 16:22:58 +00001293 if (VG_(clo_gen_suppressions) > 0 &&
1294 !VG_(needs).core_errors && !VG_(needs).tool_errors) {
1295 VG_(message)(Vg_UserMsg,
1296 "Can't use --gen-suppressions= with this tool,");
1297 VG_(message)(Vg_UserMsg,
1298 "as it doesn't generate errors.");
1299 VG_(bad_option)("--gen-suppressions=");
1300 }
1301
sewardj71bc3cb2005-05-19 00:25:45 +00001302 /* If we've been asked to emit XML, mash around various other
1303 options so as to constrain the output somewhat, and to remove
1304 any need for user input during the run. */
1305 if (VG_(clo_xml)) {
1306 /* Disable suppression generation (requires user input) */
1307 VG_(clo_gen_suppressions) = 0;
1308 /* Disable attaching to GDB (requires user input) */
1309 VG_(clo_db_attach) = False;
1310 /* Set a known verbosity level */
1311 VG_(clo_verbosity) = 1;
1312 /* Disable error limits (this might be a bad idea!) */
1313 VG_(clo_error_limit) = False;
1314 /* Disable emulation warnings */
1315 VG_(clo_show_emwarns) = False;
1316 /* Disable waiting for GDB to debug Valgrind */
1317 VG_(clo_wait_for_gdb) = False;
1318 /* No file-descriptor leak checking yet */
1319 VG_(clo_track_fds) = False;
sewardj21f7f0c2005-07-06 19:46:48 +00001320 /* Disable timestamped output */
1321 VG_(clo_time_stamp) = False;
sewardj71bc3cb2005-05-19 00:25:45 +00001322 /* Also, we want to set options for the leak checker, but that
1323 will have to be done in Memcheck's flag-handling code, not
1324 here. */
1325 }
1326
njnbe9b47b2005-05-15 16:22:58 +00001327 /* All non-logging-related options have been checked. If the logging
1328 option specified is ok, we can switch to it, as we know we won't
1329 have to generate any other command-line-related error messages.
1330 (So far we should be still attached to stderr, so we can show on
1331 the terminal any problems to do with processing command line
1332 opts.)
1333
1334 So set up logging now. After this is done, VG_(clo_log_fd)
sewardj4cf05692002-10-27 20:28:29 +00001335 should be connected to whatever sink has been selected, and we
1336 indiscriminately chuck stuff into it without worrying what the
1337 nature of it is. Oh the wonder of Unix streams. */
1338
njnbe9b47b2005-05-15 16:22:58 +00001339 vg_assert(VG_(clo_log_fd) == 2 /* stderr */);
1340 vg_assert(VG_(logging_to_socket) == False);
sewardj4cf05692002-10-27 20:28:29 +00001341
njnbe9b47b2005-05-15 16:22:58 +00001342 switch (log_to) {
sewardj73cf3bc2002-11-03 03:20:15 +00001343
sewardj4cf05692002-10-27 20:28:29 +00001344 case VgLogTo_Fd:
nethercotef8548672004-06-21 12:42:35 +00001345 vg_assert(VG_(clo_log_name) == NULL);
sewardj4cf05692002-10-27 20:28:29 +00001346 break;
sewardj73cf3bc2002-11-03 03:20:15 +00001347
sewardj4cf05692002-10-27 20:28:29 +00001348 case VgLogTo_File: {
sewardjad311162005-07-19 11:25:02 +00001349 HChar logfilename[1000];
1350 Int seq = 0;
1351 Int pid = VG_(getpid)();
1352 HChar* qual = NULL;
jsgff3c3f1a2003-10-14 22:13:28 +00001353
nethercotef8548672004-06-21 12:42:35 +00001354 vg_assert(VG_(clo_log_name) != NULL);
1355 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
jsgff3c3f1a2003-10-14 22:13:28 +00001356
sewardjad311162005-07-19 11:25:02 +00001357 if (VG_(clo_log_file_qualifier)) {
1358 qual = VG_(getenv)(VG_(clo_log_file_qualifier));
1359 }
1360
nethercote71980f02004-01-24 18:18:54 +00001361 for (;;) {
sewardj92645592005-07-23 09:18:34 +00001362 HChar pidtxt[20], seqtxt[20];
1363
1364 VG_(sprintf)(pidtxt, "%d", pid);
1365
1366 if (seq == 0)
1367 seqtxt[0] = 0;
1368 else
1369 VG_(sprintf)(seqtxt, ".%d", seq);
1370
jsgff3c3f1a2003-10-14 22:13:28 +00001371 seq++;
1372
sewardj92645592005-07-23 09:18:34 +00001373 /* Result:
1374 if (qual) base_name ++ "." ++ qual ++ seqtxt
1375 if (not qual) base_name ++ "." ++ pid ++ seqtxt
1376 */
1377 VG_(sprintf)( logfilename,
1378 "%s.%s%s",
1379 VG_(clo_log_name),
1380 qual ? qual : pidtxt,
1381 seqtxt );
1382
njnbe9b47b2005-05-15 16:22:58 +00001383 // EXCL: it will fail with EEXIST if the file already exists.
njnda033f52005-12-19 21:27:58 +00001384 sres = VG_(open)(logfilename,
1385 VKI_O_CREAT|VKI_O_WRONLY|VKI_O_EXCL|VKI_O_TRUNC,
1386 VKI_S_IRUSR|VKI_S_IWUSR);
sewardj92645592005-07-23 09:18:34 +00001387 if (!sres.isError) {
njnda033f52005-12-19 21:27:58 +00001388 tmp_log_fd = sres.val;
sewardj603d4102005-01-11 14:01:02 +00001389 break; /* for (;;) */
jsgff3c3f1a2003-10-14 22:13:28 +00001390 } else {
njnbe9b47b2005-05-15 16:22:58 +00001391 // If the file already existed, we try the next name. If it
1392 // was some other file error, we give up.
sewardj92645592005-07-23 09:18:34 +00001393 if (sres.val != VKI_EEXIST) {
jsgff3c3f1a2003-10-14 22:13:28 +00001394 VG_(message)(Vg_UserMsg,
tombbe14b12005-11-04 16:49:39 +00001395 "Can't create/open log file '%s.%d'; giving up!",
nethercotef8548672004-06-21 12:42:35 +00001396 VG_(clo_log_name), pid);
jsgff3c3f1a2003-10-14 22:13:28 +00001397 VG_(bad_option)(
sewardj603d4102005-01-11 14:01:02 +00001398 "--log-file=<file> (didn't work out for some reason.)");
njnbe9b47b2005-05-15 16:22:58 +00001399 /*NOTREACHED*/
jsgff3c3f1a2003-10-14 22:13:28 +00001400 }
1401 }
1402 }
sewardj603d4102005-01-11 14:01:02 +00001403 break; /* switch (VG_(clo_log_to)) */
1404 }
1405
1406 case VgLogTo_FileExactly: {
sewardj603d4102005-01-11 14:01:02 +00001407 vg_assert(VG_(clo_log_name) != NULL);
1408 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
sewardj603d4102005-01-11 14:01:02 +00001409
njnda033f52005-12-19 21:27:58 +00001410 sres = VG_(open)(VG_(clo_log_name),
1411 VKI_O_CREAT|VKI_O_WRONLY|VKI_O_TRUNC,
1412 VKI_S_IRUSR|VKI_S_IWUSR);
sewardj92645592005-07-23 09:18:34 +00001413 if (!sres.isError) {
njnda033f52005-12-19 21:27:58 +00001414 tmp_log_fd = sres.val;
njnbe9b47b2005-05-15 16:22:58 +00001415 } else {
sewardj603d4102005-01-11 14:01:02 +00001416 VG_(message)(Vg_UserMsg,
njn02bc4b82005-05-15 17:28:26 +00001417 "Can't create/open log file '%s'; giving up!",
sewardj603d4102005-01-11 14:01:02 +00001418 VG_(clo_log_name));
1419 VG_(bad_option)(
1420 "--log-file-exactly=<file> (didn't work out for some reason.)");
1421 /*NOTREACHED*/
1422 }
1423 break; /* switch (VG_(clo_log_to)) */
sewardj73cf3bc2002-11-03 03:20:15 +00001424 }
1425
1426 case VgLogTo_Socket: {
nethercotef8548672004-06-21 12:42:35 +00001427 vg_assert(VG_(clo_log_name) != NULL);
1428 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
njnda033f52005-12-19 21:27:58 +00001429 tmp_log_fd = VG_(connect_via_socket)( VG_(clo_log_name) );
1430 if (tmp_log_fd == -1) {
sewardj73cf3bc2002-11-03 03:20:15 +00001431 VG_(message)(Vg_UserMsg,
nethercotef8548672004-06-21 12:42:35 +00001432 "Invalid --log-socket=ipaddr or --log-socket=ipaddr:port spec");
sewardj73cf3bc2002-11-03 03:20:15 +00001433 VG_(message)(Vg_UserMsg,
njn02bc4b82005-05-15 17:28:26 +00001434 "of '%s'; giving up!", VG_(clo_log_name) );
sewardj73cf3bc2002-11-03 03:20:15 +00001435 VG_(bad_option)(
nethercotef8548672004-06-21 12:42:35 +00001436 "--log-socket=");
njnbe9b47b2005-05-15 16:22:58 +00001437 /*NOTREACHED*/
sewardj4cf05692002-10-27 20:28:29 +00001438 }
njnda033f52005-12-19 21:27:58 +00001439 if (tmp_log_fd == -2) {
sewardj73cf3bc2002-11-03 03:20:15 +00001440 VG_(message)(Vg_UserMsg,
njn02bc4b82005-05-15 17:28:26 +00001441 "valgrind: failed to connect to logging server '%s'.",
nethercotef8548672004-06-21 12:42:35 +00001442 VG_(clo_log_name) );
sewardj570f8902002-11-03 11:44:36 +00001443 VG_(message)(Vg_UserMsg,
1444 "Log messages will sent to stderr instead." );
1445 VG_(message)(Vg_UserMsg,
1446 "" );
1447 /* We don't change anything here. */
njnbe9b47b2005-05-15 16:22:58 +00001448 vg_assert(VG_(clo_log_fd) == 2);
njnda033f52005-12-19 21:27:58 +00001449 tmp_log_fd = 2;
sewardj570f8902002-11-03 11:44:36 +00001450 } else {
njnda033f52005-12-19 21:27:58 +00001451 vg_assert(tmp_log_fd > 0);
njnbe9b47b2005-05-15 16:22:58 +00001452 VG_(logging_to_socket) = True;
sewardj570f8902002-11-03 11:44:36 +00001453 }
sewardj73cf3bc2002-11-03 03:20:15 +00001454 break;
1455 }
sewardj4cf05692002-10-27 20:28:29 +00001456 }
1457
sewardj71bc3cb2005-05-19 00:25:45 +00001458
1459 /* Check that the requested tool actually supports XML output. */
sewardj45f4e7c2005-09-27 19:20:21 +00001460 if (VG_(clo_xml) && !VG_STREQ(toolname, "memcheck")
1461 && !VG_STREQ(toolname, "none")) {
sewardj71bc3cb2005-05-19 00:25:45 +00001462 VG_(clo_xml) = False;
1463 VG_(message)(Vg_UserMsg,
cerion39655202005-07-13 14:18:24 +00001464 "Currently only Memcheck|None supports XML output.");
sewardj71bc3cb2005-05-19 00:25:45 +00001465 VG_(bad_option)("--xml=yes");
1466 /*NOTREACHED*/
1467 }
1468
njnda033f52005-12-19 21:27:58 +00001469 if (tmp_log_fd >= 0) {
1470 // Move log_fd into the safe range, so it doesn't conflict with any app fds.
1471 tmp_log_fd = VG_(fcntl)(tmp_log_fd, VKI_F_DUPFD, VG_(fd_hard_limit));
1472 if (tmp_log_fd < 0) {
1473 VG_(message)(Vg_UserMsg, "valgrind: failed to move logfile fd into safe range, using stderr");
1474 VG_(clo_log_fd) = 2; // stderr
1475 } else {
1476 VG_(clo_log_fd) = tmp_log_fd;
1477 VG_(fcntl)(VG_(clo_log_fd), VKI_F_SETFD, VKI_FD_CLOEXEC);
1478 }
1479 } else {
1480 // If they said --log-fd=-1, don't print anything. Plausible for use in
1481 // regression testing suites that use client requests to count errors.
1482 VG_(clo_log_fd) = tmp_log_fd;
jsgf855d93d2003-10-13 22:26:55 +00001483 }
1484
sewardj45f4e7c2005-09-27 19:20:21 +00001485 if (VG_(clo_n_suppressions) < VG_CLO_MAX_SFILES-1 &&
1486 (VG_(needs).core_errors || VG_(needs).tool_errors)) {
1487 /* If we haven't reached the max number of suppressions, load
1488 the default one. */
1489 static const Char default_supp[] = "default.supp";
1490 Int len = VG_(strlen)(VG_(libdir)) + 1 + sizeof(default_supp);
1491 Char *buf = VG_(arena_malloc)(VG_AR_CORE, len);
1492 VG_(sprintf)(buf, "%s/%s", VG_(libdir), default_supp);
1493 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = buf;
1494 VG_(clo_n_suppressions)++;
1495 }
sewardjde4a1d02002-03-22 01:27:54 +00001496
sewardj45f4e7c2005-09-27 19:20:21 +00001497 return (log_to == VgLogTo_Fd);
1498}
1499
1500
1501/*====================================================================*/
1502/*=== Printing the preamble ===*/
1503/*====================================================================*/
1504
1505/* Ok, the logging sink is running now. Print a suitable preamble.
1506 If logging to file or a socket, write details of parent PID and
1507 command line args, to help people trying to interpret the
1508 results of a run which encompasses multiple processes. */
1509static void print_preamble(Bool logging_to_fd, const char* toolname)
1510{
tom60a4b0b2005-10-12 10:45:27 +00001511 HChar* xpre = VG_(clo_xml) ? " <line>" : "";
1512 HChar* xpost = VG_(clo_xml) ? "</line>" : "";
1513 Int i;
1514
sewardj71bc3cb2005-05-19 00:25:45 +00001515 if (VG_(clo_xml)) {
sewardj8665d8e2005-06-01 17:35:23 +00001516 VG_(message)(Vg_UserMsg, "<?xml version=\"1.0\"?>");
1517 VG_(message)(Vg_UserMsg, "");
sewardj71bc3cb2005-05-19 00:25:45 +00001518 VG_(message)(Vg_UserMsg, "<valgrindoutput>");
1519 VG_(message)(Vg_UserMsg, "");
cerion20241ba2005-11-15 19:07:53 +00001520 VG_(message)(Vg_UserMsg, "<protocolversion>2</protocolversion>");
sewardj71bc3cb2005-05-19 00:25:45 +00001521 VG_(message)(Vg_UserMsg, "");
1522 }
1523
sewardj83adf412002-05-01 01:25:45 +00001524 if (VG_(clo_verbosity > 0)) {
sewardjd7bddad2005-06-13 16:48:32 +00001525
1526 if (VG_(clo_xml))
1527 VG_(message)(Vg_UserMsg, "<preamble>");
1528
nethercote996901a2004-08-03 13:29:09 +00001529 /* Tool details */
sewardj71bc3cb2005-05-19 00:25:45 +00001530 VG_(message)(Vg_UserMsg, "%s%s%s%s, %s.%s",
1531 xpre,
njnd04b7c62002-10-03 14:05:52 +00001532 VG_(details).name,
njnb9c427c2004-12-01 14:14:42 +00001533 NULL == VG_(details).version ? "" : "-",
njnd04b7c62002-10-03 14:05:52 +00001534 NULL == VG_(details).version
1535 ? (Char*)"" : VG_(details).version,
sewardj71bc3cb2005-05-19 00:25:45 +00001536 VG_(details).description,
1537 xpost);
1538 VG_(message)(Vg_UserMsg, "%s%s%s",
1539 xpre, VG_(details).copyright_author, xpost);
sewardj3b2736a2002-03-24 12:18:35 +00001540
njnd04b7c62002-10-03 14:05:52 +00001541 /* Core details */
1542 VG_(message)(Vg_UserMsg,
sewardj71bc3cb2005-05-19 00:25:45 +00001543 "%sUsing LibVEX rev %s, a library for dynamic binary translation.%s",
1544 xpre, LibVEX_Version(), xpost );
sewardjc7025332004-12-13 18:30:39 +00001545 VG_(message)(Vg_UserMsg,
sewardj71bc3cb2005-05-19 00:25:45 +00001546 "%sCopyright (C) 2004-2005, and GNU GPL'd, by OpenWorks LLP.%s",
1547 xpre, xpost );
sewardjc7025332004-12-13 18:30:39 +00001548 VG_(message)(Vg_UserMsg,
sewardj71bc3cb2005-05-19 00:25:45 +00001549 "%sUsing valgrind-%s, a dynamic binary instrumentation framework.%s",
1550 xpre, VERSION, xpost);
sewardjde4a1d02002-03-22 01:27:54 +00001551 VG_(message)(Vg_UserMsg,
sewardj71bc3cb2005-05-19 00:25:45 +00001552 "%sCopyright (C) 2000-2005, and GNU GPL'd, by Julian Seward et al.%s",
1553 xpre, xpost );
sewardjd7bddad2005-06-13 16:48:32 +00001554
sewardj45f4e7c2005-09-27 19:20:21 +00001555 if (VG_(clo_verbosity) == 1 && !VG_(clo_xml))
1556 VG_(message)(Vg_UserMsg, "For more details, rerun with: -v");
1557
sewardjd7bddad2005-06-13 16:48:32 +00001558 if (VG_(clo_xml))
1559 VG_(message)(Vg_UserMsg, "</preamble>");
njnd04b7c62002-10-03 14:05:52 +00001560 }
1561
sewardj45f4e7c2005-09-27 19:20:21 +00001562 if (!VG_(clo_xml) && VG_(clo_verbosity) > 0 && !logging_to_fd) {
sewardj4cf05692002-10-27 20:28:29 +00001563 VG_(message)(Vg_UserMsg, "");
1564 VG_(message)(Vg_UserMsg,
1565 "My PID = %d, parent PID = %d. Prog and args are:",
1566 VG_(getpid)(), VG_(getppid)() );
sewardj5e940782005-09-28 19:59:19 +00001567 if (VG_(args_the_exename))
1568 VG_(message)(Vg_UserMsg, " %s", VG_(args_the_exename));
sewardj45f4e7c2005-09-27 19:20:21 +00001569 for (i = 0; i < VG_(args_for_client).used; i++)
1570 VG_(message)(Vg_UserMsg, " %s", VG_(args_for_client).strs[i]);
sewardj5b742c32005-07-26 23:43:26 +00001571 if (VG_(clo_log_file_qualifier)) {
1572 HChar* val = VG_(getenv)(VG_(clo_log_file_qualifier));
1573 VG_(message)(Vg_UserMsg, "");
1574 VG_(message)(Vg_UserMsg, "Log file qualifier: var %s, value %s.",
1575 VG_(clo_log_file_qualifier),
1576 val ? val : "");
1577 }
sewardj4cf05692002-10-27 20:28:29 +00001578 }
sewardj71bc3cb2005-05-19 00:25:45 +00001579 else
1580 if (VG_(clo_xml)) {
1581 VG_(message)(Vg_UserMsg, "");
1582 VG_(message)(Vg_UserMsg, "<pid>%d</pid>", VG_(getpid)());
1583 VG_(message)(Vg_UserMsg, "<ppid>%d</ppid>", VG_(getppid)());
sewardj97f7e0c2005-07-19 15:00:25 +00001584 VG_(message)(Vg_UserMsg, "<tool>%t</tool>", toolname);
sewardjad311162005-07-19 11:25:02 +00001585 if (VG_(clo_log_file_qualifier)) {
1586 HChar* val = VG_(getenv)(VG_(clo_log_file_qualifier));
sewardj97f7e0c2005-07-19 15:00:25 +00001587 VG_(message)(Vg_UserMsg, "<logfilequalifier> <var>%t</var> "
1588 "<value>%t</value> </logfilequalifier>",
sewardjad311162005-07-19 11:25:02 +00001589 VG_(clo_log_file_qualifier),
1590 val ? val : "");
1591 }
sewardj768db0e2005-07-19 14:18:56 +00001592 if (VG_(clo_xml_user_comment)) {
1593 /* Note: the user comment itself is XML and is therefore to
1594 be passed through verbatim (%s) rather than escaped
1595 (%t). */
1596 VG_(message)(Vg_UserMsg, "<usercomment>%s</usercomment>",
1597 VG_(clo_xml_user_comment));
1598 }
sewardj71bc3cb2005-05-19 00:25:45 +00001599 VG_(message)(Vg_UserMsg, "");
sewardjb8a3dac2005-07-19 12:39:11 +00001600 VG_(message)(Vg_UserMsg, "<args>");
sewardj45f4e7c2005-09-27 19:20:21 +00001601
sewardjb8a3dac2005-07-19 12:39:11 +00001602 VG_(message)(Vg_UserMsg, " <vargv>");
sewardj45f4e7c2005-09-27 19:20:21 +00001603 if (VG_(name_of_launcher))
1604 VG_(message)(Vg_UserMsg, " <exe>%t</exe>",
1605 VG_(name_of_launcher));
1606 for (i = 0; i < VG_(args_for_valgrind).used; i++) {
1607 VG_(message)(Vg_UserMsg,
1608 " <arg>%t</arg>",
1609 VG_(args_for_valgrind).strs[i]);
sewardjb8a3dac2005-07-19 12:39:11 +00001610 }
1611 VG_(message)(Vg_UserMsg, " </vargv>");
sewardj45f4e7c2005-09-27 19:20:21 +00001612
sewardjb8a3dac2005-07-19 12:39:11 +00001613 VG_(message)(Vg_UserMsg, " <argv>");
sewardj45f4e7c2005-09-27 19:20:21 +00001614 if (VG_(args_the_exename))
1615 VG_(message)(Vg_UserMsg, " <exe>%t</exe>",
1616 VG_(args_the_exename));
1617 for (i = 0; i < VG_(args_for_client).used; i++) {
1618 VG_(message)(Vg_UserMsg, " <arg>%t</arg>",
1619 VG_(args_for_client).strs[i]);
sewardj8665d8e2005-06-01 17:35:23 +00001620 }
sewardjb8a3dac2005-07-19 12:39:11 +00001621 VG_(message)(Vg_UserMsg, " </argv>");
sewardj45f4e7c2005-09-27 19:20:21 +00001622
sewardjb8a3dac2005-07-19 12:39:11 +00001623 VG_(message)(Vg_UserMsg, "</args>");
sewardj71bc3cb2005-05-19 00:25:45 +00001624 }
sewardj4cf05692002-10-27 20:28:29 +00001625
sewardj45f4e7c2005-09-27 19:20:21 +00001626 // Empty line after the preamble
1627 if (VG_(clo_verbosity) > 0)
1628 VG_(message)(Vg_UserMsg, "");
1629
sewardjde4a1d02002-03-22 01:27:54 +00001630 if (VG_(clo_verbosity) > 1) {
sewardj92645592005-07-23 09:18:34 +00001631 SysRes fd;
sewardj1f0bbc72005-11-16 03:51:02 +00001632 VexArch vex_arch;
1633 VexArchInfo vex_archinfo;
sewardj45f4e7c2005-09-27 19:20:21 +00001634 if (!logging_to_fd)
njn1fd5eb22005-03-13 05:43:23 +00001635 VG_(message)(Vg_DebugMsg, "");
njn1fd5eb22005-03-13 05:43:23 +00001636 VG_(message)(Vg_DebugMsg, "Command line");
sewardj45f4e7c2005-09-27 19:20:21 +00001637 if (VG_(args_the_exename))
1638 VG_(message)(Vg_DebugMsg, " %s", VG_(args_the_exename));
1639 for (i = 0; i < VG_(args_for_client).used; i++)
1640 VG_(message)(Vg_DebugMsg, " %s", VG_(args_for_client).strs[i]);
njn86dc2bc2003-09-09 07:26:21 +00001641
njn1fd5eb22005-03-13 05:43:23 +00001642 VG_(message)(Vg_DebugMsg, "Startup, with flags:");
sewardj45f4e7c2005-09-27 19:20:21 +00001643 for (i = 0; i < VG_(args_for_valgrind).used; i++) {
1644 VG_(message)(Vg_DebugMsg, " %s", VG_(args_for_valgrind).strs[i]);
sewardjde4a1d02002-03-22 01:27:54 +00001645 }
nethercotea70f7352004-04-18 12:08:46 +00001646
njn1fd5eb22005-03-13 05:43:23 +00001647 VG_(message)(Vg_DebugMsg, "Contents of /proc/version:");
nethercotea70f7352004-04-18 12:08:46 +00001648 fd = VG_(open) ( "/proc/version", VKI_O_RDONLY, 0 );
sewardj92645592005-07-23 09:18:34 +00001649 if (fd.isError) {
njn1fd5eb22005-03-13 05:43:23 +00001650 VG_(message)(Vg_DebugMsg, " can't open /proc/version");
nethercotea70f7352004-04-18 12:08:46 +00001651 } else {
sewardj71bc3cb2005-05-19 00:25:45 +00001652# define BUF_LEN 256
nethercotea70f7352004-04-18 12:08:46 +00001653 Char version_buf[BUF_LEN];
sewardj92645592005-07-23 09:18:34 +00001654 Int n = VG_(read) ( fd.val, version_buf, BUF_LEN );
njnbe9b47b2005-05-15 16:22:58 +00001655 vg_assert(n <= BUF_LEN);
nethercotea70f7352004-04-18 12:08:46 +00001656 if (n > 0) {
1657 version_buf[n-1] = '\0';
njn1fd5eb22005-03-13 05:43:23 +00001658 VG_(message)(Vg_DebugMsg, " %s", version_buf);
nethercotea70f7352004-04-18 12:08:46 +00001659 } else {
njn1fd5eb22005-03-13 05:43:23 +00001660 VG_(message)(Vg_DebugMsg, " (empty?)");
nethercotea70f7352004-04-18 12:08:46 +00001661 }
sewardj92645592005-07-23 09:18:34 +00001662 VG_(close)(fd.val);
sewardj71bc3cb2005-05-19 00:25:45 +00001663# undef BUF_LEN
nethercotea70f7352004-04-18 12:08:46 +00001664 }
sewardj1f0bbc72005-11-16 03:51:02 +00001665
1666 VG_(machine_get_VexArchInfo)( &vex_arch, &vex_archinfo );
sewardje3121f32006-01-27 21:23:23 +00001667 VG_(message)(
1668 Vg_DebugMsg,
1669 "Arch and hwcaps: %s, %s",
1670 LibVEX_ppVexArch ( vex_arch ),
1671 LibVEX_ppVexHwCaps ( vex_arch, vex_archinfo.hwcaps )
1672 );
sewardj1f0bbc72005-11-16 03:51:02 +00001673 VG_(message)(Vg_DebugMsg, "Valgrind library directory: %s", VG_(libdir));
sewardjde4a1d02002-03-22 01:27:54 +00001674 }
nethercotef6a1d502004-08-09 12:21:57 +00001675}
1676
sewardjde4a1d02002-03-22 01:27:54 +00001677
nethercote71980f02004-01-24 18:18:54 +00001678/*====================================================================*/
1679/*=== File descriptor setup ===*/
1680/*====================================================================*/
1681
sewardj5f229e22005-09-28 01:36:01 +00001682/* Number of file descriptors that Valgrind tries to reserve for
1683 it's own use - just a small constant. */
1684#define N_RESERVED_FDS (10)
1685
nethercote71980f02004-01-24 18:18:54 +00001686static void setup_file_descriptors(void)
1687{
1688 struct vki_rlimit rl;
1689
1690 /* Get the current file descriptor limits. */
1691 if (VG_(getrlimit)(VKI_RLIMIT_NOFILE, &rl) < 0) {
1692 rl.rlim_cur = 1024;
1693 rl.rlim_max = 1024;
1694 }
1695
1696 /* Work out where to move the soft limit to. */
njn14319cc2005-03-13 06:26:22 +00001697 if (rl.rlim_cur + N_RESERVED_FDS <= rl.rlim_max) {
1698 rl.rlim_cur = rl.rlim_cur + N_RESERVED_FDS;
nethercote71980f02004-01-24 18:18:54 +00001699 } else {
1700 rl.rlim_cur = rl.rlim_max;
1701 }
1702
1703 /* Reserve some file descriptors for our use. */
njn14319cc2005-03-13 06:26:22 +00001704 VG_(fd_soft_limit) = rl.rlim_cur - N_RESERVED_FDS;
1705 VG_(fd_hard_limit) = rl.rlim_cur - N_RESERVED_FDS;
nethercote71980f02004-01-24 18:18:54 +00001706
1707 /* Update the soft limit. */
1708 VG_(setrlimit)(VKI_RLIMIT_NOFILE, &rl);
1709
sewardj45f4e7c2005-09-27 19:20:21 +00001710 if (VG_(cl_exec_fd) != -1)
1711 VG_(cl_exec_fd) = VG_(safe_fd)( VG_(cl_exec_fd) );
nethercote71980f02004-01-24 18:18:54 +00001712}
1713
sewardjde4a1d02002-03-22 01:27:54 +00001714
njn2da73352005-06-18 01:35:16 +00001715/*====================================================================*/
1716/*=== Initialise the first thread. ===*/
1717/*====================================================================*/
1718
1719/* Given a pointer to the ThreadArchState for thread 1 (the root
1720 thread), initialise the VEX guest state, and copy in essential
1721 starting values.
1722*/
1723static void init_thread1state ( Addr client_ip,
sewardjfdf91b42005-09-28 00:53:09 +00001724 Addr client_sp,
sewardj13247ca2005-12-30 22:52:20 +00001725 Addr client_toc,
njn2da73352005-06-18 01:35:16 +00001726 /*inout*/ ThreadArchState* arch )
1727{
1728#if defined(VGA_x86)
1729 vg_assert(0 == sizeof(VexGuestX86State) % 8);
1730
1731 /* Zero out the initial state, and set up the simulated FPU in a
1732 sane way. */
1733 LibVEX_GuestX86_initialise(&arch->vex);
1734
1735 /* Zero out the shadow area. */
1736 VG_(memset)(&arch->vex_shadow, 0, sizeof(VexGuestX86State));
1737
1738 /* Put essential stuff into the new state. */
sewardjfdf91b42005-09-28 00:53:09 +00001739 arch->vex.guest_ESP = client_sp;
njn2da73352005-06-18 01:35:16 +00001740 arch->vex.guest_EIP = client_ip;
1741
1742 /* initialise %cs, %ds and %ss to point at the operating systems
1743 default code, data and stack segments */
1744 asm volatile("movw %%cs, %0" : : "m" (arch->vex.guest_CS));
1745 asm volatile("movw %%ds, %0" : : "m" (arch->vex.guest_DS));
1746 asm volatile("movw %%ss, %0" : : "m" (arch->vex.guest_SS));
cerion85665ca2005-06-20 15:51:07 +00001747
njn2da73352005-06-18 01:35:16 +00001748#elif defined(VGA_amd64)
1749 vg_assert(0 == sizeof(VexGuestAMD64State) % 8);
1750
1751 /* Zero out the initial state, and set up the simulated FPU in a
1752 sane way. */
1753 LibVEX_GuestAMD64_initialise(&arch->vex);
1754
1755 /* Zero out the shadow area. */
1756 VG_(memset)(&arch->vex_shadow, 0, sizeof(VexGuestAMD64State));
1757
1758 /* Put essential stuff into the new state. */
sewardjfdf91b42005-09-28 00:53:09 +00001759 arch->vex.guest_RSP = client_sp;
njn2da73352005-06-18 01:35:16 +00001760 arch->vex.guest_RIP = client_ip;
cerion85665ca2005-06-20 15:51:07 +00001761
1762#elif defined(VGA_ppc32)
1763 vg_assert(0 == sizeof(VexGuestPPC32State) % 8);
1764
1765 /* Zero out the initial state, and set up the simulated FPU in a
1766 sane way. */
1767 LibVEX_GuestPPC32_initialise(&arch->vex);
1768
1769 /* Zero out the shadow area. */
1770 VG_(memset)(&arch->vex_shadow, 0, sizeof(VexGuestPPC32State));
1771
1772 /* Put essential stuff into the new state. */
sewardjfdf91b42005-09-28 00:53:09 +00001773 arch->vex.guest_GPR1 = client_sp;
cerion85665ca2005-06-20 15:51:07 +00001774 arch->vex.guest_CIA = client_ip;
1775
sewardj2c48c7b2005-11-29 13:05:56 +00001776#elif defined(VGA_ppc64)
cerion21082042005-12-06 19:07:08 +00001777 vg_assert(0 == sizeof(VexGuestPPC64State) % 16);
sewardj2c48c7b2005-11-29 13:05:56 +00001778
1779 /* Zero out the initial state, and set up the simulated FPU in a
1780 sane way. */
1781 LibVEX_GuestPPC64_initialise(&arch->vex);
1782
1783 /* Zero out the shadow area. */
1784 VG_(memset)(&arch->vex_shadow, 0, sizeof(VexGuestPPC64State));
1785
1786 /* Put essential stuff into the new state. */
1787 arch->vex.guest_GPR1 = client_sp;
sewardj13247ca2005-12-30 22:52:20 +00001788 arch->vex.guest_GPR2 = client_toc;
sewardj2c48c7b2005-11-29 13:05:56 +00001789 arch->vex.guest_CIA = client_ip;
njn2da73352005-06-18 01:35:16 +00001790#else
1791# error Unknown arch
1792#endif
1793 // Tell the tool that we just wrote to the registers.
1794 VG_TRACK( post_reg_write, Vg_CoreStartup, /*tid*/1, /*offset*/0,
1795 sizeof(VexGuestArchState));
1796}
1797
sewardjde4a1d02002-03-22 01:27:54 +00001798
nethercote71980f02004-01-24 18:18:54 +00001799/*====================================================================*/
njn2025cf92005-06-26 20:44:48 +00001800/*=== BB profiling ===*/
1801/*====================================================================*/
1802
1803static
1804void show_BB_profile ( BBProfEntry tops[], UInt n_tops, ULong score_total )
1805{
1806 ULong score_cumul, score_here;
1807 Char buf_cumul[10], buf_here[10];
1808 Char name[64];
1809 Int r;
1810
1811 VG_(printf)("\n");
1812 VG_(printf)("-----------------------------------------------------------\n");
1813 VG_(printf)("--- BEGIN BB Profile (summary of scores) ---\n");
1814 VG_(printf)("-----------------------------------------------------------\n");
1815 VG_(printf)("\n");
1816
1817 VG_(printf)("Total score = %lld\n\n", score_total);
1818
1819 score_cumul = 0;
1820 for (r = 0; r < n_tops; r++) {
1821 if (tops[r].addr == 0)
1822 continue;
1823 name[0] = 0;
1824 VG_(get_fnname_w_offset)(tops[r].addr, name, 64);
1825 name[63] = 0;
1826 score_here = tops[r].score;
1827 score_cumul += score_here;
1828 VG_(percentify)(score_cumul, score_total, 2, 6, buf_cumul);
1829 VG_(percentify)(score_here, score_total, 2, 6, buf_here);
1830 VG_(printf)("%3d: (%9lld %s) %9lld %s 0x%llx %s\n",
1831 r,
1832 score_cumul, buf_cumul,
1833 score_here, buf_here, tops[r].addr, name );
1834 }
1835
1836 VG_(printf)("\n");
1837 VG_(printf)("-----------------------------------------------------------\n");
1838 VG_(printf)("--- BB Profile (BB details) ---\n");
1839 VG_(printf)("-----------------------------------------------------------\n");
1840 VG_(printf)("\n");
1841
1842 score_cumul = 0;
1843 for (r = 0; r < n_tops; r++) {
1844 if (tops[r].addr == 0)
1845 continue;
1846 name[0] = 0;
1847 VG_(get_fnname_w_offset)(tops[r].addr, name, 64);
1848 name[63] = 0;
1849 score_here = tops[r].score;
1850 score_cumul += score_here;
1851 VG_(percentify)(score_cumul, score_total, 2, 6, buf_cumul);
1852 VG_(percentify)(score_here, score_total, 2, 6, buf_here);
1853 VG_(printf)("\n");
1854 VG_(printf)("=-=-=-=-=-=-=-=-=-=-=-=-=-= begin BB rank %d "
1855 "=-=-=-=-=-=-=-=-=-=-=-=-=-=\n\n", r);
1856 VG_(printf)("%3d: (%9lld %s) %9lld %s 0x%llx %s\n",
1857 r,
1858 score_cumul, buf_cumul,
1859 score_here, buf_here, tops[r].addr, name );
1860 VG_(printf)("\n");
sewardj0ec07f32006-01-12 12:32:32 +00001861 VG_(translate)(0, tops[r].addr, True, VG_(clo_profile_flags), 0, True);
njn2025cf92005-06-26 20:44:48 +00001862 VG_(printf)("=-=-=-=-=-=-=-=-=-=-=-=-=-= end BB rank %d "
1863 "=-=-=-=-=-=-=-=-=-=-=-=-=-=\n\n", r);
1864 }
1865
1866 VG_(printf)("\n");
1867 VG_(printf)("-----------------------------------------------------------\n");
1868 VG_(printf)("--- END BB Profile ---\n");
1869 VG_(printf)("-----------------------------------------------------------\n");
1870 VG_(printf)("\n");
1871}
1872
1873
1874/*====================================================================*/
nethercote71980f02004-01-24 18:18:54 +00001875/*=== main() ===*/
1876/*====================================================================*/
1877
sewardjfdf91b42005-09-28 00:53:09 +00001878/* When main() is entered, we should be on the following stack, not
1879 the one the kernel gave us. We will run on this stack until
1880 simulation of the root thread is started, at which point a transfer
1881 is made to a dynamically allocated stack. This is for the sake of
1882 uniform overflow detection for all Valgrind threads. This is
1883 marked global even though it isn't, because assembly code below
1884 needs to reference the name. */
1885
1886/*static*/ VgStack VG_(interim_stack);
1887
1888/* This should get some address inside the stack on which we gained
1889 control (eg, it could be the SP at startup). It doesn't matter
1890 exactly where in the stack it is. This value is passed to the
1891 address space manager at startup, which uses it to identify the
1892 initial stack segment and hence the upper end of the usable address
1893 space. */
1894
1895static Addr sp_at_startup = 0;
1896
sewardj1ae3f3a2005-09-28 10:47:38 +00001897/* --- Forwards decls to do with shutdown --- */
1898
1899static void final_tidyup(ThreadId tid);
1900
1901/* Do everything which needs doing when the last thread exits */
1902static
1903void shutdown_actions_NORETURN( ThreadId tid,
1904 VgSchedReturnCode tids_schedretcode );
1905
1906/* --- end of Forwards decls to do with shutdown --- */
sewardjfdf91b42005-09-28 00:53:09 +00001907
1908
sewardj45f4e7c2005-09-27 19:20:21 +00001909/* TODO: GIVE THIS A PROPER HOME
1910 TODO: MERGE THIS WITH DUPLICATE IN mac_leakcheck.c
1911 Extract from aspacem a vector of the current segment start
1912 addresses. The vector is dynamically allocated and should be freed
1913 by the caller when done. REQUIRES m_mallocfree to be running.
1914 Writes the number of addresses required into *n_acquired. */
nethercotec314eba2004-07-15 12:59:41 +00001915
sewardj45f4e7c2005-09-27 19:20:21 +00001916static Addr* get_seg_starts ( /*OUT*/Int* n_acquired )
sewardj1cf558c2005-04-25 01:36:56 +00001917{
sewardj45f4e7c2005-09-27 19:20:21 +00001918 Addr* starts;
sewardja48a4932005-09-29 11:09:56 +00001919 Int n_starts, r = 0;
sewardj45f4e7c2005-09-27 19:20:21 +00001920
1921 n_starts = 1;
sewardj1cf558c2005-04-25 01:36:56 +00001922 while (True) {
sewardj45f4e7c2005-09-27 19:20:21 +00001923 starts = VG_(malloc)( n_starts * sizeof(Addr) );
1924 if (starts == NULL)
1925 break;
1926 r = VG_(am_get_segment_starts)( starts, n_starts );
1927 if (r >= 0)
1928 break;
1929 VG_(free)(starts);
1930 n_starts *= 2;
sewardj1cf558c2005-04-25 01:36:56 +00001931 }
sewardj45f4e7c2005-09-27 19:20:21 +00001932
1933 if (starts == NULL) {
1934 *n_acquired = 0;
1935 return NULL;
1936 }
1937
1938 *n_acquired = r;
1939 return starts;
sewardj1cf558c2005-04-25 01:36:56 +00001940}
1941
1942
sewardj45f4e7c2005-09-27 19:20:21 +00001943
sewardj45f4e7c2005-09-27 19:20:21 +00001944Int main(Int argc, HChar **argv, HChar **envp)
nethercote71980f02004-01-24 18:18:54 +00001945{
sewardj13247ca2005-12-30 22:52:20 +00001946 HChar* toolname = "memcheck"; // default to Memcheck
1947 HChar** env = NULL;
1948 Int need_help = 0; // 0 = no, 1 = --help, 2 = --help-debug
1949 Addr initial_client_IP = 0;
1950 Addr initial_client_SP = 0;
1951 Addr initial_client_TOC = 0;
1952 Addr clstack_top = 0;
1953 SizeT clstack_max_size = 0;
sewardj45f4e7c2005-09-27 19:20:21 +00001954 UInt* client_auxv;
1955 Int loglevel, i;
1956 Bool logging_to_fd;
nethercote73b526f2004-10-31 18:48:21 +00001957 struct vki_rlimit zero = { 0, 0 };
sewardj13247ca2005-12-30 22:52:20 +00001958 ExeInfo info;
nethercote71980f02004-01-24 18:18:54 +00001959
1960 //============================================================
nethercote71980f02004-01-24 18:18:54 +00001961 //
sewardj45f4e7c2005-09-27 19:20:21 +00001962 // Nb: startup is complex. Prerequisites are shown at every step.
nethercote71980f02004-01-24 18:18:54 +00001963 // *** Be very careful when messing with the order ***
sewardj45f4e7c2005-09-27 19:20:21 +00001964 //
1965 // The first order of business is to get debug logging, the address
1966 // space manager and the dynamic memory manager up and running.
1967 // Once that's done, we can relax a bit.
1968 //
nethercote71980f02004-01-24 18:18:54 +00001969 //============================================================
sewardj45f4e7c2005-09-27 19:20:21 +00001970
1971 /* This is needed to make VG_(getenv) usable early. */
1972 VG_(client_envp) = (Char**)envp;
nethercote71980f02004-01-24 18:18:54 +00001973
sewardj1cf558c2005-04-25 01:36:56 +00001974 //--------------------------------------------------------------
1975 // Start up the logging mechanism
1976 // p: none
1977 //--------------------------------------------------------------
1978 /* Start the debugging-log system ASAP. First find out how many
1979 "-d"s were specified. This is a pre-scan of the command line. */
1980 loglevel = 0;
1981 for (i = 1; i < argc; i++) {
sewardj10759312005-05-30 23:52:47 +00001982 if (argv[i][0] != '-')
1983 break;
sewardj45f4e7c2005-09-27 19:20:21 +00001984 if (VG_STREQ(argv[i], "--"))
sewardj10759312005-05-30 23:52:47 +00001985 break;
sewardj45f4e7c2005-09-27 19:20:21 +00001986 if (VG_STREQ(argv[i], "-d"))
sewardj10759312005-05-30 23:52:47 +00001987 loglevel++;
sewardj1cf558c2005-04-25 01:36:56 +00001988 }
1989
1990 /* ... and start the debug logger. Now we can safely emit logging
1991 messages all through startup. */
sewardj10759312005-05-30 23:52:47 +00001992 VG_(debugLog_startup)(loglevel, "Stage 2 (main)");
sewardj45f4e7c2005-09-27 19:20:21 +00001993 VG_(debugLog)(1, "main", "Welcome to Valgrind version "
1994 VERSION " debug logging\n");
1995
1996 //--------------------------------------------------------------
1997 // Ensure we're on a plausible stack.
1998 // p: logging
1999 //--------------------------------------------------------------
2000 VG_(debugLog)(1, "main", "Checking current stack is plausible\n");
sewardjfdf91b42005-09-28 00:53:09 +00002001 { HChar* limLo = (HChar*)(&VG_(interim_stack).bytes[0]);
2002 HChar* limHi = limLo + sizeof(VG_(interim_stack));
sewardj45f4e7c2005-09-27 19:20:21 +00002003 HChar* aLocal = (HChar*)&zero; /* any auto local will do */
2004 if (aLocal < limLo || aLocal >= limHi) {
2005 /* something's wrong. Stop. */
2006 VG_(debugLog)(0, "main", "Root stack %p to %p, a local %p\n",
2007 limLo, limHi, aLocal );
2008 VG_(debugLog)(0, "main", "Valgrind: FATAL: "
2009 "Initial stack switched failed.\n");
2010 VG_(debugLog)(0, "main", " Cannot continue. Sorry.\n");
2011 VG_(exit)(1);
2012 }
2013 }
2014
2015 //--------------------------------------------------------------
2016 // Ensure we have a plausible pointer to the stack on which
2017 // we gained control (not the current stack!)
2018 // p: logging
2019 //--------------------------------------------------------------
2020 VG_(debugLog)(1, "main", "Checking initial stack was noted\n");
sewardjfdf91b42005-09-28 00:53:09 +00002021 if (sp_at_startup == 0) {
sewardj45f4e7c2005-09-27 19:20:21 +00002022 VG_(debugLog)(0, "main", "Valgrind: FATAL: "
2023 "Initial stack was not noted.\n");
2024 VG_(debugLog)(0, "main", " Cannot continue. Sorry.\n");
2025 VG_(exit)(1);
2026 }
2027
2028 //--------------------------------------------------------------
2029 // Start up the address space manager, and determine the
2030 // approximate location of the client's stack
2031 // p: logging, plausible-stack
2032 //--------------------------------------------------------------
2033 VG_(debugLog)(1, "main", "Starting the address space manager\n");
sewardjfdf91b42005-09-28 00:53:09 +00002034 clstack_top = VG_(am_startup)( sp_at_startup );
sewardj45f4e7c2005-09-27 19:20:21 +00002035 VG_(debugLog)(1, "main", "Address space manager is running\n");
2036
2037 //--------------------------------------------------------------
2038 // Start up the dynamic memory manager
2039 // p: address space management
2040 // In fact m_mallocfree is self-initialising, so there's no
2041 // initialisation call to do. Instead, try a simple malloc/
2042 // free pair right now to check that nothing is broken.
2043 //--------------------------------------------------------------
2044 VG_(debugLog)(1, "main", "Starting the dynamic memory manager\n");
2045 { void* p = VG_(malloc)( 12345 );
2046 if (p) VG_(free)( p );
2047 }
2048 VG_(debugLog)(1, "main", "Dynamic memory manager is running\n");
sewardj1cf558c2005-04-25 01:36:56 +00002049
nethercotef4928da2004-06-15 10:54:40 +00002050 //============================================================
sewardj45f4e7c2005-09-27 19:20:21 +00002051 //
2052 // Dynamic memory management is now available.
2053 //
nethercotef4928da2004-06-15 10:54:40 +00002054 //============================================================
2055
sewardj45f4e7c2005-09-27 19:20:21 +00002056 //--------------------------------------------------------------
2057 // Look for alternative libdir
2058 { HChar *cp = VG_(getenv)(VALGRIND_LIB);
2059 if (cp != NULL)
2060 VG_(libdir) = cp;
2061 }
2062
2063 //--------------------------------------------------------------
2064 // Extract the launcher name from the environment.
2065 VG_(debugLog)(1, "main", "Getting stage1's name\n");
2066 VG_(name_of_launcher) = VG_(getenv)(VALGRIND_LAUNCHER);
2067 if (VG_(name_of_launcher) == NULL) {
2068 VG_(printf)("valgrind: You cannot run '%s' directly.\n", argv[0]);
2069 VG_(printf)("valgrind: You should use $prefix/bin/valgrind.\n");
2070 VG_(exit)(1);
2071 }
2072
2073 //--------------------------------------------------------------
fitzhardingeb50068f2004-02-24 23:42:55 +00002074 // Get the current process datasize rlimit, and set it to zero.
2075 // This prevents any internal uses of brk() from having any effect.
2076 // We remember the old value so we can restore it on exec, so that
2077 // child processes will have a reasonable brk value.
2078 VG_(getrlimit)(VKI_RLIMIT_DATA, &VG_(client_rlimit_data));
2079 zero.rlim_max = VG_(client_rlimit_data).rlim_max;
2080 VG_(setrlimit)(VKI_RLIMIT_DATA, &zero);
thughesc37184f2004-09-11 14:16:57 +00002081
2082 // Get the current process stack rlimit.
2083 VG_(getrlimit)(VKI_RLIMIT_STACK, &VG_(client_rlimit_stack));
2084
sewardje2d1e672005-11-12 23:10:48 +00002085 //--------------------------------------------------------------
2086 // Figure out what sort of CPU we're on, and whether it is
2087 // able to run V.
2088 VG_(debugLog)(1, "main", "Get hardware capabilities ...\n");
2089 { VexArch vex_arch;
2090 VexArchInfo vex_archinfo;
2091 Bool ok = VG_(machine_get_hwcaps)();
2092 if (!ok) {
2093 VG_(printf)("\n");
2094 VG_(printf)("valgrind: fatal error: unsupported CPU.\n");
2095 VG_(printf)(" Supported CPUs are:\n");
2096 VG_(printf)(" * x86 (practically any; Pentium-I or above), "
2097 "AMD Athlon or above)\n");
2098 VG_(printf)(" * AMD Athlon64/Opteron\n");
2099 VG_(printf)(" * PowerPC (most; ppc405 and above)\n");
2100 VG_(printf)("\n");
2101 VG_(exit)(1);
2102 }
2103 VG_(machine_get_VexArchInfo)( &vex_arch, &vex_archinfo );
sewardje3121f32006-01-27 21:23:23 +00002104 VG_(debugLog)(
2105 1, "main", "... arch = %s, hwcaps = %s\n",
2106 LibVEX_ppVexArch ( vex_arch ),
2107 LibVEX_ppVexHwCaps ( vex_arch, vex_archinfo.hwcaps )
2108 );
sewardje2d1e672005-11-12 23:10:48 +00002109 }
2110
sewardj45f4e7c2005-09-27 19:20:21 +00002111 //============================================================
2112 // Command line argument handling order:
2113 // * If --help/--help-debug are present, show usage message
2114 // (including the tool-specific usage)
2115 // * (If no --tool option given, default to Memcheck)
2116 // * Then, if client is missing, abort with error msg
2117 // * Then, if any cmdline args are bad, abort with error msg
2118 //============================================================
2119
2120 //--------------------------------------------------------------
2121 // Split up argv into: C args, V args, V extra args, and exename.
2122 // p: dynamic memory allocation
2123 //--------------------------------------------------------------
2124 VG_(debugLog)(1, "main", "Split up command line\n");
2125 VG_(split_up_argv)( argc, argv );
2126 if (0) {
2127 for (i = 0; i < VG_(args_for_valgrind).used; i++)
2128 VG_(printf)("varg %s\n", VG_(args_for_valgrind).strs[i]);
2129 VG_(printf)(" exe %s\n", VG_(args_the_exename));
2130 for (i = 0; i < VG_(args_for_client).used; i++)
2131 VG_(printf)("carg %s\n", VG_(args_for_client).strs[i]);
nethercote71980f02004-01-24 18:18:54 +00002132 }
2133
2134 //--------------------------------------------------------------
sewardj45f4e7c2005-09-27 19:20:21 +00002135 // Extract tool name and whether help has been requested.
2136 // Note we can't print the help message yet, even if requested,
2137 // because the tool has not been initialised.
2138 // p: split_up_argv [for VG_(args_for_valgrind)]
nethercote71980f02004-01-24 18:18:54 +00002139 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002140 VG_(debugLog)(1, "main", "Preprocess command line opts\n");
sewardj45f4e7c2005-09-27 19:20:21 +00002141 get_helprequest_and_toolname(&need_help, &toolname);
nethercote71980f02004-01-24 18:18:54 +00002142
sewardj45f4e7c2005-09-27 19:20:21 +00002143 // Set default vex control params
2144 LibVEX_default_VexControl(& VG_(clo_vex_control));
nethercote71980f02004-01-24 18:18:54 +00002145
2146 //--------------------------------------------------------------
2147 // Load client executable, finding in $PATH if necessary
sewardj45f4e7c2005-09-27 19:20:21 +00002148 // p: get_helprequest_and_toolname() [for 'exec', 'need_help']
nethercote71980f02004-01-24 18:18:54 +00002149 // p: layout_remaining_space [so there's space]
2150 //--------------------------------------------------------------
sewardj45f4e7c2005-09-27 19:20:21 +00002151 if (!need_help) {
2152 VG_(debugLog)(1, "main", "Loading client\n");
nethercote71980f02004-01-24 18:18:54 +00002153
sewardj45f4e7c2005-09-27 19:20:21 +00002154 if (VG_(args_the_exename) == NULL)
2155 missing_prog();
2156
sewardj13247ca2005-12-30 22:52:20 +00002157 load_client(&info, &initial_client_IP, &initial_client_TOC);
sewardj45f4e7c2005-09-27 19:20:21 +00002158 }
nethercote71980f02004-01-24 18:18:54 +00002159
2160 //--------------------------------------------------------------
2161 // Set up client's environment
sewardj45f4e7c2005-09-27 19:20:21 +00002162 // p: set-libdir [for VG_(libdir)]
2163 // p: get_helprequest_and_toolname [for toolname]
nethercote71980f02004-01-24 18:18:54 +00002164 //--------------------------------------------------------------
sewardj45f4e7c2005-09-27 19:20:21 +00002165 if (!need_help) {
2166 VG_(debugLog)(1, "main", "Setup client env\n");
2167 env = setup_client_env(envp, toolname);
2168 }
nethercote71980f02004-01-24 18:18:54 +00002169
2170 //--------------------------------------------------------------
nethercote5ee67ca2004-06-22 14:00:09 +00002171 // Setup client stack, eip, and VG_(client_arg[cv])
nethercote71980f02004-01-24 18:18:54 +00002172 // p: load_client() [for 'info']
2173 // p: fix_environment() [for 'env']
2174 //--------------------------------------------------------------
sewardj45f4e7c2005-09-27 19:20:21 +00002175 if (!need_help) {
2176 void* init_sp = argv - 1;
sewardjc8c5c872006-02-09 11:16:18 +00002177 SizeT m1 = 1024 * 1024;
2178 SizeT m16 = 16 * m1;
sewardj45f4e7c2005-09-27 19:20:21 +00002179 VG_(debugLog)(1, "main", "Setup client stack\n");
2180 clstack_max_size = (SizeT)VG_(client_rlimit_stack).rlim_cur;
sewardjc8c5c872006-02-09 11:16:18 +00002181 if (clstack_max_size < m1) clstack_max_size = m1;
2182 if (clstack_max_size > m16) clstack_max_size = m16;
sewardj45f4e7c2005-09-27 19:20:21 +00002183 clstack_max_size = VG_PGROUNDUP(clstack_max_size);
sewardjb5f6f512005-03-10 23:59:00 +00002184
sewardj45f4e7c2005-09-27 19:20:21 +00002185 initial_client_SP
2186 = setup_client_stack( init_sp, env,
2187 &info, &client_auxv,
2188 clstack_top, clstack_max_size );
2189
2190 VG_(free)(env);
2191
2192 VG_(debugLog)(2, "main",
2193 "Client info: "
sewardj13247ca2005-12-30 22:52:20 +00002194 "initial_IP=%p initial_SP=%p initial_TOC=%p brk_base=%p\n",
sewardj45f4e7c2005-09-27 19:20:21 +00002195 (void*)initial_client_IP,
2196 (void*)initial_client_SP,
sewardj13247ca2005-12-30 22:52:20 +00002197 (void*)initial_client_TOC,
sewardj45f4e7c2005-09-27 19:20:21 +00002198 (void*)VG_(brk_base) );
nethercotec25c4492004-10-18 11:52:17 +00002199 }
nethercote71980f02004-01-24 18:18:54 +00002200
sewardj45f4e7c2005-09-27 19:20:21 +00002201 //--------------------------------------------------------------
2202 // Setup client data (brk) segment. Initially a 1-page segment
2203 // which abuts a shrinkable reservation.
2204 // p: load_client() [for 'info' and hence VG_(brk_base)]
2205 //--------------------------------------------------------------
2206 if (!need_help) {
2207 SizeT m1 = 1024 * 1024;
2208 SizeT m8 = 8 * m1;
2209 SizeT dseg_max_size = (SizeT)VG_(client_rlimit_data).rlim_cur;
2210 VG_(debugLog)(1, "main", "Setup client data (brk) segment\n");
2211 if (dseg_max_size < m1) dseg_max_size = m1;
2212 if (dseg_max_size > m8) dseg_max_size = m8;
2213 dseg_max_size = VG_PGROUNDUP(dseg_max_size);
2214
2215 setup_client_dataseg( dseg_max_size );
2216 }
nethercote71980f02004-01-24 18:18:54 +00002217
2218 //==============================================================
sewardj45f4e7c2005-09-27 19:20:21 +00002219 //
2220 // Finished loading/setting up the client address space.
2221 //
nethercote71980f02004-01-24 18:18:54 +00002222 //==============================================================
2223
2224 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002225 // setup file descriptors
2226 // p: n/a
2227 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002228 VG_(debugLog)(1, "main", "Setup file descriptors\n");
nethercote71980f02004-01-24 18:18:54 +00002229 setup_file_descriptors();
2230
2231 //--------------------------------------------------------------
sewardj45f4e7c2005-09-27 19:20:21 +00002232 // create the fake /proc/<pid>/cmdline file and then unlink it,
2233 // but hold onto the fd, so we can hand it out to the client
2234 // when it tries to open /proc/<pid>/cmdline for itself.
2235 // p: setup file descriptors
nethercotec314eba2004-07-15 12:59:41 +00002236 //--------------------------------------------------------------
sewardj45f4e7c2005-09-27 19:20:21 +00002237 if (!need_help) {
2238 HChar buf[50], buf2[50+64];
2239 HChar nul[1];
2240 Int fd, r;
2241 HChar* exename;
nethercotec314eba2004-07-15 12:59:41 +00002242
sewardj45f4e7c2005-09-27 19:20:21 +00002243 VG_(debugLog)(1, "main", "Create fake /proc/<pid>/cmdline\n");
2244
2245 VG_(sprintf)(buf, "proc_%d_cmdline", VG_(getpid)());
2246 fd = VG_(mkstemp)( buf, buf2 );
2247 if (fd == -1)
2248 config_error("Can't create client cmdline file in /tmp.");
2249
2250 nul[0] = 0;
2251 exename = VG_(args_the_exename) ? VG_(args_the_exename)
2252 : "unknown_exename";
2253
2254 VG_(write)(fd, VG_(args_the_exename),
2255 VG_(strlen)( VG_(args_the_exename) ));
2256 VG_(write)(fd, nul, 1);
2257
2258 for (i = 0; i < VG_(args_for_client).used; i++) {
2259 VG_(write)(fd, VG_(args_for_client).strs[i],
2260 VG_(strlen)( VG_(args_for_client).strs[i] ));
2261 VG_(write)(fd, nul, 1);
2262 }
2263
2264 /* Don't bother to seek the file back to the start; instead do
2265 it every time a copy of it is given out (by PRE(sys_open)).
2266 That is probably more robust across fork() etc. */
2267
2268 /* Now delete it, but hang on to the fd. */
2269 r = VG_(unlink)( buf2 );
2270 if (r)
2271 config_error("Can't delete client cmdline file in /tmp.");
2272
2273 VG_(cl_cmdline_fd) = fd;
2274 }
nethercotec314eba2004-07-15 12:59:41 +00002275
2276 //--------------------------------------------------------------
sewardj45f4e7c2005-09-27 19:20:21 +00002277 // Init tool part 1: pre_clo_init
nethercotec314eba2004-07-15 12:59:41 +00002278 // p: setup_client_stack() [for 'VG_(client_arg[cv]']
nethercotec314eba2004-07-15 12:59:41 +00002279 // p: setup_file_descriptors() [for 'VG_(fd_xxx_limit)']
nethercote71980f02004-01-24 18:18:54 +00002280 //--------------------------------------------------------------
njn64c83242005-06-21 01:54:38 +00002281 {
2282 Char* s;
2283 Bool ok;
sewardj45f4e7c2005-09-27 19:20:21 +00002284 VG_(debugLog)(1, "main", "Initialise the tool part 1 (pre_clo_init)\n");
2285 (VG_(tool_info).tl_pre_clo_init)();
2286 ok = VG_(sanity_check_needs)( &s );
njn64c83242005-06-21 01:54:38 +00002287 if (!ok) {
2288 VG_(tool_panic)(s);
2289 }
2290 }
nethercote71980f02004-01-24 18:18:54 +00002291
sewardj45f4e7c2005-09-27 19:20:21 +00002292 //--------------------------------------------------------------
nethercotef4928da2004-06-15 10:54:40 +00002293 // If --tool and --help/--help-debug was given, now give the core+tool
2294 // help message
sewardj45f4e7c2005-09-27 19:20:21 +00002295 // p: get_helprequest_and_toolname() [for 'need_help']
2296 // p: tl_pre_clo_init [for 'VG_(tdict).usage']
2297 //--------------------------------------------------------------
2298 VG_(debugLog)(1, "main", "Print help and quit, if requested\n");
nethercotef4928da2004-06-15 10:54:40 +00002299 if (need_help) {
sewardj45f4e7c2005-09-27 19:20:21 +00002300 usage_NORETURN(/*--help-debug?*/2 == need_help);
nethercotef4928da2004-06-15 10:54:40 +00002301 }
nethercotec314eba2004-07-15 12:59:41 +00002302
sewardj45f4e7c2005-09-27 19:20:21 +00002303 //--------------------------------------------------------------
2304 // Process command line options to Valgrind + tool
2305 // p: setup_client_stack() [for 'VG_(client_arg[cv]']
2306 // p: setup_file_descriptors() [for 'VG_(fd_xxx_limit)']
2307 //--------------------------------------------------------------
2308 VG_(debugLog)(1, "main", "Process Valgrind's command line options, "
sewardja48a4932005-09-29 11:09:56 +00002309 "setup logging\n");
sewardj45f4e7c2005-09-27 19:20:21 +00002310 logging_to_fd = process_cmd_line_options(client_auxv, toolname);
2311
2312 //--------------------------------------------------------------
sewardj592ae092005-11-08 19:01:44 +00002313 // Zeroise the millisecond counter by doing a first read of it.
2314 // p: none
2315 //--------------------------------------------------------------
2316 (void) VG_(read_millisecond_timer)();
2317
2318 //--------------------------------------------------------------
sewardj45f4e7c2005-09-27 19:20:21 +00002319 // Print the preamble
2320 // p: tl_pre_clo_init [for 'VG_(details).name' and friends]
2321 // p: process_cmd_line_options() [for VG_(clo_verbosity), VG_(clo_xml),
2322 // VG_(clo_log_file_qualifier),
2323 // logging_to_fd]
2324 //--------------------------------------------------------------
2325 VG_(debugLog)(1, "main", "Print the preamble...\n");
2326 print_preamble(logging_to_fd, toolname);
2327 VG_(debugLog)(1, "main", "...finished the preamble\n");
2328
2329 //--------------------------------------------------------------
2330 // Init tool part 2: post_clo_init
2331 // p: setup_client_stack() [for 'VG_(client_arg[cv]']
2332 // p: setup_file_descriptors() [for 'VG_(fd_xxx_limit)']
2333 // p: print_preamble() [so any warnings printed in post_clo_init
2334 // are shown after the preamble]
2335 //--------------------------------------------------------------
2336 VG_(debugLog)(1, "main", "Initialise the tool part 2 (post_clo_init)\n");
njn51d827b2005-05-09 01:02:08 +00002337 VG_TDICT_CALL(tool_post_clo_init);
nethercotef4928da2004-06-15 10:54:40 +00002338
2339 //--------------------------------------------------------------
sewardj45f4e7c2005-09-27 19:20:21 +00002340 // Initialise translation table and translation cache
2341 // p: aspacem [??]
2342 // p: tl_pre_clo_init [for 'VG_(details).avg_translation_sizeB']
nethercote71980f02004-01-24 18:18:54 +00002343 //--------------------------------------------------------------
sewardj45f4e7c2005-09-27 19:20:21 +00002344 VG_(debugLog)(1, "main", "Initialise TT/TC\n");
2345 VG_(init_tt_tc)();
sewardjb5f6f512005-03-10 23:59:00 +00002346
sewardj45f4e7c2005-09-27 19:20:21 +00002347 //--------------------------------------------------------------
2348 // Initialise the redirect table.
2349 // p: init_tt_tc [so it can call VG_(search_transtab) safely]
2350 // p: aspacem [so can change ownership of sysinfo pages]
2351 //--------------------------------------------------------------
2352 VG_(debugLog)(1, "main", "Initialise redirects\n");
sewardj0ec07f32006-01-12 12:32:32 +00002353 VG_(redir_initialise)();
nethercote71980f02004-01-24 18:18:54 +00002354
2355 //--------------------------------------------------------------
2356 // Allow GDB attach
2357 // p: process_cmd_line_options() [for VG_(clo_wait_for_gdb)]
2358 //--------------------------------------------------------------
2359 /* Hook to delay things long enough so we can get the pid and
2360 attach GDB in another shell. */
2361 if (VG_(clo_wait_for_gdb)) {
sewardj8211a572005-06-23 21:37:47 +00002362 Long q, iters;
sewardj1fbc1a52005-04-25 02:05:54 +00002363 VG_(debugLog)(1, "main", "Wait for GDB\n");
sewardj93ab8572005-02-06 14:10:40 +00002364 VG_(printf)("pid=%d, entering delay loop\n", VG_(getpid)());
2365 /* jrs 20050206: I don't understand why this works on x86. On
2366 amd64 the obvious analogues (jump *$rip or jump *$rcx) don't
2367 work. */
2368 /* do "jump *$eip" to skip this in gdb (x86) */
2369 //VG_(do_syscall0)(__NR_pause);
sewardj8211a572005-06-23 21:37:47 +00002370
2371# if defined(VGP_x86_linux)
2372 iters = 5;
sewardj2c48c7b2005-11-29 13:05:56 +00002373# elif defined(VGP_amd64_linux) || defined(VGP_ppc64_linux)
sewardj8211a572005-06-23 21:37:47 +00002374 iters = 10;
2375# elif defined(VGP_ppc32_linux)
sewardjd714d2e2005-07-08 18:24:04 +00002376 iters = 5;
sewardj8211a572005-06-23 21:37:47 +00002377# else
2378# error "Unknown plat"
2379# endif
2380
2381 iters *= 1000*1000*1000;
2382 for (q = 0; q < iters; q++)
2383 ;
nethercote71980f02004-01-24 18:18:54 +00002384 }
2385
sewardjb5d320c2005-03-13 18:57:15 +00002386 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002387 // Search for file descriptors that are inherited from our parent
2388 // p: process_cmd_line_options [for VG_(clo_track_fds)]
2389 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002390 if (VG_(clo_track_fds)) {
2391 VG_(debugLog)(1, "main", "Init preopened fds\n");
nethercote71980f02004-01-24 18:18:54 +00002392 VG_(init_preopened_fds)();
sewardj1fbc1a52005-04-25 02:05:54 +00002393 }
nethercote71980f02004-01-24 18:18:54 +00002394
2395 //--------------------------------------------------------------
sewardj45f4e7c2005-09-27 19:20:21 +00002396 // Load debug info for the existing segments.
2397 // p: setup_code_redirect_table [so that redirs can be recorded]
2398 // p: mallocfree
2399 // p: probably: setup fds and process CLOs, so that logging works
2400 //--------------------------------------------------------------
2401 VG_(debugLog)(1, "main", "Load initial debug info\n");
2402 { Addr* seg_starts;
2403 Int n_seg_starts;
2404
2405 seg_starts = get_seg_starts( &n_seg_starts );
2406 vg_assert(seg_starts && n_seg_starts > 0);
2407
sewardjf72cced2005-11-08 00:45:47 +00002408 /* show them all to the debug info reader. allow_SkFileV has to
2409 be True here so that we read info from the valgrind executable
2410 itself. */
sewardj45f4e7c2005-09-27 19:20:21 +00002411 for (i = 0; i < n_seg_starts; i++)
sewardjf72cced2005-11-08 00:45:47 +00002412 VG_(di_notify_mmap)( seg_starts[i], True/*allow_SkFileV*/ );
sewardj45f4e7c2005-09-27 19:20:21 +00002413
2414 VG_(free)( seg_starts );
2415 }
2416
2417 //--------------------------------------------------------------
2418 // Tell aspacem of ownership change of the asm helpers, so that
2419 // m_translate allows them to be translated. However, only do this
2420 // after the initial debug info read, since making a hole in the
2421 // address range for the stage2 binary confuses the debug info reader.
2422 // p: aspacem
2423 //--------------------------------------------------------------
2424 { Bool change_ownership_v_c_OK;
sewardj1a85f4f2006-01-12 21:15:35 +00002425 Addr co_start = VG_PGROUNDDN( (Addr)&VG_(trampoline_stuff_start) );
2426 Addr co_endPlus = VG_PGROUNDUP( (Addr)&VG_(trampoline_stuff_end) );
sewardj45f4e7c2005-09-27 19:20:21 +00002427 VG_(debugLog)(1,"redir",
2428 "transfer ownership V -> C of 0x%llx .. 0x%llx\n",
2429 (ULong)co_start, (ULong)co_endPlus-1 );
2430
2431 change_ownership_v_c_OK
2432 = VG_(am_change_ownership_v_to_c)( co_start, co_endPlus - co_start );
2433 vg_assert(change_ownership_v_c_OK);
2434 }
2435
2436 //--------------------------------------------------------------
2437 // Tell the tool about the initial client memory permissions
2438 // p: aspacem
2439 // p: mallocfree
2440 // p: setup_client_stack
2441 // p: setup_client_dataseg
2442 //--------------------------------------------------------------
2443 VG_(debugLog)(1, "main", "Tell tool about initial permissions\n");
2444 { Addr* seg_starts;
2445 Int n_seg_starts;
2446 NSegment* seg;
2447
2448 seg_starts = get_seg_starts( &n_seg_starts );
2449 vg_assert(seg_starts && n_seg_starts > 0);
2450
2451 /* show interesting ones to the tool */
2452 for (i = 0; i < n_seg_starts; i++) {
2453 seg = VG_(am_find_nsegment)( seg_starts[i] );
2454 vg_assert(seg);
2455 if (seg->kind == SkFileC || seg->kind == SkAnonC) {
2456 VG_(debugLog)(2, "main",
2457 "tell tool about %010lx-%010lx %c%c%c\n",
2458 seg->start, seg->end,
2459 seg->hasR ? 'r' : '-',
2460 seg->hasW ? 'w' : '-',
2461 seg->hasX ? 'x' : '-' );
2462 VG_TRACK( new_mem_startup, seg->start, seg->end+1-seg->start,
2463 seg->hasR, seg->hasW, seg->hasX );
2464 }
2465 }
2466
2467 VG_(free)( seg_starts );
2468
2469 /* Also do the initial stack permissions. */
2470 seg = VG_(am_find_nsegment)( initial_client_SP );
2471 vg_assert(seg);
2472 vg_assert(seg->kind == SkAnonC);
2473 vg_assert(initial_client_SP >= seg->start);
2474 vg_assert(initial_client_SP <= seg->end);
2475
sewardjc6527d62006-02-13 17:54:31 +00002476 /* Stuff below the initial SP is unaddressable. Take into
2477 account any ABI-mandated space below the stack pointer that is
2478 required (VG_STACK_REDZONE_SZB). setup_client_stack() will
2479 have allocated an extra page if a red zone is required, to be on
2480 the safe side. */
sewardj6b3e0d72006-02-13 18:16:41 +00002481 vg_assert(initial_client_SP - VG_STACK_REDZONE_SZB >= seg->start);
sewardjc6527d62006-02-13 17:54:31 +00002482 VG_TRACK( die_mem_stack, seg->start, initial_client_SP
2483 - VG_STACK_REDZONE_SZB - seg->start );
sewardj45f4e7c2005-09-27 19:20:21 +00002484 VG_(debugLog)(2, "main", "mark stack inaccessible %010lx-%010lx\n",
sewardjc6527d62006-02-13 17:54:31 +00002485 seg->start, initial_client_SP-1 - VG_STACK_REDZONE_SZB);
sewardj45f4e7c2005-09-27 19:20:21 +00002486
2487 /* Also the assembly helpers. */
2488 VG_TRACK( new_mem_startup,
2489 (Addr)&VG_(trampoline_stuff_start),
sewardjc6527d62006-02-13 17:54:31 +00002490 (Addr)&VG_(trampoline_stuff_end)
2491 - (Addr)&VG_(trampoline_stuff_start),
sewardj45f4e7c2005-09-27 19:20:21 +00002492 False, /* readable? */
2493 False, /* writable? */
2494 True /* executable? */ );
2495 }
2496
2497 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002498 // Initialise the scheduler
nethercote71980f02004-01-24 18:18:54 +00002499 // p: setup_file_descriptors() [else VG_(safe_fd)() breaks]
sewardj45f4e7c2005-09-27 19:20:21 +00002500 // p: setup_client_stack
nethercote71980f02004-01-24 18:18:54 +00002501 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002502 VG_(debugLog)(1, "main", "Initialise scheduler\n");
sewardj45f4e7c2005-09-27 19:20:21 +00002503 { NSegment* seg = VG_(am_find_nsegment)( initial_client_SP );
2504 vg_assert(seg);
2505 vg_assert(seg->kind == SkAnonC);
2506 vg_assert(initial_client_SP >= seg->start);
2507 vg_assert(initial_client_SP <= seg->end);
2508 VG_(scheduler_init)( seg->end, clstack_max_size );
2509 }
nethercote71980f02004-01-24 18:18:54 +00002510
2511 //--------------------------------------------------------------
sewardjb5f6f512005-03-10 23:59:00 +00002512 // Initialise the pthread model
2513 // p: ?
sewardj2a99cf62004-11-24 10:44:19 +00002514 // load_client() [for 'client_eip']
2515 // setup_client_stack() [for 'sp_at_startup']
2516 // setup_scheduler() [for the rest of state 1 stuff]
2517 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002518 VG_(debugLog)(1, "main", "Initialise thread 1's state\n");
sewardj13247ca2005-12-30 22:52:20 +00002519 init_thread1state( initial_client_IP,
2520 initial_client_SP,
2521 initial_client_TOC,
sewardj45f4e7c2005-09-27 19:20:21 +00002522 &VG_(threads)[1].arch);
njnea4b28c2004-11-30 16:04:58 +00002523
sewardj2a99cf62004-11-24 10:44:19 +00002524 //--------------------------------------------------------------
sewardj39b88fb2005-03-12 15:16:07 +00002525 // Initialise the pthread model
2526 // p: ?
nethercote71980f02004-01-24 18:18:54 +00002527 //--------------------------------------------------------------
sewardjb5f6f512005-03-10 23:59:00 +00002528 //if (VG_(clo_model_pthreads))
2529 // VG_(pthread_init)();
nethercote71980f02004-01-24 18:18:54 +00002530
2531 //--------------------------------------------------------------
2532 // Initialise the signal handling subsystem
sewardjb5f6f512005-03-10 23:59:00 +00002533 // p: n/a
nethercote71980f02004-01-24 18:18:54 +00002534 //--------------------------------------------------------------
2535 // Nb: temporarily parks the saved blocking-mask in saved_sigmask.
sewardj1fbc1a52005-04-25 02:05:54 +00002536 VG_(debugLog)(1, "main", "Initialise signal management\n");
nethercote71980f02004-01-24 18:18:54 +00002537 VG_(sigstartup_actions)();
2538
2539 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002540 // Read suppression file
2541 // p: process_cmd_line_options() [for VG_(clo_suppressions)]
2542 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002543 if (VG_(needs).core_errors || VG_(needs).tool_errors) {
2544 VG_(debugLog)(1, "main", "Load suppressions\n");
nethercote71980f02004-01-24 18:18:54 +00002545 VG_(load_suppressions)();
sewardj1fbc1a52005-04-25 02:05:54 +00002546 }
nethercote71980f02004-01-24 18:18:54 +00002547
2548 //--------------------------------------------------------------
rjwalsh0140af52005-06-04 20:42:33 +00002549 // register client stack
2550 //--------------------------------------------------------------
njn945ed2e2005-06-24 03:28:30 +00002551 VG_(clstk_id) = VG_(register_stack)(VG_(clstk_base), VG_(clstk_end));
rjwalsh0140af52005-06-04 20:42:33 +00002552
2553 //--------------------------------------------------------------
sewardj45f4e7c2005-09-27 19:20:21 +00002554 // Show the address space state so far
2555 //--------------------------------------------------------------
2556 VG_(debugLog)(1, "main", "\n");
2557 VG_(debugLog)(1, "main", "\n");
2558 VG_(am_show_nsegments)(1,"Memory layout at client startup");
2559 VG_(debugLog)(1, "main", "\n");
2560 VG_(debugLog)(1, "main", "\n");
2561
2562 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002563 // Run!
2564 //--------------------------------------------------------------
sewardj71bc3cb2005-05-19 00:25:45 +00002565 if (VG_(clo_xml)) {
sewardj68cde6f2005-07-19 12:17:51 +00002566 HChar buf[50];
sewardj592ae092005-11-08 19:01:44 +00002567 VG_(elapsed_wallclock_time)(buf);
sewardj753673f2005-08-09 22:03:08 +00002568 VG_(message)(Vg_UserMsg, "<status>\n"
2569 " <state>RUNNING</state>\n"
2570 " <time>%t</time>\n"
2571 "</status>",
2572 buf);
sewardj71bc3cb2005-05-19 00:25:45 +00002573 VG_(message)(Vg_UserMsg, "");
2574 }
2575
sewardj1fbc1a52005-04-25 02:05:54 +00002576 VG_(debugLog)(1, "main", "Running thread 1\n");
sewardj1ae3f3a2005-09-28 10:47:38 +00002577
sewardj1d887112005-05-30 21:44:08 +00002578 /* As a result of the following call, the last thread standing
sewardj1ae3f3a2005-09-28 10:47:38 +00002579 eventually winds up running shutdown_actions_NORETURN
2580 just below. Unfortunately, simply exporting said function
2581 causes m_main to be part of a module cycle, which is pretty
2582 nonsensical. So instead of doing that, the address of said
2583 function is stored in a global variable 'owned' by m_syswrap,
2584 and it uses that function pointer to get back here when it needs
2585 to. */
2586
2587 /* Set continuation address. */
2588 VG_(address_of_m_main_shutdown_actions_NORETURN)
2589 = & shutdown_actions_NORETURN;
2590
2591 /* Run the first thread, eventually ending up at the continuation
2592 address. */
njnaf839f52005-06-23 03:27:57 +00002593 VG_(main_thread_wrapper_NORETURN)(1);
nethercote71980f02004-01-24 18:18:54 +00002594
sewardj1d887112005-05-30 21:44:08 +00002595 /*NOTREACHED*/
2596 vg_assert(0);
sewardjb5f6f512005-03-10 23:59:00 +00002597}
2598
sewardj1ae3f3a2005-09-28 10:47:38 +00002599/* Do everything which needs doing when the last thread exits. */
sewardjb5f6f512005-03-10 23:59:00 +00002600
sewardj1ae3f3a2005-09-28 10:47:38 +00002601static
2602void shutdown_actions_NORETURN( ThreadId tid,
2603 VgSchedReturnCode tids_schedretcode )
sewardjb5f6f512005-03-10 23:59:00 +00002604{
sewardj1d887112005-05-30 21:44:08 +00002605 VG_(debugLog)(1, "main", "entering VG_(shutdown_actions_NORETURN)\n");
2606
2607 vg_assert( VG_(count_living_threads)() == 1 );
sewardjb5f6f512005-03-10 23:59:00 +00002608 vg_assert(VG_(is_running_thread)(tid));
2609
2610 // Wait for all other threads to exit.
njn7b85dd52005-06-12 17:26:29 +00002611 VG_(reap_threads)(tid);
sewardjb5f6f512005-03-10 23:59:00 +00002612
2613 VG_(clo_model_pthreads) = False;
2614
2615 // Clean the client up before the final report
njn9cb54ac2005-06-12 04:19:17 +00002616 final_tidyup(tid);
sewardjb5f6f512005-03-10 23:59:00 +00002617
2618 // OK, done
2619 VG_(exit_thread)(tid);
2620
2621 /* should be no threads left */
2622 vg_assert(VG_(count_living_threads)() == 0);
2623
2624 VG_(threads)[tid].status = VgTs_Empty;
nethercote71980f02004-01-24 18:18:54 +00002625 //--------------------------------------------------------------
2626 // Finalisation: cleanup, messages, etc. Order no so important, only
2627 // affects what order the messages come.
2628 //--------------------------------------------------------------
2629 if (VG_(clo_verbosity) > 0)
2630 VG_(message)(Vg_UserMsg, "");
2631
sewardj71bc3cb2005-05-19 00:25:45 +00002632 if (VG_(clo_xml)) {
sewardj68cde6f2005-07-19 12:17:51 +00002633 HChar buf[50];
sewardj9f297ca2005-05-20 02:29:52 +00002634 if (VG_(needs).core_errors || VG_(needs).tool_errors) {
2635 VG_(show_error_counts_as_XML)();
2636 VG_(message)(Vg_UserMsg, "");
2637 }
sewardj592ae092005-11-08 19:01:44 +00002638 VG_(elapsed_wallclock_time)(buf);
sewardj753673f2005-08-09 22:03:08 +00002639 VG_(message)(Vg_UserMsg, "<status>\n"
2640 " <state>FINISHED</state>\n"
2641 " <time>%t</time>\n"
2642 "</status>",
2643 buf);
sewardj71bc3cb2005-05-19 00:25:45 +00002644 VG_(message)(Vg_UserMsg, "");
2645 }
2646
nethercote71980f02004-01-24 18:18:54 +00002647 /* Print out file descriptor summary and stats. */
2648 if (VG_(clo_track_fds))
nethercote3a42fb82004-08-03 18:08:50 +00002649 VG_(show_open_fds)();
nethercote71980f02004-01-24 18:18:54 +00002650
njn95ec8702004-11-22 16:46:13 +00002651 if (VG_(needs).core_errors || VG_(needs).tool_errors)
nethercote71980f02004-01-24 18:18:54 +00002652 VG_(show_all_errors)();
2653
njn51d827b2005-05-09 01:02:08 +00002654 VG_TDICT_CALL(tool_fini, 0/*exitcode*/);
nethercote71980f02004-01-24 18:18:54 +00002655
sewardj71bc3cb2005-05-19 00:25:45 +00002656 if (VG_(clo_xml)) {
2657 VG_(message)(Vg_UserMsg, "");
2658 VG_(message)(Vg_UserMsg, "</valgrindoutput>");
2659 VG_(message)(Vg_UserMsg, "");
2660 }
2661
nethercote885dd912004-08-03 23:14:00 +00002662 VG_(sanity_check_general)( True /*include expensive checks*/ );
nethercote71980f02004-01-24 18:18:54 +00002663
2664 if (VG_(clo_verbosity) > 1)
nethercote3a42fb82004-08-03 18:08:50 +00002665 print_all_stats();
nethercote71980f02004-01-24 18:18:54 +00002666
njn2025cf92005-06-26 20:44:48 +00002667 if (VG_(clo_profile_flags) > 0) {
2668 #define N_MAX 100
2669 BBProfEntry tops[N_MAX];
2670 ULong score_total = VG_(get_BB_profile) (tops, N_MAX);
2671 show_BB_profile(tops, N_MAX, score_total);
2672 }
sewardjfa8ec112005-01-19 11:55:34 +00002673
sewardj8b635a42004-11-22 19:01:47 +00002674 /* Print Vex storage stats */
sewardjbf426512005-01-17 18:35:30 +00002675 if (0)
2676 LibVEX_ShowAllocStats();
sewardj1d887112005-05-30 21:44:08 +00002677
njn8aa35852005-06-10 22:59:56 +00002678 /* Ok, finally exit in the os-specific way, according to the scheduler's
2679 return code. In short, if the (last) thread exited by calling
2680 sys_exit, do likewise; if the (last) thread stopped due to a fatal
2681 signal, terminate the entire system with that same fatal signal. */
2682 VG_(debugLog)(1, "core_os",
njn7b85dd52005-06-12 17:26:29 +00002683 "VG_(terminate_NORETURN)(tid=%lld)\n", (ULong)tid);
njn8aa35852005-06-10 22:59:56 +00002684
2685 vg_assert(VG_(count_living_threads)() == 0);
2686
2687 switch (tids_schedretcode) {
2688 case VgSrc_ExitSyscall: /* the normal way out */
2689 VG_(exit)( VG_(threads)[tid].os_state.exitcode );
2690 /* NOT ALIVE HERE! */
2691 VG_(core_panic)("entered the afterlife in main() -- ExitSyscall");
2692 break; /* what the hell :) */
2693
2694 case VgSrc_FatalSig:
2695 /* We were killed by a fatal signal, so replicate the effect */
2696 vg_assert(VG_(threads)[tid].os_state.fatalsig != 0);
2697 VG_(kill_self)(VG_(threads)[tid].os_state.fatalsig);
2698 VG_(core_panic)("main(): signal was supposed to be fatal");
2699 break;
2700
2701 default:
2702 VG_(core_panic)("main(): unexpected scheduler return code");
2703 }
njne96be672005-05-08 19:08:54 +00002704}
sewardj8b635a42004-11-22 19:01:47 +00002705
sewardj1ae3f3a2005-09-28 10:47:38 +00002706/* -------------------- */
2707
2708/* Final clean-up before terminating the process.
2709 Clean up the client by calling __libc_freeres() (if requested)
2710 This is Linux-specific?
2711*/
2712static void final_tidyup(ThreadId tid)
2713{
sewardjcf951812006-01-17 02:22:21 +00002714# if defined(VGP_ppc64_linux)
2715 Addr r2;
2716# endif
sewardj0ec07f32006-01-12 12:32:32 +00002717 Addr __libc_freeres_wrapper = VG_(client___libc_freeres_wrapper);
sewardj1ae3f3a2005-09-28 10:47:38 +00002718
2719 vg_assert(VG_(is_running_thread)(tid));
2720
2721 if ( !VG_(needs).libc_freeres ||
2722 !VG_(clo_run_libc_freeres) ||
sewardj0ec07f32006-01-12 12:32:32 +00002723 0 == __libc_freeres_wrapper )
sewardj1ae3f3a2005-09-28 10:47:38 +00002724 return; /* can't/won't do it */
2725
sewardjcf951812006-01-17 02:22:21 +00002726# if defined(VGP_ppc64_linux)
2727 r2 = VG_(get_tocptr)( __libc_freeres_wrapper );
2728 if (r2 == 0) {
2729 VG_(message)(Vg_UserMsg,
2730 "Caught __NR_exit, but can't run __libc_freeres()");
2731 VG_(message)(Vg_UserMsg,
2732 " since cannot establish TOC pointer for it.");
2733 return;
2734 }
2735# endif
2736
sewardj1ae3f3a2005-09-28 10:47:38 +00002737 if (VG_(clo_verbosity) > 2 ||
2738 VG_(clo_trace_syscalls) ||
2739 VG_(clo_trace_sched))
2740 VG_(message)(Vg_DebugMsg,
2741 "Caught __NR_exit; running __libc_freeres()");
2742
sewardj0ec07f32006-01-12 12:32:32 +00002743 /* set thread context to point to libc_freeres_wrapper */
sewardj1a85f4f2006-01-12 21:15:35 +00002744 /* ppc64-linux note: __libc_freeres_wrapper gives us the real
2745 function entry point, not a fn descriptor, so can use it
2746 directly. However, we need to set R2 (the toc pointer)
2747 appropriately. */
sewardj1ae3f3a2005-09-28 10:47:38 +00002748 VG_(set_IP)(tid, __libc_freeres_wrapper);
sewardjcf951812006-01-17 02:22:21 +00002749# if defined(VGP_ppc64_linux)
2750 VG_(threads)[tid].arch.vex.guest_GPR2 = r2;
2751# endif
sewardj1ae3f3a2005-09-28 10:47:38 +00002752
2753 /* Block all blockable signals by copying the real block state into
2754 the thread's block state*/
2755 VG_(sigprocmask)(VKI_SIG_BLOCK, NULL, &VG_(threads)[tid].sig_mask);
2756 VG_(threads)[tid].tmp_sig_mask = VG_(threads)[tid].sig_mask;
2757
2758 /* and restore handlers to default */
2759 VG_(set_default_handler)(VKI_SIGSEGV);
2760 VG_(set_default_handler)(VKI_SIGBUS);
2761 VG_(set_default_handler)(VKI_SIGILL);
2762 VG_(set_default_handler)(VKI_SIGFPE);
2763
2764 // We were exiting, so assert that...
2765 vg_assert(VG_(is_exiting)(tid));
2766 // ...but now we're not again
2767 VG_(threads)[tid].exitreason = VgSrc_None;
2768
2769 // run until client thread exits - ideally with LIBC_FREERES_DONE,
2770 // but exit/exitgroup/signal will do
2771 VG_(scheduler)(tid);
2772
2773 vg_assert(VG_(is_exiting)(tid));
2774}
2775
sewardj45f4e7c2005-09-27 19:20:21 +00002776
2777/*====================================================================*/
2778/*=== Getting to main() alive ===*/
2779/*====================================================================*/
2780
2781/* If linking of the final executables is done with glibc present,
2782 then Valgrind starts at main() above as usual, and all of the
2783 following code is irrelevant.
2784
2785 However, this is not the intended mode of use. The plan is to
2786 avoid linking against glibc, by giving gcc the flags
2787 -nodefaultlibs -lgcc -nostartfiles at startup.
2788
2789 From this derive two requirements:
2790
2791 1. gcc may emit calls to memcpy and memset to deal with structure
2792 assignments etc. Since we have chosen to ignore all the
2793 "normal" supporting libraries, we have to provide our own
2794 implementations of them. No problem.
2795
2796 2. We have to provide a symbol "_start", to which the kernel
2797 hands control at startup. Hence the code below.
2798*/
2799
2800/* ---------------- Requirement 1 ---------------- */
2801
2802void* memcpy(void *dest, const void *src, size_t n);
2803void* memcpy(void *dest, const void *src, size_t n) {
2804 return VG_(memcpy)(dest,src,n);
2805}
2806void* memset(void *s, int c, size_t n);
2807void* memset(void *s, int c, size_t n) {
2808 return VG_(memset)(s,c,n);
2809}
2810
2811/* ---------------- Requirement 2 ---------------- */
2812
2813/* Glibc's sysdeps/i386/elf/start.S has the following gem of a
2814 comment, which explains how the stack looks right at process start
2815 (when _start is jumped to). Hence _start passes %esp to
2816 _start_in_C, which extracts argc/argv/envp and starts up
2817 correctly. */
2818
2819/* This is the canonical entry point, usually the first thing in the text
2820 segment. The SVR4/i386 ABI (pages 3-31, 3-32) says that when the entry
2821 point runs, most registers' values are unspecified, except for:
2822
2823 %edx Contains a function pointer to be registered with `atexit'.
2824 This is how the dynamic linker arranges to have DT_FINI
2825 functions called for shared libraries that have been loaded
2826 before this code runs.
2827
2828 %esp The stack contains the arguments and environment:
2829 0(%esp) argc
2830 4(%esp) argv[0]
2831 ...
2832 (4*argc)(%esp) NULL
2833 (4*(argc+1))(%esp) envp[0]
2834 ...
2835 NULL
2836*/
2837
2838/* The kernel hands control to _start, which extracts the initial
sewardja48a4932005-09-29 11:09:56 +00002839 stack pointer and calls onwards to _start_in_C. This also switches
2840 the new stack. */
sewardj45f4e7c2005-09-27 19:20:21 +00002841#if defined(VGP_x86_linux)
2842asm("\n"
sewardjd9fc3822005-11-18 23:50:43 +00002843 ".text\n"
sewardj45f4e7c2005-09-27 19:20:21 +00002844 "\t.globl _start\n"
2845 "\t.type _start,@function\n"
2846 "_start:\n"
2847 /* set up the new stack in %eax */
sewardjfdf91b42005-09-28 00:53:09 +00002848 "\tmovl $vgPlain_interim_stack, %eax\n"
sewardj45f4e7c2005-09-27 19:20:21 +00002849 "\taddl $"VG_STRINGIFY(VG_STACK_GUARD_SZB)", %eax\n"
2850 "\taddl $"VG_STRINGIFY(VG_STACK_ACTIVE_SZB)", %eax\n"
2851 "\tsubl $16, %eax\n"
2852 "\tandl $~15, %eax\n"
2853 /* install it, and collect the original one */
2854 "\txchgl %eax, %esp\n"
2855 /* call _start_in_C, passing it the startup %esp */
2856 "\tpushl %eax\n"
2857 "\tcall _start_in_C\n"
2858 "\thlt\n"
sewardj2fedc642005-11-19 02:02:57 +00002859 ".previous\n"
sewardj45f4e7c2005-09-27 19:20:21 +00002860);
2861#elif defined(VGP_amd64_linux)
2862asm("\n"
sewardjd9fc3822005-11-18 23:50:43 +00002863 ".text\n"
sewardj45f4e7c2005-09-27 19:20:21 +00002864 "\t.globl _start\n"
2865 "\t.type _start,@function\n"
2866 "_start:\n"
2867 /* set up the new stack in %rdi */
sewardjfdf91b42005-09-28 00:53:09 +00002868 "\tmovq $vgPlain_interim_stack, %rdi\n"
sewardj45f4e7c2005-09-27 19:20:21 +00002869 "\taddq $"VG_STRINGIFY(VG_STACK_GUARD_SZB)", %rdi\n"
2870 "\taddq $"VG_STRINGIFY(VG_STACK_ACTIVE_SZB)", %rdi\n"
2871 "\tandq $~15, %rdi\n"
2872 /* install it, and collect the original one */
2873 "\txchgq %rdi, %rsp\n"
2874 /* call _start_in_C, passing it the startup %rsp */
2875 "\tcall _start_in_C\n"
2876 "\thlt\n"
sewardj2fedc642005-11-19 02:02:57 +00002877 ".previous\n"
sewardj45f4e7c2005-09-27 19:20:21 +00002878);
sewardja48a4932005-09-29 11:09:56 +00002879#elif defined(VGP_ppc32_linux)
2880asm("\n"
sewardjd9fc3822005-11-18 23:50:43 +00002881 ".text\n"
sewardja48a4932005-09-29 11:09:56 +00002882 "\t.globl _start\n"
2883 "\t.type _start,@function\n"
2884 "_start:\n"
2885 /* set up the new stack in r16 */
2886 "\tlis 16,vgPlain_interim_stack@ha\n"
2887 "\tla 16,vgPlain_interim_stack@l(16)\n"
2888 "\tlis 17,("VG_STRINGIFY(VG_STACK_GUARD_SZB)" >> 16)\n"
2889 "\tori 17,17,("VG_STRINGIFY(VG_STACK_GUARD_SZB)" & 0xFFFF)\n"
2890 "\tlis 18,("VG_STRINGIFY(VG_STACK_ACTIVE_SZB)" >> 16)\n"
2891 "\tori 18,18,("VG_STRINGIFY(VG_STACK_ACTIVE_SZB)" & 0xFFFF)\n"
2892 "\tadd 16,17,16\n"
2893 "\tadd 16,18,16\n"
2894 "\trlwinm 16,16,0,0,27\n"
2895 /* now r16 = &vgPlain_interim_stack + VG_STACK_GUARD_SZB +
2896 VG_STACK_ACTIVE_SZB rounded down to the nearest 16-byte
2897 boundary. And r1 is the original SP. Set the SP to r16 and
2898 call _start_in_C, passing it the initial SP. */
2899 "\tmr 3,1\n"
2900 "\tmr 1,16\n"
2901 "\tbl _start_in_C\n"
2902 "\ttrap\n"
sewardj2fedc642005-11-19 02:02:57 +00002903 ".previous\n"
sewardja48a4932005-09-29 11:09:56 +00002904);
sewardj2c48c7b2005-11-29 13:05:56 +00002905#elif defined(VGP_ppc64_linux)
2906asm("\n"
cerion21082042005-12-06 19:07:08 +00002907 /* PPC64 ELF ABI says '_start' points to a function descriptor.
2908 So we must have one, and that is what goes into the .opd section. */
cerion297c88f2005-12-22 15:53:12 +00002909 "\t.align 2\n"
cerion21082042005-12-06 19:07:08 +00002910 "\t.global _start\n"
2911 "\t.section \".opd\",\"aw\"\n"
2912 "\t.align 3\n"
sewardj2c48c7b2005-11-29 13:05:56 +00002913 "_start:\n"
cerion21082042005-12-06 19:07:08 +00002914 "\t.quad ._start,.TOC.@tocbase,0\n"
2915 "\t.previous\n"
2916 "\t.type ._start,@function\n"
2917 "\t.global ._start\n"
2918 "._start:\n"
sewardj2c48c7b2005-11-29 13:05:56 +00002919 /* set up the new stack in r16 */
2920 "\tlis 16, vgPlain_interim_stack@highest\n"
2921 "\tori 16,16,vgPlain_interim_stack@higher\n"
2922 "\tsldi 16,16,32\n"
2923 "\toris 16,16,vgPlain_interim_stack@h\n"
2924 "\tori 16,16,vgPlain_interim_stack@l\n"
2925 "\txor 17,17,17\n"
2926 "\tlis 17,("VG_STRINGIFY(VG_STACK_GUARD_SZB)" >> 16)\n"
2927 "\tori 17,17,("VG_STRINGIFY(VG_STACK_GUARD_SZB)" & 0xFFFF)\n"
2928 "\txor 18,18,18\n"
2929 "\tlis 18,("VG_STRINGIFY(VG_STACK_ACTIVE_SZB)" >> 16)\n"
2930 "\tori 18,18,("VG_STRINGIFY(VG_STACK_ACTIVE_SZB)" & 0xFFFF)\n"
2931 "\tadd 16,17,16\n"
2932 "\tadd 16,18,16\n"
2933 "\trldicr 16,16,0,59\n"
2934 /* now r16 = &vgPlain_interim_stack + VG_STACK_GUARD_SZB +
2935 VG_STACK_ACTIVE_SZB rounded down to the nearest 16-byte
2936 boundary. And r1 is the original SP. Set the SP to r16 and
2937 call _start_in_C, passing it the initial SP. */
2938 "\tmr 3,1\n"
2939 "\tmr 1,16\n"
cerion21082042005-12-06 19:07:08 +00002940 "\tbl ._start_in_C\n"
2941 "\tnop\n"
sewardj2c48c7b2005-11-29 13:05:56 +00002942 "\ttrap\n"
sewardj2c48c7b2005-11-29 13:05:56 +00002943);
sewardj45f4e7c2005-09-27 19:20:21 +00002944#else
2945#error "_start: needs implementation on this platform"
2946#endif
2947
2948/* Avoid compiler warnings: this fn _is_ used, but labelling it
2949 'static' causes gcc to complain it isn't. */
2950void _start_in_C ( UWord* pArgc );
2951void _start_in_C ( UWord* pArgc )
2952{
2953 Int r;
2954 Word argc = pArgc[0];
2955 HChar** argv = (HChar**)&pArgc[1];
2956 HChar** envp = (HChar**)&pArgc[1+argc+1];
sewardjfdf91b42005-09-28 00:53:09 +00002957 sp_at_startup = (Addr)pArgc;
sewardj45f4e7c2005-09-27 19:20:21 +00002958 r = main( (Int)argc, argv, envp );
2959 VG_(exit)(r);
2960}
2961
sewardjde4a1d02002-03-22 01:27:54 +00002962/*--------------------------------------------------------------------*/
njn04e16982005-05-31 00:23:43 +00002963/*--- end ---*/
sewardjde4a1d02002-03-22 01:27:54 +00002964/*--------------------------------------------------------------------*/