sewardj | 3282402 | 2005-05-17 13:45:04 +0000 | [diff] [blame] | 1 | |
| 2 | /*--------------------------------------------------------------------*/ |
njn | b1cc5d6 | 2010-07-06 04:05:23 +0000 | [diff] [blame] | 3 | /*--- Command line options. m_options.c ---*/ |
sewardj | 3282402 | 2005-05-17 13:45:04 +0000 | [diff] [blame] | 4 | /*--------------------------------------------------------------------*/ |
| 5 | |
| 6 | /* |
| 7 | This file is part of Valgrind, a dynamic binary instrumentation |
| 8 | framework. |
| 9 | |
Elliott Hughes | ed39800 | 2017-06-21 14:41:24 -0700 | [diff] [blame] | 10 | Copyright (C) 2000-2017 Nicholas Nethercote |
sewardj | 3282402 | 2005-05-17 13:45:04 +0000 | [diff] [blame] | 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 | |
njn | c7561b9 | 2005-06-19 01:24:32 +0000 | [diff] [blame] | 31 | #include "pub_core_basics.h" |
njn | 374a36d | 2007-11-23 01:41:32 +0000 | [diff] [blame] | 32 | #include "pub_core_vki.h" |
njn | a3506d3 | 2005-05-18 04:36:01 +0000 | [diff] [blame] | 33 | #include "pub_core_options.h" |
sewardj | 6893d65 | 2006-10-15 01:25:13 +0000 | [diff] [blame] | 34 | #include "pub_core_libcassert.h" |
njn | 374a36d | 2007-11-23 01:41:32 +0000 | [diff] [blame] | 35 | #include "pub_core_libcbase.h" |
| 36 | #include "pub_core_libcfile.h" |
sewardj | 6893d65 | 2006-10-15 01:25:13 +0000 | [diff] [blame] | 37 | #include "pub_core_libcprint.h" |
njn | 374a36d | 2007-11-23 01:41:32 +0000 | [diff] [blame] | 38 | #include "pub_core_libcproc.h" |
| 39 | #include "pub_core_mallocfree.h" |
sewardj | 0642127 | 2009-11-05 08:55:13 +0000 | [diff] [blame] | 40 | #include "pub_core_seqmatch.h" // VG_(string_match) |
philippe | d0720e4 | 2015-03-12 20:43:46 +0000 | [diff] [blame] | 41 | #include "pub_core_aspacemgr.h" |
sewardj | 3282402 | 2005-05-17 13:45:04 +0000 | [diff] [blame] | 42 | |
njn | a3506d3 | 2005-05-18 04:36:01 +0000 | [diff] [blame] | 43 | // See pub_{core,tool}_options.h for explanations of all these. |
| 44 | |
| 45 | |
| 46 | /* Define, and set defaults. */ |
sewardj | 8d47a61 | 2015-02-05 12:59:46 +0000 | [diff] [blame] | 47 | |
Elliott Hughes | ed39800 | 2017-06-21 14:41:24 -0700 | [diff] [blame] | 48 | const HChar *VG_(clo_toolname) = "memcheck"; // default to Memcheck |
njn | a3506d3 | 2005-05-18 04:36:01 +0000 | [diff] [blame] | 49 | VexControl VG_(clo_vex_control); |
sewardj | 8d47a61 | 2015-02-05 12:59:46 +0000 | [diff] [blame] | 50 | VexRegisterUpdates VG_(clo_px_file_backed) = VexRegUpd_INVALID; |
| 51 | |
njn | a3506d3 | 2005-05-18 04:36:01 +0000 | [diff] [blame] | 52 | Bool VG_(clo_error_limit) = True; |
sewardj | b977908 | 2006-05-12 23:50:15 +0000 | [diff] [blame] | 53 | Int VG_(clo_error_exitcode) = 0; |
philippe | 7b3d356 | 2014-11-12 19:43:29 +0000 | [diff] [blame] | 54 | HChar *VG_(clo_error_markers)[2] = {NULL, NULL}; |
sewardj | 0ba37c9 | 2011-07-12 11:46:24 +0000 | [diff] [blame] | 55 | |
sewardj | 26ed419 | 2014-11-04 17:44:21 +0000 | [diff] [blame] | 56 | #if defined(VGPV_arm_linux_android) \ |
| 57 | || defined(VGPV_x86_linux_android) \ |
| 58 | || defined(VGPV_mips32_linux_android) \ |
| 59 | || defined(VGPV_arm64_linux_android) |
sewardj | deddfdf | 2011-10-26 15:07:56 +0000 | [diff] [blame] | 60 | VgVgdb VG_(clo_vgdb) = Vg_VgdbNo; // currently disabled on Android |
| 61 | #else |
sewardj | 0ba37c9 | 2011-07-12 11:46:24 +0000 | [diff] [blame] | 62 | VgVgdb VG_(clo_vgdb) = Vg_VgdbYes; |
sewardj | deddfdf | 2011-10-26 15:07:56 +0000 | [diff] [blame] | 63 | #endif |
sewardj | 3b29048 | 2011-05-06 21:02:55 +0000 | [diff] [blame] | 64 | Int VG_(clo_vgdb_poll) = 5000; |
| 65 | Int VG_(clo_vgdb_error) = 999999999; |
philippe | 180a750 | 2014-04-20 13:41:10 +0000 | [diff] [blame] | 66 | UInt VG_(clo_vgdb_stop_at) = 0; |
philippe | cffe2a5 | 2014-01-11 13:56:48 +0000 | [diff] [blame] | 67 | const HChar *VG_(clo_vgdb_prefix) = NULL; |
| 68 | const HChar *VG_(arg_vgdb_prefix) = NULL; |
sewardj | 3b29048 | 2011-05-06 21:02:55 +0000 | [diff] [blame] | 69 | Bool VG_(clo_vgdb_shadow_registers) = False; |
sewardj | 0ba37c9 | 2011-07-12 11:46:24 +0000 | [diff] [blame] | 70 | |
njn | a3506d3 | 2005-05-18 04:36:01 +0000 | [diff] [blame] | 71 | Int VG_(clo_gen_suppressions) = 0; |
| 72 | Int VG_(clo_sanity_level) = 1; |
| 73 | Int VG_(clo_verbosity) = 1; |
sewardj | 2d9e874 | 2009-08-07 15:46:56 +0000 | [diff] [blame] | 74 | Bool VG_(clo_stats) = False; |
sewardj | 71bc3cb | 2005-05-19 00:25:45 +0000 | [diff] [blame] | 75 | Bool VG_(clo_xml) = False; |
florian | 19f91bb | 2012-11-10 22:29:54 +0000 | [diff] [blame] | 76 | const HChar* VG_(clo_xml_user_comment) = NULL; |
njn | a3506d3 | 2005-05-18 04:36:01 +0000 | [diff] [blame] | 77 | Bool VG_(clo_demangle) = True; |
florian | 19f91bb | 2012-11-10 22:29:54 +0000 | [diff] [blame] | 78 | const HChar* VG_(clo_soname_synonyms) = NULL; |
njn | a3506d3 | 2005-05-18 04:36:01 +0000 | [diff] [blame] | 79 | Bool VG_(clo_trace_children) = False; |
florian | 19f91bb | 2012-11-10 22:29:54 +0000 | [diff] [blame] | 80 | const HChar* VG_(clo_trace_children_skip) = NULL; |
| 81 | const HChar* VG_(clo_trace_children_skip_by_arg) = NULL; |
sewardj | 6e31f80 | 2007-11-17 22:29:25 +0000 | [diff] [blame] | 82 | Bool VG_(clo_child_silent_after_fork) = False; |
Elliott Hughes | ed39800 | 2017-06-21 14:41:24 -0700 | [diff] [blame] | 83 | const HChar *VG_(clo_log_fname_unexpanded) = NULL; |
| 84 | const HChar *VG_(clo_xml_fname_unexpanded) = NULL; |
njn | a3506d3 | 2005-05-18 04:36:01 +0000 | [diff] [blame] | 85 | Bool VG_(clo_time_stamp) = False; |
| 86 | Int VG_(clo_input_fd) = 0; /* stdin */ |
bart | 2c68e3e | 2014-06-22 10:11:59 +0000 | [diff] [blame] | 87 | Bool VG_(clo_default_supp) = True; |
florian | 7931627 | 2014-10-07 18:36:28 +0000 | [diff] [blame] | 88 | XArray *VG_(clo_suppressions); // array of strings |
| 89 | XArray *VG_(clo_fullpath_after); // array of strings |
sewardj | 71826f7 | 2012-12-06 18:23:20 +0000 | [diff] [blame] | 90 | const HChar* VG_(clo_extra_debuginfo_path) = NULL; |
sewardj | 5d616df | 2013-07-02 08:07:15 +0000 | [diff] [blame] | 91 | const HChar* VG_(clo_debuginfo_server) = NULL; |
| 92 | Bool VG_(clo_allow_mismatched_debuginfo) = False; |
njn | a3506d3 | 2005-05-18 04:36:01 +0000 | [diff] [blame] | 93 | UChar VG_(clo_trace_flags) = 0; // 00000000b |
sewardj | 17c5e2e | 2012-12-28 09:12:14 +0000 | [diff] [blame] | 94 | Bool VG_(clo_profyle_sbs) = False; |
| 95 | UChar VG_(clo_profyle_flags) = 0; // 00000000b |
| 96 | ULong VG_(clo_profyle_interval) = 0; |
florian | 29e022d | 2012-07-02 21:13:34 +0000 | [diff] [blame] | 97 | Int VG_(clo_trace_notbelow) = -1; // unspecified |
| 98 | Int VG_(clo_trace_notabove) = -1; // unspecified |
njn | a3506d3 | 2005-05-18 04:36:01 +0000 | [diff] [blame] | 99 | Bool VG_(clo_trace_syscalls) = False; |
| 100 | Bool VG_(clo_trace_signals) = False; |
| 101 | Bool VG_(clo_trace_symtab) = False; |
florian | 19f91bb | 2012-11-10 22:29:54 +0000 | [diff] [blame] | 102 | const HChar* VG_(clo_trace_symtab_patt) = "*"; |
njn | a3506d3 | 2005-05-18 04:36:01 +0000 | [diff] [blame] | 103 | Bool VG_(clo_trace_cfi) = False; |
sewardj | f767d96 | 2007-02-12 17:47:14 +0000 | [diff] [blame] | 104 | Bool VG_(clo_debug_dump_syms) = False; |
| 105 | Bool VG_(clo_debug_dump_line) = False; |
| 106 | Bool VG_(clo_debug_dump_frames) = False; |
njn | a3506d3 | 2005-05-18 04:36:01 +0000 | [diff] [blame] | 107 | Bool VG_(clo_trace_redir) = False; |
bart | 78bfc71 | 2011-12-08 16:14:59 +0000 | [diff] [blame] | 108 | enum FairSchedType |
| 109 | VG_(clo_fair_sched) = disable_fair_sched; |
njn | a3506d3 | 2005-05-18 04:36:01 +0000 | [diff] [blame] | 110 | Bool VG_(clo_trace_sched) = False; |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 111 | Bool VG_(clo_profile_heap) = False; |
philippe | d99c26a | 2012-07-31 22:17:28 +0000 | [diff] [blame] | 112 | Int VG_(clo_core_redzone_size) = CORE_REDZONE_DEFAULT_SZB; |
| 113 | // A value != -1 overrides the tool-specific value |
| 114 | // VG_(needs_malloc_replacement).tool_client_redzone_szB |
| 115 | Int VG_(clo_redzone_size) = -1; |
Elliott Hughes | ed39800 | 2017-06-21 14:41:24 -0700 | [diff] [blame] | 116 | VgXTMemory VG_(clo_xtree_memory) = Vg_XTMemory_None; |
| 117 | const HChar* VG_(clo_xtree_memory_file) = "xtmemory.kcg.%p"; |
| 118 | Bool VG_(clo_xtree_compress_strings) = True; |
| 119 | |
njn | a3506d3 | 2005-05-18 04:36:01 +0000 | [diff] [blame] | 120 | Int VG_(clo_dump_error) = 0; |
| 121 | Int VG_(clo_backtrace_size) = 12; |
philippe | 4620765 | 2013-01-20 17:11:58 +0000 | [diff] [blame] | 122 | Int VG_(clo_merge_recursive_frames) = 0; // default value: no merge |
philippe | ec905f7 | 2014-08-17 20:03:51 +0000 | [diff] [blame] | 123 | UInt VG_(clo_sim_hints) = 0; |
sewardj | 41ded2c | 2006-10-17 01:34:57 +0000 | [diff] [blame] | 124 | Bool VG_(clo_sym_offsets) = False; |
philippe | a0a7393 | 2014-06-15 15:42:20 +0000 | [diff] [blame] | 125 | Bool VG_(clo_read_inline_info) = False; // Or should be put it to True by default ??? |
sewardj | b8b79ad | 2008-03-03 01:35:41 +0000 | [diff] [blame] | 126 | Bool VG_(clo_read_var_info) = False; |
florian | 7931627 | 2014-10-07 18:36:28 +0000 | [diff] [blame] | 127 | XArray *VG_(clo_req_tsyms); // array of strings |
njn | a3506d3 | 2005-05-18 04:36:01 +0000 | [diff] [blame] | 128 | Bool VG_(clo_run_libc_freeres) = True; |
Elliott Hughes | a0664b9 | 2017-04-18 17:46:52 -0700 | [diff] [blame] | 129 | Bool VG_(clo_run_cxx_freeres) = True; |
njn | a3506d3 | 2005-05-18 04:36:01 +0000 | [diff] [blame] | 130 | Bool VG_(clo_track_fds) = False; |
| 131 | Bool VG_(clo_show_below_main)= False; |
njn | a3506d3 | 2005-05-18 04:36:01 +0000 | [diff] [blame] | 132 | Bool VG_(clo_show_emwarns) = False; |
sewardj | 91b470c | 2007-08-28 17:03:01 +0000 | [diff] [blame] | 133 | Word VG_(clo_max_stackframe) = 2000000; |
florian | 1e802b6 | 2015-02-13 19:08:26 +0000 | [diff] [blame] | 134 | UInt VG_(clo_max_threads) = MAX_THREADS_DEFAULT; |
sewardj | 95d86c0 | 2007-12-18 01:49:23 +0000 | [diff] [blame] | 135 | Word VG_(clo_main_stacksize) = 0; /* use client's rlimit.stack */ |
philippe | d0720e4 | 2015-03-12 20:43:46 +0000 | [diff] [blame] | 136 | Word VG_(clo_valgrind_stacksize) = VG_DEFAULT_STACK_ACTIVE_SZB; |
njn | a3506d3 | 2005-05-18 04:36:01 +0000 | [diff] [blame] | 137 | Bool VG_(clo_wait_for_gdb) = False; |
philippe | ec905f7 | 2014-08-17 20:03:51 +0000 | [diff] [blame] | 138 | UInt VG_(clo_kernel_variant) = 0; |
sewardj | 29dd9e6 | 2015-08-31 14:37:25 +0000 | [diff] [blame] | 139 | Bool VG_(clo_dsymutil) = True; |
sewardj | c30cd9b | 2012-12-06 18:08:54 +0000 | [diff] [blame] | 140 | Bool VG_(clo_sigill_diag) = True; |
sewardj | 49984ea | 2013-10-18 13:21:26 +0000 | [diff] [blame] | 141 | UInt VG_(clo_unw_stack_scan_thresh) = 0; /* disabled by default */ |
| 142 | UInt VG_(clo_unw_stack_scan_frames) = 5; |
| 143 | |
sewardj | 18d27dd | 2015-08-31 14:24:14 +0000 | [diff] [blame] | 144 | // Set clo_smc_check so that it provides transparent self modifying |
| 145 | // code support for "correct" programs at the smallest achievable |
| 146 | // expense for this arch. |
| 147 | #if defined(VGA_x86) || defined(VGA_amd64) || defined(VGA_s390x) |
| 148 | VgSmc VG_(clo_smc_check) = Vg_SmcAllNonFile; |
| 149 | #elif defined(VGA_ppc32) || defined(VGA_ppc64be) || defined(VGA_ppc64le) \ |
| 150 | || defined(VGA_arm) || defined(VGA_arm64) \ |
Elliott Hughes | ed39800 | 2017-06-21 14:41:24 -0700 | [diff] [blame] | 151 | || defined(VGA_mips32) || defined(VGA_mips64) |
sewardj | 18d27dd | 2015-08-31 14:24:14 +0000 | [diff] [blame] | 152 | VgSmc VG_(clo_smc_check) = Vg_SmcStack; |
| 153 | #else |
| 154 | # error "Unknown arch" |
| 155 | #endif |
| 156 | |
sewardj | 67f7c03 | 2014-10-23 19:48:01 +0000 | [diff] [blame] | 157 | #if defined(VGO_darwin) |
| 158 | UInt VG_(clo_resync_filter) = 1; /* enabled, but quiet */ |
| 159 | #else |
| 160 | UInt VG_(clo_resync_filter) = 0; /* disabled */ |
| 161 | #endif |
| 162 | |
sewardj | 3282402 | 2005-05-17 13:45:04 +0000 | [diff] [blame] | 163 | |
sewardj | 6893d65 | 2006-10-15 01:25:13 +0000 | [diff] [blame] | 164 | /*====================================================================*/ |
njn | b1cc5d6 | 2010-07-06 04:05:23 +0000 | [diff] [blame] | 165 | /*=== File expansion ===*/ |
sewardj | 6893d65 | 2006-10-15 01:25:13 +0000 | [diff] [blame] | 166 | /*====================================================================*/ |
| 167 | |
njn | 374a36d | 2007-11-23 01:41:32 +0000 | [diff] [blame] | 168 | // Copies the string, prepending it with the startup working directory, and |
| 169 | // expanding %p and %q entries. Returns a new, malloc'd string. |
florian | 19f91bb | 2012-11-10 22:29:54 +0000 | [diff] [blame] | 170 | HChar* VG_(expand_file_name)(const HChar* option_name, const HChar* format) |
njn | 374a36d | 2007-11-23 01:41:32 +0000 | [diff] [blame] | 171 | { |
florian | 29d82f6 | 2014-09-27 17:42:07 +0000 | [diff] [blame] | 172 | const HChar *base_dir; |
njn | 374a36d | 2007-11-23 01:41:32 +0000 | [diff] [blame] | 173 | Int len, i = 0, j = 0; |
florian | 19f91bb | 2012-11-10 22:29:54 +0000 | [diff] [blame] | 174 | HChar* out; |
florian | f34ee4e | 2014-11-29 13:31:18 +0000 | [diff] [blame] | 175 | const HChar *message = NULL; |
njn | 374a36d | 2007-11-23 01:41:32 +0000 | [diff] [blame] | 176 | |
florian | 29d82f6 | 2014-09-27 17:42:07 +0000 | [diff] [blame] | 177 | base_dir = VG_(get_startup_wd)(); |
njn | 374a36d | 2007-11-23 01:41:32 +0000 | [diff] [blame] | 178 | |
| 179 | if (VG_STREQ(format, "")) { |
| 180 | // Empty name, bad. |
florian | f34ee4e | 2014-11-29 13:31:18 +0000 | [diff] [blame] | 181 | message = "No filename given\n"; |
njn | 5542d8f | 2009-06-09 00:50:45 +0000 | [diff] [blame] | 182 | goto bad; |
| 183 | } |
| 184 | |
| 185 | // If 'format' starts with a '~', abort -- the user probably expected the |
| 186 | // shell to expand but it didn't (see bug 195268 for details). This means |
| 187 | // that we don't allow a legitimate filename beginning with '~' but that |
| 188 | // seems very unlikely. |
| 189 | if (format[0] == '~') { |
florian | f34ee4e | 2014-11-29 13:31:18 +0000 | [diff] [blame] | 190 | message = |
| 191 | "Filename begins with '~'\n" |
njn | b1cc5d6 | 2010-07-06 04:05:23 +0000 | [diff] [blame] | 192 | "You probably expected the shell to expand the '~', but it\n" |
| 193 | "didn't. The rules for '~'-expansion vary from shell to shell.\n" |
florian | f34ee4e | 2014-11-29 13:31:18 +0000 | [diff] [blame] | 194 | "You might have more luck using $HOME instead.\n"; |
njn | 374a36d | 2007-11-23 01:41:32 +0000 | [diff] [blame] | 195 | goto bad; |
| 196 | } |
| 197 | |
florian | 3e17274 | 2014-02-19 11:16:00 +0000 | [diff] [blame] | 198 | len = VG_(strlen)(format) + 1; |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 199 | out = VG_(malloc)( "options.efn.1", len ); |
njn | 374a36d | 2007-11-23 01:41:32 +0000 | [diff] [blame] | 200 | |
| 201 | #define ENSURE_THIS_MUCH_SPACE(x) \ |
| 202 | if (j + x >= len) { \ |
| 203 | len += (10 + x); \ |
sewardj | 9c606bd | 2008-09-18 18:12:50 +0000 | [diff] [blame] | 204 | out = VG_(realloc)("options.efn.2(multiple)", out, len); \ |
njn | 374a36d | 2007-11-23 01:41:32 +0000 | [diff] [blame] | 205 | } |
| 206 | |
njn | 374a36d | 2007-11-23 01:41:32 +0000 | [diff] [blame] | 207 | while (format[i]) { |
| 208 | if (format[i] != '%') { |
| 209 | ENSURE_THIS_MUCH_SPACE(1); |
| 210 | out[j++] = format[i++]; |
| 211 | |
| 212 | } else { |
| 213 | // We saw a '%'. What's next... |
| 214 | i++; |
| 215 | if ('%' == format[i]) { |
| 216 | // Replace '%%' with '%'. |
| 217 | ENSURE_THIS_MUCH_SPACE(1); |
| 218 | out[j++] = format[i++]; |
| 219 | } |
| 220 | else if ('p' == format[i]) { |
| 221 | // Print the PID. Assume that it's not longer than 10 chars -- |
| 222 | // reasonable since 'pid' is an Int (ie. 32 bits). |
| 223 | Int pid = VG_(getpid)(); |
| 224 | ENSURE_THIS_MUCH_SPACE(10); |
| 225 | j += VG_(sprintf)(&out[j], "%d", pid); |
| 226 | i++; |
| 227 | } |
Elliott Hughes | ed39800 | 2017-06-21 14:41:24 -0700 | [diff] [blame] | 228 | else if ('n' == format[i]) { |
| 229 | // Print a seq nr. |
| 230 | static Int last_pid; |
| 231 | static Int seq_nr; |
| 232 | Int pid = VG_(getpid)(); |
| 233 | if (last_pid != pid) |
| 234 | seq_nr = 0; |
| 235 | last_pid = pid; |
| 236 | seq_nr++; |
| 237 | ENSURE_THIS_MUCH_SPACE(10); |
| 238 | j += VG_(sprintf)(&out[j], "%d", seq_nr); |
| 239 | i++; |
| 240 | } |
njn | 2dd08f5 | 2007-11-23 22:37:35 +0000 | [diff] [blame] | 241 | else if ('q' == format[i]) { |
| 242 | i++; |
| 243 | if ('{' == format[i]) { |
| 244 | // Get the env var name, print its contents. |
florian | 57d534d | 2014-09-06 20:40:28 +0000 | [diff] [blame] | 245 | HChar *qual; |
| 246 | Int begin_qualname = ++i; |
njn | 2dd08f5 | 2007-11-23 22:37:35 +0000 | [diff] [blame] | 247 | while (True) { |
| 248 | if (0 == format[i]) { |
florian | f34ee4e | 2014-11-29 13:31:18 +0000 | [diff] [blame] | 249 | message = "Missing '}' in %q specifier\n"; |
njn | 2dd08f5 | 2007-11-23 22:37:35 +0000 | [diff] [blame] | 250 | goto bad; |
| 251 | } else if ('}' == format[i]) { |
florian | 57d534d | 2014-09-06 20:40:28 +0000 | [diff] [blame] | 252 | Int qualname_len = i - begin_qualname; |
| 253 | HChar qualname[qualname_len + 1]; |
| 254 | VG_(strncpy)(qualname, format + begin_qualname, |
| 255 | qualname_len); |
| 256 | qualname[qualname_len] = '\0'; |
njn | 2dd08f5 | 2007-11-23 22:37:35 +0000 | [diff] [blame] | 257 | qual = VG_(getenv)(qualname); |
| 258 | if (NULL == qual) { |
florian | f34ee4e | 2014-11-29 13:31:18 +0000 | [diff] [blame] | 259 | // This memory will leak, But we don't care because |
| 260 | // VG_(fmsg_bad_option) will terminate the process. |
| 261 | HChar *str = VG_(malloc)("options.efn.3", |
| 262 | 100 + qualname_len); |
| 263 | VG_(sprintf)(str, |
| 264 | "Environment variable '%s' is not set\n", |
| 265 | qualname); |
| 266 | message = str; |
njn | 2dd08f5 | 2007-11-23 22:37:35 +0000 | [diff] [blame] | 267 | goto bad; |
| 268 | } |
njn | 2dd08f5 | 2007-11-23 22:37:35 +0000 | [diff] [blame] | 269 | i++; |
| 270 | break; |
| 271 | } |
| 272 | i++; |
| 273 | } |
| 274 | ENSURE_THIS_MUCH_SPACE(VG_(strlen)(qual)); |
| 275 | j += VG_(sprintf)(&out[j], "%s", qual); |
| 276 | } else { |
florian | f34ee4e | 2014-11-29 13:31:18 +0000 | [diff] [blame] | 277 | message = "Expected '{' after '%q'\n"; |
njn | 2dd08f5 | 2007-11-23 22:37:35 +0000 | [diff] [blame] | 278 | goto bad; |
njn | 374a36d | 2007-11-23 01:41:32 +0000 | [diff] [blame] | 279 | } |
njn | 374a36d | 2007-11-23 01:41:32 +0000 | [diff] [blame] | 280 | } |
| 281 | else { |
| 282 | // Something else, abort. |
florian | f34ee4e | 2014-11-29 13:31:18 +0000 | [diff] [blame] | 283 | message = "Expected 'p' or 'q' or '%' after '%'\n"; |
njn | 374a36d | 2007-11-23 01:41:32 +0000 | [diff] [blame] | 284 | goto bad; |
| 285 | } |
| 286 | } |
| 287 | } |
| 288 | ENSURE_THIS_MUCH_SPACE(1); |
| 289 | out[j++] = 0; |
| 290 | |
florian | 3e17274 | 2014-02-19 11:16:00 +0000 | [diff] [blame] | 291 | // If 'out' is not an absolute path name, prefix it with the startup dir. |
| 292 | if (out[0] != '/') { |
Elliott Hughes | a0664b9 | 2017-04-18 17:46:52 -0700 | [diff] [blame] | 293 | if (base_dir == NULL) { |
| 294 | message = "Current working dir doesn't exist, use absolute path\n"; |
| 295 | goto bad; |
| 296 | } |
florian | 3e17274 | 2014-02-19 11:16:00 +0000 | [diff] [blame] | 297 | len = VG_(strlen)(base_dir) + 1 + VG_(strlen)(out) + 1; |
| 298 | |
| 299 | HChar *absout = VG_(malloc)("options.efn.4", len); |
| 300 | VG_(strcpy)(absout, base_dir); |
| 301 | VG_(strcat)(absout, "/"); |
| 302 | VG_(strcat)(absout, out); |
| 303 | VG_(free)(out); |
| 304 | out = absout; |
| 305 | } |
| 306 | |
njn | 374a36d | 2007-11-23 01:41:32 +0000 | [diff] [blame] | 307 | return out; |
| 308 | |
| 309 | bad: { |
florian | f34ee4e | 2014-11-29 13:31:18 +0000 | [diff] [blame] | 310 | vg_assert(message != NULL); |
| 311 | // 2: 1 for the '=', 1 for the NUL. |
| 312 | HChar opt[VG_(strlen)(option_name) + VG_(strlen)(format) + 2]; |
| 313 | VG_(sprintf)(opt, "%s=%s", option_name, format); |
| 314 | VG_(fmsg_bad_option)(opt, "%s", message); |
njn | 374a36d | 2007-11-23 01:41:32 +0000 | [diff] [blame] | 315 | } |
| 316 | } |
| 317 | |
sewardj | 0642127 | 2009-11-05 08:55:13 +0000 | [diff] [blame] | 318 | /*====================================================================*/ |
| 319 | /*=== --trace-children= support ===*/ |
| 320 | /*====================================================================*/ |
| 321 | |
| 322 | static HChar const* consume_commas ( HChar const* c ) { |
| 323 | while (*c && *c == ',') { |
| 324 | ++c; |
| 325 | } |
| 326 | return c; |
| 327 | } |
| 328 | |
| 329 | static HChar const* consume_field ( HChar const* c ) { |
| 330 | while (*c && *c != ',') { |
| 331 | ++c; |
| 332 | } |
| 333 | return c; |
| 334 | } |
| 335 | |
sewardj | 8eb8bab | 2015-07-21 14:44:28 +0000 | [diff] [blame] | 336 | /* Should we trace into this child executable (across execve, spawn etc) ? |
sewardj | 9ab64a4 | 2010-12-06 11:40:04 +0000 | [diff] [blame] | 337 | This involves considering --trace-children=, |
| 338 | --trace-children-skip=, --trace-children-skip-by-arg=, and the name |
| 339 | of the executable. 'child_argv' must not include the name of the |
| 340 | executable itself; iow child_argv[0] must be the first arg, if any, |
| 341 | for the child. */ |
florian | 518850b | 2014-10-22 22:25:30 +0000 | [diff] [blame] | 342 | Bool VG_(should_we_trace_this_child) ( const HChar* child_exe_name, |
| 343 | const HChar** child_argv ) |
sewardj | 0642127 | 2009-11-05 08:55:13 +0000 | [diff] [blame] | 344 | { |
| 345 | // child_exe_name is pulled out of the guest's space. We |
| 346 | // should be at least marginally cautious with it, lest it |
| 347 | // explode or burst into flames unexpectedly. |
| 348 | if (child_exe_name == NULL || VG_(strlen)(child_exe_name) == 0) |
| 349 | return VG_(clo_trace_children); // we know narfink |
| 350 | |
sewardj | 0642127 | 2009-11-05 08:55:13 +0000 | [diff] [blame] | 351 | // If --trace-children=no, the answer is simply NO. |
| 352 | if (! VG_(clo_trace_children)) |
| 353 | return False; |
| 354 | |
sewardj | 9ab64a4 | 2010-12-06 11:40:04 +0000 | [diff] [blame] | 355 | // Otherwise, look for other reasons to say NO. First, |
| 356 | // see if the exe name matches any of the patterns specified |
| 357 | // by --trace-children-skip=. |
sewardj | 0642127 | 2009-11-05 08:55:13 +0000 | [diff] [blame] | 358 | if (VG_(clo_trace_children_skip)) { |
| 359 | HChar const* last = VG_(clo_trace_children_skip); |
florian | 19f91bb | 2012-11-10 22:29:54 +0000 | [diff] [blame] | 360 | HChar const* name = child_exe_name; |
sewardj | 0642127 | 2009-11-05 08:55:13 +0000 | [diff] [blame] | 361 | while (*last) { |
| 362 | Bool matches; |
| 363 | HChar* patt; |
| 364 | HChar const* first = consume_commas(last); |
| 365 | last = consume_field(first); |
| 366 | if (first == last) |
| 367 | break; |
| 368 | vg_assert(last > first); |
| 369 | /* copy the candidate string into a temporary malloc'd block |
| 370 | so we can use VG_(string_match) on it. */ |
| 371 | patt = VG_(calloc)("m_options.swttc.1", last - first + 1, 1); |
| 372 | VG_(memcpy)(patt, first, last - first); |
| 373 | vg_assert(patt[last-first] == 0); |
| 374 | matches = VG_(string_match)(patt, name); |
| 375 | VG_(free)(patt); |
| 376 | if (matches) |
| 377 | return False; |
| 378 | } |
| 379 | } |
sewardj | 9ab64a4 | 2010-12-06 11:40:04 +0000 | [diff] [blame] | 380 | |
| 381 | // Check if any of the args match any of the patterns specified |
| 382 | // by --trace-children-skip-by-arg=. |
| 383 | if (VG_(clo_trace_children_skip_by_arg) && child_argv != NULL) { |
| 384 | HChar const* last = VG_(clo_trace_children_skip_by_arg); |
| 385 | while (*last) { |
| 386 | Int i; |
| 387 | Bool matches; |
| 388 | HChar* patt; |
| 389 | HChar const* first = consume_commas(last); |
| 390 | last = consume_field(first); |
| 391 | if (first == last) |
| 392 | break; |
| 393 | vg_assert(last > first); |
| 394 | /* copy the candidate string into a temporary malloc'd block |
| 395 | so we can use VG_(string_match) on it. */ |
| 396 | patt = VG_(calloc)("m_options.swttc.1", last - first + 1, 1); |
| 397 | VG_(memcpy)(patt, first, last - first); |
| 398 | vg_assert(patt[last-first] == 0); |
| 399 | for (i = 0; child_argv[i]; i++) { |
| 400 | matches = VG_(string_match)(patt, child_argv[i]); |
| 401 | if (matches) { |
| 402 | VG_(free)(patt); |
| 403 | return False; |
| 404 | } |
| 405 | } |
| 406 | VG_(free)(patt); |
| 407 | } |
| 408 | } |
| 409 | |
sewardj | 0642127 | 2009-11-05 08:55:13 +0000 | [diff] [blame] | 410 | // --trace-children=yes, and this particular executable isn't |
| 411 | // excluded |
| 412 | return True; |
| 413 | } |
njn | 374a36d | 2007-11-23 01:41:32 +0000 | [diff] [blame] | 414 | |
sewardj | 6893d65 | 2006-10-15 01:25:13 +0000 | [diff] [blame] | 415 | |
sewardj | 3282402 | 2005-05-17 13:45:04 +0000 | [diff] [blame] | 416 | /*--------------------------------------------------------------------*/ |
njn | b1cc5d6 | 2010-07-06 04:05:23 +0000 | [diff] [blame] | 417 | /*--- end ---*/ |
sewardj | 3282402 | 2005-05-17 13:45:04 +0000 | [diff] [blame] | 418 | /*--------------------------------------------------------------------*/ |