blob: 331e8bda64b2cfd95571d420b0fffc1a41b1e0f8 [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"
njn04e16982005-05-31 00:23:43 +000047#include "pub_core_main.h"
njnaf1d7df2005-06-11 01:31:52 +000048#include "pub_core_mallocfree.h"
njn20242342005-05-16 23:31:24 +000049#include "pub_core_options.h"
njn31513b42005-06-01 03:09:59 +000050#include "pub_core_profile.h"
sewardjfdf91b42005-09-28 00:53:09 +000051#include "pub_core_debuginfo.h"
njnd1af0032005-05-29 17:01:48 +000052#include "pub_core_redir.h"
njnc7561b92005-06-19 01:24:32 +000053#include "pub_core_scheduler.h"
njn0c246472005-05-31 01:00:08 +000054#include "pub_core_signals.h"
njn2025cf92005-06-26 20:44:48 +000055#include "pub_core_stacks.h" // For VG_(register_stack)
njnc1b01812005-06-17 22:19:06 +000056#include "pub_core_syswrap.h"
sewardjfdf91b42005-09-28 00:53:09 +000057#include "pub_core_translate.h" // For VG_(translate)
njn43b9a8a2005-05-10 04:37:01 +000058#include "pub_core_tooliface.h"
njna7598f62005-06-18 03:27:58 +000059#include "pub_core_trampoline.h"
njn8bddf582005-05-13 23:40:55 +000060#include "pub_core_transtab.h"
njn08a2e172005-06-21 22:47:54 +000061#include "pub_core_ume.h"
nethercote71980f02004-01-24 18:18:54 +000062
sewardjb5f6f512005-03-10 23:59:00 +000063
thughes74b8de22004-04-22 18:12:31 +000064#ifndef AT_DCACHEBSIZE
65#define AT_DCACHEBSIZE 19
66#endif /* AT_DCACHEBSIZE */
67
68#ifndef AT_ICACHEBSIZE
69#define AT_ICACHEBSIZE 20
70#endif /* AT_ICACHEBSIZE */
71
72#ifndef AT_UCACHEBSIZE
73#define AT_UCACHEBSIZE 21
74#endif /* AT_UCACHEBSIZE */
75
nethercote71980f02004-01-24 18:18:54 +000076#ifndef AT_SYSINFO
77#define AT_SYSINFO 32
78#endif /* AT_SYSINFO */
79
80#ifndef AT_SYSINFO_EHDR
81#define AT_SYSINFO_EHDR 33
82#endif /* AT_SYSINFO_EHDR */
83
84#ifndef AT_SECURE
85#define AT_SECURE 23 /* secure mode boolean */
86#endif /* AT_SECURE */
87
njn14319cc2005-03-13 06:26:22 +000088/* Number of file descriptors that Valgrind tries to reserve for
89 it's own use - just a small constant. */
90#define N_RESERVED_FDS (10)
91
sewardj45f4e7c2005-09-27 19:20:21 +000092
nethercote71980f02004-01-24 18:18:54 +000093/*====================================================================*/
94/*=== Counters, for profiling purposes only ===*/
95/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +000096
nethercote3a42fb82004-08-03 18:08:50 +000097static void print_all_stats ( void )
nethercote71980f02004-01-24 18:18:54 +000098{
nethercote92e7b7f2004-08-07 17:52:25 +000099 VG_(print_tt_tc_stats)();
nethercote844e7122004-08-02 15:27:22 +0000100 VG_(print_scheduler_stats)();
njn9271cbc2005-03-13 05:38:25 +0000101 VG_(print_ExeContext_stats)();
102
nethercote3a42fb82004-08-03 18:08:50 +0000103 // Memory stats
nethercote885dd912004-08-03 23:14:00 +0000104 if (VG_(clo_verbosity) > 2) {
nethercote3a42fb82004-08-03 18:08:50 +0000105 VG_(message)(Vg_DebugMsg, "");
106 VG_(message)(Vg_DebugMsg,
107 "------ Valgrind's internal memory use stats follow ------" );
nethercote885dd912004-08-03 23:14:00 +0000108 VG_(sanity_check_malloc_all)();
njn11adeb22005-07-03 20:22:39 +0000109 VG_(message)(Vg_DebugMsg, "------" );
nethercote3a42fb82004-08-03 18:08:50 +0000110 VG_(print_all_arena_stats)();
nethercote885dd912004-08-03 23:14:00 +0000111 VG_(message)(Vg_DebugMsg, "");
nethercote3a42fb82004-08-03 18:08:50 +0000112 }
nethercote71980f02004-01-24 18:18:54 +0000113}
114
115
116/*====================================================================*/
nethercote71980f02004-01-24 18:18:54 +0000117/*=== Environment and stack setup ===*/
118/*====================================================================*/
119
nethercote71980f02004-01-24 18:18:54 +0000120/* Prepare the client's environment. This is basically a copy of our
121 environment, except:
sewardj45f4e7c2005-09-27 19:20:21 +0000122
123 LD_PRELOAD=$VALGRIND_LIB/vg_preload_core.so:
124 ($VALGRIND_LIB/vgpreload_TOOL.so:)?
125 $LD_PRELOAD
nethercote71980f02004-01-24 18:18:54 +0000126
sewardjb5f6f512005-03-10 23:59:00 +0000127 If this is missing, then it is added.
nethercote71980f02004-01-24 18:18:54 +0000128
sewardj45f4e7c2005-09-27 19:20:21 +0000129 Also, remove any binding for VALGRIND_LAUNCHER=. The client should
130 not be able to see this.
nethercote71980f02004-01-24 18:18:54 +0000131
132 If this needs to handle any more variables it should be hacked
sewardj45f4e7c2005-09-27 19:20:21 +0000133 into something table driven. The copy is VG_(malloc)'d space.
134*/
135static HChar** setup_client_env ( HChar** origenv, const HChar* toolname)
nethercote71980f02004-01-24 18:18:54 +0000136{
sewardj45f4e7c2005-09-27 19:20:21 +0000137 HChar* preload_core_so = "vg_preload_core.so";
138 HChar* ld_preload = "LD_PRELOAD=";
139 HChar* v_launcher = VALGRIND_LAUNCHER "=";
140 Int ld_preload_len = VG_(strlen)( ld_preload );
141 Int v_launcher_len = VG_(strlen)( v_launcher );
142 Bool ld_preload_done = False;
143 Int vglib_len = VG_(strlen)(VG_(libdir));
nethercote71980f02004-01-24 18:18:54 +0000144
sewardj45f4e7c2005-09-27 19:20:21 +0000145 HChar** cpp;
146 HChar** ret;
147 HChar* preload_tool_path;;
148 Int envc, i;
nethercote71980f02004-01-24 18:18:54 +0000149
sewardj45f4e7c2005-09-27 19:20:21 +0000150 /* Alloc space for the vgpreload_core.so path and vgpreload_<tool>.so
151 paths. We might not need the space for vgpreload_<tool>.so, but it
152 doesn't hurt to over-allocate briefly. The 16s are just cautious
153 slop. */
154 Int preload_core_path_len = vglib_len + sizeof(preload_core_so) + 16;
155 Int preload_tool_path_len = vglib_len + VG_(strlen)(toolname) + 16;
156 Int preload_string_len = preload_core_path_len + preload_tool_path_len;
157 HChar* preload_string = VG_(malloc)(preload_string_len);
158 vg_assert(preload_string);
159
160 /* Determine if there's a vgpreload_<tool>.so file, and setup
161 preload_string. */
162 preload_tool_path = VG_(malloc)(preload_tool_path_len);
163 vg_assert(preload_tool_path);
164 VG_(snprintf)(preload_tool_path, preload_tool_path_len,
165 "%s/vgpreload_%s.so", VG_(libdir), toolname);
166 if (VG_(access)(preload_tool_path, True/*r*/, False/*w*/, False/*x*/) == 0) {
167 VG_(snprintf)(preload_string, preload_string_len, "%s/%s:%s",
168 VG_(libdir), preload_core_so, preload_tool_path);
169 } else {
170 VG_(snprintf)(preload_string, preload_string_len, "%s/%s",
171 VG_(libdir), preload_core_so);
172 }
173 VG_(free)(preload_tool_path);
174
175 VG_(debugLog)(1, "main", "preload_string = %s\n", preload_string);
176
nethercote71980f02004-01-24 18:18:54 +0000177 /* Count the original size of the env */
sewardj45f4e7c2005-09-27 19:20:21 +0000178 envc = 0;
nethercote71980f02004-01-24 18:18:54 +0000179 for (cpp = origenv; cpp && *cpp; cpp++)
180 envc++;
181
182 /* Allocate a new space */
sewardj45f4e7c2005-09-27 19:20:21 +0000183 ret = VG_(malloc) (sizeof(HChar *) * (envc+1+1)); /* 1 new entry + NULL */
nethercote7c018f42004-07-17 16:40:50 +0000184 vg_assert(ret);
nethercote71980f02004-01-24 18:18:54 +0000185
186 /* copy it over */
187 for (cpp = ret; *origenv; )
188 *cpp++ = *origenv++;
189 *cpp = NULL;
190
191 vg_assert(envc == (cpp - ret));
192
193 /* Walk over the new environment, mashing as we go */
194 for (cpp = ret; cpp && *cpp; cpp++) {
sewardj45f4e7c2005-09-27 19:20:21 +0000195 if (VG_(memcmp)(*cpp, ld_preload, ld_preload_len) == 0) {
196 Int len = VG_(strlen)(*cpp) + preload_string_len;
197 HChar *cp = VG_(malloc)(len);
nethercote7c018f42004-07-17 16:40:50 +0000198 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000199
sewardj45f4e7c2005-09-27 19:20:21 +0000200 VG_(snprintf)(cp, len, "%s%s:%s",
201 ld_preload, preload_string, (*cpp)+ld_preload_len);
nethercote71980f02004-01-24 18:18:54 +0000202
sewardj45f4e7c2005-09-27 19:20:21 +0000203 *cpp = cp;
204
205 ld_preload_done = True;
nethercote71980f02004-01-24 18:18:54 +0000206 }
207 }
208
209 /* Add the missing bits */
nethercote71980f02004-01-24 18:18:54 +0000210 if (!ld_preload_done) {
sewardj45f4e7c2005-09-27 19:20:21 +0000211 Int len = ld_preload_len + preload_string_len;
212 HChar *cp = VG_(malloc) (len);
nethercote7c018f42004-07-17 16:40:50 +0000213 vg_assert(cp);
sewardj45f4e7c2005-09-27 19:20:21 +0000214
215 VG_(snprintf)(cp, len, "%s%s", ld_preload, preload_string);
216
nethercote71980f02004-01-24 18:18:54 +0000217 ret[envc++] = cp;
218 }
219
sewardj45f4e7c2005-09-27 19:20:21 +0000220 /* ret[0 .. envc-1] is live now. */
221 /* Find and remove a binding for VALGRIND_LAUNCHER. */
222 for (i = 0; i < envc; i++)
223 if (0 == VG_(memcmp(ret[i], v_launcher, v_launcher_len)))
224 break;
225
226 if (i < envc) {
227 for (; i < envc-1; i++)
228 ret[i] = ret[i+1];
229 envc--;
230 }
231
232 VG_(free)(preload_string);
nethercote71980f02004-01-24 18:18:54 +0000233 ret[envc] = NULL;
234
235 return ret;
236}
237
nethercote71980f02004-01-24 18:18:54 +0000238
239/* Add a string onto the string table, and return its address */
240static char *copy_str(char **tab, const char *str)
241{
242 char *cp = *tab;
243 char *orig = cp;
244
245 while(*str)
246 *cp++ = *str++;
247 *cp++ = '\0';
248
249 if (0)
sewardj45f4e7c2005-09-27 19:20:21 +0000250 VG_(printf)("copied %p \"%s\" len %lld\n", orig, orig, (Long)(cp-orig));
nethercote71980f02004-01-24 18:18:54 +0000251
252 *tab = cp;
253
254 return orig;
255}
256
257/*
258 This sets up the client's initial stack, containing the args,
259 environment and aux vector.
260
261 The format of the stack is:
262
sewardj45f4e7c2005-09-27 19:20:21 +0000263 higher address +-----------------+ <- clstack_end
nethercote71980f02004-01-24 18:18:54 +0000264 | |
265 : string table :
266 | |
267 +-----------------+
268 | AT_NULL |
269 - -
270 | auxv |
271 +-----------------+
sewardjfdf91b42005-09-28 00:53:09 +0000272 | NULL |
nethercote71980f02004-01-24 18:18:54 +0000273 - -
274 | envp |
275 +-----------------+
sewardjfdf91b42005-09-28 00:53:09 +0000276 | NULL |
nethercote71980f02004-01-24 18:18:54 +0000277 - -
278 | argv |
279 +-----------------+
280 | argc |
nethercote4ad74312004-10-26 09:59:49 +0000281 lower address +-----------------+ <- sp
nethercote71980f02004-01-24 18:18:54 +0000282 | undefined |
283 : :
sewardj45f4e7c2005-09-27 19:20:21 +0000284
sewardjfdf91b42005-09-28 00:53:09 +0000285 Allocate and create the initial client stack. It is allocated down
sewardj45f4e7c2005-09-27 19:20:21 +0000286 from clstack_end, which was previously determined by the address
sewardjfdf91b42005-09-28 00:53:09 +0000287 space manager. The returned value is the SP value for the client.
288
289 The client's auxv is created by copying and modifying our own one.
290 As a side effect of scanning our own auxv, some important bits of
291 info are collected:
292
293 VG_(cache_line_size_ppc32) // ppc32 only -- cache line size
294 VG_(have_altivec_ppc32) // ppc32 only -- is Altivec supported?
295*/
296
sewardj45f4e7c2005-09-27 19:20:21 +0000297static
298Addr setup_client_stack( void* init_sp,
299 char** orig_envp,
300 const struct exeinfo *info,
301 UInt** client_auxv,
302 Addr clstack_end,
303 SizeT clstack_max_size )
nethercote71980f02004-01-24 18:18:54 +0000304{
njn83407492005-06-19 16:10:47 +0000305 SysRes res;
nethercote71980f02004-01-24 18:18:54 +0000306 char **cpp;
307 char *strtab; /* string table */
308 char *stringbase;
nethercotea3c3cf22004-11-01 18:38:00 +0000309 Addr *ptr;
nethercote71980f02004-01-24 18:18:54 +0000310 struct ume_auxv *auxv;
311 const struct ume_auxv *orig_auxv;
312 const struct ume_auxv *cauxv;
313 unsigned stringsize; /* total size of strings in bytes */
314 unsigned auxsize; /* total size of auxv in bytes */
sewardj45f4e7c2005-09-27 19:20:21 +0000315 Int argc; /* total argc */
316 Int envc; /* total number of env vars */
nethercote71980f02004-01-24 18:18:54 +0000317 unsigned stacksize; /* total client stack size */
sewardj45f4e7c2005-09-27 19:20:21 +0000318 Addr client_SP; /* client stack base (initial SP) */
319 Addr clstack_start;
320 Int i;
321 Bool have_exename;
322
323 vg_assert(VG_IS_PAGE_ALIGNED(clstack_end+1));
nethercote71980f02004-01-24 18:18:54 +0000324
325 /* use our own auxv as a prototype */
njn62ff0f22005-06-21 23:03:36 +0000326 orig_auxv = VG_(find_auxv)(init_sp);
nethercote71980f02004-01-24 18:18:54 +0000327
328 /* ==================== compute sizes ==================== */
329
330 /* first of all, work out how big the client stack will be */
sewardj45f4e7c2005-09-27 19:20:21 +0000331 stringsize = 0;
332 have_exename = VG_(args_the_exename) != NULL;
nethercote71980f02004-01-24 18:18:54 +0000333
334 /* paste on the extra args if the loader needs them (ie, the #!
335 interpreter and its argument) */
336 argc = 0;
nethercoted6a56872004-07-26 15:32:47 +0000337 if (info->interp_name != NULL) {
nethercote71980f02004-01-24 18:18:54 +0000338 argc++;
sewardj45f4e7c2005-09-27 19:20:21 +0000339 stringsize += VG_(strlen)(info->interp_name) + 1;
nethercote71980f02004-01-24 18:18:54 +0000340 }
nethercoted6a56872004-07-26 15:32:47 +0000341 if (info->interp_args != NULL) {
nethercote71980f02004-01-24 18:18:54 +0000342 argc++;
sewardj45f4e7c2005-09-27 19:20:21 +0000343 stringsize += VG_(strlen)(info->interp_args) + 1;
nethercote71980f02004-01-24 18:18:54 +0000344 }
345
346 /* now scan the args we're given... */
sewardj45f4e7c2005-09-27 19:20:21 +0000347 if (have_exename)
348 stringsize += VG_(strlen)( VG_(args_the_exename) ) + 1;
349
350 for (i = 0; i < VG_(args_for_client).used; i++) {
nethercote71980f02004-01-24 18:18:54 +0000351 argc++;
sewardj45f4e7c2005-09-27 19:20:21 +0000352 stringsize += VG_(strlen)( VG_(args_for_client).strs[i] ) + 1;
nethercote71980f02004-01-24 18:18:54 +0000353 }
sewardj45f4e7c2005-09-27 19:20:21 +0000354
nethercote71980f02004-01-24 18:18:54 +0000355 /* ...and the environment */
356 envc = 0;
357 for (cpp = orig_envp; cpp && *cpp; cpp++) {
358 envc++;
sewardj45f4e7c2005-09-27 19:20:21 +0000359 stringsize += VG_(strlen)(*cpp) + 1;
nethercote71980f02004-01-24 18:18:54 +0000360 }
361
362 /* now, how big is the auxv? */
363 auxsize = sizeof(*auxv); /* there's always at least one entry: AT_NULL */
364 for (cauxv = orig_auxv; cauxv->a_type != AT_NULL; cauxv++) {
365 if (cauxv->a_type == AT_PLATFORM)
sewardj45f4e7c2005-09-27 19:20:21 +0000366 stringsize += VG_(strlen)(cauxv->u.a_ptr) + 1;
nethercote71980f02004-01-24 18:18:54 +0000367 auxsize += sizeof(*cauxv);
368 }
369
sewardjfdf91b42005-09-28 00:53:09 +0000370# if defined(VGP_ppc32_linux)
cerion85665ca2005-06-20 15:51:07 +0000371 auxsize += 2 * sizeof(*cauxv);
sewardjfdf91b42005-09-28 00:53:09 +0000372# endif
cerion85665ca2005-06-20 15:51:07 +0000373
nethercote71980f02004-01-24 18:18:54 +0000374 /* OK, now we know how big the client stack is */
375 stacksize =
sewardj45f4e7c2005-09-27 19:20:21 +0000376 sizeof(Word) + /* argc */
377 (have_exename ? sizeof(char **) : 0) + /* argc[0] == exename */
378 sizeof(char **)*argc + /* argv */
379 sizeof(char **) + /* terminal NULL */
380 sizeof(char **)*envc + /* envp */
381 sizeof(char **) + /* terminal NULL */
382 auxsize + /* auxv */
sewardj90d38542005-09-27 23:53:09 +0000383 VG_ROUNDUP(stringsize, sizeof(Word)); /* strings (aligned) */
nethercote71980f02004-01-24 18:18:54 +0000384
sewardj79048ce2005-02-18 08:28:32 +0000385 if (0) VG_(printf)("stacksize = %d\n", stacksize);
386
sewardj45f4e7c2005-09-27 19:20:21 +0000387 /* client_SP is the client's stack pointer */
388 client_SP = clstack_end - stacksize;
389 client_SP = VG_ROUNDDN(client_SP, 16); /* make stack 16 byte aligned */
nethercote71980f02004-01-24 18:18:54 +0000390
nethercote71980f02004-01-24 18:18:54 +0000391 /* base of the string table (aligned) */
sewardj45f4e7c2005-09-27 19:20:21 +0000392 stringbase = strtab = (char *)clstack_end
393 - VG_ROUNDUP(stringsize, sizeof(int));
nethercote71980f02004-01-24 18:18:54 +0000394
sewardj45f4e7c2005-09-27 19:20:21 +0000395 clstack_start = VG_PGROUNDDN(client_SP);
396
397 /* The max stack size */
398 clstack_max_size = VG_PGROUNDUP(clstack_max_size);
399
400 /* Record stack extent -- needed for stack-change code. */
401 VG_(clstk_base) = clstack_start;
402 VG_(clstk_end) = clstack_end;
nethercote71980f02004-01-24 18:18:54 +0000403
sewardj79048ce2005-02-18 08:28:32 +0000404 if (0)
sewardj45f4e7c2005-09-27 19:20:21 +0000405 VG_(printf)("stringsize=%d auxsize=%d stacksize=%d maxsize=0x%x\n"
406 "clstack_start %p\n"
407 "clstack_end %p\n",
408 stringsize, auxsize, stacksize, (Int)clstack_max_size,
409 (void*)clstack_start, (void*)clstack_end);
nethercote5ee67ca2004-06-22 14:00:09 +0000410
nethercote71980f02004-01-24 18:18:54 +0000411 /* ==================== allocate space ==================== */
412
sewardj45f4e7c2005-09-27 19:20:21 +0000413 { SizeT anon_size = clstack_end - clstack_start + 1;
414 SizeT resvn_size = clstack_max_size - anon_size;
415 Addr anon_start = clstack_start;
416 Addr resvn_start = anon_start - resvn_size;
417 SizeT inner_HACK = 0;
nethercote71980f02004-01-24 18:18:54 +0000418
sewardj45f4e7c2005-09-27 19:20:21 +0000419 vg_assert(VG_IS_PAGE_ALIGNED(anon_size));
420 vg_assert(VG_IS_PAGE_ALIGNED(resvn_size));
421 vg_assert(VG_IS_PAGE_ALIGNED(anon_start));
422 vg_assert(VG_IS_PAGE_ALIGNED(resvn_start));
423 vg_assert(resvn_start == clstack_end + 1 - clstack_max_size);
nethercote71980f02004-01-24 18:18:54 +0000424
sewardj45f4e7c2005-09-27 19:20:21 +0000425# ifdef ENABLE_INNER
426 inner_HACK = 1024*1024; // create 1M non-fault-extending stack
427# endif
nethercote71980f02004-01-24 18:18:54 +0000428
sewardj45f4e7c2005-09-27 19:20:21 +0000429 if (0)
430 VG_(printf)("%p 0x%x %p 0x%x\n",
431 resvn_start, resvn_size, anon_start, anon_size);
nethercote71980f02004-01-24 18:18:54 +0000432
sewardj45f4e7c2005-09-27 19:20:21 +0000433 /* Create a shrinkable reservation followed by an anonymous
434 segment. Together these constitute a growdown stack. */
435 Bool ok = VG_(am_create_reservation)(
436 resvn_start,
437 resvn_size -inner_HACK,
438 SmUpper,
439 anon_size +inner_HACK
440 );
441 vg_assert(ok);
442 /* allocate a stack - mmap enough space for the stack */
443 res = VG_(am_mmap_anon_fixed_client)(
444 anon_start -inner_HACK,
445 anon_size +inner_HACK,
446 VKI_PROT_READ|VKI_PROT_WRITE|VKI_PROT_EXEC
447 );
448 vg_assert(!res.isError);
449 }
450
451 /* ==================== create client stack ==================== */
452
453 ptr = (Addr*)client_SP;
454
455 /* --- client argc --- */
456 *ptr++ = argc + (have_exename ? 1 : 0);
457
458 /* --- client argv --- */
nethercoted6a56872004-07-26 15:32:47 +0000459 if (info->interp_name) {
nethercotea3c3cf22004-11-01 18:38:00 +0000460 *ptr++ = (Addr)copy_str(&strtab, info->interp_name);
sewardj45f4e7c2005-09-27 19:20:21 +0000461 VG_(free)(info->interp_name);
nethercote71980f02004-01-24 18:18:54 +0000462 }
nethercoted6a56872004-07-26 15:32:47 +0000463 if (info->interp_args) {
nethercotea3c3cf22004-11-01 18:38:00 +0000464 *ptr++ = (Addr)copy_str(&strtab, info->interp_args);
sewardj45f4e7c2005-09-27 19:20:21 +0000465 VG_(free)(info->interp_args);
nethercote71980f02004-01-24 18:18:54 +0000466 }
sewardj45f4e7c2005-09-27 19:20:21 +0000467
468 if (have_exename)
469 *ptr++ = (Addr)copy_str(&strtab, VG_(args_the_exename));
470
471 for (i = 0; i < VG_(args_for_client).used; i++) {
472 *ptr++ = (Addr)copy_str(&strtab, VG_(args_for_client).strs[i]);
nethercote71980f02004-01-24 18:18:54 +0000473 }
474 *ptr++ = 0;
475
476 /* --- envp --- */
477 VG_(client_envp) = (Char **)ptr;
478 for (cpp = orig_envp; cpp && *cpp; ptr++, cpp++)
nethercotea3c3cf22004-11-01 18:38:00 +0000479 *ptr = (Addr)copy_str(&strtab, *cpp);
nethercote71980f02004-01-24 18:18:54 +0000480 *ptr++ = 0;
481
482 /* --- auxv --- */
483 auxv = (struct ume_auxv *)ptr;
484 *client_auxv = (UInt *)auxv;
485
sewardjfdf91b42005-09-28 00:53:09 +0000486# if defined(VGP_ppc32_linux)
cerion85665ca2005-06-20 15:51:07 +0000487 auxv[0].a_type = AT_IGNOREPPC;
488 auxv[0].u.a_val = AT_IGNOREPPC;
489 auxv[1].a_type = AT_IGNOREPPC;
490 auxv[1].u.a_val = AT_IGNOREPPC;
491 auxv += 2;
sewardjfdf91b42005-09-28 00:53:09 +0000492# endif
cerion85665ca2005-06-20 15:51:07 +0000493
nethercote71980f02004-01-24 18:18:54 +0000494 for (; orig_auxv->a_type != AT_NULL; auxv++, orig_auxv++) {
sewardjfdf91b42005-09-28 00:53:09 +0000495
nethercote71980f02004-01-24 18:18:54 +0000496 /* copy the entry... */
497 *auxv = *orig_auxv;
498
sewardjfdf91b42005-09-28 00:53:09 +0000499 /* ...and fix up / examine the copy */
nethercote71980f02004-01-24 18:18:54 +0000500 switch(auxv->a_type) {
nethercote71980f02004-01-24 18:18:54 +0000501
sewardjfdf91b42005-09-28 00:53:09 +0000502 case AT_IGNORE:
503 case AT_PHENT:
504 case AT_PAGESZ:
505 case AT_FLAGS:
506 case AT_NOTELF:
507 case AT_UID:
508 case AT_EUID:
509 case AT_GID:
510 case AT_EGID:
511 case AT_CLKTCK:
512 case AT_FPUCW:
513 case AT_SYSINFO:
514 /* All these are pointerless, so we don't need to do
515 anything about them. */
516 break;
nethercote71980f02004-01-24 18:18:54 +0000517
sewardjfdf91b42005-09-28 00:53:09 +0000518 case AT_PHDR:
519 if (info->phdr == 0)
520 auxv->a_type = AT_IGNORE;
521 else
522 auxv->u.a_val = info->phdr;
523 break;
nethercote71980f02004-01-24 18:18:54 +0000524
sewardjfdf91b42005-09-28 00:53:09 +0000525 case AT_PHNUM:
526 if (info->phdr == 0)
527 auxv->a_type = AT_IGNORE;
528 else
529 auxv->u.a_val = info->phnum;
530 break;
nethercote71980f02004-01-24 18:18:54 +0000531
sewardjfdf91b42005-09-28 00:53:09 +0000532 case AT_BASE:
533 auxv->u.a_val = info->interp_base;
534 break;
nethercote71980f02004-01-24 18:18:54 +0000535
sewardjfdf91b42005-09-28 00:53:09 +0000536 case AT_PLATFORM:
537 /* points to a platform description string */
538 auxv->u.a_ptr = copy_str(&strtab, orig_auxv->u.a_ptr);
539 break;
nethercote71980f02004-01-24 18:18:54 +0000540
sewardjfdf91b42005-09-28 00:53:09 +0000541 case AT_ENTRY:
542 auxv->u.a_val = info->entry;
543 break;
nethercote71980f02004-01-24 18:18:54 +0000544
sewardjfdf91b42005-09-28 00:53:09 +0000545 case AT_HWCAP:
546# if defined(VGP_ppc32_linux)
547 /* Acquire altivecness info */
548 VG_(debugLog)(1, "main", "PPC32 hwcaps: 0x%x\n",
549 (UInt)auxv->u.a_val);
550 if (auxv->u.a_val & 0x10000000)
551 VG_(have_altivec_ppc32) = 1;
552 VG_(debugLog)(1, "main", "PPC32 AltiVec support: %u\n",
553 VG_(have_altivec_ppc32));
554# endif
555 break;
nethercote71980f02004-01-24 18:18:54 +0000556
sewardjfdf91b42005-09-28 00:53:09 +0000557 case AT_DCACHEBSIZE:
558 case AT_ICACHEBSIZE:
559 case AT_UCACHEBSIZE:
560# if defined(VGP_ppc32_linux)
561 /* acquire cache info */
562 if (auxv->u.a_val > 0) {
563 VG_(cache_line_size_ppc32) = auxv->u.a_val;
564 VG_(debugLog)(1, "main",
565 "PPC32 cache line size %u (type %u)\n",
566 (UInt)auxv->u.a_val, (UInt)auxv->a_type );
567 }
568# endif
569 break;
nethercote71980f02004-01-24 18:18:54 +0000570
sewardjfdf91b42005-09-28 00:53:09 +0000571# if defined(VGP_ppc32_linux)
572 case AT_IGNOREPPC:
573 break;
574# endif
575
576 case AT_SECURE:
577 /* If this is 1, then it means that this program is
578 running suid, and therefore the dynamic linker should
579 be careful about LD_PRELOAD, etc. However, since
580 stage1 (the thing the kernel actually execve's) should
581 never be SUID, and we need LD_PRELOAD to work for the
582 client, we set AT_SECURE to 0. */
583 auxv->u.a_val = 0;
584 break;
585
586# if !defined(VGP_ppc32_linux)
587 case AT_SYSINFO_EHDR:
588 /* Trash this, because we don't reproduce it */
589 auxv->a_type = AT_IGNORE;
590 break;
591# endif
592
593 default:
594 /* stomp out anything we don't know about */
595 VG_(debugLog)(2, "main",
596 "stomping auxv entry %lld\n",
597 (ULong)auxv->a_type);
598 auxv->a_type = AT_IGNORE;
599 break;
nethercote71980f02004-01-24 18:18:54 +0000600 }
601 }
602 *auxv = *orig_auxv;
603 vg_assert(auxv->a_type == AT_NULL);
604
605 vg_assert((strtab-stringbase) == stringsize);
606
sewardj45f4e7c2005-09-27 19:20:21 +0000607 /* client_SP is pointing at client's argc/argv */
nethercote5ee67ca2004-06-22 14:00:09 +0000608
sewardj45f4e7c2005-09-27 19:20:21 +0000609 if (0) VG_(printf)("startup SP = %p\n", client_SP);
610 return client_SP;
nethercote71980f02004-01-24 18:18:54 +0000611}
612
sewardj45f4e7c2005-09-27 19:20:21 +0000613
614/* Allocate the client data segment. It is an expandable anonymous
615 mapping abutting a shrinkable reservation of size max_dseg_size.
616 The data segment starts at VG_(brk_base), which is page-aligned,
617 and runs up to VG_(brk_limit), which isn't. */
618
619static void setup_client_dataseg ( SizeT max_size )
620{
621 Bool ok;
622 SysRes sres;
623 Addr anon_start = VG_(brk_base);
624 SizeT anon_size = VKI_PAGE_SIZE;
625 Addr resvn_start = anon_start + anon_size;
626 SizeT resvn_size = max_size - anon_size;
627
628 vg_assert(VG_IS_PAGE_ALIGNED(anon_size));
629 vg_assert(VG_IS_PAGE_ALIGNED(resvn_size));
630 vg_assert(VG_IS_PAGE_ALIGNED(anon_start));
631 vg_assert(VG_IS_PAGE_ALIGNED(resvn_start));
632
633 /* Because there's been no brk activity yet: */
634 vg_assert(VG_(brk_base) == VG_(brk_limit));
635
636 /* Try to create the data seg and associated reservation where
637 VG_(brk_base) says. */
638 ok = VG_(am_create_reservation)(
639 resvn_start,
640 resvn_size,
641 SmLower,
642 anon_size
643 );
644
645 if (!ok) {
646 /* Hmm, that didn't work. Well, let aspacem suggest an address
647 it likes better, and try again with that. */
648 anon_start = VG_(am_get_advisory_client_simple)
649 ( 0/*floating*/, anon_size+resvn_size, &ok );
650 if (ok) {
651 resvn_start = anon_start + anon_size;
652 ok = VG_(am_create_reservation)(
653 resvn_start,
654 resvn_size,
655 SmLower,
656 anon_size
657 );
658 if (ok)
659 VG_(brk_base) = VG_(brk_limit) = anon_start;
660 }
661 /* that too might have failed, but if it has, we're hosed: there
662 is no Plan C. */
663 }
664 vg_assert(ok);
665
666 sres = VG_(am_mmap_anon_fixed_client)(
667 anon_start,
668 anon_size,
669 VKI_PROT_READ|VKI_PROT_WRITE|VKI_PROT_EXEC
670 );
671 vg_assert(!sres.isError);
672 vg_assert(sres.val == anon_start);
673}
674
675
nethercote71980f02004-01-24 18:18:54 +0000676/*====================================================================*/
677/*=== Find executable ===*/
678/*====================================================================*/
679
sewardjfdf91b42005-09-28 00:53:09 +0000680/* Scan a colon-separated list, and call a function on each element.
681 The string must be mutable, because we insert a temporary '\0', but
682 the string will end up unmodified. (*func) should return True if it
683 doesn't need to see any more.
684
685 This routine will return True if (*func) returns True and False if
686 it reaches the end of the list without that happening.
687*/
688static Bool scan_colsep(char *colsep, Bool (*func)(const char *))
689{
690 char *cp, *entry;
691 int end;
692
693 if (colsep == NULL ||
694 *colsep == '\0')
695 return False;
696
697 entry = cp = colsep;
698
699 do {
700 end = (*cp == '\0');
701
702 if (*cp == ':' || *cp == '\0') {
703 char save = *cp;
704
705 *cp = '\0';
706 if ((*func)(entry)) {
707 *cp = save;
708 return True;
709 }
710 *cp = save;
711 entry = cp+1;
712 }
713 cp++;
714 } while(!end);
715
716 return False;
717}
718
sewardj45f4e7c2005-09-27 19:20:21 +0000719/* Need a static copy because can't use dynamic mem allocation yet */
720static HChar executable_name[VKI_PATH_MAX];
thughes4ad52d02004-06-27 17:37:21 +0000721
sewardj45f4e7c2005-09-27 19:20:21 +0000722static Bool match_executable(const char *entry)
723{
724 HChar buf[VG_(strlen)(entry) + VG_(strlen)(executable_name) + 3];
thughes4ad52d02004-06-27 17:37:21 +0000725
726 /* empty PATH element means . */
727 if (*entry == '\0')
728 entry = ".";
729
sewardj45f4e7c2005-09-27 19:20:21 +0000730 VG_(snprintf)(buf, sizeof(buf), "%s/%s", entry, executable_name);
731 if (VG_(access)(buf, True/*r*/, False/*w*/, True/*x*/) == 0) {
732 VG_(strncpy)( executable_name, buf, VKI_PATH_MAX-1 );
733 executable_name[VKI_PATH_MAX-1] = 0;
thughes4ad52d02004-06-27 17:37:21 +0000734 return True;
735 }
736 return False;
737}
738
sewardj45f4e7c2005-09-27 19:20:21 +0000739static HChar* find_executable ( HChar* exec )
nethercote71980f02004-01-24 18:18:54 +0000740{
741 vg_assert(NULL != exec);
sewardj45f4e7c2005-09-27 19:20:21 +0000742 VG_(strncpy)( executable_name, exec, VKI_PATH_MAX-1 );
743 executable_name[VKI_PATH_MAX-1] = 0;
744
745 if (VG_(strchr)(executable_name, '/') == NULL) {
nethercote71980f02004-01-24 18:18:54 +0000746 /* no '/' - we need to search the path */
sewardj45f4e7c2005-09-27 19:20:21 +0000747 HChar *path = VG_(getenv)("PATH");
thughes4ad52d02004-06-27 17:37:21 +0000748 scan_colsep(path, match_executable);
nethercote71980f02004-01-24 18:18:54 +0000749 }
thughes4ad52d02004-06-27 17:37:21 +0000750 return executable_name;
nethercote71980f02004-01-24 18:18:54 +0000751}
752
753
754/*====================================================================*/
nethercotef4928da2004-06-15 10:54:40 +0000755/*=== Command line errors ===*/
756/*====================================================================*/
757
njnbe9b47b2005-05-15 16:22:58 +0000758static void revert_to_stderr ( void )
nethercotef4928da2004-06-15 10:54:40 +0000759{
njnbe9b47b2005-05-15 16:22:58 +0000760 vg_assert( !VG_(logging_to_socket) );
nethercotef8548672004-06-21 12:42:35 +0000761 VG_(clo_log_fd) = 2; /* stderr */
nethercotef4928da2004-06-15 10:54:40 +0000762}
763
764void VG_(bad_option) ( Char* opt )
765{
njnbe9b47b2005-05-15 16:22:58 +0000766 revert_to_stderr();
njn02bc4b82005-05-15 17:28:26 +0000767 VG_(printf)("valgrind: Bad option '%s'; aborting.\n", opt);
nethercotef4928da2004-06-15 10:54:40 +0000768 VG_(printf)("valgrind: Use --help for more information.\n");
769 VG_(exit)(1);
770}
771
nethercotef4928da2004-06-15 10:54:40 +0000772static void missing_prog ( void )
773{
njnbe9b47b2005-05-15 16:22:58 +0000774 revert_to_stderr();
nethercotef4928da2004-06-15 10:54:40 +0000775 VG_(printf)("valgrind: no program specified\n");
776 VG_(printf)("valgrind: Use --help for more information.\n");
777 VG_(exit)(1);
778}
779
780static void config_error ( Char* msg )
781{
njnbe9b47b2005-05-15 16:22:58 +0000782 revert_to_stderr();
nethercotef4928da2004-06-15 10:54:40 +0000783 VG_(printf)("valgrind: Startup or configuration error:\n %s\n", msg);
784 VG_(printf)("valgrind: Unable to start up properly. Giving up.\n");
785 VG_(exit)(1);
786}
787
788
nethercote71980f02004-01-24 18:18:54 +0000789/*====================================================================*/
790/*=== Loading the client ===*/
791/*====================================================================*/
792
sewardj45f4e7c2005-09-27 19:20:21 +0000793/* Load the client whose name is VG_(argv_the_exename). */
nethercote71980f02004-01-24 18:18:54 +0000794
sewardj45f4e7c2005-09-27 19:20:21 +0000795static void load_client ( /*OUT*/struct exeinfo* info,
796 /*OUT*/Addr* client_eip)
797{
798 HChar* exec;
799 Int ret;
800 SysRes res;
801
802 vg_assert( VG_(args_the_exename) != NULL);
803 exec = find_executable( VG_(args_the_exename) );
804
805 VG_(memset)(info, 0, sizeof(*info));
nethercote71980f02004-01-24 18:18:54 +0000806 info->exe_base = VG_(client_base);
807 info->exe_end = VG_(client_end);
nethercote71980f02004-01-24 18:18:54 +0000808
sewardj45f4e7c2005-09-27 19:20:21 +0000809 ret = VG_(do_exec)(exec, info);
810 if (ret != 0) {
811 VG_(printf)("valgrind: do_exec(%s) failed: %s\n",
812 exec, VG_(strerror)(ret));
813 VG_(exit)(127);
nethercote71980f02004-01-24 18:18:54 +0000814 }
815
sewardj45f4e7c2005-09-27 19:20:21 +0000816 /* Get hold of a file descriptor which refers to the client
817 executable. This is needed for attaching to GDB. */
818 res = VG_(open)(exec, VKI_O_RDONLY, VKI_S_IRUSR);
819 if (!res.isError)
820 VG_(cl_exec_fd) = res.val;
821
nethercote71980f02004-01-24 18:18:54 +0000822 /* Copy necessary bits of 'info' that were filled in */
823 *client_eip = info->init_eip;
sewardj45f4e7c2005-09-27 19:20:21 +0000824 VG_(brk_base) = VG_(brk_limit) = VG_PGROUNDUP(info->brkbase);
nethercote71980f02004-01-24 18:18:54 +0000825}
826
nethercote969ecf12004-10-13 17:29:01 +0000827
sewardj71bc3cb2005-05-19 00:25:45 +0000828/*====================================================================*/
829/*=== Command-line: variables, processing, etc ===*/
830/*====================================================================*/
831
832// See pub_{core,tool}_options.h for explanations of all these.
833
sewardj45f4e7c2005-09-27 19:20:21 +0000834static void usage_NORETURN ( Bool debug_help )
njn7cf0bd32002-06-08 13:36:03 +0000835{
njn25e49d8e72002-09-23 09:36:25 +0000836 Char* usage1 =
nethercote71980f02004-01-24 18:18:54 +0000837"usage: valgrind --tool=<toolname> [options] prog-and-args\n"
njn25e49d8e72002-09-23 09:36:25 +0000838"\n"
nethercote2b0793f2003-12-02 10:41:18 +0000839" common user options for all Valgrind tools, with defaults in [ ]:\n"
sewardjb5f6f512005-03-10 23:59:00 +0000840" --tool=<name> use the Valgrind tool named <name> [memcheck]\n"
nethercotea76368b2004-06-16 11:56:29 +0000841" -h --help show this message\n"
nethercote6c999f22004-01-31 22:55:15 +0000842" --help-debug show this message, plus debugging options\n"
njn25e49d8e72002-09-23 09:36:25 +0000843" --version show version\n"
njn25e49d8e72002-09-23 09:36:25 +0000844" -q --quiet run silently; only print error msgs\n"
845" -v --verbose be more verbose, incl counts of errors\n"
nethercote77eba602003-11-13 17:35:04 +0000846" --trace-children=no|yes Valgrind-ise child processes? [no]\n"
nethercote0d588502004-06-21 13:27:11 +0000847" --track-fds=no|yes track open file descriptors? [no]\n"
thughes6233a382004-08-21 11:10:44 +0000848" --time-stamp=no|yes add timestamps to log messages? [no]\n"
njnce545552005-07-25 22:36:52 +0000849" --log-fd=<number> log messages to file descriptor [2=stderr]\n"
850" --log-file=<file> log messages to <file>.pid<pid>\n"
851" --log-file-exactly=<file> log messages to <file>\n"
852" --log-file-qualifier=<VAR> incorporate $VAR in logfile name [none]\n"
853" --log-socket=ipaddr:port log messages to socket ipaddr:port\n"
nethercote2b0793f2003-12-02 10:41:18 +0000854"\n"
855" uncommon user options for all Valgrind tools:\n"
nethercote0d588502004-06-21 13:27:11 +0000856" --run-libc-freeres=no|yes free up glibc memory at exit? [yes]\n"
sewardja0461a62005-09-28 01:14:32 +0000857" --weird-hacks=hack1,hack2,... known hacks: lax-ioctls\n"
sewardj45f4e7c2005-09-27 19:20:21 +0000858" enable-outer [none]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +0000859" --pointercheck=no|yes enforce client address space limits [yes]\n"
sewardjb1131a82005-03-19 15:12:21 +0000860" --show-emwarns=no|yes show warnings about emulation limits? [no]\n"
sewardj6c3a2192005-07-24 07:00:45 +0000861" --smc-check=none|stack|all checks for self-modifying code: none,\n"
862" only for code found in stacks, or all [stack]\n"
njn25e49d8e72002-09-23 09:36:25 +0000863"\n"
nethercote2b0793f2003-12-02 10:41:18 +0000864" user options for Valgrind tools that report errors:\n"
njnce545552005-07-25 22:36:52 +0000865" --xml=yes all output is in XML (Memcheck/Nulgrind only)\n"
njnc8ec9f82005-07-20 03:03:28 +0000866" --xml-user-comment=STR copy STR verbatim to XML output\n"
nethercote2b0793f2003-12-02 10:41:18 +0000867" --demangle=no|yes automatically demangle C++ names? [yes]\n"
njncc6cc142005-03-12 20:59:29 +0000868" --num-callers=<number> show <num> callers in stack traces [12]\n"
nethercote2b0793f2003-12-02 10:41:18 +0000869" --error-limit=no|yes stop showing new errors if too many? [yes]\n"
870" --show-below-main=no|yes continue stack traces below main() [no]\n"
871" --suppressions=<filename> suppress errors described in <filename>\n"
sewardjd153fae2005-01-10 17:24:47 +0000872" --gen-suppressions=no|yes|all print suppressions for errors? [no]\n"
nethercote04d0fbc2004-01-26 16:48:06 +0000873" --db-attach=no|yes start debugger when errors detected? [no]\n"
874" --db-command=<command> command to start debugger [gdb -nw %%f %%p]\n"
875" --input-fd=<number> file descriptor for input [0=stdin]\n"
sewardj97724e52005-04-02 23:40:59 +0000876" --max-stackframe=<number> assume stack switch for SP changes larger\n"
877" than <number> bytes [2000000]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +0000878"\n";
njn7cf0bd32002-06-08 13:36:03 +0000879
njn25e49d8e72002-09-23 09:36:25 +0000880 Char* usage2 =
881"\n"
nethercote2b0793f2003-12-02 10:41:18 +0000882" debugging options for all Valgrind tools:\n"
njn25e49d8e72002-09-23 09:36:25 +0000883" --sanity-level=<number> level of sanity checking to do [1]\n"
nethercote137bc552003-11-14 17:47:54 +0000884" --profile=no|yes profile? (tool must be built for it) [no]\n"
sewardjfa8ec112005-01-19 11:55:34 +0000885" --trace-flags=<XXXXXXXX> show generated code? (X = 0|1) [00000000]\n"
886" --profile-flags=<XXXXXXXX> ditto, but for profiling (X = 0|1) [00000000]\n"
sewardjc771b292004-11-30 18:55:21 +0000887" --trace-notbelow=<number> only show BBs above <number> [0]\n"
njn25e49d8e72002-09-23 09:36:25 +0000888" --trace-syscalls=no|yes show all system calls? [no]\n"
889" --trace-signals=no|yes show signal handling details? [no]\n"
890" --trace-symtab=no|yes show symbol table details? [no]\n"
sewardjce058b02005-05-01 08:55:38 +0000891" --trace-cfi=no|yes show call-frame-info details? [no]\n"
njn25e49d8e72002-09-23 09:36:25 +0000892" --trace-sched=no|yes show thread scheduler details? [no]\n"
jsgf855d93d2003-10-13 22:26:55 +0000893" --wait-for-gdb=yes|no pause on startup to wait for gdb attach\n"
sewardjb5f6f512005-03-10 23:59:00 +0000894#if 0
895" --model-pthreads=yes|no model the pthreads library [no]\n"
896#endif
897" --command-line-only=no|yes only use command line options [no]\n"
njn613812e2005-03-11 04:57:30 +0000898"\n"
899" --vex-iropt-verbosity 0 .. 9 [0]\n"
900" --vex-iropt-level 0 .. 2 [2]\n"
901" --vex-iropt-precise-memory-exns [no]\n"
sewardj8b635a42004-11-22 19:01:47 +0000902" --vex-iropt-unroll-thresh 0 .. 400 [120]\n"
903" --vex-guest-max-insns 1 .. 100 [50]\n"
904" --vex-guest-chase-thresh 0 .. 99 [10]\n"
905"\n"
sewardjfa8ec112005-01-19 11:55:34 +0000906" --trace-flags and --profile-flags values (omit the middle space):\n"
sewardj2a99cf62004-11-24 10:44:19 +0000907" 1000 0000 show conversion into IR\n"
908" 0100 0000 show after initial opt\n"
909" 0010 0000 show after instrumentation\n"
910" 0001 0000 show after second opt\n"
911" 0000 1000 show after tree building\n"
912" 0000 0100 show selecting insns\n"
913" 0000 0010 show after reg-alloc\n"
914" 0000 0001 show final assembly\n"
915"\n"
nethercote2b0793f2003-12-02 10:41:18 +0000916" debugging options for Valgrind tools that report errors\n"
917" --dump-error=<number> show translation for basic block associated\n"
918" with <number>'th error context [0=show none]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +0000919"\n";
njn3e884182003-04-15 13:03:23 +0000920
921 Char* usage3 =
922"\n"
nethercote71980f02004-01-24 18:18:54 +0000923" Extra options read from ~/.valgrindrc, $VALGRIND_OPTS, ./.valgrindrc\n"
njn25e49d8e72002-09-23 09:36:25 +0000924"\n"
njn53612422005-03-12 16:22:54 +0000925" Valgrind is Copyright (C) 2000-2005 Julian Seward et al.\n"
njn25e49d8e72002-09-23 09:36:25 +0000926" and licensed under the GNU General Public License, version 2.\n"
927" Bug reports, feedback, admiration, abuse, etc, to: %s.\n"
njnd04b7c62002-10-03 14:05:52 +0000928"\n"
nethercote137bc552003-11-14 17:47:54 +0000929" Tools are copyright and licensed by their authors. See each\n"
930" tool's start-up message for more information.\n"
njn25e49d8e72002-09-23 09:36:25 +0000931"\n";
njn7cf0bd32002-06-08 13:36:03 +0000932
njnbe9b47b2005-05-15 16:22:58 +0000933 // Ensure the message goes to stdout
934 VG_(clo_log_fd) = 1;
935 vg_assert( !VG_(logging_to_socket) );
936
fitzhardinge98abfc72003-12-16 02:05:15 +0000937 VG_(printf)(usage1);
938 if (VG_(details).name) {
939 VG_(printf)(" user options for %s:\n", VG_(details).name);
fitzhardinge98abfc72003-12-16 02:05:15 +0000940 if (VG_(needs).command_line_options)
njn51d827b2005-05-09 01:02:08 +0000941 VG_TDICT_CALL(tool_print_usage);
fitzhardinge98abfc72003-12-16 02:05:15 +0000942 else
943 VG_(printf)(" (none)\n");
944 }
nethercote6c999f22004-01-31 22:55:15 +0000945 if (debug_help) {
946 VG_(printf)(usage2);
fitzhardinge98abfc72003-12-16 02:05:15 +0000947
nethercote6c999f22004-01-31 22:55:15 +0000948 if (VG_(details).name) {
949 VG_(printf)(" debugging options for %s:\n", VG_(details).name);
950
951 if (VG_(needs).command_line_options)
njn51d827b2005-05-09 01:02:08 +0000952 VG_TDICT_CALL(tool_print_debug_usage);
nethercote6c999f22004-01-31 22:55:15 +0000953 else
954 VG_(printf)(" (none)\n");
955 }
fitzhardinge98abfc72003-12-16 02:05:15 +0000956 }
nethercote421281e2003-11-20 16:20:55 +0000957 VG_(printf)(usage3, VG_BUGS_TO);
nethercotef4928da2004-06-15 10:54:40 +0000958 VG_(exit)(0);
njn7cf0bd32002-06-08 13:36:03 +0000959}
sewardjde4a1d02002-03-22 01:27:54 +0000960
sewardjde4a1d02002-03-22 01:27:54 +0000961
sewardj45f4e7c2005-09-27 19:20:21 +0000962/* Peer at previously set up VG_(args_for_valgrind) and extract any
963 request for help and also the tool name. */
964
965static void get_helprequest_and_toolname ( Int* need_help, HChar** tool )
966{
967 UInt i;
968 HChar* str;
sewardj8b635a42004-11-22 19:01:47 +0000969
nethercote71980f02004-01-24 18:18:54 +0000970 /* parse the options we have (only the options we care about now) */
sewardj45f4e7c2005-09-27 19:20:21 +0000971 for (i = 0; i < VG_(args_for_valgrind).used; i++) {
nethercote71980f02004-01-24 18:18:54 +0000972
sewardj45f4e7c2005-09-27 19:20:21 +0000973 str = VG_(args_for_valgrind).strs[i];
974 vg_assert(str);
nethercote71980f02004-01-24 18:18:54 +0000975
sewardj45f4e7c2005-09-27 19:20:21 +0000976 if (VG_STREQ(str, "--version")) {
977 VG_(printf)("valgrind-" VERSION "\n");
978 VG_(exit)(0);
979
980 } else if (VG_CLO_STREQ(str, "--help") ||
981 VG_CLO_STREQ(str, "-h")) {
nethercote6c999f22004-01-31 22:55:15 +0000982 *need_help = 1;
983
sewardj45f4e7c2005-09-27 19:20:21 +0000984 } else if (VG_CLO_STREQ(str, "--help-debug")) {
nethercote6c999f22004-01-31 22:55:15 +0000985 *need_help = 2;
nethercote71980f02004-01-24 18:18:54 +0000986
sewardj45f4e7c2005-09-27 19:20:21 +0000987 // The tool has already been determined, but we need to know the name
988 // here.
989 } else if (VG_CLO_STREQN(7, str, "--tool=")) {
990 *tool = &str[7];
nethercote71980f02004-01-24 18:18:54 +0000991 }
992 }
nethercote71980f02004-01-24 18:18:54 +0000993}
994
sewardj45f4e7c2005-09-27 19:20:21 +0000995static Bool process_cmd_line_options( UInt* client_auxv, const char* toolname )
nethercote71980f02004-01-24 18:18:54 +0000996{
sewardj92645592005-07-23 09:18:34 +0000997 SysRes sres;
998 Int i, eventually_log_fd;
999 Int toolname_len = VG_(strlen)(toolname);
njnbe9b47b2005-05-15 16:22:58 +00001000 enum {
1001 VgLogTo_Fd,
1002 VgLogTo_File,
1003 VgLogTo_FileExactly,
1004 VgLogTo_Socket
1005 } log_to = VgLogTo_Fd; // Where is logging output to be sent?
sewardjde4a1d02002-03-22 01:27:54 +00001006
nethercotee1730692003-11-20 10:38:07 +00001007 /* log to stderr by default, but usage message goes to stdout */
nethercotef8548672004-06-21 12:42:35 +00001008 eventually_log_fd = 2;
sewardjde4a1d02002-03-22 01:27:54 +00001009
sewardj19d81412002-06-03 01:10:40 +00001010 /* Check for sane path in ./configure --prefix=... */
fitzhardinge98abfc72003-12-16 02:05:15 +00001011 if (VG_LIBDIR[0] != '/')
sewardj19d81412002-06-03 01:10:40 +00001012 config_error("Please use absolute paths in "
1013 "./configure --prefix=... or --libdir=...");
sewardj38170912002-05-10 21:07:22 +00001014
sewardj45f4e7c2005-09-27 19:20:21 +00001015 for (i = 0; i < VG_(args_for_valgrind).used; i++) {
nethercote71980f02004-01-24 18:18:54 +00001016
sewardj45f4e7c2005-09-27 19:20:21 +00001017 HChar* arg = VG_(args_for_valgrind).strs[i];
1018 HChar* colon = arg;
nethercote71980f02004-01-24 18:18:54 +00001019
thughes3bfd5a02004-07-18 08:05:44 +00001020 /* Look for a colon in the switch name */
1021 while (*colon && *colon != ':' && *colon != '=')
1022 colon++;
nethercote71980f02004-01-24 18:18:54 +00001023
1024 /* Look for matching "--toolname:foo" */
thughes3bfd5a02004-07-18 08:05:44 +00001025 if (*colon == ':') {
nethercote71980f02004-01-24 18:18:54 +00001026 if (VG_CLO_STREQN(2, arg, "--") &&
1027 VG_CLO_STREQN(toolname_len, arg+2, toolname) &&
1028 VG_CLO_STREQN(1, arg+2+toolname_len, ":"))
1029 {
1030 // prefix matches, convert "--toolname:foo" to "--foo"
1031 if (0)
1032 VG_(printf)("tool-specific arg: %s\n", arg);
sewardj45f4e7c2005-09-27 19:20:21 +00001033 arg = VG_(strdup)(arg + toolname_len + 1);
nethercote71980f02004-01-24 18:18:54 +00001034 arg[0] = '-';
1035 arg[1] = '-';
1036
1037 } else {
1038 // prefix doesn't match, skip to next arg
1039 continue;
1040 }
1041 }
1042
fitzhardinge98abfc72003-12-16 02:05:15 +00001043 /* Ignore these options - they've already been handled */
njn45270a22005-03-27 01:00:11 +00001044 if (VG_CLO_STREQN( 7, arg, "--tool=")) goto skip_arg;
njn45270a22005-03-27 01:00:11 +00001045 if (VG_CLO_STREQN(20, arg, "--command-line-only=")) goto skip_arg;
fitzhardinge98abfc72003-12-16 02:05:15 +00001046
njn45270a22005-03-27 01:00:11 +00001047 if ( VG_CLO_STREQ(arg, "--")) goto skip_arg;
nethercote27fec902004-06-16 21:26:32 +00001048
nethercote71980f02004-01-24 18:18:54 +00001049 else if (VG_CLO_STREQ(arg, "-v") ||
1050 VG_CLO_STREQ(arg, "--verbose"))
sewardjde4a1d02002-03-22 01:27:54 +00001051 VG_(clo_verbosity)++;
nethercote27fec902004-06-16 21:26:32 +00001052
nethercote71980f02004-01-24 18:18:54 +00001053 else if (VG_CLO_STREQ(arg, "-q") ||
1054 VG_CLO_STREQ(arg, "--quiet"))
sewardjde4a1d02002-03-22 01:27:54 +00001055 VG_(clo_verbosity)--;
1056
sewardj1cf558c2005-04-25 01:36:56 +00001057 else if (VG_CLO_STREQ(arg, "-d")) {
1058 /* do nothing */
1059 }
1060
sewardj71bc3cb2005-05-19 00:25:45 +00001061 else VG_BOOL_CLO(arg, "--xml", VG_(clo_xml))
njn45270a22005-03-27 01:00:11 +00001062 else VG_BOOL_CLO(arg, "--db-attach", VG_(clo_db_attach))
1063 else VG_BOOL_CLO(arg, "--demangle", VG_(clo_demangle))
1064 else VG_BOOL_CLO(arg, "--error-limit", VG_(clo_error_limit))
1065 else VG_BOOL_CLO(arg, "--pointercheck", VG_(clo_pointercheck))
njn45270a22005-03-27 01:00:11 +00001066 else VG_BOOL_CLO(arg, "--show-emwarns", VG_(clo_show_emwarns))
sewardj97724e52005-04-02 23:40:59 +00001067 else VG_NUM_CLO (arg, "--max-stackframe", VG_(clo_max_stackframe))
njn45270a22005-03-27 01:00:11 +00001068 else VG_BOOL_CLO(arg, "--profile", VG_(clo_profile))
1069 else VG_BOOL_CLO(arg, "--run-libc-freeres", VG_(clo_run_libc_freeres))
1070 else VG_BOOL_CLO(arg, "--show-below-main", VG_(clo_show_below_main))
1071 else VG_BOOL_CLO(arg, "--time-stamp", VG_(clo_time_stamp))
1072 else VG_BOOL_CLO(arg, "--track-fds", VG_(clo_track_fds))
1073 else VG_BOOL_CLO(arg, "--trace-children", VG_(clo_trace_children))
1074 else VG_BOOL_CLO(arg, "--trace-sched", VG_(clo_trace_sched))
1075 else VG_BOOL_CLO(arg, "--trace-signals", VG_(clo_trace_signals))
1076 else VG_BOOL_CLO(arg, "--trace-symtab", VG_(clo_trace_symtab))
sewardjce058b02005-05-01 08:55:38 +00001077 else VG_BOOL_CLO(arg, "--trace-cfi", VG_(clo_trace_cfi))
njn45270a22005-03-27 01:00:11 +00001078 else VG_BOOL_CLO(arg, "--trace-redir", VG_(clo_trace_redir))
1079 else VG_BOOL_CLO(arg, "--trace-syscalls", VG_(clo_trace_syscalls))
1080 else VG_BOOL_CLO(arg, "--trace-pthreads", VG_(clo_trace_pthreads))
1081 else VG_BOOL_CLO(arg, "--wait-for-gdb", VG_(clo_wait_for_gdb))
1082 else VG_BOOL_CLO(arg, "--model-pthreads", VG_(clo_model_pthreads))
sewardj72f98ff2002-06-13 17:23:38 +00001083
njn45270a22005-03-27 01:00:11 +00001084 else VG_STR_CLO (arg, "--db-command", VG_(clo_db_command))
1085 else VG_STR_CLO (arg, "--weird-hacks", VG_(clo_weird_hacks))
sewardjde4a1d02002-03-22 01:27:54 +00001086
njn45270a22005-03-27 01:00:11 +00001087 else VG_NUM_CLO (arg, "--dump-error", VG_(clo_dump_error))
1088 else VG_NUM_CLO (arg, "--input-fd", VG_(clo_input_fd))
1089 else VG_NUM_CLO (arg, "--sanity-level", VG_(clo_sanity_level))
1090 else VG_BNUM_CLO(arg, "--num-callers", VG_(clo_backtrace_size), 1,
1091 VG_DEEPEST_BACKTRACE)
sewardjde4a1d02002-03-22 01:27:54 +00001092
sewardj6c3a2192005-07-24 07:00:45 +00001093 else if (VG_CLO_STREQ(arg, "--smc-check=none"))
1094 VG_(clo_smc_check) = Vg_SmcNone;
1095 else if (VG_CLO_STREQ(arg, "--smc-check=stack"))
1096 VG_(clo_smc_check) = Vg_SmcStack;
1097 else if (VG_CLO_STREQ(arg, "--smc-check=all"))
1098 VG_(clo_smc_check) = Vg_SmcAll;
sewardj26412bd2005-07-07 10:05:05 +00001099
njn45270a22005-03-27 01:00:11 +00001100 else VG_BNUM_CLO(arg, "--vex-iropt-verbosity",
sewardj8b635a42004-11-22 19:01:47 +00001101 VG_(clo_vex_control).iropt_verbosity, 0, 10)
njn45270a22005-03-27 01:00:11 +00001102 else VG_BNUM_CLO(arg, "--vex-iropt-level",
sewardj8b635a42004-11-22 19:01:47 +00001103 VG_(clo_vex_control).iropt_level, 0, 2)
njn45270a22005-03-27 01:00:11 +00001104 else VG_BOOL_CLO(arg, "--vex-iropt-precise-memory-exns",
sewardj8b635a42004-11-22 19:01:47 +00001105 VG_(clo_vex_control).iropt_precise_memory_exns)
njn45270a22005-03-27 01:00:11 +00001106 else VG_BNUM_CLO(arg, "--vex-iropt-unroll-thresh",
sewardj8b635a42004-11-22 19:01:47 +00001107 VG_(clo_vex_control).iropt_unroll_thresh, 0, 400)
njn45270a22005-03-27 01:00:11 +00001108 else VG_BNUM_CLO(arg, "--vex-guest-max-insns",
sewardj8b635a42004-11-22 19:01:47 +00001109 VG_(clo_vex_control).guest_max_insns, 1, 100)
njn45270a22005-03-27 01:00:11 +00001110 else VG_BNUM_CLO(arg, "--vex-guest-chase-thresh",
sewardj8b635a42004-11-22 19:01:47 +00001111 VG_(clo_vex_control).guest_chase_thresh, 0, 99)
1112
nethercotef8548672004-06-21 12:42:35 +00001113 else if (VG_CLO_STREQN(9, arg, "--log-fd=")) {
njnbe9b47b2005-05-15 16:22:58 +00001114 log_to = VgLogTo_Fd;
nethercotef8548672004-06-21 12:42:35 +00001115 VG_(clo_log_name) = NULL;
1116 eventually_log_fd = (Int)VG_(atoll)(&arg[9]);
sewardj4cf05692002-10-27 20:28:29 +00001117 }
1118
nethercotef8548672004-06-21 12:42:35 +00001119 else if (VG_CLO_STREQN(11, arg, "--log-file=")) {
njnbe9b47b2005-05-15 16:22:58 +00001120 log_to = VgLogTo_File;
nethercotef8548672004-06-21 12:42:35 +00001121 VG_(clo_log_name) = &arg[11];
sewardj4cf05692002-10-27 20:28:29 +00001122 }
njnd6bc3c32005-03-27 00:44:31 +00001123
sewardjad311162005-07-19 11:25:02 +00001124 else if (VG_CLO_STREQN(11, arg, "--log-file=")) {
1125 log_to = VgLogTo_File;
1126 VG_(clo_log_name) = &arg[11];
1127 }
1128
1129 else if (VG_CLO_STREQN(21, arg, "--log-file-qualifier=")) {
1130 VG_(clo_log_file_qualifier) = &arg[21];
1131 }
1132
sewardj603d4102005-01-11 14:01:02 +00001133 else if (VG_CLO_STREQN(19, arg, "--log-file-exactly=")) {
njnbe9b47b2005-05-15 16:22:58 +00001134 log_to = VgLogTo_FileExactly;
sewardj603d4102005-01-11 14:01:02 +00001135 VG_(clo_log_name) = &arg[19];
1136 }
sewardjde4a1d02002-03-22 01:27:54 +00001137
nethercotef8548672004-06-21 12:42:35 +00001138 else if (VG_CLO_STREQN(13, arg, "--log-socket=")) {
njnbe9b47b2005-05-15 16:22:58 +00001139 log_to = VgLogTo_Socket;
nethercotef8548672004-06-21 12:42:35 +00001140 VG_(clo_log_name) = &arg[13];
sewardj73cf3bc2002-11-03 03:20:15 +00001141 }
1142
sewardj768db0e2005-07-19 14:18:56 +00001143 else if (VG_CLO_STREQN(19, arg, "--xml-user-comment=")) {
1144 VG_(clo_xml_user_comment) = &arg[19];
1145 }
1146
nethercote71980f02004-01-24 18:18:54 +00001147 else if (VG_CLO_STREQN(15, arg, "--suppressions=")) {
sewardjde4a1d02002-03-22 01:27:54 +00001148 if (VG_(clo_n_suppressions) >= VG_CLO_MAX_SFILES) {
njn25e49d8e72002-09-23 09:36:25 +00001149 VG_(message)(Vg_UserMsg, "Too many suppression files specified.");
sewardjde4a1d02002-03-22 01:27:54 +00001150 VG_(message)(Vg_UserMsg,
1151 "Increase VG_CLO_MAX_SFILES and recompile.");
nethercote71980f02004-01-24 18:18:54 +00001152 VG_(bad_option)(arg);
sewardjde4a1d02002-03-22 01:27:54 +00001153 }
nethercote71980f02004-01-24 18:18:54 +00001154 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = &arg[15];
sewardjde4a1d02002-03-22 01:27:54 +00001155 VG_(clo_n_suppressions)++;
1156 }
sewardjde4a1d02002-03-22 01:27:54 +00001157
sewardjfa8ec112005-01-19 11:55:34 +00001158 /* "stuvwxyz" --> stuvwxyz (binary) */
1159 else if (VG_CLO_STREQN(14, arg, "--trace-flags=")) {
1160 Int j;
1161 char* opt = & arg[14];
1162
1163 if (8 != VG_(strlen)(opt)) {
1164 VG_(message)(Vg_UserMsg,
1165 "--trace-flags argument must have 8 digits");
1166 VG_(bad_option)(arg);
1167 }
1168 for (j = 0; j < 8; j++) {
1169 if ('0' == opt[j]) { /* do nothing */ }
1170 else if ('1' == opt[j]) VG_(clo_trace_flags) |= (1 << (7-j));
1171 else {
1172 VG_(message)(Vg_UserMsg, "--trace-flags argument can only "
1173 "contain 0s and 1s");
1174 VG_(bad_option)(arg);
1175 }
1176 }
1177 }
1178
1179 /* "stuvwxyz" --> stuvwxyz (binary) */
1180 else if (VG_CLO_STREQN(16, arg, "--profile-flags=")) {
njn25e49d8e72002-09-23 09:36:25 +00001181 Int j;
nethercote71980f02004-01-24 18:18:54 +00001182 char* opt = & arg[16];
njn25e49d8e72002-09-23 09:36:25 +00001183
sewardj2a99cf62004-11-24 10:44:19 +00001184 if (8 != VG_(strlen)(opt)) {
njn25e49d8e72002-09-23 09:36:25 +00001185 VG_(message)(Vg_UserMsg,
sewardjfa8ec112005-01-19 11:55:34 +00001186 "--profile-flags argument must have 8 digits");
nethercote71980f02004-01-24 18:18:54 +00001187 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001188 }
sewardj8b635a42004-11-22 19:01:47 +00001189 for (j = 0; j < 8; j++) {
njn25e49d8e72002-09-23 09:36:25 +00001190 if ('0' == opt[j]) { /* do nothing */ }
sewardjfa8ec112005-01-19 11:55:34 +00001191 else if ('1' == opt[j]) VG_(clo_profile_flags) |= (1 << (7-j));
njn25e49d8e72002-09-23 09:36:25 +00001192 else {
sewardjfa8ec112005-01-19 11:55:34 +00001193 VG_(message)(Vg_UserMsg, "--profile-flags argument can only "
njn25e49d8e72002-09-23 09:36:25 +00001194 "contain 0s and 1s");
nethercote71980f02004-01-24 18:18:54 +00001195 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001196 }
1197 }
1198 }
sewardjde4a1d02002-03-22 01:27:54 +00001199
njn45270a22005-03-27 01:00:11 +00001200 else VG_NUM_CLO (arg, "--trace-notbelow", VG_(clo_trace_notbelow))
sewardjc771b292004-11-30 18:55:21 +00001201
sewardjd153fae2005-01-10 17:24:47 +00001202 else if (VG_CLO_STREQ(arg, "--gen-suppressions=no"))
1203 VG_(clo_gen_suppressions) = 0;
1204 else if (VG_CLO_STREQ(arg, "--gen-suppressions=yes"))
1205 VG_(clo_gen_suppressions) = 1;
1206 else if (VG_CLO_STREQ(arg, "--gen-suppressions=all"))
1207 VG_(clo_gen_suppressions) = 2;
1208
nethercote71980f02004-01-24 18:18:54 +00001209 else if ( ! VG_(needs).command_line_options
njn51d827b2005-05-09 01:02:08 +00001210 || ! VG_TDICT_CALL(tool_process_cmd_line_option, arg) ) {
nethercotef4928da2004-06-15 10:54:40 +00001211 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001212 }
njn8c0b3bb2005-03-12 21:20:39 +00001213 skip_arg:
sewardj45f4e7c2005-09-27 19:20:21 +00001214 if (arg != VG_(args_for_valgrind).strs[i]) {
1215 VG_(free)(arg);
1216 }
sewardjde4a1d02002-03-22 01:27:54 +00001217 }
1218
sewardj998d40d2004-12-06 14:24:52 +00001219 /* Make VEX control parameters sane */
1220
1221 if (VG_(clo_vex_control).guest_chase_thresh
1222 >= VG_(clo_vex_control).guest_max_insns)
1223 VG_(clo_vex_control).guest_chase_thresh
1224 = VG_(clo_vex_control).guest_max_insns - 1;
1225
1226 if (VG_(clo_vex_control).guest_chase_thresh < 0)
1227 VG_(clo_vex_control).guest_chase_thresh = 0;
1228
1229 /* Check various option values */
nethercote27fec902004-06-16 21:26:32 +00001230
njnf9ebf672003-05-12 21:41:30 +00001231 if (VG_(clo_verbosity) < 0)
sewardjde4a1d02002-03-22 01:27:54 +00001232 VG_(clo_verbosity) = 0;
1233
nethercote04d0fbc2004-01-26 16:48:06 +00001234 if (VG_(clo_db_attach) && VG_(clo_trace_children)) {
sewardjde4a1d02002-03-22 01:27:54 +00001235 VG_(message)(Vg_UserMsg, "");
1236 VG_(message)(Vg_UserMsg,
nethercote04d0fbc2004-01-26 16:48:06 +00001237 "--db-attach=yes conflicts with --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001238 VG_(message)(Vg_UserMsg,
1239 "Please choose one or the other, but not both.");
nethercote04d0fbc2004-01-26 16:48:06 +00001240 VG_(bad_option)("--db-attach=yes and --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001241 }
1242
njnbe9b47b2005-05-15 16:22:58 +00001243 if (VG_(clo_gen_suppressions) > 0 &&
1244 !VG_(needs).core_errors && !VG_(needs).tool_errors) {
1245 VG_(message)(Vg_UserMsg,
1246 "Can't use --gen-suppressions= with this tool,");
1247 VG_(message)(Vg_UserMsg,
1248 "as it doesn't generate errors.");
1249 VG_(bad_option)("--gen-suppressions=");
1250 }
1251
sewardj71bc3cb2005-05-19 00:25:45 +00001252 /* If we've been asked to emit XML, mash around various other
1253 options so as to constrain the output somewhat, and to remove
1254 any need for user input during the run. */
1255 if (VG_(clo_xml)) {
1256 /* Disable suppression generation (requires user input) */
1257 VG_(clo_gen_suppressions) = 0;
1258 /* Disable attaching to GDB (requires user input) */
1259 VG_(clo_db_attach) = False;
1260 /* Set a known verbosity level */
1261 VG_(clo_verbosity) = 1;
1262 /* Disable error limits (this might be a bad idea!) */
1263 VG_(clo_error_limit) = False;
1264 /* Disable emulation warnings */
1265 VG_(clo_show_emwarns) = False;
1266 /* Disable waiting for GDB to debug Valgrind */
1267 VG_(clo_wait_for_gdb) = False;
1268 /* No file-descriptor leak checking yet */
1269 VG_(clo_track_fds) = False;
sewardj21f7f0c2005-07-06 19:46:48 +00001270 /* Disable timestamped output */
1271 VG_(clo_time_stamp) = False;
sewardj71bc3cb2005-05-19 00:25:45 +00001272 /* Also, we want to set options for the leak checker, but that
1273 will have to be done in Memcheck's flag-handling code, not
1274 here. */
1275 }
1276
njnbe9b47b2005-05-15 16:22:58 +00001277 /* All non-logging-related options have been checked. If the logging
1278 option specified is ok, we can switch to it, as we know we won't
1279 have to generate any other command-line-related error messages.
1280 (So far we should be still attached to stderr, so we can show on
1281 the terminal any problems to do with processing command line
1282 opts.)
1283
1284 So set up logging now. After this is done, VG_(clo_log_fd)
sewardj4cf05692002-10-27 20:28:29 +00001285 should be connected to whatever sink has been selected, and we
1286 indiscriminately chuck stuff into it without worrying what the
1287 nature of it is. Oh the wonder of Unix streams. */
1288
njnbe9b47b2005-05-15 16:22:58 +00001289 vg_assert(VG_(clo_log_fd) == 2 /* stderr */);
1290 vg_assert(VG_(logging_to_socket) == False);
sewardj4cf05692002-10-27 20:28:29 +00001291
njnbe9b47b2005-05-15 16:22:58 +00001292 switch (log_to) {
sewardj73cf3bc2002-11-03 03:20:15 +00001293
sewardj4cf05692002-10-27 20:28:29 +00001294 case VgLogTo_Fd:
nethercotef8548672004-06-21 12:42:35 +00001295 vg_assert(VG_(clo_log_name) == NULL);
1296 VG_(clo_log_fd) = eventually_log_fd;
sewardj4cf05692002-10-27 20:28:29 +00001297 break;
sewardj73cf3bc2002-11-03 03:20:15 +00001298
sewardj4cf05692002-10-27 20:28:29 +00001299 case VgLogTo_File: {
sewardjad311162005-07-19 11:25:02 +00001300 HChar logfilename[1000];
1301 Int seq = 0;
1302 Int pid = VG_(getpid)();
1303 HChar* qual = NULL;
jsgff3c3f1a2003-10-14 22:13:28 +00001304
nethercotef8548672004-06-21 12:42:35 +00001305 vg_assert(VG_(clo_log_name) != NULL);
1306 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
jsgff3c3f1a2003-10-14 22:13:28 +00001307
sewardjad311162005-07-19 11:25:02 +00001308 if (VG_(clo_log_file_qualifier)) {
1309 qual = VG_(getenv)(VG_(clo_log_file_qualifier));
1310 }
1311
nethercote71980f02004-01-24 18:18:54 +00001312 for (;;) {
sewardj92645592005-07-23 09:18:34 +00001313 HChar pidtxt[20], seqtxt[20];
1314
1315 VG_(sprintf)(pidtxt, "%d", pid);
1316
1317 if (seq == 0)
1318 seqtxt[0] = 0;
1319 else
1320 VG_(sprintf)(seqtxt, ".%d", seq);
1321
jsgff3c3f1a2003-10-14 22:13:28 +00001322 seq++;
1323
sewardj92645592005-07-23 09:18:34 +00001324 /* Result:
1325 if (qual) base_name ++ "." ++ qual ++ seqtxt
1326 if (not qual) base_name ++ "." ++ pid ++ seqtxt
1327 */
1328 VG_(sprintf)( logfilename,
1329 "%s.%s%s",
1330 VG_(clo_log_name),
1331 qual ? qual : pidtxt,
1332 seqtxt );
1333
njnbe9b47b2005-05-15 16:22:58 +00001334 // EXCL: it will fail with EEXIST if the file already exists.
sewardj92645592005-07-23 09:18:34 +00001335 sres
jsgff3c3f1a2003-10-14 22:13:28 +00001336 = VG_(open)(logfilename,
1337 VKI_O_CREAT|VKI_O_WRONLY|VKI_O_EXCL|VKI_O_TRUNC,
1338 VKI_S_IRUSR|VKI_S_IWUSR);
sewardj92645592005-07-23 09:18:34 +00001339 if (!sres.isError) {
1340 eventually_log_fd = sres.val;
nethercotef8548672004-06-21 12:42:35 +00001341 VG_(clo_log_fd) = VG_(safe_fd)(eventually_log_fd);
sewardj603d4102005-01-11 14:01:02 +00001342 break; /* for (;;) */
jsgff3c3f1a2003-10-14 22:13:28 +00001343 } else {
njnbe9b47b2005-05-15 16:22:58 +00001344 // If the file already existed, we try the next name. If it
1345 // was some other file error, we give up.
sewardj92645592005-07-23 09:18:34 +00001346 if (sres.val != VKI_EEXIST) {
jsgff3c3f1a2003-10-14 22:13:28 +00001347 VG_(message)(Vg_UserMsg,
njn02bc4b82005-05-15 17:28:26 +00001348 "Can't create/open log file '%s.pid%d'; giving up!",
nethercotef8548672004-06-21 12:42:35 +00001349 VG_(clo_log_name), pid);
jsgff3c3f1a2003-10-14 22:13:28 +00001350 VG_(bad_option)(
sewardj603d4102005-01-11 14:01:02 +00001351 "--log-file=<file> (didn't work out for some reason.)");
njnbe9b47b2005-05-15 16:22:58 +00001352 /*NOTREACHED*/
jsgff3c3f1a2003-10-14 22:13:28 +00001353 }
1354 }
1355 }
sewardj603d4102005-01-11 14:01:02 +00001356 break; /* switch (VG_(clo_log_to)) */
1357 }
1358
1359 case VgLogTo_FileExactly: {
sewardj603d4102005-01-11 14:01:02 +00001360 vg_assert(VG_(clo_log_name) != NULL);
1361 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
sewardj603d4102005-01-11 14:01:02 +00001362
sewardj92645592005-07-23 09:18:34 +00001363 sres
njnbe9b47b2005-05-15 16:22:58 +00001364 = VG_(open)(VG_(clo_log_name),
sewardj603d4102005-01-11 14:01:02 +00001365 VKI_O_CREAT|VKI_O_WRONLY|VKI_O_TRUNC,
1366 VKI_S_IRUSR|VKI_S_IWUSR);
sewardj92645592005-07-23 09:18:34 +00001367 if (!sres.isError) {
1368 eventually_log_fd = sres.val;
sewardj603d4102005-01-11 14:01:02 +00001369 VG_(clo_log_fd) = VG_(safe_fd)(eventually_log_fd);
njnbe9b47b2005-05-15 16:22:58 +00001370 } else {
sewardj603d4102005-01-11 14:01:02 +00001371 VG_(message)(Vg_UserMsg,
njn02bc4b82005-05-15 17:28:26 +00001372 "Can't create/open log file '%s'; giving up!",
sewardj603d4102005-01-11 14:01:02 +00001373 VG_(clo_log_name));
1374 VG_(bad_option)(
1375 "--log-file-exactly=<file> (didn't work out for some reason.)");
1376 /*NOTREACHED*/
1377 }
1378 break; /* switch (VG_(clo_log_to)) */
sewardj73cf3bc2002-11-03 03:20:15 +00001379 }
1380
1381 case VgLogTo_Socket: {
nethercotef8548672004-06-21 12:42:35 +00001382 vg_assert(VG_(clo_log_name) != NULL);
1383 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
1384 eventually_log_fd = VG_(connect_via_socket)( VG_(clo_log_name) );
1385 if (eventually_log_fd == -1) {
sewardj73cf3bc2002-11-03 03:20:15 +00001386 VG_(message)(Vg_UserMsg,
nethercotef8548672004-06-21 12:42:35 +00001387 "Invalid --log-socket=ipaddr or --log-socket=ipaddr:port spec");
sewardj73cf3bc2002-11-03 03:20:15 +00001388 VG_(message)(Vg_UserMsg,
njn02bc4b82005-05-15 17:28:26 +00001389 "of '%s'; giving up!", VG_(clo_log_name) );
sewardj73cf3bc2002-11-03 03:20:15 +00001390 VG_(bad_option)(
nethercotef8548672004-06-21 12:42:35 +00001391 "--log-socket=");
njnbe9b47b2005-05-15 16:22:58 +00001392 /*NOTREACHED*/
sewardj4cf05692002-10-27 20:28:29 +00001393 }
nethercotef8548672004-06-21 12:42:35 +00001394 if (eventually_log_fd == -2) {
sewardj73cf3bc2002-11-03 03:20:15 +00001395 VG_(message)(Vg_UserMsg,
njn02bc4b82005-05-15 17:28:26 +00001396 "valgrind: failed to connect to logging server '%s'.",
nethercotef8548672004-06-21 12:42:35 +00001397 VG_(clo_log_name) );
sewardj570f8902002-11-03 11:44:36 +00001398 VG_(message)(Vg_UserMsg,
1399 "Log messages will sent to stderr instead." );
1400 VG_(message)(Vg_UserMsg,
1401 "" );
1402 /* We don't change anything here. */
njnbe9b47b2005-05-15 16:22:58 +00001403 vg_assert(VG_(clo_log_fd) == 2);
sewardj570f8902002-11-03 11:44:36 +00001404 } else {
nethercotef8548672004-06-21 12:42:35 +00001405 vg_assert(eventually_log_fd > 0);
1406 VG_(clo_log_fd) = eventually_log_fd;
njnbe9b47b2005-05-15 16:22:58 +00001407 VG_(logging_to_socket) = True;
sewardj570f8902002-11-03 11:44:36 +00001408 }
sewardj73cf3bc2002-11-03 03:20:15 +00001409 break;
1410 }
sewardj4cf05692002-10-27 20:28:29 +00001411 }
1412
sewardj71bc3cb2005-05-19 00:25:45 +00001413
1414 /* Check that the requested tool actually supports XML output. */
sewardj45f4e7c2005-09-27 19:20:21 +00001415 if (VG_(clo_xml) && !VG_STREQ(toolname, "memcheck")
1416 && !VG_STREQ(toolname, "none")) {
sewardj71bc3cb2005-05-19 00:25:45 +00001417 VG_(clo_xml) = False;
1418 VG_(message)(Vg_UserMsg,
cerion39655202005-07-13 14:18:24 +00001419 "Currently only Memcheck|None supports XML output.");
sewardj71bc3cb2005-05-19 00:25:45 +00001420 VG_(bad_option)("--xml=yes");
1421 /*NOTREACHED*/
1422 }
1423
njnbe9b47b2005-05-15 16:22:58 +00001424 // Move log_fd into the safe range, so it doesn't conflict with any app fds.
1425 // XXX: this is more or less duplicating the behaviour of the calls to
1426 // VG_(safe_fd)() above, although this does not close the original fd.
1427 // Perhaps the VG_(safe_fd)() calls above should be removed, and this
1428 // code should be replaced with a call to VG_(safe_fd)(). --njn
thughesad1c9562004-06-26 11:27:52 +00001429 eventually_log_fd = VG_(fcntl)(VG_(clo_log_fd), VKI_F_DUPFD, VG_(fd_hard_limit));
nethercotef8548672004-06-21 12:42:35 +00001430 if (eventually_log_fd < 0)
jsgf855d93d2003-10-13 22:26:55 +00001431 VG_(message)(Vg_UserMsg, "valgrind: failed to move logfile fd into safe range");
1432 else {
nethercotef8548672004-06-21 12:42:35 +00001433 VG_(clo_log_fd) = eventually_log_fd;
1434 VG_(fcntl)(VG_(clo_log_fd), VKI_F_SETFD, VKI_FD_CLOEXEC);
jsgf855d93d2003-10-13 22:26:55 +00001435 }
1436
sewardj45f4e7c2005-09-27 19:20:21 +00001437 if (VG_(clo_n_suppressions) < VG_CLO_MAX_SFILES-1 &&
1438 (VG_(needs).core_errors || VG_(needs).tool_errors)) {
1439 /* If we haven't reached the max number of suppressions, load
1440 the default one. */
1441 static const Char default_supp[] = "default.supp";
1442 Int len = VG_(strlen)(VG_(libdir)) + 1 + sizeof(default_supp);
1443 Char *buf = VG_(arena_malloc)(VG_AR_CORE, len);
1444 VG_(sprintf)(buf, "%s/%s", VG_(libdir), default_supp);
1445 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = buf;
1446 VG_(clo_n_suppressions)++;
1447 }
sewardjde4a1d02002-03-22 01:27:54 +00001448
sewardj45f4e7c2005-09-27 19:20:21 +00001449 return (log_to == VgLogTo_Fd);
1450}
1451
1452
1453/*====================================================================*/
1454/*=== Printing the preamble ===*/
1455/*====================================================================*/
1456
1457/* Ok, the logging sink is running now. Print a suitable preamble.
1458 If logging to file or a socket, write details of parent PID and
1459 command line args, to help people trying to interpret the
1460 results of a run which encompasses multiple processes. */
1461static void print_preamble(Bool logging_to_fd, const char* toolname)
1462{
1463 Int i;
1464
sewardj71bc3cb2005-05-19 00:25:45 +00001465 if (VG_(clo_xml)) {
sewardj8665d8e2005-06-01 17:35:23 +00001466 VG_(message)(Vg_UserMsg, "<?xml version=\"1.0\"?>");
1467 VG_(message)(Vg_UserMsg, "");
sewardj71bc3cb2005-05-19 00:25:45 +00001468 VG_(message)(Vg_UserMsg, "<valgrindoutput>");
1469 VG_(message)(Vg_UserMsg, "");
1470 VG_(message)(Vg_UserMsg, "<protocolversion>1</protocolversion>");
1471 VG_(message)(Vg_UserMsg, "");
1472 }
1473
sewardjd7bddad2005-06-13 16:48:32 +00001474 HChar* xpre = VG_(clo_xml) ? " <line>" : "";
1475 HChar* xpost = VG_(clo_xml) ? "</line>" : "";
sewardj71bc3cb2005-05-19 00:25:45 +00001476
sewardj83adf412002-05-01 01:25:45 +00001477 if (VG_(clo_verbosity > 0)) {
sewardjd7bddad2005-06-13 16:48:32 +00001478
1479 if (VG_(clo_xml))
1480 VG_(message)(Vg_UserMsg, "<preamble>");
1481
nethercote996901a2004-08-03 13:29:09 +00001482 /* Tool details */
sewardj71bc3cb2005-05-19 00:25:45 +00001483 VG_(message)(Vg_UserMsg, "%s%s%s%s, %s.%s",
1484 xpre,
njnd04b7c62002-10-03 14:05:52 +00001485 VG_(details).name,
njnb9c427c2004-12-01 14:14:42 +00001486 NULL == VG_(details).version ? "" : "-",
njnd04b7c62002-10-03 14:05:52 +00001487 NULL == VG_(details).version
1488 ? (Char*)"" : VG_(details).version,
sewardj71bc3cb2005-05-19 00:25:45 +00001489 VG_(details).description,
1490 xpost);
1491 VG_(message)(Vg_UserMsg, "%s%s%s",
1492 xpre, VG_(details).copyright_author, xpost);
sewardj3b2736a2002-03-24 12:18:35 +00001493
njnd04b7c62002-10-03 14:05:52 +00001494 /* Core details */
1495 VG_(message)(Vg_UserMsg,
sewardj71bc3cb2005-05-19 00:25:45 +00001496 "%sUsing LibVEX rev %s, a library for dynamic binary translation.%s",
1497 xpre, LibVEX_Version(), xpost );
sewardjc7025332004-12-13 18:30:39 +00001498 VG_(message)(Vg_UserMsg,
sewardj71bc3cb2005-05-19 00:25:45 +00001499 "%sCopyright (C) 2004-2005, and GNU GPL'd, by OpenWorks LLP.%s",
1500 xpre, xpost );
sewardjc7025332004-12-13 18:30:39 +00001501 VG_(message)(Vg_UserMsg,
sewardj71bc3cb2005-05-19 00:25:45 +00001502 "%sUsing valgrind-%s, a dynamic binary instrumentation framework.%s",
1503 xpre, VERSION, xpost);
sewardjde4a1d02002-03-22 01:27:54 +00001504 VG_(message)(Vg_UserMsg,
sewardj71bc3cb2005-05-19 00:25:45 +00001505 "%sCopyright (C) 2000-2005, and GNU GPL'd, by Julian Seward et al.%s",
1506 xpre, xpost );
sewardjd7bddad2005-06-13 16:48:32 +00001507
sewardj45f4e7c2005-09-27 19:20:21 +00001508 if (VG_(clo_verbosity) == 1 && !VG_(clo_xml))
1509 VG_(message)(Vg_UserMsg, "For more details, rerun with: -v");
1510
sewardjd7bddad2005-06-13 16:48:32 +00001511 if (VG_(clo_xml))
1512 VG_(message)(Vg_UserMsg, "</preamble>");
njnd04b7c62002-10-03 14:05:52 +00001513 }
1514
sewardj45f4e7c2005-09-27 19:20:21 +00001515 if (!VG_(clo_xml) && VG_(clo_verbosity) > 0 && !logging_to_fd) {
sewardj4cf05692002-10-27 20:28:29 +00001516 VG_(message)(Vg_UserMsg, "");
1517 VG_(message)(Vg_UserMsg,
1518 "My PID = %d, parent PID = %d. Prog and args are:",
1519 VG_(getpid)(), VG_(getppid)() );
sewardj45f4e7c2005-09-27 19:20:21 +00001520 for (i = 0; i < VG_(args_for_client).used; i++)
1521 VG_(message)(Vg_UserMsg, " %s", VG_(args_for_client).strs[i]);
sewardj5b742c32005-07-26 23:43:26 +00001522 if (VG_(clo_log_file_qualifier)) {
1523 HChar* val = VG_(getenv)(VG_(clo_log_file_qualifier));
1524 VG_(message)(Vg_UserMsg, "");
1525 VG_(message)(Vg_UserMsg, "Log file qualifier: var %s, value %s.",
1526 VG_(clo_log_file_qualifier),
1527 val ? val : "");
1528 }
sewardj4cf05692002-10-27 20:28:29 +00001529 }
sewardj71bc3cb2005-05-19 00:25:45 +00001530 else
1531 if (VG_(clo_xml)) {
1532 VG_(message)(Vg_UserMsg, "");
1533 VG_(message)(Vg_UserMsg, "<pid>%d</pid>", VG_(getpid)());
1534 VG_(message)(Vg_UserMsg, "<ppid>%d</ppid>", VG_(getppid)());
sewardj97f7e0c2005-07-19 15:00:25 +00001535 VG_(message)(Vg_UserMsg, "<tool>%t</tool>", toolname);
sewardjad311162005-07-19 11:25:02 +00001536 if (VG_(clo_log_file_qualifier)) {
1537 HChar* val = VG_(getenv)(VG_(clo_log_file_qualifier));
sewardj97f7e0c2005-07-19 15:00:25 +00001538 VG_(message)(Vg_UserMsg, "<logfilequalifier> <var>%t</var> "
1539 "<value>%t</value> </logfilequalifier>",
sewardjad311162005-07-19 11:25:02 +00001540 VG_(clo_log_file_qualifier),
1541 val ? val : "");
1542 }
sewardj768db0e2005-07-19 14:18:56 +00001543 if (VG_(clo_xml_user_comment)) {
1544 /* Note: the user comment itself is XML and is therefore to
1545 be passed through verbatim (%s) rather than escaped
1546 (%t). */
1547 VG_(message)(Vg_UserMsg, "<usercomment>%s</usercomment>",
1548 VG_(clo_xml_user_comment));
1549 }
sewardj71bc3cb2005-05-19 00:25:45 +00001550 VG_(message)(Vg_UserMsg, "");
sewardjb8a3dac2005-07-19 12:39:11 +00001551 VG_(message)(Vg_UserMsg, "<args>");
sewardj45f4e7c2005-09-27 19:20:21 +00001552
sewardjb8a3dac2005-07-19 12:39:11 +00001553 VG_(message)(Vg_UserMsg, " <vargv>");
sewardj45f4e7c2005-09-27 19:20:21 +00001554 if (VG_(name_of_launcher))
1555 VG_(message)(Vg_UserMsg, " <exe>%t</exe>",
1556 VG_(name_of_launcher));
1557 for (i = 0; i < VG_(args_for_valgrind).used; i++) {
1558 VG_(message)(Vg_UserMsg,
1559 " <arg>%t</arg>",
1560 VG_(args_for_valgrind).strs[i]);
sewardjb8a3dac2005-07-19 12:39:11 +00001561 }
1562 VG_(message)(Vg_UserMsg, " </vargv>");
sewardj45f4e7c2005-09-27 19:20:21 +00001563
sewardjb8a3dac2005-07-19 12:39:11 +00001564 VG_(message)(Vg_UserMsg, " <argv>");
sewardj45f4e7c2005-09-27 19:20:21 +00001565 if (VG_(args_the_exename))
1566 VG_(message)(Vg_UserMsg, " <exe>%t</exe>",
1567 VG_(args_the_exename));
1568 for (i = 0; i < VG_(args_for_client).used; i++) {
1569 VG_(message)(Vg_UserMsg, " <arg>%t</arg>",
1570 VG_(args_for_client).strs[i]);
sewardj8665d8e2005-06-01 17:35:23 +00001571 }
sewardjb8a3dac2005-07-19 12:39:11 +00001572 VG_(message)(Vg_UserMsg, " </argv>");
sewardj45f4e7c2005-09-27 19:20:21 +00001573
sewardjb8a3dac2005-07-19 12:39:11 +00001574 VG_(message)(Vg_UserMsg, "</args>");
sewardj71bc3cb2005-05-19 00:25:45 +00001575 }
sewardj4cf05692002-10-27 20:28:29 +00001576
sewardj45f4e7c2005-09-27 19:20:21 +00001577 // Empty line after the preamble
1578 if (VG_(clo_verbosity) > 0)
1579 VG_(message)(Vg_UserMsg, "");
1580
sewardjde4a1d02002-03-22 01:27:54 +00001581 if (VG_(clo_verbosity) > 1) {
sewardj92645592005-07-23 09:18:34 +00001582 SysRes fd;
sewardj45f4e7c2005-09-27 19:20:21 +00001583 if (!logging_to_fd)
njn1fd5eb22005-03-13 05:43:23 +00001584 VG_(message)(Vg_DebugMsg, "");
1585 VG_(message)(Vg_DebugMsg, "Valgrind library directory: %s", VG_(libdir));
sewardj45f4e7c2005-09-27 19:20:21 +00001586
njn1fd5eb22005-03-13 05:43:23 +00001587 VG_(message)(Vg_DebugMsg, "Command line");
sewardj45f4e7c2005-09-27 19:20:21 +00001588 if (VG_(args_the_exename))
1589 VG_(message)(Vg_DebugMsg, " %s", VG_(args_the_exename));
1590 for (i = 0; i < VG_(args_for_client).used; i++)
1591 VG_(message)(Vg_DebugMsg, " %s", VG_(args_for_client).strs[i]);
njn86dc2bc2003-09-09 07:26:21 +00001592
njn1fd5eb22005-03-13 05:43:23 +00001593 VG_(message)(Vg_DebugMsg, "Startup, with flags:");
sewardj45f4e7c2005-09-27 19:20:21 +00001594 for (i = 0; i < VG_(args_for_valgrind).used; i++) {
1595 VG_(message)(Vg_DebugMsg, " %s", VG_(args_for_valgrind).strs[i]);
sewardjde4a1d02002-03-22 01:27:54 +00001596 }
nethercotea70f7352004-04-18 12:08:46 +00001597
njn1fd5eb22005-03-13 05:43:23 +00001598 VG_(message)(Vg_DebugMsg, "Contents of /proc/version:");
nethercotea70f7352004-04-18 12:08:46 +00001599 fd = VG_(open) ( "/proc/version", VKI_O_RDONLY, 0 );
sewardj92645592005-07-23 09:18:34 +00001600 if (fd.isError) {
njn1fd5eb22005-03-13 05:43:23 +00001601 VG_(message)(Vg_DebugMsg, " can't open /proc/version");
nethercotea70f7352004-04-18 12:08:46 +00001602 } else {
sewardj71bc3cb2005-05-19 00:25:45 +00001603# define BUF_LEN 256
nethercotea70f7352004-04-18 12:08:46 +00001604 Char version_buf[BUF_LEN];
sewardj92645592005-07-23 09:18:34 +00001605 Int n = VG_(read) ( fd.val, version_buf, BUF_LEN );
njnbe9b47b2005-05-15 16:22:58 +00001606 vg_assert(n <= BUF_LEN);
nethercotea70f7352004-04-18 12:08:46 +00001607 if (n > 0) {
1608 version_buf[n-1] = '\0';
njn1fd5eb22005-03-13 05:43:23 +00001609 VG_(message)(Vg_DebugMsg, " %s", version_buf);
nethercotea70f7352004-04-18 12:08:46 +00001610 } else {
njn1fd5eb22005-03-13 05:43:23 +00001611 VG_(message)(Vg_DebugMsg, " (empty?)");
nethercotea70f7352004-04-18 12:08:46 +00001612 }
sewardj92645592005-07-23 09:18:34 +00001613 VG_(close)(fd.val);
sewardj71bc3cb2005-05-19 00:25:45 +00001614# undef BUF_LEN
nethercotea70f7352004-04-18 12:08:46 +00001615 }
sewardjde4a1d02002-03-22 01:27:54 +00001616 }
nethercotef6a1d502004-08-09 12:21:57 +00001617}
1618
sewardjde4a1d02002-03-22 01:27:54 +00001619
nethercote71980f02004-01-24 18:18:54 +00001620/*====================================================================*/
1621/*=== File descriptor setup ===*/
1622/*====================================================================*/
1623
1624static void setup_file_descriptors(void)
1625{
1626 struct vki_rlimit rl;
1627
1628 /* Get the current file descriptor limits. */
1629 if (VG_(getrlimit)(VKI_RLIMIT_NOFILE, &rl) < 0) {
1630 rl.rlim_cur = 1024;
1631 rl.rlim_max = 1024;
1632 }
1633
1634 /* Work out where to move the soft limit to. */
njn14319cc2005-03-13 06:26:22 +00001635 if (rl.rlim_cur + N_RESERVED_FDS <= rl.rlim_max) {
1636 rl.rlim_cur = rl.rlim_cur + N_RESERVED_FDS;
nethercote71980f02004-01-24 18:18:54 +00001637 } else {
1638 rl.rlim_cur = rl.rlim_max;
1639 }
1640
1641 /* Reserve some file descriptors for our use. */
njn14319cc2005-03-13 06:26:22 +00001642 VG_(fd_soft_limit) = rl.rlim_cur - N_RESERVED_FDS;
1643 VG_(fd_hard_limit) = rl.rlim_cur - N_RESERVED_FDS;
nethercote71980f02004-01-24 18:18:54 +00001644
1645 /* Update the soft limit. */
1646 VG_(setrlimit)(VKI_RLIMIT_NOFILE, &rl);
1647
sewardj45f4e7c2005-09-27 19:20:21 +00001648 if (VG_(cl_exec_fd) != -1)
1649 VG_(cl_exec_fd) = VG_(safe_fd)( VG_(cl_exec_fd) );
nethercote71980f02004-01-24 18:18:54 +00001650}
1651
sewardjde4a1d02002-03-22 01:27:54 +00001652
njn2da73352005-06-18 01:35:16 +00001653/*====================================================================*/
1654/*=== Initialise the first thread. ===*/
1655/*====================================================================*/
1656
1657/* Given a pointer to the ThreadArchState for thread 1 (the root
1658 thread), initialise the VEX guest state, and copy in essential
1659 starting values.
1660*/
1661static void init_thread1state ( Addr client_ip,
sewardjfdf91b42005-09-28 00:53:09 +00001662 Addr client_sp,
njn2da73352005-06-18 01:35:16 +00001663 /*inout*/ ThreadArchState* arch )
1664{
1665#if defined(VGA_x86)
1666 vg_assert(0 == sizeof(VexGuestX86State) % 8);
1667
1668 /* Zero out the initial state, and set up the simulated FPU in a
1669 sane way. */
1670 LibVEX_GuestX86_initialise(&arch->vex);
1671
1672 /* Zero out the shadow area. */
1673 VG_(memset)(&arch->vex_shadow, 0, sizeof(VexGuestX86State));
1674
1675 /* Put essential stuff into the new state. */
sewardjfdf91b42005-09-28 00:53:09 +00001676 arch->vex.guest_ESP = client_sp;
njn2da73352005-06-18 01:35:16 +00001677 arch->vex.guest_EIP = client_ip;
1678
1679 /* initialise %cs, %ds and %ss to point at the operating systems
1680 default code, data and stack segments */
1681 asm volatile("movw %%cs, %0" : : "m" (arch->vex.guest_CS));
1682 asm volatile("movw %%ds, %0" : : "m" (arch->vex.guest_DS));
1683 asm volatile("movw %%ss, %0" : : "m" (arch->vex.guest_SS));
cerion85665ca2005-06-20 15:51:07 +00001684
njn2da73352005-06-18 01:35:16 +00001685#elif defined(VGA_amd64)
1686 vg_assert(0 == sizeof(VexGuestAMD64State) % 8);
1687
1688 /* Zero out the initial state, and set up the simulated FPU in a
1689 sane way. */
1690 LibVEX_GuestAMD64_initialise(&arch->vex);
1691
1692 /* Zero out the shadow area. */
1693 VG_(memset)(&arch->vex_shadow, 0, sizeof(VexGuestAMD64State));
1694
1695 /* Put essential stuff into the new state. */
sewardjfdf91b42005-09-28 00:53:09 +00001696 arch->vex.guest_RSP = client_sp;
njn2da73352005-06-18 01:35:16 +00001697 arch->vex.guest_RIP = client_ip;
cerion85665ca2005-06-20 15:51:07 +00001698
1699#elif defined(VGA_ppc32)
1700 vg_assert(0 == sizeof(VexGuestPPC32State) % 8);
1701
1702 /* Zero out the initial state, and set up the simulated FPU in a
1703 sane way. */
1704 LibVEX_GuestPPC32_initialise(&arch->vex);
1705
1706 /* Zero out the shadow area. */
1707 VG_(memset)(&arch->vex_shadow, 0, sizeof(VexGuestPPC32State));
1708
1709 /* Put essential stuff into the new state. */
sewardjfdf91b42005-09-28 00:53:09 +00001710 arch->vex.guest_GPR1 = client_sp;
cerion85665ca2005-06-20 15:51:07 +00001711 arch->vex.guest_CIA = client_ip;
1712
njn2da73352005-06-18 01:35:16 +00001713#else
1714# error Unknown arch
1715#endif
1716 // Tell the tool that we just wrote to the registers.
1717 VG_TRACK( post_reg_write, Vg_CoreStartup, /*tid*/1, /*offset*/0,
1718 sizeof(VexGuestArchState));
1719}
1720
sewardjde4a1d02002-03-22 01:27:54 +00001721
nethercote71980f02004-01-24 18:18:54 +00001722/*====================================================================*/
njn2025cf92005-06-26 20:44:48 +00001723/*=== BB profiling ===*/
1724/*====================================================================*/
1725
1726static
1727void show_BB_profile ( BBProfEntry tops[], UInt n_tops, ULong score_total )
1728{
1729 ULong score_cumul, score_here;
1730 Char buf_cumul[10], buf_here[10];
1731 Char name[64];
1732 Int r;
1733
1734 VG_(printf)("\n");
1735 VG_(printf)("-----------------------------------------------------------\n");
1736 VG_(printf)("--- BEGIN BB Profile (summary of scores) ---\n");
1737 VG_(printf)("-----------------------------------------------------------\n");
1738 VG_(printf)("\n");
1739
1740 VG_(printf)("Total score = %lld\n\n", score_total);
1741
1742 score_cumul = 0;
1743 for (r = 0; r < n_tops; r++) {
1744 if (tops[r].addr == 0)
1745 continue;
1746 name[0] = 0;
1747 VG_(get_fnname_w_offset)(tops[r].addr, name, 64);
1748 name[63] = 0;
1749 score_here = tops[r].score;
1750 score_cumul += score_here;
1751 VG_(percentify)(score_cumul, score_total, 2, 6, buf_cumul);
1752 VG_(percentify)(score_here, score_total, 2, 6, buf_here);
1753 VG_(printf)("%3d: (%9lld %s) %9lld %s 0x%llx %s\n",
1754 r,
1755 score_cumul, buf_cumul,
1756 score_here, buf_here, tops[r].addr, name );
1757 }
1758
1759 VG_(printf)("\n");
1760 VG_(printf)("-----------------------------------------------------------\n");
1761 VG_(printf)("--- BB Profile (BB details) ---\n");
1762 VG_(printf)("-----------------------------------------------------------\n");
1763 VG_(printf)("\n");
1764
1765 score_cumul = 0;
1766 for (r = 0; r < n_tops; r++) {
1767 if (tops[r].addr == 0)
1768 continue;
1769 name[0] = 0;
1770 VG_(get_fnname_w_offset)(tops[r].addr, name, 64);
1771 name[63] = 0;
1772 score_here = tops[r].score;
1773 score_cumul += score_here;
1774 VG_(percentify)(score_cumul, score_total, 2, 6, buf_cumul);
1775 VG_(percentify)(score_here, score_total, 2, 6, buf_here);
1776 VG_(printf)("\n");
1777 VG_(printf)("=-=-=-=-=-=-=-=-=-=-=-=-=-= begin BB rank %d "
1778 "=-=-=-=-=-=-=-=-=-=-=-=-=-=\n\n", r);
1779 VG_(printf)("%3d: (%9lld %s) %9lld %s 0x%llx %s\n",
1780 r,
1781 score_cumul, buf_cumul,
1782 score_here, buf_here, tops[r].addr, name );
1783 VG_(printf)("\n");
1784 VG_(translate)(0, tops[r].addr, True, VG_(clo_profile_flags), 0);
1785 VG_(printf)("=-=-=-=-=-=-=-=-=-=-=-=-=-= end BB rank %d "
1786 "=-=-=-=-=-=-=-=-=-=-=-=-=-=\n\n", r);
1787 }
1788
1789 VG_(printf)("\n");
1790 VG_(printf)("-----------------------------------------------------------\n");
1791 VG_(printf)("--- END BB Profile ---\n");
1792 VG_(printf)("-----------------------------------------------------------\n");
1793 VG_(printf)("\n");
1794}
1795
1796
1797/*====================================================================*/
nethercote71980f02004-01-24 18:18:54 +00001798/*=== main() ===*/
1799/*====================================================================*/
1800
sewardjfdf91b42005-09-28 00:53:09 +00001801/* When main() is entered, we should be on the following stack, not
1802 the one the kernel gave us. We will run on this stack until
1803 simulation of the root thread is started, at which point a transfer
1804 is made to a dynamically allocated stack. This is for the sake of
1805 uniform overflow detection for all Valgrind threads. This is
1806 marked global even though it isn't, because assembly code below
1807 needs to reference the name. */
1808
1809/*static*/ VgStack VG_(interim_stack);
1810
1811/* This should get some address inside the stack on which we gained
1812 control (eg, it could be the SP at startup). It doesn't matter
1813 exactly where in the stack it is. This value is passed to the
1814 address space manager at startup, which uses it to identify the
1815 initial stack segment and hence the upper end of the usable address
1816 space. */
1817
1818static Addr sp_at_startup = 0;
1819
1820
1821
sewardj45f4e7c2005-09-27 19:20:21 +00001822/* TODO: GIVE THIS A PROPER HOME
1823 TODO: MERGE THIS WITH DUPLICATE IN mac_leakcheck.c
1824 Extract from aspacem a vector of the current segment start
1825 addresses. The vector is dynamically allocated and should be freed
1826 by the caller when done. REQUIRES m_mallocfree to be running.
1827 Writes the number of addresses required into *n_acquired. */
nethercotec314eba2004-07-15 12:59:41 +00001828
sewardj45f4e7c2005-09-27 19:20:21 +00001829static Addr* get_seg_starts ( /*OUT*/Int* n_acquired )
sewardj1cf558c2005-04-25 01:36:56 +00001830{
sewardj45f4e7c2005-09-27 19:20:21 +00001831 Addr* starts;
1832 Int n_starts, r;
1833
1834 n_starts = 1;
sewardj1cf558c2005-04-25 01:36:56 +00001835 while (True) {
sewardj45f4e7c2005-09-27 19:20:21 +00001836 starts = VG_(malloc)( n_starts * sizeof(Addr) );
1837 if (starts == NULL)
1838 break;
1839 r = VG_(am_get_segment_starts)( starts, n_starts );
1840 if (r >= 0)
1841 break;
1842 VG_(free)(starts);
1843 n_starts *= 2;
sewardj1cf558c2005-04-25 01:36:56 +00001844 }
sewardj45f4e7c2005-09-27 19:20:21 +00001845
1846 if (starts == NULL) {
1847 *n_acquired = 0;
1848 return NULL;
1849 }
1850
1851 *n_acquired = r;
1852 return starts;
sewardj1cf558c2005-04-25 01:36:56 +00001853}
1854
1855
sewardj45f4e7c2005-09-27 19:20:21 +00001856
sewardj45f4e7c2005-09-27 19:20:21 +00001857
1858
1859Int main(Int argc, HChar **argv, HChar **envp)
nethercote71980f02004-01-24 18:18:54 +00001860{
sewardj45f4e7c2005-09-27 19:20:21 +00001861 HChar* toolname = "memcheck"; // default to Memcheck
1862 HChar** env = NULL;
1863 Int need_help = 0; // 0 = no, 1 = --help, 2 = --help-debug
1864 Addr initial_client_IP = 0;
1865 Addr initial_client_SP = 0;
1866 Addr clstack_top = 0;
1867 SizeT clstack_max_size = 0;
1868 UInt* client_auxv;
1869 Int loglevel, i;
1870 Bool logging_to_fd;
nethercote73b526f2004-10-31 18:48:21 +00001871 struct vki_rlimit zero = { 0, 0 };
sewardj45f4e7c2005-09-27 19:20:21 +00001872 struct exeinfo info;
nethercote71980f02004-01-24 18:18:54 +00001873
1874 //============================================================
nethercote71980f02004-01-24 18:18:54 +00001875 //
sewardj45f4e7c2005-09-27 19:20:21 +00001876 // Nb: startup is complex. Prerequisites are shown at every step.
nethercote71980f02004-01-24 18:18:54 +00001877 // *** Be very careful when messing with the order ***
sewardj45f4e7c2005-09-27 19:20:21 +00001878 //
1879 // The first order of business is to get debug logging, the address
1880 // space manager and the dynamic memory manager up and running.
1881 // Once that's done, we can relax a bit.
1882 //
nethercote71980f02004-01-24 18:18:54 +00001883 //============================================================
sewardj45f4e7c2005-09-27 19:20:21 +00001884
1885 /* This is needed to make VG_(getenv) usable early. */
1886 VG_(client_envp) = (Char**)envp;
nethercote71980f02004-01-24 18:18:54 +00001887
sewardj1cf558c2005-04-25 01:36:56 +00001888 //--------------------------------------------------------------
1889 // Start up the logging mechanism
1890 // p: none
1891 //--------------------------------------------------------------
1892 /* Start the debugging-log system ASAP. First find out how many
1893 "-d"s were specified. This is a pre-scan of the command line. */
1894 loglevel = 0;
1895 for (i = 1; i < argc; i++) {
sewardj10759312005-05-30 23:52:47 +00001896 if (argv[i][0] != '-')
1897 break;
sewardj45f4e7c2005-09-27 19:20:21 +00001898 if (VG_STREQ(argv[i], "--"))
sewardj10759312005-05-30 23:52:47 +00001899 break;
sewardj45f4e7c2005-09-27 19:20:21 +00001900 if (VG_STREQ(argv[i], "-d"))
sewardj10759312005-05-30 23:52:47 +00001901 loglevel++;
sewardj1cf558c2005-04-25 01:36:56 +00001902 }
1903
1904 /* ... and start the debug logger. Now we can safely emit logging
1905 messages all through startup. */
sewardj10759312005-05-30 23:52:47 +00001906 VG_(debugLog_startup)(loglevel, "Stage 2 (main)");
sewardj45f4e7c2005-09-27 19:20:21 +00001907 VG_(debugLog)(1, "main", "Welcome to Valgrind version "
1908 VERSION " debug logging\n");
1909
1910 //--------------------------------------------------------------
1911 // Ensure we're on a plausible stack.
1912 // p: logging
1913 //--------------------------------------------------------------
1914 VG_(debugLog)(1, "main", "Checking current stack is plausible\n");
sewardjfdf91b42005-09-28 00:53:09 +00001915 { HChar* limLo = (HChar*)(&VG_(interim_stack).bytes[0]);
1916 HChar* limHi = limLo + sizeof(VG_(interim_stack));
sewardj45f4e7c2005-09-27 19:20:21 +00001917 HChar* aLocal = (HChar*)&zero; /* any auto local will do */
1918 if (aLocal < limLo || aLocal >= limHi) {
1919 /* something's wrong. Stop. */
1920 VG_(debugLog)(0, "main", "Root stack %p to %p, a local %p\n",
1921 limLo, limHi, aLocal );
1922 VG_(debugLog)(0, "main", "Valgrind: FATAL: "
1923 "Initial stack switched failed.\n");
1924 VG_(debugLog)(0, "main", " Cannot continue. Sorry.\n");
1925 VG_(exit)(1);
1926 }
1927 }
1928
1929 //--------------------------------------------------------------
1930 // Ensure we have a plausible pointer to the stack on which
1931 // we gained control (not the current stack!)
1932 // p: logging
1933 //--------------------------------------------------------------
1934 VG_(debugLog)(1, "main", "Checking initial stack was noted\n");
sewardjfdf91b42005-09-28 00:53:09 +00001935 if (sp_at_startup == 0) {
sewardj45f4e7c2005-09-27 19:20:21 +00001936 VG_(debugLog)(0, "main", "Valgrind: FATAL: "
1937 "Initial stack was not noted.\n");
1938 VG_(debugLog)(0, "main", " Cannot continue. Sorry.\n");
1939 VG_(exit)(1);
1940 }
1941
1942 //--------------------------------------------------------------
1943 // Start up the address space manager, and determine the
1944 // approximate location of the client's stack
1945 // p: logging, plausible-stack
1946 //--------------------------------------------------------------
1947 VG_(debugLog)(1, "main", "Starting the address space manager\n");
sewardjfdf91b42005-09-28 00:53:09 +00001948 clstack_top = VG_(am_startup)( sp_at_startup );
sewardj45f4e7c2005-09-27 19:20:21 +00001949 VG_(debugLog)(1, "main", "Address space manager is running\n");
1950
1951 //--------------------------------------------------------------
1952 // Start up the dynamic memory manager
1953 // p: address space management
1954 // In fact m_mallocfree is self-initialising, so there's no
1955 // initialisation call to do. Instead, try a simple malloc/
1956 // free pair right now to check that nothing is broken.
1957 //--------------------------------------------------------------
1958 VG_(debugLog)(1, "main", "Starting the dynamic memory manager\n");
1959 { void* p = VG_(malloc)( 12345 );
1960 if (p) VG_(free)( p );
1961 }
1962 VG_(debugLog)(1, "main", "Dynamic memory manager is running\n");
sewardj1cf558c2005-04-25 01:36:56 +00001963
nethercotef4928da2004-06-15 10:54:40 +00001964 //============================================================
sewardj45f4e7c2005-09-27 19:20:21 +00001965 //
1966 // Dynamic memory management is now available.
1967 //
nethercotef4928da2004-06-15 10:54:40 +00001968 //============================================================
1969
sewardj45f4e7c2005-09-27 19:20:21 +00001970 //--------------------------------------------------------------
1971 // Look for alternative libdir
1972 { HChar *cp = VG_(getenv)(VALGRIND_LIB);
1973 if (cp != NULL)
1974 VG_(libdir) = cp;
1975 }
1976
1977 //--------------------------------------------------------------
1978 // Extract the launcher name from the environment.
1979 VG_(debugLog)(1, "main", "Getting stage1's name\n");
1980 VG_(name_of_launcher) = VG_(getenv)(VALGRIND_LAUNCHER);
1981 if (VG_(name_of_launcher) == NULL) {
1982 VG_(printf)("valgrind: You cannot run '%s' directly.\n", argv[0]);
1983 VG_(printf)("valgrind: You should use $prefix/bin/valgrind.\n");
1984 VG_(exit)(1);
1985 }
1986
1987 //--------------------------------------------------------------
fitzhardingeb50068f2004-02-24 23:42:55 +00001988 // Get the current process datasize rlimit, and set it to zero.
1989 // This prevents any internal uses of brk() from having any effect.
1990 // We remember the old value so we can restore it on exec, so that
1991 // child processes will have a reasonable brk value.
1992 VG_(getrlimit)(VKI_RLIMIT_DATA, &VG_(client_rlimit_data));
1993 zero.rlim_max = VG_(client_rlimit_data).rlim_max;
1994 VG_(setrlimit)(VKI_RLIMIT_DATA, &zero);
thughesc37184f2004-09-11 14:16:57 +00001995
1996 // Get the current process stack rlimit.
1997 VG_(getrlimit)(VKI_RLIMIT_STACK, &VG_(client_rlimit_stack));
1998
sewardj45f4e7c2005-09-27 19:20:21 +00001999 //============================================================
2000 // Command line argument handling order:
2001 // * If --help/--help-debug are present, show usage message
2002 // (including the tool-specific usage)
2003 // * (If no --tool option given, default to Memcheck)
2004 // * Then, if client is missing, abort with error msg
2005 // * Then, if any cmdline args are bad, abort with error msg
2006 //============================================================
2007
2008 //--------------------------------------------------------------
2009 // Split up argv into: C args, V args, V extra args, and exename.
2010 // p: dynamic memory allocation
2011 //--------------------------------------------------------------
2012 VG_(debugLog)(1, "main", "Split up command line\n");
2013 VG_(split_up_argv)( argc, argv );
2014 if (0) {
2015 for (i = 0; i < VG_(args_for_valgrind).used; i++)
2016 VG_(printf)("varg %s\n", VG_(args_for_valgrind).strs[i]);
2017 VG_(printf)(" exe %s\n", VG_(args_the_exename));
2018 for (i = 0; i < VG_(args_for_client).used; i++)
2019 VG_(printf)("carg %s\n", VG_(args_for_client).strs[i]);
nethercote71980f02004-01-24 18:18:54 +00002020 }
2021
2022 //--------------------------------------------------------------
sewardj45f4e7c2005-09-27 19:20:21 +00002023 // Extract tool name and whether help has been requested.
2024 // Note we can't print the help message yet, even if requested,
2025 // because the tool has not been initialised.
2026 // p: split_up_argv [for VG_(args_for_valgrind)]
nethercote71980f02004-01-24 18:18:54 +00002027 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002028 VG_(debugLog)(1, "main", "Preprocess command line opts\n");
sewardj45f4e7c2005-09-27 19:20:21 +00002029 get_helprequest_and_toolname(&need_help, &toolname);
nethercote71980f02004-01-24 18:18:54 +00002030
sewardj45f4e7c2005-09-27 19:20:21 +00002031 // Set default vex control params
2032 LibVEX_default_VexControl(& VG_(clo_vex_control));
nethercote71980f02004-01-24 18:18:54 +00002033
2034 //--------------------------------------------------------------
2035 // Load client executable, finding in $PATH if necessary
sewardj45f4e7c2005-09-27 19:20:21 +00002036 // p: get_helprequest_and_toolname() [for 'exec', 'need_help']
nethercote71980f02004-01-24 18:18:54 +00002037 // p: layout_remaining_space [so there's space]
2038 //--------------------------------------------------------------
sewardj45f4e7c2005-09-27 19:20:21 +00002039 if (!need_help) {
2040 VG_(debugLog)(1, "main", "Loading client\n");
nethercote71980f02004-01-24 18:18:54 +00002041
sewardj45f4e7c2005-09-27 19:20:21 +00002042 if (VG_(args_the_exename) == NULL)
2043 missing_prog();
2044
2045 load_client(&info, &initial_client_IP);
2046 }
nethercote71980f02004-01-24 18:18:54 +00002047
2048 //--------------------------------------------------------------
2049 // Set up client's environment
sewardj45f4e7c2005-09-27 19:20:21 +00002050 // p: set-libdir [for VG_(libdir)]
2051 // p: get_helprequest_and_toolname [for toolname]
nethercote71980f02004-01-24 18:18:54 +00002052 //--------------------------------------------------------------
sewardj45f4e7c2005-09-27 19:20:21 +00002053 if (!need_help) {
2054 VG_(debugLog)(1, "main", "Setup client env\n");
2055 env = setup_client_env(envp, toolname);
2056 }
nethercote71980f02004-01-24 18:18:54 +00002057
2058 //--------------------------------------------------------------
nethercote5ee67ca2004-06-22 14:00:09 +00002059 // Setup client stack, eip, and VG_(client_arg[cv])
nethercote71980f02004-01-24 18:18:54 +00002060 // p: load_client() [for 'info']
2061 // p: fix_environment() [for 'env']
2062 //--------------------------------------------------------------
sewardj45f4e7c2005-09-27 19:20:21 +00002063 if (!need_help) {
2064 void* init_sp = argv - 1;
2065 SizeT m1 = 1024 * 1024;
2066 SizeT m8 = 8 * m1;
2067 VG_(debugLog)(1, "main", "Setup client stack\n");
2068 clstack_max_size = (SizeT)VG_(client_rlimit_stack).rlim_cur;
2069 if (clstack_max_size < m1) clstack_max_size = m1;
2070 if (clstack_max_size > m8) clstack_max_size = m8;
2071 clstack_max_size = VG_PGROUNDUP(clstack_max_size);
sewardjb5f6f512005-03-10 23:59:00 +00002072
sewardj45f4e7c2005-09-27 19:20:21 +00002073 initial_client_SP
2074 = setup_client_stack( init_sp, env,
2075 &info, &client_auxv,
2076 clstack_top, clstack_max_size );
2077
2078 VG_(free)(env);
2079
2080 VG_(debugLog)(2, "main",
2081 "Client info: "
2082 "entry=%p client_SP=%p brkbase=%p\n",
2083 (void*)initial_client_IP,
2084 (void*)initial_client_SP,
2085 (void*)VG_(brk_base) );
nethercotec25c4492004-10-18 11:52:17 +00002086 }
nethercote71980f02004-01-24 18:18:54 +00002087
sewardj45f4e7c2005-09-27 19:20:21 +00002088 //--------------------------------------------------------------
2089 // Setup client data (brk) segment. Initially a 1-page segment
2090 // which abuts a shrinkable reservation.
2091 // p: load_client() [for 'info' and hence VG_(brk_base)]
2092 //--------------------------------------------------------------
2093 if (!need_help) {
2094 SizeT m1 = 1024 * 1024;
2095 SizeT m8 = 8 * m1;
2096 SizeT dseg_max_size = (SizeT)VG_(client_rlimit_data).rlim_cur;
2097 VG_(debugLog)(1, "main", "Setup client data (brk) segment\n");
2098 if (dseg_max_size < m1) dseg_max_size = m1;
2099 if (dseg_max_size > m8) dseg_max_size = m8;
2100 dseg_max_size = VG_PGROUNDUP(dseg_max_size);
2101
2102 setup_client_dataseg( dseg_max_size );
2103 }
nethercote71980f02004-01-24 18:18:54 +00002104
2105 //==============================================================
sewardj45f4e7c2005-09-27 19:20:21 +00002106 //
2107 // Finished loading/setting up the client address space.
2108 //
nethercote71980f02004-01-24 18:18:54 +00002109 //==============================================================
2110
2111 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002112 // setup file descriptors
2113 // p: n/a
2114 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002115 VG_(debugLog)(1, "main", "Setup file descriptors\n");
nethercote71980f02004-01-24 18:18:54 +00002116 setup_file_descriptors();
2117
2118 //--------------------------------------------------------------
sewardj45f4e7c2005-09-27 19:20:21 +00002119 // create the fake /proc/<pid>/cmdline file and then unlink it,
2120 // but hold onto the fd, so we can hand it out to the client
2121 // when it tries to open /proc/<pid>/cmdline for itself.
2122 // p: setup file descriptors
nethercotec314eba2004-07-15 12:59:41 +00002123 //--------------------------------------------------------------
sewardj45f4e7c2005-09-27 19:20:21 +00002124 if (!need_help) {
2125 HChar buf[50], buf2[50+64];
2126 HChar nul[1];
2127 Int fd, r;
2128 HChar* exename;
nethercotec314eba2004-07-15 12:59:41 +00002129
sewardj45f4e7c2005-09-27 19:20:21 +00002130 VG_(debugLog)(1, "main", "Create fake /proc/<pid>/cmdline\n");
2131
2132 VG_(sprintf)(buf, "proc_%d_cmdline", VG_(getpid)());
2133 fd = VG_(mkstemp)( buf, buf2 );
2134 if (fd == -1)
2135 config_error("Can't create client cmdline file in /tmp.");
2136
2137 nul[0] = 0;
2138 exename = VG_(args_the_exename) ? VG_(args_the_exename)
2139 : "unknown_exename";
2140
2141 VG_(write)(fd, VG_(args_the_exename),
2142 VG_(strlen)( VG_(args_the_exename) ));
2143 VG_(write)(fd, nul, 1);
2144
2145 for (i = 0; i < VG_(args_for_client).used; i++) {
2146 VG_(write)(fd, VG_(args_for_client).strs[i],
2147 VG_(strlen)( VG_(args_for_client).strs[i] ));
2148 VG_(write)(fd, nul, 1);
2149 }
2150
2151 /* Don't bother to seek the file back to the start; instead do
2152 it every time a copy of it is given out (by PRE(sys_open)).
2153 That is probably more robust across fork() etc. */
2154
2155 /* Now delete it, but hang on to the fd. */
2156 r = VG_(unlink)( buf2 );
2157 if (r)
2158 config_error("Can't delete client cmdline file in /tmp.");
2159
2160 VG_(cl_cmdline_fd) = fd;
2161 }
nethercotec314eba2004-07-15 12:59:41 +00002162
2163 //--------------------------------------------------------------
sewardj45f4e7c2005-09-27 19:20:21 +00002164 // Init tool part 1: pre_clo_init
nethercotec314eba2004-07-15 12:59:41 +00002165 // p: setup_client_stack() [for 'VG_(client_arg[cv]']
nethercotec314eba2004-07-15 12:59:41 +00002166 // p: setup_file_descriptors() [for 'VG_(fd_xxx_limit)']
nethercote71980f02004-01-24 18:18:54 +00002167 //--------------------------------------------------------------
njn64c83242005-06-21 01:54:38 +00002168 {
2169 Char* s;
2170 Bool ok;
sewardj45f4e7c2005-09-27 19:20:21 +00002171 VG_(debugLog)(1, "main", "Initialise the tool part 1 (pre_clo_init)\n");
2172 (VG_(tool_info).tl_pre_clo_init)();
2173 ok = VG_(sanity_check_needs)( &s );
njn64c83242005-06-21 01:54:38 +00002174 if (!ok) {
2175 VG_(tool_panic)(s);
2176 }
2177 }
nethercote71980f02004-01-24 18:18:54 +00002178
sewardj45f4e7c2005-09-27 19:20:21 +00002179 //--------------------------------------------------------------
nethercotef4928da2004-06-15 10:54:40 +00002180 // If --tool and --help/--help-debug was given, now give the core+tool
2181 // help message
sewardj45f4e7c2005-09-27 19:20:21 +00002182 // p: get_helprequest_and_toolname() [for 'need_help']
2183 // p: tl_pre_clo_init [for 'VG_(tdict).usage']
2184 //--------------------------------------------------------------
2185 VG_(debugLog)(1, "main", "Print help and quit, if requested\n");
nethercotef4928da2004-06-15 10:54:40 +00002186 if (need_help) {
sewardj45f4e7c2005-09-27 19:20:21 +00002187 usage_NORETURN(/*--help-debug?*/2 == need_help);
nethercotef4928da2004-06-15 10:54:40 +00002188 }
nethercotec314eba2004-07-15 12:59:41 +00002189
sewardj45f4e7c2005-09-27 19:20:21 +00002190 //--------------------------------------------------------------
2191 // Process command line options to Valgrind + tool
2192 // p: setup_client_stack() [for 'VG_(client_arg[cv]']
2193 // p: setup_file_descriptors() [for 'VG_(fd_xxx_limit)']
2194 //--------------------------------------------------------------
2195 VG_(debugLog)(1, "main", "Process Valgrind's command line options, "
2196 " setup logging\n");
2197 logging_to_fd = process_cmd_line_options(client_auxv, toolname);
2198
2199 //--------------------------------------------------------------
2200 // Print the preamble
2201 // p: tl_pre_clo_init [for 'VG_(details).name' and friends]
2202 // p: process_cmd_line_options() [for VG_(clo_verbosity), VG_(clo_xml),
2203 // VG_(clo_log_file_qualifier),
2204 // logging_to_fd]
2205 //--------------------------------------------------------------
2206 VG_(debugLog)(1, "main", "Print the preamble...\n");
2207 print_preamble(logging_to_fd, toolname);
2208 VG_(debugLog)(1, "main", "...finished the preamble\n");
2209
2210 //--------------------------------------------------------------
2211 // Init tool part 2: post_clo_init
2212 // p: setup_client_stack() [for 'VG_(client_arg[cv]']
2213 // p: setup_file_descriptors() [for 'VG_(fd_xxx_limit)']
2214 // p: print_preamble() [so any warnings printed in post_clo_init
2215 // are shown after the preamble]
2216 //--------------------------------------------------------------
2217 VG_(debugLog)(1, "main", "Initialise the tool part 2 (post_clo_init)\n");
njn51d827b2005-05-09 01:02:08 +00002218 VG_TDICT_CALL(tool_post_clo_init);
nethercotef4928da2004-06-15 10:54:40 +00002219
2220 //--------------------------------------------------------------
sewardj45f4e7c2005-09-27 19:20:21 +00002221 // Initialise translation table and translation cache
2222 // p: aspacem [??]
2223 // p: tl_pre_clo_init [for 'VG_(details).avg_translation_sizeB']
nethercote71980f02004-01-24 18:18:54 +00002224 //--------------------------------------------------------------
sewardj45f4e7c2005-09-27 19:20:21 +00002225 VG_(debugLog)(1, "main", "Initialise TT/TC\n");
2226 VG_(init_tt_tc)();
sewardjb5f6f512005-03-10 23:59:00 +00002227
sewardj45f4e7c2005-09-27 19:20:21 +00002228 //--------------------------------------------------------------
2229 // Initialise the redirect table.
2230 // p: init_tt_tc [so it can call VG_(search_transtab) safely]
2231 // p: aspacem [so can change ownership of sysinfo pages]
2232 //--------------------------------------------------------------
2233 VG_(debugLog)(1, "main", "Initialise redirects\n");
2234 VG_(setup_code_redirect_table)();
nethercote71980f02004-01-24 18:18:54 +00002235
2236 //--------------------------------------------------------------
2237 // Allow GDB attach
2238 // p: process_cmd_line_options() [for VG_(clo_wait_for_gdb)]
2239 //--------------------------------------------------------------
2240 /* Hook to delay things long enough so we can get the pid and
2241 attach GDB in another shell. */
2242 if (VG_(clo_wait_for_gdb)) {
sewardj8211a572005-06-23 21:37:47 +00002243 Long q, iters;
sewardj1fbc1a52005-04-25 02:05:54 +00002244 VG_(debugLog)(1, "main", "Wait for GDB\n");
sewardj93ab8572005-02-06 14:10:40 +00002245 VG_(printf)("pid=%d, entering delay loop\n", VG_(getpid)());
2246 /* jrs 20050206: I don't understand why this works on x86. On
2247 amd64 the obvious analogues (jump *$rip or jump *$rcx) don't
2248 work. */
2249 /* do "jump *$eip" to skip this in gdb (x86) */
2250 //VG_(do_syscall0)(__NR_pause);
sewardj8211a572005-06-23 21:37:47 +00002251
2252# if defined(VGP_x86_linux)
2253 iters = 5;
2254# elif defined(VGP_amd64_linux)
2255 iters = 10;
2256# elif defined(VGP_ppc32_linux)
sewardjd714d2e2005-07-08 18:24:04 +00002257 iters = 5;
sewardj8211a572005-06-23 21:37:47 +00002258# else
2259# error "Unknown plat"
2260# endif
2261
2262 iters *= 1000*1000*1000;
2263 for (q = 0; q < iters; q++)
2264 ;
nethercote71980f02004-01-24 18:18:54 +00002265 }
2266
sewardjb5d320c2005-03-13 18:57:15 +00002267 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002268 // Search for file descriptors that are inherited from our parent
2269 // p: process_cmd_line_options [for VG_(clo_track_fds)]
2270 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002271 if (VG_(clo_track_fds)) {
2272 VG_(debugLog)(1, "main", "Init preopened fds\n");
nethercote71980f02004-01-24 18:18:54 +00002273 VG_(init_preopened_fds)();
sewardj1fbc1a52005-04-25 02:05:54 +00002274 }
nethercote71980f02004-01-24 18:18:54 +00002275
2276 //--------------------------------------------------------------
sewardj45f4e7c2005-09-27 19:20:21 +00002277 // Load debug info for the existing segments.
2278 // p: setup_code_redirect_table [so that redirs can be recorded]
2279 // p: mallocfree
2280 // p: probably: setup fds and process CLOs, so that logging works
2281 //--------------------------------------------------------------
2282 VG_(debugLog)(1, "main", "Load initial debug info\n");
2283 { Addr* seg_starts;
2284 Int n_seg_starts;
2285
2286 seg_starts = get_seg_starts( &n_seg_starts );
2287 vg_assert(seg_starts && n_seg_starts > 0);
2288
2289 /* show them all to the debug info reader */
2290 for (i = 0; i < n_seg_starts; i++)
2291 VG_(di_notify_mmap)( seg_starts[i] );
2292
2293 VG_(free)( seg_starts );
2294 }
2295
2296 //--------------------------------------------------------------
2297 // Tell aspacem of ownership change of the asm helpers, so that
2298 // m_translate allows them to be translated. However, only do this
2299 // after the initial debug info read, since making a hole in the
2300 // address range for the stage2 binary confuses the debug info reader.
2301 // p: aspacem
2302 //--------------------------------------------------------------
2303 { Bool change_ownership_v_c_OK;
2304 Addr co_start = VG_PGROUNDDN( (Addr)&VG_(trampoline_stuff_start) );
2305 Addr co_endPlus = VG_PGROUNDUP( (Addr)&VG_(trampoline_stuff_end) );
2306 VG_(debugLog)(1,"redir",
2307 "transfer ownership V -> C of 0x%llx .. 0x%llx\n",
2308 (ULong)co_start, (ULong)co_endPlus-1 );
2309
2310 change_ownership_v_c_OK
2311 = VG_(am_change_ownership_v_to_c)( co_start, co_endPlus - co_start );
2312 vg_assert(change_ownership_v_c_OK);
2313 }
2314
2315 //--------------------------------------------------------------
2316 // Tell the tool about the initial client memory permissions
2317 // p: aspacem
2318 // p: mallocfree
2319 // p: setup_client_stack
2320 // p: setup_client_dataseg
2321 //--------------------------------------------------------------
2322 VG_(debugLog)(1, "main", "Tell tool about initial permissions\n");
2323 { Addr* seg_starts;
2324 Int n_seg_starts;
2325 NSegment* seg;
2326
2327 seg_starts = get_seg_starts( &n_seg_starts );
2328 vg_assert(seg_starts && n_seg_starts > 0);
2329
2330 /* show interesting ones to the tool */
2331 for (i = 0; i < n_seg_starts; i++) {
2332 seg = VG_(am_find_nsegment)( seg_starts[i] );
2333 vg_assert(seg);
2334 if (seg->kind == SkFileC || seg->kind == SkAnonC) {
2335 VG_(debugLog)(2, "main",
2336 "tell tool about %010lx-%010lx %c%c%c\n",
2337 seg->start, seg->end,
2338 seg->hasR ? 'r' : '-',
2339 seg->hasW ? 'w' : '-',
2340 seg->hasX ? 'x' : '-' );
2341 VG_TRACK( new_mem_startup, seg->start, seg->end+1-seg->start,
2342 seg->hasR, seg->hasW, seg->hasX );
2343 }
2344 }
2345
2346 VG_(free)( seg_starts );
2347
2348 /* Also do the initial stack permissions. */
2349 seg = VG_(am_find_nsegment)( initial_client_SP );
2350 vg_assert(seg);
2351 vg_assert(seg->kind == SkAnonC);
2352 vg_assert(initial_client_SP >= seg->start);
2353 vg_assert(initial_client_SP <= seg->end);
2354
2355 /* Stuff below the initial SP is unaddressable. */
2356 /* NB: shouldn't this take into account the VG_STACK_REDZONE_SZB
2357 bytes below SP? */
2358 VG_TRACK( die_mem_stack, seg->start, initial_client_SP - seg->start );
2359 VG_(debugLog)(2, "main", "mark stack inaccessible %010lx-%010lx\n",
2360 seg->start, initial_client_SP-1 );
2361
2362 /* Also the assembly helpers. */
2363 VG_TRACK( new_mem_startup,
2364 (Addr)&VG_(trampoline_stuff_start),
2365 &VG_(trampoline_stuff_end) - &VG_(trampoline_stuff_start),
2366 False, /* readable? */
2367 False, /* writable? */
2368 True /* executable? */ );
2369 }
2370
2371 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002372 // Initialise the scheduler
nethercote71980f02004-01-24 18:18:54 +00002373 // p: setup_file_descriptors() [else VG_(safe_fd)() breaks]
sewardj45f4e7c2005-09-27 19:20:21 +00002374 // p: setup_client_stack
nethercote71980f02004-01-24 18:18:54 +00002375 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002376 VG_(debugLog)(1, "main", "Initialise scheduler\n");
sewardj45f4e7c2005-09-27 19:20:21 +00002377 { NSegment* seg = VG_(am_find_nsegment)( initial_client_SP );
2378 vg_assert(seg);
2379 vg_assert(seg->kind == SkAnonC);
2380 vg_assert(initial_client_SP >= seg->start);
2381 vg_assert(initial_client_SP <= seg->end);
2382 VG_(scheduler_init)( seg->end, clstack_max_size );
2383 }
nethercote71980f02004-01-24 18:18:54 +00002384
2385 //--------------------------------------------------------------
sewardjb5f6f512005-03-10 23:59:00 +00002386 // Initialise the pthread model
2387 // p: ?
sewardj2a99cf62004-11-24 10:44:19 +00002388 // load_client() [for 'client_eip']
2389 // setup_client_stack() [for 'sp_at_startup']
2390 // setup_scheduler() [for the rest of state 1 stuff]
2391 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002392 VG_(debugLog)(1, "main", "Initialise thread 1's state\n");
sewardj45f4e7c2005-09-27 19:20:21 +00002393 init_thread1state( initial_client_IP, initial_client_SP,
2394 &VG_(threads)[1].arch);
njnea4b28c2004-11-30 16:04:58 +00002395
sewardj2a99cf62004-11-24 10:44:19 +00002396 //--------------------------------------------------------------
sewardj39b88fb2005-03-12 15:16:07 +00002397 // Initialise the pthread model
2398 // p: ?
nethercote71980f02004-01-24 18:18:54 +00002399 //--------------------------------------------------------------
sewardjb5f6f512005-03-10 23:59:00 +00002400 //if (VG_(clo_model_pthreads))
2401 // VG_(pthread_init)();
nethercote71980f02004-01-24 18:18:54 +00002402
2403 //--------------------------------------------------------------
2404 // Initialise the signal handling subsystem
sewardjb5f6f512005-03-10 23:59:00 +00002405 // p: n/a
nethercote71980f02004-01-24 18:18:54 +00002406 //--------------------------------------------------------------
2407 // Nb: temporarily parks the saved blocking-mask in saved_sigmask.
sewardj1fbc1a52005-04-25 02:05:54 +00002408 VG_(debugLog)(1, "main", "Initialise signal management\n");
nethercote71980f02004-01-24 18:18:54 +00002409 VG_(sigstartup_actions)();
2410
2411 //--------------------------------------------------------------
2412 // Perhaps we're profiling Valgrind?
2413 // p: process_cmd_line_options() [for VG_(clo_profile)]
2414 // p: others?
2415 //
2416 // XXX: this seems to be broken? It always says the tool wasn't built
2417 // for profiling; vg_profile.c's functions don't seem to be overriding
2418 // vg_dummy_profile.c's?
2419 //
2420 // XXX: want this as early as possible. Looking for --profile
sewardj45f4e7c2005-09-27 19:20:21 +00002421 // in get_helprequest_and_toolname() could get it earlier.
nethercote71980f02004-01-24 18:18:54 +00002422 //--------------------------------------------------------------
2423 if (VG_(clo_profile))
njn31066fd2005-03-26 00:42:02 +00002424 VG_(init_profiling)();
nethercote71980f02004-01-24 18:18:54 +00002425
2426 VGP_PUSHCC(VgpStartup);
2427
2428 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002429 // Read suppression file
2430 // p: process_cmd_line_options() [for VG_(clo_suppressions)]
2431 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002432 if (VG_(needs).core_errors || VG_(needs).tool_errors) {
2433 VG_(debugLog)(1, "main", "Load suppressions\n");
nethercote71980f02004-01-24 18:18:54 +00002434 VG_(load_suppressions)();
sewardj1fbc1a52005-04-25 02:05:54 +00002435 }
nethercote71980f02004-01-24 18:18:54 +00002436
2437 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002438 // Setup pointercheck
njn04e16982005-05-31 00:23:43 +00002439 // p: layout_remaining_space() [for VG_(client_{base,end})]
nethercote71980f02004-01-24 18:18:54 +00002440 // p: process_cmd_line_options() [for VG_(clo_pointercheck)]
2441 //--------------------------------------------------------------
sewardj45f4e7c2005-09-27 19:20:21 +00002442 //if (VG_(clo_pointercheck))
2443 // VG_(clo_pointercheck) =
2444 // VG_(setup_pointercheck)( VG_(client_base), VG_(client_end));
nethercote71980f02004-01-24 18:18:54 +00002445
nethercote71980f02004-01-24 18:18:54 +00002446 //--------------------------------------------------------------
rjwalsh0140af52005-06-04 20:42:33 +00002447 // register client stack
2448 //--------------------------------------------------------------
njn945ed2e2005-06-24 03:28:30 +00002449 VG_(clstk_id) = VG_(register_stack)(VG_(clstk_base), VG_(clstk_end));
rjwalsh0140af52005-06-04 20:42:33 +00002450
2451 //--------------------------------------------------------------
sewardj45f4e7c2005-09-27 19:20:21 +00002452 // Show the address space state so far
2453 //--------------------------------------------------------------
2454 VG_(debugLog)(1, "main", "\n");
2455 VG_(debugLog)(1, "main", "\n");
2456 VG_(am_show_nsegments)(1,"Memory layout at client startup");
2457 VG_(debugLog)(1, "main", "\n");
2458 VG_(debugLog)(1, "main", "\n");
2459
2460 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002461 // Run!
2462 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002463 VGP_POPCC(VgpStartup);
nethercote71980f02004-01-24 18:18:54 +00002464
sewardj71bc3cb2005-05-19 00:25:45 +00002465 if (VG_(clo_xml)) {
sewardj68cde6f2005-07-19 12:17:51 +00002466 HChar buf[50];
2467 VG_(ctime)(buf);
sewardj753673f2005-08-09 22:03:08 +00002468 VG_(message)(Vg_UserMsg, "<status>\n"
2469 " <state>RUNNING</state>\n"
2470 " <time>%t</time>\n"
2471 "</status>",
2472 buf);
sewardj71bc3cb2005-05-19 00:25:45 +00002473 VG_(message)(Vg_UserMsg, "");
2474 }
2475
sewardj1fbc1a52005-04-25 02:05:54 +00002476 VG_(debugLog)(1, "main", "Running thread 1\n");
sewardj1d887112005-05-30 21:44:08 +00002477 /* As a result of the following call, the last thread standing
2478 eventually winds up running VG_(shutdown_actions_NORETURN) just
2479 below. */
njnaf839f52005-06-23 03:27:57 +00002480 VG_(main_thread_wrapper_NORETURN)(1);
nethercote71980f02004-01-24 18:18:54 +00002481
sewardj1d887112005-05-30 21:44:08 +00002482 /*NOTREACHED*/
2483 vg_assert(0);
sewardjb5f6f512005-03-10 23:59:00 +00002484}
2485
2486
njn9cb54ac2005-06-12 04:19:17 +00002487/* Final clean-up before terminating the process.
2488 Clean up the client by calling __libc_freeres() (if requested)
2489 This is Linux-specific?
2490*/
2491static void final_tidyup(ThreadId tid)
2492{
njnbc6d84d2005-06-19 18:58:03 +00002493 Addr __libc_freeres_wrapper;
2494
njn9cb54ac2005-06-12 04:19:17 +00002495 vg_assert(VG_(is_running_thread)(tid));
2496
njnbc6d84d2005-06-19 18:58:03 +00002497 if ( !VG_(needs).libc_freeres ||
2498 !VG_(clo_run_libc_freeres) ||
2499 0 == (__libc_freeres_wrapper = VG_(get_libc_freeres_wrapper)()) )
njn9cb54ac2005-06-12 04:19:17 +00002500 return; /* can't/won't do it */
2501
2502 if (VG_(clo_verbosity) > 2 ||
2503 VG_(clo_trace_syscalls) ||
2504 VG_(clo_trace_sched))
2505 VG_(message)(Vg_DebugMsg,
2506 "Caught __NR_exit; running __libc_freeres()");
2507
2508 /* point thread context to point to libc_freeres_wrapper */
njnf536bbb2005-06-13 04:21:38 +00002509 VG_(set_IP)(tid, __libc_freeres_wrapper);
njn9cb54ac2005-06-12 04:19:17 +00002510 // XXX should we use a special stack?
2511
2512 /* Block all blockable signals by copying the real block state into
2513 the thread's block state*/
2514 VG_(sigprocmask)(VKI_SIG_BLOCK, NULL, &VG_(threads)[tid].sig_mask);
2515 VG_(threads)[tid].tmp_sig_mask = VG_(threads)[tid].sig_mask;
2516
2517 /* and restore handlers to default */
2518 VG_(set_default_handler)(VKI_SIGSEGV);
2519 VG_(set_default_handler)(VKI_SIGBUS);
2520 VG_(set_default_handler)(VKI_SIGILL);
2521 VG_(set_default_handler)(VKI_SIGFPE);
2522
2523 // We were exiting, so assert that...
2524 vg_assert(VG_(is_exiting)(tid));
2525 // ...but now we're not again
2526 VG_(threads)[tid].exitreason = VgSrc_None;
2527
2528 // run until client thread exits - ideally with LIBC_FREERES_DONE,
2529 // but exit/exitgroup/signal will do
2530 VG_(scheduler)(tid);
2531
2532 vg_assert(VG_(is_exiting)(tid));
2533}
2534
sewardjb5f6f512005-03-10 23:59:00 +00002535/* Do everything which needs doing when the last thread exits */
sewardj1d887112005-05-30 21:44:08 +00002536void VG_(shutdown_actions_NORETURN) ( ThreadId tid,
2537 VgSchedReturnCode tids_schedretcode )
sewardjb5f6f512005-03-10 23:59:00 +00002538{
sewardj1d887112005-05-30 21:44:08 +00002539 VG_(debugLog)(1, "main", "entering VG_(shutdown_actions_NORETURN)\n");
2540
2541 vg_assert( VG_(count_living_threads)() == 1 );
sewardjb5f6f512005-03-10 23:59:00 +00002542 vg_assert(VG_(is_running_thread)(tid));
2543
2544 // Wait for all other threads to exit.
njn7b85dd52005-06-12 17:26:29 +00002545 VG_(reap_threads)(tid);
sewardjb5f6f512005-03-10 23:59:00 +00002546
2547 VG_(clo_model_pthreads) = False;
2548
2549 // Clean the client up before the final report
njn9cb54ac2005-06-12 04:19:17 +00002550 final_tidyup(tid);
sewardjb5f6f512005-03-10 23:59:00 +00002551
2552 // OK, done
2553 VG_(exit_thread)(tid);
2554
2555 /* should be no threads left */
2556 vg_assert(VG_(count_living_threads)() == 0);
2557
2558 VG_(threads)[tid].status = VgTs_Empty;
nethercote71980f02004-01-24 18:18:54 +00002559 //--------------------------------------------------------------
2560 // Finalisation: cleanup, messages, etc. Order no so important, only
2561 // affects what order the messages come.
2562 //--------------------------------------------------------------
2563 if (VG_(clo_verbosity) > 0)
2564 VG_(message)(Vg_UserMsg, "");
2565
sewardj71bc3cb2005-05-19 00:25:45 +00002566 if (VG_(clo_xml)) {
sewardj68cde6f2005-07-19 12:17:51 +00002567 HChar buf[50];
sewardj9f297ca2005-05-20 02:29:52 +00002568 if (VG_(needs).core_errors || VG_(needs).tool_errors) {
2569 VG_(show_error_counts_as_XML)();
2570 VG_(message)(Vg_UserMsg, "");
2571 }
sewardj68cde6f2005-07-19 12:17:51 +00002572 VG_(ctime)(buf);
sewardj753673f2005-08-09 22:03:08 +00002573 VG_(message)(Vg_UserMsg, "<status>\n"
2574 " <state>FINISHED</state>\n"
2575 " <time>%t</time>\n"
2576 "</status>",
2577 buf);
sewardj71bc3cb2005-05-19 00:25:45 +00002578 VG_(message)(Vg_UserMsg, "");
2579 }
2580
nethercote71980f02004-01-24 18:18:54 +00002581 /* Print out file descriptor summary and stats. */
2582 if (VG_(clo_track_fds))
nethercote3a42fb82004-08-03 18:08:50 +00002583 VG_(show_open_fds)();
nethercote71980f02004-01-24 18:18:54 +00002584
njn95ec8702004-11-22 16:46:13 +00002585 if (VG_(needs).core_errors || VG_(needs).tool_errors)
nethercote71980f02004-01-24 18:18:54 +00002586 VG_(show_all_errors)();
2587
njn51d827b2005-05-09 01:02:08 +00002588 VG_TDICT_CALL(tool_fini, 0/*exitcode*/);
nethercote71980f02004-01-24 18:18:54 +00002589
sewardj71bc3cb2005-05-19 00:25:45 +00002590 if (VG_(clo_xml)) {
2591 VG_(message)(Vg_UserMsg, "");
2592 VG_(message)(Vg_UserMsg, "</valgrindoutput>");
2593 VG_(message)(Vg_UserMsg, "");
2594 }
2595
nethercote885dd912004-08-03 23:14:00 +00002596 VG_(sanity_check_general)( True /*include expensive checks*/ );
nethercote71980f02004-01-24 18:18:54 +00002597
2598 if (VG_(clo_verbosity) > 1)
nethercote3a42fb82004-08-03 18:08:50 +00002599 print_all_stats();
nethercote71980f02004-01-24 18:18:54 +00002600
nethercote71980f02004-01-24 18:18:54 +00002601 if (VG_(clo_profile))
njn31066fd2005-03-26 00:42:02 +00002602 VG_(done_profiling)();
njn2025cf92005-06-26 20:44:48 +00002603
2604 if (VG_(clo_profile_flags) > 0) {
2605 #define N_MAX 100
2606 BBProfEntry tops[N_MAX];
2607 ULong score_total = VG_(get_BB_profile) (tops, N_MAX);
2608 show_BB_profile(tops, N_MAX, score_total);
2609 }
sewardjfa8ec112005-01-19 11:55:34 +00002610
sewardj8b635a42004-11-22 19:01:47 +00002611 /* Print Vex storage stats */
sewardjbf426512005-01-17 18:35:30 +00002612 if (0)
2613 LibVEX_ShowAllocStats();
sewardj1d887112005-05-30 21:44:08 +00002614
njn8aa35852005-06-10 22:59:56 +00002615 /* Ok, finally exit in the os-specific way, according to the scheduler's
2616 return code. In short, if the (last) thread exited by calling
2617 sys_exit, do likewise; if the (last) thread stopped due to a fatal
2618 signal, terminate the entire system with that same fatal signal. */
2619 VG_(debugLog)(1, "core_os",
njn7b85dd52005-06-12 17:26:29 +00002620 "VG_(terminate_NORETURN)(tid=%lld)\n", (ULong)tid);
njn8aa35852005-06-10 22:59:56 +00002621
2622 vg_assert(VG_(count_living_threads)() == 0);
2623
2624 switch (tids_schedretcode) {
2625 case VgSrc_ExitSyscall: /* the normal way out */
2626 VG_(exit)( VG_(threads)[tid].os_state.exitcode );
2627 /* NOT ALIVE HERE! */
2628 VG_(core_panic)("entered the afterlife in main() -- ExitSyscall");
2629 break; /* what the hell :) */
2630
2631 case VgSrc_FatalSig:
2632 /* We were killed by a fatal signal, so replicate the effect */
2633 vg_assert(VG_(threads)[tid].os_state.fatalsig != 0);
2634 VG_(kill_self)(VG_(threads)[tid].os_state.fatalsig);
2635 VG_(core_panic)("main(): signal was supposed to be fatal");
2636 break;
2637
2638 default:
2639 VG_(core_panic)("main(): unexpected scheduler return code");
2640 }
njne96be672005-05-08 19:08:54 +00002641}
sewardj8b635a42004-11-22 19:01:47 +00002642
sewardj45f4e7c2005-09-27 19:20:21 +00002643
2644/*====================================================================*/
2645/*=== Getting to main() alive ===*/
2646/*====================================================================*/
2647
2648/* If linking of the final executables is done with glibc present,
2649 then Valgrind starts at main() above as usual, and all of the
2650 following code is irrelevant.
2651
2652 However, this is not the intended mode of use. The plan is to
2653 avoid linking against glibc, by giving gcc the flags
2654 -nodefaultlibs -lgcc -nostartfiles at startup.
2655
2656 From this derive two requirements:
2657
2658 1. gcc may emit calls to memcpy and memset to deal with structure
2659 assignments etc. Since we have chosen to ignore all the
2660 "normal" supporting libraries, we have to provide our own
2661 implementations of them. No problem.
2662
2663 2. We have to provide a symbol "_start", to which the kernel
2664 hands control at startup. Hence the code below.
2665*/
2666
2667/* ---------------- Requirement 1 ---------------- */
2668
2669void* memcpy(void *dest, const void *src, size_t n);
2670void* memcpy(void *dest, const void *src, size_t n) {
2671 return VG_(memcpy)(dest,src,n);
2672}
2673void* memset(void *s, int c, size_t n);
2674void* memset(void *s, int c, size_t n) {
2675 return VG_(memset)(s,c,n);
2676}
2677
2678/* ---------------- Requirement 2 ---------------- */
2679
2680/* Glibc's sysdeps/i386/elf/start.S has the following gem of a
2681 comment, which explains how the stack looks right at process start
2682 (when _start is jumped to). Hence _start passes %esp to
2683 _start_in_C, which extracts argc/argv/envp and starts up
2684 correctly. */
2685
2686/* This is the canonical entry point, usually the first thing in the text
2687 segment. The SVR4/i386 ABI (pages 3-31, 3-32) says that when the entry
2688 point runs, most registers' values are unspecified, except for:
2689
2690 %edx Contains a function pointer to be registered with `atexit'.
2691 This is how the dynamic linker arranges to have DT_FINI
2692 functions called for shared libraries that have been loaded
2693 before this code runs.
2694
2695 %esp The stack contains the arguments and environment:
2696 0(%esp) argc
2697 4(%esp) argv[0]
2698 ...
2699 (4*argc)(%esp) NULL
2700 (4*(argc+1))(%esp) envp[0]
2701 ...
2702 NULL
2703*/
2704
2705/* The kernel hands control to _start, which extracts the initial
2706 stack pointer and calls onwards to _start_in_C. This also switches the new stack. */
2707#if defined(VGP_x86_linux)
2708asm("\n"
2709 "\t.globl _start\n"
2710 "\t.type _start,@function\n"
2711 "_start:\n"
2712 /* set up the new stack in %eax */
sewardjfdf91b42005-09-28 00:53:09 +00002713 "\tmovl $vgPlain_interim_stack, %eax\n"
sewardj45f4e7c2005-09-27 19:20:21 +00002714 "\taddl $"VG_STRINGIFY(VG_STACK_GUARD_SZB)", %eax\n"
2715 "\taddl $"VG_STRINGIFY(VG_STACK_ACTIVE_SZB)", %eax\n"
2716 "\tsubl $16, %eax\n"
2717 "\tandl $~15, %eax\n"
2718 /* install it, and collect the original one */
2719 "\txchgl %eax, %esp\n"
2720 /* call _start_in_C, passing it the startup %esp */
2721 "\tpushl %eax\n"
2722 "\tcall _start_in_C\n"
2723 "\thlt\n"
2724);
2725#elif defined(VGP_amd64_linux)
2726asm("\n"
2727 "\t.globl _start\n"
2728 "\t.type _start,@function\n"
2729 "_start:\n"
2730 /* set up the new stack in %rdi */
sewardjfdf91b42005-09-28 00:53:09 +00002731 "\tmovq $vgPlain_interim_stack, %rdi\n"
sewardj45f4e7c2005-09-27 19:20:21 +00002732 "\taddq $"VG_STRINGIFY(VG_STACK_GUARD_SZB)", %rdi\n"
2733 "\taddq $"VG_STRINGIFY(VG_STACK_ACTIVE_SZB)", %rdi\n"
2734 "\tandq $~15, %rdi\n"
2735 /* install it, and collect the original one */
2736 "\txchgq %rdi, %rsp\n"
2737 /* call _start_in_C, passing it the startup %rsp */
2738 "\tcall _start_in_C\n"
2739 "\thlt\n"
2740);
2741#else
2742#error "_start: needs implementation on this platform"
2743#endif
2744
2745/* Avoid compiler warnings: this fn _is_ used, but labelling it
2746 'static' causes gcc to complain it isn't. */
2747void _start_in_C ( UWord* pArgc );
2748void _start_in_C ( UWord* pArgc )
2749{
2750 Int r;
2751 Word argc = pArgc[0];
2752 HChar** argv = (HChar**)&pArgc[1];
2753 HChar** envp = (HChar**)&pArgc[1+argc+1];
sewardjfdf91b42005-09-28 00:53:09 +00002754 sp_at_startup = (Addr)pArgc;
sewardj45f4e7c2005-09-27 19:20:21 +00002755 r = main( (Int)argc, argv, envp );
2756 VG_(exit)(r);
2757}
2758
sewardjde4a1d02002-03-22 01:27:54 +00002759/*--------------------------------------------------------------------*/
njn04e16982005-05-31 00:23:43 +00002760/*--- end ---*/
sewardjde4a1d02002-03-22 01:27:54 +00002761/*--------------------------------------------------------------------*/