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