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