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-2011 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. */
46 VexControl VG_(clo_vex_control);
47 Bool VG_(clo_error_limit) = True;
48 Int VG_(clo_error_exitcode) = 0;
49
50 VgVgdb VG_(clo_vgdb) = Vg_VgdbYes;
51 Int VG_(clo_vgdb_poll) = 5000;
52 Int VG_(clo_vgdb_error) = 999999999;
53 HChar* VG_(clo_vgdb_prefix) = NULL;
54 Bool VG_(clo_vgdb_shadow_registers) = False;
55
56 Bool VG_(clo_db_attach) = False;
57 Char* VG_(clo_db_command) = GDB_PATH " -nw %f %p";
58 Int VG_(clo_gen_suppressions) = 0;
59 Int VG_(clo_sanity_level) = 1;
60 Int VG_(clo_verbosity) = 1;
61 Bool VG_(clo_stats) = False;
62 Bool VG_(clo_xml) = False;
63 HChar* VG_(clo_xml_user_comment) = NULL;
64 Bool VG_(clo_demangle) = True;
65 Bool VG_(clo_trace_children) = False;
66 HChar* VG_(clo_trace_children_skip) = NULL;
67 HChar* VG_(clo_trace_children_skip_by_arg) = NULL;
68 Bool VG_(clo_child_silent_after_fork) = False;
69 Char* VG_(clo_log_fname_expanded) = NULL;
70 Char* VG_(clo_xml_fname_expanded) = NULL;
71 Bool VG_(clo_time_stamp) = False;
72 Int VG_(clo_input_fd) = 0; /* stdin */
73 Int VG_(clo_n_suppressions) = 0;
74 Char* VG_(clo_suppressions)[VG_CLO_MAX_SFILES];
75 Int VG_(clo_n_fullpath_after) = 0;
76 Char* VG_(clo_fullpath_after)[VG_CLO_MAX_FULLPATH_AFTER];
77 UChar VG_(clo_trace_flags) = 0; // 00000000b
78 UChar VG_(clo_profile_flags) = 0; // 00000000b
79 Int VG_(clo_trace_notbelow) = 999999999;
80 Bool VG_(clo_trace_syscalls) = False;
81 Bool VG_(clo_trace_signals) = False;
82 Bool VG_(clo_trace_symtab) = False;
83 HChar* VG_(clo_trace_symtab_patt) = "*";
84 Bool VG_(clo_trace_cfi) = False;
85 Bool VG_(clo_debug_dump_syms) = False;
86 Bool VG_(clo_debug_dump_line) = False;
87 Bool VG_(clo_debug_dump_frames) = False;
88 Bool VG_(clo_trace_redir) = False;
89 Bool VG_(clo_trace_sched) = False;
90 Bool VG_(clo_profile_heap) = False;
91 Int VG_(clo_dump_error) = 0;
92 Int VG_(clo_backtrace_size) = 12;
93 Char* VG_(clo_sim_hints) = NULL;
94 Bool VG_(clo_sym_offsets) = False;
95 Bool VG_(clo_read_var_info) = False;
96 Int VG_(clo_n_req_tsyms) = 0;
97 HChar* VG_(clo_req_tsyms)[VG_CLO_MAX_REQ_TSYMS];
98 HChar* VG_(clo_require_text_symbol) = NULL;
99 Bool VG_(clo_run_libc_freeres) = True;
100 Bool VG_(clo_track_fds) = False;
101 Bool VG_(clo_show_below_main)= False;
102 Bool VG_(clo_show_emwarns) = False;
103 Word VG_(clo_max_stackframe) = 2000000;
104 Word VG_(clo_main_stacksize) = 0; /* use client's rlimit.stack */
105 Bool VG_(clo_wait_for_gdb) = False;
106 VgSmc VG_(clo_smc_check) = Vg_SmcStack;
107 HChar* VG_(clo_kernel_variant) = NULL;
108 Bool VG_(clo_dsymutil) = False;
109 Char* VG_(clo_nacl_file) = NULL;
110 Char* VG_(clo_memfs_malloc_path) = NULL;
111 Int VG_(clo_memfs_page_size) = 2048; /* 2M */
112
113
114 /*====================================================================*/
115 /*=== File expansion ===*/
116 /*====================================================================*/
117
118 // Copies the string, prepending it with the startup working directory, and
119 // expanding %p and %q entries. Returns a new, malloc'd string.
VG_(expand_file_name)120 Char* VG_(expand_file_name)(Char* option_name, Char* format)
121 {
122 static Char base_dir[VKI_PATH_MAX];
123 Int len, i = 0, j = 0;
124 Char* out;
125
126 Bool ok = VG_(get_startup_wd)(base_dir, VKI_PATH_MAX);
127 tl_assert(ok);
128
129 if (VG_STREQ(format, "")) {
130 // Empty name, bad.
131 VG_(fmsg)("%s: filename is empty", option_name);
132 goto bad;
133 }
134
135 // If 'format' starts with a '~', abort -- the user probably expected the
136 // shell to expand but it didn't (see bug 195268 for details). This means
137 // that we don't allow a legitimate filename beginning with '~' but that
138 // seems very unlikely.
139 if (format[0] == '~') {
140 VG_(fmsg)(
141 "%s: filename begins with '~'\n"
142 "You probably expected the shell to expand the '~', but it\n"
143 "didn't. The rules for '~'-expansion vary from shell to shell.\n"
144 "You might have more luck using $HOME instead.\n",
145 option_name
146 );
147 goto bad;
148 }
149
150 // If 'format' starts with a '/', do not prefix with startup dir.
151 if (format[0] != '/') {
152 j += VG_(strlen)(base_dir);
153 }
154
155 // The 10 is slop, it should be enough in most cases.
156 len = j + VG_(strlen)(format) + 10;
157 out = VG_(malloc)( "options.efn.1", len );
158 if (format[0] != '/') {
159 VG_(strcpy)(out, base_dir);
160 out[j++] = '/';
161 }
162
163 #define ENSURE_THIS_MUCH_SPACE(x) \
164 if (j + x >= len) { \
165 len += (10 + x); \
166 out = VG_(realloc)("options.efn.2(multiple)", out, len); \
167 }
168
169 while (format[i]) {
170 if (format[i] != '%') {
171 ENSURE_THIS_MUCH_SPACE(1);
172 out[j++] = format[i++];
173
174 } else {
175 // We saw a '%'. What's next...
176 i++;
177 if ('%' == format[i]) {
178 // Replace '%%' with '%'.
179 ENSURE_THIS_MUCH_SPACE(1);
180 out[j++] = format[i++];
181 }
182 else if ('p' == format[i]) {
183 // Print the PID. Assume that it's not longer than 10 chars --
184 // reasonable since 'pid' is an Int (ie. 32 bits).
185 Int pid = VG_(getpid)();
186 ENSURE_THIS_MUCH_SPACE(10);
187 j += VG_(sprintf)(&out[j], "%d", pid);
188 i++;
189 }
190 else if ('q' == format[i]) {
191 i++;
192 if ('{' == format[i]) {
193 // Get the env var name, print its contents.
194 Char* qualname;
195 Char* qual;
196 i++;
197 qualname = &format[i];
198 while (True) {
199 if (0 == format[i]) {
200 VG_(fmsg)("%s: malformed %%q specifier\n", 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_(fmsg)("%s: environment variable %s is not set\n",
209 option_name, qualname);
210 format[i] = '}'; // Put the '}' back.
211 goto bad;
212 }
213 format[i] = '}'; // Put the '}' back.
214 i++;
215 break;
216 }
217 i++;
218 }
219 ENSURE_THIS_MUCH_SPACE(VG_(strlen)(qual));
220 j += VG_(sprintf)(&out[j], "%s", qual);
221 } else {
222 VG_(fmsg)("%s: expected '{' after '%%q'\n", option_name);
223 goto bad;
224 }
225 }
226 else {
227 // Something else, abort.
228 VG_(fmsg)("%s: expected 'p' or 'q' or '%%' after '%%'\n",
229 option_name);
230 goto bad;
231 }
232 }
233 }
234 ENSURE_THIS_MUCH_SPACE(1);
235 out[j++] = 0;
236
237 return out;
238
239 bad: {
240 Char* opt = // 2: 1 for the '=', 1 for the NUL.
241 VG_(malloc)( "options.efn.3",
242 VG_(strlen)(option_name) + VG_(strlen)(format) + 2 );
243 VG_(strcpy)(opt, option_name);
244 VG_(strcat)(opt, "=");
245 VG_(strcat)(opt, format);
246 VG_(fmsg_bad_option)(opt, "");
247 }
248 }
249
250 /*====================================================================*/
251 /*=== --trace-children= support ===*/
252 /*====================================================================*/
253
consume_commas(HChar const * c)254 static HChar const* consume_commas ( HChar const* c ) {
255 while (*c && *c == ',') {
256 ++c;
257 }
258 return c;
259 }
260
consume_field(HChar const * c)261 static HChar const* consume_field ( HChar const* c ) {
262 while (*c && *c != ',') {
263 ++c;
264 }
265 return c;
266 }
267
268 /* Should we trace into this child executable (across execve etc) ?
269 This involves considering --trace-children=,
270 --trace-children-skip=, --trace-children-skip-by-arg=, and the name
271 of the executable. 'child_argv' must not include the name of the
272 executable itself; iow child_argv[0] must be the first arg, if any,
273 for the child. */
VG_(should_we_trace_this_child)274 Bool VG_(should_we_trace_this_child) ( HChar* child_exe_name,
275 HChar** child_argv )
276 {
277 // child_exe_name is pulled out of the guest's space. We
278 // should be at least marginally cautious with it, lest it
279 // explode or burst into flames unexpectedly.
280 if (child_exe_name == NULL || VG_(strlen)(child_exe_name) == 0)
281 return VG_(clo_trace_children); // we know narfink
282
283 // If --trace-children=no, the answer is simply NO.
284 if (! VG_(clo_trace_children))
285 return False;
286
287 // Otherwise, look for other reasons to say NO. First,
288 // see if the exe name matches any of the patterns specified
289 // by --trace-children-skip=.
290 if (VG_(clo_trace_children_skip)) {
291 HChar const* last = VG_(clo_trace_children_skip);
292 HChar const* name = (HChar const*)child_exe_name;
293 while (*last) {
294 Bool matches;
295 HChar* patt;
296 HChar const* first = consume_commas(last);
297 last = consume_field(first);
298 if (first == last)
299 break;
300 vg_assert(last > first);
301 /* copy the candidate string into a temporary malloc'd block
302 so we can use VG_(string_match) on it. */
303 patt = VG_(calloc)("m_options.swttc.1", last - first + 1, 1);
304 VG_(memcpy)(patt, first, last - first);
305 vg_assert(patt[last-first] == 0);
306 matches = VG_(string_match)(patt, name);
307 VG_(free)(patt);
308 if (matches)
309 return False;
310 }
311 }
312
313 // Check if any of the args match any of the patterns specified
314 // by --trace-children-skip-by-arg=.
315 if (VG_(clo_trace_children_skip_by_arg) && child_argv != NULL) {
316 HChar const* last = VG_(clo_trace_children_skip_by_arg);
317 while (*last) {
318 Int i;
319 Bool matches;
320 HChar* patt;
321 HChar const* first = consume_commas(last);
322 last = consume_field(first);
323 if (first == last)
324 break;
325 vg_assert(last > first);
326 /* copy the candidate string into a temporary malloc'd block
327 so we can use VG_(string_match) on it. */
328 patt = VG_(calloc)("m_options.swttc.1", last - first + 1, 1);
329 VG_(memcpy)(patt, first, last - first);
330 vg_assert(patt[last-first] == 0);
331 for (i = 0; child_argv[i]; i++) {
332 matches = VG_(string_match)(patt, child_argv[i]);
333 if (matches) {
334 VG_(free)(patt);
335 return False;
336 }
337 }
338 VG_(free)(patt);
339 }
340 }
341
342 // --trace-children=yes, and this particular executable isn't
343 // excluded
344 return True;
345 }
346
347
348 /*--------------------------------------------------------------------*/
349 /*--- end ---*/
350 /*--------------------------------------------------------------------*/
351