2 /*--------------------------------------------------------------------*/
3 /*--- Command line options. m_options.c ---*/
4 /*--------------------------------------------------------------------*/
7 This file is part of Valgrind, a dynamic binary instrumentation
10 Copyright (C) 2000-2017 Nicholas Nethercote
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.
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.
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, see <http://www.gnu.org/licenses/>.
26 The GNU General Public License is contained in the file COPYING.
29 #include "pub_core_basics.h"
30 #include "pub_core_vki.h"
31 #include "pub_core_options.h"
32 #include "pub_core_libcassert.h"
33 #include "pub_core_libcbase.h"
34 #include "pub_core_libcfile.h"
35 #include "pub_core_libcprint.h"
36 #include "pub_core_libcproc.h"
37 #include "pub_core_mallocfree.h"
38 #include "pub_core_seqmatch.h" // VG_(string_match)
39 #include "pub_core_aspacemgr.h"
41 // See pub_{core,tool}_options.h for explanations of all these.
43 static Clo_Mode clo_mode
= cloE
;
44 static Bool clo_recognised
= False
;
46 void VG_(set_Clo_Mode
) (Clo_Mode mode
)
49 clo_recognised
= False
;
51 Clo_Mode
VG_(Clo_Mode
) (void)
56 void VG_(set_Clo_Recognised
) (void)
58 clo_recognised
= True
;
61 Bool
VG_(Clo_Recognised
) (void)
63 return clo_recognised
;
66 Bool
VG_(check_clom
) (Clo_Mode modes
, const HChar
* arg
, const HChar
* option
,
69 Bool res
= recognised
&& (modes
& VG_(Clo_Mode
)());
70 Bool dynamic
= cloD
== VG_(Clo_Mode
)();
73 VG_(set_Clo_Recognised
) ();
75 VG_(umsg
)("Cannot change %s option dynamically\n", option
);
76 else if (dynamic
&& VG_(clo_verbosity
) >= 1)
77 VG_(umsg
)("Handling new value %s for option %s\n", arg
, option
);
79 if (cloH
== VG_(Clo_Mode
)() && (cloD
& modes
))
80 VG_(list_clo
)(option
);
85 /* Define, and set defaults. */
87 const HChar
*VG_(clo_toolname
) = "memcheck"; // default to Memcheck
88 VexControl
VG_(clo_vex_control
);
89 VexRegisterUpdates
VG_(clo_px_file_backed
) = VexRegUpd_INVALID
;
91 Bool
VG_(clo_error_limit
) = True
;
92 Int
VG_(clo_error_exitcode
) = 0;
93 HChar
*VG_(clo_error_markers
)[2] = {NULL
, NULL
};
94 Bool
VG_(clo_exit_on_first_error
) = False
;
96 Int
VG_(clo_show_error_list
) = 0;
98 #if defined(VGPV_arm_linux_android) \
99 || defined(VGPV_x86_linux_android) \
100 || defined(VGPV_mips32_linux_android) \
101 || defined(VGPV_arm64_linux_android) \
102 || defined(VGP_nanomips_linux)
103 VgVgdb
VG_(clo_vgdb
) = Vg_VgdbNo
; // currently disabled on Android
105 VgVgdb
VG_(clo_vgdb
) = Vg_VgdbYes
;
107 Int
VG_(clo_vgdb_poll
) = 5000;
108 Int
VG_(clo_vgdb_error
) = 999999999;
109 Bool
VG_(clo_launched_with_multi
) = False
;
110 UInt
VG_(clo_vgdb_stop_at
) = 0;
111 const HChar
*VG_(clo_vgdb_prefix
) = NULL
;
112 const HChar
*VG_(arg_vgdb_prefix
) = NULL
;
113 Bool
VG_(clo_vgdb_shadow_registers
) = False
;
115 Int
VG_(clo_gen_suppressions
) = 0;
116 Int
VG_(clo_sanity_level
) = 1;
117 Int
VG_(clo_verbosity
) = 1;
118 Bool
VG_(clo_stats
) = False
;
119 Bool
VG_(clo_xml
) = False
;
120 const HChar
* VG_(clo_xml_user_comment
) = NULL
;
121 Bool
VG_(clo_demangle
) = True
;
122 const HChar
* VG_(clo_soname_synonyms
) = NULL
;
123 Bool
VG_(clo_trace_children
) = False
;
124 const HChar
* VG_(clo_trace_children_skip
) = NULL
;
125 const HChar
* VG_(clo_trace_children_skip_by_arg
) = NULL
;
126 Bool
VG_(clo_child_silent_after_fork
) = False
;
127 const HChar
*VG_(clo_log_fname_unexpanded
) = NULL
;
128 const HChar
*VG_(clo_xml_fname_unexpanded
) = NULL
;
129 Bool
VG_(clo_time_stamp
) = False
;
130 Int
VG_(clo_input_fd
) = 0; /* stdin */
131 Bool
VG_(clo_default_supp
) = True
;
132 XArray
*VG_(clo_suppressions
); // array of strings
133 XArray
*VG_(clo_fullpath_after
); // array of strings
134 const HChar
* VG_(clo_extra_debuginfo_path
) = NULL
;
135 const HChar
* VG_(clo_debuginfo_server
) = NULL
;
136 Bool
VG_(clo_allow_mismatched_debuginfo
) = False
;
137 UChar
VG_(clo_trace_flags
) = 0; // 00000000b
138 Bool
VG_(clo_profyle_sbs
) = False
;
139 UChar
VG_(clo_profyle_flags
) = 0; // 00000000b
140 ULong
VG_(clo_profyle_interval
) = 0;
141 Int
VG_(clo_trace_notbelow
) = -1; // unspecified
142 Int
VG_(clo_trace_notabove
) = -1; // unspecified
143 Bool
VG_(clo_trace_syscalls
) = False
;
144 Bool
VG_(clo_trace_signals
) = False
;
145 Bool
VG_(clo_trace_symtab
) = False
;
146 const HChar
* VG_(clo_trace_symtab_patt
) = "*";
147 Bool
VG_(clo_trace_cfi
) = False
;
148 Bool
VG_(clo_debug_dump_syms
) = False
;
149 Bool
VG_(clo_debug_dump_line
) = False
;
150 Bool
VG_(clo_debug_dump_frames
) = False
;
151 Bool
VG_(clo_trace_redir
) = False
;
153 VG_(clo_fair_sched
) = disable_fair_sched
;
154 /* VG_(clo_scheduling_quantum) defines the thread-scheduling timeslice,
155 in terms of the number of basic blocks we attempt to run each thread for.
156 Smaller values give finer interleaving but much increased scheduling
158 Word
VG_(clo_scheduling_quantum
) = 100000;
159 Bool
VG_(clo_trace_sched
) = False
;
160 Bool
VG_(clo_profile_heap
) = False
;
161 UInt
VG_(clo_progress_interval
) = 0; /* in seconds, 1 .. 3600,
163 Int
VG_(clo_core_redzone_size
) = CORE_REDZONE_DEFAULT_SZB
;
164 // A value != -1 overrides the tool-specific value
165 // VG_(needs_malloc_replacement).tool_client_redzone_szB
166 Int
VG_(clo_redzone_size
) = -1;
167 VgXTMemory
VG_(clo_xtree_memory
) = Vg_XTMemory_None
;
168 const HChar
* VG_(clo_xtree_memory_file
) = "xtmemory.kcg.%p";
169 Bool
VG_(clo_xtree_compress_strings
) = True
;
171 #if defined(VGO_linux)
172 Bool
VG_(clo_enable_debuginfod
) = True
;
174 Int
VG_(clo_dump_error
) = 0;
175 Int
VG_(clo_backtrace_size
) = 12;
176 Int
VG_(clo_merge_recursive_frames
) = 0; // default value: no merge
177 UInt
VG_(clo_sim_hints
) = 0;
178 Bool
VG_(clo_sym_offsets
) = False
;
179 Bool
VG_(clo_read_inline_info
) = False
; // Or should be put it to True by default ???
180 Bool
VG_(clo_read_var_info
) = False
;
181 XArray
*VG_(clo_req_tsyms
); // array of strings
182 Bool
VG_(clo_run_libc_freeres
) = True
;
183 Bool
VG_(clo_run_cxx_freeres
) = True
;
184 UInt
VG_(clo_track_fds
) = 0;
185 Bool
VG_(clo_show_below_main
)= False
;
186 Bool
VG_(clo_keep_debuginfo
) = False
;
187 Bool
VG_(clo_show_emwarns
) = False
;
188 Word
VG_(clo_max_stackframe
) = 2000000;
189 UInt
VG_(clo_max_threads
) = MAX_THREADS_DEFAULT
;
190 Word
VG_(clo_main_stacksize
) = 0; /* use client's rlimit.stack */
191 Word
VG_(clo_valgrind_stacksize
) = VG_DEFAULT_STACK_ACTIVE_SZB
;
192 Bool
VG_(clo_wait_for_gdb
) = False
;
193 UInt
VG_(clo_kernel_variant
) = 0;
194 Bool
VG_(clo_dsymutil
) = True
;
195 Bool
VG_(clo_sigill_diag
) = True
;
196 UInt
VG_(clo_unw_stack_scan_thresh
) = 0; /* disabled by default */
197 UInt
VG_(clo_unw_stack_scan_frames
) = 5;
199 // Set clo_smc_check so that it provides transparent self modifying
200 // code support for "correct" programs at the smallest achievable
201 // expense for this arch.
202 #if defined(VGA_x86) || defined(VGA_amd64) || defined(VGA_s390x)
203 VgSmc
VG_(clo_smc_check
) = Vg_SmcAllNonFile
;
204 #elif defined(VGA_ppc32) || defined(VGA_ppc64be) || defined(VGA_ppc64le) \
205 || defined(VGA_arm) || defined(VGA_arm64) \
206 || defined(VGA_mips32) || defined(VGA_mips64) || defined(VGA_nanomips)
207 VgSmc
VG_(clo_smc_check
) = Vg_SmcStack
;
209 # error "Unknown arch"
212 #if defined(VGO_darwin)
213 UInt
VG_(clo_resync_filter
) = 1; /* enabled, but quiet */
215 UInt
VG_(clo_resync_filter
) = 0; /* disabled */
219 /*====================================================================*/
220 /*=== File expansion ===*/
221 /*====================================================================*/
223 // Copies the string, prepending it with the startup working directory, and
224 // expanding %p and %q entries. Returns a new, malloc'd string.
225 HChar
* VG_(expand_file_name
)(const HChar
* option_name
, const HChar
* format
)
227 const HChar
*base_dir
;
228 Int len
, i
= 0, j
= 0;
230 const HChar
*message
= NULL
;
232 base_dir
= VG_(get_startup_wd
)();
234 if (VG_STREQ(format
, "")) {
236 message
= "No filename given\n";
240 // If 'format' starts with a '~', abort -- the user probably expected the
241 // shell to expand but it didn't (see bug 195268 for details). This means
242 // that we don't allow a legitimate filename beginning with '~' but that
243 // seems very unlikely.
244 if (format
[0] == '~') {
246 "Filename begins with '~'\n"
247 "You probably expected the shell to expand the '~', but it\n"
248 "didn't. The rules for '~'-expansion vary from shell to shell.\n"
249 "You might have more luck using $HOME instead.\n";
253 len
= VG_(strlen
)(format
) + 1;
254 out
= VG_(malloc
)( "options.efn.1", len
);
256 #define ENSURE_THIS_MUCH_SPACE(x) \
257 if (j + x >= len) { \
259 out = VG_(realloc)("options.efn.2(multiple)", out, len); \
263 if (format
[i
] != '%') {
264 ENSURE_THIS_MUCH_SPACE(1);
265 out
[j
++] = format
[i
++];
268 // We saw a '%'. What's next...
270 if ('%' == format
[i
]) {
271 // Replace '%%' with '%'.
272 ENSURE_THIS_MUCH_SPACE(1);
273 out
[j
++] = format
[i
++];
275 else if ('p' == format
[i
]) {
276 // Print the PID. Assume that it's not longer than 10 chars --
277 // reasonable since 'pid' is an Int (ie. 32 bits).
278 Int pid
= VG_(getpid
)();
279 ENSURE_THIS_MUCH_SPACE(10);
280 j
+= VG_(sprintf
)(&out
[j
], "%d", pid
);
283 else if ('n' == format
[i
]) {
287 Int pid
= VG_(getpid
)();
292 ENSURE_THIS_MUCH_SPACE(10);
293 j
+= VG_(sprintf
)(&out
[j
], "%d", seq_nr
);
296 else if ('q' == format
[i
]) {
298 if ('{' == format
[i
]) {
299 // Get the env var name, print its contents.
301 Int begin_qualname
= ++i
;
303 if (0 == format
[i
]) {
304 message
= "Missing '}' in %q specifier\n";
306 } else if ('}' == format
[i
]) {
307 Int qualname_len
= i
- begin_qualname
;
308 HChar qualname
[qualname_len
+ 1];
309 VG_(strncpy
)(qualname
, format
+ begin_qualname
,
311 qualname
[qualname_len
] = '\0';
312 qual
= VG_(getenv
)(qualname
);
314 // This memory will leak, But we don't care because
315 // VG_(fmsg_bad_option) will terminate the process.
316 HChar
*str
= VG_(malloc
)("options.efn.3",
319 "Environment variable '%s' is not set\n",
329 ENSURE_THIS_MUCH_SPACE(VG_(strlen
)(qual
));
330 j
+= VG_(sprintf
)(&out
[j
], "%s", qual
);
332 message
= "Expected '{' after '%q'\n";
337 // Something else, abort.
338 message
= "Expected 'p' or 'q' or '%' after '%'\n";
343 ENSURE_THIS_MUCH_SPACE(1);
346 // If 'out' is not an absolute path name, prefix it with the startup dir.
348 if (base_dir
== NULL
) {
349 message
= "Current working dir doesn't exist, use absolute path\n";
352 len
= VG_(strlen
)(base_dir
) + 1 + VG_(strlen
)(out
) + 1;
354 HChar
*absout
= VG_(malloc
)("options.efn.4", len
);
355 VG_(strcpy
)(absout
, base_dir
);
356 VG_(strcat
)(absout
, "/");
357 VG_(strcat
)(absout
, out
);
365 vg_assert(message
!= NULL
);
366 // 2: 1 for the '=', 1 for the NUL.
367 HChar opt
[VG_(strlen
)(option_name
) + VG_(strlen
)(format
) + 2];
368 VG_(sprintf
)(opt
, "%s=%s", option_name
, format
);
369 VG_(fmsg_bad_option
)(opt
, "%s", message
);
370 VG_(exit
)(1); // Cannot continue
376 void VG_(list_clo
)(const HChar
*qq_option
)
378 int len
= VG_(strlen
)(qq_option
);
379 if (col
+ len
+ 1 > 80) {
391 VG_(printf
)("%s", qq_option
);
394 void VG_(list_dynamic_options
) (void)
398 VG_(sprintf
)(dummy
, "%s", "<dummy option to trigger help>");
399 VG_(printf
)(" dynamically changeable options:\n");
400 VG_(process_dynamic_option
) (cloH
, dummy
);
407 /*====================================================================*/
408 /*=== --trace-children= support ===*/
409 /*====================================================================*/
411 static HChar
const* consume_commas ( HChar
const* c
) {
412 while (*c
&& *c
== ',') {
418 static HChar
const* consume_field ( HChar
const* c
) {
419 while (*c
&& *c
!= ',') {
425 /* Should we trace into this child executable (across execve, spawn etc) ?
426 This involves considering --trace-children=,
427 --trace-children-skip=, --trace-children-skip-by-arg=, and the name
428 of the executable. 'child_argv' must not include the name of the
429 executable itself; iow child_argv[0] must be the first arg, if any,
431 Bool
VG_(should_we_trace_this_child
) ( const HChar
* child_exe_name
,
432 const HChar
** child_argv
)
434 // child_exe_name is pulled out of the guest's space. We
435 // should be at least marginally cautious with it, lest it
436 // explode or burst into flames unexpectedly.
437 if (child_exe_name
== NULL
|| VG_(strlen
)(child_exe_name
) == 0)
438 return VG_(clo_trace_children
); // we know narfink
440 // If --trace-children=no, the answer is simply NO.
441 if (! VG_(clo_trace_children
))
444 // Otherwise, look for other reasons to say NO. First,
445 // see if the exe name matches any of the patterns specified
446 // by --trace-children-skip=.
447 if (VG_(clo_trace_children_skip
)) {
448 HChar
const* last
= VG_(clo_trace_children_skip
);
449 HChar
const* name
= child_exe_name
;
453 HChar
const* first
= consume_commas(last
);
454 last
= consume_field(first
);
457 vg_assert(last
> first
);
458 /* copy the candidate string into a temporary malloc'd block
459 so we can use VG_(string_match) on it. */
460 patt
= VG_(calloc
)("m_options.swttc.1", last
- first
+ 1, 1);
461 VG_(memcpy
)(patt
, first
, last
- first
);
462 vg_assert(patt
[last
-first
] == 0);
463 matches
= VG_(string_match
)(patt
, name
);
470 // Check if any of the args match any of the patterns specified
471 // by --trace-children-skip-by-arg=.
472 if (VG_(clo_trace_children_skip_by_arg
) && child_argv
!= NULL
) {
473 HChar
const* last
= VG_(clo_trace_children_skip_by_arg
);
478 HChar
const* first
= consume_commas(last
);
479 last
= consume_field(first
);
482 vg_assert(last
> first
);
483 /* copy the candidate string into a temporary malloc'd block
484 so we can use VG_(string_match) on it. */
485 patt
= VG_(calloc
)("m_options.swttc.1", last
- first
+ 1, 1);
486 VG_(memcpy
)(patt
, first
, last
- first
);
487 vg_assert(patt
[last
-first
] == 0);
488 for (i
= 0; child_argv
[i
]; i
++) {
489 matches
= VG_(string_match
)(patt
, child_argv
[i
]);
499 // --trace-children=yes, and this particular executable isn't
505 /*--------------------------------------------------------------------*/
507 /*--------------------------------------------------------------------*/