blob: 594af625c695411290cf4bce52191f1b758aa0af [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
sewardje4b0bf02006-06-05 23:21:15 +000010 Copyright (C) 2000-2006 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"
sewardj4cfea4f2006-10-14 19:26:10 +000032#include "pub_core_vki.h"
sewardj17c11042006-10-15 01:26:40 +000033#include "pub_core_vkiscnums.h"
njnc7561b92005-06-19 01:24:32 +000034#include "pub_core_threadstate.h"
sewardj45f4e7c2005-09-27 19:20:21 +000035#include "pub_core_clientstate.h"
sewardj55f9d1a2005-04-25 11:11:44 +000036#include "pub_core_aspacemgr.h"
sewardj45f4e7c2005-09-27 19:20:21 +000037#include "pub_core_commandline.h"
njn2521d322005-05-08 14:45:13 +000038#include "pub_core_debuglog.h"
39#include "pub_core_errormgr.h"
40#include "pub_core_execontext.h"
sewardj17c11042006-10-15 01:26:40 +000041#include "pub_core_initimg.h"
njn97405b22005-06-02 03:39:33 +000042#include "pub_core_libcbase.h"
njn132bfcc2005-06-04 19:16:06 +000043#include "pub_core_libcassert.h"
njneb8896b2005-06-04 20:03:55 +000044#include "pub_core_libcfile.h"
njn36a20fa2005-06-03 03:08:39 +000045#include "pub_core_libcprint.h"
njnf39e9a32005-06-12 02:43:17 +000046#include "pub_core_libcproc.h"
njnde62cbf2005-06-10 22:08:14 +000047#include "pub_core_libcsignal.h"
sewardj45f4e7c2005-09-27 19:20:21 +000048#include "pub_core_syscall.h" // VG_(strerror)
njnf536bbb2005-06-13 04:21:38 +000049#include "pub_core_machine.h"
njnaf1d7df2005-06-11 01:31:52 +000050#include "pub_core_mallocfree.h"
njn20242342005-05-16 23:31:24 +000051#include "pub_core_options.h"
sewardjfdf91b42005-09-28 00:53:09 +000052#include "pub_core_debuginfo.h"
njnd1af0032005-05-29 17:01:48 +000053#include "pub_core_redir.h"
njnc7561b92005-06-19 01:24:32 +000054#include "pub_core_scheduler.h"
njn0c246472005-05-31 01:00:08 +000055#include "pub_core_signals.h"
njn2025cf92005-06-26 20:44:48 +000056#include "pub_core_stacks.h" // For VG_(register_stack)
njnc1b01812005-06-17 22:19:06 +000057#include "pub_core_syswrap.h"
njn43b9a8a2005-05-10 04:37:01 +000058#include "pub_core_tooliface.h"
sewardj17c11042006-10-15 01:26:40 +000059#include "pub_core_translate.h" // For VG_(translate)
njna7598f62005-06-18 03:27:58 +000060#include "pub_core_trampoline.h"
njn8bddf582005-05-13 23:40:55 +000061#include "pub_core_transtab.h"
sewardj17c11042006-10-15 01:26:40 +000062
63/* Stuff for reading AIX5 /proc/<pid>/sysent files */
64#if defined(VGO_aix5)
65 /* --- !!! --- EXTERNAL HEADERS start --- !!! --- */
66# include <sys/procfs.h> /* prsysent_t */
67 /* --- !!! --- EXTERNAL HEADERS end --- !!! --- */
68# define VG_AIX5_SYSENT_SIZE 100000
69 static UChar aix5_sysent_buf[VG_AIX5_SYSENT_SIZE];
70#endif
nethercote71980f02004-01-24 18:18:54 +000071
sewardjb5f6f512005-03-10 23:59:00 +000072
nethercote71980f02004-01-24 18:18:54 +000073/*====================================================================*/
74/*=== Counters, for profiling purposes only ===*/
75/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +000076
nethercote3a42fb82004-08-03 18:08:50 +000077static void print_all_stats ( void )
nethercote71980f02004-01-24 18:18:54 +000078{
njn42c83552005-12-05 20:45:59 +000079 VG_(print_translation_stats)();
nethercote92e7b7f2004-08-07 17:52:25 +000080 VG_(print_tt_tc_stats)();
nethercote844e7122004-08-02 15:27:22 +000081 VG_(print_scheduler_stats)();
njn9271cbc2005-03-13 05:38:25 +000082 VG_(print_ExeContext_stats)();
sewardj12ab7652006-10-17 02:10:42 +000083 VG_(print_errormgr_stats)();
njn9271cbc2005-03-13 05:38:25 +000084
nethercote3a42fb82004-08-03 18:08:50 +000085 // Memory stats
nethercote885dd912004-08-03 23:14:00 +000086 if (VG_(clo_verbosity) > 2) {
nethercote3a42fb82004-08-03 18:08:50 +000087 VG_(message)(Vg_DebugMsg, "");
88 VG_(message)(Vg_DebugMsg,
89 "------ Valgrind's internal memory use stats follow ------" );
nethercote885dd912004-08-03 23:14:00 +000090 VG_(sanity_check_malloc_all)();
njn11adeb22005-07-03 20:22:39 +000091 VG_(message)(Vg_DebugMsg, "------" );
nethercote3a42fb82004-08-03 18:08:50 +000092 VG_(print_all_arena_stats)();
nethercote885dd912004-08-03 23:14:00 +000093 VG_(message)(Vg_DebugMsg, "");
nethercote3a42fb82004-08-03 18:08:50 +000094 }
nethercote71980f02004-01-24 18:18:54 +000095}
96
97
98/*====================================================================*/
sewardj71bc3cb2005-05-19 00:25:45 +000099/*=== Command-line: variables, processing, etc ===*/
100/*====================================================================*/
101
102// See pub_{core,tool}_options.h for explanations of all these.
103
sewardj45f4e7c2005-09-27 19:20:21 +0000104static void usage_NORETURN ( Bool debug_help )
njn7cf0bd32002-06-08 13:36:03 +0000105{
njn25e49d8e72002-09-23 09:36:25 +0000106 Char* usage1 =
njn00cfcfc2005-11-12 18:53:50 +0000107"usage: valgrind [options] prog-and-args\n"
njn25e49d8e72002-09-23 09:36:25 +0000108"\n"
nethercote2b0793f2003-12-02 10:41:18 +0000109" common user options for all Valgrind tools, with defaults in [ ]:\n"
sewardjb5f6f512005-03-10 23:59:00 +0000110" --tool=<name> use the Valgrind tool named <name> [memcheck]\n"
nethercotea76368b2004-06-16 11:56:29 +0000111" -h --help show this message\n"
nethercote6c999f22004-01-31 22:55:15 +0000112" --help-debug show this message, plus debugging options\n"
njn25e49d8e72002-09-23 09:36:25 +0000113" --version show version\n"
njn25e49d8e72002-09-23 09:36:25 +0000114" -q --quiet run silently; only print error msgs\n"
115" -v --verbose be more verbose, incl counts of errors\n"
nethercote77eba602003-11-13 17:35:04 +0000116" --trace-children=no|yes Valgrind-ise child processes? [no]\n"
nethercote0d588502004-06-21 13:27:11 +0000117" --track-fds=no|yes track open file descriptors? [no]\n"
thughes6233a382004-08-21 11:10:44 +0000118" --time-stamp=no|yes add timestamps to log messages? [no]\n"
njnce545552005-07-25 22:36:52 +0000119" --log-fd=<number> log messages to file descriptor [2=stderr]\n"
tombbe14b12005-11-04 16:49:39 +0000120" --log-file=<file> log messages to <file>.<pid>\n"
njnce545552005-07-25 22:36:52 +0000121" --log-file-exactly=<file> log messages to <file>\n"
122" --log-file-qualifier=<VAR> incorporate $VAR in logfile name [none]\n"
123" --log-socket=ipaddr:port log messages to socket ipaddr:port\n"
nethercote2b0793f2003-12-02 10:41:18 +0000124"\n"
125" uncommon user options for all Valgrind tools:\n"
nethercote0d588502004-06-21 13:27:11 +0000126" --run-libc-freeres=no|yes free up glibc memory at exit? [yes]\n"
njn628add62005-11-12 18:21:40 +0000127" --sim-hints=hint1,hint2,... known hints:\n"
sewardj19617ae2005-10-20 01:09:57 +0000128" lax-ioctls, enable-outer [none]\n"
sewardjb1131a82005-03-19 15:12:21 +0000129" --show-emwarns=no|yes show warnings about emulation limits? [no]\n"
sewardj6c3a2192005-07-24 07:00:45 +0000130" --smc-check=none|stack|all checks for self-modifying code: none,\n"
131" only for code found in stacks, or all [stack]\n"
sewardj3c3f0c12005-11-08 15:52:36 +0000132" --kernel-variant=variant1,variant2,... known variants: bproc [none]\n"
133" handle non-standard kernel variants\n"
njn25e49d8e72002-09-23 09:36:25 +0000134"\n"
nethercote2b0793f2003-12-02 10:41:18 +0000135" user options for Valgrind tools that report errors:\n"
njnca54af32006-04-16 10:25:43 +0000136" --xml=yes all output is in XML (some tools only)\n"
njnc8ec9f82005-07-20 03:03:28 +0000137" --xml-user-comment=STR copy STR verbatim to XML output\n"
nethercote2b0793f2003-12-02 10:41:18 +0000138" --demangle=no|yes automatically demangle C++ names? [yes]\n"
njn20b4a152005-10-19 22:39:40 +0000139" --num-callers=<number> show <number> callers in stack traces [12]\n"
nethercote2b0793f2003-12-02 10:41:18 +0000140" --error-limit=no|yes stop showing new errors if too many? [yes]\n"
sewardjb9779082006-05-12 23:50:15 +0000141" --error-exitcode=<number> exit code to return if errors found [0=disable]\n"
nethercote2b0793f2003-12-02 10:41:18 +0000142" --show-below-main=no|yes continue stack traces below main() [no]\n"
143" --suppressions=<filename> suppress errors described in <filename>\n"
sewardjd153fae2005-01-10 17:24:47 +0000144" --gen-suppressions=no|yes|all print suppressions for errors? [no]\n"
nethercote04d0fbc2004-01-26 16:48:06 +0000145" --db-attach=no|yes start debugger when errors detected? [no]\n"
146" --db-command=<command> command to start debugger [gdb -nw %%f %%p]\n"
147" --input-fd=<number> file descriptor for input [0=stdin]\n"
sewardj97724e52005-04-02 23:40:59 +0000148" --max-stackframe=<number> assume stack switch for SP changes larger\n"
149" than <number> bytes [2000000]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +0000150"\n";
njn7cf0bd32002-06-08 13:36:03 +0000151
njn25e49d8e72002-09-23 09:36:25 +0000152 Char* usage2 =
153"\n"
nethercote2b0793f2003-12-02 10:41:18 +0000154" debugging options for all Valgrind tools:\n"
njn25e49d8e72002-09-23 09:36:25 +0000155" --sanity-level=<number> level of sanity checking to do [1]\n"
sewardjfa8ec112005-01-19 11:55:34 +0000156" --trace-flags=<XXXXXXXX> show generated code? (X = 0|1) [00000000]\n"
157" --profile-flags=<XXXXXXXX> ditto, but for profiling (X = 0|1) [00000000]\n"
sewardj33afdb52006-01-17 02:36:40 +0000158" --trace-notbelow=<number> only show BBs above <number> [999999999]\n"
njn25e49d8e72002-09-23 09:36:25 +0000159" --trace-syscalls=no|yes show all system calls? [no]\n"
160" --trace-signals=no|yes show signal handling details? [no]\n"
161" --trace-symtab=no|yes show symbol table details? [no]\n"
sewardjce058b02005-05-01 08:55:38 +0000162" --trace-cfi=no|yes show call-frame-info details? [no]\n"
sewardj0ec07f32006-01-12 12:32:32 +0000163" --trace-redir=no|yes show redirection details? [no]\n"
njn25e49d8e72002-09-23 09:36:25 +0000164" --trace-sched=no|yes show thread scheduler details? [no]\n"
jsgf855d93d2003-10-13 22:26:55 +0000165" --wait-for-gdb=yes|no pause on startup to wait for gdb attach\n"
sewardj17c11042006-10-15 01:26:40 +0000166" --sym-offsets=yes|no show syms in form 'name+offset' ? [no]\n"
sewardjb5f6f512005-03-10 23:59:00 +0000167#if 0
168" --model-pthreads=yes|no model the pthreads library [no]\n"
169#endif
170" --command-line-only=no|yes only use command line options [no]\n"
njn613812e2005-03-11 04:57:30 +0000171"\n"
172" --vex-iropt-verbosity 0 .. 9 [0]\n"
173" --vex-iropt-level 0 .. 2 [2]\n"
174" --vex-iropt-precise-memory-exns [no]\n"
sewardj8b635a42004-11-22 19:01:47 +0000175" --vex-iropt-unroll-thresh 0 .. 400 [120]\n"
176" --vex-guest-max-insns 1 .. 100 [50]\n"
177" --vex-guest-chase-thresh 0 .. 99 [10]\n"
178"\n"
sewardjfa8ec112005-01-19 11:55:34 +0000179" --trace-flags and --profile-flags values (omit the middle space):\n"
sewardj2a99cf62004-11-24 10:44:19 +0000180" 1000 0000 show conversion into IR\n"
181" 0100 0000 show after initial opt\n"
182" 0010 0000 show after instrumentation\n"
183" 0001 0000 show after second opt\n"
184" 0000 1000 show after tree building\n"
185" 0000 0100 show selecting insns\n"
186" 0000 0010 show after reg-alloc\n"
187" 0000 0001 show final assembly\n"
njn33dbfce2006-06-02 22:58:34 +0000188" (Nb: you need --trace-notbelow with --trace-flags for full details)\n"
sewardj2a99cf62004-11-24 10:44:19 +0000189"\n"
nethercote2b0793f2003-12-02 10:41:18 +0000190" debugging options for Valgrind tools that report errors\n"
191" --dump-error=<number> show translation for basic block associated\n"
192" with <number>'th error context [0=show none]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +0000193"\n";
njn3e884182003-04-15 13:03:23 +0000194
195 Char* usage3 =
196"\n"
nethercote71980f02004-01-24 18:18:54 +0000197" Extra options read from ~/.valgrindrc, $VALGRIND_OPTS, ./.valgrindrc\n"
njn25e49d8e72002-09-23 09:36:25 +0000198"\n"
sewardja2cd32d2006-05-27 03:22:47 +0000199" Valgrind is Copyright (C) 2000-2006 Julian Seward et al.\n"
njn25e49d8e72002-09-23 09:36:25 +0000200" and licensed under the GNU General Public License, version 2.\n"
201" Bug reports, feedback, admiration, abuse, etc, to: %s.\n"
njnd04b7c62002-10-03 14:05:52 +0000202"\n"
nethercote137bc552003-11-14 17:47:54 +0000203" Tools are copyright and licensed by their authors. See each\n"
204" tool's start-up message for more information.\n"
njn25e49d8e72002-09-23 09:36:25 +0000205"\n";
njn7cf0bd32002-06-08 13:36:03 +0000206
njnbe9b47b2005-05-15 16:22:58 +0000207 // Ensure the message goes to stdout
208 VG_(clo_log_fd) = 1;
209 vg_assert( !VG_(logging_to_socket) );
210
fitzhardinge98abfc72003-12-16 02:05:15 +0000211 VG_(printf)(usage1);
212 if (VG_(details).name) {
213 VG_(printf)(" user options for %s:\n", VG_(details).name);
fitzhardinge98abfc72003-12-16 02:05:15 +0000214 if (VG_(needs).command_line_options)
njn51d827b2005-05-09 01:02:08 +0000215 VG_TDICT_CALL(tool_print_usage);
fitzhardinge98abfc72003-12-16 02:05:15 +0000216 else
217 VG_(printf)(" (none)\n");
218 }
nethercote6c999f22004-01-31 22:55:15 +0000219 if (debug_help) {
220 VG_(printf)(usage2);
fitzhardinge98abfc72003-12-16 02:05:15 +0000221
nethercote6c999f22004-01-31 22:55:15 +0000222 if (VG_(details).name) {
223 VG_(printf)(" debugging options for %s:\n", VG_(details).name);
224
225 if (VG_(needs).command_line_options)
njn51d827b2005-05-09 01:02:08 +0000226 VG_TDICT_CALL(tool_print_debug_usage);
nethercote6c999f22004-01-31 22:55:15 +0000227 else
228 VG_(printf)(" (none)\n");
229 }
fitzhardinge98abfc72003-12-16 02:05:15 +0000230 }
nethercote421281e2003-11-20 16:20:55 +0000231 VG_(printf)(usage3, VG_BUGS_TO);
nethercotef4928da2004-06-15 10:54:40 +0000232 VG_(exit)(0);
njn7cf0bd32002-06-08 13:36:03 +0000233}
sewardjde4a1d02002-03-22 01:27:54 +0000234
sewardjde4a1d02002-03-22 01:27:54 +0000235
sewardj45f4e7c2005-09-27 19:20:21 +0000236/* Peer at previously set up VG_(args_for_valgrind) and extract any
237 request for help and also the tool name. */
238
239static void get_helprequest_and_toolname ( Int* need_help, HChar** tool )
240{
241 UInt i;
242 HChar* str;
sewardj8b635a42004-11-22 19:01:47 +0000243
nethercote71980f02004-01-24 18:18:54 +0000244 /* parse the options we have (only the options we care about now) */
sewardj45f4e7c2005-09-27 19:20:21 +0000245 for (i = 0; i < VG_(args_for_valgrind).used; i++) {
nethercote71980f02004-01-24 18:18:54 +0000246
sewardj45f4e7c2005-09-27 19:20:21 +0000247 str = VG_(args_for_valgrind).strs[i];
248 vg_assert(str);
nethercote71980f02004-01-24 18:18:54 +0000249
sewardj45f4e7c2005-09-27 19:20:21 +0000250 if (VG_STREQ(str, "--version")) {
njn2e9f3f32005-10-26 16:17:46 +0000251 // Ensure the version string goes to stdout
252 VG_(clo_log_fd) = 1;
sewardj45f4e7c2005-09-27 19:20:21 +0000253 VG_(printf)("valgrind-" VERSION "\n");
254 VG_(exit)(0);
255
256 } else if (VG_CLO_STREQ(str, "--help") ||
257 VG_CLO_STREQ(str, "-h")) {
nethercote6c999f22004-01-31 22:55:15 +0000258 *need_help = 1;
259
sewardj45f4e7c2005-09-27 19:20:21 +0000260 } else if (VG_CLO_STREQ(str, "--help-debug")) {
nethercote6c999f22004-01-31 22:55:15 +0000261 *need_help = 2;
nethercote71980f02004-01-24 18:18:54 +0000262
sewardj45f4e7c2005-09-27 19:20:21 +0000263 // The tool has already been determined, but we need to know the name
264 // here.
265 } else if (VG_CLO_STREQN(7, str, "--tool=")) {
266 *tool = &str[7];
nethercote71980f02004-01-24 18:18:54 +0000267 }
268 }
nethercote71980f02004-01-24 18:18:54 +0000269}
270
sewardj45f4e7c2005-09-27 19:20:21 +0000271static Bool process_cmd_line_options( UInt* client_auxv, const char* toolname )
nethercote71980f02004-01-24 18:18:54 +0000272{
njnda033f52005-12-19 21:27:58 +0000273 // VG_(clo_log_fd) is used by all the messaging. It starts as 2 (stderr)
274 // and we cannot change it until we know what we are changing it to is
275 // ok. So we have tmp_log_fd to hold the tmp fd prior to that point.
sewardj92645592005-07-23 09:18:34 +0000276 SysRes sres;
njnda033f52005-12-19 21:27:58 +0000277 Int i, tmp_log_fd;
sewardj92645592005-07-23 09:18:34 +0000278 Int toolname_len = VG_(strlen)(toolname);
njnbe9b47b2005-05-15 16:22:58 +0000279 enum {
280 VgLogTo_Fd,
281 VgLogTo_File,
282 VgLogTo_FileExactly,
283 VgLogTo_Socket
284 } log_to = VgLogTo_Fd; // Where is logging output to be sent?
sewardjde4a1d02002-03-22 01:27:54 +0000285
nethercotee1730692003-11-20 10:38:07 +0000286 /* log to stderr by default, but usage message goes to stdout */
njnda033f52005-12-19 21:27:58 +0000287 tmp_log_fd = 2;
sewardjde4a1d02002-03-22 01:27:54 +0000288
sewardj19d81412002-06-03 01:10:40 +0000289 /* Check for sane path in ./configure --prefix=... */
fitzhardinge98abfc72003-12-16 02:05:15 +0000290 if (VG_LIBDIR[0] != '/')
sewardj17c11042006-10-15 01:26:40 +0000291 VG_(err_config_error)("Please use absolute paths in "
292 "./configure --prefix=... or --libdir=...");
sewardj38170912002-05-10 21:07:22 +0000293
sewardj45f4e7c2005-09-27 19:20:21 +0000294 for (i = 0; i < VG_(args_for_valgrind).used; i++) {
nethercote71980f02004-01-24 18:18:54 +0000295
sewardj45f4e7c2005-09-27 19:20:21 +0000296 HChar* arg = VG_(args_for_valgrind).strs[i];
297 HChar* colon = arg;
nethercote71980f02004-01-24 18:18:54 +0000298
thughes3bfd5a02004-07-18 08:05:44 +0000299 /* Look for a colon in the switch name */
300 while (*colon && *colon != ':' && *colon != '=')
301 colon++;
nethercote71980f02004-01-24 18:18:54 +0000302
303 /* Look for matching "--toolname:foo" */
thughes3bfd5a02004-07-18 08:05:44 +0000304 if (*colon == ':') {
nethercote71980f02004-01-24 18:18:54 +0000305 if (VG_CLO_STREQN(2, arg, "--") &&
306 VG_CLO_STREQN(toolname_len, arg+2, toolname) &&
307 VG_CLO_STREQN(1, arg+2+toolname_len, ":"))
308 {
309 // prefix matches, convert "--toolname:foo" to "--foo"
310 if (0)
311 VG_(printf)("tool-specific arg: %s\n", arg);
sewardj45f4e7c2005-09-27 19:20:21 +0000312 arg = VG_(strdup)(arg + toolname_len + 1);
nethercote71980f02004-01-24 18:18:54 +0000313 arg[0] = '-';
314 arg[1] = '-';
315
316 } else {
317 // prefix doesn't match, skip to next arg
318 continue;
319 }
320 }
321
fitzhardinge98abfc72003-12-16 02:05:15 +0000322 /* Ignore these options - they've already been handled */
njn45270a22005-03-27 01:00:11 +0000323 if (VG_CLO_STREQN( 7, arg, "--tool=")) goto skip_arg;
njn45270a22005-03-27 01:00:11 +0000324 if (VG_CLO_STREQN(20, arg, "--command-line-only=")) goto skip_arg;
fitzhardinge98abfc72003-12-16 02:05:15 +0000325
njn45270a22005-03-27 01:00:11 +0000326 if ( VG_CLO_STREQ(arg, "--")) goto skip_arg;
nethercote27fec902004-06-16 21:26:32 +0000327
nethercote71980f02004-01-24 18:18:54 +0000328 else if (VG_CLO_STREQ(arg, "-v") ||
329 VG_CLO_STREQ(arg, "--verbose"))
sewardjde4a1d02002-03-22 01:27:54 +0000330 VG_(clo_verbosity)++;
nethercote27fec902004-06-16 21:26:32 +0000331
nethercote71980f02004-01-24 18:18:54 +0000332 else if (VG_CLO_STREQ(arg, "-q") ||
333 VG_CLO_STREQ(arg, "--quiet"))
sewardjde4a1d02002-03-22 01:27:54 +0000334 VG_(clo_verbosity)--;
335
sewardj1cf558c2005-04-25 01:36:56 +0000336 else if (VG_CLO_STREQ(arg, "-d")) {
337 /* do nothing */
338 }
339
sewardj71bc3cb2005-05-19 00:25:45 +0000340 else VG_BOOL_CLO(arg, "--xml", VG_(clo_xml))
njn45270a22005-03-27 01:00:11 +0000341 else VG_BOOL_CLO(arg, "--db-attach", VG_(clo_db_attach))
342 else VG_BOOL_CLO(arg, "--demangle", VG_(clo_demangle))
343 else VG_BOOL_CLO(arg, "--error-limit", VG_(clo_error_limit))
sewardjb9779082006-05-12 23:50:15 +0000344 else VG_NUM_CLO (arg, "--error-exitcode", VG_(clo_error_exitcode))
njn45270a22005-03-27 01:00:11 +0000345 else VG_BOOL_CLO(arg, "--show-emwarns", VG_(clo_show_emwarns))
sewardj97724e52005-04-02 23:40:59 +0000346 else VG_NUM_CLO (arg, "--max-stackframe", VG_(clo_max_stackframe))
njn45270a22005-03-27 01:00:11 +0000347 else VG_BOOL_CLO(arg, "--run-libc-freeres", VG_(clo_run_libc_freeres))
348 else VG_BOOL_CLO(arg, "--show-below-main", VG_(clo_show_below_main))
349 else VG_BOOL_CLO(arg, "--time-stamp", VG_(clo_time_stamp))
350 else VG_BOOL_CLO(arg, "--track-fds", VG_(clo_track_fds))
351 else VG_BOOL_CLO(arg, "--trace-children", VG_(clo_trace_children))
352 else VG_BOOL_CLO(arg, "--trace-sched", VG_(clo_trace_sched))
353 else VG_BOOL_CLO(arg, "--trace-signals", VG_(clo_trace_signals))
354 else VG_BOOL_CLO(arg, "--trace-symtab", VG_(clo_trace_symtab))
sewardjce058b02005-05-01 08:55:38 +0000355 else VG_BOOL_CLO(arg, "--trace-cfi", VG_(clo_trace_cfi))
njn45270a22005-03-27 01:00:11 +0000356 else VG_BOOL_CLO(arg, "--trace-redir", VG_(clo_trace_redir))
357 else VG_BOOL_CLO(arg, "--trace-syscalls", VG_(clo_trace_syscalls))
358 else VG_BOOL_CLO(arg, "--trace-pthreads", VG_(clo_trace_pthreads))
359 else VG_BOOL_CLO(arg, "--wait-for-gdb", VG_(clo_wait_for_gdb))
360 else VG_BOOL_CLO(arg, "--model-pthreads", VG_(clo_model_pthreads))
sewardj72f98ff2002-06-13 17:23:38 +0000361
njn45270a22005-03-27 01:00:11 +0000362 else VG_STR_CLO (arg, "--db-command", VG_(clo_db_command))
njn628add62005-11-12 18:21:40 +0000363 else VG_STR_CLO (arg, "--sim-hints", VG_(clo_sim_hints))
sewardj12ab7652006-10-17 02:10:42 +0000364 else VG_BOOL_CLO(arg, "--sym-offsets", VG_(clo_sym_offsets))
sewardjde4a1d02002-03-22 01:27:54 +0000365
njn45270a22005-03-27 01:00:11 +0000366 else VG_NUM_CLO (arg, "--dump-error", VG_(clo_dump_error))
367 else VG_NUM_CLO (arg, "--input-fd", VG_(clo_input_fd))
368 else VG_NUM_CLO (arg, "--sanity-level", VG_(clo_sanity_level))
369 else VG_BNUM_CLO(arg, "--num-callers", VG_(clo_backtrace_size), 1,
370 VG_DEEPEST_BACKTRACE)
sewardjde4a1d02002-03-22 01:27:54 +0000371
sewardj6c3a2192005-07-24 07:00:45 +0000372 else if (VG_CLO_STREQ(arg, "--smc-check=none"))
373 VG_(clo_smc_check) = Vg_SmcNone;
374 else if (VG_CLO_STREQ(arg, "--smc-check=stack"))
375 VG_(clo_smc_check) = Vg_SmcStack;
376 else if (VG_CLO_STREQ(arg, "--smc-check=all"))
377 VG_(clo_smc_check) = Vg_SmcAll;
sewardj26412bd2005-07-07 10:05:05 +0000378
sewardjce5a5662005-10-06 03:19:49 +0000379 else VG_STR_CLO (arg, "--kernel-variant", VG_(clo_kernel_variant))
380
njn45270a22005-03-27 01:00:11 +0000381 else VG_BNUM_CLO(arg, "--vex-iropt-verbosity",
sewardj8b635a42004-11-22 19:01:47 +0000382 VG_(clo_vex_control).iropt_verbosity, 0, 10)
njn45270a22005-03-27 01:00:11 +0000383 else VG_BNUM_CLO(arg, "--vex-iropt-level",
sewardj8b635a42004-11-22 19:01:47 +0000384 VG_(clo_vex_control).iropt_level, 0, 2)
njn45270a22005-03-27 01:00:11 +0000385 else VG_BOOL_CLO(arg, "--vex-iropt-precise-memory-exns",
sewardj8b635a42004-11-22 19:01:47 +0000386 VG_(clo_vex_control).iropt_precise_memory_exns)
njn45270a22005-03-27 01:00:11 +0000387 else VG_BNUM_CLO(arg, "--vex-iropt-unroll-thresh",
sewardj8b635a42004-11-22 19:01:47 +0000388 VG_(clo_vex_control).iropt_unroll_thresh, 0, 400)
njn45270a22005-03-27 01:00:11 +0000389 else VG_BNUM_CLO(arg, "--vex-guest-max-insns",
sewardj8b635a42004-11-22 19:01:47 +0000390 VG_(clo_vex_control).guest_max_insns, 1, 100)
njn45270a22005-03-27 01:00:11 +0000391 else VG_BNUM_CLO(arg, "--vex-guest-chase-thresh",
sewardj8b635a42004-11-22 19:01:47 +0000392 VG_(clo_vex_control).guest_chase_thresh, 0, 99)
393
nethercotef8548672004-06-21 12:42:35 +0000394 else if (VG_CLO_STREQN(9, arg, "--log-fd=")) {
njnbe9b47b2005-05-15 16:22:58 +0000395 log_to = VgLogTo_Fd;
nethercotef8548672004-06-21 12:42:35 +0000396 VG_(clo_log_name) = NULL;
njnda033f52005-12-19 21:27:58 +0000397 tmp_log_fd = (Int)VG_(atoll)(&arg[9]);
sewardj4cf05692002-10-27 20:28:29 +0000398 }
399
nethercotef8548672004-06-21 12:42:35 +0000400 else if (VG_CLO_STREQN(11, arg, "--log-file=")) {
njnbe9b47b2005-05-15 16:22:58 +0000401 log_to = VgLogTo_File;
nethercotef8548672004-06-21 12:42:35 +0000402 VG_(clo_log_name) = &arg[11];
sewardj4cf05692002-10-27 20:28:29 +0000403 }
njnd6bc3c32005-03-27 00:44:31 +0000404
sewardjad311162005-07-19 11:25:02 +0000405 else if (VG_CLO_STREQN(21, arg, "--log-file-qualifier=")) {
406 VG_(clo_log_file_qualifier) = &arg[21];
407 }
408
sewardj603d4102005-01-11 14:01:02 +0000409 else if (VG_CLO_STREQN(19, arg, "--log-file-exactly=")) {
njnbe9b47b2005-05-15 16:22:58 +0000410 log_to = VgLogTo_FileExactly;
sewardj603d4102005-01-11 14:01:02 +0000411 VG_(clo_log_name) = &arg[19];
412 }
sewardjde4a1d02002-03-22 01:27:54 +0000413
nethercotef8548672004-06-21 12:42:35 +0000414 else if (VG_CLO_STREQN(13, arg, "--log-socket=")) {
njnbe9b47b2005-05-15 16:22:58 +0000415 log_to = VgLogTo_Socket;
nethercotef8548672004-06-21 12:42:35 +0000416 VG_(clo_log_name) = &arg[13];
sewardj73cf3bc2002-11-03 03:20:15 +0000417 }
418
sewardj768db0e2005-07-19 14:18:56 +0000419 else if (VG_CLO_STREQN(19, arg, "--xml-user-comment=")) {
420 VG_(clo_xml_user_comment) = &arg[19];
421 }
422
nethercote71980f02004-01-24 18:18:54 +0000423 else if (VG_CLO_STREQN(15, arg, "--suppressions=")) {
sewardjde4a1d02002-03-22 01:27:54 +0000424 if (VG_(clo_n_suppressions) >= VG_CLO_MAX_SFILES) {
njn25e49d8e72002-09-23 09:36:25 +0000425 VG_(message)(Vg_UserMsg, "Too many suppression files specified.");
sewardjde4a1d02002-03-22 01:27:54 +0000426 VG_(message)(Vg_UserMsg,
427 "Increase VG_CLO_MAX_SFILES and recompile.");
sewardj17c11042006-10-15 01:26:40 +0000428 VG_(err_bad_option)(arg);
sewardjde4a1d02002-03-22 01:27:54 +0000429 }
nethercote71980f02004-01-24 18:18:54 +0000430 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = &arg[15];
sewardjde4a1d02002-03-22 01:27:54 +0000431 VG_(clo_n_suppressions)++;
432 }
sewardjde4a1d02002-03-22 01:27:54 +0000433
sewardjfa8ec112005-01-19 11:55:34 +0000434 /* "stuvwxyz" --> stuvwxyz (binary) */
435 else if (VG_CLO_STREQN(14, arg, "--trace-flags=")) {
436 Int j;
437 char* opt = & arg[14];
438
439 if (8 != VG_(strlen)(opt)) {
440 VG_(message)(Vg_UserMsg,
441 "--trace-flags argument must have 8 digits");
sewardj17c11042006-10-15 01:26:40 +0000442 VG_(err_bad_option)(arg);
sewardjfa8ec112005-01-19 11:55:34 +0000443 }
444 for (j = 0; j < 8; j++) {
445 if ('0' == opt[j]) { /* do nothing */ }
446 else if ('1' == opt[j]) VG_(clo_trace_flags) |= (1 << (7-j));
447 else {
448 VG_(message)(Vg_UserMsg, "--trace-flags argument can only "
449 "contain 0s and 1s");
sewardj17c11042006-10-15 01:26:40 +0000450 VG_(err_bad_option)(arg);
sewardjfa8ec112005-01-19 11:55:34 +0000451 }
452 }
453 }
454
455 /* "stuvwxyz" --> stuvwxyz (binary) */
456 else if (VG_CLO_STREQN(16, arg, "--profile-flags=")) {
njn25e49d8e72002-09-23 09:36:25 +0000457 Int j;
nethercote71980f02004-01-24 18:18:54 +0000458 char* opt = & arg[16];
njn25e49d8e72002-09-23 09:36:25 +0000459
sewardj2a99cf62004-11-24 10:44:19 +0000460 if (8 != VG_(strlen)(opt)) {
njn25e49d8e72002-09-23 09:36:25 +0000461 VG_(message)(Vg_UserMsg,
sewardjfa8ec112005-01-19 11:55:34 +0000462 "--profile-flags argument must have 8 digits");
sewardj17c11042006-10-15 01:26:40 +0000463 VG_(err_bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +0000464 }
sewardj8b635a42004-11-22 19:01:47 +0000465 for (j = 0; j < 8; j++) {
njn25e49d8e72002-09-23 09:36:25 +0000466 if ('0' == opt[j]) { /* do nothing */ }
sewardjfa8ec112005-01-19 11:55:34 +0000467 else if ('1' == opt[j]) VG_(clo_profile_flags) |= (1 << (7-j));
njn25e49d8e72002-09-23 09:36:25 +0000468 else {
sewardjfa8ec112005-01-19 11:55:34 +0000469 VG_(message)(Vg_UserMsg, "--profile-flags argument can only "
njn25e49d8e72002-09-23 09:36:25 +0000470 "contain 0s and 1s");
sewardj17c11042006-10-15 01:26:40 +0000471 VG_(err_bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +0000472 }
473 }
474 }
sewardjde4a1d02002-03-22 01:27:54 +0000475
njn45270a22005-03-27 01:00:11 +0000476 else VG_NUM_CLO (arg, "--trace-notbelow", VG_(clo_trace_notbelow))
sewardjc771b292004-11-30 18:55:21 +0000477
sewardjd153fae2005-01-10 17:24:47 +0000478 else if (VG_CLO_STREQ(arg, "--gen-suppressions=no"))
479 VG_(clo_gen_suppressions) = 0;
480 else if (VG_CLO_STREQ(arg, "--gen-suppressions=yes"))
481 VG_(clo_gen_suppressions) = 1;
482 else if (VG_CLO_STREQ(arg, "--gen-suppressions=all"))
483 VG_(clo_gen_suppressions) = 2;
484
nethercote71980f02004-01-24 18:18:54 +0000485 else if ( ! VG_(needs).command_line_options
njn51d827b2005-05-09 01:02:08 +0000486 || ! VG_TDICT_CALL(tool_process_cmd_line_option, arg) ) {
sewardj17c11042006-10-15 01:26:40 +0000487 VG_(err_bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +0000488 }
njn8c0b3bb2005-03-12 21:20:39 +0000489 skip_arg:
sewardj45f4e7c2005-09-27 19:20:21 +0000490 if (arg != VG_(args_for_valgrind).strs[i]) {
491 VG_(free)(arg);
492 }
sewardjde4a1d02002-03-22 01:27:54 +0000493 }
494
sewardj998d40d2004-12-06 14:24:52 +0000495 /* Make VEX control parameters sane */
496
497 if (VG_(clo_vex_control).guest_chase_thresh
498 >= VG_(clo_vex_control).guest_max_insns)
499 VG_(clo_vex_control).guest_chase_thresh
500 = VG_(clo_vex_control).guest_max_insns - 1;
501
502 if (VG_(clo_vex_control).guest_chase_thresh < 0)
503 VG_(clo_vex_control).guest_chase_thresh = 0;
504
505 /* Check various option values */
nethercote27fec902004-06-16 21:26:32 +0000506
njnf9ebf672003-05-12 21:41:30 +0000507 if (VG_(clo_verbosity) < 0)
sewardjde4a1d02002-03-22 01:27:54 +0000508 VG_(clo_verbosity) = 0;
509
nethercote04d0fbc2004-01-26 16:48:06 +0000510 if (VG_(clo_db_attach) && VG_(clo_trace_children)) {
sewardjde4a1d02002-03-22 01:27:54 +0000511 VG_(message)(Vg_UserMsg, "");
512 VG_(message)(Vg_UserMsg,
nethercote04d0fbc2004-01-26 16:48:06 +0000513 "--db-attach=yes conflicts with --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +0000514 VG_(message)(Vg_UserMsg,
515 "Please choose one or the other, but not both.");
sewardj17c11042006-10-15 01:26:40 +0000516 VG_(err_bad_option)("--db-attach=yes and --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +0000517 }
518
njnbe9b47b2005-05-15 16:22:58 +0000519 if (VG_(clo_gen_suppressions) > 0 &&
520 !VG_(needs).core_errors && !VG_(needs).tool_errors) {
521 VG_(message)(Vg_UserMsg,
522 "Can't use --gen-suppressions= with this tool,");
523 VG_(message)(Vg_UserMsg,
524 "as it doesn't generate errors.");
sewardj17c11042006-10-15 01:26:40 +0000525 VG_(err_bad_option)("--gen-suppressions=");
njnbe9b47b2005-05-15 16:22:58 +0000526 }
527
sewardj71bc3cb2005-05-19 00:25:45 +0000528 /* If we've been asked to emit XML, mash around various other
529 options so as to constrain the output somewhat, and to remove
530 any need for user input during the run. */
531 if (VG_(clo_xml)) {
532 /* Disable suppression generation (requires user input) */
533 VG_(clo_gen_suppressions) = 0;
534 /* Disable attaching to GDB (requires user input) */
535 VG_(clo_db_attach) = False;
536 /* Set a known verbosity level */
537 VG_(clo_verbosity) = 1;
538 /* Disable error limits (this might be a bad idea!) */
539 VG_(clo_error_limit) = False;
540 /* Disable emulation warnings */
541 VG_(clo_show_emwarns) = False;
542 /* Disable waiting for GDB to debug Valgrind */
543 VG_(clo_wait_for_gdb) = False;
544 /* No file-descriptor leak checking yet */
545 VG_(clo_track_fds) = False;
sewardj21f7f0c2005-07-06 19:46:48 +0000546 /* Disable timestamped output */
547 VG_(clo_time_stamp) = False;
sewardj71bc3cb2005-05-19 00:25:45 +0000548 /* Also, we want to set options for the leak checker, but that
549 will have to be done in Memcheck's flag-handling code, not
550 here. */
551 }
552
njnbe9b47b2005-05-15 16:22:58 +0000553 /* All non-logging-related options have been checked. If the logging
554 option specified is ok, we can switch to it, as we know we won't
555 have to generate any other command-line-related error messages.
556 (So far we should be still attached to stderr, so we can show on
557 the terminal any problems to do with processing command line
558 opts.)
559
560 So set up logging now. After this is done, VG_(clo_log_fd)
sewardj4cf05692002-10-27 20:28:29 +0000561 should be connected to whatever sink has been selected, and we
562 indiscriminately chuck stuff into it without worrying what the
563 nature of it is. Oh the wonder of Unix streams. */
564
njnbe9b47b2005-05-15 16:22:58 +0000565 vg_assert(VG_(clo_log_fd) == 2 /* stderr */);
566 vg_assert(VG_(logging_to_socket) == False);
sewardj4cf05692002-10-27 20:28:29 +0000567
njnbe9b47b2005-05-15 16:22:58 +0000568 switch (log_to) {
sewardj73cf3bc2002-11-03 03:20:15 +0000569
sewardj4cf05692002-10-27 20:28:29 +0000570 case VgLogTo_Fd:
nethercotef8548672004-06-21 12:42:35 +0000571 vg_assert(VG_(clo_log_name) == NULL);
sewardj4cf05692002-10-27 20:28:29 +0000572 break;
sewardj73cf3bc2002-11-03 03:20:15 +0000573
sewardj4cf05692002-10-27 20:28:29 +0000574 case VgLogTo_File: {
sewardjad311162005-07-19 11:25:02 +0000575 HChar logfilename[1000];
576 Int seq = 0;
577 Int pid = VG_(getpid)();
578 HChar* qual = NULL;
jsgff3c3f1a2003-10-14 22:13:28 +0000579
nethercotef8548672004-06-21 12:42:35 +0000580 vg_assert(VG_(clo_log_name) != NULL);
581 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
jsgff3c3f1a2003-10-14 22:13:28 +0000582
sewardjad311162005-07-19 11:25:02 +0000583 if (VG_(clo_log_file_qualifier)) {
584 qual = VG_(getenv)(VG_(clo_log_file_qualifier));
585 }
586
nethercote71980f02004-01-24 18:18:54 +0000587 for (;;) {
sewardj92645592005-07-23 09:18:34 +0000588 HChar pidtxt[20], seqtxt[20];
589
590 VG_(sprintf)(pidtxt, "%d", pid);
591
592 if (seq == 0)
593 seqtxt[0] = 0;
594 else
595 VG_(sprintf)(seqtxt, ".%d", seq);
596
jsgff3c3f1a2003-10-14 22:13:28 +0000597 seq++;
598
sewardj92645592005-07-23 09:18:34 +0000599 /* Result:
600 if (qual) base_name ++ "." ++ qual ++ seqtxt
601 if (not qual) base_name ++ "." ++ pid ++ seqtxt
602 */
603 VG_(sprintf)( logfilename,
604 "%s.%s%s",
605 VG_(clo_log_name),
606 qual ? qual : pidtxt,
607 seqtxt );
608
njnbe9b47b2005-05-15 16:22:58 +0000609 // EXCL: it will fail with EEXIST if the file already exists.
njnda033f52005-12-19 21:27:58 +0000610 sres = VG_(open)(logfilename,
611 VKI_O_CREAT|VKI_O_WRONLY|VKI_O_EXCL|VKI_O_TRUNC,
612 VKI_S_IRUSR|VKI_S_IWUSR);
sewardj92645592005-07-23 09:18:34 +0000613 if (!sres.isError) {
sewardj12ab7652006-10-17 02:10:42 +0000614 tmp_log_fd = sres.res;
sewardj603d4102005-01-11 14:01:02 +0000615 break; /* for (;;) */
jsgff3c3f1a2003-10-14 22:13:28 +0000616 } else {
njnbe9b47b2005-05-15 16:22:58 +0000617 // If the file already existed, we try the next name. If it
618 // was some other file error, we give up.
sewardj12ab7652006-10-17 02:10:42 +0000619 if (sres.err != VKI_EEXIST) {
jsgff3c3f1a2003-10-14 22:13:28 +0000620 VG_(message)(Vg_UserMsg,
sewardjc40fce52006-05-03 13:52:17 +0000621 "Can't create log file '%s' (%s); giving up!",
sewardj12ab7652006-10-17 02:10:42 +0000622 logfilename, VG_(strerror)(sres.err));
sewardj17c11042006-10-15 01:26:40 +0000623 VG_(err_bad_option)(
sewardj603d4102005-01-11 14:01:02 +0000624 "--log-file=<file> (didn't work out for some reason.)");
njnbe9b47b2005-05-15 16:22:58 +0000625 /*NOTREACHED*/
jsgff3c3f1a2003-10-14 22:13:28 +0000626 }
627 }
628 }
sewardj603d4102005-01-11 14:01:02 +0000629 break; /* switch (VG_(clo_log_to)) */
630 }
631
632 case VgLogTo_FileExactly: {
sewardj603d4102005-01-11 14:01:02 +0000633 vg_assert(VG_(clo_log_name) != NULL);
634 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
sewardj603d4102005-01-11 14:01:02 +0000635
njnda033f52005-12-19 21:27:58 +0000636 sres = VG_(open)(VG_(clo_log_name),
637 VKI_O_CREAT|VKI_O_WRONLY|VKI_O_TRUNC,
638 VKI_S_IRUSR|VKI_S_IWUSR);
sewardj92645592005-07-23 09:18:34 +0000639 if (!sres.isError) {
sewardj12ab7652006-10-17 02:10:42 +0000640 tmp_log_fd = sres.res;
njnbe9b47b2005-05-15 16:22:58 +0000641 } else {
sewardj603d4102005-01-11 14:01:02 +0000642 VG_(message)(Vg_UserMsg,
njn02bc4b82005-05-15 17:28:26 +0000643 "Can't create/open log file '%s'; giving up!",
sewardj603d4102005-01-11 14:01:02 +0000644 VG_(clo_log_name));
sewardj17c11042006-10-15 01:26:40 +0000645 VG_(err_bad_option)(
sewardj603d4102005-01-11 14:01:02 +0000646 "--log-file-exactly=<file> (didn't work out for some reason.)");
647 /*NOTREACHED*/
648 }
649 break; /* switch (VG_(clo_log_to)) */
sewardj73cf3bc2002-11-03 03:20:15 +0000650 }
651
652 case VgLogTo_Socket: {
nethercotef8548672004-06-21 12:42:35 +0000653 vg_assert(VG_(clo_log_name) != NULL);
654 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
njnda033f52005-12-19 21:27:58 +0000655 tmp_log_fd = VG_(connect_via_socket)( VG_(clo_log_name) );
656 if (tmp_log_fd == -1) {
sewardj73cf3bc2002-11-03 03:20:15 +0000657 VG_(message)(Vg_UserMsg,
nethercotef8548672004-06-21 12:42:35 +0000658 "Invalid --log-socket=ipaddr or --log-socket=ipaddr:port spec");
sewardj73cf3bc2002-11-03 03:20:15 +0000659 VG_(message)(Vg_UserMsg,
njn02bc4b82005-05-15 17:28:26 +0000660 "of '%s'; giving up!", VG_(clo_log_name) );
sewardj17c11042006-10-15 01:26:40 +0000661 VG_(err_bad_option)(
nethercotef8548672004-06-21 12:42:35 +0000662 "--log-socket=");
njnbe9b47b2005-05-15 16:22:58 +0000663 /*NOTREACHED*/
sewardj4cf05692002-10-27 20:28:29 +0000664 }
njnda033f52005-12-19 21:27:58 +0000665 if (tmp_log_fd == -2) {
sewardj73cf3bc2002-11-03 03:20:15 +0000666 VG_(message)(Vg_UserMsg,
njn02bc4b82005-05-15 17:28:26 +0000667 "valgrind: failed to connect to logging server '%s'.",
nethercotef8548672004-06-21 12:42:35 +0000668 VG_(clo_log_name) );
sewardj570f8902002-11-03 11:44:36 +0000669 VG_(message)(Vg_UserMsg,
670 "Log messages will sent to stderr instead." );
671 VG_(message)(Vg_UserMsg,
672 "" );
673 /* We don't change anything here. */
njnbe9b47b2005-05-15 16:22:58 +0000674 vg_assert(VG_(clo_log_fd) == 2);
njnda033f52005-12-19 21:27:58 +0000675 tmp_log_fd = 2;
sewardj570f8902002-11-03 11:44:36 +0000676 } else {
njnda033f52005-12-19 21:27:58 +0000677 vg_assert(tmp_log_fd > 0);
njnbe9b47b2005-05-15 16:22:58 +0000678 VG_(logging_to_socket) = True;
sewardj570f8902002-11-03 11:44:36 +0000679 }
sewardj73cf3bc2002-11-03 03:20:15 +0000680 break;
681 }
sewardj4cf05692002-10-27 20:28:29 +0000682 }
683
sewardj71bc3cb2005-05-19 00:25:45 +0000684
685 /* Check that the requested tool actually supports XML output. */
njnca54af32006-04-16 10:25:43 +0000686 if (VG_(clo_xml) && !VG_(needs).xml_output) {
sewardj71bc3cb2005-05-19 00:25:45 +0000687 VG_(clo_xml) = False;
688 VG_(message)(Vg_UserMsg,
njnca54af32006-04-16 10:25:43 +0000689 "%s does not support XML output.", VG_(details).name);
sewardj17c11042006-10-15 01:26:40 +0000690 VG_(err_bad_option)("--xml=yes");
sewardj71bc3cb2005-05-19 00:25:45 +0000691 /*NOTREACHED*/
692 }
693
njnda033f52005-12-19 21:27:58 +0000694 if (tmp_log_fd >= 0) {
695 // Move log_fd into the safe range, so it doesn't conflict with any app fds.
696 tmp_log_fd = VG_(fcntl)(tmp_log_fd, VKI_F_DUPFD, VG_(fd_hard_limit));
697 if (tmp_log_fd < 0) {
698 VG_(message)(Vg_UserMsg, "valgrind: failed to move logfile fd into safe range, using stderr");
699 VG_(clo_log_fd) = 2; // stderr
700 } else {
701 VG_(clo_log_fd) = tmp_log_fd;
702 VG_(fcntl)(VG_(clo_log_fd), VKI_F_SETFD, VKI_FD_CLOEXEC);
703 }
704 } else {
705 // If they said --log-fd=-1, don't print anything. Plausible for use in
706 // regression testing suites that use client requests to count errors.
707 VG_(clo_log_fd) = tmp_log_fd;
jsgf855d93d2003-10-13 22:26:55 +0000708 }
709
sewardj45f4e7c2005-09-27 19:20:21 +0000710 if (VG_(clo_n_suppressions) < VG_CLO_MAX_SFILES-1 &&
711 (VG_(needs).core_errors || VG_(needs).tool_errors)) {
712 /* If we haven't reached the max number of suppressions, load
713 the default one. */
714 static const Char default_supp[] = "default.supp";
715 Int len = VG_(strlen)(VG_(libdir)) + 1 + sizeof(default_supp);
716 Char *buf = VG_(arena_malloc)(VG_AR_CORE, len);
717 VG_(sprintf)(buf, "%s/%s", VG_(libdir), default_supp);
718 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = buf;
719 VG_(clo_n_suppressions)++;
720 }
sewardjde4a1d02002-03-22 01:27:54 +0000721
sewardj45f4e7c2005-09-27 19:20:21 +0000722 return (log_to == VgLogTo_Fd);
723}
724
725
726/*====================================================================*/
727/*=== Printing the preamble ===*/
728/*====================================================================*/
729
730/* Ok, the logging sink is running now. Print a suitable preamble.
731 If logging to file or a socket, write details of parent PID and
732 command line args, to help people trying to interpret the
733 results of a run which encompasses multiple processes. */
734static void print_preamble(Bool logging_to_fd, const char* toolname)
735{
tom60a4b0b2005-10-12 10:45:27 +0000736 HChar* xpre = VG_(clo_xml) ? " <line>" : "";
737 HChar* xpost = VG_(clo_xml) ? "</line>" : "";
738 Int i;
739
sewardj71bc3cb2005-05-19 00:25:45 +0000740 if (VG_(clo_xml)) {
sewardj8665d8e2005-06-01 17:35:23 +0000741 VG_(message)(Vg_UserMsg, "<?xml version=\"1.0\"?>");
742 VG_(message)(Vg_UserMsg, "");
sewardj71bc3cb2005-05-19 00:25:45 +0000743 VG_(message)(Vg_UserMsg, "<valgrindoutput>");
744 VG_(message)(Vg_UserMsg, "");
cerion20241ba2005-11-15 19:07:53 +0000745 VG_(message)(Vg_UserMsg, "<protocolversion>2</protocolversion>");
sewardj71bc3cb2005-05-19 00:25:45 +0000746 VG_(message)(Vg_UserMsg, "");
747 }
748
sewardj83adf412002-05-01 01:25:45 +0000749 if (VG_(clo_verbosity > 0)) {
sewardjd7bddad2005-06-13 16:48:32 +0000750
751 if (VG_(clo_xml))
752 VG_(message)(Vg_UserMsg, "<preamble>");
753
nethercote996901a2004-08-03 13:29:09 +0000754 /* Tool details */
sewardj71bc3cb2005-05-19 00:25:45 +0000755 VG_(message)(Vg_UserMsg, "%s%s%s%s, %s.%s",
756 xpre,
njnd04b7c62002-10-03 14:05:52 +0000757 VG_(details).name,
njnb9c427c2004-12-01 14:14:42 +0000758 NULL == VG_(details).version ? "" : "-",
njnd04b7c62002-10-03 14:05:52 +0000759 NULL == VG_(details).version
760 ? (Char*)"" : VG_(details).version,
sewardj71bc3cb2005-05-19 00:25:45 +0000761 VG_(details).description,
762 xpost);
763 VG_(message)(Vg_UserMsg, "%s%s%s",
764 xpre, VG_(details).copyright_author, xpost);
sewardj3b2736a2002-03-24 12:18:35 +0000765
njnd04b7c62002-10-03 14:05:52 +0000766 /* Core details */
767 VG_(message)(Vg_UserMsg,
sewardj71bc3cb2005-05-19 00:25:45 +0000768 "%sUsing LibVEX rev %s, a library for dynamic binary translation.%s",
769 xpre, LibVEX_Version(), xpost );
sewardjc7025332004-12-13 18:30:39 +0000770 VG_(message)(Vg_UserMsg,
sewardja2cd32d2006-05-27 03:22:47 +0000771 "%sCopyright (C) 2004-2006, and GNU GPL'd, by OpenWorks LLP.%s",
sewardj71bc3cb2005-05-19 00:25:45 +0000772 xpre, xpost );
sewardjc7025332004-12-13 18:30:39 +0000773 VG_(message)(Vg_UserMsg,
sewardj71bc3cb2005-05-19 00:25:45 +0000774 "%sUsing valgrind-%s, a dynamic binary instrumentation framework.%s",
775 xpre, VERSION, xpost);
sewardjde4a1d02002-03-22 01:27:54 +0000776 VG_(message)(Vg_UserMsg,
sewardja2cd32d2006-05-27 03:22:47 +0000777 "%sCopyright (C) 2000-2006, and GNU GPL'd, by Julian Seward et al.%s",
sewardj71bc3cb2005-05-19 00:25:45 +0000778 xpre, xpost );
sewardjd7bddad2005-06-13 16:48:32 +0000779
sewardj45f4e7c2005-09-27 19:20:21 +0000780 if (VG_(clo_verbosity) == 1 && !VG_(clo_xml))
781 VG_(message)(Vg_UserMsg, "For more details, rerun with: -v");
782
sewardjd7bddad2005-06-13 16:48:32 +0000783 if (VG_(clo_xml))
784 VG_(message)(Vg_UserMsg, "</preamble>");
njnd04b7c62002-10-03 14:05:52 +0000785 }
786
sewardj45f4e7c2005-09-27 19:20:21 +0000787 if (!VG_(clo_xml) && VG_(clo_verbosity) > 0 && !logging_to_fd) {
sewardj4cf05692002-10-27 20:28:29 +0000788 VG_(message)(Vg_UserMsg, "");
789 VG_(message)(Vg_UserMsg,
790 "My PID = %d, parent PID = %d. Prog and args are:",
791 VG_(getpid)(), VG_(getppid)() );
sewardj5e940782005-09-28 19:59:19 +0000792 if (VG_(args_the_exename))
793 VG_(message)(Vg_UserMsg, " %s", VG_(args_the_exename));
sewardj45f4e7c2005-09-27 19:20:21 +0000794 for (i = 0; i < VG_(args_for_client).used; i++)
795 VG_(message)(Vg_UserMsg, " %s", VG_(args_for_client).strs[i]);
sewardj5b742c32005-07-26 23:43:26 +0000796 if (VG_(clo_log_file_qualifier)) {
797 HChar* val = VG_(getenv)(VG_(clo_log_file_qualifier));
798 VG_(message)(Vg_UserMsg, "");
799 VG_(message)(Vg_UserMsg, "Log file qualifier: var %s, value %s.",
800 VG_(clo_log_file_qualifier),
801 val ? val : "");
802 }
sewardj4cf05692002-10-27 20:28:29 +0000803 }
sewardj71bc3cb2005-05-19 00:25:45 +0000804 else
805 if (VG_(clo_xml)) {
806 VG_(message)(Vg_UserMsg, "");
807 VG_(message)(Vg_UserMsg, "<pid>%d</pid>", VG_(getpid)());
808 VG_(message)(Vg_UserMsg, "<ppid>%d</ppid>", VG_(getppid)());
sewardj97f7e0c2005-07-19 15:00:25 +0000809 VG_(message)(Vg_UserMsg, "<tool>%t</tool>", toolname);
sewardjad311162005-07-19 11:25:02 +0000810 if (VG_(clo_log_file_qualifier)) {
811 HChar* val = VG_(getenv)(VG_(clo_log_file_qualifier));
sewardj97f7e0c2005-07-19 15:00:25 +0000812 VG_(message)(Vg_UserMsg, "<logfilequalifier> <var>%t</var> "
813 "<value>%t</value> </logfilequalifier>",
sewardjad311162005-07-19 11:25:02 +0000814 VG_(clo_log_file_qualifier),
815 val ? val : "");
816 }
sewardj768db0e2005-07-19 14:18:56 +0000817 if (VG_(clo_xml_user_comment)) {
818 /* Note: the user comment itself is XML and is therefore to
819 be passed through verbatim (%s) rather than escaped
820 (%t). */
821 VG_(message)(Vg_UserMsg, "<usercomment>%s</usercomment>",
822 VG_(clo_xml_user_comment));
823 }
sewardj71bc3cb2005-05-19 00:25:45 +0000824 VG_(message)(Vg_UserMsg, "");
sewardjb8a3dac2005-07-19 12:39:11 +0000825 VG_(message)(Vg_UserMsg, "<args>");
sewardj45f4e7c2005-09-27 19:20:21 +0000826
sewardjb8a3dac2005-07-19 12:39:11 +0000827 VG_(message)(Vg_UserMsg, " <vargv>");
sewardj45f4e7c2005-09-27 19:20:21 +0000828 if (VG_(name_of_launcher))
829 VG_(message)(Vg_UserMsg, " <exe>%t</exe>",
830 VG_(name_of_launcher));
831 for (i = 0; i < VG_(args_for_valgrind).used; i++) {
832 VG_(message)(Vg_UserMsg,
833 " <arg>%t</arg>",
834 VG_(args_for_valgrind).strs[i]);
sewardjb8a3dac2005-07-19 12:39:11 +0000835 }
836 VG_(message)(Vg_UserMsg, " </vargv>");
sewardj45f4e7c2005-09-27 19:20:21 +0000837
sewardjb8a3dac2005-07-19 12:39:11 +0000838 VG_(message)(Vg_UserMsg, " <argv>");
sewardj45f4e7c2005-09-27 19:20:21 +0000839 if (VG_(args_the_exename))
840 VG_(message)(Vg_UserMsg, " <exe>%t</exe>",
841 VG_(args_the_exename));
842 for (i = 0; i < VG_(args_for_client).used; i++) {
843 VG_(message)(Vg_UserMsg, " <arg>%t</arg>",
844 VG_(args_for_client).strs[i]);
sewardj8665d8e2005-06-01 17:35:23 +0000845 }
sewardjb8a3dac2005-07-19 12:39:11 +0000846 VG_(message)(Vg_UserMsg, " </argv>");
sewardj45f4e7c2005-09-27 19:20:21 +0000847
sewardjb8a3dac2005-07-19 12:39:11 +0000848 VG_(message)(Vg_UserMsg, "</args>");
sewardj71bc3cb2005-05-19 00:25:45 +0000849 }
sewardj4cf05692002-10-27 20:28:29 +0000850
sewardj45f4e7c2005-09-27 19:20:21 +0000851 // Empty line after the preamble
852 if (VG_(clo_verbosity) > 0)
853 VG_(message)(Vg_UserMsg, "");
854
sewardjde4a1d02002-03-22 01:27:54 +0000855 if (VG_(clo_verbosity) > 1) {
sewardj92645592005-07-23 09:18:34 +0000856 SysRes fd;
sewardj1f0bbc72005-11-16 03:51:02 +0000857 VexArch vex_arch;
858 VexArchInfo vex_archinfo;
sewardj45f4e7c2005-09-27 19:20:21 +0000859 if (!logging_to_fd)
njn1fd5eb22005-03-13 05:43:23 +0000860 VG_(message)(Vg_DebugMsg, "");
njn1fd5eb22005-03-13 05:43:23 +0000861 VG_(message)(Vg_DebugMsg, "Command line");
sewardj45f4e7c2005-09-27 19:20:21 +0000862 if (VG_(args_the_exename))
863 VG_(message)(Vg_DebugMsg, " %s", VG_(args_the_exename));
864 for (i = 0; i < VG_(args_for_client).used; i++)
865 VG_(message)(Vg_DebugMsg, " %s", VG_(args_for_client).strs[i]);
njn86dc2bc2003-09-09 07:26:21 +0000866
njn1fd5eb22005-03-13 05:43:23 +0000867 VG_(message)(Vg_DebugMsg, "Startup, with flags:");
sewardj45f4e7c2005-09-27 19:20:21 +0000868 for (i = 0; i < VG_(args_for_valgrind).used; i++) {
869 VG_(message)(Vg_DebugMsg, " %s", VG_(args_for_valgrind).strs[i]);
sewardjde4a1d02002-03-22 01:27:54 +0000870 }
nethercotea70f7352004-04-18 12:08:46 +0000871
njn1fd5eb22005-03-13 05:43:23 +0000872 VG_(message)(Vg_DebugMsg, "Contents of /proc/version:");
nethercotea70f7352004-04-18 12:08:46 +0000873 fd = VG_(open) ( "/proc/version", VKI_O_RDONLY, 0 );
sewardj92645592005-07-23 09:18:34 +0000874 if (fd.isError) {
njn1fd5eb22005-03-13 05:43:23 +0000875 VG_(message)(Vg_DebugMsg, " can't open /proc/version");
nethercotea70f7352004-04-18 12:08:46 +0000876 } else {
sewardj71bc3cb2005-05-19 00:25:45 +0000877# define BUF_LEN 256
nethercotea70f7352004-04-18 12:08:46 +0000878 Char version_buf[BUF_LEN];
sewardj12ab7652006-10-17 02:10:42 +0000879 Int n = VG_(read) ( fd.res, version_buf, BUF_LEN );
njnbe9b47b2005-05-15 16:22:58 +0000880 vg_assert(n <= BUF_LEN);
nethercotea70f7352004-04-18 12:08:46 +0000881 if (n > 0) {
882 version_buf[n-1] = '\0';
njn1fd5eb22005-03-13 05:43:23 +0000883 VG_(message)(Vg_DebugMsg, " %s", version_buf);
nethercotea70f7352004-04-18 12:08:46 +0000884 } else {
njn1fd5eb22005-03-13 05:43:23 +0000885 VG_(message)(Vg_DebugMsg, " (empty?)");
nethercotea70f7352004-04-18 12:08:46 +0000886 }
sewardj12ab7652006-10-17 02:10:42 +0000887 VG_(close)(fd.res);
sewardj71bc3cb2005-05-19 00:25:45 +0000888# undef BUF_LEN
nethercotea70f7352004-04-18 12:08:46 +0000889 }
sewardj1f0bbc72005-11-16 03:51:02 +0000890
891 VG_(machine_get_VexArchInfo)( &vex_arch, &vex_archinfo );
sewardje3121f32006-01-27 21:23:23 +0000892 VG_(message)(
893 Vg_DebugMsg,
894 "Arch and hwcaps: %s, %s",
895 LibVEX_ppVexArch ( vex_arch ),
896 LibVEX_ppVexHwCaps ( vex_arch, vex_archinfo.hwcaps )
897 );
sewardj1f0bbc72005-11-16 03:51:02 +0000898 VG_(message)(Vg_DebugMsg, "Valgrind library directory: %s", VG_(libdir));
sewardjde4a1d02002-03-22 01:27:54 +0000899 }
nethercotef6a1d502004-08-09 12:21:57 +0000900}
901
sewardjde4a1d02002-03-22 01:27:54 +0000902
nethercote71980f02004-01-24 18:18:54 +0000903/*====================================================================*/
904/*=== File descriptor setup ===*/
905/*====================================================================*/
906
sewardj5f229e22005-09-28 01:36:01 +0000907/* Number of file descriptors that Valgrind tries to reserve for
908 it's own use - just a small constant. */
909#define N_RESERVED_FDS (10)
910
nethercote71980f02004-01-24 18:18:54 +0000911static void setup_file_descriptors(void)
912{
913 struct vki_rlimit rl;
sewardj17c11042006-10-15 01:26:40 +0000914 Bool show = False;
nethercote71980f02004-01-24 18:18:54 +0000915
916 /* Get the current file descriptor limits. */
917 if (VG_(getrlimit)(VKI_RLIMIT_NOFILE, &rl) < 0) {
918 rl.rlim_cur = 1024;
919 rl.rlim_max = 1024;
920 }
921
sewardj17c11042006-10-15 01:26:40 +0000922 if (show)
923 VG_(printf)("fd limits: host, before: cur %u max %u\n",
924 rl.rlim_cur, rl.rlim_max);
925
926# if defined(VGP_ppc32_aix5) || defined(VGP_ppc64_aix5)
927 /* I don't know why this kludge is needed; however if rl.rlim_cur
928 is RLIM_INFINITY, then VG_(safe_fd)'s attempts using VG_(fcntl)
929 to lift V's file descriptors above the threshold RLIM_INFINITY -
930 N_RESERVED_FDS fail. So just use a relatively conservative
931 value in this case. */
932 if (rl.rlim_cur > 1024)
933 rl.rlim_cur = 1024;
934# endif
935
nethercote71980f02004-01-24 18:18:54 +0000936 /* Work out where to move the soft limit to. */
njn14319cc2005-03-13 06:26:22 +0000937 if (rl.rlim_cur + N_RESERVED_FDS <= rl.rlim_max) {
938 rl.rlim_cur = rl.rlim_cur + N_RESERVED_FDS;
nethercote71980f02004-01-24 18:18:54 +0000939 } else {
940 rl.rlim_cur = rl.rlim_max;
941 }
942
943 /* Reserve some file descriptors for our use. */
njn14319cc2005-03-13 06:26:22 +0000944 VG_(fd_soft_limit) = rl.rlim_cur - N_RESERVED_FDS;
945 VG_(fd_hard_limit) = rl.rlim_cur - N_RESERVED_FDS;
nethercote71980f02004-01-24 18:18:54 +0000946
947 /* Update the soft limit. */
948 VG_(setrlimit)(VKI_RLIMIT_NOFILE, &rl);
949
sewardj17c11042006-10-15 01:26:40 +0000950 if (show) {
951 VG_(printf)("fd limits: host, after: cur %u max %u\n",
952 rl.rlim_cur, rl.rlim_max);
953 VG_(printf)("fd limits: guest : cur %u max %u\n",
954 VG_(fd_soft_limit), VG_(fd_hard_limit));
955 }
956
sewardj45f4e7c2005-09-27 19:20:21 +0000957 if (VG_(cl_exec_fd) != -1)
958 VG_(cl_exec_fd) = VG_(safe_fd)( VG_(cl_exec_fd) );
nethercote71980f02004-01-24 18:18:54 +0000959}
960
sewardjde4a1d02002-03-22 01:27:54 +0000961
njn2da73352005-06-18 01:35:16 +0000962/*====================================================================*/
njn2025cf92005-06-26 20:44:48 +0000963/*=== BB profiling ===*/
964/*====================================================================*/
965
966static
967void show_BB_profile ( BBProfEntry tops[], UInt n_tops, ULong score_total )
968{
969 ULong score_cumul, score_here;
970 Char buf_cumul[10], buf_here[10];
971 Char name[64];
972 Int r;
973
974 VG_(printf)("\n");
975 VG_(printf)("-----------------------------------------------------------\n");
976 VG_(printf)("--- BEGIN BB Profile (summary of scores) ---\n");
977 VG_(printf)("-----------------------------------------------------------\n");
978 VG_(printf)("\n");
979
980 VG_(printf)("Total score = %lld\n\n", score_total);
981
982 score_cumul = 0;
983 for (r = 0; r < n_tops; r++) {
984 if (tops[r].addr == 0)
985 continue;
986 name[0] = 0;
987 VG_(get_fnname_w_offset)(tops[r].addr, name, 64);
988 name[63] = 0;
989 score_here = tops[r].score;
990 score_cumul += score_here;
991 VG_(percentify)(score_cumul, score_total, 2, 6, buf_cumul);
992 VG_(percentify)(score_here, score_total, 2, 6, buf_here);
993 VG_(printf)("%3d: (%9lld %s) %9lld %s 0x%llx %s\n",
994 r,
995 score_cumul, buf_cumul,
996 score_here, buf_here, tops[r].addr, name );
997 }
998
999 VG_(printf)("\n");
1000 VG_(printf)("-----------------------------------------------------------\n");
1001 VG_(printf)("--- BB Profile (BB details) ---\n");
1002 VG_(printf)("-----------------------------------------------------------\n");
1003 VG_(printf)("\n");
1004
1005 score_cumul = 0;
1006 for (r = 0; r < n_tops; r++) {
1007 if (tops[r].addr == 0)
1008 continue;
1009 name[0] = 0;
1010 VG_(get_fnname_w_offset)(tops[r].addr, name, 64);
1011 name[63] = 0;
1012 score_here = tops[r].score;
1013 score_cumul += score_here;
1014 VG_(percentify)(score_cumul, score_total, 2, 6, buf_cumul);
1015 VG_(percentify)(score_here, score_total, 2, 6, buf_here);
1016 VG_(printf)("\n");
1017 VG_(printf)("=-=-=-=-=-=-=-=-=-=-=-=-=-= begin BB rank %d "
1018 "=-=-=-=-=-=-=-=-=-=-=-=-=-=\n\n", r);
1019 VG_(printf)("%3d: (%9lld %s) %9lld %s 0x%llx %s\n",
1020 r,
1021 score_cumul, buf_cumul,
1022 score_here, buf_here, tops[r].addr, name );
1023 VG_(printf)("\n");
sewardj0ec07f32006-01-12 12:32:32 +00001024 VG_(translate)(0, tops[r].addr, True, VG_(clo_profile_flags), 0, True);
njn2025cf92005-06-26 20:44:48 +00001025 VG_(printf)("=-=-=-=-=-=-=-=-=-=-=-=-=-= end BB rank %d "
1026 "=-=-=-=-=-=-=-=-=-=-=-=-=-=\n\n", r);
1027 }
1028
1029 VG_(printf)("\n");
1030 VG_(printf)("-----------------------------------------------------------\n");
1031 VG_(printf)("--- END BB Profile ---\n");
1032 VG_(printf)("-----------------------------------------------------------\n");
1033 VG_(printf)("\n");
1034}
1035
1036
1037/*====================================================================*/
nethercote71980f02004-01-24 18:18:54 +00001038/*=== main() ===*/
1039/*====================================================================*/
1040
sewardjfdf91b42005-09-28 00:53:09 +00001041/* When main() is entered, we should be on the following stack, not
1042 the one the kernel gave us. We will run on this stack until
1043 simulation of the root thread is started, at which point a transfer
1044 is made to a dynamically allocated stack. This is for the sake of
1045 uniform overflow detection for all Valgrind threads. This is
1046 marked global even though it isn't, because assembly code below
1047 needs to reference the name. */
1048
1049/*static*/ VgStack VG_(interim_stack);
1050
1051/* This should get some address inside the stack on which we gained
1052 control (eg, it could be the SP at startup). It doesn't matter
1053 exactly where in the stack it is. This value is passed to the
1054 address space manager at startup, which uses it to identify the
1055 initial stack segment and hence the upper end of the usable address
1056 space. */
1057
1058static Addr sp_at_startup = 0;
1059
sewardj1ae3f3a2005-09-28 10:47:38 +00001060/* --- Forwards decls to do with shutdown --- */
1061
1062static void final_tidyup(ThreadId tid);
1063
1064/* Do everything which needs doing when the last thread exits */
1065static
1066void shutdown_actions_NORETURN( ThreadId tid,
1067 VgSchedReturnCode tids_schedretcode );
1068
1069/* --- end of Forwards decls to do with shutdown --- */
sewardjfdf91b42005-09-28 00:53:09 +00001070
1071
sewardj45f4e7c2005-09-27 19:20:21 +00001072/* TODO: GIVE THIS A PROPER HOME
njn1d0825f2006-03-27 11:37:07 +00001073 TODO: MERGE THIS WITH DUPLICATE IN mc_leakcheck.c and coredump-elf.c.
sewardj45f4e7c2005-09-27 19:20:21 +00001074 Extract from aspacem a vector of the current segment start
1075 addresses. The vector is dynamically allocated and should be freed
1076 by the caller when done. REQUIRES m_mallocfree to be running.
1077 Writes the number of addresses required into *n_acquired. */
nethercotec314eba2004-07-15 12:59:41 +00001078
sewardj45f4e7c2005-09-27 19:20:21 +00001079static Addr* get_seg_starts ( /*OUT*/Int* n_acquired )
sewardj1cf558c2005-04-25 01:36:56 +00001080{
sewardj45f4e7c2005-09-27 19:20:21 +00001081 Addr* starts;
sewardja48a4932005-09-29 11:09:56 +00001082 Int n_starts, r = 0;
sewardj45f4e7c2005-09-27 19:20:21 +00001083
1084 n_starts = 1;
sewardj1cf558c2005-04-25 01:36:56 +00001085 while (True) {
sewardj45f4e7c2005-09-27 19:20:21 +00001086 starts = VG_(malloc)( n_starts * sizeof(Addr) );
1087 if (starts == NULL)
1088 break;
1089 r = VG_(am_get_segment_starts)( starts, n_starts );
1090 if (r >= 0)
1091 break;
1092 VG_(free)(starts);
1093 n_starts *= 2;
sewardj1cf558c2005-04-25 01:36:56 +00001094 }
sewardj45f4e7c2005-09-27 19:20:21 +00001095
1096 if (starts == NULL) {
1097 *n_acquired = 0;
1098 return NULL;
1099 }
1100
1101 *n_acquired = r;
1102 return starts;
sewardj1cf558c2005-04-25 01:36:56 +00001103}
1104
1105
sewardj17c11042006-10-15 01:26:40 +00001106static
1107Int valgrind_main ( Int argc, HChar **argv, HChar **envp,
1108 ULong* ppc_aix_initial_client_intregs37,
1109 void* ppc_aix_bootblock,
1110 UInt ppc_aix_adler32_for_compressed_page )
nethercote71980f02004-01-24 18:18:54 +00001111{
sewardj13247ca2005-12-30 22:52:20 +00001112 HChar* toolname = "memcheck"; // default to Memcheck
sewardj13247ca2005-12-30 22:52:20 +00001113 Int need_help = 0; // 0 = no, 1 = --help, 2 = --help-debug
sewardj13247ca2005-12-30 22:52:20 +00001114 Addr clstack_top = 0;
1115 SizeT clstack_max_size = 0;
sewardj4c3faae2006-03-15 11:50:32 +00001116 UInt* client_auxv = NULL;
sewardj45f4e7c2005-09-27 19:20:21 +00001117 Int loglevel, i;
1118 Bool logging_to_fd;
nethercote73b526f2004-10-31 18:48:21 +00001119 struct vki_rlimit zero = { 0, 0 };
sewardj17c11042006-10-15 01:26:40 +00001120
1121 ClientInitImgInfo ciii;
1122 VG_(memset)(&ciii, 0, sizeof(ClientInitImgInfo));
nethercote71980f02004-01-24 18:18:54 +00001123
1124 //============================================================
nethercote71980f02004-01-24 18:18:54 +00001125 //
sewardj45f4e7c2005-09-27 19:20:21 +00001126 // Nb: startup is complex. Prerequisites are shown at every step.
nethercote71980f02004-01-24 18:18:54 +00001127 // *** Be very careful when messing with the order ***
sewardj45f4e7c2005-09-27 19:20:21 +00001128 //
1129 // The first order of business is to get debug logging, the address
1130 // space manager and the dynamic memory manager up and running.
1131 // Once that's done, we can relax a bit.
1132 //
nethercote71980f02004-01-24 18:18:54 +00001133 //============================================================
sewardj45f4e7c2005-09-27 19:20:21 +00001134
1135 /* This is needed to make VG_(getenv) usable early. */
1136 VG_(client_envp) = (Char**)envp;
nethercote71980f02004-01-24 18:18:54 +00001137
sewardj1cf558c2005-04-25 01:36:56 +00001138 //--------------------------------------------------------------
1139 // Start up the logging mechanism
1140 // p: none
1141 //--------------------------------------------------------------
1142 /* Start the debugging-log system ASAP. First find out how many
1143 "-d"s were specified. This is a pre-scan of the command line. */
1144 loglevel = 0;
1145 for (i = 1; i < argc; i++) {
sewardj10759312005-05-30 23:52:47 +00001146 if (argv[i][0] != '-')
1147 break;
sewardj45f4e7c2005-09-27 19:20:21 +00001148 if (VG_STREQ(argv[i], "--"))
sewardj10759312005-05-30 23:52:47 +00001149 break;
sewardj45f4e7c2005-09-27 19:20:21 +00001150 if (VG_STREQ(argv[i], "-d"))
sewardj10759312005-05-30 23:52:47 +00001151 loglevel++;
sewardj1cf558c2005-04-25 01:36:56 +00001152 }
1153
1154 /* ... and start the debug logger. Now we can safely emit logging
1155 messages all through startup. */
sewardj10759312005-05-30 23:52:47 +00001156 VG_(debugLog_startup)(loglevel, "Stage 2 (main)");
sewardj45f4e7c2005-09-27 19:20:21 +00001157 VG_(debugLog)(1, "main", "Welcome to Valgrind version "
1158 VERSION " debug logging\n");
1159
1160 //--------------------------------------------------------------
sewardj17c11042006-10-15 01:26:40 +00001161 // AIX5 only: register the system call numbers
1162 // p: logging
1163 // p: that the initial few syscall numbers stated in the
1164 // bootblock have been installed (else we can't
1165 // open/read/close).
1166 //--------------------------------------------------------------
1167# if defined(VGO_aix5)
1168 VG_(debugLog)(1, "main", "aix5: registering syscalls ..\n");
1169 { UChar sysent_name[50];
1170 SysRes fd;
1171 Bool ok;
1172 Int n_unregd, sysent_used = 0;
1173 prsysent_t* sysent_hdr;
1174
1175 VG_(sprintf)(sysent_name, "/proc/%d/sysent", VG_(getpid)());
1176 fd = VG_(open)(sysent_name, VKI_O_RDONLY, 0);
1177 if (fd.isError)
1178 VG_(err_config_error)("aix5: can't open /proc/<pid>/sysent");
1179
1180 sysent_used = VG_(read)(fd.res, aix5_sysent_buf, VG_AIX5_SYSENT_SIZE);
1181 if (sysent_used < 0)
1182 VG_(err_config_error)("aix5: error reading /proc/<pid>/sysent");
1183 if (sysent_used >= VG_AIX5_SYSENT_SIZE)
1184 VG_(err_config_error)("aix5: VG_AIX5_SYSENT_SIZE is too low; "
1185 "increase and recompile");
1186 VG_(close)(fd.res);
1187
1188 vg_assert(sysent_used > 0 && sysent_used < VG_AIX5_SYSENT_SIZE);
1189
1190 sysent_hdr = (prsysent_t*)&aix5_sysent_buf[0];
1191
1192 n_unregd = 0;
1193 for (i = 0; i < sysent_hdr->pr_nsyscalls; i++) {
1194 UChar* name = &aix5_sysent_buf[ sysent_hdr
1195 ->pr_syscall[i].pr_nameoff ];
1196 UInt nmbr = sysent_hdr->pr_syscall[i].pr_number;
1197 VG_(debugLog)(3, "main", "aix5: bind syscall %d to \"%s\"\n",
1198 nmbr, name);
1199 ok = VG_(aix5_register_syscall)(nmbr, name);
1200 if (!ok)
1201 n_unregd++;
1202 if (!ok)
1203 VG_(debugLog)(3, "main",
1204 "aix5: bind FAILED: %d to \"%s\"\n",
1205 nmbr, name);
1206 }
1207 VG_(debugLog)(1, "main", "aix5: .. %d syscalls known, %d unknown\n",
1208 sysent_hdr->pr_nsyscalls - n_unregd, n_unregd );
1209 VG_(debugLog)(1, "main", "aix5: __NR_AIX5_FAKE_SIGRETURN = %d\n",
1210 __NR_AIX5_FAKE_SIGRETURN );
1211 }
1212# endif
1213
1214 //--------------------------------------------------------------
sewardj45f4e7c2005-09-27 19:20:21 +00001215 // Ensure we're on a plausible stack.
1216 // p: logging
1217 //--------------------------------------------------------------
1218 VG_(debugLog)(1, "main", "Checking current stack is plausible\n");
sewardjfdf91b42005-09-28 00:53:09 +00001219 { HChar* limLo = (HChar*)(&VG_(interim_stack).bytes[0]);
1220 HChar* limHi = limLo + sizeof(VG_(interim_stack));
sewardj45f4e7c2005-09-27 19:20:21 +00001221 HChar* aLocal = (HChar*)&zero; /* any auto local will do */
1222 if (aLocal < limLo || aLocal >= limHi) {
1223 /* something's wrong. Stop. */
1224 VG_(debugLog)(0, "main", "Root stack %p to %p, a local %p\n",
1225 limLo, limHi, aLocal );
1226 VG_(debugLog)(0, "main", "Valgrind: FATAL: "
1227 "Initial stack switched failed.\n");
1228 VG_(debugLog)(0, "main", " Cannot continue. Sorry.\n");
1229 VG_(exit)(1);
1230 }
1231 }
1232
1233 //--------------------------------------------------------------
1234 // Ensure we have a plausible pointer to the stack on which
1235 // we gained control (not the current stack!)
1236 // p: logging
1237 //--------------------------------------------------------------
1238 VG_(debugLog)(1, "main", "Checking initial stack was noted\n");
sewardjfdf91b42005-09-28 00:53:09 +00001239 if (sp_at_startup == 0) {
sewardj45f4e7c2005-09-27 19:20:21 +00001240 VG_(debugLog)(0, "main", "Valgrind: FATAL: "
1241 "Initial stack was not noted.\n");
1242 VG_(debugLog)(0, "main", " Cannot continue. Sorry.\n");
1243 VG_(exit)(1);
1244 }
1245
1246 //--------------------------------------------------------------
1247 // Start up the address space manager, and determine the
1248 // approximate location of the client's stack
1249 // p: logging, plausible-stack
1250 //--------------------------------------------------------------
1251 VG_(debugLog)(1, "main", "Starting the address space manager\n");
sewardjfdf91b42005-09-28 00:53:09 +00001252 clstack_top = VG_(am_startup)( sp_at_startup );
sewardj45f4e7c2005-09-27 19:20:21 +00001253 VG_(debugLog)(1, "main", "Address space manager is running\n");
1254
1255 //--------------------------------------------------------------
1256 // Start up the dynamic memory manager
1257 // p: address space management
1258 // In fact m_mallocfree is self-initialising, so there's no
1259 // initialisation call to do. Instead, try a simple malloc/
1260 // free pair right now to check that nothing is broken.
1261 //--------------------------------------------------------------
1262 VG_(debugLog)(1, "main", "Starting the dynamic memory manager\n");
1263 { void* p = VG_(malloc)( 12345 );
1264 if (p) VG_(free)( p );
1265 }
1266 VG_(debugLog)(1, "main", "Dynamic memory manager is running\n");
sewardj1cf558c2005-04-25 01:36:56 +00001267
nethercotef4928da2004-06-15 10:54:40 +00001268 //============================================================
sewardj45f4e7c2005-09-27 19:20:21 +00001269 //
1270 // Dynamic memory management is now available.
1271 //
nethercotef4928da2004-06-15 10:54:40 +00001272 //============================================================
1273
sewardj45f4e7c2005-09-27 19:20:21 +00001274 //--------------------------------------------------------------
1275 // Look for alternative libdir
1276 { HChar *cp = VG_(getenv)(VALGRIND_LIB);
1277 if (cp != NULL)
1278 VG_(libdir) = cp;
1279 }
1280
1281 //--------------------------------------------------------------
1282 // Extract the launcher name from the environment.
1283 VG_(debugLog)(1, "main", "Getting stage1's name\n");
1284 VG_(name_of_launcher) = VG_(getenv)(VALGRIND_LAUNCHER);
1285 if (VG_(name_of_launcher) == NULL) {
1286 VG_(printf)("valgrind: You cannot run '%s' directly.\n", argv[0]);
1287 VG_(printf)("valgrind: You should use $prefix/bin/valgrind.\n");
1288 VG_(exit)(1);
1289 }
1290
1291 //--------------------------------------------------------------
fitzhardingeb50068f2004-02-24 23:42:55 +00001292 // Get the current process datasize rlimit, and set it to zero.
1293 // This prevents any internal uses of brk() from having any effect.
1294 // We remember the old value so we can restore it on exec, so that
1295 // child processes will have a reasonable brk value.
1296 VG_(getrlimit)(VKI_RLIMIT_DATA, &VG_(client_rlimit_data));
1297 zero.rlim_max = VG_(client_rlimit_data).rlim_max;
1298 VG_(setrlimit)(VKI_RLIMIT_DATA, &zero);
thughesc37184f2004-09-11 14:16:57 +00001299
1300 // Get the current process stack rlimit.
1301 VG_(getrlimit)(VKI_RLIMIT_STACK, &VG_(client_rlimit_stack));
1302
sewardje2d1e672005-11-12 23:10:48 +00001303 //--------------------------------------------------------------
1304 // Figure out what sort of CPU we're on, and whether it is
1305 // able to run V.
1306 VG_(debugLog)(1, "main", "Get hardware capabilities ...\n");
1307 { VexArch vex_arch;
1308 VexArchInfo vex_archinfo;
1309 Bool ok = VG_(machine_get_hwcaps)();
1310 if (!ok) {
1311 VG_(printf)("\n");
1312 VG_(printf)("valgrind: fatal error: unsupported CPU.\n");
1313 VG_(printf)(" Supported CPUs are:\n");
1314 VG_(printf)(" * x86 (practically any; Pentium-I or above), "
1315 "AMD Athlon or above)\n");
1316 VG_(printf)(" * AMD Athlon64/Opteron\n");
1317 VG_(printf)(" * PowerPC (most; ppc405 and above)\n");
1318 VG_(printf)("\n");
1319 VG_(exit)(1);
1320 }
1321 VG_(machine_get_VexArchInfo)( &vex_arch, &vex_archinfo );
sewardje3121f32006-01-27 21:23:23 +00001322 VG_(debugLog)(
1323 1, "main", "... arch = %s, hwcaps = %s\n",
1324 LibVEX_ppVexArch ( vex_arch ),
1325 LibVEX_ppVexHwCaps ( vex_arch, vex_archinfo.hwcaps )
1326 );
sewardje2d1e672005-11-12 23:10:48 +00001327 }
1328
sewardj45f4e7c2005-09-27 19:20:21 +00001329 //============================================================
1330 // Command line argument handling order:
1331 // * If --help/--help-debug are present, show usage message
1332 // (including the tool-specific usage)
1333 // * (If no --tool option given, default to Memcheck)
1334 // * Then, if client is missing, abort with error msg
1335 // * Then, if any cmdline args are bad, abort with error msg
1336 //============================================================
1337
1338 //--------------------------------------------------------------
1339 // Split up argv into: C args, V args, V extra args, and exename.
1340 // p: dynamic memory allocation
1341 //--------------------------------------------------------------
1342 VG_(debugLog)(1, "main", "Split up command line\n");
1343 VG_(split_up_argv)( argc, argv );
1344 if (0) {
1345 for (i = 0; i < VG_(args_for_valgrind).used; i++)
1346 VG_(printf)("varg %s\n", VG_(args_for_valgrind).strs[i]);
1347 VG_(printf)(" exe %s\n", VG_(args_the_exename));
1348 for (i = 0; i < VG_(args_for_client).used; i++)
1349 VG_(printf)("carg %s\n", VG_(args_for_client).strs[i]);
nethercote71980f02004-01-24 18:18:54 +00001350 }
1351
1352 //--------------------------------------------------------------
sewardj45f4e7c2005-09-27 19:20:21 +00001353 // Extract tool name and whether help has been requested.
1354 // Note we can't print the help message yet, even if requested,
1355 // because the tool has not been initialised.
1356 // p: split_up_argv [for VG_(args_for_valgrind)]
nethercote71980f02004-01-24 18:18:54 +00001357 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00001358 VG_(debugLog)(1, "main", "Preprocess command line opts\n");
sewardj45f4e7c2005-09-27 19:20:21 +00001359 get_helprequest_and_toolname(&need_help, &toolname);
nethercote71980f02004-01-24 18:18:54 +00001360
sewardj45f4e7c2005-09-27 19:20:21 +00001361 // Set default vex control params
1362 LibVEX_default_VexControl(& VG_(clo_vex_control));
nethercote71980f02004-01-24 18:18:54 +00001363
1364 //--------------------------------------------------------------
1365 // Load client executable, finding in $PATH if necessary
sewardj45f4e7c2005-09-27 19:20:21 +00001366 // p: get_helprequest_and_toolname() [for 'exec', 'need_help']
nethercote71980f02004-01-24 18:18:54 +00001367 // p: layout_remaining_space [so there's space]
sewardj17c11042006-10-15 01:26:40 +00001368 //
nethercote71980f02004-01-24 18:18:54 +00001369 // Set up client's environment
sewardj45f4e7c2005-09-27 19:20:21 +00001370 // p: set-libdir [for VG_(libdir)]
1371 // p: get_helprequest_and_toolname [for toolname]
sewardj17c11042006-10-15 01:26:40 +00001372 //
nethercote5ee67ca2004-06-22 14:00:09 +00001373 // Setup client stack, eip, and VG_(client_arg[cv])
nethercote71980f02004-01-24 18:18:54 +00001374 // p: load_client() [for 'info']
1375 // p: fix_environment() [for 'env']
sewardj17c11042006-10-15 01:26:40 +00001376 //
sewardj45f4e7c2005-09-27 19:20:21 +00001377 // Setup client data (brk) segment. Initially a 1-page segment
1378 // which abuts a shrinkable reservation.
1379 // p: load_client() [for 'info' and hence VG_(brk_base)]
1380 //--------------------------------------------------------------
sewardj17c11042006-10-15 01:26:40 +00001381 if (!need_help) {
1382 VG_(debugLog)(1, "main", "Setting up initial image\n");
1383 ciii = VG_(setup_client_initial_image)(
1384 argv, envp, toolname,
1385 clstack_top, clstack_max_size
1386 );
1387# if defined(VGO_aix5)
1388 ciii.adler32_exp = ppc_aix_adler32_for_compressed_page;
1389 ciii.compressed_page = VG_PGROUNDDN((Addr)ppc_aix_bootblock);
1390 ciii.intregs37 = ppc_aix_initial_client_intregs37;
1391 ciii.initial_client_SP = ciii.intregs37[1]; /* r1 */
1392 /* Tell aspacem where the initial client stack is, so that it
1393 can later produce a faked-up NSegment in response to
1394 VG_(am_find_nsegment) for that address range, if asked. */
1395 VG_(am_aix5_set_initial_client_sp)( ciii.initial_client_SP );
1396# endif
sewardj45f4e7c2005-09-27 19:20:21 +00001397 }
nethercote71980f02004-01-24 18:18:54 +00001398
1399 //==============================================================
sewardj45f4e7c2005-09-27 19:20:21 +00001400 //
1401 // Finished loading/setting up the client address space.
1402 //
nethercote71980f02004-01-24 18:18:54 +00001403 //==============================================================
1404
1405 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00001406 // setup file descriptors
1407 // p: n/a
1408 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00001409 VG_(debugLog)(1, "main", "Setup file descriptors\n");
nethercote71980f02004-01-24 18:18:54 +00001410 setup_file_descriptors();
1411
1412 //--------------------------------------------------------------
sewardj45f4e7c2005-09-27 19:20:21 +00001413 // create the fake /proc/<pid>/cmdline file and then unlink it,
1414 // but hold onto the fd, so we can hand it out to the client
1415 // when it tries to open /proc/<pid>/cmdline for itself.
1416 // p: setup file descriptors
nethercotec314eba2004-07-15 12:59:41 +00001417 //--------------------------------------------------------------
sewardj45f4e7c2005-09-27 19:20:21 +00001418 if (!need_help) {
1419 HChar buf[50], buf2[50+64];
1420 HChar nul[1];
1421 Int fd, r;
1422 HChar* exename;
nethercotec314eba2004-07-15 12:59:41 +00001423
sewardj45f4e7c2005-09-27 19:20:21 +00001424 VG_(debugLog)(1, "main", "Create fake /proc/<pid>/cmdline\n");
1425
1426 VG_(sprintf)(buf, "proc_%d_cmdline", VG_(getpid)());
1427 fd = VG_(mkstemp)( buf, buf2 );
1428 if (fd == -1)
sewardj17c11042006-10-15 01:26:40 +00001429 VG_(err_config_error)("Can't create client cmdline file in /tmp.");
sewardj45f4e7c2005-09-27 19:20:21 +00001430
1431 nul[0] = 0;
1432 exename = VG_(args_the_exename) ? VG_(args_the_exename)
1433 : "unknown_exename";
sewardj45f4e7c2005-09-27 19:20:21 +00001434 VG_(write)(fd, VG_(args_the_exename),
1435 VG_(strlen)( VG_(args_the_exename) ));
1436 VG_(write)(fd, nul, 1);
1437
1438 for (i = 0; i < VG_(args_for_client).used; i++) {
1439 VG_(write)(fd, VG_(args_for_client).strs[i],
1440 VG_(strlen)( VG_(args_for_client).strs[i] ));
1441 VG_(write)(fd, nul, 1);
1442 }
1443
1444 /* Don't bother to seek the file back to the start; instead do
1445 it every time a copy of it is given out (by PRE(sys_open)).
1446 That is probably more robust across fork() etc. */
1447
1448 /* Now delete it, but hang on to the fd. */
1449 r = VG_(unlink)( buf2 );
1450 if (r)
sewardj17c11042006-10-15 01:26:40 +00001451 VG_(err_config_error)("Can't delete client cmdline file in /tmp.");
sewardj45f4e7c2005-09-27 19:20:21 +00001452
1453 VG_(cl_cmdline_fd) = fd;
1454 }
nethercotec314eba2004-07-15 12:59:41 +00001455
1456 //--------------------------------------------------------------
sewardj45f4e7c2005-09-27 19:20:21 +00001457 // Init tool part 1: pre_clo_init
nethercotec314eba2004-07-15 12:59:41 +00001458 // p: setup_client_stack() [for 'VG_(client_arg[cv]']
nethercotec314eba2004-07-15 12:59:41 +00001459 // p: setup_file_descriptors() [for 'VG_(fd_xxx_limit)']
nethercote71980f02004-01-24 18:18:54 +00001460 //--------------------------------------------------------------
njn64c83242005-06-21 01:54:38 +00001461 {
1462 Char* s;
1463 Bool ok;
sewardj45f4e7c2005-09-27 19:20:21 +00001464 VG_(debugLog)(1, "main", "Initialise the tool part 1 (pre_clo_init)\n");
1465 (VG_(tool_info).tl_pre_clo_init)();
1466 ok = VG_(sanity_check_needs)( &s );
njn64c83242005-06-21 01:54:38 +00001467 if (!ok) {
1468 VG_(tool_panic)(s);
1469 }
1470 }
nethercote71980f02004-01-24 18:18:54 +00001471
sewardj45f4e7c2005-09-27 19:20:21 +00001472 //--------------------------------------------------------------
nethercotef4928da2004-06-15 10:54:40 +00001473 // If --tool and --help/--help-debug was given, now give the core+tool
1474 // help message
sewardj45f4e7c2005-09-27 19:20:21 +00001475 // p: get_helprequest_and_toolname() [for 'need_help']
1476 // p: tl_pre_clo_init [for 'VG_(tdict).usage']
1477 //--------------------------------------------------------------
1478 VG_(debugLog)(1, "main", "Print help and quit, if requested\n");
nethercotef4928da2004-06-15 10:54:40 +00001479 if (need_help) {
sewardj45f4e7c2005-09-27 19:20:21 +00001480 usage_NORETURN(/*--help-debug?*/2 == need_help);
nethercotef4928da2004-06-15 10:54:40 +00001481 }
nethercotec314eba2004-07-15 12:59:41 +00001482
sewardj45f4e7c2005-09-27 19:20:21 +00001483 //--------------------------------------------------------------
1484 // Process command line options to Valgrind + tool
1485 // p: setup_client_stack() [for 'VG_(client_arg[cv]']
1486 // p: setup_file_descriptors() [for 'VG_(fd_xxx_limit)']
1487 //--------------------------------------------------------------
1488 VG_(debugLog)(1, "main", "Process Valgrind's command line options, "
sewardja48a4932005-09-29 11:09:56 +00001489 "setup logging\n");
sewardj45f4e7c2005-09-27 19:20:21 +00001490 logging_to_fd = process_cmd_line_options(client_auxv, toolname);
1491
1492 //--------------------------------------------------------------
sewardj592ae092005-11-08 19:01:44 +00001493 // Zeroise the millisecond counter by doing a first read of it.
1494 // p: none
1495 //--------------------------------------------------------------
1496 (void) VG_(read_millisecond_timer)();
1497
1498 //--------------------------------------------------------------
sewardj45f4e7c2005-09-27 19:20:21 +00001499 // Print the preamble
1500 // p: tl_pre_clo_init [for 'VG_(details).name' and friends]
1501 // p: process_cmd_line_options() [for VG_(clo_verbosity), VG_(clo_xml),
1502 // VG_(clo_log_file_qualifier),
1503 // logging_to_fd]
1504 //--------------------------------------------------------------
1505 VG_(debugLog)(1, "main", "Print the preamble...\n");
1506 print_preamble(logging_to_fd, toolname);
1507 VG_(debugLog)(1, "main", "...finished the preamble\n");
1508
1509 //--------------------------------------------------------------
1510 // Init tool part 2: post_clo_init
1511 // p: setup_client_stack() [for 'VG_(client_arg[cv]']
1512 // p: setup_file_descriptors() [for 'VG_(fd_xxx_limit)']
1513 // p: print_preamble() [so any warnings printed in post_clo_init
1514 // are shown after the preamble]
1515 //--------------------------------------------------------------
1516 VG_(debugLog)(1, "main", "Initialise the tool part 2 (post_clo_init)\n");
njn51d827b2005-05-09 01:02:08 +00001517 VG_TDICT_CALL(tool_post_clo_init);
nethercotef4928da2004-06-15 10:54:40 +00001518
1519 //--------------------------------------------------------------
sewardj45f4e7c2005-09-27 19:20:21 +00001520 // Initialise translation table and translation cache
1521 // p: aspacem [??]
1522 // p: tl_pre_clo_init [for 'VG_(details).avg_translation_sizeB']
nethercote71980f02004-01-24 18:18:54 +00001523 //--------------------------------------------------------------
sewardj45f4e7c2005-09-27 19:20:21 +00001524 VG_(debugLog)(1, "main", "Initialise TT/TC\n");
1525 VG_(init_tt_tc)();
sewardjb5f6f512005-03-10 23:59:00 +00001526
sewardj45f4e7c2005-09-27 19:20:21 +00001527 //--------------------------------------------------------------
1528 // Initialise the redirect table.
1529 // p: init_tt_tc [so it can call VG_(search_transtab) safely]
1530 // p: aspacem [so can change ownership of sysinfo pages]
1531 //--------------------------------------------------------------
1532 VG_(debugLog)(1, "main", "Initialise redirects\n");
sewardj0ec07f32006-01-12 12:32:32 +00001533 VG_(redir_initialise)();
nethercote71980f02004-01-24 18:18:54 +00001534
1535 //--------------------------------------------------------------
1536 // Allow GDB attach
1537 // p: process_cmd_line_options() [for VG_(clo_wait_for_gdb)]
1538 //--------------------------------------------------------------
1539 /* Hook to delay things long enough so we can get the pid and
1540 attach GDB in another shell. */
1541 if (VG_(clo_wait_for_gdb)) {
sewardj8211a572005-06-23 21:37:47 +00001542 Long q, iters;
sewardj1fbc1a52005-04-25 02:05:54 +00001543 VG_(debugLog)(1, "main", "Wait for GDB\n");
sewardj93ab8572005-02-06 14:10:40 +00001544 VG_(printf)("pid=%d, entering delay loop\n", VG_(getpid)());
sewardj8211a572005-06-23 21:37:47 +00001545
1546# if defined(VGP_x86_linux)
1547 iters = 5;
sewardj2c48c7b2005-11-29 13:05:56 +00001548# elif defined(VGP_amd64_linux) || defined(VGP_ppc64_linux)
sewardj8211a572005-06-23 21:37:47 +00001549 iters = 10;
1550# elif defined(VGP_ppc32_linux)
sewardjd714d2e2005-07-08 18:24:04 +00001551 iters = 5;
sewardj17c11042006-10-15 01:26:40 +00001552# elif defined(VGP_ppc32_aix5) || defined(VGP_ppc64_aix5)
1553 iters = 4;
sewardj8211a572005-06-23 21:37:47 +00001554# else
sewardj17c11042006-10-15 01:26:40 +00001555# error "Unknown plat"
sewardj8211a572005-06-23 21:37:47 +00001556# endif
1557
1558 iters *= 1000*1000*1000;
1559 for (q = 0; q < iters; q++)
1560 ;
nethercote71980f02004-01-24 18:18:54 +00001561 }
1562
sewardjb5d320c2005-03-13 18:57:15 +00001563 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00001564 // Search for file descriptors that are inherited from our parent
1565 // p: process_cmd_line_options [for VG_(clo_track_fds)]
1566 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00001567 if (VG_(clo_track_fds)) {
1568 VG_(debugLog)(1, "main", "Init preopened fds\n");
nethercote71980f02004-01-24 18:18:54 +00001569 VG_(init_preopened_fds)();
sewardj1fbc1a52005-04-25 02:05:54 +00001570 }
nethercote71980f02004-01-24 18:18:54 +00001571
1572 //--------------------------------------------------------------
sewardj45f4e7c2005-09-27 19:20:21 +00001573 // Load debug info for the existing segments.
1574 // p: setup_code_redirect_table [so that redirs can be recorded]
1575 // p: mallocfree
1576 // p: probably: setup fds and process CLOs, so that logging works
1577 //--------------------------------------------------------------
1578 VG_(debugLog)(1, "main", "Load initial debug info\n");
sewardj17c11042006-10-15 01:26:40 +00001579# if defined(VGO_linux)
sewardj45f4e7c2005-09-27 19:20:21 +00001580 { Addr* seg_starts;
1581 Int n_seg_starts;
1582
1583 seg_starts = get_seg_starts( &n_seg_starts );
sewardj17c11042006-10-15 01:26:40 +00001584 vg_assert(seg_starts && n_seg_starts >= 0);
sewardj45f4e7c2005-09-27 19:20:21 +00001585
sewardjf72cced2005-11-08 00:45:47 +00001586 /* show them all to the debug info reader. allow_SkFileV has to
1587 be True here so that we read info from the valgrind executable
1588 itself. */
sewardj45f4e7c2005-09-27 19:20:21 +00001589 for (i = 0; i < n_seg_starts; i++)
sewardjf72cced2005-11-08 00:45:47 +00001590 VG_(di_notify_mmap)( seg_starts[i], True/*allow_SkFileV*/ );
sewardj45f4e7c2005-09-27 19:20:21 +00001591
1592 VG_(free)( seg_starts );
1593 }
sewardj17c11042006-10-15 01:26:40 +00001594# elif defined(VGO_aix5)
1595 { AixCodeSegChange* changes;
1596 Int changes_size, changes_used;
1597
1598 /* Find out how many AixCodeSegChange records we will need,
1599 and acquire them. */
1600 changes_size = VG_(am_aix5_reread_procmap_howmany_directives)();
1601 changes = VG_(malloc)(changes_size * sizeof(AixCodeSegChange));
1602 vg_assert(changes);
1603
1604 /* Now re-read /proc/<pid>/map and acquire a change set */
1605 VG_(am_aix5_reread_procmap)( changes, &changes_used );
1606 vg_assert(changes_used >= 0 && changes_used <= changes_size);
1607
1608 /* And notify m_debuginfo of the changes. */
1609 for (i = 0; i < changes_used; i++)
1610 VG_(di_aix5_notify_segchange)(
1611 changes[i].code_start,
1612 changes[i].code_len,
1613 changes[i].data_start,
1614 changes[i].data_len,
1615 changes[i].file_name,
1616 changes[i].mem_name,
1617 changes[i].is_mainexe,
1618 changes[i].acquire
1619 );
1620
1621 VG_(free)(changes);
1622 }
1623# else
1624# error Unknown OS
1625# endif
sewardj45f4e7c2005-09-27 19:20:21 +00001626
1627 //--------------------------------------------------------------
1628 // Tell aspacem of ownership change of the asm helpers, so that
1629 // m_translate allows them to be translated. However, only do this
1630 // after the initial debug info read, since making a hole in the
1631 // address range for the stage2 binary confuses the debug info reader.
1632 // p: aspacem
1633 //--------------------------------------------------------------
1634 { Bool change_ownership_v_c_OK;
sewardj1a85f4f2006-01-12 21:15:35 +00001635 Addr co_start = VG_PGROUNDDN( (Addr)&VG_(trampoline_stuff_start) );
1636 Addr co_endPlus = VG_PGROUNDUP( (Addr)&VG_(trampoline_stuff_end) );
sewardj45f4e7c2005-09-27 19:20:21 +00001637 VG_(debugLog)(1,"redir",
1638 "transfer ownership V -> C of 0x%llx .. 0x%llx\n",
1639 (ULong)co_start, (ULong)co_endPlus-1 );
1640
1641 change_ownership_v_c_OK
1642 = VG_(am_change_ownership_v_to_c)( co_start, co_endPlus - co_start );
1643 vg_assert(change_ownership_v_c_OK);
1644 }
1645
1646 //--------------------------------------------------------------
1647 // Tell the tool about the initial client memory permissions
1648 // p: aspacem
1649 // p: mallocfree
1650 // p: setup_client_stack
1651 // p: setup_client_dataseg
1652 //--------------------------------------------------------------
1653 VG_(debugLog)(1, "main", "Tell tool about initial permissions\n");
1654 { Addr* seg_starts;
1655 Int n_seg_starts;
sewardj45f4e7c2005-09-27 19:20:21 +00001656
1657 seg_starts = get_seg_starts( &n_seg_starts );
sewardj17c11042006-10-15 01:26:40 +00001658 vg_assert(seg_starts && n_seg_starts >= 0);
sewardj45f4e7c2005-09-27 19:20:21 +00001659
1660 /* show interesting ones to the tool */
1661 for (i = 0; i < n_seg_starts; i++) {
sewardj12ab7652006-10-17 02:10:42 +00001662 NSegment const* seg
sewardj17c11042006-10-15 01:26:40 +00001663 = VG_(am_find_nsegment)( seg_starts[i] );
sewardj45f4e7c2005-09-27 19:20:21 +00001664 vg_assert(seg);
1665 if (seg->kind == SkFileC || seg->kind == SkAnonC) {
1666 VG_(debugLog)(2, "main",
1667 "tell tool about %010lx-%010lx %c%c%c\n",
1668 seg->start, seg->end,
1669 seg->hasR ? 'r' : '-',
1670 seg->hasW ? 'w' : '-',
1671 seg->hasX ? 'x' : '-' );
1672 VG_TRACK( new_mem_startup, seg->start, seg->end+1-seg->start,
1673 seg->hasR, seg->hasW, seg->hasX );
1674 }
1675 }
1676
1677 VG_(free)( seg_starts );
1678
1679 /* Also do the initial stack permissions. */
sewardj12ab7652006-10-17 02:10:42 +00001680 { NSegment const* seg
sewardj17c11042006-10-15 01:26:40 +00001681 = VG_(am_find_nsegment)( ciii.initial_client_SP );
1682 vg_assert(seg);
1683 vg_assert(seg->kind == SkAnonC);
1684 vg_assert(ciii.initial_client_SP >= seg->start);
1685 vg_assert(ciii.initial_client_SP <= seg->end);
1686# if defined(VGO_aix5)
1687 VG_(clstk_base) = seg->start;
1688 VG_(clstk_end) = seg->end;
1689# endif
sewardj45f4e7c2005-09-27 19:20:21 +00001690
sewardj17c11042006-10-15 01:26:40 +00001691 /* Stuff below the initial SP is unaddressable. Take into
1692 account any ABI-mandated space below the stack pointer that
1693 is required (VG_STACK_REDZONE_SZB). setup_client_stack()
1694 will have allocated an extra page if a red zone is required,
1695 to be on the safe side. */
1696 vg_assert(ciii.initial_client_SP - VG_STACK_REDZONE_SZB >= seg->start);
1697 VG_TRACK( die_mem_stack,
1698 seg->start,
1699 ciii.initial_client_SP - VG_STACK_REDZONE_SZB
1700 - seg->start );
1701 VG_(debugLog)(2, "main", "mark stack inaccessible %010lx-%010lx\n",
1702 seg->start,
1703 ciii.initial_client_SP-1 - VG_STACK_REDZONE_SZB);
1704 }
sewardj45f4e7c2005-09-27 19:20:21 +00001705
1706 /* Also the assembly helpers. */
1707 VG_TRACK( new_mem_startup,
1708 (Addr)&VG_(trampoline_stuff_start),
sewardjc6527d62006-02-13 17:54:31 +00001709 (Addr)&VG_(trampoline_stuff_end)
1710 - (Addr)&VG_(trampoline_stuff_start),
sewardj45f4e7c2005-09-27 19:20:21 +00001711 False, /* readable? */
1712 False, /* writable? */
1713 True /* executable? */ );
1714 }
1715
1716 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00001717 // Initialise the scheduler
nethercote71980f02004-01-24 18:18:54 +00001718 // p: setup_file_descriptors() [else VG_(safe_fd)() breaks]
sewardj45f4e7c2005-09-27 19:20:21 +00001719 // p: setup_client_stack
nethercote71980f02004-01-24 18:18:54 +00001720 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00001721 VG_(debugLog)(1, "main", "Initialise scheduler\n");
sewardj12ab7652006-10-17 02:10:42 +00001722 { NSegment const* seg
sewardj17c11042006-10-15 01:26:40 +00001723 = VG_(am_find_nsegment)( ciii.initial_client_SP );
sewardj45f4e7c2005-09-27 19:20:21 +00001724 vg_assert(seg);
1725 vg_assert(seg->kind == SkAnonC);
sewardj17c11042006-10-15 01:26:40 +00001726 vg_assert(ciii.initial_client_SP >= seg->start);
1727 vg_assert(ciii.initial_client_SP <= seg->end);
sewardj45f4e7c2005-09-27 19:20:21 +00001728 VG_(scheduler_init)( seg->end, clstack_max_size );
1729 }
nethercote71980f02004-01-24 18:18:54 +00001730
1731 //--------------------------------------------------------------
sewardj17c11042006-10-15 01:26:40 +00001732 // Set up state for the root thread
sewardjb5f6f512005-03-10 23:59:00 +00001733 // p: ?
sewardj17c11042006-10-15 01:26:40 +00001734 // setup_scheduler() [for sched-specific thread 1 stuff]
1735 // VG_(setup_client_initial_image)
1736 // [for 'ciii' initial layout info]
sewardj2a99cf62004-11-24 10:44:19 +00001737 //--------------------------------------------------------------
sewardj17c11042006-10-15 01:26:40 +00001738 VG_(debugLog)(1, "main", "Finalise thread 1's state\n");
1739 VG_(finalise_thread1state)( &VG_(threads)[1].arch, ciii );
njnea4b28c2004-11-30 16:04:58 +00001740
sewardj2a99cf62004-11-24 10:44:19 +00001741 //--------------------------------------------------------------
sewardj39b88fb2005-03-12 15:16:07 +00001742 // Initialise the pthread model
1743 // p: ?
nethercote71980f02004-01-24 18:18:54 +00001744 //--------------------------------------------------------------
sewardjb5f6f512005-03-10 23:59:00 +00001745 //if (VG_(clo_model_pthreads))
1746 // VG_(pthread_init)();
nethercote71980f02004-01-24 18:18:54 +00001747
1748 //--------------------------------------------------------------
1749 // Initialise the signal handling subsystem
sewardjb5f6f512005-03-10 23:59:00 +00001750 // p: n/a
nethercote71980f02004-01-24 18:18:54 +00001751 //--------------------------------------------------------------
1752 // Nb: temporarily parks the saved blocking-mask in saved_sigmask.
sewardj1fbc1a52005-04-25 02:05:54 +00001753 VG_(debugLog)(1, "main", "Initialise signal management\n");
nethercote71980f02004-01-24 18:18:54 +00001754 VG_(sigstartup_actions)();
1755
1756 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00001757 // Read suppression file
1758 // p: process_cmd_line_options() [for VG_(clo_suppressions)]
1759 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00001760 if (VG_(needs).core_errors || VG_(needs).tool_errors) {
1761 VG_(debugLog)(1, "main", "Load suppressions\n");
nethercote71980f02004-01-24 18:18:54 +00001762 VG_(load_suppressions)();
sewardj1fbc1a52005-04-25 02:05:54 +00001763 }
nethercote71980f02004-01-24 18:18:54 +00001764
1765 //--------------------------------------------------------------
rjwalsh0140af52005-06-04 20:42:33 +00001766 // register client stack
1767 //--------------------------------------------------------------
njn945ed2e2005-06-24 03:28:30 +00001768 VG_(clstk_id) = VG_(register_stack)(VG_(clstk_base), VG_(clstk_end));
rjwalsh0140af52005-06-04 20:42:33 +00001769
1770 //--------------------------------------------------------------
sewardj45f4e7c2005-09-27 19:20:21 +00001771 // Show the address space state so far
1772 //--------------------------------------------------------------
1773 VG_(debugLog)(1, "main", "\n");
1774 VG_(debugLog)(1, "main", "\n");
1775 VG_(am_show_nsegments)(1,"Memory layout at client startup");
1776 VG_(debugLog)(1, "main", "\n");
1777 VG_(debugLog)(1, "main", "\n");
1778
1779 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00001780 // Run!
1781 //--------------------------------------------------------------
sewardj71bc3cb2005-05-19 00:25:45 +00001782 if (VG_(clo_xml)) {
sewardj68cde6f2005-07-19 12:17:51 +00001783 HChar buf[50];
sewardj592ae092005-11-08 19:01:44 +00001784 VG_(elapsed_wallclock_time)(buf);
sewardj753673f2005-08-09 22:03:08 +00001785 VG_(message)(Vg_UserMsg, "<status>\n"
1786 " <state>RUNNING</state>\n"
1787 " <time>%t</time>\n"
1788 "</status>",
1789 buf);
sewardj71bc3cb2005-05-19 00:25:45 +00001790 VG_(message)(Vg_UserMsg, "");
1791 }
1792
sewardj1fbc1a52005-04-25 02:05:54 +00001793 VG_(debugLog)(1, "main", "Running thread 1\n");
sewardj1ae3f3a2005-09-28 10:47:38 +00001794
sewardj1d887112005-05-30 21:44:08 +00001795 /* As a result of the following call, the last thread standing
sewardj1ae3f3a2005-09-28 10:47:38 +00001796 eventually winds up running shutdown_actions_NORETURN
1797 just below. Unfortunately, simply exporting said function
1798 causes m_main to be part of a module cycle, which is pretty
1799 nonsensical. So instead of doing that, the address of said
1800 function is stored in a global variable 'owned' by m_syswrap,
1801 and it uses that function pointer to get back here when it needs
1802 to. */
1803
1804 /* Set continuation address. */
1805 VG_(address_of_m_main_shutdown_actions_NORETURN)
1806 = & shutdown_actions_NORETURN;
1807
1808 /* Run the first thread, eventually ending up at the continuation
1809 address. */
njnaf839f52005-06-23 03:27:57 +00001810 VG_(main_thread_wrapper_NORETURN)(1);
nethercote71980f02004-01-24 18:18:54 +00001811
sewardj1d887112005-05-30 21:44:08 +00001812 /*NOTREACHED*/
1813 vg_assert(0);
sewardjb5f6f512005-03-10 23:59:00 +00001814}
1815
sewardj17c11042006-10-15 01:26:40 +00001816/* Do everything which needs doing when the last thread exits or when
1817 a thread exits requesting a complete process exit (exit on AIX).
1818
1819 We enter here holding The Lock. For the case VgSrc_ExitProcess we
1820 must never release it, because to do so would allow other threads
1821 to continue after the system is ostensibly shut down. So we must
1822 go to our grave, so to speak, holding the lock.
1823
1824 In fact, there is never any point in releasing the lock at this
1825 point - we have it, we're shutting down the entire system, and
1826 for the case VgSrc_ExitProcess doing so positively causes trouble.
1827 So don't.
1828
1829 The final_tidyup call makes a bit of a nonsense of the ExitProcess
1830 case, since it will run the libc_freeres function, thus allowing
1831 other lurking threads to run again. Hmm. */
sewardjb5f6f512005-03-10 23:59:00 +00001832
sewardj1ae3f3a2005-09-28 10:47:38 +00001833static
1834void shutdown_actions_NORETURN( ThreadId tid,
1835 VgSchedReturnCode tids_schedretcode )
sewardjb5f6f512005-03-10 23:59:00 +00001836{
sewardj1d887112005-05-30 21:44:08 +00001837 VG_(debugLog)(1, "main", "entering VG_(shutdown_actions_NORETURN)\n");
sewardj17c11042006-10-15 01:26:40 +00001838 VG_(am_show_nsegments)(1,"Memory layout at client shutdown");
sewardj1d887112005-05-30 21:44:08 +00001839
sewardjb5f6f512005-03-10 23:59:00 +00001840 vg_assert(VG_(is_running_thread)(tid));
1841
sewardj12ab7652006-10-17 02:10:42 +00001842 vg_assert(tids_schedretcode == VgSrc_ExitThread
1843 || tids_schedretcode == VgSrc_ExitProcess
1844 || tids_schedretcode == VgSrc_FatalSig );
sewardjb5f6f512005-03-10 23:59:00 +00001845
sewardj12ab7652006-10-17 02:10:42 +00001846 if (tids_schedretcode == VgSrc_ExitThread) {
sewardjb5f6f512005-03-10 23:59:00 +00001847
sewardj17c11042006-10-15 01:26:40 +00001848 // We are the last surviving thread. Right?
1849 vg_assert( VG_(count_living_threads)() == 1 );
sewardjb5f6f512005-03-10 23:59:00 +00001850
sewardj17c11042006-10-15 01:26:40 +00001851 // Wait for all other threads to exit.
1852 // jrs: Huh? but they surely are already gone
1853 VG_(reap_threads)(tid);
sewardjb5f6f512005-03-10 23:59:00 +00001854
sewardj17c11042006-10-15 01:26:40 +00001855 VG_(clo_model_pthreads) = False;
1856
1857 // Clean the client up before the final report
1858 // this causes the libc_freeres function to run
1859 final_tidyup(tid);
1860
1861 /* be paranoid */
1862 vg_assert(VG_(is_running_thread)(tid));
1863 vg_assert(VG_(count_living_threads)() == 1);
1864
1865 } else {
1866
1867 // We may not be the last surviving thread. However, we
1868 // want to shut down the entire process. We hold the lock
1869 // and we need to keep hold of it all the way out, in order
1870 // that none of the other threads ever run again.
1871 vg_assert( VG_(count_living_threads)() >= 1 );
1872
1873 VG_(clo_model_pthreads) = False;
1874
1875 // Clean the client up before the final report
1876 // this causes the libc_freeres function to run
1877 // perhaps this is unsafe, as per comment above
1878 final_tidyup(tid);
1879
1880 /* be paranoid */
1881 vg_assert(VG_(is_running_thread)(tid));
1882 vg_assert(VG_(count_living_threads)() >= 1);
1883 }
sewardjb5f6f512005-03-10 23:59:00 +00001884
1885 VG_(threads)[tid].status = VgTs_Empty;
nethercote71980f02004-01-24 18:18:54 +00001886 //--------------------------------------------------------------
1887 // Finalisation: cleanup, messages, etc. Order no so important, only
1888 // affects what order the messages come.
1889 //--------------------------------------------------------------
1890 if (VG_(clo_verbosity) > 0)
1891 VG_(message)(Vg_UserMsg, "");
1892
sewardj71bc3cb2005-05-19 00:25:45 +00001893 if (VG_(clo_xml)) {
sewardj68cde6f2005-07-19 12:17:51 +00001894 HChar buf[50];
sewardj9f297ca2005-05-20 02:29:52 +00001895 if (VG_(needs).core_errors || VG_(needs).tool_errors) {
1896 VG_(show_error_counts_as_XML)();
1897 VG_(message)(Vg_UserMsg, "");
1898 }
sewardj592ae092005-11-08 19:01:44 +00001899 VG_(elapsed_wallclock_time)(buf);
sewardj753673f2005-08-09 22:03:08 +00001900 VG_(message)(Vg_UserMsg, "<status>\n"
1901 " <state>FINISHED</state>\n"
1902 " <time>%t</time>\n"
1903 "</status>",
1904 buf);
sewardj71bc3cb2005-05-19 00:25:45 +00001905 VG_(message)(Vg_UserMsg, "");
1906 }
1907
nethercote71980f02004-01-24 18:18:54 +00001908 /* Print out file descriptor summary and stats. */
1909 if (VG_(clo_track_fds))
nethercote3a42fb82004-08-03 18:08:50 +00001910 VG_(show_open_fds)();
nethercote71980f02004-01-24 18:18:54 +00001911
njn95ec8702004-11-22 16:46:13 +00001912 if (VG_(needs).core_errors || VG_(needs).tool_errors)
nethercote71980f02004-01-24 18:18:54 +00001913 VG_(show_all_errors)();
1914
njn51d827b2005-05-09 01:02:08 +00001915 VG_TDICT_CALL(tool_fini, 0/*exitcode*/);
nethercote71980f02004-01-24 18:18:54 +00001916
sewardj71bc3cb2005-05-19 00:25:45 +00001917 if (VG_(clo_xml)) {
1918 VG_(message)(Vg_UserMsg, "");
1919 VG_(message)(Vg_UserMsg, "</valgrindoutput>");
1920 VG_(message)(Vg_UserMsg, "");
1921 }
1922
nethercote885dd912004-08-03 23:14:00 +00001923 VG_(sanity_check_general)( True /*include expensive checks*/ );
nethercote71980f02004-01-24 18:18:54 +00001924
1925 if (VG_(clo_verbosity) > 1)
nethercote3a42fb82004-08-03 18:08:50 +00001926 print_all_stats();
nethercote71980f02004-01-24 18:18:54 +00001927
njn2025cf92005-06-26 20:44:48 +00001928 if (VG_(clo_profile_flags) > 0) {
1929 #define N_MAX 100
1930 BBProfEntry tops[N_MAX];
1931 ULong score_total = VG_(get_BB_profile) (tops, N_MAX);
1932 show_BB_profile(tops, N_MAX, score_total);
1933 }
sewardjfa8ec112005-01-19 11:55:34 +00001934
sewardj8b635a42004-11-22 19:01:47 +00001935 /* Print Vex storage stats */
sewardjbf426512005-01-17 18:35:30 +00001936 if (0)
1937 LibVEX_ShowAllocStats();
sewardj1d887112005-05-30 21:44:08 +00001938
njn8aa35852005-06-10 22:59:56 +00001939 /* Ok, finally exit in the os-specific way, according to the scheduler's
1940 return code. In short, if the (last) thread exited by calling
1941 sys_exit, do likewise; if the (last) thread stopped due to a fatal
1942 signal, terminate the entire system with that same fatal signal. */
1943 VG_(debugLog)(1, "core_os",
njn7b85dd52005-06-12 17:26:29 +00001944 "VG_(terminate_NORETURN)(tid=%lld)\n", (ULong)tid);
njn8aa35852005-06-10 22:59:56 +00001945
njn8aa35852005-06-10 22:59:56 +00001946 switch (tids_schedretcode) {
sewardj12ab7652006-10-17 02:10:42 +00001947 case VgSrc_ExitThread: /* the normal way out (Linux) */
1948 case VgSrc_ExitProcess: /* the normal way out (AIX) */
sewardjb9779082006-05-12 23:50:15 +00001949 /* Change the application return code to user's return code,
1950 if an error was found */
1951 if (VG_(clo_error_exitcode) > 0
1952 && VG_(get_n_errs_found)() > 0) {
1953 VG_(exit)( VG_(clo_error_exitcode) );
1954 } else {
1955 /* otherwise, return the client's exit code, in the normal
1956 way. */
1957 VG_(exit)( VG_(threads)[tid].os_state.exitcode );
1958 }
njn8aa35852005-06-10 22:59:56 +00001959 /* NOT ALIVE HERE! */
sewardj17c11042006-10-15 01:26:40 +00001960 VG_(core_panic)("entered the afterlife in main() -- ExitT/P");
njn8aa35852005-06-10 22:59:56 +00001961 break; /* what the hell :) */
1962
1963 case VgSrc_FatalSig:
1964 /* We were killed by a fatal signal, so replicate the effect */
1965 vg_assert(VG_(threads)[tid].os_state.fatalsig != 0);
1966 VG_(kill_self)(VG_(threads)[tid].os_state.fatalsig);
1967 VG_(core_panic)("main(): signal was supposed to be fatal");
1968 break;
1969
1970 default:
1971 VG_(core_panic)("main(): unexpected scheduler return code");
1972 }
njne96be672005-05-08 19:08:54 +00001973}
sewardj8b635a42004-11-22 19:01:47 +00001974
sewardj1ae3f3a2005-09-28 10:47:38 +00001975/* -------------------- */
1976
1977/* Final clean-up before terminating the process.
1978 Clean up the client by calling __libc_freeres() (if requested)
1979 This is Linux-specific?
1980*/
1981static void final_tidyup(ThreadId tid)
1982{
sewardjcf951812006-01-17 02:22:21 +00001983# if defined(VGP_ppc64_linux)
1984 Addr r2;
1985# endif
sewardj0ec07f32006-01-12 12:32:32 +00001986 Addr __libc_freeres_wrapper = VG_(client___libc_freeres_wrapper);
sewardj1ae3f3a2005-09-28 10:47:38 +00001987
1988 vg_assert(VG_(is_running_thread)(tid));
1989
1990 if ( !VG_(needs).libc_freeres ||
1991 !VG_(clo_run_libc_freeres) ||
sewardj0ec07f32006-01-12 12:32:32 +00001992 0 == __libc_freeres_wrapper )
sewardj1ae3f3a2005-09-28 10:47:38 +00001993 return; /* can't/won't do it */
sewardj17c11042006-10-15 01:26:40 +00001994# if defined(VGO_aix5)
1995 return; /* inapplicable on non-Linux platforms */
1996# endif
sewardj1ae3f3a2005-09-28 10:47:38 +00001997
sewardjcf951812006-01-17 02:22:21 +00001998# if defined(VGP_ppc64_linux)
1999 r2 = VG_(get_tocptr)( __libc_freeres_wrapper );
2000 if (r2 == 0) {
2001 VG_(message)(Vg_UserMsg,
2002 "Caught __NR_exit, but can't run __libc_freeres()");
2003 VG_(message)(Vg_UserMsg,
2004 " since cannot establish TOC pointer for it.");
2005 return;
2006 }
2007# endif
2008
sewardj1ae3f3a2005-09-28 10:47:38 +00002009 if (VG_(clo_verbosity) > 2 ||
2010 VG_(clo_trace_syscalls) ||
2011 VG_(clo_trace_sched))
2012 VG_(message)(Vg_DebugMsg,
2013 "Caught __NR_exit; running __libc_freeres()");
2014
sewardj0ec07f32006-01-12 12:32:32 +00002015 /* set thread context to point to libc_freeres_wrapper */
sewardj1a85f4f2006-01-12 21:15:35 +00002016 /* ppc64-linux note: __libc_freeres_wrapper gives us the real
2017 function entry point, not a fn descriptor, so can use it
2018 directly. However, we need to set R2 (the toc pointer)
2019 appropriately. */
sewardj1ae3f3a2005-09-28 10:47:38 +00002020 VG_(set_IP)(tid, __libc_freeres_wrapper);
sewardjcf951812006-01-17 02:22:21 +00002021# if defined(VGP_ppc64_linux)
2022 VG_(threads)[tid].arch.vex.guest_GPR2 = r2;
2023# endif
sewardj1ae3f3a2005-09-28 10:47:38 +00002024
2025 /* Block all blockable signals by copying the real block state into
2026 the thread's block state*/
2027 VG_(sigprocmask)(VKI_SIG_BLOCK, NULL, &VG_(threads)[tid].sig_mask);
2028 VG_(threads)[tid].tmp_sig_mask = VG_(threads)[tid].sig_mask;
2029
2030 /* and restore handlers to default */
2031 VG_(set_default_handler)(VKI_SIGSEGV);
2032 VG_(set_default_handler)(VKI_SIGBUS);
2033 VG_(set_default_handler)(VKI_SIGILL);
2034 VG_(set_default_handler)(VKI_SIGFPE);
2035
2036 // We were exiting, so assert that...
2037 vg_assert(VG_(is_exiting)(tid));
2038 // ...but now we're not again
2039 VG_(threads)[tid].exitreason = VgSrc_None;
2040
2041 // run until client thread exits - ideally with LIBC_FREERES_DONE,
2042 // but exit/exitgroup/signal will do
2043 VG_(scheduler)(tid);
2044
2045 vg_assert(VG_(is_exiting)(tid));
2046}
2047
sewardj45f4e7c2005-09-27 19:20:21 +00002048
2049/*====================================================================*/
sewardj17c11042006-10-15 01:26:40 +00002050/*=== Getting to main() alive: LINUX (for AIX5 see below) ===*/
sewardj45f4e7c2005-09-27 19:20:21 +00002051/*====================================================================*/
2052
sewardj17c11042006-10-15 01:26:40 +00002053#if defined(VGO_linux)
2054
sewardj45f4e7c2005-09-27 19:20:21 +00002055/* If linking of the final executables is done with glibc present,
2056 then Valgrind starts at main() above as usual, and all of the
2057 following code is irrelevant.
2058
2059 However, this is not the intended mode of use. The plan is to
2060 avoid linking against glibc, by giving gcc the flags
2061 -nodefaultlibs -lgcc -nostartfiles at startup.
2062
2063 From this derive two requirements:
2064
2065 1. gcc may emit calls to memcpy and memset to deal with structure
2066 assignments etc. Since we have chosen to ignore all the
2067 "normal" supporting libraries, we have to provide our own
2068 implementations of them. No problem.
2069
2070 2. We have to provide a symbol "_start", to which the kernel
2071 hands control at startup. Hence the code below.
2072*/
2073
2074/* ---------------- Requirement 1 ---------------- */
2075
sewardj17c11042006-10-15 01:26:40 +00002076void* memcpy(void *dest, const void *src, SizeT n);
2077void* memcpy(void *dest, const void *src, SizeT n) {
sewardj45f4e7c2005-09-27 19:20:21 +00002078 return VG_(memcpy)(dest,src,n);
2079}
sewardj17c11042006-10-15 01:26:40 +00002080void* memset(void *s, int c, SizeT n);
2081void* memset(void *s, int c, SizeT n) {
sewardj45f4e7c2005-09-27 19:20:21 +00002082 return VG_(memset)(s,c,n);
2083}
2084
2085/* ---------------- Requirement 2 ---------------- */
2086
2087/* Glibc's sysdeps/i386/elf/start.S has the following gem of a
2088 comment, which explains how the stack looks right at process start
2089 (when _start is jumped to). Hence _start passes %esp to
sewardj17c11042006-10-15 01:26:40 +00002090 _start_in_C_linux, which extracts argc/argv/envp and starts up
sewardj45f4e7c2005-09-27 19:20:21 +00002091 correctly. */
2092
2093/* This is the canonical entry point, usually the first thing in the text
2094 segment. The SVR4/i386 ABI (pages 3-31, 3-32) says that when the entry
2095 point runs, most registers' values are unspecified, except for:
2096
2097 %edx Contains a function pointer to be registered with `atexit'.
2098 This is how the dynamic linker arranges to have DT_FINI
2099 functions called for shared libraries that have been loaded
2100 before this code runs.
2101
2102 %esp The stack contains the arguments and environment:
2103 0(%esp) argc
2104 4(%esp) argv[0]
2105 ...
2106 (4*argc)(%esp) NULL
2107 (4*(argc+1))(%esp) envp[0]
2108 ...
2109 NULL
2110*/
2111
2112/* The kernel hands control to _start, which extracts the initial
sewardj17c11042006-10-15 01:26:40 +00002113 stack pointer and calls onwards to _start_in_C_linux. This also switches
sewardja48a4932005-09-29 11:09:56 +00002114 the new stack. */
sewardj45f4e7c2005-09-27 19:20:21 +00002115#if defined(VGP_x86_linux)
2116asm("\n"
sewardjd9fc3822005-11-18 23:50:43 +00002117 ".text\n"
sewardj45f4e7c2005-09-27 19:20:21 +00002118 "\t.globl _start\n"
2119 "\t.type _start,@function\n"
2120 "_start:\n"
2121 /* set up the new stack in %eax */
sewardjfdf91b42005-09-28 00:53:09 +00002122 "\tmovl $vgPlain_interim_stack, %eax\n"
sewardj45f4e7c2005-09-27 19:20:21 +00002123 "\taddl $"VG_STRINGIFY(VG_STACK_GUARD_SZB)", %eax\n"
2124 "\taddl $"VG_STRINGIFY(VG_STACK_ACTIVE_SZB)", %eax\n"
2125 "\tsubl $16, %eax\n"
2126 "\tandl $~15, %eax\n"
2127 /* install it, and collect the original one */
2128 "\txchgl %eax, %esp\n"
sewardj17c11042006-10-15 01:26:40 +00002129 /* call _start_in_C_linux, passing it the startup %esp */
sewardj45f4e7c2005-09-27 19:20:21 +00002130 "\tpushl %eax\n"
sewardj17c11042006-10-15 01:26:40 +00002131 "\tcall _start_in_C_linux\n"
sewardj45f4e7c2005-09-27 19:20:21 +00002132 "\thlt\n"
sewardj2fedc642005-11-19 02:02:57 +00002133 ".previous\n"
sewardj45f4e7c2005-09-27 19:20:21 +00002134);
2135#elif defined(VGP_amd64_linux)
2136asm("\n"
sewardjd9fc3822005-11-18 23:50:43 +00002137 ".text\n"
sewardj45f4e7c2005-09-27 19:20:21 +00002138 "\t.globl _start\n"
2139 "\t.type _start,@function\n"
2140 "_start:\n"
2141 /* set up the new stack in %rdi */
sewardjfdf91b42005-09-28 00:53:09 +00002142 "\tmovq $vgPlain_interim_stack, %rdi\n"
sewardj45f4e7c2005-09-27 19:20:21 +00002143 "\taddq $"VG_STRINGIFY(VG_STACK_GUARD_SZB)", %rdi\n"
2144 "\taddq $"VG_STRINGIFY(VG_STACK_ACTIVE_SZB)", %rdi\n"
2145 "\tandq $~15, %rdi\n"
2146 /* install it, and collect the original one */
2147 "\txchgq %rdi, %rsp\n"
sewardj17c11042006-10-15 01:26:40 +00002148 /* call _start_in_C_linux, passing it the startup %rsp */
2149 "\tcall _start_in_C_linux\n"
sewardj45f4e7c2005-09-27 19:20:21 +00002150 "\thlt\n"
sewardj2fedc642005-11-19 02:02:57 +00002151 ".previous\n"
sewardj45f4e7c2005-09-27 19:20:21 +00002152);
sewardja48a4932005-09-29 11:09:56 +00002153#elif defined(VGP_ppc32_linux)
2154asm("\n"
sewardjd9fc3822005-11-18 23:50:43 +00002155 ".text\n"
sewardja48a4932005-09-29 11:09:56 +00002156 "\t.globl _start\n"
2157 "\t.type _start,@function\n"
2158 "_start:\n"
2159 /* set up the new stack in r16 */
2160 "\tlis 16,vgPlain_interim_stack@ha\n"
2161 "\tla 16,vgPlain_interim_stack@l(16)\n"
2162 "\tlis 17,("VG_STRINGIFY(VG_STACK_GUARD_SZB)" >> 16)\n"
2163 "\tori 17,17,("VG_STRINGIFY(VG_STACK_GUARD_SZB)" & 0xFFFF)\n"
2164 "\tlis 18,("VG_STRINGIFY(VG_STACK_ACTIVE_SZB)" >> 16)\n"
2165 "\tori 18,18,("VG_STRINGIFY(VG_STACK_ACTIVE_SZB)" & 0xFFFF)\n"
2166 "\tadd 16,17,16\n"
2167 "\tadd 16,18,16\n"
2168 "\trlwinm 16,16,0,0,27\n"
2169 /* now r16 = &vgPlain_interim_stack + VG_STACK_GUARD_SZB +
2170 VG_STACK_ACTIVE_SZB rounded down to the nearest 16-byte
2171 boundary. And r1 is the original SP. Set the SP to r16 and
sewardj17c11042006-10-15 01:26:40 +00002172 call _start_in_C_linux, passing it the initial SP. */
sewardja48a4932005-09-29 11:09:56 +00002173 "\tmr 3,1\n"
2174 "\tmr 1,16\n"
sewardj17c11042006-10-15 01:26:40 +00002175 "\tbl _start_in_C_linux\n"
sewardja48a4932005-09-29 11:09:56 +00002176 "\ttrap\n"
sewardj2fedc642005-11-19 02:02:57 +00002177 ".previous\n"
sewardja48a4932005-09-29 11:09:56 +00002178);
sewardj2c48c7b2005-11-29 13:05:56 +00002179#elif defined(VGP_ppc64_linux)
2180asm("\n"
cerion21082042005-12-06 19:07:08 +00002181 /* PPC64 ELF ABI says '_start' points to a function descriptor.
2182 So we must have one, and that is what goes into the .opd section. */
cerion297c88f2005-12-22 15:53:12 +00002183 "\t.align 2\n"
cerion21082042005-12-06 19:07:08 +00002184 "\t.global _start\n"
2185 "\t.section \".opd\",\"aw\"\n"
2186 "\t.align 3\n"
sewardj2c48c7b2005-11-29 13:05:56 +00002187 "_start:\n"
cerion21082042005-12-06 19:07:08 +00002188 "\t.quad ._start,.TOC.@tocbase,0\n"
2189 "\t.previous\n"
2190 "\t.type ._start,@function\n"
2191 "\t.global ._start\n"
2192 "._start:\n"
sewardj2c48c7b2005-11-29 13:05:56 +00002193 /* set up the new stack in r16 */
2194 "\tlis 16, vgPlain_interim_stack@highest\n"
2195 "\tori 16,16,vgPlain_interim_stack@higher\n"
2196 "\tsldi 16,16,32\n"
2197 "\toris 16,16,vgPlain_interim_stack@h\n"
2198 "\tori 16,16,vgPlain_interim_stack@l\n"
2199 "\txor 17,17,17\n"
2200 "\tlis 17,("VG_STRINGIFY(VG_STACK_GUARD_SZB)" >> 16)\n"
2201 "\tori 17,17,("VG_STRINGIFY(VG_STACK_GUARD_SZB)" & 0xFFFF)\n"
2202 "\txor 18,18,18\n"
2203 "\tlis 18,("VG_STRINGIFY(VG_STACK_ACTIVE_SZB)" >> 16)\n"
2204 "\tori 18,18,("VG_STRINGIFY(VG_STACK_ACTIVE_SZB)" & 0xFFFF)\n"
2205 "\tadd 16,17,16\n"
2206 "\tadd 16,18,16\n"
2207 "\trldicr 16,16,0,59\n"
2208 /* now r16 = &vgPlain_interim_stack + VG_STACK_GUARD_SZB +
2209 VG_STACK_ACTIVE_SZB rounded down to the nearest 16-byte
2210 boundary. And r1 is the original SP. Set the SP to r16 and
sewardj17c11042006-10-15 01:26:40 +00002211 call _start_in_C_linux, passing it the initial SP. */
sewardj2c48c7b2005-11-29 13:05:56 +00002212 "\tmr 3,1\n"
2213 "\tmr 1,16\n"
sewardj17c11042006-10-15 01:26:40 +00002214 "\tbl ._start_in_C_linux\n"
cerion21082042005-12-06 19:07:08 +00002215 "\tnop\n"
sewardj2c48c7b2005-11-29 13:05:56 +00002216 "\ttrap\n"
sewardj2c48c7b2005-11-29 13:05:56 +00002217);
sewardj45f4e7c2005-09-27 19:20:21 +00002218#else
2219#error "_start: needs implementation on this platform"
2220#endif
2221
2222/* Avoid compiler warnings: this fn _is_ used, but labelling it
2223 'static' causes gcc to complain it isn't. */
sewardj17c11042006-10-15 01:26:40 +00002224void _start_in_C_linux ( UWord* pArgc );
2225void _start_in_C_linux ( UWord* pArgc )
sewardj45f4e7c2005-09-27 19:20:21 +00002226{
2227 Int r;
2228 Word argc = pArgc[0];
2229 HChar** argv = (HChar**)&pArgc[1];
2230 HChar** envp = (HChar**)&pArgc[1+argc+1];
sewardjfdf91b42005-09-28 00:53:09 +00002231 sp_at_startup = (Addr)pArgc;
sewardj17c11042006-10-15 01:26:40 +00002232 r = valgrind_main( (Int)argc, argv, envp,
2233 NULL/*aix5-specific stuff*/,
2234 NULL/*aix5-specific stuff*/,
2235 0/*aix5-specific stuff*/ );
2236 /* NOTREACHED */
sewardj45f4e7c2005-09-27 19:20:21 +00002237 VG_(exit)(r);
2238}
2239
sewardj17c11042006-10-15 01:26:40 +00002240#endif /* defined(VGO_linux) */
2241
2242
2243/*====================================================================*/
2244/*=== Getting to main() alive: AIX5 ===*/
2245/*====================================================================*/
2246
2247#if defined(VGP_ppc32_aix5) || defined(VGP_ppc64_aix5)
2248
2249/* This is somewhat simpler than the Linux case. _start_valgrind
2250 receives control from the magic piece of code created in this
2251 process' address space by the launcher, via use of ptrace(). At
2252 the point of entry:
2253
2254 - the initial client process image is in memory and ready to roll,
2255 except that we've partially trashed its integer register state
2256 in order to get this far. So ..
2257
2258 - intregs37 holds the client's initial integer register state, so
2259 we can restore it before starting the client on the VCPU.
2260
2261 - we're on the client's stack. This is not good; therefore the
2262 first order of business is to switch to our temporary stack.
2263
2264 - the client's initial argc/v/envp is in r3/r4/r5 (32 bit mode) or
2265 r14/r15/r16 (64 bit mode). They are pulled out of the stashed
2266 integer register state and passed to our main().
2267
2268 The launcher will have played some games with argv. If the launcher
2269 ($prefix/bin/valgrind) was started like this
2270
2271 valgrind [args-for-V] app [args-for-app]
2272
2273 then the launcher will have started the client as
2274
2275 app [args-for-V] app [args-for-app]
2276
2277 m_initimg will have to mess with the client's initial r4/r5
2278 (32-bit) or r15/r16 (64-bit) so that it believes it was execd as
2279 "app [args-for-app]". Well, that's no big deal.
2280*/
2281
2282#include "launcher-aix5-bootblock.h"
2283
2284void _start_in_C_aix5 ( AIX5Bootblock* bootblock );
2285void _start_in_C_aix5 ( AIX5Bootblock* bootblock )
2286{
2287 Int r;
2288 ULong* intregs37;
2289 UWord argc, argv, envp;
2290 __NR_getpid = bootblock->__NR_getpid;
2291 __NR_write = bootblock->__NR_write;
2292 __NR_exit = bootblock->__NR_exit;
2293 __NR_open = bootblock->__NR_open;
2294 __NR_read = bootblock->__NR_read;
2295 __NR_close = bootblock->__NR_close;
2296 intregs37 = &bootblock->iregs_pc_cr_lr_ctr_xer[0];
2297# if defined(VGP_ppc32_aix5)
2298 argc = (UWord)intregs37[3]; /* client's r3 == argc */
2299 argv = (UWord)intregs37[4];
2300 envp = (UWord)intregs37[5];
2301# else /* defined(VGP_ppc64_aix5) */
2302 argc = (UWord)intregs37[14]; /* client's r14 == argc */
2303 argv = (UWord)intregs37[15];
2304 envp = (UWord)intregs37[16];
2305# endif
2306 sp_at_startup = (Addr)0xDeadBeefDeadBeefULL; /* Not important on AIX. */
2307 r = valgrind_main( (Int)argc, (HChar**)argv, (HChar**)envp,
2308 intregs37,
2309 (void*)bootblock,
2310 bootblock->adler32 );
2311 /* NOTREACHED */
2312 VG_(exit)(r);
2313}
2314
2315/* THE ENTRY POINT */
2316void _start_valgrind ( AIX5Bootblock* bootblock );
2317void _start_valgrind ( AIX5Bootblock* bootblock )
2318{
2319 /* Switch immediately to our temporary stack, and continue. This
2320 is pretty dodgy in that it assumes that gcc does not place on
2321 the stack, anything needed to form the _start_in_C_aix5 call,
2322 since it will be on the old stack. */
2323 register UWord new_r1;
2324 new_r1 = (UWord)&VG_(interim_stack);
2325 new_r1 += VG_STACK_GUARD_SZB; /* step over lower guard page */
2326 new_r1 += VG_STACK_ACTIVE_SZB; /* step to top of active area */
2327 new_r1 -= 512; /* paranoia */
2328 __asm__ __volatile__("mr 1,%0" :/*wr*/
2329 :/*rd*/ "b"(new_r1)
2330 :/*trash*/"r1","memory");
2331 _start_in_C_aix5(bootblock);
2332 /*NOTREACHED*/
2333 VG_(exit)(0);
2334}
2335
2336#endif /* defined(VGP_ppc{32,64}_aix5) */
2337
2338
sewardjde4a1d02002-03-22 01:27:54 +00002339/*--------------------------------------------------------------------*/
njn04e16982005-05-31 00:23:43 +00002340/*--- end ---*/
sewardjde4a1d02002-03-22 01:27:54 +00002341/*--------------------------------------------------------------------*/