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];
248 "mov r0, #2\n\t" /* stderr */
249 "ldr r1, [%0]\n\t" /* buf */
250 "ldr r2, [%0, #4]\n\t" /* n */
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];
537 #elif defined(VGP_s390x_linux)
538 static UInt local_sys_write_stderr ( HChar* buf, Int n )
540 register Int r2 asm("2") = 2; /* file descriptor STDERR */
541 register HChar* r3 asm("3") = buf;
542 register ULong r4 asm("4") = n;
543 register ULong r2_res asm("2");
546 __asm__ __volatile__ (
556 if (__res >= (ULong)(-125))
558 return (UInt)(__res);
561 static UInt local_sys_getpid ( void )
563 register ULong r2 asm("2");
566 __asm__ __volatile__ (
573 if (__res >= (ULong)(-125))
575 return (UInt)(__res);
580 # error Unknown platform
584 /* ----- generic ----- */
586 /* strlen, so we don't need m_libc */
587 static Int local_strlen ( const HChar* str )
590 while (str[i] != 0) i++;
594 static HChar local_toupper ( HChar c )
596 if (c >= 'a' && c <= 'z')
597 return c + ('A' - 'a');
602 /* Emit buf[0 .. n-1] to stderr. Unfortunately platform-specific.
604 static void emit ( HChar* buf, Int n )
607 (void)local_sys_write_stderr(buf, n);
611 /*------------------------------------------------------------*/
612 /*--- A simple, generic, vprintf implementation. ---*/
613 /*------------------------------------------------------------*/
615 /* -----------------------------------------------
616 Distantly derived from:
618 vprintf replacement for Checker.
619 Copyright 1993, 1994, 1995 Tristan Gingold
620 Written September 1993 Tristan Gingold
621 Tristan Gingold, 8 rue Parmentier, F-91120 PALAISEAU, FRANCE
623 (Checker itself was GPL'd.)
624 ----------------------------------------------- */
627 #define VG_MSG_SIGNED 1 /* The value is signed. */
628 #define VG_MSG_ZJUSTIFY 2 /* Must justify with '0'. */
629 #define VG_MSG_LJUSTIFY 4 /* Must justify on the left. */
630 #define VG_MSG_PAREN 8 /* Parenthesize if present (for %y) */
631 #define VG_MSG_COMMA 16 /* Add commas to numbers (for %d, %u) */
632 #define VG_MSG_ALTFORMAT 32 /* Convert the value to alternate format */
634 /* Copy a string into the buffer. */
636 UInt myvprintf_str ( void(*send)(HChar,void*),
643 # define MAYBE_TOUPPER(ch) (capitalise ? local_toupper(ch) : (ch))
646 Int len = local_strlen(str);
650 for (i = 0; i < len; i++)
651 send(MAYBE_TOUPPER(str[i]), send_arg2);
657 for (i = 0; i < width; i++)
658 send(MAYBE_TOUPPER(str[i]), send_arg2);
663 if (flags & VG_MSG_LJUSTIFY) {
665 for (i = 0; i < extra; i++)
666 send(' ', send_arg2);
669 for (i = 0; i < len; i++)
670 send(MAYBE_TOUPPER(str[i]), send_arg2);
671 if (!(flags & VG_MSG_LJUSTIFY)) {
673 for (i = 0; i < extra; i++)
674 send(' ', send_arg2);
677 # undef MAYBE_TOUPPER
682 /* Copy a string into the buffer, escaping bad XML chars. */
684 UInt myvprintf_str_XML_simplistic ( void(*send)(HChar,void*),
690 Int len = local_strlen(str);
693 for (i = 0; i < len; i++) {
695 case '&': alt = "&"; break;
696 case '<': alt = "<"; break;
697 case '>': alt = ">"; break;
703 send(*alt, send_arg2);
708 send(str[i], send_arg2);
717 /* Write P into the buffer according to these args:
718 * If SIGN is true, p is a signed.
720 * If WITH_ZERO is true, '0' must be added.
721 * WIDTH is the width of the field.
724 UInt myvprintf_int64 ( void(*send)(HChar,void*),
736 HChar* digits = capitalised ? "0123456789ABCDEF" : "0123456789abcdef";
739 if (base < 2 || base > 16)
742 if ((flags & VG_MSG_SIGNED) && (Long)p < 0) {
751 if (flags & VG_MSG_COMMA && 10 == base &&
752 0 == (ind-nc) % 3 && 0 != ind)
757 buf[ind++] = digits[p % base];
765 if (width > 0 && !(flags & VG_MSG_LJUSTIFY)) {
766 for(; ind < width; ind++) {
767 /* vg_assert(ind < 39); */
772 buf[ind] = (flags & VG_MSG_ZJUSTIFY) ? '0': ' ';
776 /* Reverse copy to buffer. */
778 for (i = ind -1; i >= 0; i--) {
779 send(buf[i], send_arg2);
781 if (width > 0 && (flags & VG_MSG_LJUSTIFY)) {
782 for(; ind < width; ind++) {
784 /* Never pad with zeroes on RHS -- changes the value! */
785 send(' ', send_arg2);
792 /* A simple vprintf(). */
795 VG_(debugLog_vprintf) (
796 void(*send)(HChar,void*),
809 /* We assume that vargs has already been initialised by the
810 caller, using va_start, and that the caller will similarly
811 clean up with va_end.
814 for (i = 0; format[i] != 0; i++) {
815 if (format[i] != '%') {
816 send(format[i], send_arg2);
821 /* A '%' has been found. Ignore a trailing %. */
824 if (format[i] == '%') {
825 /* '%%' is replaced by '%'. */
826 send('%', send_arg2);
832 width = 0; /* length of the field. */
836 flags |= VG_MSG_PAREN;
840 /* If ',' or '\'' follows '%', commas will be inserted. */
841 flags |= VG_MSG_COMMA;
844 /* If '-' follows '%', justify on the left. */
845 flags |= VG_MSG_LJUSTIFY;
848 /* If '0' follows '%', pads will be inserted. */
849 flags |= VG_MSG_ZJUSTIFY;
852 /* If '#' follows '%', alternative format will be used. */
853 flags |= VG_MSG_ALTFORMAT;
856 goto parse_fieldwidth;
861 /* Compute the field length. */
862 while (format[i] >= '0' && format[i] <= '9') {
864 width += format[i++] - '0';
866 while (format[i] == 'l') {
871 // %d means print a 32-bit integer.
872 // %ld means print a word-size integer.
873 // %lld means print a 64-bit integer.
874 if (0 == n_ls) { is_long = False; }
875 else if (1 == n_ls) { is_long = ( sizeof(void*) == sizeof(Long) ); }
876 else { is_long = True; }
880 if (flags & VG_MSG_ALTFORMAT) {
885 ret += myvprintf_int64(send, send_arg2, flags, 8, width, False,
886 (ULong)(va_arg (vargs, ULong)));
888 ret += myvprintf_int64(send, send_arg2, flags, 8, width, False,
889 (ULong)(va_arg (vargs, UInt)));
892 flags |= VG_MSG_SIGNED;
894 ret += myvprintf_int64(send, send_arg2, flags, 10, width, False,
895 (ULong)(va_arg (vargs, Long)));
897 ret += myvprintf_int64(send, send_arg2, flags, 10, width, False,
898 (ULong)(va_arg (vargs, Int)));
902 ret += myvprintf_int64(send, send_arg2, flags, 10, width, False,
903 (ULong)(va_arg (vargs, ULong)));
905 ret += myvprintf_int64(send, send_arg2, flags, 10, width, False,
906 (ULong)(va_arg (vargs, UInt)));
912 ret += myvprintf_int64(send, send_arg2, flags, 16, width, True,
913 (ULong)((UWord)va_arg (vargs, void *)));
917 caps = toBool(format[i] == 'X');
918 if (flags & VG_MSG_ALTFORMAT) {
924 ret += myvprintf_int64(send, send_arg2, flags, 16, width, caps,
925 (ULong)(va_arg (vargs, ULong)));
927 ret += myvprintf_int64(send, send_arg2, flags, 16, width, caps,
928 (ULong)(va_arg (vargs, UInt)));
932 send(va_arg (vargs, int), send_arg2);
934 case 's': case 'S': { /* %s */
935 char *str = va_arg (vargs, char *);
936 if (str == (char*) 0) str = "(null)";
937 ret += myvprintf_str(send, send_arg2,
938 flags, width, str, format[i]=='S');
941 case 't': { /* %t, like %s but escaping chars for XML safety */
942 /* Note: simplistic; ignores field width and flags */
943 char *str = va_arg (vargs, char *);
944 if (str == (char*) 0) str = "(null)";
945 ret += myvprintf_str_XML_simplistic(send, send_arg2, str);
949 // case 'y': { /* %y - print symbol */
952 // Addr a = va_arg(vargs, Addr);
954 // if (flags & VG_MSG_PAREN)
956 // if (VG_(get_fnname_w_offset)(a, cp, sizeof(buf)-4)) {
957 // if (flags & VG_MSG_PAREN) {
958 // cp += VG_(strlen)(cp);
962 // ret += myvprintf_str(send, send_arg2, flags, width, buf, 0);
974 /*------------------------------------------------------------*/
975 /*--- Debuglog stuff. ---*/
976 /*------------------------------------------------------------*/
978 /* Only print messages whose stated level is less than or equal to
979 this. By default, it makes this entire subsystem silent. */
981 static Int loglevel = 0;
983 /* Module startup. */
985 void VG_(debugLog_startup) ( Int level, HChar* who )
987 if (level < 0) level = 0;
988 if (level > 10) level = 10;
990 VG_(debugLog)(1, "debuglog",
991 "DebugLog system started by %s, "
992 "level %d logging requested\n",
996 /* Get the logging threshold level, as set by the most recent call to
997 VG_(debugLog_startup), or zero if there have been no such calls so
1000 Int VG_(debugLog_getLevel) ( void )
1015 static void add_to_buf ( HChar c, void* p )
1017 printf_buf* buf = (printf_buf*)p;
1019 if (buf->n >= 100-10 /*paranoia*/ ) {
1020 emit( buf->buf, local_strlen(buf->buf) );
1022 buf->buf[buf->n] = 0;
1024 buf->buf[buf->n++] = c;
1025 buf->buf[buf->n] = 0;
1028 /* Send a logging message. Nothing is output unless 'level'
1029 is <= the current loglevel. */
1031 void VG_(debugLog) ( Int level, const HChar* modulename,
1032 const HChar* format, ... )
1035 Int indent, depth, i;
1039 if (level > loglevel)
1042 indent = 2*level - 1;
1043 if (indent < 1) indent = 1;
1047 pid = local_sys_getpid();
1049 // Print one '>' in front of the messages for each level of self-hosting
1051 depth = RUNNING_ON_VALGRIND;
1052 for (i = 0; i < depth; i++) {
1053 (void)myvprintf_str ( add_to_buf, &buf, 0, 1, ">", False );
1056 (void)myvprintf_str ( add_to_buf, &buf, 0, 2, "--", False );
1057 (void)myvprintf_int64 ( add_to_buf, &buf, 0, 10, 1, False, (ULong)pid );
1058 (void)myvprintf_str ( add_to_buf, &buf, 0, 1, ":", False );
1059 (void)myvprintf_int64 ( add_to_buf, &buf, 0, 10, 1, False, (ULong)level );
1060 (void)myvprintf_str ( add_to_buf, &buf, 0, 1, ":", False );
1061 (void)myvprintf_str ( add_to_buf, &buf, 0, 8, (HChar*)modulename, False );
1062 (void)myvprintf_str ( add_to_buf, &buf, 0, indent, "", False );
1064 va_start(vargs,format);
1066 (void) VG_(debugLog_vprintf) ( add_to_buf, &buf, format, vargs );
1069 emit( buf.buf, local_strlen(buf.buf) );
1077 /*--------------------------------------------------------------------*/
1078 /*--- end m_debuglog.c ---*/
1079 /*--------------------------------------------------------------------*/