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. 56static 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. 69static 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. 78static 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. */ 119void 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 */ 324OutputSink VG_(log_output_sink) = { 2, VgLogTo_Fd, NULL }; /* 2 = stderr */ 325OutputSink VG_(xml_output_sink) = { -1, VgLogTo_Fd, NULL }; /* disabled */ 326 327static 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 335static 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 363static 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 394static 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 */ 411static 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 431void 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. */ 480void 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. */ 570static 571void 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 601typedef 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. 611static 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 624static 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 635static 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 651UInt VG_(vprintf) ( const HChar *format, va_list vargs ) 652{ 653 return vprintf_WRK( &VG_(log_output_sink), format, vargs ); 654} 655 656UInt 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 666UInt VG_(vprintf_xml) ( const HChar *format, va_list vargs ) 667{ 668 return vprintf_WRK( &VG_(xml_output_sink), format, vargs ); 669} 670 671UInt 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 681static 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} 691UInt 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 707static void add_to__sprintf_buf ( HChar c, void *p ) 708{ 709 HChar** b = p; 710 *(*b)++ = c; 711} 712 713UInt 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 727UInt 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 751typedef 752 struct { 753 HChar* buf; 754 Int buf_size; 755 Int buf_used; 756 } 757 snprintf_buf_t; 758 759static 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 771UInt 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 785UInt 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 798void 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 814struct _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 821static 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 833VgFile *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 849UInt VG_(vfprintf) ( VgFile *fp, const HChar *format, va_list vargs ) 850{ 851 return VG_(debugLog_vprintf)(add_to__vgfile, fp, format, vargs); 852} 853 854UInt 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 864void 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 884void 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*/ 923typedef 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 936static 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. 945static 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 1028UInt 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. */ 1056UInt 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 1066static 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 1073UInt 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 1083void 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 1095void 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 1103UInt 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 1113UInt 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. */ 1125void 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)) 1133void 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)) 1142void 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 ? 1160const 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 1173const 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