blob: a2f5795745d516be87d04b2cf679e91d7a9a7a0b [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"
njnca54af32006-04-16 10:25:43 +0000915" --xml=yes all output is in XML (some tools 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"
sewardjb9779082006-05-12 23:50:15 +0000920" --error-exitcode=<number> exit code to return if errors found [0=disable]\n"
nethercote2b0793f2003-12-02 10:41:18 +0000921" --show-below-main=no|yes continue stack traces below main() [no]\n"
922" --suppressions=<filename> suppress errors described in <filename>\n"
sewardjd153fae2005-01-10 17:24:47 +0000923" --gen-suppressions=no|yes|all print suppressions for errors? [no]\n"
nethercote04d0fbc2004-01-26 16:48:06 +0000924" --db-attach=no|yes start debugger when errors detected? [no]\n"
925" --db-command=<command> command to start debugger [gdb -nw %%f %%p]\n"
926" --input-fd=<number> file descriptor for input [0=stdin]\n"
sewardj97724e52005-04-02 23:40:59 +0000927" --max-stackframe=<number> assume stack switch for SP changes larger\n"
928" than <number> bytes [2000000]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +0000929"\n";
njn7cf0bd32002-06-08 13:36:03 +0000930
njn25e49d8e72002-09-23 09:36:25 +0000931 Char* usage2 =
932"\n"
nethercote2b0793f2003-12-02 10:41:18 +0000933" debugging options for all Valgrind tools:\n"
njn25e49d8e72002-09-23 09:36:25 +0000934" --sanity-level=<number> level of sanity checking to do [1]\n"
sewardjfa8ec112005-01-19 11:55:34 +0000935" --trace-flags=<XXXXXXXX> show generated code? (X = 0|1) [00000000]\n"
936" --profile-flags=<XXXXXXXX> ditto, but for profiling (X = 0|1) [00000000]\n"
sewardj33afdb52006-01-17 02:36:40 +0000937" --trace-notbelow=<number> only show BBs above <number> [999999999]\n"
njn25e49d8e72002-09-23 09:36:25 +0000938" --trace-syscalls=no|yes show all system calls? [no]\n"
939" --trace-signals=no|yes show signal handling details? [no]\n"
940" --trace-symtab=no|yes show symbol table details? [no]\n"
sewardjce058b02005-05-01 08:55:38 +0000941" --trace-cfi=no|yes show call-frame-info details? [no]\n"
sewardj0ec07f32006-01-12 12:32:32 +0000942" --trace-redir=no|yes show redirection details? [no]\n"
njn25e49d8e72002-09-23 09:36:25 +0000943" --trace-sched=no|yes show thread scheduler details? [no]\n"
jsgf855d93d2003-10-13 22:26:55 +0000944" --wait-for-gdb=yes|no pause on startup to wait for gdb attach\n"
sewardjb5f6f512005-03-10 23:59:00 +0000945#if 0
946" --model-pthreads=yes|no model the pthreads library [no]\n"
947#endif
948" --command-line-only=no|yes only use command line options [no]\n"
njn613812e2005-03-11 04:57:30 +0000949"\n"
950" --vex-iropt-verbosity 0 .. 9 [0]\n"
951" --vex-iropt-level 0 .. 2 [2]\n"
952" --vex-iropt-precise-memory-exns [no]\n"
sewardj8b635a42004-11-22 19:01:47 +0000953" --vex-iropt-unroll-thresh 0 .. 400 [120]\n"
954" --vex-guest-max-insns 1 .. 100 [50]\n"
955" --vex-guest-chase-thresh 0 .. 99 [10]\n"
956"\n"
sewardjfa8ec112005-01-19 11:55:34 +0000957" --trace-flags and --profile-flags values (omit the middle space):\n"
sewardj2a99cf62004-11-24 10:44:19 +0000958" 1000 0000 show conversion into IR\n"
959" 0100 0000 show after initial opt\n"
960" 0010 0000 show after instrumentation\n"
961" 0001 0000 show after second opt\n"
962" 0000 1000 show after tree building\n"
963" 0000 0100 show selecting insns\n"
964" 0000 0010 show after reg-alloc\n"
965" 0000 0001 show final assembly\n"
966"\n"
nethercote2b0793f2003-12-02 10:41:18 +0000967" debugging options for Valgrind tools that report errors\n"
968" --dump-error=<number> show translation for basic block associated\n"
969" with <number>'th error context [0=show none]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +0000970"\n";
njn3e884182003-04-15 13:03:23 +0000971
972 Char* usage3 =
973"\n"
nethercote71980f02004-01-24 18:18:54 +0000974" Extra options read from ~/.valgrindrc, $VALGRIND_OPTS, ./.valgrindrc\n"
njn25e49d8e72002-09-23 09:36:25 +0000975"\n"
sewardja2cd32d2006-05-27 03:22:47 +0000976" Valgrind is Copyright (C) 2000-2006 Julian Seward et al.\n"
njn25e49d8e72002-09-23 09:36:25 +0000977" and licensed under the GNU General Public License, version 2.\n"
978" Bug reports, feedback, admiration, abuse, etc, to: %s.\n"
njnd04b7c62002-10-03 14:05:52 +0000979"\n"
nethercote137bc552003-11-14 17:47:54 +0000980" Tools are copyright and licensed by their authors. See each\n"
981" tool's start-up message for more information.\n"
njn25e49d8e72002-09-23 09:36:25 +0000982"\n";
njn7cf0bd32002-06-08 13:36:03 +0000983
njnbe9b47b2005-05-15 16:22:58 +0000984 // Ensure the message goes to stdout
985 VG_(clo_log_fd) = 1;
986 vg_assert( !VG_(logging_to_socket) );
987
fitzhardinge98abfc72003-12-16 02:05:15 +0000988 VG_(printf)(usage1);
989 if (VG_(details).name) {
990 VG_(printf)(" user options for %s:\n", VG_(details).name);
fitzhardinge98abfc72003-12-16 02:05:15 +0000991 if (VG_(needs).command_line_options)
njn51d827b2005-05-09 01:02:08 +0000992 VG_TDICT_CALL(tool_print_usage);
fitzhardinge98abfc72003-12-16 02:05:15 +0000993 else
994 VG_(printf)(" (none)\n");
995 }
nethercote6c999f22004-01-31 22:55:15 +0000996 if (debug_help) {
997 VG_(printf)(usage2);
fitzhardinge98abfc72003-12-16 02:05:15 +0000998
nethercote6c999f22004-01-31 22:55:15 +0000999 if (VG_(details).name) {
1000 VG_(printf)(" debugging options for %s:\n", VG_(details).name);
1001
1002 if (VG_(needs).command_line_options)
njn51d827b2005-05-09 01:02:08 +00001003 VG_TDICT_CALL(tool_print_debug_usage);
nethercote6c999f22004-01-31 22:55:15 +00001004 else
1005 VG_(printf)(" (none)\n");
1006 }
fitzhardinge98abfc72003-12-16 02:05:15 +00001007 }
nethercote421281e2003-11-20 16:20:55 +00001008 VG_(printf)(usage3, VG_BUGS_TO);
nethercotef4928da2004-06-15 10:54:40 +00001009 VG_(exit)(0);
njn7cf0bd32002-06-08 13:36:03 +00001010}
sewardjde4a1d02002-03-22 01:27:54 +00001011
sewardjde4a1d02002-03-22 01:27:54 +00001012
sewardj45f4e7c2005-09-27 19:20:21 +00001013/* Peer at previously set up VG_(args_for_valgrind) and extract any
1014 request for help and also the tool name. */
1015
1016static void get_helprequest_and_toolname ( Int* need_help, HChar** tool )
1017{
1018 UInt i;
1019 HChar* str;
sewardj8b635a42004-11-22 19:01:47 +00001020
nethercote71980f02004-01-24 18:18:54 +00001021 /* parse the options we have (only the options we care about now) */
sewardj45f4e7c2005-09-27 19:20:21 +00001022 for (i = 0; i < VG_(args_for_valgrind).used; i++) {
nethercote71980f02004-01-24 18:18:54 +00001023
sewardj45f4e7c2005-09-27 19:20:21 +00001024 str = VG_(args_for_valgrind).strs[i];
1025 vg_assert(str);
nethercote71980f02004-01-24 18:18:54 +00001026
sewardj45f4e7c2005-09-27 19:20:21 +00001027 if (VG_STREQ(str, "--version")) {
njn2e9f3f32005-10-26 16:17:46 +00001028 // Ensure the version string goes to stdout
1029 VG_(clo_log_fd) = 1;
sewardj45f4e7c2005-09-27 19:20:21 +00001030 VG_(printf)("valgrind-" VERSION "\n");
1031 VG_(exit)(0);
1032
1033 } else if (VG_CLO_STREQ(str, "--help") ||
1034 VG_CLO_STREQ(str, "-h")) {
nethercote6c999f22004-01-31 22:55:15 +00001035 *need_help = 1;
1036
sewardj45f4e7c2005-09-27 19:20:21 +00001037 } else if (VG_CLO_STREQ(str, "--help-debug")) {
nethercote6c999f22004-01-31 22:55:15 +00001038 *need_help = 2;
nethercote71980f02004-01-24 18:18:54 +00001039
sewardj45f4e7c2005-09-27 19:20:21 +00001040 // The tool has already been determined, but we need to know the name
1041 // here.
1042 } else if (VG_CLO_STREQN(7, str, "--tool=")) {
1043 *tool = &str[7];
nethercote71980f02004-01-24 18:18:54 +00001044 }
1045 }
nethercote71980f02004-01-24 18:18:54 +00001046}
1047
sewardj45f4e7c2005-09-27 19:20:21 +00001048static Bool process_cmd_line_options( UInt* client_auxv, const char* toolname )
nethercote71980f02004-01-24 18:18:54 +00001049{
njnda033f52005-12-19 21:27:58 +00001050 // VG_(clo_log_fd) is used by all the messaging. It starts as 2 (stderr)
1051 // and we cannot change it until we know what we are changing it to is
1052 // ok. So we have tmp_log_fd to hold the tmp fd prior to that point.
sewardj92645592005-07-23 09:18:34 +00001053 SysRes sres;
njnda033f52005-12-19 21:27:58 +00001054 Int i, tmp_log_fd;
sewardj92645592005-07-23 09:18:34 +00001055 Int toolname_len = VG_(strlen)(toolname);
njnbe9b47b2005-05-15 16:22:58 +00001056 enum {
1057 VgLogTo_Fd,
1058 VgLogTo_File,
1059 VgLogTo_FileExactly,
1060 VgLogTo_Socket
1061 } log_to = VgLogTo_Fd; // Where is logging output to be sent?
sewardjde4a1d02002-03-22 01:27:54 +00001062
nethercotee1730692003-11-20 10:38:07 +00001063 /* log to stderr by default, but usage message goes to stdout */
njnda033f52005-12-19 21:27:58 +00001064 tmp_log_fd = 2;
sewardjde4a1d02002-03-22 01:27:54 +00001065
sewardj19d81412002-06-03 01:10:40 +00001066 /* Check for sane path in ./configure --prefix=... */
fitzhardinge98abfc72003-12-16 02:05:15 +00001067 if (VG_LIBDIR[0] != '/')
sewardj19d81412002-06-03 01:10:40 +00001068 config_error("Please use absolute paths in "
1069 "./configure --prefix=... or --libdir=...");
sewardj38170912002-05-10 21:07:22 +00001070
sewardj45f4e7c2005-09-27 19:20:21 +00001071 for (i = 0; i < VG_(args_for_valgrind).used; i++) {
nethercote71980f02004-01-24 18:18:54 +00001072
sewardj45f4e7c2005-09-27 19:20:21 +00001073 HChar* arg = VG_(args_for_valgrind).strs[i];
1074 HChar* colon = arg;
nethercote71980f02004-01-24 18:18:54 +00001075
thughes3bfd5a02004-07-18 08:05:44 +00001076 /* Look for a colon in the switch name */
1077 while (*colon && *colon != ':' && *colon != '=')
1078 colon++;
nethercote71980f02004-01-24 18:18:54 +00001079
1080 /* Look for matching "--toolname:foo" */
thughes3bfd5a02004-07-18 08:05:44 +00001081 if (*colon == ':') {
nethercote71980f02004-01-24 18:18:54 +00001082 if (VG_CLO_STREQN(2, arg, "--") &&
1083 VG_CLO_STREQN(toolname_len, arg+2, toolname) &&
1084 VG_CLO_STREQN(1, arg+2+toolname_len, ":"))
1085 {
1086 // prefix matches, convert "--toolname:foo" to "--foo"
1087 if (0)
1088 VG_(printf)("tool-specific arg: %s\n", arg);
sewardj45f4e7c2005-09-27 19:20:21 +00001089 arg = VG_(strdup)(arg + toolname_len + 1);
nethercote71980f02004-01-24 18:18:54 +00001090 arg[0] = '-';
1091 arg[1] = '-';
1092
1093 } else {
1094 // prefix doesn't match, skip to next arg
1095 continue;
1096 }
1097 }
1098
fitzhardinge98abfc72003-12-16 02:05:15 +00001099 /* Ignore these options - they've already been handled */
njn45270a22005-03-27 01:00:11 +00001100 if (VG_CLO_STREQN( 7, arg, "--tool=")) goto skip_arg;
njn45270a22005-03-27 01:00:11 +00001101 if (VG_CLO_STREQN(20, arg, "--command-line-only=")) goto skip_arg;
fitzhardinge98abfc72003-12-16 02:05:15 +00001102
njn45270a22005-03-27 01:00:11 +00001103 if ( VG_CLO_STREQ(arg, "--")) goto skip_arg;
nethercote27fec902004-06-16 21:26:32 +00001104
nethercote71980f02004-01-24 18:18:54 +00001105 else if (VG_CLO_STREQ(arg, "-v") ||
1106 VG_CLO_STREQ(arg, "--verbose"))
sewardjde4a1d02002-03-22 01:27:54 +00001107 VG_(clo_verbosity)++;
nethercote27fec902004-06-16 21:26:32 +00001108
nethercote71980f02004-01-24 18:18:54 +00001109 else if (VG_CLO_STREQ(arg, "-q") ||
1110 VG_CLO_STREQ(arg, "--quiet"))
sewardjde4a1d02002-03-22 01:27:54 +00001111 VG_(clo_verbosity)--;
1112
sewardj1cf558c2005-04-25 01:36:56 +00001113 else if (VG_CLO_STREQ(arg, "-d")) {
1114 /* do nothing */
1115 }
1116
sewardj71bc3cb2005-05-19 00:25:45 +00001117 else VG_BOOL_CLO(arg, "--xml", VG_(clo_xml))
njn45270a22005-03-27 01:00:11 +00001118 else VG_BOOL_CLO(arg, "--db-attach", VG_(clo_db_attach))
1119 else VG_BOOL_CLO(arg, "--demangle", VG_(clo_demangle))
1120 else VG_BOOL_CLO(arg, "--error-limit", VG_(clo_error_limit))
sewardjb9779082006-05-12 23:50:15 +00001121 else VG_NUM_CLO (arg, "--error-exitcode", VG_(clo_error_exitcode))
njn45270a22005-03-27 01:00:11 +00001122 else VG_BOOL_CLO(arg, "--show-emwarns", VG_(clo_show_emwarns))
sewardj97724e52005-04-02 23:40:59 +00001123 else VG_NUM_CLO (arg, "--max-stackframe", VG_(clo_max_stackframe))
njn45270a22005-03-27 01:00:11 +00001124 else VG_BOOL_CLO(arg, "--run-libc-freeres", VG_(clo_run_libc_freeres))
1125 else VG_BOOL_CLO(arg, "--show-below-main", VG_(clo_show_below_main))
1126 else VG_BOOL_CLO(arg, "--time-stamp", VG_(clo_time_stamp))
1127 else VG_BOOL_CLO(arg, "--track-fds", VG_(clo_track_fds))
1128 else VG_BOOL_CLO(arg, "--trace-children", VG_(clo_trace_children))
1129 else VG_BOOL_CLO(arg, "--trace-sched", VG_(clo_trace_sched))
1130 else VG_BOOL_CLO(arg, "--trace-signals", VG_(clo_trace_signals))
1131 else VG_BOOL_CLO(arg, "--trace-symtab", VG_(clo_trace_symtab))
sewardjce058b02005-05-01 08:55:38 +00001132 else VG_BOOL_CLO(arg, "--trace-cfi", VG_(clo_trace_cfi))
njn45270a22005-03-27 01:00:11 +00001133 else VG_BOOL_CLO(arg, "--trace-redir", VG_(clo_trace_redir))
1134 else VG_BOOL_CLO(arg, "--trace-syscalls", VG_(clo_trace_syscalls))
1135 else VG_BOOL_CLO(arg, "--trace-pthreads", VG_(clo_trace_pthreads))
1136 else VG_BOOL_CLO(arg, "--wait-for-gdb", VG_(clo_wait_for_gdb))
1137 else VG_BOOL_CLO(arg, "--model-pthreads", VG_(clo_model_pthreads))
sewardj72f98ff2002-06-13 17:23:38 +00001138
njn45270a22005-03-27 01:00:11 +00001139 else VG_STR_CLO (arg, "--db-command", VG_(clo_db_command))
njn628add62005-11-12 18:21:40 +00001140 else VG_STR_CLO (arg, "--sim-hints", VG_(clo_sim_hints))
sewardjde4a1d02002-03-22 01:27:54 +00001141
njn45270a22005-03-27 01:00:11 +00001142 else VG_NUM_CLO (arg, "--dump-error", VG_(clo_dump_error))
1143 else VG_NUM_CLO (arg, "--input-fd", VG_(clo_input_fd))
1144 else VG_NUM_CLO (arg, "--sanity-level", VG_(clo_sanity_level))
1145 else VG_BNUM_CLO(arg, "--num-callers", VG_(clo_backtrace_size), 1,
1146 VG_DEEPEST_BACKTRACE)
sewardjde4a1d02002-03-22 01:27:54 +00001147
sewardj6c3a2192005-07-24 07:00:45 +00001148 else if (VG_CLO_STREQ(arg, "--smc-check=none"))
1149 VG_(clo_smc_check) = Vg_SmcNone;
1150 else if (VG_CLO_STREQ(arg, "--smc-check=stack"))
1151 VG_(clo_smc_check) = Vg_SmcStack;
1152 else if (VG_CLO_STREQ(arg, "--smc-check=all"))
1153 VG_(clo_smc_check) = Vg_SmcAll;
sewardj26412bd2005-07-07 10:05:05 +00001154
sewardjce5a5662005-10-06 03:19:49 +00001155 else VG_STR_CLO (arg, "--kernel-variant", VG_(clo_kernel_variant))
1156
njn45270a22005-03-27 01:00:11 +00001157 else VG_BNUM_CLO(arg, "--vex-iropt-verbosity",
sewardj8b635a42004-11-22 19:01:47 +00001158 VG_(clo_vex_control).iropt_verbosity, 0, 10)
njn45270a22005-03-27 01:00:11 +00001159 else VG_BNUM_CLO(arg, "--vex-iropt-level",
sewardj8b635a42004-11-22 19:01:47 +00001160 VG_(clo_vex_control).iropt_level, 0, 2)
njn45270a22005-03-27 01:00:11 +00001161 else VG_BOOL_CLO(arg, "--vex-iropt-precise-memory-exns",
sewardj8b635a42004-11-22 19:01:47 +00001162 VG_(clo_vex_control).iropt_precise_memory_exns)
njn45270a22005-03-27 01:00:11 +00001163 else VG_BNUM_CLO(arg, "--vex-iropt-unroll-thresh",
sewardj8b635a42004-11-22 19:01:47 +00001164 VG_(clo_vex_control).iropt_unroll_thresh, 0, 400)
njn45270a22005-03-27 01:00:11 +00001165 else VG_BNUM_CLO(arg, "--vex-guest-max-insns",
sewardj8b635a42004-11-22 19:01:47 +00001166 VG_(clo_vex_control).guest_max_insns, 1, 100)
njn45270a22005-03-27 01:00:11 +00001167 else VG_BNUM_CLO(arg, "--vex-guest-chase-thresh",
sewardj8b635a42004-11-22 19:01:47 +00001168 VG_(clo_vex_control).guest_chase_thresh, 0, 99)
1169
nethercotef8548672004-06-21 12:42:35 +00001170 else if (VG_CLO_STREQN(9, arg, "--log-fd=")) {
njnbe9b47b2005-05-15 16:22:58 +00001171 log_to = VgLogTo_Fd;
nethercotef8548672004-06-21 12:42:35 +00001172 VG_(clo_log_name) = NULL;
njnda033f52005-12-19 21:27:58 +00001173 tmp_log_fd = (Int)VG_(atoll)(&arg[9]);
sewardj4cf05692002-10-27 20:28:29 +00001174 }
1175
nethercotef8548672004-06-21 12:42:35 +00001176 else if (VG_CLO_STREQN(11, arg, "--log-file=")) {
njnbe9b47b2005-05-15 16:22:58 +00001177 log_to = VgLogTo_File;
nethercotef8548672004-06-21 12:42:35 +00001178 VG_(clo_log_name) = &arg[11];
sewardj4cf05692002-10-27 20:28:29 +00001179 }
njnd6bc3c32005-03-27 00:44:31 +00001180
sewardjad311162005-07-19 11:25:02 +00001181 else if (VG_CLO_STREQN(21, arg, "--log-file-qualifier=")) {
1182 VG_(clo_log_file_qualifier) = &arg[21];
1183 }
1184
sewardj603d4102005-01-11 14:01:02 +00001185 else if (VG_CLO_STREQN(19, arg, "--log-file-exactly=")) {
njnbe9b47b2005-05-15 16:22:58 +00001186 log_to = VgLogTo_FileExactly;
sewardj603d4102005-01-11 14:01:02 +00001187 VG_(clo_log_name) = &arg[19];
1188 }
sewardjde4a1d02002-03-22 01:27:54 +00001189
nethercotef8548672004-06-21 12:42:35 +00001190 else if (VG_CLO_STREQN(13, arg, "--log-socket=")) {
njnbe9b47b2005-05-15 16:22:58 +00001191 log_to = VgLogTo_Socket;
nethercotef8548672004-06-21 12:42:35 +00001192 VG_(clo_log_name) = &arg[13];
sewardj73cf3bc2002-11-03 03:20:15 +00001193 }
1194
sewardj768db0e2005-07-19 14:18:56 +00001195 else if (VG_CLO_STREQN(19, arg, "--xml-user-comment=")) {
1196 VG_(clo_xml_user_comment) = &arg[19];
1197 }
1198
nethercote71980f02004-01-24 18:18:54 +00001199 else if (VG_CLO_STREQN(15, arg, "--suppressions=")) {
sewardjde4a1d02002-03-22 01:27:54 +00001200 if (VG_(clo_n_suppressions) >= VG_CLO_MAX_SFILES) {
njn25e49d8e72002-09-23 09:36:25 +00001201 VG_(message)(Vg_UserMsg, "Too many suppression files specified.");
sewardjde4a1d02002-03-22 01:27:54 +00001202 VG_(message)(Vg_UserMsg,
1203 "Increase VG_CLO_MAX_SFILES and recompile.");
nethercote71980f02004-01-24 18:18:54 +00001204 VG_(bad_option)(arg);
sewardjde4a1d02002-03-22 01:27:54 +00001205 }
nethercote71980f02004-01-24 18:18:54 +00001206 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = &arg[15];
sewardjde4a1d02002-03-22 01:27:54 +00001207 VG_(clo_n_suppressions)++;
1208 }
sewardjde4a1d02002-03-22 01:27:54 +00001209
sewardjfa8ec112005-01-19 11:55:34 +00001210 /* "stuvwxyz" --> stuvwxyz (binary) */
1211 else if (VG_CLO_STREQN(14, arg, "--trace-flags=")) {
1212 Int j;
1213 char* opt = & arg[14];
1214
1215 if (8 != VG_(strlen)(opt)) {
1216 VG_(message)(Vg_UserMsg,
1217 "--trace-flags argument must have 8 digits");
1218 VG_(bad_option)(arg);
1219 }
1220 for (j = 0; j < 8; j++) {
1221 if ('0' == opt[j]) { /* do nothing */ }
1222 else if ('1' == opt[j]) VG_(clo_trace_flags) |= (1 << (7-j));
1223 else {
1224 VG_(message)(Vg_UserMsg, "--trace-flags argument can only "
1225 "contain 0s and 1s");
1226 VG_(bad_option)(arg);
1227 }
1228 }
1229 }
1230
1231 /* "stuvwxyz" --> stuvwxyz (binary) */
1232 else if (VG_CLO_STREQN(16, arg, "--profile-flags=")) {
njn25e49d8e72002-09-23 09:36:25 +00001233 Int j;
nethercote71980f02004-01-24 18:18:54 +00001234 char* opt = & arg[16];
njn25e49d8e72002-09-23 09:36:25 +00001235
sewardj2a99cf62004-11-24 10:44:19 +00001236 if (8 != VG_(strlen)(opt)) {
njn25e49d8e72002-09-23 09:36:25 +00001237 VG_(message)(Vg_UserMsg,
sewardjfa8ec112005-01-19 11:55:34 +00001238 "--profile-flags argument must have 8 digits");
nethercote71980f02004-01-24 18:18:54 +00001239 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001240 }
sewardj8b635a42004-11-22 19:01:47 +00001241 for (j = 0; j < 8; j++) {
njn25e49d8e72002-09-23 09:36:25 +00001242 if ('0' == opt[j]) { /* do nothing */ }
sewardjfa8ec112005-01-19 11:55:34 +00001243 else if ('1' == opt[j]) VG_(clo_profile_flags) |= (1 << (7-j));
njn25e49d8e72002-09-23 09:36:25 +00001244 else {
sewardjfa8ec112005-01-19 11:55:34 +00001245 VG_(message)(Vg_UserMsg, "--profile-flags argument can only "
njn25e49d8e72002-09-23 09:36:25 +00001246 "contain 0s and 1s");
nethercote71980f02004-01-24 18:18:54 +00001247 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001248 }
1249 }
1250 }
sewardjde4a1d02002-03-22 01:27:54 +00001251
njn45270a22005-03-27 01:00:11 +00001252 else VG_NUM_CLO (arg, "--trace-notbelow", VG_(clo_trace_notbelow))
sewardjc771b292004-11-30 18:55:21 +00001253
sewardjd153fae2005-01-10 17:24:47 +00001254 else if (VG_CLO_STREQ(arg, "--gen-suppressions=no"))
1255 VG_(clo_gen_suppressions) = 0;
1256 else if (VG_CLO_STREQ(arg, "--gen-suppressions=yes"))
1257 VG_(clo_gen_suppressions) = 1;
1258 else if (VG_CLO_STREQ(arg, "--gen-suppressions=all"))
1259 VG_(clo_gen_suppressions) = 2;
1260
nethercote71980f02004-01-24 18:18:54 +00001261 else if ( ! VG_(needs).command_line_options
njn51d827b2005-05-09 01:02:08 +00001262 || ! VG_TDICT_CALL(tool_process_cmd_line_option, arg) ) {
nethercotef4928da2004-06-15 10:54:40 +00001263 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001264 }
njn8c0b3bb2005-03-12 21:20:39 +00001265 skip_arg:
sewardj45f4e7c2005-09-27 19:20:21 +00001266 if (arg != VG_(args_for_valgrind).strs[i]) {
1267 VG_(free)(arg);
1268 }
sewardjde4a1d02002-03-22 01:27:54 +00001269 }
1270
sewardj998d40d2004-12-06 14:24:52 +00001271 /* Make VEX control parameters sane */
1272
1273 if (VG_(clo_vex_control).guest_chase_thresh
1274 >= VG_(clo_vex_control).guest_max_insns)
1275 VG_(clo_vex_control).guest_chase_thresh
1276 = VG_(clo_vex_control).guest_max_insns - 1;
1277
1278 if (VG_(clo_vex_control).guest_chase_thresh < 0)
1279 VG_(clo_vex_control).guest_chase_thresh = 0;
1280
1281 /* Check various option values */
nethercote27fec902004-06-16 21:26:32 +00001282
njnf9ebf672003-05-12 21:41:30 +00001283 if (VG_(clo_verbosity) < 0)
sewardjde4a1d02002-03-22 01:27:54 +00001284 VG_(clo_verbosity) = 0;
1285
nethercote04d0fbc2004-01-26 16:48:06 +00001286 if (VG_(clo_db_attach) && VG_(clo_trace_children)) {
sewardjde4a1d02002-03-22 01:27:54 +00001287 VG_(message)(Vg_UserMsg, "");
1288 VG_(message)(Vg_UserMsg,
nethercote04d0fbc2004-01-26 16:48:06 +00001289 "--db-attach=yes conflicts with --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001290 VG_(message)(Vg_UserMsg,
1291 "Please choose one or the other, but not both.");
nethercote04d0fbc2004-01-26 16:48:06 +00001292 VG_(bad_option)("--db-attach=yes and --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001293 }
1294
njnbe9b47b2005-05-15 16:22:58 +00001295 if (VG_(clo_gen_suppressions) > 0 &&
1296 !VG_(needs).core_errors && !VG_(needs).tool_errors) {
1297 VG_(message)(Vg_UserMsg,
1298 "Can't use --gen-suppressions= with this tool,");
1299 VG_(message)(Vg_UserMsg,
1300 "as it doesn't generate errors.");
1301 VG_(bad_option)("--gen-suppressions=");
1302 }
1303
sewardj71bc3cb2005-05-19 00:25:45 +00001304 /* If we've been asked to emit XML, mash around various other
1305 options so as to constrain the output somewhat, and to remove
1306 any need for user input during the run. */
1307 if (VG_(clo_xml)) {
1308 /* Disable suppression generation (requires user input) */
1309 VG_(clo_gen_suppressions) = 0;
1310 /* Disable attaching to GDB (requires user input) */
1311 VG_(clo_db_attach) = False;
1312 /* Set a known verbosity level */
1313 VG_(clo_verbosity) = 1;
1314 /* Disable error limits (this might be a bad idea!) */
1315 VG_(clo_error_limit) = False;
1316 /* Disable emulation warnings */
1317 VG_(clo_show_emwarns) = False;
1318 /* Disable waiting for GDB to debug Valgrind */
1319 VG_(clo_wait_for_gdb) = False;
1320 /* No file-descriptor leak checking yet */
1321 VG_(clo_track_fds) = False;
sewardj21f7f0c2005-07-06 19:46:48 +00001322 /* Disable timestamped output */
1323 VG_(clo_time_stamp) = False;
sewardj71bc3cb2005-05-19 00:25:45 +00001324 /* Also, we want to set options for the leak checker, but that
1325 will have to be done in Memcheck's flag-handling code, not
1326 here. */
1327 }
1328
njnbe9b47b2005-05-15 16:22:58 +00001329 /* All non-logging-related options have been checked. If the logging
1330 option specified is ok, we can switch to it, as we know we won't
1331 have to generate any other command-line-related error messages.
1332 (So far we should be still attached to stderr, so we can show on
1333 the terminal any problems to do with processing command line
1334 opts.)
1335
1336 So set up logging now. After this is done, VG_(clo_log_fd)
sewardj4cf05692002-10-27 20:28:29 +00001337 should be connected to whatever sink has been selected, and we
1338 indiscriminately chuck stuff into it without worrying what the
1339 nature of it is. Oh the wonder of Unix streams. */
1340
njnbe9b47b2005-05-15 16:22:58 +00001341 vg_assert(VG_(clo_log_fd) == 2 /* stderr */);
1342 vg_assert(VG_(logging_to_socket) == False);
sewardj4cf05692002-10-27 20:28:29 +00001343
njnbe9b47b2005-05-15 16:22:58 +00001344 switch (log_to) {
sewardj73cf3bc2002-11-03 03:20:15 +00001345
sewardj4cf05692002-10-27 20:28:29 +00001346 case VgLogTo_Fd:
nethercotef8548672004-06-21 12:42:35 +00001347 vg_assert(VG_(clo_log_name) == NULL);
sewardj4cf05692002-10-27 20:28:29 +00001348 break;
sewardj73cf3bc2002-11-03 03:20:15 +00001349
sewardj4cf05692002-10-27 20:28:29 +00001350 case VgLogTo_File: {
sewardjad311162005-07-19 11:25:02 +00001351 HChar logfilename[1000];
1352 Int seq = 0;
1353 Int pid = VG_(getpid)();
1354 HChar* qual = NULL;
jsgff3c3f1a2003-10-14 22:13:28 +00001355
nethercotef8548672004-06-21 12:42:35 +00001356 vg_assert(VG_(clo_log_name) != NULL);
1357 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
jsgff3c3f1a2003-10-14 22:13:28 +00001358
sewardjad311162005-07-19 11:25:02 +00001359 if (VG_(clo_log_file_qualifier)) {
1360 qual = VG_(getenv)(VG_(clo_log_file_qualifier));
1361 }
1362
nethercote71980f02004-01-24 18:18:54 +00001363 for (;;) {
sewardj92645592005-07-23 09:18:34 +00001364 HChar pidtxt[20], seqtxt[20];
1365
1366 VG_(sprintf)(pidtxt, "%d", pid);
1367
1368 if (seq == 0)
1369 seqtxt[0] = 0;
1370 else
1371 VG_(sprintf)(seqtxt, ".%d", seq);
1372
jsgff3c3f1a2003-10-14 22:13:28 +00001373 seq++;
1374
sewardj92645592005-07-23 09:18:34 +00001375 /* Result:
1376 if (qual) base_name ++ "." ++ qual ++ seqtxt
1377 if (not qual) base_name ++ "." ++ pid ++ seqtxt
1378 */
1379 VG_(sprintf)( logfilename,
1380 "%s.%s%s",
1381 VG_(clo_log_name),
1382 qual ? qual : pidtxt,
1383 seqtxt );
1384
njnbe9b47b2005-05-15 16:22:58 +00001385 // EXCL: it will fail with EEXIST if the file already exists.
njnda033f52005-12-19 21:27:58 +00001386 sres = VG_(open)(logfilename,
1387 VKI_O_CREAT|VKI_O_WRONLY|VKI_O_EXCL|VKI_O_TRUNC,
1388 VKI_S_IRUSR|VKI_S_IWUSR);
sewardj92645592005-07-23 09:18:34 +00001389 if (!sres.isError) {
njnda033f52005-12-19 21:27:58 +00001390 tmp_log_fd = sres.val;
sewardj603d4102005-01-11 14:01:02 +00001391 break; /* for (;;) */
jsgff3c3f1a2003-10-14 22:13:28 +00001392 } else {
njnbe9b47b2005-05-15 16:22:58 +00001393 // If the file already existed, we try the next name. If it
1394 // was some other file error, we give up.
sewardj92645592005-07-23 09:18:34 +00001395 if (sres.val != VKI_EEXIST) {
jsgff3c3f1a2003-10-14 22:13:28 +00001396 VG_(message)(Vg_UserMsg,
sewardjc40fce52006-05-03 13:52:17 +00001397 "Can't create log file '%s' (%s); giving up!",
1398 logfilename, VG_(strerror)(sres.val));
jsgff3c3f1a2003-10-14 22:13:28 +00001399 VG_(bad_option)(
sewardj603d4102005-01-11 14:01:02 +00001400 "--log-file=<file> (didn't work out for some reason.)");
njnbe9b47b2005-05-15 16:22:58 +00001401 /*NOTREACHED*/
jsgff3c3f1a2003-10-14 22:13:28 +00001402 }
1403 }
1404 }
sewardj603d4102005-01-11 14:01:02 +00001405 break; /* switch (VG_(clo_log_to)) */
1406 }
1407
1408 case VgLogTo_FileExactly: {
sewardj603d4102005-01-11 14:01:02 +00001409 vg_assert(VG_(clo_log_name) != NULL);
1410 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
sewardj603d4102005-01-11 14:01:02 +00001411
njnda033f52005-12-19 21:27:58 +00001412 sres = VG_(open)(VG_(clo_log_name),
1413 VKI_O_CREAT|VKI_O_WRONLY|VKI_O_TRUNC,
1414 VKI_S_IRUSR|VKI_S_IWUSR);
sewardj92645592005-07-23 09:18:34 +00001415 if (!sres.isError) {
njnda033f52005-12-19 21:27:58 +00001416 tmp_log_fd = sres.val;
njnbe9b47b2005-05-15 16:22:58 +00001417 } else {
sewardj603d4102005-01-11 14:01:02 +00001418 VG_(message)(Vg_UserMsg,
njn02bc4b82005-05-15 17:28:26 +00001419 "Can't create/open log file '%s'; giving up!",
sewardj603d4102005-01-11 14:01:02 +00001420 VG_(clo_log_name));
1421 VG_(bad_option)(
1422 "--log-file-exactly=<file> (didn't work out for some reason.)");
1423 /*NOTREACHED*/
1424 }
1425 break; /* switch (VG_(clo_log_to)) */
sewardj73cf3bc2002-11-03 03:20:15 +00001426 }
1427
1428 case VgLogTo_Socket: {
nethercotef8548672004-06-21 12:42:35 +00001429 vg_assert(VG_(clo_log_name) != NULL);
1430 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
njnda033f52005-12-19 21:27:58 +00001431 tmp_log_fd = VG_(connect_via_socket)( VG_(clo_log_name) );
1432 if (tmp_log_fd == -1) {
sewardj73cf3bc2002-11-03 03:20:15 +00001433 VG_(message)(Vg_UserMsg,
nethercotef8548672004-06-21 12:42:35 +00001434 "Invalid --log-socket=ipaddr or --log-socket=ipaddr:port spec");
sewardj73cf3bc2002-11-03 03:20:15 +00001435 VG_(message)(Vg_UserMsg,
njn02bc4b82005-05-15 17:28:26 +00001436 "of '%s'; giving up!", VG_(clo_log_name) );
sewardj73cf3bc2002-11-03 03:20:15 +00001437 VG_(bad_option)(
nethercotef8548672004-06-21 12:42:35 +00001438 "--log-socket=");
njnbe9b47b2005-05-15 16:22:58 +00001439 /*NOTREACHED*/
sewardj4cf05692002-10-27 20:28:29 +00001440 }
njnda033f52005-12-19 21:27:58 +00001441 if (tmp_log_fd == -2) {
sewardj73cf3bc2002-11-03 03:20:15 +00001442 VG_(message)(Vg_UserMsg,
njn02bc4b82005-05-15 17:28:26 +00001443 "valgrind: failed to connect to logging server '%s'.",
nethercotef8548672004-06-21 12:42:35 +00001444 VG_(clo_log_name) );
sewardj570f8902002-11-03 11:44:36 +00001445 VG_(message)(Vg_UserMsg,
1446 "Log messages will sent to stderr instead." );
1447 VG_(message)(Vg_UserMsg,
1448 "" );
1449 /* We don't change anything here. */
njnbe9b47b2005-05-15 16:22:58 +00001450 vg_assert(VG_(clo_log_fd) == 2);
njnda033f52005-12-19 21:27:58 +00001451 tmp_log_fd = 2;
sewardj570f8902002-11-03 11:44:36 +00001452 } else {
njnda033f52005-12-19 21:27:58 +00001453 vg_assert(tmp_log_fd > 0);
njnbe9b47b2005-05-15 16:22:58 +00001454 VG_(logging_to_socket) = True;
sewardj570f8902002-11-03 11:44:36 +00001455 }
sewardj73cf3bc2002-11-03 03:20:15 +00001456 break;
1457 }
sewardj4cf05692002-10-27 20:28:29 +00001458 }
1459
sewardj71bc3cb2005-05-19 00:25:45 +00001460
1461 /* Check that the requested tool actually supports XML output. */
njnca54af32006-04-16 10:25:43 +00001462 if (VG_(clo_xml) && !VG_(needs).xml_output) {
sewardj71bc3cb2005-05-19 00:25:45 +00001463 VG_(clo_xml) = False;
1464 VG_(message)(Vg_UserMsg,
njnca54af32006-04-16 10:25:43 +00001465 "%s does not support XML output.", VG_(details).name);
sewardj71bc3cb2005-05-19 00:25:45 +00001466 VG_(bad_option)("--xml=yes");
1467 /*NOTREACHED*/
1468 }
1469
njnda033f52005-12-19 21:27:58 +00001470 if (tmp_log_fd >= 0) {
1471 // Move log_fd into the safe range, so it doesn't conflict with any app fds.
1472 tmp_log_fd = VG_(fcntl)(tmp_log_fd, VKI_F_DUPFD, VG_(fd_hard_limit));
1473 if (tmp_log_fd < 0) {
1474 VG_(message)(Vg_UserMsg, "valgrind: failed to move logfile fd into safe range, using stderr");
1475 VG_(clo_log_fd) = 2; // stderr
1476 } else {
1477 VG_(clo_log_fd) = tmp_log_fd;
1478 VG_(fcntl)(VG_(clo_log_fd), VKI_F_SETFD, VKI_FD_CLOEXEC);
1479 }
1480 } else {
1481 // If they said --log-fd=-1, don't print anything. Plausible for use in
1482 // regression testing suites that use client requests to count errors.
1483 VG_(clo_log_fd) = tmp_log_fd;
jsgf855d93d2003-10-13 22:26:55 +00001484 }
1485
sewardj45f4e7c2005-09-27 19:20:21 +00001486 if (VG_(clo_n_suppressions) < VG_CLO_MAX_SFILES-1 &&
1487 (VG_(needs).core_errors || VG_(needs).tool_errors)) {
1488 /* If we haven't reached the max number of suppressions, load
1489 the default one. */
1490 static const Char default_supp[] = "default.supp";
1491 Int len = VG_(strlen)(VG_(libdir)) + 1 + sizeof(default_supp);
1492 Char *buf = VG_(arena_malloc)(VG_AR_CORE, len);
1493 VG_(sprintf)(buf, "%s/%s", VG_(libdir), default_supp);
1494 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = buf;
1495 VG_(clo_n_suppressions)++;
1496 }
sewardjde4a1d02002-03-22 01:27:54 +00001497
sewardj45f4e7c2005-09-27 19:20:21 +00001498 return (log_to == VgLogTo_Fd);
1499}
1500
1501
1502/*====================================================================*/
1503/*=== Printing the preamble ===*/
1504/*====================================================================*/
1505
1506/* Ok, the logging sink is running now. Print a suitable preamble.
1507 If logging to file or a socket, write details of parent PID and
1508 command line args, to help people trying to interpret the
1509 results of a run which encompasses multiple processes. */
1510static void print_preamble(Bool logging_to_fd, const char* toolname)
1511{
tom60a4b0b2005-10-12 10:45:27 +00001512 HChar* xpre = VG_(clo_xml) ? " <line>" : "";
1513 HChar* xpost = VG_(clo_xml) ? "</line>" : "";
1514 Int i;
1515
sewardj71bc3cb2005-05-19 00:25:45 +00001516 if (VG_(clo_xml)) {
sewardj8665d8e2005-06-01 17:35:23 +00001517 VG_(message)(Vg_UserMsg, "<?xml version=\"1.0\"?>");
1518 VG_(message)(Vg_UserMsg, "");
sewardj71bc3cb2005-05-19 00:25:45 +00001519 VG_(message)(Vg_UserMsg, "<valgrindoutput>");
1520 VG_(message)(Vg_UserMsg, "");
cerion20241ba2005-11-15 19:07:53 +00001521 VG_(message)(Vg_UserMsg, "<protocolversion>2</protocolversion>");
sewardj71bc3cb2005-05-19 00:25:45 +00001522 VG_(message)(Vg_UserMsg, "");
1523 }
1524
sewardj83adf412002-05-01 01:25:45 +00001525 if (VG_(clo_verbosity > 0)) {
sewardjd7bddad2005-06-13 16:48:32 +00001526
1527 if (VG_(clo_xml))
1528 VG_(message)(Vg_UserMsg, "<preamble>");
1529
nethercote996901a2004-08-03 13:29:09 +00001530 /* Tool details */
sewardj71bc3cb2005-05-19 00:25:45 +00001531 VG_(message)(Vg_UserMsg, "%s%s%s%s, %s.%s",
1532 xpre,
njnd04b7c62002-10-03 14:05:52 +00001533 VG_(details).name,
njnb9c427c2004-12-01 14:14:42 +00001534 NULL == VG_(details).version ? "" : "-",
njnd04b7c62002-10-03 14:05:52 +00001535 NULL == VG_(details).version
1536 ? (Char*)"" : VG_(details).version,
sewardj71bc3cb2005-05-19 00:25:45 +00001537 VG_(details).description,
1538 xpost);
1539 VG_(message)(Vg_UserMsg, "%s%s%s",
1540 xpre, VG_(details).copyright_author, xpost);
sewardj3b2736a2002-03-24 12:18:35 +00001541
njnd04b7c62002-10-03 14:05:52 +00001542 /* Core details */
1543 VG_(message)(Vg_UserMsg,
sewardj71bc3cb2005-05-19 00:25:45 +00001544 "%sUsing LibVEX rev %s, a library for dynamic binary translation.%s",
1545 xpre, LibVEX_Version(), xpost );
sewardjc7025332004-12-13 18:30:39 +00001546 VG_(message)(Vg_UserMsg,
sewardja2cd32d2006-05-27 03:22:47 +00001547 "%sCopyright (C) 2004-2006, and GNU GPL'd, by OpenWorks LLP.%s",
sewardj71bc3cb2005-05-19 00:25:45 +00001548 xpre, xpost );
sewardjc7025332004-12-13 18:30:39 +00001549 VG_(message)(Vg_UserMsg,
sewardj71bc3cb2005-05-19 00:25:45 +00001550 "%sUsing valgrind-%s, a dynamic binary instrumentation framework.%s",
1551 xpre, VERSION, xpost);
sewardjde4a1d02002-03-22 01:27:54 +00001552 VG_(message)(Vg_UserMsg,
sewardja2cd32d2006-05-27 03:22:47 +00001553 "%sCopyright (C) 2000-2006, and GNU GPL'd, by Julian Seward et al.%s",
sewardj71bc3cb2005-05-19 00:25:45 +00001554 xpre, xpost );
sewardjd7bddad2005-06-13 16:48:32 +00001555
sewardj45f4e7c2005-09-27 19:20:21 +00001556 if (VG_(clo_verbosity) == 1 && !VG_(clo_xml))
1557 VG_(message)(Vg_UserMsg, "For more details, rerun with: -v");
1558
sewardjd7bddad2005-06-13 16:48:32 +00001559 if (VG_(clo_xml))
1560 VG_(message)(Vg_UserMsg, "</preamble>");
njnd04b7c62002-10-03 14:05:52 +00001561 }
1562
sewardj45f4e7c2005-09-27 19:20:21 +00001563 if (!VG_(clo_xml) && VG_(clo_verbosity) > 0 && !logging_to_fd) {
sewardj4cf05692002-10-27 20:28:29 +00001564 VG_(message)(Vg_UserMsg, "");
1565 VG_(message)(Vg_UserMsg,
1566 "My PID = %d, parent PID = %d. Prog and args are:",
1567 VG_(getpid)(), VG_(getppid)() );
sewardj5e940782005-09-28 19:59:19 +00001568 if (VG_(args_the_exename))
1569 VG_(message)(Vg_UserMsg, " %s", VG_(args_the_exename));
sewardj45f4e7c2005-09-27 19:20:21 +00001570 for (i = 0; i < VG_(args_for_client).used; i++)
1571 VG_(message)(Vg_UserMsg, " %s", VG_(args_for_client).strs[i]);
sewardj5b742c32005-07-26 23:43:26 +00001572 if (VG_(clo_log_file_qualifier)) {
1573 HChar* val = VG_(getenv)(VG_(clo_log_file_qualifier));
1574 VG_(message)(Vg_UserMsg, "");
1575 VG_(message)(Vg_UserMsg, "Log file qualifier: var %s, value %s.",
1576 VG_(clo_log_file_qualifier),
1577 val ? val : "");
1578 }
sewardj4cf05692002-10-27 20:28:29 +00001579 }
sewardj71bc3cb2005-05-19 00:25:45 +00001580 else
1581 if (VG_(clo_xml)) {
1582 VG_(message)(Vg_UserMsg, "");
1583 VG_(message)(Vg_UserMsg, "<pid>%d</pid>", VG_(getpid)());
1584 VG_(message)(Vg_UserMsg, "<ppid>%d</ppid>", VG_(getppid)());
sewardj97f7e0c2005-07-19 15:00:25 +00001585 VG_(message)(Vg_UserMsg, "<tool>%t</tool>", toolname);
sewardjad311162005-07-19 11:25:02 +00001586 if (VG_(clo_log_file_qualifier)) {
1587 HChar* val = VG_(getenv)(VG_(clo_log_file_qualifier));
sewardj97f7e0c2005-07-19 15:00:25 +00001588 VG_(message)(Vg_UserMsg, "<logfilequalifier> <var>%t</var> "
1589 "<value>%t</value> </logfilequalifier>",
sewardjad311162005-07-19 11:25:02 +00001590 VG_(clo_log_file_qualifier),
1591 val ? val : "");
1592 }
sewardj768db0e2005-07-19 14:18:56 +00001593 if (VG_(clo_xml_user_comment)) {
1594 /* Note: the user comment itself is XML and is therefore to
1595 be passed through verbatim (%s) rather than escaped
1596 (%t). */
1597 VG_(message)(Vg_UserMsg, "<usercomment>%s</usercomment>",
1598 VG_(clo_xml_user_comment));
1599 }
sewardj71bc3cb2005-05-19 00:25:45 +00001600 VG_(message)(Vg_UserMsg, "");
sewardjb8a3dac2005-07-19 12:39:11 +00001601 VG_(message)(Vg_UserMsg, "<args>");
sewardj45f4e7c2005-09-27 19:20:21 +00001602
sewardjb8a3dac2005-07-19 12:39:11 +00001603 VG_(message)(Vg_UserMsg, " <vargv>");
sewardj45f4e7c2005-09-27 19:20:21 +00001604 if (VG_(name_of_launcher))
1605 VG_(message)(Vg_UserMsg, " <exe>%t</exe>",
1606 VG_(name_of_launcher));
1607 for (i = 0; i < VG_(args_for_valgrind).used; i++) {
1608 VG_(message)(Vg_UserMsg,
1609 " <arg>%t</arg>",
1610 VG_(args_for_valgrind).strs[i]);
sewardjb8a3dac2005-07-19 12:39:11 +00001611 }
1612 VG_(message)(Vg_UserMsg, " </vargv>");
sewardj45f4e7c2005-09-27 19:20:21 +00001613
sewardjb8a3dac2005-07-19 12:39:11 +00001614 VG_(message)(Vg_UserMsg, " <argv>");
sewardj45f4e7c2005-09-27 19:20:21 +00001615 if (VG_(args_the_exename))
1616 VG_(message)(Vg_UserMsg, " <exe>%t</exe>",
1617 VG_(args_the_exename));
1618 for (i = 0; i < VG_(args_for_client).used; i++) {
1619 VG_(message)(Vg_UserMsg, " <arg>%t</arg>",
1620 VG_(args_for_client).strs[i]);
sewardj8665d8e2005-06-01 17:35:23 +00001621 }
sewardjb8a3dac2005-07-19 12:39:11 +00001622 VG_(message)(Vg_UserMsg, " </argv>");
sewardj45f4e7c2005-09-27 19:20:21 +00001623
sewardjb8a3dac2005-07-19 12:39:11 +00001624 VG_(message)(Vg_UserMsg, "</args>");
sewardj71bc3cb2005-05-19 00:25:45 +00001625 }
sewardj4cf05692002-10-27 20:28:29 +00001626
sewardj45f4e7c2005-09-27 19:20:21 +00001627 // Empty line after the preamble
1628 if (VG_(clo_verbosity) > 0)
1629 VG_(message)(Vg_UserMsg, "");
1630
sewardjde4a1d02002-03-22 01:27:54 +00001631 if (VG_(clo_verbosity) > 1) {
sewardj92645592005-07-23 09:18:34 +00001632 SysRes fd;
sewardj1f0bbc72005-11-16 03:51:02 +00001633 VexArch vex_arch;
1634 VexArchInfo vex_archinfo;
sewardj45f4e7c2005-09-27 19:20:21 +00001635 if (!logging_to_fd)
njn1fd5eb22005-03-13 05:43:23 +00001636 VG_(message)(Vg_DebugMsg, "");
njn1fd5eb22005-03-13 05:43:23 +00001637 VG_(message)(Vg_DebugMsg, "Command line");
sewardj45f4e7c2005-09-27 19:20:21 +00001638 if (VG_(args_the_exename))
1639 VG_(message)(Vg_DebugMsg, " %s", VG_(args_the_exename));
1640 for (i = 0; i < VG_(args_for_client).used; i++)
1641 VG_(message)(Vg_DebugMsg, " %s", VG_(args_for_client).strs[i]);
njn86dc2bc2003-09-09 07:26:21 +00001642
njn1fd5eb22005-03-13 05:43:23 +00001643 VG_(message)(Vg_DebugMsg, "Startup, with flags:");
sewardj45f4e7c2005-09-27 19:20:21 +00001644 for (i = 0; i < VG_(args_for_valgrind).used; i++) {
1645 VG_(message)(Vg_DebugMsg, " %s", VG_(args_for_valgrind).strs[i]);
sewardjde4a1d02002-03-22 01:27:54 +00001646 }
nethercotea70f7352004-04-18 12:08:46 +00001647
njn1fd5eb22005-03-13 05:43:23 +00001648 VG_(message)(Vg_DebugMsg, "Contents of /proc/version:");
nethercotea70f7352004-04-18 12:08:46 +00001649 fd = VG_(open) ( "/proc/version", VKI_O_RDONLY, 0 );
sewardj92645592005-07-23 09:18:34 +00001650 if (fd.isError) {
njn1fd5eb22005-03-13 05:43:23 +00001651 VG_(message)(Vg_DebugMsg, " can't open /proc/version");
nethercotea70f7352004-04-18 12:08:46 +00001652 } else {
sewardj71bc3cb2005-05-19 00:25:45 +00001653# define BUF_LEN 256
nethercotea70f7352004-04-18 12:08:46 +00001654 Char version_buf[BUF_LEN];
sewardj92645592005-07-23 09:18:34 +00001655 Int n = VG_(read) ( fd.val, version_buf, BUF_LEN );
njnbe9b47b2005-05-15 16:22:58 +00001656 vg_assert(n <= BUF_LEN);
nethercotea70f7352004-04-18 12:08:46 +00001657 if (n > 0) {
1658 version_buf[n-1] = '\0';
njn1fd5eb22005-03-13 05:43:23 +00001659 VG_(message)(Vg_DebugMsg, " %s", version_buf);
nethercotea70f7352004-04-18 12:08:46 +00001660 } else {
njn1fd5eb22005-03-13 05:43:23 +00001661 VG_(message)(Vg_DebugMsg, " (empty?)");
nethercotea70f7352004-04-18 12:08:46 +00001662 }
sewardj92645592005-07-23 09:18:34 +00001663 VG_(close)(fd.val);
sewardj71bc3cb2005-05-19 00:25:45 +00001664# undef BUF_LEN
nethercotea70f7352004-04-18 12:08:46 +00001665 }
sewardj1f0bbc72005-11-16 03:51:02 +00001666
1667 VG_(machine_get_VexArchInfo)( &vex_arch, &vex_archinfo );
sewardje3121f32006-01-27 21:23:23 +00001668 VG_(message)(
1669 Vg_DebugMsg,
1670 "Arch and hwcaps: %s, %s",
1671 LibVEX_ppVexArch ( vex_arch ),
1672 LibVEX_ppVexHwCaps ( vex_arch, vex_archinfo.hwcaps )
1673 );
sewardj1f0bbc72005-11-16 03:51:02 +00001674 VG_(message)(Vg_DebugMsg, "Valgrind library directory: %s", VG_(libdir));
sewardjde4a1d02002-03-22 01:27:54 +00001675 }
nethercotef6a1d502004-08-09 12:21:57 +00001676}
1677
sewardjde4a1d02002-03-22 01:27:54 +00001678
nethercote71980f02004-01-24 18:18:54 +00001679/*====================================================================*/
1680/*=== File descriptor setup ===*/
1681/*====================================================================*/
1682
sewardj5f229e22005-09-28 01:36:01 +00001683/* Number of file descriptors that Valgrind tries to reserve for
1684 it's own use - just a small constant. */
1685#define N_RESERVED_FDS (10)
1686
nethercote71980f02004-01-24 18:18:54 +00001687static void setup_file_descriptors(void)
1688{
1689 struct vki_rlimit rl;
1690
1691 /* Get the current file descriptor limits. */
1692 if (VG_(getrlimit)(VKI_RLIMIT_NOFILE, &rl) < 0) {
1693 rl.rlim_cur = 1024;
1694 rl.rlim_max = 1024;
1695 }
1696
1697 /* Work out where to move the soft limit to. */
njn14319cc2005-03-13 06:26:22 +00001698 if (rl.rlim_cur + N_RESERVED_FDS <= rl.rlim_max) {
1699 rl.rlim_cur = rl.rlim_cur + N_RESERVED_FDS;
nethercote71980f02004-01-24 18:18:54 +00001700 } else {
1701 rl.rlim_cur = rl.rlim_max;
1702 }
1703
1704 /* Reserve some file descriptors for our use. */
njn14319cc2005-03-13 06:26:22 +00001705 VG_(fd_soft_limit) = rl.rlim_cur - N_RESERVED_FDS;
1706 VG_(fd_hard_limit) = rl.rlim_cur - N_RESERVED_FDS;
nethercote71980f02004-01-24 18:18:54 +00001707
1708 /* Update the soft limit. */
1709 VG_(setrlimit)(VKI_RLIMIT_NOFILE, &rl);
1710
sewardj45f4e7c2005-09-27 19:20:21 +00001711 if (VG_(cl_exec_fd) != -1)
1712 VG_(cl_exec_fd) = VG_(safe_fd)( VG_(cl_exec_fd) );
nethercote71980f02004-01-24 18:18:54 +00001713}
1714
sewardjde4a1d02002-03-22 01:27:54 +00001715
njn2da73352005-06-18 01:35:16 +00001716/*====================================================================*/
1717/*=== Initialise the first thread. ===*/
1718/*====================================================================*/
1719
1720/* Given a pointer to the ThreadArchState for thread 1 (the root
1721 thread), initialise the VEX guest state, and copy in essential
1722 starting values.
1723*/
1724static void init_thread1state ( Addr client_ip,
sewardjfdf91b42005-09-28 00:53:09 +00001725 Addr client_sp,
sewardj13247ca2005-12-30 22:52:20 +00001726 Addr client_toc,
njn2da73352005-06-18 01:35:16 +00001727 /*inout*/ ThreadArchState* arch )
1728{
1729#if defined(VGA_x86)
1730 vg_assert(0 == sizeof(VexGuestX86State) % 8);
1731
1732 /* Zero out the initial state, and set up the simulated FPU in a
1733 sane way. */
1734 LibVEX_GuestX86_initialise(&arch->vex);
1735
1736 /* Zero out the shadow area. */
1737 VG_(memset)(&arch->vex_shadow, 0, sizeof(VexGuestX86State));
1738
1739 /* Put essential stuff into the new state. */
sewardjfdf91b42005-09-28 00:53:09 +00001740 arch->vex.guest_ESP = client_sp;
njn2da73352005-06-18 01:35:16 +00001741 arch->vex.guest_EIP = client_ip;
1742
1743 /* initialise %cs, %ds and %ss to point at the operating systems
1744 default code, data and stack segments */
1745 asm volatile("movw %%cs, %0" : : "m" (arch->vex.guest_CS));
1746 asm volatile("movw %%ds, %0" : : "m" (arch->vex.guest_DS));
1747 asm volatile("movw %%ss, %0" : : "m" (arch->vex.guest_SS));
cerion85665ca2005-06-20 15:51:07 +00001748
njn2da73352005-06-18 01:35:16 +00001749#elif defined(VGA_amd64)
1750 vg_assert(0 == sizeof(VexGuestAMD64State) % 8);
1751
1752 /* Zero out the initial state, and set up the simulated FPU in a
1753 sane way. */
1754 LibVEX_GuestAMD64_initialise(&arch->vex);
1755
1756 /* Zero out the shadow area. */
1757 VG_(memset)(&arch->vex_shadow, 0, sizeof(VexGuestAMD64State));
1758
1759 /* Put essential stuff into the new state. */
sewardjfdf91b42005-09-28 00:53:09 +00001760 arch->vex.guest_RSP = client_sp;
njn2da73352005-06-18 01:35:16 +00001761 arch->vex.guest_RIP = client_ip;
cerion85665ca2005-06-20 15:51:07 +00001762
1763#elif defined(VGA_ppc32)
1764 vg_assert(0 == sizeof(VexGuestPPC32State) % 8);
1765
1766 /* Zero out the initial state, and set up the simulated FPU in a
1767 sane way. */
1768 LibVEX_GuestPPC32_initialise(&arch->vex);
1769
1770 /* Zero out the shadow area. */
1771 VG_(memset)(&arch->vex_shadow, 0, sizeof(VexGuestPPC32State));
1772
1773 /* Put essential stuff into the new state. */
sewardjfdf91b42005-09-28 00:53:09 +00001774 arch->vex.guest_GPR1 = client_sp;
cerion85665ca2005-06-20 15:51:07 +00001775 arch->vex.guest_CIA = client_ip;
1776
sewardj2c48c7b2005-11-29 13:05:56 +00001777#elif defined(VGA_ppc64)
cerion21082042005-12-06 19:07:08 +00001778 vg_assert(0 == sizeof(VexGuestPPC64State) % 16);
sewardj2c48c7b2005-11-29 13:05:56 +00001779
1780 /* Zero out the initial state, and set up the simulated FPU in a
1781 sane way. */
1782 LibVEX_GuestPPC64_initialise(&arch->vex);
1783
1784 /* Zero out the shadow area. */
1785 VG_(memset)(&arch->vex_shadow, 0, sizeof(VexGuestPPC64State));
1786
1787 /* Put essential stuff into the new state. */
1788 arch->vex.guest_GPR1 = client_sp;
sewardj13247ca2005-12-30 22:52:20 +00001789 arch->vex.guest_GPR2 = client_toc;
sewardj2c48c7b2005-11-29 13:05:56 +00001790 arch->vex.guest_CIA = client_ip;
njn2da73352005-06-18 01:35:16 +00001791#else
1792# error Unknown arch
1793#endif
1794 // Tell the tool that we just wrote to the registers.
1795 VG_TRACK( post_reg_write, Vg_CoreStartup, /*tid*/1, /*offset*/0,
1796 sizeof(VexGuestArchState));
1797}
1798
sewardjde4a1d02002-03-22 01:27:54 +00001799
nethercote71980f02004-01-24 18:18:54 +00001800/*====================================================================*/
njn2025cf92005-06-26 20:44:48 +00001801/*=== BB profiling ===*/
1802/*====================================================================*/
1803
1804static
1805void show_BB_profile ( BBProfEntry tops[], UInt n_tops, ULong score_total )
1806{
1807 ULong score_cumul, score_here;
1808 Char buf_cumul[10], buf_here[10];
1809 Char name[64];
1810 Int r;
1811
1812 VG_(printf)("\n");
1813 VG_(printf)("-----------------------------------------------------------\n");
1814 VG_(printf)("--- BEGIN BB Profile (summary of scores) ---\n");
1815 VG_(printf)("-----------------------------------------------------------\n");
1816 VG_(printf)("\n");
1817
1818 VG_(printf)("Total score = %lld\n\n", score_total);
1819
1820 score_cumul = 0;
1821 for (r = 0; r < n_tops; r++) {
1822 if (tops[r].addr == 0)
1823 continue;
1824 name[0] = 0;
1825 VG_(get_fnname_w_offset)(tops[r].addr, name, 64);
1826 name[63] = 0;
1827 score_here = tops[r].score;
1828 score_cumul += score_here;
1829 VG_(percentify)(score_cumul, score_total, 2, 6, buf_cumul);
1830 VG_(percentify)(score_here, score_total, 2, 6, buf_here);
1831 VG_(printf)("%3d: (%9lld %s) %9lld %s 0x%llx %s\n",
1832 r,
1833 score_cumul, buf_cumul,
1834 score_here, buf_here, tops[r].addr, name );
1835 }
1836
1837 VG_(printf)("\n");
1838 VG_(printf)("-----------------------------------------------------------\n");
1839 VG_(printf)("--- BB Profile (BB details) ---\n");
1840 VG_(printf)("-----------------------------------------------------------\n");
1841 VG_(printf)("\n");
1842
1843 score_cumul = 0;
1844 for (r = 0; r < n_tops; r++) {
1845 if (tops[r].addr == 0)
1846 continue;
1847 name[0] = 0;
1848 VG_(get_fnname_w_offset)(tops[r].addr, name, 64);
1849 name[63] = 0;
1850 score_here = tops[r].score;
1851 score_cumul += score_here;
1852 VG_(percentify)(score_cumul, score_total, 2, 6, buf_cumul);
1853 VG_(percentify)(score_here, score_total, 2, 6, buf_here);
1854 VG_(printf)("\n");
1855 VG_(printf)("=-=-=-=-=-=-=-=-=-=-=-=-=-= begin BB rank %d "
1856 "=-=-=-=-=-=-=-=-=-=-=-=-=-=\n\n", r);
1857 VG_(printf)("%3d: (%9lld %s) %9lld %s 0x%llx %s\n",
1858 r,
1859 score_cumul, buf_cumul,
1860 score_here, buf_here, tops[r].addr, name );
1861 VG_(printf)("\n");
sewardj0ec07f32006-01-12 12:32:32 +00001862 VG_(translate)(0, tops[r].addr, True, VG_(clo_profile_flags), 0, True);
njn2025cf92005-06-26 20:44:48 +00001863 VG_(printf)("=-=-=-=-=-=-=-=-=-=-=-=-=-= end BB rank %d "
1864 "=-=-=-=-=-=-=-=-=-=-=-=-=-=\n\n", r);
1865 }
1866
1867 VG_(printf)("\n");
1868 VG_(printf)("-----------------------------------------------------------\n");
1869 VG_(printf)("--- END BB Profile ---\n");
1870 VG_(printf)("-----------------------------------------------------------\n");
1871 VG_(printf)("\n");
1872}
1873
1874
1875/*====================================================================*/
nethercote71980f02004-01-24 18:18:54 +00001876/*=== main() ===*/
1877/*====================================================================*/
1878
sewardjfdf91b42005-09-28 00:53:09 +00001879/* When main() is entered, we should be on the following stack, not
1880 the one the kernel gave us. We will run on this stack until
1881 simulation of the root thread is started, at which point a transfer
1882 is made to a dynamically allocated stack. This is for the sake of
1883 uniform overflow detection for all Valgrind threads. This is
1884 marked global even though it isn't, because assembly code below
1885 needs to reference the name. */
1886
1887/*static*/ VgStack VG_(interim_stack);
1888
1889/* This should get some address inside the stack on which we gained
1890 control (eg, it could be the SP at startup). It doesn't matter
1891 exactly where in the stack it is. This value is passed to the
1892 address space manager at startup, which uses it to identify the
1893 initial stack segment and hence the upper end of the usable address
1894 space. */
1895
1896static Addr sp_at_startup = 0;
1897
sewardj1ae3f3a2005-09-28 10:47:38 +00001898/* --- Forwards decls to do with shutdown --- */
1899
1900static void final_tidyup(ThreadId tid);
1901
1902/* Do everything which needs doing when the last thread exits */
1903static
1904void shutdown_actions_NORETURN( ThreadId tid,
1905 VgSchedReturnCode tids_schedretcode );
1906
1907/* --- end of Forwards decls to do with shutdown --- */
sewardjfdf91b42005-09-28 00:53:09 +00001908
1909
sewardj45f4e7c2005-09-27 19:20:21 +00001910/* TODO: GIVE THIS A PROPER HOME
njn1d0825f2006-03-27 11:37:07 +00001911 TODO: MERGE THIS WITH DUPLICATE IN mc_leakcheck.c and coredump-elf.c.
sewardj45f4e7c2005-09-27 19:20:21 +00001912 Extract from aspacem a vector of the current segment start
1913 addresses. The vector is dynamically allocated and should be freed
1914 by the caller when done. REQUIRES m_mallocfree to be running.
1915 Writes the number of addresses required into *n_acquired. */
nethercotec314eba2004-07-15 12:59:41 +00001916
sewardj45f4e7c2005-09-27 19:20:21 +00001917static Addr* get_seg_starts ( /*OUT*/Int* n_acquired )
sewardj1cf558c2005-04-25 01:36:56 +00001918{
sewardj45f4e7c2005-09-27 19:20:21 +00001919 Addr* starts;
sewardja48a4932005-09-29 11:09:56 +00001920 Int n_starts, r = 0;
sewardj45f4e7c2005-09-27 19:20:21 +00001921
1922 n_starts = 1;
sewardj1cf558c2005-04-25 01:36:56 +00001923 while (True) {
sewardj45f4e7c2005-09-27 19:20:21 +00001924 starts = VG_(malloc)( n_starts * sizeof(Addr) );
1925 if (starts == NULL)
1926 break;
1927 r = VG_(am_get_segment_starts)( starts, n_starts );
1928 if (r >= 0)
1929 break;
1930 VG_(free)(starts);
1931 n_starts *= 2;
sewardj1cf558c2005-04-25 01:36:56 +00001932 }
sewardj45f4e7c2005-09-27 19:20:21 +00001933
1934 if (starts == NULL) {
1935 *n_acquired = 0;
1936 return NULL;
1937 }
1938
1939 *n_acquired = r;
1940 return starts;
sewardj1cf558c2005-04-25 01:36:56 +00001941}
1942
1943
sewardj45f4e7c2005-09-27 19:20:21 +00001944
sewardj45f4e7c2005-09-27 19:20:21 +00001945Int main(Int argc, HChar **argv, HChar **envp)
nethercote71980f02004-01-24 18:18:54 +00001946{
sewardj13247ca2005-12-30 22:52:20 +00001947 HChar* toolname = "memcheck"; // default to Memcheck
1948 HChar** env = NULL;
1949 Int need_help = 0; // 0 = no, 1 = --help, 2 = --help-debug
1950 Addr initial_client_IP = 0;
1951 Addr initial_client_SP = 0;
1952 Addr initial_client_TOC = 0;
1953 Addr clstack_top = 0;
1954 SizeT clstack_max_size = 0;
sewardj4c3faae2006-03-15 11:50:32 +00001955 UInt* client_auxv = NULL;
sewardj45f4e7c2005-09-27 19:20:21 +00001956 Int loglevel, i;
1957 Bool logging_to_fd;
nethercote73b526f2004-10-31 18:48:21 +00001958 struct vki_rlimit zero = { 0, 0 };
sewardj13247ca2005-12-30 22:52:20 +00001959 ExeInfo info;
nethercote71980f02004-01-24 18:18:54 +00001960
1961 //============================================================
nethercote71980f02004-01-24 18:18:54 +00001962 //
sewardj45f4e7c2005-09-27 19:20:21 +00001963 // Nb: startup is complex. Prerequisites are shown at every step.
nethercote71980f02004-01-24 18:18:54 +00001964 // *** Be very careful when messing with the order ***
sewardj45f4e7c2005-09-27 19:20:21 +00001965 //
1966 // The first order of business is to get debug logging, the address
1967 // space manager and the dynamic memory manager up and running.
1968 // Once that's done, we can relax a bit.
1969 //
nethercote71980f02004-01-24 18:18:54 +00001970 //============================================================
sewardj45f4e7c2005-09-27 19:20:21 +00001971
1972 /* This is needed to make VG_(getenv) usable early. */
1973 VG_(client_envp) = (Char**)envp;
nethercote71980f02004-01-24 18:18:54 +00001974
sewardj1cf558c2005-04-25 01:36:56 +00001975 //--------------------------------------------------------------
1976 // Start up the logging mechanism
1977 // p: none
1978 //--------------------------------------------------------------
1979 /* Start the debugging-log system ASAP. First find out how many
1980 "-d"s were specified. This is a pre-scan of the command line. */
1981 loglevel = 0;
1982 for (i = 1; i < argc; i++) {
sewardj10759312005-05-30 23:52:47 +00001983 if (argv[i][0] != '-')
1984 break;
sewardj45f4e7c2005-09-27 19:20:21 +00001985 if (VG_STREQ(argv[i], "--"))
sewardj10759312005-05-30 23:52:47 +00001986 break;
sewardj45f4e7c2005-09-27 19:20:21 +00001987 if (VG_STREQ(argv[i], "-d"))
sewardj10759312005-05-30 23:52:47 +00001988 loglevel++;
sewardj1cf558c2005-04-25 01:36:56 +00001989 }
1990
1991 /* ... and start the debug logger. Now we can safely emit logging
1992 messages all through startup. */
sewardj10759312005-05-30 23:52:47 +00001993 VG_(debugLog_startup)(loglevel, "Stage 2 (main)");
sewardj45f4e7c2005-09-27 19:20:21 +00001994 VG_(debugLog)(1, "main", "Welcome to Valgrind version "
1995 VERSION " debug logging\n");
1996
1997 //--------------------------------------------------------------
1998 // Ensure we're on a plausible stack.
1999 // p: logging
2000 //--------------------------------------------------------------
2001 VG_(debugLog)(1, "main", "Checking current stack is plausible\n");
sewardjfdf91b42005-09-28 00:53:09 +00002002 { HChar* limLo = (HChar*)(&VG_(interim_stack).bytes[0]);
2003 HChar* limHi = limLo + sizeof(VG_(interim_stack));
sewardj45f4e7c2005-09-27 19:20:21 +00002004 HChar* aLocal = (HChar*)&zero; /* any auto local will do */
2005 if (aLocal < limLo || aLocal >= limHi) {
2006 /* something's wrong. Stop. */
2007 VG_(debugLog)(0, "main", "Root stack %p to %p, a local %p\n",
2008 limLo, limHi, aLocal );
2009 VG_(debugLog)(0, "main", "Valgrind: FATAL: "
2010 "Initial stack switched failed.\n");
2011 VG_(debugLog)(0, "main", " Cannot continue. Sorry.\n");
2012 VG_(exit)(1);
2013 }
2014 }
2015
2016 //--------------------------------------------------------------
2017 // Ensure we have a plausible pointer to the stack on which
2018 // we gained control (not the current stack!)
2019 // p: logging
2020 //--------------------------------------------------------------
2021 VG_(debugLog)(1, "main", "Checking initial stack was noted\n");
sewardjfdf91b42005-09-28 00:53:09 +00002022 if (sp_at_startup == 0) {
sewardj45f4e7c2005-09-27 19:20:21 +00002023 VG_(debugLog)(0, "main", "Valgrind: FATAL: "
2024 "Initial stack was not noted.\n");
2025 VG_(debugLog)(0, "main", " Cannot continue. Sorry.\n");
2026 VG_(exit)(1);
2027 }
2028
2029 //--------------------------------------------------------------
2030 // Start up the address space manager, and determine the
2031 // approximate location of the client's stack
2032 // p: logging, plausible-stack
2033 //--------------------------------------------------------------
2034 VG_(debugLog)(1, "main", "Starting the address space manager\n");
sewardjfdf91b42005-09-28 00:53:09 +00002035 clstack_top = VG_(am_startup)( sp_at_startup );
sewardj45f4e7c2005-09-27 19:20:21 +00002036 VG_(debugLog)(1, "main", "Address space manager is running\n");
2037
2038 //--------------------------------------------------------------
2039 // Start up the dynamic memory manager
2040 // p: address space management
2041 // In fact m_mallocfree is self-initialising, so there's no
2042 // initialisation call to do. Instead, try a simple malloc/
2043 // free pair right now to check that nothing is broken.
2044 //--------------------------------------------------------------
2045 VG_(debugLog)(1, "main", "Starting the dynamic memory manager\n");
2046 { void* p = VG_(malloc)( 12345 );
2047 if (p) VG_(free)( p );
2048 }
2049 VG_(debugLog)(1, "main", "Dynamic memory manager is running\n");
sewardj1cf558c2005-04-25 01:36:56 +00002050
nethercotef4928da2004-06-15 10:54:40 +00002051 //============================================================
sewardj45f4e7c2005-09-27 19:20:21 +00002052 //
2053 // Dynamic memory management is now available.
2054 //
nethercotef4928da2004-06-15 10:54:40 +00002055 //============================================================
2056
sewardj45f4e7c2005-09-27 19:20:21 +00002057 //--------------------------------------------------------------
2058 // Look for alternative libdir
2059 { HChar *cp = VG_(getenv)(VALGRIND_LIB);
2060 if (cp != NULL)
2061 VG_(libdir) = cp;
2062 }
2063
2064 //--------------------------------------------------------------
2065 // Extract the launcher name from the environment.
2066 VG_(debugLog)(1, "main", "Getting stage1's name\n");
2067 VG_(name_of_launcher) = VG_(getenv)(VALGRIND_LAUNCHER);
2068 if (VG_(name_of_launcher) == NULL) {
2069 VG_(printf)("valgrind: You cannot run '%s' directly.\n", argv[0]);
2070 VG_(printf)("valgrind: You should use $prefix/bin/valgrind.\n");
2071 VG_(exit)(1);
2072 }
2073
2074 //--------------------------------------------------------------
fitzhardingeb50068f2004-02-24 23:42:55 +00002075 // Get the current process datasize rlimit, and set it to zero.
2076 // This prevents any internal uses of brk() from having any effect.
2077 // We remember the old value so we can restore it on exec, so that
2078 // child processes will have a reasonable brk value.
2079 VG_(getrlimit)(VKI_RLIMIT_DATA, &VG_(client_rlimit_data));
2080 zero.rlim_max = VG_(client_rlimit_data).rlim_max;
2081 VG_(setrlimit)(VKI_RLIMIT_DATA, &zero);
thughesc37184f2004-09-11 14:16:57 +00002082
2083 // Get the current process stack rlimit.
2084 VG_(getrlimit)(VKI_RLIMIT_STACK, &VG_(client_rlimit_stack));
2085
sewardje2d1e672005-11-12 23:10:48 +00002086 //--------------------------------------------------------------
2087 // Figure out what sort of CPU we're on, and whether it is
2088 // able to run V.
2089 VG_(debugLog)(1, "main", "Get hardware capabilities ...\n");
2090 { VexArch vex_arch;
2091 VexArchInfo vex_archinfo;
2092 Bool ok = VG_(machine_get_hwcaps)();
2093 if (!ok) {
2094 VG_(printf)("\n");
2095 VG_(printf)("valgrind: fatal error: unsupported CPU.\n");
2096 VG_(printf)(" Supported CPUs are:\n");
2097 VG_(printf)(" * x86 (practically any; Pentium-I or above), "
2098 "AMD Athlon or above)\n");
2099 VG_(printf)(" * AMD Athlon64/Opteron\n");
2100 VG_(printf)(" * PowerPC (most; ppc405 and above)\n");
2101 VG_(printf)("\n");
2102 VG_(exit)(1);
2103 }
2104 VG_(machine_get_VexArchInfo)( &vex_arch, &vex_archinfo );
sewardje3121f32006-01-27 21:23:23 +00002105 VG_(debugLog)(
2106 1, "main", "... arch = %s, hwcaps = %s\n",
2107 LibVEX_ppVexArch ( vex_arch ),
2108 LibVEX_ppVexHwCaps ( vex_arch, vex_archinfo.hwcaps )
2109 );
sewardje2d1e672005-11-12 23:10:48 +00002110 }
2111
sewardj45f4e7c2005-09-27 19:20:21 +00002112 //============================================================
2113 // Command line argument handling order:
2114 // * If --help/--help-debug are present, show usage message
2115 // (including the tool-specific usage)
2116 // * (If no --tool option given, default to Memcheck)
2117 // * Then, if client is missing, abort with error msg
2118 // * Then, if any cmdline args are bad, abort with error msg
2119 //============================================================
2120
2121 //--------------------------------------------------------------
2122 // Split up argv into: C args, V args, V extra args, and exename.
2123 // p: dynamic memory allocation
2124 //--------------------------------------------------------------
2125 VG_(debugLog)(1, "main", "Split up command line\n");
2126 VG_(split_up_argv)( argc, argv );
2127 if (0) {
2128 for (i = 0; i < VG_(args_for_valgrind).used; i++)
2129 VG_(printf)("varg %s\n", VG_(args_for_valgrind).strs[i]);
2130 VG_(printf)(" exe %s\n", VG_(args_the_exename));
2131 for (i = 0; i < VG_(args_for_client).used; i++)
2132 VG_(printf)("carg %s\n", VG_(args_for_client).strs[i]);
nethercote71980f02004-01-24 18:18:54 +00002133 }
2134
2135 //--------------------------------------------------------------
sewardj45f4e7c2005-09-27 19:20:21 +00002136 // Extract tool name and whether help has been requested.
2137 // Note we can't print the help message yet, even if requested,
2138 // because the tool has not been initialised.
2139 // p: split_up_argv [for VG_(args_for_valgrind)]
nethercote71980f02004-01-24 18:18:54 +00002140 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002141 VG_(debugLog)(1, "main", "Preprocess command line opts\n");
sewardj45f4e7c2005-09-27 19:20:21 +00002142 get_helprequest_and_toolname(&need_help, &toolname);
nethercote71980f02004-01-24 18:18:54 +00002143
sewardj45f4e7c2005-09-27 19:20:21 +00002144 // Set default vex control params
2145 LibVEX_default_VexControl(& VG_(clo_vex_control));
nethercote71980f02004-01-24 18:18:54 +00002146
2147 //--------------------------------------------------------------
2148 // Load client executable, finding in $PATH if necessary
sewardj45f4e7c2005-09-27 19:20:21 +00002149 // p: get_helprequest_and_toolname() [for 'exec', 'need_help']
nethercote71980f02004-01-24 18:18:54 +00002150 // p: layout_remaining_space [so there's space]
2151 //--------------------------------------------------------------
sewardj45f4e7c2005-09-27 19:20:21 +00002152 if (!need_help) {
2153 VG_(debugLog)(1, "main", "Loading client\n");
nethercote71980f02004-01-24 18:18:54 +00002154
sewardj45f4e7c2005-09-27 19:20:21 +00002155 if (VG_(args_the_exename) == NULL)
2156 missing_prog();
2157
sewardj13247ca2005-12-30 22:52:20 +00002158 load_client(&info, &initial_client_IP, &initial_client_TOC);
sewardj45f4e7c2005-09-27 19:20:21 +00002159 }
nethercote71980f02004-01-24 18:18:54 +00002160
2161 //--------------------------------------------------------------
2162 // Set up client's environment
sewardj45f4e7c2005-09-27 19:20:21 +00002163 // p: set-libdir [for VG_(libdir)]
2164 // p: get_helprequest_and_toolname [for toolname]
nethercote71980f02004-01-24 18:18:54 +00002165 //--------------------------------------------------------------
sewardj45f4e7c2005-09-27 19:20:21 +00002166 if (!need_help) {
2167 VG_(debugLog)(1, "main", "Setup client env\n");
2168 env = setup_client_env(envp, toolname);
2169 }
nethercote71980f02004-01-24 18:18:54 +00002170
2171 //--------------------------------------------------------------
nethercote5ee67ca2004-06-22 14:00:09 +00002172 // Setup client stack, eip, and VG_(client_arg[cv])
nethercote71980f02004-01-24 18:18:54 +00002173 // p: load_client() [for 'info']
2174 // p: fix_environment() [for 'env']
2175 //--------------------------------------------------------------
sewardj45f4e7c2005-09-27 19:20:21 +00002176 if (!need_help) {
2177 void* init_sp = argv - 1;
sewardjc8c5c872006-02-09 11:16:18 +00002178 SizeT m1 = 1024 * 1024;
2179 SizeT m16 = 16 * m1;
sewardj45f4e7c2005-09-27 19:20:21 +00002180 VG_(debugLog)(1, "main", "Setup client stack\n");
2181 clstack_max_size = (SizeT)VG_(client_rlimit_stack).rlim_cur;
sewardjc8c5c872006-02-09 11:16:18 +00002182 if (clstack_max_size < m1) clstack_max_size = m1;
2183 if (clstack_max_size > m16) clstack_max_size = m16;
sewardj45f4e7c2005-09-27 19:20:21 +00002184 clstack_max_size = VG_PGROUNDUP(clstack_max_size);
sewardjb5f6f512005-03-10 23:59:00 +00002185
sewardj45f4e7c2005-09-27 19:20:21 +00002186 initial_client_SP
2187 = setup_client_stack( init_sp, env,
2188 &info, &client_auxv,
2189 clstack_top, clstack_max_size );
2190
2191 VG_(free)(env);
2192
2193 VG_(debugLog)(2, "main",
2194 "Client info: "
sewardj13247ca2005-12-30 22:52:20 +00002195 "initial_IP=%p initial_SP=%p initial_TOC=%p brk_base=%p\n",
sewardj45f4e7c2005-09-27 19:20:21 +00002196 (void*)initial_client_IP,
2197 (void*)initial_client_SP,
sewardj13247ca2005-12-30 22:52:20 +00002198 (void*)initial_client_TOC,
sewardj45f4e7c2005-09-27 19:20:21 +00002199 (void*)VG_(brk_base) );
nethercotec25c4492004-10-18 11:52:17 +00002200 }
nethercote71980f02004-01-24 18:18:54 +00002201
sewardj45f4e7c2005-09-27 19:20:21 +00002202 //--------------------------------------------------------------
2203 // Setup client data (brk) segment. Initially a 1-page segment
2204 // which abuts a shrinkable reservation.
2205 // p: load_client() [for 'info' and hence VG_(brk_base)]
2206 //--------------------------------------------------------------
2207 if (!need_help) {
2208 SizeT m1 = 1024 * 1024;
2209 SizeT m8 = 8 * m1;
2210 SizeT dseg_max_size = (SizeT)VG_(client_rlimit_data).rlim_cur;
2211 VG_(debugLog)(1, "main", "Setup client data (brk) segment\n");
2212 if (dseg_max_size < m1) dseg_max_size = m1;
2213 if (dseg_max_size > m8) dseg_max_size = m8;
2214 dseg_max_size = VG_PGROUNDUP(dseg_max_size);
2215
2216 setup_client_dataseg( dseg_max_size );
2217 }
nethercote71980f02004-01-24 18:18:54 +00002218
2219 //==============================================================
sewardj45f4e7c2005-09-27 19:20:21 +00002220 //
2221 // Finished loading/setting up the client address space.
2222 //
nethercote71980f02004-01-24 18:18:54 +00002223 //==============================================================
2224
2225 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002226 // setup file descriptors
2227 // p: n/a
2228 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002229 VG_(debugLog)(1, "main", "Setup file descriptors\n");
nethercote71980f02004-01-24 18:18:54 +00002230 setup_file_descriptors();
2231
2232 //--------------------------------------------------------------
sewardj45f4e7c2005-09-27 19:20:21 +00002233 // create the fake /proc/<pid>/cmdline file and then unlink it,
2234 // but hold onto the fd, so we can hand it out to the client
2235 // when it tries to open /proc/<pid>/cmdline for itself.
2236 // p: setup file descriptors
nethercotec314eba2004-07-15 12:59:41 +00002237 //--------------------------------------------------------------
sewardj45f4e7c2005-09-27 19:20:21 +00002238 if (!need_help) {
2239 HChar buf[50], buf2[50+64];
2240 HChar nul[1];
2241 Int fd, r;
2242 HChar* exename;
nethercotec314eba2004-07-15 12:59:41 +00002243
sewardj45f4e7c2005-09-27 19:20:21 +00002244 VG_(debugLog)(1, "main", "Create fake /proc/<pid>/cmdline\n");
2245
2246 VG_(sprintf)(buf, "proc_%d_cmdline", VG_(getpid)());
2247 fd = VG_(mkstemp)( buf, buf2 );
2248 if (fd == -1)
2249 config_error("Can't create client cmdline file in /tmp.");
2250
2251 nul[0] = 0;
2252 exename = VG_(args_the_exename) ? VG_(args_the_exename)
2253 : "unknown_exename";
2254
2255 VG_(write)(fd, VG_(args_the_exename),
2256 VG_(strlen)( VG_(args_the_exename) ));
2257 VG_(write)(fd, nul, 1);
2258
2259 for (i = 0; i < VG_(args_for_client).used; i++) {
2260 VG_(write)(fd, VG_(args_for_client).strs[i],
2261 VG_(strlen)( VG_(args_for_client).strs[i] ));
2262 VG_(write)(fd, nul, 1);
2263 }
2264
2265 /* Don't bother to seek the file back to the start; instead do
2266 it every time a copy of it is given out (by PRE(sys_open)).
2267 That is probably more robust across fork() etc. */
2268
2269 /* Now delete it, but hang on to the fd. */
2270 r = VG_(unlink)( buf2 );
2271 if (r)
2272 config_error("Can't delete client cmdline file in /tmp.");
2273
2274 VG_(cl_cmdline_fd) = fd;
2275 }
nethercotec314eba2004-07-15 12:59:41 +00002276
2277 //--------------------------------------------------------------
sewardj45f4e7c2005-09-27 19:20:21 +00002278 // Init tool part 1: pre_clo_init
nethercotec314eba2004-07-15 12:59:41 +00002279 // p: setup_client_stack() [for 'VG_(client_arg[cv]']
nethercotec314eba2004-07-15 12:59:41 +00002280 // p: setup_file_descriptors() [for 'VG_(fd_xxx_limit)']
nethercote71980f02004-01-24 18:18:54 +00002281 //--------------------------------------------------------------
njn64c83242005-06-21 01:54:38 +00002282 {
2283 Char* s;
2284 Bool ok;
sewardj45f4e7c2005-09-27 19:20:21 +00002285 VG_(debugLog)(1, "main", "Initialise the tool part 1 (pre_clo_init)\n");
2286 (VG_(tool_info).tl_pre_clo_init)();
2287 ok = VG_(sanity_check_needs)( &s );
njn64c83242005-06-21 01:54:38 +00002288 if (!ok) {
2289 VG_(tool_panic)(s);
2290 }
2291 }
nethercote71980f02004-01-24 18:18:54 +00002292
sewardj45f4e7c2005-09-27 19:20:21 +00002293 //--------------------------------------------------------------
nethercotef4928da2004-06-15 10:54:40 +00002294 // If --tool and --help/--help-debug was given, now give the core+tool
2295 // help message
sewardj45f4e7c2005-09-27 19:20:21 +00002296 // p: get_helprequest_and_toolname() [for 'need_help']
2297 // p: tl_pre_clo_init [for 'VG_(tdict).usage']
2298 //--------------------------------------------------------------
2299 VG_(debugLog)(1, "main", "Print help and quit, if requested\n");
nethercotef4928da2004-06-15 10:54:40 +00002300 if (need_help) {
sewardj45f4e7c2005-09-27 19:20:21 +00002301 usage_NORETURN(/*--help-debug?*/2 == need_help);
nethercotef4928da2004-06-15 10:54:40 +00002302 }
nethercotec314eba2004-07-15 12:59:41 +00002303
sewardj45f4e7c2005-09-27 19:20:21 +00002304 //--------------------------------------------------------------
2305 // Process command line options to Valgrind + tool
2306 // p: setup_client_stack() [for 'VG_(client_arg[cv]']
2307 // p: setup_file_descriptors() [for 'VG_(fd_xxx_limit)']
2308 //--------------------------------------------------------------
2309 VG_(debugLog)(1, "main", "Process Valgrind's command line options, "
sewardja48a4932005-09-29 11:09:56 +00002310 "setup logging\n");
sewardj45f4e7c2005-09-27 19:20:21 +00002311 logging_to_fd = process_cmd_line_options(client_auxv, toolname);
2312
2313 //--------------------------------------------------------------
sewardj592ae092005-11-08 19:01:44 +00002314 // Zeroise the millisecond counter by doing a first read of it.
2315 // p: none
2316 //--------------------------------------------------------------
2317 (void) VG_(read_millisecond_timer)();
2318
2319 //--------------------------------------------------------------
sewardj45f4e7c2005-09-27 19:20:21 +00002320 // Print the preamble
2321 // p: tl_pre_clo_init [for 'VG_(details).name' and friends]
2322 // p: process_cmd_line_options() [for VG_(clo_verbosity), VG_(clo_xml),
2323 // VG_(clo_log_file_qualifier),
2324 // logging_to_fd]
2325 //--------------------------------------------------------------
2326 VG_(debugLog)(1, "main", "Print the preamble...\n");
2327 print_preamble(logging_to_fd, toolname);
2328 VG_(debugLog)(1, "main", "...finished the preamble\n");
2329
2330 //--------------------------------------------------------------
2331 // Init tool part 2: post_clo_init
2332 // p: setup_client_stack() [for 'VG_(client_arg[cv]']
2333 // p: setup_file_descriptors() [for 'VG_(fd_xxx_limit)']
2334 // p: print_preamble() [so any warnings printed in post_clo_init
2335 // are shown after the preamble]
2336 //--------------------------------------------------------------
2337 VG_(debugLog)(1, "main", "Initialise the tool part 2 (post_clo_init)\n");
njn51d827b2005-05-09 01:02:08 +00002338 VG_TDICT_CALL(tool_post_clo_init);
nethercotef4928da2004-06-15 10:54:40 +00002339
2340 //--------------------------------------------------------------
sewardj45f4e7c2005-09-27 19:20:21 +00002341 // Initialise translation table and translation cache
2342 // p: aspacem [??]
2343 // p: tl_pre_clo_init [for 'VG_(details).avg_translation_sizeB']
nethercote71980f02004-01-24 18:18:54 +00002344 //--------------------------------------------------------------
sewardj45f4e7c2005-09-27 19:20:21 +00002345 VG_(debugLog)(1, "main", "Initialise TT/TC\n");
2346 VG_(init_tt_tc)();
sewardjb5f6f512005-03-10 23:59:00 +00002347
sewardj45f4e7c2005-09-27 19:20:21 +00002348 //--------------------------------------------------------------
2349 // Initialise the redirect table.
2350 // p: init_tt_tc [so it can call VG_(search_transtab) safely]
2351 // p: aspacem [so can change ownership of sysinfo pages]
2352 //--------------------------------------------------------------
2353 VG_(debugLog)(1, "main", "Initialise redirects\n");
sewardj0ec07f32006-01-12 12:32:32 +00002354 VG_(redir_initialise)();
nethercote71980f02004-01-24 18:18:54 +00002355
2356 //--------------------------------------------------------------
2357 // Allow GDB attach
2358 // p: process_cmd_line_options() [for VG_(clo_wait_for_gdb)]
2359 //--------------------------------------------------------------
2360 /* Hook to delay things long enough so we can get the pid and
2361 attach GDB in another shell. */
2362 if (VG_(clo_wait_for_gdb)) {
sewardj8211a572005-06-23 21:37:47 +00002363 Long q, iters;
sewardj1fbc1a52005-04-25 02:05:54 +00002364 VG_(debugLog)(1, "main", "Wait for GDB\n");
sewardj93ab8572005-02-06 14:10:40 +00002365 VG_(printf)("pid=%d, entering delay loop\n", VG_(getpid)());
2366 /* jrs 20050206: I don't understand why this works on x86. On
2367 amd64 the obvious analogues (jump *$rip or jump *$rcx) don't
2368 work. */
2369 /* do "jump *$eip" to skip this in gdb (x86) */
2370 //VG_(do_syscall0)(__NR_pause);
sewardj8211a572005-06-23 21:37:47 +00002371
2372# if defined(VGP_x86_linux)
2373 iters = 5;
sewardj2c48c7b2005-11-29 13:05:56 +00002374# elif defined(VGP_amd64_linux) || defined(VGP_ppc64_linux)
sewardj8211a572005-06-23 21:37:47 +00002375 iters = 10;
2376# elif defined(VGP_ppc32_linux)
sewardjd714d2e2005-07-08 18:24:04 +00002377 iters = 5;
sewardj8211a572005-06-23 21:37:47 +00002378# else
2379# error "Unknown plat"
2380# endif
2381
2382 iters *= 1000*1000*1000;
2383 for (q = 0; q < iters; q++)
2384 ;
nethercote71980f02004-01-24 18:18:54 +00002385 }
2386
sewardjb5d320c2005-03-13 18:57:15 +00002387 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002388 // Search for file descriptors that are inherited from our parent
2389 // p: process_cmd_line_options [for VG_(clo_track_fds)]
2390 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002391 if (VG_(clo_track_fds)) {
2392 VG_(debugLog)(1, "main", "Init preopened fds\n");
nethercote71980f02004-01-24 18:18:54 +00002393 VG_(init_preopened_fds)();
sewardj1fbc1a52005-04-25 02:05:54 +00002394 }
nethercote71980f02004-01-24 18:18:54 +00002395
2396 //--------------------------------------------------------------
sewardj45f4e7c2005-09-27 19:20:21 +00002397 // Load debug info for the existing segments.
2398 // p: setup_code_redirect_table [so that redirs can be recorded]
2399 // p: mallocfree
2400 // p: probably: setup fds and process CLOs, so that logging works
2401 //--------------------------------------------------------------
2402 VG_(debugLog)(1, "main", "Load initial debug info\n");
2403 { Addr* seg_starts;
2404 Int n_seg_starts;
2405
2406 seg_starts = get_seg_starts( &n_seg_starts );
2407 vg_assert(seg_starts && n_seg_starts > 0);
2408
sewardjf72cced2005-11-08 00:45:47 +00002409 /* show them all to the debug info reader. allow_SkFileV has to
2410 be True here so that we read info from the valgrind executable
2411 itself. */
sewardj45f4e7c2005-09-27 19:20:21 +00002412 for (i = 0; i < n_seg_starts; i++)
sewardjf72cced2005-11-08 00:45:47 +00002413 VG_(di_notify_mmap)( seg_starts[i], True/*allow_SkFileV*/ );
sewardj45f4e7c2005-09-27 19:20:21 +00002414
2415 VG_(free)( seg_starts );
2416 }
2417
2418 //--------------------------------------------------------------
2419 // Tell aspacem of ownership change of the asm helpers, so that
2420 // m_translate allows them to be translated. However, only do this
2421 // after the initial debug info read, since making a hole in the
2422 // address range for the stage2 binary confuses the debug info reader.
2423 // p: aspacem
2424 //--------------------------------------------------------------
2425 { Bool change_ownership_v_c_OK;
sewardj1a85f4f2006-01-12 21:15:35 +00002426 Addr co_start = VG_PGROUNDDN( (Addr)&VG_(trampoline_stuff_start) );
2427 Addr co_endPlus = VG_PGROUNDUP( (Addr)&VG_(trampoline_stuff_end) );
sewardj45f4e7c2005-09-27 19:20:21 +00002428 VG_(debugLog)(1,"redir",
2429 "transfer ownership V -> C of 0x%llx .. 0x%llx\n",
2430 (ULong)co_start, (ULong)co_endPlus-1 );
2431
2432 change_ownership_v_c_OK
2433 = VG_(am_change_ownership_v_to_c)( co_start, co_endPlus - co_start );
2434 vg_assert(change_ownership_v_c_OK);
2435 }
2436
2437 //--------------------------------------------------------------
2438 // Tell the tool about the initial client memory permissions
2439 // p: aspacem
2440 // p: mallocfree
2441 // p: setup_client_stack
2442 // p: setup_client_dataseg
2443 //--------------------------------------------------------------
2444 VG_(debugLog)(1, "main", "Tell tool about initial permissions\n");
2445 { Addr* seg_starts;
2446 Int n_seg_starts;
2447 NSegment* seg;
2448
2449 seg_starts = get_seg_starts( &n_seg_starts );
2450 vg_assert(seg_starts && n_seg_starts > 0);
2451
2452 /* show interesting ones to the tool */
2453 for (i = 0; i < n_seg_starts; i++) {
2454 seg = VG_(am_find_nsegment)( seg_starts[i] );
2455 vg_assert(seg);
2456 if (seg->kind == SkFileC || seg->kind == SkAnonC) {
2457 VG_(debugLog)(2, "main",
2458 "tell tool about %010lx-%010lx %c%c%c\n",
2459 seg->start, seg->end,
2460 seg->hasR ? 'r' : '-',
2461 seg->hasW ? 'w' : '-',
2462 seg->hasX ? 'x' : '-' );
2463 VG_TRACK( new_mem_startup, seg->start, seg->end+1-seg->start,
2464 seg->hasR, seg->hasW, seg->hasX );
2465 }
2466 }
2467
2468 VG_(free)( seg_starts );
2469
2470 /* Also do the initial stack permissions. */
2471 seg = VG_(am_find_nsegment)( initial_client_SP );
2472 vg_assert(seg);
2473 vg_assert(seg->kind == SkAnonC);
2474 vg_assert(initial_client_SP >= seg->start);
2475 vg_assert(initial_client_SP <= seg->end);
2476
sewardjc6527d62006-02-13 17:54:31 +00002477 /* Stuff below the initial SP is unaddressable. Take into
2478 account any ABI-mandated space below the stack pointer that is
2479 required (VG_STACK_REDZONE_SZB). setup_client_stack() will
2480 have allocated an extra page if a red zone is required, to be on
2481 the safe side. */
sewardj6b3e0d72006-02-13 18:16:41 +00002482 vg_assert(initial_client_SP - VG_STACK_REDZONE_SZB >= seg->start);
sewardjc6527d62006-02-13 17:54:31 +00002483 VG_TRACK( die_mem_stack, seg->start, initial_client_SP
2484 - VG_STACK_REDZONE_SZB - seg->start );
sewardj45f4e7c2005-09-27 19:20:21 +00002485 VG_(debugLog)(2, "main", "mark stack inaccessible %010lx-%010lx\n",
sewardjc6527d62006-02-13 17:54:31 +00002486 seg->start, initial_client_SP-1 - VG_STACK_REDZONE_SZB);
sewardj45f4e7c2005-09-27 19:20:21 +00002487
2488 /* Also the assembly helpers. */
2489 VG_TRACK( new_mem_startup,
2490 (Addr)&VG_(trampoline_stuff_start),
sewardjc6527d62006-02-13 17:54:31 +00002491 (Addr)&VG_(trampoline_stuff_end)
2492 - (Addr)&VG_(trampoline_stuff_start),
sewardj45f4e7c2005-09-27 19:20:21 +00002493 False, /* readable? */
2494 False, /* writable? */
2495 True /* executable? */ );
2496 }
2497
2498 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002499 // Initialise the scheduler
nethercote71980f02004-01-24 18:18:54 +00002500 // p: setup_file_descriptors() [else VG_(safe_fd)() breaks]
sewardj45f4e7c2005-09-27 19:20:21 +00002501 // p: setup_client_stack
nethercote71980f02004-01-24 18:18:54 +00002502 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002503 VG_(debugLog)(1, "main", "Initialise scheduler\n");
sewardj45f4e7c2005-09-27 19:20:21 +00002504 { NSegment* seg = VG_(am_find_nsegment)( initial_client_SP );
2505 vg_assert(seg);
2506 vg_assert(seg->kind == SkAnonC);
2507 vg_assert(initial_client_SP >= seg->start);
2508 vg_assert(initial_client_SP <= seg->end);
2509 VG_(scheduler_init)( seg->end, clstack_max_size );
2510 }
nethercote71980f02004-01-24 18:18:54 +00002511
2512 //--------------------------------------------------------------
sewardjb5f6f512005-03-10 23:59:00 +00002513 // Initialise the pthread model
2514 // p: ?
sewardj2a99cf62004-11-24 10:44:19 +00002515 // load_client() [for 'client_eip']
2516 // setup_client_stack() [for 'sp_at_startup']
2517 // setup_scheduler() [for the rest of state 1 stuff]
2518 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002519 VG_(debugLog)(1, "main", "Initialise thread 1's state\n");
sewardj13247ca2005-12-30 22:52:20 +00002520 init_thread1state( initial_client_IP,
2521 initial_client_SP,
2522 initial_client_TOC,
sewardj45f4e7c2005-09-27 19:20:21 +00002523 &VG_(threads)[1].arch);
njnea4b28c2004-11-30 16:04:58 +00002524
sewardj2a99cf62004-11-24 10:44:19 +00002525 //--------------------------------------------------------------
sewardj39b88fb2005-03-12 15:16:07 +00002526 // Initialise the pthread model
2527 // p: ?
nethercote71980f02004-01-24 18:18:54 +00002528 //--------------------------------------------------------------
sewardjb5f6f512005-03-10 23:59:00 +00002529 //if (VG_(clo_model_pthreads))
2530 // VG_(pthread_init)();
nethercote71980f02004-01-24 18:18:54 +00002531
2532 //--------------------------------------------------------------
2533 // Initialise the signal handling subsystem
sewardjb5f6f512005-03-10 23:59:00 +00002534 // p: n/a
nethercote71980f02004-01-24 18:18:54 +00002535 //--------------------------------------------------------------
2536 // Nb: temporarily parks the saved blocking-mask in saved_sigmask.
sewardj1fbc1a52005-04-25 02:05:54 +00002537 VG_(debugLog)(1, "main", "Initialise signal management\n");
nethercote71980f02004-01-24 18:18:54 +00002538 VG_(sigstartup_actions)();
2539
2540 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002541 // Read suppression file
2542 // p: process_cmd_line_options() [for VG_(clo_suppressions)]
2543 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002544 if (VG_(needs).core_errors || VG_(needs).tool_errors) {
2545 VG_(debugLog)(1, "main", "Load suppressions\n");
nethercote71980f02004-01-24 18:18:54 +00002546 VG_(load_suppressions)();
sewardj1fbc1a52005-04-25 02:05:54 +00002547 }
nethercote71980f02004-01-24 18:18:54 +00002548
2549 //--------------------------------------------------------------
rjwalsh0140af52005-06-04 20:42:33 +00002550 // register client stack
2551 //--------------------------------------------------------------
njn945ed2e2005-06-24 03:28:30 +00002552 VG_(clstk_id) = VG_(register_stack)(VG_(clstk_base), VG_(clstk_end));
rjwalsh0140af52005-06-04 20:42:33 +00002553
2554 //--------------------------------------------------------------
sewardj45f4e7c2005-09-27 19:20:21 +00002555 // Show the address space state so far
2556 //--------------------------------------------------------------
2557 VG_(debugLog)(1, "main", "\n");
2558 VG_(debugLog)(1, "main", "\n");
2559 VG_(am_show_nsegments)(1,"Memory layout at client startup");
2560 VG_(debugLog)(1, "main", "\n");
2561 VG_(debugLog)(1, "main", "\n");
2562
2563 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002564 // Run!
2565 //--------------------------------------------------------------
sewardj71bc3cb2005-05-19 00:25:45 +00002566 if (VG_(clo_xml)) {
sewardj68cde6f2005-07-19 12:17:51 +00002567 HChar buf[50];
sewardj592ae092005-11-08 19:01:44 +00002568 VG_(elapsed_wallclock_time)(buf);
sewardj753673f2005-08-09 22:03:08 +00002569 VG_(message)(Vg_UserMsg, "<status>\n"
2570 " <state>RUNNING</state>\n"
2571 " <time>%t</time>\n"
2572 "</status>",
2573 buf);
sewardj71bc3cb2005-05-19 00:25:45 +00002574 VG_(message)(Vg_UserMsg, "");
2575 }
2576
sewardj1fbc1a52005-04-25 02:05:54 +00002577 VG_(debugLog)(1, "main", "Running thread 1\n");
sewardj1ae3f3a2005-09-28 10:47:38 +00002578
sewardj1d887112005-05-30 21:44:08 +00002579 /* As a result of the following call, the last thread standing
sewardj1ae3f3a2005-09-28 10:47:38 +00002580 eventually winds up running shutdown_actions_NORETURN
2581 just below. Unfortunately, simply exporting said function
2582 causes m_main to be part of a module cycle, which is pretty
2583 nonsensical. So instead of doing that, the address of said
2584 function is stored in a global variable 'owned' by m_syswrap,
2585 and it uses that function pointer to get back here when it needs
2586 to. */
2587
2588 /* Set continuation address. */
2589 VG_(address_of_m_main_shutdown_actions_NORETURN)
2590 = & shutdown_actions_NORETURN;
2591
2592 /* Run the first thread, eventually ending up at the continuation
2593 address. */
njnaf839f52005-06-23 03:27:57 +00002594 VG_(main_thread_wrapper_NORETURN)(1);
nethercote71980f02004-01-24 18:18:54 +00002595
sewardj1d887112005-05-30 21:44:08 +00002596 /*NOTREACHED*/
2597 vg_assert(0);
sewardjb5f6f512005-03-10 23:59:00 +00002598}
2599
sewardj1ae3f3a2005-09-28 10:47:38 +00002600/* Do everything which needs doing when the last thread exits. */
sewardjb5f6f512005-03-10 23:59:00 +00002601
sewardj1ae3f3a2005-09-28 10:47:38 +00002602static
2603void shutdown_actions_NORETURN( ThreadId tid,
2604 VgSchedReturnCode tids_schedretcode )
sewardjb5f6f512005-03-10 23:59:00 +00002605{
sewardj1d887112005-05-30 21:44:08 +00002606 VG_(debugLog)(1, "main", "entering VG_(shutdown_actions_NORETURN)\n");
2607
2608 vg_assert( VG_(count_living_threads)() == 1 );
sewardjb5f6f512005-03-10 23:59:00 +00002609 vg_assert(VG_(is_running_thread)(tid));
2610
2611 // Wait for all other threads to exit.
njn7b85dd52005-06-12 17:26:29 +00002612 VG_(reap_threads)(tid);
sewardjb5f6f512005-03-10 23:59:00 +00002613
2614 VG_(clo_model_pthreads) = False;
2615
2616 // Clean the client up before the final report
njn9cb54ac2005-06-12 04:19:17 +00002617 final_tidyup(tid);
sewardjb5f6f512005-03-10 23:59:00 +00002618
2619 // OK, done
2620 VG_(exit_thread)(tid);
2621
2622 /* should be no threads left */
2623 vg_assert(VG_(count_living_threads)() == 0);
2624
2625 VG_(threads)[tid].status = VgTs_Empty;
nethercote71980f02004-01-24 18:18:54 +00002626 //--------------------------------------------------------------
2627 // Finalisation: cleanup, messages, etc. Order no so important, only
2628 // affects what order the messages come.
2629 //--------------------------------------------------------------
2630 if (VG_(clo_verbosity) > 0)
2631 VG_(message)(Vg_UserMsg, "");
2632
sewardj71bc3cb2005-05-19 00:25:45 +00002633 if (VG_(clo_xml)) {
sewardj68cde6f2005-07-19 12:17:51 +00002634 HChar buf[50];
sewardj9f297ca2005-05-20 02:29:52 +00002635 if (VG_(needs).core_errors || VG_(needs).tool_errors) {
2636 VG_(show_error_counts_as_XML)();
2637 VG_(message)(Vg_UserMsg, "");
2638 }
sewardj592ae092005-11-08 19:01:44 +00002639 VG_(elapsed_wallclock_time)(buf);
sewardj753673f2005-08-09 22:03:08 +00002640 VG_(message)(Vg_UserMsg, "<status>\n"
2641 " <state>FINISHED</state>\n"
2642 " <time>%t</time>\n"
2643 "</status>",
2644 buf);
sewardj71bc3cb2005-05-19 00:25:45 +00002645 VG_(message)(Vg_UserMsg, "");
2646 }
2647
nethercote71980f02004-01-24 18:18:54 +00002648 /* Print out file descriptor summary and stats. */
2649 if (VG_(clo_track_fds))
nethercote3a42fb82004-08-03 18:08:50 +00002650 VG_(show_open_fds)();
nethercote71980f02004-01-24 18:18:54 +00002651
njn95ec8702004-11-22 16:46:13 +00002652 if (VG_(needs).core_errors || VG_(needs).tool_errors)
nethercote71980f02004-01-24 18:18:54 +00002653 VG_(show_all_errors)();
2654
njn51d827b2005-05-09 01:02:08 +00002655 VG_TDICT_CALL(tool_fini, 0/*exitcode*/);
nethercote71980f02004-01-24 18:18:54 +00002656
sewardj71bc3cb2005-05-19 00:25:45 +00002657 if (VG_(clo_xml)) {
2658 VG_(message)(Vg_UserMsg, "");
2659 VG_(message)(Vg_UserMsg, "</valgrindoutput>");
2660 VG_(message)(Vg_UserMsg, "");
2661 }
2662
nethercote885dd912004-08-03 23:14:00 +00002663 VG_(sanity_check_general)( True /*include expensive checks*/ );
nethercote71980f02004-01-24 18:18:54 +00002664
2665 if (VG_(clo_verbosity) > 1)
nethercote3a42fb82004-08-03 18:08:50 +00002666 print_all_stats();
nethercote71980f02004-01-24 18:18:54 +00002667
njn2025cf92005-06-26 20:44:48 +00002668 if (VG_(clo_profile_flags) > 0) {
2669 #define N_MAX 100
2670 BBProfEntry tops[N_MAX];
2671 ULong score_total = VG_(get_BB_profile) (tops, N_MAX);
2672 show_BB_profile(tops, N_MAX, score_total);
2673 }
sewardjfa8ec112005-01-19 11:55:34 +00002674
sewardj8b635a42004-11-22 19:01:47 +00002675 /* Print Vex storage stats */
sewardjbf426512005-01-17 18:35:30 +00002676 if (0)
2677 LibVEX_ShowAllocStats();
sewardj1d887112005-05-30 21:44:08 +00002678
njn8aa35852005-06-10 22:59:56 +00002679 /* Ok, finally exit in the os-specific way, according to the scheduler's
2680 return code. In short, if the (last) thread exited by calling
2681 sys_exit, do likewise; if the (last) thread stopped due to a fatal
2682 signal, terminate the entire system with that same fatal signal. */
2683 VG_(debugLog)(1, "core_os",
njn7b85dd52005-06-12 17:26:29 +00002684 "VG_(terminate_NORETURN)(tid=%lld)\n", (ULong)tid);
njn8aa35852005-06-10 22:59:56 +00002685
2686 vg_assert(VG_(count_living_threads)() == 0);
2687
2688 switch (tids_schedretcode) {
2689 case VgSrc_ExitSyscall: /* the normal way out */
sewardjb9779082006-05-12 23:50:15 +00002690 /* Change the application return code to user's return code,
2691 if an error was found */
2692 if (VG_(clo_error_exitcode) > 0
2693 && VG_(get_n_errs_found)() > 0) {
2694 VG_(exit)( VG_(clo_error_exitcode) );
2695 } else {
2696 /* otherwise, return the client's exit code, in the normal
2697 way. */
2698 VG_(exit)( VG_(threads)[tid].os_state.exitcode );
2699 }
njn8aa35852005-06-10 22:59:56 +00002700 /* NOT ALIVE HERE! */
2701 VG_(core_panic)("entered the afterlife in main() -- ExitSyscall");
2702 break; /* what the hell :) */
2703
2704 case VgSrc_FatalSig:
2705 /* We were killed by a fatal signal, so replicate the effect */
2706 vg_assert(VG_(threads)[tid].os_state.fatalsig != 0);
2707 VG_(kill_self)(VG_(threads)[tid].os_state.fatalsig);
2708 VG_(core_panic)("main(): signal was supposed to be fatal");
2709 break;
2710
2711 default:
2712 VG_(core_panic)("main(): unexpected scheduler return code");
2713 }
njne96be672005-05-08 19:08:54 +00002714}
sewardj8b635a42004-11-22 19:01:47 +00002715
sewardj1ae3f3a2005-09-28 10:47:38 +00002716/* -------------------- */
2717
2718/* Final clean-up before terminating the process.
2719 Clean up the client by calling __libc_freeres() (if requested)
2720 This is Linux-specific?
2721*/
2722static void final_tidyup(ThreadId tid)
2723{
sewardjcf951812006-01-17 02:22:21 +00002724# if defined(VGP_ppc64_linux)
2725 Addr r2;
2726# endif
sewardj0ec07f32006-01-12 12:32:32 +00002727 Addr __libc_freeres_wrapper = VG_(client___libc_freeres_wrapper);
sewardj1ae3f3a2005-09-28 10:47:38 +00002728
2729 vg_assert(VG_(is_running_thread)(tid));
2730
2731 if ( !VG_(needs).libc_freeres ||
2732 !VG_(clo_run_libc_freeres) ||
sewardj0ec07f32006-01-12 12:32:32 +00002733 0 == __libc_freeres_wrapper )
sewardj1ae3f3a2005-09-28 10:47:38 +00002734 return; /* can't/won't do it */
2735
sewardjcf951812006-01-17 02:22:21 +00002736# if defined(VGP_ppc64_linux)
2737 r2 = VG_(get_tocptr)( __libc_freeres_wrapper );
2738 if (r2 == 0) {
2739 VG_(message)(Vg_UserMsg,
2740 "Caught __NR_exit, but can't run __libc_freeres()");
2741 VG_(message)(Vg_UserMsg,
2742 " since cannot establish TOC pointer for it.");
2743 return;
2744 }
2745# endif
2746
sewardj1ae3f3a2005-09-28 10:47:38 +00002747 if (VG_(clo_verbosity) > 2 ||
2748 VG_(clo_trace_syscalls) ||
2749 VG_(clo_trace_sched))
2750 VG_(message)(Vg_DebugMsg,
2751 "Caught __NR_exit; running __libc_freeres()");
2752
sewardj0ec07f32006-01-12 12:32:32 +00002753 /* set thread context to point to libc_freeres_wrapper */
sewardj1a85f4f2006-01-12 21:15:35 +00002754 /* ppc64-linux note: __libc_freeres_wrapper gives us the real
2755 function entry point, not a fn descriptor, so can use it
2756 directly. However, we need to set R2 (the toc pointer)
2757 appropriately. */
sewardj1ae3f3a2005-09-28 10:47:38 +00002758 VG_(set_IP)(tid, __libc_freeres_wrapper);
sewardjcf951812006-01-17 02:22:21 +00002759# if defined(VGP_ppc64_linux)
2760 VG_(threads)[tid].arch.vex.guest_GPR2 = r2;
2761# endif
sewardj1ae3f3a2005-09-28 10:47:38 +00002762
2763 /* Block all blockable signals by copying the real block state into
2764 the thread's block state*/
2765 VG_(sigprocmask)(VKI_SIG_BLOCK, NULL, &VG_(threads)[tid].sig_mask);
2766 VG_(threads)[tid].tmp_sig_mask = VG_(threads)[tid].sig_mask;
2767
2768 /* and restore handlers to default */
2769 VG_(set_default_handler)(VKI_SIGSEGV);
2770 VG_(set_default_handler)(VKI_SIGBUS);
2771 VG_(set_default_handler)(VKI_SIGILL);
2772 VG_(set_default_handler)(VKI_SIGFPE);
2773
2774 // We were exiting, so assert that...
2775 vg_assert(VG_(is_exiting)(tid));
2776 // ...but now we're not again
2777 VG_(threads)[tid].exitreason = VgSrc_None;
2778
2779 // run until client thread exits - ideally with LIBC_FREERES_DONE,
2780 // but exit/exitgroup/signal will do
2781 VG_(scheduler)(tid);
2782
2783 vg_assert(VG_(is_exiting)(tid));
2784}
2785
sewardj45f4e7c2005-09-27 19:20:21 +00002786
2787/*====================================================================*/
2788/*=== Getting to main() alive ===*/
2789/*====================================================================*/
2790
2791/* If linking of the final executables is done with glibc present,
2792 then Valgrind starts at main() above as usual, and all of the
2793 following code is irrelevant.
2794
2795 However, this is not the intended mode of use. The plan is to
2796 avoid linking against glibc, by giving gcc the flags
2797 -nodefaultlibs -lgcc -nostartfiles at startup.
2798
2799 From this derive two requirements:
2800
2801 1. gcc may emit calls to memcpy and memset to deal with structure
2802 assignments etc. Since we have chosen to ignore all the
2803 "normal" supporting libraries, we have to provide our own
2804 implementations of them. No problem.
2805
2806 2. We have to provide a symbol "_start", to which the kernel
2807 hands control at startup. Hence the code below.
2808*/
2809
2810/* ---------------- Requirement 1 ---------------- */
2811
2812void* memcpy(void *dest, const void *src, size_t n);
2813void* memcpy(void *dest, const void *src, size_t n) {
2814 return VG_(memcpy)(dest,src,n);
2815}
2816void* memset(void *s, int c, size_t n);
2817void* memset(void *s, int c, size_t n) {
2818 return VG_(memset)(s,c,n);
2819}
2820
2821/* ---------------- Requirement 2 ---------------- */
2822
2823/* Glibc's sysdeps/i386/elf/start.S has the following gem of a
2824 comment, which explains how the stack looks right at process start
2825 (when _start is jumped to). Hence _start passes %esp to
2826 _start_in_C, which extracts argc/argv/envp and starts up
2827 correctly. */
2828
2829/* This is the canonical entry point, usually the first thing in the text
2830 segment. The SVR4/i386 ABI (pages 3-31, 3-32) says that when the entry
2831 point runs, most registers' values are unspecified, except for:
2832
2833 %edx Contains a function pointer to be registered with `atexit'.
2834 This is how the dynamic linker arranges to have DT_FINI
2835 functions called for shared libraries that have been loaded
2836 before this code runs.
2837
2838 %esp The stack contains the arguments and environment:
2839 0(%esp) argc
2840 4(%esp) argv[0]
2841 ...
2842 (4*argc)(%esp) NULL
2843 (4*(argc+1))(%esp) envp[0]
2844 ...
2845 NULL
2846*/
2847
2848/* The kernel hands control to _start, which extracts the initial
sewardja48a4932005-09-29 11:09:56 +00002849 stack pointer and calls onwards to _start_in_C. This also switches
2850 the new stack. */
sewardj45f4e7c2005-09-27 19:20:21 +00002851#if defined(VGP_x86_linux)
2852asm("\n"
sewardjd9fc3822005-11-18 23:50:43 +00002853 ".text\n"
sewardj45f4e7c2005-09-27 19:20:21 +00002854 "\t.globl _start\n"
2855 "\t.type _start,@function\n"
2856 "_start:\n"
2857 /* set up the new stack in %eax */
sewardjfdf91b42005-09-28 00:53:09 +00002858 "\tmovl $vgPlain_interim_stack, %eax\n"
sewardj45f4e7c2005-09-27 19:20:21 +00002859 "\taddl $"VG_STRINGIFY(VG_STACK_GUARD_SZB)", %eax\n"
2860 "\taddl $"VG_STRINGIFY(VG_STACK_ACTIVE_SZB)", %eax\n"
2861 "\tsubl $16, %eax\n"
2862 "\tandl $~15, %eax\n"
2863 /* install it, and collect the original one */
2864 "\txchgl %eax, %esp\n"
2865 /* call _start_in_C, passing it the startup %esp */
2866 "\tpushl %eax\n"
2867 "\tcall _start_in_C\n"
2868 "\thlt\n"
sewardj2fedc642005-11-19 02:02:57 +00002869 ".previous\n"
sewardj45f4e7c2005-09-27 19:20:21 +00002870);
2871#elif defined(VGP_amd64_linux)
2872asm("\n"
sewardjd9fc3822005-11-18 23:50:43 +00002873 ".text\n"
sewardj45f4e7c2005-09-27 19:20:21 +00002874 "\t.globl _start\n"
2875 "\t.type _start,@function\n"
2876 "_start:\n"
2877 /* set up the new stack in %rdi */
sewardjfdf91b42005-09-28 00:53:09 +00002878 "\tmovq $vgPlain_interim_stack, %rdi\n"
sewardj45f4e7c2005-09-27 19:20:21 +00002879 "\taddq $"VG_STRINGIFY(VG_STACK_GUARD_SZB)", %rdi\n"
2880 "\taddq $"VG_STRINGIFY(VG_STACK_ACTIVE_SZB)", %rdi\n"
2881 "\tandq $~15, %rdi\n"
2882 /* install it, and collect the original one */
2883 "\txchgq %rdi, %rsp\n"
2884 /* call _start_in_C, passing it the startup %rsp */
2885 "\tcall _start_in_C\n"
2886 "\thlt\n"
sewardj2fedc642005-11-19 02:02:57 +00002887 ".previous\n"
sewardj45f4e7c2005-09-27 19:20:21 +00002888);
sewardja48a4932005-09-29 11:09:56 +00002889#elif defined(VGP_ppc32_linux)
2890asm("\n"
sewardjd9fc3822005-11-18 23:50:43 +00002891 ".text\n"
sewardja48a4932005-09-29 11:09:56 +00002892 "\t.globl _start\n"
2893 "\t.type _start,@function\n"
2894 "_start:\n"
2895 /* set up the new stack in r16 */
2896 "\tlis 16,vgPlain_interim_stack@ha\n"
2897 "\tla 16,vgPlain_interim_stack@l(16)\n"
2898 "\tlis 17,("VG_STRINGIFY(VG_STACK_GUARD_SZB)" >> 16)\n"
2899 "\tori 17,17,("VG_STRINGIFY(VG_STACK_GUARD_SZB)" & 0xFFFF)\n"
2900 "\tlis 18,("VG_STRINGIFY(VG_STACK_ACTIVE_SZB)" >> 16)\n"
2901 "\tori 18,18,("VG_STRINGIFY(VG_STACK_ACTIVE_SZB)" & 0xFFFF)\n"
2902 "\tadd 16,17,16\n"
2903 "\tadd 16,18,16\n"
2904 "\trlwinm 16,16,0,0,27\n"
2905 /* now r16 = &vgPlain_interim_stack + VG_STACK_GUARD_SZB +
2906 VG_STACK_ACTIVE_SZB rounded down to the nearest 16-byte
2907 boundary. And r1 is the original SP. Set the SP to r16 and
2908 call _start_in_C, passing it the initial SP. */
2909 "\tmr 3,1\n"
2910 "\tmr 1,16\n"
2911 "\tbl _start_in_C\n"
2912 "\ttrap\n"
sewardj2fedc642005-11-19 02:02:57 +00002913 ".previous\n"
sewardja48a4932005-09-29 11:09:56 +00002914);
sewardj2c48c7b2005-11-29 13:05:56 +00002915#elif defined(VGP_ppc64_linux)
2916asm("\n"
cerion21082042005-12-06 19:07:08 +00002917 /* PPC64 ELF ABI says '_start' points to a function descriptor.
2918 So we must have one, and that is what goes into the .opd section. */
cerion297c88f2005-12-22 15:53:12 +00002919 "\t.align 2\n"
cerion21082042005-12-06 19:07:08 +00002920 "\t.global _start\n"
2921 "\t.section \".opd\",\"aw\"\n"
2922 "\t.align 3\n"
sewardj2c48c7b2005-11-29 13:05:56 +00002923 "_start:\n"
cerion21082042005-12-06 19:07:08 +00002924 "\t.quad ._start,.TOC.@tocbase,0\n"
2925 "\t.previous\n"
2926 "\t.type ._start,@function\n"
2927 "\t.global ._start\n"
2928 "._start:\n"
sewardj2c48c7b2005-11-29 13:05:56 +00002929 /* set up the new stack in r16 */
2930 "\tlis 16, vgPlain_interim_stack@highest\n"
2931 "\tori 16,16,vgPlain_interim_stack@higher\n"
2932 "\tsldi 16,16,32\n"
2933 "\toris 16,16,vgPlain_interim_stack@h\n"
2934 "\tori 16,16,vgPlain_interim_stack@l\n"
2935 "\txor 17,17,17\n"
2936 "\tlis 17,("VG_STRINGIFY(VG_STACK_GUARD_SZB)" >> 16)\n"
2937 "\tori 17,17,("VG_STRINGIFY(VG_STACK_GUARD_SZB)" & 0xFFFF)\n"
2938 "\txor 18,18,18\n"
2939 "\tlis 18,("VG_STRINGIFY(VG_STACK_ACTIVE_SZB)" >> 16)\n"
2940 "\tori 18,18,("VG_STRINGIFY(VG_STACK_ACTIVE_SZB)" & 0xFFFF)\n"
2941 "\tadd 16,17,16\n"
2942 "\tadd 16,18,16\n"
2943 "\trldicr 16,16,0,59\n"
2944 /* now r16 = &vgPlain_interim_stack + VG_STACK_GUARD_SZB +
2945 VG_STACK_ACTIVE_SZB rounded down to the nearest 16-byte
2946 boundary. And r1 is the original SP. Set the SP to r16 and
2947 call _start_in_C, passing it the initial SP. */
2948 "\tmr 3,1\n"
2949 "\tmr 1,16\n"
cerion21082042005-12-06 19:07:08 +00002950 "\tbl ._start_in_C\n"
2951 "\tnop\n"
sewardj2c48c7b2005-11-29 13:05:56 +00002952 "\ttrap\n"
sewardj2c48c7b2005-11-29 13:05:56 +00002953);
sewardj45f4e7c2005-09-27 19:20:21 +00002954#else
2955#error "_start: needs implementation on this platform"
2956#endif
2957
2958/* Avoid compiler warnings: this fn _is_ used, but labelling it
2959 'static' causes gcc to complain it isn't. */
2960void _start_in_C ( UWord* pArgc );
2961void _start_in_C ( UWord* pArgc )
2962{
2963 Int r;
2964 Word argc = pArgc[0];
2965 HChar** argv = (HChar**)&pArgc[1];
2966 HChar** envp = (HChar**)&pArgc[1+argc+1];
sewardjfdf91b42005-09-28 00:53:09 +00002967 sp_at_startup = (Addr)pArgc;
sewardj45f4e7c2005-09-27 19:20:21 +00002968 r = main( (Int)argc, argv, envp );
2969 VG_(exit)(r);
2970}
2971
sewardjde4a1d02002-03-22 01:27:54 +00002972/*--------------------------------------------------------------------*/
njn04e16982005-05-31 00:23:43 +00002973/*--- end ---*/
sewardjde4a1d02002-03-22 01:27:54 +00002974/*--------------------------------------------------------------------*/