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-2017 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 */
59 #if defined(VGO_solaris)
60 #include "pub_core_vki.h" /* for EINTR and ERESTART */
65 void VG_(debugLog_setXml
)(Bool xml
)
70 /*------------------------------------------------------------*/
71 /*--- Stuff to make us completely independent. ---*/
72 /*------------------------------------------------------------*/
74 /* ----- Platform-specifics ----- */
76 #if defined(VGP_x86_linux)
78 static UInt
local_sys_write_stderr ( const HChar
* buf
, Int n
)
84 "movl $"VG_STRINGIFY(__NR_write
)", %%eax\n" /* %eax = __NR_write */
85 "movl $2, %%ebx\n" /* %ebx = stderr */
86 "int $0x80\n" /* write(stderr, buf, n) */
88 : /*wr*/ "=a" (result
)
89 : /*rd*/ "c" (buf
), "d" (n
)
90 : /*trash*/ "edi", "memory", "cc"
93 return result
>= 0 ? result
: -1;
96 static UInt
local_sys_getpid ( void )
100 "movl $"VG_STRINGIFY(__NR_getpid
)", %%eax\n" /* %eax = __NR_getpid */
101 "int $0x80\n" /* getpid() */
102 "movl %%eax, %0\n" /* set __res = eax */
109 #elif defined(VGP_amd64_linux)
111 __attribute__((noinline
))
112 static UInt
local_sys_write_stderr ( const HChar
* buf
, Int n
)
114 volatile Long block
[2];
115 block
[0] = (Long
)buf
;
118 "subq $256, %%rsp\n" /* don't trash the stack redzone */
119 "pushq %%r15\n" /* r15 is callee-save */
120 "movq %0, %%r15\n" /* r15 = &block */
121 "pushq %%r15\n" /* save &block */
122 "movq $"VG_STRINGIFY(__NR_write
)", %%rax\n" /* rax = __NR_write */
123 "movq $2, %%rdi\n" /* rdi = stderr */
124 "movq 0(%%r15), %%rsi\n" /* rsi = buf */
125 "movq 8(%%r15), %%rdx\n" /* rdx = n */
126 "syscall\n" /* write(stderr, buf, n) */
127 "popq %%r15\n" /* reestablish &block */
128 "movq %%rax, 0(%%r15)\n" /* block[0] = result */
129 "popq %%r15\n" /* restore r15 */
130 "addq $256, %%rsp\n" /* restore stack ptr */
133 : /*trash*/ "rax", "rdi", "rsi", "rdx", "memory", "cc", "rcx", "r11"
137 return (UInt
)block
[0];
140 static UInt
local_sys_getpid ( void )
144 "movq $"VG_STRINGIFY(__NR_getpid
)", %%rax\n" /* %rax = __NR_getpid */
145 "syscall\n" /* getpid() */
146 "movl %%eax, %0\n" /* set __res = %eax */
149 : "rax", "rcx", "r11"
154 #elif defined(VGP_ppc32_linux)
156 static UInt
local_sys_write_stderr ( const 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_ppc64be_linux) || defined(VGP_ppc64le_linux)
199 static UInt
local_sys_write_stderr ( const 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","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","r4","r5","r6","r7","r8","r9","r10","r11","r12"
240 #elif defined(VGP_arm_linux)
242 static UInt
local_sys_write_stderr ( const 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 */
252 "mov r7, #"VG_STRINGIFY(__NR_write
)"\n\t"
253 "svc 0x0\n" /* write() */
262 return (UInt
)block
[0];
265 static UInt
local_sys_getpid ( void )
270 "mov r7, #"VG_STRINGIFY(__NR_getpid
)"\n\t"
271 "svc 0x0\n\t" /* getpid() */
280 #elif defined(VGP_arm64_linux)
282 static UInt
local_sys_write_stderr ( const HChar
* buf
, Int n
)
284 volatile ULong block
[2];
285 block
[0] = (ULong
)buf
;
288 "mov x0, #2\n\t" /* stderr */
289 "ldr x1, [%0]\n\t" /* buf */
290 "ldr x2, [%0, #8]\n\t" /* n */
291 "mov x8, #"VG_STRINGIFY(__NR_write
)"\n\t"
292 "svc 0x0\n" /* write() */
296 : "x0","x1","x2","x7"
300 return (UInt
)block
[0];
303 static UInt
local_sys_getpid ( void )
307 "mov x8, #"VG_STRINGIFY(__NR_getpid
)"\n"
308 "svc 0x0\n" /* getpid() */
316 #elif defined(VGP_x86_darwin)
318 /* We would use VG_DARWIN_SYSNO_TO_KERNEL instead of VG_DARWIN_SYSNO_INDEX
319 except that the former has a C ternary ?: operator which isn't valid in
320 asm code. Both macros give the same results for Unix-class syscalls (which
321 these all are, as identified by the use of 'int 0x80'). */
322 __attribute__((noinline
))
323 static UInt
local_sys_write_stderr ( const HChar
* buf
, Int n
)
327 "movl %2, %%eax\n" /* push n */
329 "movl %1, %%eax\n" /* push buf */
331 "movl $2, %%eax\n" /* push stderr */
333 "movl $"VG_STRINGIFY(VG_DARWIN_SYSNO_INDEX(__NR_write_nocancel
))
335 "pushl %%eax\n" /* push fake return address */
336 "int $0x80\n" /* write(stderr, buf, n) */
337 "jnc 1f\n" /* jump if no error */
338 "movl $-1, %%eax\n" /* return -1 if error */
340 "movl %%eax, %0\n" /* __res = eax */
341 "addl $16, %%esp\n" /* pop x4 */
349 static UInt
local_sys_getpid ( void )
353 "movl $"VG_STRINGIFY(VG_DARWIN_SYSNO_INDEX(__NR_getpid
))", %%eax\n"
354 "int $0x80\n" /* getpid() */
355 "movl %%eax, %0\n" /* set __res = eax */
362 #elif defined(VGP_amd64_darwin)
364 __attribute__((noinline
))
365 static UInt
local_sys_write_stderr ( const HChar
* buf
, Int n
)
369 "movq $2, %%rdi\n" /* push stderr */
370 "movq %1, %%rsi\n" /* push buf */
371 "movl %2, %%edx\n" /* push n */
372 "movl $"VG_STRINGIFY(VG_DARWIN_SYSNO_FOR_KERNEL(__NR_write_nocancel
))
374 "syscall\n" /* write(stderr, buf, n) */
375 "jnc 1f\n" /* jump if no error */
376 "movq $-1, %%rax\n" /* return -1 if error */
378 "movl %%eax, %0\n" /* __res = eax */
381 : "rdi", "rsi", "rdx", "rcx", "rax", "cc" );
385 static UInt
local_sys_getpid ( void )
389 "movl $"VG_STRINGIFY(VG_DARWIN_SYSNO_FOR_KERNEL(__NR_getpid
))", %%eax\n"
390 "syscall\n" /* getpid() */
391 "movl %%eax, %0\n" /* set __res = eax */
394 : "rax", "rcx", "cc" );
398 #elif defined(VGP_s390x_linux)
400 static UInt
local_sys_write_stderr ( const HChar
* buf
, Int n
)
402 register Int r2
asm("2") = 2; /* file descriptor STDERR */
403 register const HChar
* r3
asm("3") = buf
;
404 register ULong r4
asm("4") = n
;
405 register ULong r2_res
asm("2");
408 __asm__
__volatile__ (
418 if (__res
>= (ULong
)(-125))
420 return (UInt
)(__res
);
423 static UInt
local_sys_getpid ( void )
425 register ULong r2
asm("2");
428 __asm__
__volatile__ (
435 if (__res
>= (ULong
)(-125))
437 return (UInt
)(__res
);
440 #elif defined(VGP_mips32_linux) || defined(VGP_mips64_linux)
442 static UInt
local_sys_write_stderr ( const HChar
* buf
, Int n
)
444 register RegWord v0
asm("2");
445 register RegWord a0
asm("4");
446 register RegWord a1
asm("5");
447 register RegWord a2
asm("6");
450 a1
= (RegWord
)(Addr
)buf
;
454 "addiu $4, $0, -1 \n\t"
455 "movn $2, $4, $7 \n\t"
456 : "+d" (v0
), "+d" (a0
), "+d" (a1
), "+d" (a2
)
458 : "$1", "$3", "$7", "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15",
464 static UInt
local_sys_getpid ( void )
466 register RegWord v0
asm("2");
472 : "$1", "$3", "$4", "$5", "$6", "$7", "$8", "$9", "$10", "$11", "$12",
473 "$13", "$14", "$15", "$24", "$25", "$31"
478 #elif defined(VGP_x86_solaris)
479 static UInt
local_sys_write_stderr ( const HChar
* buf
, Int n
)
485 /* The Solaris kernel does not restart syscalls automatically so it is
487 __asm__
__volatile__ (
488 "movl %[n], %%eax\n" /* push n */
490 "movl %[buf], %%eax\n" /* push buf */
492 "movl $2, %%eax\n" /* push stderr */
494 "movl $"VG_STRINGIFY(__NR_write
)", %%eax\n"
495 "pushl %%eax\n" /* push fake return address */
496 "int $0x91\n" /* write(stderr, buf, n) */
497 "movl $0, %%edx\n" /* assume no error */
498 "jnc 1f\n" /* jump if no error */
499 "movl $1, %%edx\n" /* set error flag */
501 "addl $16, %%esp\n" /* pop x4 */
502 : "=&a" (res
), "=d" (err
)
503 : [buf
] "g" (buf
), [n
] "g" (n
)
505 restart
= err
&& (res
== VKI_EINTR
|| res
== VKI_ERESTART
);
511 static UInt
local_sys_getpid ( void )
515 /* The getpid() syscall never returns EINTR or ERESTART so there is no need
516 for restarting it. */
517 __asm__
__volatile__ (
518 "movl $"VG_STRINGIFY(__NR_getpid
)", %%eax\n"
519 "int $0x91\n" /* getpid() */
527 #elif defined(VGP_amd64_solaris)
528 static UInt
local_sys_write_stderr ( const HChar
* buf
, Int n
)
534 /* The Solaris kernel does not restart syscalls automatically so it is
536 __asm__
__volatile__ (
537 "movq $2, %%rdi\n" /* push stderr */
538 "movq $"VG_STRINGIFY(__NR_write
)", %%rax\n"
539 "syscall\n" /* write(stderr, buf, n) */
540 "movq $0, %%rdx\n" /* assume no error */
541 "jnc 1f\n" /* jump if no error */
542 "movq $1, %%rdx\n" /* set error flag */
544 : "=a" (res
), "=d" (err
)
547 restart
= err
&& (res
== VKI_EINTR
|| res
== VKI_ERESTART
);
553 static UInt
local_sys_getpid ( void )
557 /* The getpid() syscall never returns EINTR or ERESTART so there is no need
558 for restarting it. */
559 __asm__
__volatile__ (
560 "movq $"VG_STRINGIFY(__NR_getpid
)", %%rax\n"
561 "syscall\n" /* getpid() */
570 # error Unknown platform
574 /* ----- generic ----- */
576 /* strlen, so we don't need m_libc */
577 static Int
local_strlen ( const HChar
* str
)
580 while (str
[i
] != 0) i
++;
584 static HChar
local_toupper ( HChar c
)
586 if (c
>= 'a' && c
<= 'z')
587 return c
+ ('A' - 'a');
592 /* Emit buf[0 .. n-1] to stderr. Unfortunately platform-specific.
594 static void emit ( const HChar
* buf
, Int n
)
597 (void)local_sys_write_stderr(buf
, n
);
601 /*------------------------------------------------------------*/
602 /*--- A simple, generic, vprintf implementation. ---*/
603 /*------------------------------------------------------------*/
605 /* -----------------------------------------------
606 Distantly derived from:
608 vprintf replacement for Checker.
609 Copyright 1993, 1994, 1995 Tristan Gingold
610 Written September 1993 Tristan Gingold
611 Tristan Gingold, 8 rue Parmentier, F-91120 PALAISEAU, FRANCE
613 (Checker itself was GPL'd.)
614 ----------------------------------------------- */
617 #define VG_MSG_SIGNED 1 /* The value is signed. */
618 #define VG_MSG_ZJUSTIFY 2 /* Must justify with '0'. */
619 #define VG_MSG_LJUSTIFY 4 /* Must justify on the left. */
620 #define VG_MSG_PAREN 8 /* Parenthesize if present (for %y) */
621 #define VG_MSG_COMMA 16 /* Add commas to numbers (for %d, %u) */
622 #define VG_MSG_ALTFORMAT 32 /* Convert the value to alternate format */
624 /* Copy a string into the buffer. */
626 UInt
myvprintf_str ( void(*send
)(HChar
,void*),
633 # define MAYBE_TOUPPER(ch) (capitalise ? local_toupper(ch) : (ch))
636 Int len
= local_strlen(str
);
640 for (i
= 0; i
< len
; i
++)
641 send(MAYBE_TOUPPER(str
[i
]), send_arg2
);
647 for (i
= 0; i
< width
; i
++)
648 send(MAYBE_TOUPPER(str
[i
]), send_arg2
);
653 if (! (flags
& VG_MSG_LJUSTIFY
)) {
655 for (i
= 0; i
< extra
; i
++)
656 send(' ', send_arg2
);
659 for (i
= 0; i
< len
; i
++)
660 send(MAYBE_TOUPPER(str
[i
]), send_arg2
);
661 if (flags
& VG_MSG_LJUSTIFY
) {
663 for (i
= 0; i
< extra
; i
++)
664 send(' ', send_arg2
);
667 # undef MAYBE_TOUPPER
672 /* Copy a string into the buffer, escaping bad XML chars. */
674 UInt
myvprintf_str_XML_simplistic ( void(*send
)(HChar
,void*),
680 Int len
= local_strlen(str
);
683 for (i
= 0; i
< len
; i
++) {
685 case '&': alt
= "&"; break;
686 case '<': alt
= "<"; break;
687 case '>': alt
= ">"; break;
693 send(*alt
, send_arg2
);
698 send(str
[i
], send_arg2
);
707 /* Write P into the buffer according to these args:
708 * If SIGN is true, p is a signed.
710 * If WITH_ZERO is true, '0' must be added.
711 * WIDTH is the width of the field.
714 UInt
myvprintf_int64 ( void(*send
)(HChar
,void*),
722 /* To print an ULong base 2 needs 64 characters. If commas are requested,
723 add 21. Plus 1 for a possible sign plus 1 for \0. Makes 87 -- so let's
724 say 90. The size of BUF needs to be max(90, WIDTH + 1) */
725 HChar buf
[width
+ 1 > 90 ? width
+ 1 : 90];
729 const HChar
* digits
= capitalised
? "0123456789ABCDEF" : "0123456789abcdef";
732 if (base
< 2 || base
> 16)
735 if ((flags
& VG_MSG_SIGNED
) && (Long
)p
< 0) {
744 if (flags
& VG_MSG_COMMA
&& 10 == base
&&
745 0 == (ind
-nc
) % 3 && 0 != ind
)
750 buf
[ind
++] = digits
[p
% base
];
758 if (width
> 0 && !(flags
& VG_MSG_LJUSTIFY
)) {
759 for(; ind
< width
; ind
++) {
760 buf
[ind
] = (flags
& VG_MSG_ZJUSTIFY
) ? '0': ' ';
764 /* Reverse copy to buffer. */
766 for (i
= ind
-1; i
>= 0; i
--) {
767 send(buf
[i
], send_arg2
);
769 if (width
> 0 && (flags
& VG_MSG_LJUSTIFY
)) {
770 for(; ind
< width
; ind
++) {
772 /* Never pad with zeroes on RHS -- changes the value! */
773 send(' ', send_arg2
);
780 /* A simple vprintf(). */
783 VG_(debugLog_vprintf
) (
784 void(*send
)(HChar
,void*),
793 Int width
, precision
;
795 Bool is_long
, is_sizet
, caps
;
797 /* We assume that vargs has already been initialised by the
798 caller, using va_start, and that the caller will similarly
799 clean up with va_end.
802 for (i
= 0; format
[i
] != 0; i
++) {
803 if (format
[i
] != '%') {
804 send(format
[i
], send_arg2
);
809 /* A '%' has been found. Ignore a trailing %. */
812 if (format
[i
] == '%') {
813 /* '%%' is replaced by '%'. */
814 send('%', send_arg2
);
820 width
= 0; /* length of the field. */
821 precision
= -1; /* unspecified precision */
825 flags
|= VG_MSG_PAREN
;
829 /* If ',' or '\'' follows '%', commas will be inserted. */
830 flags
|= VG_MSG_COMMA
;
833 /* If '-' follows '%', justify on the left. */
834 flags
|= VG_MSG_LJUSTIFY
;
837 /* If '0' follows '%', pads will be inserted. */
838 flags
|= VG_MSG_ZJUSTIFY
;
841 /* If '#' follows '%', alternative format will be used. */
842 flags
|= VG_MSG_ALTFORMAT
;
845 goto parse_fieldwidth
;
850 /* Compute the field length. */
851 if (format
[i
] == '*') {
852 width
= va_arg(vargs
, Int
);
855 while (format
[i
] >= '0' && format
[i
] <= '9') {
857 width
+= format
[i
++] - '0';
860 /* Parse precision, if any. Only meaningful for %f. For all other
861 format specifiers the precision will be silently ignored. */
862 if (format
[i
] == '.') {
864 if (format
[i
] == '*') {
865 precision
= va_arg(vargs
, Int
);
869 while (format
[i
] >= '0' && format
[i
] <= '9') {
871 precision
+= format
[i
++] - '0';
877 if (format
[i
] == 'z') {
881 while (format
[i
] == 'l') {
887 // %d means print a 32-bit integer.
888 // %ld means print a word-size integer.
889 // %lld means print a 64-bit integer.
890 if (0 == n_ls
) { is_long
= False
; }
891 else if (1 == n_ls
) { is_long
= ( sizeof(void*) == sizeof(Long
) ); }
892 else { is_long
= True
; }
896 if (flags
& VG_MSG_ALTFORMAT
) {
901 ret
+= myvprintf_int64(send
, send_arg2
, flags
, 8, width
, False
,
902 (ULong
)(va_arg (vargs
, SizeT
)));
904 ret
+= myvprintf_int64(send
, send_arg2
, flags
, 8, width
, False
,
905 (ULong
)(va_arg (vargs
, ULong
)));
907 ret
+= myvprintf_int64(send
, send_arg2
, flags
, 8, width
, False
,
908 (ULong
)(va_arg (vargs
, UInt
)));
911 flags
|= VG_MSG_SIGNED
;
913 ret
+= myvprintf_int64(send
, send_arg2
, flags
, 10, width
, False
,
914 (ULong
)(va_arg (vargs
, Long
)));
916 ret
+= myvprintf_int64(send
, send_arg2
, flags
, 10, width
, False
,
917 (ULong
)(va_arg (vargs
, Int
)));
921 ret
+= myvprintf_int64(send
, send_arg2
, flags
, 10, width
, False
,
922 (ULong
)(va_arg (vargs
, SizeT
)));
924 ret
+= myvprintf_int64(send
, send_arg2
, flags
, 10, width
, False
,
925 (ULong
)(va_arg (vargs
, ULong
)));
927 ret
+= myvprintf_int64(send
, send_arg2
, flags
, 10, width
, False
,
928 (ULong
)(va_arg (vargs
, UInt
)));
931 if (format
[i
+1] == 'S') {
933 /* %pS, like %s but escaping chars for XML safety */
934 /* Note: simplistic; ignores field width and flags */
935 const HChar
*str
= va_arg (vargs
, HChar
*);
938 ret
+= myvprintf_str_XML_simplistic(send
, send_arg2
, str
);
939 } else if (format
[i
+1] == 's') {
941 /* %ps, synonym for %s with --xml=no / %pS with --xml=yes */
942 const HChar
*str
= va_arg (vargs
, HChar
*);
946 ret
+= myvprintf_str_XML_simplistic(send
, send_arg2
, str
);
948 ret
+= myvprintf_str(send
, send_arg2
, flags
, width
, str
,
955 ret
+= myvprintf_int64(send
, send_arg2
, flags
, 16, width
, True
,
956 (ULong
)((UWord
)va_arg (vargs
, void *)));
961 caps
= toBool(format
[i
] == 'X');
962 if (flags
& VG_MSG_ALTFORMAT
) {
968 ret
+= myvprintf_int64(send
, send_arg2
, flags
, 16, width
, False
,
969 (ULong
)(va_arg (vargs
, SizeT
)));
971 ret
+= myvprintf_int64(send
, send_arg2
, flags
, 16, width
, caps
,
972 (ULong
)(va_arg (vargs
, ULong
)));
974 ret
+= myvprintf_int64(send
, send_arg2
, flags
, 16, width
, caps
,
975 (ULong
)(va_arg (vargs
, UInt
)));
979 send(va_arg (vargs
, int), send_arg2
);
981 case 's': case 'S': { /* %s */
982 const HChar
*str
= va_arg (vargs
, HChar
*);
983 if (str
== NULL
) str
= "(null)";
984 ret
+= myvprintf_str(send
, send_arg2
,
985 flags
, width
, str
, format
[i
]=='S');
989 /* Print a floating point number in the format x.y without
990 any exponent. Capabilities are extremely limited, basically
991 a joke, but good enough for our needs. */
992 Double val
= va_arg (vargs
, Double
);
993 Bool is_negative
= False
;
1000 /* If the integral part of the floating point number cannot be
1001 represented by an ULONG_MAX, print '*' characters */
1002 if (val
> (Double
)(~0ULL)) {
1003 if (width
== 0) width
= 6; // say
1004 for (cnt
= 0; cnt
< width
; ++cnt
)
1005 send('*', send_arg2
);
1009 /* The integral part of the floating point number is representable
1012 Double frac
= val
- ipval
;
1014 if (precision
== -1) precision
= 6; // say
1016 /* Silently limit the precision to 10 digits. */
1017 if (precision
> 10) precision
= 10;
1019 /* Determine fractional part, possibly round up */
1021 for (cnt
= 0; cnt
< precision
; ++cnt
)
1023 ULong frval
= frac
* factor
;
1024 if ((frac
* factor
- frval
) > 0.5) // round up
1026 /* Check rounding. */
1027 if (frval
== factor
)
1031 /* Find out how many characters are needed to print the number */
1033 /* The integral part... */
1034 UInt ipwidth
, num_digit
= 1; // at least one digit
1036 for (x
= 10; ; old_x
= x
, x
*= 10, ++num_digit
) {
1037 if (x
<= old_x
) break; // overflow occurred
1038 if (ipval
< x
) break;
1040 ipwidth
= num_digit
; // width of integral part.
1041 if (is_negative
) ++num_digit
;
1043 num_digit
+= 1 + precision
;
1047 // Fill in blanks on the left
1048 if (num_digit
< width
&& (flags
& VG_MSG_LJUSTIFY
) == 0) {
1049 for (cnt
= 0; cnt
< width
- num_digit
; ++cnt
)
1050 send(' ', send_arg2
);
1051 ret
+= width
- num_digit
;
1055 send('-', send_arg2
);
1059 ret
+= myvprintf_int64(send
, send_arg2
, 0, 10, ipwidth
, False
,
1061 // Decimal point and fractional part
1062 if (precision
!= 0) {
1063 send('.', send_arg2
);
1066 ret
+= myvprintf_int64(send
, send_arg2
, VG_MSG_ZJUSTIFY
, 10,
1067 precision
, False
, frval
);
1069 // Fill in blanks on the right
1070 if (num_digit
< width
&& (flags
& VG_MSG_LJUSTIFY
) != 0) {
1071 for (cnt
= 0; cnt
< width
- num_digit
; ++cnt
)
1072 send(' ', send_arg2
);
1073 ret
+= width
- num_digit
;
1078 // case 'y': { /* %y - print symbol */
1079 // Addr a = va_arg(vargs, Addr);
1082 // if (VG_(get_fnname_w_offset)(a, &name)) {
1083 // HChar buf[1 + VG_strlen(name) + 1 + 1];
1084 // if (flags & VG_MSG_PAREN) {
1085 // VG_(sprintf)(str, "(%s)", name):
1087 // VG_(sprintf)(str, "%s", name):
1089 // ret += myvprintf_str(send, flags, width, buf, 0);
1101 /*------------------------------------------------------------*/
1102 /*--- Debuglog stuff. ---*/
1103 /*------------------------------------------------------------*/
1105 /* Only print messages whose stated level is less than or equal to
1106 this. By default, it makes this entire subsystem silent. */
1108 static Int loglevel
= 0;
1110 /* Module startup. */
1112 void VG_(debugLog_startup
) ( Int level
, const HChar
* who
)
1114 if (level
< 0) level
= 0;
1115 if (level
> 10) level
= 10;
1117 VG_(debugLog
)(1, "debuglog",
1118 "DebugLog system started by %s, "
1119 "level %d logging requested\n",
1123 /* Get the logging threshold level, as set by the most recent call to
1124 VG_(debugLog_startup), or zero if there have been no such calls so
1127 Int
VG_(debugLog_getLevel
) ( void )
1142 static void add_to_buf ( HChar c
, void* p
)
1144 printf_buf
* buf
= (printf_buf
*)p
;
1146 if (buf
->n
>= 100-10 /*paranoia*/ ) {
1147 emit( buf
->buf
, local_strlen(buf
->buf
) );
1149 buf
->buf
[buf
->n
] = 0;
1151 buf
->buf
[buf
->n
++] = c
;
1152 buf
->buf
[buf
->n
] = 0;
1155 /* Send a logging message. Nothing is output unless 'level'
1156 is <= the current loglevel. */
1158 void VG_(debugLog
) ( Int level
, const HChar
* modulename
,
1159 const HChar
* format
, ... )
1162 Int indent
, depth
, i
;
1166 if (level
> loglevel
)
1169 indent
= 2*level
- 1;
1170 if (indent
< 1) indent
= 1;
1174 pid
= local_sys_getpid();
1176 // Print one '>' in front of the messages for each level of self-hosting
1178 depth
= RUNNING_ON_VALGRIND
;
1179 for (i
= 0; i
< depth
; i
++) {
1180 (void)myvprintf_str ( add_to_buf
, &buf
, 0, 1, ">", False
);
1183 (void)myvprintf_str ( add_to_buf
, &buf
, 0, 2, "--", False
);
1184 (void)myvprintf_int64 ( add_to_buf
, &buf
, 0, 10, 1, False
, (ULong
)pid
);
1185 (void)myvprintf_str ( add_to_buf
, &buf
, 0, 1, ":", False
);
1186 (void)myvprintf_int64 ( add_to_buf
, &buf
, 0, 10, 1, False
, (ULong
)level
);
1187 (void)myvprintf_str ( add_to_buf
, &buf
, 0, 1, ":", False
);
1188 (void)myvprintf_str ( add_to_buf
, &buf
, 0, 8, modulename
, False
);
1189 (void)myvprintf_str ( add_to_buf
, &buf
, 0, indent
, "", False
);
1191 va_start(vargs
,format
);
1193 (void) VG_(debugLog_vprintf
) ( add_to_buf
, &buf
, format
, vargs
);
1196 emit( buf
.buf
, local_strlen(buf
.buf
) );
1204 /*--------------------------------------------------------------------*/
1205 /*--- end m_debuglog.c ---*/
1206 /*--------------------------------------------------------------------*/