m_options.c revision 5dd0190bc0ea66f8ffa7218c66f5a2e1c7b51b30
1 2/*--------------------------------------------------------------------*/ 3/*--- Command line options. m_options.c ---*/ 4/*--------------------------------------------------------------------*/ 5 6/* 7 This file is part of Valgrind, a dynamic binary instrumentation 8 framework. 9 10 Copyright (C) 2000-2010 Nicholas Nethercote 11 njn@valgrind.org 12 13 This program is free software; you can redistribute it and/or 14 modify it under the terms of the GNU General Public License as 15 published by the Free Software Foundation; either version 2 of the 16 License, or (at your option) any later version. 17 18 This program is distributed in the hope that it will be useful, but 19 WITHOUT ANY WARRANTY; without even the implied warranty of 20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 21 General Public License for more details. 22 23 You should have received a copy of the GNU General Public License 24 along with this program; if not, write to the Free Software 25 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 26 02111-1307, USA. 27 28 The GNU General Public License is contained in the file COPYING. 29*/ 30 31#include "pub_core_basics.h" 32#include "pub_core_vki.h" 33#include "pub_core_options.h" 34#include "pub_core_libcassert.h" 35#include "pub_core_libcbase.h" 36#include "pub_core_libcfile.h" 37#include "pub_core_libcprint.h" 38#include "pub_core_libcproc.h" 39#include "pub_core_mallocfree.h" 40#include "pub_core_seqmatch.h" // VG_(string_match) 41 42// See pub_{core,tool}_options.h for explanations of all these. 43 44 45/* Define, and set defaults. */ 46VexControl VG_(clo_vex_control); 47Bool VG_(clo_error_limit) = True; 48Int VG_(clo_error_exitcode) = 0; 49Bool VG_(clo_db_attach) = False; 50Char* VG_(clo_db_command) = GDB_PATH " -nw %f %p"; 51Int VG_(clo_gen_suppressions) = 0; 52Int VG_(clo_sanity_level) = 1; 53Int VG_(clo_verbosity) = 1; 54Bool VG_(clo_stats) = False; 55Bool VG_(clo_xml) = False; 56HChar* VG_(clo_xml_user_comment) = NULL; 57Bool VG_(clo_demangle) = True; 58Bool VG_(clo_trace_children) = False; 59HChar* VG_(clo_trace_children_skip) = NULL; 60Bool VG_(clo_child_silent_after_fork) = False; 61Char* VG_(clo_log_fname_expanded) = NULL; 62Char* VG_(clo_xml_fname_expanded) = NULL; 63Bool VG_(clo_time_stamp) = False; 64Int VG_(clo_input_fd) = 0; /* stdin */ 65Int VG_(clo_n_suppressions) = 0; 66Char* VG_(clo_suppressions)[VG_CLO_MAX_SFILES]; 67UChar VG_(clo_trace_flags) = 0; // 00000000b 68UChar VG_(clo_profile_flags) = 0; // 00000000b 69Int VG_(clo_trace_notbelow) = 999999999; 70Bool VG_(clo_trace_syscalls) = False; 71Bool VG_(clo_trace_signals) = False; 72Bool VG_(clo_trace_symtab) = False; 73HChar* VG_(clo_trace_symtab_patt) = "*"; 74Bool VG_(clo_trace_cfi) = False; 75Bool VG_(clo_debug_dump_syms) = False; 76Bool VG_(clo_debug_dump_line) = False; 77Bool VG_(clo_debug_dump_frames) = False; 78Bool VG_(clo_trace_redir) = False; 79Bool VG_(clo_trace_sched) = False; 80Bool VG_(clo_profile_heap) = False; 81Int VG_(clo_dump_error) = 0; 82Int VG_(clo_backtrace_size) = 12; 83Char* VG_(clo_sim_hints) = NULL; 84Bool VG_(clo_sym_offsets) = False; 85Bool VG_(clo_read_var_info) = False; 86Char* VG_(clo_prefix_to_strip) = NULL; 87Int VG_(clo_n_req_tsyms) = 0; 88HChar* VG_(clo_req_tsyms)[VG_CLO_MAX_REQ_TSYMS]; 89HChar* VG_(clo_require_text_symbol) = NULL; 90Bool VG_(clo_run_libc_freeres) = True; 91Bool VG_(clo_track_fds) = False; 92Bool VG_(clo_show_below_main)= False; 93Bool VG_(clo_show_emwarns) = False; 94Word VG_(clo_max_stackframe) = 2000000; 95Word VG_(clo_main_stacksize) = 0; /* use client's rlimit.stack */ 96Bool VG_(clo_wait_for_gdb) = False; 97VgSmc VG_(clo_smc_check) = Vg_SmcStack; 98HChar* VG_(clo_kernel_variant) = NULL; 99Bool VG_(clo_dsymutil) = False; 100 101 102/*====================================================================*/ 103/*=== File expansion ===*/ 104/*====================================================================*/ 105 106// Copies the string, prepending it with the startup working directory, and 107// expanding %p and %q entries. Returns a new, malloc'd string. 108Char* VG_(expand_file_name)(Char* option_name, Char* format) 109{ 110 static Char base_dir[VKI_PATH_MAX]; 111 Int len, i = 0, j = 0; 112 Char* out; 113 114 Bool ok = VG_(get_startup_wd)(base_dir, VKI_PATH_MAX); 115 tl_assert(ok); 116 117 if (VG_STREQ(format, "")) { 118 // Empty name, bad. 119 VG_(fmsg)("%s: filename is empty", option_name); 120 goto bad; 121 } 122 123 // If 'format' starts with a '~', abort -- the user probably expected the 124 // shell to expand but it didn't (see bug 195268 for details). This means 125 // that we don't allow a legitimate filename beginning with '~' but that 126 // seems very unlikely. 127 if (format[0] == '~') { 128 VG_(fmsg)( 129 "%s: filename begins with '~'\n" 130 "You probably expected the shell to expand the '~', but it\n" 131 "didn't. The rules for '~'-expansion vary from shell to shell.\n" 132 "You might have more luck using $HOME instead.\n", 133 option_name 134 ); 135 goto bad; 136 } 137 138 // If 'format' starts with a '/', do not prefix with startup dir. 139 if (format[0] != '/') { 140 j += VG_(strlen)(base_dir); 141 } 142 143 // The 10 is slop, it should be enough in most cases. 144 len = j + VG_(strlen)(format) + 10; 145 out = VG_(malloc)( "options.efn.1", len ); 146 if (format[0] != '/') { 147 VG_(strcpy)(out, base_dir); 148 out[j++] = '/'; 149 } 150 151#define ENSURE_THIS_MUCH_SPACE(x) \ 152 if (j + x >= len) { \ 153 len += (10 + x); \ 154 out = VG_(realloc)("options.efn.2(multiple)", out, len); \ 155 } 156 157 while (format[i]) { 158 if (format[i] != '%') { 159 ENSURE_THIS_MUCH_SPACE(1); 160 out[j++] = format[i++]; 161 162 } else { 163 // We saw a '%'. What's next... 164 i++; 165 if ('%' == format[i]) { 166 // Replace '%%' with '%'. 167 ENSURE_THIS_MUCH_SPACE(1); 168 out[j++] = format[i++]; 169 } 170 else if ('p' == format[i]) { 171 // Print the PID. Assume that it's not longer than 10 chars -- 172 // reasonable since 'pid' is an Int (ie. 32 bits). 173 Int pid = VG_(getpid)(); 174 ENSURE_THIS_MUCH_SPACE(10); 175 j += VG_(sprintf)(&out[j], "%d", pid); 176 i++; 177 } 178 else if ('q' == format[i]) { 179 i++; 180 if ('{' == format[i]) { 181 // Get the env var name, print its contents. 182 Char* qualname; 183 Char* qual; 184 i++; 185 qualname = &format[i]; 186 while (True) { 187 if (0 == format[i]) { 188 VG_(fmsg)("%s: malformed %%q specifier\n", option_name); 189 goto bad; 190 } else if ('}' == format[i]) { 191 // Temporarily replace the '}' with NUL to extract var 192 // name. 193 format[i] = 0; 194 qual = VG_(getenv)(qualname); 195 if (NULL == qual) { 196 VG_(fmsg)("%s: environment variable %s is not set\n", 197 option_name, qualname); 198 format[i] = '}'; // Put the '}' back. 199 goto bad; 200 } 201 format[i] = '}'; // Put the '}' back. 202 i++; 203 break; 204 } 205 i++; 206 } 207 ENSURE_THIS_MUCH_SPACE(VG_(strlen)(qual)); 208 j += VG_(sprintf)(&out[j], "%s", qual); 209 } else { 210 VG_(fmsg)("%s: expected '{' after '%%q'\n", option_name); 211 goto bad; 212 } 213 } 214 else { 215 // Something else, abort. 216 VG_(fmsg)("%s: expected 'p' or 'q' or '%%' after '%%'\n", 217 option_name); 218 goto bad; 219 } 220 } 221 } 222 ENSURE_THIS_MUCH_SPACE(1); 223 out[j++] = 0; 224 225 return out; 226 227 bad: { 228 Char* opt = // 2: 1 for the '=', 1 for the NUL. 229 VG_(malloc)( "options.efn.3", 230 VG_(strlen)(option_name) + VG_(strlen)(format) + 2 ); 231 VG_(strcpy)(opt, option_name); 232 VG_(strcat)(opt, "="); 233 VG_(strcat)(opt, format); 234 VG_(fmsg_bad_option)(opt, ""); 235 } 236} 237 238/*====================================================================*/ 239/*=== --trace-children= support ===*/ 240/*====================================================================*/ 241 242static HChar const* consume_commas ( HChar const* c ) { 243 while (*c && *c == ',') { 244 ++c; 245 } 246 return c; 247} 248 249static HChar const* consume_field ( HChar const* c ) { 250 while (*c && *c != ',') { 251 ++c; 252 } 253 return c; 254} 255 256/* Should we trace into this child executable (across execve etc) ? 257 This involves considering --trace-children=, --trace-children-skip= 258 and the name of the executable. */ 259Bool VG_(should_we_trace_this_child) ( HChar* child_exe_name ) 260{ 261 // child_exe_name is pulled out of the guest's space. We 262 // should be at least marginally cautious with it, lest it 263 // explode or burst into flames unexpectedly. 264 if (child_exe_name == NULL || VG_(strlen)(child_exe_name) == 0) 265 return VG_(clo_trace_children); // we know narfink 266 267 // the main logic 268 // If --trace-children=no, the answer is simply NO. 269 if (! VG_(clo_trace_children)) 270 return False; 271 272 // otherwise, return True, unless the exe name matches any of the 273 // patterns specified by --trace-children-skip=. 274 if (VG_(clo_trace_children_skip)) { 275 HChar const* last = VG_(clo_trace_children_skip); 276 HChar const* name = (HChar const*)child_exe_name; 277 while (*last) { 278 Bool matches; 279 HChar* patt; 280 HChar const* first = consume_commas(last); 281 last = consume_field(first); 282 if (first == last) 283 break; 284 vg_assert(last > first); 285 /* copy the candidate string into a temporary malloc'd block 286 so we can use VG_(string_match) on it. */ 287 patt = VG_(calloc)("m_options.swttc.1", last - first + 1, 1); 288 VG_(memcpy)(patt, first, last - first); 289 vg_assert(patt[last-first] == 0); 290 matches = VG_(string_match)(patt, name); 291 VG_(free)(patt); 292 if (matches) 293 return False; 294 } 295 } 296 297 // --trace-children=yes, and this particular executable isn't 298 // excluded 299 return True; 300} 301 302 303/*--------------------------------------------------------------------*/ 304/*--- end ---*/ 305/*--------------------------------------------------------------------*/ 306