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