drd: Add a consistency check
[valgrind.git] / coregrind / m_debuglog.c
blob5ae2a5df1e15f842341397eea08a85205343b8d7
2 /*--------------------------------------------------------------------*/
3 /*--- Debug (not-for-user) logging; also vprintf. m_debuglog.c ---*/
4 /*--------------------------------------------------------------------*/
6 /*
7 This file is part of Valgrind, a dynamic binary instrumentation
8 framework.
10 Copyright (C) 2000-2013 Julian Seward
11 jseward@acm.org
13 This program is free software; you can redistribute it and/or
14 modify it under the terms of the GNU General Public License as
15 published by the Free Software Foundation; either version 2 of the
16 License, or (at your option) any later version.
18 This program is distributed in the hope that it will be useful, but
19 WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 General Public License for more details.
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software
25 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
26 02111-1307, USA.
28 The GNU General Public License is contained in the file COPYING.
32 /* Performs low-level debug logging that can safely run immediately
33 after startup. To minimise the dependencies on any other parts of
34 the system, the only place the debug output may go is file
35 descriptor 2 (stderr).
37 /* This is the first-initialised module in the entire system!
38 Therefore it is CRITICAL that it does not depend on any other code
39 running first. Hence only the following very limited includes. We
40 cannot depend (directly or indirectly) on any dynamic memory
41 allocation facilities, nor on the m_libc facilities, since the
42 latter depend on this module. DO NOT MESS WITH THESE INCLUDES
43 UNLESS YOU ARE 100% CERTAIN YOU UNDERSTAND THE CONSEQUENCES.
46 /* This module is also notable because it is linked into both
47 stage1 and stage2. */
49 /* IMPORTANT: on Darwin it is essential to use the _nocancel versions
50 of syscalls rather than the vanilla version, if a _nocancel version
51 is available. See docs/internals/Darwin-notes.txt for the reason
52 why. */
54 #include "pub_core_basics.h" /* basic types */
55 #include "pub_core_vkiscnums.h" /* for syscall numbers */
56 #include "pub_core_debuglog.h" /* our own iface */
57 #include "pub_core_clreq.h" /* for RUNNING_ON_VALGRIND */
59 static Bool clo_xml;
61 void VG_(debugLog_setXml)(Bool xml)
63 clo_xml = xml;
66 /*------------------------------------------------------------*/
67 /*--- Stuff to make us completely independent. ---*/
68 /*------------------------------------------------------------*/
70 /* ----- Platform-specifics ----- */
72 #if defined(VGP_x86_linux)
74 static UInt local_sys_write_stderr ( const HChar* buf, Int n )
76 Int result;
78 __asm__ volatile (
79 "pushl %%ebx\n"
80 "movl $"VG_STRINGIFY(__NR_write)", %%eax\n" /* %eax = __NR_write */
81 "movl $2, %%ebx\n" /* %ebx = stderr */
82 "int $0x80\n" /* write(stderr, buf, n) */
83 "popl %%ebx\n"
84 : /*wr*/ "=a" (result)
85 : /*rd*/ "c" (buf), "d" (n)
86 : /*trash*/ "edi", "memory", "cc"
89 return result >= 0 ? result : -1;
92 static UInt local_sys_getpid ( void )
94 UInt __res;
95 __asm__ volatile (
96 "movl $"VG_STRINGIFY(__NR_getpid)", %%eax\n" /* %eax = __NR_getpid */
97 "int $0x80\n" /* getpid() */
98 "movl %%eax, %0\n" /* set __res = eax */
99 : "=mr" (__res)
101 : "eax" );
102 return __res;
105 #elif defined(VGP_amd64_linux)
107 __attribute__((noinline))
108 static UInt local_sys_write_stderr ( const HChar* buf, Int n )
110 volatile Long block[2];
111 block[0] = (Long)buf;
112 block[1] = n;
113 __asm__ volatile (
114 "subq $256, %%rsp\n" /* don't trash the stack redzone */
115 "pushq %%r15\n" /* r15 is callee-save */
116 "movq %0, %%r15\n" /* r15 = &block */
117 "pushq %%r15\n" /* save &block */
118 "movq $"VG_STRINGIFY(__NR_write)", %%rax\n" /* rax = __NR_write */
119 "movq $2, %%rdi\n" /* rdi = stderr */
120 "movq 0(%%r15), %%rsi\n" /* rsi = buf */
121 "movq 8(%%r15), %%rdx\n" /* rdx = n */
122 "syscall\n" /* write(stderr, buf, n) */
123 "popq %%r15\n" /* reestablish &block */
124 "movq %%rax, 0(%%r15)\n" /* block[0] = result */
125 "popq %%r15\n" /* restore r15 */
126 "addq $256, %%rsp\n" /* restore stack ptr */
127 : /*wr*/
128 : /*rd*/ "r" (block)
129 : /*trash*/ "rax", "rdi", "rsi", "rdx", "memory", "cc"
131 if (block[0] < 0)
132 block[0] = -1;
133 return (UInt)block[0];
136 static UInt local_sys_getpid ( void )
138 UInt __res;
139 __asm__ volatile (
140 "movq $"VG_STRINGIFY(__NR_getpid)", %%rax\n" /* %rax = __NR_getpid */
141 "syscall\n" /* getpid() */
142 "movl %%eax, %0\n" /* set __res = %eax */
143 : "=mr" (__res)
145 : "rax" );
146 return __res;
149 #elif defined(VGP_ppc32_linux)
151 static UInt local_sys_write_stderr ( const HChar* buf, Int n )
153 volatile Int block[2];
154 block[0] = (Int)buf;
155 block[1] = n;
156 __asm__ volatile (
157 "addi 1,1,-256\n\t"
158 "mr 5,%0\n\t" /* r5 = &block[0] */
159 "stw 5,0(1)\n\t" /* stash on stack */
160 "li 0,"VG_STRINGIFY(__NR_write)"\n\t" /* set %r0 = __NR_write */
161 "li 3,2\n\t" /* set %r3 = stderr */
162 "lwz 4,0(5)\n\t" /* set %r4 = buf */
163 "lwz 5,4(5)\n\t" /* set %r5 = n */
164 "sc\n\t" /* write(stderr, buf, n) */
165 "lwz 5,0(1)\n\t"
166 "addi 1,1,256\n\t"
167 "stw 3,0(5)\n" /* block[0] = result */
169 : "b" (block)
170 : "cc","memory","cr0","ctr",
171 "r0","r2","r3","r4","r5","r6","r7","r8","r9","r10","r11","r12"
173 if (block[0] < 0)
174 block[0] = -1;
175 return (UInt)block[0];
178 static UInt local_sys_getpid ( void )
180 register UInt __res __asm__ ("r3");
181 __asm__ volatile (
182 "li 0, %1\n\t"
183 "sc"
184 : "=&r" (__res)
185 : "i" (__NR_getpid)
186 : "cc","memory","cr0","ctr",
187 "r0","r2","r4","r5","r6","r7","r8","r9","r10","r11","r12"
189 return __res;
192 #elif defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux)
194 static UInt local_sys_write_stderr ( const HChar* buf, Int n )
196 volatile Long block[2];
197 block[0] = (Long)buf;
198 block[1] = (Long)n;
199 __asm__ volatile (
200 "addi 1,1,-256\n\t"
201 "mr 5,%0\n\t" /* r5 = &block[0] */
202 "std 5,0(1)\n\t" /* stash on stack */
203 "li 0,"VG_STRINGIFY(__NR_write)"\n\t" /* %r0 = __NR_write */
204 "li 3,2\n\t" /* set %r3 = stderr */
205 "ld 4,0(5)\n\t" /* set %r4 = buf */
206 "ld 5,8(5)\n\t" /* set %r5 = n */
207 "sc\n\t" /* write(stderr, buf, n) */
208 "ld 5,0(1)\n\t"
209 "addi 1,1,256\n\t"
210 "std 3,0(5)\n" /* block[0] = result */
212 : "b" (block)
213 : "cc","memory","cr0","ctr",
214 "r0","r2","r3","r4","r5","r6","r7","r8","r9","r10","r11","r12"
216 if (block[0] < 0)
217 block[0] = -1;
218 return (UInt)(Int)block[0];
221 static UInt local_sys_getpid ( void )
223 register ULong __res __asm__ ("r3");
224 __asm__ volatile (
225 "li 0, %1\n\t"
226 "sc"
227 : "=&r" (__res)
228 : "i" (__NR_getpid)
229 : "cc","memory","cr0","ctr",
230 "r0","r2","r4","r5","r6","r7","r8","r9","r10","r11","r12"
232 return (UInt)__res;
235 #elif defined(VGP_arm_linux)
237 static UInt local_sys_write_stderr ( const HChar* buf, Int n )
239 volatile Int block[2];
240 block[0] = (Int)buf;
241 block[1] = n;
242 __asm__ volatile (
243 "mov r0, #2\n\t" /* stderr */
244 "ldr r1, [%0]\n\t" /* buf */
245 "ldr r2, [%0, #4]\n\t" /* n */
246 "mov r7, #"VG_STRINGIFY(__NR_write)"\n\t"
247 "svc 0x0\n" /* write() */
248 "str r0, [%0]\n\t"
250 : "r" (block)
251 : "r0","r1","r2","r7"
253 if (block[0] < 0)
254 block[0] = -1;
255 return (UInt)block[0];
258 static UInt local_sys_getpid ( void )
260 UInt __res;
261 __asm__ volatile (
262 "mov r7, #"VG_STRINGIFY(__NR_getpid)"\n"
263 "svc 0x0\n" /* getpid() */
264 "mov %0, r0\n"
265 : "=r" (__res)
267 : "r0", "r7" );
268 return __res;
271 #elif defined(VGP_arm64_linux)
273 static UInt local_sys_write_stderr ( const HChar* buf, Int n )
275 volatile ULong block[2];
276 block[0] = (ULong)buf;
277 block[1] = (ULong)n;
278 __asm__ volatile (
279 "mov x0, #2\n\t" /* stderr */
280 "ldr x1, [%0]\n\t" /* buf */
281 "ldr x2, [%0, #8]\n\t" /* n */
282 "mov x8, #"VG_STRINGIFY(__NR_write)"\n\t"
283 "svc 0x0\n" /* write() */
284 "str x0, [%0]\n\t"
286 : "r" (block)
287 : "x0","x1","x2","x7"
289 if (block[0] < 0)
290 block[0] = -1;
291 return (UInt)block[0];
294 static UInt local_sys_getpid ( void )
296 UInt __res;
297 __asm__ volatile (
298 "mov x8, #"VG_STRINGIFY(__NR_getpid)"\n"
299 "svc 0x0\n" /* getpid() */
300 "mov %0, x0\n"
301 : "=r" (__res)
303 : "x0", "x8" );
304 return (UInt)__res;
307 #elif defined(VGP_x86_darwin)
309 /* We would use VG_DARWIN_SYSNO_TO_KERNEL instead of VG_DARWIN_SYSNO_INDEX
310 except that the former has a C ternary ?: operator which isn't valid in
311 asm code. Both macros give the same results for Unix-class syscalls (which
312 these all are, as identified by the use of 'int 0x80'). */
313 __attribute__((noinline))
314 static UInt local_sys_write_stderr ( const HChar* buf, Int n )
316 UInt __res;
317 __asm__ volatile (
318 "movl %2, %%eax\n" /* push n */
319 "pushl %%eax\n"
320 "movl %1, %%eax\n" /* push buf */
321 "pushl %%eax\n"
322 "movl $2, %%eax\n" /* push stderr */
323 "pushl %%eax\n"
324 "movl $"VG_STRINGIFY(VG_DARWIN_SYSNO_INDEX(__NR_write_nocancel))
325 ", %%eax\n"
326 "pushl %%eax\n" /* push fake return address */
327 "int $0x80\n" /* write(stderr, buf, n) */
328 "jnc 1f\n" /* jump if no error */
329 "movl $-1, %%eax\n" /* return -1 if error */
330 "1: "
331 "movl %%eax, %0\n" /* __res = eax */
332 "addl $16, %%esp\n" /* pop x4 */
333 : "=mr" (__res)
334 : "g" (buf), "g" (n)
335 : "eax", "edx", "cc"
337 return __res;
340 static UInt local_sys_getpid ( void )
342 UInt __res;
343 __asm__ volatile (
344 "movl $"VG_STRINGIFY(VG_DARWIN_SYSNO_INDEX(__NR_getpid))", %%eax\n"
345 "int $0x80\n" /* getpid() */
346 "movl %%eax, %0\n" /* set __res = eax */
347 : "=mr" (__res)
349 : "eax", "cc" );
350 return __res;
353 #elif defined(VGP_amd64_darwin)
355 __attribute__((noinline))
356 static UInt local_sys_write_stderr ( const HChar* buf, Int n )
358 UInt __res;
359 __asm__ volatile (
360 "movq $2, %%rdi\n" /* push stderr */
361 "movq %1, %%rsi\n" /* push buf */
362 "movl %2, %%edx\n" /* push n */
363 "movl $"VG_STRINGIFY(VG_DARWIN_SYSNO_FOR_KERNEL(__NR_write_nocancel))
364 ", %%eax\n"
365 "syscall\n" /* write(stderr, buf, n) */
366 "jnc 1f\n" /* jump if no error */
367 "movq $-1, %%rax\n" /* return -1 if error */
368 "1: "
369 "movl %%eax, %0\n" /* __res = eax */
370 : "=mr" (__res)
371 : "g" (buf), "g" (n)
372 : "rdi", "rsi", "rdx", "rcx", "rax", "cc" );
373 return __res;
376 static UInt local_sys_getpid ( void )
378 UInt __res;
379 __asm__ volatile (
380 "movl $"VG_STRINGIFY(VG_DARWIN_SYSNO_FOR_KERNEL(__NR_getpid))", %%eax\n"
381 "syscall\n" /* getpid() */
382 "movl %%eax, %0\n" /* set __res = eax */
383 : "=mr" (__res)
385 : "rax", "rcx", "cc" );
386 return __res;
389 #elif defined(VGP_s390x_linux)
391 static UInt local_sys_write_stderr ( const HChar* buf, Int n )
393 register Int r2 asm("2") = 2; /* file descriptor STDERR */
394 register const HChar* r3 asm("3") = buf;
395 register ULong r4 asm("4") = n;
396 register ULong r2_res asm("2");
397 ULong __res;
399 __asm__ __volatile__ (
400 "svc %b1\n"
401 : "=d" (r2_res)
402 : "i" (__NR_write),
403 "0" (r2),
404 "d" (r3),
405 "d" (r4)
406 : "cc", "memory");
407 __res = r2_res;
409 if (__res >= (ULong)(-125))
410 __res = -1;
411 return (UInt)(__res);
414 static UInt local_sys_getpid ( void )
416 register ULong r2 asm("2");
417 ULong __res;
419 __asm__ __volatile__ (
420 "svc %b1\n"
421 : "=d" (r2)
422 : "i" (__NR_getpid)
423 : "cc", "memory");
424 __res = r2;
426 if (__res >= (ULong)(-125))
427 __res = -1;
428 return (UInt)(__res);
431 #elif defined(VGP_mips32_linux)
433 static UInt local_sys_write_stderr ( const HChar* buf, Int n )
435 volatile Int block[2];
436 block[0] = (Int)buf;
437 block[1] = n;
438 __asm__ volatile (
439 "li $4, 2\n\t" /* stderr */
440 "lw $5, 0(%0)\n\t" /* buf */
441 "lw $6, 4(%0)\n\t" /* n */
442 "move $7, $0\n\t"
443 "li $2, %1\n\t" /* set v0 = __NR_write */
444 "syscall\n\t" /* write() */
445 "nop\n\t"
447 : "r" (block), "n" (__NR_write)
448 : "2", "4", "5", "6", "7"
450 if (block[0] < 0)
451 block[0] = -1;
452 return (UInt)block[0];
455 static UInt local_sys_getpid ( void )
457 UInt __res;
458 __asm__ volatile (
459 "li $2, %1\n\t" /* set v0 = __NR_getpid */
460 "syscall\n\t" /* getpid() */
461 "nop\n\t"
462 "move %0, $2\n"
463 : "=r" (__res)
464 : "n" (__NR_getpid)
465 : "$2" );
466 return __res;
469 #elif defined(VGP_mips64_linux)
471 static UInt local_sys_write_stderr ( const HChar* buf, Int n )
473 volatile Long block[2];
474 block[0] = (Long)buf;
475 block[1] = n;
476 __asm__ volatile (
477 "li $4, 2\n\t" /* std output*/
478 "ld $5, 0(%0)\n\t" /*$5 = buf*/
479 "ld $6, 8(%0)\n\t" /*$6 = n */
480 "move $7, $0\n\t"
481 "li $2, %1\n\t" /* set v0 = __NR_write */
482 "\tsyscall\n"
483 "\tnop\n"
484 : /*wr*/
485 : /*rd*/ "r" (block), "n" (__NR_write)
486 : "2", "4", "5", "6", "7"
488 if (block[0] < 0)
489 block[0] = -1;
490 return (UInt)(Int)block[0];
493 static UInt local_sys_getpid ( void )
495 ULong __res;
496 __asm__ volatile (
497 "li $2, %1\n\t" /* set v0 = __NR_getpid */
498 "syscall\n\t" /* getpid() */
499 "nop\n\t"
500 "move %0, $2\n"
501 : "=r" (__res)
502 : "n" (__NR_getpid)
503 : "$2" );
504 return (UInt)(__res);
507 #else
508 # error Unknown platform
509 #endif
512 /* ----- generic ----- */
514 /* strlen, so we don't need m_libc */
515 static Int local_strlen ( const HChar* str )
517 Int i = 0;
518 while (str[i] != 0) i++;
519 return i;
522 static HChar local_toupper ( HChar c )
524 if (c >= 'a' && c <= 'z')
525 return c + ('A' - 'a');
526 else
527 return c;
530 /* Emit buf[0 .. n-1] to stderr. Unfortunately platform-specific.
532 static void emit ( const HChar* buf, Int n )
534 if (n >= 1)
535 (void)local_sys_write_stderr(buf, n);
539 /*------------------------------------------------------------*/
540 /*--- A simple, generic, vprintf implementation. ---*/
541 /*------------------------------------------------------------*/
543 /* -----------------------------------------------
544 Distantly derived from:
546 vprintf replacement for Checker.
547 Copyright 1993, 1994, 1995 Tristan Gingold
548 Written September 1993 Tristan Gingold
549 Tristan Gingold, 8 rue Parmentier, F-91120 PALAISEAU, FRANCE
551 (Checker itself was GPL'd.)
552 ----------------------------------------------- */
554 /* Some flags. */
555 #define VG_MSG_SIGNED 1 /* The value is signed. */
556 #define VG_MSG_ZJUSTIFY 2 /* Must justify with '0'. */
557 #define VG_MSG_LJUSTIFY 4 /* Must justify on the left. */
558 #define VG_MSG_PAREN 8 /* Parenthesize if present (for %y) */
559 #define VG_MSG_COMMA 16 /* Add commas to numbers (for %d, %u) */
560 #define VG_MSG_ALTFORMAT 32 /* Convert the value to alternate format */
562 /* Copy a string into the buffer. */
563 static
564 UInt myvprintf_str ( void(*send)(HChar,void*),
565 void* send_arg2,
566 Int flags,
567 Int width,
568 const HChar* str,
569 Bool capitalise )
571 # define MAYBE_TOUPPER(ch) (capitalise ? local_toupper(ch) : (ch))
572 UInt ret = 0;
573 Int i, extra;
574 Int len = local_strlen(str);
576 if (width == 0) {
577 ret += len;
578 for (i = 0; i < len; i++)
579 send(MAYBE_TOUPPER(str[i]), send_arg2);
580 return ret;
583 if (len > width) {
584 ret += width;
585 for (i = 0; i < width; i++)
586 send(MAYBE_TOUPPER(str[i]), send_arg2);
587 return ret;
590 extra = width - len;
591 if (flags & VG_MSG_LJUSTIFY) {
592 ret += extra;
593 for (i = 0; i < extra; i++)
594 send(' ', send_arg2);
596 ret += len;
597 for (i = 0; i < len; i++)
598 send(MAYBE_TOUPPER(str[i]), send_arg2);
599 if (!(flags & VG_MSG_LJUSTIFY)) {
600 ret += extra;
601 for (i = 0; i < extra; i++)
602 send(' ', send_arg2);
605 # undef MAYBE_TOUPPER
606 return ret;
610 /* Copy a string into the buffer, escaping bad XML chars. */
611 static
612 UInt myvprintf_str_XML_simplistic ( void(*send)(HChar,void*),
613 void* send_arg2,
614 const HChar* str )
616 UInt ret = 0;
617 Int i;
618 Int len = local_strlen(str);
619 const HChar* alt;
621 for (i = 0; i < len; i++) {
622 switch (str[i]) {
623 case '&': alt = "&amp;"; break;
624 case '<': alt = "&lt;"; break;
625 case '>': alt = "&gt;"; break;
626 default: alt = NULL;
629 if (alt) {
630 while (*alt) {
631 send(*alt, send_arg2);
632 ret++;
633 alt++;
635 } else {
636 send(str[i], send_arg2);
637 ret++;
641 return ret;
645 /* Write P into the buffer according to these args:
646 * If SIGN is true, p is a signed.
647 * BASE is the base.
648 * If WITH_ZERO is true, '0' must be added.
649 * WIDTH is the width of the field.
651 static
652 UInt myvprintf_int64 ( void(*send)(HChar,void*),
653 void* send_arg2,
654 Int flags,
655 Int base,
656 Int width,
657 Bool capitalised,
658 ULong p )
660 HChar buf[40];
661 Int ind = 0;
662 Int i, nc = 0;
663 Bool neg = False;
664 const HChar* digits = capitalised ? "0123456789ABCDEF" : "0123456789abcdef";
665 UInt ret = 0;
667 if (base < 2 || base > 16)
668 return ret;
670 if ((flags & VG_MSG_SIGNED) && (Long)p < 0) {
671 p = - (Long)p;
672 neg = True;
675 if (p == 0)
676 buf[ind++] = '0';
677 else {
678 while (p > 0) {
679 if (flags & VG_MSG_COMMA && 10 == base &&
680 0 == (ind-nc) % 3 && 0 != ind)
682 buf[ind++] = ',';
683 nc++;
685 buf[ind++] = digits[p % base];
686 p /= base;
690 if (neg)
691 buf[ind++] = '-';
693 if (width > 0 && !(flags & VG_MSG_LJUSTIFY)) {
694 for(; ind < width; ind++) {
695 /* vg_assert(ind < 39); */
696 if (ind > 39) {
697 buf[39] = 0;
698 break;
700 buf[ind] = (flags & VG_MSG_ZJUSTIFY) ? '0': ' ';
704 /* Reverse copy to buffer. */
705 ret += ind;
706 for (i = ind -1; i >= 0; i--) {
707 send(buf[i], send_arg2);
709 if (width > 0 && (flags & VG_MSG_LJUSTIFY)) {
710 for(; ind < width; ind++) {
711 ret++;
712 /* Never pad with zeroes on RHS -- changes the value! */
713 send(' ', send_arg2);
716 return ret;
720 /* A simple vprintf(). */
721 /* EXPORTED */
722 UInt
723 VG_(debugLog_vprintf) (
724 void(*send)(HChar,void*),
725 void* send_arg2,
726 const HChar* format,
727 va_list vargs
730 UInt ret = 0;
731 Int i;
732 Int flags;
733 Int width;
734 Int n_ls = 0;
735 Bool is_long, caps;
737 /* We assume that vargs has already been initialised by the
738 caller, using va_start, and that the caller will similarly
739 clean up with va_end.
742 for (i = 0; format[i] != 0; i++) {
743 if (format[i] != '%') {
744 send(format[i], send_arg2);
745 ret++;
746 continue;
748 i++;
749 /* A '%' has been found. Ignore a trailing %. */
750 if (format[i] == 0)
751 break;
752 if (format[i] == '%') {
753 /* '%%' is replaced by '%'. */
754 send('%', send_arg2);
755 ret++;
756 continue;
758 flags = 0;
759 n_ls = 0;
760 width = 0; /* length of the field. */
761 while (1) {
762 switch (format[i]) {
763 case '(':
764 flags |= VG_MSG_PAREN;
765 break;
766 case ',':
767 case '\'':
768 /* If ',' or '\'' follows '%', commas will be inserted. */
769 flags |= VG_MSG_COMMA;
770 break;
771 case '-':
772 /* If '-' follows '%', justify on the left. */
773 flags |= VG_MSG_LJUSTIFY;
774 break;
775 case '0':
776 /* If '0' follows '%', pads will be inserted. */
777 flags |= VG_MSG_ZJUSTIFY;
778 break;
779 case '#':
780 /* If '#' follows '%', alternative format will be used. */
781 flags |= VG_MSG_ALTFORMAT;
782 break;
783 default:
784 goto parse_fieldwidth;
786 i++;
788 parse_fieldwidth:
789 /* Compute the field length. */
790 while (format[i] >= '0' && format[i] <= '9') {
791 width *= 10;
792 width += format[i++] - '0';
794 while (format[i] == 'l') {
795 i++;
796 n_ls++;
799 // %d means print a 32-bit integer.
800 // %ld means print a word-size integer.
801 // %lld means print a 64-bit integer.
802 if (0 == n_ls) { is_long = False; }
803 else if (1 == n_ls) { is_long = ( sizeof(void*) == sizeof(Long) ); }
804 else { is_long = True; }
806 switch (format[i]) {
807 case 'o': /* %o */
808 if (flags & VG_MSG_ALTFORMAT) {
809 ret += 2;
810 send('0',send_arg2);
812 if (is_long)
813 ret += myvprintf_int64(send, send_arg2, flags, 8, width, False,
814 (ULong)(va_arg (vargs, ULong)));
815 else
816 ret += myvprintf_int64(send, send_arg2, flags, 8, width, False,
817 (ULong)(va_arg (vargs, UInt)));
818 break;
819 case 'd': /* %d */
820 flags |= VG_MSG_SIGNED;
821 if (is_long)
822 ret += myvprintf_int64(send, send_arg2, flags, 10, width, False,
823 (ULong)(va_arg (vargs, Long)));
824 else
825 ret += myvprintf_int64(send, send_arg2, flags, 10, width, False,
826 (ULong)(va_arg (vargs, Int)));
827 break;
828 case 'u': /* %u */
829 if (is_long)
830 ret += myvprintf_int64(send, send_arg2, flags, 10, width, False,
831 (ULong)(va_arg (vargs, ULong)));
832 else
833 ret += myvprintf_int64(send, send_arg2, flags, 10, width, False,
834 (ULong)(va_arg (vargs, UInt)));
835 break;
836 case 'p':
837 if (format[i+1] == 'S') {
838 i++;
839 /* %pS, like %s but escaping chars for XML safety */
840 /* Note: simplistic; ignores field width and flags */
841 const HChar *str = va_arg (vargs, HChar *);
842 if (str == NULL)
843 str = "(null)";
844 ret += myvprintf_str_XML_simplistic(send, send_arg2, str);
845 } else if (format[i+1] == 's') {
846 i++;
847 /* %ps, synonym for %s with --xml=no / %pS with --xml=yes */
848 const HChar *str = va_arg (vargs, HChar *);
849 if (str == NULL)
850 str = "(null)";
851 if (clo_xml)
852 ret += myvprintf_str_XML_simplistic(send, send_arg2, str);
853 else
854 ret += myvprintf_str(send, send_arg2, flags, width, str,
855 False);
856 } else {
857 /* %p */
858 ret += 2;
859 send('0',send_arg2);
860 send('x',send_arg2);
861 ret += myvprintf_int64(send, send_arg2, flags, 16, width, True,
862 (ULong)((UWord)va_arg (vargs, void *)));
864 break;
865 case 'x': /* %x */
866 case 'X': /* %X */
867 caps = toBool(format[i] == 'X');
868 if (flags & VG_MSG_ALTFORMAT) {
869 ret += 2;
870 send('0',send_arg2);
871 send('x',send_arg2);
873 if (is_long)
874 ret += myvprintf_int64(send, send_arg2, flags, 16, width, caps,
875 (ULong)(va_arg (vargs, ULong)));
876 else
877 ret += myvprintf_int64(send, send_arg2, flags, 16, width, caps,
878 (ULong)(va_arg (vargs, UInt)));
879 break;
880 case 'c': /* %c */
881 ret++;
882 send(va_arg (vargs, int), send_arg2);
883 break;
884 case 's': case 'S': { /* %s */
885 const HChar *str = va_arg (vargs, HChar *);
886 if (str == NULL) str = "(null)";
887 ret += myvprintf_str(send, send_arg2,
888 flags, width, str, format[i]=='S');
889 break;
892 // case 'y': { /* %y - print symbol */
893 // Addr a = va_arg(vargs, Addr);
895 // HChar *name;
896 // if (VG_(get_fnname_w_offset)(a, &name)) {
897 // HChar buf[1 + VG_strlen(name) + 1 + 1];
898 // if (flags & VG_MSG_PAREN) {
899 // VG_(sprintf)(str, "(%s)", name):
900 // } else {
901 // VG_(sprintf)(str, "%s", name):
902 // }
903 // ret += myvprintf_str(send, flags, width, buf, 0);
904 // }
905 // break;
906 // }
907 default:
908 break;
911 return ret;
915 /*------------------------------------------------------------*/
916 /*--- Debuglog stuff. ---*/
917 /*------------------------------------------------------------*/
919 /* Only print messages whose stated level is less than or equal to
920 this. By default, it makes this entire subsystem silent. */
922 static Int loglevel = 0;
924 /* Module startup. */
925 /* EXPORTED */
926 void VG_(debugLog_startup) ( Int level, const HChar* who )
928 if (level < 0) level = 0;
929 if (level > 10) level = 10;
930 loglevel = level;
931 VG_(debugLog)(1, "debuglog",
932 "DebugLog system started by %s, "
933 "level %d logging requested\n",
934 who, loglevel);
937 /* Get the logging threshold level, as set by the most recent call to
938 VG_(debugLog_startup), or zero if there have been no such calls so
939 far. */
940 /* EXPORTED */
941 Int VG_(debugLog_getLevel) ( void )
943 return loglevel;
947 /* ------------ */
949 typedef
950 struct {
951 HChar buf[100];
952 Int n;
954 printf_buf;
956 static void add_to_buf ( HChar c, void* p )
958 printf_buf* buf = (printf_buf*)p;
960 if (buf->n >= 100-10 /*paranoia*/ ) {
961 emit( buf->buf, local_strlen(buf->buf) );
962 buf->n = 0;
963 buf->buf[buf->n] = 0;
965 buf->buf[buf->n++] = c;
966 buf->buf[buf->n] = 0;
969 /* Send a logging message. Nothing is output unless 'level'
970 is <= the current loglevel. */
971 /* EXPORTED */
972 void VG_(debugLog) ( Int level, const HChar* modulename,
973 const HChar* format, ... )
975 UInt pid;
976 Int indent, depth, i;
977 va_list vargs;
978 printf_buf buf;
980 if (level > loglevel)
981 return;
983 indent = 2*level - 1;
984 if (indent < 1) indent = 1;
986 buf.n = 0;
987 buf.buf[0] = 0;
988 pid = local_sys_getpid();
990 // Print one '>' in front of the messages for each level of self-hosting
991 // being performed.
992 depth = RUNNING_ON_VALGRIND;
993 for (i = 0; i < depth; i++) {
994 (void)myvprintf_str ( add_to_buf, &buf, 0, 1, ">", False );
997 (void)myvprintf_str ( add_to_buf, &buf, 0, 2, "--", False );
998 (void)myvprintf_int64 ( add_to_buf, &buf, 0, 10, 1, False, (ULong)pid );
999 (void)myvprintf_str ( add_to_buf, &buf, 0, 1, ":", False );
1000 (void)myvprintf_int64 ( add_to_buf, &buf, 0, 10, 1, False, (ULong)level );
1001 (void)myvprintf_str ( add_to_buf, &buf, 0, 1, ":", False );
1002 (void)myvprintf_str ( add_to_buf, &buf, 0, 8, modulename, False );
1003 (void)myvprintf_str ( add_to_buf, &buf, 0, indent, "", False );
1005 va_start(vargs,format);
1007 (void) VG_(debugLog_vprintf) ( add_to_buf, &buf, format, vargs );
1009 if (buf.n > 0) {
1010 emit( buf.buf, local_strlen(buf.buf) );
1013 va_end(vargs);
1018 /*--------------------------------------------------------------------*/
1019 /*--- end m_debuglog.c ---*/
1020 /*--------------------------------------------------------------------*/