1ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/
3ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Startup: the real stuff                             m_main.c ---*/
4ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/
5ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*
7ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   This file is part of Valgrind, a dynamic binary instrumentation
8ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   framework.
9ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   Copyright (C) 2000-2011 Julian Seward
11ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      jseward@acm.org
12ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   This program is free software; you can redistribute it and/or
14ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   modify it under the terms of the GNU General Public License as
15ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   published by the Free Software Foundation; either version 2 of the
16ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   License, or (at your option) any later version.
17ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   This program is distributed in the hope that it will be useful, but
19ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   WITHOUT ANY WARRANTY; without even the implied warranty of
20ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
21ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   General Public License for more details.
22ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
23ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   You should have received a copy of the GNU General Public License
24ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   along with this program; if not, write to the Free Software
25ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
26ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   02111-1307, USA.
27ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
28ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   The GNU General Public License is contained in the file COPYING.
29ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
30ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
31ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_basics.h"
32ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_vki.h"
33ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_vkiscnums.h"
34b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#include "pub_core_libcsetjmp.h"    // to keep _threadstate.h happy
35ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_threadstate.h"
36ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_xarray.h"
37ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_clientstate.h"
38ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_aspacemgr.h"
39ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_aspacehl.h"
40ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_commandline.h"
41ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_debuglog.h"
42ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_errormgr.h"
43ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_execontext.h"
44b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#include "pub_core_gdbserver.h"
45ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_initimg.h"
46ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_libcbase.h"
47ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_libcassert.h"
48ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_libcfile.h"
49ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_libcprint.h"
50ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_libcproc.h"
51ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_libcsignal.h"
52ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_syscall.h"       // VG_(strerror)
53ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_mach.h"
54ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_machine.h"
55ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_mallocfree.h"
56ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_options.h"
57ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_debuginfo.h"
58ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_redir.h"
59ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_scheduler.h"
60ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_seqmatch.h"      // For VG_(string_match)
61ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_signals.h"
62ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_stacks.h"        // For VG_(register_stack)
63ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_syswrap.h"
64ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_tooliface.h"
65ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_translate.h"     // For VG_(translate)
66ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_trampoline.h"
67ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_transtab.h"
68ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
69ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
70ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*====================================================================*/
71ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*=== Counters, for profiling purposes only                        ===*/
72ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*====================================================================*/
73ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
74ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void print_all_stats ( void )
75ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
76ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(print_translation_stats)();
77ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(print_tt_tc_stats)();
78ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(print_scheduler_stats)();
79ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(print_ExeContext_stats)();
80ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(print_errormgr_stats)();
81ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
82ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Memory stats
83ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (VG_(clo_verbosity) > 2) {
84ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(message)(Vg_DebugMsg, "\n");
85ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(message)(Vg_DebugMsg,
86ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         "------ Valgrind's internal memory use stats follow ------\n" );
87ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(sanity_check_malloc_all)();
88ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(message)(Vg_DebugMsg, "------\n" );
89ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(print_all_arena_stats)();
90ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(message)(Vg_DebugMsg, "\n");
91ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
92ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
93ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
94ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
95ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*====================================================================*/
96ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*=== Command-line: variables, processing, etc                     ===*/
97ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*====================================================================*/
98ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
99ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// See pub_{core,tool}_options.h for explanations of all these.
100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void usage_NORETURN ( Bool debug_help )
102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
103b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /* 'usage1' contains a %s
104b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      - for the name of the GDB executable
105b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      - for the name of vgdb's path prefix
106b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      which must be supplied when they are VG_(printf)'d. */
107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Char* usage1 =
108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"usage: valgrind [options] prog-and-args\n"
109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"\n"
110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"  tool-selection option, with default in [ ]:\n"
111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"    --tool=<name>             use the Valgrind tool named <name> [memcheck]\n"
112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"\n"
113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"  basic user options for all Valgrind tools, with defaults in [ ]:\n"
114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"    -h --help                 show this message\n"
115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"    --help-debug              show this message, plus debugging options\n"
116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"    --version                 show version\n"
117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"    -q --quiet                run silently; only print error msgs\n"
118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"    -v --verbose              be more verbose -- show misc extra info\n"
119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"    --trace-children=no|yes   Valgrind-ise child processes (follow execve)? [no]\n"
120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"    --trace-children-skip=patt1,patt2,...    specifies a list of executables\n"
121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"                              that --trace-children=yes should not trace into\n"
122b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov"    --trace-children-skip-by-arg=patt1,patt2,...   same as --trace-children-skip=\n"
123b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov"                              but check the argv[] entries for children, rather\n"
124b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov"                              than the exe name, to make a follow/no-follow decision\n"
125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"    --child-silent-after-fork=no|yes omit child output between fork & exec? [no]\n"
126b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov"    --vgdb=no|yes|full        activate gdbserver? [yes]\n"
127b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov"                              full is slower but provides precise watchpoint/step\n"
128b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov"    --vgdb-error=<number>     invoke gdbserver after <number> errors [%d]\n"
129b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov"                              to get started quickly, use --vgdb-error=0\n"
130b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov"                              and follow the on-screen directions\n"
131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"    --track-fds=no|yes        track open file descriptors? [no]\n"
132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"    --time-stamp=no|yes       add timestamps to log messages? [no]\n"
133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"    --log-fd=<number>         log messages to file descriptor [2=stderr]\n"
134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"    --log-file=<file>         log messages to <file>\n"
135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"    --log-socket=ipaddr:port  log messages to socket ipaddr:port\n"
136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"\n"
137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"  user options for Valgrind tools that report errors:\n"
138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"    --xml=yes                 emit error output in XML (some tools only)\n"
139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"    --xml-fd=<number>         XML output to file descriptor\n"
140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"    --xml-file=<file>         XML output to <file>\n"
141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"    --xml-socket=ipaddr:port  XML output to socket ipaddr:port\n"
142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"    --xml-user-comment=STR    copy STR verbatim into XML output\n"
143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"    --demangle=no|yes         automatically demangle C++ names? [yes]\n"
144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"    --num-callers=<number>    show <number> callers in stack traces [12]\n"
145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"    --error-limit=no|yes      stop showing new errors if too many? [yes]\n"
146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"    --error-exitcode=<number> exit code to return if errors found [0=disable]\n"
147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"    --show-below-main=no|yes  continue stack traces below main() [no]\n"
148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"    --suppressions=<filename> suppress errors described in <filename>\n"
149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"    --gen-suppressions=no|yes|all    print suppressions for errors? [no]\n"
150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"    --db-attach=no|yes        start debugger when errors detected? [no]\n"
151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"    --db-command=<command>    command to start debugger [%s -nw %%f %%p]\n"
152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"    --input-fd=<number>       file descriptor for input [0=stdin]\n"
153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"    --dsymutil=no|yes         run dsymutil on Mac OS X when helpful? [no]\n"
154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"    --max-stackframe=<number> assume stack switch for SP changes larger\n"
155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"                              than <number> bytes [2000000]\n"
156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"    --main-stacksize=<number> set size of main thread's stack (in bytes)\n"
157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"                              [use current 'ulimit' value]\n"
158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"\n"
159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"  user options for Valgrind tools that replace malloc:\n"
160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"    --alignment=<number>      set minimum alignment of heap allocations [%ld]\n"
161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"\n"
162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"  uncommon user options for all Valgrind tools:\n"
163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"    --fullpath-after=         (with nothing after the '=')\n"
164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"                              show full source paths in call stacks\n"
165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"    --fullpath-after=string   like --fullpath-after=, but only show the\n"
166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"                              part of the path after 'string'.  Allows removal\n"
167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"                              of path prefixes.  Use this flag multiple times\n"
168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"                              to specify a set of prefixes to remove.\n"
169b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov"    --smc-check=none|stack|all|all-non-file [stack]\n"
170b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov"                              checks for self-modifying code: none, only for\n"
171b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov"                              code found in stacks, for all code, or for all\n"
172b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov"                              code except that from file-backed mappings\n"
173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"    --read-var-info=yes|no    read debug info on stack and global variables\n"
174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"                              and use it to print better error messages in\n"
175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"                              tools that make use of it (Memcheck, Helgrind,\n"
176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"                              DRD) [no]\n"
177b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov"    --vgdb-poll=<number>      gdbserver poll max every <number> basic blocks [%d] \n"
178b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov"    --vgdb-shadow-registers=no|yes   let gdb see the shadow registers [no]\n"
179b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov"    --vgdb-prefix=<prefix>    prefix for vgdb FIFOs [%s]\n"
180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"    --run-libc-freeres=no|yes free up glibc memory at exit on Linux? [yes]\n"
181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"    --sim-hints=hint1,hint2,...  known hints:\n"
182b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov"                                 lax-ioctls, enable-outer, fuse-compatible [none]\n"
183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"    --kernel-variant=variant1,variant2,...  known variants: bproc [none]\n"
184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"                              handle non-standard kernel variants\n"
185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"    --show-emwarns=no|yes     show warnings about emulation limits? [no]\n"
186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"    --require-text-symbol=:sonamepattern:symbolpattern    abort run if the\n"
187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"                              stated shared object doesn't have the stated\n"
188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"                              text symbol.  Patterns can contain ? and *.\n"
189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"\n";
190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Char* usage2 =
192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"\n"
193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"  debugging options for all Valgrind tools:\n"
194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"    -d                        show verbose debugging output\n"
195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"    --stats=no|yes            show tool and core statistics [no]\n"
196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"    --sanity-level=<number>   level of sanity checking to do [1]\n"
197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"    --trace-flags=<XXXXXXXX>   show generated code? (X = 0|1) [00000000]\n"
198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"    --profile-flags=<XXXXXXXX> ditto, but for profiling (X = 0|1) [00000000]\n"
199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"    --trace-notbelow=<number> only show BBs above <number> [999999999]\n"
200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"    --trace-syscalls=no|yes   show all system calls? [no]\n"
201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"    --trace-signals=no|yes    show signal handling details? [no]\n"
202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"    --trace-symtab=no|yes     show symbol table details? [no]\n"
203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"    --trace-symtab-patt=<patt> limit debuginfo tracing to obj name <patt>\n"
204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"    --trace-cfi=no|yes        show call-frame-info details? [no]\n"
205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"    --debug-dump=syms         mimic /usr/bin/readelf --syms\n"
206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"    --debug-dump=line         mimic /usr/bin/readelf --debug-dump=line\n"
207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"    --debug-dump=frames       mimic /usr/bin/readelf --debug-dump=frames\n"
208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"    --trace-redir=no|yes      show redirection details? [no]\n"
209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"    --trace-sched=no|yes      show thread scheduler details? [no]\n"
210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"    --profile-heap=no|yes     profile Valgrind's own space use\n"
211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"    --wait-for-gdb=yes|no     pause on startup to wait for gdb attach\n"
212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"    --sym-offsets=yes|no      show syms in form 'name+offset' ? [no]\n"
213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"    --command-line-only=no|yes  only use command line options [no]\n"
214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"\n"
215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"  Vex options for all Valgrind tools:\n"
216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"    --vex-iropt-verbosity=<0..9>           [0]\n"
217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"    --vex-iropt-level=<0..2>               [2]\n"
218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"    --vex-iropt-precise-memory-exns=no|yes [no]\n"
219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"    --vex-iropt-unroll-thresh=<0..400>     [120]\n"
220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"    --vex-guest-max-insns=<1..100>         [50]\n"
221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"    --vex-guest-chase-thresh=<0..99>       [10]\n"
222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"    --vex-guest-chase-cond=no|yes          [no]\n"
223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"    --trace-flags and --profile-flags values (omit the middle space):\n"
224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"       1000 0000   show conversion into IR\n"
225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"       0100 0000   show after initial opt\n"
226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"       0010 0000   show after instrumentation\n"
227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"       0001 0000   show after second opt\n"
228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"       0000 1000   show after tree building\n"
229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"       0000 0100   show selecting insns\n"
230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"       0000 0010   show after reg-alloc\n"
231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"       0000 0001   show final assembly\n"
232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"      (Nb: you need --trace-notbelow with --trace-flags for full details)\n"
233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"\n"
234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"  debugging options for Valgrind tools that report errors\n"
235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"    --dump-error=<number>     show translation for basic block associated\n"
236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"                              with <number>'th error context [0=show none]\n"
237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"\n"
238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"  debugging options for Valgrind tools that replace malloc:\n"
239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"    --trace-malloc=no|yes     show client malloc details? [no]\n"
240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"\n";
241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Char* usage3 =
243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"\n"
244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"  Extra options read from ~/.valgrindrc, $VALGRIND_OPTS, ./.valgrindrc\n"
245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"\n"
246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"  %s is %s\n"
247b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov"  Valgrind is Copyright (C) 2000-2011, and GNU GPL'd, by Julian Seward et al.\n"
248b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov"  LibVEX is Copyright (C) 2004-2011, and GNU GPL'd, by OpenWorks LLP et al.\n"
249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"\n"
250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"  Bug reports, feedback, admiration, abuse, etc, to: %s.\n"
251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"\n";
252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Char* gdb_path = GDB_PATH;
254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Ensure the message goes to stdout
256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(log_output_sink).fd = 1;
257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(log_output_sink).is_socket = False;
258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
259b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /* 'usage1' expects two int, two char* argument, and one SizeT argument. */
260b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   VG_(printf)(usage1,
261b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               VG_(clo_vgdb_error), gdb_path, VG_MIN_MALLOC_SZB,
262b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               VG_(clo_vgdb_poll), VG_(vgdb_prefix_default)());
263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (VG_(details).name) {
264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf)("  user options for %s:\n", VG_(details).name);
265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (VG_(needs).command_line_options)
266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 VG_TDICT_CALL(tool_print_usage);
267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else
268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 VG_(printf)("    (none)\n");
269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (debug_help) {
271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf)("%s", usage2);
272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (VG_(details).name) {
274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(printf)("  debugging options for %s:\n", VG_(details).name);
275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (VG_(needs).command_line_options)
277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_TDICT_CALL(tool_print_debug_usage);
278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         else
279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(printf)("    (none)\n");
280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(printf)(usage3, VG_(details).name, VG_(details).copyright_author,
283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               VG_BUGS_TO);
284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(exit)(0);
285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Peer at previously set up VG_(args_for_valgrind) and do some
289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   minimal command line processing that must happen early on:
290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   - show the version string, if requested (-v)
292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   - extract any request for help (--help, -h, --help-debug)
293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   - get the toolname (--tool=)
294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   - set VG_(clo_max_stackframe) (--max-stackframe=)
295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   - set VG_(clo_main_stacksize) (--main-stacksize=)
296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   That's all it does.  The main command line processing is done below
298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   by main_process_cmd_line_options.  Note that
299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   main_process_cmd_line_options has to handle but ignore the ones we
300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   have handled here.
301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void early_process_cmd_line_options ( /*OUT*/Int* need_help,
303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                             /*OUT*/HChar** tool )
304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt   i;
306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HChar* str;
307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert( VG_(args_for_valgrind) );
309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* parse the options we have (only the options we care about now) */
311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 0; i < VG_(sizeXA)( VG_(args_for_valgrind) ); i++) {
312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      str = * (HChar**) VG_(indexXA)( VG_(args_for_valgrind), i );
314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vg_assert(str);
315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // Nb: the version string goes to stdout.
317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if VG_XACT_CLO(str, "--version", VG_(log_output_sink).fd, 1) {
318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(log_output_sink).is_socket = False;
319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(printf)("valgrind-" VERSION "\n");
320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(exit)(0);
321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else if VG_XACT_CLO(str, "--help", *need_help, *need_help+1) {}
323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else if VG_XACT_CLO(str, "-h",     *need_help, *need_help+1) {}
324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else if VG_XACT_CLO(str, "--help-debug", *need_help, *need_help+2) {}
326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // The tool has already been determined, but we need to know the name
328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // here.
329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else if VG_STR_CLO(str, "--tool", *tool) {}
330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // Set up VG_(clo_max_stackframe) and VG_(clo_main_stacksize).
332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // These are needed by VG_(ii_create_image), which happens
333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // before main_process_cmd_line_options().
334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else if VG_INT_CLO(str, "--max-stackframe", VG_(clo_max_stackframe)) {}
335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else if VG_INT_CLO(str, "--main-stacksize", VG_(clo_main_stacksize)) {}
336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
339f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy StepanovInt reopen_output_fd(Bool xml) {
340f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov  // Returns FD
341f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov  Char *filename = NULL;
342f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov  Char *fsname_unexpanded = xml ? VG_(clo_xml_fname_unexpanded) :
343f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov                                 VG_(clo_log_fname_unexpanded);
344f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov  const Char *output_type = xml ? "xml" : "log";
345f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov  Int ret = -1;
346f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov  SysRes sres;
347f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov
348f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov  vg_assert(fsname_unexpanded != NULL);
349f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov  vg_assert(VG_(strlen)(fsname_unexpanded) <= 900); /* paranoia */
350f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov
351f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov  // Nb: we overwrite an existing file of this name without asking
352f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov  // any questions.
353f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov  filename = VG_(expand_file_name)(xml ? "--xml-file" : "--log-file",
354f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov                                   fsname_unexpanded);
355f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov  sres = VG_(open)(filename,
356f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov                   VKI_O_CREAT|VKI_O_WRONLY|VKI_O_TRUNC,
357f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov                   VKI_S_IRUSR|VKI_S_IWUSR);
358f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov  if (!sr_isError(sres)) {
359f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov    ret = sr_Res(sres);
360f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov    if (xml)
361f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov      VG_(clo_xml_fname_expanded) = filename;
362f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov    else
363f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov      VG_(clo_log_fname_expanded) = filename;
364f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov
365f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov    /* strdup here is probably paranoid overkill, but ... */
366f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov    // TODO: do we need to do anything with it?
367f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov    /* *fsname_unexpanded = VG_(strdup)( "main.mpclo.2",
368f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov                                         xml_fsname_unexpanded ); */
369f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov  } else {
370f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov    VG_(message)(Vg_UserMsg,
371f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov                 "Can't create %s file '%s' (%s); giving up!\n",
372f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov                 output_type, filename, VG_(strerror)(sr_Err(sres)));
373f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov    VG_(fmsg_bad_option)("--[xml|log]-file=<file>",
374f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov        "--[xml|log]-file=<file> (didn't work out for some reason.)");
375f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov    /*NOTREACHED*/
376f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov  }
377f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov
378f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov  return ret;
379f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov}
380f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov
381f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanovstatic Int move_fd_into_safe_range(Int fd, Bool xml) {
382f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov   OutputSink *sink = xml ? &(VG_(xml_output_sink)) : &(VG_(log_output_sink));
383f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov   // Move fd into the safe range, so it doesn't conflict with any app fds.
384f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov   fd = VG_(fcntl)(fd, VKI_F_DUPFD, VG_(fd_hard_limit));
385f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov   if (fd < 0) {
386f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov      VG_(printf)("valgrind: failed to move %s file fd "
387f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov                  "into safe range, using stderr\n", xml ? "XML" : "log");
388f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov      sink->fd = 2;   // stderr
389f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov      sink->is_socket = False;
390f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov   } else {
391f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov      sink->fd = fd;
392f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov      VG_(fcntl)(fd, VKI_F_SETFD, VKI_FD_CLOEXEC);
393f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov   }
394f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov   return fd;
395f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov}
396f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov
397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* The main processing for command line options.  See comments above
398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   on early_process_cmd_line_options.
399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Comments on how the logging options are handled:
401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   User can specify:
403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      --log-fd=      for a fd to write to (default setting, fd = 2)
404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      --log-file=    for a file name to write to
405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      --log-socket=  for a socket to write to
406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   As a result of examining these and doing relevant socket/file
408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   opening, a final fd is established.  This is stored in
409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(log_output_sink) in m_libcprint.  Also, if --log-file=STR was
410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   specified, then STR, after expansion of %p and %q templates within
411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   it, is stored in VG_(clo_log_fname_expanded), in m_options, just in
412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case anybody wants to know what it is.
413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   When printing, VG_(log_output_sink) is consulted to find the
415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   fd to send output to.
416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Exactly analogous actions are undertaken for the XML output
418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   channel, with the one difference that the default fd is -1, meaning
419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   the channel is disabled by default.
420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid main_process_cmd_line_options ( /*OUT*/Bool* logging_to_fd,
423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     const HChar* toolname )
424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // VG_(clo_log_fd) is used by all the messaging.  It starts as 2 (stderr)
426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // and we cannot change it until we know what we are changing it to is
427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // ok.  So we have tmp_log_fd to hold the tmp fd prior to that point.
428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int    i, tmp_log_fd, tmp_xml_fd;
429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int    toolname_len = VG_(strlen)(toolname);
430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Char*  tmp_str;         // Used in a couple of places.
431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   enum {
432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VgLogTo_Fd,
433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VgLogTo_File,
434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VgLogTo_Socket
435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } log_to = VgLogTo_Fd,   // Where is logging output to be sent?
436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     xml_to = VgLogTo_Fd;   // Where is XML output to be sent?
437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Temporarily holds the string STR specified with
439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      --{log,xml}-{name,socket}=STR.  'fs' stands for
440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      file-or-socket. */
441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Char* log_fsname_unexpanded = NULL;
442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Char* xml_fsname_unexpanded = NULL;
443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Log to stderr by default, but usage message goes to stdout.  XML
445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      output is initially disabled. */
446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tmp_log_fd = 2;
447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tmp_xml_fd = -1;
448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Check for sane path in ./configure --prefix=... */
450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (VG_LIBDIR[0] != '/')
451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(err_config_error)("Please use absolute paths in "
452b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                            "./configure --prefix=... or --libdir=...\n");
453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert( VG_(args_for_valgrind) );
455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* BEGIN command-line processing loop */
457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 0; i < VG_(sizeXA)( VG_(args_for_valgrind) ); i++) {
459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HChar* arg   = * (HChar**) VG_(indexXA)( VG_(args_for_valgrind), i );
461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HChar* colon = arg;
462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // Look for a colon in the option name.
464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      while (*colon && *colon != ':' && *colon != '=')
465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         colon++;
466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // Does it have the form "--toolname:foo"?  We have to do it at the start
468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // in case someone has combined a prefix with a core-specific option,
469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // eg.  "--memcheck:verbose".
470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (*colon == ':') {
471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (VG_STREQN(2,            arg,                "--") &&
472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             VG_STREQN(toolname_len, arg+2,              toolname) &&
473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             VG_STREQN(1,            arg+2+toolname_len, ":"))
474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         {
475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            // Prefix matches, convert "--toolname:foo" to "--foo".
476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            // Two things to note:
477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            // - We cannot modify the option in-place.  If we did, and then
478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            //   a child was spawned with --trace-children=yes, the
479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            //   now-non-prefixed option would be passed and could screw up
480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            //   the child.
481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            // - We create copies, and never free them.  Why?  Non-prefixed
482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            //   options hang around forever, so tools need not make copies
483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            //   of strings within them.  We need to have the same behaviour
484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            //   for prefixed options.  The pointer to the copy will be lost
485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            //   once we leave this function (although a tool may keep a
486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            //   pointer into it), but the space wasted is insignificant.
487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            //   (In bug #142197, the copies were being freed, which caused
488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            //   problems for tools that reasonably assumed that arguments
489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            //   wouldn't disappear on them.)
490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (0)
491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               VG_(printf)("tool-specific arg: %s\n", arg);
492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            arg = VG_(strdup)("main.mpclo.1", arg + toolname_len + 1);
493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            arg[0] = '-';
494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            arg[1] = '-';
495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            // prefix doesn't match, skip to next arg
498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            continue;
499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Ignore these options - they've already been handled */
503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if      VG_STREQN( 7, arg, "--tool=")              {}
504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else if VG_STREQN(20, arg, "--command-line-only=") {}
505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else if VG_STREQ(     arg, "--")                   {}
506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else if VG_STREQ(     arg, "-d")                   {}
507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else if VG_STREQN(16, arg, "--max-stackframe")     {}
508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else if VG_STREQN(16, arg, "--main-stacksize")     {}
509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else if VG_STREQN(14, arg, "--profile-heap")       {}
510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // These options are new.
512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else if (VG_STREQ(arg, "-v") ||
513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               VG_STREQ(arg, "--verbose"))
514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(clo_verbosity)++;
515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else if (VG_STREQ(arg, "-q") ||
517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               VG_STREQ(arg, "--quiet"))
518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(clo_verbosity)--;
519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else if VG_BOOL_CLO(arg, "--stats",          VG_(clo_stats)) {}
521b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      else if VG_BOOL_CLO(arg, "--xml",            VG_(clo_xml))
522b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         VG_(debugLog_setXml)(VG_(clo_xml));
523b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
524b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      else if VG_XACT_CLO(arg, "--vgdb=no",        VG_(clo_vgdb), Vg_VgdbNo) {}
525b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      else if VG_XACT_CLO(arg, "--vgdb=yes",       VG_(clo_vgdb), Vg_VgdbYes) {}
526b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      else if VG_XACT_CLO(arg, "--vgdb=full",      VG_(clo_vgdb), Vg_VgdbFull) {}
527b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      else if VG_INT_CLO (arg, "--vgdb-poll",      VG_(clo_vgdb_poll)) {}
528b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      else if VG_INT_CLO (arg, "--vgdb-error",     VG_(clo_vgdb_error)) {}
529b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      else if VG_STR_CLO (arg, "--vgdb-prefix",    VG_(clo_vgdb_prefix)) {}
530b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      else if VG_BOOL_CLO(arg, "--vgdb-shadow-registers",
531b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                            VG_(clo_vgdb_shadow_registers)) {}
532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else if VG_BOOL_CLO(arg, "--db-attach",      VG_(clo_db_attach)) {}
533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else if VG_BOOL_CLO(arg, "--demangle",       VG_(clo_demangle)) {}
534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else if VG_BOOL_CLO(arg, "--error-limit",    VG_(clo_error_limit)) {}
535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else if VG_INT_CLO (arg, "--error-exitcode", VG_(clo_error_exitcode)) {}
536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else if VG_BOOL_CLO(arg, "--show-emwarns",   VG_(clo_show_emwarns)) {}
537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else if VG_BOOL_CLO(arg, "--run-libc-freeres", VG_(clo_run_libc_freeres)) {}
539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else if VG_BOOL_CLO(arg, "--show-below-main",  VG_(clo_show_below_main)) {}
540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else if VG_BOOL_CLO(arg, "--time-stamp",       VG_(clo_time_stamp)) {}
541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else if VG_BOOL_CLO(arg, "--track-fds",        VG_(clo_track_fds)) {}
542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else if VG_BOOL_CLO(arg, "--trace-children",   VG_(clo_trace_children)) {}
543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else if VG_BOOL_CLO(arg, "--child-silent-after-fork",
544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            VG_(clo_child_silent_after_fork)) {}
545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else if VG_BOOL_CLO(arg, "--trace-sched",      VG_(clo_trace_sched)) {}
546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else if VG_BOOL_CLO(arg, "--trace-signals",    VG_(clo_trace_signals)) {}
547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else if VG_BOOL_CLO(arg, "--trace-symtab",     VG_(clo_trace_symtab)) {}
548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else if VG_STR_CLO (arg, "--trace-symtab-patt", VG_(clo_trace_symtab_patt)) {}
549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else if VG_BOOL_CLO(arg, "--trace-cfi",        VG_(clo_trace_cfi)) {}
550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else if VG_XACT_CLO(arg, "--debug-dump=syms",  VG_(clo_debug_dump_syms),
551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                     True) {}
552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else if VG_XACT_CLO(arg, "--debug-dump=line",  VG_(clo_debug_dump_line),
553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                     True) {}
554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else if VG_XACT_CLO(arg, "--debug-dump=frames",
555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               VG_(clo_debug_dump_frames), True) {}
556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else if VG_BOOL_CLO(arg, "--trace-redir",      VG_(clo_trace_redir)) {}
557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else if VG_BOOL_CLO(arg, "--trace-syscalls",   VG_(clo_trace_syscalls)) {}
559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else if VG_BOOL_CLO(arg, "--wait-for-gdb",     VG_(clo_wait_for_gdb)) {}
560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else if VG_STR_CLO (arg, "--db-command",       VG_(clo_db_command)) {}
561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else if VG_STR_CLO (arg, "--sim-hints",        VG_(clo_sim_hints)) {}
562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else if VG_BOOL_CLO(arg, "--sym-offsets",      VG_(clo_sym_offsets)) {}
563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else if VG_BOOL_CLO(arg, "--read-var-info",    VG_(clo_read_var_info)) {}
564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else if VG_INT_CLO (arg, "--dump-error",       VG_(clo_dump_error))   {}
566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else if VG_INT_CLO (arg, "--input-fd",         VG_(clo_input_fd))     {}
567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else if VG_INT_CLO (arg, "--sanity-level",     VG_(clo_sanity_level)) {}
568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else if VG_BINT_CLO(arg, "--num-callers",      VG_(clo_backtrace_size), 1,
569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                     VG_DEEPEST_BACKTRACE) {}
570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else if VG_XACT_CLO(arg, "--smc-check=none",  VG_(clo_smc_check),
572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                    Vg_SmcNone);
573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else if VG_XACT_CLO(arg, "--smc-check=stack", VG_(clo_smc_check),
574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                    Vg_SmcStack);
575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else if VG_XACT_CLO(arg, "--smc-check=all",   VG_(clo_smc_check),
576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                    Vg_SmcAll);
577b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      else if VG_XACT_CLO(arg, "--smc-check=all-non-file",
578b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                                    VG_(clo_smc_check),
579b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                                    Vg_SmcAllNonFile);
580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
581f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov      else if VG_STR_CLO (arg, "--memfs-malloc-path",  VG_(clo_memfs_malloc_path)) {}
582f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov      else if VG_INT_CLO (arg, "--memfs-page-size",   VG_(clo_memfs_page_size))   {}
583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else if VG_STR_CLO (arg, "--kernel-variant",  VG_(clo_kernel_variant)) {}
584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else if VG_BOOL_CLO(arg, "--dsymutil",        VG_(clo_dsymutil)) {}
586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
587b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      else if VG_STR_CLO (arg, "--trace-children-skip",
588b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                               VG_(clo_trace_children_skip)) {}
589b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      else if VG_STR_CLO (arg, "--trace-children-skip-by-arg",
590b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                               VG_(clo_trace_children_skip_by_arg)) {}
591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else if VG_BINT_CLO(arg, "--vex-iropt-verbosity",
593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       VG_(clo_vex_control).iropt_verbosity, 0, 10) {}
594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else if VG_BINT_CLO(arg, "--vex-iropt-level",
595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       VG_(clo_vex_control).iropt_level, 0, 2) {}
596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else if VG_BOOL_CLO(arg, "--vex-iropt-precise-memory-exns",
597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       VG_(clo_vex_control).iropt_precise_memory_exns) {}
598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else if VG_BINT_CLO(arg, "--vex-iropt-unroll-thresh",
599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       VG_(clo_vex_control).iropt_unroll_thresh, 0, 400) {}
600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else if VG_BINT_CLO(arg, "--vex-guest-max-insns",
601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       VG_(clo_vex_control).guest_max_insns, 1, 100) {}
602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else if VG_BINT_CLO(arg, "--vex-guest-chase-thresh",
603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       VG_(clo_vex_control).guest_chase_thresh, 0, 99) {}
604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else if VG_BOOL_CLO(arg, "--vex-guest-chase-cond",
605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       VG_(clo_vex_control).guest_chase_cond) {}
606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else if VG_INT_CLO(arg, "--log-fd", tmp_log_fd) {
608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         log_to = VgLogTo_Fd;
609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         log_fsname_unexpanded = NULL;
610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else if VG_INT_CLO(arg, "--xml-fd", tmp_xml_fd) {
612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         xml_to = VgLogTo_Fd;
613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         xml_fsname_unexpanded = NULL;
614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else if VG_STR_CLO(arg, "--log-file", log_fsname_unexpanded) {
617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         log_to = VgLogTo_File;
618f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov         VG_(clo_log_fname_unexpanded) =
619f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov             VG_(strdup)("", log_fsname_unexpanded);
620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else if VG_STR_CLO(arg, "--xml-file", xml_fsname_unexpanded) {
622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         xml_to = VgLogTo_File;
623f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov         VG_(clo_xml_fname_unexpanded) =
624f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov             VG_(strdup)("", xml_fsname_unexpanded);
625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else if VG_STR_CLO(arg, "--log-socket", log_fsname_unexpanded) {
628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         log_to = VgLogTo_Socket;
629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else if VG_STR_CLO(arg, "--xml-socket", xml_fsname_unexpanded) {
631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         xml_to = VgLogTo_Socket;
632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else if VG_STR_CLO(arg, "--xml-user-comment",
635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              VG_(clo_xml_user_comment)) {}
636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else if VG_STR_CLO(arg, "--suppressions", tmp_str) {
638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (VG_(clo_n_suppressions) >= VG_CLO_MAX_SFILES) {
639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(fmsg_bad_option)(arg,
640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               "Too many suppression files specified.\n"
641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               "Increase VG_CLO_MAX_SFILES and recompile.\n");
642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(clo_suppressions)[VG_(clo_n_suppressions)] = tmp_str;
644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(clo_n_suppressions)++;
645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else if VG_STR_CLO (arg, "--fullpath-after", tmp_str) {
648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (VG_(clo_n_fullpath_after) >= VG_CLO_MAX_FULLPATH_AFTER) {
649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(fmsg_bad_option)(arg,
650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               "Too many --fullpath-after= specifications.\n"
651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               "Increase VG_CLO_MAX_FULLPATH_AFTER and recompile.\n");
652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(clo_fullpath_after)[VG_(clo_n_fullpath_after)] = tmp_str;
654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(clo_n_fullpath_after)++;
655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else if VG_STR_CLO(arg, "--require-text-symbol", tmp_str) {
658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (VG_(clo_n_req_tsyms) >= VG_CLO_MAX_REQ_TSYMS) {
659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(fmsg_bad_option)(arg,
660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               "Too many --require-text-symbol= specifications.\n"
661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               "Increase VG_CLO_MAX_REQ_TSYMS and recompile.\n");
662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* String needs to be of the form C?*C?*, where C is any
664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            character, but is the same both times.  Having it in this
665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            form facilitates finding the boundary between the sopatt
666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            and the fnpatt just by looking for the second occurrence
667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            of C, without hardwiring any assumption about what C
668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            is. */
669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Char patt[7];
670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Bool ok = True;
671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ok = tmp_str && VG_(strlen)(tmp_str) > 0;
672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (ok) {
673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           patt[0] = patt[3] = tmp_str[0];
674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           patt[1] = patt[4] = '?';
675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           patt[2] = patt[5] = '*';
676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           patt[6] = 0;
677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           ok = VG_(string_match)(patt, tmp_str);
678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (!ok) {
680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(fmsg_bad_option)(arg,
681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               "Invalid --require-text-symbol= specification.\n");
682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(clo_req_tsyms)[VG_(clo_n_req_tsyms)] = tmp_str;
684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(clo_n_req_tsyms)++;
685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* "stuvwxyz" --> stuvwxyz (binary) */
688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else if VG_STR_CLO(arg, "--trace-flags", tmp_str) {
689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Int j;
690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (8 != VG_(strlen)(tmp_str)) {
692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(fmsg_bad_option)(arg,
693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               "--trace-flags argument must have 8 digits\n");
694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         for (j = 0; j < 8; j++) {
696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if      ('0' == tmp_str[j]) { /* do nothing */ }
697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            else if ('1' == tmp_str[j]) VG_(clo_trace_flags) |= (1 << (7-j));
698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            else {
699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               VG_(fmsg_bad_option)(arg,
700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  "--trace-flags argument can only contain 0s and 1s\n");
701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* "stuvwxyz" --> stuvwxyz (binary) */
706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else if VG_STR_CLO(arg, "--profile-flags", tmp_str) {
707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Int j;
708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (8 != VG_(strlen)(tmp_str)) {
710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(fmsg_bad_option)(arg,
711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               "--profile-flags argument must have 8 digits\n");
712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         for (j = 0; j < 8; j++) {
714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if      ('0' == tmp_str[j]) { /* do nothing */ }
715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            else if ('1' == tmp_str[j]) VG_(clo_profile_flags) |= (1 << (7-j));
716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            else {
717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               VG_(fmsg_bad_option)(arg,
718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  "--profile-flags argument can only contain 0s and 1s\n");
719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else if VG_INT_CLO (arg, "--trace-notbelow", VG_(clo_trace_notbelow)) {}
724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else if VG_XACT_CLO(arg, "--gen-suppressions=no",
726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               VG_(clo_gen_suppressions), 0) {}
727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else if VG_XACT_CLO(arg, "--gen-suppressions=yes",
728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               VG_(clo_gen_suppressions), 1) {}
729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else if VG_XACT_CLO(arg, "--gen-suppressions=all",
730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               VG_(clo_gen_suppressions), 2) {}
731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
732b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      else if VG_STR_CLO(arg, "--nacl-file", VG_(clo_nacl_file)) {}
733b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else if ( ! VG_(needs).command_line_options
735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             || ! VG_TDICT_CALL(tool_process_cmd_line_option, arg) ) {
736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(fmsg_bad_option)(arg, "");
737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* END command-line processing loop */
741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
742b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /* Determine the path prefix for vgdb */
743b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (VG_(clo_vgdb_prefix) == NULL)
744b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov     VG_(clo_vgdb_prefix) = VG_(vgdb_prefix_default)();
745b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Make VEX control parameters sane */
747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (VG_(clo_vex_control).guest_chase_thresh
749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       >= VG_(clo_vex_control).guest_max_insns)
750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(clo_vex_control).guest_chase_thresh
751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         = VG_(clo_vex_control).guest_max_insns - 1;
752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (VG_(clo_vex_control).guest_chase_thresh < 0)
754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(clo_vex_control).guest_chase_thresh = 0;
755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Check various option values */
757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (VG_(clo_verbosity) < 0)
759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(clo_verbosity) = 0;
760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
761b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   VG_(dyn_vgdb_error) = VG_(clo_vgdb_error);
762b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* If XML output is requested, check that the tool actually
764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      supports it. */
765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (VG_(clo_xml) && !VG_(needs).xml_output) {
766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(clo_xml) = False;
767f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov      VG_(message)(Vg_UserMsg,
768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         "%s does not support XML output.\n", VG_(details).name);
769f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov      VG_(fmsg_bad_option)("--xml=yes", "\n");
770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /*NOTREACHED*/
771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert( VG_(clo_gen_suppressions) >= 0 );
774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert( VG_(clo_gen_suppressions) <= 2 );
775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* If we've been asked to emit XML, mash around various other
777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      options so as to constrain the output somewhat, and to remove
778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      any need for user input during the run.
779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   */
780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (VG_(clo_xml)) {
781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* We can't allow --gen-suppressions=yes, since that requires us
783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         to print the error and then ask the user if she wants a
784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         suppression for it, but in XML mode we won't print it until
785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         we know whether we also need to print a suppression.  Hence a
786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         circular dependency.  So disallow this.
787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         (--gen-suppressions=all is still OK since we don't need any
788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         user interaction in this case.) */
789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (VG_(clo_gen_suppressions) == 1) {
790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(fmsg_bad_option)(
791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            "--xml=yes together with --gen-suppressions=yes",
792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            "When --xml=yes is specified, --gen-suppressions=no\n"
793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            "or --gen-suppressions=all is allowed, but not "
794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            "--gen-suppressions=yes.\n");
795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* We can't allow DB attaching (or we maybe could, but results
798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         could be chaotic ..) since it requires user input.  Hence
799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         disallow. */
800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (VG_(clo_db_attach)) {
801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(fmsg_bad_option)(
802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            "--xml=yes together with --db-attach=yes",
803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            "--db-attach=yes is not allowed with --xml=yes\n"
804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            "because it would require user input.\n");
805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Disallow dump_error in XML mode; sounds like a recipe for
808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         chaos.  No big deal; dump_error is a flag for debugging V
809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         itself. */
810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (VG_(clo_dump_error) > 0) {
811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(fmsg_bad_option)("--xml=yes together with --dump-error", "");
812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Disable error limits (this might be a bad idea!) */
815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(clo_error_limit) = False;
816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Disable emulation warnings */
817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Also, we want to set options for the leak checker, but that
819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         will have to be done in Memcheck's flag-handling code, not
820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         here. */
821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* All non-logging-related options have been checked.  If the logging
824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      option specified is ok, we can switch to it, as we know we won't
825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      have to generate any other command-line-related error messages.
826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      (So far we should be still attached to stderr, so we can show on
827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      the terminal any problems to do with processing command line
828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      opts.)
829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      So set up logging now.  After this is done, VG_(log_output_sink)
831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      and (if relevant) VG_(xml_output_sink) should be connected to
832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      whatever sink has been selected, and we indiscriminately chuck
833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      stuff into it without worrying what the nature of it is.  Oh the
834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      wonder of Unix streams. */
835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(VG_(log_output_sink).fd == 2 /* stderr */);
837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(VG_(log_output_sink).is_socket == False);
838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(VG_(clo_log_fname_expanded) == NULL);
839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(VG_(xml_output_sink).fd == -1 /* disabled */);
841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(VG_(xml_output_sink).is_socket == False);
842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(VG_(clo_xml_fname_expanded) == NULL);
843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --- set up the normal text output channel --- */
845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (log_to) {
847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case VgLogTo_Fd:
849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vg_assert(log_fsname_unexpanded == NULL);
850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case VgLogTo_File: {
853f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov         tmp_log_fd = reopen_output_fd(False);
854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case VgLogTo_Socket: {
858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vg_assert(log_fsname_unexpanded != NULL);
859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vg_assert(VG_(strlen)(log_fsname_unexpanded) <= 900); /* paranoia */
860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         tmp_log_fd = VG_(connect_via_socket)( log_fsname_unexpanded );
861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (tmp_log_fd == -1) {
862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(fmsg)("Invalid --log-socket spec of '%s'\n",
863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      log_fsname_unexpanded);
864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(exit)(1);
865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /*NOTREACHED*/
866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 }
867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (tmp_log_fd == -2) {
868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(umsg)("failed to connect to logging server '%s'.\n"
869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      "Log messages will sent to stderr instead.\n",
870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      log_fsname_unexpanded );
871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* We don't change anything here. */
873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vg_assert(VG_(log_output_sink).fd == 2);
874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            tmp_log_fd = 2;
875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 } else {
876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vg_assert(tmp_log_fd > 0);
877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(log_output_sink).is_socket = True;
878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* --- set up the XML output channel --- */
884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (xml_to) {
886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case VgLogTo_Fd:
888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vg_assert(xml_fsname_unexpanded == NULL);
889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case VgLogTo_File: {
892f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov         tmp_xml_fd = reopen_output_fd(True);
893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case VgLogTo_Socket: {
897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vg_assert(xml_fsname_unexpanded != NULL);
898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vg_assert(VG_(strlen)(xml_fsname_unexpanded) <= 900); /* paranoia */
899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         tmp_xml_fd = VG_(connect_via_socket)( xml_fsname_unexpanded );
900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (tmp_xml_fd == -1) {
901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(fmsg)("Invalid --xml-socket spec of '%s'\n",
902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      xml_fsname_unexpanded );
903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(exit)(1);
904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /*NOTREACHED*/
905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 }
906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (tmp_xml_fd == -2) {
907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(umsg)("failed to connect to XML logging server '%s'.\n"
908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      "XML output will sent to stderr instead.\n",
909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      xml_fsname_unexpanded);
910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* We don't change anything here. */
911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vg_assert(VG_(xml_output_sink).fd == 2);
912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            tmp_xml_fd = 2;
913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 } else {
914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vg_assert(tmp_xml_fd > 0);
915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(xml_output_sink).is_socket = True;
916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* If we've got this far, and XML mode was requested, but no XML
922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      output channel appears to have been specified, just stop.  We
923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      could continue, and XML output will simply vanish into nowhere,
924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      but that is likely to confuse the hell out of users, which is
925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      distinctly Ungood. */
926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (VG_(clo_xml) && tmp_xml_fd == -1) {
927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(fmsg_bad_option)(
928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          "--xml=yes, but no XML destination specified",
929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          "--xml=yes has been specified, but there is no XML output\n"
930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          "destination.  You must specify an XML output destination\n"
931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          "using --xml-fd, --xml-file or --xml-socket.\n"
932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      );
933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Finalise the output fds: the log fd ..
936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (tmp_log_fd >= 0) {
938f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov      tmp_log_fd = move_fd_into_safe_range(tmp_log_fd, False);
939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // If they said --log-fd=-1, don't print anything.  Plausible for use in
941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // regression testing suites that use client requests to count errors.
942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(log_output_sink).fd = -1;
943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(log_output_sink).is_socket = False;
944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Finalise the output fds: and the XML fd ..
947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (tmp_xml_fd >= 0) {
949f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov      tmp_xml_fd = move_fd_into_safe_range(tmp_xml_fd, True);
950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // If they said --xml-fd=-1, don't print anything.  Plausible for use in
952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // regression testing suites that use client requests to count errors.
953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(xml_output_sink).fd = -1;
954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(xml_output_sink).is_socket = False;
955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Suppressions related stuff
958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (VG_(clo_n_suppressions) < VG_CLO_MAX_SFILES-1 &&
960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       (VG_(needs).core_errors || VG_(needs).tool_errors)) {
961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* If we haven't reached the max number of suppressions, load
962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         the default one. */
963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      static const Char default_supp[] = "default.supp";
964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Int len = VG_(strlen)(VG_(libdir)) + 1 + sizeof(default_supp);
965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Char *buf = VG_(arena_malloc)(VG_AR_CORE, "main.mpclo.3", len);
966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(sprintf)(buf, "%s/%s", VG_(libdir), default_supp);
967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(clo_suppressions)[VG_(clo_n_suppressions)] = buf;
968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(clo_n_suppressions)++;
969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *logging_to_fd = log_to == VgLogTo_Fd || log_to == VgLogTo_Socket;
972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Write the name and value of log file qualifiers to the xml file.
975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void print_file_vars(Char* format)
976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int i = 0;
978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   while (format[i]) {
980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (format[i] == '%') {
981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // We saw a '%'.  What's next...
982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         i++;
983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 if ('q' == format[i]) {
984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            i++;
985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if ('{' == format[i]) {
986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	       // Get the env var name, print its contents.
987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	       Char* qualname;
988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               Char* qual;
989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               i++;
990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               qualname = &format[i];
991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               while (True) {
992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		  if ('}' == format[i]) {
993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     // Temporarily replace the '}' with NUL to extract var
994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     // name.
995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		     format[i] = 0;
996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     qual = VG_(getenv)(qualname);
997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		     break;
998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  }
999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  i++;
1000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               }
1001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1002b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               VG_(printf_xml)(
1003b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  "<logfilequalifier> <var>%pS</var> "
1004b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  "<value>%pS</value> </logfilequalifier>\n",
1005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  qualname,qual
1006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               );
1007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	       format[i] = '}';
1008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	       i++;
1009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    }
1010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
1012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 i++;
1013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*====================================================================*/
1019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*=== Printing the preamble                                        ===*/
1020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*====================================================================*/
1021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Print the command, escaping any chars that require it.
1023b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic void umsg_arg(const Char* arg)
1024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   SizeT len = VG_(strlen)(arg);
1026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Char* special = " \\<>";
1027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int i;
1028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 0; i < len; i++) {
1029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (VG_(strchr)(special, arg[i])) {
1030b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        VG_(umsg)("\\");   // escape with a backslash if necessary
1031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1032b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      VG_(umsg)("%c", arg[i]);
1033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1036b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov// Send output to the XML-stream and escape any XML meta-characters.
1037b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic void xml_arg(const Char* arg) {
1038b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov  VG_(printf_xml)("%t", arg);
1039b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
1040b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Ok, the logging sink is running now.  Print a suitable preamble.
1042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   If logging to file or a socket, write details of parent PID and
1043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   command line args, to help people trying to interpret the
1044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   results of a run which encompasses multiple processes. */
1045f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov// TODO(timurrrr): we add a non-static declaration of this function since
1046f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov// we need it in coregrind/m_libcproc.c
1047f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov// NOTE: Keep this definition in sync with coregrind/m_libcproc.c
1048f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov//       in case of merge conflict.
1049f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov// Should we move it to some header file?
1050f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanovvoid print_preamble ( Bool logging_to_fd, const HChar* toolname );
1051f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov
1052f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanovvoid print_preamble ( Bool logging_to_fd, const HChar* toolname )
1053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int    i;
1055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HChar* xpre  = VG_(clo_xml) ? "  <line>" : "";
1056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HChar* xpost = VG_(clo_xml) ? "</line>" : "";
1057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt (*umsg_or_xml)( const HChar*, ... )
1058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      = VG_(clo_xml) ? VG_(printf_xml) : VG_(umsg);
1059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1060b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   void (*umsg_or_xml_arg)( const Char* )
1061b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      = VG_(clo_xml) ? xml_arg : umsg_arg;
1062b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1063f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov   static const char* last_toolname = NULL;
1064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert( VG_(args_for_client) );
1065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert( VG_(args_for_valgrind) );
1066f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov
1067f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov   // This way you may pass toolname == NULL provided the first invocation
1068f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov   // with toolname != NULL takes place in valgrind_main().
1069f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov   toolname = (toolname == NULL ? last_toolname : toolname);
1070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert( toolname );
1071f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov   last_toolname = toolname;
1072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (VG_(clo_xml)) {
1074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf_xml)("<?xml version=\"1.0\"?>\n");
1075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf_xml)("\n");
1076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf_xml)("<valgrindoutput>\n");
1077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf_xml)("\n");
1078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf_xml)("<protocolversion>4</protocolversion>\n");
1079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf_xml)("<protocoltool>%s</protocoltool>\n", toolname);
1080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf_xml)("\n");
1081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1083f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov   if (VG_(clo_xml) || VG_(clo_verbosity) > 0) {
1084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (VG_(clo_xml))
1086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(printf_xml)("<preamble>\n");
1087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Tool details */
1089b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      umsg_or_xml( VG_(clo_xml) ? "%s%pS%pS%pS, %pS%s\n" : "%s%s%s%s, %s%s\n",
1090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   xpre,
1091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   VG_(details).name,
1092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   NULL == VG_(details).version ? "" : "-",
1093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   NULL == VG_(details).version
1094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      ? (Char*)"" : VG_(details).version,
1095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   VG_(details).description,
1096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   xpost );
1097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (VG_(strlen)(toolname) >= 4 && VG_STREQN(4, toolname, "exp-")) {
1099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         umsg_or_xml(
1100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            "%sNOTE: This is an Experimental-Class Valgrind Tool%s\n",
1101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            xpre, xpost
1102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         );
1103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1105b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      umsg_or_xml( VG_(clo_xml) ? "%s%pS%s\n" : "%s%s%s\n",
1106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   xpre, VG_(details).copyright_author, xpost );
1107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Core details */
1109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      umsg_or_xml(
1110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         "%sUsing Valgrind-%s and LibVEX; rerun with -h for copyright info%s\n",
1111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         xpre, VERSION, xpost
1112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      );
1113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // Print the command line.  At one point we wrapped at 80 chars and
1115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // printed a '\' as a line joiner, but that makes it hard to cut and
1116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // paste the command line (because of the "==pid==" prefixes), so we now
1117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // favour utility and simplicity over aesthetics.
1118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      umsg_or_xml("%sCommand: ", xpre);
1119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (VG_(args_the_exename))
1120b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov          umsg_or_xml_arg(VG_(args_the_exename));
1121b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      for (i = 0; i < VG_(sizeXA)( VG_(args_for_client) ); i++) {
1123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HChar* s = *(HChar**)VG_(indexXA)( VG_(args_for_client), i );
1124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         umsg_or_xml(" ");
1125b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         umsg_or_xml_arg(s);
1126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      umsg_or_xml("%s\n", xpost);
1128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (VG_(clo_xml))
1130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(printf_xml)("</preamble>\n");
1131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Print the parent PID, and other stuff, if necessary.
1134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (!VG_(clo_xml) && VG_(clo_verbosity) > 0 && !logging_to_fd) {
1135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(umsg)("Parent PID: %d\n", VG_(getppid)());
1136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else
1138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (VG_(clo_xml)) {
1139f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov      Char *xml_fname_unexpanded = VG_(clo_xml_fname_unexpanded);
1140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf_xml)("\n");
1141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf_xml)("<pid>%d</pid>\n", VG_(getpid)());
1142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf_xml)("<ppid>%d</ppid>\n", VG_(getppid)());
1143b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      VG_(printf_xml)("<tool>%pS</tool>\n", toolname);
1144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (xml_fname_unexpanded)
1145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         print_file_vars(xml_fname_unexpanded);
1146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (VG_(clo_xml_user_comment)) {
1147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Note: the user comment itself is XML and is therefore to
1148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            be passed through verbatim (%s) rather than escaped
1149b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            (%pS). */
1150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(printf_xml)("<usercomment>%s</usercomment>\n",
1151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         VG_(clo_xml_user_comment));
1152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf_xml)("\n");
1154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf_xml)("<args>\n");
1155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf_xml)("  <vargv>\n");
1157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (VG_(name_of_launcher))
1158b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         VG_(printf_xml)("    <exe>%pS</exe>\n",
1159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                VG_(name_of_launcher));
1160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else
1161b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         VG_(printf_xml)("    <exe>%pS</exe>\n",
1162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                "(launcher name unknown)");
1163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      for (i = 0; i < VG_(sizeXA)( VG_(args_for_valgrind) ); i++) {
1164b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         VG_(printf_xml)(
1165b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            "    <arg>%pS</arg>\n",
1166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            * (HChar**) VG_(indexXA)( VG_(args_for_valgrind), i )
1167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         );
1168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf_xml)("  </vargv>\n");
1170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf_xml)("  <argv>\n");
1172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (VG_(args_the_exename))
1173b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         VG_(printf_xml)("    <exe>%pS</exe>\n",
1174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                VG_(args_the_exename));
1175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      for (i = 0; i < VG_(sizeXA)( VG_(args_for_client) ); i++) {
1176b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         VG_(printf_xml)(
1177b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            "    <arg>%pS</arg>\n",
1178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            * (HChar**) VG_(indexXA)( VG_(args_for_client), i )
1179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         );
1180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf_xml)("  </argv>\n");
1182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf_xml)("</args>\n");
1184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Last thing in the preamble is a blank line.
1187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (VG_(clo_xml))
1188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf_xml)("\n");
1189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else if (VG_(clo_verbosity) > 0)
1190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(umsg)("\n");
1191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (VG_(clo_verbosity) > 1) {
1193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      SysRes fd;
1194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VexArch vex_arch;
1195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VexArchInfo vex_archinfo;
1196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (!logging_to_fd)
1197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(message)(Vg_DebugMsg, "\n");
1198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(message)(Vg_DebugMsg, "Valgrind options:\n");
1199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      for (i = 0; i < VG_(sizeXA)( VG_(args_for_valgrind) ); i++) {
1200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(message)(Vg_DebugMsg,
1201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     "   %s\n",
1202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     * (HChar**) VG_(indexXA)( VG_(args_for_valgrind), i ));
1203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(message)(Vg_DebugMsg, "Contents of /proc/version:\n");
1206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fd = VG_(open) ( "/proc/version", VKI_O_RDONLY, 0 );
1207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (sr_isError(fd)) {
1208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(message)(Vg_DebugMsg, "  can't open /proc/version\n");
1209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
1210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#        define BUF_LEN    256
1211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Char version_buf[BUF_LEN];
1212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Int n = VG_(read) ( sr_Res(fd), version_buf, BUF_LEN );
1213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vg_assert(n <= BUF_LEN);
1214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (n > 0) {
1215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            version_buf[n-1] = '\0';
1216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(message)(Vg_DebugMsg, "  %s\n", version_buf);
1217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
1218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(message)(Vg_DebugMsg, "  (empty?)\n");
1219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
1220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(close)(sr_Res(fd));
1221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#        undef BUF_LEN
1222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(machine_get_VexArchInfo)( &vex_arch, &vex_archinfo );
1225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(message)(
1226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Vg_DebugMsg,
1227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         "Arch and hwcaps: %s, %s\n",
1228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         LibVEX_ppVexArch   ( vex_arch ),
1229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         LibVEX_ppVexHwCaps ( vex_arch, vex_archinfo.hwcaps )
1230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      );
1231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(message)(
1232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Vg_DebugMsg,
1233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         "Page sizes: currently %d, max supported %d\n",
1234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         (Int)VKI_PAGE_SIZE, (Int)VKI_MAX_PAGE_SIZE
1235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      );
1236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(message)(Vg_DebugMsg,
1237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   "Valgrind library directory: %s\n", VG_(libdir));
1238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*====================================================================*/
1243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*=== File descriptor setup                                        ===*/
1244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*====================================================================*/
1245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Number of file descriptors that Valgrind tries to reserve for
1247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   it's own use - just a small constant. */
1248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define N_RESERVED_FDS (10)
1249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void setup_file_descriptors(void)
1251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   struct vki_rlimit rl;
1253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool show = False;
1254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Get the current file descriptor limits. */
1256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (VG_(getrlimit)(VKI_RLIMIT_NOFILE, &rl) < 0) {
1257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      rl.rlim_cur = 1024;
1258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      rl.rlim_max = 1024;
1259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  if defined(VGO_darwin)
1262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Darwin lies. It reports file max as RLIM_INFINITY but
1263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      silently disallows anything bigger than 10240. */
1264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (rl.rlim_cur >= 10240  &&  rl.rlim_max == 0x7fffffffffffffffULL) {
1265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      rl.rlim_max = 10240;
1266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  endif
1268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (show)
1270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf)("fd limits: host, before: cur %lu max %lu\n",
1271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  (UWord)rl.rlim_cur, (UWord)rl.rlim_max);
1272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1273b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /* kcc: workaround for a Linux Kernel bug */
1274b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (rl.rlim_cur > 1000000)
1275b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      rl.rlim_cur = 1000000;
1276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Work out where to move the soft limit to. */
1278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (rl.rlim_cur + N_RESERVED_FDS <= rl.rlim_max) {
1279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      rl.rlim_cur = rl.rlim_cur + N_RESERVED_FDS;
1280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
1281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      rl.rlim_cur = rl.rlim_max;
1282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Reserve some file descriptors for our use. */
1285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(fd_soft_limit) = rl.rlim_cur - N_RESERVED_FDS;
1286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(fd_hard_limit) = rl.rlim_cur - N_RESERVED_FDS;
1287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Update the soft limit. */
1289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(setrlimit)(VKI_RLIMIT_NOFILE, &rl);
1290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (show) {
1292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf)("fd limits: host,  after: cur %lu max %lu\n",
1293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  (UWord)rl.rlim_cur, (UWord)rl.rlim_max);
1294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf)("fd limits: guest       : cur %u max %u\n",
1295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  VG_(fd_soft_limit), VG_(fd_hard_limit));
1296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (VG_(cl_exec_fd) != -1)
1299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(cl_exec_fd) = VG_(safe_fd)( VG_(cl_exec_fd) );
1300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*====================================================================*/
1304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*=== BB profiling                                                 ===*/
1305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*====================================================================*/
1306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
1308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid show_BB_profile ( BBProfEntry tops[], UInt n_tops, ULong score_total )
1309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ULong score_cumul,   score_here;
1311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Char  buf_cumul[10], buf_here[10];
1312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Char  name[64];
1313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int   r;
1314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(printf)("\n");
1316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(printf)("-----------------------------------------------------------\n");
1317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(printf)("--- BEGIN BB Profile (summary of scores)                ---\n");
1318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(printf)("-----------------------------------------------------------\n");
1319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(printf)("\n");
1320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(printf)("Total score = %lld\n\n", score_total);
1322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   score_cumul = 0;
1324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (r = 0; r < n_tops; r++) {
1325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (tops[r].addr == 0)
1326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         continue;
1327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      name[0] = 0;
1328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(get_fnname_w_offset)(tops[r].addr, name, 64);
1329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      name[63] = 0;
1330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      score_here = tops[r].score;
1331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      score_cumul += score_here;
1332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(percentify)(score_cumul, score_total, 2, 6, buf_cumul);
1333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(percentify)(score_here,  score_total, 2, 6, buf_here);
1334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf)("%3d: (%9lld %s)   %9lld %s      0x%llx %s\n",
1335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  r,
1336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  score_cumul, buf_cumul,
1337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  score_here,  buf_here, tops[r].addr, name );
1338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(printf)("\n");
1341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(printf)("-----------------------------------------------------------\n");
1342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(printf)("--- BB Profile (BB details)                             ---\n");
1343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(printf)("-----------------------------------------------------------\n");
1344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(printf)("\n");
1345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   score_cumul = 0;
1347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (r = 0; r < n_tops; r++) {
1348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (tops[r].addr == 0)
1349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         continue;
1350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      name[0] = 0;
1351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(get_fnname_w_offset)(tops[r].addr, name, 64);
1352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      name[63] = 0;
1353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      score_here = tops[r].score;
1354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      score_cumul += score_here;
1355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(percentify)(score_cumul, score_total, 2, 6, buf_cumul);
1356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(percentify)(score_here,  score_total, 2, 6, buf_here);
1357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf)("\n");
1358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf)("=-=-=-=-=-=-=-=-=-=-=-=-=-= begin BB rank %d "
1359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  "=-=-=-=-=-=-=-=-=-=-=-=-=-=\n\n", r);
1360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf)("%3d: (%9lld %s)   %9lld %s      0x%llx %s\n",
1361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  r,
1362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  score_cumul, buf_cumul,
1363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  score_here,  buf_here, tops[r].addr, name );
1364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf)("\n");
1365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(discard_translations)(tops[r].addr, 1, "bb profile");
1366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(translate)(0, tops[r].addr, True, VG_(clo_profile_flags), 0, True);
1367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf)("=-=-=-=-=-=-=-=-=-=-=-=-=-=  end BB rank %d  "
1368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  "=-=-=-=-=-=-=-=-=-=-=-=-=-=\n\n", r);
1369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(printf)("\n");
1372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(printf)("-----------------------------------------------------------\n");
1373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(printf)("--- END BB Profile                                      ---\n");
1374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(printf)("-----------------------------------------------------------\n");
1375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(printf)("\n");
1376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*====================================================================*/
1380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*=== main()                                                       ===*/
1381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*====================================================================*/
1382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* When main() is entered, we should be on the following stack, not
1384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   the one the kernel gave us.  We will run on this stack until
1385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   simulation of the root thread is started, at which point a transfer
1386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   is made to a dynamically allocated stack.  This is for the sake of
1387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   uniform overflow detection for all Valgrind threads.  This is
1388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   marked global even though it isn't, because assembly code below
1389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   needs to reference the name. */
1390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*static*/ VgStack VG_(interim_stack);
1392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* These are the structures used to hold info for creating the initial
1394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   client image.
1395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   'iicii' mostly holds important register state present at system
1397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   startup (_start_valgrind).  valgrind_main() then fills in the rest
1398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   of it and passes it to VG_(ii_create_image)().  That produces
1399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   'iifii', which is later handed to VG_(ii_finalise_image). */
1400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* In all OS-instantiations, the_iicii has a field .sp_at_startup.
1402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   This should get some address inside the stack on which we gained
1403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   control (eg, it could be the SP at startup).  It doesn't matter
1404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   exactly where in the stack it is.  This value is passed to the
1405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   address space manager at startup.  On Linux, aspacem then uses it
1406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   to identify the initial stack segment and hence the upper end of
1407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   the usable address space. */
1408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IICreateImageInfo   the_iicii;
1410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IIFinaliseImageInfo the_iifii;
1411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* A simple pair structure, used for conveying debuginfo handles to
1414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   calls to VG_TRACK(new_mem_startup, ...). */
1415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef  struct { Addr a; ULong ull; }  Addr_n_ULong;
1416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --- Forwards decls to do with shutdown --- */
1419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void final_tidyup(ThreadId tid);
1421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Do everything which needs doing when the last thread exits */
1423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
1424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid shutdown_actions_NORETURN( ThreadId tid,
1425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                VgSchedReturnCode tids_schedretcode );
1426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --- end of Forwards decls to do with shutdown --- */
1428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* By the time we get to valgrind_main, the_iicii should already have
1431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   been filled in with any important details as required by whatever
1432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   OS we have been built for.
1433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
1434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
1435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownInt valgrind_main ( Int argc, HChar **argv, HChar **envp )
1436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HChar*  toolname           = "memcheck";    // default to Memcheck
1438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int     need_help          = 0; // 0 = no, 1 = --help, 2 = --help-debug
1439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ThreadId tid_main          = VG_INVALID_THREADID;
1440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool    logging_to_fd      = False;
1441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int     loglevel, i;
1442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   struct vki_rlimit zero = { 0, 0 };
1443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   XArray* addr2dihandle = NULL;
1444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //============================================================
1446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //
1447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Nb: startup is complex.  Prerequisites are shown at every step.
1448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // *** Be very careful when messing with the order ***
1449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //
1450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // The first order of business is to get debug logging, the address
1451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // space manager and the dynamic memory manager up and running.
1452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Once that's done, we can relax a bit.
1453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //
1454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //============================================================
1455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* This is needed to make VG_(getenv) usable early. */
1457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(client_envp) = (Char**)envp;
1458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //--------------------------------------------------------------
1460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Start up Mach kernel interface, if any
1461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //   p: none
1462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //--------------------------------------------------------------
1463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  if defined(VGO_darwin)
1464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(mach_init)();
1465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  endif
1466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //--------------------------------------------------------------
1468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Start up the logging mechanism
1469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //   p: none
1470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //--------------------------------------------------------------
1471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Start the debugging-log system ASAP.  First find out how many
1472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      "-d"s were specified.  This is a pre-scan of the command line.  Also
1473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      get --profile-heap=yes which is needed by the time we start up dynamic
1474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      memory management.  */
1475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   loglevel = 0;
1476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 1; i < argc; i++) {
1477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (argv[i][0] != '-') break;
1478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if VG_STREQ(argv[i], "--") break;
1479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if VG_STREQ(argv[i], "-d") loglevel++;
1480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if VG_BOOL_CLO(argv[i], "--profile-heap", VG_(clo_profile_heap)) {}
1481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ... and start the debug logger.  Now we can safely emit logging
1484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      messages all through startup. */
1485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(debugLog_startup)(loglevel, "Stage 2 (main)");
1486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(debugLog)(1, "main", "Welcome to Valgrind version "
1487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            VERSION " debug logging\n");
1488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //--------------------------------------------------------------
1490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Ensure we're on a plausible stack.
1491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //   p: logging
1492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //--------------------------------------------------------------
1493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(debugLog)(1, "main", "Checking current stack is plausible\n");
1494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   { HChar* limLo  = (HChar*)(&VG_(interim_stack).bytes[0]);
1495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     HChar* limHi  = limLo + sizeof(VG_(interim_stack));
1496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     HChar* aLocal = (HChar*)&zero; /* any auto local will do */
1497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     if (aLocal < limLo || aLocal >= limHi) {
1498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* something's wrong.  Stop. */
1499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        VG_(debugLog)(0, "main", "Root stack %p to %p, a local %p\n",
1500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          limLo, limHi, aLocal );
1501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        VG_(debugLog)(0, "main", "Valgrind: FATAL: "
1502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 "Initial stack switched failed.\n");
1503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        VG_(debugLog)(0, "main", "   Cannot continue.  Sorry.\n");
1504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        VG_(exit)(1);
1505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     }
1506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //--------------------------------------------------------------
1509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Ensure we have a plausible pointer to the stack on which
1510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // we gained control (not the current stack!)
1511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //   p: logging
1512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //--------------------------------------------------------------
1513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(debugLog)(1, "main", "Checking initial stack was noted\n");
1514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (the_iicii.sp_at_startup == 0) {
1515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(debugLog)(0, "main", "Valgrind: FATAL: "
1516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               "Initial stack was not noted.\n");
1517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(debugLog)(0, "main", "   Cannot continue.  Sorry.\n");
1518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(exit)(1);
1519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //--------------------------------------------------------------
1522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Start up the address space manager, and determine the
1523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // approximate location of the client's stack
1524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //   p: logging, plausible-stack
1525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //--------------------------------------------------------------
1526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(debugLog)(1, "main", "Starting the address space manager\n");
1527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(VKI_PAGE_SIZE     == 4096 || VKI_PAGE_SIZE     == 65536);
1528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(VKI_MAX_PAGE_SIZE == 4096 || VKI_MAX_PAGE_SIZE == 65536);
1529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(VKI_PAGE_SIZE <= VKI_MAX_PAGE_SIZE);
1530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(VKI_PAGE_SIZE     == (1 << VKI_PAGE_SHIFT));
1531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(VKI_MAX_PAGE_SIZE == (1 << VKI_MAX_PAGE_SHIFT));
1532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   the_iicii.clstack_top = VG_(am_startup)( the_iicii.sp_at_startup );
1533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(debugLog)(1, "main", "Address space manager is running\n");
1534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //--------------------------------------------------------------
1536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Start up the dynamic memory manager
1537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //   p: address space management
1538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //   p: getting --profile-heap
1539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //   In fact m_mallocfree is self-initialising, so there's no
1540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //   initialisation call to do.  Instead, try a simple malloc/
1541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //   free pair right now to check that nothing is broken.
1542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //--------------------------------------------------------------
1543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(debugLog)(1, "main", "Starting the dynamic memory manager\n");
1544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   { void* p = VG_(malloc)( "main.vm.1", 12345 );
1545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     if (p) VG_(free)( p );
1546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(debugLog)(1, "main", "Dynamic memory manager is running\n");
1548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //============================================================
1550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //
1551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Dynamic memory management is now available.
1552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //
1553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //============================================================
1554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //--------------------------------------------------------------
1556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Initialise m_debuginfo
1557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //  p: dynamic memory allocation
1558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(debugLog)(1, "main", "Initialise m_debuginfo\n");
1559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(di_initialise)();
1560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //--------------------------------------------------------------
1562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Look for alternative libdir
1563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   { HChar *cp = VG_(getenv)(VALGRIND_LIB);
1564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     if (cp != NULL)
1565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        VG_(libdir) = cp;
1566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     VG_(debugLog)(1, "main", "VG_(libdir) = %s\n", VG_(libdir));
1567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //--------------------------------------------------------------
1570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Extract the launcher name from the environment.
1571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(debugLog)(1, "main", "Getting launcher's name ...\n");
1572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(name_of_launcher) = VG_(getenv)(VALGRIND_LAUNCHER);
1573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (VG_(name_of_launcher) == NULL) {
1574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf)("valgrind: You cannot run '%s' directly.\n", argv[0]);
1575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf)("valgrind: You should use $prefix/bin/valgrind.\n");
1576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(exit)(1);
1577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(debugLog)(1, "main", "... %s\n", VG_(name_of_launcher));
1579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //--------------------------------------------------------------
1581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Get the current process datasize rlimit, and set it to zero.
1582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // This prevents any internal uses of brk() from having any effect.
1583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // We remember the old value so we can restore it on exec, so that
1584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // child processes will have a reasonable brk value.
1585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(getrlimit)(VKI_RLIMIT_DATA, &VG_(client_rlimit_data));
1586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   zero.rlim_max = VG_(client_rlimit_data).rlim_max;
1587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(setrlimit)(VKI_RLIMIT_DATA, &zero);
1588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Get the current process stack rlimit.
1590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(getrlimit)(VKI_RLIMIT_STACK, &VG_(client_rlimit_stack));
1591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //--------------------------------------------------------------
1593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Figure out what sort of CPU we're on, and whether it is
1594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // able to run V.
1595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(debugLog)(1, "main", "Get hardware capabilities ...\n");
1596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   { VexArch     vex_arch;
1597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     VexArchInfo vex_archinfo;
1598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     Bool ok = VG_(machine_get_hwcaps)();
1599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     if (!ok) {
1600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        VG_(printf)("\n");
1601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        VG_(printf)("valgrind: fatal error: unsupported CPU.\n");
1602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        VG_(printf)("   Supported CPUs are:\n");
1603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        VG_(printf)("   * x86 (practically any; Pentium-I or above), "
1604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    "AMD Athlon or above)\n");
1605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        VG_(printf)("   * AMD Athlon64/Opteron\n");
1606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        VG_(printf)("   * PowerPC (most; ppc405 and above)\n");
1607b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        VG_(printf)("   * System z (64bit only - s390x; z900 and above)\n");
1608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        VG_(printf)("\n");
1609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        VG_(exit)(1);
1610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     }
1611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     VG_(machine_get_VexArchInfo)( &vex_arch, &vex_archinfo );
1612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     VG_(debugLog)(
1613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        1, "main", "... arch = %s, hwcaps = %s\n",
1614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           LibVEX_ppVexArch   ( vex_arch ),
1615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           LibVEX_ppVexHwCaps ( vex_arch, vex_archinfo.hwcaps )
1616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     );
1617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //--------------------------------------------------------------
1620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Record the working directory at startup
1621b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   //   p: none
1622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(debugLog)(1, "main", "Getting the working directory at startup\n");
1623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   { Bool ok = VG_(record_startup_wd)();
1624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     if (!ok)
1625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        VG_(err_config_error)( "Can't establish current working "
1626b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                               "directory at startup\n");
1627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   { Char buf[VKI_PATH_MAX+1];
1629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     Bool ok = VG_(get_startup_wd)( buf, sizeof(buf) );
1630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     vg_assert(ok);
1631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     buf[VKI_PATH_MAX] = 0;
1632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     VG_(debugLog)(1, "main", "... %s\n", buf );
1633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //============================================================
1636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Command line argument handling order:
1637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // * If --help/--help-debug are present, show usage message
1638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //   (including the tool-specific usage)
1639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // * (If no --tool option given, default to Memcheck)
1640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // * Then, if client is missing, abort with error msg
1641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // * Then, if any cmdline args are bad, abort with error msg
1642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //============================================================
1643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //--------------------------------------------------------------
1645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Split up argv into: C args, V args, V extra args, and exename.
1646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //   p: dynamic memory allocation
1647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //--------------------------------------------------------------
1648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(debugLog)(1, "main", "Split up command line\n");
1649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(split_up_argv)( argc, argv );
1650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert( VG_(args_for_valgrind) );
1651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert( VG_(args_for_client) );
1652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (0) {
1653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      for (i = 0; i < VG_(sizeXA)( VG_(args_for_valgrind) ); i++)
1654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(printf)(
1655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            "varg %s\n",
1656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            * (HChar**) VG_(indexXA)( VG_(args_for_valgrind), i )
1657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         );
1658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf)(" exe %s\n", VG_(args_the_exename));
1659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      for (i = 0; i < VG_(sizeXA)( VG_(args_for_client) ); i++)
1660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(printf)(
1661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            "carg %s\n",
1662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            * (HChar**) VG_(indexXA)( VG_(args_for_client), i )
1663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         );
1664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //--------------------------------------------------------------
1667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Extract tool name and whether help has been requested.
1668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Note we can't print the help message yet, even if requested,
1669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // because the tool has not been initialised.
1670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //   p: split_up_argv [for VG_(args_for_valgrind)]
1671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //--------------------------------------------------------------
1672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(debugLog)(1, "main",
1673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    "(early_) Process Valgrind's command line options\n");
1674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   early_process_cmd_line_options(&need_help, &toolname);
1675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Set default vex control params
1677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LibVEX_default_VexControl(& VG_(clo_vex_control));
1678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //--------------------------------------------------------------
1680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Load client executable, finding in $PATH if necessary
1681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //   p: early_process_cmd_line_options()  [for 'exec', 'need_help',
1682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //                                         clo_max_stackframe,
1683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //                                         clo_main_stacksize]
1684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //   p: layout_remaining_space            [so there's space]
1685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //
1686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Set up client's environment
1687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //   p: set-libdir                     [for VG_(libdir)]
1688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //   p: early_process_cmd_line_options [for toolname]
1689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //
1690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Setup client stack, eip, and VG_(client_arg[cv])
1691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //   p: load_client()     [for 'info']
1692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //   p: fix_environment() [for 'env']
1693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //
1694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Setup client data (brk) segment.  Initially a 1-page segment
1695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // which abuts a shrinkable reservation.
1696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //     p: load_client()     [for 'info' and hence VG_(brk_base)]
1697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //
1698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // p: _start_in_C (for zeroing out the_iicii and putting some
1699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //    initial values into it)
1700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //--------------------------------------------------------------
1701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (!need_help) {
1702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(debugLog)(1, "main", "Create initial image\n");
1703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#     if defined(VGO_linux) || defined(VGO_darwin)
1705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      the_iicii.argv              = argv;
1706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      the_iicii.envp              = envp;
1707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      the_iicii.toolname          = toolname;
1708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#     else
1709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#       error "Unknown platform"
1710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#     endif
1711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* NOTE: this call reads VG_(clo_main_stacksize). */
1713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      the_iifii = VG_(ii_create_image)( the_iicii );
1714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //==============================================================
1717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //
1718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Finished loading/setting up the client address space.
1719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //
1720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //==============================================================
1721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //--------------------------------------------------------------
1723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // setup file descriptors
1724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //   p: n/a
1725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //--------------------------------------------------------------
1726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(debugLog)(1, "main", "Setup file descriptors\n");
1727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   setup_file_descriptors();
1728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //--------------------------------------------------------------
1730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // create the fake /proc/<pid>/cmdline file and then unlink it,
1731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // but hold onto the fd, so we can hand it out to the client
1732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // when it tries to open /proc/<pid>/cmdline for itself.
1733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //   p: setup file descriptors
1734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //--------------------------------------------------------------
1735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if !defined(VGO_linux)
1736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // client shouldn't be using /proc!
1737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(cl_cmdline_fd) = -1;
1738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#else
1739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (!need_help) {
1740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HChar  buf[50], buf2[50+64];
1741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HChar  nul[1];
1742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Int    fd, r;
1743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      const HChar* exename;
1744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(debugLog)(1, "main", "Create fake /proc/<pid>/cmdline\n");
1746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(sprintf)(buf, "proc_%d_cmdline", VG_(getpid)());
1748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fd = VG_(mkstemp)( buf, buf2 );
1749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (fd == -1)
1750b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         VG_(err_config_error)("Can't create client cmdline file in %s\n", buf2);
1751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      nul[0] = 0;
1753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      exename = VG_(args_the_exename) ? VG_(args_the_exename)
1754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                      : "unknown_exename";
1755b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      VG_(write)(fd, exename, VG_(strlen)( exename ));
1756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(write)(fd, nul, 1);
1757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      for (i = 0; i < VG_(sizeXA)( VG_(args_for_client) ); i++) {
1759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         HChar* arg = * (HChar**) VG_(indexXA)( VG_(args_for_client), i );
1760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(write)(fd, arg, VG_(strlen)( arg ));
1761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(write)(fd, nul, 1);
1762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Don't bother to seek the file back to the start; instead do
1765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 it every time a copy of it is given out (by PRE(sys_open)).
1766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 That is probably more robust across fork() etc. */
1767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Now delete it, but hang on to the fd. */
1769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      r = VG_(unlink)( buf2 );
1770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (r)
1771b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         VG_(err_config_error)("Can't delete client cmdline file in %s\n", buf2);
1772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(cl_cmdline_fd) = fd;
1774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
1776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //--------------------------------------------------------------
1778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Init tool part 1: pre_clo_init
1779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //   p: setup_client_stack()      [for 'VG_(client_arg[cv]']
1780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //   p: setup_file_descriptors()  [for 'VG_(fd_xxx_limit)']
1781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //--------------------------------------------------------------
1782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(debugLog)(1, "main", "Initialise the tool part 1 (pre_clo_init)\n");
1783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(tl_pre_clo_init)();
1784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //--------------------------------------------------------------
1786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // If --tool and --help/--help-debug was given, now give the core+tool
1787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // help message
1788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //   p: early_process_cmd_line_options() [for 'need_help']
1789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //   p: tl_pre_clo_init                  [for 'VG_(tdict).usage']
1790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //--------------------------------------------------------------
1791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(debugLog)(1, "main", "Print help and quit, if requested\n");
1792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (need_help) {
1793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      usage_NORETURN(/*--help-debug?*/need_help >= 2);
1794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //--------------------------------------------------------------
1797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Process command line options to Valgrind + tool
1798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //   p: setup_client_stack()      [for 'VG_(client_arg[cv]']
1799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //   p: setup_file_descriptors()  [for 'VG_(fd_xxx_limit)']
1800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //--------------------------------------------------------------
1801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(debugLog)(1, "main",
1802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    "(main_) Process Valgrind's command line options, "
1803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    "setup logging\n");
1804f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov   main_process_cmd_line_options ( &logging_to_fd, toolname );
1805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //--------------------------------------------------------------
1807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Zeroise the millisecond counter by doing a first read of it.
1808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //   p: none
1809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //--------------------------------------------------------------
1810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   (void) VG_(read_millisecond_timer)();
1811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //--------------------------------------------------------------
1813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Print the preamble
1814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //   p: tl_pre_clo_init            [for 'VG_(details).name' and friends]
1815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //   p: main_process_cmd_line_options()
1816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //         [for VG_(clo_verbosity), VG_(clo_xml),
1817f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov   //          logging_to_fd]
1818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //--------------------------------------------------------------
1819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(debugLog)(1, "main", "Print the preamble...\n");
1820f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov   print_preamble(logging_to_fd, toolname);
1821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(debugLog)(1, "main", "...finished the preamble\n");
1822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //--------------------------------------------------------------
1824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Init tool part 2: post_clo_init
1825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //   p: setup_client_stack()      [for 'VG_(client_arg[cv]']
1826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //   p: setup_file_descriptors()  [for 'VG_(fd_xxx_limit)']
1827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //   p: print_preamble()          [so any warnings printed in post_clo_init
1828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //                                 are shown after the preamble]
1829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //--------------------------------------------------------------
1830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(debugLog)(1, "main", "Initialise the tool part 2 (post_clo_init)\n");
1831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_TDICT_CALL(tool_post_clo_init);
1832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
1833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* The tool's "needs" will by now be finalised, since it has no
1834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         further opportunity to specify them.  So now sanity check
1835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         them. */
1836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Char* s;
1837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Bool  ok;
1838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ok = VG_(sanity_check_needs)( &s );
1839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (!ok) {
1840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(tool_panic)(s);
1841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //--------------------------------------------------------------
1845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Initialise translation table and translation cache
1846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //   p: aspacem         [??]
1847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //   p: tl_pre_clo_init [for 'VG_(details).avg_translation_sizeB']
1848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //--------------------------------------------------------------
1849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(debugLog)(1, "main", "Initialise TT/TC\n");
1850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(init_tt_tc)();
1851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //--------------------------------------------------------------
1853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Initialise the redirect table.
1854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //   p: init_tt_tc [so it can call VG_(search_transtab) safely]
1855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //   p: aspacem [so can change ownership of sysinfo pages]
1856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //--------------------------------------------------------------
1857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(debugLog)(1, "main", "Initialise redirects\n");
1858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(redir_initialise)();
1859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //--------------------------------------------------------------
1861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Allow GDB attach
1862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //   p: main_process_cmd_line_options()  [for VG_(clo_wait_for_gdb)]
1863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //--------------------------------------------------------------
1864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Hook to delay things long enough so we can get the pid and
1865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      attach GDB in another shell. */
1866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (VG_(clo_wait_for_gdb)) {
1867b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      ULong iters, q;
1868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(debugLog)(1, "main", "Wait for GDB\n");
1869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf)("pid=%d, entering delay loop\n", VG_(getpid)());
1870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#     if defined(VGP_x86_linux)
1872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      iters = 5;
1873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#     elif defined(VGP_amd64_linux) || defined(VGP_ppc64_linux)
1874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      iters = 10;
1875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#     elif defined(VGP_ppc32_linux)
1876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      iters = 5;
1877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#     elif defined(VGP_arm_linux)
1878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      iters = 1;
1879b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#     elif defined(VGP_s390x_linux)
1880b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      iters = 10;
1881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#     elif defined(VGO_darwin)
1882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      iters = 3;
1883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#     else
1884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#       error "Unknown plat"
1885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#     endif
1886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1887b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      iters *= 1000ULL * 1000 * 1000;
1888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      for (q = 0; q < iters; q++)
1889b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         __asm__ __volatile__("" ::: "memory","cc");
1890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //--------------------------------------------------------------
1893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Search for file descriptors that are inherited from our parent
1894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //   p: main_process_cmd_line_options  [for VG_(clo_track_fds)]
1895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //--------------------------------------------------------------
1896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (VG_(clo_track_fds)) {
1897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(debugLog)(1, "main", "Init preopened fds\n");
1898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(init_preopened_fds)();
1899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //--------------------------------------------------------------
1902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Load debug info for the existing segments.
1903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //   p: setup_code_redirect_table [so that redirs can be recorded]
1904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //   p: mallocfree
1905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //   p: probably: setup fds and process CLOs, so that logging works
1906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //   p: initialise m_debuginfo
1907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //
1908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // While doing this, make a note of the debuginfo-handles that
1909b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   // come back from VG_(di_notify_mmap).
1910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Later, in "Tell the tool about the initial client memory permissions"
1911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // (just below) we can then hand these handles off to the tool in
1912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // calls to VG_TRACK(new_mem_startup, ...).  This gives the tool the
1913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // opportunity to make further queries to m_debuginfo before the
1914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // client is started, if it wants.  We put this information into an
1915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // XArray, each handle along with the associated segment start address,
1916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // and search the XArray for the handles later, when calling
1917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // VG_TRACK(new_mem_startup, ...).
1918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //--------------------------------------------------------------
1919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(debugLog)(1, "main", "Load initial debug info\n");
1920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(!addr2dihandle);
1922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addr2dihandle = VG_(newXA)( VG_(malloc), "main.vm.2",
1923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               VG_(free), sizeof(Addr_n_ULong) );
1924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(addr2dihandle);
1925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  if defined(VGO_linux)
1927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   { Addr* seg_starts;
1928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     Int   n_seg_starts;
1929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     Addr_n_ULong anu;
1930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     seg_starts = VG_(get_segment_starts)( &n_seg_starts );
1932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     vg_assert(seg_starts && n_seg_starts >= 0);
1933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     /* show them all to the debug info reader.  allow_SkFileV has to
1935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        be True here so that we read info from the valgrind executable
1936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        itself. */
1937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     for (i = 0; i < n_seg_starts; i++) {
1938b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        anu.ull = VG_(di_notify_mmap)( seg_starts[i], True/*allow_SkFileV*/,
1939b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                       -1/*Don't use_fd*/);
1940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* anu.ull holds the debuginfo handle returned by di_notify_mmap,
1941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           if any. */
1942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (anu.ull > 0) {
1943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           anu.a = seg_starts[i];
1944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           VG_(addToXA)( addr2dihandle, &anu );
1945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
1946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     }
1947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     VG_(free)( seg_starts );
1949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  elif defined(VGO_darwin)
1951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   { Addr* seg_starts;
1952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     Int   n_seg_starts;
1953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     seg_starts = VG_(get_segment_starts)( &n_seg_starts );
1954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     vg_assert(seg_starts && n_seg_starts >= 0);
1955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     /* show them all to the debug info reader.
1957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        Don't read from V segments (unlike Linux) */
1958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     // GrP fixme really?
1959b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov     for (i = 0; i < n_seg_starts; i++) {
1960b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        VG_(di_notify_mmap)( seg_starts[i], False/*don't allow_SkFileV*/,
1961b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                             -1/*don't use_fd*/);
1962b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov     }
1963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     VG_(free)( seg_starts );
1965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  else
1967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#    error Unknown OS
1968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  endif
1969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //--------------------------------------------------------------
1971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Tell aspacem of ownership change of the asm helpers, so that
1972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // m_translate allows them to be translated.  However, only do this
1973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // after the initial debug info read, since making a hole in the
1974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // address range for the stage2 binary confuses the debug info reader.
1975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //   p: aspacem
1976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //--------------------------------------------------------------
1977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   { Bool change_ownership_v_c_OK;
1978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     Addr co_start   = VG_PGROUNDDN( (Addr)&VG_(trampoline_stuff_start) );
1979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     Addr co_endPlus = VG_PGROUNDUP( (Addr)&VG_(trampoline_stuff_end) );
1980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     VG_(debugLog)(1,"redir",
1981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     "transfer ownership V -> C of 0x%llx .. 0x%llx\n",
1982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     (ULong)co_start, (ULong)co_endPlus-1 );
1983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     change_ownership_v_c_OK
1985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        = VG_(am_change_ownership_v_to_c)( co_start, co_endPlus - co_start );
1986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     vg_assert(change_ownership_v_c_OK);
1987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1989b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (VG_(clo_xml)) {
1990b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      HChar buf[50];
1991b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      VG_(elapsed_wallclock_time)(buf);
1992b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      VG_(printf_xml)( "<status>\n"
1993b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                       "  <state>RUNNING</state>\n"
1994b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                       "  <time>%pS</time>\n"
1995b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                       "</status>\n",
1996b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                       buf );
1997b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      VG_(printf_xml)( "\n" );
1998b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
1999b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
2000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //--------------------------------------------------------------
2001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Initialise the scheduler (phase 1) [generates tid_main]
2002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //   p: none, afaics
2003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //--------------------------------------------------------------
2004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(debugLog)(1, "main", "Initialise scheduler (phase 1)\n");
2005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tid_main = VG_(scheduler_init_phase1)();
2006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(tid_main >= 0 && tid_main < VG_N_THREADS
2007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             && tid_main != VG_INVALID_THREADID);
2008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Tell the tool about tid_main */
2009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_TRACK( pre_thread_ll_create, VG_INVALID_THREADID, tid_main );
2010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //--------------------------------------------------------------
2012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Tell the tool about the initial client memory permissions
2013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //   p: aspacem
2014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //   p: mallocfree
2015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //   p: setup_client_stack
2016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //   p: setup_client_dataseg
2017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //
2018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // For each segment we tell the client about, look up in
2019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // addr2dihandle as created above, to see if there's a debuginfo
2020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // handle associated with the segment, that we can hand along
2021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // to the tool, to be helpful.
2022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //--------------------------------------------------------------
2023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(debugLog)(1, "main", "Tell tool about initial permissions\n");
2024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   { Addr*     seg_starts;
2025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     Int       n_seg_starts;
2026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     tl_assert(addr2dihandle);
2028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     /* Mark the main thread as running while we tell the tool about
2030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        the client memory so that the tool can associate that memory
2031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        with the main thread. */
2032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     tl_assert(VG_(running_tid) == VG_INVALID_THREADID);
2033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     VG_(running_tid) = tid_main;
2034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     seg_starts = VG_(get_segment_starts)( &n_seg_starts );
2036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     vg_assert(seg_starts && n_seg_starts >= 0);
2037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     /* show interesting ones to the tool */
2039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     for (i = 0; i < n_seg_starts; i++) {
2040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        Word j, n;
2041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        NSegment const* seg
2042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           = VG_(am_find_nsegment)( seg_starts[i] );
2043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        vg_assert(seg);
2044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (seg->kind == SkFileC || seg->kind == SkAnonC) {
2045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          /* This next assertion is tricky.  If it is placed
2046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             immediately before this 'if', it very occasionally fails.
2047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             Why?  Because previous iterations of the loop may have
2048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             caused tools (via the new_mem_startup calls) to do
2049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             dynamic memory allocation, and that may affect the mapped
2050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             segments; in particular it may cause segment merging to
2051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             happen.  Hence we cannot assume that seg_starts[i], which
2052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             reflects the state of the world before we started this
2053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             loop, is the same as seg->start, as the latter reflects
2054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             the state of the world (viz, mappings) at this particular
2055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             iteration of the loop.
2056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             Why does moving it inside the 'if' make it safe?  Because
2058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             any dynamic memory allocation done by the tools will
2059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             affect only the state of Valgrind-owned segments, not of
2060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             Client-owned segments.  And the 'if' guards against that
2061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             -- we only get in here for Client-owned segments.
2062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             In other words: the loop may change the state of
2064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             Valgrind-owned segments as it proceeds.  But it should
2065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             not cause the Client-owned segments to change. */
2066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           vg_assert(seg->start == seg_starts[i]);
2067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           VG_(debugLog)(2, "main",
2068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            "tell tool about %010lx-%010lx %c%c%c\n",
2069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             seg->start, seg->end,
2070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             seg->hasR ? 'r' : '-',
2071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             seg->hasW ? 'w' : '-',
2072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             seg->hasX ? 'x' : '-' );
2073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           /* search addr2dihandle to see if we have an entry
2074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              matching seg->start. */
2075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           n = VG_(sizeXA)( addr2dihandle );
2076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           for (j = 0; j < n; j++) {
2077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              Addr_n_ULong* anl = VG_(indexXA)( addr2dihandle, j );
2078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              if (anl->a == seg->start) {
2079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  tl_assert(anl->ull > 0); /* check it's a valid handle */
2080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  break;
2081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              }
2082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           }
2083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           vg_assert(j >= 0 && j <= n);
2084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           VG_TRACK( new_mem_startup, seg->start, seg->end+1-seg->start,
2085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     seg->hasR, seg->hasW, seg->hasX,
2086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     /* and the retrieved debuginfo handle, if any */
2087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     j < n
2088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     ? ((Addr_n_ULong*)VG_(indexXA)( addr2dihandle, j ))->ull
2089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        : 0 );
2090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
2091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     }
2092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     VG_(free)( seg_starts );
2094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     VG_(deleteXA)( addr2dihandle );
2095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     /* Also do the initial stack permissions. */
2097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     {
2098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       SSizeT inaccessible_len;
2099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       NSegment const* seg
2100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          = VG_(am_find_nsegment)( the_iifii.initial_client_SP );
2101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       vg_assert(seg);
2102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       vg_assert(seg->kind == SkAnonC);
2103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       vg_assert(the_iifii.initial_client_SP >= seg->start);
2104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       vg_assert(the_iifii.initial_client_SP <= seg->end);
2105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       /* Stuff below the initial SP is unaddressable.  Take into
2107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	  account any ABI-mandated space below the stack pointer that
2108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	  is required (VG_STACK_REDZONE_SZB).  setup_client_stack()
2109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	  will have allocated an extra page if a red zone is required,
2110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	  to be on the safe side. */
2111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       inaccessible_len = the_iifii.initial_client_SP - VG_STACK_REDZONE_SZB
2112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          - seg->start;
2113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       vg_assert(inaccessible_len >= 0);
2114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       if (inaccessible_len > 0)
2115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          VG_TRACK( die_mem_stack,
2116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    seg->start,
2117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    inaccessible_len );
2118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       VG_(debugLog)(2, "main", "mark stack inaccessible %010lx-%010lx\n",
2119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        seg->start,
2120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        the_iifii.initial_client_SP-1 - VG_STACK_REDZONE_SZB);
2121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     }
2122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     /* Also the assembly helpers. */
2124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     VG_TRACK( new_mem_startup,
2125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               (Addr)&VG_(trampoline_stuff_start),
2126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               (Addr)&VG_(trampoline_stuff_end)
2127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  - (Addr)&VG_(trampoline_stuff_start),
2128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               False, /* readable? */
2129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               False, /* writable? */
2130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               True   /* executable? */,
2131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               0 /* di_handle: no associated debug info */ );
2132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     /* Clear the running thread indicator */
2134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     VG_(running_tid) = VG_INVALID_THREADID;
2135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     tl_assert(VG_(running_tid) == VG_INVALID_THREADID);
2136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //--------------------------------------------------------------
2139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Initialise the scheduler (phase 2)
2140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //   p: Initialise the scheduler (phase 1) [for tid_main]
2141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //   p: setup_file_descriptors() [else VG_(safe_fd)() breaks]
2142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //   p: setup_client_stack
2143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //--------------------------------------------------------------
2144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(debugLog)(1, "main", "Initialise scheduler (phase 2)\n");
2145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   { NSegment const* seg
2146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        = VG_(am_find_nsegment)( the_iifii.initial_client_SP );
2147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     vg_assert(seg);
2148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     vg_assert(seg->kind == SkAnonC);
2149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     vg_assert(the_iifii.initial_client_SP >= seg->start);
2150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     vg_assert(the_iifii.initial_client_SP <= seg->end);
2151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     VG_(scheduler_init_phase2)( tid_main,
2152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 seg->end, the_iifii.clstack_max_size );
2153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //--------------------------------------------------------------
2156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Set up state for the root thread
2157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //   p: ?
2158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //      setup_scheduler()      [for sched-specific thread 1 stuff]
2159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //      VG_(ii_create_image)   [for 'the_iicii' initial info]
2160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //--------------------------------------------------------------
2161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(debugLog)(1, "main", "Finalise initial image\n");
2162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(ii_finalise_image)( the_iifii );
2163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //--------------------------------------------------------------
2165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Initialise the signal handling subsystem
2166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //   p: n/a
2167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //--------------------------------------------------------------
2168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Nb: temporarily parks the saved blocking-mask in saved_sigmask.
2169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(debugLog)(1, "main", "Initialise signal management\n");
2170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Check that the kernel-interface signal definitions look sane */
2171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(vki_do_initial_consistency_checks)();
2172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* .. and go on to use them. */
2173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(sigstartup_actions)();
2174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //--------------------------------------------------------------
2176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Read suppression file
2177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //   p: main_process_cmd_line_options()  [for VG_(clo_suppressions)]
2178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //--------------------------------------------------------------
2179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (VG_(needs).core_errors || VG_(needs).tool_errors) {
2180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(debugLog)(1, "main", "Load suppressions\n");
2181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(load_suppressions)();
2182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //--------------------------------------------------------------
2185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // register client stack
2186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //--------------------------------------------------------------
2187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(clstk_id) = VG_(register_stack)(VG_(clstk_base), VG_(clstk_end));
2188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //--------------------------------------------------------------
2190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Show the address space state so far
2191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //--------------------------------------------------------------
2192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(debugLog)(1, "main", "\n");
2193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(debugLog)(1, "main", "\n");
2194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(am_show_nsegments)(1,"Memory layout at client startup");
2195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(debugLog)(1, "main", "\n");
2196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(debugLog)(1, "main", "\n");
2197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //--------------------------------------------------------------
2199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Run!
2200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //--------------------------------------------------------------
2201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(debugLog)(1, "main", "Running thread 1\n");
2202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* As a result of the following call, the last thread standing
2204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      eventually winds up running shutdown_actions_NORETURN
2205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      just below.  Unfortunately, simply exporting said function
2206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      causes m_main to be part of a module cycle, which is pretty
2207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      nonsensical.  So instead of doing that, the address of said
2208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      function is stored in a global variable 'owned' by m_syswrap,
2209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      and it uses that function pointer to get back here when it needs
2210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      to. */
2211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Set continuation address. */
2213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(address_of_m_main_shutdown_actions_NORETURN)
2214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      = & shutdown_actions_NORETURN;
2215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Run the first thread, eventually ending up at the continuation
2217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      address. */
2218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(main_thread_wrapper_NORETURN)(1);
2219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /*NOTREACHED*/
2221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(0);
2222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Do everything which needs doing when the last thread exits or when
2225b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   a thread exits requesting a complete process exit.
2226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   We enter here holding The Lock.  For the case VgSrc_ExitProcess we
2228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   must never release it, because to do so would allow other threads
2229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   to continue after the system is ostensibly shut down.  So we must
2230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   go to our grave, so to speak, holding the lock.
2231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   In fact, there is never any point in releasing the lock at this
2233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   point - we have it, we're shutting down the entire system, and
2234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for the case VgSrc_ExitProcess doing so positively causes trouble.
2235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   So don't.
2236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   The final_tidyup call makes a bit of a nonsense of the ExitProcess
2238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case, since it will run the libc_freeres function, thus allowing
2239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   other lurking threads to run again.  Hmm. */
2240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
2242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid shutdown_actions_NORETURN( ThreadId tid,
2243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                VgSchedReturnCode tids_schedretcode )
2244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(debugLog)(1, "main", "entering VG_(shutdown_actions_NORETURN)\n");
2246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(am_show_nsegments)(1,"Memory layout at client shutdown");
2247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(VG_(is_running_thread)(tid));
2249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(tids_schedretcode == VgSrc_ExitThread
2251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	     || tids_schedretcode == VgSrc_ExitProcess
2252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             || tids_schedretcode == VgSrc_FatalSig );
2253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (tids_schedretcode == VgSrc_ExitThread) {
2255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // We are the last surviving thread.  Right?
2257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vg_assert( VG_(count_living_threads)() == 1 );
2258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // Wait for all other threads to exit.
2260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // jrs: Huh?  but they surely are already gone
2261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(reap_threads)(tid);
2262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // Clean the client up before the final report
2264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // this causes the libc_freeres function to run
2265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      final_tidyup(tid);
2266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* be paranoid */
2268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vg_assert(VG_(is_running_thread)(tid));
2269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vg_assert(VG_(count_living_threads)() == 1);
2270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
2272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // We may not be the last surviving thread.  However, we
2274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // want to shut down the entire process.  We hold the lock
2275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // and we need to keep hold of it all the way out, in order
2276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // that none of the other threads ever run again.
2277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vg_assert( VG_(count_living_threads)() >= 1 );
2278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // Clean the client up before the final report
2280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // this causes the libc_freeres function to run
2281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // perhaps this is unsafe, as per comment above
2282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      final_tidyup(tid);
2283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* be paranoid */
2285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vg_assert(VG_(is_running_thread)(tid));
2286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vg_assert(VG_(count_living_threads)() >= 1);
2287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(threads)[tid].status = VgTs_Empty;
2290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //--------------------------------------------------------------
2291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Finalisation: cleanup, messages, etc.  Order not so important, only
2292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // affects what order the messages come.
2293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //--------------------------------------------------------------
2294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // First thing in the post-amble is a blank line.
2295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (VG_(clo_xml))
2296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf_xml)("\n");
2297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else if (VG_(clo_verbosity) > 0)
2298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(message)(Vg_UserMsg, "\n");
2299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (VG_(clo_xml)) {
2301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HChar buf[50];
2302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(elapsed_wallclock_time)(buf);
2303b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      VG_(printf_xml)( "<status>\n"
2304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              "  <state>FINISHED</state>\n"
2305b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                              "  <time>%pS</time>\n"
2306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              "</status>\n"
2307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              "\n",
2308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              buf);
2309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Print out file descriptor summary and stats. */
2312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (VG_(clo_track_fds))
2313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(show_open_fds)();
2314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Call the tool's finalisation function.  This makes Memcheck's
2316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      leak checker run, and possibly chuck a bunch of leak errors into
2317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      the error management machinery. */
2318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_TDICT_CALL(tool_fini, 0/*exitcode*/);
2319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Show the error counts. */
2321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (VG_(clo_xml)
2322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       && (VG_(needs).core_errors || VG_(needs).tool_errors)) {
2323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(show_error_counts_as_XML)();
2324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* In XML mode, this merely prints the used suppressions. */
2327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (VG_(needs).core_errors || VG_(needs).tool_errors)
2328b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      VG_(show_all_errors)(VG_(clo_verbosity), VG_(clo_xml));
2329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (VG_(clo_xml)) {
2331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf_xml)("\n");
2332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf_xml)("</valgrindoutput>\n");
2333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf_xml)("\n");
2334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(sanity_check_general)( True /*include expensive checks*/ );
2337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (VG_(clo_stats))
2339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      print_all_stats();
2340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Show a profile of the heap(s) at shutdown.  Optionally, first
2342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      throw away all the debug info, as that makes it easy to spot
2343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      leaks in the debuginfo reader. */
2344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (VG_(clo_profile_heap)) {
2345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (0) VG_(di_discard_ALL_debuginfo)();
2346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(print_arena_cc_analysis)();
2347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (VG_(clo_profile_flags) > 0) {
2350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      #define N_MAX 200
2351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      BBProfEntry tops[N_MAX];
2352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ULong score_total = VG_(get_BB_profile) (tops, N_MAX);
2353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      show_BB_profile(tops, N_MAX, score_total);
2354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Print Vex storage stats */
2357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (0)
2358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       LibVEX_ShowAllocStats();
2359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Flush any output cached by previous calls to VG_(message). */
2361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(message_flush)();
2362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2363b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /* terminate gdbserver if ever it was started. We terminate it here so that it get
2364b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      the output above if output was redirected to gdb */
2365b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   VG_(gdbserver) (0);
2366b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
2367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Ok, finally exit in the os-specific way, according to the scheduler's
2368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return code.  In short, if the (last) thread exited by calling
2369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      sys_exit, do likewise; if the (last) thread stopped due to a fatal
2370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      signal, terminate the entire system with that same fatal signal. */
2371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(debugLog)(1, "core_os",
2372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    "VG_(terminate_NORETURN)(tid=%lld)\n", (ULong)tid);
2373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (tids_schedretcode) {
2375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case VgSrc_ExitThread:  /* the normal way out (Linux) */
2376b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case VgSrc_ExitProcess: /* the normal way out (AIX) -- still needed? */
2377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Change the application return code to user's return code,
2378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if an error was found */
2379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (VG_(clo_error_exitcode) > 0
2380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          && VG_(get_n_errs_found)() > 0) {
2381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(exit)( VG_(clo_error_exitcode) );
2382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
2383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* otherwise, return the client's exit code, in the normal
2384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            way. */
2385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(exit)( VG_(threads)[tid].os_state.exitcode );
2386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* NOT ALIVE HERE! */
2388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(core_panic)("entered the afterlife in main() -- ExitT/P");
2389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break; /* what the hell :) */
2390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case VgSrc_FatalSig:
2392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* We were killed by a fatal signal, so replicate the effect */
2393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vg_assert(VG_(threads)[tid].os_state.fatalsig != 0);
2394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(kill_self)(VG_(threads)[tid].os_state.fatalsig);
2395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* we shouldn't be alive at this point.  But VG_(kill_self)
2396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         sometimes fails with EPERM on Darwin, for unclear reasons. */
2397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#     if defined(VGO_darwin)
2398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(debugLog)(0, "main", "VG_(kill_self) failed.  Exiting normally.\n");
2399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(exit)(0); /* bogus, but we really need to exit now */
2400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* fall through .. */
2401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#     endif
2402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(core_panic)("main(): signal was supposed to be fatal");
2403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
2404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   default:
2406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(core_panic)("main(): unexpected scheduler return code");
2407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* -------------------- */
2411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Final clean-up before terminating the process.
2413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Clean up the client by calling __libc_freeres() (if requested)
2414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   This is Linux-specific?
2415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   GrP fixme glibc-specific, anyway
2416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
2417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void final_tidyup(ThreadId tid)
2418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if !defined(VGO_darwin)
2420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  if defined(VGP_ppc64_linux)
2421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Addr r2;
2422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  endif
2423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Addr __libc_freeres_wrapper = VG_(client___libc_freeres_wrapper);
2424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(VG_(is_running_thread)(tid));
2426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if ( !VG_(needs).libc_freeres ||
2428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        !VG_(clo_run_libc_freeres) ||
2429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        0 == __libc_freeres_wrapper )
2430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return;			/* can't/won't do it */
2431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  if defined(VGP_ppc64_linux)
2433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   r2 = VG_(get_tocptr)( __libc_freeres_wrapper );
2434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (r2 == 0) {
2435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(message)(Vg_UserMsg,
2436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   "Caught __NR_exit, but can't run __libc_freeres()\n");
2437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(message)(Vg_UserMsg,
2438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   "   since cannot establish TOC pointer for it.\n");
2439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return;
2440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  endif
2442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (VG_(clo_verbosity) > 2  ||
2444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       VG_(clo_trace_syscalls) ||
2445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       VG_(clo_trace_sched))
2446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(message)(Vg_DebugMsg,
2447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		   "Caught __NR_exit; running __libc_freeres()\n");
2448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* set thread context to point to libc_freeres_wrapper */
2450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* ppc64-linux note: __libc_freeres_wrapper gives us the real
2451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      function entry point, not a fn descriptor, so can use it
2452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      directly.  However, we need to set R2 (the toc pointer)
2453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      appropriately. */
2454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(set_IP)(tid, __libc_freeres_wrapper);
2455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  if defined(VGP_ppc64_linux)
2456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(threads)[tid].arch.vex.guest_GPR2 = r2;
2457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  endif
2458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Block all blockable signals by copying the real block state into
2460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      the thread's block state*/
2461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(sigprocmask)(VKI_SIG_BLOCK, NULL, &VG_(threads)[tid].sig_mask);
2462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(threads)[tid].tmp_sig_mask = VG_(threads)[tid].sig_mask;
2463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* and restore handlers to default */
2465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(set_default_handler)(VKI_SIGSEGV);
2466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(set_default_handler)(VKI_SIGBUS);
2467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(set_default_handler)(VKI_SIGILL);
2468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(set_default_handler)(VKI_SIGFPE);
2469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // We were exiting, so assert that...
2471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(VG_(is_exiting)(tid));
2472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // ...but now we're not again
2473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(threads)[tid].exitreason = VgSrc_None;
2474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // run until client thread exits - ideally with LIBC_FREERES_DONE,
2476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // but exit/exitgroup/signal will do
2477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(scheduler)(tid);
2478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(VG_(is_exiting)(tid));
2480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
2481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*====================================================================*/
2485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*=== Getting to main() alive: LINUX                               ===*/
2486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*====================================================================*/
2487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGO_linux)
2489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* If linking of the final executables is done with glibc present,
2491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   then Valgrind starts at main() above as usual, and all of the
2492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   following code is irrelevant.
2493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   However, this is not the intended mode of use.  The plan is to
2495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   avoid linking against glibc, by giving gcc the flags
2496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   -nodefaultlibs -lgcc -nostartfiles at startup.
2497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   From this derive two requirements:
2499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   1. gcc may emit calls to memcpy and memset to deal with structure
2501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assignments etc.  Since we have chosen to ignore all the
2502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      "normal" supporting libraries, we have to provide our own
2503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      implementations of them.  No problem.
2504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   2. We have to provide a symbol "_start", to which the kernel
2506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      hands control at startup.  Hence the code below.
2507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
2508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ---------------- Requirement 1 ---------------- */
2510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid* memcpy(void *dest, const void *src, SizeT n);
2512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid* memcpy(void *dest, const void *src, SizeT n) {
2513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return VG_(memcpy)(dest,src,n);
2514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid* memset(void *s, int c, SizeT n);
2516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid* memset(void *s, int c, SizeT n) {
2517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  return VG_(memset)(s,c,n);
2518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* BVA: abort() for those platforms that need it (PPC and ARM). */
2521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid abort(void);
2522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid abort(void){
2523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(printf)("Something called raise().\n");
2524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(0);
2525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* EAZG: ARM's EABI will call floating point exception handlers in
2528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   libgcc which boil down to an abort or raise, that's usually defined
2529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   in libc. Instead, define them here. */
2530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGP_arm_linux)
2531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid raise(void);
2532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid raise(void){
2533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(printf)("Something called raise().\n");
2534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(0);
2535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid __aeabi_unwind_cpp_pr0(void);
2538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid __aeabi_unwind_cpp_pr0(void){
2539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(printf)("Something called __aeabi_unwind_cpp_pr0()\n");
2540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(0);
2541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid __aeabi_unwind_cpp_pr1(void);
2544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid __aeabi_unwind_cpp_pr1(void){
2545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(printf)("Something called __aeabi_unwind_cpp_pr1()\n");
2546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(0);
2547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
2549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ---------------- Requirement 2 ---------------- */
2551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Glibc's sysdeps/i386/elf/start.S has the following gem of a
2553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   comment, which explains how the stack looks right at process start
2554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   (when _start is jumped to).  Hence _start passes %esp to
2555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   _start_in_C_linux, which extracts argc/argv/envp and starts up
2556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   correctly. */
2557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* This is the canonical entry point, usually the first thing in the text
2559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   segment.  The SVR4/i386 ABI (pages 3-31, 3-32) says that when the entry
2560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   point runs, most registers' values are unspecified, except for:
2561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   %edx         Contains a function pointer to be registered with `atexit'.
2563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                This is how the dynamic linker arranges to have DT_FINI
2564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                functions called for shared libraries that have been loaded
2565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                before this code runs.
2566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   %esp         The stack contains the arguments and environment:
2568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                0(%esp)                 argc
2569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                4(%esp)                 argv[0]
2570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                ...
2571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                (4*argc)(%esp)          NULL
2572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                (4*(argc+1))(%esp)      envp[0]
2573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                ...
2574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                        NULL
2575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
2576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* The kernel hands control to _start, which extracts the initial
2578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   stack pointer and calls onwards to _start_in_C_linux.  This also switches
2579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   the new stack.  */
2580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGP_x86_linux)
2581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownasm("\n"
2582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ".text\n"
2583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    "\t.globl _start\n"
2584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    "\t.type _start,@function\n"
2585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    "_start:\n"
2586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* set up the new stack in %eax */
2587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    "\tmovl  $vgPlain_interim_stack, %eax\n"
2588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    "\taddl  $"VG_STRINGIFY(VG_STACK_GUARD_SZB)", %eax\n"
2589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    "\taddl  $"VG_STRINGIFY(VG_STACK_ACTIVE_SZB)", %eax\n"
2590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    "\tsubl  $16, %eax\n"
2591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    "\tandl  $~15, %eax\n"
2592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* install it, and collect the original one */
2593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    "\txchgl %eax, %esp\n"
2594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* call _start_in_C_linux, passing it the startup %esp */
2595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    "\tpushl %eax\n"
2596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    "\tcall  _start_in_C_linux\n"
2597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    "\thlt\n"
2598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ".previous\n"
2599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown);
2600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGP_amd64_linux)
2601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownasm("\n"
2602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ".text\n"
2603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    "\t.globl _start\n"
2604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    "\t.type _start,@function\n"
2605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    "_start:\n"
2606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* set up the new stack in %rdi */
2607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    "\tmovq  $vgPlain_interim_stack, %rdi\n"
2608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    "\taddq  $"VG_STRINGIFY(VG_STACK_GUARD_SZB)", %rdi\n"
2609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    "\taddq  $"VG_STRINGIFY(VG_STACK_ACTIVE_SZB)", %rdi\n"
2610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    "\tandq  $~15, %rdi\n"
2611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* install it, and collect the original one */
2612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    "\txchgq %rdi, %rsp\n"
2613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* call _start_in_C_linux, passing it the startup %rsp */
2614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    "\tcall  _start_in_C_linux\n"
2615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    "\thlt\n"
2616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ".previous\n"
2617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown);
2618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGP_ppc32_linux)
2619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownasm("\n"
2620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ".text\n"
2621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    "\t.globl _start\n"
2622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    "\t.type _start,@function\n"
2623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    "_start:\n"
2624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* set up the new stack in r16 */
2625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    "\tlis 16,vgPlain_interim_stack@ha\n"
2626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    "\tla  16,vgPlain_interim_stack@l(16)\n"
2627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    "\tlis    17,("VG_STRINGIFY(VG_STACK_GUARD_SZB)" >> 16)\n"
2628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    "\tori 17,17,("VG_STRINGIFY(VG_STACK_GUARD_SZB)" & 0xFFFF)\n"
2629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    "\tlis    18,("VG_STRINGIFY(VG_STACK_ACTIVE_SZB)" >> 16)\n"
2630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    "\tori 18,18,("VG_STRINGIFY(VG_STACK_ACTIVE_SZB)" & 0xFFFF)\n"
2631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    "\tadd 16,17,16\n"
2632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    "\tadd 16,18,16\n"
2633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    "\trlwinm 16,16,0,0,27\n"
2634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* now r16 = &vgPlain_interim_stack + VG_STACK_GUARD_SZB +
2635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       VG_STACK_ACTIVE_SZB rounded down to the nearest 16-byte
2636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       boundary.  And r1 is the original SP.  Set the SP to r16 and
2637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       call _start_in_C_linux, passing it the initial SP. */
2638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    "\tmr 3,1\n"
2639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    "\tmr 1,16\n"
2640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    "\tbl _start_in_C_linux\n"
2641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    "\ttrap\n"
2642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ".previous\n"
2643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown);
2644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGP_ppc64_linux)
2645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownasm("\n"
2646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* PPC64 ELF ABI says '_start' points to a function descriptor.
2647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       So we must have one, and that is what goes into the .opd section. */
2648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    "\t.align 2\n"
2649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    "\t.global _start\n"
2650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    "\t.section \".opd\",\"aw\"\n"
2651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    "\t.align 3\n"
2652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    "_start:\n"
2653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    "\t.quad ._start,.TOC.@tocbase,0\n"
2654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    "\t.previous\n"
2655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    "\t.type ._start,@function\n"
2656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    "\t.global  ._start\n"
2657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    "._start:\n"
2658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* set up the new stack in r16 */
2659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    "\tlis  16,   vgPlain_interim_stack@highest\n"
2660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    "\tori  16,16,vgPlain_interim_stack@higher\n"
2661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    "\tsldi 16,16,32\n"
2662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    "\toris 16,16,vgPlain_interim_stack@h\n"
2663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    "\tori  16,16,vgPlain_interim_stack@l\n"
2664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    "\txor  17,17,17\n"
2665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    "\tlis    17,("VG_STRINGIFY(VG_STACK_GUARD_SZB)" >> 16)\n"
2666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    "\tori 17,17,("VG_STRINGIFY(VG_STACK_GUARD_SZB)" & 0xFFFF)\n"
2667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    "\txor 18,18,18\n"
2668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    "\tlis    18,("VG_STRINGIFY(VG_STACK_ACTIVE_SZB)" >> 16)\n"
2669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    "\tori 18,18,("VG_STRINGIFY(VG_STACK_ACTIVE_SZB)" & 0xFFFF)\n"
2670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    "\tadd 16,17,16\n"
2671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    "\tadd 16,18,16\n"
2672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    "\trldicr 16,16,0,59\n"
2673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* now r16 = &vgPlain_interim_stack + VG_STACK_GUARD_SZB +
2674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       VG_STACK_ACTIVE_SZB rounded down to the nearest 16-byte
2675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       boundary.  And r1 is the original SP.  Set the SP to r16 and
2676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       call _start_in_C_linux, passing it the initial SP. */
2677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    "\tmr 3,1\n"
2678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    "\tmr 1,16\n"
2679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    "\tbl ._start_in_C_linux\n"
2680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    "\tnop\n"
2681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    "\ttrap\n"
2682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown);
2683b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#elif defined(VGP_s390x_linux)
2684b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*
2685b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    This is the canonical entry point, usually the first thing in the text
2686b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    segment. Most registers' values are unspecified, except for:
2687b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
2688b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    %r14         Contains a function pointer to be registered with `atexit'.
2689b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                 This is how the dynamic linker arranges to have DT_FINI
2690b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                 functions called for shared libraries that have been loaded
2691b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                 before this code runs.
2692b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
2693b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    %r15         The stack contains the arguments and environment:
2694b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                 0(%r15)              argc
2695b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                 8(%r15)              argv[0]
2696b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                 ...
2697b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                 (8*argc)(%r15)       NULL
2698b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                 (8*(argc+1))(%r15)   envp[0]
2699b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                 ...
2700b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                      NULL
2701b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov*/
2702b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovasm("\n\t"
2703b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    ".text\n\t"
2704b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    ".globl _start\n\t"
2705b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    ".type  _start,@function\n\t"
2706b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    "_start:\n\t"
2707b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    /* set up the new stack in %r1 */
2708b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    "larl   %r1,  vgPlain_interim_stack\n\t"
2709b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    "larl   %r5,  1f\n\t"
2710b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    "ag     %r1,  0(%r5)\n\t"
2711b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    "ag     %r1,  2f-1f(%r5)\n\t"
2712b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    "nill   %r1,  0xFFF0\n\t"
2713b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    /* install it, and collect the original one */
2714b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    "lgr    %r2,  %r15\n\t"
2715b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    "lgr    %r15, %r1\n\t"
2716b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    /* call _start_in_C_linux, passing it the startup %r15 */
2717b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    "brasl  %r14, _start_in_C_linux\n\t"
2718b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    /* trigger execution of an invalid opcode -> halt machine */
2719b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    "j      .+2\n\t"
2720b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    "1:   .quad "VG_STRINGIFY(VG_STACK_GUARD_SZB)"\n\t"
2721b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    "2:   .quad "VG_STRINGIFY(VG_STACK_ACTIVE_SZB)"\n\t"
2722b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    ".previous\n"
2723b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov);
2724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGP_arm_linux)
2725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownasm("\n"
27261b891657a2208341cc71c68ae16eada0bee46d91Jeff Brown    "\t.text\n"
27271b891657a2208341cc71c68ae16eada0bee46d91Jeff Brown    "\t.align 4\n"
27281b891657a2208341cc71c68ae16eada0bee46d91Jeff Brown    "\t.type _start,#function\n"
2729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    "\t.global _start\n"
2730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    "_start:\n"
2731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    "\tldr  r0, [pc, #36]\n"
2732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    "\tldr  r1, [pc, #36]\n"
2733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    "\tadd  r0, r1, r0\n"
2734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    "\tldr  r1, [pc, #32]\n"
2735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    "\tadd  r0, r1, r0\n"
2736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    "\tmvn  r1, #15\n"
2737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    "\tand  r0, r0, r1\n"
2738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    "\tmov  r1, sp\n"
2739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    "\tmov  sp, r0\n"
2740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    "\tmov  r0, r1\n"
2741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    "\tb _start_in_C_linux\n"
2742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    "\t.word vgPlain_interim_stack\n"
2743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    "\t.word "VG_STRINGIFY(VG_STACK_GUARD_SZB)"\n"
2744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    "\t.word "VG_STRINGIFY(VG_STACK_ACTIVE_SZB)"\n"
2745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown);
2746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#else
2747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  error "Unknown linux platform"
2748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
2749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --- !!! --- EXTERNAL HEADERS start --- !!! --- */
2751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define _GNU_SOURCE
2752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define _FILE_OFFSET_BITS 64
2753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* This is in order to get AT_NULL and AT_PAGESIZE. */
2754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <elf.h>
2755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --- !!! --- EXTERNAL HEADERS end --- !!! --- */
2756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Avoid compiler warnings: this fn _is_ used, but labelling it
2758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   'static' causes gcc to complain it isn't. */
2759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid _start_in_C_linux ( UWord* pArgc );
2760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid _start_in_C_linux ( UWord* pArgc )
2761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int     r;
2763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Word    argc = pArgc[0];
2764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HChar** argv = (HChar**)&pArgc[1];
2765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HChar** envp = (HChar**)&pArgc[1+argc+1];
2766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(memset)( &the_iicii, 0, sizeof(the_iicii) );
2768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(memset)( &the_iifii, 0, sizeof(the_iifii) );
2769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   the_iicii.sp_at_startup = (Addr)pArgc;
2771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  if defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux)
2773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
2774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* ppc/ppc64 can be configured with different page sizes.
2775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Determine this early.  This is an ugly hack and really should
2776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         be moved into valgrind_main. */
2777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UWord *sp = &pArgc[1+argc+1];
2778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      while (*sp++ != 0)
2779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ;
2780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      for (; *sp != AT_NULL && *sp != AT_PAGESZ; sp += 2);
2781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (*sp == AT_PAGESZ) {
2782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VKI_PAGE_SIZE = sp[1];
2783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         for (VKI_PAGE_SHIFT = 12;
2784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              VKI_PAGE_SHIFT <= VKI_MAX_PAGE_SHIFT; VKI_PAGE_SHIFT++)
2785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (VKI_PAGE_SIZE == (1UL << VKI_PAGE_SHIFT))
2786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
2787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  endif
2790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   r = valgrind_main( (Int)argc, argv, envp );
2792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* NOTREACHED */
2793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(exit)(r);
2794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*====================================================================*/
2798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*=== Getting to main() alive: darwin                              ===*/
2799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*====================================================================*/
2800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGO_darwin)
2802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*
2804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Memory layout established by kernel:
2805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   0(%esp)   argc
2807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   4(%esp)   argv[0]
2808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             ...
2809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             argv[argc-1]
2810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             NULL
2811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             envp[0]
2812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             ...
2813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             envp[n]
2814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             NULL
2815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             executable name (presumably, a pointer to it)
2816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             NULL
2817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Ditto in the 64-bit case, except all offsets from SP are obviously
2819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   twice as large.
2820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
2821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* The kernel hands control to _start, which extracts the initial
2823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   stack pointer and calls onwards to _start_in_C_darwin.  This also
2824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switches to the new stack.  */
2825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGP_x86_darwin)
2826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownasm("\n"
2827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ".text\n"
2828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ".align 2,0x90\n"
2829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    "\t.globl __start\n"
2830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    "__start:\n"
2831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* set up the new stack in %eax */
2832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    "\tmovl  $_vgPlain_interim_stack, %eax\n"
2833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    "\taddl  $"VG_STRINGIFY(VG_STACK_GUARD_SZB)", %eax\n"
2834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    "\taddl  $"VG_STRINGIFY(VG_STACK_ACTIVE_SZB)", %eax\n"
2835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    "\tsubl  $16, %eax\n"
2836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    "\tandl  $~15, %eax\n"
2837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* install it, and collect the original one */
2838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    "\txchgl %eax, %esp\n"
2839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* call _start_in_C_darwin, passing it the startup %esp */
2840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    "\tpushl %eax\n"
2841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    "\tcall  __start_in_C_darwin\n"
2842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    "\tint $3\n"
2843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    "\tint $3\n"
2844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown);
2845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGP_amd64_darwin)
2846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownasm("\n"
2847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ".text\n"
2848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    "\t.globl __start\n"
2849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ".align 3,0x90\n"
2850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    "__start:\n"
2851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* set up the new stack in %rdi */
2852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    "\tmovabsq $_vgPlain_interim_stack, %rdi\n"
2853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    "\taddq    $"VG_STRINGIFY(VG_STACK_GUARD_SZB)", %rdi\n"
2854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    "\taddq    $"VG_STRINGIFY(VG_STACK_ACTIVE_SZB)", %rdi\n"
2855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    "\tandq    $~15, %rdi\n"
2856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* install it, and collect the original one */
2857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    "\txchgq %rdi, %rsp\n"
2858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* call _start_in_C_darwin, passing it the startup %rsp */
2859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    "\tcall  __start_in_C_darwin\n"
2860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    "\tint $3\n"
2861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    "\tint $3\n"
2862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown);
2863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
2864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid* __memcpy_chk(void *dest, const void *src, SizeT n, SizeT n2);
2866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid* __memcpy_chk(void *dest, const void *src, SizeT n, SizeT n2) {
2867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    // skip check
2868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return VG_(memcpy)(dest,src,n);
2869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid* __memset_chk(void *s, int c, SizeT n, SizeT n2);
2871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid* __memset_chk(void *s, int c, SizeT n, SizeT n2) {
2872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    // skip check
2873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  return VG_(memset)(s,c,n);
2874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid bzero(void *s, SizeT n);
2876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid bzero(void *s, SizeT n) {
2877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    VG_(memset)(s,0,n);
2878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid* memcpy(void *dest, const void *src, SizeT n);
2881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid* memcpy(void *dest, const void *src, SizeT n) {
2882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return VG_(memcpy)(dest,src,n);
2883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid* memset(void *s, int c, SizeT n);
2885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid* memset(void *s, int c, SizeT n) {
2886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  return VG_(memset)(s,c,n);
2887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Avoid compiler warnings: this fn _is_ used, but labelling it
2890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   'static' causes gcc to complain it isn't. */
2891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid _start_in_C_darwin ( UWord* pArgc );
2892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid _start_in_C_darwin ( UWord* pArgc )
2893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int     r;
2895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int     argc = *(Int *)pArgc;  // not pArgc[0] on LP64
2896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HChar** argv = (HChar**)&pArgc[1];
2897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   HChar** envp = (HChar**)&pArgc[1+argc+1];
2898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(memset)( &the_iicii, 0, sizeof(the_iicii) );
2900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(memset)( &the_iifii, 0, sizeof(the_iifii) );
2901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   the_iicii.sp_at_startup = (Addr)pArgc;
2903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   r = valgrind_main( (Int)argc, argv, envp );
2905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* NOTREACHED */
2906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(exit)(r);
2907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#else
2911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  error "Unknown OS"
2913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
2914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*====================================================================*/
2917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*=== {u,}{div,mod}di3 replacements                                ===*/
2918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*====================================================================*/
2919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* For static linking on x86-darwin, we need to supply our own 64-bit
2921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   integer division code, else the link dies thusly:
2922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ld_classic: Undefined symbols:
2924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     ___udivdi3
2925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     ___umoddi3
2926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
2927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGP_x86_darwin)
2928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Routines for doing signed/unsigned 64 x 64 ==> 64 div and mod
2930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   (udivdi3, umoddi3, divdi3, moddi3) using only 32 x 32 ==> 32
2931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   division.  Cobbled together from
2932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   http://www.hackersdelight.org/HDcode/divlu.c
2934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   http://www.hackersdelight.org/HDcode/divls.c
2935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   http://www.hackersdelight.org/HDcode/newCode/divDouble.c
2936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   The code from those three files is covered by the following license,
2938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   as it appears at:
2939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   http://www.hackersdelight.org/permissions.htm
2941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      You are free to use, copy, and distribute any of the code on
2943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      this web site, whether modified by you or not. You need not give
2944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      attribution. This includes the algorithms (some of which appear
2945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      in Hacker's Delight), the Hacker's Assistant, and any code
2946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      submitted by readers. Submitters implicitly agree to this.
2947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
2948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Long division, unsigned (64/32 ==> 32).
2950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   This procedure performs unsigned "long division" i.e., division of a
2951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown64-bit unsigned dividend by a 32-bit unsigned divisor, producing a
2952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown32-bit quotient.  In the overflow cases (divide by 0, or quotient
2953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownexceeds 32 bits), it returns a remainder of 0xFFFFFFFF (an impossible
2954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvalue).
2955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   The dividend is u1 and u0, with u1 being the most significant word.
2956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownThe divisor is parameter v. The value returned is the quotient.
2957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Max line length is 57, to fit in hacker.book. */
2958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Int nlz32(UInt x)
2960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int n;
2962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (x == 0) return(32);
2963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   n = 0;
2964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (x <= 0x0000FFFF) {n = n +16; x = x <<16;}
2965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (x <= 0x00FFFFFF) {n = n + 8; x = x << 8;}
2966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (x <= 0x0FFFFFFF) {n = n + 4; x = x << 4;}
2967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (x <= 0x3FFFFFFF) {n = n + 2; x = x << 2;}
2968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (x <= 0x7FFFFFFF) {n = n + 1;}
2969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return n;
2970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* 64 x 32 ==> 32 unsigned division, using only 32 x 32 ==> 32
2973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   division as a primitive. */
2974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UInt divlu2(UInt u1, UInt u0, UInt v, UInt *r)
2975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   const UInt b = 65536;     // Number base (16 bits).
2977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt un1, un0,            // Norm. dividend LSD's.
2978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        vn1, vn0,            // Norm. divisor digits.
2979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        q1, q0,              // Quotient digits.
2980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        un32, un21, un10,    // Dividend digit pairs.
2981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        rhat;                // A remainder.
2982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int s;                    // Shift amount for norm.
2983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (u1 >= v) {            // If overflow, set rem.
2985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (r != NULL)         // to an impossible value,
2986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *r = 0xFFFFFFFF;    // and return the largest
2987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return 0xFFFFFFFF;}    // possible quotient.
2988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   s = nlz32(v);             // 0 <= s <= 31.
2990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   v = v << s;               // Normalize divisor.
2991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vn1 = v >> 16;            // Break divisor up into
2992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vn0 = v & 0xFFFF;         // two 16-bit digits.
2993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   un32 = (u1 << s) | ((u0 >> (32 - s)) & (-s >> 31));
2995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   un10 = u0 << s;           // Shift dividend left.
2996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   un1 = un10 >> 16;         // Break right half of
2998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   un0 = un10 & 0xFFFF;      // dividend into two digits.
2999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   q1 = un32/vn1;            // Compute the first
3001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   rhat = un32 - q1*vn1;     // quotient digit, q1.
3002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown again1:
3003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (q1 >= b || q1*vn0 > b*rhat + un1) {
3004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     q1 = q1 - 1;
3005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     rhat = rhat + vn1;
3006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     if (rhat < b) goto again1;}
3007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   un21 = un32*b + un1 - q1*v;  // Multiply and subtract.
3009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   q0 = un21/vn1;            // Compute the second
3011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   rhat = un21 - q0*vn1;     // quotient digit, q0.
3012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown again2:
3013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (q0 >= b || q0*vn0 > b*rhat + un0) {
3014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     q0 = q0 - 1;
3015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     rhat = rhat + vn1;
3016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     if (rhat < b) goto again2;}
3017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (r != NULL)            // If remainder is wanted,
3019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *r = (un21*b + un0 - q0*v) >> s;     // return it.
3020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return q1*b + q0;
3021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* 64 x 32 ==> 32 signed division, using only 32 x 32 ==> 32 division
3025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   as a primitive. */
3026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Int divls(Int u1, UInt u0, Int v, Int *r)
3027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int q, uneg, vneg, diff, borrow;
3029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   uneg = u1 >> 31;          // -1 if u < 0.
3031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (uneg) {               // Compute the absolute
3032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      u0 = -u0;              // value of the dividend u.
3033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      borrow = (u0 != 0);
3034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      u1 = -u1 - borrow;}
3035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vneg = v >> 31;           // -1 if v < 0.
3037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   v = (v ^ vneg) - vneg;    // Absolute value of v.
3038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if ((UInt)u1 >= (UInt)v) goto overflow;
3040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   q = divlu2(u1, u0, v, (UInt *)r);
3042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   diff = uneg ^ vneg;       // Negate q if signs of
3044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   q = (q ^ diff) - diff;    // u and v differed.
3045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (uneg && r != NULL)
3046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *r = -*r;
3047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if ((diff ^ q) < 0 && q != 0) {  // If overflow,
3049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown overflow:                    // set remainder
3050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (r != NULL)         // to an impossible value,
3051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *r = 0x80000000;    // and return the largest
3052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      q = 0x80000000;}       // possible neg. quotient.
3053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return q;
3054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* This file contains a program for doing 64/64 ==> 64 division, on a
3059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownmachine that does not have that instruction but that does have
3060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browninstructions for "long division" (64/32 ==> 32). Code for unsigned
3061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browndivision is given first, followed by a simple program for doing the
3062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownsigned version by using the unsigned version.
3063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   These programs are useful in implementing "long long" (64-bit)
3064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownarithmetic on a machine that has the long division instruction. It will
3065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownwork on 64- and 32-bit machines, provided the compiler implements long
3066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownlong's (64-bit integers). It is desirable that the machine have the
3067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownCount Leading Zeros instruction.
3068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   In the GNU world, these programs are known as __divdi3 and __udivdi3,
3069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownand similar names are used here.
3070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   This material is not in HD, but may be in a future edition.
3071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownMax line length is 57, to fit in hacker.book. */
3072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Int nlz64(ULong x)
3075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int n;
3077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (x == 0) return(64);
3078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   n = 0;
3079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (x <= 0x00000000FFFFFFFFULL) {n = n + 32; x = x << 32;}
3080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (x <= 0x0000FFFFFFFFFFFFULL) {n = n + 16; x = x << 16;}
3081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (x <= 0x00FFFFFFFFFFFFFFULL) {n = n +  8; x = x <<  8;}
3082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (x <= 0x0FFFFFFFFFFFFFFFULL) {n = n +  4; x = x <<  4;}
3083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (x <= 0x3FFFFFFFFFFFFFFFULL) {n = n +  2; x = x <<  2;}
3084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (x <= 0x7FFFFFFFFFFFFFFFULL) {n = n +  1;}
3085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return n;
3086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// ---------------------------- udivdi3 --------------------------------
3089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* The variables u0, u1, etc. take on only 32-bit values, but they
3091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   are declared long long to avoid some compiler warning messages and to
3092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   avoid some unnecessary EXTRs that the compiler would put in, to
3093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   convert long longs to ints.
3094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   First the procedure takes care of the case in which the divisor is a
3096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   32-bit quantity. There are two subcases: (1) If the left half of the
3097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   dividend is less than the divisor, one execution of DIVU is all that
3098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   is required (overflow is not possible). (2) Otherwise it does two
3099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   divisions, using the grade school method, with variables used as
3100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   suggested below.
3101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       q1 q0
3103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ________
3104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   v)  u1 u0
3105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     q1*v
3106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     ____
3107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        k u0   */
3108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* These macros must be used with arguments of the appropriate type
3110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown(unsigned long long for DIVU and long long for DIVS. They are
3111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownsimulations of the presumed machines ops. I.e., they look at only the
3112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownlow-order 32 bits of the divisor, they return garbage if the division
3113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownoverflows, and they return garbage in the high-order half of the
3114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownquotient doubleword.
3115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   In practice, these would be replaced with uses of the machine's DIVU
3116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownand DIVS instructions (e.g., by using the GNU "asm" facility). */
3117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UInt DIVU ( ULong u, UInt v )
3119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  UInt uHi = (UInt)(u >> 32);
3121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  UInt uLo = (UInt)u;
3122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  return divlu2(uHi, uLo, v, NULL);
3123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Int DIVS ( Long u, Int v )
3126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Int  uHi = (Int)(u >> 32);
3128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  UInt uLo = (UInt)u;
3129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  return divls(uHi, uLo, v, NULL);
3130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* 64 x 64 ==> 64 unsigned division, using only 32 x 32 ==> 32
3133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   division as a primitive. */
3134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic ULong udivdi3(ULong u, ULong v)
3135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ULong u0, u1, v1, q0, q1, k, n;
3137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (v >> 32 == 0) {          // If v < 2**32:
3139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (u >> 32 < v)          // If u/v cannot overflow,
3140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return DIVU(u, v)      // just do one division.
3141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            & 0xFFFFFFFF;
3142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else {                    // If u/v would overflow:
3143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         u1 = u >> 32;          // Break u up into two
3144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         u0 = u & 0xFFFFFFFF;   // halves.
3145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         q1 = DIVU(u1, v)       // First quotient digit.
3146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            & 0xFFFFFFFF;
3147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         k = u1 - q1*v;         // First remainder, < v.
3148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         q0 = DIVU((k << 32) + u0, v) // 2nd quot. digit.
3149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            & 0xFFFFFFFF;
3150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return (q1 << 32) + q0;
3151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                // Here v >= 2**32.
3154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   n = nlz64(v);                // 0 <= n <= 31.
3155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   v1 = (v << n) >> 32;         // Normalize the divisor
3156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                // so its MSB is 1.
3157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   u1 = u >> 1;                 // To ensure no overflow.
3158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   q1 = DIVU(u1, v1)            // Get quotient from
3159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       & 0xFFFFFFFF;            // divide unsigned insn.
3160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   q0 = (q1 << n) >> 31;        // Undo normalization and
3161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                // division of u by 2.
3162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (q0 != 0)                 // Make q0 correct or
3163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      q0 = q0 - 1;              // too small by 1.
3164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if ((u - q0*v) >= v)
3165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      q0 = q0 + 1;              // Now q0 is correct.
3166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return q0;
3167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// ----------------------------- divdi3 --------------------------------
3171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* This routine presumes that smallish cases (those which can be done in
3173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownone execution of DIVS) are common. If this is not the case, the test for
3174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownthis case should be deleted.
3175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Note that the test for when DIVS can be used is not entirely
3176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownaccurate. For example, DIVS is not used if v = 0xFFFFFFFF8000000,
3177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownwhereas if could be (if u is sufficiently small in magnitude). */
3178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// ------------------------------ cut ----------------------------------
3180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic ULong my_llabs ( Long x )
3182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ULong t = x >> 63;
3184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return (x ^ t) - t;
3185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* 64 x 64 ==> 64 signed division, using only 32 x 32 ==> 32 division
3188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   as a primitive. */
3189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Long divdi3(Long u, Long v)
3190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ULong au, av;
3192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Long q, t;
3193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   au = my_llabs(u);
3194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   av = my_llabs(v);
3195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (av >> 31 == 0) {         // If |v| < 2**31 and
3196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // if (v << 32 >> 32 == v) { // If v is in range and
3197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (au < av << 31) {      // |u|/|v| cannot
3198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         q = DIVS(u, v);        // overflow, use DIVS.
3199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return (q << 32) >> 32;
3200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   q = udivdi3(au,av);          // Invoke udivdi3.
3203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   t = (u ^ v) >> 63;           // If u, v have different
3204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return (q ^ t) - t;          // signs, negate q.
3205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// ---------------------------- end cut --------------------------------
3208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownULong __udivdi3 (ULong u, ULong v);
3210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownULong __udivdi3 (ULong u, ULong v)
3211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  return udivdi3(u,v);
3213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownLong __divdi3 (Long u, Long v);
3216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownLong __divdi3 (Long u, Long v)
3217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  return divdi3(u,v);
3219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownULong __umoddi3 (ULong u, ULong v);
3222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownULong __umoddi3 (ULong u, ULong v)
3223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ULong q = __udivdi3(u, v);
3225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ULong r = u - q * v;
3226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  return r;
3227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownLong __moddi3 (Long u, Long v);
3230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownLong __moddi3 (Long u, Long v)
3231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Long q = __divdi3(u, v);
3233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Long r = u - q * v;
3234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  return r;
3235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3237b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* ------------------------------------------------
3238b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   ld_classic: Undefined symbols:
3239b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      ___fixunsdfdi
3240b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   ------------------------------------------------
3241b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov*/
3242b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
3243b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* ===-- fixunsdfdi.c - Implement __fixunsdfdi -----------------------------===
3244b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov *
3245b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov *                     The LLVM Compiler Infrastructure
3246b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov *
3247b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * This file is dual licensed under the MIT and the University of Illinois Open
3248b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * Source Licenses. See LICENSE.TXT for details.
3249b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov *
3250b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * ===----------------------------------------------------------------------===
3251b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov *
3252b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * This file implements __fixunsdfdi for the compiler_rt library.
3253b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov *
3254b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * ===----------------------------------------------------------------------===
3255b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov */
3256b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
3257b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* As per http://www.gnu.org/licenses/license-list.html#GPLCompatibleLicenses,
3258b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
3259b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   the "NCSA/University of Illinois Open Source License" is compatible
3260b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   with the GPL (both version 2 and 3).  What is claimed to be
3261b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   compatible is this
3262b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
3263b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   http://www.opensource.org/licenses/UoI-NCSA.php
3264b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
3265b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   and the LLVM documentation at
3266b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
3267b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   http://www.llvm.org/docs/DeveloperPolicy.html#license
3268b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
3269b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   says all the code in LLVM is available under the University of
3270b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   Illinois/NCSA Open Source License, at this URL
3271b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
3272b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   http://www.opensource.org/licenses/UoI-NCSA.php
3273b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
3274b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   viz, the same one that the FSF pages claim is compatible.  So I
3275b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   think it's OK to include it.
3276b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov*/
3277b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
3278b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* Returns: convert a to a unsigned long long, rounding toward zero.
3279b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov *          Negative values all become zero.
3280b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov */
3281b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
3282b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* Assumption: double is a IEEE 64 bit floating point type
3283b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov *             du_int is a 64 bit integral type
3284b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov *             value in double is representable in du_int or is negative
3285b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov *                 (no range checking performed)
3286b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov */
3287b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
3288b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* seee eeee eeee mmmm mmmm mmmm mmmm mmmm | mmmm mmmm mmmm mmmm mmmm mmmm mmmm mmmm */
3289b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
3290b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovtypedef unsigned long long du_int;
3291b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovtypedef unsigned su_int;
3292b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
3293b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovtypedef union
3294b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
3295b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    du_int all;
3296b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    struct
3297b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    {
3298b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#if VG_LITTLEENDIAN
3299b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        su_int low;
3300b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        su_int high;
3301b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#else
3302b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        su_int high;
3303b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        su_int low;
3304b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#endif /* VG_LITTLEENDIAN */
3305b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    }s;
3306b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov} udwords;
3307b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
3308b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovtypedef union
3309b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
3310b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    udwords u;
3311b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    double  f;
3312b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov} double_bits;
3313b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
3314b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovdu_int __fixunsdfdi(double a);
3315b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
3316b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovdu_int
3317b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov__fixunsdfdi(double a)
3318b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
3319b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    double_bits fb;
3320b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    fb.f = a;
3321b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    int e = ((fb.u.s.high & 0x7FF00000) >> 20) - 1023;
3322b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    if (e < 0 || (fb.u.s.high & 0x80000000))
3323b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        return 0;
3324b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    udwords r;
3325b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    r.s.high = (fb.u.s.high & 0x000FFFFF) | 0x00100000;
3326b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    r.s.low = fb.u.s.low;
3327b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    if (e > 52)
3328b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        r.all <<= (e - 52);
3329b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    else
3330b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        r.all >>= (52 - e);
3331b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    return r.all;
3332b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
3333b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
3334b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
3335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
3336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/
3339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- end                                                          ---*/
3340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/
3341