1 /* -*- mode: C; c-basic-offset: 3; -*- */
2
3 /*--------------------------------------------------------------------*/
4 /*--- Debug (not-for-user) logging; also vprintf. m_debuglog.c ---*/
5 /*--------------------------------------------------------------------*/
6
7 /*
8 This file is part of Valgrind, a dynamic binary instrumentation
9 framework.
10
11 Copyright (C) 2000-2015 Julian Seward
12 jseward@acm.org
13
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.
18
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.
23
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.
28
29 The GNU General Public License is contained in the file COPYING.
30 */
31
32
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).
37 */
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.
45 */
46
47 /* This module is also notable because it is linked into both
48 stage1 and stage2. */
49
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. */
54
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
62
63 static Bool clo_xml;
64
VG_(debugLog_setXml)65 void VG_(debugLog_setXml)(Bool xml)
66 {
67 clo_xml = xml;
68 }
69
70 /*------------------------------------------------------------*/
71 /*--- Stuff to make us completely independent. ---*/
72 /*------------------------------------------------------------*/
73
74 /* ----- Platform-specifics ----- */
75
76 #if defined(VGP_x86_linux)
77
local_sys_write_stderr(const HChar * buf,Int n)78 static UInt local_sys_write_stderr ( const HChar* buf, Int n )
79 {
80 Int result;
81
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"
91 );
92
93 return result >= 0 ? result : -1;
94 }
95
local_sys_getpid(void)96 static UInt local_sys_getpid ( void )
97 {
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)
104 :
105 : "eax" );
106 return __res;
107 }
108
109 #elif defined(VGP_amd64_linux)
110
111 __attribute__((noinline))
local_sys_write_stderr(const HChar * buf,Int n)112 static UInt local_sys_write_stderr ( const HChar* buf, Int n )
113 {
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"
134 );
135 if (block[0] < 0)
136 block[0] = -1;
137 return (UInt)block[0];
138 }
139
local_sys_getpid(void)140 static UInt local_sys_getpid ( void )
141 {
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)
148 :
149 : "rax" );
150 return __res;
151 }
152
153 #elif defined(VGP_ppc32_linux)
154
local_sys_write_stderr(const HChar * buf,Int n)155 static UInt local_sys_write_stderr ( const HChar* buf, Int n )
156 {
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 */
172 :
173 : "b" (block)
174 : "cc","memory","cr0","ctr",
175 "r0","r2","r3","r4","r5","r6","r7","r8","r9","r10","r11","r12"
176 );
177 if (block[0] < 0)
178 block[0] = -1;
179 return (UInt)block[0];
180 }
181
local_sys_getpid(void)182 static UInt local_sys_getpid ( void )
183 {
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"
192 );
193 return __res;
194 }
195
196 #elif defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux)
197
local_sys_write_stderr(const HChar * buf,Int n)198 static UInt local_sys_write_stderr ( const HChar* buf, Int n )
199 {
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 */
215 :
216 : "b" (block)
217 : "cc","memory","cr0","ctr",
218 "r0","r2","r3","r4","r5","r6","r7","r8","r9","r10","r11","r12"
219 );
220 if (block[0] < 0)
221 block[0] = -1;
222 return (UInt)(Int)block[0];
223 }
224
local_sys_getpid(void)225 static UInt local_sys_getpid ( void )
226 {
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"
235 );
236 return (UInt)__res;
237 }
238
239 #elif defined(VGP_arm_linux)
240
local_sys_write_stderr(const HChar * buf,Int n)241 static UInt local_sys_write_stderr ( const HChar* buf, Int n )
242 {
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"
255 :
256 : "r" (block)
257 : "r0","r1","r2"
258 );
259 if (block[0] < 0)
260 block[0] = -1;
261 return (UInt)block[0];
262 }
263
local_sys_getpid(void)264 static UInt local_sys_getpid ( void )
265 {
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)
274 :
275 : "r0" );
276 return __res;
277 }
278
279 #elif defined(VGP_arm64_linux)
280
local_sys_write_stderr(const HChar * buf,Int n)281 static UInt local_sys_write_stderr ( const HChar* buf, Int n )
282 {
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"
293 :
294 : "r" (block)
295 : "x0","x1","x2","x7"
296 );
297 if (block[0] < 0)
298 block[0] = -1;
299 return (UInt)block[0];
300 }
301
local_sys_getpid(void)302 static UInt local_sys_getpid ( void )
303 {
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)
310 :
311 : "x0", "x8" );
312 return (UInt)__res;
313 }
314
315 #elif defined(VGP_x86_darwin)
316
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))
local_sys_write_stderr(const HChar * buf,Int n)322 static UInt local_sys_write_stderr ( const HChar* buf, Int n )
323 {
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"
344 );
345 return __res;
346 }
347
local_sys_getpid(void)348 static UInt local_sys_getpid ( void )
349 {
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)
356 :
357 : "eax", "cc" );
358 return __res;
359 }
360
361 #elif defined(VGP_amd64_darwin)
362
363 __attribute__((noinline))
local_sys_write_stderr(const HChar * buf,Int n)364 static UInt local_sys_write_stderr ( const HChar* buf, Int n )
365 {
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;
382 }
383
local_sys_getpid(void)384 static UInt local_sys_getpid ( void )
385 {
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)
392 :
393 : "rax", "rcx", "cc" );
394 return __res;
395 }
396
397 #elif defined(VGP_s390x_linux)
398
local_sys_write_stderr(const HChar * buf,Int n)399 static UInt local_sys_write_stderr ( const HChar* buf, Int n )
400 {
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;
406
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;
416
417 if (__res >= (ULong)(-125))
418 __res = -1;
419 return (UInt)(__res);
420 }
421
local_sys_getpid(void)422 static UInt local_sys_getpid ( void )
423 {
424 register ULong r2 asm("2");
425 ULong __res;
426
427 __asm__ __volatile__ (
428 "svc %b1\n"
429 : "=d" (r2)
430 : "i" (__NR_getpid)
431 : "cc", "memory");
432 __res = r2;
433
434 if (__res >= (ULong)(-125))
435 __res = -1;
436 return (UInt)(__res);
437 }
438
439 #elif defined(VGP_mips32_linux)
440
local_sys_write_stderr(const HChar * buf,Int n)441 static UInt local_sys_write_stderr ( const HChar* buf, Int n )
442 {
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"
454 :
455 : "r" (block), "n" (__NR_write)
456 : "2", "4", "5", "6", "7"
457 );
458 if (block[0] < 0)
459 block[0] = -1;
460 return (UInt)block[0];
461 }
462
local_sys_getpid(void)463 static UInt local_sys_getpid ( void )
464 {
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;
475 }
476
477 #elif defined(VGP_mips64_linux)
478
local_sys_write_stderr(const HChar * buf,Int n)479 static UInt local_sys_write_stderr ( const HChar* buf, Int n )
480 {
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"
495 );
496 if (block[0] < 0)
497 block[0] = -1;
498 return (UInt)(Int)block[0];
499 }
500
local_sys_getpid(void)501 static UInt local_sys_getpid ( void )
502 {
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);
513 }
514
515 #elif defined(VGP_tilegx_linux)
516
local_sys_write_stderr(const HChar * buf,Int n)517 static UInt local_sys_write_stderr ( const HChar* buf, Int n )
518 {
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;
538 }
539
local_sys_getpid(void)540 static UInt local_sys_getpid ( void )
541 {
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;
560 }
561
562 #elif defined(VGP_x86_solaris)
local_sys_write_stderr(const HChar * buf,Int n)563 static UInt local_sys_write_stderr ( const HChar* buf, Int n )
564 {
565 UInt res, err;
566 Bool restart;
567
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);
591
592 return res;
593 }
594
local_sys_getpid(void)595 static UInt local_sys_getpid ( void )
596 {
597 UInt res;
598
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)
605 :
606 : "edx", "cc");
607
608 return res;
609 }
610
611 #elif defined(VGP_amd64_solaris)
local_sys_write_stderr(const HChar * buf,Int n)612 static UInt local_sys_write_stderr ( const HChar* buf, Int n )
613 {
614 ULong res, err;
615 Bool restart;
616
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);
633
634 return res;
635 }
636
local_sys_getpid(void)637 static UInt local_sys_getpid ( void )
638 {
639 UInt res;
640
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)
647 :
648 : "edx", "cc");
649
650 return res;
651 }
652
653 #else
654 # error Unknown platform
655 #endif
656
657
658 /* ----- generic ----- */
659
660 /* strlen, so we don't need m_libc */
local_strlen(const HChar * str)661 static Int local_strlen ( const HChar* str )
662 {
663 Int i = 0;
664 while (str[i] != 0) i++;
665 return i;
666 }
667
local_toupper(HChar c)668 static HChar local_toupper ( HChar c )
669 {
670 if (c >= 'a' && c <= 'z')
671 return c + ('A' - 'a');
672 else
673 return c;
674 }
675
676 /* Emit buf[0 .. n-1] to stderr. Unfortunately platform-specific.
677 */
emit(const HChar * buf,Int n)678 static void emit ( const HChar* buf, Int n )
679 {
680 if (n >= 1)
681 (void)local_sys_write_stderr(buf, n);
682 }
683
684
685 /*------------------------------------------------------------*/
686 /*--- A simple, generic, vprintf implementation. ---*/
687 /*------------------------------------------------------------*/
688
689 /* -----------------------------------------------
690 Distantly derived from:
691
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
696
697 (Checker itself was GPL'd.)
698 ----------------------------------------------- */
699
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 */
707
708 /* Copy a string into the buffer. */
709 static
myvprintf_str(void (* send)(HChar,void *),void * send_arg2,Int flags,Int width,const HChar * str,Bool capitalise)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 )
716 {
717 # define MAYBE_TOUPPER(ch) (capitalise ? local_toupper(ch) : (ch))
718 UInt ret = 0;
719 Int i, extra;
720 Int len = local_strlen(str);
721
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;
727 }
728
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;
734 }
735
736 extra = width - len;
737 if (! (flags & VG_MSG_LJUSTIFY)) {
738 ret += extra;
739 for (i = 0; i < extra; i++)
740 send(' ', send_arg2);
741 }
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);
749 }
750
751 # undef MAYBE_TOUPPER
752 return ret;
753 }
754
755
756 /* Copy a string into the buffer, escaping bad XML chars. */
757 static
myvprintf_str_XML_simplistic(void (* send)(HChar,void *),void * send_arg2,const HChar * str)758 UInt myvprintf_str_XML_simplistic ( void(*send)(HChar,void*),
759 void* send_arg2,
760 const HChar* str )
761 {
762 UInt ret = 0;
763 Int i;
764 Int len = local_strlen(str);
765 const HChar* alt;
766
767 for (i = 0; i < len; i++) {
768 switch (str[i]) {
769 case '&': alt = "&"; break;
770 case '<': alt = "<"; break;
771 case '>': alt = ">"; break;
772 default: alt = NULL;
773 }
774
775 if (alt) {
776 while (*alt) {
777 send(*alt, send_arg2);
778 ret++;
779 alt++;
780 }
781 } else {
782 send(str[i], send_arg2);
783 ret++;
784 }
785 }
786
787 return ret;
788 }
789
790
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.
796 */
797 static
myvprintf_int64(void (* send)(HChar,void *),void * send_arg2,Int flags,Int base,Int width,Bool capitalised,ULong p)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 )
805 {
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;
815
816 if (base < 2 || base > 16)
817 return ret;
818
819 if ((flags & VG_MSG_SIGNED) && (Long)p < 0) {
820 p = - (Long)p;
821 neg = True;
822 }
823
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)
830 {
831 buf[ind++] = ',';
832 nc++;
833 }
834 buf[ind++] = digits[p % base];
835 p /= base;
836 }
837 }
838
839 if (neg)
840 buf[ind++] = '-';
841
842 if (width > 0 && !(flags & VG_MSG_LJUSTIFY)) {
843 for(; ind < width; ind++) {
844 buf[ind] = (flags & VG_MSG_ZJUSTIFY) ? '0': ' ';
845 }
846 }
847
848 /* Reverse copy to buffer. */
849 ret += ind;
850 for (i = ind -1; i >= 0; i--) {
851 send(buf[i], send_arg2);
852 }
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);
858 }
859 }
860 return ret;
861 }
862
863
864 /* A simple vprintf(). */
865 /* EXPORTED */
866 UInt
VG_(debugLog_vprintf)867 VG_(debugLog_vprintf) (
868 void(*send)(HChar,void*),
869 void* send_arg2,
870 const HChar* format,
871 va_list vargs
872 )
873 {
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;
880
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.
884 */
885
886 for (i = 0; format[i] != 0; i++) {
887 if (format[i] != '%') {
888 send(format[i], send_arg2);
889 ret++;
890 continue;
891 }
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;
901 }
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;
930 }
931 i++;
932 }
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';
942 }
943 }
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';
956 }
957 }
958 }
959
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++;
968 }
969 }
970
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; }
977
978 switch (format[i]) {
979 case 'o': /* %o */
980 if (flags & VG_MSG_ALTFORMAT) {
981 ret += 2;
982 send('0',send_arg2);
983 }
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 *)));
1041 }
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);
1050 }
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;
1071 }
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;
1079
1080 if (val < 0.0) {
1081 is_negative = True;
1082 val = - val;
1083 }
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;
1092 }
1093 /* The integral part of the floating point number is representable
1094 by an ULong. */
1095 ULong ipval = val;
1096 Double frac = val - ipval;
1097
1098 if (precision == -1) precision = 6; // say
1099
1100 /* Silently limit the precision to 10 digits. */
1101 if (precision > 10) precision = 10;
1102
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;
1114
1115 /* Find out how many characters are needed to print the number */
1116
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;
1123 }
1124 ipwidth = num_digit; // width of integral part.
1125 if (is_negative) ++num_digit;
1126 if (precision != 0)
1127 num_digit += 1 + precision;
1128
1129 // Print the number
1130
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;
1136 }
1137 // Sign, maybe
1138 if (is_negative) {
1139 send('-', send_arg2);
1140 ret += 1;
1141 }
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;
1149
1150 ret += myvprintf_int64(send, send_arg2, VG_MSG_ZJUSTIFY, 10,
1151 precision, False, frval);
1152 }
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;
1158 }
1159 break;
1160 }
1161
1162 // case 'y': { /* %y - print symbol */
1163 // Addr a = va_arg(vargs, Addr);
1164 //
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;
1179 }
1180 }
1181 return ret;
1182 }
1183
1184
1185 /*------------------------------------------------------------*/
1186 /*--- Debuglog stuff. ---*/
1187 /*------------------------------------------------------------*/
1188
1189 /* Only print messages whose stated level is less than or equal to
1190 this. By default, it makes this entire subsystem silent. */
1191
1192 static Int loglevel = 0;
1193
1194 /* Module startup. */
1195 /* EXPORTED */
VG_(debugLog_startup)1196 void VG_(debugLog_startup) ( Int level, const HChar* who )
1197 {
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);
1205 }
1206
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 */
VG_(debugLog_getLevel)1211 Int VG_(debugLog_getLevel) ( void )
1212 {
1213 return loglevel;
1214 }
1215
1216
1217 /* ------------ */
1218
1219 typedef
1220 struct {
1221 HChar buf[100];
1222 Int n;
1223 }
1224 printf_buf;
1225
add_to_buf(HChar c,void * p)1226 static void add_to_buf ( HChar c, void* p )
1227 {
1228 printf_buf* buf = (printf_buf*)p;
1229
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;
1234 }
1235 buf->buf[buf->n++] = c;
1236 buf->buf[buf->n] = 0;
1237 }
1238
1239 /* Send a logging message. Nothing is output unless 'level'
1240 is <= the current loglevel. */
1241 /* EXPORTED */
VG_(debugLog)1242 void VG_(debugLog) ( Int level, const HChar* modulename,
1243 const HChar* format, ... )
1244 {
1245 UInt pid;
1246 Int indent, depth, i;
1247 va_list vargs;
1248 printf_buf buf;
1249
1250 if (level > loglevel)
1251 return;
1252
1253 indent = 2*level - 1;
1254 if (indent < 1) indent = 1;
1255
1256 buf.n = 0;
1257 buf.buf[0] = 0;
1258 pid = local_sys_getpid();
1259
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 );
1265 }
1266
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 );
1274
1275 va_start(vargs,format);
1276
1277 (void) VG_(debugLog_vprintf) ( add_to_buf, &buf, format, vargs );
1278
1279 if (buf.n > 0) {
1280 emit( buf.buf, local_strlen(buf.buf) );
1281 }
1282
1283 va_end(vargs);
1284 }
1285
1286
1287
1288 /*--------------------------------------------------------------------*/
1289 /*--- end m_debuglog.c ---*/
1290 /*--------------------------------------------------------------------*/
1291