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-2015 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"
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 */
153 #elif defined(VGP_ppc32_linux)
155 static UInt
local_sys_write_stderr ( const HChar
* buf
, Int n
)
157 volatile Int block
[2];
162 "mr 5,%0\n\t" /* r5 = &block[0] */
163 "stw 5,0(1)\n\t" /* stash on stack */
164 "li 0,"VG_STRINGIFY(__NR_write
)"\n\t" /* set %r0 = __NR_write */
165 "li 3,2\n\t" /* set %r3 = stderr */
166 "lwz 4,0(5)\n\t" /* set %r4 = buf */
167 "lwz 5,4(5)\n\t" /* set %r5 = n */
168 "sc\n\t" /* write(stderr, buf, n) */
171 "stw 3,0(5)\n" /* block[0] = result */
174 : "cc","memory","cr0","ctr",
175 "r0","r2","r3","r4","r5","r6","r7","r8","r9","r10","r11","r12"
179 return (UInt
)block
[0];
182 static UInt
local_sys_getpid ( void )
184 register UInt __res
__asm__ ("r3");
190 : "cc","memory","cr0","ctr",
191 "r0","r2","r4","r5","r6","r7","r8","r9","r10","r11","r12"
196 #elif defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux)
198 static UInt
local_sys_write_stderr ( const HChar
* buf
, Int n
)
200 volatile Long block
[2];
201 block
[0] = (Long
)buf
;
205 "mr 5,%0\n\t" /* r5 = &block[0] */
206 "std 5,0(1)\n\t" /* stash on stack */
207 "li 0,"VG_STRINGIFY(__NR_write
)"\n\t" /* %r0 = __NR_write */
208 "li 3,2\n\t" /* set %r3 = stderr */
209 "ld 4,0(5)\n\t" /* set %r4 = buf */
210 "ld 5,8(5)\n\t" /* set %r5 = n */
211 "sc\n\t" /* write(stderr, buf, n) */
214 "std 3,0(5)\n" /* block[0] = result */
217 : "cc","memory","cr0","ctr",
218 "r0","r2","r3","r4","r5","r6","r7","r8","r9","r10","r11","r12"
222 return (UInt
)(Int
)block
[0];
225 static UInt
local_sys_getpid ( void )
227 register ULong __res
__asm__ ("r3");
233 : "cc","memory","cr0","ctr",
234 "r0","r2","r4","r5","r6","r7","r8","r9","r10","r11","r12"
239 #elif defined(VGP_arm_linux)
241 static UInt
local_sys_write_stderr ( const HChar
* buf
, Int n
)
243 volatile Int block
[2];
247 "mov r0, #2\n\t" /* stderr */
248 "ldr r1, [%0]\n\t" /* buf */
249 "ldr r2, [%0, #4]\n\t" /* n */
251 "mov r7, #"VG_STRINGIFY(__NR_write
)"\n\t"
252 "svc 0x0\n" /* write() */
261 return (UInt
)block
[0];
264 static UInt
local_sys_getpid ( void )
269 "mov r7, #"VG_STRINGIFY(__NR_getpid
)"\n\t"
270 "svc 0x0\n\t" /* getpid() */
279 #elif defined(VGP_arm64_linux)
281 static UInt
local_sys_write_stderr ( const HChar
* buf
, Int n
)
283 volatile ULong block
[2];
284 block
[0] = (ULong
)buf
;
287 "mov x0, #2\n\t" /* stderr */
288 "ldr x1, [%0]\n\t" /* buf */
289 "ldr x2, [%0, #8]\n\t" /* n */
290 "mov x8, #"VG_STRINGIFY(__NR_write
)"\n\t"
291 "svc 0x0\n" /* write() */
295 : "x0","x1","x2","x7"
299 return (UInt
)block
[0];
302 static UInt
local_sys_getpid ( void )
306 "mov x8, #"VG_STRINGIFY(__NR_getpid
)"\n"
307 "svc 0x0\n" /* getpid() */
315 #elif defined(VGP_x86_darwin)
317 /* We would use VG_DARWIN_SYSNO_TO_KERNEL instead of VG_DARWIN_SYSNO_INDEX
318 except that the former has a C ternary ?: operator which isn't valid in
319 asm code. Both macros give the same results for Unix-class syscalls (which
320 these all are, as identified by the use of 'int 0x80'). */
321 __attribute__((noinline
))
322 static UInt
local_sys_write_stderr ( const HChar
* buf
, Int n
)
326 "movl %2, %%eax\n" /* push n */
328 "movl %1, %%eax\n" /* push buf */
330 "movl $2, %%eax\n" /* push stderr */
332 "movl $"VG_STRINGIFY(VG_DARWIN_SYSNO_INDEX(__NR_write_nocancel
))
334 "pushl %%eax\n" /* push fake return address */
335 "int $0x80\n" /* write(stderr, buf, n) */
336 "jnc 1f\n" /* jump if no error */
337 "movl $-1, %%eax\n" /* return -1 if error */
339 "movl %%eax, %0\n" /* __res = eax */
340 "addl $16, %%esp\n" /* pop x4 */
348 static UInt
local_sys_getpid ( void )
352 "movl $"VG_STRINGIFY(VG_DARWIN_SYSNO_INDEX(__NR_getpid
))", %%eax\n"
353 "int $0x80\n" /* getpid() */
354 "movl %%eax, %0\n" /* set __res = eax */
361 #elif defined(VGP_amd64_darwin)
363 __attribute__((noinline
))
364 static UInt
local_sys_write_stderr ( const HChar
* buf
, Int n
)
368 "movq $2, %%rdi\n" /* push stderr */
369 "movq %1, %%rsi\n" /* push buf */
370 "movl %2, %%edx\n" /* push n */
371 "movl $"VG_STRINGIFY(VG_DARWIN_SYSNO_FOR_KERNEL(__NR_write_nocancel
))
373 "syscall\n" /* write(stderr, buf, n) */
374 "jnc 1f\n" /* jump if no error */
375 "movq $-1, %%rax\n" /* return -1 if error */
377 "movl %%eax, %0\n" /* __res = eax */
380 : "rdi", "rsi", "rdx", "rcx", "rax", "cc" );
384 static UInt
local_sys_getpid ( void )
388 "movl $"VG_STRINGIFY(VG_DARWIN_SYSNO_FOR_KERNEL(__NR_getpid
))", %%eax\n"
389 "syscall\n" /* getpid() */
390 "movl %%eax, %0\n" /* set __res = eax */
393 : "rax", "rcx", "cc" );
397 #elif defined(VGP_s390x_linux)
399 static UInt
local_sys_write_stderr ( const HChar
* buf
, Int n
)
401 register Int r2
asm("2") = 2; /* file descriptor STDERR */
402 register const HChar
* r3
asm("3") = buf
;
403 register ULong r4
asm("4") = n
;
404 register ULong r2_res
asm("2");
407 __asm__
__volatile__ (
417 if (__res
>= (ULong
)(-125))
419 return (UInt
)(__res
);
422 static UInt
local_sys_getpid ( void )
424 register ULong r2
asm("2");
427 __asm__
__volatile__ (
434 if (__res
>= (ULong
)(-125))
436 return (UInt
)(__res
);
439 #elif defined(VGP_mips32_linux)
441 static UInt
local_sys_write_stderr ( const HChar
* buf
, Int n
)
443 volatile Int block
[2];
447 "li $4, 2\n\t" /* stderr */
448 "lw $5, 0(%0)\n\t" /* buf */
449 "lw $6, 4(%0)\n\t" /* n */
451 "li $2, %1\n\t" /* set v0 = __NR_write */
452 "syscall\n\t" /* write() */
455 : "r" (block
), "n" (__NR_write
)
456 : "2", "4", "5", "6", "7"
460 return (UInt
)block
[0];
463 static UInt
local_sys_getpid ( void )
467 "li $2, %1\n\t" /* set v0 = __NR_getpid */
468 "syscall\n\t" /* getpid() */
477 #elif defined(VGP_mips64_linux)
479 static UInt
local_sys_write_stderr ( const HChar
* buf
, Int n
)
481 volatile Long block
[2];
482 block
[0] = (Long
)buf
;
485 "li $4, 2\n\t" /* std output*/
486 "ld $5, 0(%0)\n\t" /*$5 = buf*/
487 "ld $6, 8(%0)\n\t" /*$6 = n */
489 "li $2, %1\n\t" /* set v0 = __NR_write */
493 : /*rd*/ "r" (block
), "n" (__NR_write
)
494 : "2", "4", "5", "6", "7"
498 return (UInt
)(Int
)block
[0];
501 static UInt
local_sys_getpid ( void )
505 "li $2, %1\n\t" /* set v0 = __NR_getpid */
506 "syscall\n\t" /* getpid() */
512 return (UInt
)(__res
);
515 #elif defined(VGP_tilegx_linux)
517 static UInt
local_sys_write_stderr ( const HChar
* buf
, Int n
)
519 volatile Long block
[2];
520 block
[0] = (Long
)buf
;
524 "movei r0, 2 \n\t" /* stderr */
525 "move r1, %1 \n\t" /* buf */
526 "move r2, %2 \n\t" /* n */
528 "moveli r10, %3 \n\t" /* set r10 = __NR_write */
529 "swint1 \n\t" /* write() */
531 "move %0, r0 \n\t" /* save return into block[0] */
533 : "r" (block
[0]), "r"(block
[1]), "n" (__NR_write
)
534 : "r0", "r1", "r2", "r3", "r4", "r5");
540 static UInt
local_sys_getpid ( void )
546 "moveli r10, %2\n\t" /* set r10 = __NR_getpid */
547 "swint1\n\t" /* getpid() */
551 : "=r" (__res
), "=r"(__err
)
553 : "r0", "r1", "r2", "r3", "r4",
554 "r5", "r6", "r7", "r8", "r9",
555 "r10", "r11", "r12", "r13", "r14",
556 "r15", "r16", "r17", "r18", "r19",
557 "r20", "r21", "r22", "r23", "r24",
558 "r25", "r26", "r27", "r28", "r29");
562 #elif defined(VGP_x86_solaris)
563 static UInt
local_sys_write_stderr ( const HChar
* buf
, Int n
)
569 /* The Solaris kernel does not restart syscalls automatically so it is
571 __asm__
__volatile__ (
572 "movl %[n], %%eax\n" /* push n */
574 "movl %[buf], %%eax\n" /* push buf */
576 "movl $2, %%eax\n" /* push stderr */
578 "movl $"VG_STRINGIFY(__NR_write
)", %%eax\n"
579 "pushl %%eax\n" /* push fake return address */
580 "int $0x91\n" /* write(stderr, buf, n) */
581 "movl $0, %%edx\n" /* assume no error */
582 "jnc 1f\n" /* jump if no error */
583 "movl $1, %%edx\n" /* set error flag */
585 "addl $16, %%esp\n" /* pop x4 */
586 : "=&a" (res
), "=d" (err
)
587 : [buf
] "g" (buf
), [n
] "g" (n
)
589 restart
= err
&& (res
== VKI_EINTR
|| res
== VKI_ERESTART
);
595 static UInt
local_sys_getpid ( void )
599 /* The getpid() syscall never returns EINTR or ERESTART so there is no need
600 for restarting it. */
601 __asm__
__volatile__ (
602 "movl $"VG_STRINGIFY(__NR_getpid
)", %%eax\n"
603 "int $0x91\n" /* getpid() */
611 #elif defined(VGP_amd64_solaris)
612 static UInt
local_sys_write_stderr ( const HChar
* buf
, Int n
)
618 /* The Solaris kernel does not restart syscalls automatically so it is
620 __asm__
__volatile__ (
621 "movq $2, %%rdi\n" /* push stderr */
622 "movq $"VG_STRINGIFY(__NR_write
)", %%rax\n"
623 "syscall\n" /* write(stderr, buf, n) */
624 "movq $0, %%rdx\n" /* assume no error */
625 "jnc 1f\n" /* jump if no error */
626 "movq $1, %%rdx\n" /* set error flag */
628 : "=a" (res
), "=d" (err
)
631 restart
= err
&& (res
== VKI_EINTR
|| res
== VKI_ERESTART
);
637 static UInt
local_sys_getpid ( void )
641 /* The getpid() syscall never returns EINTR or ERESTART so there is no need
642 for restarting it. */
643 __asm__
__volatile__ (
644 "movq $"VG_STRINGIFY(__NR_getpid
)", %%rax\n"
645 "syscall\n" /* getpid() */
654 # error Unknown platform
658 /* ----- generic ----- */
660 /* strlen, so we don't need m_libc */
661 static Int
local_strlen ( const HChar
* str
)
664 while (str
[i
] != 0) i
++;
668 static HChar
local_toupper ( HChar c
)
670 if (c
>= 'a' && c
<= 'z')
671 return c
+ ('A' - 'a');
676 /* Emit buf[0 .. n-1] to stderr. Unfortunately platform-specific.
678 static void emit ( const HChar
* buf
, Int n
)
681 (void)local_sys_write_stderr(buf
, n
);
685 /*------------------------------------------------------------*/
686 /*--- A simple, generic, vprintf implementation. ---*/
687 /*------------------------------------------------------------*/
689 /* -----------------------------------------------
690 Distantly derived from:
692 vprintf replacement for Checker.
693 Copyright 1993, 1994, 1995 Tristan Gingold
694 Written September 1993 Tristan Gingold
695 Tristan Gingold, 8 rue Parmentier, F-91120 PALAISEAU, FRANCE
697 (Checker itself was GPL'd.)
698 ----------------------------------------------- */
701 #define VG_MSG_SIGNED 1 /* The value is signed. */
702 #define VG_MSG_ZJUSTIFY 2 /* Must justify with '0'. */
703 #define VG_MSG_LJUSTIFY 4 /* Must justify on the left. */
704 #define VG_MSG_PAREN 8 /* Parenthesize if present (for %y) */
705 #define VG_MSG_COMMA 16 /* Add commas to numbers (for %d, %u) */
706 #define VG_MSG_ALTFORMAT 32 /* Convert the value to alternate format */
708 /* Copy a string into the buffer. */
710 UInt
myvprintf_str ( void(*send
)(HChar
,void*),
717 # define MAYBE_TOUPPER(ch) (capitalise ? local_toupper(ch) : (ch))
720 Int len
= local_strlen(str
);
724 for (i
= 0; i
< len
; i
++)
725 send(MAYBE_TOUPPER(str
[i
]), send_arg2
);
731 for (i
= 0; i
< width
; i
++)
732 send(MAYBE_TOUPPER(str
[i
]), send_arg2
);
737 if (! (flags
& VG_MSG_LJUSTIFY
)) {
739 for (i
= 0; i
< extra
; i
++)
740 send(' ', send_arg2
);
743 for (i
= 0; i
< len
; i
++)
744 send(MAYBE_TOUPPER(str
[i
]), send_arg2
);
745 if (flags
& VG_MSG_LJUSTIFY
) {
747 for (i
= 0; i
< extra
; i
++)
748 send(' ', send_arg2
);
751 # undef MAYBE_TOUPPER
756 /* Copy a string into the buffer, escaping bad XML chars. */
758 UInt
myvprintf_str_XML_simplistic ( void(*send
)(HChar
,void*),
764 Int len
= local_strlen(str
);
767 for (i
= 0; i
< len
; i
++) {
769 case '&': alt
= "&"; break;
770 case '<': alt
= "<"; break;
771 case '>': alt
= ">"; break;
777 send(*alt
, send_arg2
);
782 send(str
[i
], send_arg2
);
791 /* Write P into the buffer according to these args:
792 * If SIGN is true, p is a signed.
794 * If WITH_ZERO is true, '0' must be added.
795 * WIDTH is the width of the field.
798 UInt
myvprintf_int64 ( void(*send
)(HChar
,void*),
806 /* To print an ULong base 2 needs 64 characters. If commas are requested,
807 add 21. Plus 1 for a possible sign plus 1 for \0. Makes 87 -- so let's
808 say 90. The size of BUF needs to be max(90, WIDTH + 1) */
809 HChar buf
[width
+ 1 > 90 ? width
+ 1 : 90];
813 const HChar
* digits
= capitalised
? "0123456789ABCDEF" : "0123456789abcdef";
816 if (base
< 2 || base
> 16)
819 if ((flags
& VG_MSG_SIGNED
) && (Long
)p
< 0) {
828 if (flags
& VG_MSG_COMMA
&& 10 == base
&&
829 0 == (ind
-nc
) % 3 && 0 != ind
)
834 buf
[ind
++] = digits
[p
% base
];
842 if (width
> 0 && !(flags
& VG_MSG_LJUSTIFY
)) {
843 for(; ind
< width
; ind
++) {
844 buf
[ind
] = (flags
& VG_MSG_ZJUSTIFY
) ? '0': ' ';
848 /* Reverse copy to buffer. */
850 for (i
= ind
-1; i
>= 0; i
--) {
851 send(buf
[i
], send_arg2
);
853 if (width
> 0 && (flags
& VG_MSG_LJUSTIFY
)) {
854 for(; ind
< width
; ind
++) {
856 /* Never pad with zeroes on RHS -- changes the value! */
857 send(' ', send_arg2
);
864 /* A simple vprintf(). */
867 VG_(debugLog_vprintf
) (
868 void(*send
)(HChar
,void*),
877 Int width
, precision
;
879 Bool is_long
, is_sizet
, caps
;
881 /* We assume that vargs has already been initialised by the
882 caller, using va_start, and that the caller will similarly
883 clean up with va_end.
886 for (i
= 0; format
[i
] != 0; i
++) {
887 if (format
[i
] != '%') {
888 send(format
[i
], send_arg2
);
893 /* A '%' has been found. Ignore a trailing %. */
896 if (format
[i
] == '%') {
897 /* '%%' is replaced by '%'. */
898 send('%', send_arg2
);
904 width
= 0; /* length of the field. */
905 precision
= -1; /* unspecified precision */
909 flags
|= VG_MSG_PAREN
;
913 /* If ',' or '\'' follows '%', commas will be inserted. */
914 flags
|= VG_MSG_COMMA
;
917 /* If '-' follows '%', justify on the left. */
918 flags
|= VG_MSG_LJUSTIFY
;
921 /* If '0' follows '%', pads will be inserted. */
922 flags
|= VG_MSG_ZJUSTIFY
;
925 /* If '#' follows '%', alternative format will be used. */
926 flags
|= VG_MSG_ALTFORMAT
;
929 goto parse_fieldwidth
;
934 /* Compute the field length. */
935 if (format
[i
] == '*') {
936 width
= va_arg(vargs
, Int
);
939 while (format
[i
] >= '0' && format
[i
] <= '9') {
941 width
+= format
[i
++] - '0';
944 /* Parse precision, if any. Only meaningful for %f. For all other
945 format specifiers the precision will be silently ignored. */
946 if (format
[i
] == '.') {
948 if (format
[i
] == '*') {
949 precision
= va_arg(vargs
, Int
);
953 while (format
[i
] >= '0' && format
[i
] <= '9') {
955 precision
+= format
[i
++] - '0';
961 if (format
[i
] == 'z') {
965 while (format
[i
] == 'l') {
971 // %d means print a 32-bit integer.
972 // %ld means print a word-size integer.
973 // %lld means print a 64-bit integer.
974 if (0 == n_ls
) { is_long
= False
; }
975 else if (1 == n_ls
) { is_long
= ( sizeof(void*) == sizeof(Long
) ); }
976 else { is_long
= True
; }
980 if (flags
& VG_MSG_ALTFORMAT
) {
985 ret
+= myvprintf_int64(send
, send_arg2
, flags
, 8, width
, False
,
986 (ULong
)(va_arg (vargs
, SizeT
)));
988 ret
+= myvprintf_int64(send
, send_arg2
, flags
, 8, width
, False
,
989 (ULong
)(va_arg (vargs
, ULong
)));
991 ret
+= myvprintf_int64(send
, send_arg2
, flags
, 8, width
, False
,
992 (ULong
)(va_arg (vargs
, UInt
)));
995 flags
|= VG_MSG_SIGNED
;
997 ret
+= myvprintf_int64(send
, send_arg2
, flags
, 10, width
, False
,
998 (ULong
)(va_arg (vargs
, Long
)));
1000 ret
+= myvprintf_int64(send
, send_arg2
, flags
, 10, width
, False
,
1001 (ULong
)(va_arg (vargs
, Int
)));
1005 ret
+= myvprintf_int64(send
, send_arg2
, flags
, 10, width
, False
,
1006 (ULong
)(va_arg (vargs
, SizeT
)));
1008 ret
+= myvprintf_int64(send
, send_arg2
, flags
, 10, width
, False
,
1009 (ULong
)(va_arg (vargs
, ULong
)));
1011 ret
+= myvprintf_int64(send
, send_arg2
, flags
, 10, width
, False
,
1012 (ULong
)(va_arg (vargs
, UInt
)));
1015 if (format
[i
+1] == 'S') {
1017 /* %pS, like %s but escaping chars for XML safety */
1018 /* Note: simplistic; ignores field width and flags */
1019 const HChar
*str
= va_arg (vargs
, HChar
*);
1022 ret
+= myvprintf_str_XML_simplistic(send
, send_arg2
, str
);
1023 } else if (format
[i
+1] == 's') {
1025 /* %ps, synonym for %s with --xml=no / %pS with --xml=yes */
1026 const HChar
*str
= va_arg (vargs
, HChar
*);
1030 ret
+= myvprintf_str_XML_simplistic(send
, send_arg2
, str
);
1032 ret
+= myvprintf_str(send
, send_arg2
, flags
, width
, str
,
1037 send('0',send_arg2
);
1038 send('x',send_arg2
);
1039 ret
+= myvprintf_int64(send
, send_arg2
, flags
, 16, width
, True
,
1040 (ULong
)((UWord
)va_arg (vargs
, void *)));
1045 caps
= toBool(format
[i
] == 'X');
1046 if (flags
& VG_MSG_ALTFORMAT
) {
1048 send('0',send_arg2
);
1049 send('x',send_arg2
);
1052 ret
+= myvprintf_int64(send
, send_arg2
, flags
, 16, width
, False
,
1053 (ULong
)(va_arg (vargs
, SizeT
)));
1055 ret
+= myvprintf_int64(send
, send_arg2
, flags
, 16, width
, caps
,
1056 (ULong
)(va_arg (vargs
, ULong
)));
1058 ret
+= myvprintf_int64(send
, send_arg2
, flags
, 16, width
, caps
,
1059 (ULong
)(va_arg (vargs
, UInt
)));
1063 send(va_arg (vargs
, int), send_arg2
);
1065 case 's': case 'S': { /* %s */
1066 const HChar
*str
= va_arg (vargs
, HChar
*);
1067 if (str
== NULL
) str
= "(null)";
1068 ret
+= myvprintf_str(send
, send_arg2
,
1069 flags
, width
, str
, format
[i
]=='S');
1073 /* Print a floating point number in the format x.y without
1074 any exponent. Capabilities are extremely limited, basically
1075 a joke, but good enough for our needs. */
1076 Double val
= va_arg (vargs
, Double
);
1077 Bool is_negative
= False
;
1084 /* If the integral part of the floating point number cannot be
1085 represented by an ULONG_MAX, print '*' characters */
1086 if (val
> (Double
)(~0ULL)) {
1087 if (width
== 0) width
= 6; // say
1088 for (cnt
= 0; cnt
< width
; ++cnt
)
1089 send('*', send_arg2
);
1093 /* The integral part of the floating point number is representable
1096 Double frac
= val
- ipval
;
1098 if (precision
== -1) precision
= 6; // say
1100 /* Silently limit the precision to 10 digits. */
1101 if (precision
> 10) precision
= 10;
1103 /* Determine fractional part, possibly round up */
1105 for (cnt
= 0; cnt
< precision
; ++cnt
)
1107 ULong frval
= frac
* factor
;
1108 if ((frac
* factor
- frval
) > 0.5) // round up
1110 /* Check rounding. */
1111 if (frval
== factor
)
1115 /* Find out how many characters are needed to print the number */
1117 /* The integral part... */
1118 UInt ipwidth
, num_digit
= 1; // at least one digit
1120 for (x
= 10; ; old_x
= x
, x
*= 10, ++num_digit
) {
1121 if (x
<= old_x
) break; // overflow occurred
1122 if (ipval
< x
) break;
1124 ipwidth
= num_digit
; // width of integral part.
1125 if (is_negative
) ++num_digit
;
1127 num_digit
+= 1 + precision
;
1131 // Fill in blanks on the left
1132 if (num_digit
< width
&& (flags
& VG_MSG_LJUSTIFY
) == 0) {
1133 for (cnt
= 0; cnt
< width
- num_digit
; ++cnt
)
1134 send(' ', send_arg2
);
1135 ret
+= width
- num_digit
;
1139 send('-', send_arg2
);
1143 ret
+= myvprintf_int64(send
, send_arg2
, 0, 10, ipwidth
, False
,
1145 // Decimal point and fractional part
1146 if (precision
!= 0) {
1147 send('.', send_arg2
);
1150 ret
+= myvprintf_int64(send
, send_arg2
, VG_MSG_ZJUSTIFY
, 10,
1151 precision
, False
, frval
);
1153 // Fill in blanks on the right
1154 if (num_digit
< width
&& (flags
& VG_MSG_LJUSTIFY
) != 0) {
1155 for (cnt
= 0; cnt
< width
- num_digit
; ++cnt
)
1156 send(' ', send_arg2
);
1157 ret
+= width
- num_digit
;
1162 // case 'y': { /* %y - print symbol */
1163 // Addr a = va_arg(vargs, Addr);
1166 // if (VG_(get_fnname_w_offset)(a, &name)) {
1167 // HChar buf[1 + VG_strlen(name) + 1 + 1];
1168 // if (flags & VG_MSG_PAREN) {
1169 // VG_(sprintf)(str, "(%s)", name):
1171 // VG_(sprintf)(str, "%s", name):
1173 // ret += myvprintf_str(send, flags, width, buf, 0);
1185 /*------------------------------------------------------------*/
1186 /*--- Debuglog stuff. ---*/
1187 /*------------------------------------------------------------*/
1189 /* Only print messages whose stated level is less than or equal to
1190 this. By default, it makes this entire subsystem silent. */
1192 static Int loglevel
= 0;
1194 /* Module startup. */
1196 void VG_(debugLog_startup
) ( Int level
, const HChar
* who
)
1198 if (level
< 0) level
= 0;
1199 if (level
> 10) level
= 10;
1201 VG_(debugLog
)(1, "debuglog",
1202 "DebugLog system started by %s, "
1203 "level %d logging requested\n",
1207 /* Get the logging threshold level, as set by the most recent call to
1208 VG_(debugLog_startup), or zero if there have been no such calls so
1211 Int
VG_(debugLog_getLevel
) ( void )
1226 static void add_to_buf ( HChar c
, void* p
)
1228 printf_buf
* buf
= (printf_buf
*)p
;
1230 if (buf
->n
>= 100-10 /*paranoia*/ ) {
1231 emit( buf
->buf
, local_strlen(buf
->buf
) );
1233 buf
->buf
[buf
->n
] = 0;
1235 buf
->buf
[buf
->n
++] = c
;
1236 buf
->buf
[buf
->n
] = 0;
1239 /* Send a logging message. Nothing is output unless 'level'
1240 is <= the current loglevel. */
1242 void VG_(debugLog
) ( Int level
, const HChar
* modulename
,
1243 const HChar
* format
, ... )
1246 Int indent
, depth
, i
;
1250 if (level
> loglevel
)
1253 indent
= 2*level
- 1;
1254 if (indent
< 1) indent
= 1;
1258 pid
= local_sys_getpid();
1260 // Print one '>' in front of the messages for each level of self-hosting
1262 depth
= RUNNING_ON_VALGRIND
;
1263 for (i
= 0; i
< depth
; i
++) {
1264 (void)myvprintf_str ( add_to_buf
, &buf
, 0, 1, ">", False
);
1267 (void)myvprintf_str ( add_to_buf
, &buf
, 0, 2, "--", False
);
1268 (void)myvprintf_int64 ( add_to_buf
, &buf
, 0, 10, 1, False
, (ULong
)pid
);
1269 (void)myvprintf_str ( add_to_buf
, &buf
, 0, 1, ":", False
);
1270 (void)myvprintf_int64 ( add_to_buf
, &buf
, 0, 10, 1, False
, (ULong
)level
);
1271 (void)myvprintf_str ( add_to_buf
, &buf
, 0, 1, ":", False
);
1272 (void)myvprintf_str ( add_to_buf
, &buf
, 0, 8, modulename
, False
);
1273 (void)myvprintf_str ( add_to_buf
, &buf
, 0, indent
, "", False
);
1275 va_start(vargs
,format
);
1277 (void) VG_(debugLog_vprintf
) ( add_to_buf
, &buf
, format
, vargs
);
1280 emit( buf
.buf
, local_strlen(buf
.buf
) );
1288 /*--------------------------------------------------------------------*/
1289 /*--- end m_debuglog.c ---*/
1290 /*--------------------------------------------------------------------*/