Fix 343173 - helgrind crash during stack unwind
[valgrind.git] / coregrind / m_debuglog.c
blob25ac7eebb02505bc36cb41ede7f427e49a9f6e12
1 /* -*- mode: C; c-basic-offset: 3; -*- */
3 /*--------------------------------------------------------------------*/
4 /*--- Debug (not-for-user) logging; also vprintf. m_debuglog.c ---*/
5 /*--------------------------------------------------------------------*/
7 /*
8 This file is part of Valgrind, a dynamic binary instrumentation
9 framework.
11 Copyright (C) 2000-2013 Julian Seward
12 jseward@acm.org
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
27 02111-1307, USA.
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
48 stage1 and stage2. */
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
53 why. */
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 */
60 static Bool clo_xml;
62 void VG_(debugLog_setXml)(Bool xml)
64 clo_xml = xml;
67 /*------------------------------------------------------------*/
68 /*--- Stuff to make us completely independent. ---*/
69 /*------------------------------------------------------------*/
71 /* ----- Platform-specifics ----- */
73 #if defined(VGP_x86_linux)
75 static UInt local_sys_write_stderr ( const HChar* buf, Int n )
77 Int result;
79 __asm__ volatile (
80 "pushl %%ebx\n"
81 "movl $"VG_STRINGIFY(__NR_write)", %%eax\n" /* %eax = __NR_write */
82 "movl $2, %%ebx\n" /* %ebx = stderr */
83 "int $0x80\n" /* write(stderr, buf, n) */
84 "popl %%ebx\n"
85 : /*wr*/ "=a" (result)
86 : /*rd*/ "c" (buf), "d" (n)
87 : /*trash*/ "edi", "memory", "cc"
90 return result >= 0 ? result : -1;
93 static UInt local_sys_getpid ( void )
95 UInt __res;
96 __asm__ volatile (
97 "movl $"VG_STRINGIFY(__NR_getpid)", %%eax\n" /* %eax = __NR_getpid */
98 "int $0x80\n" /* getpid() */
99 "movl %%eax, %0\n" /* set __res = eax */
100 : "=mr" (__res)
102 : "eax" );
103 return __res;
106 #elif defined(VGP_amd64_linux)
108 __attribute__((noinline))
109 static UInt local_sys_write_stderr ( const HChar* buf, Int n )
111 volatile Long block[2];
112 block[0] = (Long)buf;
113 block[1] = n;
114 __asm__ volatile (
115 "subq $256, %%rsp\n" /* don't trash the stack redzone */
116 "pushq %%r15\n" /* r15 is callee-save */
117 "movq %0, %%r15\n" /* r15 = &block */
118 "pushq %%r15\n" /* save &block */
119 "movq $"VG_STRINGIFY(__NR_write)", %%rax\n" /* rax = __NR_write */
120 "movq $2, %%rdi\n" /* rdi = stderr */
121 "movq 0(%%r15), %%rsi\n" /* rsi = buf */
122 "movq 8(%%r15), %%rdx\n" /* rdx = n */
123 "syscall\n" /* write(stderr, buf, n) */
124 "popq %%r15\n" /* reestablish &block */
125 "movq %%rax, 0(%%r15)\n" /* block[0] = result */
126 "popq %%r15\n" /* restore r15 */
127 "addq $256, %%rsp\n" /* restore stack ptr */
128 : /*wr*/
129 : /*rd*/ "r" (block)
130 : /*trash*/ "rax", "rdi", "rsi", "rdx", "memory", "cc"
132 if (block[0] < 0)
133 block[0] = -1;
134 return (UInt)block[0];
137 static UInt local_sys_getpid ( void )
139 UInt __res;
140 __asm__ volatile (
141 "movq $"VG_STRINGIFY(__NR_getpid)", %%rax\n" /* %rax = __NR_getpid */
142 "syscall\n" /* getpid() */
143 "movl %%eax, %0\n" /* set __res = %eax */
144 : "=mr" (__res)
146 : "rax" );
147 return __res;
150 #elif defined(VGP_ppc32_linux)
152 static UInt local_sys_write_stderr ( const HChar* buf, Int n )
154 volatile Int block[2];
155 block[0] = (Int)buf;
156 block[1] = n;
157 __asm__ volatile (
158 "addi 1,1,-256\n\t"
159 "mr 5,%0\n\t" /* r5 = &block[0] */
160 "stw 5,0(1)\n\t" /* stash on stack */
161 "li 0,"VG_STRINGIFY(__NR_write)"\n\t" /* set %r0 = __NR_write */
162 "li 3,2\n\t" /* set %r3 = stderr */
163 "lwz 4,0(5)\n\t" /* set %r4 = buf */
164 "lwz 5,4(5)\n\t" /* set %r5 = n */
165 "sc\n\t" /* write(stderr, buf, n) */
166 "lwz 5,0(1)\n\t"
167 "addi 1,1,256\n\t"
168 "stw 3,0(5)\n" /* block[0] = result */
170 : "b" (block)
171 : "cc","memory","cr0","ctr",
172 "r0","r2","r3","r4","r5","r6","r7","r8","r9","r10","r11","r12"
174 if (block[0] < 0)
175 block[0] = -1;
176 return (UInt)block[0];
179 static UInt local_sys_getpid ( void )
181 register UInt __res __asm__ ("r3");
182 __asm__ volatile (
183 "li 0, %1\n\t"
184 "sc"
185 : "=&r" (__res)
186 : "i" (__NR_getpid)
187 : "cc","memory","cr0","ctr",
188 "r0","r2","r4","r5","r6","r7","r8","r9","r10","r11","r12"
190 return __res;
193 #elif defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux)
195 static UInt local_sys_write_stderr ( const HChar* buf, Int n )
197 volatile Long block[2];
198 block[0] = (Long)buf;
199 block[1] = (Long)n;
200 __asm__ volatile (
201 "addi 1,1,-256\n\t"
202 "mr 5,%0\n\t" /* r5 = &block[0] */
203 "std 5,0(1)\n\t" /* stash on stack */
204 "li 0,"VG_STRINGIFY(__NR_write)"\n\t" /* %r0 = __NR_write */
205 "li 3,2\n\t" /* set %r3 = stderr */
206 "ld 4,0(5)\n\t" /* set %r4 = buf */
207 "ld 5,8(5)\n\t" /* set %r5 = n */
208 "sc\n\t" /* write(stderr, buf, n) */
209 "ld 5,0(1)\n\t"
210 "addi 1,1,256\n\t"
211 "std 3,0(5)\n" /* block[0] = result */
213 : "b" (block)
214 : "cc","memory","cr0","ctr",
215 "r0","r2","r3","r4","r5","r6","r7","r8","r9","r10","r11","r12"
217 if (block[0] < 0)
218 block[0] = -1;
219 return (UInt)(Int)block[0];
222 static UInt local_sys_getpid ( void )
224 register ULong __res __asm__ ("r3");
225 __asm__ volatile (
226 "li 0, %1\n\t"
227 "sc"
228 : "=&r" (__res)
229 : "i" (__NR_getpid)
230 : "cc","memory","cr0","ctr",
231 "r0","r2","r4","r5","r6","r7","r8","r9","r10","r11","r12"
233 return (UInt)__res;
236 #elif defined(VGP_arm_linux)
238 static UInt local_sys_write_stderr ( const HChar* buf, Int n )
240 volatile Int block[2];
241 block[0] = (Int)buf;
242 block[1] = n;
243 __asm__ volatile (
244 "mov r0, #2\n\t" /* stderr */
245 "ldr r1, [%0]\n\t" /* buf */
246 "ldr r2, [%0, #4]\n\t" /* n */
247 "push {r6,r7}\n\t"
248 "mov r7, #"VG_STRINGIFY(__NR_write)"\n\t"
249 "svc 0x0\n" /* write() */
250 "pop {r6,r7}\n\t"
251 "str r0, [%0]\n\t"
253 : "r" (block)
254 : "r0","r1","r2"
256 if (block[0] < 0)
257 block[0] = -1;
258 return (UInt)block[0];
261 static UInt local_sys_getpid ( void )
263 UInt __res;
264 __asm__ volatile (
265 "push {r6,r7}\n\t"
266 "mov r7, #"VG_STRINGIFY(__NR_getpid)"\n\t"
267 "svc 0x0\n\t" /* getpid() */
268 "pop {r6,r7}\n\t"
269 "mov %0, r0\n\t"
270 : "=r" (__res)
272 : "r0" );
273 return __res;
276 #elif defined(VGP_arm64_linux)
278 static UInt local_sys_write_stderr ( const HChar* buf, Int n )
280 volatile ULong block[2];
281 block[0] = (ULong)buf;
282 block[1] = (ULong)n;
283 __asm__ volatile (
284 "mov x0, #2\n\t" /* stderr */
285 "ldr x1, [%0]\n\t" /* buf */
286 "ldr x2, [%0, #8]\n\t" /* n */
287 "mov x8, #"VG_STRINGIFY(__NR_write)"\n\t"
288 "svc 0x0\n" /* write() */
289 "str x0, [%0]\n\t"
291 : "r" (block)
292 : "x0","x1","x2","x7"
294 if (block[0] < 0)
295 block[0] = -1;
296 return (UInt)block[0];
299 static UInt local_sys_getpid ( void )
301 UInt __res;
302 __asm__ volatile (
303 "mov x8, #"VG_STRINGIFY(__NR_getpid)"\n"
304 "svc 0x0\n" /* getpid() */
305 "mov %0, x0\n"
306 : "=r" (__res)
308 : "x0", "x8" );
309 return (UInt)__res;
312 #elif defined(VGP_x86_darwin)
314 /* We would use VG_DARWIN_SYSNO_TO_KERNEL instead of VG_DARWIN_SYSNO_INDEX
315 except that the former has a C ternary ?: operator which isn't valid in
316 asm code. Both macros give the same results for Unix-class syscalls (which
317 these all are, as identified by the use of 'int 0x80'). */
318 __attribute__((noinline))
319 static UInt local_sys_write_stderr ( const HChar* buf, Int n )
321 UInt __res;
322 __asm__ volatile (
323 "movl %2, %%eax\n" /* push n */
324 "pushl %%eax\n"
325 "movl %1, %%eax\n" /* push buf */
326 "pushl %%eax\n"
327 "movl $2, %%eax\n" /* push stderr */
328 "pushl %%eax\n"
329 "movl $"VG_STRINGIFY(VG_DARWIN_SYSNO_INDEX(__NR_write_nocancel))
330 ", %%eax\n"
331 "pushl %%eax\n" /* push fake return address */
332 "int $0x80\n" /* write(stderr, buf, n) */
333 "jnc 1f\n" /* jump if no error */
334 "movl $-1, %%eax\n" /* return -1 if error */
335 "1: "
336 "movl %%eax, %0\n" /* __res = eax */
337 "addl $16, %%esp\n" /* pop x4 */
338 : "=mr" (__res)
339 : "g" (buf), "g" (n)
340 : "eax", "edx", "cc"
342 return __res;
345 static UInt local_sys_getpid ( void )
347 UInt __res;
348 __asm__ volatile (
349 "movl $"VG_STRINGIFY(VG_DARWIN_SYSNO_INDEX(__NR_getpid))", %%eax\n"
350 "int $0x80\n" /* getpid() */
351 "movl %%eax, %0\n" /* set __res = eax */
352 : "=mr" (__res)
354 : "eax", "cc" );
355 return __res;
358 #elif defined(VGP_amd64_darwin)
360 __attribute__((noinline))
361 static UInt local_sys_write_stderr ( const HChar* buf, Int n )
363 UInt __res;
364 __asm__ volatile (
365 "movq $2, %%rdi\n" /* push stderr */
366 "movq %1, %%rsi\n" /* push buf */
367 "movl %2, %%edx\n" /* push n */
368 "movl $"VG_STRINGIFY(VG_DARWIN_SYSNO_FOR_KERNEL(__NR_write_nocancel))
369 ", %%eax\n"
370 "syscall\n" /* write(stderr, buf, n) */
371 "jnc 1f\n" /* jump if no error */
372 "movq $-1, %%rax\n" /* return -1 if error */
373 "1: "
374 "movl %%eax, %0\n" /* __res = eax */
375 : "=mr" (__res)
376 : "g" (buf), "g" (n)
377 : "rdi", "rsi", "rdx", "rcx", "rax", "cc" );
378 return __res;
381 static UInt local_sys_getpid ( void )
383 UInt __res;
384 __asm__ volatile (
385 "movl $"VG_STRINGIFY(VG_DARWIN_SYSNO_FOR_KERNEL(__NR_getpid))", %%eax\n"
386 "syscall\n" /* getpid() */
387 "movl %%eax, %0\n" /* set __res = eax */
388 : "=mr" (__res)
390 : "rax", "rcx", "cc" );
391 return __res;
394 #elif defined(VGP_s390x_linux)
396 static UInt local_sys_write_stderr ( const HChar* buf, Int n )
398 register Int r2 asm("2") = 2; /* file descriptor STDERR */
399 register const HChar* r3 asm("3") = buf;
400 register ULong r4 asm("4") = n;
401 register ULong r2_res asm("2");
402 ULong __res;
404 __asm__ __volatile__ (
405 "svc %b1\n"
406 : "=d" (r2_res)
407 : "i" (__NR_write),
408 "0" (r2),
409 "d" (r3),
410 "d" (r4)
411 : "cc", "memory");
412 __res = r2_res;
414 if (__res >= (ULong)(-125))
415 __res = -1;
416 return (UInt)(__res);
419 static UInt local_sys_getpid ( void )
421 register ULong r2 asm("2");
422 ULong __res;
424 __asm__ __volatile__ (
425 "svc %b1\n"
426 : "=d" (r2)
427 : "i" (__NR_getpid)
428 : "cc", "memory");
429 __res = r2;
431 if (__res >= (ULong)(-125))
432 __res = -1;
433 return (UInt)(__res);
436 #elif defined(VGP_mips32_linux)
438 static UInt local_sys_write_stderr ( const HChar* buf, Int n )
440 volatile Int block[2];
441 block[0] = (Int)buf;
442 block[1] = n;
443 __asm__ volatile (
444 "li $4, 2\n\t" /* stderr */
445 "lw $5, 0(%0)\n\t" /* buf */
446 "lw $6, 4(%0)\n\t" /* n */
447 "move $7, $0\n\t"
448 "li $2, %1\n\t" /* set v0 = __NR_write */
449 "syscall\n\t" /* write() */
450 "nop\n\t"
452 : "r" (block), "n" (__NR_write)
453 : "2", "4", "5", "6", "7"
455 if (block[0] < 0)
456 block[0] = -1;
457 return (UInt)block[0];
460 static UInt local_sys_getpid ( void )
462 UInt __res;
463 __asm__ volatile (
464 "li $2, %1\n\t" /* set v0 = __NR_getpid */
465 "syscall\n\t" /* getpid() */
466 "nop\n\t"
467 "move %0, $2\n"
468 : "=r" (__res)
469 : "n" (__NR_getpid)
470 : "$2" );
471 return __res;
474 #elif defined(VGP_mips64_linux)
476 static UInt local_sys_write_stderr ( const HChar* buf, Int n )
478 volatile Long block[2];
479 block[0] = (Long)buf;
480 block[1] = n;
481 __asm__ volatile (
482 "li $4, 2\n\t" /* std output*/
483 "ld $5, 0(%0)\n\t" /*$5 = buf*/
484 "ld $6, 8(%0)\n\t" /*$6 = n */
485 "move $7, $0\n\t"
486 "li $2, %1\n\t" /* set v0 = __NR_write */
487 "\tsyscall\n"
488 "\tnop\n"
489 : /*wr*/
490 : /*rd*/ "r" (block), "n" (__NR_write)
491 : "2", "4", "5", "6", "7"
493 if (block[0] < 0)
494 block[0] = -1;
495 return (UInt)(Int)block[0];
498 static UInt local_sys_getpid ( void )
500 ULong __res;
501 __asm__ volatile (
502 "li $2, %1\n\t" /* set v0 = __NR_getpid */
503 "syscall\n\t" /* getpid() */
504 "nop\n\t"
505 "move %0, $2\n"
506 : "=r" (__res)
507 : "n" (__NR_getpid)
508 : "$2" );
509 return (UInt)(__res);
512 #else
513 # error Unknown platform
514 #endif
517 /* ----- generic ----- */
519 /* strlen, so we don't need m_libc */
520 static Int local_strlen ( const HChar* str )
522 Int i = 0;
523 while (str[i] != 0) i++;
524 return i;
527 static HChar local_toupper ( HChar c )
529 if (c >= 'a' && c <= 'z')
530 return c + ('A' - 'a');
531 else
532 return c;
535 /* Emit buf[0 .. n-1] to stderr. Unfortunately platform-specific.
537 static void emit ( const HChar* buf, Int n )
539 if (n >= 1)
540 (void)local_sys_write_stderr(buf, n);
544 /*------------------------------------------------------------*/
545 /*--- A simple, generic, vprintf implementation. ---*/
546 /*------------------------------------------------------------*/
548 /* -----------------------------------------------
549 Distantly derived from:
551 vprintf replacement for Checker.
552 Copyright 1993, 1994, 1995 Tristan Gingold
553 Written September 1993 Tristan Gingold
554 Tristan Gingold, 8 rue Parmentier, F-91120 PALAISEAU, FRANCE
556 (Checker itself was GPL'd.)
557 ----------------------------------------------- */
559 /* Some flags. */
560 #define VG_MSG_SIGNED 1 /* The value is signed. */
561 #define VG_MSG_ZJUSTIFY 2 /* Must justify with '0'. */
562 #define VG_MSG_LJUSTIFY 4 /* Must justify on the left. */
563 #define VG_MSG_PAREN 8 /* Parenthesize if present (for %y) */
564 #define VG_MSG_COMMA 16 /* Add commas to numbers (for %d, %u) */
565 #define VG_MSG_ALTFORMAT 32 /* Convert the value to alternate format */
567 /* Copy a string into the buffer. */
568 static
569 UInt myvprintf_str ( void(*send)(HChar,void*),
570 void* send_arg2,
571 Int flags,
572 Int width,
573 const HChar* str,
574 Bool capitalise )
576 # define MAYBE_TOUPPER(ch) (capitalise ? local_toupper(ch) : (ch))
577 UInt ret = 0;
578 Int i, extra;
579 Int len = local_strlen(str);
581 if (width == 0) {
582 ret += len;
583 for (i = 0; i < len; i++)
584 send(MAYBE_TOUPPER(str[i]), send_arg2);
585 return ret;
588 if (len > width) {
589 ret += width;
590 for (i = 0; i < width; i++)
591 send(MAYBE_TOUPPER(str[i]), send_arg2);
592 return ret;
595 extra = width - len;
596 if (! (flags & VG_MSG_LJUSTIFY)) {
597 ret += extra;
598 for (i = 0; i < extra; i++)
599 send(' ', send_arg2);
601 ret += len;
602 for (i = 0; i < len; i++)
603 send(MAYBE_TOUPPER(str[i]), send_arg2);
604 if (flags & VG_MSG_LJUSTIFY) {
605 ret += extra;
606 for (i = 0; i < extra; i++)
607 send(' ', send_arg2);
610 # undef MAYBE_TOUPPER
611 return ret;
615 /* Copy a string into the buffer, escaping bad XML chars. */
616 static
617 UInt myvprintf_str_XML_simplistic ( void(*send)(HChar,void*),
618 void* send_arg2,
619 const HChar* str )
621 UInt ret = 0;
622 Int i;
623 Int len = local_strlen(str);
624 const HChar* alt;
626 for (i = 0; i < len; i++) {
627 switch (str[i]) {
628 case '&': alt = "&amp;"; break;
629 case '<': alt = "&lt;"; break;
630 case '>': alt = "&gt;"; break;
631 default: alt = NULL;
634 if (alt) {
635 while (*alt) {
636 send(*alt, send_arg2);
637 ret++;
638 alt++;
640 } else {
641 send(str[i], send_arg2);
642 ret++;
646 return ret;
650 /* Write P into the buffer according to these args:
651 * If SIGN is true, p is a signed.
652 * BASE is the base.
653 * If WITH_ZERO is true, '0' must be added.
654 * WIDTH is the width of the field.
656 static
657 UInt myvprintf_int64 ( void(*send)(HChar,void*),
658 void* send_arg2,
659 Int flags,
660 Int base,
661 Int width,
662 Bool capitalised,
663 ULong p )
665 /* To print an ULong base 2 needs 64 characters. If commas are requested,
666 add 21. Plus 1 for a possible sign plus 1 for \0. Makes 87 -- so let's
667 say 90. The size of BUF needs to be max(90, WIDTH + 1) */
668 HChar buf[width + 1 > 90 ? width + 1 : 90];
669 Int ind = 0;
670 Int i, nc = 0;
671 Bool neg = False;
672 const HChar* digits = capitalised ? "0123456789ABCDEF" : "0123456789abcdef";
673 UInt ret = 0;
675 if (base < 2 || base > 16)
676 return ret;
678 if ((flags & VG_MSG_SIGNED) && (Long)p < 0) {
679 p = - (Long)p;
680 neg = True;
683 if (p == 0)
684 buf[ind++] = '0';
685 else {
686 while (p > 0) {
687 if (flags & VG_MSG_COMMA && 10 == base &&
688 0 == (ind-nc) % 3 && 0 != ind)
690 buf[ind++] = ',';
691 nc++;
693 buf[ind++] = digits[p % base];
694 p /= base;
698 if (neg)
699 buf[ind++] = '-';
701 if (width > 0 && !(flags & VG_MSG_LJUSTIFY)) {
702 for(; ind < width; ind++) {
703 buf[ind] = (flags & VG_MSG_ZJUSTIFY) ? '0': ' ';
707 /* Reverse copy to buffer. */
708 ret += ind;
709 for (i = ind -1; i >= 0; i--) {
710 send(buf[i], send_arg2);
712 if (width > 0 && (flags & VG_MSG_LJUSTIFY)) {
713 for(; ind < width; ind++) {
714 ret++;
715 /* Never pad with zeroes on RHS -- changes the value! */
716 send(' ', send_arg2);
719 return ret;
723 /* A simple vprintf(). */
724 /* EXPORTED */
725 UInt
726 VG_(debugLog_vprintf) (
727 void(*send)(HChar,void*),
728 void* send_arg2,
729 const HChar* format,
730 va_list vargs
733 UInt ret = 0;
734 Int i;
735 Int flags;
736 Int width, precision;
737 Int n_ls = 0;
738 Bool is_long, is_sizet, caps;
740 /* We assume that vargs has already been initialised by the
741 caller, using va_start, and that the caller will similarly
742 clean up with va_end.
745 for (i = 0; format[i] != 0; i++) {
746 if (format[i] != '%') {
747 send(format[i], send_arg2);
748 ret++;
749 continue;
751 i++;
752 /* A '%' has been found. Ignore a trailing %. */
753 if (format[i] == 0)
754 break;
755 if (format[i] == '%') {
756 /* '%%' is replaced by '%'. */
757 send('%', send_arg2);
758 ret++;
759 continue;
761 flags = 0;
762 n_ls = 0;
763 width = 0; /* length of the field. */
764 precision = -1; /* unspecified precision */
765 while (1) {
766 switch (format[i]) {
767 case '(':
768 flags |= VG_MSG_PAREN;
769 break;
770 case ',':
771 case '\'':
772 /* If ',' or '\'' follows '%', commas will be inserted. */
773 flags |= VG_MSG_COMMA;
774 break;
775 case '-':
776 /* If '-' follows '%', justify on the left. */
777 flags |= VG_MSG_LJUSTIFY;
778 break;
779 case '0':
780 /* If '0' follows '%', pads will be inserted. */
781 flags |= VG_MSG_ZJUSTIFY;
782 break;
783 case '#':
784 /* If '#' follows '%', alternative format will be used. */
785 flags |= VG_MSG_ALTFORMAT;
786 break;
787 default:
788 goto parse_fieldwidth;
790 i++;
792 parse_fieldwidth:
793 /* Compute the field length. */
794 if (format[i] == '*') {
795 width = va_arg(vargs, Int);
796 ++i;
797 } else {
798 while (format[i] >= '0' && format[i] <= '9') {
799 width *= 10;
800 width += format[i++] - '0';
803 /* Parse precision, if any. Only meaningful for %f. For all other
804 format specifiers the precision will be silently ignored. */
805 if (format[i] == '.') {
806 ++i;
807 if (format[i] == '*') {
808 precision = va_arg(vargs, Int);
809 ++i;
810 } else {
811 precision = 0;
812 while (format[i] >= '0' && format[i] <= '9') {
813 precision *= 10;
814 precision += format[i++] - '0';
819 is_sizet = False;
820 if (format[i] == 'z') {
821 is_sizet = True;
822 } else {
823 while (format[i] == 'l') {
824 i++;
825 n_ls++;
829 // %d means print a 32-bit integer.
830 // %ld means print a word-size integer.
831 // %lld means print a 64-bit integer.
832 if (0 == n_ls) { is_long = False; }
833 else if (1 == n_ls) { is_long = ( sizeof(void*) == sizeof(Long) ); }
834 else { is_long = True; }
836 switch (format[i]) {
837 case 'o': /* %o */
838 if (flags & VG_MSG_ALTFORMAT) {
839 ret += 2;
840 send('0',send_arg2);
842 if (is_sizet)
843 ret += myvprintf_int64(send, send_arg2, flags, 8, width, False,
844 (ULong)(va_arg (vargs, SizeT)));
845 else if (is_long)
846 ret += myvprintf_int64(send, send_arg2, flags, 8, width, False,
847 (ULong)(va_arg (vargs, ULong)));
848 else
849 ret += myvprintf_int64(send, send_arg2, flags, 8, width, False,
850 (ULong)(va_arg (vargs, UInt)));
851 break;
852 case 'd': /* %d */
853 flags |= VG_MSG_SIGNED;
854 if (is_long)
855 ret += myvprintf_int64(send, send_arg2, flags, 10, width, False,
856 (ULong)(va_arg (vargs, Long)));
857 else
858 ret += myvprintf_int64(send, send_arg2, flags, 10, width, False,
859 (ULong)(va_arg (vargs, Int)));
860 break;
861 case 'u': /* %u */
862 if (is_sizet)
863 ret += myvprintf_int64(send, send_arg2, flags, 10, width, False,
864 (ULong)(va_arg (vargs, SizeT)));
865 else if (is_long)
866 ret += myvprintf_int64(send, send_arg2, flags, 10, width, False,
867 (ULong)(va_arg (vargs, ULong)));
868 else
869 ret += myvprintf_int64(send, send_arg2, flags, 10, width, False,
870 (ULong)(va_arg (vargs, UInt)));
871 break;
872 case 'p':
873 if (format[i+1] == 'S') {
874 i++;
875 /* %pS, like %s but escaping chars for XML safety */
876 /* Note: simplistic; ignores field width and flags */
877 const HChar *str = va_arg (vargs, HChar *);
878 if (str == NULL)
879 str = "(null)";
880 ret += myvprintf_str_XML_simplistic(send, send_arg2, str);
881 } else if (format[i+1] == 's') {
882 i++;
883 /* %ps, synonym for %s with --xml=no / %pS with --xml=yes */
884 const HChar *str = va_arg (vargs, HChar *);
885 if (str == NULL)
886 str = "(null)";
887 if (clo_xml)
888 ret += myvprintf_str_XML_simplistic(send, send_arg2, str);
889 else
890 ret += myvprintf_str(send, send_arg2, flags, width, str,
891 False);
892 } else {
893 /* %p */
894 ret += 2;
895 send('0',send_arg2);
896 send('x',send_arg2);
897 ret += myvprintf_int64(send, send_arg2, flags, 16, width, True,
898 (ULong)((UWord)va_arg (vargs, void *)));
900 break;
901 case 'x': /* %x */
902 case 'X': /* %X */
903 caps = toBool(format[i] == 'X');
904 if (flags & VG_MSG_ALTFORMAT) {
905 ret += 2;
906 send('0',send_arg2);
907 send('x',send_arg2);
909 if (is_sizet)
910 ret += myvprintf_int64(send, send_arg2, flags, 16, width, False,
911 (ULong)(va_arg (vargs, SizeT)));
912 else if (is_long)
913 ret += myvprintf_int64(send, send_arg2, flags, 16, width, caps,
914 (ULong)(va_arg (vargs, ULong)));
915 else
916 ret += myvprintf_int64(send, send_arg2, flags, 16, width, caps,
917 (ULong)(va_arg (vargs, UInt)));
918 break;
919 case 'c': /* %c */
920 ret++;
921 send(va_arg (vargs, int), send_arg2);
922 break;
923 case 's': case 'S': { /* %s */
924 const HChar *str = va_arg (vargs, HChar *);
925 if (str == NULL) str = "(null)";
926 ret += myvprintf_str(send, send_arg2,
927 flags, width, str, format[i]=='S');
928 break;
930 case 'f': {
931 /* Print a floating point number in the format x.y without
932 any exponent. Capabilities are extremely limited, basically
933 a joke, but good enough for our needs. */
934 Double val = va_arg (vargs, Double);
935 Bool is_negative = False;
936 Int cnt;
938 if (val < 0.0) {
939 is_negative = True;
940 val = - val;
942 /* If the integral part of the floating point number cannot be
943 represented by an ULONG_MAX, print '*' characters */
944 if (val > (Double)(~0ULL)) {
945 if (width == 0) width = 6; // say
946 for (cnt = 0; cnt < width; ++cnt)
947 send('*', send_arg2);
948 ret += width;
949 break;
951 /* The integral part of the floating point number is representable
952 by an ULong. */
953 ULong ipval = val;
954 Double frac = val - ipval;
956 if (precision == -1) precision = 6; // say
958 /* Silently limit the precision to 10 digits. */
959 if (precision > 10) precision = 10;
961 /* If fracional part is not printed (precision == 0), may have to
962 round up */
963 if (precision == 0 && frac >= 0.5)
964 ipval += 1;
966 /* Find out how many characters are needed to print the number */
968 /* The integral part... */
969 UInt ipwidth, num_digit = 1; // at least one digit
970 ULong x, old_x = 0;
971 for (x = 10; ; old_x = x, x *= 10, ++num_digit) {
972 if (x <= old_x) break; // overflow occurred
973 if (ipval < x) break;
975 ipwidth = num_digit; // width of integral part.
976 if (is_negative) ++num_digit;
977 if (precision != 0)
978 num_digit += 1 + precision;
980 // Print the number
982 // Fill in blanks on the left
983 if (num_digit < width && (flags & VG_MSG_LJUSTIFY) == 0) {
984 for (cnt = 0; cnt < width - num_digit; ++cnt)
985 send(' ', send_arg2);
986 ret += width - num_digit;
988 // Sign, maybe
989 if (is_negative) {
990 send('-', send_arg2);
991 ret += 1;
993 // Integral part
994 ret += myvprintf_int64(send, send_arg2, 0, 10, ipwidth, False,
995 ipval);
996 // Decimal point and fractional part
997 if (precision != 0) {
998 send('.', send_arg2);
999 ret += 1;
1001 // Fractional part
1002 ULong factor = 1;
1003 for (cnt = 0; cnt < precision; ++cnt)
1004 factor *= 10;
1005 ULong frval = frac * factor;
1006 if ((frac * factor - frval) > 0.5) // round up
1007 frval += 1;
1008 frval %= factor;
1009 ret += myvprintf_int64(send, send_arg2, VG_MSG_ZJUSTIFY, 10,
1010 precision, False, frval);
1012 // Fill in blanks on the right
1013 if (num_digit < width && (flags & VG_MSG_LJUSTIFY) != 0) {
1014 for (cnt = 0; cnt < width - num_digit; ++cnt)
1015 send(' ', send_arg2);
1016 ret += width - num_digit;
1018 break;
1021 // case 'y': { /* %y - print symbol */
1022 // Addr a = va_arg(vargs, Addr);
1024 // HChar *name;
1025 // if (VG_(get_fnname_w_offset)(a, &name)) {
1026 // HChar buf[1 + VG_strlen(name) + 1 + 1];
1027 // if (flags & VG_MSG_PAREN) {
1028 // VG_(sprintf)(str, "(%s)", name):
1029 // } else {
1030 // VG_(sprintf)(str, "%s", name):
1031 // }
1032 // ret += myvprintf_str(send, flags, width, buf, 0);
1033 // }
1034 // break;
1035 // }
1036 default:
1037 break;
1040 return ret;
1044 /*------------------------------------------------------------*/
1045 /*--- Debuglog stuff. ---*/
1046 /*------------------------------------------------------------*/
1048 /* Only print messages whose stated level is less than or equal to
1049 this. By default, it makes this entire subsystem silent. */
1051 static Int loglevel = 0;
1053 /* Module startup. */
1054 /* EXPORTED */
1055 void VG_(debugLog_startup) ( Int level, const HChar* who )
1057 if (level < 0) level = 0;
1058 if (level > 10) level = 10;
1059 loglevel = level;
1060 VG_(debugLog)(1, "debuglog",
1061 "DebugLog system started by %s, "
1062 "level %d logging requested\n",
1063 who, loglevel);
1066 /* Get the logging threshold level, as set by the most recent call to
1067 VG_(debugLog_startup), or zero if there have been no such calls so
1068 far. */
1069 /* EXPORTED */
1070 Int VG_(debugLog_getLevel) ( void )
1072 return loglevel;
1076 /* ------------ */
1078 typedef
1079 struct {
1080 HChar buf[100];
1081 Int n;
1083 printf_buf;
1085 static void add_to_buf ( HChar c, void* p )
1087 printf_buf* buf = (printf_buf*)p;
1089 if (buf->n >= 100-10 /*paranoia*/ ) {
1090 emit( buf->buf, local_strlen(buf->buf) );
1091 buf->n = 0;
1092 buf->buf[buf->n] = 0;
1094 buf->buf[buf->n++] = c;
1095 buf->buf[buf->n] = 0;
1098 /* Send a logging message. Nothing is output unless 'level'
1099 is <= the current loglevel. */
1100 /* EXPORTED */
1101 void VG_(debugLog) ( Int level, const HChar* modulename,
1102 const HChar* format, ... )
1104 UInt pid;
1105 Int indent, depth, i;
1106 va_list vargs;
1107 printf_buf buf;
1109 if (level > loglevel)
1110 return;
1112 indent = 2*level - 1;
1113 if (indent < 1) indent = 1;
1115 buf.n = 0;
1116 buf.buf[0] = 0;
1117 pid = local_sys_getpid();
1119 // Print one '>' in front of the messages for each level of self-hosting
1120 // being performed.
1121 depth = RUNNING_ON_VALGRIND;
1122 for (i = 0; i < depth; i++) {
1123 (void)myvprintf_str ( add_to_buf, &buf, 0, 1, ">", False );
1126 (void)myvprintf_str ( add_to_buf, &buf, 0, 2, "--", False );
1127 (void)myvprintf_int64 ( add_to_buf, &buf, 0, 10, 1, False, (ULong)pid );
1128 (void)myvprintf_str ( add_to_buf, &buf, 0, 1, ":", False );
1129 (void)myvprintf_int64 ( add_to_buf, &buf, 0, 10, 1, False, (ULong)level );
1130 (void)myvprintf_str ( add_to_buf, &buf, 0, 1, ":", False );
1131 (void)myvprintf_str ( add_to_buf, &buf, 0, 8, modulename, False );
1132 (void)myvprintf_str ( add_to_buf, &buf, 0, indent, "", False );
1134 va_start(vargs,format);
1136 (void) VG_(debugLog_vprintf) ( add_to_buf, &buf, format, vargs );
1138 if (buf.n > 0) {
1139 emit( buf.buf, local_strlen(buf.buf) );
1142 va_end(vargs);
1147 /*--------------------------------------------------------------------*/
1148 /*--- end m_debuglog.c ---*/
1149 /*--------------------------------------------------------------------*/