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