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