blob: 84fb4e39fca949bc8820deaec938e8fdd1cd06db [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
sewardj9ebd6e02007-01-08 06:01:59 +000010 Copyright (C) 2000-2007 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"
sewardj14c7cc52007-02-25 15:08:24 +000035#include "pub_core_xarray.h"
sewardj45f4e7c2005-09-27 19:20:21 +000036#include "pub_core_clientstate.h"
sewardj55f9d1a2005-04-25 11:11:44 +000037#include "pub_core_aspacemgr.h"
sewardj45f4e7c2005-09-27 19:20:21 +000038#include "pub_core_commandline.h"
njn2521d322005-05-08 14:45:13 +000039#include "pub_core_debuglog.h"
40#include "pub_core_errormgr.h"
41#include "pub_core_execontext.h"
sewardj17c11042006-10-15 01:26:40 +000042#include "pub_core_initimg.h"
njn97405b22005-06-02 03:39:33 +000043#include "pub_core_libcbase.h"
njn132bfcc2005-06-04 19:16:06 +000044#include "pub_core_libcassert.h"
njneb8896b2005-06-04 20:03:55 +000045#include "pub_core_libcfile.h"
njn36a20fa2005-06-03 03:08:39 +000046#include "pub_core_libcprint.h"
njnf39e9a32005-06-12 02:43:17 +000047#include "pub_core_libcproc.h"
njnde62cbf2005-06-10 22:08:14 +000048#include "pub_core_libcsignal.h"
sewardj45f4e7c2005-09-27 19:20:21 +000049#include "pub_core_syscall.h" // VG_(strerror)
njnf536bbb2005-06-13 04:21:38 +000050#include "pub_core_machine.h"
njnaf1d7df2005-06-11 01:31:52 +000051#include "pub_core_mallocfree.h"
njn20242342005-05-16 23:31:24 +000052#include "pub_core_options.h"
sewardjfdf91b42005-09-28 00:53:09 +000053#include "pub_core_debuginfo.h"
njnd1af0032005-05-29 17:01:48 +000054#include "pub_core_redir.h"
njnc7561b92005-06-19 01:24:32 +000055#include "pub_core_scheduler.h"
njn0c246472005-05-31 01:00:08 +000056#include "pub_core_signals.h"
njn2025cf92005-06-26 20:44:48 +000057#include "pub_core_stacks.h" // For VG_(register_stack)
njnc1b01812005-06-17 22:19:06 +000058#include "pub_core_syswrap.h"
njn43b9a8a2005-05-10 04:37:01 +000059#include "pub_core_tooliface.h"
sewardj17c11042006-10-15 01:26:40 +000060#include "pub_core_translate.h" // For VG_(translate)
njna7598f62005-06-18 03:27:58 +000061#include "pub_core_trampoline.h"
njn8bddf582005-05-13 23:40:55 +000062#include "pub_core_transtab.h"
sewardj17c11042006-10-15 01:26:40 +000063
64/* Stuff for reading AIX5 /proc/<pid>/sysent files */
65#if defined(VGO_aix5)
66 /* --- !!! --- EXTERNAL HEADERS start --- !!! --- */
67# include <sys/procfs.h> /* prsysent_t */
68 /* --- !!! --- EXTERNAL HEADERS end --- !!! --- */
69# define VG_AIX5_SYSENT_SIZE 100000
70 static UChar aix5_sysent_buf[VG_AIX5_SYSENT_SIZE];
71#endif
nethercote71980f02004-01-24 18:18:54 +000072
sewardjb5f6f512005-03-10 23:59:00 +000073
nethercote71980f02004-01-24 18:18:54 +000074/*====================================================================*/
75/*=== Counters, for profiling purposes only ===*/
76/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +000077
nethercote3a42fb82004-08-03 18:08:50 +000078static void print_all_stats ( void )
nethercote71980f02004-01-24 18:18:54 +000079{
njn42c83552005-12-05 20:45:59 +000080 VG_(print_translation_stats)();
nethercote92e7b7f2004-08-07 17:52:25 +000081 VG_(print_tt_tc_stats)();
nethercote844e7122004-08-02 15:27:22 +000082 VG_(print_scheduler_stats)();
njn9271cbc2005-03-13 05:38:25 +000083 VG_(print_ExeContext_stats)();
sewardj12ab7652006-10-17 02:10:42 +000084 VG_(print_errormgr_stats)();
njn9271cbc2005-03-13 05:38:25 +000085
nethercote3a42fb82004-08-03 18:08:50 +000086 // Memory stats
nethercote885dd912004-08-03 23:14:00 +000087 if (VG_(clo_verbosity) > 2) {
nethercote3a42fb82004-08-03 18:08:50 +000088 VG_(message)(Vg_DebugMsg, "");
89 VG_(message)(Vg_DebugMsg,
90 "------ Valgrind's internal memory use stats follow ------" );
nethercote885dd912004-08-03 23:14:00 +000091 VG_(sanity_check_malloc_all)();
njn11adeb22005-07-03 20:22:39 +000092 VG_(message)(Vg_DebugMsg, "------" );
nethercote3a42fb82004-08-03 18:08:50 +000093 VG_(print_all_arena_stats)();
nethercote885dd912004-08-03 23:14:00 +000094 VG_(message)(Vg_DebugMsg, "");
nethercote3a42fb82004-08-03 18:08:50 +000095 }
nethercote71980f02004-01-24 18:18:54 +000096}
97
98
99/*====================================================================*/
sewardj71bc3cb2005-05-19 00:25:45 +0000100/*=== Command-line: variables, processing, etc ===*/
101/*====================================================================*/
102
103// See pub_{core,tool}_options.h for explanations of all these.
104
sewardj45f4e7c2005-09-27 19:20:21 +0000105static void usage_NORETURN ( Bool debug_help )
njn7cf0bd32002-06-08 13:36:03 +0000106{
njn25e49d8e72002-09-23 09:36:25 +0000107 Char* usage1 =
njn00cfcfc2005-11-12 18:53:50 +0000108"usage: valgrind [options] prog-and-args\n"
njn25e49d8e72002-09-23 09:36:25 +0000109"\n"
nethercote2b0793f2003-12-02 10:41:18 +0000110" common user options for all Valgrind tools, with defaults in [ ]:\n"
sewardjb5f6f512005-03-10 23:59:00 +0000111" --tool=<name> use the Valgrind tool named <name> [memcheck]\n"
nethercotea76368b2004-06-16 11:56:29 +0000112" -h --help show this message\n"
nethercote6c999f22004-01-31 22:55:15 +0000113" --help-debug show this message, plus debugging options\n"
njn25e49d8e72002-09-23 09:36:25 +0000114" --version show version\n"
njn25e49d8e72002-09-23 09:36:25 +0000115" -q --quiet run silently; only print error msgs\n"
116" -v --verbose be more verbose, incl counts of errors\n"
nethercote77eba602003-11-13 17:35:04 +0000117" --trace-children=no|yes Valgrind-ise child processes? [no]\n"
nethercote0d588502004-06-21 13:27:11 +0000118" --track-fds=no|yes track open file descriptors? [no]\n"
thughes6233a382004-08-21 11:10:44 +0000119" --time-stamp=no|yes add timestamps to log messages? [no]\n"
njnce545552005-07-25 22:36:52 +0000120" --log-fd=<number> log messages to file descriptor [2=stderr]\n"
tombbe14b12005-11-04 16:49:39 +0000121" --log-file=<file> log messages to <file>.<pid>\n"
njnce545552005-07-25 22:36:52 +0000122" --log-file-exactly=<file> log messages to <file>\n"
123" --log-file-qualifier=<VAR> incorporate $VAR in logfile name [none]\n"
124" --log-socket=ipaddr:port log messages to socket ipaddr:port\n"
nethercote2b0793f2003-12-02 10:41:18 +0000125"\n"
126" uncommon user options for all Valgrind tools:\n"
nethercote0d588502004-06-21 13:27:11 +0000127" --run-libc-freeres=no|yes free up glibc memory at exit? [yes]\n"
njn628add62005-11-12 18:21:40 +0000128" --sim-hints=hint1,hint2,... known hints:\n"
sewardj19617ae2005-10-20 01:09:57 +0000129" lax-ioctls, enable-outer [none]\n"
sewardjb1131a82005-03-19 15:12:21 +0000130" --show-emwarns=no|yes show warnings about emulation limits? [no]\n"
sewardj6c3a2192005-07-24 07:00:45 +0000131" --smc-check=none|stack|all checks for self-modifying code: none,\n"
132" only for code found in stacks, or all [stack]\n"
sewardj3c3f0c12005-11-08 15:52:36 +0000133" --kernel-variant=variant1,variant2,... known variants: bproc [none]\n"
134" handle non-standard kernel variants\n"
njn25e49d8e72002-09-23 09:36:25 +0000135"\n"
nethercote2b0793f2003-12-02 10:41:18 +0000136" user options for Valgrind tools that report errors:\n"
njnca54af32006-04-16 10:25:43 +0000137" --xml=yes all output is in XML (some tools only)\n"
njnc8ec9f82005-07-20 03:03:28 +0000138" --xml-user-comment=STR copy STR verbatim to XML output\n"
nethercote2b0793f2003-12-02 10:41:18 +0000139" --demangle=no|yes automatically demangle C++ names? [yes]\n"
njn20b4a152005-10-19 22:39:40 +0000140" --num-callers=<number> show <number> callers in stack traces [12]\n"
nethercote2b0793f2003-12-02 10:41:18 +0000141" --error-limit=no|yes stop showing new errors if too many? [yes]\n"
sewardjb9779082006-05-12 23:50:15 +0000142" --error-exitcode=<number> exit code to return if errors found [0=disable]\n"
nethercote2b0793f2003-12-02 10:41:18 +0000143" --show-below-main=no|yes continue stack traces below main() [no]\n"
144" --suppressions=<filename> suppress errors described in <filename>\n"
sewardjd153fae2005-01-10 17:24:47 +0000145" --gen-suppressions=no|yes|all print suppressions for errors? [no]\n"
nethercote04d0fbc2004-01-26 16:48:06 +0000146" --db-attach=no|yes start debugger when errors detected? [no]\n"
147" --db-command=<command> command to start debugger [gdb -nw %%f %%p]\n"
148" --input-fd=<number> file descriptor for input [0=stdin]\n"
sewardj97724e52005-04-02 23:40:59 +0000149" --max-stackframe=<number> assume stack switch for SP changes larger\n"
150" than <number> bytes [2000000]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +0000151"\n";
njn7cf0bd32002-06-08 13:36:03 +0000152
njn25e49d8e72002-09-23 09:36:25 +0000153 Char* usage2 =
154"\n"
nethercote2b0793f2003-12-02 10:41:18 +0000155" debugging options for all Valgrind tools:\n"
njn25e49d8e72002-09-23 09:36:25 +0000156" --sanity-level=<number> level of sanity checking to do [1]\n"
sewardjfa8ec112005-01-19 11:55:34 +0000157" --trace-flags=<XXXXXXXX> show generated code? (X = 0|1) [00000000]\n"
158" --profile-flags=<XXXXXXXX> ditto, but for profiling (X = 0|1) [00000000]\n"
sewardj33afdb52006-01-17 02:36:40 +0000159" --trace-notbelow=<number> only show BBs above <number> [999999999]\n"
njn25e49d8e72002-09-23 09:36:25 +0000160" --trace-syscalls=no|yes show all system calls? [no]\n"
161" --trace-signals=no|yes show signal handling details? [no]\n"
162" --trace-symtab=no|yes show symbol table details? [no]\n"
sewardjf767d962007-02-12 17:47:14 +0000163" --trace-symtab-patt=<patt> limit debuginfo tracing to obj name <patt>\n"
sewardjce058b02005-05-01 08:55:38 +0000164" --trace-cfi=no|yes show call-frame-info details? [no]\n"
sewardjf767d962007-02-12 17:47:14 +0000165" --debug-dump=syms mimic /usr/bin/readelf --syms\n"
166" --debug-dump=line mimic /usr/bin/readelf --debug-dump=line\n"
167" --debug-dump=frames mimic /usr/bin/readelf --debug-dump=frames\n"
sewardj0ec07f32006-01-12 12:32:32 +0000168" --trace-redir=no|yes show redirection details? [no]\n"
njn25e49d8e72002-09-23 09:36:25 +0000169" --trace-sched=no|yes show thread scheduler details? [no]\n"
jsgf855d93d2003-10-13 22:26:55 +0000170" --wait-for-gdb=yes|no pause on startup to wait for gdb attach\n"
sewardj17c11042006-10-15 01:26:40 +0000171" --sym-offsets=yes|no show syms in form 'name+offset' ? [no]\n"
sewardjb5f6f512005-03-10 23:59:00 +0000172#if 0
173" --model-pthreads=yes|no model the pthreads library [no]\n"
174#endif
175" --command-line-only=no|yes only use command line options [no]\n"
njn613812e2005-03-11 04:57:30 +0000176"\n"
177" --vex-iropt-verbosity 0 .. 9 [0]\n"
178" --vex-iropt-level 0 .. 2 [2]\n"
179" --vex-iropt-precise-memory-exns [no]\n"
sewardj8b635a42004-11-22 19:01:47 +0000180" --vex-iropt-unroll-thresh 0 .. 400 [120]\n"
181" --vex-guest-max-insns 1 .. 100 [50]\n"
182" --vex-guest-chase-thresh 0 .. 99 [10]\n"
183"\n"
sewardjfa8ec112005-01-19 11:55:34 +0000184" --trace-flags and --profile-flags values (omit the middle space):\n"
sewardj2a99cf62004-11-24 10:44:19 +0000185" 1000 0000 show conversion into IR\n"
186" 0100 0000 show after initial opt\n"
187" 0010 0000 show after instrumentation\n"
188" 0001 0000 show after second opt\n"
189" 0000 1000 show after tree building\n"
190" 0000 0100 show selecting insns\n"
191" 0000 0010 show after reg-alloc\n"
192" 0000 0001 show final assembly\n"
njn33dbfce2006-06-02 22:58:34 +0000193" (Nb: you need --trace-notbelow with --trace-flags for full details)\n"
sewardj2a99cf62004-11-24 10:44:19 +0000194"\n"
nethercote2b0793f2003-12-02 10:41:18 +0000195" debugging options for Valgrind tools that report errors\n"
196" --dump-error=<number> show translation for basic block associated\n"
197" with <number>'th error context [0=show none]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +0000198"\n";
njn3e884182003-04-15 13:03:23 +0000199
200 Char* usage3 =
201"\n"
nethercote71980f02004-01-24 18:18:54 +0000202" Extra options read from ~/.valgrindrc, $VALGRIND_OPTS, ./.valgrindrc\n"
njn25e49d8e72002-09-23 09:36:25 +0000203"\n"
sewardj9ebd6e02007-01-08 06:01:59 +0000204" Valgrind is Copyright (C) 2000-2007 Julian Seward et al.\n"
njn25e49d8e72002-09-23 09:36:25 +0000205" and licensed under the GNU General Public License, version 2.\n"
206" Bug reports, feedback, admiration, abuse, etc, to: %s.\n"
njnd04b7c62002-10-03 14:05:52 +0000207"\n"
nethercote137bc552003-11-14 17:47:54 +0000208" Tools are copyright and licensed by their authors. See each\n"
209" tool's start-up message for more information.\n"
njn25e49d8e72002-09-23 09:36:25 +0000210"\n";
njn7cf0bd32002-06-08 13:36:03 +0000211
njnbe9b47b2005-05-15 16:22:58 +0000212 // Ensure the message goes to stdout
213 VG_(clo_log_fd) = 1;
214 vg_assert( !VG_(logging_to_socket) );
215
fitzhardinge98abfc72003-12-16 02:05:15 +0000216 VG_(printf)(usage1);
217 if (VG_(details).name) {
218 VG_(printf)(" user options for %s:\n", VG_(details).name);
fitzhardinge98abfc72003-12-16 02:05:15 +0000219 if (VG_(needs).command_line_options)
njn51d827b2005-05-09 01:02:08 +0000220 VG_TDICT_CALL(tool_print_usage);
fitzhardinge98abfc72003-12-16 02:05:15 +0000221 else
222 VG_(printf)(" (none)\n");
223 }
nethercote6c999f22004-01-31 22:55:15 +0000224 if (debug_help) {
225 VG_(printf)(usage2);
fitzhardinge98abfc72003-12-16 02:05:15 +0000226
nethercote6c999f22004-01-31 22:55:15 +0000227 if (VG_(details).name) {
228 VG_(printf)(" debugging options for %s:\n", VG_(details).name);
229
230 if (VG_(needs).command_line_options)
njn51d827b2005-05-09 01:02:08 +0000231 VG_TDICT_CALL(tool_print_debug_usage);
nethercote6c999f22004-01-31 22:55:15 +0000232 else
233 VG_(printf)(" (none)\n");
234 }
fitzhardinge98abfc72003-12-16 02:05:15 +0000235 }
nethercote421281e2003-11-20 16:20:55 +0000236 VG_(printf)(usage3, VG_BUGS_TO);
nethercotef4928da2004-06-15 10:54:40 +0000237 VG_(exit)(0);
njn7cf0bd32002-06-08 13:36:03 +0000238}
sewardjde4a1d02002-03-22 01:27:54 +0000239
sewardjde4a1d02002-03-22 01:27:54 +0000240
sewardj45f4e7c2005-09-27 19:20:21 +0000241/* Peer at previously set up VG_(args_for_valgrind) and extract any
242 request for help and also the tool name. */
243
244static void get_helprequest_and_toolname ( Int* need_help, HChar** tool )
245{
246 UInt i;
247 HChar* str;
sewardj8b635a42004-11-22 19:01:47 +0000248
sewardj14c7cc52007-02-25 15:08:24 +0000249 vg_assert( VG_(args_for_valgrind) );
nethercote71980f02004-01-24 18:18:54 +0000250
sewardj14c7cc52007-02-25 15:08:24 +0000251 /* parse the options we have (only the options we care about now) */
252 for (i = 0; i < VG_(sizeXA)( VG_(args_for_valgrind) ); i++) {
253
254 str = * (HChar**) VG_(indexXA)( VG_(args_for_valgrind), i );
sewardj45f4e7c2005-09-27 19:20:21 +0000255 vg_assert(str);
nethercote71980f02004-01-24 18:18:54 +0000256
sewardj45f4e7c2005-09-27 19:20:21 +0000257 if (VG_STREQ(str, "--version")) {
njn2e9f3f32005-10-26 16:17:46 +0000258 // Ensure the version string goes to stdout
259 VG_(clo_log_fd) = 1;
sewardj45f4e7c2005-09-27 19:20:21 +0000260 VG_(printf)("valgrind-" VERSION "\n");
261 VG_(exit)(0);
262
263 } else if (VG_CLO_STREQ(str, "--help") ||
264 VG_CLO_STREQ(str, "-h")) {
nethercote6c999f22004-01-31 22:55:15 +0000265 *need_help = 1;
266
sewardj45f4e7c2005-09-27 19:20:21 +0000267 } else if (VG_CLO_STREQ(str, "--help-debug")) {
nethercote6c999f22004-01-31 22:55:15 +0000268 *need_help = 2;
nethercote71980f02004-01-24 18:18:54 +0000269
sewardj45f4e7c2005-09-27 19:20:21 +0000270 // The tool has already been determined, but we need to know the name
271 // here.
272 } else if (VG_CLO_STREQN(7, str, "--tool=")) {
273 *tool = &str[7];
nethercote71980f02004-01-24 18:18:54 +0000274 }
275 }
nethercote71980f02004-01-24 18:18:54 +0000276}
277
sewardj45f4e7c2005-09-27 19:20:21 +0000278static Bool process_cmd_line_options( UInt* client_auxv, const char* toolname )
nethercote71980f02004-01-24 18:18:54 +0000279{
njnda033f52005-12-19 21:27:58 +0000280 // VG_(clo_log_fd) is used by all the messaging. It starts as 2 (stderr)
281 // and we cannot change it until we know what we are changing it to is
282 // ok. So we have tmp_log_fd to hold the tmp fd prior to that point.
sewardj92645592005-07-23 09:18:34 +0000283 SysRes sres;
njnda033f52005-12-19 21:27:58 +0000284 Int i, tmp_log_fd;
sewardj92645592005-07-23 09:18:34 +0000285 Int toolname_len = VG_(strlen)(toolname);
njnbe9b47b2005-05-15 16:22:58 +0000286 enum {
287 VgLogTo_Fd,
288 VgLogTo_File,
289 VgLogTo_FileExactly,
290 VgLogTo_Socket
291 } log_to = VgLogTo_Fd; // Where is logging output to be sent?
sewardjde4a1d02002-03-22 01:27:54 +0000292
nethercotee1730692003-11-20 10:38:07 +0000293 /* log to stderr by default, but usage message goes to stdout */
njnda033f52005-12-19 21:27:58 +0000294 tmp_log_fd = 2;
sewardjde4a1d02002-03-22 01:27:54 +0000295
sewardj19d81412002-06-03 01:10:40 +0000296 /* Check for sane path in ./configure --prefix=... */
fitzhardinge98abfc72003-12-16 02:05:15 +0000297 if (VG_LIBDIR[0] != '/')
sewardj17c11042006-10-15 01:26:40 +0000298 VG_(err_config_error)("Please use absolute paths in "
299 "./configure --prefix=... or --libdir=...");
sewardj38170912002-05-10 21:07:22 +0000300
sewardj14c7cc52007-02-25 15:08:24 +0000301 vg_assert( VG_(args_for_valgrind) );
nethercote71980f02004-01-24 18:18:54 +0000302
sewardj14c7cc52007-02-25 15:08:24 +0000303 for (i = 0; i < VG_(sizeXA)( VG_(args_for_valgrind) ); i++) {
304
305 HChar* arg = * (HChar**) VG_(indexXA)( VG_(args_for_valgrind), i );
sewardj45f4e7c2005-09-27 19:20:21 +0000306 HChar* colon = arg;
nethercote71980f02004-01-24 18:18:54 +0000307
thughes3bfd5a02004-07-18 08:05:44 +0000308 /* Look for a colon in the switch name */
309 while (*colon && *colon != ':' && *colon != '=')
310 colon++;
nethercote71980f02004-01-24 18:18:54 +0000311
312 /* Look for matching "--toolname:foo" */
thughes3bfd5a02004-07-18 08:05:44 +0000313 if (*colon == ':') {
nethercote71980f02004-01-24 18:18:54 +0000314 if (VG_CLO_STREQN(2, arg, "--") &&
315 VG_CLO_STREQN(toolname_len, arg+2, toolname) &&
316 VG_CLO_STREQN(1, arg+2+toolname_len, ":"))
317 {
318 // prefix matches, convert "--toolname:foo" to "--foo"
319 if (0)
320 VG_(printf)("tool-specific arg: %s\n", arg);
sewardj45f4e7c2005-09-27 19:20:21 +0000321 arg = VG_(strdup)(arg + toolname_len + 1);
nethercote71980f02004-01-24 18:18:54 +0000322 arg[0] = '-';
323 arg[1] = '-';
324
325 } else {
326 // prefix doesn't match, skip to next arg
327 continue;
328 }
329 }
330
fitzhardinge98abfc72003-12-16 02:05:15 +0000331 /* Ignore these options - they've already been handled */
njn45270a22005-03-27 01:00:11 +0000332 if (VG_CLO_STREQN( 7, arg, "--tool=")) goto skip_arg;
njn45270a22005-03-27 01:00:11 +0000333 if (VG_CLO_STREQN(20, arg, "--command-line-only=")) goto skip_arg;
fitzhardinge98abfc72003-12-16 02:05:15 +0000334
njn45270a22005-03-27 01:00:11 +0000335 if ( VG_CLO_STREQ(arg, "--")) goto skip_arg;
nethercote27fec902004-06-16 21:26:32 +0000336
nethercote71980f02004-01-24 18:18:54 +0000337 else if (VG_CLO_STREQ(arg, "-v") ||
338 VG_CLO_STREQ(arg, "--verbose"))
sewardjde4a1d02002-03-22 01:27:54 +0000339 VG_(clo_verbosity)++;
nethercote27fec902004-06-16 21:26:32 +0000340
nethercote71980f02004-01-24 18:18:54 +0000341 else if (VG_CLO_STREQ(arg, "-q") ||
342 VG_CLO_STREQ(arg, "--quiet"))
sewardjde4a1d02002-03-22 01:27:54 +0000343 VG_(clo_verbosity)--;
344
sewardj1cf558c2005-04-25 01:36:56 +0000345 else if (VG_CLO_STREQ(arg, "-d")) {
346 /* do nothing */
347 }
348
sewardj71bc3cb2005-05-19 00:25:45 +0000349 else VG_BOOL_CLO(arg, "--xml", VG_(clo_xml))
njn45270a22005-03-27 01:00:11 +0000350 else VG_BOOL_CLO(arg, "--db-attach", VG_(clo_db_attach))
351 else VG_BOOL_CLO(arg, "--demangle", VG_(clo_demangle))
352 else VG_BOOL_CLO(arg, "--error-limit", VG_(clo_error_limit))
sewardjb9779082006-05-12 23:50:15 +0000353 else VG_NUM_CLO (arg, "--error-exitcode", VG_(clo_error_exitcode))
njn45270a22005-03-27 01:00:11 +0000354 else VG_BOOL_CLO(arg, "--show-emwarns", VG_(clo_show_emwarns))
sewardj97724e52005-04-02 23:40:59 +0000355 else VG_NUM_CLO (arg, "--max-stackframe", VG_(clo_max_stackframe))
njn45270a22005-03-27 01:00:11 +0000356 else VG_BOOL_CLO(arg, "--run-libc-freeres", VG_(clo_run_libc_freeres))
357 else VG_BOOL_CLO(arg, "--show-below-main", VG_(clo_show_below_main))
358 else VG_BOOL_CLO(arg, "--time-stamp", VG_(clo_time_stamp))
359 else VG_BOOL_CLO(arg, "--track-fds", VG_(clo_track_fds))
360 else VG_BOOL_CLO(arg, "--trace-children", VG_(clo_trace_children))
361 else VG_BOOL_CLO(arg, "--trace-sched", VG_(clo_trace_sched))
362 else VG_BOOL_CLO(arg, "--trace-signals", VG_(clo_trace_signals))
363 else VG_BOOL_CLO(arg, "--trace-symtab", VG_(clo_trace_symtab))
sewardjf767d962007-02-12 17:47:14 +0000364 else VG_STR_CLO (arg, "--trace-symtab-patt", VG_(clo_trace_symtab_patt))
sewardjce058b02005-05-01 08:55:38 +0000365 else VG_BOOL_CLO(arg, "--trace-cfi", VG_(clo_trace_cfi))
sewardjf767d962007-02-12 17:47:14 +0000366 else VG_XACT_CLO(arg, "--debug-dump=syms", VG_(clo_debug_dump_syms))
367 else VG_XACT_CLO(arg, "--debug-dump=line", VG_(clo_debug_dump_line))
368 else VG_XACT_CLO(arg, "--debug-dump=frames", VG_(clo_debug_dump_frames))
njn45270a22005-03-27 01:00:11 +0000369 else VG_BOOL_CLO(arg, "--trace-redir", VG_(clo_trace_redir))
sewardjf767d962007-02-12 17:47:14 +0000370
njn45270a22005-03-27 01:00:11 +0000371 else VG_BOOL_CLO(arg, "--trace-syscalls", VG_(clo_trace_syscalls))
372 else VG_BOOL_CLO(arg, "--trace-pthreads", VG_(clo_trace_pthreads))
373 else VG_BOOL_CLO(arg, "--wait-for-gdb", VG_(clo_wait_for_gdb))
njn45270a22005-03-27 01:00:11 +0000374 else VG_STR_CLO (arg, "--db-command", VG_(clo_db_command))
njn628add62005-11-12 18:21:40 +0000375 else VG_STR_CLO (arg, "--sim-hints", VG_(clo_sim_hints))
sewardj12ab7652006-10-17 02:10:42 +0000376 else VG_BOOL_CLO(arg, "--sym-offsets", VG_(clo_sym_offsets))
sewardjde4a1d02002-03-22 01:27:54 +0000377
njn45270a22005-03-27 01:00:11 +0000378 else VG_NUM_CLO (arg, "--dump-error", VG_(clo_dump_error))
379 else VG_NUM_CLO (arg, "--input-fd", VG_(clo_input_fd))
380 else VG_NUM_CLO (arg, "--sanity-level", VG_(clo_sanity_level))
381 else VG_BNUM_CLO(arg, "--num-callers", VG_(clo_backtrace_size), 1,
382 VG_DEEPEST_BACKTRACE)
sewardjde4a1d02002-03-22 01:27:54 +0000383
sewardj6c3a2192005-07-24 07:00:45 +0000384 else if (VG_CLO_STREQ(arg, "--smc-check=none"))
385 VG_(clo_smc_check) = Vg_SmcNone;
386 else if (VG_CLO_STREQ(arg, "--smc-check=stack"))
387 VG_(clo_smc_check) = Vg_SmcStack;
388 else if (VG_CLO_STREQ(arg, "--smc-check=all"))
389 VG_(clo_smc_check) = Vg_SmcAll;
sewardj26412bd2005-07-07 10:05:05 +0000390
sewardjce5a5662005-10-06 03:19:49 +0000391 else VG_STR_CLO (arg, "--kernel-variant", VG_(clo_kernel_variant))
392
njn45270a22005-03-27 01:00:11 +0000393 else VG_BNUM_CLO(arg, "--vex-iropt-verbosity",
sewardj8b635a42004-11-22 19:01:47 +0000394 VG_(clo_vex_control).iropt_verbosity, 0, 10)
njn45270a22005-03-27 01:00:11 +0000395 else VG_BNUM_CLO(arg, "--vex-iropt-level",
sewardj8b635a42004-11-22 19:01:47 +0000396 VG_(clo_vex_control).iropt_level, 0, 2)
njn45270a22005-03-27 01:00:11 +0000397 else VG_BOOL_CLO(arg, "--vex-iropt-precise-memory-exns",
sewardj8b635a42004-11-22 19:01:47 +0000398 VG_(clo_vex_control).iropt_precise_memory_exns)
njn45270a22005-03-27 01:00:11 +0000399 else VG_BNUM_CLO(arg, "--vex-iropt-unroll-thresh",
sewardj8b635a42004-11-22 19:01:47 +0000400 VG_(clo_vex_control).iropt_unroll_thresh, 0, 400)
njn45270a22005-03-27 01:00:11 +0000401 else VG_BNUM_CLO(arg, "--vex-guest-max-insns",
sewardj8b635a42004-11-22 19:01:47 +0000402 VG_(clo_vex_control).guest_max_insns, 1, 100)
njn45270a22005-03-27 01:00:11 +0000403 else VG_BNUM_CLO(arg, "--vex-guest-chase-thresh",
sewardj8b635a42004-11-22 19:01:47 +0000404 VG_(clo_vex_control).guest_chase_thresh, 0, 99)
405
nethercotef8548672004-06-21 12:42:35 +0000406 else if (VG_CLO_STREQN(9, arg, "--log-fd=")) {
njnbe9b47b2005-05-15 16:22:58 +0000407 log_to = VgLogTo_Fd;
nethercotef8548672004-06-21 12:42:35 +0000408 VG_(clo_log_name) = NULL;
njnda033f52005-12-19 21:27:58 +0000409 tmp_log_fd = (Int)VG_(atoll)(&arg[9]);
sewardj4cf05692002-10-27 20:28:29 +0000410 }
411
nethercotef8548672004-06-21 12:42:35 +0000412 else if (VG_CLO_STREQN(11, arg, "--log-file=")) {
njnbe9b47b2005-05-15 16:22:58 +0000413 log_to = VgLogTo_File;
nethercotef8548672004-06-21 12:42:35 +0000414 VG_(clo_log_name) = &arg[11];
sewardj4cf05692002-10-27 20:28:29 +0000415 }
njnd6bc3c32005-03-27 00:44:31 +0000416
sewardjad311162005-07-19 11:25:02 +0000417 else if (VG_CLO_STREQN(21, arg, "--log-file-qualifier=")) {
418 VG_(clo_log_file_qualifier) = &arg[21];
419 }
420
sewardj603d4102005-01-11 14:01:02 +0000421 else if (VG_CLO_STREQN(19, arg, "--log-file-exactly=")) {
njnbe9b47b2005-05-15 16:22:58 +0000422 log_to = VgLogTo_FileExactly;
sewardj603d4102005-01-11 14:01:02 +0000423 VG_(clo_log_name) = &arg[19];
424 }
sewardjde4a1d02002-03-22 01:27:54 +0000425
nethercotef8548672004-06-21 12:42:35 +0000426 else if (VG_CLO_STREQN(13, arg, "--log-socket=")) {
njnbe9b47b2005-05-15 16:22:58 +0000427 log_to = VgLogTo_Socket;
nethercotef8548672004-06-21 12:42:35 +0000428 VG_(clo_log_name) = &arg[13];
sewardj73cf3bc2002-11-03 03:20:15 +0000429 }
430
sewardj768db0e2005-07-19 14:18:56 +0000431 else if (VG_CLO_STREQN(19, arg, "--xml-user-comment=")) {
432 VG_(clo_xml_user_comment) = &arg[19];
433 }
434
nethercote71980f02004-01-24 18:18:54 +0000435 else if (VG_CLO_STREQN(15, arg, "--suppressions=")) {
sewardjde4a1d02002-03-22 01:27:54 +0000436 if (VG_(clo_n_suppressions) >= VG_CLO_MAX_SFILES) {
njn25e49d8e72002-09-23 09:36:25 +0000437 VG_(message)(Vg_UserMsg, "Too many suppression files specified.");
sewardjde4a1d02002-03-22 01:27:54 +0000438 VG_(message)(Vg_UserMsg,
439 "Increase VG_CLO_MAX_SFILES and recompile.");
sewardj17c11042006-10-15 01:26:40 +0000440 VG_(err_bad_option)(arg);
sewardjde4a1d02002-03-22 01:27:54 +0000441 }
nethercote71980f02004-01-24 18:18:54 +0000442 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = &arg[15];
sewardjde4a1d02002-03-22 01:27:54 +0000443 VG_(clo_n_suppressions)++;
444 }
sewardjde4a1d02002-03-22 01:27:54 +0000445
sewardjfa8ec112005-01-19 11:55:34 +0000446 /* "stuvwxyz" --> stuvwxyz (binary) */
447 else if (VG_CLO_STREQN(14, arg, "--trace-flags=")) {
448 Int j;
449 char* opt = & arg[14];
450
451 if (8 != VG_(strlen)(opt)) {
452 VG_(message)(Vg_UserMsg,
453 "--trace-flags argument must have 8 digits");
sewardj17c11042006-10-15 01:26:40 +0000454 VG_(err_bad_option)(arg);
sewardjfa8ec112005-01-19 11:55:34 +0000455 }
456 for (j = 0; j < 8; j++) {
457 if ('0' == opt[j]) { /* do nothing */ }
458 else if ('1' == opt[j]) VG_(clo_trace_flags) |= (1 << (7-j));
459 else {
460 VG_(message)(Vg_UserMsg, "--trace-flags argument can only "
461 "contain 0s and 1s");
sewardj17c11042006-10-15 01:26:40 +0000462 VG_(err_bad_option)(arg);
sewardjfa8ec112005-01-19 11:55:34 +0000463 }
464 }
465 }
466
467 /* "stuvwxyz" --> stuvwxyz (binary) */
468 else if (VG_CLO_STREQN(16, arg, "--profile-flags=")) {
njn25e49d8e72002-09-23 09:36:25 +0000469 Int j;
nethercote71980f02004-01-24 18:18:54 +0000470 char* opt = & arg[16];
njn25e49d8e72002-09-23 09:36:25 +0000471
sewardj2a99cf62004-11-24 10:44:19 +0000472 if (8 != VG_(strlen)(opt)) {
njn25e49d8e72002-09-23 09:36:25 +0000473 VG_(message)(Vg_UserMsg,
sewardjfa8ec112005-01-19 11:55:34 +0000474 "--profile-flags argument must have 8 digits");
sewardj17c11042006-10-15 01:26:40 +0000475 VG_(err_bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +0000476 }
sewardj8b635a42004-11-22 19:01:47 +0000477 for (j = 0; j < 8; j++) {
njn25e49d8e72002-09-23 09:36:25 +0000478 if ('0' == opt[j]) { /* do nothing */ }
sewardjfa8ec112005-01-19 11:55:34 +0000479 else if ('1' == opt[j]) VG_(clo_profile_flags) |= (1 << (7-j));
njn25e49d8e72002-09-23 09:36:25 +0000480 else {
sewardjfa8ec112005-01-19 11:55:34 +0000481 VG_(message)(Vg_UserMsg, "--profile-flags argument can only "
njn25e49d8e72002-09-23 09:36:25 +0000482 "contain 0s and 1s");
sewardj17c11042006-10-15 01:26:40 +0000483 VG_(err_bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +0000484 }
485 }
486 }
sewardjde4a1d02002-03-22 01:27:54 +0000487
njn45270a22005-03-27 01:00:11 +0000488 else VG_NUM_CLO (arg, "--trace-notbelow", VG_(clo_trace_notbelow))
sewardjc771b292004-11-30 18:55:21 +0000489
sewardjd153fae2005-01-10 17:24:47 +0000490 else if (VG_CLO_STREQ(arg, "--gen-suppressions=no"))
491 VG_(clo_gen_suppressions) = 0;
492 else if (VG_CLO_STREQ(arg, "--gen-suppressions=yes"))
493 VG_(clo_gen_suppressions) = 1;
494 else if (VG_CLO_STREQ(arg, "--gen-suppressions=all"))
495 VG_(clo_gen_suppressions) = 2;
496
nethercote71980f02004-01-24 18:18:54 +0000497 else if ( ! VG_(needs).command_line_options
njn51d827b2005-05-09 01:02:08 +0000498 || ! VG_TDICT_CALL(tool_process_cmd_line_option, arg) ) {
sewardj17c11042006-10-15 01:26:40 +0000499 VG_(err_bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +0000500 }
njn8c0b3bb2005-03-12 21:20:39 +0000501 skip_arg:
sewardj14c7cc52007-02-25 15:08:24 +0000502 if (arg != * (HChar**) VG_(indexXA)( VG_(args_for_valgrind), i )) {
sewardj45f4e7c2005-09-27 19:20:21 +0000503 VG_(free)(arg);
504 }
sewardjde4a1d02002-03-22 01:27:54 +0000505 }
506
sewardj998d40d2004-12-06 14:24:52 +0000507 /* Make VEX control parameters sane */
508
509 if (VG_(clo_vex_control).guest_chase_thresh
510 >= VG_(clo_vex_control).guest_max_insns)
511 VG_(clo_vex_control).guest_chase_thresh
512 = VG_(clo_vex_control).guest_max_insns - 1;
513
514 if (VG_(clo_vex_control).guest_chase_thresh < 0)
515 VG_(clo_vex_control).guest_chase_thresh = 0;
516
517 /* Check various option values */
nethercote27fec902004-06-16 21:26:32 +0000518
njnf9ebf672003-05-12 21:41:30 +0000519 if (VG_(clo_verbosity) < 0)
sewardjde4a1d02002-03-22 01:27:54 +0000520 VG_(clo_verbosity) = 0;
521
nethercote04d0fbc2004-01-26 16:48:06 +0000522 if (VG_(clo_db_attach) && VG_(clo_trace_children)) {
sewardjde4a1d02002-03-22 01:27:54 +0000523 VG_(message)(Vg_UserMsg, "");
524 VG_(message)(Vg_UserMsg,
nethercote04d0fbc2004-01-26 16:48:06 +0000525 "--db-attach=yes conflicts with --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +0000526 VG_(message)(Vg_UserMsg,
527 "Please choose one or the other, but not both.");
sewardj17c11042006-10-15 01:26:40 +0000528 VG_(err_bad_option)("--db-attach=yes and --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +0000529 }
530
njnbe9b47b2005-05-15 16:22:58 +0000531 if (VG_(clo_gen_suppressions) > 0 &&
532 !VG_(needs).core_errors && !VG_(needs).tool_errors) {
533 VG_(message)(Vg_UserMsg,
534 "Can't use --gen-suppressions= with this tool,");
535 VG_(message)(Vg_UserMsg,
536 "as it doesn't generate errors.");
sewardj17c11042006-10-15 01:26:40 +0000537 VG_(err_bad_option)("--gen-suppressions=");
njnbe9b47b2005-05-15 16:22:58 +0000538 }
539
sewardj71bc3cb2005-05-19 00:25:45 +0000540 /* If we've been asked to emit XML, mash around various other
541 options so as to constrain the output somewhat, and to remove
542 any need for user input during the run. */
543 if (VG_(clo_xml)) {
544 /* Disable suppression generation (requires user input) */
545 VG_(clo_gen_suppressions) = 0;
546 /* Disable attaching to GDB (requires user input) */
547 VG_(clo_db_attach) = False;
548 /* Set a known verbosity level */
549 VG_(clo_verbosity) = 1;
550 /* Disable error limits (this might be a bad idea!) */
551 VG_(clo_error_limit) = False;
552 /* Disable emulation warnings */
553 VG_(clo_show_emwarns) = False;
554 /* Disable waiting for GDB to debug Valgrind */
555 VG_(clo_wait_for_gdb) = False;
556 /* No file-descriptor leak checking yet */
557 VG_(clo_track_fds) = False;
sewardj21f7f0c2005-07-06 19:46:48 +0000558 /* Disable timestamped output */
559 VG_(clo_time_stamp) = False;
sewardj71bc3cb2005-05-19 00:25:45 +0000560 /* Also, we want to set options for the leak checker, but that
561 will have to be done in Memcheck's flag-handling code, not
562 here. */
563 }
564
njnbe9b47b2005-05-15 16:22:58 +0000565 /* All non-logging-related options have been checked. If the logging
566 option specified is ok, we can switch to it, as we know we won't
567 have to generate any other command-line-related error messages.
568 (So far we should be still attached to stderr, so we can show on
569 the terminal any problems to do with processing command line
570 opts.)
571
572 So set up logging now. After this is done, VG_(clo_log_fd)
sewardj4cf05692002-10-27 20:28:29 +0000573 should be connected to whatever sink has been selected, and we
574 indiscriminately chuck stuff into it without worrying what the
575 nature of it is. Oh the wonder of Unix streams. */
576
njnbe9b47b2005-05-15 16:22:58 +0000577 vg_assert(VG_(clo_log_fd) == 2 /* stderr */);
578 vg_assert(VG_(logging_to_socket) == False);
sewardj4cf05692002-10-27 20:28:29 +0000579
njnbe9b47b2005-05-15 16:22:58 +0000580 switch (log_to) {
sewardj73cf3bc2002-11-03 03:20:15 +0000581
sewardj4cf05692002-10-27 20:28:29 +0000582 case VgLogTo_Fd:
nethercotef8548672004-06-21 12:42:35 +0000583 vg_assert(VG_(clo_log_name) == NULL);
sewardj4cf05692002-10-27 20:28:29 +0000584 break;
sewardj73cf3bc2002-11-03 03:20:15 +0000585
sewardj4cf05692002-10-27 20:28:29 +0000586 case VgLogTo_File: {
sewardjad311162005-07-19 11:25:02 +0000587 HChar logfilename[1000];
588 Int seq = 0;
589 Int pid = VG_(getpid)();
590 HChar* qual = NULL;
jsgff3c3f1a2003-10-14 22:13:28 +0000591
nethercotef8548672004-06-21 12:42:35 +0000592 vg_assert(VG_(clo_log_name) != NULL);
593 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
jsgff3c3f1a2003-10-14 22:13:28 +0000594
sewardjad311162005-07-19 11:25:02 +0000595 if (VG_(clo_log_file_qualifier)) {
596 qual = VG_(getenv)(VG_(clo_log_file_qualifier));
597 }
598
nethercote71980f02004-01-24 18:18:54 +0000599 for (;;) {
sewardj92645592005-07-23 09:18:34 +0000600 HChar pidtxt[20], seqtxt[20];
601
602 VG_(sprintf)(pidtxt, "%d", pid);
603
604 if (seq == 0)
605 seqtxt[0] = 0;
606 else
607 VG_(sprintf)(seqtxt, ".%d", seq);
608
jsgff3c3f1a2003-10-14 22:13:28 +0000609 seq++;
610
sewardj92645592005-07-23 09:18:34 +0000611 /* Result:
612 if (qual) base_name ++ "." ++ qual ++ seqtxt
613 if (not qual) base_name ++ "." ++ pid ++ seqtxt
614 */
615 VG_(sprintf)( logfilename,
616 "%s.%s%s",
617 VG_(clo_log_name),
618 qual ? qual : pidtxt,
619 seqtxt );
620
njnbe9b47b2005-05-15 16:22:58 +0000621 // EXCL: it will fail with EEXIST if the file already exists.
njnda033f52005-12-19 21:27:58 +0000622 sres = VG_(open)(logfilename,
623 VKI_O_CREAT|VKI_O_WRONLY|VKI_O_EXCL|VKI_O_TRUNC,
624 VKI_S_IRUSR|VKI_S_IWUSR);
sewardj92645592005-07-23 09:18:34 +0000625 if (!sres.isError) {
sewardj12ab7652006-10-17 02:10:42 +0000626 tmp_log_fd = sres.res;
sewardj603d4102005-01-11 14:01:02 +0000627 break; /* for (;;) */
jsgff3c3f1a2003-10-14 22:13:28 +0000628 } else {
njnbe9b47b2005-05-15 16:22:58 +0000629 // If the file already existed, we try the next name. If it
630 // was some other file error, we give up.
sewardj12ab7652006-10-17 02:10:42 +0000631 if (sres.err != VKI_EEXIST) {
jsgff3c3f1a2003-10-14 22:13:28 +0000632 VG_(message)(Vg_UserMsg,
sewardjc40fce52006-05-03 13:52:17 +0000633 "Can't create log file '%s' (%s); giving up!",
sewardj12ab7652006-10-17 02:10:42 +0000634 logfilename, VG_(strerror)(sres.err));
sewardj17c11042006-10-15 01:26:40 +0000635 VG_(err_bad_option)(
sewardj603d4102005-01-11 14:01:02 +0000636 "--log-file=<file> (didn't work out for some reason.)");
njnbe9b47b2005-05-15 16:22:58 +0000637 /*NOTREACHED*/
jsgff3c3f1a2003-10-14 22:13:28 +0000638 }
639 }
640 }
sewardj603d4102005-01-11 14:01:02 +0000641 break; /* switch (VG_(clo_log_to)) */
642 }
643
644 case VgLogTo_FileExactly: {
sewardj603d4102005-01-11 14:01:02 +0000645 vg_assert(VG_(clo_log_name) != NULL);
646 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
sewardj603d4102005-01-11 14:01:02 +0000647
njnda033f52005-12-19 21:27:58 +0000648 sres = VG_(open)(VG_(clo_log_name),
649 VKI_O_CREAT|VKI_O_WRONLY|VKI_O_TRUNC,
650 VKI_S_IRUSR|VKI_S_IWUSR);
sewardj92645592005-07-23 09:18:34 +0000651 if (!sres.isError) {
sewardj12ab7652006-10-17 02:10:42 +0000652 tmp_log_fd = sres.res;
njnbe9b47b2005-05-15 16:22:58 +0000653 } else {
sewardj603d4102005-01-11 14:01:02 +0000654 VG_(message)(Vg_UserMsg,
njn02bc4b82005-05-15 17:28:26 +0000655 "Can't create/open log file '%s'; giving up!",
sewardj603d4102005-01-11 14:01:02 +0000656 VG_(clo_log_name));
sewardj17c11042006-10-15 01:26:40 +0000657 VG_(err_bad_option)(
sewardj603d4102005-01-11 14:01:02 +0000658 "--log-file-exactly=<file> (didn't work out for some reason.)");
659 /*NOTREACHED*/
660 }
661 break; /* switch (VG_(clo_log_to)) */
sewardj73cf3bc2002-11-03 03:20:15 +0000662 }
663
664 case VgLogTo_Socket: {
nethercotef8548672004-06-21 12:42:35 +0000665 vg_assert(VG_(clo_log_name) != NULL);
666 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
njnda033f52005-12-19 21:27:58 +0000667 tmp_log_fd = VG_(connect_via_socket)( VG_(clo_log_name) );
668 if (tmp_log_fd == -1) {
sewardj73cf3bc2002-11-03 03:20:15 +0000669 VG_(message)(Vg_UserMsg,
nethercotef8548672004-06-21 12:42:35 +0000670 "Invalid --log-socket=ipaddr or --log-socket=ipaddr:port spec");
sewardj73cf3bc2002-11-03 03:20:15 +0000671 VG_(message)(Vg_UserMsg,
njn02bc4b82005-05-15 17:28:26 +0000672 "of '%s'; giving up!", VG_(clo_log_name) );
sewardj17c11042006-10-15 01:26:40 +0000673 VG_(err_bad_option)(
nethercotef8548672004-06-21 12:42:35 +0000674 "--log-socket=");
njnbe9b47b2005-05-15 16:22:58 +0000675 /*NOTREACHED*/
sewardj4cf05692002-10-27 20:28:29 +0000676 }
njnda033f52005-12-19 21:27:58 +0000677 if (tmp_log_fd == -2) {
sewardj73cf3bc2002-11-03 03:20:15 +0000678 VG_(message)(Vg_UserMsg,
njn02bc4b82005-05-15 17:28:26 +0000679 "valgrind: failed to connect to logging server '%s'.",
nethercotef8548672004-06-21 12:42:35 +0000680 VG_(clo_log_name) );
sewardj570f8902002-11-03 11:44:36 +0000681 VG_(message)(Vg_UserMsg,
682 "Log messages will sent to stderr instead." );
683 VG_(message)(Vg_UserMsg,
684 "" );
685 /* We don't change anything here. */
njnbe9b47b2005-05-15 16:22:58 +0000686 vg_assert(VG_(clo_log_fd) == 2);
njnda033f52005-12-19 21:27:58 +0000687 tmp_log_fd = 2;
sewardj570f8902002-11-03 11:44:36 +0000688 } else {
njnda033f52005-12-19 21:27:58 +0000689 vg_assert(tmp_log_fd > 0);
njnbe9b47b2005-05-15 16:22:58 +0000690 VG_(logging_to_socket) = True;
sewardj570f8902002-11-03 11:44:36 +0000691 }
sewardj73cf3bc2002-11-03 03:20:15 +0000692 break;
693 }
sewardj4cf05692002-10-27 20:28:29 +0000694 }
695
sewardj71bc3cb2005-05-19 00:25:45 +0000696
697 /* Check that the requested tool actually supports XML output. */
njnca54af32006-04-16 10:25:43 +0000698 if (VG_(clo_xml) && !VG_(needs).xml_output) {
sewardj71bc3cb2005-05-19 00:25:45 +0000699 VG_(clo_xml) = False;
700 VG_(message)(Vg_UserMsg,
njnca54af32006-04-16 10:25:43 +0000701 "%s does not support XML output.", VG_(details).name);
sewardj17c11042006-10-15 01:26:40 +0000702 VG_(err_bad_option)("--xml=yes");
sewardj71bc3cb2005-05-19 00:25:45 +0000703 /*NOTREACHED*/
704 }
705
njnda033f52005-12-19 21:27:58 +0000706 if (tmp_log_fd >= 0) {
707 // Move log_fd into the safe range, so it doesn't conflict with any app fds.
708 tmp_log_fd = VG_(fcntl)(tmp_log_fd, VKI_F_DUPFD, VG_(fd_hard_limit));
709 if (tmp_log_fd < 0) {
710 VG_(message)(Vg_UserMsg, "valgrind: failed to move logfile fd into safe range, using stderr");
711 VG_(clo_log_fd) = 2; // stderr
712 } else {
713 VG_(clo_log_fd) = tmp_log_fd;
714 VG_(fcntl)(VG_(clo_log_fd), VKI_F_SETFD, VKI_FD_CLOEXEC);
715 }
716 } else {
717 // If they said --log-fd=-1, don't print anything. Plausible for use in
718 // regression testing suites that use client requests to count errors.
719 VG_(clo_log_fd) = tmp_log_fd;
jsgf855d93d2003-10-13 22:26:55 +0000720 }
721
sewardj45f4e7c2005-09-27 19:20:21 +0000722 if (VG_(clo_n_suppressions) < VG_CLO_MAX_SFILES-1 &&
723 (VG_(needs).core_errors || VG_(needs).tool_errors)) {
724 /* If we haven't reached the max number of suppressions, load
725 the default one. */
726 static const Char default_supp[] = "default.supp";
727 Int len = VG_(strlen)(VG_(libdir)) + 1 + sizeof(default_supp);
728 Char *buf = VG_(arena_malloc)(VG_AR_CORE, len);
729 VG_(sprintf)(buf, "%s/%s", VG_(libdir), default_supp);
730 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = buf;
731 VG_(clo_n_suppressions)++;
732 }
sewardjde4a1d02002-03-22 01:27:54 +0000733
sewardj45f4e7c2005-09-27 19:20:21 +0000734 return (log_to == VgLogTo_Fd);
735}
736
737
738/*====================================================================*/
739/*=== Printing the preamble ===*/
740/*====================================================================*/
741
742/* Ok, the logging sink is running now. Print a suitable preamble.
743 If logging to file or a socket, write details of parent PID and
744 command line args, to help people trying to interpret the
745 results of a run which encompasses multiple processes. */
746static void print_preamble(Bool logging_to_fd, const char* toolname)
747{
tom60a4b0b2005-10-12 10:45:27 +0000748 HChar* xpre = VG_(clo_xml) ? " <line>" : "";
749 HChar* xpost = VG_(clo_xml) ? "</line>" : "";
750 Int i;
751
sewardj14c7cc52007-02-25 15:08:24 +0000752 vg_assert( VG_(args_for_client) );
753 vg_assert( VG_(args_for_valgrind) );
754
sewardj71bc3cb2005-05-19 00:25:45 +0000755 if (VG_(clo_xml)) {
sewardj8665d8e2005-06-01 17:35:23 +0000756 VG_(message)(Vg_UserMsg, "<?xml version=\"1.0\"?>");
757 VG_(message)(Vg_UserMsg, "");
sewardj71bc3cb2005-05-19 00:25:45 +0000758 VG_(message)(Vg_UserMsg, "<valgrindoutput>");
759 VG_(message)(Vg_UserMsg, "");
cerion20241ba2005-11-15 19:07:53 +0000760 VG_(message)(Vg_UserMsg, "<protocolversion>2</protocolversion>");
sewardj71bc3cb2005-05-19 00:25:45 +0000761 VG_(message)(Vg_UserMsg, "");
762 }
763
sewardj83adf412002-05-01 01:25:45 +0000764 if (VG_(clo_verbosity > 0)) {
sewardjd7bddad2005-06-13 16:48:32 +0000765
766 if (VG_(clo_xml))
767 VG_(message)(Vg_UserMsg, "<preamble>");
768
nethercote996901a2004-08-03 13:29:09 +0000769 /* Tool details */
sewardj71bc3cb2005-05-19 00:25:45 +0000770 VG_(message)(Vg_UserMsg, "%s%s%s%s, %s.%s",
771 xpre,
njnd04b7c62002-10-03 14:05:52 +0000772 VG_(details).name,
njnb9c427c2004-12-01 14:14:42 +0000773 NULL == VG_(details).version ? "" : "-",
njnd04b7c62002-10-03 14:05:52 +0000774 NULL == VG_(details).version
775 ? (Char*)"" : VG_(details).version,
sewardj71bc3cb2005-05-19 00:25:45 +0000776 VG_(details).description,
777 xpost);
778 VG_(message)(Vg_UserMsg, "%s%s%s",
779 xpre, VG_(details).copyright_author, xpost);
sewardj3b2736a2002-03-24 12:18:35 +0000780
njnd04b7c62002-10-03 14:05:52 +0000781 /* Core details */
782 VG_(message)(Vg_UserMsg,
sewardj71bc3cb2005-05-19 00:25:45 +0000783 "%sUsing LibVEX rev %s, a library for dynamic binary translation.%s",
784 xpre, LibVEX_Version(), xpost );
sewardjc7025332004-12-13 18:30:39 +0000785 VG_(message)(Vg_UserMsg,
sewardj9ebd6e02007-01-08 06:01:59 +0000786 "%sCopyright (C) 2004-2007, and GNU GPL'd, by OpenWorks LLP.%s",
sewardj71bc3cb2005-05-19 00:25:45 +0000787 xpre, xpost );
sewardjc7025332004-12-13 18:30:39 +0000788 VG_(message)(Vg_UserMsg,
sewardj71bc3cb2005-05-19 00:25:45 +0000789 "%sUsing valgrind-%s, a dynamic binary instrumentation framework.%s",
790 xpre, VERSION, xpost);
sewardjde4a1d02002-03-22 01:27:54 +0000791 VG_(message)(Vg_UserMsg,
sewardj9ebd6e02007-01-08 06:01:59 +0000792 "%sCopyright (C) 2000-2007, and GNU GPL'd, by Julian Seward et al.%s",
sewardj71bc3cb2005-05-19 00:25:45 +0000793 xpre, xpost );
sewardjd7bddad2005-06-13 16:48:32 +0000794
sewardj45f4e7c2005-09-27 19:20:21 +0000795 if (VG_(clo_verbosity) == 1 && !VG_(clo_xml))
796 VG_(message)(Vg_UserMsg, "For more details, rerun with: -v");
797
sewardjd7bddad2005-06-13 16:48:32 +0000798 if (VG_(clo_xml))
799 VG_(message)(Vg_UserMsg, "</preamble>");
njnd04b7c62002-10-03 14:05:52 +0000800 }
801
sewardj45f4e7c2005-09-27 19:20:21 +0000802 if (!VG_(clo_xml) && VG_(clo_verbosity) > 0 && !logging_to_fd) {
sewardj4cf05692002-10-27 20:28:29 +0000803 VG_(message)(Vg_UserMsg, "");
804 VG_(message)(Vg_UserMsg,
805 "My PID = %d, parent PID = %d. Prog and args are:",
806 VG_(getpid)(), VG_(getppid)() );
sewardj5e940782005-09-28 19:59:19 +0000807 if (VG_(args_the_exename))
808 VG_(message)(Vg_UserMsg, " %s", VG_(args_the_exename));
sewardj14c7cc52007-02-25 15:08:24 +0000809 for (i = 0; i < VG_(sizeXA)( VG_(args_for_client) ); i++)
810 VG_(message)(Vg_UserMsg,
811 " %s",
812 * (HChar**) VG_(indexXA)( VG_(args_for_client), i ));
sewardj5b742c32005-07-26 23:43:26 +0000813 if (VG_(clo_log_file_qualifier)) {
814 HChar* val = VG_(getenv)(VG_(clo_log_file_qualifier));
815 VG_(message)(Vg_UserMsg, "");
816 VG_(message)(Vg_UserMsg, "Log file qualifier: var %s, value %s.",
817 VG_(clo_log_file_qualifier),
818 val ? val : "");
819 }
sewardj4cf05692002-10-27 20:28:29 +0000820 }
sewardj71bc3cb2005-05-19 00:25:45 +0000821 else
822 if (VG_(clo_xml)) {
823 VG_(message)(Vg_UserMsg, "");
824 VG_(message)(Vg_UserMsg, "<pid>%d</pid>", VG_(getpid)());
825 VG_(message)(Vg_UserMsg, "<ppid>%d</ppid>", VG_(getppid)());
sewardj97f7e0c2005-07-19 15:00:25 +0000826 VG_(message)(Vg_UserMsg, "<tool>%t</tool>", toolname);
sewardjad311162005-07-19 11:25:02 +0000827 if (VG_(clo_log_file_qualifier)) {
828 HChar* val = VG_(getenv)(VG_(clo_log_file_qualifier));
sewardj97f7e0c2005-07-19 15:00:25 +0000829 VG_(message)(Vg_UserMsg, "<logfilequalifier> <var>%t</var> "
830 "<value>%t</value> </logfilequalifier>",
sewardjad311162005-07-19 11:25:02 +0000831 VG_(clo_log_file_qualifier),
832 val ? val : "");
833 }
sewardj768db0e2005-07-19 14:18:56 +0000834 if (VG_(clo_xml_user_comment)) {
835 /* Note: the user comment itself is XML and is therefore to
836 be passed through verbatim (%s) rather than escaped
837 (%t). */
838 VG_(message)(Vg_UserMsg, "<usercomment>%s</usercomment>",
839 VG_(clo_xml_user_comment));
840 }
sewardj71bc3cb2005-05-19 00:25:45 +0000841 VG_(message)(Vg_UserMsg, "");
sewardjb8a3dac2005-07-19 12:39:11 +0000842 VG_(message)(Vg_UserMsg, "<args>");
sewardj45f4e7c2005-09-27 19:20:21 +0000843
sewardjb8a3dac2005-07-19 12:39:11 +0000844 VG_(message)(Vg_UserMsg, " <vargv>");
sewardj45f4e7c2005-09-27 19:20:21 +0000845 if (VG_(name_of_launcher))
846 VG_(message)(Vg_UserMsg, " <exe>%t</exe>",
847 VG_(name_of_launcher));
sewardj125fd4f2007-03-08 19:56:14 +0000848 else
849 VG_(message)(Vg_UserMsg, " <exe>%t</exe>",
850 "(launcher name unknown)");
sewardj14c7cc52007-02-25 15:08:24 +0000851 for (i = 0; i < VG_(sizeXA)( VG_(args_for_valgrind) ); i++) {
sewardj45f4e7c2005-09-27 19:20:21 +0000852 VG_(message)(Vg_UserMsg,
853 " <arg>%t</arg>",
sewardj14c7cc52007-02-25 15:08:24 +0000854 * (HChar**) VG_(indexXA)( VG_(args_for_valgrind), i ));
sewardjb8a3dac2005-07-19 12:39:11 +0000855 }
856 VG_(message)(Vg_UserMsg, " </vargv>");
sewardj45f4e7c2005-09-27 19:20:21 +0000857
sewardjb8a3dac2005-07-19 12:39:11 +0000858 VG_(message)(Vg_UserMsg, " <argv>");
sewardj45f4e7c2005-09-27 19:20:21 +0000859 if (VG_(args_the_exename))
860 VG_(message)(Vg_UserMsg, " <exe>%t</exe>",
861 VG_(args_the_exename));
sewardj14c7cc52007-02-25 15:08:24 +0000862 for (i = 0; i < VG_(sizeXA)( VG_(args_for_client) ); i++) {
863 VG_(message)(Vg_UserMsg,
864 " <arg>%t</arg>",
865 * (HChar**) VG_(indexXA)( VG_(args_for_client), i ));
sewardj8665d8e2005-06-01 17:35:23 +0000866 }
sewardjb8a3dac2005-07-19 12:39:11 +0000867 VG_(message)(Vg_UserMsg, " </argv>");
sewardj45f4e7c2005-09-27 19:20:21 +0000868
sewardjb8a3dac2005-07-19 12:39:11 +0000869 VG_(message)(Vg_UserMsg, "</args>");
sewardj71bc3cb2005-05-19 00:25:45 +0000870 }
sewardj4cf05692002-10-27 20:28:29 +0000871
sewardj45f4e7c2005-09-27 19:20:21 +0000872 // Empty line after the preamble
873 if (VG_(clo_verbosity) > 0)
874 VG_(message)(Vg_UserMsg, "");
875
sewardjde4a1d02002-03-22 01:27:54 +0000876 if (VG_(clo_verbosity) > 1) {
sewardj92645592005-07-23 09:18:34 +0000877 SysRes fd;
sewardj1f0bbc72005-11-16 03:51:02 +0000878 VexArch vex_arch;
879 VexArchInfo vex_archinfo;
sewardj45f4e7c2005-09-27 19:20:21 +0000880 if (!logging_to_fd)
njn1fd5eb22005-03-13 05:43:23 +0000881 VG_(message)(Vg_DebugMsg, "");
njn1fd5eb22005-03-13 05:43:23 +0000882 VG_(message)(Vg_DebugMsg, "Command line");
sewardj45f4e7c2005-09-27 19:20:21 +0000883 if (VG_(args_the_exename))
884 VG_(message)(Vg_DebugMsg, " %s", VG_(args_the_exename));
sewardj14c7cc52007-02-25 15:08:24 +0000885 for (i = 0; i < VG_(sizeXA)( VG_(args_for_client) ); i++)
886 VG_(message)(Vg_DebugMsg,
887 " %s",
888 * (HChar**) VG_(indexXA)( VG_(args_for_client), i ));
njn86dc2bc2003-09-09 07:26:21 +0000889
njn1fd5eb22005-03-13 05:43:23 +0000890 VG_(message)(Vg_DebugMsg, "Startup, with flags:");
sewardj14c7cc52007-02-25 15:08:24 +0000891 for (i = 0; i < VG_(sizeXA)( VG_(args_for_valgrind) ); i++) {
892 VG_(message)(Vg_DebugMsg,
893 " %s",
894 * (HChar**) VG_(indexXA)( VG_(args_for_valgrind), i ));
sewardjde4a1d02002-03-22 01:27:54 +0000895 }
nethercotea70f7352004-04-18 12:08:46 +0000896
njn1fd5eb22005-03-13 05:43:23 +0000897 VG_(message)(Vg_DebugMsg, "Contents of /proc/version:");
nethercotea70f7352004-04-18 12:08:46 +0000898 fd = VG_(open) ( "/proc/version", VKI_O_RDONLY, 0 );
sewardj92645592005-07-23 09:18:34 +0000899 if (fd.isError) {
njn1fd5eb22005-03-13 05:43:23 +0000900 VG_(message)(Vg_DebugMsg, " can't open /proc/version");
nethercotea70f7352004-04-18 12:08:46 +0000901 } else {
sewardj71bc3cb2005-05-19 00:25:45 +0000902# define BUF_LEN 256
nethercotea70f7352004-04-18 12:08:46 +0000903 Char version_buf[BUF_LEN];
sewardj12ab7652006-10-17 02:10:42 +0000904 Int n = VG_(read) ( fd.res, version_buf, BUF_LEN );
njnbe9b47b2005-05-15 16:22:58 +0000905 vg_assert(n <= BUF_LEN);
nethercotea70f7352004-04-18 12:08:46 +0000906 if (n > 0) {
907 version_buf[n-1] = '\0';
njn1fd5eb22005-03-13 05:43:23 +0000908 VG_(message)(Vg_DebugMsg, " %s", version_buf);
nethercotea70f7352004-04-18 12:08:46 +0000909 } else {
njn1fd5eb22005-03-13 05:43:23 +0000910 VG_(message)(Vg_DebugMsg, " (empty?)");
nethercotea70f7352004-04-18 12:08:46 +0000911 }
sewardj12ab7652006-10-17 02:10:42 +0000912 VG_(close)(fd.res);
sewardj71bc3cb2005-05-19 00:25:45 +0000913# undef BUF_LEN
nethercotea70f7352004-04-18 12:08:46 +0000914 }
sewardj1f0bbc72005-11-16 03:51:02 +0000915
916 VG_(machine_get_VexArchInfo)( &vex_arch, &vex_archinfo );
sewardje3121f32006-01-27 21:23:23 +0000917 VG_(message)(
918 Vg_DebugMsg,
919 "Arch and hwcaps: %s, %s",
920 LibVEX_ppVexArch ( vex_arch ),
921 LibVEX_ppVexHwCaps ( vex_arch, vex_archinfo.hwcaps )
922 );
sewardje66f2e02006-12-30 17:45:08 +0000923 VG_(message)(
924 Vg_DebugMsg,
sewardj07854682006-12-30 17:56:32 +0000925 "Page sizes: currently %d, max supported %d",
sewardje66f2e02006-12-30 17:45:08 +0000926 (Int)VKI_PAGE_SIZE, (Int)VKI_MAX_PAGE_SIZE
927 );
sewardj1f0bbc72005-11-16 03:51:02 +0000928 VG_(message)(Vg_DebugMsg, "Valgrind library directory: %s", VG_(libdir));
sewardjde4a1d02002-03-22 01:27:54 +0000929 }
nethercotef6a1d502004-08-09 12:21:57 +0000930}
931
sewardjde4a1d02002-03-22 01:27:54 +0000932
nethercote71980f02004-01-24 18:18:54 +0000933/*====================================================================*/
934/*=== File descriptor setup ===*/
935/*====================================================================*/
936
sewardj5f229e22005-09-28 01:36:01 +0000937/* Number of file descriptors that Valgrind tries to reserve for
938 it's own use - just a small constant. */
939#define N_RESERVED_FDS (10)
940
nethercote71980f02004-01-24 18:18:54 +0000941static void setup_file_descriptors(void)
942{
943 struct vki_rlimit rl;
sewardj17c11042006-10-15 01:26:40 +0000944 Bool show = False;
nethercote71980f02004-01-24 18:18:54 +0000945
946 /* Get the current file descriptor limits. */
947 if (VG_(getrlimit)(VKI_RLIMIT_NOFILE, &rl) < 0) {
948 rl.rlim_cur = 1024;
949 rl.rlim_max = 1024;
950 }
951
sewardj17c11042006-10-15 01:26:40 +0000952 if (show)
953 VG_(printf)("fd limits: host, before: cur %u max %u\n",
954 rl.rlim_cur, rl.rlim_max);
955
956# if defined(VGP_ppc32_aix5) || defined(VGP_ppc64_aix5)
957 /* I don't know why this kludge is needed; however if rl.rlim_cur
958 is RLIM_INFINITY, then VG_(safe_fd)'s attempts using VG_(fcntl)
959 to lift V's file descriptors above the threshold RLIM_INFINITY -
960 N_RESERVED_FDS fail. So just use a relatively conservative
961 value in this case. */
962 if (rl.rlim_cur > 1024)
963 rl.rlim_cur = 1024;
964# endif
965
nethercote71980f02004-01-24 18:18:54 +0000966 /* Work out where to move the soft limit to. */
njn14319cc2005-03-13 06:26:22 +0000967 if (rl.rlim_cur + N_RESERVED_FDS <= rl.rlim_max) {
968 rl.rlim_cur = rl.rlim_cur + N_RESERVED_FDS;
nethercote71980f02004-01-24 18:18:54 +0000969 } else {
970 rl.rlim_cur = rl.rlim_max;
971 }
972
973 /* Reserve some file descriptors for our use. */
njn14319cc2005-03-13 06:26:22 +0000974 VG_(fd_soft_limit) = rl.rlim_cur - N_RESERVED_FDS;
975 VG_(fd_hard_limit) = rl.rlim_cur - N_RESERVED_FDS;
nethercote71980f02004-01-24 18:18:54 +0000976
977 /* Update the soft limit. */
978 VG_(setrlimit)(VKI_RLIMIT_NOFILE, &rl);
979
sewardj17c11042006-10-15 01:26:40 +0000980 if (show) {
981 VG_(printf)("fd limits: host, after: cur %u max %u\n",
982 rl.rlim_cur, rl.rlim_max);
983 VG_(printf)("fd limits: guest : cur %u max %u\n",
984 VG_(fd_soft_limit), VG_(fd_hard_limit));
985 }
986
sewardj45f4e7c2005-09-27 19:20:21 +0000987 if (VG_(cl_exec_fd) != -1)
988 VG_(cl_exec_fd) = VG_(safe_fd)( VG_(cl_exec_fd) );
nethercote71980f02004-01-24 18:18:54 +0000989}
990
sewardjde4a1d02002-03-22 01:27:54 +0000991
njn2da73352005-06-18 01:35:16 +0000992/*====================================================================*/
njn2025cf92005-06-26 20:44:48 +0000993/*=== BB profiling ===*/
994/*====================================================================*/
995
996static
997void show_BB_profile ( BBProfEntry tops[], UInt n_tops, ULong score_total )
998{
999 ULong score_cumul, score_here;
1000 Char buf_cumul[10], buf_here[10];
1001 Char name[64];
1002 Int r;
1003
1004 VG_(printf)("\n");
1005 VG_(printf)("-----------------------------------------------------------\n");
1006 VG_(printf)("--- BEGIN BB Profile (summary of scores) ---\n");
1007 VG_(printf)("-----------------------------------------------------------\n");
1008 VG_(printf)("\n");
1009
1010 VG_(printf)("Total score = %lld\n\n", score_total);
1011
1012 score_cumul = 0;
1013 for (r = 0; r < n_tops; r++) {
1014 if (tops[r].addr == 0)
1015 continue;
1016 name[0] = 0;
1017 VG_(get_fnname_w_offset)(tops[r].addr, name, 64);
1018 name[63] = 0;
1019 score_here = tops[r].score;
1020 score_cumul += score_here;
1021 VG_(percentify)(score_cumul, score_total, 2, 6, buf_cumul);
1022 VG_(percentify)(score_here, score_total, 2, 6, buf_here);
1023 VG_(printf)("%3d: (%9lld %s) %9lld %s 0x%llx %s\n",
1024 r,
1025 score_cumul, buf_cumul,
1026 score_here, buf_here, tops[r].addr, name );
1027 }
1028
1029 VG_(printf)("\n");
1030 VG_(printf)("-----------------------------------------------------------\n");
1031 VG_(printf)("--- BB Profile (BB details) ---\n");
1032 VG_(printf)("-----------------------------------------------------------\n");
1033 VG_(printf)("\n");
1034
1035 score_cumul = 0;
1036 for (r = 0; r < n_tops; r++) {
1037 if (tops[r].addr == 0)
1038 continue;
1039 name[0] = 0;
1040 VG_(get_fnname_w_offset)(tops[r].addr, name, 64);
1041 name[63] = 0;
1042 score_here = tops[r].score;
1043 score_cumul += score_here;
1044 VG_(percentify)(score_cumul, score_total, 2, 6, buf_cumul);
1045 VG_(percentify)(score_here, score_total, 2, 6, buf_here);
1046 VG_(printf)("\n");
1047 VG_(printf)("=-=-=-=-=-=-=-=-=-=-=-=-=-= begin BB rank %d "
1048 "=-=-=-=-=-=-=-=-=-=-=-=-=-=\n\n", r);
1049 VG_(printf)("%3d: (%9lld %s) %9lld %s 0x%llx %s\n",
1050 r,
1051 score_cumul, buf_cumul,
1052 score_here, buf_here, tops[r].addr, name );
1053 VG_(printf)("\n");
sewardj0ec07f32006-01-12 12:32:32 +00001054 VG_(translate)(0, tops[r].addr, True, VG_(clo_profile_flags), 0, True);
njn2025cf92005-06-26 20:44:48 +00001055 VG_(printf)("=-=-=-=-=-=-=-=-=-=-=-=-=-= end BB rank %d "
1056 "=-=-=-=-=-=-=-=-=-=-=-=-=-=\n\n", r);
1057 }
1058
1059 VG_(printf)("\n");
1060 VG_(printf)("-----------------------------------------------------------\n");
1061 VG_(printf)("--- END BB Profile ---\n");
1062 VG_(printf)("-----------------------------------------------------------\n");
1063 VG_(printf)("\n");
1064}
1065
1066
1067/*====================================================================*/
nethercote71980f02004-01-24 18:18:54 +00001068/*=== main() ===*/
1069/*====================================================================*/
1070
sewardjfdf91b42005-09-28 00:53:09 +00001071/* When main() is entered, we should be on the following stack, not
1072 the one the kernel gave us. We will run on this stack until
1073 simulation of the root thread is started, at which point a transfer
1074 is made to a dynamically allocated stack. This is for the sake of
1075 uniform overflow detection for all Valgrind threads. This is
1076 marked global even though it isn't, because assembly code below
1077 needs to reference the name. */
1078
1079/*static*/ VgStack VG_(interim_stack);
1080
sewardjf9d2f9b2006-11-17 20:00:57 +00001081/* These are the structures used to hold info for creating the initial
1082 client image.
1083
1084 'iicii' mostly holds important register state present at system
1085 startup (_start_valgrind). valgrind_main() then fills in the rest
1086 of it and passes it to VG_(ii_create_image)(). That produces
1087 'iifii', which is later handed to VG_(ii_finalise_image). */
1088
1089/* In all OS-instantiations, the_iicii has a field .sp_at_startup.
1090 This should get some address inside the stack on which we gained
sewardjfdf91b42005-09-28 00:53:09 +00001091 control (eg, it could be the SP at startup). It doesn't matter
1092 exactly where in the stack it is. This value is passed to the
sewardjf9d2f9b2006-11-17 20:00:57 +00001093 address space manager at startup. On Linux, aspacem then uses it
1094 to identify the initial stack segment and hence the upper end of
1095 the usable address space. */
sewardjfdf91b42005-09-28 00:53:09 +00001096
sewardjf9d2f9b2006-11-17 20:00:57 +00001097static IICreateImageInfo the_iicii;
1098static IIFinaliseImageInfo the_iifii;
1099
sewardjfdf91b42005-09-28 00:53:09 +00001100
sewardj1ae3f3a2005-09-28 10:47:38 +00001101/* --- Forwards decls to do with shutdown --- */
1102
1103static void final_tidyup(ThreadId tid);
1104
1105/* Do everything which needs doing when the last thread exits */
1106static
1107void shutdown_actions_NORETURN( ThreadId tid,
1108 VgSchedReturnCode tids_schedretcode );
1109
1110/* --- end of Forwards decls to do with shutdown --- */
sewardjfdf91b42005-09-28 00:53:09 +00001111
1112
sewardj45f4e7c2005-09-27 19:20:21 +00001113/* TODO: GIVE THIS A PROPER HOME
njn1d0825f2006-03-27 11:37:07 +00001114 TODO: MERGE THIS WITH DUPLICATE IN mc_leakcheck.c and coredump-elf.c.
sewardj45f4e7c2005-09-27 19:20:21 +00001115 Extract from aspacem a vector of the current segment start
1116 addresses. The vector is dynamically allocated and should be freed
1117 by the caller when done. REQUIRES m_mallocfree to be running.
1118 Writes the number of addresses required into *n_acquired. */
nethercotec314eba2004-07-15 12:59:41 +00001119
sewardj45f4e7c2005-09-27 19:20:21 +00001120static Addr* get_seg_starts ( /*OUT*/Int* n_acquired )
sewardj1cf558c2005-04-25 01:36:56 +00001121{
sewardj45f4e7c2005-09-27 19:20:21 +00001122 Addr* starts;
sewardja48a4932005-09-29 11:09:56 +00001123 Int n_starts, r = 0;
sewardj45f4e7c2005-09-27 19:20:21 +00001124
1125 n_starts = 1;
sewardj1cf558c2005-04-25 01:36:56 +00001126 while (True) {
sewardj45f4e7c2005-09-27 19:20:21 +00001127 starts = VG_(malloc)( n_starts * sizeof(Addr) );
1128 if (starts == NULL)
1129 break;
1130 r = VG_(am_get_segment_starts)( starts, n_starts );
1131 if (r >= 0)
1132 break;
1133 VG_(free)(starts);
1134 n_starts *= 2;
sewardj1cf558c2005-04-25 01:36:56 +00001135 }
sewardj45f4e7c2005-09-27 19:20:21 +00001136
1137 if (starts == NULL) {
1138 *n_acquired = 0;
1139 return NULL;
1140 }
1141
1142 *n_acquired = r;
1143 return starts;
sewardj1cf558c2005-04-25 01:36:56 +00001144}
1145
1146
sewardjf9d2f9b2006-11-17 20:00:57 +00001147/* By the time we get to valgrind_main, the_iicii should already have
1148 been filled in with any important details as required by whatever
1149 OS we have been built for.
1150*/
sewardj17c11042006-10-15 01:26:40 +00001151static
sewardjf9d2f9b2006-11-17 20:00:57 +00001152Int valgrind_main ( Int argc, HChar **argv, HChar **envp )
nethercote71980f02004-01-24 18:18:54 +00001153{
sewardj13247ca2005-12-30 22:52:20 +00001154 HChar* toolname = "memcheck"; // default to Memcheck
sewardj13247ca2005-12-30 22:52:20 +00001155 Int need_help = 0; // 0 = no, 1 = --help, 2 = --help-debug
sewardj4c3faae2006-03-15 11:50:32 +00001156 UInt* client_auxv = NULL;
sewardj45f4e7c2005-09-27 19:20:21 +00001157 Int loglevel, i;
1158 Bool logging_to_fd;
nethercote73b526f2004-10-31 18:48:21 +00001159 struct vki_rlimit zero = { 0, 0 };
sewardj17c11042006-10-15 01:26:40 +00001160
nethercote71980f02004-01-24 18:18:54 +00001161 //============================================================
nethercote71980f02004-01-24 18:18:54 +00001162 //
sewardj45f4e7c2005-09-27 19:20:21 +00001163 // Nb: startup is complex. Prerequisites are shown at every step.
nethercote71980f02004-01-24 18:18:54 +00001164 // *** Be very careful when messing with the order ***
sewardj45f4e7c2005-09-27 19:20:21 +00001165 //
1166 // The first order of business is to get debug logging, the address
1167 // space manager and the dynamic memory manager up and running.
1168 // Once that's done, we can relax a bit.
1169 //
nethercote71980f02004-01-24 18:18:54 +00001170 //============================================================
sewardj45f4e7c2005-09-27 19:20:21 +00001171
1172 /* This is needed to make VG_(getenv) usable early. */
1173 VG_(client_envp) = (Char**)envp;
nethercote71980f02004-01-24 18:18:54 +00001174
sewardj1cf558c2005-04-25 01:36:56 +00001175 //--------------------------------------------------------------
1176 // Start up the logging mechanism
1177 // p: none
1178 //--------------------------------------------------------------
1179 /* Start the debugging-log system ASAP. First find out how many
1180 "-d"s were specified. This is a pre-scan of the command line. */
1181 loglevel = 0;
1182 for (i = 1; i < argc; i++) {
sewardj10759312005-05-30 23:52:47 +00001183 if (argv[i][0] != '-')
1184 break;
sewardj45f4e7c2005-09-27 19:20:21 +00001185 if (VG_STREQ(argv[i], "--"))
sewardj10759312005-05-30 23:52:47 +00001186 break;
sewardj45f4e7c2005-09-27 19:20:21 +00001187 if (VG_STREQ(argv[i], "-d"))
sewardj10759312005-05-30 23:52:47 +00001188 loglevel++;
sewardj1cf558c2005-04-25 01:36:56 +00001189 }
1190
1191 /* ... and start the debug logger. Now we can safely emit logging
1192 messages all through startup. */
sewardj10759312005-05-30 23:52:47 +00001193 VG_(debugLog_startup)(loglevel, "Stage 2 (main)");
sewardj45f4e7c2005-09-27 19:20:21 +00001194 VG_(debugLog)(1, "main", "Welcome to Valgrind version "
1195 VERSION " debug logging\n");
1196
1197 //--------------------------------------------------------------
sewardj17c11042006-10-15 01:26:40 +00001198 // AIX5 only: register the system call numbers
1199 // p: logging
1200 // p: that the initial few syscall numbers stated in the
1201 // bootblock have been installed (else we can't
1202 // open/read/close).
1203 //--------------------------------------------------------------
1204# if defined(VGO_aix5)
1205 VG_(debugLog)(1, "main", "aix5: registering syscalls ..\n");
1206 { UChar sysent_name[50];
1207 SysRes fd;
1208 Bool ok;
1209 Int n_unregd, sysent_used = 0;
1210 prsysent_t* sysent_hdr;
1211
1212 VG_(sprintf)(sysent_name, "/proc/%d/sysent", VG_(getpid)());
1213 fd = VG_(open)(sysent_name, VKI_O_RDONLY, 0);
1214 if (fd.isError)
1215 VG_(err_config_error)("aix5: can't open /proc/<pid>/sysent");
1216
1217 sysent_used = VG_(read)(fd.res, aix5_sysent_buf, VG_AIX5_SYSENT_SIZE);
1218 if (sysent_used < 0)
1219 VG_(err_config_error)("aix5: error reading /proc/<pid>/sysent");
1220 if (sysent_used >= VG_AIX5_SYSENT_SIZE)
1221 VG_(err_config_error)("aix5: VG_AIX5_SYSENT_SIZE is too low; "
1222 "increase and recompile");
1223 VG_(close)(fd.res);
1224
1225 vg_assert(sysent_used > 0 && sysent_used < VG_AIX5_SYSENT_SIZE);
1226
1227 sysent_hdr = (prsysent_t*)&aix5_sysent_buf[0];
1228
1229 n_unregd = 0;
1230 for (i = 0; i < sysent_hdr->pr_nsyscalls; i++) {
1231 UChar* name = &aix5_sysent_buf[ sysent_hdr
1232 ->pr_syscall[i].pr_nameoff ];
1233 UInt nmbr = sysent_hdr->pr_syscall[i].pr_number;
1234 VG_(debugLog)(3, "main", "aix5: bind syscall %d to \"%s\"\n",
1235 nmbr, name);
1236 ok = VG_(aix5_register_syscall)(nmbr, name);
1237 if (!ok)
1238 n_unregd++;
1239 if (!ok)
1240 VG_(debugLog)(3, "main",
1241 "aix5: bind FAILED: %d to \"%s\"\n",
1242 nmbr, name);
1243 }
1244 VG_(debugLog)(1, "main", "aix5: .. %d syscalls known, %d unknown\n",
1245 sysent_hdr->pr_nsyscalls - n_unregd, n_unregd );
1246 VG_(debugLog)(1, "main", "aix5: __NR_AIX5_FAKE_SIGRETURN = %d\n",
1247 __NR_AIX5_FAKE_SIGRETURN );
1248 }
1249# endif
1250
1251 //--------------------------------------------------------------
sewardj45f4e7c2005-09-27 19:20:21 +00001252 // Ensure we're on a plausible stack.
1253 // p: logging
1254 //--------------------------------------------------------------
1255 VG_(debugLog)(1, "main", "Checking current stack is plausible\n");
sewardjfdf91b42005-09-28 00:53:09 +00001256 { HChar* limLo = (HChar*)(&VG_(interim_stack).bytes[0]);
1257 HChar* limHi = limLo + sizeof(VG_(interim_stack));
sewardj45f4e7c2005-09-27 19:20:21 +00001258 HChar* aLocal = (HChar*)&zero; /* any auto local will do */
1259 if (aLocal < limLo || aLocal >= limHi) {
1260 /* something's wrong. Stop. */
1261 VG_(debugLog)(0, "main", "Root stack %p to %p, a local %p\n",
1262 limLo, limHi, aLocal );
1263 VG_(debugLog)(0, "main", "Valgrind: FATAL: "
1264 "Initial stack switched failed.\n");
1265 VG_(debugLog)(0, "main", " Cannot continue. Sorry.\n");
1266 VG_(exit)(1);
1267 }
1268 }
1269
1270 //--------------------------------------------------------------
1271 // Ensure we have a plausible pointer to the stack on which
1272 // we gained control (not the current stack!)
1273 // p: logging
1274 //--------------------------------------------------------------
1275 VG_(debugLog)(1, "main", "Checking initial stack was noted\n");
sewardjf9d2f9b2006-11-17 20:00:57 +00001276 if (the_iicii.sp_at_startup == 0) {
sewardj45f4e7c2005-09-27 19:20:21 +00001277 VG_(debugLog)(0, "main", "Valgrind: FATAL: "
1278 "Initial stack was not noted.\n");
1279 VG_(debugLog)(0, "main", " Cannot continue. Sorry.\n");
1280 VG_(exit)(1);
1281 }
1282
1283 //--------------------------------------------------------------
1284 // Start up the address space manager, and determine the
1285 // approximate location of the client's stack
1286 // p: logging, plausible-stack
1287 //--------------------------------------------------------------
1288 VG_(debugLog)(1, "main", "Starting the address space manager\n");
sewardje66f2e02006-12-30 17:45:08 +00001289 vg_assert(VKI_PAGE_SIZE == 4096 || VKI_PAGE_SIZE == 65536);
1290 vg_assert(VKI_MAX_PAGE_SIZE == 4096 || VKI_MAX_PAGE_SIZE == 65536);
1291 vg_assert(VKI_PAGE_SIZE <= VKI_MAX_PAGE_SIZE);
1292 vg_assert(VKI_PAGE_SIZE == (1 << VKI_PAGE_SHIFT));
1293 vg_assert(VKI_MAX_PAGE_SIZE == (1 << VKI_MAX_PAGE_SHIFT));
sewardjf9d2f9b2006-11-17 20:00:57 +00001294 the_iicii.clstack_top = VG_(am_startup)( the_iicii.sp_at_startup );
sewardj45f4e7c2005-09-27 19:20:21 +00001295 VG_(debugLog)(1, "main", "Address space manager is running\n");
1296
1297 //--------------------------------------------------------------
1298 // Start up the dynamic memory manager
1299 // p: address space management
1300 // In fact m_mallocfree is self-initialising, so there's no
1301 // initialisation call to do. Instead, try a simple malloc/
1302 // free pair right now to check that nothing is broken.
1303 //--------------------------------------------------------------
1304 VG_(debugLog)(1, "main", "Starting the dynamic memory manager\n");
1305 { void* p = VG_(malloc)( 12345 );
1306 if (p) VG_(free)( p );
1307 }
1308 VG_(debugLog)(1, "main", "Dynamic memory manager is running\n");
sewardj1cf558c2005-04-25 01:36:56 +00001309
nethercotef4928da2004-06-15 10:54:40 +00001310 //============================================================
sewardj45f4e7c2005-09-27 19:20:21 +00001311 //
1312 // Dynamic memory management is now available.
1313 //
nethercotef4928da2004-06-15 10:54:40 +00001314 //============================================================
1315
sewardj45f4e7c2005-09-27 19:20:21 +00001316 //--------------------------------------------------------------
1317 // Look for alternative libdir
1318 { HChar *cp = VG_(getenv)(VALGRIND_LIB);
1319 if (cp != NULL)
1320 VG_(libdir) = cp;
1321 }
1322
1323 //--------------------------------------------------------------
1324 // Extract the launcher name from the environment.
1325 VG_(debugLog)(1, "main", "Getting stage1's name\n");
1326 VG_(name_of_launcher) = VG_(getenv)(VALGRIND_LAUNCHER);
1327 if (VG_(name_of_launcher) == NULL) {
1328 VG_(printf)("valgrind: You cannot run '%s' directly.\n", argv[0]);
1329 VG_(printf)("valgrind: You should use $prefix/bin/valgrind.\n");
1330 VG_(exit)(1);
1331 }
1332
1333 //--------------------------------------------------------------
fitzhardingeb50068f2004-02-24 23:42:55 +00001334 // Get the current process datasize rlimit, and set it to zero.
1335 // This prevents any internal uses of brk() from having any effect.
1336 // We remember the old value so we can restore it on exec, so that
1337 // child processes will have a reasonable brk value.
1338 VG_(getrlimit)(VKI_RLIMIT_DATA, &VG_(client_rlimit_data));
1339 zero.rlim_max = VG_(client_rlimit_data).rlim_max;
1340 VG_(setrlimit)(VKI_RLIMIT_DATA, &zero);
thughesc37184f2004-09-11 14:16:57 +00001341
1342 // Get the current process stack rlimit.
1343 VG_(getrlimit)(VKI_RLIMIT_STACK, &VG_(client_rlimit_stack));
1344
sewardje2d1e672005-11-12 23:10:48 +00001345 //--------------------------------------------------------------
1346 // Figure out what sort of CPU we're on, and whether it is
1347 // able to run V.
1348 VG_(debugLog)(1, "main", "Get hardware capabilities ...\n");
1349 { VexArch vex_arch;
1350 VexArchInfo vex_archinfo;
1351 Bool ok = VG_(machine_get_hwcaps)();
1352 if (!ok) {
1353 VG_(printf)("\n");
1354 VG_(printf)("valgrind: fatal error: unsupported CPU.\n");
1355 VG_(printf)(" Supported CPUs are:\n");
1356 VG_(printf)(" * x86 (practically any; Pentium-I or above), "
1357 "AMD Athlon or above)\n");
1358 VG_(printf)(" * AMD Athlon64/Opteron\n");
1359 VG_(printf)(" * PowerPC (most; ppc405 and above)\n");
1360 VG_(printf)("\n");
1361 VG_(exit)(1);
1362 }
1363 VG_(machine_get_VexArchInfo)( &vex_arch, &vex_archinfo );
sewardje3121f32006-01-27 21:23:23 +00001364 VG_(debugLog)(
1365 1, "main", "... arch = %s, hwcaps = %s\n",
1366 LibVEX_ppVexArch ( vex_arch ),
1367 LibVEX_ppVexHwCaps ( vex_arch, vex_archinfo.hwcaps )
1368 );
sewardje2d1e672005-11-12 23:10:48 +00001369 }
1370
sewardj45f4e7c2005-09-27 19:20:21 +00001371 //============================================================
1372 // Command line argument handling order:
1373 // * If --help/--help-debug are present, show usage message
1374 // (including the tool-specific usage)
1375 // * (If no --tool option given, default to Memcheck)
1376 // * Then, if client is missing, abort with error msg
1377 // * Then, if any cmdline args are bad, abort with error msg
1378 //============================================================
1379
1380 //--------------------------------------------------------------
1381 // Split up argv into: C args, V args, V extra args, and exename.
1382 // p: dynamic memory allocation
1383 //--------------------------------------------------------------
1384 VG_(debugLog)(1, "main", "Split up command line\n");
1385 VG_(split_up_argv)( argc, argv );
sewardj14c7cc52007-02-25 15:08:24 +00001386 vg_assert( VG_(args_for_valgrind) );
1387 vg_assert( VG_(args_for_client) );
sewardj45f4e7c2005-09-27 19:20:21 +00001388 if (0) {
sewardj14c7cc52007-02-25 15:08:24 +00001389 for (i = 0; i < VG_(sizeXA)( VG_(args_for_valgrind) ); i++)
1390 VG_(printf)(
1391 "varg %s\n",
1392 * (HChar**) VG_(indexXA)( VG_(args_for_valgrind), i )
1393 );
sewardj45f4e7c2005-09-27 19:20:21 +00001394 VG_(printf)(" exe %s\n", VG_(args_the_exename));
sewardj14c7cc52007-02-25 15:08:24 +00001395 for (i = 0; i < VG_(sizeXA)( VG_(args_for_client) ); i++)
1396 VG_(printf)(
1397 "carg %s\n",
1398 * (HChar**) VG_(indexXA)( VG_(args_for_client), i )
1399 );
nethercote71980f02004-01-24 18:18:54 +00001400 }
1401
1402 //--------------------------------------------------------------
sewardj45f4e7c2005-09-27 19:20:21 +00001403 // Extract tool name and whether help has been requested.
1404 // Note we can't print the help message yet, even if requested,
1405 // because the tool has not been initialised.
1406 // p: split_up_argv [for VG_(args_for_valgrind)]
nethercote71980f02004-01-24 18:18:54 +00001407 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00001408 VG_(debugLog)(1, "main", "Preprocess command line opts\n");
sewardj45f4e7c2005-09-27 19:20:21 +00001409 get_helprequest_and_toolname(&need_help, &toolname);
nethercote71980f02004-01-24 18:18:54 +00001410
sewardj45f4e7c2005-09-27 19:20:21 +00001411 // Set default vex control params
1412 LibVEX_default_VexControl(& VG_(clo_vex_control));
nethercote71980f02004-01-24 18:18:54 +00001413
1414 //--------------------------------------------------------------
1415 // Load client executable, finding in $PATH if necessary
sewardj45f4e7c2005-09-27 19:20:21 +00001416 // p: get_helprequest_and_toolname() [for 'exec', 'need_help']
nethercote71980f02004-01-24 18:18:54 +00001417 // p: layout_remaining_space [so there's space]
sewardj17c11042006-10-15 01:26:40 +00001418 //
nethercote71980f02004-01-24 18:18:54 +00001419 // Set up client's environment
sewardj45f4e7c2005-09-27 19:20:21 +00001420 // p: set-libdir [for VG_(libdir)]
1421 // p: get_helprequest_and_toolname [for toolname]
sewardj17c11042006-10-15 01:26:40 +00001422 //
nethercote5ee67ca2004-06-22 14:00:09 +00001423 // Setup client stack, eip, and VG_(client_arg[cv])
nethercote71980f02004-01-24 18:18:54 +00001424 // p: load_client() [for 'info']
1425 // p: fix_environment() [for 'env']
sewardj17c11042006-10-15 01:26:40 +00001426 //
sewardj45f4e7c2005-09-27 19:20:21 +00001427 // Setup client data (brk) segment. Initially a 1-page segment
1428 // which abuts a shrinkable reservation.
1429 // p: load_client() [for 'info' and hence VG_(brk_base)]
sewardjf9d2f9b2006-11-17 20:00:57 +00001430 //
1431 // p: _start_in_C (for zeroing out the_iicii and putting some
1432 // initial values into it)
sewardj45f4e7c2005-09-27 19:20:21 +00001433 //--------------------------------------------------------------
sewardj17c11042006-10-15 01:26:40 +00001434 if (!need_help) {
sewardjf9d2f9b2006-11-17 20:00:57 +00001435 VG_(debugLog)(1, "main", "Create initial image\n");
1436
1437# if defined(VGO_linux)
1438 the_iicii.argv = argv;
1439 the_iicii.envp = envp;
1440 the_iicii.toolname = toolname;
1441# elif defined(VGO_aix5)
1442 /* the_iicii.intregs37 already set up */
1443 /* the_iicii.bootblock already set up */
1444 /* the_iicii.adler32_exp already set up */
1445 /* the_iicii.sp_at_startup is irrelevant */
1446 /* the_iicii.clstack_top is irrelevant */
1447 the_iicii.toolname = toolname;
1448# else
1449# error "Uknown platform"
1450# endif
1451
1452 the_iifii = VG_(ii_create_image)( the_iicii );
1453
sewardj17c11042006-10-15 01:26:40 +00001454# if defined(VGO_aix5)
sewardj17c11042006-10-15 01:26:40 +00001455 /* Tell aspacem where the initial client stack is, so that it
1456 can later produce a faked-up NSegment in response to
1457 VG_(am_find_nsegment) for that address range, if asked. */
sewardjf9d2f9b2006-11-17 20:00:57 +00001458 VG_(am_aix5_set_initial_client_sp)( the_iifii.initial_client_SP );
1459 /* Now have a look at said fake segment, so we can find out
1460 the size of it. */
1461 { SizeT sz;
1462 NSegment const* seg
1463 = VG_(am_find_nsegment)( the_iifii.initial_client_SP );
1464 vg_assert(seg);
1465 sz = seg->end - seg->start + 1;
1466 vg_assert(sz >= 0 && sz <= 64*1024*1024); /* stay sane */
1467 the_iifii.clstack_max_size = sz;
1468 }
sewardj17c11042006-10-15 01:26:40 +00001469# endif
sewardj45f4e7c2005-09-27 19:20:21 +00001470 }
nethercote71980f02004-01-24 18:18:54 +00001471
1472 //==============================================================
sewardj45f4e7c2005-09-27 19:20:21 +00001473 //
1474 // Finished loading/setting up the client address space.
1475 //
nethercote71980f02004-01-24 18:18:54 +00001476 //==============================================================
1477
1478 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00001479 // setup file descriptors
1480 // p: n/a
1481 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00001482 VG_(debugLog)(1, "main", "Setup file descriptors\n");
nethercote71980f02004-01-24 18:18:54 +00001483 setup_file_descriptors();
1484
1485 //--------------------------------------------------------------
sewardj45f4e7c2005-09-27 19:20:21 +00001486 // create the fake /proc/<pid>/cmdline file and then unlink it,
1487 // but hold onto the fd, so we can hand it out to the client
1488 // when it tries to open /proc/<pid>/cmdline for itself.
1489 // p: setup file descriptors
nethercotec314eba2004-07-15 12:59:41 +00001490 //--------------------------------------------------------------
sewardj45f4e7c2005-09-27 19:20:21 +00001491 if (!need_help) {
1492 HChar buf[50], buf2[50+64];
1493 HChar nul[1];
1494 Int fd, r;
1495 HChar* exename;
nethercotec314eba2004-07-15 12:59:41 +00001496
sewardj45f4e7c2005-09-27 19:20:21 +00001497 VG_(debugLog)(1, "main", "Create fake /proc/<pid>/cmdline\n");
1498
1499 VG_(sprintf)(buf, "proc_%d_cmdline", VG_(getpid)());
1500 fd = VG_(mkstemp)( buf, buf2 );
1501 if (fd == -1)
sewardj17c11042006-10-15 01:26:40 +00001502 VG_(err_config_error)("Can't create client cmdline file in /tmp.");
sewardj45f4e7c2005-09-27 19:20:21 +00001503
1504 nul[0] = 0;
1505 exename = VG_(args_the_exename) ? VG_(args_the_exename)
1506 : "unknown_exename";
sewardj45f4e7c2005-09-27 19:20:21 +00001507 VG_(write)(fd, VG_(args_the_exename),
1508 VG_(strlen)( VG_(args_the_exename) ));
1509 VG_(write)(fd, nul, 1);
1510
sewardj14c7cc52007-02-25 15:08:24 +00001511 for (i = 0; i < VG_(sizeXA)( VG_(args_for_client) ); i++) {
1512 HChar* arg = * (HChar**) VG_(indexXA)( VG_(args_for_client), i );
1513 VG_(write)(fd, arg, VG_(strlen)( arg ));
sewardj45f4e7c2005-09-27 19:20:21 +00001514 VG_(write)(fd, nul, 1);
1515 }
1516
1517 /* Don't bother to seek the file back to the start; instead do
1518 it every time a copy of it is given out (by PRE(sys_open)).
1519 That is probably more robust across fork() etc. */
1520
1521 /* Now delete it, but hang on to the fd. */
1522 r = VG_(unlink)( buf2 );
1523 if (r)
sewardj17c11042006-10-15 01:26:40 +00001524 VG_(err_config_error)("Can't delete client cmdline file in /tmp.");
sewardj45f4e7c2005-09-27 19:20:21 +00001525
1526 VG_(cl_cmdline_fd) = fd;
1527 }
nethercotec314eba2004-07-15 12:59:41 +00001528
1529 //--------------------------------------------------------------
sewardj45f4e7c2005-09-27 19:20:21 +00001530 // Init tool part 1: pre_clo_init
nethercotec314eba2004-07-15 12:59:41 +00001531 // p: setup_client_stack() [for 'VG_(client_arg[cv]']
nethercotec314eba2004-07-15 12:59:41 +00001532 // p: setup_file_descriptors() [for 'VG_(fd_xxx_limit)']
nethercote71980f02004-01-24 18:18:54 +00001533 //--------------------------------------------------------------
njn64c83242005-06-21 01:54:38 +00001534 {
1535 Char* s;
1536 Bool ok;
sewardj45f4e7c2005-09-27 19:20:21 +00001537 VG_(debugLog)(1, "main", "Initialise the tool part 1 (pre_clo_init)\n");
1538 (VG_(tool_info).tl_pre_clo_init)();
1539 ok = VG_(sanity_check_needs)( &s );
njn64c83242005-06-21 01:54:38 +00001540 if (!ok) {
1541 VG_(tool_panic)(s);
1542 }
1543 }
nethercote71980f02004-01-24 18:18:54 +00001544
sewardj45f4e7c2005-09-27 19:20:21 +00001545 //--------------------------------------------------------------
nethercotef4928da2004-06-15 10:54:40 +00001546 // If --tool and --help/--help-debug was given, now give the core+tool
1547 // help message
sewardj45f4e7c2005-09-27 19:20:21 +00001548 // p: get_helprequest_and_toolname() [for 'need_help']
1549 // p: tl_pre_clo_init [for 'VG_(tdict).usage']
1550 //--------------------------------------------------------------
1551 VG_(debugLog)(1, "main", "Print help and quit, if requested\n");
nethercotef4928da2004-06-15 10:54:40 +00001552 if (need_help) {
sewardj45f4e7c2005-09-27 19:20:21 +00001553 usage_NORETURN(/*--help-debug?*/2 == need_help);
nethercotef4928da2004-06-15 10:54:40 +00001554 }
nethercotec314eba2004-07-15 12:59:41 +00001555
sewardj45f4e7c2005-09-27 19:20:21 +00001556 //--------------------------------------------------------------
1557 // Process command line options to Valgrind + tool
1558 // p: setup_client_stack() [for 'VG_(client_arg[cv]']
1559 // p: setup_file_descriptors() [for 'VG_(fd_xxx_limit)']
1560 //--------------------------------------------------------------
1561 VG_(debugLog)(1, "main", "Process Valgrind's command line options, "
sewardja48a4932005-09-29 11:09:56 +00001562 "setup logging\n");
sewardj45f4e7c2005-09-27 19:20:21 +00001563 logging_to_fd = process_cmd_line_options(client_auxv, toolname);
1564
1565 //--------------------------------------------------------------
sewardj592ae092005-11-08 19:01:44 +00001566 // Zeroise the millisecond counter by doing a first read of it.
1567 // p: none
1568 //--------------------------------------------------------------
1569 (void) VG_(read_millisecond_timer)();
1570
1571 //--------------------------------------------------------------
sewardj45f4e7c2005-09-27 19:20:21 +00001572 // Print the preamble
1573 // p: tl_pre_clo_init [for 'VG_(details).name' and friends]
1574 // p: process_cmd_line_options() [for VG_(clo_verbosity), VG_(clo_xml),
1575 // VG_(clo_log_file_qualifier),
1576 // logging_to_fd]
1577 //--------------------------------------------------------------
1578 VG_(debugLog)(1, "main", "Print the preamble...\n");
1579 print_preamble(logging_to_fd, toolname);
1580 VG_(debugLog)(1, "main", "...finished the preamble\n");
1581
1582 //--------------------------------------------------------------
1583 // Init tool part 2: post_clo_init
1584 // p: setup_client_stack() [for 'VG_(client_arg[cv]']
1585 // p: setup_file_descriptors() [for 'VG_(fd_xxx_limit)']
1586 // p: print_preamble() [so any warnings printed in post_clo_init
1587 // are shown after the preamble]
1588 //--------------------------------------------------------------
1589 VG_(debugLog)(1, "main", "Initialise the tool part 2 (post_clo_init)\n");
njn51d827b2005-05-09 01:02:08 +00001590 VG_TDICT_CALL(tool_post_clo_init);
nethercotef4928da2004-06-15 10:54:40 +00001591
1592 //--------------------------------------------------------------
sewardj45f4e7c2005-09-27 19:20:21 +00001593 // Initialise translation table and translation cache
1594 // p: aspacem [??]
1595 // p: tl_pre_clo_init [for 'VG_(details).avg_translation_sizeB']
nethercote71980f02004-01-24 18:18:54 +00001596 //--------------------------------------------------------------
sewardj45f4e7c2005-09-27 19:20:21 +00001597 VG_(debugLog)(1, "main", "Initialise TT/TC\n");
1598 VG_(init_tt_tc)();
sewardjb5f6f512005-03-10 23:59:00 +00001599
sewardj45f4e7c2005-09-27 19:20:21 +00001600 //--------------------------------------------------------------
1601 // Initialise the redirect table.
1602 // p: init_tt_tc [so it can call VG_(search_transtab) safely]
1603 // p: aspacem [so can change ownership of sysinfo pages]
1604 //--------------------------------------------------------------
1605 VG_(debugLog)(1, "main", "Initialise redirects\n");
sewardj0ec07f32006-01-12 12:32:32 +00001606 VG_(redir_initialise)();
nethercote71980f02004-01-24 18:18:54 +00001607
1608 //--------------------------------------------------------------
1609 // Allow GDB attach
1610 // p: process_cmd_line_options() [for VG_(clo_wait_for_gdb)]
1611 //--------------------------------------------------------------
1612 /* Hook to delay things long enough so we can get the pid and
1613 attach GDB in another shell. */
1614 if (VG_(clo_wait_for_gdb)) {
sewardj95611ff2007-02-16 13:57:07 +00001615 Long iters;
1616 volatile Long q;
sewardj1fbc1a52005-04-25 02:05:54 +00001617 VG_(debugLog)(1, "main", "Wait for GDB\n");
sewardj93ab8572005-02-06 14:10:40 +00001618 VG_(printf)("pid=%d, entering delay loop\n", VG_(getpid)());
sewardj8211a572005-06-23 21:37:47 +00001619
1620# if defined(VGP_x86_linux)
1621 iters = 5;
sewardj2c48c7b2005-11-29 13:05:56 +00001622# elif defined(VGP_amd64_linux) || defined(VGP_ppc64_linux)
sewardj8211a572005-06-23 21:37:47 +00001623 iters = 10;
1624# elif defined(VGP_ppc32_linux)
sewardjd714d2e2005-07-08 18:24:04 +00001625 iters = 5;
sewardj17c11042006-10-15 01:26:40 +00001626# elif defined(VGP_ppc32_aix5) || defined(VGP_ppc64_aix5)
1627 iters = 4;
sewardj8211a572005-06-23 21:37:47 +00001628# else
sewardj17c11042006-10-15 01:26:40 +00001629# error "Unknown plat"
sewardj8211a572005-06-23 21:37:47 +00001630# endif
1631
1632 iters *= 1000*1000*1000;
1633 for (q = 0; q < iters; q++)
1634 ;
nethercote71980f02004-01-24 18:18:54 +00001635 }
1636
sewardjb5d320c2005-03-13 18:57:15 +00001637 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00001638 // Search for file descriptors that are inherited from our parent
1639 // p: process_cmd_line_options [for VG_(clo_track_fds)]
1640 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00001641 if (VG_(clo_track_fds)) {
1642 VG_(debugLog)(1, "main", "Init preopened fds\n");
nethercote71980f02004-01-24 18:18:54 +00001643 VG_(init_preopened_fds)();
sewardj1fbc1a52005-04-25 02:05:54 +00001644 }
nethercote71980f02004-01-24 18:18:54 +00001645
1646 //--------------------------------------------------------------
sewardj45f4e7c2005-09-27 19:20:21 +00001647 // Load debug info for the existing segments.
1648 // p: setup_code_redirect_table [so that redirs can be recorded]
1649 // p: mallocfree
1650 // p: probably: setup fds and process CLOs, so that logging works
1651 //--------------------------------------------------------------
1652 VG_(debugLog)(1, "main", "Load initial debug info\n");
sewardj17c11042006-10-15 01:26:40 +00001653# if defined(VGO_linux)
sewardj45f4e7c2005-09-27 19:20:21 +00001654 { Addr* seg_starts;
1655 Int n_seg_starts;
1656
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
sewardjf72cced2005-11-08 00:45:47 +00001660 /* show them all to the debug info reader. allow_SkFileV has to
1661 be True here so that we read info from the valgrind executable
1662 itself. */
sewardj45f4e7c2005-09-27 19:20:21 +00001663 for (i = 0; i < n_seg_starts; i++)
sewardjf72cced2005-11-08 00:45:47 +00001664 VG_(di_notify_mmap)( seg_starts[i], True/*allow_SkFileV*/ );
sewardj45f4e7c2005-09-27 19:20:21 +00001665
1666 VG_(free)( seg_starts );
1667 }
sewardj17c11042006-10-15 01:26:40 +00001668# elif defined(VGO_aix5)
1669 { AixCodeSegChange* changes;
1670 Int changes_size, changes_used;
1671
1672 /* Find out how many AixCodeSegChange records we will need,
1673 and acquire them. */
1674 changes_size = VG_(am_aix5_reread_procmap_howmany_directives)();
1675 changes = VG_(malloc)(changes_size * sizeof(AixCodeSegChange));
1676 vg_assert(changes);
1677
1678 /* Now re-read /proc/<pid>/map and acquire a change set */
1679 VG_(am_aix5_reread_procmap)( changes, &changes_used );
1680 vg_assert(changes_used >= 0 && changes_used <= changes_size);
1681
1682 /* And notify m_debuginfo of the changes. */
1683 for (i = 0; i < changes_used; i++)
1684 VG_(di_aix5_notify_segchange)(
1685 changes[i].code_start,
1686 changes[i].code_len,
1687 changes[i].data_start,
1688 changes[i].data_len,
1689 changes[i].file_name,
1690 changes[i].mem_name,
1691 changes[i].is_mainexe,
1692 changes[i].acquire
1693 );
1694
1695 VG_(free)(changes);
1696 }
1697# else
1698# error Unknown OS
1699# endif
sewardj45f4e7c2005-09-27 19:20:21 +00001700
1701 //--------------------------------------------------------------
1702 // Tell aspacem of ownership change of the asm helpers, so that
1703 // m_translate allows them to be translated. However, only do this
1704 // after the initial debug info read, since making a hole in the
1705 // address range for the stage2 binary confuses the debug info reader.
1706 // p: aspacem
1707 //--------------------------------------------------------------
1708 { Bool change_ownership_v_c_OK;
sewardj1a85f4f2006-01-12 21:15:35 +00001709 Addr co_start = VG_PGROUNDDN( (Addr)&VG_(trampoline_stuff_start) );
1710 Addr co_endPlus = VG_PGROUNDUP( (Addr)&VG_(trampoline_stuff_end) );
sewardj45f4e7c2005-09-27 19:20:21 +00001711 VG_(debugLog)(1,"redir",
1712 "transfer ownership V -> C of 0x%llx .. 0x%llx\n",
1713 (ULong)co_start, (ULong)co_endPlus-1 );
1714
1715 change_ownership_v_c_OK
1716 = VG_(am_change_ownership_v_to_c)( co_start, co_endPlus - co_start );
1717 vg_assert(change_ownership_v_c_OK);
1718 }
1719
1720 //--------------------------------------------------------------
1721 // Tell the tool about the initial client memory permissions
1722 // p: aspacem
1723 // p: mallocfree
1724 // p: setup_client_stack
1725 // p: setup_client_dataseg
1726 //--------------------------------------------------------------
1727 VG_(debugLog)(1, "main", "Tell tool about initial permissions\n");
1728 { Addr* seg_starts;
1729 Int n_seg_starts;
sewardj45f4e7c2005-09-27 19:20:21 +00001730
1731 seg_starts = get_seg_starts( &n_seg_starts );
sewardj17c11042006-10-15 01:26:40 +00001732 vg_assert(seg_starts && n_seg_starts >= 0);
sewardj45f4e7c2005-09-27 19:20:21 +00001733
1734 /* show interesting ones to the tool */
1735 for (i = 0; i < n_seg_starts; i++) {
sewardj12ab7652006-10-17 02:10:42 +00001736 NSegment const* seg
sewardj17c11042006-10-15 01:26:40 +00001737 = VG_(am_find_nsegment)( seg_starts[i] );
sewardj45f4e7c2005-09-27 19:20:21 +00001738 vg_assert(seg);
1739 if (seg->kind == SkFileC || seg->kind == SkAnonC) {
1740 VG_(debugLog)(2, "main",
1741 "tell tool about %010lx-%010lx %c%c%c\n",
1742 seg->start, seg->end,
1743 seg->hasR ? 'r' : '-',
1744 seg->hasW ? 'w' : '-',
1745 seg->hasX ? 'x' : '-' );
1746 VG_TRACK( new_mem_startup, seg->start, seg->end+1-seg->start,
1747 seg->hasR, seg->hasW, seg->hasX );
1748 }
1749 }
1750
1751 VG_(free)( seg_starts );
1752
1753 /* Also do the initial stack permissions. */
sewardj12ab7652006-10-17 02:10:42 +00001754 { NSegment const* seg
sewardjf9d2f9b2006-11-17 20:00:57 +00001755 = VG_(am_find_nsegment)( the_iifii.initial_client_SP );
sewardj17c11042006-10-15 01:26:40 +00001756 vg_assert(seg);
1757 vg_assert(seg->kind == SkAnonC);
sewardjf9d2f9b2006-11-17 20:00:57 +00001758 vg_assert(the_iifii.initial_client_SP >= seg->start);
1759 vg_assert(the_iifii.initial_client_SP <= seg->end);
sewardj17c11042006-10-15 01:26:40 +00001760# if defined(VGO_aix5)
1761 VG_(clstk_base) = seg->start;
1762 VG_(clstk_end) = seg->end;
1763# endif
sewardj45f4e7c2005-09-27 19:20:21 +00001764
sewardj17c11042006-10-15 01:26:40 +00001765 /* Stuff below the initial SP is unaddressable. Take into
1766 account any ABI-mandated space below the stack pointer that
1767 is required (VG_STACK_REDZONE_SZB). setup_client_stack()
1768 will have allocated an extra page if a red zone is required,
1769 to be on the safe side. */
sewardjf9d2f9b2006-11-17 20:00:57 +00001770 vg_assert(the_iifii.initial_client_SP - VG_STACK_REDZONE_SZB
1771 >= seg->start);
sewardj17c11042006-10-15 01:26:40 +00001772 VG_TRACK( die_mem_stack,
1773 seg->start,
sewardjf9d2f9b2006-11-17 20:00:57 +00001774 the_iifii.initial_client_SP - VG_STACK_REDZONE_SZB
1775 - seg->start );
sewardj17c11042006-10-15 01:26:40 +00001776 VG_(debugLog)(2, "main", "mark stack inaccessible %010lx-%010lx\n",
1777 seg->start,
sewardjf9d2f9b2006-11-17 20:00:57 +00001778 the_iifii.initial_client_SP-1 - VG_STACK_REDZONE_SZB);
sewardj17c11042006-10-15 01:26:40 +00001779 }
sewardj45f4e7c2005-09-27 19:20:21 +00001780
1781 /* Also the assembly helpers. */
1782 VG_TRACK( new_mem_startup,
1783 (Addr)&VG_(trampoline_stuff_start),
sewardjc6527d62006-02-13 17:54:31 +00001784 (Addr)&VG_(trampoline_stuff_end)
1785 - (Addr)&VG_(trampoline_stuff_start),
sewardj45f4e7c2005-09-27 19:20:21 +00001786 False, /* readable? */
1787 False, /* writable? */
1788 True /* executable? */ );
1789 }
1790
1791 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00001792 // Initialise the scheduler
nethercote71980f02004-01-24 18:18:54 +00001793 // p: setup_file_descriptors() [else VG_(safe_fd)() breaks]
sewardj45f4e7c2005-09-27 19:20:21 +00001794 // p: setup_client_stack
nethercote71980f02004-01-24 18:18:54 +00001795 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00001796 VG_(debugLog)(1, "main", "Initialise scheduler\n");
sewardj12ab7652006-10-17 02:10:42 +00001797 { NSegment const* seg
sewardjf9d2f9b2006-11-17 20:00:57 +00001798 = VG_(am_find_nsegment)( the_iifii.initial_client_SP );
sewardj45f4e7c2005-09-27 19:20:21 +00001799 vg_assert(seg);
1800 vg_assert(seg->kind == SkAnonC);
sewardjf9d2f9b2006-11-17 20:00:57 +00001801 vg_assert(the_iifii.initial_client_SP >= seg->start);
1802 vg_assert(the_iifii.initial_client_SP <= seg->end);
1803 VG_(scheduler_init)( seg->end, the_iifii.clstack_max_size );
sewardj45f4e7c2005-09-27 19:20:21 +00001804 }
nethercote71980f02004-01-24 18:18:54 +00001805
1806 //--------------------------------------------------------------
sewardj17c11042006-10-15 01:26:40 +00001807 // Set up state for the root thread
sewardjb5f6f512005-03-10 23:59:00 +00001808 // p: ?
sewardj17c11042006-10-15 01:26:40 +00001809 // setup_scheduler() [for sched-specific thread 1 stuff]
sewardjf9d2f9b2006-11-17 20:00:57 +00001810 // VG_(ii_create_image) [for 'the_iicii' initial info]
sewardj2a99cf62004-11-24 10:44:19 +00001811 //--------------------------------------------------------------
sewardjf9d2f9b2006-11-17 20:00:57 +00001812 VG_(debugLog)(1, "main", "Finalise initial image\n");
1813 VG_(ii_finalise_image)( the_iifii );
njnea4b28c2004-11-30 16:04:58 +00001814
sewardj2a99cf62004-11-24 10:44:19 +00001815 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00001816 // Initialise the signal handling subsystem
sewardjb5f6f512005-03-10 23:59:00 +00001817 // p: n/a
nethercote71980f02004-01-24 18:18:54 +00001818 //--------------------------------------------------------------
1819 // Nb: temporarily parks the saved blocking-mask in saved_sigmask.
sewardj1fbc1a52005-04-25 02:05:54 +00001820 VG_(debugLog)(1, "main", "Initialise signal management\n");
nethercote71980f02004-01-24 18:18:54 +00001821 VG_(sigstartup_actions)();
1822
1823 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00001824 // Read suppression file
1825 // p: process_cmd_line_options() [for VG_(clo_suppressions)]
1826 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00001827 if (VG_(needs).core_errors || VG_(needs).tool_errors) {
1828 VG_(debugLog)(1, "main", "Load suppressions\n");
nethercote71980f02004-01-24 18:18:54 +00001829 VG_(load_suppressions)();
sewardj1fbc1a52005-04-25 02:05:54 +00001830 }
nethercote71980f02004-01-24 18:18:54 +00001831
1832 //--------------------------------------------------------------
rjwalsh0140af52005-06-04 20:42:33 +00001833 // register client stack
1834 //--------------------------------------------------------------
njn945ed2e2005-06-24 03:28:30 +00001835 VG_(clstk_id) = VG_(register_stack)(VG_(clstk_base), VG_(clstk_end));
rjwalsh0140af52005-06-04 20:42:33 +00001836
1837 //--------------------------------------------------------------
sewardj45f4e7c2005-09-27 19:20:21 +00001838 // Show the address space state so far
1839 //--------------------------------------------------------------
1840 VG_(debugLog)(1, "main", "\n");
1841 VG_(debugLog)(1, "main", "\n");
1842 VG_(am_show_nsegments)(1,"Memory layout at client startup");
1843 VG_(debugLog)(1, "main", "\n");
1844 VG_(debugLog)(1, "main", "\n");
1845
1846 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00001847 // Run!
1848 //--------------------------------------------------------------
sewardj71bc3cb2005-05-19 00:25:45 +00001849 if (VG_(clo_xml)) {
sewardj68cde6f2005-07-19 12:17:51 +00001850 HChar buf[50];
sewardj592ae092005-11-08 19:01:44 +00001851 VG_(elapsed_wallclock_time)(buf);
sewardj753673f2005-08-09 22:03:08 +00001852 VG_(message)(Vg_UserMsg, "<status>\n"
1853 " <state>RUNNING</state>\n"
1854 " <time>%t</time>\n"
1855 "</status>",
1856 buf);
sewardj71bc3cb2005-05-19 00:25:45 +00001857 VG_(message)(Vg_UserMsg, "");
1858 }
1859
sewardj1fbc1a52005-04-25 02:05:54 +00001860 VG_(debugLog)(1, "main", "Running thread 1\n");
sewardj1ae3f3a2005-09-28 10:47:38 +00001861
sewardj1d887112005-05-30 21:44:08 +00001862 /* As a result of the following call, the last thread standing
sewardj1ae3f3a2005-09-28 10:47:38 +00001863 eventually winds up running shutdown_actions_NORETURN
1864 just below. Unfortunately, simply exporting said function
1865 causes m_main to be part of a module cycle, which is pretty
1866 nonsensical. So instead of doing that, the address of said
1867 function is stored in a global variable 'owned' by m_syswrap,
1868 and it uses that function pointer to get back here when it needs
1869 to. */
1870
1871 /* Set continuation address. */
1872 VG_(address_of_m_main_shutdown_actions_NORETURN)
1873 = & shutdown_actions_NORETURN;
1874
1875 /* Run the first thread, eventually ending up at the continuation
1876 address. */
njnaf839f52005-06-23 03:27:57 +00001877 VG_(main_thread_wrapper_NORETURN)(1);
nethercote71980f02004-01-24 18:18:54 +00001878
sewardj1d887112005-05-30 21:44:08 +00001879 /*NOTREACHED*/
1880 vg_assert(0);
sewardjb5f6f512005-03-10 23:59:00 +00001881}
1882
sewardj17c11042006-10-15 01:26:40 +00001883/* Do everything which needs doing when the last thread exits or when
1884 a thread exits requesting a complete process exit (exit on AIX).
1885
1886 We enter here holding The Lock. For the case VgSrc_ExitProcess we
1887 must never release it, because to do so would allow other threads
1888 to continue after the system is ostensibly shut down. So we must
1889 go to our grave, so to speak, holding the lock.
1890
1891 In fact, there is never any point in releasing the lock at this
1892 point - we have it, we're shutting down the entire system, and
1893 for the case VgSrc_ExitProcess doing so positively causes trouble.
1894 So don't.
1895
1896 The final_tidyup call makes a bit of a nonsense of the ExitProcess
1897 case, since it will run the libc_freeres function, thus allowing
1898 other lurking threads to run again. Hmm. */
sewardjb5f6f512005-03-10 23:59:00 +00001899
sewardj1ae3f3a2005-09-28 10:47:38 +00001900static
1901void shutdown_actions_NORETURN( ThreadId tid,
1902 VgSchedReturnCode tids_schedretcode )
sewardjb5f6f512005-03-10 23:59:00 +00001903{
sewardj1d887112005-05-30 21:44:08 +00001904 VG_(debugLog)(1, "main", "entering VG_(shutdown_actions_NORETURN)\n");
sewardj17c11042006-10-15 01:26:40 +00001905 VG_(am_show_nsegments)(1,"Memory layout at client shutdown");
sewardj1d887112005-05-30 21:44:08 +00001906
sewardjb5f6f512005-03-10 23:59:00 +00001907 vg_assert(VG_(is_running_thread)(tid));
1908
sewardj12ab7652006-10-17 02:10:42 +00001909 vg_assert(tids_schedretcode == VgSrc_ExitThread
1910 || tids_schedretcode == VgSrc_ExitProcess
1911 || tids_schedretcode == VgSrc_FatalSig );
sewardjb5f6f512005-03-10 23:59:00 +00001912
sewardj12ab7652006-10-17 02:10:42 +00001913 if (tids_schedretcode == VgSrc_ExitThread) {
sewardjb5f6f512005-03-10 23:59:00 +00001914
sewardj17c11042006-10-15 01:26:40 +00001915 // We are the last surviving thread. Right?
1916 vg_assert( VG_(count_living_threads)() == 1 );
sewardjb5f6f512005-03-10 23:59:00 +00001917
sewardj17c11042006-10-15 01:26:40 +00001918 // Wait for all other threads to exit.
1919 // jrs: Huh? but they surely are already gone
1920 VG_(reap_threads)(tid);
sewardjb5f6f512005-03-10 23:59:00 +00001921
sewardj17c11042006-10-15 01:26:40 +00001922 // Clean the client up before the final report
1923 // this causes the libc_freeres function to run
1924 final_tidyup(tid);
1925
1926 /* be paranoid */
1927 vg_assert(VG_(is_running_thread)(tid));
1928 vg_assert(VG_(count_living_threads)() == 1);
1929
1930 } else {
1931
1932 // We may not be the last surviving thread. However, we
1933 // want to shut down the entire process. We hold the lock
1934 // and we need to keep hold of it all the way out, in order
1935 // that none of the other threads ever run again.
1936 vg_assert( VG_(count_living_threads)() >= 1 );
1937
sewardj17c11042006-10-15 01:26:40 +00001938 // Clean the client up before the final report
1939 // this causes the libc_freeres function to run
1940 // perhaps this is unsafe, as per comment above
1941 final_tidyup(tid);
1942
1943 /* be paranoid */
1944 vg_assert(VG_(is_running_thread)(tid));
1945 vg_assert(VG_(count_living_threads)() >= 1);
1946 }
sewardjb5f6f512005-03-10 23:59:00 +00001947
1948 VG_(threads)[tid].status = VgTs_Empty;
nethercote71980f02004-01-24 18:18:54 +00001949 //--------------------------------------------------------------
1950 // Finalisation: cleanup, messages, etc. Order no so important, only
1951 // affects what order the messages come.
1952 //--------------------------------------------------------------
1953 if (VG_(clo_verbosity) > 0)
1954 VG_(message)(Vg_UserMsg, "");
1955
sewardj71bc3cb2005-05-19 00:25:45 +00001956 if (VG_(clo_xml)) {
sewardj68cde6f2005-07-19 12:17:51 +00001957 HChar buf[50];
sewardj9f297ca2005-05-20 02:29:52 +00001958 if (VG_(needs).core_errors || VG_(needs).tool_errors) {
1959 VG_(show_error_counts_as_XML)();
1960 VG_(message)(Vg_UserMsg, "");
1961 }
sewardj592ae092005-11-08 19:01:44 +00001962 VG_(elapsed_wallclock_time)(buf);
sewardj753673f2005-08-09 22:03:08 +00001963 VG_(message)(Vg_UserMsg, "<status>\n"
1964 " <state>FINISHED</state>\n"
1965 " <time>%t</time>\n"
1966 "</status>",
1967 buf);
sewardj71bc3cb2005-05-19 00:25:45 +00001968 VG_(message)(Vg_UserMsg, "");
1969 }
1970
nethercote71980f02004-01-24 18:18:54 +00001971 /* Print out file descriptor summary and stats. */
1972 if (VG_(clo_track_fds))
nethercote3a42fb82004-08-03 18:08:50 +00001973 VG_(show_open_fds)();
nethercote71980f02004-01-24 18:18:54 +00001974
njn95ec8702004-11-22 16:46:13 +00001975 if (VG_(needs).core_errors || VG_(needs).tool_errors)
nethercote71980f02004-01-24 18:18:54 +00001976 VG_(show_all_errors)();
1977
njn51d827b2005-05-09 01:02:08 +00001978 VG_TDICT_CALL(tool_fini, 0/*exitcode*/);
nethercote71980f02004-01-24 18:18:54 +00001979
sewardj71bc3cb2005-05-19 00:25:45 +00001980 if (VG_(clo_xml)) {
1981 VG_(message)(Vg_UserMsg, "");
1982 VG_(message)(Vg_UserMsg, "</valgrindoutput>");
1983 VG_(message)(Vg_UserMsg, "");
1984 }
1985
nethercote885dd912004-08-03 23:14:00 +00001986 VG_(sanity_check_general)( True /*include expensive checks*/ );
nethercote71980f02004-01-24 18:18:54 +00001987
1988 if (VG_(clo_verbosity) > 1)
nethercote3a42fb82004-08-03 18:08:50 +00001989 print_all_stats();
nethercote71980f02004-01-24 18:18:54 +00001990
njn2025cf92005-06-26 20:44:48 +00001991 if (VG_(clo_profile_flags) > 0) {
sewardj5471ec62006-10-17 13:58:17 +00001992 #define N_MAX 200
njn2025cf92005-06-26 20:44:48 +00001993 BBProfEntry tops[N_MAX];
1994 ULong score_total = VG_(get_BB_profile) (tops, N_MAX);
1995 show_BB_profile(tops, N_MAX, score_total);
1996 }
sewardjfa8ec112005-01-19 11:55:34 +00001997
sewardj8b635a42004-11-22 19:01:47 +00001998 /* Print Vex storage stats */
sewardjbf426512005-01-17 18:35:30 +00001999 if (0)
2000 LibVEX_ShowAllocStats();
sewardj1d887112005-05-30 21:44:08 +00002001
njn8aa35852005-06-10 22:59:56 +00002002 /* Ok, finally exit in the os-specific way, according to the scheduler's
2003 return code. In short, if the (last) thread exited by calling
2004 sys_exit, do likewise; if the (last) thread stopped due to a fatal
2005 signal, terminate the entire system with that same fatal signal. */
2006 VG_(debugLog)(1, "core_os",
njn7b85dd52005-06-12 17:26:29 +00002007 "VG_(terminate_NORETURN)(tid=%lld)\n", (ULong)tid);
njn8aa35852005-06-10 22:59:56 +00002008
njn8aa35852005-06-10 22:59:56 +00002009 switch (tids_schedretcode) {
sewardj12ab7652006-10-17 02:10:42 +00002010 case VgSrc_ExitThread: /* the normal way out (Linux) */
2011 case VgSrc_ExitProcess: /* the normal way out (AIX) */
sewardjb9779082006-05-12 23:50:15 +00002012 /* Change the application return code to user's return code,
2013 if an error was found */
2014 if (VG_(clo_error_exitcode) > 0
2015 && VG_(get_n_errs_found)() > 0) {
2016 VG_(exit)( VG_(clo_error_exitcode) );
2017 } else {
2018 /* otherwise, return the client's exit code, in the normal
2019 way. */
2020 VG_(exit)( VG_(threads)[tid].os_state.exitcode );
2021 }
njn8aa35852005-06-10 22:59:56 +00002022 /* NOT ALIVE HERE! */
sewardj17c11042006-10-15 01:26:40 +00002023 VG_(core_panic)("entered the afterlife in main() -- ExitT/P");
njn8aa35852005-06-10 22:59:56 +00002024 break; /* what the hell :) */
2025
2026 case VgSrc_FatalSig:
2027 /* We were killed by a fatal signal, so replicate the effect */
2028 vg_assert(VG_(threads)[tid].os_state.fatalsig != 0);
2029 VG_(kill_self)(VG_(threads)[tid].os_state.fatalsig);
2030 VG_(core_panic)("main(): signal was supposed to be fatal");
2031 break;
2032
2033 default:
2034 VG_(core_panic)("main(): unexpected scheduler return code");
2035 }
njne96be672005-05-08 19:08:54 +00002036}
sewardj8b635a42004-11-22 19:01:47 +00002037
sewardj1ae3f3a2005-09-28 10:47:38 +00002038/* -------------------- */
2039
2040/* Final clean-up before terminating the process.
2041 Clean up the client by calling __libc_freeres() (if requested)
2042 This is Linux-specific?
2043*/
2044static void final_tidyup(ThreadId tid)
2045{
sewardjcf951812006-01-17 02:22:21 +00002046# if defined(VGP_ppc64_linux)
2047 Addr r2;
2048# endif
sewardj0ec07f32006-01-12 12:32:32 +00002049 Addr __libc_freeres_wrapper = VG_(client___libc_freeres_wrapper);
sewardj1ae3f3a2005-09-28 10:47:38 +00002050
2051 vg_assert(VG_(is_running_thread)(tid));
2052
2053 if ( !VG_(needs).libc_freeres ||
2054 !VG_(clo_run_libc_freeres) ||
sewardj0ec07f32006-01-12 12:32:32 +00002055 0 == __libc_freeres_wrapper )
sewardj1ae3f3a2005-09-28 10:47:38 +00002056 return; /* can't/won't do it */
sewardj17c11042006-10-15 01:26:40 +00002057# if defined(VGO_aix5)
2058 return; /* inapplicable on non-Linux platforms */
2059# endif
sewardj1ae3f3a2005-09-28 10:47:38 +00002060
sewardjcf951812006-01-17 02:22:21 +00002061# if defined(VGP_ppc64_linux)
2062 r2 = VG_(get_tocptr)( __libc_freeres_wrapper );
2063 if (r2 == 0) {
2064 VG_(message)(Vg_UserMsg,
2065 "Caught __NR_exit, but can't run __libc_freeres()");
2066 VG_(message)(Vg_UserMsg,
2067 " since cannot establish TOC pointer for it.");
2068 return;
2069 }
2070# endif
2071
sewardj1ae3f3a2005-09-28 10:47:38 +00002072 if (VG_(clo_verbosity) > 2 ||
2073 VG_(clo_trace_syscalls) ||
2074 VG_(clo_trace_sched))
2075 VG_(message)(Vg_DebugMsg,
2076 "Caught __NR_exit; running __libc_freeres()");
2077
sewardj0ec07f32006-01-12 12:32:32 +00002078 /* set thread context to point to libc_freeres_wrapper */
sewardj1a85f4f2006-01-12 21:15:35 +00002079 /* ppc64-linux note: __libc_freeres_wrapper gives us the real
2080 function entry point, not a fn descriptor, so can use it
2081 directly. However, we need to set R2 (the toc pointer)
2082 appropriately. */
sewardj1ae3f3a2005-09-28 10:47:38 +00002083 VG_(set_IP)(tid, __libc_freeres_wrapper);
sewardjcf951812006-01-17 02:22:21 +00002084# if defined(VGP_ppc64_linux)
2085 VG_(threads)[tid].arch.vex.guest_GPR2 = r2;
2086# endif
sewardj1ae3f3a2005-09-28 10:47:38 +00002087
2088 /* Block all blockable signals by copying the real block state into
2089 the thread's block state*/
2090 VG_(sigprocmask)(VKI_SIG_BLOCK, NULL, &VG_(threads)[tid].sig_mask);
2091 VG_(threads)[tid].tmp_sig_mask = VG_(threads)[tid].sig_mask;
2092
2093 /* and restore handlers to default */
2094 VG_(set_default_handler)(VKI_SIGSEGV);
2095 VG_(set_default_handler)(VKI_SIGBUS);
2096 VG_(set_default_handler)(VKI_SIGILL);
2097 VG_(set_default_handler)(VKI_SIGFPE);
2098
2099 // We were exiting, so assert that...
2100 vg_assert(VG_(is_exiting)(tid));
2101 // ...but now we're not again
2102 VG_(threads)[tid].exitreason = VgSrc_None;
2103
2104 // run until client thread exits - ideally with LIBC_FREERES_DONE,
2105 // but exit/exitgroup/signal will do
2106 VG_(scheduler)(tid);
2107
2108 vg_assert(VG_(is_exiting)(tid));
2109}
2110
sewardj45f4e7c2005-09-27 19:20:21 +00002111
2112/*====================================================================*/
sewardj17c11042006-10-15 01:26:40 +00002113/*=== Getting to main() alive: LINUX (for AIX5 see below) ===*/
sewardj45f4e7c2005-09-27 19:20:21 +00002114/*====================================================================*/
2115
sewardj17c11042006-10-15 01:26:40 +00002116#if defined(VGO_linux)
2117
sewardj45f4e7c2005-09-27 19:20:21 +00002118/* If linking of the final executables is done with glibc present,
2119 then Valgrind starts at main() above as usual, and all of the
2120 following code is irrelevant.
2121
2122 However, this is not the intended mode of use. The plan is to
2123 avoid linking against glibc, by giving gcc the flags
2124 -nodefaultlibs -lgcc -nostartfiles at startup.
2125
2126 From this derive two requirements:
2127
2128 1. gcc may emit calls to memcpy and memset to deal with structure
2129 assignments etc. Since we have chosen to ignore all the
2130 "normal" supporting libraries, we have to provide our own
2131 implementations of them. No problem.
2132
2133 2. We have to provide a symbol "_start", to which the kernel
2134 hands control at startup. Hence the code below.
2135*/
2136
2137/* ---------------- Requirement 1 ---------------- */
2138
sewardj17c11042006-10-15 01:26:40 +00002139void* memcpy(void *dest, const void *src, SizeT n);
2140void* memcpy(void *dest, const void *src, SizeT n) {
sewardj45f4e7c2005-09-27 19:20:21 +00002141 return VG_(memcpy)(dest,src,n);
2142}
sewardj17c11042006-10-15 01:26:40 +00002143void* memset(void *s, int c, SizeT n);
2144void* memset(void *s, int c, SizeT n) {
sewardj45f4e7c2005-09-27 19:20:21 +00002145 return VG_(memset)(s,c,n);
2146}
2147
2148/* ---------------- Requirement 2 ---------------- */
2149
2150/* Glibc's sysdeps/i386/elf/start.S has the following gem of a
2151 comment, which explains how the stack looks right at process start
2152 (when _start is jumped to). Hence _start passes %esp to
sewardj17c11042006-10-15 01:26:40 +00002153 _start_in_C_linux, which extracts argc/argv/envp and starts up
sewardj45f4e7c2005-09-27 19:20:21 +00002154 correctly. */
2155
2156/* This is the canonical entry point, usually the first thing in the text
2157 segment. The SVR4/i386 ABI (pages 3-31, 3-32) says that when the entry
2158 point runs, most registers' values are unspecified, except for:
2159
2160 %edx Contains a function pointer to be registered with `atexit'.
2161 This is how the dynamic linker arranges to have DT_FINI
2162 functions called for shared libraries that have been loaded
2163 before this code runs.
2164
2165 %esp The stack contains the arguments and environment:
2166 0(%esp) argc
2167 4(%esp) argv[0]
2168 ...
2169 (4*argc)(%esp) NULL
2170 (4*(argc+1))(%esp) envp[0]
2171 ...
2172 NULL
2173*/
2174
2175/* The kernel hands control to _start, which extracts the initial
sewardj17c11042006-10-15 01:26:40 +00002176 stack pointer and calls onwards to _start_in_C_linux. This also switches
sewardja48a4932005-09-29 11:09:56 +00002177 the new stack. */
sewardj45f4e7c2005-09-27 19:20:21 +00002178#if defined(VGP_x86_linux)
2179asm("\n"
sewardjd9fc3822005-11-18 23:50:43 +00002180 ".text\n"
sewardj45f4e7c2005-09-27 19:20:21 +00002181 "\t.globl _start\n"
2182 "\t.type _start,@function\n"
2183 "_start:\n"
2184 /* set up the new stack in %eax */
sewardjfdf91b42005-09-28 00:53:09 +00002185 "\tmovl $vgPlain_interim_stack, %eax\n"
sewardj45f4e7c2005-09-27 19:20:21 +00002186 "\taddl $"VG_STRINGIFY(VG_STACK_GUARD_SZB)", %eax\n"
2187 "\taddl $"VG_STRINGIFY(VG_STACK_ACTIVE_SZB)", %eax\n"
2188 "\tsubl $16, %eax\n"
2189 "\tandl $~15, %eax\n"
2190 /* install it, and collect the original one */
2191 "\txchgl %eax, %esp\n"
sewardj17c11042006-10-15 01:26:40 +00002192 /* call _start_in_C_linux, passing it the startup %esp */
sewardj45f4e7c2005-09-27 19:20:21 +00002193 "\tpushl %eax\n"
sewardj17c11042006-10-15 01:26:40 +00002194 "\tcall _start_in_C_linux\n"
sewardj45f4e7c2005-09-27 19:20:21 +00002195 "\thlt\n"
sewardj2fedc642005-11-19 02:02:57 +00002196 ".previous\n"
sewardj45f4e7c2005-09-27 19:20:21 +00002197);
2198#elif defined(VGP_amd64_linux)
2199asm("\n"
sewardjd9fc3822005-11-18 23:50:43 +00002200 ".text\n"
sewardj45f4e7c2005-09-27 19:20:21 +00002201 "\t.globl _start\n"
2202 "\t.type _start,@function\n"
2203 "_start:\n"
2204 /* set up the new stack in %rdi */
sewardjfdf91b42005-09-28 00:53:09 +00002205 "\tmovq $vgPlain_interim_stack, %rdi\n"
sewardj45f4e7c2005-09-27 19:20:21 +00002206 "\taddq $"VG_STRINGIFY(VG_STACK_GUARD_SZB)", %rdi\n"
2207 "\taddq $"VG_STRINGIFY(VG_STACK_ACTIVE_SZB)", %rdi\n"
2208 "\tandq $~15, %rdi\n"
2209 /* install it, and collect the original one */
2210 "\txchgq %rdi, %rsp\n"
sewardj17c11042006-10-15 01:26:40 +00002211 /* call _start_in_C_linux, passing it the startup %rsp */
2212 "\tcall _start_in_C_linux\n"
sewardj45f4e7c2005-09-27 19:20:21 +00002213 "\thlt\n"
sewardj2fedc642005-11-19 02:02:57 +00002214 ".previous\n"
sewardj45f4e7c2005-09-27 19:20:21 +00002215);
sewardja48a4932005-09-29 11:09:56 +00002216#elif defined(VGP_ppc32_linux)
2217asm("\n"
sewardjd9fc3822005-11-18 23:50:43 +00002218 ".text\n"
sewardja48a4932005-09-29 11:09:56 +00002219 "\t.globl _start\n"
2220 "\t.type _start,@function\n"
2221 "_start:\n"
2222 /* set up the new stack in r16 */
2223 "\tlis 16,vgPlain_interim_stack@ha\n"
2224 "\tla 16,vgPlain_interim_stack@l(16)\n"
2225 "\tlis 17,("VG_STRINGIFY(VG_STACK_GUARD_SZB)" >> 16)\n"
2226 "\tori 17,17,("VG_STRINGIFY(VG_STACK_GUARD_SZB)" & 0xFFFF)\n"
2227 "\tlis 18,("VG_STRINGIFY(VG_STACK_ACTIVE_SZB)" >> 16)\n"
2228 "\tori 18,18,("VG_STRINGIFY(VG_STACK_ACTIVE_SZB)" & 0xFFFF)\n"
2229 "\tadd 16,17,16\n"
2230 "\tadd 16,18,16\n"
2231 "\trlwinm 16,16,0,0,27\n"
2232 /* now r16 = &vgPlain_interim_stack + VG_STACK_GUARD_SZB +
2233 VG_STACK_ACTIVE_SZB rounded down to the nearest 16-byte
2234 boundary. And r1 is the original SP. Set the SP to r16 and
sewardj17c11042006-10-15 01:26:40 +00002235 call _start_in_C_linux, passing it the initial SP. */
sewardja48a4932005-09-29 11:09:56 +00002236 "\tmr 3,1\n"
2237 "\tmr 1,16\n"
sewardj17c11042006-10-15 01:26:40 +00002238 "\tbl _start_in_C_linux\n"
sewardja48a4932005-09-29 11:09:56 +00002239 "\ttrap\n"
sewardj2fedc642005-11-19 02:02:57 +00002240 ".previous\n"
sewardja48a4932005-09-29 11:09:56 +00002241);
sewardj2c48c7b2005-11-29 13:05:56 +00002242#elif defined(VGP_ppc64_linux)
2243asm("\n"
cerion21082042005-12-06 19:07:08 +00002244 /* PPC64 ELF ABI says '_start' points to a function descriptor.
2245 So we must have one, and that is what goes into the .opd section. */
cerion297c88f2005-12-22 15:53:12 +00002246 "\t.align 2\n"
cerion21082042005-12-06 19:07:08 +00002247 "\t.global _start\n"
2248 "\t.section \".opd\",\"aw\"\n"
2249 "\t.align 3\n"
sewardj2c48c7b2005-11-29 13:05:56 +00002250 "_start:\n"
cerion21082042005-12-06 19:07:08 +00002251 "\t.quad ._start,.TOC.@tocbase,0\n"
2252 "\t.previous\n"
2253 "\t.type ._start,@function\n"
2254 "\t.global ._start\n"
2255 "._start:\n"
sewardj2c48c7b2005-11-29 13:05:56 +00002256 /* set up the new stack in r16 */
2257 "\tlis 16, vgPlain_interim_stack@highest\n"
2258 "\tori 16,16,vgPlain_interim_stack@higher\n"
2259 "\tsldi 16,16,32\n"
2260 "\toris 16,16,vgPlain_interim_stack@h\n"
2261 "\tori 16,16,vgPlain_interim_stack@l\n"
2262 "\txor 17,17,17\n"
2263 "\tlis 17,("VG_STRINGIFY(VG_STACK_GUARD_SZB)" >> 16)\n"
2264 "\tori 17,17,("VG_STRINGIFY(VG_STACK_GUARD_SZB)" & 0xFFFF)\n"
2265 "\txor 18,18,18\n"
2266 "\tlis 18,("VG_STRINGIFY(VG_STACK_ACTIVE_SZB)" >> 16)\n"
2267 "\tori 18,18,("VG_STRINGIFY(VG_STACK_ACTIVE_SZB)" & 0xFFFF)\n"
2268 "\tadd 16,17,16\n"
2269 "\tadd 16,18,16\n"
2270 "\trldicr 16,16,0,59\n"
2271 /* now r16 = &vgPlain_interim_stack + VG_STACK_GUARD_SZB +
2272 VG_STACK_ACTIVE_SZB rounded down to the nearest 16-byte
2273 boundary. And r1 is the original SP. Set the SP to r16 and
sewardj17c11042006-10-15 01:26:40 +00002274 call _start_in_C_linux, passing it the initial SP. */
sewardj2c48c7b2005-11-29 13:05:56 +00002275 "\tmr 3,1\n"
2276 "\tmr 1,16\n"
sewardj17c11042006-10-15 01:26:40 +00002277 "\tbl ._start_in_C_linux\n"
cerion21082042005-12-06 19:07:08 +00002278 "\tnop\n"
sewardj2c48c7b2005-11-29 13:05:56 +00002279 "\ttrap\n"
sewardj2c48c7b2005-11-29 13:05:56 +00002280);
sewardj45f4e7c2005-09-27 19:20:21 +00002281#else
2282#error "_start: needs implementation on this platform"
2283#endif
2284
sewardje66f2e02006-12-30 17:45:08 +00002285/* --- !!! --- EXTERNAL HEADERS start --- !!! --- */
2286#define _GNU_SOURCE
2287#define _FILE_OFFSET_BITS 64
2288/* This is in order to get AT_NULL and AT_PAGESIZE. */
2289#include <elf.h>
2290/* --- !!! --- EXTERNAL HEADERS end --- !!! --- */
2291
sewardj45f4e7c2005-09-27 19:20:21 +00002292/* Avoid compiler warnings: this fn _is_ used, but labelling it
2293 'static' causes gcc to complain it isn't. */
sewardj17c11042006-10-15 01:26:40 +00002294void _start_in_C_linux ( UWord* pArgc );
2295void _start_in_C_linux ( UWord* pArgc )
sewardj45f4e7c2005-09-27 19:20:21 +00002296{
2297 Int r;
2298 Word argc = pArgc[0];
2299 HChar** argv = (HChar**)&pArgc[1];
2300 HChar** envp = (HChar**)&pArgc[1+argc+1];
sewardjf9d2f9b2006-11-17 20:00:57 +00002301
2302 VG_(memset)( &the_iicii, 0, sizeof(the_iicii) );
2303 VG_(memset)( &the_iifii, 0, sizeof(the_iifii) );
2304
2305 the_iicii.sp_at_startup = (Addr)pArgc;
2306
sewardje66f2e02006-12-30 17:45:08 +00002307# if defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux)
2308 {
2309 /* ppc/ppc64 can be configured with different page sizes.
2310 Determine this early. This is an ugly hack and really should
2311 be moved into valgrind_main. */
2312 UWord *sp = &pArgc[1+argc+1];
2313 while (*sp++ != 0)
2314 ;
2315 for (; *sp != AT_NULL && *sp != AT_PAGESZ; sp += 2);
2316 if (*sp == AT_PAGESZ) {
2317 VKI_PAGE_SIZE = sp[1];
2318 for (VKI_PAGE_SHIFT = 12;
2319 VKI_PAGE_SHIFT <= VKI_MAX_PAGE_SHIFT; VKI_PAGE_SHIFT++)
2320 if (VKI_PAGE_SIZE == (1UL << VKI_PAGE_SHIFT))
2321 break;
2322 }
2323 }
2324# endif
2325
sewardjf9d2f9b2006-11-17 20:00:57 +00002326 r = valgrind_main( (Int)argc, argv, envp );
sewardj17c11042006-10-15 01:26:40 +00002327 /* NOTREACHED */
sewardj45f4e7c2005-09-27 19:20:21 +00002328 VG_(exit)(r);
2329}
2330
sewardj17c11042006-10-15 01:26:40 +00002331#endif /* defined(VGO_linux) */
2332
2333
2334/*====================================================================*/
2335/*=== Getting to main() alive: AIX5 ===*/
2336/*====================================================================*/
2337
2338#if defined(VGP_ppc32_aix5) || defined(VGP_ppc64_aix5)
2339
2340/* This is somewhat simpler than the Linux case. _start_valgrind
2341 receives control from the magic piece of code created in this
2342 process' address space by the launcher, via use of ptrace(). At
2343 the point of entry:
2344
2345 - the initial client process image is in memory and ready to roll,
2346 except that we've partially trashed its integer register state
2347 in order to get this far. So ..
2348
2349 - intregs37 holds the client's initial integer register state, so
2350 we can restore it before starting the client on the VCPU.
2351
2352 - we're on the client's stack. This is not good; therefore the
2353 first order of business is to switch to our temporary stack.
2354
2355 - the client's initial argc/v/envp is in r3/r4/r5 (32 bit mode) or
2356 r14/r15/r16 (64 bit mode). They are pulled out of the stashed
2357 integer register state and passed to our main().
2358
2359 The launcher will have played some games with argv. If the launcher
2360 ($prefix/bin/valgrind) was started like this
2361
2362 valgrind [args-for-V] app [args-for-app]
2363
2364 then the launcher will have started the client as
2365
2366 app [args-for-V] app [args-for-app]
2367
2368 m_initimg will have to mess with the client's initial r4/r5
2369 (32-bit) or r15/r16 (64-bit) so that it believes it was execd as
2370 "app [args-for-app]". Well, that's no big deal.
2371*/
2372
2373#include "launcher-aix5-bootblock.h"
2374
2375void _start_in_C_aix5 ( AIX5Bootblock* bootblock );
2376void _start_in_C_aix5 ( AIX5Bootblock* bootblock )
2377{
2378 Int r;
2379 ULong* intregs37;
2380 UWord argc, argv, envp;
2381 __NR_getpid = bootblock->__NR_getpid;
2382 __NR_write = bootblock->__NR_write;
2383 __NR_exit = bootblock->__NR_exit;
2384 __NR_open = bootblock->__NR_open;
2385 __NR_read = bootblock->__NR_read;
2386 __NR_close = bootblock->__NR_close;
sewardjf9d2f9b2006-11-17 20:00:57 +00002387
2388 VG_(memset)( &the_iicii, 0, sizeof(the_iicii) );
2389 VG_(memset)( &the_iifii, 0, sizeof(the_iifii) );
2390
sewardj17c11042006-10-15 01:26:40 +00002391 intregs37 = &bootblock->iregs_pc_cr_lr_ctr_xer[0];
sewardjf9d2f9b2006-11-17 20:00:57 +00002392 the_iicii.intregs37 = intregs37;
2393 the_iicii.bootblock = (void*)bootblock;
2394 the_iicii.adler32_exp = bootblock->adler32;
2395
2396 /* Not important on AIX. */
2397 the_iicii.sp_at_startup = (Addr)0x31415927ULL;
2398
sewardj17c11042006-10-15 01:26:40 +00002399# if defined(VGP_ppc32_aix5)
2400 argc = (UWord)intregs37[3]; /* client's r3 == argc */
2401 argv = (UWord)intregs37[4];
2402 envp = (UWord)intregs37[5];
2403# else /* defined(VGP_ppc64_aix5) */
2404 argc = (UWord)intregs37[14]; /* client's r14 == argc */
2405 argv = (UWord)intregs37[15];
2406 envp = (UWord)intregs37[16];
2407# endif
sewardjf9d2f9b2006-11-17 20:00:57 +00002408
2409 r = valgrind_main( (Int)argc, (HChar**)argv, (HChar**)envp );
2410
sewardj17c11042006-10-15 01:26:40 +00002411 /* NOTREACHED */
2412 VG_(exit)(r);
2413}
2414
2415/* THE ENTRY POINT */
2416void _start_valgrind ( AIX5Bootblock* bootblock );
2417void _start_valgrind ( AIX5Bootblock* bootblock )
2418{
2419 /* Switch immediately to our temporary stack, and continue. This
2420 is pretty dodgy in that it assumes that gcc does not place on
2421 the stack, anything needed to form the _start_in_C_aix5 call,
2422 since it will be on the old stack. */
2423 register UWord new_r1;
2424 new_r1 = (UWord)&VG_(interim_stack);
2425 new_r1 += VG_STACK_GUARD_SZB; /* step over lower guard page */
2426 new_r1 += VG_STACK_ACTIVE_SZB; /* step to top of active area */
2427 new_r1 -= 512; /* paranoia */
2428 __asm__ __volatile__("mr 1,%0" :/*wr*/
2429 :/*rd*/ "b"(new_r1)
2430 :/*trash*/"r1","memory");
2431 _start_in_C_aix5(bootblock);
2432 /*NOTREACHED*/
2433 VG_(exit)(0);
2434}
2435
2436#endif /* defined(VGP_ppc{32,64}_aix5) */
2437
2438
sewardjde4a1d02002-03-22 01:27:54 +00002439/*--------------------------------------------------------------------*/
njn04e16982005-05-31 00:23:43 +00002440/*--- end ---*/
sewardjde4a1d02002-03-22 01:27:54 +00002441/*--------------------------------------------------------------------*/