1
2 /*--------------------------------------------------------------------*/
3 /*--- Libc printing. m_libcprint.c ---*/
4 /*--------------------------------------------------------------------*/
5
6 /*
7 This file is part of Valgrind, a dynamic binary instrumentation
8 framework.
9
10 Copyright (C) 2000-2010 Julian Seward
11 jseward@acm.org
12
13 This program is free software; you can redistribute it and/or
14 modify it under the terms of the GNU General Public License as
15 published by the Free Software Foundation; either version 2 of the
16 License, or (at your option) any later version.
17
18 This program is distributed in the hope that it will be useful, but
19 WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 General Public License for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software
25 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
26 02111-1307, USA.
27
28 The GNU General Public License is contained in the file COPYING.
29 */
30
31 #include "pub_core_basics.h"
32 #include "pub_core_vki.h"
33 #include "pub_core_debuglog.h"
34 #include "pub_core_libcbase.h"
35 #include "pub_core_libcassert.h"
36 #include "pub_core_libcfile.h" // VG_(write)(), VG_(write_socket)()
37 #include "pub_core_libcprint.h"
38 #include "pub_core_libcproc.h" // VG_(getpid)(), VG_(read_millisecond_timer()
39 #include "pub_core_options.h"
40 #include "valgrind.h" // For RUNNING_ON_VALGRIND
41
42
43 /* ---------------------------------------------------------------------
44 Writing to file or a socket
45 ------------------------------------------------------------------ */
46
47 /* The destination sinks for normal and XML output. These have their
48 initial values here; they are set to final values by
49 m_main.main_process_cmd_line_options(). See comment at the top of
50 that function for the associated logic. */
51 OutputSink VG_(log_output_sink) = { 2, False }; /* 2 = stderr */
52 OutputSink VG_(xml_output_sink) = { -1, False }; /* disabled */
53
54 /* Do the low-level send of a message to the logging sink. */
55 static
send_bytes_to_logging_sink(OutputSink * sink,Char * msg,Int nbytes)56 void send_bytes_to_logging_sink ( OutputSink* sink, Char* msg, Int nbytes )
57 {
58 if (sink->is_socket) {
59 Int rc = VG_(write_socket)( sink->fd, msg, nbytes );
60 if (rc == -1) {
61 // For example, the listener process died. Switch back to stderr.
62 sink->is_socket = False;
63 sink->fd = 2;
64 VG_(write)( sink->fd, msg, nbytes );
65 }
66 } else {
67 /* sink->fd could have been set to -1 in the various
68 sys-wrappers for sys_fork, if --child-silent-after-fork=yes
69 is in effect. That is a signal that we should not produce
70 any more output. */
71 if (sink->fd >= 0)
72 VG_(write)( sink->fd, msg, nbytes );
73 }
74 }
75
76
77 /* ---------------------------------------------------------------------
78 printf() and friends
79 ------------------------------------------------------------------ */
80
81 /* --------- printf --------- */
82
83 typedef
84 struct {
85 HChar buf[512];
86 Int buf_used;
87 OutputSink* sink;
88 }
89 printf_buf_t;
90
91 // Adds a single char to the buffer. When the buffer gets sufficiently
92 // full, we write its contents to the logging sink.
add_to__printf_buf(HChar c,void * p)93 static void add_to__printf_buf ( HChar c, void *p )
94 {
95 printf_buf_t *b = (printf_buf_t *)p;
96
97 if (b->buf_used > sizeof(b->buf) - 2 ) {
98 send_bytes_to_logging_sink( b->sink, b->buf, b->buf_used );
99 b->buf_used = 0;
100 }
101 b->buf[b->buf_used++] = c;
102 b->buf[b->buf_used] = 0;
103 tl_assert(b->buf_used < sizeof(b->buf));
104 }
105
vprintf_to_buf(printf_buf_t * b,const HChar * format,va_list vargs)106 static UInt vprintf_to_buf ( printf_buf_t* b,
107 const HChar *format, va_list vargs )
108 {
109 UInt ret = 0;
110 if (b->sink->fd >= 0) {
111 ret = VG_(debugLog_vprintf)
112 ( add_to__printf_buf, b, format, vargs );
113 }
114 return ret;
115 }
116
vprintf_WRK(OutputSink * sink,const HChar * format,va_list vargs)117 static UInt vprintf_WRK ( OutputSink* sink,
118 const HChar *format, va_list vargs )
119 {
120 printf_buf_t myprintf_buf
121 = { "", 0, sink };
122 UInt ret
123 = vprintf_to_buf(&myprintf_buf, format, vargs);
124 // Write out any chars left in the buffer.
125 if (myprintf_buf.buf_used > 0) {
126 send_bytes_to_logging_sink( myprintf_buf.sink,
127 myprintf_buf.buf,
128 myprintf_buf.buf_used );
129 }
130 return ret;
131 }
132
VG_(vprintf)133 UInt VG_(vprintf) ( const HChar *format, va_list vargs )
134 {
135 return vprintf_WRK( &VG_(log_output_sink), format, vargs );
136 }
137
VG_(printf)138 UInt VG_(printf) ( const HChar *format, ... )
139 {
140 UInt ret;
141 va_list vargs;
142 va_start(vargs, format);
143 ret = VG_(vprintf)(format, vargs);
144 va_end(vargs);
145 return ret;
146 }
147
VG_(vprintf_xml)148 UInt VG_(vprintf_xml) ( const HChar *format, va_list vargs )
149 {
150 return vprintf_WRK( &VG_(xml_output_sink), format, vargs );
151 }
152
VG_(printf_xml)153 UInt VG_(printf_xml) ( const HChar *format, ... )
154 {
155 UInt ret;
156 va_list vargs;
157 va_start(vargs, format);
158 ret = VG_(vprintf_xml)(format, vargs);
159 va_end(vargs);
160 return ret;
161 }
162
163 /* An exact clone of VG_(printf_xml), unfortunately. */
VG_(printf_xml_no_f_c)164 UInt VG_(printf_xml_no_f_c) ( const HChar *format, ... )
165 {
166 UInt ret;
167 va_list vargs;
168 va_start(vargs, format);
169 ret = VG_(vprintf_xml)(format, vargs);
170 va_end(vargs);
171 return ret;
172 }
173
174
175 /* --------- sprintf --------- */
176
177 /* If we had an explicit buf structure here, it would contain only one
178 field, indicating where the next char is to go. So use p directly
179 for that, rather than having it be a pointer to a structure. */
180
add_to__sprintf_buf(HChar c,void * p)181 static void add_to__sprintf_buf ( HChar c, void *p )
182 {
183 HChar** b = p;
184 *(*b)++ = c;
185 }
186
VG_(vsprintf)187 UInt VG_(vsprintf) ( Char* buf, const HChar *format, va_list vargs )
188 {
189 Int ret;
190 HChar* sprintf_ptr = buf;
191
192 ret = VG_(debugLog_vprintf)
193 ( add_to__sprintf_buf, &sprintf_ptr, format, vargs );
194 add_to__sprintf_buf('\0', &sprintf_ptr);
195
196 vg_assert(VG_(strlen)(buf) == ret);
197
198 return ret;
199 }
200
VG_(sprintf)201 UInt VG_(sprintf) ( Char* buf, const HChar *format, ... )
202 {
203 UInt ret;
204 va_list vargs;
205 va_start(vargs,format);
206 ret = VG_(vsprintf)(buf, format, vargs);
207 va_end(vargs);
208 return ret;
209 }
210
211
212 /* --------- snprintf --------- */
213
214 typedef
215 struct {
216 HChar* buf;
217 Int buf_size;
218 Int buf_used;
219 }
220 snprintf_buf_t;
221
add_to__snprintf_buf(HChar c,void * p)222 static void add_to__snprintf_buf ( HChar c, void* p )
223 {
224 snprintf_buf_t* b = p;
225 if (b->buf_size > 0 && b->buf_used < b->buf_size) {
226 b->buf[b->buf_used++] = c;
227 if (b->buf_used < b->buf_size)
228 b->buf[b->buf_used] = 0;
229 else
230 b->buf[b->buf_size-1] = 0; /* pre: b->buf_size > 0 */
231 }
232 }
233
VG_(vsnprintf)234 UInt VG_(vsnprintf) ( Char* buf, Int size, const HChar *format, va_list vargs )
235 {
236 Int ret;
237 snprintf_buf_t b;
238 b.buf = buf;
239 b.buf_size = size < 0 ? 0 : size;
240 b.buf_used = 0;
241
242 ret = VG_(debugLog_vprintf)
243 ( add_to__snprintf_buf, &b, format, vargs );
244
245 return b.buf_used;
246 }
247
VG_(snprintf)248 UInt VG_(snprintf) ( Char* buf, Int size, const HChar *format, ... )
249 {
250 UInt ret;
251 va_list vargs;
252 va_start(vargs,format);
253 ret = VG_(vsnprintf)(buf, size, format, vargs);
254 va_end(vargs);
255 return ret;
256 }
257
258
259 /* --------- vcbprintf --------- */
260
VG_(vcbprintf)261 void VG_(vcbprintf)( void(*char_sink)(HChar, void* opaque),
262 void* opaque,
263 const HChar* format, va_list vargs )
264 {
265 (void) VG_(debugLog_vprintf)
266 ( char_sink, opaque, format, vargs );
267 }
268
269
270 /* ---------------------------------------------------------------------
271 percentify()
272 ------------------------------------------------------------------ */
273
274 // Percentify n/m with d decimal places. Includes the '%' symbol at the end.
275 // Right justifies in 'buf'.
VG_(percentify)276 void VG_(percentify)(ULong n, ULong m, UInt d, Int n_buf, char buf[])
277 {
278 Int i, len, space;
279 ULong p1;
280 Char fmt[32];
281
282 if (m == 0) {
283 // Have to generate the format string in order to be flexible about
284 // the width of the field.
285 VG_(sprintf)(fmt, "%%-%ds", n_buf);
286 // fmt is now "%<n_buf>s" where <d> is 1,2,3...
287 VG_(sprintf)(buf, fmt, "--%");
288 return;
289 }
290
291 p1 = (100*n) / m;
292
293 if (d == 0) {
294 VG_(sprintf)(buf, "%lld%%", p1);
295 } else {
296 ULong p2;
297 UInt ex;
298 switch (d) {
299 case 1: ex = 10; break;
300 case 2: ex = 100; break;
301 case 3: ex = 1000; break;
302 default: VG_(tool_panic)("Currently can only handle 3 decimal places");
303 }
304 p2 = ((100*n*ex) / m) % ex;
305 // Have to generate the format string in order to be flexible about
306 // the width of the post-decimal-point part.
307 VG_(sprintf)(fmt, "%%lld.%%0%dlld%%%%", d);
308 // fmt is now "%lld.%0<d>lld%%" where <d> is 1,2,3...
309 VG_(sprintf)(buf, fmt, p1, p2);
310 }
311
312 len = VG_(strlen)(buf);
313 space = n_buf - len;
314 if (space < 0) space = 0; /* Allow for v. small field_width */
315 i = len;
316
317 /* Right justify in field */
318 for ( ; i >= 0; i--) buf[i + space] = buf[i];
319 for (i = 0; i < space; i++) buf[i] = ' ';
320 }
321
322
323 /* ---------------------------------------------------------------------
324 elapsed_wallclock_time()
325 ------------------------------------------------------------------ */
326
327 /* Get the elapsed wallclock time since startup into buf, which must
328 16 chars long. This is unchecked. It also relies on the
329 millisecond timer having been set to zero by an initial read in
330 m_main during startup. */
331
VG_(elapsed_wallclock_time)332 void VG_(elapsed_wallclock_time) ( /*OUT*/HChar* buf )
333 {
334 UInt t, ms, s, mins, hours, days;
335
336 t = VG_(read_millisecond_timer)(); /* milliseconds */
337
338 ms = t % 1000;
339 t /= 1000; /* now in seconds */
340
341 s = t % 60;
342 t /= 60; /* now in minutes */
343
344 mins = t % 60;
345 t /= 60; /* now in hours */
346
347 hours = t % 24;
348 t /= 24; /* now in days */
349
350 days = t;
351
352 VG_(sprintf)(buf, "%02u:%02u:%02u:%02u.%03u ", days, hours, mins, s, ms);
353 }
354
355
356 /* ---------------------------------------------------------------------
357 message()
358 ------------------------------------------------------------------ */
359
360 /* A buffer for accumulating VG_(message) style output. This is
361 pretty much the same as VG_(printf)'s scheme, with two differences:
362
363 * The message buffer persists between calls, so that multiple
364 calls to VG_(message) can build up output.
365
366 * Whenever the first character on a line is emitted, the
367 ==PID== style preamble is stuffed in before it.
368 */
369 typedef
370 struct {
371 HChar buf[512+128];
372 Int buf_used;
373 Bool atLeft; /* notionally, is the next char position at the
374 leftmost column? */
375 /* Current message kind - changes from call to call */
376 VgMsgKind kind;
377 /* destination */
378 OutputSink* sink;
379 }
380 vmessage_buf_t;
381
382 static vmessage_buf_t vmessage_buf
383 = { "", 0, True, Vg_UserMsg, &VG_(log_output_sink) };
384
385
386 // Adds a single char to the buffer. We aim to have at least 128
387 // bytes free in the buffer, so that it's always possible to emit
388 // the preamble into the buffer if c happens to be the character
389 // following a \n. When the buffer gets too full, we write its
390 // contents to the logging sink.
add_to__vmessage_buf(HChar c,void * p)391 static void add_to__vmessage_buf ( HChar c, void *p )
392 {
393 HChar tmp[64];
394 vmessage_buf_t* b = (vmessage_buf_t*)p;
395
396 vg_assert(b->buf_used >= 0 && b->buf_used < sizeof(b->buf)-128);
397
398 if (UNLIKELY(b->atLeft)) {
399 // insert preamble
400 HChar ch;
401 Int i, depth;
402
403 // Print one '>' in front of the messages for each level of
404 // self-hosting being performed.
405 depth = RUNNING_ON_VALGRIND;
406 if (depth > 10)
407 depth = 10; // ?!?!
408 for (i = 0; i < depth; i++) {
409 b->buf[b->buf_used++] = '>';
410 }
411
412 if (Vg_FailMsg == b->kind) {
413 // "valgrind: " prefix.
414 b->buf[b->buf_used++] = 'v';
415 b->buf[b->buf_used++] = 'a';
416 b->buf[b->buf_used++] = 'l';
417 b->buf[b->buf_used++] = 'g';
418 b->buf[b->buf_used++] = 'r';
419 b->buf[b->buf_used++] = 'i';
420 b->buf[b->buf_used++] = 'n';
421 b->buf[b->buf_used++] = 'd';
422 b->buf[b->buf_used++] = ':';
423 b->buf[b->buf_used++] = ' ';
424 } else {
425 switch (b->kind) {
426 case Vg_UserMsg: ch = '='; break;
427 case Vg_DebugMsg: ch = '-'; break;
428 case Vg_ClientMsg: ch = '*'; break;
429 default: ch = '?'; break;
430 }
431
432 b->buf[b->buf_used++] = ch;
433 b->buf[b->buf_used++] = ch;
434
435 if (VG_(clo_time_stamp)) {
436 VG_(memset)(tmp, 0, sizeof(tmp));
437 VG_(elapsed_wallclock_time)(tmp);
438 tmp[sizeof(tmp)-1] = 0;
439 for (i = 0; tmp[i]; i++)
440 b->buf[b->buf_used++] = tmp[i];
441 }
442
443 VG_(sprintf)(tmp, "%d", VG_(getpid)());
444 tmp[sizeof(tmp)-1] = 0;
445 for (i = 0; tmp[i]; i++)
446 b->buf[b->buf_used++] = tmp[i];
447
448 b->buf[b->buf_used++] = ch;
449 b->buf[b->buf_used++] = ch;
450 b->buf[b->buf_used++] = ' ';
451 }
452
453 /* We can't possibly have stuffed 96 chars in merely as a result
454 of making the preamble (can we?) */
455 vg_assert(b->buf_used < sizeof(b->buf)-32);
456 }
457
458 b->buf[b->buf_used++] = c;
459 b->buf[b->buf_used] = 0;
460
461 if (b->buf_used >= sizeof(b->buf) - 128) {
462 send_bytes_to_logging_sink( b->sink, b->buf, b->buf_used );
463 b->buf_used = 0;
464 }
465
466 b->atLeft = c == '\n';
467 }
468
469
VG_(vmessage)470 UInt VG_(vmessage) ( VgMsgKind kind, const HChar* format, va_list vargs )
471 {
472 UInt ret;
473
474 /* Note (carefully) that the buf persists from call to call, unlike
475 with the other printf variants in earlier parts of this file. */
476 vmessage_buf_t* b = &vmessage_buf; /* shorthand for convenience */
477
478 /* We have to set this each call, so that the correct flavour
479 of preamble is emitted at each \n. */
480 b->kind = kind;
481
482 ret = VG_(debugLog_vprintf) ( add_to__vmessage_buf,
483 b, format, vargs );
484
485 /* If the message finished exactly with a \n, then flush it at this
486 point. If not, assume more bits of the same line will turn up
487 in later messages, so don't bother to flush it right now. */
488
489 if (b->atLeft && b->buf_used > 0) {
490 send_bytes_to_logging_sink( b->sink, b->buf, b->buf_used );
491 b->buf_used = 0;
492 }
493
494 return ret;
495 }
496
497 /* Send a simple single-part XML message. */
VG_(message_no_f_c)498 UInt VG_(message_no_f_c) ( VgMsgKind kind, const HChar* format, ... )
499 {
500 UInt count;
501 va_list vargs;
502 va_start(vargs,format);
503 count = VG_(vmessage) ( kind, format, vargs );
504 va_end(vargs);
505 return count;
506 }
507
508 /* Send a simple single-part message. */
VG_(message)509 UInt VG_(message) ( VgMsgKind kind, const HChar* format, ... )
510 {
511 UInt count;
512 va_list vargs;
513 va_start(vargs,format);
514 count = VG_(vmessage) ( kind, format, vargs );
515 va_end(vargs);
516 return count;
517 }
518
revert_to_stderr(void)519 static void revert_to_stderr ( void )
520 {
521 VG_(log_output_sink).fd = 2; /* stderr */
522 VG_(log_output_sink).is_socket = False;
523 }
524
525 /* VG_(message) variants with hardwired first argument. */
526
VG_(fmsg)527 UInt VG_(fmsg) ( const HChar* format, ... )
528 {
529 UInt count;
530 va_list vargs;
531 va_start(vargs,format);
532 count = VG_(vmessage) ( Vg_FailMsg, format, vargs );
533 va_end(vargs);
534 return count;
535 }
536
VG_(fmsg_bad_option)537 void VG_(fmsg_bad_option) ( HChar* opt, const HChar* format, ... )
538 {
539 va_list vargs;
540 va_start(vargs,format);
541 revert_to_stderr();
542 VG_(message) (Vg_FailMsg, "Bad option: %s\n", opt);
543 VG_(vmessage)(Vg_FailMsg, format, vargs );
544 VG_(message) (Vg_FailMsg, "Use --help for more information or consult the user manual.\n");
545 VG_(exit)(1);
546 va_end(vargs);
547 }
548
VG_(umsg)549 UInt VG_(umsg) ( const HChar* format, ... )
550 {
551 UInt count;
552 va_list vargs;
553 va_start(vargs,format);
554 count = VG_(vmessage) ( Vg_UserMsg, format, vargs );
555 va_end(vargs);
556 return count;
557 }
558
VG_(dmsg)559 UInt VG_(dmsg) ( const HChar* format, ... )
560 {
561 UInt count;
562 va_list vargs;
563 va_start(vargs,format);
564 count = VG_(vmessage) ( Vg_DebugMsg, format, vargs );
565 va_end(vargs);
566 return count;
567 }
568
569 /* Flush any output that has accumulated in vmessage_buf as a
570 result of previous calls to VG_(message) et al. */
VG_(message_flush)571 void VG_(message_flush) ( void )
572 {
573 vmessage_buf_t* b = &vmessage_buf;
574 send_bytes_to_logging_sink( b->sink, b->buf, b->buf_used );
575 b->buf_used = 0;
576 }
577
578 __attribute__((noreturn))
VG_(err_missing_prog)579 void VG_(err_missing_prog) ( void )
580 {
581 revert_to_stderr();
582 VG_(fmsg)("no program specified\n");
583 VG_(fmsg)("Use --help for more information.\n");
584 VG_(exit)(1);
585 }
586
587 __attribute__((noreturn))
VG_(err_config_error)588 void VG_(err_config_error) ( Char* msg )
589 {
590 revert_to_stderr();
591 VG_(fmsg)("Startup or configuration error:\n %s\n", msg);
592 VG_(fmsg)("Unable to start up properly. Giving up.\n");
593 VG_(exit)(1);
594 }
595
596
597 /*--------------------------------------------------------------------*/
598 /*--- end ---*/
599 /*--------------------------------------------------------------------*/
600
601