1 /* -*- mode: C; c-basic-offset: 3; -*- */
3 /*--------------------------------------------------------------------*/
4 /*--- Debug (not-for-user) logging; also vprintf. m_debuglog.c ---*/
5 /*--------------------------------------------------------------------*/
8 This file is part of Valgrind, a dynamic binary instrumentation
11 Copyright (C) 2000-2013 Julian Seward
14 This program is free software; you can redistribute it and/or
15 modify it under the terms of the GNU General Public License as
16 published by the Free Software Foundation; either version 2 of the
17 License, or (at your option) any later version.
19 This program is distributed in the hope that it will be useful, but
20 WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 General Public License for more details.
24 You should have received a copy of the GNU General Public License
25 along with this program; if not, write to the Free Software
26 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
29 The GNU General Public License is contained in the file COPYING.
33 /* Performs low-level debug logging that can safely run immediately
34 after startup. To minimise the dependencies on any other parts of
35 the system, the only place the debug output may go is file
36 descriptor 2 (stderr).
38 /* This is the first-initialised module in the entire system!
39 Therefore it is CRITICAL that it does not depend on any other code
40 running first. Hence only the following very limited includes. We
41 cannot depend (directly or indirectly) on any dynamic memory
42 allocation facilities, nor on the m_libc facilities, since the
43 latter depend on this module. DO NOT MESS WITH THESE INCLUDES
44 UNLESS YOU ARE 100% CERTAIN YOU UNDERSTAND THE CONSEQUENCES.
47 /* This module is also notable because it is linked into both
50 /* IMPORTANT: on Darwin it is essential to use the _nocancel versions
51 of syscalls rather than the vanilla version, if a _nocancel version
52 is available. See docs/internals/Darwin-notes.txt for the reason
55 #include "pub_core_basics.h" /* basic types */
56 #include "pub_core_vkiscnums.h" /* for syscall numbers */
57 #include "pub_core_debuglog.h" /* our own iface */
58 #include "pub_core_clreq.h" /* for RUNNING_ON_VALGRIND */
62 void VG_(debugLog_setXml
)(Bool xml
)
67 /*------------------------------------------------------------*/
68 /*--- Stuff to make us completely independent. ---*/
69 /*------------------------------------------------------------*/
71 /* ----- Platform-specifics ----- */
73 #if defined(VGP_x86_linux)
75 static UInt
local_sys_write_stderr ( const HChar
* buf
, Int n
)
81 "movl $"VG_STRINGIFY(__NR_write
)", %%eax\n" /* %eax = __NR_write */
82 "movl $2, %%ebx\n" /* %ebx = stderr */
83 "int $0x80\n" /* write(stderr, buf, n) */
85 : /*wr*/ "=a" (result
)
86 : /*rd*/ "c" (buf
), "d" (n
)
87 : /*trash*/ "edi", "memory", "cc"
90 return result
>= 0 ? result
: -1;
93 static UInt
local_sys_getpid ( void )
97 "movl $"VG_STRINGIFY(__NR_getpid
)", %%eax\n" /* %eax = __NR_getpid */
98 "int $0x80\n" /* getpid() */
99 "movl %%eax, %0\n" /* set __res = eax */
106 #elif defined(VGP_amd64_linux)
108 __attribute__((noinline
))
109 static UInt
local_sys_write_stderr ( const HChar
* buf
, Int n
)
111 volatile Long block
[2];
112 block
[0] = (Long
)buf
;
115 "subq $256, %%rsp\n" /* don't trash the stack redzone */
116 "pushq %%r15\n" /* r15 is callee-save */
117 "movq %0, %%r15\n" /* r15 = &block */
118 "pushq %%r15\n" /* save &block */
119 "movq $"VG_STRINGIFY(__NR_write
)", %%rax\n" /* rax = __NR_write */
120 "movq $2, %%rdi\n" /* rdi = stderr */
121 "movq 0(%%r15), %%rsi\n" /* rsi = buf */
122 "movq 8(%%r15), %%rdx\n" /* rdx = n */
123 "syscall\n" /* write(stderr, buf, n) */
124 "popq %%r15\n" /* reestablish &block */
125 "movq %%rax, 0(%%r15)\n" /* block[0] = result */
126 "popq %%r15\n" /* restore r15 */
127 "addq $256, %%rsp\n" /* restore stack ptr */
130 : /*trash*/ "rax", "rdi", "rsi", "rdx", "memory", "cc"
134 return (UInt
)block
[0];
137 static UInt
local_sys_getpid ( void )
141 "movq $"VG_STRINGIFY(__NR_getpid
)", %%rax\n" /* %rax = __NR_getpid */
142 "syscall\n" /* getpid() */
143 "movl %%eax, %0\n" /* set __res = %eax */
150 #elif defined(VGP_ppc32_linux)
152 static UInt
local_sys_write_stderr ( const HChar
* buf
, Int n
)
154 volatile Int block
[2];
159 "mr 5,%0\n\t" /* r5 = &block[0] */
160 "stw 5,0(1)\n\t" /* stash on stack */
161 "li 0,"VG_STRINGIFY(__NR_write
)"\n\t" /* set %r0 = __NR_write */
162 "li 3,2\n\t" /* set %r3 = stderr */
163 "lwz 4,0(5)\n\t" /* set %r4 = buf */
164 "lwz 5,4(5)\n\t" /* set %r5 = n */
165 "sc\n\t" /* write(stderr, buf, n) */
168 "stw 3,0(5)\n" /* block[0] = result */
171 : "cc","memory","cr0","ctr",
172 "r0","r2","r3","r4","r5","r6","r7","r8","r9","r10","r11","r12"
176 return (UInt
)block
[0];
179 static UInt
local_sys_getpid ( void )
181 register UInt __res
__asm__ ("r3");
187 : "cc","memory","cr0","ctr",
188 "r0","r2","r4","r5","r6","r7","r8","r9","r10","r11","r12"
193 #elif defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux)
195 static UInt
local_sys_write_stderr ( const HChar
* buf
, Int n
)
197 volatile Long block
[2];
198 block
[0] = (Long
)buf
;
202 "mr 5,%0\n\t" /* r5 = &block[0] */
203 "std 5,0(1)\n\t" /* stash on stack */
204 "li 0,"VG_STRINGIFY(__NR_write
)"\n\t" /* %r0 = __NR_write */
205 "li 3,2\n\t" /* set %r3 = stderr */
206 "ld 4,0(5)\n\t" /* set %r4 = buf */
207 "ld 5,8(5)\n\t" /* set %r5 = n */
208 "sc\n\t" /* write(stderr, buf, n) */
211 "std 3,0(5)\n" /* block[0] = result */
214 : "cc","memory","cr0","ctr",
215 "r0","r2","r3","r4","r5","r6","r7","r8","r9","r10","r11","r12"
219 return (UInt
)(Int
)block
[0];
222 static UInt
local_sys_getpid ( void )
224 register ULong __res
__asm__ ("r3");
230 : "cc","memory","cr0","ctr",
231 "r0","r2","r4","r5","r6","r7","r8","r9","r10","r11","r12"
236 #elif defined(VGP_arm_linux)
238 static UInt
local_sys_write_stderr ( const HChar
* buf
, Int n
)
240 volatile Int block
[2];
244 "mov r0, #2\n\t" /* stderr */
245 "ldr r1, [%0]\n\t" /* buf */
246 "ldr r2, [%0, #4]\n\t" /* n */
248 "mov r7, #"VG_STRINGIFY(__NR_write
)"\n\t"
249 "svc 0x0\n" /* write() */
258 return (UInt
)block
[0];
261 static UInt
local_sys_getpid ( void )
266 "mov r7, #"VG_STRINGIFY(__NR_getpid
)"\n\t"
267 "svc 0x0\n\t" /* getpid() */
276 #elif defined(VGP_arm64_linux)
278 static UInt
local_sys_write_stderr ( const HChar
* buf
, Int n
)
280 volatile ULong block
[2];
281 block
[0] = (ULong
)buf
;
284 "mov x0, #2\n\t" /* stderr */
285 "ldr x1, [%0]\n\t" /* buf */
286 "ldr x2, [%0, #8]\n\t" /* n */
287 "mov x8, #"VG_STRINGIFY(__NR_write
)"\n\t"
288 "svc 0x0\n" /* write() */
292 : "x0","x1","x2","x7"
296 return (UInt
)block
[0];
299 static UInt
local_sys_getpid ( void )
303 "mov x8, #"VG_STRINGIFY(__NR_getpid
)"\n"
304 "svc 0x0\n" /* getpid() */
312 #elif defined(VGP_x86_darwin)
314 /* We would use VG_DARWIN_SYSNO_TO_KERNEL instead of VG_DARWIN_SYSNO_INDEX
315 except that the former has a C ternary ?: operator which isn't valid in
316 asm code. Both macros give the same results for Unix-class syscalls (which
317 these all are, as identified by the use of 'int 0x80'). */
318 __attribute__((noinline
))
319 static UInt
local_sys_write_stderr ( const HChar
* buf
, Int n
)
323 "movl %2, %%eax\n" /* push n */
325 "movl %1, %%eax\n" /* push buf */
327 "movl $2, %%eax\n" /* push stderr */
329 "movl $"VG_STRINGIFY(VG_DARWIN_SYSNO_INDEX(__NR_write_nocancel
))
331 "pushl %%eax\n" /* push fake return address */
332 "int $0x80\n" /* write(stderr, buf, n) */
333 "jnc 1f\n" /* jump if no error */
334 "movl $-1, %%eax\n" /* return -1 if error */
336 "movl %%eax, %0\n" /* __res = eax */
337 "addl $16, %%esp\n" /* pop x4 */
345 static UInt
local_sys_getpid ( void )
349 "movl $"VG_STRINGIFY(VG_DARWIN_SYSNO_INDEX(__NR_getpid
))", %%eax\n"
350 "int $0x80\n" /* getpid() */
351 "movl %%eax, %0\n" /* set __res = eax */
358 #elif defined(VGP_amd64_darwin)
360 __attribute__((noinline
))
361 static UInt
local_sys_write_stderr ( const HChar
* buf
, Int n
)
365 "movq $2, %%rdi\n" /* push stderr */
366 "movq %1, %%rsi\n" /* push buf */
367 "movl %2, %%edx\n" /* push n */
368 "movl $"VG_STRINGIFY(VG_DARWIN_SYSNO_FOR_KERNEL(__NR_write_nocancel
))
370 "syscall\n" /* write(stderr, buf, n) */
371 "jnc 1f\n" /* jump if no error */
372 "movq $-1, %%rax\n" /* return -1 if error */
374 "movl %%eax, %0\n" /* __res = eax */
377 : "rdi", "rsi", "rdx", "rcx", "rax", "cc" );
381 static UInt
local_sys_getpid ( void )
385 "movl $"VG_STRINGIFY(VG_DARWIN_SYSNO_FOR_KERNEL(__NR_getpid
))", %%eax\n"
386 "syscall\n" /* getpid() */
387 "movl %%eax, %0\n" /* set __res = eax */
390 : "rax", "rcx", "cc" );
394 #elif defined(VGP_s390x_linux)
396 static UInt
local_sys_write_stderr ( const HChar
* buf
, Int n
)
398 register Int r2
asm("2") = 2; /* file descriptor STDERR */
399 register const HChar
* r3
asm("3") = buf
;
400 register ULong r4
asm("4") = n
;
401 register ULong r2_res
asm("2");
404 __asm__
__volatile__ (
414 if (__res
>= (ULong
)(-125))
416 return (UInt
)(__res
);
419 static UInt
local_sys_getpid ( void )
421 register ULong r2
asm("2");
424 __asm__
__volatile__ (
431 if (__res
>= (ULong
)(-125))
433 return (UInt
)(__res
);
436 #elif defined(VGP_mips32_linux)
438 static UInt
local_sys_write_stderr ( const HChar
* buf
, Int n
)
440 volatile Int block
[2];
444 "li $4, 2\n\t" /* stderr */
445 "lw $5, 0(%0)\n\t" /* buf */
446 "lw $6, 4(%0)\n\t" /* n */
448 "li $2, %1\n\t" /* set v0 = __NR_write */
449 "syscall\n\t" /* write() */
452 : "r" (block
), "n" (__NR_write
)
453 : "2", "4", "5", "6", "7"
457 return (UInt
)block
[0];
460 static UInt
local_sys_getpid ( void )
464 "li $2, %1\n\t" /* set v0 = __NR_getpid */
465 "syscall\n\t" /* getpid() */
474 #elif defined(VGP_mips64_linux)
476 static UInt
local_sys_write_stderr ( const HChar
* buf
, Int n
)
478 volatile Long block
[2];
479 block
[0] = (Long
)buf
;
482 "li $4, 2\n\t" /* std output*/
483 "ld $5, 0(%0)\n\t" /*$5 = buf*/
484 "ld $6, 8(%0)\n\t" /*$6 = n */
486 "li $2, %1\n\t" /* set v0 = __NR_write */
490 : /*rd*/ "r" (block
), "n" (__NR_write
)
491 : "2", "4", "5", "6", "7"
495 return (UInt
)(Int
)block
[0];
498 static UInt
local_sys_getpid ( void )
502 "li $2, %1\n\t" /* set v0 = __NR_getpid */
503 "syscall\n\t" /* getpid() */
509 return (UInt
)(__res
);
513 # error Unknown platform
517 /* ----- generic ----- */
519 /* strlen, so we don't need m_libc */
520 static Int
local_strlen ( const HChar
* str
)
523 while (str
[i
] != 0) i
++;
527 static HChar
local_toupper ( HChar c
)
529 if (c
>= 'a' && c
<= 'z')
530 return c
+ ('A' - 'a');
535 /* Emit buf[0 .. n-1] to stderr. Unfortunately platform-specific.
537 static void emit ( const HChar
* buf
, Int n
)
540 (void)local_sys_write_stderr(buf
, n
);
544 /*------------------------------------------------------------*/
545 /*--- A simple, generic, vprintf implementation. ---*/
546 /*------------------------------------------------------------*/
548 /* -----------------------------------------------
549 Distantly derived from:
551 vprintf replacement for Checker.
552 Copyright 1993, 1994, 1995 Tristan Gingold
553 Written September 1993 Tristan Gingold
554 Tristan Gingold, 8 rue Parmentier, F-91120 PALAISEAU, FRANCE
556 (Checker itself was GPL'd.)
557 ----------------------------------------------- */
560 #define VG_MSG_SIGNED 1 /* The value is signed. */
561 #define VG_MSG_ZJUSTIFY 2 /* Must justify with '0'. */
562 #define VG_MSG_LJUSTIFY 4 /* Must justify on the left. */
563 #define VG_MSG_PAREN 8 /* Parenthesize if present (for %y) */
564 #define VG_MSG_COMMA 16 /* Add commas to numbers (for %d, %u) */
565 #define VG_MSG_ALTFORMAT 32 /* Convert the value to alternate format */
567 /* Copy a string into the buffer. */
569 UInt
myvprintf_str ( void(*send
)(HChar
,void*),
576 # define MAYBE_TOUPPER(ch) (capitalise ? local_toupper(ch) : (ch))
579 Int len
= local_strlen(str
);
583 for (i
= 0; i
< len
; i
++)
584 send(MAYBE_TOUPPER(str
[i
]), send_arg2
);
590 for (i
= 0; i
< width
; i
++)
591 send(MAYBE_TOUPPER(str
[i
]), send_arg2
);
596 if (! (flags
& VG_MSG_LJUSTIFY
)) {
598 for (i
= 0; i
< extra
; i
++)
599 send(' ', send_arg2
);
602 for (i
= 0; i
< len
; i
++)
603 send(MAYBE_TOUPPER(str
[i
]), send_arg2
);
604 if (flags
& VG_MSG_LJUSTIFY
) {
606 for (i
= 0; i
< extra
; i
++)
607 send(' ', send_arg2
);
610 # undef MAYBE_TOUPPER
615 /* Copy a string into the buffer, escaping bad XML chars. */
617 UInt
myvprintf_str_XML_simplistic ( void(*send
)(HChar
,void*),
623 Int len
= local_strlen(str
);
626 for (i
= 0; i
< len
; i
++) {
628 case '&': alt
= "&"; break;
629 case '<': alt
= "<"; break;
630 case '>': alt
= ">"; break;
636 send(*alt
, send_arg2
);
641 send(str
[i
], send_arg2
);
650 /* Write P into the buffer according to these args:
651 * If SIGN is true, p is a signed.
653 * If WITH_ZERO is true, '0' must be added.
654 * WIDTH is the width of the field.
657 UInt
myvprintf_int64 ( void(*send
)(HChar
,void*),
665 /* To print an ULong base 2 needs 64 characters. If commas are requested,
666 add 21. Plus 1 for a possible sign plus 1 for \0. Makes 87 -- so let's
667 say 90. The size of BUF needs to be max(90, WIDTH + 1) */
668 HChar buf
[width
+ 1 > 90 ? width
+ 1 : 90];
672 const HChar
* digits
= capitalised
? "0123456789ABCDEF" : "0123456789abcdef";
675 if (base
< 2 || base
> 16)
678 if ((flags
& VG_MSG_SIGNED
) && (Long
)p
< 0) {
687 if (flags
& VG_MSG_COMMA
&& 10 == base
&&
688 0 == (ind
-nc
) % 3 && 0 != ind
)
693 buf
[ind
++] = digits
[p
% base
];
701 if (width
> 0 && !(flags
& VG_MSG_LJUSTIFY
)) {
702 for(; ind
< width
; ind
++) {
703 buf
[ind
] = (flags
& VG_MSG_ZJUSTIFY
) ? '0': ' ';
707 /* Reverse copy to buffer. */
709 for (i
= ind
-1; i
>= 0; i
--) {
710 send(buf
[i
], send_arg2
);
712 if (width
> 0 && (flags
& VG_MSG_LJUSTIFY
)) {
713 for(; ind
< width
; ind
++) {
715 /* Never pad with zeroes on RHS -- changes the value! */
716 send(' ', send_arg2
);
723 /* A simple vprintf(). */
726 VG_(debugLog_vprintf
) (
727 void(*send
)(HChar
,void*),
736 Int width
, precision
;
738 Bool is_long
, is_sizet
, caps
;
740 /* We assume that vargs has already been initialised by the
741 caller, using va_start, and that the caller will similarly
742 clean up with va_end.
745 for (i
= 0; format
[i
] != 0; i
++) {
746 if (format
[i
] != '%') {
747 send(format
[i
], send_arg2
);
752 /* A '%' has been found. Ignore a trailing %. */
755 if (format
[i
] == '%') {
756 /* '%%' is replaced by '%'. */
757 send('%', send_arg2
);
763 width
= 0; /* length of the field. */
764 precision
= -1; /* unspecified precision */
768 flags
|= VG_MSG_PAREN
;
772 /* If ',' or '\'' follows '%', commas will be inserted. */
773 flags
|= VG_MSG_COMMA
;
776 /* If '-' follows '%', justify on the left. */
777 flags
|= VG_MSG_LJUSTIFY
;
780 /* If '0' follows '%', pads will be inserted. */
781 flags
|= VG_MSG_ZJUSTIFY
;
784 /* If '#' follows '%', alternative format will be used. */
785 flags
|= VG_MSG_ALTFORMAT
;
788 goto parse_fieldwidth
;
793 /* Compute the field length. */
794 if (format
[i
] == '*') {
795 width
= va_arg(vargs
, Int
);
798 while (format
[i
] >= '0' && format
[i
] <= '9') {
800 width
+= format
[i
++] - '0';
803 /* Parse precision, if any. Only meaningful for %f. For all other
804 format specifiers the precision will be silently ignored. */
805 if (format
[i
] == '.') {
807 if (format
[i
] == '*') {
808 precision
= va_arg(vargs
, Int
);
812 while (format
[i
] >= '0' && format
[i
] <= '9') {
814 precision
+= format
[i
++] - '0';
820 if (format
[i
] == 'z') {
823 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
, SizeT
)));
846 ret
+= myvprintf_int64(send
, send_arg2
, flags
, 8, width
, False
,
847 (ULong
)(va_arg (vargs
, ULong
)));
849 ret
+= myvprintf_int64(send
, send_arg2
, flags
, 8, width
, False
,
850 (ULong
)(va_arg (vargs
, UInt
)));
853 flags
|= VG_MSG_SIGNED
;
855 ret
+= myvprintf_int64(send
, send_arg2
, flags
, 10, width
, False
,
856 (ULong
)(va_arg (vargs
, Long
)));
858 ret
+= myvprintf_int64(send
, send_arg2
, flags
, 10, width
, False
,
859 (ULong
)(va_arg (vargs
, Int
)));
863 ret
+= myvprintf_int64(send
, send_arg2
, flags
, 10, width
, False
,
864 (ULong
)(va_arg (vargs
, SizeT
)));
866 ret
+= myvprintf_int64(send
, send_arg2
, flags
, 10, width
, False
,
867 (ULong
)(va_arg (vargs
, ULong
)));
869 ret
+= myvprintf_int64(send
, send_arg2
, flags
, 10, width
, False
,
870 (ULong
)(va_arg (vargs
, UInt
)));
873 if (format
[i
+1] == 'S') {
875 /* %pS, like %s but escaping chars for XML safety */
876 /* Note: simplistic; ignores field width and flags */
877 const HChar
*str
= va_arg (vargs
, HChar
*);
880 ret
+= myvprintf_str_XML_simplistic(send
, send_arg2
, str
);
881 } else if (format
[i
+1] == 's') {
883 /* %ps, synonym for %s with --xml=no / %pS with --xml=yes */
884 const HChar
*str
= va_arg (vargs
, HChar
*);
888 ret
+= myvprintf_str_XML_simplistic(send
, send_arg2
, str
);
890 ret
+= myvprintf_str(send
, send_arg2
, flags
, width
, str
,
897 ret
+= myvprintf_int64(send
, send_arg2
, flags
, 16, width
, True
,
898 (ULong
)((UWord
)va_arg (vargs
, void *)));
903 caps
= toBool(format
[i
] == 'X');
904 if (flags
& VG_MSG_ALTFORMAT
) {
910 ret
+= myvprintf_int64(send
, send_arg2
, flags
, 16, width
, False
,
911 (ULong
)(va_arg (vargs
, SizeT
)));
913 ret
+= myvprintf_int64(send
, send_arg2
, flags
, 16, width
, caps
,
914 (ULong
)(va_arg (vargs
, ULong
)));
916 ret
+= myvprintf_int64(send
, send_arg2
, flags
, 16, width
, caps
,
917 (ULong
)(va_arg (vargs
, UInt
)));
921 send(va_arg (vargs
, int), send_arg2
);
923 case 's': case 'S': { /* %s */
924 const HChar
*str
= va_arg (vargs
, HChar
*);
925 if (str
== NULL
) str
= "(null)";
926 ret
+= myvprintf_str(send
, send_arg2
,
927 flags
, width
, str
, format
[i
]=='S');
931 /* Print a floating point number in the format x.y without
932 any exponent. Capabilities are extremely limited, basically
933 a joke, but good enough for our needs. */
934 Double val
= va_arg (vargs
, Double
);
935 Bool is_negative
= False
;
942 /* If the integral part of the floating point number cannot be
943 represented by an ULONG_MAX, print '*' characters */
944 if (val
> (Double
)(~0ULL)) {
945 if (width
== 0) width
= 6; // say
946 for (cnt
= 0; cnt
< width
; ++cnt
)
947 send('*', send_arg2
);
951 /* The integral part of the floating point number is representable
954 Double frac
= val
- ipval
;
956 if (precision
== -1) precision
= 6; // say
958 /* Silently limit the precision to 10 digits. */
959 if (precision
> 10) precision
= 10;
961 /* If fracional part is not printed (precision == 0), may have to
963 if (precision
== 0 && frac
>= 0.5)
966 /* Find out how many characters are needed to print the number */
968 /* The integral part... */
969 UInt ipwidth
, num_digit
= 1; // at least one digit
971 for (x
= 10; ; old_x
= x
, x
*= 10, ++num_digit
) {
972 if (x
<= old_x
) break; // overflow occurred
973 if (ipval
< x
) break;
975 ipwidth
= num_digit
; // width of integral part.
976 if (is_negative
) ++num_digit
;
978 num_digit
+= 1 + precision
;
982 // Fill in blanks on the left
983 if (num_digit
< width
&& (flags
& VG_MSG_LJUSTIFY
) == 0) {
984 for (cnt
= 0; cnt
< width
- num_digit
; ++cnt
)
985 send(' ', send_arg2
);
986 ret
+= width
- num_digit
;
990 send('-', send_arg2
);
994 ret
+= myvprintf_int64(send
, send_arg2
, 0, 10, ipwidth
, False
,
996 // Decimal point and fractional part
997 if (precision
!= 0) {
998 send('.', send_arg2
);
1003 for (cnt
= 0; cnt
< precision
; ++cnt
)
1005 ULong frval
= frac
* factor
;
1006 if ((frac
* factor
- frval
) > 0.5) // round up
1009 ret
+= myvprintf_int64(send
, send_arg2
, VG_MSG_ZJUSTIFY
, 10,
1010 precision
, False
, frval
);
1012 // Fill in blanks on the right
1013 if (num_digit
< width
&& (flags
& VG_MSG_LJUSTIFY
) != 0) {
1014 for (cnt
= 0; cnt
< width
- num_digit
; ++cnt
)
1015 send(' ', send_arg2
);
1016 ret
+= width
- num_digit
;
1021 // case 'y': { /* %y - print symbol */
1022 // Addr a = va_arg(vargs, Addr);
1025 // if (VG_(get_fnname_w_offset)(a, &name)) {
1026 // HChar buf[1 + VG_strlen(name) + 1 + 1];
1027 // if (flags & VG_MSG_PAREN) {
1028 // VG_(sprintf)(str, "(%s)", name):
1030 // VG_(sprintf)(str, "%s", name):
1032 // ret += myvprintf_str(send, flags, width, buf, 0);
1044 /*------------------------------------------------------------*/
1045 /*--- Debuglog stuff. ---*/
1046 /*------------------------------------------------------------*/
1048 /* Only print messages whose stated level is less than or equal to
1049 this. By default, it makes this entire subsystem silent. */
1051 static Int loglevel
= 0;
1053 /* Module startup. */
1055 void VG_(debugLog_startup
) ( Int level
, const HChar
* who
)
1057 if (level
< 0) level
= 0;
1058 if (level
> 10) level
= 10;
1060 VG_(debugLog
)(1, "debuglog",
1061 "DebugLog system started by %s, "
1062 "level %d logging requested\n",
1066 /* Get the logging threshold level, as set by the most recent call to
1067 VG_(debugLog_startup), or zero if there have been no such calls so
1070 Int
VG_(debugLog_getLevel
) ( void )
1085 static void add_to_buf ( HChar c
, void* p
)
1087 printf_buf
* buf
= (printf_buf
*)p
;
1089 if (buf
->n
>= 100-10 /*paranoia*/ ) {
1090 emit( buf
->buf
, local_strlen(buf
->buf
) );
1092 buf
->buf
[buf
->n
] = 0;
1094 buf
->buf
[buf
->n
++] = c
;
1095 buf
->buf
[buf
->n
] = 0;
1098 /* Send a logging message. Nothing is output unless 'level'
1099 is <= the current loglevel. */
1101 void VG_(debugLog
) ( Int level
, const HChar
* modulename
,
1102 const HChar
* format
, ... )
1105 Int indent
, depth
, i
;
1109 if (level
> loglevel
)
1112 indent
= 2*level
- 1;
1113 if (indent
< 1) indent
= 1;
1117 pid
= local_sys_getpid();
1119 // Print one '>' in front of the messages for each level of self-hosting
1121 depth
= RUNNING_ON_VALGRIND
;
1122 for (i
= 0; i
< depth
; i
++) {
1123 (void)myvprintf_str ( add_to_buf
, &buf
, 0, 1, ">", False
);
1126 (void)myvprintf_str ( add_to_buf
, &buf
, 0, 2, "--", False
);
1127 (void)myvprintf_int64 ( add_to_buf
, &buf
, 0, 10, 1, False
, (ULong
)pid
);
1128 (void)myvprintf_str ( add_to_buf
, &buf
, 0, 1, ":", False
);
1129 (void)myvprintf_int64 ( add_to_buf
, &buf
, 0, 10, 1, False
, (ULong
)level
);
1130 (void)myvprintf_str ( add_to_buf
, &buf
, 0, 1, ":", False
);
1131 (void)myvprintf_str ( add_to_buf
, &buf
, 0, 8, modulename
, False
);
1132 (void)myvprintf_str ( add_to_buf
, &buf
, 0, indent
, "", False
);
1134 va_start(vargs
,format
);
1136 (void) VG_(debugLog_vprintf
) ( add_to_buf
, &buf
, format
, vargs
);
1139 emit( buf
.buf
, local_strlen(buf
.buf
) );
1147 /*--------------------------------------------------------------------*/
1148 /*--- end m_debuglog.c ---*/
1149 /*--------------------------------------------------------------------*/