blob: d66c67dc6488dedec920053a7c5a2b1066300f97 [file] [log] [blame]
florian12d2eb52014-10-30 22:17:56 +00001/* -*- mode: C; c-basic-offset: 3; -*- */
njnc44a6c22005-06-03 13:21:18 +00002
3/*--------------------------------------------------------------------*/
4/*--- Libc printing. m_libcprint.c ---*/
5/*--------------------------------------------------------------------*/
6
7/*
8 This file is part of Valgrind, a dynamic binary instrumentation
9 framework.
10
Elliott Hughesed398002017-06-21 14:41:24 -070011 Copyright (C) 2000-2017 Julian Seward
njnc44a6c22005-06-03 13:21:18 +000012 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
njnc7561b92005-06-19 01:24:32 +000032#include "pub_core_basics.h"
sewardj4cfea4f2006-10-14 19:26:10 +000033#include "pub_core_vki.h"
Elliott Hughesed398002017-06-21 14:41:24 -070034#include "pub_core_vkiscnums.h"
njnc44a6c22005-06-03 13:21:18 +000035#include "pub_core_debuglog.h"
florianc91f5842013-09-15 10:42:26 +000036#include "pub_core_gdbserver.h" // VG_(gdb_printf)
njnc44a6c22005-06-03 13:21:18 +000037#include "pub_core_libcbase.h"
njn132bfcc2005-06-04 19:16:06 +000038#include "pub_core_libcassert.h"
sewardj592ae092005-11-08 19:01:44 +000039#include "pub_core_libcfile.h" // VG_(write)(), VG_(write_socket)()
njnc44a6c22005-06-03 13:21:18 +000040#include "pub_core_libcprint.h"
sewardj592ae092005-11-08 19:01:44 +000041#include "pub_core_libcproc.h" // VG_(getpid)(), VG_(read_millisecond_timer()
florian12d2eb52014-10-30 22:17:56 +000042#include "pub_core_mallocfree.h" // VG_(malloc)
Elliott Hughesed398002017-06-21 14:41:24 -070043#include "pub_core_machine.h" // VG_(machine_get_VexArchInfo)
njnc44a6c22005-06-03 13:21:18 +000044#include "pub_core_options.h"
florian1a046d52013-09-16 20:56:35 +000045#include "pub_core_clreq.h" // For RUNNING_ON_VALGRIND
Elliott Hughesed398002017-06-21 14:41:24 -070046#include "pub_core_clientstate.h"
47#include "pub_core_syscall.h" // VG_(strerror)
48#include "pub_core_tooliface.h" // VG_(details)
njnc44a6c22005-06-03 13:21:18 +000049
njnc44a6c22005-06-03 13:21:18 +000050
Elliott Hughesed398002017-06-21 14:41:24 -070051/*====================================================================*/
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
njnc44a6c22005-06-03 13:21:18 +0000313/* ---------------------------------------------------------------------
314 Writing to file or a socket
315 ------------------------------------------------------------------ */
316
sewardj738856f2009-07-15 14:48:32 +0000317/* 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
sewardj3b290482011-05-06 21:02:55 +0000320 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 */
Elliott Hughesed398002017-06-21 14:41:24 -0700324OutputSink 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
njnc44a6c22005-06-03 13:21:18 +0000569/* Do the low-level send of a message to the logging sink. */
sewardj738856f2009-07-15 14:48:32 +0000570static
floriandbb35842012-10-27 18:39:11 +0000571void send_bytes_to_logging_sink ( OutputSink* sink, const HChar* msg, Int nbytes )
njnc44a6c22005-06-03 13:21:18 +0000572{
Elliott Hughesed398002017-06-21 14:41:24 -0700573 if (sink->type == VgLogTo_Socket) {
sewardj738856f2009-07-15 14:48:32 +0000574 Int rc = VG_(write_socket)( sink->fd, msg, nbytes );
575 if (rc == -1) {
576 // For example, the listener process died. Switch back to stderr.
Elliott Hughesed398002017-06-21 14:41:24 -0700577 revert_sink_to_stderr(sink);
sewardj738856f2009-07-15 14:48:32 +0000578 VG_(write)( sink->fd, msg, nbytes );
579 }
580 } else {
581 /* sink->fd could have been set to -1 in the various
sewardj6e31f802007-11-17 22:29:25 +0000582 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. */
sewardj738856f2009-07-15 14:48:32 +0000585 if (sink->fd >= 0)
586 VG_(write)( sink->fd, msg, nbytes );
philippe02ea4132013-09-04 21:42:43 +0000587 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 */
sewardj3b290482011-05-06 21:02:55 +0000590 VG_(gdb_printf)("%s", msg);
njnc44a6c22005-06-03 13:21:18 +0000591 }
592}
593
sewardj738856f2009-07-15 14:48:32 +0000594
njnc44a6c22005-06-03 13:21:18 +0000595/* ---------------------------------------------------------------------
596 printf() and friends
597 ------------------------------------------------------------------ */
598
sewardj738856f2009-07-15 14:48:32 +0000599/* --------- printf --------- */
600
sewardj45f4e7c2005-09-27 19:20:21 +0000601typedef
602 struct {
sewardj738856f2009-07-15 14:48:32 +0000603 HChar buf[512];
604 Int buf_used;
605 OutputSink* sink;
sewardj45f4e7c2005-09-27 19:20:21 +0000606 }
sewardj738856f2009-07-15 14:48:32 +0000607 printf_buf_t;
bart1a0cb6a2008-04-14 16:35:32 +0000608
njnc44a6c22005-06-03 13:21:18 +0000609// Adds a single char to the buffer. When the buffer gets sufficiently
610// full, we write its contents to the logging sink.
sewardj738856f2009-07-15 14:48:32 +0000611static void add_to__printf_buf ( HChar c, void *p )
njnc44a6c22005-06-03 13:21:18 +0000612{
sewardj738856f2009-07-15 14:48:32 +0000613 printf_buf_t *b = (printf_buf_t *)p;
njnc44a6c22005-06-03 13:21:18 +0000614
sewardj738856f2009-07-15 14:48:32 +0000615 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;
njnc44a6c22005-06-03 13:21:18 +0000618 }
sewardj738856f2009-07-15 14:48:32 +0000619 b->buf[b->buf_used++] = c;
620 b->buf[b->buf_used] = 0;
floriane2800c92014-09-15 20:57:45 +0000621 vg_assert(b->buf_used < sizeof(b->buf));
sewardj738856f2009-07-15 14:48:32 +0000622}
623
624static UInt vprintf_to_buf ( printf_buf_t* b,
625 const HChar *format, va_list vargs )
626{
627 UInt ret = 0;
sewardj3b290482011-05-06 21:02:55 +0000628 if (b->sink->fd >= 0 || b->sink->fd == -2) {
sewardj738856f2009-07-15 14:48:32 +0000629 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;
njnc44a6c22005-06-03 13:21:18 +0000649}
650
651UInt VG_(vprintf) ( const HChar *format, va_list vargs )
652{
sewardj738856f2009-07-15 14:48:32 +0000653 return vprintf_WRK( &VG_(log_output_sink), format, vargs );
njnc44a6c22005-06-03 13:21:18 +0000654}
655
656UInt VG_(printf) ( const HChar *format, ... )
657{
658 UInt ret;
659 va_list vargs;
njnc44a6c22005-06-03 13:21:18 +0000660 va_start(vargs, format);
661 ret = VG_(vprintf)(format, vargs);
662 va_end(vargs);
njnc44a6c22005-06-03 13:21:18 +0000663 return ret;
664}
665
sewardj738856f2009-07-15 14:48:32 +0000666UInt 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, ... )
bart1a0cb6a2008-04-14 16:35:32 +0000672{
673 UInt ret;
674 va_list vargs;
bart1a0cb6a2008-04-14 16:35:32 +0000675 va_start(vargs, format);
sewardj738856f2009-07-15 14:48:32 +0000676 ret = VG_(vprintf_xml)(format, vargs);
bart1a0cb6a2008-04-14 16:35:32 +0000677 va_end(vargs);
bart1a0cb6a2008-04-14 16:35:32 +0000678 return ret;
679}
680
philippe07c08522014-05-14 20:39:27 +0000681static 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}
sewardj738856f2009-07-15 14:48:32 +0000700
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;
njnc44a6c22005-06-03 13:21:18 +0000711}
712
floriandbb35842012-10-27 18:39:11 +0000713UInt VG_(vsprintf) ( HChar* buf, const HChar *format, va_list vargs )
njnc44a6c22005-06-03 13:21:18 +0000714{
715 Int ret;
sewardj738856f2009-07-15 14:48:32 +0000716 HChar* sprintf_ptr = buf;
njnc44a6c22005-06-03 13:21:18 +0000717
718 ret = VG_(debugLog_vprintf)
sewardj738856f2009-07-15 14:48:32 +0000719 ( add_to__sprintf_buf, &sprintf_ptr, format, vargs );
720 add_to__sprintf_buf('\0', &sprintf_ptr);
njnc44a6c22005-06-03 13:21:18 +0000721
722 vg_assert(VG_(strlen)(buf) == ret);
723
724 return ret;
725}
726
floriandbb35842012-10-27 18:39:11 +0000727UInt VG_(sprintf) ( HChar* buf, const HChar *format, ... )
njnc44a6c22005-06-03 13:21:18 +0000728{
729 UInt ret;
730 va_list vargs;
njnc44a6c22005-06-03 13:21:18 +0000731 va_start(vargs,format);
732 ret = VG_(vsprintf)(buf, format, vargs);
733 va_end(vargs);
njnc44a6c22005-06-03 13:21:18 +0000734 return ret;
735}
736
sewardj45f4e7c2005-09-27 19:20:21 +0000737
sewardj738856f2009-07-15 14:48:32 +0000738/* --------- snprintf --------- */
739
florian3e81b8b2014-10-07 14:28:52 +0000740/* 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
sewardj45f4e7c2005-09-27 19:20:21 +0000751typedef
752 struct {
753 HChar* buf;
754 Int buf_size;
755 Int buf_used;
756 }
sewardj738856f2009-07-15 14:48:32 +0000757 snprintf_buf_t;
sewardj45f4e7c2005-09-27 19:20:21 +0000758
sewardj738856f2009-07-15 14:48:32 +0000759static void add_to__snprintf_buf ( HChar c, void* p )
sewardj45f4e7c2005-09-27 19:20:21 +0000760{
sewardj738856f2009-07-15 14:48:32 +0000761 snprintf_buf_t* b = p;
sewardj45f4e7c2005-09-27 19:20:21 +0000762 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;
sewardj03e2bb82006-12-24 03:02:18 +0000766 else
767 b->buf[b->buf_size-1] = 0; /* pre: b->buf_size > 0 */
sewardj45f4e7c2005-09-27 19:20:21 +0000768 }
769}
770
floriandbb35842012-10-27 18:39:11 +0000771UInt VG_(vsnprintf) ( HChar* buf, Int size, const HChar *format, va_list vargs )
sewardj45f4e7c2005-09-27 19:20:21 +0000772{
sewardj738856f2009-07-15 14:48:32 +0000773 snprintf_buf_t b;
sewardj45f4e7c2005-09-27 19:20:21 +0000774 b.buf = buf;
775 b.buf_size = size < 0 ? 0 : size;
776 b.buf_used = 0;
philippe3a00f522013-02-26 21:54:28 +0000777 if (b.buf_size > 0)
778 b.buf[0] = 0; // ensure to null terminate buf if empty format
sewardjc7ffc942011-03-28 16:26:42 +0000779 (void) VG_(debugLog_vprintf)
780 ( add_to__snprintf_buf, &b, format, vargs );
sewardj45f4e7c2005-09-27 19:20:21 +0000781
782 return b.buf_used;
783}
784
floriandbb35842012-10-27 18:39:11 +0000785UInt VG_(snprintf) ( HChar* buf, Int size, const HChar *format, ... )
sewardj45f4e7c2005-09-27 19:20:21 +0000786{
787 UInt ret;
788 va_list vargs;
sewardj45f4e7c2005-09-27 19:20:21 +0000789 va_start(vargs,format);
790 ret = VG_(vsnprintf)(buf, size, format, vargs);
791 va_end(vargs);
sewardj45f4e7c2005-09-27 19:20:21 +0000792 return ret;
793}
794
795
sewardj738856f2009-07-15 14:48:32 +0000796/* --------- 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
florian12d2eb52014-10-30 22:17:56 +0000807/* --------- 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
Elliott Hughesa0664b92017-04-18 17:46:52 -0700870 VG_(close)(fp->fd);
florian12d2eb52014-10-30 22:17:56 +0000871 VG_(free)(fp);
872}
873
sewardja11553a2005-07-19 12:17:05 +0000874
875/* ---------------------------------------------------------------------
sewardj592ae092005-11-08 19:01:44 +0000876 elapsed_wallclock_time()
sewardja11553a2005-07-19 12:17:05 +0000877 ------------------------------------------------------------------ */
878
sewardj592ae092005-11-08 19:01:44 +0000879/* 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. */
sewardja11553a2005-07-19 12:17:05 +0000883
florian77dec3a2014-11-14 22:34:40 +0000884void VG_(elapsed_wallclock_time) ( /*OUT*/HChar* buf, SizeT bufsize )
sewardja11553a2005-07-19 12:17:05 +0000885{
sewardj592ae092005-11-08 19:01:44 +0000886 UInt t, ms, s, mins, hours, days;
887
florian77dec3a2014-11-14 22:34:40 +0000888 vg_assert(bufsize > 20);
889
sewardj592ae092005-11-08 19:01:44 +0000890 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
njn82baca72009-07-24 05:35:49 +0000906 VG_(sprintf)(buf, "%02u:%02u:%02u:%02u.%03u ", days, hours, mins, s, ms);
sewardja11553a2005-07-19 12:17:05 +0000907}
908
909
njn856c54e2005-06-26 18:43:40 +0000910/* ---------------------------------------------------------------------
njnc44a6c22005-06-03 13:21:18 +0000911 message()
912 ------------------------------------------------------------------ */
913
sewardj738856f2009-07-15 14:48:32 +0000914/* 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;
sewardj738856f2009-07-15 14:48:32 +0000931 /* destination */
932 OutputSink* sink;
933 }
934 vmessage_buf_t;
935
936static vmessage_buf_t vmessage_buf
sewardj8ddb93a2010-02-15 10:07:05 +0000937 = { "", 0, True, Vg_UserMsg, &VG_(log_output_sink) };
sewardj738856f2009-07-15 14:48:32 +0000938
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
sewardj738856f2009-07-15 14:48:32 +0000957 // Print one '>' in front of the messages for each level of
958 // self-hosting being performed.
philippe72faf102012-03-11 22:24:03 +0000959 // 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 '>').
sewardj738856f2009-07-15 14:48:32 +0000962 depth = RUNNING_ON_VALGRIND;
philippeec905f72014-08-17 20:03:51 +0000963 if (depth > 0
964 && !SimHintiS(SimHint_no_inner_prefix, VG_(clo_sim_hints))) {
philippe72faf102012-03-11 22:24:03 +0000965 if (depth > 10)
966 depth = 10; // ?!?!
967 for (i = 0; i < depth; i++) {
968 b->buf[b->buf_used++] = '>';
969 }
sewardj738856f2009-07-15 14:48:32 +0000970 }
971
njnb1cc5d62010-07-06 04:05:23 +0000972 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;
njnb1cc5d62010-07-06 04:05:23 +0000988 case Vg_ClientMsg: ch = '*'; break;
989 default: ch = '?'; break;
990 }
sewardj738856f2009-07-15 14:48:32 +0000991
njnb1cc5d62010-07-06 04:05:23 +0000992 b->buf[b->buf_used++] = ch;
993 b->buf[b->buf_used++] = ch;
994
995 if (VG_(clo_time_stamp)) {
florian77dec3a2014-11-14 22:34:40 +0000996 VG_(elapsed_wallclock_time)(tmp, sizeof tmp);
njnb1cc5d62010-07-06 04:05:23 +0000997 for (i = 0; tmp[i]; i++)
998 b->buf[b->buf_used++] = tmp[i];
999 }
1000
1001 VG_(sprintf)(tmp, "%d", VG_(getpid)());
sewardj738856f2009-07-15 14:48:32 +00001002 tmp[sizeof(tmp)-1] = 0;
1003 for (i = 0; tmp[i]; i++)
1004 b->buf[b->buf_used++] = tmp[i];
njnb1cc5d62010-07-06 04:05:23 +00001005
1006 b->buf[b->buf_used++] = ch;
1007 b->buf[b->buf_used++] = ch;
1008 b->buf[b->buf_used++] = ' ';
sewardj738856f2009-07-15 14:48:32 +00001009 }
1010
sewardj738856f2009-07-15 14:48:32 +00001011 /* 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
njnc44a6c22005-06-03 13:21:18 +00001028UInt VG_(vmessage) ( VgMsgKind kind, const HChar* format, va_list vargs )
1029{
sewardj738856f2009-07-15 14:48:32 +00001030 UInt ret;
njnc44a6c22005-06-03 13:21:18 +00001031
sewardj738856f2009-07-15 14:48:32 +00001032 /* 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
sewardj738856f2009-07-15 14:48:32 +00001040 ret = VG_(debugLog_vprintf) ( add_to__vmessage_buf,
1041 b, format, vargs );
njnc44a6c22005-06-03 13:21:18 +00001042
sewardj738856f2009-07-15 14:48:32 +00001043 /* 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;
njnc44a6c22005-06-03 13:21:18 +00001050 }
1051
sewardj738856f2009-07-15 14:48:32 +00001052 return ret;
njnc44a6c22005-06-03 13:21:18 +00001053}
1054
njnc44a6c22005-06-03 13:21:18 +00001055/* 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
njnb1cc5d62010-07-06 04:05:23 +00001066static void revert_to_stderr ( void )
1067{
Elliott Hughesed398002017-06-21 14:41:24 -07001068 revert_sink_to_stderr(&VG_(log_output_sink));
njnb1cc5d62010-07-06 04:05:23 +00001069}
1070
sewardj738856f2009-07-15 14:48:32 +00001071/* VG_(message) variants with hardwired first argument. */
njnb1cc5d62010-07-06 04:05:23 +00001072
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
florianbbd9a212012-10-14 00:16:28 +00001083void VG_(fmsg_bad_option) ( const HChar* opt, const HChar* format, ... )
njnb1cc5d62010-07-06 04:05:23 +00001084{
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");
njnb1cc5d62010-07-06 04:05:23 +00001091 va_end(vargs);
florianbe1036e2014-10-17 19:44:55 +00001092 VG_(exit)(1);
njnb1cc5d62010-07-06 04:05:23 +00001093}
1094
florian5b99e662014-11-29 14:41:32 +00001095void 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
sewardj738856f2009-07-15 14:48:32 +00001103UInt 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
sewardj738856f2009-07-15 14:48:32 +00001123/* 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
njnb1cc5d62010-07-06 04:05:23 +00001132__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))
florianbbd9a212012-10-14 00:16:28 +00001142void VG_(err_config_error) ( const HChar* format, ... )
njnb1cc5d62010-07-06 04:05:23 +00001143{
florian1763e812011-07-12 19:07:05 +00001144 va_list vargs;
1145 va_start(vargs,format);
njnb1cc5d62010-07-06 04:05:23 +00001146 revert_to_stderr();
florian1763e812011-07-12 19:07:05 +00001147 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");
florian1763e812011-07-12 19:07:05 +00001150 va_end(vargs);
florianbe1036e2014-10-17 19:44:55 +00001151 VG_(exit)(1);
njnb1cc5d62010-07-06 04:05:23 +00001152}
1153
florian596b3fe2015-04-20 20:42:42 +00001154/* ---------------------------------------------------------------------
1155 VG_(sr_as_string)()
1156 ------------------------------------------------------------------ */
1157
florian596b3fe2015-04-20 20:42:42 +00001158#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
Elliott Hughesed398002017-06-21 14:41:24 -07001171#elif defined(VGO_darwin) || defined(VGO_solaris)
florian596b3fe2015-04-20 20:42:42 +00001172
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
sewardj738856f2009-07-15 14:48:32 +00001189
njnc44a6c22005-06-03 13:21:18 +00001190/*--------------------------------------------------------------------*/
1191/*--- end ---*/
1192/*--------------------------------------------------------------------*/