arm64 insn selector: improved handling of Or1/And1 trees.
[valgrind.git] / coregrind / m_debuglog.c
blobce4714d1bfbfd9042bddc999fd19fa01baab7117
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, see <http://www.gnu.org/licenses/>.
27 The GNU General Public License is contained in the file COPYING.
31 /* Performs low-level debug logging that can safely run immediately
32 after startup. To minimise the dependencies on any other parts of
33 the system, the only place the debug output may go is file
34 descriptor 2 (stderr).
36 /* This is the first-initialised module in the entire system!
37 Therefore it is CRITICAL that it does not depend on any other code
38 running first. Hence only the following very limited includes. We
39 cannot depend (directly or indirectly) on any dynamic memory
40 allocation facilities, nor on the m_libc facilities, since the
41 latter depend on this module. DO NOT MESS WITH THESE INCLUDES
42 UNLESS YOU ARE 100% CERTAIN YOU UNDERSTAND THE CONSEQUENCES.
45 /* This module is also notable because it is linked into both
46 stage1 and stage2. */
48 /* IMPORTANT: on Darwin it is essential to use the _nocancel versions
49 of syscalls rather than the vanilla version, if a _nocancel version
50 is available. See docs/internals/Darwin-notes.txt for the reason
51 why. */
53 #include "pub_core_basics.h" /* basic types */
54 #include "pub_core_vkiscnums.h" /* for syscall numbers */
55 #include "pub_core_debuglog.h" /* our own iface */
56 #include "pub_core_clreq.h" /* for RUNNING_ON_VALGRIND */
57 #if defined(VGO_solaris)
58 #include "pub_core_vki.h" /* for EINTR and ERESTART */
59 #endif
61 static Bool clo_xml;
63 void VG_(debugLog_setXml)(Bool xml)
65 clo_xml = xml;
68 /*------------------------------------------------------------*/
69 /*--- Stuff to make us completely independent. ---*/
70 /*------------------------------------------------------------*/
72 /* ----- Platform-specifics ----- */
74 #if defined(VGP_x86_linux)
76 static UInt local_sys_write_stderr ( const HChar* buf, Int n )
78 Int result;
80 __asm__ volatile (
81 "pushl %%ebx\n"
82 "movl $"VG_STRINGIFY(__NR_write)", %%eax\n" /* %eax = __NR_write */
83 "movl $2, %%ebx\n" /* %ebx = stderr */
84 "int $0x80\n" /* write(stderr, buf, n) */
85 "popl %%ebx\n"
86 : /*wr*/ "=a" (result)
87 : /*rd*/ "c" (buf), "d" (n)
88 : /*trash*/ "edi", "memory", "cc"
91 return result >= 0 ? result : -1;
94 static UInt local_sys_getpid ( void )
96 UInt __res;
97 __asm__ volatile (
98 "movl $"VG_STRINGIFY(__NR_getpid)", %%eax\n" /* %eax = __NR_getpid */
99 "int $0x80\n" /* getpid() */
100 "movl %%eax, %0\n" /* set __res = eax */
101 : "=mr" (__res)
103 : "eax" );
104 return __res;
107 #elif defined(VGP_amd64_linux)
109 __attribute__((noinline))
110 static UInt local_sys_write_stderr ( const HChar* buf, Int n )
112 volatile Long block[2];
113 block[0] = (Long)buf;
114 block[1] = n;
115 __asm__ volatile (
116 "subq $256, %%rsp\n" /* don't trash the stack redzone */
117 "pushq %%r15\n" /* r15 is callee-save */
118 "movq %0, %%r15\n" /* r15 = &block */
119 "pushq %%r15\n" /* save &block */
120 "movq $"VG_STRINGIFY(__NR_write)", %%rax\n" /* rax = __NR_write */
121 "movq $2, %%rdi\n" /* rdi = stderr */
122 "movq 0(%%r15), %%rsi\n" /* rsi = buf */
123 "movq 8(%%r15), %%rdx\n" /* rdx = n */
124 "syscall\n" /* write(stderr, buf, n) */
125 "popq %%r15\n" /* reestablish &block */
126 "movq %%rax, 0(%%r15)\n" /* block[0] = result */
127 "popq %%r15\n" /* restore r15 */
128 "addq $256, %%rsp\n" /* restore stack ptr */
129 : /*wr*/
130 : /*rd*/ "r" (block)
131 : /*trash*/ "rax", "rdi", "rsi", "rdx", "memory", "cc", "rcx", "r11"
133 if (block[0] < 0)
134 block[0] = -1;
135 return (UInt)block[0];
138 static UInt local_sys_getpid ( void )
140 UInt __res;
141 __asm__ volatile (
142 "movq $"VG_STRINGIFY(__NR_getpid)", %%rax\n" /* %rax = __NR_getpid */
143 "syscall\n" /* getpid() */
144 "movl %%eax, %0\n" /* set __res = %eax */
145 : "=mr" (__res)
147 : "rax", "rcx", "r11"
149 return __res;
152 #elif defined(VGP_ppc32_linux)
154 static UInt local_sys_write_stderr ( const HChar* buf, Int n )
156 volatile Int block[2];
157 block[0] = (Int)buf;
158 block[1] = n;
159 __asm__ volatile (
160 "addi 1,1,-256\n\t"
161 "mr 5,%0\n\t" /* r5 = &block[0] */
162 "stw 5,0(1)\n\t" /* stash on stack */
163 "li 0,"VG_STRINGIFY(__NR_write)"\n\t" /* set %r0 = __NR_write */
164 "li 3,2\n\t" /* set %r3 = stderr */
165 "lwz 4,0(5)\n\t" /* set %r4 = buf */
166 "lwz 5,4(5)\n\t" /* set %r5 = n */
167 "sc\n\t" /* write(stderr, buf, n) */
168 "lwz 5,0(1)\n\t"
169 "addi 1,1,256\n\t"
170 "stw 3,0(5)\n" /* block[0] = result */
172 : "b" (block)
173 : "cc","memory","cr0","ctr",
174 "r0","r2","r3","r4","r5","r6","r7","r8","r9","r10","r11","r12"
176 if (block[0] < 0)
177 block[0] = -1;
178 return (UInt)block[0];
181 static UInt local_sys_getpid ( void )
183 register UInt __res __asm__ ("r3");
184 __asm__ volatile (
185 "li 0, %1\n\t"
186 "sc"
187 : "=&r" (__res)
188 : "i" (__NR_getpid)
189 : "cc","memory","cr0","ctr",
190 "r0","r2","r4","r5","r6","r7","r8","r9","r10","r11","r12"
192 return __res;
195 #elif defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux)
197 static UInt local_sys_write_stderr ( const HChar* buf, Int n )
199 volatile Long block[2];
200 block[0] = (Long)buf;
201 block[1] = (Long)n;
202 __asm__ volatile (
203 "addi 1,1,-256\n\t"
204 "mr 5,%0\n\t" /* r5 = &block[0] */
205 "std 5,0(1)\n\t" /* stash on stack */
206 "li 0,"VG_STRINGIFY(__NR_write)"\n\t" /* %r0 = __NR_write */
207 "li 3,2\n\t" /* set %r3 = stderr */
208 "ld 4,0(5)\n\t" /* set %r4 = buf */
209 "ld 5,8(5)\n\t" /* set %r5 = n */
210 "sc\n\t" /* write(stderr, buf, n) */
211 "ld 5,0(1)\n\t"
212 "addi 1,1,256\n\t"
213 "std 3,0(5)\n" /* block[0] = result */
215 : "b" (block)
216 : "cc","memory","cr0","ctr",
217 "r0","r3","r4","r5","r6","r7","r8","r9","r10","r11","r12"
219 if (block[0] < 0)
220 block[0] = -1;
221 return (UInt)(Int)block[0];
224 static UInt local_sys_getpid ( void )
226 register ULong __res __asm__ ("r3");
227 __asm__ volatile (
228 "li 0, %1\n\t"
229 "sc"
230 : "=&r" (__res)
231 : "i" (__NR_getpid)
232 : "cc","memory","cr0","ctr",
233 "r0","r4","r5","r6","r7","r8","r9","r10","r11","r12"
235 return (UInt)__res;
238 #elif defined(VGP_arm_linux)
240 static UInt local_sys_write_stderr ( const HChar* buf, Int n )
242 volatile Int block[2];
243 block[0] = (Int)buf;
244 block[1] = n;
245 __asm__ volatile (
246 "mov r0, #2\n\t" /* stderr */
247 "ldr r1, [%0]\n\t" /* buf */
248 "ldr r2, [%0, #4]\n\t" /* n */
249 "push {r6,r7}\n\t"
250 "mov r7, #"VG_STRINGIFY(__NR_write)"\n\t"
251 "svc 0x0\n" /* write() */
252 "pop {r6,r7}\n\t"
253 "str r0, [%0]\n\t"
255 : "r" (block)
256 : "r0","r1","r2"
258 if (block[0] < 0)
259 block[0] = -1;
260 return (UInt)block[0];
263 static UInt local_sys_getpid ( void )
265 UInt __res;
266 __asm__ volatile (
267 "push {r6,r7}\n\t"
268 "mov r7, #"VG_STRINGIFY(__NR_getpid)"\n\t"
269 "svc 0x0\n\t" /* getpid() */
270 "pop {r6,r7}\n\t"
271 "mov %0, r0\n\t"
272 : "=r" (__res)
274 : "r0" );
275 return __res;
278 #elif defined(VGP_arm64_linux)
280 static UInt local_sys_write_stderr ( const HChar* buf, Int n )
282 volatile ULong block[2];
283 block[0] = (ULong)buf;
284 block[1] = (ULong)n;
285 __asm__ volatile (
286 "mov x0, #2\n\t" /* stderr */
287 "ldr x1, [%0]\n\t" /* buf */
288 "ldr x2, [%0, #8]\n\t" /* n */
289 "mov x8, #"VG_STRINGIFY(__NR_write)"\n\t"
290 "svc 0x0\n" /* write() */
291 "str x0, [%0]\n\t"
293 : "r" (block)
294 : "x0","x1","x2","x7"
296 if (block[0] < 0)
297 block[0] = -1;
298 return (UInt)block[0];
301 static UInt local_sys_getpid ( void )
303 UInt __res;
304 __asm__ volatile (
305 "mov x8, #"VG_STRINGIFY(__NR_getpid)"\n"
306 "svc 0x0\n" /* getpid() */
307 "mov %0, x0\n"
308 : "=r" (__res)
310 : "x0", "x8" );
311 return (UInt)__res;
314 #elif defined(VGP_x86_darwin)
316 /* We would use VG_DARWIN_SYSNO_TO_KERNEL instead of VG_DARWIN_SYSNO_INDEX
317 except that the former has a C ternary ?: operator which isn't valid in
318 asm code. Both macros give the same results for Unix-class syscalls (which
319 these all are, as identified by the use of 'int 0x80'). */
320 __attribute__((noinline))
321 static UInt local_sys_write_stderr ( const HChar* buf, Int n )
323 UInt __res;
324 __asm__ volatile (
325 "movl %2, %%eax\n" /* push n */
326 "pushl %%eax\n"
327 "movl %1, %%eax\n" /* push buf */
328 "pushl %%eax\n"
329 "movl $2, %%eax\n" /* push stderr */
330 "pushl %%eax\n"
331 "movl $"VG_STRINGIFY(VG_DARWIN_SYSNO_INDEX(__NR_write_nocancel))
332 ", %%eax\n"
333 "pushl %%eax\n" /* push fake return address */
334 "int $0x80\n" /* write(stderr, buf, n) */
335 "jnc 1f\n" /* jump if no error */
336 "movl $-1, %%eax\n" /* return -1 if error */
337 "1: "
338 "movl %%eax, %0\n" /* __res = eax */
339 "addl $16, %%esp\n" /* pop x4 */
340 : "=mr" (__res)
341 : "g" (buf), "g" (n)
342 : "eax", "edx", "cc"
344 return __res;
347 static UInt local_sys_getpid ( void )
349 UInt __res;
350 __asm__ volatile (
351 "movl $"VG_STRINGIFY(VG_DARWIN_SYSNO_INDEX(__NR_getpid))", %%eax\n"
352 "int $0x80\n" /* getpid() */
353 "movl %%eax, %0\n" /* set __res = eax */
354 : "=mr" (__res)
356 : "eax", "cc" );
357 return __res;
360 #elif defined(VGP_amd64_darwin)
362 __attribute__((noinline))
363 static UInt local_sys_write_stderr ( const HChar* buf, Int n )
365 UInt __res;
366 __asm__ volatile (
367 "movq $2, %%rdi\n" /* push stderr */
368 "movq %1, %%rsi\n" /* push buf */
369 "movl %2, %%edx\n" /* push n */
370 "movl $"VG_STRINGIFY(VG_DARWIN_SYSNO_FOR_KERNEL(__NR_write_nocancel))
371 ", %%eax\n"
372 "syscall\n" /* write(stderr, buf, n) */
373 "jnc 1f\n" /* jump if no error */
374 "movq $-1, %%rax\n" /* return -1 if error */
375 "1: "
376 "movl %%eax, %0\n" /* __res = eax */
377 : "=mr" (__res)
378 : "g" (buf), "g" (n)
379 : "rdi", "rsi", "rdx", "rcx", "rax", "cc" );
380 return __res;
383 static UInt local_sys_getpid ( void )
385 UInt __res;
386 __asm__ volatile (
387 "movl $"VG_STRINGIFY(VG_DARWIN_SYSNO_FOR_KERNEL(__NR_getpid))", %%eax\n"
388 "syscall\n" /* getpid() */
389 "movl %%eax, %0\n" /* set __res = eax */
390 : "=mr" (__res)
392 : "rax", "rcx", "cc" );
393 return __res;
396 #elif defined(VGP_s390x_linux)
398 static UInt local_sys_write_stderr ( const HChar* buf, Int n )
400 register Int r2 asm("2") = 2; /* file descriptor STDERR */
401 register const HChar* r3 asm("3") = buf;
402 register ULong r4 asm("4") = n;
403 register ULong r2_res asm("2");
404 ULong __res;
406 __asm__ __volatile__ (
407 "svc %b1\n"
408 : "=d" (r2_res)
409 : "i" (__NR_write),
410 "0" (r2),
411 "d" (r3),
412 "d" (r4)
413 : "cc", "memory");
414 __res = r2_res;
416 if (__res >= (ULong)(-125))
417 __res = -1;
418 return (UInt)(__res);
421 static UInt local_sys_getpid ( void )
423 register ULong r2 asm("2");
424 ULong __res;
426 __asm__ __volatile__ (
427 "svc %b1\n"
428 : "=d" (r2)
429 : "i" (__NR_getpid)
430 : "cc", "memory");
431 __res = r2;
433 if (__res >= (ULong)(-125))
434 __res = -1;
435 return (UInt)(__res);
438 #elif defined(VGP_mips32_linux) || defined(VGP_mips64_linux)
440 static UInt local_sys_write_stderr ( const HChar* buf, Int n )
442 register RegWord v0 asm("2");
443 register RegWord a0 asm("4");
444 register RegWord a1 asm("5");
445 register RegWord a2 asm("6");
446 v0 = __NR_write;
447 a2 = n;
448 a1 = (RegWord)(Addr)buf;
449 a0 = 2; // stderr
450 __asm__ volatile (
451 "syscall \n\t"
452 "addiu $4, $0, -1 \n\t"
453 #if ((defined(__mips_isa_rev) && __mips_isa_rev >= 6))
454 "selnez $4, $4, $7 \n\t"
455 "seleqz $2, $2, $7 \n\t"
456 "or $2, $2, $4 \n\t"
457 #else
458 "movn $2, $4, $7 \n\t"
459 #endif
460 : "+d" (v0), "+d" (a0), "+d" (a1), "+d" (a2)
462 : "$1", "$3", "$7", "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15",
463 "$24", "$25", "$31"
465 return v0;
468 static UInt local_sys_getpid ( void )
470 register RegWord v0 asm("2");
471 v0 = __NR_getpid;
472 __asm__ volatile (
473 "syscall \n\t"
474 : "+d" (v0)
476 : "$1", "$3", "$4", "$5", "$6", "$7", "$8", "$9", "$10", "$11", "$12",
477 "$13", "$14", "$15", "$24", "$25", "$31"
479 return v0;
482 #elif defined(VGP_nanomips_linux)
484 __attribute__((noinline))
485 static UInt local_sys_write_stderr ( const HChar* buf, Int n )
487 register RegWord t4 asm("2");
488 register RegWord a0 asm("4");
489 register RegWord a1 asm("5");
490 register RegWord a2 asm("6");
491 t4 = __NR_write;
492 a2 = n;
493 a1 = (RegWord)(Addr)buf;
494 a0 = 2; // stderr
495 __asm__ volatile (
496 "syscall[32] \n\t"
497 : "+d" (t4), "+d" (a0), "+d" (a1), "+d" (a2)
499 : "$at", "$t5", "$a3", "$a4", "$a5", "$a6", "$a7", "$t0", "$t1", "$t2",
500 "$t3", "$t8", "$t9"
502 return a0;
505 __attribute__((noinline))
506 static UInt local_sys_getpid ( void )
508 register RegWord t4 asm("2");
509 register RegWord a0 asm("4");
510 t4 = __NR_getpid;
511 __asm__ volatile (
512 "syscall[32] \n\t"
513 : "+d" (t4), "=d" (a0)
515 : "$at", "$t5", "$a1", "$a2", "$a3", "$a4", "$a5", "$a6", "$a7", "$t0",
516 "$t1", "$t2", "$t3", "$t8", "$t9"
518 return a0;
521 #elif defined(VGP_x86_solaris)
522 static UInt local_sys_write_stderr ( const HChar* buf, Int n )
524 UInt res, err;
525 Bool restart;
527 do {
528 /* The Solaris kernel does not restart syscalls automatically so it is
529 done here. */
530 __asm__ __volatile__ (
531 "movl %[n], %%eax\n" /* push n */
532 "pushl %%eax\n"
533 "movl %[buf], %%eax\n" /* push buf */
534 "pushl %%eax\n"
535 "movl $2, %%eax\n" /* push stderr */
536 "pushl %%eax\n"
537 "movl $"VG_STRINGIFY(__NR_write)", %%eax\n"
538 "pushl %%eax\n" /* push fake return address */
539 "int $0x91\n" /* write(stderr, buf, n) */
540 "movl $0, %%edx\n" /* assume no error */
541 "jnc 1f\n" /* jump if no error */
542 "movl $1, %%edx\n" /* set error flag */
543 "1: "
544 "addl $16, %%esp\n" /* pop x4 */
545 : "=&a" (res), "=d" (err)
546 : [buf] "g" (buf), [n] "g" (n)
547 : "cc");
548 restart = err && (res == VKI_EINTR || res == VKI_ERESTART);
549 } while (restart);
551 return res;
554 static UInt local_sys_getpid ( void )
556 UInt res;
558 /* The getpid() syscall never returns EINTR or ERESTART so there is no need
559 for restarting it. */
560 __asm__ __volatile__ (
561 "movl $"VG_STRINGIFY(__NR_getpid)", %%eax\n"
562 "int $0x91\n" /* getpid() */
563 : "=a" (res)
565 : "edx", "cc");
567 return res;
570 #elif defined(VGP_amd64_solaris)
571 static UInt local_sys_write_stderr ( const HChar* buf, Int n )
573 ULong res, err;
574 Bool restart;
576 do {
577 /* The Solaris kernel does not restart syscalls automatically so it is
578 done here. */
579 __asm__ __volatile__ (
580 "movq $2, %%rdi\n" /* push stderr */
581 "movq $"VG_STRINGIFY(__NR_write)", %%rax\n"
582 "syscall\n" /* write(stderr, buf, n) */
583 "movq $0, %%rdx\n" /* assume no error */
584 "jnc 1f\n" /* jump if no error */
585 "movq $1, %%rdx\n" /* set error flag */
586 "1: "
587 : "=a" (res), "=d" (err)
588 : "S" (buf), "d" (n)
589 : "cc");
590 restart = err && (res == VKI_EINTR || res == VKI_ERESTART);
591 } while (restart);
593 return res;
596 static UInt local_sys_getpid ( void )
598 UInt res;
600 /* The getpid() syscall never returns EINTR or ERESTART so there is no need
601 for restarting it. */
602 __asm__ __volatile__ (
603 "movq $"VG_STRINGIFY(__NR_getpid)", %%rax\n"
604 "syscall\n" /* getpid() */
605 : "=a" (res)
607 : "edx", "cc");
609 return res;
612 #else
613 # error Unknown platform
614 #endif
617 /* ----- generic ----- */
619 /* strlen, so we don't need m_libc */
620 static Int local_strlen ( const HChar* str )
622 Int i = 0;
623 while (str[i] != 0) i++;
624 return i;
627 static HChar local_toupper ( HChar c )
629 if (c >= 'a' && c <= 'z')
630 return c + ('A' - 'a');
631 else
632 return c;
635 /* Emit buf[0 .. n-1] to stderr. Unfortunately platform-specific.
637 static void emit ( const HChar* buf, Int n )
639 if (n >= 1)
640 (void)local_sys_write_stderr(buf, n);
644 /*------------------------------------------------------------*/
645 /*--- A simple, generic, vprintf implementation. ---*/
646 /*------------------------------------------------------------*/
648 /* -----------------------------------------------
649 Distantly derived from:
651 vprintf replacement for Checker.
652 Copyright 1993, 1994, 1995 Tristan Gingold
653 Written September 1993 Tristan Gingold
654 Tristan Gingold, 8 rue Parmentier, F-91120 PALAISEAU, FRANCE
656 (Checker itself was GPL'd.)
657 ----------------------------------------------- */
659 /* Some flags. */
660 #define VG_MSG_SIGNED 1 /* The value is signed. */
661 #define VG_MSG_ZJUSTIFY 2 /* Must justify with '0'. */
662 #define VG_MSG_LJUSTIFY 4 /* Must justify on the left. */
663 #define VG_MSG_PAREN 8 /* Parenthesize if present (for %y) */
664 #define VG_MSG_COMMA 16 /* Add commas to numbers (for %d, %u) */
665 #define VG_MSG_ALTFORMAT 32 /* Convert the value to alternate format */
667 /* Copy a string into the buffer. */
668 static
669 UInt myvprintf_str ( void(*send)(HChar,void*),
670 void* send_arg2,
671 Int flags,
672 Int width,
673 const HChar* str,
674 Bool capitalise )
676 # define MAYBE_TOUPPER(ch) (capitalise ? local_toupper(ch) : (ch))
677 UInt ret = 0;
678 Int i, extra;
679 Int len = local_strlen(str);
681 if (width == 0) {
682 ret += len;
683 for (i = 0; i < len; i++)
684 send(MAYBE_TOUPPER(str[i]), send_arg2);
685 return ret;
688 if (len > width) {
689 ret += width;
690 for (i = 0; i < width; i++)
691 send(MAYBE_TOUPPER(str[i]), send_arg2);
692 return ret;
695 extra = width - len;
696 if (! (flags & VG_MSG_LJUSTIFY)) {
697 ret += extra;
698 for (i = 0; i < extra; i++)
699 send(' ', send_arg2);
701 ret += len;
702 for (i = 0; i < len; i++)
703 send(MAYBE_TOUPPER(str[i]), send_arg2);
704 if (flags & VG_MSG_LJUSTIFY) {
705 ret += extra;
706 for (i = 0; i < extra; i++)
707 send(' ', send_arg2);
710 # undef MAYBE_TOUPPER
711 return ret;
715 /* Copy a string into the buffer, escaping bad XML chars. */
716 static
717 UInt myvprintf_str_XML_simplistic ( void(*send)(HChar,void*),
718 void* send_arg2,
719 const HChar* str )
721 UInt ret = 0;
722 Int i;
723 Int len = local_strlen(str);
724 const HChar* alt;
726 for (i = 0; i < len; i++) {
727 switch (str[i]) {
728 case '&': alt = "&amp;"; break;
729 case '<': alt = "&lt;"; break;
730 case '>': alt = "&gt;"; break;
731 default: alt = NULL;
734 if (alt) {
735 while (*alt) {
736 send(*alt, send_arg2);
737 ret++;
738 alt++;
740 } else {
741 send(str[i], send_arg2);
742 ret++;
746 return ret;
750 /* Write P into the buffer according to these args:
751 * If SIGN is true, p is a signed.
752 * BASE is the base.
753 * If WITH_ZERO is true, '0' must be added.
754 * WIDTH is the width of the field.
756 static
757 UInt myvprintf_int64 ( void(*send)(HChar,void*),
758 void* send_arg2,
759 Int flags,
760 Int base,
761 Int width,
762 Bool capitalised,
763 ULong p )
765 /* To print an ULong base 2 needs 64 characters. If commas are requested,
766 add 21. Plus 1 for a possible sign plus 1 for \0. Makes 87 -- so let's
767 say 90. The size of BUF needs to be max(90, WIDTH + 1) */
768 HChar buf[width + 1 > 90 ? width + 1 : 90];
769 Int ind = 0;
770 Int i, nc = 0;
771 Bool neg = False;
772 const HChar* digits = capitalised ? "0123456789ABCDEF" : "0123456789abcdef";
773 UInt ret = 0;
775 if (base < 2 || base > 16)
776 return ret;
778 if ((flags & VG_MSG_SIGNED) && (Long)p < 0) {
779 p = - (Long)p;
780 neg = True;
783 if (p == 0)
784 buf[ind++] = '0';
785 else {
786 while (p > 0) {
787 if (flags & VG_MSG_COMMA && 10 == base &&
788 0 == (ind-nc) % 3 && 0 != ind)
790 buf[ind++] = ',';
791 nc++;
793 buf[ind++] = digits[p % base];
794 p /= base;
798 if (neg)
799 buf[ind++] = '-';
801 if (width > 0 && !(flags & VG_MSG_LJUSTIFY)) {
802 for(; ind < width; ind++) {
803 buf[ind] = (flags & VG_MSG_ZJUSTIFY) ? '0': ' ';
807 /* Reverse copy to buffer. */
808 ret += ind;
809 for (i = ind -1; i >= 0; i--) {
810 send(buf[i], send_arg2);
812 if (width > 0 && (flags & VG_MSG_LJUSTIFY)) {
813 for(; ind < width; ind++) {
814 ret++;
815 /* Never pad with zeroes on RHS -- changes the value! */
816 send(' ', send_arg2);
819 return ret;
823 /* A simple vprintf(). */
824 /* EXPORTED */
825 UInt
826 VG_(debugLog_vprintf) (
827 void(*send)(HChar,void*),
828 void* send_arg2,
829 const HChar* format,
830 va_list vargs
833 UInt ret = 0;
834 Int i;
835 Int flags;
836 Int width, precision;
837 Int n_ls = 0;
838 Bool is_long, is_sizet, caps;
840 /* We assume that vargs has already been initialised by the
841 caller, using va_start, and that the caller will similarly
842 clean up with va_end.
845 for (i = 0; format[i] != 0; i++) {
846 if (format[i] != '%') {
847 send(format[i], send_arg2);
848 ret++;
849 continue;
851 i++;
852 /* A '%' has been found. Ignore a trailing %. */
853 if (format[i] == 0)
854 break;
855 if (format[i] == '%') {
856 /* '%%' is replaced by '%'. */
857 send('%', send_arg2);
858 ret++;
859 continue;
861 flags = 0;
862 n_ls = 0;
863 width = 0; /* length of the field. */
864 precision = -1; /* unspecified precision */
865 while (1) {
866 switch (format[i]) {
867 case '(':
868 flags |= VG_MSG_PAREN;
869 break;
870 case ',':
871 case '\'':
872 /* If ',' or '\'' follows '%', commas will be inserted. */
873 flags |= VG_MSG_COMMA;
874 break;
875 case '-':
876 /* If '-' follows '%', justify on the left. */
877 flags |= VG_MSG_LJUSTIFY;
878 break;
879 case '0':
880 /* If '0' follows '%', pads will be inserted. */
881 flags |= VG_MSG_ZJUSTIFY;
882 break;
883 case '#':
884 /* If '#' follows '%', alternative format will be used. */
885 flags |= VG_MSG_ALTFORMAT;
886 break;
887 default:
888 goto parse_fieldwidth;
890 i++;
892 parse_fieldwidth:
893 /* Compute the field length. */
894 if (format[i] == '*') {
895 width = va_arg(vargs, Int);
896 ++i;
897 } else {
898 while (format[i] >= '0' && format[i] <= '9') {
899 width *= 10;
900 width += format[i++] - '0';
903 /* Parse precision, if any. Only meaningful for %f. For all other
904 format specifiers the precision will be silently ignored. */
905 if (format[i] == '.') {
906 ++i;
907 if (format[i] == '*') {
908 precision = va_arg(vargs, Int);
909 ++i;
910 } else {
911 precision = 0;
912 while (format[i] >= '0' && format[i] <= '9') {
913 precision *= 10;
914 precision += format[i++] - '0';
919 is_sizet = False;
920 if (format[i] == 'z') {
921 is_sizet = True;
922 ++i;
923 } else {
924 while (format[i] == 'l') {
925 i++;
926 n_ls++;
930 // %d means print a 32-bit integer.
931 // %ld means print a word-size integer.
932 // %lld means print a 64-bit integer.
933 if (0 == n_ls) { is_long = False; }
934 else if (1 == n_ls) { is_long = ( sizeof(void*) == sizeof(Long) ); }
935 else { is_long = True; }
937 switch (format[i]) {
938 case 'o': /* %o */
939 if (flags & VG_MSG_ALTFORMAT) {
940 ret += 2;
941 send('0',send_arg2);
943 if (is_sizet)
944 ret += myvprintf_int64(send, send_arg2, flags, 8, width, False,
945 (ULong)(va_arg (vargs, SizeT)));
946 else if (is_long)
947 ret += myvprintf_int64(send, send_arg2, flags, 8, width, False,
948 (ULong)(va_arg (vargs, ULong)));
949 else
950 ret += myvprintf_int64(send, send_arg2, flags, 8, width, False,
951 (ULong)(va_arg (vargs, UInt)));
952 break;
953 case 'd': /* %d */
954 flags |= VG_MSG_SIGNED;
955 if (is_long)
956 ret += myvprintf_int64(send, send_arg2, flags, 10, width, False,
957 (ULong)(va_arg (vargs, Long)));
958 else
959 ret += myvprintf_int64(send, send_arg2, flags, 10, width, False,
960 (ULong)(va_arg (vargs, Int)));
961 break;
962 case 'u': /* %u */
963 if (is_sizet)
964 ret += myvprintf_int64(send, send_arg2, flags, 10, width, False,
965 (ULong)(va_arg (vargs, SizeT)));
966 else if (is_long)
967 ret += myvprintf_int64(send, send_arg2, flags, 10, width, False,
968 (ULong)(va_arg (vargs, ULong)));
969 else
970 ret += myvprintf_int64(send, send_arg2, flags, 10, width, False,
971 (ULong)(va_arg (vargs, UInt)));
972 break;
973 case 'p':
974 if (format[i+1] == 'S') {
975 i++;
976 /* %pS, like %s but escaping chars for XML safety */
977 /* Note: simplistic; ignores field width and flags */
978 const HChar *str = va_arg (vargs, HChar *);
979 if (str == NULL)
980 str = "(null)";
981 ret += myvprintf_str_XML_simplistic(send, send_arg2, str);
982 } else if (format[i+1] == 's') {
983 i++;
984 /* %ps, synonym for %s with --xml=no / %pS with --xml=yes */
985 const HChar *str = va_arg (vargs, HChar *);
986 if (str == NULL)
987 str = "(null)";
988 if (clo_xml)
989 ret += myvprintf_str_XML_simplistic(send, send_arg2, str);
990 else
991 ret += myvprintf_str(send, send_arg2, flags, width, str,
992 False);
993 } else {
994 /* %p */
995 ret += 2;
996 send('0',send_arg2);
997 send('x',send_arg2);
998 ret += myvprintf_int64(send, send_arg2, flags, 16, width, True,
999 (ULong)((UWord)va_arg (vargs, void *)));
1001 break;
1002 case 'x': /* %x */
1003 case 'X': /* %X */
1004 caps = toBool(format[i] == 'X');
1005 if (flags & VG_MSG_ALTFORMAT) {
1006 ret += 2;
1007 send('0',send_arg2);
1008 send('x',send_arg2);
1010 if (is_sizet)
1011 ret += myvprintf_int64(send, send_arg2, flags, 16, width, False,
1012 (ULong)(va_arg (vargs, SizeT)));
1013 else if (is_long)
1014 ret += myvprintf_int64(send, send_arg2, flags, 16, width, caps,
1015 (ULong)(va_arg (vargs, ULong)));
1016 else
1017 ret += myvprintf_int64(send, send_arg2, flags, 16, width, caps,
1018 (ULong)(va_arg (vargs, UInt)));
1019 break;
1020 case 'c': /* %c */
1021 ret++;
1022 send(va_arg (vargs, int), send_arg2);
1023 break;
1024 case 's': case 'S': { /* %s */
1025 const HChar *str = va_arg (vargs, HChar *);
1026 if (str == NULL) str = "(null)";
1027 ret += myvprintf_str(send, send_arg2,
1028 flags, width, str, format[i]=='S');
1029 break;
1031 case 'f': {
1032 /* Print a floating point number in the format x.y without
1033 any exponent. Capabilities are extremely limited, basically
1034 a joke, but good enough for our needs. */
1035 Double val = va_arg (vargs, Double);
1036 Bool is_negative = False;
1037 Int cnt;
1039 if (val < 0.0) {
1040 is_negative = True;
1041 val = - val;
1043 /* If the integral part of the floating point number cannot be
1044 represented by an ULONG_MAX, print '*' characters */
1045 if (val > (Double)(~0ULL)) {
1046 if (width == 0) width = 6; // say
1047 for (cnt = 0; cnt < width; ++cnt)
1048 send('*', send_arg2);
1049 ret += width;
1050 break;
1052 /* The integral part of the floating point number is representable
1053 by an ULong. */
1054 ULong ipval = val;
1055 Double frac = val - ipval;
1057 if (precision == -1) precision = 6; // say
1059 /* Silently limit the precision to 10 digits. */
1060 if (precision > 10) precision = 10;
1062 /* Determine fractional part, possibly round up */
1063 ULong factor = 1;
1064 for (cnt = 0; cnt < precision; ++cnt)
1065 factor *= 10;
1066 ULong frval = frac * factor;
1067 if ((frac * factor - frval) > 0.5) // round up
1068 frval += 1;
1069 /* Check rounding. */
1070 if (frval == factor)
1071 ipval += 1;
1072 frval %= factor;
1074 /* Find out how many characters are needed to print the number */
1076 /* The integral part... */
1077 UInt ipwidth, num_digit = 1; // at least one digit
1078 ULong x, old_x = 0;
1079 for (x = 10; ; old_x = x, x *= 10, ++num_digit) {
1080 if (x <= old_x) break; // overflow occurred
1081 if (ipval < x) break;
1083 ipwidth = num_digit; // width of integral part.
1084 if (is_negative) ++num_digit;
1085 if (precision != 0)
1086 num_digit += 1 + precision;
1088 // Print the number
1090 // Fill in blanks on the left
1091 if (num_digit < width && (flags & VG_MSG_LJUSTIFY) == 0) {
1092 for (cnt = 0; cnt < width - num_digit; ++cnt)
1093 send(' ', send_arg2);
1094 ret += width - num_digit;
1096 // Sign, maybe
1097 if (is_negative) {
1098 send('-', send_arg2);
1099 ret += 1;
1101 // Integral part
1102 ret += myvprintf_int64(send, send_arg2, 0, 10, ipwidth, False,
1103 ipval);
1104 // Decimal point and fractional part
1105 if (precision != 0) {
1106 send('.', send_arg2);
1107 ret += 1;
1109 ret += myvprintf_int64(send, send_arg2, VG_MSG_ZJUSTIFY, 10,
1110 precision, False, frval);
1112 // Fill in blanks on the right
1113 if (num_digit < width && (flags & VG_MSG_LJUSTIFY) != 0) {
1114 for (cnt = 0; cnt < width - num_digit; ++cnt)
1115 send(' ', send_arg2);
1116 ret += width - num_digit;
1118 break;
1121 // case 'y': { /* %y - print symbol */
1122 // Addr a = va_arg(vargs, Addr);
1124 // HChar *name;
1125 // if (VG_(get_fnname_w_offset)(a, &name)) {
1126 // HChar buf[1 + VG_strlen(name) + 1 + 1];
1127 // if (flags & VG_MSG_PAREN) {
1128 // VG_(sprintf)(str, "(%s)", name):
1129 // } else {
1130 // VG_(sprintf)(str, "%s", name):
1131 // }
1132 // ret += myvprintf_str(send, flags, width, buf, 0);
1133 // }
1134 // break;
1135 // }
1136 default:
1137 break;
1140 return ret;
1144 /*------------------------------------------------------------*/
1145 /*--- Debuglog stuff. ---*/
1146 /*------------------------------------------------------------*/
1148 /* Only print messages whose stated level is less than or equal to
1149 this. By default, it makes this entire subsystem silent. */
1151 static Int loglevel = 0;
1153 /* Module startup. */
1154 /* EXPORTED */
1155 void VG_(debugLog_startup) ( Int level, const HChar* who )
1157 if (level < 0) level = 0;
1158 if (level > 10) level = 10;
1159 loglevel = level;
1160 VG_(debugLog)(1, "debuglog",
1161 "DebugLog system started by %s, "
1162 "level %d logging requested\n",
1163 who, loglevel);
1166 /* Get the logging threshold level, as set by the most recent call to
1167 VG_(debugLog_startup), or zero if there have been no such calls so
1168 far. */
1169 /* EXPORTED */
1170 Int VG_(debugLog_getLevel) ( void )
1172 return loglevel;
1176 /* ------------ */
1178 typedef
1179 struct {
1180 HChar buf[100];
1181 Int n;
1183 printf_buf;
1185 static void add_to_buf ( HChar c, void* p )
1187 printf_buf* buf = (printf_buf*)p;
1189 if (buf->n >= 100-10 /*paranoia*/ ) {
1190 emit( buf->buf, local_strlen(buf->buf) );
1191 buf->n = 0;
1192 buf->buf[buf->n] = 0;
1194 buf->buf[buf->n++] = c;
1195 buf->buf[buf->n] = 0;
1198 /* Send a logging message. Nothing is output unless 'level'
1199 is <= the current loglevel. */
1200 /* EXPORTED */
1201 void VG_(debugLog) ( Int level, const HChar* modulename,
1202 const HChar* format, ... )
1204 UInt pid;
1205 Int indent, depth, i;
1206 va_list vargs;
1207 printf_buf buf;
1209 if (level > loglevel)
1210 return;
1212 indent = 2*level - 1;
1213 if (indent < 1) indent = 1;
1215 buf.n = 0;
1216 buf.buf[0] = 0;
1217 pid = local_sys_getpid();
1219 // Print one '>' in front of the messages for each level of self-hosting
1220 // being performed.
1221 depth = RUNNING_ON_VALGRIND;
1222 for (i = 0; i < depth; i++) {
1223 (void)myvprintf_str ( add_to_buf, &buf, 0, 1, ">", False );
1226 (void)myvprintf_str ( add_to_buf, &buf, 0, 2, "--", False );
1227 (void)myvprintf_int64 ( add_to_buf, &buf, 0, 10, 1, False, (ULong)pid );
1228 (void)myvprintf_str ( add_to_buf, &buf, 0, 1, ":", False );
1229 (void)myvprintf_int64 ( add_to_buf, &buf, 0, 10, 1, False, (ULong)level );
1230 (void)myvprintf_str ( add_to_buf, &buf, 0, 1, ":", False );
1231 (void)myvprintf_str ( add_to_buf, &buf, 0, 8, modulename, False );
1232 (void)myvprintf_str ( add_to_buf, &buf, 0, indent, "", False );
1234 va_start(vargs,format);
1236 (void) VG_(debugLog_vprintf) ( add_to_buf, &buf, format, vargs );
1238 if (buf.n > 0) {
1239 emit( buf.buf, local_strlen(buf.buf) );
1242 va_end(vargs);
1247 /*--------------------------------------------------------------------*/
1248 /*--- end m_debuglog.c ---*/
1249 /*--------------------------------------------------------------------*/