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