m_libcprint.c revision 72faf10172c04674ac1e31cf4f7e57be241da7da
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 */
55OutputSink VG_(log_output_sink) = {  2, False }; /* 2 = stderr */
56OutputSink VG_(xml_output_sink) = { -1, False }; /* disabled */
57
58/* Do the low-level send of a message to the logging sink. */
59static
60void 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
89typedef
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.
99static 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
112static 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
123static 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
139UInt VG_(vprintf) ( const HChar *format, va_list vargs )
140{
141   return vprintf_WRK( &VG_(log_output_sink), format, vargs );
142}
143
144UInt 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
154UInt VG_(vprintf_xml) ( const HChar *format, va_list vargs )
155{
156   return vprintf_WRK( &VG_(xml_output_sink), format, vargs );
157}
158
159UInt 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
176static void add_to__sprintf_buf ( HChar c, void *p )
177{
178   HChar** b = p;
179   *(*b)++ = c;
180}
181
182UInt 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
196UInt 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
209typedef
210   struct {
211      HChar* buf;
212      Int    buf_size;
213      Int    buf_used;
214   }
215   snprintf_buf_t;
216
217static 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
229UInt 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
242UInt 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
255void 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'.
270void 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
326void 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*/
363typedef
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
376static 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.
385static 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
469UInt 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. */
497UInt 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
507static 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
515UInt 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
525void 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
537UInt 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
547UInt 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. */
559void 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))
567void 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))
576void 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