m_options.c revision 9f207460d70d38c46c9e81996a3dcdf90961c6db
1 2/*--------------------------------------------------------------------*/ 3/*--- Command line options. ---*/ 4/*--- m_options.c ---*/ 5/*--------------------------------------------------------------------*/ 6 7/* 8 This file is part of Valgrind, a dynamic binary instrumentation 9 framework. 10 11 Copyright (C) 2000-2009 Nicholas Nethercote 12 njn@valgrind.org 13 14 This program is free software; you can redistribute it and/or 15 modify it under the terms of the GNU General Public License as 16 published by the Free Software Foundation; either version 2 of the 17 License, or (at your option) any later version. 18 19 This program is distributed in the hope that it will be useful, but 20 WITHOUT ANY WARRANTY; without even the implied warranty of 21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 22 General Public License for more details. 23 24 You should have received a copy of the GNU General Public License 25 along with this program; if not, write to the Free Software 26 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 27 02111-1307, USA. 28 29 The GNU General Public License is contained in the file COPYING. 30*/ 31 32#include "pub_core_basics.h" 33#include "pub_core_vki.h" 34#include "pub_core_options.h" 35#include "pub_core_libcassert.h" 36#include "pub_core_libcbase.h" 37#include "pub_core_libcfile.h" 38#include "pub_core_libcprint.h" 39#include "pub_core_libcproc.h" 40#include "pub_core_mallocfree.h" 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_xml) = False; 55HChar* VG_(clo_xml_user_comment) = NULL; 56Bool VG_(clo_demangle) = True; 57Bool VG_(clo_trace_children) = False; 58Bool VG_(clo_child_silent_after_fork) = False; 59Int VG_(clo_log_fd) = 2; /* must be signed, as -1 is possible. */ 60Char* VG_(clo_log_name) = NULL; 61Bool VG_(clo_time_stamp) = False; 62Int VG_(clo_input_fd) = 0; /* stdin */ 63Int VG_(clo_n_suppressions) = 0; 64Char* VG_(clo_suppressions)[VG_CLO_MAX_SFILES]; 65UChar VG_(clo_trace_flags) = 0; // 00000000b 66UChar VG_(clo_profile_flags) = 0; // 00000000b 67Int VG_(clo_trace_notbelow) = 999999999; 68Bool VG_(clo_trace_syscalls) = False; 69Bool VG_(clo_trace_signals) = False; 70Bool VG_(clo_trace_symtab) = False; 71HChar* VG_(clo_trace_symtab_patt) = "*"; 72Bool VG_(clo_trace_cfi) = False; 73Bool VG_(clo_debug_dump_syms) = False; 74Bool VG_(clo_debug_dump_line) = False; 75Bool VG_(clo_debug_dump_frames) = False; 76Bool VG_(clo_trace_redir) = False; 77Bool VG_(clo_trace_sched) = False; 78Bool VG_(clo_profile_heap) = False; 79Int VG_(clo_dump_error) = 0; 80Int VG_(clo_backtrace_size) = 12; 81Char* VG_(clo_sim_hints) = NULL; 82Bool VG_(clo_sym_offsets) = False; 83Bool VG_(clo_read_var_info) = False; 84Bool VG_(clo_run_libc_freeres) = True; 85Bool VG_(clo_track_fds) = False; 86Bool VG_(clo_show_below_main)= False; 87Bool VG_(clo_show_emwarns) = False; 88Word VG_(clo_max_stackframe) = 2000000; 89Word VG_(clo_main_stacksize) = 0; /* use client's rlimit.stack */ 90Bool VG_(clo_wait_for_gdb) = False; 91VgSmc VG_(clo_smc_check) = Vg_SmcStack; 92HChar* VG_(clo_kernel_variant) = NULL; 93 94 95/*====================================================================*/ 96/*=== Command line errors ===*/ 97/*====================================================================*/ 98 99static void revert_to_stderr ( void ) 100{ 101 vg_assert( !VG_(logging_to_socket) ); 102 VG_(clo_log_fd) = 2; /* stderr */ 103} 104 105__attribute__((noreturn)) 106void VG_(err_bad_option) ( Char* opt ) 107{ 108 revert_to_stderr(); 109 VG_(printf)("valgrind: Bad option '%s'; aborting.\n", opt); 110 VG_(printf)("valgrind: Use --help for more information.\n"); 111 VG_(exit)(1); 112} 113 114__attribute__((noreturn)) 115void VG_(err_missing_prog) ( void ) 116{ 117 revert_to_stderr(); 118 VG_(printf)("valgrind: no program specified\n"); 119 VG_(printf)("valgrind: Use --help for more information.\n"); 120 VG_(exit)(1); 121} 122 123__attribute__((noreturn)) 124void VG_(err_config_error) ( Char* msg ) 125{ 126 revert_to_stderr(); 127 VG_(printf)("valgrind: Startup or configuration error:\n %s\n", msg); 128 VG_(printf)("valgrind: Unable to start up properly. Giving up.\n"); 129 VG_(exit)(1); 130} 131 132// Copies the string, prepending it with the startup working directory, and 133// expanding %p and %q entries. Returns a new, malloc'd string. 134Char* VG_(expand_file_name)(Char* option_name, Char* format) 135{ 136 static Char base_dir[VKI_PATH_MAX]; 137 Int len, i = 0, j = 0; 138 Char* out; 139 140 Bool ok = VG_(get_startup_wd)(base_dir, VKI_PATH_MAX); 141 tl_assert(ok); 142 143 if (VG_STREQ(format, "")) { 144 // Empty name, bad. 145 VG_(message)(Vg_UserMsg, "%s: filename is empty", option_name); 146 goto bad; 147 } 148 149 // If 'format' starts with a '/', do not prefix with startup dir. 150 if (format[0] != '/') { 151 j += VG_(strlen)(base_dir); 152 } 153 154 // The 10 is slop, it should be enough in most cases. 155 len = j + VG_(strlen)(format) + 10; 156 out = VG_(malloc)( "options.efn.1", len ); 157 if (format[0] != '/') { 158 VG_(strcpy)(out, base_dir); 159 out[j++] = '/'; 160 } 161 162#define ENSURE_THIS_MUCH_SPACE(x) \ 163 if (j + x >= len) { \ 164 len += (10 + x); \ 165 out = VG_(realloc)("options.efn.2(multiple)", out, len); \ 166 } 167 168 while (format[i]) { 169 if (format[i] != '%') { 170 ENSURE_THIS_MUCH_SPACE(1); 171 out[j++] = format[i++]; 172 173 } else { 174 // We saw a '%'. What's next... 175 i++; 176 if ('%' == format[i]) { 177 // Replace '%%' with '%'. 178 ENSURE_THIS_MUCH_SPACE(1); 179 out[j++] = format[i++]; 180 } 181 else if ('p' == format[i]) { 182 // Print the PID. Assume that it's not longer than 10 chars -- 183 // reasonable since 'pid' is an Int (ie. 32 bits). 184 Int pid = VG_(getpid)(); 185 ENSURE_THIS_MUCH_SPACE(10); 186 j += VG_(sprintf)(&out[j], "%d", pid); 187 i++; 188 } 189 else if ('q' == format[i]) { 190 i++; 191 if ('{' == format[i]) { 192 // Get the env var name, print its contents. 193 Char* qualname; 194 Char* qual; 195 i++; 196 qualname = &format[i]; 197 while (True) { 198 if (0 == format[i]) { 199 VG_(message)(Vg_UserMsg, "%s: malformed %%q specifier", 200 option_name); 201 goto bad; 202 } else if ('}' == format[i]) { 203 // Temporarily replace the '}' with NUL to extract var 204 // name. 205 format[i] = 0; 206 qual = VG_(getenv)(qualname); 207 if (NULL == qual) { 208 VG_(message)(Vg_UserMsg, 209 "%s: environment variable %s is not set", 210 option_name, qualname); 211 format[i] = '}'; // Put the '}' back. 212 goto bad; 213 } 214 format[i] = '}'; // Put the '}' back. 215 i++; 216 break; 217 } 218 i++; 219 } 220 ENSURE_THIS_MUCH_SPACE(VG_(strlen)(qual)); 221 j += VG_(sprintf)(&out[j], "%s", qual); 222 } else { 223 VG_(message)(Vg_UserMsg, 224 "%s: expected '{' after '%%q'", option_name); 225 goto bad; 226 } 227 } 228 else { 229 // Something else, abort. 230 VG_(message)(Vg_UserMsg, 231 "%s: expected 'p' or 'q' or '%%' after '%%'", option_name); 232 goto bad; 233 } 234 } 235 } 236 ENSURE_THIS_MUCH_SPACE(1); 237 out[j++] = 0; 238 239 return out; 240 241 bad: { 242 Char* opt = // 2: 1 for the '=', 1 for the NUL. 243 VG_(malloc)( "options.efn.3", 244 VG_(strlen)(option_name) + VG_(strlen)(format) + 2 ); 245 VG_(strcpy)(opt, option_name); 246 VG_(strcat)(opt, "="); 247 VG_(strcat)(opt, format); 248 VG_(err_bad_option)(opt); 249 } 250} 251 252 253 254/*--------------------------------------------------------------------*/ 255/*--- end m_options.c ---*/ 256/*--------------------------------------------------------------------*/ 257