• 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-2012 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       // Do not print such '>' if sim hint "no-inner-prefix" given
400       // (useful to run regression tests in an outer/inner setup
401       // and avoid the diff failing due to these unexpected '>').
402       depth = RUNNING_ON_VALGRIND;
403       if (depth > 0 && !VG_(strstr)(VG_(clo_sim_hints), "no-inner-prefix")) {
404          if (depth > 10)
405             depth = 10; // ?!?!
406          for (i = 0; i < depth; i++) {
407             b->buf[b->buf_used++] = '>';
408          }
409       }
410 
411       if (Vg_FailMsg == b->kind) {
412          // "valgrind: " prefix.
413          b->buf[b->buf_used++] = 'v';
414          b->buf[b->buf_used++] = 'a';
415          b->buf[b->buf_used++] = 'l';
416          b->buf[b->buf_used++] = 'g';
417          b->buf[b->buf_used++] = 'r';
418          b->buf[b->buf_used++] = 'i';
419          b->buf[b->buf_used++] = 'n';
420          b->buf[b->buf_used++] = 'd';
421          b->buf[b->buf_used++] = ':';
422          b->buf[b->buf_used++] = ' ';
423       } else {
424          switch (b->kind) {
425             case Vg_UserMsg:       ch = '='; break;
426             case Vg_DebugMsg:      ch = '-'; break;
427             case Vg_ClientMsg:     ch = '*'; break;
428             default:               ch = '?'; break;
429          }
430 
431          b->buf[b->buf_used++] = ch;
432          b->buf[b->buf_used++] = ch;
433 
434          if (VG_(clo_time_stamp)) {
435             VG_(memset)(tmp, 0, sizeof(tmp));
436             VG_(elapsed_wallclock_time)(tmp);
437             tmp[sizeof(tmp)-1] = 0;
438             for (i = 0; tmp[i]; i++)
439                b->buf[b->buf_used++] = tmp[i];
440          }
441 
442          VG_(sprintf)(tmp, "%d", VG_(getpid)());
443          tmp[sizeof(tmp)-1] = 0;
444          for (i = 0; tmp[i]; i++)
445             b->buf[b->buf_used++] = tmp[i];
446 
447          b->buf[b->buf_used++] = ch;
448          b->buf[b->buf_used++] = ch;
449          b->buf[b->buf_used++] = ' ';
450       }
451 
452       /* We can't possibly have stuffed 96 chars in merely as a result
453          of making the preamble (can we?) */
454       vg_assert(b->buf_used < sizeof(b->buf)-32);
455    }
456 
457    b->buf[b->buf_used++] = c;
458    b->buf[b->buf_used]   = 0;
459 
460    if (b->buf_used >= sizeof(b->buf) - 128) {
461       send_bytes_to_logging_sink( b->sink, b->buf, b->buf_used );
462       b->buf_used = 0;
463    }
464 
465    b->atLeft = c == '\n';
466 }
467 
468 
VG_(vmessage)469 UInt VG_(vmessage) ( VgMsgKind kind, const HChar* format, va_list vargs )
470 {
471    UInt ret;
472 
473    /* Note (carefully) that the buf persists from call to call, unlike
474       with the other printf variants in earlier parts of this file. */
475    vmessage_buf_t* b = &vmessage_buf; /* shorthand for convenience */
476 
477    /* We have to set this each call, so that the correct flavour
478       of preamble is emitted at each \n. */
479    b->kind = kind;
480 
481    ret = VG_(debugLog_vprintf) ( add_to__vmessage_buf,
482                                  b, format, vargs );
483 
484    /* If the message finished exactly with a \n, then flush it at this
485       point.  If not, assume more bits of the same line will turn up
486       in later messages, so don't bother to flush it right now. */
487 
488    if (b->atLeft && b->buf_used > 0) {
489       send_bytes_to_logging_sink( b->sink, b->buf, b->buf_used );
490       b->buf_used = 0;
491    }
492 
493    return ret;
494 }
495 
496 /* Send a simple single-part message. */
VG_(message)497 UInt VG_(message) ( VgMsgKind kind, const HChar* format, ... )
498 {
499    UInt count;
500    va_list vargs;
501    va_start(vargs,format);
502    count = VG_(vmessage) ( kind, format, vargs );
503    va_end(vargs);
504    return count;
505 }
506 
revert_to_stderr(void)507 static void revert_to_stderr ( void )
508 {
509    VG_(log_output_sink).fd = 2; /* stderr */
510    VG_(log_output_sink).is_socket = False;
511 }
512 
513 /* VG_(message) variants with hardwired first argument. */
514 
VG_(fmsg)515 UInt VG_(fmsg) ( const HChar* format, ... )
516 {
517    UInt count;
518    va_list vargs;
519    va_start(vargs,format);
520    count = VG_(vmessage) ( Vg_FailMsg, format, vargs );
521    va_end(vargs);
522    return count;
523 }
524 
VG_(fmsg_bad_option)525 void VG_(fmsg_bad_option) ( HChar* opt, const HChar* format, ... )
526 {
527    va_list vargs;
528    va_start(vargs,format);
529    revert_to_stderr();
530    VG_(message) (Vg_FailMsg, "Bad option: %s\n", opt);
531    VG_(vmessage)(Vg_FailMsg, format, vargs );
532    VG_(message) (Vg_FailMsg, "Use --help for more information or consult the user manual.\n");
533    VG_(exit)(1);
534    va_end(vargs);
535 }
536 
VG_(umsg)537 UInt VG_(umsg) ( const HChar* format, ... )
538 {
539    UInt count;
540    va_list vargs;
541    va_start(vargs,format);
542    count = VG_(vmessage) ( Vg_UserMsg, format, vargs );
543    va_end(vargs);
544    return count;
545 }
546 
VG_(dmsg)547 UInt VG_(dmsg) ( const HChar* format, ... )
548 {
549    UInt count;
550    va_list vargs;
551    va_start(vargs,format);
552    count = VG_(vmessage) ( Vg_DebugMsg, format, vargs );
553    va_end(vargs);
554    return count;
555 }
556 
557 /* Flush any output that has accumulated in vmessage_buf as a
558    result of previous calls to VG_(message) et al. */
VG_(message_flush)559 void VG_(message_flush) ( void )
560 {
561    vmessage_buf_t* b = &vmessage_buf;
562    send_bytes_to_logging_sink( b->sink, b->buf, b->buf_used );
563    b->buf_used = 0;
564 }
565 
566 __attribute__((noreturn))
VG_(err_missing_prog)567 void VG_(err_missing_prog) ( void  )
568 {
569    revert_to_stderr();
570    VG_(fmsg)("no program specified\n");
571    VG_(fmsg)("Use --help for more information.\n");
572    VG_(exit)(1);
573 }
574 
575 __attribute__((noreturn))
VG_(err_config_error)576 void VG_(err_config_error) ( Char* format, ... )
577 {
578    va_list vargs;
579    va_start(vargs,format);
580    revert_to_stderr();
581    VG_(message) (Vg_FailMsg, "Startup or configuration error:\n   ");
582    VG_(vmessage)(Vg_FailMsg, format, vargs );
583    VG_(message) (Vg_FailMsg, "Unable to start up properly.  Giving up.\n");
584    VG_(exit)(1);
585    va_end(vargs);
586 }
587 
588 
589 /*--------------------------------------------------------------------*/
590 /*--- end                                                          ---*/
591 /*--------------------------------------------------------------------*/
592 
593