2 /*--------------------------------------------------------------------*/
3 /*--- Debug (not-for-user) logging; also vprintf. m_debuglog.c ---*/
4 /*--------------------------------------------------------------------*/
7 This file is part of Valgrind, a dynamic binary instrumentation
10 Copyright (C) 2000-2010 Julian Seward
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.
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.
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
28 The GNU General Public License is contained in the file COPYING.
32 /* Performs low-level debug logging that can safely run immediately
33 after startup. To minimise the dependencies on any other parts of
34 the system, the only place the debug output may go is file
35 descriptor 2 (stderr).
37 /* This is the first-initialised module in the entire system!
38 Therefore it is CRITICAL that it does not depend on any other code
39 running first. Hence only the following very limited includes. We
40 cannot depend (directly or indirectly) on any dynamic memory
41 allocation facilities, nor on the m_libc facilities, since the
42 latter depend on this module. DO NOT MESS WITH THESE INCLUDES
43 UNLESS YOU ARE 100% CERTAIN YOU UNDERSTAND THE CONSEQUENCES.
46 /* This module is also notable because it is linked into both
49 /* IMPORTANT: on Darwin it is essential to use the _nocancel versions
50 of syscalls rather than the vanilla version, if a _nocancel version
51 is available. See docs/internals/Darwin-notes.txt for the reason
54 #include "pub_core_basics.h" /* basic types */
55 #include "pub_core_vkiscnums.h" /* for syscall numbers */
56 #include "pub_core_debuglog.h" /* our own iface */
57 #include "valgrind.h" /* for RUNNING_ON_VALGRIND */
60 #include <l4/sys/utcb.h>
64 /*------------------------------------------------------------*/
65 /*--- Stuff to make us completely independent. ---*/
66 /*------------------------------------------------------------*/
68 /* ----- Platform-specifics ----- */
70 #if defined(VGP_x86_linux)
72 static UInt local_sys_write_stderr ( HChar* buf, Int n )
74 volatile Int block[2];
78 "pushl %%ebx\n" /* ebx is callee-save */
79 "movl %0, %%ebx\n" /* ebx = &block */
80 "pushl %%ebx\n" /* save &block */
81 "movl 0(%%ebx), %%ecx\n" /* %ecx = buf */
82 "movl 4(%%ebx), %%edx\n" /* %edx = n */
83 "movl $"VG_STRINGIFY(__NR_write)", %%eax\n" /* %eax = __NR_write */
84 "movl $2, %%ebx\n" /* %ebx = stderr */
85 "int $0x80\n" /* write(stderr, buf, n) */
86 "popl %%ebx\n" /* reestablish &block */
87 "movl %%eax, 0(%%ebx)\n" /* block[0] = result */
88 "popl %%ebx\n" /* restore ebx */
91 : /*trash*/ "eax", "edi", "ecx", "edx", "memory", "cc"
98 static UInt local_sys_getpid ( void )
102 "movl $"VG_STRINGIFY(__NR_getpid)", %%eax\n" /* %eax = __NR_getpid */
103 "int $0x80\n" /* getpid() */
104 "movl %%eax, %0\n" /* set __res = eax */
111 #elif defined(VGP_amd64_linux)
112 __attribute__((noinline))
113 static UInt local_sys_write_stderr ( HChar* buf, Int n )
115 volatile Long block[2];
116 block[0] = (Long)buf;
119 "subq $256, %%rsp\n" /* don't trash the stack redzone */
120 "pushq %%r15\n" /* r15 is callee-save */
121 "movq %0, %%r15\n" /* r15 = &block */
122 "pushq %%r15\n" /* save &block */
123 "movq $"VG_STRINGIFY(__NR_write)", %%rax\n" /* rax = __NR_write */
124 "movq $2, %%rdi\n" /* rdi = stderr */
125 "movq 0(%%r15), %%rsi\n" /* rsi = buf */
126 "movq 8(%%r15), %%rdx\n" /* rdx = n */
127 "syscall\n" /* write(stderr, buf, n) */
128 "popq %%r15\n" /* reestablish &block */
129 "movq %%rax, 0(%%r15)\n" /* block[0] = result */
130 "popq %%r15\n" /* restore r15 */
131 "addq $256, %%rsp\n" /* restore stack ptr */
134 : /*trash*/ "rax", "rdi", "rsi", "rdx", "memory", "cc"
138 return (UInt)block[0];
141 static UInt local_sys_getpid ( void )
145 "movq $"VG_STRINGIFY(__NR_getpid)", %%rax\n" /* %rax = __NR_getpid */
146 "syscall\n" /* getpid() */
147 "movl %%eax, %0\n" /* set __res = %eax */
154 #elif defined(VGP_ppc32_linux)
156 static UInt local_sys_write_stderr ( HChar* buf, Int n )
158 volatile Int block[2];
163 "mr 5,%0\n\t" /* r5 = &block[0] */
164 "stw 5,0(1)\n\t" /* stash on stack */
165 "li 0,"VG_STRINGIFY(__NR_write)"\n\t" /* set %r0 = __NR_write */
166 "li 3,2\n\t" /* set %r3 = stderr */
167 "lwz 4,0(5)\n\t" /* set %r4 = buf */
168 "lwz 5,4(5)\n\t" /* set %r5 = n */
169 "sc\n\t" /* write(stderr, buf, n) */
172 "stw 3,0(5)\n" /* block[0] = result */
175 : "cc","memory","cr0","ctr",
176 "r0","r2","r3","r4","r5","r6","r7","r8","r9","r10","r11","r12"
180 return (UInt)block[0];
183 static UInt local_sys_getpid ( void )
185 register UInt __res __asm__ ("r3");
191 : "cc","memory","cr0","ctr",
192 "r0","r2","r4","r5","r6","r7","r8","r9","r10","r11","r12"
197 #elif defined(VGP_ppc64_linux)
199 static UInt local_sys_write_stderr ( HChar* buf, Int n )
201 volatile Long block[2];
202 block[0] = (Long)buf;
206 "mr 5,%0\n\t" /* r5 = &block[0] */
207 "std 5,0(1)\n\t" /* stash on stack */
208 "li 0,"VG_STRINGIFY(__NR_write)"\n\t" /* %r0 = __NR_write */
209 "li 3,2\n\t" /* set %r3 = stderr */
210 "ld 4,0(5)\n\t" /* set %r4 = buf */
211 "ld 5,8(5)\n\t" /* set %r5 = n */
212 "sc\n\t" /* write(stderr, buf, n) */
215 "std 3,0(5)\n" /* block[0] = result */
218 : "cc","memory","cr0","ctr",
219 "r0","r2","r3","r4","r5","r6","r7","r8","r9","r10","r11","r12"
223 return (UInt)(Int)block[0];
226 static UInt local_sys_getpid ( void )
228 register ULong __res __asm__ ("r3");
234 : "cc","memory","cr0","ctr",
235 "r0","r2","r4","r5","r6","r7","r8","r9","r10","r11","r12"
240 #elif defined(VGP_arm_linux)
242 static UInt local_sys_write_stderr ( HChar* buf, Int n )
244 volatile Int block[2];
250 "ldr r2, [%0, #4]\n\t"
251 "mov r7, #"VG_STRINGIFY(__NR_write)"\n\t"
252 "svc 0x0\n" /* write() */
256 : "r0","r1","r2","r7"
260 return (UInt)block[0];
263 static UInt local_sys_getpid ( void )
267 "mov r7, #"VG_STRINGIFY(__NR_getpid)"\n"
268 "svc 0x0\n" /* getpid() */
276 #elif defined(VGP_ppc32_aix5)
278 static UInt local_sys_write_stderr ( HChar* buf, Int n )
280 /* For some reason gcc-3.3.2 doesn't preserve r31 across the asm
281 even though we state it to be trashed. So use r27 instead. */
282 volatile UInt block[3];
283 block[0] = (UInt)buf;
285 block[2] = __NR_write;
286 __asm__ __volatile__ (
287 "mr 28,%0\n\t" /* establish base ptr */
288 "mr 27,2\n\t" /* save r2 in r27 */
289 "mflr 30\n\t" /* save lr in r30 */
291 "lwz 2,8(28)\n\t" /* set %r2 = __NR_write */
292 "li 3,2\n\t" /* set %r3 = stderr */
293 "lwz 4,0(28)\n\t" /* set %r4 = buf */
294 "lwz 5,4(28)\n\t" /* set %r5 = n */
297 ".long 0x48000005\n\t" /* bl .+4 */
301 "sc\n\t" /* write() */
303 "stw 3,0(28)\n\t" /* result */
304 "stw 4,4(28)\n\t" /* error? */
306 "mr 2,27\n\t" /* restore r2 */
307 "mtlr 30" /* restore lr */
310 : /*in*/ "b" (&block[0])
312 /*temps*/ "r31","r30","r29","r28","r27",
313 /*args*/ "r3","r4","r5","r6","r7","r8","r9","r10",
314 /*paranoia*/ "memory","cc","r0","r1","r11","r12","r13",
315 "xer","ctr","cr0","cr1","cr2","cr3",
316 "cr4","cr5","cr6","cr7"
324 static UInt local_sys_getpid ( void )
326 /* For some reason gcc-3.3.2 doesn't preserve r31 across the asm
327 even though we state it to be trashed. So use r27 instead. */
328 volatile UInt block[1];
329 block[0] = __NR_getpid;
330 __asm__ __volatile__ (
331 "mr 28,%0\n\t" /* establish base ptr */
332 "mr 27,2\n\t" /* save r2 in r27 */
333 "mflr 30\n\t" /* save lr in r30 */
335 "lwz 2,0(28)\n\t" /* set %r2 = __NR_getpid */
338 ".long 0x48000005\n\t" /* bl .+4 */
342 "sc\n\t" /* getpid() */
344 "stw 3,0(28)\n\t" /* result -> block[0] */
346 "mr 2,27\n\t" /* restore r2 */
347 "mtlr 30" /* restore lr */
350 : /*in*/ "b" (&block[0])
352 /*temps*/ "r31","r30","r29","r28","r27",
353 /*args*/ "r3","r4","r5","r6","r7","r8","r9","r10",
354 /*paranoia*/ "memory","cc","r0","r1","r11","r12","r13",
355 "xer","ctr","cr0","cr1","cr2","cr3",
356 "cr4","cr5","cr6","cr7"
361 #elif defined(VGP_ppc64_aix5)
363 static UInt local_sys_write_stderr ( HChar* buf, Int n )
365 volatile ULong block[3];
366 block[0] = (ULong)buf;
368 block[2] = (ULong)__NR_write;
369 __asm__ __volatile__ (
370 "mr 28,%0\n\t" /* establish base ptr */
371 "mr 27,2\n\t" /* save r2 in r27 */
372 "mflr 30\n\t" /* save lr in r30 */
374 "ld 2,16(28)\n\t" /* set %r2 = __NR_write */
375 "li 3,2\n\t" /* set %r3 = stderr */
376 "ld 4,0(28)\n\t" /* set %r4 = buf */
377 "ld 5,8(28)\n\t" /* set %r5 = n */
380 ".long 0x48000005\n\t" /* bl .+4 */
384 "sc\n\t" /* write() */
386 "std 3,0(28)\n\t" /* result */
387 "std 4,8(28)\n\t" /* error? */
389 "mr 2,27\n\t" /* restore r2 */
390 "mtlr 30" /* restore lr */
393 : /*in*/ "b" (&block[0])
395 /*temps*/ "r31","r30","r29","r28","r27",
396 /*args*/ "r3","r4","r5","r6","r7","r8","r9","r10",
397 /*paranoia*/ "memory","cc","r0","r1","r11","r12","r13",
398 "xer","ctr","cr0","cr1","cr2","cr3",
399 "cr4","cr5","cr6","cr7"
404 return (UInt)block[0];
407 static UInt local_sys_getpid ( void )
409 volatile ULong block[1];
410 block[0] = __NR_getpid;
411 __asm__ __volatile__ (
412 "mr 28,%0\n\t" /* establish base ptr */
413 "mr 27,2\n\t" /* save r2 in r27 */
414 "mflr 30\n\t" /* save lr in r30 */
416 "ld 2,0(28)\n\t" /* set %r2 = __NR_getpid */
419 ".long 0x48000005\n\t" /* bl .+4 */
423 "sc\n\t" /* getpid() */
425 "std 3,0(28)\n\t" /* result -> block[0] */
427 "mr 2,27\n\t" /* restore r2 */
428 "mtlr 30" /* restore lr */
431 : /*in*/ "b" (&block[0])
433 /*temps*/ "r31","r30","r29","r28","r27",
434 /*args*/ "r3","r4","r5","r6","r7","r8","r9","r10",
435 /*paranoia*/ "memory","cc","r0","r1","r11","r12","r13",
436 "xer","ctr","cr0","cr1","cr2","cr3",
437 "cr4","cr5","cr6","cr7"
439 return (UInt)block[0];
442 #elif defined(VGP_x86_darwin)
444 /* We would use VG_DARWIN_SYSNO_TO_KERNEL instead of VG_DARWIN_SYSNO_INDEX
445 except that the former has a C ternary ?: operator which isn't valid in
446 asm code. Both macros give the same results for Unix-class syscalls (which
447 these all are, as identified by the use of 'int 0x80'). */
448 __attribute__((noinline))
449 static UInt local_sys_write_stderr ( HChar* buf, Int n )
453 "movl %2, %%eax\n" /* push n */
455 "movl %1, %%eax\n" /* push buf */
457 "movl $2, %%eax\n" /* push stderr */
459 "movl $"VG_STRINGIFY(VG_DARWIN_SYSNO_INDEX(__NR_write_nocancel))
461 "pushl %%eax\n" /* push fake return address */
462 "int $0x80\n" /* write(stderr, buf, n) */
463 "jnc 1f\n" /* jump if no error */
464 "movl $-1, %%eax\n" /* return -1 if error */
466 "movl %%eax, %0\n" /* __res = eax */
467 "addl $16, %%esp\n" /* pop x4 */
475 static UInt local_sys_getpid ( void )
479 "movl $"VG_STRINGIFY(VG_DARWIN_SYSNO_INDEX(__NR_getpid))", %%eax\n"
480 "int $0x80\n" /* getpid() */
481 "movl %%eax, %0\n" /* set __res = eax */
488 #elif defined(VGP_amd64_darwin)
490 __attribute__((noinline))
491 static UInt local_sys_write_stderr ( HChar* buf, Int n )
495 "movq $2, %%rdi\n" /* push stderr */
496 "movq %1, %%rsi\n" /* push buf */
497 "movl %2, %%edx\n" /* push n */
498 "movl $"VG_STRINGIFY(VG_DARWIN_SYSNO_FOR_KERNEL(__NR_write_nocancel))
500 "syscall\n" /* write(stderr, buf, n) */
501 "jnc 1f\n" /* jump if no error */
502 "movq $-1, %%rax\n" /* return -1 if error */
504 "movl %%eax, %0\n" /* __res = eax */
507 : "rdi", "rsi", "rdx", "rcx", "rax", "cc" );
511 static UInt local_sys_getpid ( void )
515 "movl $"VG_STRINGIFY(VG_DARWIN_SYSNO_FOR_KERNEL(__NR_getpid))", %%eax\n"
516 "syscall\n" /* getpid() */
517 "movl %%eax, %0\n" /* set __res = eax */
520 : "rax", "rcx", "cc" );
524 #elif defined(VGP_x86_l4re)
526 static UInt local_sys_write_stderr ( HChar* buf, Int n )
532 static UInt local_sys_getpid ( void )
534 return (UInt)l4_utcb_tcr()->user[2];
538 # error Unknown platform
542 /* ----- generic ----- */
544 /* strlen, so we don't need m_libc */
545 static Int local_strlen ( const HChar* str )
548 while (str[i] != 0) i++;
552 static HChar local_toupper ( HChar c )
554 if (c >= 'a' && c <= 'z')
555 return c + ('A' - 'a');
560 /* Emit buf[0 .. n-1] to stderr. Unfortunately platform-specific.
562 static void emit ( HChar* buf, Int n )
565 (void)local_sys_write_stderr(buf, n);
569 /*------------------------------------------------------------*/
570 /*--- A simple, generic, vprintf implementation. ---*/
571 /*------------------------------------------------------------*/
573 /* -----------------------------------------------
574 Distantly derived from:
576 vprintf replacement for Checker.
577 Copyright 1993, 1994, 1995 Tristan Gingold
578 Written September 1993 Tristan Gingold
579 Tristan Gingold, 8 rue Parmentier, F-91120 PALAISEAU, FRANCE
581 (Checker itself was GPL'd.)
582 ----------------------------------------------- */
585 #define VG_MSG_SIGNED 1 /* The value is signed. */
586 #define VG_MSG_ZJUSTIFY 2 /* Must justify with '0'. */
587 #define VG_MSG_LJUSTIFY 4 /* Must justify on the left. */
588 #define VG_MSG_PAREN 8 /* Parenthesize if present (for %y) */
589 #define VG_MSG_COMMA 16 /* Add commas to numbers (for %d, %u) */
590 #define VG_MSG_ALTFORMAT 32 /* Convert the value to alternate format */
592 /* Copy a string into the buffer. */
594 UInt myvprintf_str ( void(*send)(HChar,void*),
601 # define MAYBE_TOUPPER(ch) (capitalise ? local_toupper(ch) : (ch))
604 Int len = local_strlen(str);
608 for (i = 0; i < len; i++)
609 send(MAYBE_TOUPPER(str[i]), send_arg2);
615 for (i = 0; i < width; i++)
616 send(MAYBE_TOUPPER(str[i]), send_arg2);
621 if (flags & VG_MSG_LJUSTIFY) {
623 for (i = 0; i < extra; i++)
624 send(' ', send_arg2);
627 for (i = 0; i < len; i++)
628 send(MAYBE_TOUPPER(str[i]), send_arg2);
629 if (!(flags & VG_MSG_LJUSTIFY)) {
631 for (i = 0; i < extra; i++)
632 send(' ', send_arg2);
635 # undef MAYBE_TOUPPER
640 /* Copy a string into the buffer, escaping bad XML chars. */
642 UInt myvprintf_str_XML_simplistic ( void(*send)(HChar,void*),
648 Int len = local_strlen(str);
651 for (i = 0; i < len; i++) {
653 case '&': alt = "&"; break;
654 case '<': alt = "<"; break;
655 case '>': alt = ">"; break;
661 send(*alt, send_arg2);
666 send(str[i], send_arg2);
675 /* Write P into the buffer according to these args:
676 * If SIGN is true, p is a signed.
678 * If WITH_ZERO is true, '0' must be added.
679 * WIDTH is the width of the field.
682 UInt myvprintf_int64 ( void(*send)(HChar,void*),
694 HChar* digits = capitalised ? "0123456789ABCDEF" : "0123456789abcdef";
697 if (base < 2 || base > 16)
700 if ((flags & VG_MSG_SIGNED) && (Long)p < 0) {
709 if (flags & VG_MSG_COMMA && 10 == base &&
710 0 == (ind-nc) % 3 && 0 != ind)
715 buf[ind++] = digits[p % base];
723 if (width > 0 && !(flags & VG_MSG_LJUSTIFY)) {
724 for(; ind < width; ind++) {
725 /* vg_assert(ind < 39); */
730 buf[ind] = (flags & VG_MSG_ZJUSTIFY) ? '0': ' ';
734 /* Reverse copy to buffer. */
736 for (i = ind -1; i >= 0; i--) {
737 send(buf[i], send_arg2);
739 if (width > 0 && (flags & VG_MSG_LJUSTIFY)) {
740 for(; ind < width; ind++) {
742 /* Never pad with zeroes on RHS -- changes the value! */
743 send(' ', send_arg2);
750 /* A simple vprintf(). */
753 VG_(debugLog_vprintf) (
754 void(*send)(HChar,void*),
767 /* We assume that vargs has already been initialised by the
768 caller, using va_start, and that the caller will similarly
769 clean up with va_end.
772 for (i = 0; format[i] != 0; i++) {
773 if (format[i] != '%') {
774 send(format[i], send_arg2);
779 /* A '%' has been found. Ignore a trailing %. */
782 if (format[i] == '%') {
783 /* '%%' is replaced by '%'. */
784 send('%', send_arg2);
790 width = 0; /* length of the field. */
794 flags |= VG_MSG_PAREN;
798 /* If ',' or '\'' follows '%', commas will be inserted. */
799 flags |= VG_MSG_COMMA;
802 /* If '-' follows '%', justify on the left. */
803 flags |= VG_MSG_LJUSTIFY;
806 /* If '0' follows '%', pads will be inserted. */
807 flags |= VG_MSG_ZJUSTIFY;
810 /* If '#' follows '%', alternative format will be used. */
811 flags |= VG_MSG_ALTFORMAT;
814 goto parse_fieldwidth;
819 /* Compute the field length. */
820 while (format[i] >= '0' && format[i] <= '9') {
822 width += format[i++] - '0';
824 while (format[i] == 'l') {
829 // %d means print a 32-bit integer.
830 // %ld means print a word-size integer.
831 // %lld means print a 64-bit integer.
832 if (0 == n_ls) { is_long = False; }
833 else if (1 == n_ls) { is_long = ( sizeof(void*) == sizeof(Long) ); }
834 else { is_long = True; }
838 if (flags & VG_MSG_ALTFORMAT) {
843 ret += myvprintf_int64(send, send_arg2, flags, 8, width, False,
844 (ULong)(va_arg (vargs, ULong)));
846 ret += myvprintf_int64(send, send_arg2, flags, 8, width, False,
847 (ULong)(va_arg (vargs, UInt)));
850 flags |= VG_MSG_SIGNED;
852 ret += myvprintf_int64(send, send_arg2, flags, 10, width, False,
853 (ULong)(va_arg (vargs, Long)));
855 ret += myvprintf_int64(send, send_arg2, flags, 10, width, False,
856 (ULong)(va_arg (vargs, Int)));
860 ret += myvprintf_int64(send, send_arg2, flags, 10, width, False,
861 (ULong)(va_arg (vargs, ULong)));
863 ret += myvprintf_int64(send, send_arg2, flags, 10, width, False,
864 (ULong)(va_arg (vargs, UInt)));
870 ret += myvprintf_int64(send, send_arg2, flags, 16, width, True,
871 (ULong)((UWord)va_arg (vargs, void *)));
875 caps = toBool(format[i] == 'X');
876 if (flags & VG_MSG_ALTFORMAT) {
882 ret += myvprintf_int64(send, send_arg2, flags, 16, width, caps,
883 (ULong)(va_arg (vargs, ULong)));
885 ret += myvprintf_int64(send, send_arg2, flags, 16, width, caps,
886 (ULong)(va_arg (vargs, UInt)));
890 send(va_arg (vargs, int), send_arg2);
892 case 's': case 'S': { /* %s */
893 char *str = va_arg (vargs, char *);
894 if (str == (char*) 0) str = "(null)";
895 ret += myvprintf_str(send, send_arg2,
896 flags, width, str, format[i]=='S');
899 case 't': { /* %t, like %s but escaping chars for XML safety */
900 /* Note: simplistic; ignores field width and flags */
901 char *str = va_arg (vargs, char *);
902 if (str == (char*) 0) str = "(null)";
903 ret += myvprintf_str_XML_simplistic(send, send_arg2, str);
907 // case 'y': { /* %y - print symbol */
910 // Addr a = va_arg(vargs, Addr);
912 // if (flags & VG_MSG_PAREN)
914 // if (VG_(get_fnname_w_offset)(a, cp, sizeof(buf)-4)) {
915 // if (flags & VG_MSG_PAREN) {
916 // cp += VG_(strlen)(cp);
920 // ret += myvprintf_str(send, send_arg2, flags, width, buf, 0);
932 /*------------------------------------------------------------*/
933 /*--- Debuglog stuff. ---*/
934 /*------------------------------------------------------------*/
936 /* Only print messages whose stated level is less than or equal to
937 this. By default, it makes this entire subsystem silent. */
939 static Int loglevel = 0;
941 /* Module startup. */
943 void VG_(debugLog_startup) ( Int level, HChar* who )
945 if (level < 0) level = 0;
946 if (level > 10) level = 10;
948 VG_(debugLog)(1, "debuglog",
949 "DebugLog system started by %s, "
950 "level %d logging requested\n",
954 /* Get the logging threshold level, as set by the most recent call to
955 VG_(debugLog_startup), or zero if there have been no such calls so
958 Int VG_(debugLog_getLevel) ( void )
973 static void add_to_buf ( HChar c, void* p )
975 printf_buf* buf = (printf_buf*)p;
977 if (buf->n >= 100-10 /*paranoia*/ ) {
978 emit( buf->buf, local_strlen(buf->buf) );
980 buf->buf[buf->n] = 0;
982 buf->buf[buf->n++] = c;
983 buf->buf[buf->n] = 0;
986 /* Send a logging message. Nothing is output unless 'level'
987 is <= the current loglevel. */
989 void VG_(debugLog) ( Int level, const HChar* modulename,
990 const HChar* format, ... )
993 Int indent, depth, i;
997 if (level > loglevel)
1000 indent = 2*level - 1;
1001 if (indent < 1) indent = 1;
1005 pid = local_sys_getpid();
1007 // Print one '>' in front of the messages for each level of self-hosting
1009 depth = RUNNING_ON_VALGRIND;
1010 for (i = 0; i < depth; i++) {
1011 (void)myvprintf_str ( add_to_buf, &buf, 0, 1, ">", False );
1014 (void)myvprintf_str ( add_to_buf, &buf, 0, 2, "--", False );
1015 (void)myvprintf_int64 ( add_to_buf, &buf, 0, 10, 1, False, (ULong)pid );
1016 (void)myvprintf_str ( add_to_buf, &buf, 0, 1, ":", False );
1017 (void)myvprintf_int64 ( add_to_buf, &buf, 0, 10, 1, False, (ULong)level );
1018 (void)myvprintf_str ( add_to_buf, &buf, 0, 1, ":", False );
1019 (void)myvprintf_str ( add_to_buf, &buf, 0, 8, (HChar*)modulename, False );
1020 (void)myvprintf_str ( add_to_buf, &buf, 0, indent, "", False );
1022 va_start(vargs,format);
1024 ret = VG_(debugLog_vprintf) ( add_to_buf, &buf, format, vargs );
1027 emit( buf.buf, local_strlen(buf.buf) );
1035 /*--------------------------------------------------------------------*/
1036 /*--- end m_debuglog.c ---*/
1037 /*--------------------------------------------------------------------*/