1ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/ 3ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Command line options. m_options.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 Nicholas Nethercote 11ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown njn@valgrind.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_options.h" 34ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_libcassert.h" 35ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_libcbase.h" 36ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_libcfile.h" 37ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_libcprint.h" 38ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_libcproc.h" 39ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_mallocfree.h" 40ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_seqmatch.h" // VG_(string_match) 41ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 42ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// See pub_{core,tool}_options.h for explanations of all these. 43ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 44ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 45ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Define, and set defaults. */ 46ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownVexControl VG_(clo_vex_control); 47ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool VG_(clo_error_limit) = True; 48ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownInt VG_(clo_error_exitcode) = 0; 49b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 50b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy StepanovVgVgdb VG_(clo_vgdb) = Vg_VgdbYes; 51b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy StepanovInt VG_(clo_vgdb_poll) = 5000; 52b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy StepanovInt VG_(clo_vgdb_error) = 999999999; 53b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy StepanovHChar* VG_(clo_vgdb_prefix) = NULL; 54b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy StepanovBool VG_(clo_vgdb_shadow_registers) = False; 55b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 56ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool VG_(clo_db_attach) = False; 57ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownChar* VG_(clo_db_command) = GDB_PATH " -nw %f %p"; 58ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownInt VG_(clo_gen_suppressions) = 0; 59ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownInt VG_(clo_sanity_level) = 1; 60ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownInt VG_(clo_verbosity) = 1; 61ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool VG_(clo_stats) = False; 62ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool VG_(clo_xml) = False; 63ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownHChar* VG_(clo_xml_user_comment) = NULL; 64ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool VG_(clo_demangle) = True; 65ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool VG_(clo_trace_children) = False; 66ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownHChar* VG_(clo_trace_children_skip) = NULL; 67b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy StepanovHChar* VG_(clo_trace_children_skip_by_arg) = NULL; 68ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool VG_(clo_child_silent_after_fork) = False; 69ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownChar* VG_(clo_log_fname_expanded) = NULL; 70ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownChar* VG_(clo_xml_fname_expanded) = NULL; 71ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool VG_(clo_time_stamp) = False; 72ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownInt VG_(clo_input_fd) = 0; /* stdin */ 73ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownInt VG_(clo_n_suppressions) = 0; 74ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownChar* VG_(clo_suppressions)[VG_CLO_MAX_SFILES]; 75ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownInt VG_(clo_n_fullpath_after) = 0; 76ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownChar* VG_(clo_fullpath_after)[VG_CLO_MAX_FULLPATH_AFTER]; 77ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownUChar VG_(clo_trace_flags) = 0; // 00000000b 78ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownUChar VG_(clo_profile_flags) = 0; // 00000000b 79ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownInt VG_(clo_trace_notbelow) = 999999999; 80ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool VG_(clo_trace_syscalls) = False; 81ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool VG_(clo_trace_signals) = False; 82ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool VG_(clo_trace_symtab) = False; 83ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownHChar* VG_(clo_trace_symtab_patt) = "*"; 84ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool VG_(clo_trace_cfi) = False; 85ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool VG_(clo_debug_dump_syms) = False; 86ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool VG_(clo_debug_dump_line) = False; 87ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool VG_(clo_debug_dump_frames) = False; 88ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool VG_(clo_trace_redir) = False; 89ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool VG_(clo_trace_sched) = False; 90ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool VG_(clo_profile_heap) = False; 91ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownInt VG_(clo_dump_error) = 0; 92ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownInt VG_(clo_backtrace_size) = 12; 93ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownChar* VG_(clo_sim_hints) = NULL; 94ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool VG_(clo_sym_offsets) = False; 95ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool VG_(clo_read_var_info) = False; 96ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownInt VG_(clo_n_req_tsyms) = 0; 97ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownHChar* VG_(clo_req_tsyms)[VG_CLO_MAX_REQ_TSYMS]; 98ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownHChar* VG_(clo_require_text_symbol) = NULL; 99ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool VG_(clo_run_libc_freeres) = True; 100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool VG_(clo_track_fds) = False; 101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool VG_(clo_show_below_main)= False; 102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool VG_(clo_show_emwarns) = False; 103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownWord VG_(clo_max_stackframe) = 2000000; 104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownWord VG_(clo_main_stacksize) = 0; /* use client's rlimit.stack */ 105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool VG_(clo_wait_for_gdb) = False; 106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownVgSmc VG_(clo_smc_check) = Vg_SmcStack; 107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownHChar* VG_(clo_kernel_variant) = NULL; 108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool VG_(clo_dsymutil) = False; 109b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy StepanovChar* VG_(clo_nacl_file) = NULL; 110f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy StepanovChar* VG_(clo_memfs_malloc_path) = NULL; 111f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy StepanovInt VG_(clo_memfs_page_size) = 2048; /* 2M */ 112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*====================================================================*/ 115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*=== File expansion ===*/ 116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*====================================================================*/ 117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Copies the string, prepending it with the startup working directory, and 119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// expanding %p and %q entries. Returns a new, malloc'd string. 120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownChar* VG_(expand_file_name)(Char* option_name, Char* format) 121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown static Char base_dir[VKI_PATH_MAX]; 123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int len, i = 0, j = 0; 124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Char* out; 125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool ok = VG_(get_startup_wd)(base_dir, VKI_PATH_MAX); 127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(ok); 128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_STREQ(format, "")) { 130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // Empty name, bad. 131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(fmsg)("%s: filename is empty", option_name); 132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown goto bad; 133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // If 'format' starts with a '~', abort -- the user probably expected the 136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // shell to expand but it didn't (see bug 195268 for details). This means 137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // that we don't allow a legitimate filename beginning with '~' but that 138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // seems very unlikely. 139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (format[0] == '~') { 140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(fmsg)( 141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "%s: filename begins with '~'\n" 142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "You probably expected the shell to expand the '~', but it\n" 143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "didn't. The rules for '~'-expansion vary from shell to shell.\n" 144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "You might have more luck using $HOME instead.\n", 145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown option_name 146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ); 147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown goto bad; 148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // If 'format' starts with a '/', do not prefix with startup dir. 151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (format[0] != '/') { 152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown j += VG_(strlen)(base_dir); 153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // The 10 is slop, it should be enough in most cases. 156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown len = j + VG_(strlen)(format) + 10; 157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown out = VG_(malloc)( "options.efn.1", len ); 158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (format[0] != '/') { 159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(strcpy)(out, base_dir); 160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown out[j++] = '/'; 161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define ENSURE_THIS_MUCH_SPACE(x) \ 164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (j + x >= len) { \ 165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown len += (10 + x); \ 166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown out = VG_(realloc)("options.efn.2(multiple)", out, len); \ 167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while (format[i]) { 170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (format[i] != '%') { 171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ENSURE_THIS_MUCH_SPACE(1); 172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown out[j++] = format[i++]; 173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // We saw a '%'. What's next... 176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown i++; 177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if ('%' == format[i]) { 178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // Replace '%%' with '%'. 179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ENSURE_THIS_MUCH_SPACE(1); 180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown out[j++] = format[i++]; 181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else if ('p' == format[i]) { 183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // Print the PID. Assume that it's not longer than 10 chars -- 184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // reasonable since 'pid' is an Int (ie. 32 bits). 185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int pid = VG_(getpid)(); 186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ENSURE_THIS_MUCH_SPACE(10); 187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown j += VG_(sprintf)(&out[j], "%d", pid); 188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown i++; 189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else if ('q' == format[i]) { 191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown i++; 192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if ('{' == format[i]) { 193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // Get the env var name, print its contents. 194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Char* qualname; 195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Char* qual; 196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown i++; 197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown qualname = &format[i]; 198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while (True) { 199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (0 == format[i]) { 200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(fmsg)("%s: malformed %%q specifier\n", option_name); 201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown goto bad; 202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else if ('}' == format[i]) { 203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // Temporarily replace the '}' with NUL to extract var 204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // name. 205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown format[i] = 0; 206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown qual = VG_(getenv)(qualname); 207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (NULL == qual) { 208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(fmsg)("%s: environment variable %s is not set\n", 209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown option_name, qualname); 210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown format[i] = '}'; // Put the '}' back. 211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown goto bad; 212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown format[i] = '}'; // Put the '}' back. 214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown i++; 215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown i++; 218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ENSURE_THIS_MUCH_SPACE(VG_(strlen)(qual)); 220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown j += VG_(sprintf)(&out[j], "%s", qual); 221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(fmsg)("%s: expected '{' after '%%q'\n", option_name); 223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown goto bad; 224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else { 227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // Something else, abort. 228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(fmsg)("%s: expected 'p' or 'q' or '%%' after '%%'\n", 229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown option_name); 230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown goto bad; 231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ENSURE_THIS_MUCH_SPACE(1); 235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown out[j++] = 0; 236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return out; 238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bad: { 240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Char* opt = // 2: 1 for the '=', 1 for the NUL. 241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(malloc)( "options.efn.3", 242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(strlen)(option_name) + VG_(strlen)(format) + 2 ); 243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(strcpy)(opt, option_name); 244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(strcat)(opt, "="); 245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(strcat)(opt, format); 246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(fmsg_bad_option)(opt, ""); 247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*====================================================================*/ 251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*=== --trace-children= support ===*/ 252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*====================================================================*/ 253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HChar const* consume_commas ( HChar const* c ) { 255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while (*c && *c == ',') { 256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ++c; 257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return c; 259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic HChar const* consume_field ( HChar const* c ) { 262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while (*c && *c != ',') { 263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ++c; 264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return c; 266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Should we trace into this child executable (across execve etc) ? 269b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov This involves considering --trace-children=, 270b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov --trace-children-skip=, --trace-children-skip-by-arg=, and the name 271b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov of the executable. 'child_argv' must not include the name of the 272b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov executable itself; iow child_argv[0] must be the first arg, if any, 273b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov for the child. */ 274b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy StepanovBool VG_(should_we_trace_this_child) ( HChar* child_exe_name, 275b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov HChar** child_argv ) 276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // child_exe_name is pulled out of the guest's space. We 278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // should be at least marginally cautious with it, lest it 279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // explode or burst into flames unexpectedly. 280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (child_exe_name == NULL || VG_(strlen)(child_exe_name) == 0) 281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return VG_(clo_trace_children); // we know narfink 282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // If --trace-children=no, the answer is simply NO. 284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (! VG_(clo_trace_children)) 285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; 286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 287b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov // Otherwise, look for other reasons to say NO. First, 288b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov // see if the exe name matches any of the patterns specified 289b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov // by --trace-children-skip=. 290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_trace_children_skip)) { 291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HChar const* last = VG_(clo_trace_children_skip); 292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HChar const* name = (HChar const*)child_exe_name; 293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while (*last) { 294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool matches; 295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HChar* patt; 296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HChar const* first = consume_commas(last); 297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown last = consume_field(first); 298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (first == last) 299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(last > first); 301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* copy the candidate string into a temporary malloc'd block 302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown so we can use VG_(string_match) on it. */ 303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown patt = VG_(calloc)("m_options.swttc.1", last - first + 1, 1); 304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(memcpy)(patt, first, last - first); 305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(patt[last-first] == 0); 306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown matches = VG_(string_match)(patt, name); 307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(free)(patt); 308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (matches) 309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; 310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 312b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 313b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov // Check if any of the args match any of the patterns specified 314b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov // by --trace-children-skip-by-arg=. 315b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (VG_(clo_trace_children_skip_by_arg) && child_argv != NULL) { 316b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov HChar const* last = VG_(clo_trace_children_skip_by_arg); 317b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov while (*last) { 318b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov Int i; 319b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov Bool matches; 320b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov HChar* patt; 321b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov HChar const* first = consume_commas(last); 322b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov last = consume_field(first); 323b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (first == last) 324b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov break; 325b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov vg_assert(last > first); 326b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* copy the candidate string into a temporary malloc'd block 327b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov so we can use VG_(string_match) on it. */ 328b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov patt = VG_(calloc)("m_options.swttc.1", last - first + 1, 1); 329b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VG_(memcpy)(patt, first, last - first); 330b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov vg_assert(patt[last-first] == 0); 331b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov for (i = 0; child_argv[i]; i++) { 332b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov matches = VG_(string_match)(patt, child_argv[i]); 333b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (matches) { 334b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VG_(free)(patt); 335b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov return False; 336b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 337b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 338b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VG_(free)(patt); 339b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 340b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 341b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // --trace-children=yes, and this particular executable isn't 343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // excluded 344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return True; 345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/ 349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- end ---*/ 350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/ 351