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)
442 static UInt
local_sys_write_stderr ( const HChar
* buf
, Int n
)
444 volatile Int block
[2];
448 "li $4, 2\n\t" /* stderr */
449 "lw $5, 0(%0)\n\t" /* buf */
450 "lw $6, 4(%0)\n\t" /* n */
452 "li $2, %1\n\t" /* set v0 = __NR_write */
453 "syscall\n\t" /* write() */
456 : "r" (block
), "n" (__NR_write
)
457 : "2", "4", "5", "6", "7"
461 return (UInt
)block
[0];
464 static UInt
local_sys_getpid ( void )
468 "li $2, %1\n\t" /* set v0 = __NR_getpid */
469 "syscall\n\t" /* getpid() */
478 #elif defined(VGP_mips64_linux)
480 static UInt
local_sys_write_stderr ( const HChar
* buf
, Int n
)
482 volatile Long block
[2];
483 block
[0] = (Long
)buf
;
486 "li $4, 2\n\t" /* std output*/
487 "ld $5, 0(%0)\n\t" /*$5 = buf*/
488 "ld $6, 8(%0)\n\t" /*$6 = n */
490 "li $2, %1\n\t" /* set v0 = __NR_write */
494 : /*rd*/ "r" (block
), "n" (__NR_write
)
495 : "2", "4", "5", "6", "7"
499 return (UInt
)(Int
)block
[0];
502 static UInt
local_sys_getpid ( void )
506 "li $2, %1\n\t" /* set v0 = __NR_getpid */
507 "syscall\n\t" /* getpid() */
513 return (UInt
)(__res
);
516 #elif defined(VGP_x86_solaris)
517 static UInt
local_sys_write_stderr ( const HChar
* buf
, Int n
)
523 /* The Solaris kernel does not restart syscalls automatically so it is
525 __asm__
__volatile__ (
526 "movl %[n], %%eax\n" /* push n */
528 "movl %[buf], %%eax\n" /* push buf */
530 "movl $2, %%eax\n" /* push stderr */
532 "movl $"VG_STRINGIFY(__NR_write
)", %%eax\n"
533 "pushl %%eax\n" /* push fake return address */
534 "int $0x91\n" /* write(stderr, buf, n) */
535 "movl $0, %%edx\n" /* assume no error */
536 "jnc 1f\n" /* jump if no error */
537 "movl $1, %%edx\n" /* set error flag */
539 "addl $16, %%esp\n" /* pop x4 */
540 : "=&a" (res
), "=d" (err
)
541 : [buf
] "g" (buf
), [n
] "g" (n
)
543 restart
= err
&& (res
== VKI_EINTR
|| res
== VKI_ERESTART
);
549 static UInt
local_sys_getpid ( void )
553 /* The getpid() syscall never returns EINTR or ERESTART so there is no need
554 for restarting it. */
555 __asm__
__volatile__ (
556 "movl $"VG_STRINGIFY(__NR_getpid
)", %%eax\n"
557 "int $0x91\n" /* getpid() */
565 #elif defined(VGP_amd64_solaris)
566 static UInt
local_sys_write_stderr ( const HChar
* buf
, Int n
)
572 /* The Solaris kernel does not restart syscalls automatically so it is
574 __asm__
__volatile__ (
575 "movq $2, %%rdi\n" /* push stderr */
576 "movq $"VG_STRINGIFY(__NR_write
)", %%rax\n"
577 "syscall\n" /* write(stderr, buf, n) */
578 "movq $0, %%rdx\n" /* assume no error */
579 "jnc 1f\n" /* jump if no error */
580 "movq $1, %%rdx\n" /* set error flag */
582 : "=a" (res
), "=d" (err
)
585 restart
= err
&& (res
== VKI_EINTR
|| res
== VKI_ERESTART
);
591 static UInt
local_sys_getpid ( void )
595 /* The getpid() syscall never returns EINTR or ERESTART so there is no need
596 for restarting it. */
597 __asm__
__volatile__ (
598 "movq $"VG_STRINGIFY(__NR_getpid
)", %%rax\n"
599 "syscall\n" /* getpid() */
608 # error Unknown platform
612 /* ----- generic ----- */
614 /* strlen, so we don't need m_libc */
615 static Int
local_strlen ( const HChar
* str
)
618 while (str
[i
] != 0) i
++;
622 static HChar
local_toupper ( HChar c
)
624 if (c
>= 'a' && c
<= 'z')
625 return c
+ ('A' - 'a');
630 /* Emit buf[0 .. n-1] to stderr. Unfortunately platform-specific.
632 static void emit ( const HChar
* buf
, Int n
)
635 (void)local_sys_write_stderr(buf
, n
);
639 /*------------------------------------------------------------*/
640 /*--- A simple, generic, vprintf implementation. ---*/
641 /*------------------------------------------------------------*/
643 /* -----------------------------------------------
644 Distantly derived from:
646 vprintf replacement for Checker.
647 Copyright 1993, 1994, 1995 Tristan Gingold
648 Written September 1993 Tristan Gingold
649 Tristan Gingold, 8 rue Parmentier, F-91120 PALAISEAU, FRANCE
651 (Checker itself was GPL'd.)
652 ----------------------------------------------- */
655 #define VG_MSG_SIGNED 1 /* The value is signed. */
656 #define VG_MSG_ZJUSTIFY 2 /* Must justify with '0'. */
657 #define VG_MSG_LJUSTIFY 4 /* Must justify on the left. */
658 #define VG_MSG_PAREN 8 /* Parenthesize if present (for %y) */
659 #define VG_MSG_COMMA 16 /* Add commas to numbers (for %d, %u) */
660 #define VG_MSG_ALTFORMAT 32 /* Convert the value to alternate format */
662 /* Copy a string into the buffer. */
664 UInt
myvprintf_str ( void(*send
)(HChar
,void*),
671 # define MAYBE_TOUPPER(ch) (capitalise ? local_toupper(ch) : (ch))
674 Int len
= local_strlen(str
);
678 for (i
= 0; i
< len
; i
++)
679 send(MAYBE_TOUPPER(str
[i
]), send_arg2
);
685 for (i
= 0; i
< width
; i
++)
686 send(MAYBE_TOUPPER(str
[i
]), send_arg2
);
691 if (! (flags
& VG_MSG_LJUSTIFY
)) {
693 for (i
= 0; i
< extra
; i
++)
694 send(' ', send_arg2
);
697 for (i
= 0; i
< len
; i
++)
698 send(MAYBE_TOUPPER(str
[i
]), send_arg2
);
699 if (flags
& VG_MSG_LJUSTIFY
) {
701 for (i
= 0; i
< extra
; i
++)
702 send(' ', send_arg2
);
705 # undef MAYBE_TOUPPER
710 /* Copy a string into the buffer, escaping bad XML chars. */
712 UInt
myvprintf_str_XML_simplistic ( void(*send
)(HChar
,void*),
718 Int len
= local_strlen(str
);
721 for (i
= 0; i
< len
; i
++) {
723 case '&': alt
= "&"; break;
724 case '<': alt
= "<"; break;
725 case '>': alt
= ">"; break;
731 send(*alt
, send_arg2
);
736 send(str
[i
], send_arg2
);
745 /* Write P into the buffer according to these args:
746 * If SIGN is true, p is a signed.
748 * If WITH_ZERO is true, '0' must be added.
749 * WIDTH is the width of the field.
752 UInt
myvprintf_int64 ( void(*send
)(HChar
,void*),
760 /* To print an ULong base 2 needs 64 characters. If commas are requested,
761 add 21. Plus 1 for a possible sign plus 1 for \0. Makes 87 -- so let's
762 say 90. The size of BUF needs to be max(90, WIDTH + 1) */
763 HChar buf
[width
+ 1 > 90 ? width
+ 1 : 90];
767 const HChar
* digits
= capitalised
? "0123456789ABCDEF" : "0123456789abcdef";
770 if (base
< 2 || base
> 16)
773 if ((flags
& VG_MSG_SIGNED
) && (Long
)p
< 0) {
782 if (flags
& VG_MSG_COMMA
&& 10 == base
&&
783 0 == (ind
-nc
) % 3 && 0 != ind
)
788 buf
[ind
++] = digits
[p
% base
];
796 if (width
> 0 && !(flags
& VG_MSG_LJUSTIFY
)) {
797 for(; ind
< width
; ind
++) {
798 buf
[ind
] = (flags
& VG_MSG_ZJUSTIFY
) ? '0': ' ';
802 /* Reverse copy to buffer. */
804 for (i
= ind
-1; i
>= 0; i
--) {
805 send(buf
[i
], send_arg2
);
807 if (width
> 0 && (flags
& VG_MSG_LJUSTIFY
)) {
808 for(; ind
< width
; ind
++) {
810 /* Never pad with zeroes on RHS -- changes the value! */
811 send(' ', send_arg2
);
818 /* A simple vprintf(). */
821 VG_(debugLog_vprintf
) (
822 void(*send
)(HChar
,void*),
831 Int width
, precision
;
833 Bool is_long
, is_sizet
, caps
;
835 /* We assume that vargs has already been initialised by the
836 caller, using va_start, and that the caller will similarly
837 clean up with va_end.
840 for (i
= 0; format
[i
] != 0; i
++) {
841 if (format
[i
] != '%') {
842 send(format
[i
], send_arg2
);
847 /* A '%' has been found. Ignore a trailing %. */
850 if (format
[i
] == '%') {
851 /* '%%' is replaced by '%'. */
852 send('%', send_arg2
);
858 width
= 0; /* length of the field. */
859 precision
= -1; /* unspecified precision */
863 flags
|= VG_MSG_PAREN
;
867 /* If ',' or '\'' follows '%', commas will be inserted. */
868 flags
|= VG_MSG_COMMA
;
871 /* If '-' follows '%', justify on the left. */
872 flags
|= VG_MSG_LJUSTIFY
;
875 /* If '0' follows '%', pads will be inserted. */
876 flags
|= VG_MSG_ZJUSTIFY
;
879 /* If '#' follows '%', alternative format will be used. */
880 flags
|= VG_MSG_ALTFORMAT
;
883 goto parse_fieldwidth
;
888 /* Compute the field length. */
889 if (format
[i
] == '*') {
890 width
= va_arg(vargs
, Int
);
893 while (format
[i
] >= '0' && format
[i
] <= '9') {
895 width
+= format
[i
++] - '0';
898 /* Parse precision, if any. Only meaningful for %f. For all other
899 format specifiers the precision will be silently ignored. */
900 if (format
[i
] == '.') {
902 if (format
[i
] == '*') {
903 precision
= va_arg(vargs
, Int
);
907 while (format
[i
] >= '0' && format
[i
] <= '9') {
909 precision
+= format
[i
++] - '0';
915 if (format
[i
] == 'z') {
919 while (format
[i
] == 'l') {
925 // %d means print a 32-bit integer.
926 // %ld means print a word-size integer.
927 // %lld means print a 64-bit integer.
928 if (0 == n_ls
) { is_long
= False
; }
929 else if (1 == n_ls
) { is_long
= ( sizeof(void*) == sizeof(Long
) ); }
930 else { is_long
= True
; }
934 if (flags
& VG_MSG_ALTFORMAT
) {
939 ret
+= myvprintf_int64(send
, send_arg2
, flags
, 8, width
, False
,
940 (ULong
)(va_arg (vargs
, SizeT
)));
942 ret
+= myvprintf_int64(send
, send_arg2
, flags
, 8, width
, False
,
943 (ULong
)(va_arg (vargs
, ULong
)));
945 ret
+= myvprintf_int64(send
, send_arg2
, flags
, 8, width
, False
,
946 (ULong
)(va_arg (vargs
, UInt
)));
949 flags
|= VG_MSG_SIGNED
;
951 ret
+= myvprintf_int64(send
, send_arg2
, flags
, 10, width
, False
,
952 (ULong
)(va_arg (vargs
, Long
)));
954 ret
+= myvprintf_int64(send
, send_arg2
, flags
, 10, width
, False
,
955 (ULong
)(va_arg (vargs
, Int
)));
959 ret
+= myvprintf_int64(send
, send_arg2
, flags
, 10, width
, False
,
960 (ULong
)(va_arg (vargs
, SizeT
)));
962 ret
+= myvprintf_int64(send
, send_arg2
, flags
, 10, width
, False
,
963 (ULong
)(va_arg (vargs
, ULong
)));
965 ret
+= myvprintf_int64(send
, send_arg2
, flags
, 10, width
, False
,
966 (ULong
)(va_arg (vargs
, UInt
)));
969 if (format
[i
+1] == 'S') {
971 /* %pS, like %s but escaping chars for XML safety */
972 /* Note: simplistic; ignores field width and flags */
973 const HChar
*str
= va_arg (vargs
, HChar
*);
976 ret
+= myvprintf_str_XML_simplistic(send
, send_arg2
, str
);
977 } else if (format
[i
+1] == 's') {
979 /* %ps, synonym for %s with --xml=no / %pS with --xml=yes */
980 const HChar
*str
= va_arg (vargs
, HChar
*);
984 ret
+= myvprintf_str_XML_simplistic(send
, send_arg2
, str
);
986 ret
+= myvprintf_str(send
, send_arg2
, flags
, width
, str
,
993 ret
+= myvprintf_int64(send
, send_arg2
, flags
, 16, width
, True
,
994 (ULong
)((UWord
)va_arg (vargs
, void *)));
999 caps
= toBool(format
[i
] == 'X');
1000 if (flags
& VG_MSG_ALTFORMAT
) {
1002 send('0',send_arg2
);
1003 send('x',send_arg2
);
1006 ret
+= myvprintf_int64(send
, send_arg2
, flags
, 16, width
, False
,
1007 (ULong
)(va_arg (vargs
, SizeT
)));
1009 ret
+= myvprintf_int64(send
, send_arg2
, flags
, 16, width
, caps
,
1010 (ULong
)(va_arg (vargs
, ULong
)));
1012 ret
+= myvprintf_int64(send
, send_arg2
, flags
, 16, width
, caps
,
1013 (ULong
)(va_arg (vargs
, UInt
)));
1017 send(va_arg (vargs
, int), send_arg2
);
1019 case 's': case 'S': { /* %s */
1020 const HChar
*str
= va_arg (vargs
, HChar
*);
1021 if (str
== NULL
) str
= "(null)";
1022 ret
+= myvprintf_str(send
, send_arg2
,
1023 flags
, width
, str
, format
[i
]=='S');
1027 /* Print a floating point number in the format x.y without
1028 any exponent. Capabilities are extremely limited, basically
1029 a joke, but good enough for our needs. */
1030 Double val
= va_arg (vargs
, Double
);
1031 Bool is_negative
= False
;
1038 /* If the integral part of the floating point number cannot be
1039 represented by an ULONG_MAX, print '*' characters */
1040 if (val
> (Double
)(~0ULL)) {
1041 if (width
== 0) width
= 6; // say
1042 for (cnt
= 0; cnt
< width
; ++cnt
)
1043 send('*', send_arg2
);
1047 /* The integral part of the floating point number is representable
1050 Double frac
= val
- ipval
;
1052 if (precision
== -1) precision
= 6; // say
1054 /* Silently limit the precision to 10 digits. */
1055 if (precision
> 10) precision
= 10;
1057 /* Determine fractional part, possibly round up */
1059 for (cnt
= 0; cnt
< precision
; ++cnt
)
1061 ULong frval
= frac
* factor
;
1062 if ((frac
* factor
- frval
) > 0.5) // round up
1064 /* Check rounding. */
1065 if (frval
== factor
)
1069 /* Find out how many characters are needed to print the number */
1071 /* The integral part... */
1072 UInt ipwidth
, num_digit
= 1; // at least one digit
1074 for (x
= 10; ; old_x
= x
, x
*= 10, ++num_digit
) {
1075 if (x
<= old_x
) break; // overflow occurred
1076 if (ipval
< x
) break;
1078 ipwidth
= num_digit
; // width of integral part.
1079 if (is_negative
) ++num_digit
;
1081 num_digit
+= 1 + precision
;
1085 // Fill in blanks on the left
1086 if (num_digit
< width
&& (flags
& VG_MSG_LJUSTIFY
) == 0) {
1087 for (cnt
= 0; cnt
< width
- num_digit
; ++cnt
)
1088 send(' ', send_arg2
);
1089 ret
+= width
- num_digit
;
1093 send('-', send_arg2
);
1097 ret
+= myvprintf_int64(send
, send_arg2
, 0, 10, ipwidth
, False
,
1099 // Decimal point and fractional part
1100 if (precision
!= 0) {
1101 send('.', send_arg2
);
1104 ret
+= myvprintf_int64(send
, send_arg2
, VG_MSG_ZJUSTIFY
, 10,
1105 precision
, False
, frval
);
1107 // Fill in blanks on the right
1108 if (num_digit
< width
&& (flags
& VG_MSG_LJUSTIFY
) != 0) {
1109 for (cnt
= 0; cnt
< width
- num_digit
; ++cnt
)
1110 send(' ', send_arg2
);
1111 ret
+= width
- num_digit
;
1116 // case 'y': { /* %y - print symbol */
1117 // Addr a = va_arg(vargs, Addr);
1120 // if (VG_(get_fnname_w_offset)(a, &name)) {
1121 // HChar buf[1 + VG_strlen(name) + 1 + 1];
1122 // if (flags & VG_MSG_PAREN) {
1123 // VG_(sprintf)(str, "(%s)", name):
1125 // VG_(sprintf)(str, "%s", name):
1127 // ret += myvprintf_str(send, flags, width, buf, 0);
1139 /*------------------------------------------------------------*/
1140 /*--- Debuglog stuff. ---*/
1141 /*------------------------------------------------------------*/
1143 /* Only print messages whose stated level is less than or equal to
1144 this. By default, it makes this entire subsystem silent. */
1146 static Int loglevel
= 0;
1148 /* Module startup. */
1150 void VG_(debugLog_startup
) ( Int level
, const HChar
* who
)
1152 if (level
< 0) level
= 0;
1153 if (level
> 10) level
= 10;
1155 VG_(debugLog
)(1, "debuglog",
1156 "DebugLog system started by %s, "
1157 "level %d logging requested\n",
1161 /* Get the logging threshold level, as set by the most recent call to
1162 VG_(debugLog_startup), or zero if there have been no such calls so
1165 Int
VG_(debugLog_getLevel
) ( void )
1180 static void add_to_buf ( HChar c
, void* p
)
1182 printf_buf
* buf
= (printf_buf
*)p
;
1184 if (buf
->n
>= 100-10 /*paranoia*/ ) {
1185 emit( buf
->buf
, local_strlen(buf
->buf
) );
1187 buf
->buf
[buf
->n
] = 0;
1189 buf
->buf
[buf
->n
++] = c
;
1190 buf
->buf
[buf
->n
] = 0;
1193 /* Send a logging message. Nothing is output unless 'level'
1194 is <= the current loglevel. */
1196 void VG_(debugLog
) ( Int level
, const HChar
* modulename
,
1197 const HChar
* format
, ... )
1200 Int indent
, depth
, i
;
1204 if (level
> loglevel
)
1207 indent
= 2*level
- 1;
1208 if (indent
< 1) indent
= 1;
1212 pid
= local_sys_getpid();
1214 // Print one '>' in front of the messages for each level of self-hosting
1216 depth
= RUNNING_ON_VALGRIND
;
1217 for (i
= 0; i
< depth
; i
++) {
1218 (void)myvprintf_str ( add_to_buf
, &buf
, 0, 1, ">", False
);
1221 (void)myvprintf_str ( add_to_buf
, &buf
, 0, 2, "--", False
);
1222 (void)myvprintf_int64 ( add_to_buf
, &buf
, 0, 10, 1, False
, (ULong
)pid
);
1223 (void)myvprintf_str ( add_to_buf
, &buf
, 0, 1, ":", False
);
1224 (void)myvprintf_int64 ( add_to_buf
, &buf
, 0, 10, 1, False
, (ULong
)level
);
1225 (void)myvprintf_str ( add_to_buf
, &buf
, 0, 1, ":", False
);
1226 (void)myvprintf_str ( add_to_buf
, &buf
, 0, 8, modulename
, False
);
1227 (void)myvprintf_str ( add_to_buf
, &buf
, 0, indent
, "", False
);
1229 va_start(vargs
,format
);
1231 (void) VG_(debugLog_vprintf
) ( add_to_buf
, &buf
, format
, vargs
);
1234 emit( buf
.buf
, local_strlen(buf
.buf
) );
1242 /*--------------------------------------------------------------------*/
1243 /*--- end m_debuglog.c ---*/
1244 /*--------------------------------------------------------------------*/