• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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