FreeBSD: remove code for FreeBSD 10
[valgrind.git] / coregrind / m_debuglog.c
blobcad95bcbe203c2f2bd70df86bc62784ef592980c
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 ULong __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 %c1\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 %c1\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_x86_freebsd)
439 static UInt local_sys_write_stderr (const HChar* buf, Int n )
441 Int result;
443 __asm__ volatile (
444 "movl %2, %%eax\n" /* push n */
445 "movl %1, %%edx\n" /* push buf */
446 "pushl %%eax\n"
447 "pushl %%edx\n"
448 "movl $2, %%eax\n" /* push stderr */
449 "pushl %%eax\n"
450 "movl $"VG_STRINGIFY(__NR_write)", %%eax\n"
451 "pushl %%eax\n" /* push write syscall id */
452 "int $0x80\n" /* write(stderr, buf, n) */
453 "jnc 1f\n" /* jump if no error */
454 "movl $-1, %%eax\n" /* return -1 if error */
455 "1: "
456 "movl %%eax, %0\n" /* __res = eax */
457 "addl $16, %%esp\n" /* pop x4 */
458 : /*wr*/ "=mr" (result)
459 : /*rd*/ "g" (buf), "g" (n)
460 : /*trash*/ "eax", "edx", "cc"
462 return result >= 0 ? result : -1;
465 static UInt local_sys_getpid ( void )
467 UInt __res;
468 __asm__ volatile (
469 "movl $20, %%eax\n" /* set %eax = __NR_getpid */
470 "int $0x80\n" /* getpid() */
471 "movl %%eax, %0\n" /* set __res = eax */
472 : "=mr" (__res)
474 : "eax" );
475 return __res;
478 #elif defined(VGP_amd64_freebsd)
479 __attribute__((noinline))
480 static UInt local_sys_write_stderr (const HChar* buf, Int n )
482 volatile Long block[2];
483 block[0] = (Long)buf;
484 block[1] = n;
485 __asm__ volatile (
486 "subq $256, %%rsp\n" /* don't trash the stack redzone */
487 "pushq %%r15\n" /* r15 is callee-save */
488 "movq %0, %%r15\n" /* r15 = &block */
489 "pushq %%r15\n" /* save &block */
490 "movq $"VG_STRINGIFY(__NR_write)", %%rax\n" /* rax = __NR_write */
491 "movq $2, %%rdi\n" /* rdi = stderr */
492 "movq 0(%%r15), %%rsi\n" /* rsi = buf */
493 "movq 8(%%r15), %%rdx\n" /* rdx = n */
494 "syscall\n" /* write(stderr, buf, n) */
495 "popq %%r15\n" /* reestablish &block */
496 "movq %%rax, 0(%%r15)\n" /* block[0] = result */
497 "popq %%r15\n" /* restore r15 */
498 "addq $256, %%rsp\n" /* restore stack ptr */
499 : /*wr*/
500 : /*rd*/ "r" (block)
501 : /*trash*/ "rax", "rdi", "rsi", "rdx", "memory", "cc", "rcx", "r8", "r9", "r11"
503 if (block[0] < 0)
504 block[0] = -1;
505 return (UInt)block[0];
508 static UInt local_sys_getpid ( void )
510 UInt __res;
511 __asm__ volatile (
512 "movq $20, %%rax\n" /* set %rax = __NR_getpid */
513 "syscall\n" /* getpid() */
514 "movl %%eax, %0\n" /* set __res = %eax */
515 : "=mr" (__res)
517 : "rax", "rcx");//, "r11" );
518 return __res;
521 #elif defined(VGP_arm64_freebsd)
523 static UInt local_sys_write_stderr ( const HChar* buf, SizeT n )
525 volatile ULong block[2];
526 block[0] = (ULong)buf;
527 block[1] = (ULong)n;
528 __asm__ volatile (
529 "mov x0, #2\n" /* stderr */
530 "ldr x1, [%0]\n" /* buf */
531 "ldr x2, [%0, #8]\n" /* n */
532 "mov x8, #"VG_STRINGIFY(__NR_write)"\n"
533 "svc 0x0\n" /* write() */
534 "str x0, [%0]\n"
536 : "r" (block)
537 : "x0","x1","x2","x8","cc","memory"
539 if (block[0] < 0)
540 block[0] = -1;
541 return (UInt)block[0];
544 static UInt local_sys_getpid ( void )
546 ULong res;
547 __asm__ volatile (
548 "mov x8, #"VG_STRINGIFY(__NR_getpid)"\n"
549 "svc 0x0\n" /* getpid() */
550 "mov %0, x0\n" /* set res = x0 */
551 : "=r" (res)
553 : "x8", "x0", "x1", "cc" );
554 return (UInt)res;
557 #elif defined(VGP_mips32_linux) || defined(VGP_mips64_linux)
559 static UInt local_sys_write_stderr ( const HChar* buf, Int n )
561 register RegWord v0 asm("2");
562 register RegWord a0 asm("4");
563 register RegWord a1 asm("5");
564 register RegWord a2 asm("6");
565 v0 = __NR_write;
566 a2 = n;
567 a1 = (RegWord)(Addr)buf;
568 a0 = 2; // stderr
569 __asm__ volatile (
570 "syscall \n\t"
571 "addiu $4, $0, -1 \n\t"
572 #if ((defined(__mips_isa_rev) && __mips_isa_rev >= 6))
573 "selnez $4, $4, $7 \n\t"
574 "seleqz $2, $2, $7 \n\t"
575 "or $2, $2, $4 \n\t"
576 #else
577 "movn $2, $4, $7 \n\t"
578 #endif
579 : "+d" (v0), "+d" (a0), "+d" (a1), "+d" (a2)
581 : "$1", "$3", "$7", "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15",
582 "$24", "$25", "$31"
584 return v0;
587 static UInt local_sys_getpid ( void )
589 register RegWord v0 asm("2");
590 v0 = __NR_getpid;
591 __asm__ volatile (
592 "syscall \n\t"
593 : "+d" (v0)
595 : "$1", "$3", "$4", "$5", "$6", "$7", "$8", "$9", "$10", "$11", "$12",
596 "$13", "$14", "$15", "$24", "$25", "$31"
598 return v0;
601 #elif defined(VGP_nanomips_linux)
603 __attribute__((noinline))
604 static UInt local_sys_write_stderr ( const HChar* buf, Int n )
606 register RegWord t4 asm("2");
607 register RegWord a0 asm("4");
608 register RegWord a1 asm("5");
609 register RegWord a2 asm("6");
610 t4 = __NR_write;
611 a2 = n;
612 a1 = (RegWord)(Addr)buf;
613 a0 = 2; // stderr
614 __asm__ volatile (
615 "syscall[32] \n\t"
616 : "+d" (t4), "+d" (a0), "+d" (a1), "+d" (a2)
618 : "$at", "$t5", "$a3", "$a4", "$a5", "$a6", "$a7", "$t0", "$t1", "$t2",
619 "$t3", "$t8", "$t9"
621 return a0;
624 __attribute__((noinline))
625 static UInt local_sys_getpid ( void )
627 register RegWord t4 asm("2");
628 register RegWord a0 asm("4");
629 t4 = __NR_getpid;
630 __asm__ volatile (
631 "syscall[32] \n\t"
632 : "+d" (t4), "=d" (a0)
634 : "$at", "$t5", "$a1", "$a2", "$a3", "$a4", "$a5", "$a6", "$a7", "$t0",
635 "$t1", "$t2", "$t3", "$t8", "$t9"
637 return a0;
640 #elif defined(VGP_x86_solaris)
641 static UInt local_sys_write_stderr ( const HChar* buf, Int n )
643 UInt res, err;
644 Bool restart;
646 do {
647 /* The Solaris kernel does not restart syscalls automatically so it is
648 done here. */
649 __asm__ __volatile__ (
650 "movl %[n], %%eax\n" /* push n */
651 "pushl %%eax\n"
652 "movl %[buf], %%eax\n" /* push buf */
653 "pushl %%eax\n"
654 "movl $2, %%eax\n" /* push stderr */
655 "pushl %%eax\n"
656 "movl $"VG_STRINGIFY(__NR_write)", %%eax\n"
657 "pushl %%eax\n" /* push fake return address */
658 "int $0x91\n" /* write(stderr, buf, n) */
659 "movl $0, %%edx\n" /* assume no error */
660 "jnc 1f\n" /* jump if no error */
661 "movl $1, %%edx\n" /* set error flag */
662 "1: "
663 "addl $16, %%esp\n" /* pop x4 */
664 : "=&a" (res), "=d" (err)
665 : [buf] "g" (buf), [n] "g" (n)
666 : "cc");
667 restart = err && (res == VKI_EINTR || res == VKI_ERESTART);
668 } while (restart);
670 return res;
673 static UInt local_sys_getpid ( void )
675 UInt res;
677 /* The getpid() syscall never returns EINTR or ERESTART so there is no need
678 for restarting it. */
679 __asm__ __volatile__ (
680 "movl $"VG_STRINGIFY(__NR_getpid)", %%eax\n"
681 "int $0x91\n" /* getpid() */
682 : "=a" (res)
684 : "edx", "cc");
686 return res;
689 #elif defined(VGP_amd64_solaris)
690 static UInt local_sys_write_stderr ( const HChar* buf, Int n )
692 ULong res, err;
693 Bool restart;
695 do {
696 /* The Solaris kernel does not restart syscalls automatically so it is
697 done here. */
698 __asm__ __volatile__ (
699 "movq $2, %%rdi\n" /* push stderr */
700 "movq $"VG_STRINGIFY(__NR_write)", %%rax\n"
701 "syscall\n" /* write(stderr, buf, n) */
702 "movq $0, %%rdx\n" /* assume no error */
703 "jnc 1f\n" /* jump if no error */
704 "movq $1, %%rdx\n" /* set error flag */
705 "1: "
706 : "=a" (res), "=d" (err)
707 : "S" (buf), "d" (n)
708 : "cc");
709 restart = err && (res == VKI_EINTR || res == VKI_ERESTART);
710 } while (restart);
712 return res;
715 static UInt local_sys_getpid ( void )
717 UInt res;
719 /* The getpid() syscall never returns EINTR or ERESTART so there is no need
720 for restarting it. */
721 __asm__ __volatile__ (
722 "movq $"VG_STRINGIFY(__NR_getpid)", %%rax\n"
723 "syscall\n" /* getpid() */
724 : "=a" (res)
726 : "edx", "cc");
728 return res;
731 #else
732 # error Unknown platform
733 #endif
736 /* ----- generic ----- */
738 /* strlen, so we don't need m_libc */
739 static Int local_strlen ( const HChar* str )
741 Int i = 0;
742 while (str[i] != 0) i++;
743 return i;
746 static HChar local_toupper ( HChar c )
748 if (c >= 'a' && c <= 'z')
749 return c + ('A' - 'a');
750 else
751 return c;
754 /* Emit buf[0 .. n-1] to stderr. Unfortunately platform-specific.
756 static void emit ( const HChar* buf, Int n )
758 if (n >= 1)
759 (void)local_sys_write_stderr(buf, n);
763 /*------------------------------------------------------------*/
764 /*--- A simple, generic, vprintf implementation. ---*/
765 /*------------------------------------------------------------*/
767 /* -----------------------------------------------
768 Distantly derived from:
770 vprintf replacement for Checker.
771 Copyright 1993, 1994, 1995 Tristan Gingold
772 Written September 1993 Tristan Gingold
773 Tristan Gingold, 8 rue Parmentier, F-91120 PALAISEAU, FRANCE
775 (Checker itself was GPL'd.)
776 ----------------------------------------------- */
778 /* Some flags. */
779 #define VG_MSG_SIGNED 1 /* The value is signed. */
780 #define VG_MSG_ZJUSTIFY 2 /* Must justify with '0'. */
781 #define VG_MSG_LJUSTIFY 4 /* Must justify on the left. */
782 #define VG_MSG_PAREN 8 /* Parenthesize if present (for %y) */
783 #define VG_MSG_COMMA 16 /* Add commas to numbers (for %d, %u) */
784 #define VG_MSG_ALTFORMAT 32 /* Convert the value to alternate format */
786 /* Copy a string into the buffer. */
787 static
788 UInt myvprintf_str ( void(*send)(HChar,void*),
789 void* send_arg2,
790 Int flags,
791 Int width,
792 const HChar* str,
793 Bool capitalise )
795 # define MAYBE_TOUPPER(ch) (capitalise ? local_toupper(ch) : (ch))
796 UInt ret = 0;
797 Int i, extra;
798 Int len = local_strlen(str);
800 if (width == 0) {
801 ret += len;
802 for (i = 0; i < len; i++)
803 send(MAYBE_TOUPPER(str[i]), send_arg2);
804 return ret;
807 if (len > width) {
808 ret += width;
809 for (i = 0; i < width; i++)
810 send(MAYBE_TOUPPER(str[i]), send_arg2);
811 return ret;
814 extra = width - len;
815 if (! (flags & VG_MSG_LJUSTIFY)) {
816 ret += extra;
817 for (i = 0; i < extra; i++)
818 send(' ', send_arg2);
820 ret += len;
821 for (i = 0; i < len; i++)
822 send(MAYBE_TOUPPER(str[i]), send_arg2);
823 if (flags & VG_MSG_LJUSTIFY) {
824 ret += extra;
825 for (i = 0; i < extra; i++)
826 send(' ', send_arg2);
829 # undef MAYBE_TOUPPER
830 return ret;
834 /* Copy a string into the buffer, escaping bad XML chars. */
835 static
836 UInt myvprintf_str_XML_simplistic ( void(*send)(HChar,void*),
837 void* send_arg2,
838 const HChar* str )
840 UInt ret = 0;
841 Int i;
842 Int len = local_strlen(str);
843 const HChar* alt;
845 for (i = 0; i < len; i++) {
846 switch (str[i]) {
847 case '&': alt = "&amp;"; break;
848 case '<': alt = "&lt;"; break;
849 case '>': alt = "&gt;"; break;
850 default: alt = NULL;
853 if (alt) {
854 while (*alt) {
855 send(*alt, send_arg2);
856 ret++;
857 alt++;
859 } else {
860 send(str[i], send_arg2);
861 ret++;
865 return ret;
869 /* Write P into the buffer according to these args:
870 * If SIGN is true, p is a signed.
871 * BASE is the base.
872 * If WITH_ZERO is true, '0' must be added.
873 * WIDTH is the width of the field.
875 static
876 UInt myvprintf_int64 ( void(*send)(HChar,void*),
877 void* send_arg2,
878 Int flags,
879 Int base,
880 Int width,
881 Bool capitalised,
882 ULong p )
884 /* To print an ULong base 2 needs 64 characters. If commas are requested,
885 add 21. Plus 1 for a possible sign plus 1 for \0. Makes 87 -- so let's
886 say 90. The size of BUF needs to be max(90, WIDTH + 1) */
887 HChar buf[width + 1 > 90 ? width + 1 : 90];
888 Int ind = 0;
889 Int i, nc = 0;
890 Bool neg = False;
891 const HChar* digits = capitalised ? "0123456789ABCDEF" : "0123456789abcdef";
892 UInt ret = 0;
894 if (base < 2 || base > 16)
895 return ret;
897 if ((flags & VG_MSG_SIGNED) && (Long)p < 0) {
898 p = - (Long)p;
899 neg = True;
902 if (p == 0)
903 buf[ind++] = '0';
904 else {
905 while (p > 0) {
906 if (flags & VG_MSG_COMMA && 10 == base &&
907 0 == (ind-nc) % 3 && 0 != ind)
909 buf[ind++] = ',';
910 nc++;
912 buf[ind++] = digits[p % base];
913 p /= base;
917 if (neg)
918 buf[ind++] = '-';
920 if (width > 0 && !(flags & VG_MSG_LJUSTIFY)) {
921 for(; ind < width; ind++) {
922 buf[ind] = (flags & VG_MSG_ZJUSTIFY) ? '0': ' ';
926 /* Reverse copy to buffer. */
927 ret += ind;
928 for (i = ind -1; i >= 0; i--) {
929 send(buf[i], send_arg2);
931 if (width > 0 && (flags & VG_MSG_LJUSTIFY)) {
932 for(; ind < width; ind++) {
933 ret++;
934 /* Never pad with zeroes on RHS -- changes the value! */
935 send(' ', send_arg2);
938 return ret;
942 /* A simple vprintf(). */
943 /* EXPORTED */
944 UInt
945 VG_(debugLog_vprintf) (
946 void(*send)(HChar,void*),
947 void* send_arg2,
948 const HChar* format,
949 va_list vargs
952 UInt ret = 0;
953 Int i;
954 Int flags;
955 Int width, precision;
956 Int n_ls = 0;
957 Bool is_long, is_sizet, caps;
959 /* We assume that vargs has already been initialised by the
960 caller, using va_start, and that the caller will similarly
961 clean up with va_end.
964 for (i = 0; format[i] != 0; i++) {
965 if (format[i] != '%') {
966 send(format[i], send_arg2);
967 ret++;
968 continue;
970 i++;
971 /* A '%' has been found. Ignore a trailing %. */
972 if (format[i] == 0)
973 break;
974 if (format[i] == '%') {
975 /* '%%' is replaced by '%'. */
976 send('%', send_arg2);
977 ret++;
978 continue;
980 flags = 0;
981 n_ls = 0;
982 width = 0; /* length of the field. */
983 precision = -1; /* unspecified precision */
984 while (1) {
985 switch (format[i]) {
986 case '(':
987 flags |= VG_MSG_PAREN;
988 break;
989 case ',':
990 case '\'':
991 /* If ',' or '\'' follows '%', commas will be inserted. */
992 flags |= VG_MSG_COMMA;
993 break;
994 case '-':
995 /* If '-' follows '%', justify on the left. */
996 flags |= VG_MSG_LJUSTIFY;
997 break;
998 case '0':
999 /* If '0' follows '%', pads will be inserted. */
1000 flags |= VG_MSG_ZJUSTIFY;
1001 break;
1002 case '#':
1003 /* If '#' follows '%', alternative format will be used. */
1004 flags |= VG_MSG_ALTFORMAT;
1005 break;
1006 default:
1007 goto parse_fieldwidth;
1009 i++;
1011 parse_fieldwidth:
1012 /* Compute the field length. */
1013 if (format[i] == '*') {
1014 width = va_arg(vargs, Int);
1015 ++i;
1016 } else {
1017 while (format[i] >= '0' && format[i] <= '9') {
1018 width *= 10;
1019 width += format[i++] - '0';
1022 /* Parse precision, if any. Only meaningful for %f. For all other
1023 format specifiers the precision will be silently ignored. */
1024 if (format[i] == '.') {
1025 ++i;
1026 if (format[i] == '*') {
1027 precision = va_arg(vargs, Int);
1028 ++i;
1029 } else {
1030 precision = 0;
1031 while (format[i] >= '0' && format[i] <= '9') {
1032 precision *= 10;
1033 precision += format[i++] - '0';
1038 is_sizet = False;
1039 if (format[i] == 'z') {
1040 is_sizet = True;
1041 ++i;
1042 } else {
1043 while (format[i] == 'l') {
1044 i++;
1045 n_ls++;
1049 // %d means print a 32-bit integer.
1050 // %ld means print a word-size integer.
1051 // %lld means print a 64-bit integer.
1052 if (0 == n_ls) { is_long = False; }
1053 else if (1 == n_ls) { is_long = ( sizeof(void*) == sizeof(Long) ); }
1054 else { is_long = True; }
1056 switch (format[i]) {
1057 case 'o': /* %o */
1058 if (flags & VG_MSG_ALTFORMAT) {
1059 ret += 2;
1060 send('0',send_arg2);
1062 if (is_sizet)
1063 ret += myvprintf_int64(send, send_arg2, flags, 8, width, False,
1064 (ULong)(va_arg (vargs, SizeT)));
1065 else if (is_long)
1066 ret += myvprintf_int64(send, send_arg2, flags, 8, width, False,
1067 (ULong)(va_arg (vargs, ULong)));
1068 else
1069 ret += myvprintf_int64(send, send_arg2, flags, 8, width, False,
1070 (ULong)(va_arg (vargs, UInt)));
1071 break;
1072 case 'd': /* %d */
1073 flags |= VG_MSG_SIGNED;
1074 if (is_long)
1075 ret += myvprintf_int64(send, send_arg2, flags, 10, width, False,
1076 (ULong)(va_arg (vargs, Long)));
1077 else
1078 ret += myvprintf_int64(send, send_arg2, flags, 10, width, False,
1079 (ULong)(va_arg (vargs, Int)));
1080 break;
1081 case 'u': /* %u */
1082 if (is_sizet)
1083 ret += myvprintf_int64(send, send_arg2, flags, 10, width, False,
1084 (ULong)(va_arg (vargs, SizeT)));
1085 else if (is_long)
1086 ret += myvprintf_int64(send, send_arg2, flags, 10, width, False,
1087 (ULong)(va_arg (vargs, ULong)));
1088 else
1089 ret += myvprintf_int64(send, send_arg2, flags, 10, width, False,
1090 (ULong)(va_arg (vargs, UInt)));
1091 break;
1092 case 'p':
1093 if (format[i+1] == 'S') {
1094 i++;
1095 /* %pS, like %s but escaping chars for XML safety */
1096 /* Note: simplistic; ignores field width and flags */
1097 const HChar *str = va_arg (vargs, HChar *);
1098 if (str == NULL)
1099 str = "(null)";
1100 ret += myvprintf_str_XML_simplistic(send, send_arg2, str);
1101 } else if (format[i+1] == 's') {
1102 i++;
1103 /* %ps, synonym for %s with --xml=no / %pS with --xml=yes */
1104 const HChar *str = va_arg (vargs, HChar *);
1105 if (str == NULL)
1106 str = "(null)";
1107 if (clo_xml)
1108 ret += myvprintf_str_XML_simplistic(send, send_arg2, str);
1109 else
1110 ret += myvprintf_str(send, send_arg2, flags, width, str,
1111 False);
1112 } else {
1113 /* %p */
1114 ret += 2;
1115 send('0',send_arg2);
1116 send('x',send_arg2);
1117 ret += myvprintf_int64(send, send_arg2, flags, 16, width, True,
1118 (ULong)((UWord)va_arg (vargs, void *)));
1120 break;
1121 case 'x': /* %x */
1122 case 'X': /* %X */
1123 caps = toBool(format[i] == 'X');
1124 if (flags & VG_MSG_ALTFORMAT) {
1125 ret += 2;
1126 send('0',send_arg2);
1127 send('x',send_arg2);
1129 if (is_sizet)
1130 ret += myvprintf_int64(send, send_arg2, flags, 16, width, False,
1131 (ULong)(va_arg (vargs, SizeT)));
1132 else if (is_long)
1133 ret += myvprintf_int64(send, send_arg2, flags, 16, width, caps,
1134 (ULong)(va_arg (vargs, ULong)));
1135 else
1136 ret += myvprintf_int64(send, send_arg2, flags, 16, width, caps,
1137 (ULong)(va_arg (vargs, UInt)));
1138 break;
1139 case 'c': /* %c */
1140 ret++;
1141 send(va_arg (vargs, int), send_arg2);
1142 break;
1143 case 's': case 'S': { /* %s */
1144 const HChar *str = va_arg (vargs, HChar *);
1145 if (str == NULL) str = "(null)";
1146 ret += myvprintf_str(send, send_arg2,
1147 flags, width, str, format[i]=='S');
1148 break;
1150 case 'f': {
1151 /* Print a floating point number in the format x.y without
1152 any exponent. Capabilities are extremely limited, basically
1153 a joke, but good enough for our needs. */
1154 Double val = va_arg (vargs, Double);
1155 Bool is_negative = False;
1156 Int cnt;
1158 if (val < 0.0) {
1159 is_negative = True;
1160 val = - val;
1162 /* If the integral part of the floating point number cannot be
1163 represented by an ULONG_MAX, print '*' characters */
1164 if (val > (Double)(~0ULL)) {
1165 if (width == 0) width = 6; // say
1166 for (cnt = 0; cnt < width; ++cnt)
1167 send('*', send_arg2);
1168 ret += width;
1169 break;
1171 /* The integral part of the floating point number is representable
1172 by an ULong. */
1173 ULong ipval = val;
1174 Double frac = val - ipval;
1176 if (precision == -1) precision = 6; // say
1178 /* Silently limit the precision to 10 digits. */
1179 if (precision > 10) precision = 10;
1181 /* Determine fractional part, possibly round up */
1182 ULong factor = 1;
1183 for (cnt = 0; cnt < precision; ++cnt)
1184 factor *= 10;
1185 ULong frval = frac * factor;
1186 if ((frac * factor - frval) > 0.5) // round up
1187 frval += 1;
1188 /* Check rounding. */
1189 if (frval == factor)
1190 ipval += 1;
1191 frval %= factor;
1193 /* Find out how many characters are needed to print the number */
1195 /* The integral part... */
1196 UInt ipwidth, num_digit = 1; // at least one digit
1197 ULong x, old_x = 0;
1198 for (x = 10; ; old_x = x, x *= 10, ++num_digit) {
1199 if (x <= old_x) break; // overflow occurred
1200 if (ipval < x) break;
1202 ipwidth = num_digit; // width of integral part.
1203 if (is_negative) ++num_digit;
1204 if (precision != 0)
1205 num_digit += 1 + precision;
1207 // Print the number
1209 // Fill in blanks on the left
1210 if (num_digit < width && (flags & VG_MSG_LJUSTIFY) == 0) {
1211 for (cnt = 0; cnt < width - num_digit; ++cnt)
1212 send(' ', send_arg2);
1213 ret += width - num_digit;
1215 // Sign, maybe
1216 if (is_negative) {
1217 send('-', send_arg2);
1218 ret += 1;
1220 // Integral part
1221 ret += myvprintf_int64(send, send_arg2, 0, 10, ipwidth, False,
1222 ipval);
1223 // Decimal point and fractional part
1224 if (precision != 0) {
1225 send('.', send_arg2);
1226 ret += 1;
1228 ret += myvprintf_int64(send, send_arg2, VG_MSG_ZJUSTIFY, 10,
1229 precision, False, frval);
1231 // Fill in blanks on the right
1232 if (num_digit < width && (flags & VG_MSG_LJUSTIFY) != 0) {
1233 for (cnt = 0; cnt < width - num_digit; ++cnt)
1234 send(' ', send_arg2);
1235 ret += width - num_digit;
1237 break;
1240 // case 'y': { /* %y - print symbol */
1241 // Addr a = va_arg(vargs, Addr);
1243 // HChar *name;
1244 // if (VG_(get_fnname_w_offset)(a, &name)) {
1245 // HChar buf[1 + VG_strlen(name) + 1 + 1];
1246 // if (flags & VG_MSG_PAREN) {
1247 // VG_(sprintf)(str, "(%s)", name):
1248 // } else {
1249 // VG_(sprintf)(str, "%s", name):
1250 // }
1251 // ret += myvprintf_str(send, flags, width, buf, 0);
1252 // }
1253 // break;
1254 // }
1255 default:
1256 break;
1259 return ret;
1263 /*------------------------------------------------------------*/
1264 /*--- Debuglog stuff. ---*/
1265 /*------------------------------------------------------------*/
1267 /* Only print messages whose stated level is less than or equal to
1268 this. By default, it makes this entire subsystem silent. */
1270 static Int loglevel = 0;
1272 /* Module startup. */
1273 /* EXPORTED */
1274 void VG_(debugLog_startup) ( Int level, const HChar* who )
1276 if (level < 0) level = 0;
1277 if (level > 10) level = 10;
1278 loglevel = level;
1279 VG_(debugLog)(1, "debuglog",
1280 "DebugLog system started by %s, "
1281 "level %d logging requested\n",
1282 who, loglevel);
1285 /* Get the logging threshold level, as set by the most recent call to
1286 VG_(debugLog_startup), or zero if there have been no such calls so
1287 far. */
1288 /* EXPORTED */
1289 Int VG_(debugLog_getLevel) ( void )
1291 return loglevel;
1295 /* ------------ */
1297 typedef
1298 struct {
1299 HChar buf[100];
1300 Int n;
1302 printf_buf;
1304 static void add_to_buf ( HChar c, void* p )
1306 printf_buf* buf = (printf_buf*)p;
1308 if (buf->n >= 100-10 /*paranoia*/ ) {
1309 emit( buf->buf, local_strlen(buf->buf) );
1310 buf->n = 0;
1311 buf->buf[buf->n] = 0;
1313 buf->buf[buf->n++] = c;
1314 buf->buf[buf->n] = 0;
1317 /* Send a logging message. Nothing is output unless 'level'
1318 is <= the current loglevel. */
1319 /* EXPORTED */
1320 void VG_(debugLog) ( Int level, const HChar* modulename,
1321 const HChar* format, ... )
1323 UInt pid;
1324 Int indent, depth, i;
1325 va_list vargs;
1326 printf_buf buf;
1328 if (level > loglevel)
1329 return;
1331 indent = 2*level - 1;
1332 if (indent < 1) indent = 1;
1334 buf.n = 0;
1335 buf.buf[0] = 0;
1336 pid = local_sys_getpid();
1338 // Print one '>' in front of the messages for each level of self-hosting
1339 // being performed.
1340 depth = RUNNING_ON_VALGRIND;
1341 for (i = 0; i < depth; i++) {
1342 (void)myvprintf_str ( add_to_buf, &buf, 0, 1, ">", False );
1345 (void)myvprintf_str ( add_to_buf, &buf, 0, 2, "--", False );
1346 (void)myvprintf_int64 ( add_to_buf, &buf, 0, 10, 1, False, (ULong)pid );
1347 (void)myvprintf_str ( add_to_buf, &buf, 0, 1, ":", False );
1348 (void)myvprintf_int64 ( add_to_buf, &buf, 0, 10, 1, False, (ULong)level );
1349 (void)myvprintf_str ( add_to_buf, &buf, 0, 1, ":", False );
1350 (void)myvprintf_str ( add_to_buf, &buf, 0, 8, modulename, False );
1351 (void)myvprintf_str ( add_to_buf, &buf, 0, indent, "", False );
1353 va_start(vargs,format);
1355 (void) VG_(debugLog_vprintf) ( add_to_buf, &buf, format, vargs );
1357 if (buf.n > 0) {
1358 emit( buf.buf, local_strlen(buf.buf) );
1361 va_end(vargs);
1366 /*--------------------------------------------------------------------*/
1367 /*--- end m_debuglog.c ---*/
1368 /*--------------------------------------------------------------------*/