1 /* -*- mode: C; c-basic-offset: 3; -*- */
2
3 /*--------------------------------------------------------------------*/
4 /*--- Libc printing. m_libcprint.c ---*/
5 /*--------------------------------------------------------------------*/
6
7 /*
8 This file is part of Valgrind, a dynamic binary instrumentation
9 framework.
10
11 Copyright (C) 2000-2017 Julian Seward
12 jseward@acm.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_vkiscnums.h"
35 #include "pub_core_debuglog.h"
36 #include "pub_core_gdbserver.h" // VG_(gdb_printf)
37 #include "pub_core_libcbase.h"
38 #include "pub_core_libcassert.h"
39 #include "pub_core_libcfile.h" // VG_(write)(), VG_(write_socket)()
40 #include "pub_core_libcprint.h"
41 #include "pub_core_libcproc.h" // VG_(getpid)(), VG_(read_millisecond_timer()
42 #include "pub_core_mallocfree.h" // VG_(malloc)
43 #include "pub_core_machine.h" // VG_(machine_get_VexArchInfo)
44 #include "pub_core_options.h"
45 #include "pub_core_clreq.h" // For RUNNING_ON_VALGRIND
46 #include "pub_core_clientstate.h"
47 #include "pub_core_syscall.h" // VG_(strerror)
48 #include "pub_core_tooliface.h" // VG_(details)
49
50
51 /*====================================================================*/
52 /*=== Printing the preamble ===*/
53 /*====================================================================*/
54
55 // Print the argument, escaping any chars that require it.
umsg_arg(const HChar * arg)56 static void umsg_arg(const HChar *arg)
57 {
58 SizeT len = VG_(strlen)(arg);
59 const HChar *special = " \\<>";
60 for (UInt i = 0; i < len; i++) {
61 if (VG_(strchr)(special, arg[i])) {
62 VG_(umsg)("\\"); // escape with a backslash if necessary
63 }
64 VG_(umsg)("%c", arg[i]);
65 }
66 }
67
68 // Send output to the XML-stream and escape any XML meta-characters.
xml_arg(const HChar * arg)69 static void xml_arg(const HChar *arg)
70 {
71 VG_(printf_xml)("%pS", arg);
72 }
73
74 // Write the name and value of log file qualifiers to the xml file.
75 // We can safely assume here that the format string is well-formed.
76 // It has been checked earlier in VG_(expand_file_name) when processing
77 // command line options.
print_file_vars(const HChar * format)78 static void print_file_vars(const HChar *format)
79 {
80 UInt i = 0;
81
82 while (format[i]) {
83 if (format[i] == '%') {
84 // We saw a '%'. What's next...
85 i++;
86 if ('q' == format[i]) {
87 i++;
88 if ('{' == format[i]) {
89 // Get the env var name, print its contents.
90 UInt begin_qualname = ++i;
91 while (True) {
92 if ('}' == format[i]) {
93 UInt qualname_len = i - begin_qualname;
94 HChar qualname[qualname_len + 1];
95 VG_(strncpy)(qualname, format + begin_qualname,
96 qualname_len);
97 qualname[qualname_len] = '\0';
98 HChar *qual = VG_(getenv)(qualname);
99 i++;
100 VG_(printf_xml)("<logfilequalifier> <var>%pS</var> "
101 "<value>%pS</value> </logfilequalifier>\n",
102 qualname, qual);
103 break;
104 }
105 i++;
106 }
107 }
108 }
109 } else {
110 i++;
111 }
112 }
113 }
114
115 /* Ok, the logging sink is running now. Print a suitable preamble.
116 If logging to file or a socket, write details of parent PID and
117 command line args, to help people trying to interpret the
118 results of a run which encompasses multiple processes. */
VG_(print_preamble)119 void VG_(print_preamble)(Bool logging_to_fd)
120 {
121 const HChar *xpre = VG_(clo_xml) ? " <line>" : "";
122 const HChar *xpost = VG_(clo_xml) ? "</line>" : "";
123 UInt (*umsg_or_xml)( const HChar *, ... )
124 = VG_(clo_xml) ? VG_(printf_xml) : VG_(umsg);
125 void (*umsg_or_xml_arg)( const HChar *) = VG_(clo_xml) ? xml_arg : umsg_arg;
126
127 vg_assert( VG_(args_for_client) );
128 vg_assert( VG_(args_for_valgrind) );
129 vg_assert( VG_(clo_toolname) );
130
131 if (VG_(clo_xml)) {
132 VG_(printf_xml)("<?xml version=\"1.0\"?>\n");
133 VG_(printf_xml)("\n");
134 VG_(printf_xml)("<valgrindoutput>\n");
135 VG_(printf_xml)("\n");
136 VG_(printf_xml)("<protocolversion>4</protocolversion>\n");
137 VG_(printf_xml)("<protocoltool>%s</protocoltool>\n", VG_(clo_toolname));
138 VG_(printf_xml)("\n");
139 }
140
141 if (VG_(clo_xml) || VG_(clo_verbosity) > 0) {
142
143 if (VG_(clo_xml))
144 VG_(printf_xml)("<preamble>\n");
145
146 /* Tool details */
147 umsg_or_xml(VG_(clo_xml) ? "%s%pS%pS%pS, %pS%s\n" : "%s%s%s%s, %s%s\n",
148 xpre,
149 VG_(details).name,
150 NULL == VG_(details).version ? "" : "-",
151 NULL == VG_(details).version ? "" : VG_(details).version,
152 VG_(details).description,
153 xpost);
154
155 if (VG_(strlen)(VG_(clo_toolname)) >= 4 &&
156 VG_STREQN(4, VG_(clo_toolname), "exp-")) {
157 umsg_or_xml("%sNOTE: This is an Experimental-Class Valgrind Tool%s\n",
158 xpre, xpost);
159 }
160
161 umsg_or_xml(VG_(clo_xml) ? "%s%pS%s\n" : "%s%s%s\n",
162 xpre, VG_(details).copyright_author, xpost);
163
164 /* Core details */
165 umsg_or_xml(
166 "%sUsing Valgrind-%s and LibVEX; rerun with -h for copyright info%s\n",
167 xpre, VERSION, xpost);
168
169 // Print the command line. At one point we wrapped at 80 chars and
170 // printed a '\' as a line joiner, but that makes it hard to cut and
171 // paste the command line (because of the "==pid==" prefixes), so we now
172 // favour utility and simplicity over aesthetics.
173 umsg_or_xml("%sCommand: ", xpre);
174 umsg_or_xml_arg(VG_(args_the_exename));
175
176 for (UInt i = 0; i < VG_(sizeXA)( VG_(args_for_client)); i++) {
177 HChar *s = *(HChar **)VG_(indexXA)( VG_(args_for_client), i);
178 umsg_or_xml(" ");
179 umsg_or_xml_arg(s);
180 }
181 umsg_or_xml("%s\n", xpost);
182
183 if (VG_(clo_xml))
184 VG_(printf_xml)("</preamble>\n");
185 }
186
187 // Print the parent PID, and other stuff, if necessary.
188 if (!VG_(clo_xml) && VG_(clo_verbosity) > 0 && !logging_to_fd) {
189 VG_(umsg)("Parent PID: %d\n", VG_(getppid)());
190 } else if (VG_(clo_xml)) {
191 VG_(printf_xml)("\n");
192 VG_(printf_xml)("<pid>%d</pid>\n", VG_(getpid)());
193 VG_(printf_xml)("<ppid>%d</ppid>\n", VG_(getppid)());
194 VG_(printf_xml)("<tool>%pS</tool>\n", VG_(clo_toolname));
195 if (VG_(clo_xml_fname_unexpanded) != NULL)
196 print_file_vars(VG_(clo_xml_fname_unexpanded));
197 if (VG_(clo_xml_user_comment)) {
198 /* Note: the user comment itself is XML and is therefore to
199 be passed through verbatim (%s) rather than escaped (%pS). */
200 VG_(printf_xml)("<usercomment>%s</usercomment>\n",
201 VG_(clo_xml_user_comment));
202 }
203 VG_(printf_xml)("\n");
204 VG_(printf_xml)("<args>\n");
205
206 VG_(printf_xml)(" <vargv>\n");
207 if (VG_(name_of_launcher))
208 VG_(printf_xml)(" <exe>%pS</exe>\n", VG_(name_of_launcher));
209 else
210 VG_(printf_xml)(" <exe>%pS</exe>\n", "(launcher name unknown)");
211 for (UInt i = 0; i < VG_(sizeXA)( VG_(args_for_valgrind) ); i++) {
212 VG_(printf_xml)(
213 " <arg>%pS</arg>\n",
214 *(HChar **) VG_(indexXA)( VG_(args_for_valgrind), i));
215 }
216 VG_(printf_xml)(" </vargv>\n");
217
218 VG_(printf_xml)(" <argv>\n");
219 VG_(printf_xml)(" <exe>%pS</exe>\n", VG_(args_the_exename));
220 for (UInt i = 0; i < VG_(sizeXA)( VG_(args_for_client) ); i++) {
221 VG_(printf_xml)(
222 " <arg>%pS</arg>\n",
223 *(HChar **) VG_(indexXA)( VG_(args_for_client), i));
224 }
225 VG_(printf_xml)(" </argv>\n");
226
227 VG_(printf_xml)("</args>\n");
228 }
229
230 // Last thing in the preamble is a blank line.
231 if (VG_(clo_xml))
232 VG_(printf_xml)("\n");
233 else if (VG_(clo_verbosity) > 0)
234 VG_(umsg)("\n");
235
236 if (VG_(clo_verbosity) > 1) {
237 # if defined(VGO_linux)
238 SysRes fd;
239 # endif
240 VexArch vex_arch;
241 VexArchInfo vex_archinfo;
242 if (!logging_to_fd)
243 VG_(message)(Vg_DebugMsg, "\n");
244 VG_(message)(Vg_DebugMsg, "Valgrind options:\n");
245 for (UInt i = 0; i < VG_(sizeXA)( VG_(args_for_valgrind) ); i++) {
246 VG_(message)(Vg_DebugMsg,
247 " %s\n",
248 *(HChar **) VG_(indexXA)( VG_(args_for_valgrind), i));
249 }
250
251 # if defined(VGO_linux)
252 VG_(message)(Vg_DebugMsg, "Contents of /proc/version:\n");
253 fd = VG_(open)("/proc/version", VKI_O_RDONLY, 0);
254 if (sr_isError(fd)) {
255 VG_(message)(Vg_DebugMsg, " can't open /proc/version\n");
256 } else {
257 const SizeT bufsiz = 255;
258 HChar version_buf[bufsiz+1];
259 VG_(message)(Vg_DebugMsg, " ");
260 Int n, fdno = sr_Res(fd);
261 do {
262 n = VG_(read)(fdno, version_buf, bufsiz);
263 if (n < 0) {
264 VG_(message)(Vg_DebugMsg, " error reading /proc/version\n");
265 break;
266 }
267 version_buf[n] = '\0';
268 VG_(message)(Vg_DebugMsg, "%s", version_buf);
269 } while (n == bufsiz);
270 VG_(message)(Vg_DebugMsg, "\n");
271 VG_(close)(fdno);
272 }
273 # elif defined(VGO_darwin)
274 VG_(message)(Vg_DebugMsg, "Output from sysctl({CTL_KERN,KERN_VERSION}):\n");
275 /* Note: preferable to use sysctlbyname("kern.version", kernelVersion, &len, NULL, 0)
276 however that syscall is OS X 10.10+ only. */
277 Int mib[] = {CTL_KERN, KERN_VERSION};
278 SizeT len;
279 VG_(sysctl)(mib, sizeof(mib)/sizeof(Int), NULL, &len, NULL, 0);
280 HChar *kernelVersion = VG_(malloc)("main.pp.1", len);
281 VG_(sysctl)(mib, sizeof(mib)/sizeof(Int), kernelVersion, &len, NULL, 0);
282 VG_(message)(Vg_DebugMsg, " %s\n", kernelVersion);
283 VG_(free)( kernelVersion );
284 # elif defined(VGO_solaris)
285 /* There is no /proc/version file on Solaris so we try to get some
286 system information using the uname(2) syscall. */
287 struct vki_utsname uts;
288 VG_(message)(Vg_DebugMsg, "System information:\n");
289 SysRes res = VG_(do_syscall1)(__NR_uname, (UWord)&uts);
290 if (sr_isError(res))
291 VG_(message)(Vg_DebugMsg, " uname() failed\n");
292 else
293 VG_(message)(Vg_DebugMsg, " %s %s %s %s\n",
294 uts.sysname, uts.release, uts.version, uts.machine);
295 # endif
296
297 VG_(machine_get_VexArchInfo)(&vex_arch, &vex_archinfo);
298 VG_(message)(
299 Vg_DebugMsg,
300 "Arch and hwcaps: %s, %s, %s\n",
301 LibVEX_ppVexArch ( vex_arch ),
302 LibVEX_ppVexEndness ( vex_archinfo.endness ),
303 LibVEX_ppVexHwCaps ( vex_arch, vex_archinfo.hwcaps )
304 );
305 VG_(message)(Vg_DebugMsg,
306 "Page sizes: currently %u, max supported %u\n",
307 (UInt) VKI_PAGE_SIZE, (UInt) VKI_MAX_PAGE_SIZE);
308 VG_(message)(Vg_DebugMsg,
309 "Valgrind library directory: %s\n", VG_(libdir));
310 }
311 }
312
313 /* ---------------------------------------------------------------------
314 Writing to file or a socket
315 ------------------------------------------------------------------ */
316
317 /* The destination sinks for normal and XML output. These have their
318 initial values here; they are set to final values by
319 m_main.main_process_cmd_line_options(). See comment at the top of
320 that function for the associated logic.
321 After startup, the gdbserver monitor command might temporarily
322 set the fd of log_output_sink to -2 to indicate that output is
323 to be given to gdb rather than output to the startup fd */
324 OutputSink VG_(log_output_sink) = { 2, VgLogTo_Fd, NULL }; /* 2 = stderr */
325 OutputSink VG_(xml_output_sink) = { -1, VgLogTo_Fd, NULL }; /* disabled */
326
revert_sink_to_stderr(OutputSink * sink)327 static void revert_sink_to_stderr ( OutputSink *sink )
328 {
329 sink->fd = 2; /* stderr */
330 sink->type = VgLogTo_Fd;
331 VG_(free)(sink->fsname_expanded);
332 sink->fsname_expanded = NULL;
333 }
334
prepare_sink_fd(const HChar * clo_fname_unexpanded,OutputSink * sink,Bool is_xml)335 static Int prepare_sink_fd(const HChar *clo_fname_unexpanded, OutputSink *sink,
336 Bool is_xml)
337 {
338 vg_assert(clo_fname_unexpanded != NULL);
339 vg_assert(VG_(strlen)(clo_fname_unexpanded) <= 900); /* paranoia */
340
341 // Nb: we overwrite an existing file of this name without asking
342 // any questions.
343 HChar *logfilename = VG_(expand_file_name)(
344 (is_xml) ? "--xml-file" : "--log-file",
345 clo_fname_unexpanded);
346 SysRes sres = VG_(open)(logfilename,
347 VKI_O_CREAT|VKI_O_WRONLY|VKI_O_TRUNC,
348 VKI_S_IRUSR|VKI_S_IWUSR|VKI_S_IRGRP|VKI_S_IROTH);
349 if (!sr_isError(sres)) {
350 Int fd = sr_Res(sres);
351 sink->fsname_expanded = logfilename;
352 sink->type = VgLogTo_File;
353 return fd;
354 } else {
355 VG_(fmsg)("Cannot create %s file '%s': %s\n",
356 (is_xml) ? "XML" : "log", logfilename,
357 VG_(strerror)(sr_Err(sres)));
358 VG_(exit)(1);
359 /*NOTREACHED*/
360 }
361 }
362
prepare_sink_socket(const HChar * clo_fname_unexpanded,OutputSink * sink,Bool is_xml)363 static Int prepare_sink_socket(const HChar *clo_fname_unexpanded,
364 OutputSink *sink, Bool is_xml)
365 {
366 vg_assert(clo_fname_unexpanded != NULL);
367 vg_assert(VG_(strlen)(clo_fname_unexpanded) <= 900); /* paranoia */
368
369 Int fd = VG_(connect_via_socket)(clo_fname_unexpanded);
370 if (fd == -1) {
371 VG_(fmsg)("Invalid %s spec of '%s'\n",
372 (is_xml) ? "--xml-socket" : "--log-socket",
373 clo_fname_unexpanded);
374 VG_(exit)(1);
375 /*NOTREACHED*/
376 }
377 if (fd == -2) {
378 VG_(umsg)("Failed to connect to %slogging server '%s'.\n"
379 "%s will be sent to stderr instead.\n",
380 (is_xml) ? "XML " : "",
381 clo_fname_unexpanded,
382 (is_xml) ? "XML output" : "Logging messages");
383 /* We don't change anything here. */
384 vg_assert(sink->fd == 2);
385 vg_assert(sink->type == VgLogTo_Fd);
386 return 2;
387 } else {
388 vg_assert(fd > 0);
389 sink->type = VgLogTo_Socket;
390 return fd;
391 }
392 }
393
finalize_sink_fd(OutputSink * sink,Int new_fd,Bool is_xml)394 static void finalize_sink_fd(OutputSink *sink, Int new_fd, Bool is_xml)
395 {
396 // Move new_fd into the safe range, so it doesn't conflict with any app fds.
397 Int safe_fd = VG_(fcntl)(new_fd, VKI_F_DUPFD, VG_(fd_hard_limit));
398 if (safe_fd < 0) {
399 VG_(message)(Vg_UserMsg, "Valgrind: failed to move %s file descriptor "
400 "into safe range, using stderr\n",
401 (is_xml) ? "XML" : "log");
402 revert_sink_to_stderr(sink);
403 } else {
404 VG_(fcntl)(safe_fd, VKI_F_SETFD, VKI_FD_CLOEXEC);
405 sink->fd = safe_fd;
406 }
407 }
408
409 /* Re-opens an output file sink when exanded file name differs from what we
410 have now. Returns 'True' if the sink was reopened */
reopen_sink_if_needed(const HChar * clo_fname_unexpanded,OutputSink * sink,Bool is_xml)411 static Bool reopen_sink_if_needed(const HChar *clo_fname_unexpanded,
412 OutputSink *sink, Bool is_xml)
413 {
414 if (sink->type == VgLogTo_File) {
415 /* Try to expand --log|xml-file again and see if it differs from what
416 we have now. */
417 HChar *logfilename = VG_(expand_file_name)(
418 (is_xml) ? "--xml-file" : "--log-file",
419 clo_fname_unexpanded);
420 if (VG_(strcmp)(logfilename, sink->fsname_expanded) != 0) {
421 Int fd = prepare_sink_fd(clo_fname_unexpanded, sink, is_xml);
422 finalize_sink_fd(sink, fd, is_xml);
423 return True;
424 }
425 VG_(free)(logfilename);
426 }
427
428 return False;
429 }
430
VG_(logging_atfork_child)431 void VG_(logging_atfork_child)(ThreadId tid)
432 {
433 /* If --child-silent-after-fork=yes was specified, set the output file
434 descriptors to 'impossible' values. This is noticed by
435 send_bytes_to_logging_sink(), which duly stops writing any further
436 output. */
437 if (VG_(clo_child_silent_after_fork)) {
438 if (VG_(log_output_sink).type != VgLogTo_Socket) {
439 VG_(log_output_sink).fd = -1;
440 VG_(log_output_sink).type = VgLogTo_Fd;
441 }
442 if (VG_(xml_output_sink).type != VgLogTo_Socket) {
443 VG_(xml_output_sink).fd = -1;
444 VG_(xml_output_sink).type = VgLogTo_Fd;
445 }
446 } else {
447 if (reopen_sink_if_needed(VG_(clo_log_fname_unexpanded),
448 &VG_(log_output_sink), False) ||
449 reopen_sink_if_needed(VG_(clo_xml_fname_unexpanded),
450 &VG_(xml_output_sink), True)) {
451 VG_(print_preamble)(VG_(log_output_sink).type != VgLogTo_File);
452 }
453 }
454 }
455
456 /* Initializes normal log and xml sinks (of type fd, file, or socket).
457 Any problem encountered is considered a hard error and causes V. to exit.
458
459 Comments on how the logging options are handled:
460
461 User can specify:
462 --log-fd= for a fd to write to (default setting, fd = 2)
463 --log-file= for a file name to write to
464 --log-socket= for a socket to write to
465
466 As a result of examining these and doing relevant socket/file
467 opening, a final fd is established. This is stored in
468 VG_(log_output_sink) in m_libcprint. Also, if --log-file=STR was
469 specified, then it is stored in VG_(clo_log_fname_unexpanded), in m_options.
470 And then STR, after expansion of %p and %q templates within
471 it, is stored in VG_(log_output_sink), just in case anybody wants to know
472 what it is.
473
474 When printing, VG_(log_output_sink) is consulted to find the
475 fd to send output to.
476
477 Exactly analogous actions are undertaken for the XML output
478 channel, with the one difference that the default fd is -1, meaning
479 the channel is disabled by default. */
VG_(init_log_xml_sinks)480 void VG_(init_log_xml_sinks)(VgLogTo log_to, VgLogTo xml_to,
481 Int /*initial*/log_fd, Int /*initial*/xml_fd)
482 {
483 // VG_(clo_log_fd) is used by all the messaging. It starts as 2 (stderr)
484 // and we cannot change it until we know what we are changing it to is ok.
485
486 /* Start setting up logging now. After this is done, VG_(log_output_sink)
487 and (if relevant) VG_(xml_output_sink) should be connected to whatever
488 sink has been selected, and we indiscriminately chuck stuff into it
489 without worrying what the nature of it is.
490 Oh the wonder of Unix streams. */
491
492 vg_assert(VG_(log_output_sink).fd == 2 /* stderr */);
493 vg_assert(VG_(log_output_sink).type == VgLogTo_Fd);
494 vg_assert(VG_(log_output_sink).fsname_expanded == NULL);
495
496 vg_assert(VG_(xml_output_sink).fd == -1 /* disabled */);
497 vg_assert(VG_(xml_output_sink).type == VgLogTo_Fd);
498 vg_assert(VG_(xml_output_sink).fsname_expanded == NULL);
499
500 /* --- set up the normal text output channel --- */
501 switch (log_to) {
502 case VgLogTo_Fd:
503 vg_assert(VG_(clo_log_fname_unexpanded) == NULL);
504 break;
505
506 case VgLogTo_File:
507 log_fd = prepare_sink_fd(VG_(clo_log_fname_unexpanded),
508 &VG_(log_output_sink), False);
509 break;
510
511 case VgLogTo_Socket:
512 log_fd = prepare_sink_socket(VG_(clo_log_fname_unexpanded),
513 &VG_(log_output_sink), False);
514 break;
515 }
516
517 /* --- set up the XML output channel --- */
518 switch (xml_to) {
519 case VgLogTo_Fd:
520 vg_assert(VG_(clo_xml_fname_unexpanded) == NULL);
521 break;
522
523 case VgLogTo_File:
524 xml_fd = prepare_sink_fd(VG_(clo_xml_fname_unexpanded),
525 &VG_(xml_output_sink), True);
526 break;
527
528 case VgLogTo_Socket:
529 log_fd = prepare_sink_socket(VG_(clo_xml_fname_unexpanded),
530 &VG_(xml_output_sink), True);
531 break;
532 }
533
534 /* If we've got this far, and XML mode was requested, but no XML
535 output channel appears to have been specified, just stop. We
536 could continue, and XML output will simply vanish into nowhere,
537 but that is likely to confuse the hell out of users, which is
538 distinctly Ungood. */
539 if (VG_(clo_xml) && xml_fd == -1) {
540 VG_(fmsg_bad_option)(
541 "--xml=yes, but no XML destination specified",
542 "--xml=yes has been specified, but there is no XML output\n"
543 "destination. You must specify an XML output destination\n"
544 "using --xml-fd, --xml-file or --xml-socket.\n"
545 );
546 }
547
548 // Finalise the output fds: the log fd ..
549 if (log_fd >= 0) {
550 finalize_sink_fd(&VG_(log_output_sink), log_fd, False);
551 } else {
552 // If they said --log-fd=-1, don't print anything. Plausible for use in
553 // regression testing suites that use client requests to count errors.
554 VG_(log_output_sink).fd = -1;
555 VG_(log_output_sink).type = VgLogTo_Fd;
556 }
557
558 // Finalise the output fds: and the XML fd ..
559 if (xml_fd >= 0) {
560 finalize_sink_fd(&VG_(xml_output_sink), xml_fd, True);
561 } else {
562 // If they said --xml-fd=-1, don't print anything. Plausible for use in
563 // regression testing suites that use client requests to count errors.
564 VG_(xml_output_sink).fd = -1;
565 VG_(xml_output_sink).type = VgLogTo_Fd;
566 }
567 }
568
569 /* Do the low-level send of a message to the logging sink. */
570 static
send_bytes_to_logging_sink(OutputSink * sink,const HChar * msg,Int nbytes)571 void send_bytes_to_logging_sink ( OutputSink* sink, const HChar* msg, Int nbytes )
572 {
573 if (sink->type == VgLogTo_Socket) {
574 Int rc = VG_(write_socket)( sink->fd, msg, nbytes );
575 if (rc == -1) {
576 // For example, the listener process died. Switch back to stderr.
577 revert_sink_to_stderr(sink);
578 VG_(write)( sink->fd, msg, nbytes );
579 }
580 } else {
581 /* sink->fd could have been set to -1 in the various
582 sys-wrappers for sys_fork, if --child-silent-after-fork=yes
583 is in effect. That is a signal that we should not produce
584 any more output. */
585 if (sink->fd >= 0)
586 VG_(write)( sink->fd, msg, nbytes );
587 else if (sink->fd == -2 && nbytes > 0)
588 /* send to gdb the provided data, which must be
589 a null terminated string with len >= 1 */
590 VG_(gdb_printf)("%s", msg);
591 }
592 }
593
594
595 /* ---------------------------------------------------------------------
596 printf() and friends
597 ------------------------------------------------------------------ */
598
599 /* --------- printf --------- */
600
601 typedef
602 struct {
603 HChar buf[512];
604 Int buf_used;
605 OutputSink* sink;
606 }
607 printf_buf_t;
608
609 // Adds a single char to the buffer. When the buffer gets sufficiently
610 // full, we write its contents to the logging sink.
add_to__printf_buf(HChar c,void * p)611 static void add_to__printf_buf ( HChar c, void *p )
612 {
613 printf_buf_t *b = (printf_buf_t *)p;
614
615 if (b->buf_used > sizeof(b->buf) - 2 ) {
616 send_bytes_to_logging_sink( b->sink, b->buf, b->buf_used );
617 b->buf_used = 0;
618 }
619 b->buf[b->buf_used++] = c;
620 b->buf[b->buf_used] = 0;
621 vg_assert(b->buf_used < sizeof(b->buf));
622 }
623
vprintf_to_buf(printf_buf_t * b,const HChar * format,va_list vargs)624 static UInt vprintf_to_buf ( printf_buf_t* b,
625 const HChar *format, va_list vargs )
626 {
627 UInt ret = 0;
628 if (b->sink->fd >= 0 || b->sink->fd == -2) {
629 ret = VG_(debugLog_vprintf)
630 ( add_to__printf_buf, b, format, vargs );
631 }
632 return ret;
633 }
634
vprintf_WRK(OutputSink * sink,const HChar * format,va_list vargs)635 static UInt vprintf_WRK ( OutputSink* sink,
636 const HChar *format, va_list vargs )
637 {
638 printf_buf_t myprintf_buf
639 = { "", 0, sink };
640 UInt ret
641 = vprintf_to_buf(&myprintf_buf, format, vargs);
642 // Write out any chars left in the buffer.
643 if (myprintf_buf.buf_used > 0) {
644 send_bytes_to_logging_sink( myprintf_buf.sink,
645 myprintf_buf.buf,
646 myprintf_buf.buf_used );
647 }
648 return ret;
649 }
650
VG_(vprintf)651 UInt VG_(vprintf) ( const HChar *format, va_list vargs )
652 {
653 return vprintf_WRK( &VG_(log_output_sink), format, vargs );
654 }
655
VG_(printf)656 UInt VG_(printf) ( const HChar *format, ... )
657 {
658 UInt ret;
659 va_list vargs;
660 va_start(vargs, format);
661 ret = VG_(vprintf)(format, vargs);
662 va_end(vargs);
663 return ret;
664 }
665
VG_(vprintf_xml)666 UInt VG_(vprintf_xml) ( const HChar *format, va_list vargs )
667 {
668 return vprintf_WRK( &VG_(xml_output_sink), format, vargs );
669 }
670
VG_(printf_xml)671 UInt VG_(printf_xml) ( const HChar *format, ... )
672 {
673 UInt ret;
674 va_list vargs;
675 va_start(vargs, format);
676 ret = VG_(vprintf_xml)(format, vargs);
677 va_end(vargs);
678 return ret;
679 }
680
emit_WRK(const HChar * format,va_list vargs)681 static UInt emit_WRK ( const HChar* format, va_list vargs )
682 {
683 if (VG_(clo_xml)) {
684 return VG_(vprintf_xml)(format, vargs);
685 } else if (VG_(log_output_sink).fd == -2) {
686 return VG_(vprintf) (format, vargs);
687 } else {
688 return VG_(vmessage)(Vg_UserMsg, format, vargs);
689 }
690 }
VG_(emit)691 UInt VG_(emit) ( const HChar* format, ... )
692 {
693 UInt ret;
694 va_list vargs;
695 va_start(vargs, format);
696 ret = emit_WRK(format, vargs);
697 va_end(vargs);
698 return ret;
699 }
700
701 /* --------- sprintf --------- */
702
703 /* If we had an explicit buf structure here, it would contain only one
704 field, indicating where the next char is to go. So use p directly
705 for that, rather than having it be a pointer to a structure. */
706
add_to__sprintf_buf(HChar c,void * p)707 static void add_to__sprintf_buf ( HChar c, void *p )
708 {
709 HChar** b = p;
710 *(*b)++ = c;
711 }
712
VG_(vsprintf)713 UInt VG_(vsprintf) ( HChar* buf, const HChar *format, va_list vargs )
714 {
715 Int ret;
716 HChar* sprintf_ptr = buf;
717
718 ret = VG_(debugLog_vprintf)
719 ( add_to__sprintf_buf, &sprintf_ptr, format, vargs );
720 add_to__sprintf_buf('\0', &sprintf_ptr);
721
722 vg_assert(VG_(strlen)(buf) == ret);
723
724 return ret;
725 }
726
VG_(sprintf)727 UInt VG_(sprintf) ( HChar* buf, const HChar *format, ... )
728 {
729 UInt ret;
730 va_list vargs;
731 va_start(vargs,format);
732 ret = VG_(vsprintf)(buf, format, vargs);
733 va_end(vargs);
734 return ret;
735 }
736
737
738 /* --------- snprintf --------- */
739
740 /* The return value of VG_(snprintf) and VG_(vsnprintf) differs from
741 what is defined in C99. Let S be the size of the buffer as given in
742 the 2nd argument.
743 Return value R:
744 R < S: The output string was successfully written to the buffer.
745 It is null-terminated and R == strlen( output string )
746 R == S: The supplied buffer was too small to hold the output string.
747 The first S-1 characters of the output string were written
748 to the buffer followed by the terminating null character.
749 */
750
751 typedef
752 struct {
753 HChar* buf;
754 Int buf_size;
755 Int buf_used;
756 }
757 snprintf_buf_t;
758
add_to__snprintf_buf(HChar c,void * p)759 static void add_to__snprintf_buf ( HChar c, void* p )
760 {
761 snprintf_buf_t* b = p;
762 if (b->buf_size > 0 && b->buf_used < b->buf_size) {
763 b->buf[b->buf_used++] = c;
764 if (b->buf_used < b->buf_size)
765 b->buf[b->buf_used] = 0;
766 else
767 b->buf[b->buf_size-1] = 0; /* pre: b->buf_size > 0 */
768 }
769 }
770
VG_(vsnprintf)771 UInt VG_(vsnprintf) ( HChar* buf, Int size, const HChar *format, va_list vargs )
772 {
773 snprintf_buf_t b;
774 b.buf = buf;
775 b.buf_size = size < 0 ? 0 : size;
776 b.buf_used = 0;
777 if (b.buf_size > 0)
778 b.buf[0] = 0; // ensure to null terminate buf if empty format
779 (void) VG_(debugLog_vprintf)
780 ( add_to__snprintf_buf, &b, format, vargs );
781
782 return b.buf_used;
783 }
784
VG_(snprintf)785 UInt VG_(snprintf) ( HChar* buf, Int size, const HChar *format, ... )
786 {
787 UInt ret;
788 va_list vargs;
789 va_start(vargs,format);
790 ret = VG_(vsnprintf)(buf, size, format, vargs);
791 va_end(vargs);
792 return ret;
793 }
794
795
796 /* --------- vcbprintf --------- */
797
VG_(vcbprintf)798 void VG_(vcbprintf)( void(*char_sink)(HChar, void* opaque),
799 void* opaque,
800 const HChar* format, va_list vargs )
801 {
802 (void) VG_(debugLog_vprintf)
803 ( char_sink, opaque, format, vargs );
804 }
805
806
807 /* --------- fprintf ---------- */
808
809 /* This is like [v]fprintf, except it writes to a file handle using
810 VG_(write). */
811
812 #define VGFILE_BUFSIZE 8192
813
814 struct _VgFile {
815 HChar buf[VGFILE_BUFSIZE];
816 UInt num_chars; // number of characters in buf
817 Int fd; // file descriptor to write to
818 };
819
820
add_to__vgfile(HChar c,void * p)821 static void add_to__vgfile ( HChar c, void *p )
822 {
823 VgFile *fp = p;
824
825 fp->buf[fp->num_chars++] = c;
826
827 if (fp->num_chars == VGFILE_BUFSIZE) {
828 VG_(write)(fp->fd, fp->buf, fp->num_chars);
829 fp->num_chars = 0;
830 }
831 }
832
VG_(fopen)833 VgFile *VG_(fopen)(const HChar *name, Int flags, Int mode)
834 {
835 SysRes res = VG_(open)(name, flags, mode);
836
837 if (sr_isError(res))
838 return NULL;
839
840 VgFile *fp = VG_(malloc)("fopen", sizeof(VgFile));
841
842 fp->fd = sr_Res(res);
843 fp->num_chars = 0;
844
845 return fp;
846 }
847
848
VG_(vfprintf)849 UInt VG_(vfprintf) ( VgFile *fp, const HChar *format, va_list vargs )
850 {
851 return VG_(debugLog_vprintf)(add_to__vgfile, fp, format, vargs);
852 }
853
VG_(fprintf)854 UInt VG_(fprintf) ( VgFile *fp, const HChar *format, ... )
855 {
856 UInt ret;
857 va_list vargs;
858 va_start(vargs,format);
859 ret = VG_(vfprintf)(fp, format, vargs);
860 va_end(vargs);
861 return ret;
862 }
863
VG_(fclose)864 void VG_(fclose)( VgFile *fp )
865 {
866 // Flush the buffer.
867 if (fp->num_chars)
868 VG_(write)(fp->fd, fp->buf, fp->num_chars);
869
870 VG_(close)(fp->fd);
871 VG_(free)(fp);
872 }
873
874
875 /* ---------------------------------------------------------------------
876 elapsed_wallclock_time()
877 ------------------------------------------------------------------ */
878
879 /* Get the elapsed wallclock time since startup into buf, which must
880 16 chars long. This is unchecked. It also relies on the
881 millisecond timer having been set to zero by an initial read in
882 m_main during startup. */
883
VG_(elapsed_wallclock_time)884 void VG_(elapsed_wallclock_time) ( /*OUT*/HChar* buf, SizeT bufsize )
885 {
886 UInt t, ms, s, mins, hours, days;
887
888 vg_assert(bufsize > 20);
889
890 t = VG_(read_millisecond_timer)(); /* milliseconds */
891
892 ms = t % 1000;
893 t /= 1000; /* now in seconds */
894
895 s = t % 60;
896 t /= 60; /* now in minutes */
897
898 mins = t % 60;
899 t /= 60; /* now in hours */
900
901 hours = t % 24;
902 t /= 24; /* now in days */
903
904 days = t;
905
906 VG_(sprintf)(buf, "%02u:%02u:%02u:%02u.%03u ", days, hours, mins, s, ms);
907 }
908
909
910 /* ---------------------------------------------------------------------
911 message()
912 ------------------------------------------------------------------ */
913
914 /* A buffer for accumulating VG_(message) style output. This is
915 pretty much the same as VG_(printf)'s scheme, with two differences:
916
917 * The message buffer persists between calls, so that multiple
918 calls to VG_(message) can build up output.
919
920 * Whenever the first character on a line is emitted, the
921 ==PID== style preamble is stuffed in before it.
922 */
923 typedef
924 struct {
925 HChar buf[512+128];
926 Int buf_used;
927 Bool atLeft; /* notionally, is the next char position at the
928 leftmost column? */
929 /* Current message kind - changes from call to call */
930 VgMsgKind kind;
931 /* destination */
932 OutputSink* sink;
933 }
934 vmessage_buf_t;
935
936 static vmessage_buf_t vmessage_buf
937 = { "", 0, True, Vg_UserMsg, &VG_(log_output_sink) };
938
939
940 // Adds a single char to the buffer. We aim to have at least 128
941 // bytes free in the buffer, so that it's always possible to emit
942 // the preamble into the buffer if c happens to be the character
943 // following a \n. When the buffer gets too full, we write its
944 // contents to the logging sink.
add_to__vmessage_buf(HChar c,void * p)945 static void add_to__vmessage_buf ( HChar c, void *p )
946 {
947 HChar tmp[64];
948 vmessage_buf_t* b = (vmessage_buf_t*)p;
949
950 vg_assert(b->buf_used >= 0 && b->buf_used < sizeof(b->buf)-128);
951
952 if (UNLIKELY(b->atLeft)) {
953 // insert preamble
954 HChar ch;
955 Int i, depth;
956
957 // Print one '>' in front of the messages for each level of
958 // self-hosting being performed.
959 // Do not print such '>' if sim hint "no-inner-prefix" given
960 // (useful to run regression tests in an outer/inner setup
961 // and avoid the diff failing due to these unexpected '>').
962 depth = RUNNING_ON_VALGRIND;
963 if (depth > 0
964 && !SimHintiS(SimHint_no_inner_prefix, VG_(clo_sim_hints))) {
965 if (depth > 10)
966 depth = 10; // ?!?!
967 for (i = 0; i < depth; i++) {
968 b->buf[b->buf_used++] = '>';
969 }
970 }
971
972 if (Vg_FailMsg == b->kind) {
973 // "valgrind: " prefix.
974 b->buf[b->buf_used++] = 'v';
975 b->buf[b->buf_used++] = 'a';
976 b->buf[b->buf_used++] = 'l';
977 b->buf[b->buf_used++] = 'g';
978 b->buf[b->buf_used++] = 'r';
979 b->buf[b->buf_used++] = 'i';
980 b->buf[b->buf_used++] = 'n';
981 b->buf[b->buf_used++] = 'd';
982 b->buf[b->buf_used++] = ':';
983 b->buf[b->buf_used++] = ' ';
984 } else {
985 switch (b->kind) {
986 case Vg_UserMsg: ch = '='; break;
987 case Vg_DebugMsg: ch = '-'; break;
988 case Vg_ClientMsg: ch = '*'; break;
989 default: ch = '?'; break;
990 }
991
992 b->buf[b->buf_used++] = ch;
993 b->buf[b->buf_used++] = ch;
994
995 if (VG_(clo_time_stamp)) {
996 VG_(elapsed_wallclock_time)(tmp, sizeof tmp);
997 for (i = 0; tmp[i]; i++)
998 b->buf[b->buf_used++] = tmp[i];
999 }
1000
1001 VG_(sprintf)(tmp, "%d", VG_(getpid)());
1002 tmp[sizeof(tmp)-1] = 0;
1003 for (i = 0; tmp[i]; i++)
1004 b->buf[b->buf_used++] = tmp[i];
1005
1006 b->buf[b->buf_used++] = ch;
1007 b->buf[b->buf_used++] = ch;
1008 b->buf[b->buf_used++] = ' ';
1009 }
1010
1011 /* We can't possibly have stuffed 96 chars in merely as a result
1012 of making the preamble (can we?) */
1013 vg_assert(b->buf_used < sizeof(b->buf)-32);
1014 }
1015
1016 b->buf[b->buf_used++] = c;
1017 b->buf[b->buf_used] = 0;
1018
1019 if (b->buf_used >= sizeof(b->buf) - 128) {
1020 send_bytes_to_logging_sink( b->sink, b->buf, b->buf_used );
1021 b->buf_used = 0;
1022 }
1023
1024 b->atLeft = c == '\n';
1025 }
1026
1027
VG_(vmessage)1028 UInt VG_(vmessage) ( VgMsgKind kind, const HChar* format, va_list vargs )
1029 {
1030 UInt ret;
1031
1032 /* Note (carefully) that the buf persists from call to call, unlike
1033 with the other printf variants in earlier parts of this file. */
1034 vmessage_buf_t* b = &vmessage_buf; /* shorthand for convenience */
1035
1036 /* We have to set this each call, so that the correct flavour
1037 of preamble is emitted at each \n. */
1038 b->kind = kind;
1039
1040 ret = VG_(debugLog_vprintf) ( add_to__vmessage_buf,
1041 b, format, vargs );
1042
1043 /* If the message finished exactly with a \n, then flush it at this
1044 point. If not, assume more bits of the same line will turn up
1045 in later messages, so don't bother to flush it right now. */
1046
1047 if (b->atLeft && b->buf_used > 0) {
1048 send_bytes_to_logging_sink( b->sink, b->buf, b->buf_used );
1049 b->buf_used = 0;
1050 }
1051
1052 return ret;
1053 }
1054
1055 /* Send a simple single-part message. */
VG_(message)1056 UInt VG_(message) ( VgMsgKind kind, const HChar* format, ... )
1057 {
1058 UInt count;
1059 va_list vargs;
1060 va_start(vargs,format);
1061 count = VG_(vmessage) ( kind, format, vargs );
1062 va_end(vargs);
1063 return count;
1064 }
1065
revert_to_stderr(void)1066 static void revert_to_stderr ( void )
1067 {
1068 revert_sink_to_stderr(&VG_(log_output_sink));
1069 }
1070
1071 /* VG_(message) variants with hardwired first argument. */
1072
VG_(fmsg)1073 UInt VG_(fmsg) ( const HChar* format, ... )
1074 {
1075 UInt count;
1076 va_list vargs;
1077 va_start(vargs,format);
1078 count = VG_(vmessage) ( Vg_FailMsg, format, vargs );
1079 va_end(vargs);
1080 return count;
1081 }
1082
VG_(fmsg_bad_option)1083 void VG_(fmsg_bad_option) ( const HChar* opt, const HChar* format, ... )
1084 {
1085 va_list vargs;
1086 va_start(vargs,format);
1087 revert_to_stderr();
1088 VG_(message) (Vg_FailMsg, "Bad option: %s\n", opt);
1089 VG_(vmessage)(Vg_FailMsg, format, vargs );
1090 VG_(message) (Vg_FailMsg, "Use --help for more information or consult the user manual.\n");
1091 va_end(vargs);
1092 VG_(exit)(1);
1093 }
1094
VG_(fmsg_unknown_option)1095 void VG_(fmsg_unknown_option) ( const HChar* opt)
1096 {
1097 revert_to_stderr();
1098 VG_(message) (Vg_FailMsg, "Unknown option: %s\n", opt);
1099 VG_(message) (Vg_FailMsg, "Use --help for more information or consult the user manual.\n");
1100 VG_(exit)(1);
1101 }
1102
VG_(umsg)1103 UInt VG_(umsg) ( const HChar* format, ... )
1104 {
1105 UInt count;
1106 va_list vargs;
1107 va_start(vargs,format);
1108 count = VG_(vmessage) ( Vg_UserMsg, format, vargs );
1109 va_end(vargs);
1110 return count;
1111 }
1112
VG_(dmsg)1113 UInt VG_(dmsg) ( const HChar* format, ... )
1114 {
1115 UInt count;
1116 va_list vargs;
1117 va_start(vargs,format);
1118 count = VG_(vmessage) ( Vg_DebugMsg, format, vargs );
1119 va_end(vargs);
1120 return count;
1121 }
1122
1123 /* Flush any output that has accumulated in vmessage_buf as a
1124 result of previous calls to VG_(message) et al. */
VG_(message_flush)1125 void VG_(message_flush) ( void )
1126 {
1127 vmessage_buf_t* b = &vmessage_buf;
1128 send_bytes_to_logging_sink( b->sink, b->buf, b->buf_used );
1129 b->buf_used = 0;
1130 }
1131
1132 __attribute__((noreturn))
VG_(err_missing_prog)1133 void VG_(err_missing_prog) ( void )
1134 {
1135 revert_to_stderr();
1136 VG_(fmsg)("no program specified\n");
1137 VG_(fmsg)("Use --help for more information.\n");
1138 VG_(exit)(1);
1139 }
1140
1141 __attribute__((noreturn))
VG_(err_config_error)1142 void VG_(err_config_error) ( const HChar* format, ... )
1143 {
1144 va_list vargs;
1145 va_start(vargs,format);
1146 revert_to_stderr();
1147 VG_(message) (Vg_FailMsg, "Startup or configuration error:\n ");
1148 VG_(vmessage)(Vg_FailMsg, format, vargs );
1149 VG_(message) (Vg_FailMsg, "Unable to start up properly. Giving up.\n");
1150 va_end(vargs);
1151 VG_(exit)(1);
1152 }
1153
1154 /* ---------------------------------------------------------------------
1155 VG_(sr_as_string)()
1156 ------------------------------------------------------------------ */
1157
1158 #if defined(VGO_linux)
1159 // FIXME: Does this function need to be adjusted for MIPS's _valEx ?
VG_(sr_as_string)1160 const HChar *VG_(sr_as_string) ( SysRes sr )
1161 {
1162 static HChar buf[7+1+2+16+1+1]; // large enough
1163
1164 if (sr_isError(sr))
1165 VG_(sprintf)(buf, "Failure(0x%lx)", sr_Err(sr));
1166 else
1167 VG_(sprintf)(buf, "Success(0x%lx)", sr_Res(sr));
1168 return buf;
1169 }
1170
1171 #elif defined(VGO_darwin) || defined(VGO_solaris)
1172
VG_(sr_as_string)1173 const HChar *VG_(sr_as_string) ( SysRes sr )
1174 {
1175 static HChar buf[7+1+2+16+1+2+16+1+1]; // large enough
1176
1177 if (sr_isError(sr))
1178 VG_(sprintf)(buf, "Failure(0x%lx)", sr_Err(sr));
1179 else
1180 VG_(sprintf)(buf, "Success(0x%lx:0x%lx)", sr_ResHI(sr), sr_Res(sr));
1181 return buf;
1182 }
1183
1184 #else
1185
1186 #error unknown OS
1187
1188 #endif
1189
1190 /*--------------------------------------------------------------------*/
1191 /*--- end ---*/
1192 /*--------------------------------------------------------------------*/
1193