Fix bad gdbserver_tests heap usage tests stderr output.
[valgrind.git] / coregrind / m_debuglog.c
blobdc6e26d2e8735accd67b3a492fb1772a6a04e524
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-2015 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"
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" );
150 return __res;
153 #elif defined(VGP_ppc32_linux)
155 static UInt local_sys_write_stderr ( const HChar* buf, Int n )
157 volatile Int block[2];
158 block[0] = (Int)buf;
159 block[1] = n;
160 __asm__ volatile (
161 "addi 1,1,-256\n\t"
162 "mr 5,%0\n\t" /* r5 = &block[0] */
163 "stw 5,0(1)\n\t" /* stash on stack */
164 "li 0,"VG_STRINGIFY(__NR_write)"\n\t" /* set %r0 = __NR_write */
165 "li 3,2\n\t" /* set %r3 = stderr */
166 "lwz 4,0(5)\n\t" /* set %r4 = buf */
167 "lwz 5,4(5)\n\t" /* set %r5 = n */
168 "sc\n\t" /* write(stderr, buf, n) */
169 "lwz 5,0(1)\n\t"
170 "addi 1,1,256\n\t"
171 "stw 3,0(5)\n" /* block[0] = result */
173 : "b" (block)
174 : "cc","memory","cr0","ctr",
175 "r0","r2","r3","r4","r5","r6","r7","r8","r9","r10","r11","r12"
177 if (block[0] < 0)
178 block[0] = -1;
179 return (UInt)block[0];
182 static UInt local_sys_getpid ( void )
184 register UInt __res __asm__ ("r3");
185 __asm__ volatile (
186 "li 0, %1\n\t"
187 "sc"
188 : "=&r" (__res)
189 : "i" (__NR_getpid)
190 : "cc","memory","cr0","ctr",
191 "r0","r2","r4","r5","r6","r7","r8","r9","r10","r11","r12"
193 return __res;
196 #elif defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux)
198 static UInt local_sys_write_stderr ( const HChar* buf, Int n )
200 volatile Long block[2];
201 block[0] = (Long)buf;
202 block[1] = (Long)n;
203 __asm__ volatile (
204 "addi 1,1,-256\n\t"
205 "mr 5,%0\n\t" /* r5 = &block[0] */
206 "std 5,0(1)\n\t" /* stash on stack */
207 "li 0,"VG_STRINGIFY(__NR_write)"\n\t" /* %r0 = __NR_write */
208 "li 3,2\n\t" /* set %r3 = stderr */
209 "ld 4,0(5)\n\t" /* set %r4 = buf */
210 "ld 5,8(5)\n\t" /* set %r5 = n */
211 "sc\n\t" /* write(stderr, buf, n) */
212 "ld 5,0(1)\n\t"
213 "addi 1,1,256\n\t"
214 "std 3,0(5)\n" /* block[0] = result */
216 : "b" (block)
217 : "cc","memory","cr0","ctr",
218 "r0","r2","r3","r4","r5","r6","r7","r8","r9","r10","r11","r12"
220 if (block[0] < 0)
221 block[0] = -1;
222 return (UInt)(Int)block[0];
225 static UInt local_sys_getpid ( void )
227 register ULong __res __asm__ ("r3");
228 __asm__ volatile (
229 "li 0, %1\n\t"
230 "sc"
231 : "=&r" (__res)
232 : "i" (__NR_getpid)
233 : "cc","memory","cr0","ctr",
234 "r0","r2","r4","r5","r6","r7","r8","r9","r10","r11","r12"
236 return (UInt)__res;
239 #elif defined(VGP_arm_linux)
241 static UInt local_sys_write_stderr ( const HChar* buf, Int n )
243 volatile Int block[2];
244 block[0] = (Int)buf;
245 block[1] = n;
246 __asm__ volatile (
247 "mov r0, #2\n\t" /* stderr */
248 "ldr r1, [%0]\n\t" /* buf */
249 "ldr r2, [%0, #4]\n\t" /* n */
250 "push {r6,r7}\n\t"
251 "mov r7, #"VG_STRINGIFY(__NR_write)"\n\t"
252 "svc 0x0\n" /* write() */
253 "pop {r6,r7}\n\t"
254 "str r0, [%0]\n\t"
256 : "r" (block)
257 : "r0","r1","r2"
259 if (block[0] < 0)
260 block[0] = -1;
261 return (UInt)block[0];
264 static UInt local_sys_getpid ( void )
266 UInt __res;
267 __asm__ volatile (
268 "push {r6,r7}\n\t"
269 "mov r7, #"VG_STRINGIFY(__NR_getpid)"\n\t"
270 "svc 0x0\n\t" /* getpid() */
271 "pop {r6,r7}\n\t"
272 "mov %0, r0\n\t"
273 : "=r" (__res)
275 : "r0" );
276 return __res;
279 #elif defined(VGP_arm64_linux)
281 static UInt local_sys_write_stderr ( const HChar* buf, Int n )
283 volatile ULong block[2];
284 block[0] = (ULong)buf;
285 block[1] = (ULong)n;
286 __asm__ volatile (
287 "mov x0, #2\n\t" /* stderr */
288 "ldr x1, [%0]\n\t" /* buf */
289 "ldr x2, [%0, #8]\n\t" /* n */
290 "mov x8, #"VG_STRINGIFY(__NR_write)"\n\t"
291 "svc 0x0\n" /* write() */
292 "str x0, [%0]\n\t"
294 : "r" (block)
295 : "x0","x1","x2","x7"
297 if (block[0] < 0)
298 block[0] = -1;
299 return (UInt)block[0];
302 static UInt local_sys_getpid ( void )
304 UInt __res;
305 __asm__ volatile (
306 "mov x8, #"VG_STRINGIFY(__NR_getpid)"\n"
307 "svc 0x0\n" /* getpid() */
308 "mov %0, x0\n"
309 : "=r" (__res)
311 : "x0", "x8" );
312 return (UInt)__res;
315 #elif defined(VGP_x86_darwin)
317 /* We would use VG_DARWIN_SYSNO_TO_KERNEL instead of VG_DARWIN_SYSNO_INDEX
318 except that the former has a C ternary ?: operator which isn't valid in
319 asm code. Both macros give the same results for Unix-class syscalls (which
320 these all are, as identified by the use of 'int 0x80'). */
321 __attribute__((noinline))
322 static UInt local_sys_write_stderr ( const HChar* buf, Int n )
324 UInt __res;
325 __asm__ volatile (
326 "movl %2, %%eax\n" /* push n */
327 "pushl %%eax\n"
328 "movl %1, %%eax\n" /* push buf */
329 "pushl %%eax\n"
330 "movl $2, %%eax\n" /* push stderr */
331 "pushl %%eax\n"
332 "movl $"VG_STRINGIFY(VG_DARWIN_SYSNO_INDEX(__NR_write_nocancel))
333 ", %%eax\n"
334 "pushl %%eax\n" /* push fake return address */
335 "int $0x80\n" /* write(stderr, buf, n) */
336 "jnc 1f\n" /* jump if no error */
337 "movl $-1, %%eax\n" /* return -1 if error */
338 "1: "
339 "movl %%eax, %0\n" /* __res = eax */
340 "addl $16, %%esp\n" /* pop x4 */
341 : "=mr" (__res)
342 : "g" (buf), "g" (n)
343 : "eax", "edx", "cc"
345 return __res;
348 static UInt local_sys_getpid ( void )
350 UInt __res;
351 __asm__ volatile (
352 "movl $"VG_STRINGIFY(VG_DARWIN_SYSNO_INDEX(__NR_getpid))", %%eax\n"
353 "int $0x80\n" /* getpid() */
354 "movl %%eax, %0\n" /* set __res = eax */
355 : "=mr" (__res)
357 : "eax", "cc" );
358 return __res;
361 #elif defined(VGP_amd64_darwin)
363 __attribute__((noinline))
364 static UInt local_sys_write_stderr ( const HChar* buf, Int n )
366 UInt __res;
367 __asm__ volatile (
368 "movq $2, %%rdi\n" /* push stderr */
369 "movq %1, %%rsi\n" /* push buf */
370 "movl %2, %%edx\n" /* push n */
371 "movl $"VG_STRINGIFY(VG_DARWIN_SYSNO_FOR_KERNEL(__NR_write_nocancel))
372 ", %%eax\n"
373 "syscall\n" /* write(stderr, buf, n) */
374 "jnc 1f\n" /* jump if no error */
375 "movq $-1, %%rax\n" /* return -1 if error */
376 "1: "
377 "movl %%eax, %0\n" /* __res = eax */
378 : "=mr" (__res)
379 : "g" (buf), "g" (n)
380 : "rdi", "rsi", "rdx", "rcx", "rax", "cc" );
381 return __res;
384 static UInt local_sys_getpid ( void )
386 UInt __res;
387 __asm__ volatile (
388 "movl $"VG_STRINGIFY(VG_DARWIN_SYSNO_FOR_KERNEL(__NR_getpid))", %%eax\n"
389 "syscall\n" /* getpid() */
390 "movl %%eax, %0\n" /* set __res = eax */
391 : "=mr" (__res)
393 : "rax", "rcx", "cc" );
394 return __res;
397 #elif defined(VGP_s390x_linux)
399 static UInt local_sys_write_stderr ( const HChar* buf, Int n )
401 register Int r2 asm("2") = 2; /* file descriptor STDERR */
402 register const HChar* r3 asm("3") = buf;
403 register ULong r4 asm("4") = n;
404 register ULong r2_res asm("2");
405 ULong __res;
407 __asm__ __volatile__ (
408 "svc %b1\n"
409 : "=d" (r2_res)
410 : "i" (__NR_write),
411 "0" (r2),
412 "d" (r3),
413 "d" (r4)
414 : "cc", "memory");
415 __res = r2_res;
417 if (__res >= (ULong)(-125))
418 __res = -1;
419 return (UInt)(__res);
422 static UInt local_sys_getpid ( void )
424 register ULong r2 asm("2");
425 ULong __res;
427 __asm__ __volatile__ (
428 "svc %b1\n"
429 : "=d" (r2)
430 : "i" (__NR_getpid)
431 : "cc", "memory");
432 __res = r2;
434 if (__res >= (ULong)(-125))
435 __res = -1;
436 return (UInt)(__res);
439 #elif defined(VGP_mips32_linux)
441 static UInt local_sys_write_stderr ( const HChar* buf, Int n )
443 volatile Int block[2];
444 block[0] = (Int)buf;
445 block[1] = n;
446 __asm__ volatile (
447 "li $4, 2\n\t" /* stderr */
448 "lw $5, 0(%0)\n\t" /* buf */
449 "lw $6, 4(%0)\n\t" /* n */
450 "move $7, $0\n\t"
451 "li $2, %1\n\t" /* set v0 = __NR_write */
452 "syscall\n\t" /* write() */
453 "nop\n\t"
455 : "r" (block), "n" (__NR_write)
456 : "2", "4", "5", "6", "7"
458 if (block[0] < 0)
459 block[0] = -1;
460 return (UInt)block[0];
463 static UInt local_sys_getpid ( void )
465 UInt __res;
466 __asm__ volatile (
467 "li $2, %1\n\t" /* set v0 = __NR_getpid */
468 "syscall\n\t" /* getpid() */
469 "nop\n\t"
470 "move %0, $2\n"
471 : "=r" (__res)
472 : "n" (__NR_getpid)
473 : "$2" );
474 return __res;
477 #elif defined(VGP_mips64_linux)
479 static UInt local_sys_write_stderr ( const HChar* buf, Int n )
481 volatile Long block[2];
482 block[0] = (Long)buf;
483 block[1] = n;
484 __asm__ volatile (
485 "li $4, 2\n\t" /* std output*/
486 "ld $5, 0(%0)\n\t" /*$5 = buf*/
487 "ld $6, 8(%0)\n\t" /*$6 = n */
488 "move $7, $0\n\t"
489 "li $2, %1\n\t" /* set v0 = __NR_write */
490 "\tsyscall\n"
491 "\tnop\n"
492 : /*wr*/
493 : /*rd*/ "r" (block), "n" (__NR_write)
494 : "2", "4", "5", "6", "7"
496 if (block[0] < 0)
497 block[0] = -1;
498 return (UInt)(Int)block[0];
501 static UInt local_sys_getpid ( void )
503 ULong __res;
504 __asm__ volatile (
505 "li $2, %1\n\t" /* set v0 = __NR_getpid */
506 "syscall\n\t" /* getpid() */
507 "nop\n\t"
508 "move %0, $2\n"
509 : "=r" (__res)
510 : "n" (__NR_getpid)
511 : "$2" );
512 return (UInt)(__res);
515 #elif defined(VGP_tilegx_linux)
517 static UInt local_sys_write_stderr ( const HChar* buf, Int n )
519 volatile Long block[2];
520 block[0] = (Long)buf;
521 block[1] = n;
522 Long __res = 0;
523 __asm__ volatile (
524 "movei r0, 2 \n\t" /* stderr */
525 "move r1, %1 \n\t" /* buf */
526 "move r2, %2 \n\t" /* n */
527 "move r3, zero \n\t"
528 "moveli r10, %3 \n\t" /* set r10 = __NR_write */
529 "swint1 \n\t" /* write() */
530 "nop \n\t"
531 "move %0, r0 \n\t" /* save return into block[0] */
532 : "=r"(__res)
533 : "r" (block[0]), "r"(block[1]), "n" (__NR_write)
534 : "r0", "r1", "r2", "r3", "r4", "r5");
535 if (__res < 0)
536 __res = -1;
537 return (UInt)__res;
540 static UInt local_sys_getpid ( void )
542 UInt __res, __err;
543 __res = 0;
544 __err = 0;
545 __asm__ volatile (
546 "moveli r10, %2\n\t" /* set r10 = __NR_getpid */
547 "swint1\n\t" /* getpid() */
548 "nop\n\t"
549 "move %0, r0\n"
550 "move %1, r1\n"
551 : "=r" (__res), "=r"(__err)
552 : "n" (__NR_getpid)
553 : "r0", "r1", "r2", "r3", "r4",
554 "r5", "r6", "r7", "r8", "r9",
555 "r10", "r11", "r12", "r13", "r14",
556 "r15", "r16", "r17", "r18", "r19",
557 "r20", "r21", "r22", "r23", "r24",
558 "r25", "r26", "r27", "r28", "r29");
559 return __res;
562 #elif defined(VGP_x86_solaris)
563 static UInt local_sys_write_stderr ( const HChar* buf, Int n )
565 UInt res, err;
566 Bool restart;
568 do {
569 /* The Solaris kernel does not restart syscalls automatically so it is
570 done here. */
571 __asm__ __volatile__ (
572 "movl %[n], %%eax\n" /* push n */
573 "pushl %%eax\n"
574 "movl %[buf], %%eax\n" /* push buf */
575 "pushl %%eax\n"
576 "movl $2, %%eax\n" /* push stderr */
577 "pushl %%eax\n"
578 "movl $"VG_STRINGIFY(__NR_write)", %%eax\n"
579 "pushl %%eax\n" /* push fake return address */
580 "int $0x91\n" /* write(stderr, buf, n) */
581 "movl $0, %%edx\n" /* assume no error */
582 "jnc 1f\n" /* jump if no error */
583 "movl $1, %%edx\n" /* set error flag */
584 "1: "
585 "addl $16, %%esp\n" /* pop x4 */
586 : "=&a" (res), "=d" (err)
587 : [buf] "g" (buf), [n] "g" (n)
588 : "cc");
589 restart = err && (res == VKI_EINTR || res == VKI_ERESTART);
590 } while (restart);
592 return res;
595 static UInt local_sys_getpid ( void )
597 UInt res;
599 /* The getpid() syscall never returns EINTR or ERESTART so there is no need
600 for restarting it. */
601 __asm__ __volatile__ (
602 "movl $"VG_STRINGIFY(__NR_getpid)", %%eax\n"
603 "int $0x91\n" /* getpid() */
604 : "=a" (res)
606 : "edx", "cc");
608 return res;
611 #elif defined(VGP_amd64_solaris)
612 static UInt local_sys_write_stderr ( const HChar* buf, Int n )
614 ULong res, err;
615 Bool restart;
617 do {
618 /* The Solaris kernel does not restart syscalls automatically so it is
619 done here. */
620 __asm__ __volatile__ (
621 "movq $2, %%rdi\n" /* push stderr */
622 "movq $"VG_STRINGIFY(__NR_write)", %%rax\n"
623 "syscall\n" /* write(stderr, buf, n) */
624 "movq $0, %%rdx\n" /* assume no error */
625 "jnc 1f\n" /* jump if no error */
626 "movq $1, %%rdx\n" /* set error flag */
627 "1: "
628 : "=a" (res), "=d" (err)
629 : "S" (buf), "d" (n)
630 : "cc");
631 restart = err && (res == VKI_EINTR || res == VKI_ERESTART);
632 } while (restart);
634 return res;
637 static UInt local_sys_getpid ( void )
639 UInt res;
641 /* The getpid() syscall never returns EINTR or ERESTART so there is no need
642 for restarting it. */
643 __asm__ __volatile__ (
644 "movq $"VG_STRINGIFY(__NR_getpid)", %%rax\n"
645 "syscall\n" /* getpid() */
646 : "=a" (res)
648 : "edx", "cc");
650 return res;
653 #else
654 # error Unknown platform
655 #endif
658 /* ----- generic ----- */
660 /* strlen, so we don't need m_libc */
661 static Int local_strlen ( const HChar* str )
663 Int i = 0;
664 while (str[i] != 0) i++;
665 return i;
668 static HChar local_toupper ( HChar c )
670 if (c >= 'a' && c <= 'z')
671 return c + ('A' - 'a');
672 else
673 return c;
676 /* Emit buf[0 .. n-1] to stderr. Unfortunately platform-specific.
678 static void emit ( const HChar* buf, Int n )
680 if (n >= 1)
681 (void)local_sys_write_stderr(buf, n);
685 /*------------------------------------------------------------*/
686 /*--- A simple, generic, vprintf implementation. ---*/
687 /*------------------------------------------------------------*/
689 /* -----------------------------------------------
690 Distantly derived from:
692 vprintf replacement for Checker.
693 Copyright 1993, 1994, 1995 Tristan Gingold
694 Written September 1993 Tristan Gingold
695 Tristan Gingold, 8 rue Parmentier, F-91120 PALAISEAU, FRANCE
697 (Checker itself was GPL'd.)
698 ----------------------------------------------- */
700 /* Some flags. */
701 #define VG_MSG_SIGNED 1 /* The value is signed. */
702 #define VG_MSG_ZJUSTIFY 2 /* Must justify with '0'. */
703 #define VG_MSG_LJUSTIFY 4 /* Must justify on the left. */
704 #define VG_MSG_PAREN 8 /* Parenthesize if present (for %y) */
705 #define VG_MSG_COMMA 16 /* Add commas to numbers (for %d, %u) */
706 #define VG_MSG_ALTFORMAT 32 /* Convert the value to alternate format */
708 /* Copy a string into the buffer. */
709 static
710 UInt myvprintf_str ( void(*send)(HChar,void*),
711 void* send_arg2,
712 Int flags,
713 Int width,
714 const HChar* str,
715 Bool capitalise )
717 # define MAYBE_TOUPPER(ch) (capitalise ? local_toupper(ch) : (ch))
718 UInt ret = 0;
719 Int i, extra;
720 Int len = local_strlen(str);
722 if (width == 0) {
723 ret += len;
724 for (i = 0; i < len; i++)
725 send(MAYBE_TOUPPER(str[i]), send_arg2);
726 return ret;
729 if (len > width) {
730 ret += width;
731 for (i = 0; i < width; i++)
732 send(MAYBE_TOUPPER(str[i]), send_arg2);
733 return ret;
736 extra = width - len;
737 if (! (flags & VG_MSG_LJUSTIFY)) {
738 ret += extra;
739 for (i = 0; i < extra; i++)
740 send(' ', send_arg2);
742 ret += len;
743 for (i = 0; i < len; i++)
744 send(MAYBE_TOUPPER(str[i]), send_arg2);
745 if (flags & VG_MSG_LJUSTIFY) {
746 ret += extra;
747 for (i = 0; i < extra; i++)
748 send(' ', send_arg2);
751 # undef MAYBE_TOUPPER
752 return ret;
756 /* Copy a string into the buffer, escaping bad XML chars. */
757 static
758 UInt myvprintf_str_XML_simplistic ( void(*send)(HChar,void*),
759 void* send_arg2,
760 const HChar* str )
762 UInt ret = 0;
763 Int i;
764 Int len = local_strlen(str);
765 const HChar* alt;
767 for (i = 0; i < len; i++) {
768 switch (str[i]) {
769 case '&': alt = "&amp;"; break;
770 case '<': alt = "&lt;"; break;
771 case '>': alt = "&gt;"; break;
772 default: alt = NULL;
775 if (alt) {
776 while (*alt) {
777 send(*alt, send_arg2);
778 ret++;
779 alt++;
781 } else {
782 send(str[i], send_arg2);
783 ret++;
787 return ret;
791 /* Write P into the buffer according to these args:
792 * If SIGN is true, p is a signed.
793 * BASE is the base.
794 * If WITH_ZERO is true, '0' must be added.
795 * WIDTH is the width of the field.
797 static
798 UInt myvprintf_int64 ( void(*send)(HChar,void*),
799 void* send_arg2,
800 Int flags,
801 Int base,
802 Int width,
803 Bool capitalised,
804 ULong p )
806 /* To print an ULong base 2 needs 64 characters. If commas are requested,
807 add 21. Plus 1 for a possible sign plus 1 for \0. Makes 87 -- so let's
808 say 90. The size of BUF needs to be max(90, WIDTH + 1) */
809 HChar buf[width + 1 > 90 ? width + 1 : 90];
810 Int ind = 0;
811 Int i, nc = 0;
812 Bool neg = False;
813 const HChar* digits = capitalised ? "0123456789ABCDEF" : "0123456789abcdef";
814 UInt ret = 0;
816 if (base < 2 || base > 16)
817 return ret;
819 if ((flags & VG_MSG_SIGNED) && (Long)p < 0) {
820 p = - (Long)p;
821 neg = True;
824 if (p == 0)
825 buf[ind++] = '0';
826 else {
827 while (p > 0) {
828 if (flags & VG_MSG_COMMA && 10 == base &&
829 0 == (ind-nc) % 3 && 0 != ind)
831 buf[ind++] = ',';
832 nc++;
834 buf[ind++] = digits[p % base];
835 p /= base;
839 if (neg)
840 buf[ind++] = '-';
842 if (width > 0 && !(flags & VG_MSG_LJUSTIFY)) {
843 for(; ind < width; ind++) {
844 buf[ind] = (flags & VG_MSG_ZJUSTIFY) ? '0': ' ';
848 /* Reverse copy to buffer. */
849 ret += ind;
850 for (i = ind -1; i >= 0; i--) {
851 send(buf[i], send_arg2);
853 if (width > 0 && (flags & VG_MSG_LJUSTIFY)) {
854 for(; ind < width; ind++) {
855 ret++;
856 /* Never pad with zeroes on RHS -- changes the value! */
857 send(' ', send_arg2);
860 return ret;
864 /* A simple vprintf(). */
865 /* EXPORTED */
866 UInt
867 VG_(debugLog_vprintf) (
868 void(*send)(HChar,void*),
869 void* send_arg2,
870 const HChar* format,
871 va_list vargs
874 UInt ret = 0;
875 Int i;
876 Int flags;
877 Int width, precision;
878 Int n_ls = 0;
879 Bool is_long, is_sizet, caps;
881 /* We assume that vargs has already been initialised by the
882 caller, using va_start, and that the caller will similarly
883 clean up with va_end.
886 for (i = 0; format[i] != 0; i++) {
887 if (format[i] != '%') {
888 send(format[i], send_arg2);
889 ret++;
890 continue;
892 i++;
893 /* A '%' has been found. Ignore a trailing %. */
894 if (format[i] == 0)
895 break;
896 if (format[i] == '%') {
897 /* '%%' is replaced by '%'. */
898 send('%', send_arg2);
899 ret++;
900 continue;
902 flags = 0;
903 n_ls = 0;
904 width = 0; /* length of the field. */
905 precision = -1; /* unspecified precision */
906 while (1) {
907 switch (format[i]) {
908 case '(':
909 flags |= VG_MSG_PAREN;
910 break;
911 case ',':
912 case '\'':
913 /* If ',' or '\'' follows '%', commas will be inserted. */
914 flags |= VG_MSG_COMMA;
915 break;
916 case '-':
917 /* If '-' follows '%', justify on the left. */
918 flags |= VG_MSG_LJUSTIFY;
919 break;
920 case '0':
921 /* If '0' follows '%', pads will be inserted. */
922 flags |= VG_MSG_ZJUSTIFY;
923 break;
924 case '#':
925 /* If '#' follows '%', alternative format will be used. */
926 flags |= VG_MSG_ALTFORMAT;
927 break;
928 default:
929 goto parse_fieldwidth;
931 i++;
933 parse_fieldwidth:
934 /* Compute the field length. */
935 if (format[i] == '*') {
936 width = va_arg(vargs, Int);
937 ++i;
938 } else {
939 while (format[i] >= '0' && format[i] <= '9') {
940 width *= 10;
941 width += format[i++] - '0';
944 /* Parse precision, if any. Only meaningful for %f. For all other
945 format specifiers the precision will be silently ignored. */
946 if (format[i] == '.') {
947 ++i;
948 if (format[i] == '*') {
949 precision = va_arg(vargs, Int);
950 ++i;
951 } else {
952 precision = 0;
953 while (format[i] >= '0' && format[i] <= '9') {
954 precision *= 10;
955 precision += format[i++] - '0';
960 is_sizet = False;
961 if (format[i] == 'z') {
962 is_sizet = True;
963 ++i;
964 } else {
965 while (format[i] == 'l') {
966 i++;
967 n_ls++;
971 // %d means print a 32-bit integer.
972 // %ld means print a word-size integer.
973 // %lld means print a 64-bit integer.
974 if (0 == n_ls) { is_long = False; }
975 else if (1 == n_ls) { is_long = ( sizeof(void*) == sizeof(Long) ); }
976 else { is_long = True; }
978 switch (format[i]) {
979 case 'o': /* %o */
980 if (flags & VG_MSG_ALTFORMAT) {
981 ret += 2;
982 send('0',send_arg2);
984 if (is_sizet)
985 ret += myvprintf_int64(send, send_arg2, flags, 8, width, False,
986 (ULong)(va_arg (vargs, SizeT)));
987 else if (is_long)
988 ret += myvprintf_int64(send, send_arg2, flags, 8, width, False,
989 (ULong)(va_arg (vargs, ULong)));
990 else
991 ret += myvprintf_int64(send, send_arg2, flags, 8, width, False,
992 (ULong)(va_arg (vargs, UInt)));
993 break;
994 case 'd': /* %d */
995 flags |= VG_MSG_SIGNED;
996 if (is_long)
997 ret += myvprintf_int64(send, send_arg2, flags, 10, width, False,
998 (ULong)(va_arg (vargs, Long)));
999 else
1000 ret += myvprintf_int64(send, send_arg2, flags, 10, width, False,
1001 (ULong)(va_arg (vargs, Int)));
1002 break;
1003 case 'u': /* %u */
1004 if (is_sizet)
1005 ret += myvprintf_int64(send, send_arg2, flags, 10, width, False,
1006 (ULong)(va_arg (vargs, SizeT)));
1007 else if (is_long)
1008 ret += myvprintf_int64(send, send_arg2, flags, 10, width, False,
1009 (ULong)(va_arg (vargs, ULong)));
1010 else
1011 ret += myvprintf_int64(send, send_arg2, flags, 10, width, False,
1012 (ULong)(va_arg (vargs, UInt)));
1013 break;
1014 case 'p':
1015 if (format[i+1] == 'S') {
1016 i++;
1017 /* %pS, like %s but escaping chars for XML safety */
1018 /* Note: simplistic; ignores field width and flags */
1019 const HChar *str = va_arg (vargs, HChar *);
1020 if (str == NULL)
1021 str = "(null)";
1022 ret += myvprintf_str_XML_simplistic(send, send_arg2, str);
1023 } else if (format[i+1] == 's') {
1024 i++;
1025 /* %ps, synonym for %s with --xml=no / %pS with --xml=yes */
1026 const HChar *str = va_arg (vargs, HChar *);
1027 if (str == NULL)
1028 str = "(null)";
1029 if (clo_xml)
1030 ret += myvprintf_str_XML_simplistic(send, send_arg2, str);
1031 else
1032 ret += myvprintf_str(send, send_arg2, flags, width, str,
1033 False);
1034 } else {
1035 /* %p */
1036 ret += 2;
1037 send('0',send_arg2);
1038 send('x',send_arg2);
1039 ret += myvprintf_int64(send, send_arg2, flags, 16, width, True,
1040 (ULong)((UWord)va_arg (vargs, void *)));
1042 break;
1043 case 'x': /* %x */
1044 case 'X': /* %X */
1045 caps = toBool(format[i] == 'X');
1046 if (flags & VG_MSG_ALTFORMAT) {
1047 ret += 2;
1048 send('0',send_arg2);
1049 send('x',send_arg2);
1051 if (is_sizet)
1052 ret += myvprintf_int64(send, send_arg2, flags, 16, width, False,
1053 (ULong)(va_arg (vargs, SizeT)));
1054 else if (is_long)
1055 ret += myvprintf_int64(send, send_arg2, flags, 16, width, caps,
1056 (ULong)(va_arg (vargs, ULong)));
1057 else
1058 ret += myvprintf_int64(send, send_arg2, flags, 16, width, caps,
1059 (ULong)(va_arg (vargs, UInt)));
1060 break;
1061 case 'c': /* %c */
1062 ret++;
1063 send(va_arg (vargs, int), send_arg2);
1064 break;
1065 case 's': case 'S': { /* %s */
1066 const HChar *str = va_arg (vargs, HChar *);
1067 if (str == NULL) str = "(null)";
1068 ret += myvprintf_str(send, send_arg2,
1069 flags, width, str, format[i]=='S');
1070 break;
1072 case 'f': {
1073 /* Print a floating point number in the format x.y without
1074 any exponent. Capabilities are extremely limited, basically
1075 a joke, but good enough for our needs. */
1076 Double val = va_arg (vargs, Double);
1077 Bool is_negative = False;
1078 Int cnt;
1080 if (val < 0.0) {
1081 is_negative = True;
1082 val = - val;
1084 /* If the integral part of the floating point number cannot be
1085 represented by an ULONG_MAX, print '*' characters */
1086 if (val > (Double)(~0ULL)) {
1087 if (width == 0) width = 6; // say
1088 for (cnt = 0; cnt < width; ++cnt)
1089 send('*', send_arg2);
1090 ret += width;
1091 break;
1093 /* The integral part of the floating point number is representable
1094 by an ULong. */
1095 ULong ipval = val;
1096 Double frac = val - ipval;
1098 if (precision == -1) precision = 6; // say
1100 /* Silently limit the precision to 10 digits. */
1101 if (precision > 10) precision = 10;
1103 /* Determine fractional part, possibly round up */
1104 ULong factor = 1;
1105 for (cnt = 0; cnt < precision; ++cnt)
1106 factor *= 10;
1107 ULong frval = frac * factor;
1108 if ((frac * factor - frval) > 0.5) // round up
1109 frval += 1;
1110 /* Check rounding. */
1111 if (frval == factor)
1112 ipval += 1;
1113 frval %= factor;
1115 /* Find out how many characters are needed to print the number */
1117 /* The integral part... */
1118 UInt ipwidth, num_digit = 1; // at least one digit
1119 ULong x, old_x = 0;
1120 for (x = 10; ; old_x = x, x *= 10, ++num_digit) {
1121 if (x <= old_x) break; // overflow occurred
1122 if (ipval < x) break;
1124 ipwidth = num_digit; // width of integral part.
1125 if (is_negative) ++num_digit;
1126 if (precision != 0)
1127 num_digit += 1 + precision;
1129 // Print the number
1131 // Fill in blanks on the left
1132 if (num_digit < width && (flags & VG_MSG_LJUSTIFY) == 0) {
1133 for (cnt = 0; cnt < width - num_digit; ++cnt)
1134 send(' ', send_arg2);
1135 ret += width - num_digit;
1137 // Sign, maybe
1138 if (is_negative) {
1139 send('-', send_arg2);
1140 ret += 1;
1142 // Integral part
1143 ret += myvprintf_int64(send, send_arg2, 0, 10, ipwidth, False,
1144 ipval);
1145 // Decimal point and fractional part
1146 if (precision != 0) {
1147 send('.', send_arg2);
1148 ret += 1;
1150 ret += myvprintf_int64(send, send_arg2, VG_MSG_ZJUSTIFY, 10,
1151 precision, False, frval);
1153 // Fill in blanks on the right
1154 if (num_digit < width && (flags & VG_MSG_LJUSTIFY) != 0) {
1155 for (cnt = 0; cnt < width - num_digit; ++cnt)
1156 send(' ', send_arg2);
1157 ret += width - num_digit;
1159 break;
1162 // case 'y': { /* %y - print symbol */
1163 // Addr a = va_arg(vargs, Addr);
1165 // HChar *name;
1166 // if (VG_(get_fnname_w_offset)(a, &name)) {
1167 // HChar buf[1 + VG_strlen(name) + 1 + 1];
1168 // if (flags & VG_MSG_PAREN) {
1169 // VG_(sprintf)(str, "(%s)", name):
1170 // } else {
1171 // VG_(sprintf)(str, "%s", name):
1172 // }
1173 // ret += myvprintf_str(send, flags, width, buf, 0);
1174 // }
1175 // break;
1176 // }
1177 default:
1178 break;
1181 return ret;
1185 /*------------------------------------------------------------*/
1186 /*--- Debuglog stuff. ---*/
1187 /*------------------------------------------------------------*/
1189 /* Only print messages whose stated level is less than or equal to
1190 this. By default, it makes this entire subsystem silent. */
1192 static Int loglevel = 0;
1194 /* Module startup. */
1195 /* EXPORTED */
1196 void VG_(debugLog_startup) ( Int level, const HChar* who )
1198 if (level < 0) level = 0;
1199 if (level > 10) level = 10;
1200 loglevel = level;
1201 VG_(debugLog)(1, "debuglog",
1202 "DebugLog system started by %s, "
1203 "level %d logging requested\n",
1204 who, loglevel);
1207 /* Get the logging threshold level, as set by the most recent call to
1208 VG_(debugLog_startup), or zero if there have been no such calls so
1209 far. */
1210 /* EXPORTED */
1211 Int VG_(debugLog_getLevel) ( void )
1213 return loglevel;
1217 /* ------------ */
1219 typedef
1220 struct {
1221 HChar buf[100];
1222 Int n;
1224 printf_buf;
1226 static void add_to_buf ( HChar c, void* p )
1228 printf_buf* buf = (printf_buf*)p;
1230 if (buf->n >= 100-10 /*paranoia*/ ) {
1231 emit( buf->buf, local_strlen(buf->buf) );
1232 buf->n = 0;
1233 buf->buf[buf->n] = 0;
1235 buf->buf[buf->n++] = c;
1236 buf->buf[buf->n] = 0;
1239 /* Send a logging message. Nothing is output unless 'level'
1240 is <= the current loglevel. */
1241 /* EXPORTED */
1242 void VG_(debugLog) ( Int level, const HChar* modulename,
1243 const HChar* format, ... )
1245 UInt pid;
1246 Int indent, depth, i;
1247 va_list vargs;
1248 printf_buf buf;
1250 if (level > loglevel)
1251 return;
1253 indent = 2*level - 1;
1254 if (indent < 1) indent = 1;
1256 buf.n = 0;
1257 buf.buf[0] = 0;
1258 pid = local_sys_getpid();
1260 // Print one '>' in front of the messages for each level of self-hosting
1261 // being performed.
1262 depth = RUNNING_ON_VALGRIND;
1263 for (i = 0; i < depth; i++) {
1264 (void)myvprintf_str ( add_to_buf, &buf, 0, 1, ">", False );
1267 (void)myvprintf_str ( add_to_buf, &buf, 0, 2, "--", False );
1268 (void)myvprintf_int64 ( add_to_buf, &buf, 0, 10, 1, False, (ULong)pid );
1269 (void)myvprintf_str ( add_to_buf, &buf, 0, 1, ":", False );
1270 (void)myvprintf_int64 ( add_to_buf, &buf, 0, 10, 1, False, (ULong)level );
1271 (void)myvprintf_str ( add_to_buf, &buf, 0, 1, ":", False );
1272 (void)myvprintf_str ( add_to_buf, &buf, 0, 8, modulename, False );
1273 (void)myvprintf_str ( add_to_buf, &buf, 0, indent, "", False );
1275 va_start(vargs,format);
1277 (void) VG_(debugLog_vprintf) ( add_to_buf, &buf, format, vargs );
1279 if (buf.n > 0) {
1280 emit( buf.buf, local_strlen(buf.buf) );
1283 va_end(vargs);
1288 /*--------------------------------------------------------------------*/
1289 /*--- end m_debuglog.c ---*/
1290 /*--------------------------------------------------------------------*/