Add DRD suppression patterns for races triggered by std::ostream
[valgrind.git] / coregrind / m_debuglog.c
blob5c25e33b571f42e51bc5f4a05536ead536fabed1
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-2017 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 */
59 #if defined(VGO_solaris)
60 #include "pub_core_vki.h" /* for EINTR and ERESTART */
61 #endif
63 static Bool clo_xml;
65 void VG_(debugLog_setXml)(Bool xml)
67 clo_xml = 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 )
80 Int result;
82 __asm__ volatile (
83 "pushl %%ebx\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) */
87 "popl %%ebx\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 )
98 UInt __res;
99 __asm__ volatile (
100 "movl $"VG_STRINGIFY(__NR_getpid)", %%eax\n" /* %eax = __NR_getpid */
101 "int $0x80\n" /* getpid() */
102 "movl %%eax, %0\n" /* set __res = eax */
103 : "=mr" (__res)
105 : "eax" );
106 return __res;
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;
116 block[1] = n;
117 __asm__ volatile (
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 */
131 : /*wr*/
132 : /*rd*/ "r" (block)
133 : /*trash*/ "rax", "rdi", "rsi", "rdx", "memory", "cc", "rcx", "r11"
135 if (block[0] < 0)
136 block[0] = -1;
137 return (UInt)block[0];
140 static UInt local_sys_getpid ( void )
142 UInt __res;
143 __asm__ volatile (
144 "movq $"VG_STRINGIFY(__NR_getpid)", %%rax\n" /* %rax = __NR_getpid */
145 "syscall\n" /* getpid() */
146 "movl %%eax, %0\n" /* set __res = %eax */
147 : "=mr" (__res)
149 : "rax", "rcx", "r11"
151 return __res;
154 #elif defined(VGP_ppc32_linux)
156 static UInt local_sys_write_stderr ( const HChar* buf, Int n )
158 volatile Int block[2];
159 block[0] = (Int)buf;
160 block[1] = n;
161 __asm__ volatile (
162 "addi 1,1,-256\n\t"
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) */
170 "lwz 5,0(1)\n\t"
171 "addi 1,1,256\n\t"
172 "stw 3,0(5)\n" /* block[0] = result */
174 : "b" (block)
175 : "cc","memory","cr0","ctr",
176 "r0","r2","r3","r4","r5","r6","r7","r8","r9","r10","r11","r12"
178 if (block[0] < 0)
179 block[0] = -1;
180 return (UInt)block[0];
183 static UInt local_sys_getpid ( void )
185 register UInt __res __asm__ ("r3");
186 __asm__ volatile (
187 "li 0, %1\n\t"
188 "sc"
189 : "=&r" (__res)
190 : "i" (__NR_getpid)
191 : "cc","memory","cr0","ctr",
192 "r0","r2","r4","r5","r6","r7","r8","r9","r10","r11","r12"
194 return __res;
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;
203 block[1] = (Long)n;
204 __asm__ volatile (
205 "addi 1,1,-256\n\t"
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) */
213 "ld 5,0(1)\n\t"
214 "addi 1,1,256\n\t"
215 "std 3,0(5)\n" /* block[0] = result */
217 : "b" (block)
218 : "cc","memory","cr0","ctr",
219 "r0","r3","r4","r5","r6","r7","r8","r9","r10","r11","r12"
221 if (block[0] < 0)
222 block[0] = -1;
223 return (UInt)(Int)block[0];
226 static UInt local_sys_getpid ( void )
228 register ULong __res __asm__ ("r3");
229 __asm__ volatile (
230 "li 0, %1\n\t"
231 "sc"
232 : "=&r" (__res)
233 : "i" (__NR_getpid)
234 : "cc","memory","cr0","ctr",
235 "r0","r4","r5","r6","r7","r8","r9","r10","r11","r12"
237 return (UInt)__res;
240 #elif defined(VGP_arm_linux)
242 static UInt local_sys_write_stderr ( const HChar* buf, Int n )
244 volatile Int block[2];
245 block[0] = (Int)buf;
246 block[1] = n;
247 __asm__ volatile (
248 "mov r0, #2\n\t" /* stderr */
249 "ldr r1, [%0]\n\t" /* buf */
250 "ldr r2, [%0, #4]\n\t" /* n */
251 "push {r6,r7}\n\t"
252 "mov r7, #"VG_STRINGIFY(__NR_write)"\n\t"
253 "svc 0x0\n" /* write() */
254 "pop {r6,r7}\n\t"
255 "str r0, [%0]\n\t"
257 : "r" (block)
258 : "r0","r1","r2"
260 if (block[0] < 0)
261 block[0] = -1;
262 return (UInt)block[0];
265 static UInt local_sys_getpid ( void )
267 UInt __res;
268 __asm__ volatile (
269 "push {r6,r7}\n\t"
270 "mov r7, #"VG_STRINGIFY(__NR_getpid)"\n\t"
271 "svc 0x0\n\t" /* getpid() */
272 "pop {r6,r7}\n\t"
273 "mov %0, r0\n\t"
274 : "=r" (__res)
276 : "r0" );
277 return __res;
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;
286 block[1] = (ULong)n;
287 __asm__ volatile (
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() */
293 "str x0, [%0]\n\t"
295 : "r" (block)
296 : "x0","x1","x2","x7"
298 if (block[0] < 0)
299 block[0] = -1;
300 return (UInt)block[0];
303 static UInt local_sys_getpid ( void )
305 UInt __res;
306 __asm__ volatile (
307 "mov x8, #"VG_STRINGIFY(__NR_getpid)"\n"
308 "svc 0x0\n" /* getpid() */
309 "mov %0, x0\n"
310 : "=r" (__res)
312 : "x0", "x8" );
313 return (UInt)__res;
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 )
325 UInt __res;
326 __asm__ volatile (
327 "movl %2, %%eax\n" /* push n */
328 "pushl %%eax\n"
329 "movl %1, %%eax\n" /* push buf */
330 "pushl %%eax\n"
331 "movl $2, %%eax\n" /* push stderr */
332 "pushl %%eax\n"
333 "movl $"VG_STRINGIFY(VG_DARWIN_SYSNO_INDEX(__NR_write_nocancel))
334 ", %%eax\n"
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 */
339 "1: "
340 "movl %%eax, %0\n" /* __res = eax */
341 "addl $16, %%esp\n" /* pop x4 */
342 : "=mr" (__res)
343 : "g" (buf), "g" (n)
344 : "eax", "edx", "cc"
346 return __res;
349 static UInt local_sys_getpid ( void )
351 UInt __res;
352 __asm__ volatile (
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 */
356 : "=mr" (__res)
358 : "eax", "cc" );
359 return __res;
362 #elif defined(VGP_amd64_darwin)
364 __attribute__((noinline))
365 static UInt local_sys_write_stderr ( const HChar* buf, Int n )
367 UInt __res;
368 __asm__ volatile (
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))
373 ", %%eax\n"
374 "syscall\n" /* write(stderr, buf, n) */
375 "jnc 1f\n" /* jump if no error */
376 "movq $-1, %%rax\n" /* return -1 if error */
377 "1: "
378 "movl %%eax, %0\n" /* __res = eax */
379 : "=mr" (__res)
380 : "g" (buf), "g" (n)
381 : "rdi", "rsi", "rdx", "rcx", "rax", "cc" );
382 return __res;
385 static UInt local_sys_getpid ( void )
387 UInt __res;
388 __asm__ volatile (
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 */
392 : "=mr" (__res)
394 : "rax", "rcx", "cc" );
395 return __res;
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");
406 ULong __res;
408 __asm__ __volatile__ (
409 "svc %b1\n"
410 : "=d" (r2_res)
411 : "i" (__NR_write),
412 "0" (r2),
413 "d" (r3),
414 "d" (r4)
415 : "cc", "memory");
416 __res = r2_res;
418 if (__res >= (ULong)(-125))
419 __res = -1;
420 return (UInt)(__res);
423 static UInt local_sys_getpid ( void )
425 register ULong r2 asm("2");
426 ULong __res;
428 __asm__ __volatile__ (
429 "svc %b1\n"
430 : "=d" (r2)
431 : "i" (__NR_getpid)
432 : "cc", "memory");
433 __res = r2;
435 if (__res >= (ULong)(-125))
436 __res = -1;
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];
445 block[0] = (Int)buf;
446 block[1] = n;
447 __asm__ volatile (
448 "li $4, 2\n\t" /* stderr */
449 "lw $5, 0(%0)\n\t" /* buf */
450 "lw $6, 4(%0)\n\t" /* n */
451 "move $7, $0\n\t"
452 "li $2, %1\n\t" /* set v0 = __NR_write */
453 "syscall\n\t" /* write() */
454 "nop\n\t"
456 : "r" (block), "n" (__NR_write)
457 : "2", "4", "5", "6", "7"
459 if (block[0] < 0)
460 block[0] = -1;
461 return (UInt)block[0];
464 static UInt local_sys_getpid ( void )
466 UInt __res;
467 __asm__ volatile (
468 "li $2, %1\n\t" /* set v0 = __NR_getpid */
469 "syscall\n\t" /* getpid() */
470 "nop\n\t"
471 "move %0, $2\n"
472 : "=r" (__res)
473 : "n" (__NR_getpid)
474 : "$2" );
475 return __res;
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;
484 block[1] = n;
485 __asm__ volatile (
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 */
489 "move $7, $0\n\t"
490 "li $2, %1\n\t" /* set v0 = __NR_write */
491 "\tsyscall\n"
492 "\tnop\n"
493 : /*wr*/
494 : /*rd*/ "r" (block), "n" (__NR_write)
495 : "2", "4", "5", "6", "7"
497 if (block[0] < 0)
498 block[0] = -1;
499 return (UInt)(Int)block[0];
502 static UInt local_sys_getpid ( void )
504 ULong __res;
505 __asm__ volatile (
506 "li $2, %1\n\t" /* set v0 = __NR_getpid */
507 "syscall\n\t" /* getpid() */
508 "nop\n\t"
509 "move %0, $2\n"
510 : "=r" (__res)
511 : "n" (__NR_getpid)
512 : "$2" );
513 return (UInt)(__res);
516 #elif defined(VGP_x86_solaris)
517 static UInt local_sys_write_stderr ( const HChar* buf, Int n )
519 UInt res, err;
520 Bool restart;
522 do {
523 /* The Solaris kernel does not restart syscalls automatically so it is
524 done here. */
525 __asm__ __volatile__ (
526 "movl %[n], %%eax\n" /* push n */
527 "pushl %%eax\n"
528 "movl %[buf], %%eax\n" /* push buf */
529 "pushl %%eax\n"
530 "movl $2, %%eax\n" /* push stderr */
531 "pushl %%eax\n"
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 */
538 "1: "
539 "addl $16, %%esp\n" /* pop x4 */
540 : "=&a" (res), "=d" (err)
541 : [buf] "g" (buf), [n] "g" (n)
542 : "cc");
543 restart = err && (res == VKI_EINTR || res == VKI_ERESTART);
544 } while (restart);
546 return res;
549 static UInt local_sys_getpid ( void )
551 UInt res;
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() */
558 : "=a" (res)
560 : "edx", "cc");
562 return res;
565 #elif defined(VGP_amd64_solaris)
566 static UInt local_sys_write_stderr ( const HChar* buf, Int n )
568 ULong res, err;
569 Bool restart;
571 do {
572 /* The Solaris kernel does not restart syscalls automatically so it is
573 done here. */
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 */
581 "1: "
582 : "=a" (res), "=d" (err)
583 : "S" (buf), "d" (n)
584 : "cc");
585 restart = err && (res == VKI_EINTR || res == VKI_ERESTART);
586 } while (restart);
588 return res;
591 static UInt local_sys_getpid ( void )
593 UInt res;
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() */
600 : "=a" (res)
602 : "edx", "cc");
604 return res;
607 #else
608 # error Unknown platform
609 #endif
612 /* ----- generic ----- */
614 /* strlen, so we don't need m_libc */
615 static Int local_strlen ( const HChar* str )
617 Int i = 0;
618 while (str[i] != 0) i++;
619 return i;
622 static HChar local_toupper ( HChar c )
624 if (c >= 'a' && c <= 'z')
625 return c + ('A' - 'a');
626 else
627 return c;
630 /* Emit buf[0 .. n-1] to stderr. Unfortunately platform-specific.
632 static void emit ( const HChar* buf, Int n )
634 if (n >= 1)
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 ----------------------------------------------- */
654 /* Some flags. */
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. */
663 static
664 UInt myvprintf_str ( void(*send)(HChar,void*),
665 void* send_arg2,
666 Int flags,
667 Int width,
668 const HChar* str,
669 Bool capitalise )
671 # define MAYBE_TOUPPER(ch) (capitalise ? local_toupper(ch) : (ch))
672 UInt ret = 0;
673 Int i, extra;
674 Int len = local_strlen(str);
676 if (width == 0) {
677 ret += len;
678 for (i = 0; i < len; i++)
679 send(MAYBE_TOUPPER(str[i]), send_arg2);
680 return ret;
683 if (len > width) {
684 ret += width;
685 for (i = 0; i < width; i++)
686 send(MAYBE_TOUPPER(str[i]), send_arg2);
687 return ret;
690 extra = width - len;
691 if (! (flags & VG_MSG_LJUSTIFY)) {
692 ret += extra;
693 for (i = 0; i < extra; i++)
694 send(' ', send_arg2);
696 ret += len;
697 for (i = 0; i < len; i++)
698 send(MAYBE_TOUPPER(str[i]), send_arg2);
699 if (flags & VG_MSG_LJUSTIFY) {
700 ret += extra;
701 for (i = 0; i < extra; i++)
702 send(' ', send_arg2);
705 # undef MAYBE_TOUPPER
706 return ret;
710 /* Copy a string into the buffer, escaping bad XML chars. */
711 static
712 UInt myvprintf_str_XML_simplistic ( void(*send)(HChar,void*),
713 void* send_arg2,
714 const HChar* str )
716 UInt ret = 0;
717 Int i;
718 Int len = local_strlen(str);
719 const HChar* alt;
721 for (i = 0; i < len; i++) {
722 switch (str[i]) {
723 case '&': alt = "&amp;"; break;
724 case '<': alt = "&lt;"; break;
725 case '>': alt = "&gt;"; break;
726 default: alt = NULL;
729 if (alt) {
730 while (*alt) {
731 send(*alt, send_arg2);
732 ret++;
733 alt++;
735 } else {
736 send(str[i], send_arg2);
737 ret++;
741 return ret;
745 /* Write P into the buffer according to these args:
746 * If SIGN is true, p is a signed.
747 * BASE is the base.
748 * If WITH_ZERO is true, '0' must be added.
749 * WIDTH is the width of the field.
751 static
752 UInt myvprintf_int64 ( void(*send)(HChar,void*),
753 void* send_arg2,
754 Int flags,
755 Int base,
756 Int width,
757 Bool capitalised,
758 ULong p )
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];
764 Int ind = 0;
765 Int i, nc = 0;
766 Bool neg = False;
767 const HChar* digits = capitalised ? "0123456789ABCDEF" : "0123456789abcdef";
768 UInt ret = 0;
770 if (base < 2 || base > 16)
771 return ret;
773 if ((flags & VG_MSG_SIGNED) && (Long)p < 0) {
774 p = - (Long)p;
775 neg = True;
778 if (p == 0)
779 buf[ind++] = '0';
780 else {
781 while (p > 0) {
782 if (flags & VG_MSG_COMMA && 10 == base &&
783 0 == (ind-nc) % 3 && 0 != ind)
785 buf[ind++] = ',';
786 nc++;
788 buf[ind++] = digits[p % base];
789 p /= base;
793 if (neg)
794 buf[ind++] = '-';
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. */
803 ret += ind;
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++) {
809 ret++;
810 /* Never pad with zeroes on RHS -- changes the value! */
811 send(' ', send_arg2);
814 return ret;
818 /* A simple vprintf(). */
819 /* EXPORTED */
820 UInt
821 VG_(debugLog_vprintf) (
822 void(*send)(HChar,void*),
823 void* send_arg2,
824 const HChar* format,
825 va_list vargs
828 UInt ret = 0;
829 Int i;
830 Int flags;
831 Int width, precision;
832 Int n_ls = 0;
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);
843 ret++;
844 continue;
846 i++;
847 /* A '%' has been found. Ignore a trailing %. */
848 if (format[i] == 0)
849 break;
850 if (format[i] == '%') {
851 /* '%%' is replaced by '%'. */
852 send('%', send_arg2);
853 ret++;
854 continue;
856 flags = 0;
857 n_ls = 0;
858 width = 0; /* length of the field. */
859 precision = -1; /* unspecified precision */
860 while (1) {
861 switch (format[i]) {
862 case '(':
863 flags |= VG_MSG_PAREN;
864 break;
865 case ',':
866 case '\'':
867 /* If ',' or '\'' follows '%', commas will be inserted. */
868 flags |= VG_MSG_COMMA;
869 break;
870 case '-':
871 /* If '-' follows '%', justify on the left. */
872 flags |= VG_MSG_LJUSTIFY;
873 break;
874 case '0':
875 /* If '0' follows '%', pads will be inserted. */
876 flags |= VG_MSG_ZJUSTIFY;
877 break;
878 case '#':
879 /* If '#' follows '%', alternative format will be used. */
880 flags |= VG_MSG_ALTFORMAT;
881 break;
882 default:
883 goto parse_fieldwidth;
885 i++;
887 parse_fieldwidth:
888 /* Compute the field length. */
889 if (format[i] == '*') {
890 width = va_arg(vargs, Int);
891 ++i;
892 } else {
893 while (format[i] >= '0' && format[i] <= '9') {
894 width *= 10;
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] == '.') {
901 ++i;
902 if (format[i] == '*') {
903 precision = va_arg(vargs, Int);
904 ++i;
905 } else {
906 precision = 0;
907 while (format[i] >= '0' && format[i] <= '9') {
908 precision *= 10;
909 precision += format[i++] - '0';
914 is_sizet = False;
915 if (format[i] == 'z') {
916 is_sizet = True;
917 ++i;
918 } else {
919 while (format[i] == 'l') {
920 i++;
921 n_ls++;
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; }
932 switch (format[i]) {
933 case 'o': /* %o */
934 if (flags & VG_MSG_ALTFORMAT) {
935 ret += 2;
936 send('0',send_arg2);
938 if (is_sizet)
939 ret += myvprintf_int64(send, send_arg2, flags, 8, width, False,
940 (ULong)(va_arg (vargs, SizeT)));
941 else if (is_long)
942 ret += myvprintf_int64(send, send_arg2, flags, 8, width, False,
943 (ULong)(va_arg (vargs, ULong)));
944 else
945 ret += myvprintf_int64(send, send_arg2, flags, 8, width, False,
946 (ULong)(va_arg (vargs, UInt)));
947 break;
948 case 'd': /* %d */
949 flags |= VG_MSG_SIGNED;
950 if (is_long)
951 ret += myvprintf_int64(send, send_arg2, flags, 10, width, False,
952 (ULong)(va_arg (vargs, Long)));
953 else
954 ret += myvprintf_int64(send, send_arg2, flags, 10, width, False,
955 (ULong)(va_arg (vargs, Int)));
956 break;
957 case 'u': /* %u */
958 if (is_sizet)
959 ret += myvprintf_int64(send, send_arg2, flags, 10, width, False,
960 (ULong)(va_arg (vargs, SizeT)));
961 else if (is_long)
962 ret += myvprintf_int64(send, send_arg2, flags, 10, width, False,
963 (ULong)(va_arg (vargs, ULong)));
964 else
965 ret += myvprintf_int64(send, send_arg2, flags, 10, width, False,
966 (ULong)(va_arg (vargs, UInt)));
967 break;
968 case 'p':
969 if (format[i+1] == 'S') {
970 i++;
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 *);
974 if (str == NULL)
975 str = "(null)";
976 ret += myvprintf_str_XML_simplistic(send, send_arg2, str);
977 } else if (format[i+1] == 's') {
978 i++;
979 /* %ps, synonym for %s with --xml=no / %pS with --xml=yes */
980 const HChar *str = va_arg (vargs, HChar *);
981 if (str == NULL)
982 str = "(null)";
983 if (clo_xml)
984 ret += myvprintf_str_XML_simplistic(send, send_arg2, str);
985 else
986 ret += myvprintf_str(send, send_arg2, flags, width, str,
987 False);
988 } else {
989 /* %p */
990 ret += 2;
991 send('0',send_arg2);
992 send('x',send_arg2);
993 ret += myvprintf_int64(send, send_arg2, flags, 16, width, True,
994 (ULong)((UWord)va_arg (vargs, void *)));
996 break;
997 case 'x': /* %x */
998 case 'X': /* %X */
999 caps = toBool(format[i] == 'X');
1000 if (flags & VG_MSG_ALTFORMAT) {
1001 ret += 2;
1002 send('0',send_arg2);
1003 send('x',send_arg2);
1005 if (is_sizet)
1006 ret += myvprintf_int64(send, send_arg2, flags, 16, width, False,
1007 (ULong)(va_arg (vargs, SizeT)));
1008 else if (is_long)
1009 ret += myvprintf_int64(send, send_arg2, flags, 16, width, caps,
1010 (ULong)(va_arg (vargs, ULong)));
1011 else
1012 ret += myvprintf_int64(send, send_arg2, flags, 16, width, caps,
1013 (ULong)(va_arg (vargs, UInt)));
1014 break;
1015 case 'c': /* %c */
1016 ret++;
1017 send(va_arg (vargs, int), send_arg2);
1018 break;
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');
1024 break;
1026 case 'f': {
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;
1032 Int cnt;
1034 if (val < 0.0) {
1035 is_negative = True;
1036 val = - val;
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);
1044 ret += width;
1045 break;
1047 /* The integral part of the floating point number is representable
1048 by an ULong. */
1049 ULong ipval = val;
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 */
1058 ULong factor = 1;
1059 for (cnt = 0; cnt < precision; ++cnt)
1060 factor *= 10;
1061 ULong frval = frac * factor;
1062 if ((frac * factor - frval) > 0.5) // round up
1063 frval += 1;
1064 /* Check rounding. */
1065 if (frval == factor)
1066 ipval += 1;
1067 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
1073 ULong x, old_x = 0;
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;
1080 if (precision != 0)
1081 num_digit += 1 + precision;
1083 // Print the number
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;
1091 // Sign, maybe
1092 if (is_negative) {
1093 send('-', send_arg2);
1094 ret += 1;
1096 // Integral part
1097 ret += myvprintf_int64(send, send_arg2, 0, 10, ipwidth, False,
1098 ipval);
1099 // Decimal point and fractional part
1100 if (precision != 0) {
1101 send('.', send_arg2);
1102 ret += 1;
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;
1113 break;
1116 // case 'y': { /* %y - print symbol */
1117 // Addr a = va_arg(vargs, Addr);
1119 // HChar *name;
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):
1124 // } else {
1125 // VG_(sprintf)(str, "%s", name):
1126 // }
1127 // ret += myvprintf_str(send, flags, width, buf, 0);
1128 // }
1129 // break;
1130 // }
1131 default:
1132 break;
1135 return ret;
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. */
1149 /* EXPORTED */
1150 void VG_(debugLog_startup) ( Int level, const HChar* who )
1152 if (level < 0) level = 0;
1153 if (level > 10) level = 10;
1154 loglevel = level;
1155 VG_(debugLog)(1, "debuglog",
1156 "DebugLog system started by %s, "
1157 "level %d logging requested\n",
1158 who, loglevel);
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
1163 far. */
1164 /* EXPORTED */
1165 Int VG_(debugLog_getLevel) ( void )
1167 return loglevel;
1171 /* ------------ */
1173 typedef
1174 struct {
1175 HChar buf[100];
1176 Int n;
1178 printf_buf;
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) );
1186 buf->n = 0;
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. */
1195 /* EXPORTED */
1196 void VG_(debugLog) ( Int level, const HChar* modulename,
1197 const HChar* format, ... )
1199 UInt pid;
1200 Int indent, depth, i;
1201 va_list vargs;
1202 printf_buf buf;
1204 if (level > loglevel)
1205 return;
1207 indent = 2*level - 1;
1208 if (indent < 1) indent = 1;
1210 buf.n = 0;
1211 buf.buf[0] = 0;
1212 pid = local_sys_getpid();
1214 // Print one '>' in front of the messages for each level of self-hosting
1215 // being performed.
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 );
1233 if (buf.n > 0) {
1234 emit( buf.buf, local_strlen(buf.buf) );
1237 va_end(vargs);
1242 /*--------------------------------------------------------------------*/
1243 /*--- end m_debuglog.c ---*/
1244 /*--------------------------------------------------------------------*/