Add vbit-test-sec.vgtest and vbit-test-sec.stderr.exp to EXTRA_DIST.
[valgrind.git] / coregrind / m_debuglog.c
blob456a711297f87ad4ba0f512d3c1e68e4951acb3c
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) || defined(VGP_mips64_linux)
442 static UInt local_sys_write_stderr ( const HChar* buf, Int n )
444 register RegWord v0 asm("2");
445 register RegWord a0 asm("4");
446 register RegWord a1 asm("5");
447 register RegWord a2 asm("6");
448 v0 = __NR_write;
449 a2 = n;
450 a1 = (RegWord)(Addr)buf;
451 a0 = 2; // stderr
452 __asm__ volatile (
453 "syscall \n\t"
454 "addiu $4, $0, -1 \n\t"
455 "movn $2, $4, $7 \n\t"
456 : "+d" (v0), "+d" (a0), "+d" (a1), "+d" (a2)
458 : "$1", "$3", "$7", "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15",
459 "$24", "$25", "$31"
461 return v0;
464 static UInt local_sys_getpid ( void )
466 register RegWord v0 asm("2");
467 v0 = __NR_getpid;
468 __asm__ volatile (
469 "syscall \n\t"
470 : "+d" (v0)
472 : "$1", "$3", "$4", "$5", "$6", "$7", "$8", "$9", "$10", "$11", "$12",
473 "$13", "$14", "$15", "$24", "$25", "$31"
475 return v0;
478 #elif defined(VGP_x86_solaris)
479 static UInt local_sys_write_stderr ( const HChar* buf, Int n )
481 UInt res, err;
482 Bool restart;
484 do {
485 /* The Solaris kernel does not restart syscalls automatically so it is
486 done here. */
487 __asm__ __volatile__ (
488 "movl %[n], %%eax\n" /* push n */
489 "pushl %%eax\n"
490 "movl %[buf], %%eax\n" /* push buf */
491 "pushl %%eax\n"
492 "movl $2, %%eax\n" /* push stderr */
493 "pushl %%eax\n"
494 "movl $"VG_STRINGIFY(__NR_write)", %%eax\n"
495 "pushl %%eax\n" /* push fake return address */
496 "int $0x91\n" /* write(stderr, buf, n) */
497 "movl $0, %%edx\n" /* assume no error */
498 "jnc 1f\n" /* jump if no error */
499 "movl $1, %%edx\n" /* set error flag */
500 "1: "
501 "addl $16, %%esp\n" /* pop x4 */
502 : "=&a" (res), "=d" (err)
503 : [buf] "g" (buf), [n] "g" (n)
504 : "cc");
505 restart = err && (res == VKI_EINTR || res == VKI_ERESTART);
506 } while (restart);
508 return res;
511 static UInt local_sys_getpid ( void )
513 UInt res;
515 /* The getpid() syscall never returns EINTR or ERESTART so there is no need
516 for restarting it. */
517 __asm__ __volatile__ (
518 "movl $"VG_STRINGIFY(__NR_getpid)", %%eax\n"
519 "int $0x91\n" /* getpid() */
520 : "=a" (res)
522 : "edx", "cc");
524 return res;
527 #elif defined(VGP_amd64_solaris)
528 static UInt local_sys_write_stderr ( const HChar* buf, Int n )
530 ULong res, err;
531 Bool restart;
533 do {
534 /* The Solaris kernel does not restart syscalls automatically so it is
535 done here. */
536 __asm__ __volatile__ (
537 "movq $2, %%rdi\n" /* push stderr */
538 "movq $"VG_STRINGIFY(__NR_write)", %%rax\n"
539 "syscall\n" /* write(stderr, buf, n) */
540 "movq $0, %%rdx\n" /* assume no error */
541 "jnc 1f\n" /* jump if no error */
542 "movq $1, %%rdx\n" /* set error flag */
543 "1: "
544 : "=a" (res), "=d" (err)
545 : "S" (buf), "d" (n)
546 : "cc");
547 restart = err && (res == VKI_EINTR || res == VKI_ERESTART);
548 } while (restart);
550 return res;
553 static UInt local_sys_getpid ( void )
555 UInt res;
557 /* The getpid() syscall never returns EINTR or ERESTART so there is no need
558 for restarting it. */
559 __asm__ __volatile__ (
560 "movq $"VG_STRINGIFY(__NR_getpid)", %%rax\n"
561 "syscall\n" /* getpid() */
562 : "=a" (res)
564 : "edx", "cc");
566 return res;
569 #else
570 # error Unknown platform
571 #endif
574 /* ----- generic ----- */
576 /* strlen, so we don't need m_libc */
577 static Int local_strlen ( const HChar* str )
579 Int i = 0;
580 while (str[i] != 0) i++;
581 return i;
584 static HChar local_toupper ( HChar c )
586 if (c >= 'a' && c <= 'z')
587 return c + ('A' - 'a');
588 else
589 return c;
592 /* Emit buf[0 .. n-1] to stderr. Unfortunately platform-specific.
594 static void emit ( const HChar* buf, Int n )
596 if (n >= 1)
597 (void)local_sys_write_stderr(buf, n);
601 /*------------------------------------------------------------*/
602 /*--- A simple, generic, vprintf implementation. ---*/
603 /*------------------------------------------------------------*/
605 /* -----------------------------------------------
606 Distantly derived from:
608 vprintf replacement for Checker.
609 Copyright 1993, 1994, 1995 Tristan Gingold
610 Written September 1993 Tristan Gingold
611 Tristan Gingold, 8 rue Parmentier, F-91120 PALAISEAU, FRANCE
613 (Checker itself was GPL'd.)
614 ----------------------------------------------- */
616 /* Some flags. */
617 #define VG_MSG_SIGNED 1 /* The value is signed. */
618 #define VG_MSG_ZJUSTIFY 2 /* Must justify with '0'. */
619 #define VG_MSG_LJUSTIFY 4 /* Must justify on the left. */
620 #define VG_MSG_PAREN 8 /* Parenthesize if present (for %y) */
621 #define VG_MSG_COMMA 16 /* Add commas to numbers (for %d, %u) */
622 #define VG_MSG_ALTFORMAT 32 /* Convert the value to alternate format */
624 /* Copy a string into the buffer. */
625 static
626 UInt myvprintf_str ( void(*send)(HChar,void*),
627 void* send_arg2,
628 Int flags,
629 Int width,
630 const HChar* str,
631 Bool capitalise )
633 # define MAYBE_TOUPPER(ch) (capitalise ? local_toupper(ch) : (ch))
634 UInt ret = 0;
635 Int i, extra;
636 Int len = local_strlen(str);
638 if (width == 0) {
639 ret += len;
640 for (i = 0; i < len; i++)
641 send(MAYBE_TOUPPER(str[i]), send_arg2);
642 return ret;
645 if (len > width) {
646 ret += width;
647 for (i = 0; i < width; i++)
648 send(MAYBE_TOUPPER(str[i]), send_arg2);
649 return ret;
652 extra = width - len;
653 if (! (flags & VG_MSG_LJUSTIFY)) {
654 ret += extra;
655 for (i = 0; i < extra; i++)
656 send(' ', send_arg2);
658 ret += len;
659 for (i = 0; i < len; i++)
660 send(MAYBE_TOUPPER(str[i]), send_arg2);
661 if (flags & VG_MSG_LJUSTIFY) {
662 ret += extra;
663 for (i = 0; i < extra; i++)
664 send(' ', send_arg2);
667 # undef MAYBE_TOUPPER
668 return ret;
672 /* Copy a string into the buffer, escaping bad XML chars. */
673 static
674 UInt myvprintf_str_XML_simplistic ( void(*send)(HChar,void*),
675 void* send_arg2,
676 const HChar* str )
678 UInt ret = 0;
679 Int i;
680 Int len = local_strlen(str);
681 const HChar* alt;
683 for (i = 0; i < len; i++) {
684 switch (str[i]) {
685 case '&': alt = "&amp;"; break;
686 case '<': alt = "&lt;"; break;
687 case '>': alt = "&gt;"; break;
688 default: alt = NULL;
691 if (alt) {
692 while (*alt) {
693 send(*alt, send_arg2);
694 ret++;
695 alt++;
697 } else {
698 send(str[i], send_arg2);
699 ret++;
703 return ret;
707 /* Write P into the buffer according to these args:
708 * If SIGN is true, p is a signed.
709 * BASE is the base.
710 * If WITH_ZERO is true, '0' must be added.
711 * WIDTH is the width of the field.
713 static
714 UInt myvprintf_int64 ( void(*send)(HChar,void*),
715 void* send_arg2,
716 Int flags,
717 Int base,
718 Int width,
719 Bool capitalised,
720 ULong p )
722 /* To print an ULong base 2 needs 64 characters. If commas are requested,
723 add 21. Plus 1 for a possible sign plus 1 for \0. Makes 87 -- so let's
724 say 90. The size of BUF needs to be max(90, WIDTH + 1) */
725 HChar buf[width + 1 > 90 ? width + 1 : 90];
726 Int ind = 0;
727 Int i, nc = 0;
728 Bool neg = False;
729 const HChar* digits = capitalised ? "0123456789ABCDEF" : "0123456789abcdef";
730 UInt ret = 0;
732 if (base < 2 || base > 16)
733 return ret;
735 if ((flags & VG_MSG_SIGNED) && (Long)p < 0) {
736 p = - (Long)p;
737 neg = True;
740 if (p == 0)
741 buf[ind++] = '0';
742 else {
743 while (p > 0) {
744 if (flags & VG_MSG_COMMA && 10 == base &&
745 0 == (ind-nc) % 3 && 0 != ind)
747 buf[ind++] = ',';
748 nc++;
750 buf[ind++] = digits[p % base];
751 p /= base;
755 if (neg)
756 buf[ind++] = '-';
758 if (width > 0 && !(flags & VG_MSG_LJUSTIFY)) {
759 for(; ind < width; ind++) {
760 buf[ind] = (flags & VG_MSG_ZJUSTIFY) ? '0': ' ';
764 /* Reverse copy to buffer. */
765 ret += ind;
766 for (i = ind -1; i >= 0; i--) {
767 send(buf[i], send_arg2);
769 if (width > 0 && (flags & VG_MSG_LJUSTIFY)) {
770 for(; ind < width; ind++) {
771 ret++;
772 /* Never pad with zeroes on RHS -- changes the value! */
773 send(' ', send_arg2);
776 return ret;
780 /* A simple vprintf(). */
781 /* EXPORTED */
782 UInt
783 VG_(debugLog_vprintf) (
784 void(*send)(HChar,void*),
785 void* send_arg2,
786 const HChar* format,
787 va_list vargs
790 UInt ret = 0;
791 Int i;
792 Int flags;
793 Int width, precision;
794 Int n_ls = 0;
795 Bool is_long, is_sizet, caps;
797 /* We assume that vargs has already been initialised by the
798 caller, using va_start, and that the caller will similarly
799 clean up with va_end.
802 for (i = 0; format[i] != 0; i++) {
803 if (format[i] != '%') {
804 send(format[i], send_arg2);
805 ret++;
806 continue;
808 i++;
809 /* A '%' has been found. Ignore a trailing %. */
810 if (format[i] == 0)
811 break;
812 if (format[i] == '%') {
813 /* '%%' is replaced by '%'. */
814 send('%', send_arg2);
815 ret++;
816 continue;
818 flags = 0;
819 n_ls = 0;
820 width = 0; /* length of the field. */
821 precision = -1; /* unspecified precision */
822 while (1) {
823 switch (format[i]) {
824 case '(':
825 flags |= VG_MSG_PAREN;
826 break;
827 case ',':
828 case '\'':
829 /* If ',' or '\'' follows '%', commas will be inserted. */
830 flags |= VG_MSG_COMMA;
831 break;
832 case '-':
833 /* If '-' follows '%', justify on the left. */
834 flags |= VG_MSG_LJUSTIFY;
835 break;
836 case '0':
837 /* If '0' follows '%', pads will be inserted. */
838 flags |= VG_MSG_ZJUSTIFY;
839 break;
840 case '#':
841 /* If '#' follows '%', alternative format will be used. */
842 flags |= VG_MSG_ALTFORMAT;
843 break;
844 default:
845 goto parse_fieldwidth;
847 i++;
849 parse_fieldwidth:
850 /* Compute the field length. */
851 if (format[i] == '*') {
852 width = va_arg(vargs, Int);
853 ++i;
854 } else {
855 while (format[i] >= '0' && format[i] <= '9') {
856 width *= 10;
857 width += format[i++] - '0';
860 /* Parse precision, if any. Only meaningful for %f. For all other
861 format specifiers the precision will be silently ignored. */
862 if (format[i] == '.') {
863 ++i;
864 if (format[i] == '*') {
865 precision = va_arg(vargs, Int);
866 ++i;
867 } else {
868 precision = 0;
869 while (format[i] >= '0' && format[i] <= '9') {
870 precision *= 10;
871 precision += format[i++] - '0';
876 is_sizet = False;
877 if (format[i] == 'z') {
878 is_sizet = True;
879 ++i;
880 } else {
881 while (format[i] == 'l') {
882 i++;
883 n_ls++;
887 // %d means print a 32-bit integer.
888 // %ld means print a word-size integer.
889 // %lld means print a 64-bit integer.
890 if (0 == n_ls) { is_long = False; }
891 else if (1 == n_ls) { is_long = ( sizeof(void*) == sizeof(Long) ); }
892 else { is_long = True; }
894 switch (format[i]) {
895 case 'o': /* %o */
896 if (flags & VG_MSG_ALTFORMAT) {
897 ret += 2;
898 send('0',send_arg2);
900 if (is_sizet)
901 ret += myvprintf_int64(send, send_arg2, flags, 8, width, False,
902 (ULong)(va_arg (vargs, SizeT)));
903 else if (is_long)
904 ret += myvprintf_int64(send, send_arg2, flags, 8, width, False,
905 (ULong)(va_arg (vargs, ULong)));
906 else
907 ret += myvprintf_int64(send, send_arg2, flags, 8, width, False,
908 (ULong)(va_arg (vargs, UInt)));
909 break;
910 case 'd': /* %d */
911 flags |= VG_MSG_SIGNED;
912 if (is_long)
913 ret += myvprintf_int64(send, send_arg2, flags, 10, width, False,
914 (ULong)(va_arg (vargs, Long)));
915 else
916 ret += myvprintf_int64(send, send_arg2, flags, 10, width, False,
917 (ULong)(va_arg (vargs, Int)));
918 break;
919 case 'u': /* %u */
920 if (is_sizet)
921 ret += myvprintf_int64(send, send_arg2, flags, 10, width, False,
922 (ULong)(va_arg (vargs, SizeT)));
923 else if (is_long)
924 ret += myvprintf_int64(send, send_arg2, flags, 10, width, False,
925 (ULong)(va_arg (vargs, ULong)));
926 else
927 ret += myvprintf_int64(send, send_arg2, flags, 10, width, False,
928 (ULong)(va_arg (vargs, UInt)));
929 break;
930 case 'p':
931 if (format[i+1] == 'S') {
932 i++;
933 /* %pS, like %s but escaping chars for XML safety */
934 /* Note: simplistic; ignores field width and flags */
935 const HChar *str = va_arg (vargs, HChar *);
936 if (str == NULL)
937 str = "(null)";
938 ret += myvprintf_str_XML_simplistic(send, send_arg2, str);
939 } else if (format[i+1] == 's') {
940 i++;
941 /* %ps, synonym for %s with --xml=no / %pS with --xml=yes */
942 const HChar *str = va_arg (vargs, HChar *);
943 if (str == NULL)
944 str = "(null)";
945 if (clo_xml)
946 ret += myvprintf_str_XML_simplistic(send, send_arg2, str);
947 else
948 ret += myvprintf_str(send, send_arg2, flags, width, str,
949 False);
950 } else {
951 /* %p */
952 ret += 2;
953 send('0',send_arg2);
954 send('x',send_arg2);
955 ret += myvprintf_int64(send, send_arg2, flags, 16, width, True,
956 (ULong)((UWord)va_arg (vargs, void *)));
958 break;
959 case 'x': /* %x */
960 case 'X': /* %X */
961 caps = toBool(format[i] == 'X');
962 if (flags & VG_MSG_ALTFORMAT) {
963 ret += 2;
964 send('0',send_arg2);
965 send('x',send_arg2);
967 if (is_sizet)
968 ret += myvprintf_int64(send, send_arg2, flags, 16, width, False,
969 (ULong)(va_arg (vargs, SizeT)));
970 else if (is_long)
971 ret += myvprintf_int64(send, send_arg2, flags, 16, width, caps,
972 (ULong)(va_arg (vargs, ULong)));
973 else
974 ret += myvprintf_int64(send, send_arg2, flags, 16, width, caps,
975 (ULong)(va_arg (vargs, UInt)));
976 break;
977 case 'c': /* %c */
978 ret++;
979 send(va_arg (vargs, int), send_arg2);
980 break;
981 case 's': case 'S': { /* %s */
982 const HChar *str = va_arg (vargs, HChar *);
983 if (str == NULL) str = "(null)";
984 ret += myvprintf_str(send, send_arg2,
985 flags, width, str, format[i]=='S');
986 break;
988 case 'f': {
989 /* Print a floating point number in the format x.y without
990 any exponent. Capabilities are extremely limited, basically
991 a joke, but good enough for our needs. */
992 Double val = va_arg (vargs, Double);
993 Bool is_negative = False;
994 Int cnt;
996 if (val < 0.0) {
997 is_negative = True;
998 val = - val;
1000 /* If the integral part of the floating point number cannot be
1001 represented by an ULONG_MAX, print '*' characters */
1002 if (val > (Double)(~0ULL)) {
1003 if (width == 0) width = 6; // say
1004 for (cnt = 0; cnt < width; ++cnt)
1005 send('*', send_arg2);
1006 ret += width;
1007 break;
1009 /* The integral part of the floating point number is representable
1010 by an ULong. */
1011 ULong ipval = val;
1012 Double frac = val - ipval;
1014 if (precision == -1) precision = 6; // say
1016 /* Silently limit the precision to 10 digits. */
1017 if (precision > 10) precision = 10;
1019 /* Determine fractional part, possibly round up */
1020 ULong factor = 1;
1021 for (cnt = 0; cnt < precision; ++cnt)
1022 factor *= 10;
1023 ULong frval = frac * factor;
1024 if ((frac * factor - frval) > 0.5) // round up
1025 frval += 1;
1026 /* Check rounding. */
1027 if (frval == factor)
1028 ipval += 1;
1029 frval %= factor;
1031 /* Find out how many characters are needed to print the number */
1033 /* The integral part... */
1034 UInt ipwidth, num_digit = 1; // at least one digit
1035 ULong x, old_x = 0;
1036 for (x = 10; ; old_x = x, x *= 10, ++num_digit) {
1037 if (x <= old_x) break; // overflow occurred
1038 if (ipval < x) break;
1040 ipwidth = num_digit; // width of integral part.
1041 if (is_negative) ++num_digit;
1042 if (precision != 0)
1043 num_digit += 1 + precision;
1045 // Print the number
1047 // Fill in blanks on the left
1048 if (num_digit < width && (flags & VG_MSG_LJUSTIFY) == 0) {
1049 for (cnt = 0; cnt < width - num_digit; ++cnt)
1050 send(' ', send_arg2);
1051 ret += width - num_digit;
1053 // Sign, maybe
1054 if (is_negative) {
1055 send('-', send_arg2);
1056 ret += 1;
1058 // Integral part
1059 ret += myvprintf_int64(send, send_arg2, 0, 10, ipwidth, False,
1060 ipval);
1061 // Decimal point and fractional part
1062 if (precision != 0) {
1063 send('.', send_arg2);
1064 ret += 1;
1066 ret += myvprintf_int64(send, send_arg2, VG_MSG_ZJUSTIFY, 10,
1067 precision, False, frval);
1069 // Fill in blanks on the right
1070 if (num_digit < width && (flags & VG_MSG_LJUSTIFY) != 0) {
1071 for (cnt = 0; cnt < width - num_digit; ++cnt)
1072 send(' ', send_arg2);
1073 ret += width - num_digit;
1075 break;
1078 // case 'y': { /* %y - print symbol */
1079 // Addr a = va_arg(vargs, Addr);
1081 // HChar *name;
1082 // if (VG_(get_fnname_w_offset)(a, &name)) {
1083 // HChar buf[1 + VG_strlen(name) + 1 + 1];
1084 // if (flags & VG_MSG_PAREN) {
1085 // VG_(sprintf)(str, "(%s)", name):
1086 // } else {
1087 // VG_(sprintf)(str, "%s", name):
1088 // }
1089 // ret += myvprintf_str(send, flags, width, buf, 0);
1090 // }
1091 // break;
1092 // }
1093 default:
1094 break;
1097 return ret;
1101 /*------------------------------------------------------------*/
1102 /*--- Debuglog stuff. ---*/
1103 /*------------------------------------------------------------*/
1105 /* Only print messages whose stated level is less than or equal to
1106 this. By default, it makes this entire subsystem silent. */
1108 static Int loglevel = 0;
1110 /* Module startup. */
1111 /* EXPORTED */
1112 void VG_(debugLog_startup) ( Int level, const HChar* who )
1114 if (level < 0) level = 0;
1115 if (level > 10) level = 10;
1116 loglevel = level;
1117 VG_(debugLog)(1, "debuglog",
1118 "DebugLog system started by %s, "
1119 "level %d logging requested\n",
1120 who, loglevel);
1123 /* Get the logging threshold level, as set by the most recent call to
1124 VG_(debugLog_startup), or zero if there have been no such calls so
1125 far. */
1126 /* EXPORTED */
1127 Int VG_(debugLog_getLevel) ( void )
1129 return loglevel;
1133 /* ------------ */
1135 typedef
1136 struct {
1137 HChar buf[100];
1138 Int n;
1140 printf_buf;
1142 static void add_to_buf ( HChar c, void* p )
1144 printf_buf* buf = (printf_buf*)p;
1146 if (buf->n >= 100-10 /*paranoia*/ ) {
1147 emit( buf->buf, local_strlen(buf->buf) );
1148 buf->n = 0;
1149 buf->buf[buf->n] = 0;
1151 buf->buf[buf->n++] = c;
1152 buf->buf[buf->n] = 0;
1155 /* Send a logging message. Nothing is output unless 'level'
1156 is <= the current loglevel. */
1157 /* EXPORTED */
1158 void VG_(debugLog) ( Int level, const HChar* modulename,
1159 const HChar* format, ... )
1161 UInt pid;
1162 Int indent, depth, i;
1163 va_list vargs;
1164 printf_buf buf;
1166 if (level > loglevel)
1167 return;
1169 indent = 2*level - 1;
1170 if (indent < 1) indent = 1;
1172 buf.n = 0;
1173 buf.buf[0] = 0;
1174 pid = local_sys_getpid();
1176 // Print one '>' in front of the messages for each level of self-hosting
1177 // being performed.
1178 depth = RUNNING_ON_VALGRIND;
1179 for (i = 0; i < depth; i++) {
1180 (void)myvprintf_str ( add_to_buf, &buf, 0, 1, ">", False );
1183 (void)myvprintf_str ( add_to_buf, &buf, 0, 2, "--", False );
1184 (void)myvprintf_int64 ( add_to_buf, &buf, 0, 10, 1, False, (ULong)pid );
1185 (void)myvprintf_str ( add_to_buf, &buf, 0, 1, ":", False );
1186 (void)myvprintf_int64 ( add_to_buf, &buf, 0, 10, 1, False, (ULong)level );
1187 (void)myvprintf_str ( add_to_buf, &buf, 0, 1, ":", False );
1188 (void)myvprintf_str ( add_to_buf, &buf, 0, 8, modulename, False );
1189 (void)myvprintf_str ( add_to_buf, &buf, 0, indent, "", False );
1191 va_start(vargs,format);
1193 (void) VG_(debugLog_vprintf) ( add_to_buf, &buf, format, vargs );
1195 if (buf.n > 0) {
1196 emit( buf.buf, local_strlen(buf.buf) );
1199 va_end(vargs);
1204 /*--------------------------------------------------------------------*/
1205 /*--- end m_debuglog.c ---*/
1206 /*--------------------------------------------------------------------*/