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-2013 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
60 static Bool clo_xml;
61
VG_(debugLog_setXml)62 void VG_(debugLog_setXml)(Bool xml)
63 {
64 clo_xml = xml;
65 }
66
67 /*------------------------------------------------------------*/
68 /*--- Stuff to make us completely independent. ---*/
69 /*------------------------------------------------------------*/
70
71 /* ----- Platform-specifics ----- */
72
73 #if defined(VGP_x86_linux)
74
local_sys_write_stderr(const HChar * buf,Int n)75 static UInt local_sys_write_stderr ( const HChar* buf, Int n )
76 {
77 Int result;
78
79 __asm__ volatile (
80 "pushl %%ebx\n"
81 "movl $"VG_STRINGIFY(__NR_write)", %%eax\n" /* %eax = __NR_write */
82 "movl $2, %%ebx\n" /* %ebx = stderr */
83 "int $0x80\n" /* write(stderr, buf, n) */
84 "popl %%ebx\n"
85 : /*wr*/ "=a" (result)
86 : /*rd*/ "c" (buf), "d" (n)
87 : /*trash*/ "edi", "memory", "cc"
88 );
89
90 return result >= 0 ? result : -1;
91 }
92
local_sys_getpid(void)93 static UInt local_sys_getpid ( void )
94 {
95 UInt __res;
96 __asm__ volatile (
97 "movl $"VG_STRINGIFY(__NR_getpid)", %%eax\n" /* %eax = __NR_getpid */
98 "int $0x80\n" /* getpid() */
99 "movl %%eax, %0\n" /* set __res = eax */
100 : "=mr" (__res)
101 :
102 : "eax" );
103 return __res;
104 }
105
106 #elif defined(VGP_amd64_linux)
107
108 __attribute__((noinline))
local_sys_write_stderr(const HChar * buf,Int n)109 static UInt local_sys_write_stderr ( const HChar* buf, Int n )
110 {
111 volatile Long block[2];
112 block[0] = (Long)buf;
113 block[1] = n;
114 __asm__ volatile (
115 "subq $256, %%rsp\n" /* don't trash the stack redzone */
116 "pushq %%r15\n" /* r15 is callee-save */
117 "movq %0, %%r15\n" /* r15 = &block */
118 "pushq %%r15\n" /* save &block */
119 "movq $"VG_STRINGIFY(__NR_write)", %%rax\n" /* rax = __NR_write */
120 "movq $2, %%rdi\n" /* rdi = stderr */
121 "movq 0(%%r15), %%rsi\n" /* rsi = buf */
122 "movq 8(%%r15), %%rdx\n" /* rdx = n */
123 "syscall\n" /* write(stderr, buf, n) */
124 "popq %%r15\n" /* reestablish &block */
125 "movq %%rax, 0(%%r15)\n" /* block[0] = result */
126 "popq %%r15\n" /* restore r15 */
127 "addq $256, %%rsp\n" /* restore stack ptr */
128 : /*wr*/
129 : /*rd*/ "r" (block)
130 : /*trash*/ "rax", "rdi", "rsi", "rdx", "memory", "cc"
131 );
132 if (block[0] < 0)
133 block[0] = -1;
134 return (UInt)block[0];
135 }
136
local_sys_getpid(void)137 static UInt local_sys_getpid ( void )
138 {
139 UInt __res;
140 __asm__ volatile (
141 "movq $"VG_STRINGIFY(__NR_getpid)", %%rax\n" /* %rax = __NR_getpid */
142 "syscall\n" /* getpid() */
143 "movl %%eax, %0\n" /* set __res = %eax */
144 : "=mr" (__res)
145 :
146 : "rax" );
147 return __res;
148 }
149
150 #elif defined(VGP_ppc32_linux)
151
local_sys_write_stderr(const HChar * buf,Int n)152 static UInt local_sys_write_stderr ( const HChar* buf, Int n )
153 {
154 volatile Int block[2];
155 block[0] = (Int)buf;
156 block[1] = n;
157 __asm__ volatile (
158 "addi 1,1,-256\n\t"
159 "mr 5,%0\n\t" /* r5 = &block[0] */
160 "stw 5,0(1)\n\t" /* stash on stack */
161 "li 0,"VG_STRINGIFY(__NR_write)"\n\t" /* set %r0 = __NR_write */
162 "li 3,2\n\t" /* set %r3 = stderr */
163 "lwz 4,0(5)\n\t" /* set %r4 = buf */
164 "lwz 5,4(5)\n\t" /* set %r5 = n */
165 "sc\n\t" /* write(stderr, buf, n) */
166 "lwz 5,0(1)\n\t"
167 "addi 1,1,256\n\t"
168 "stw 3,0(5)\n" /* block[0] = result */
169 :
170 : "b" (block)
171 : "cc","memory","cr0","ctr",
172 "r0","r2","r3","r4","r5","r6","r7","r8","r9","r10","r11","r12"
173 );
174 if (block[0] < 0)
175 block[0] = -1;
176 return (UInt)block[0];
177 }
178
local_sys_getpid(void)179 static UInt local_sys_getpid ( void )
180 {
181 register UInt __res __asm__ ("r3");
182 __asm__ volatile (
183 "li 0, %1\n\t"
184 "sc"
185 : "=&r" (__res)
186 : "i" (__NR_getpid)
187 : "cc","memory","cr0","ctr",
188 "r0","r2","r4","r5","r6","r7","r8","r9","r10","r11","r12"
189 );
190 return __res;
191 }
192
193 #elif defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux)
194
local_sys_write_stderr(const HChar * buf,Int n)195 static UInt local_sys_write_stderr ( const HChar* buf, Int n )
196 {
197 volatile Long block[2];
198 block[0] = (Long)buf;
199 block[1] = (Long)n;
200 __asm__ volatile (
201 "addi 1,1,-256\n\t"
202 "mr 5,%0\n\t" /* r5 = &block[0] */
203 "std 5,0(1)\n\t" /* stash on stack */
204 "li 0,"VG_STRINGIFY(__NR_write)"\n\t" /* %r0 = __NR_write */
205 "li 3,2\n\t" /* set %r3 = stderr */
206 "ld 4,0(5)\n\t" /* set %r4 = buf */
207 "ld 5,8(5)\n\t" /* set %r5 = n */
208 "sc\n\t" /* write(stderr, buf, n) */
209 "ld 5,0(1)\n\t"
210 "addi 1,1,256\n\t"
211 "std 3,0(5)\n" /* block[0] = result */
212 :
213 : "b" (block)
214 : "cc","memory","cr0","ctr",
215 "r0","r2","r3","r4","r5","r6","r7","r8","r9","r10","r11","r12"
216 );
217 if (block[0] < 0)
218 block[0] = -1;
219 return (UInt)(Int)block[0];
220 }
221
local_sys_getpid(void)222 static UInt local_sys_getpid ( void )
223 {
224 register ULong __res __asm__ ("r3");
225 __asm__ volatile (
226 "li 0, %1\n\t"
227 "sc"
228 : "=&r" (__res)
229 : "i" (__NR_getpid)
230 : "cc","memory","cr0","ctr",
231 "r0","r2","r4","r5","r6","r7","r8","r9","r10","r11","r12"
232 );
233 return (UInt)__res;
234 }
235
236 #elif defined(VGP_arm_linux)
237
local_sys_write_stderr(const HChar * buf,Int n)238 static UInt local_sys_write_stderr ( const HChar* buf, Int n )
239 {
240 volatile Int block[2];
241 block[0] = (Int)buf;
242 block[1] = n;
243 __asm__ volatile (
244 "mov r0, #2\n\t" /* stderr */
245 "ldr r1, [%0]\n\t" /* buf */
246 "ldr r2, [%0, #4]\n\t" /* n */
247 "push {r6,r7}\n\t"
248 "mov r7, #"VG_STRINGIFY(__NR_write)"\n\t"
249 "svc 0x0\n" /* write() */
250 "pop {r6,r7}\n\t"
251 "str r0, [%0]\n\t"
252 :
253 : "r" (block)
254 : "r0","r1","r2"
255 );
256 if (block[0] < 0)
257 block[0] = -1;
258 return (UInt)block[0];
259 }
260
local_sys_getpid(void)261 static UInt local_sys_getpid ( void )
262 {
263 UInt __res;
264 __asm__ volatile (
265 "push {r6,r7}\n\t"
266 "mov r7, #"VG_STRINGIFY(__NR_getpid)"\n\t"
267 "svc 0x0\n\t" /* getpid() */
268 "pop {r6,r7}\n\t"
269 "mov %0, r0\n\t"
270 : "=r" (__res)
271 :
272 : "r0" );
273 return __res;
274 }
275
276 #elif defined(VGP_arm64_linux)
277
local_sys_write_stderr(const HChar * buf,Int n)278 static UInt local_sys_write_stderr ( const HChar* buf, Int n )
279 {
280 volatile ULong block[2];
281 block[0] = (ULong)buf;
282 block[1] = (ULong)n;
283 __asm__ volatile (
284 "mov x0, #2\n\t" /* stderr */
285 "ldr x1, [%0]\n\t" /* buf */
286 "ldr x2, [%0, #8]\n\t" /* n */
287 "mov x8, #"VG_STRINGIFY(__NR_write)"\n\t"
288 "svc 0x0\n" /* write() */
289 "str x0, [%0]\n\t"
290 :
291 : "r" (block)
292 : "x0","x1","x2","x7"
293 );
294 if (block[0] < 0)
295 block[0] = -1;
296 return (UInt)block[0];
297 }
298
local_sys_getpid(void)299 static UInt local_sys_getpid ( void )
300 {
301 UInt __res;
302 __asm__ volatile (
303 "mov x8, #"VG_STRINGIFY(__NR_getpid)"\n"
304 "svc 0x0\n" /* getpid() */
305 "mov %0, x0\n"
306 : "=r" (__res)
307 :
308 : "x0", "x8" );
309 return (UInt)__res;
310 }
311
312 #elif defined(VGP_x86_darwin)
313
314 /* We would use VG_DARWIN_SYSNO_TO_KERNEL instead of VG_DARWIN_SYSNO_INDEX
315 except that the former has a C ternary ?: operator which isn't valid in
316 asm code. Both macros give the same results for Unix-class syscalls (which
317 these all are, as identified by the use of 'int 0x80'). */
318 __attribute__((noinline))
local_sys_write_stderr(const HChar * buf,Int n)319 static UInt local_sys_write_stderr ( const HChar* buf, Int n )
320 {
321 UInt __res;
322 __asm__ volatile (
323 "movl %2, %%eax\n" /* push n */
324 "pushl %%eax\n"
325 "movl %1, %%eax\n" /* push buf */
326 "pushl %%eax\n"
327 "movl $2, %%eax\n" /* push stderr */
328 "pushl %%eax\n"
329 "movl $"VG_STRINGIFY(VG_DARWIN_SYSNO_INDEX(__NR_write_nocancel))
330 ", %%eax\n"
331 "pushl %%eax\n" /* push fake return address */
332 "int $0x80\n" /* write(stderr, buf, n) */
333 "jnc 1f\n" /* jump if no error */
334 "movl $-1, %%eax\n" /* return -1 if error */
335 "1: "
336 "movl %%eax, %0\n" /* __res = eax */
337 "addl $16, %%esp\n" /* pop x4 */
338 : "=mr" (__res)
339 : "g" (buf), "g" (n)
340 : "eax", "edx", "cc"
341 );
342 return __res;
343 }
344
local_sys_getpid(void)345 static UInt local_sys_getpid ( void )
346 {
347 UInt __res;
348 __asm__ volatile (
349 "movl $"VG_STRINGIFY(VG_DARWIN_SYSNO_INDEX(__NR_getpid))", %%eax\n"
350 "int $0x80\n" /* getpid() */
351 "movl %%eax, %0\n" /* set __res = eax */
352 : "=mr" (__res)
353 :
354 : "eax", "cc" );
355 return __res;
356 }
357
358 #elif defined(VGP_amd64_darwin)
359
360 __attribute__((noinline))
local_sys_write_stderr(const HChar * buf,Int n)361 static UInt local_sys_write_stderr ( const HChar* buf, Int n )
362 {
363 UInt __res;
364 __asm__ volatile (
365 "movq $2, %%rdi\n" /* push stderr */
366 "movq %1, %%rsi\n" /* push buf */
367 "movl %2, %%edx\n" /* push n */
368 "movl $"VG_STRINGIFY(VG_DARWIN_SYSNO_FOR_KERNEL(__NR_write_nocancel))
369 ", %%eax\n"
370 "syscall\n" /* write(stderr, buf, n) */
371 "jnc 1f\n" /* jump if no error */
372 "movq $-1, %%rax\n" /* return -1 if error */
373 "1: "
374 "movl %%eax, %0\n" /* __res = eax */
375 : "=mr" (__res)
376 : "g" (buf), "g" (n)
377 : "rdi", "rsi", "rdx", "rcx", "rax", "cc" );
378 return __res;
379 }
380
local_sys_getpid(void)381 static UInt local_sys_getpid ( void )
382 {
383 UInt __res;
384 __asm__ volatile (
385 "movl $"VG_STRINGIFY(VG_DARWIN_SYSNO_FOR_KERNEL(__NR_getpid))", %%eax\n"
386 "syscall\n" /* getpid() */
387 "movl %%eax, %0\n" /* set __res = eax */
388 : "=mr" (__res)
389 :
390 : "rax", "rcx", "cc" );
391 return __res;
392 }
393
394 #elif defined(VGP_s390x_linux)
395
local_sys_write_stderr(const HChar * buf,Int n)396 static UInt local_sys_write_stderr ( const HChar* buf, Int n )
397 {
398 register Int r2 asm("2") = 2; /* file descriptor STDERR */
399 register const HChar* r3 asm("3") = buf;
400 register ULong r4 asm("4") = n;
401 register ULong r2_res asm("2");
402 ULong __res;
403
404 __asm__ __volatile__ (
405 "svc %b1\n"
406 : "=d" (r2_res)
407 : "i" (__NR_write),
408 "0" (r2),
409 "d" (r3),
410 "d" (r4)
411 : "cc", "memory");
412 __res = r2_res;
413
414 if (__res >= (ULong)(-125))
415 __res = -1;
416 return (UInt)(__res);
417 }
418
local_sys_getpid(void)419 static UInt local_sys_getpid ( void )
420 {
421 register ULong r2 asm("2");
422 ULong __res;
423
424 __asm__ __volatile__ (
425 "svc %b1\n"
426 : "=d" (r2)
427 : "i" (__NR_getpid)
428 : "cc", "memory");
429 __res = r2;
430
431 if (__res >= (ULong)(-125))
432 __res = -1;
433 return (UInt)(__res);
434 }
435
436 #elif defined(VGP_mips32_linux)
437
local_sys_write_stderr(const HChar * buf,Int n)438 static UInt local_sys_write_stderr ( const HChar* buf, Int n )
439 {
440 volatile Int block[2];
441 block[0] = (Int)buf;
442 block[1] = n;
443 __asm__ volatile (
444 "li $4, 2\n\t" /* stderr */
445 "lw $5, 0(%0)\n\t" /* buf */
446 "lw $6, 4(%0)\n\t" /* n */
447 "move $7, $0\n\t"
448 "li $2, %1\n\t" /* set v0 = __NR_write */
449 "syscall\n\t" /* write() */
450 "nop\n\t"
451 :
452 : "r" (block), "n" (__NR_write)
453 : "2", "4", "5", "6", "7"
454 );
455 if (block[0] < 0)
456 block[0] = -1;
457 return (UInt)block[0];
458 }
459
local_sys_getpid(void)460 static UInt local_sys_getpid ( void )
461 {
462 UInt __res;
463 __asm__ volatile (
464 "li $2, %1\n\t" /* set v0 = __NR_getpid */
465 "syscall\n\t" /* getpid() */
466 "nop\n\t"
467 "move %0, $2\n"
468 : "=r" (__res)
469 : "n" (__NR_getpid)
470 : "$2" );
471 return __res;
472 }
473
474 #elif defined(VGP_mips64_linux)
475
local_sys_write_stderr(const HChar * buf,Int n)476 static UInt local_sys_write_stderr ( const HChar* buf, Int n )
477 {
478 volatile Long block[2];
479 block[0] = (Long)buf;
480 block[1] = n;
481 __asm__ volatile (
482 "li $4, 2\n\t" /* std output*/
483 "ld $5, 0(%0)\n\t" /*$5 = buf*/
484 "ld $6, 8(%0)\n\t" /*$6 = n */
485 "move $7, $0\n\t"
486 "li $2, %1\n\t" /* set v0 = __NR_write */
487 "\tsyscall\n"
488 "\tnop\n"
489 : /*wr*/
490 : /*rd*/ "r" (block), "n" (__NR_write)
491 : "2", "4", "5", "6", "7"
492 );
493 if (block[0] < 0)
494 block[0] = -1;
495 return (UInt)(Int)block[0];
496 }
497
local_sys_getpid(void)498 static UInt local_sys_getpid ( void )
499 {
500 ULong __res;
501 __asm__ volatile (
502 "li $2, %1\n\t" /* set v0 = __NR_getpid */
503 "syscall\n\t" /* getpid() */
504 "nop\n\t"
505 "move %0, $2\n"
506 : "=r" (__res)
507 : "n" (__NR_getpid)
508 : "$2" );
509 return (UInt)(__res);
510 }
511
512 #elif defined(VGP_tilegx_linux)
513
local_sys_write_stderr(const HChar * buf,Int n)514 static UInt local_sys_write_stderr ( const HChar* buf, Int n )
515 {
516 volatile Long block[2];
517 block[0] = (Long)buf;
518 block[1] = n;
519 Long __res = 0;
520 __asm__ volatile (
521 "movei r0, 2 \n\t" /* stderr */
522 "move r1, %1 \n\t" /* buf */
523 "move r2, %2 \n\t" /* n */
524 "move r3, zero \n\t"
525 "moveli r10, %3 \n\t" /* set r10 = __NR_write */
526 "swint1 \n\t" /* write() */
527 "nop \n\t"
528 "move %0, r0 \n\t" /* save return into block[0] */
529 : "=r"(__res)
530 : "r" (block[0]), "r"(block[1]), "n" (__NR_write)
531 : "r0", "r1", "r2", "r3", "r4", "r5");
532 if (__res < 0)
533 __res = -1;
534 return (UInt)__res;
535 }
536
local_sys_getpid(void)537 static UInt local_sys_getpid ( void )
538 {
539 UInt __res, __err;
540 __res = 0;
541 __err = 0;
542 __asm__ volatile (
543 "moveli r10, %2\n\t" /* set r10 = __NR_getpid */
544 "swint1\n\t" /* getpid() */
545 "nop\n\t"
546 "move %0, r0\n"
547 "move %1, r1\n"
548 : "=r" (__res), "=r"(__err)
549 : "n" (__NR_getpid)
550 : "r0", "r1", "r2", "r3", "r4",
551 "r5", "r6", "r7", "r8", "r9",
552 "r10", "r11", "r12", "r13", "r14",
553 "r15", "r16", "r17", "r18", "r19",
554 "r20", "r21", "r22", "r23", "r24",
555 "r25", "r26", "r27", "r28", "r29");
556 return __res;
557 }
558
559 #else
560 # error Unknown platform
561 #endif
562
563
564 /* ----- generic ----- */
565
566 /* strlen, so we don't need m_libc */
local_strlen(const HChar * str)567 static Int local_strlen ( const HChar* str )
568 {
569 Int i = 0;
570 while (str[i] != 0) i++;
571 return i;
572 }
573
local_toupper(HChar c)574 static HChar local_toupper ( HChar c )
575 {
576 if (c >= 'a' && c <= 'z')
577 return c + ('A' - 'a');
578 else
579 return c;
580 }
581
582 /* Emit buf[0 .. n-1] to stderr. Unfortunately platform-specific.
583 */
emit(const HChar * buf,Int n)584 static void emit ( const HChar* buf, Int n )
585 {
586 if (n >= 1)
587 (void)local_sys_write_stderr(buf, n);
588 }
589
590
591 /*------------------------------------------------------------*/
592 /*--- A simple, generic, vprintf implementation. ---*/
593 /*------------------------------------------------------------*/
594
595 /* -----------------------------------------------
596 Distantly derived from:
597
598 vprintf replacement for Checker.
599 Copyright 1993, 1994, 1995 Tristan Gingold
600 Written September 1993 Tristan Gingold
601 Tristan Gingold, 8 rue Parmentier, F-91120 PALAISEAU, FRANCE
602
603 (Checker itself was GPL'd.)
604 ----------------------------------------------- */
605
606 /* Some flags. */
607 #define VG_MSG_SIGNED 1 /* The value is signed. */
608 #define VG_MSG_ZJUSTIFY 2 /* Must justify with '0'. */
609 #define VG_MSG_LJUSTIFY 4 /* Must justify on the left. */
610 #define VG_MSG_PAREN 8 /* Parenthesize if present (for %y) */
611 #define VG_MSG_COMMA 16 /* Add commas to numbers (for %d, %u) */
612 #define VG_MSG_ALTFORMAT 32 /* Convert the value to alternate format */
613
614 /* Copy a string into the buffer. */
615 static
myvprintf_str(void (* send)(HChar,void *),void * send_arg2,Int flags,Int width,const HChar * str,Bool capitalise)616 UInt myvprintf_str ( void(*send)(HChar,void*),
617 void* send_arg2,
618 Int flags,
619 Int width,
620 const HChar* str,
621 Bool capitalise )
622 {
623 # define MAYBE_TOUPPER(ch) (capitalise ? local_toupper(ch) : (ch))
624 UInt ret = 0;
625 Int i, extra;
626 Int len = local_strlen(str);
627
628 if (width == 0) {
629 ret += len;
630 for (i = 0; i < len; i++)
631 send(MAYBE_TOUPPER(str[i]), send_arg2);
632 return ret;
633 }
634
635 if (len > width) {
636 ret += width;
637 for (i = 0; i < width; i++)
638 send(MAYBE_TOUPPER(str[i]), send_arg2);
639 return ret;
640 }
641
642 extra = width - len;
643 if (! (flags & VG_MSG_LJUSTIFY)) {
644 ret += extra;
645 for (i = 0; i < extra; i++)
646 send(' ', send_arg2);
647 }
648 ret += len;
649 for (i = 0; i < len; i++)
650 send(MAYBE_TOUPPER(str[i]), send_arg2);
651 if (flags & VG_MSG_LJUSTIFY) {
652 ret += extra;
653 for (i = 0; i < extra; i++)
654 send(' ', send_arg2);
655 }
656
657 # undef MAYBE_TOUPPER
658 return ret;
659 }
660
661
662 /* Copy a string into the buffer, escaping bad XML chars. */
663 static
myvprintf_str_XML_simplistic(void (* send)(HChar,void *),void * send_arg2,const HChar * str)664 UInt myvprintf_str_XML_simplistic ( void(*send)(HChar,void*),
665 void* send_arg2,
666 const HChar* str )
667 {
668 UInt ret = 0;
669 Int i;
670 Int len = local_strlen(str);
671 const HChar* alt;
672
673 for (i = 0; i < len; i++) {
674 switch (str[i]) {
675 case '&': alt = "&"; break;
676 case '<': alt = "<"; break;
677 case '>': alt = ">"; break;
678 default: alt = NULL;
679 }
680
681 if (alt) {
682 while (*alt) {
683 send(*alt, send_arg2);
684 ret++;
685 alt++;
686 }
687 } else {
688 send(str[i], send_arg2);
689 ret++;
690 }
691 }
692
693 return ret;
694 }
695
696
697 /* Write P into the buffer according to these args:
698 * If SIGN is true, p is a signed.
699 * BASE is the base.
700 * If WITH_ZERO is true, '0' must be added.
701 * WIDTH is the width of the field.
702 */
703 static
myvprintf_int64(void (* send)(HChar,void *),void * send_arg2,Int flags,Int base,Int width,Bool capitalised,ULong p)704 UInt myvprintf_int64 ( void(*send)(HChar,void*),
705 void* send_arg2,
706 Int flags,
707 Int base,
708 Int width,
709 Bool capitalised,
710 ULong p )
711 {
712 /* To print an ULong base 2 needs 64 characters. If commas are requested,
713 add 21. Plus 1 for a possible sign plus 1 for \0. Makes 87 -- so let's
714 say 90. The size of BUF needs to be max(90, WIDTH + 1) */
715 HChar buf[width + 1 > 90 ? width + 1 : 90];
716 Int ind = 0;
717 Int i, nc = 0;
718 Bool neg = False;
719 const HChar* digits = capitalised ? "0123456789ABCDEF" : "0123456789abcdef";
720 UInt ret = 0;
721
722 if (base < 2 || base > 16)
723 return ret;
724
725 if ((flags & VG_MSG_SIGNED) && (Long)p < 0) {
726 p = - (Long)p;
727 neg = True;
728 }
729
730 if (p == 0)
731 buf[ind++] = '0';
732 else {
733 while (p > 0) {
734 if (flags & VG_MSG_COMMA && 10 == base &&
735 0 == (ind-nc) % 3 && 0 != ind)
736 {
737 buf[ind++] = ',';
738 nc++;
739 }
740 buf[ind++] = digits[p % base];
741 p /= base;
742 }
743 }
744
745 if (neg)
746 buf[ind++] = '-';
747
748 if (width > 0 && !(flags & VG_MSG_LJUSTIFY)) {
749 for(; ind < width; ind++) {
750 buf[ind] = (flags & VG_MSG_ZJUSTIFY) ? '0': ' ';
751 }
752 }
753
754 /* Reverse copy to buffer. */
755 ret += ind;
756 for (i = ind -1; i >= 0; i--) {
757 send(buf[i], send_arg2);
758 }
759 if (width > 0 && (flags & VG_MSG_LJUSTIFY)) {
760 for(; ind < width; ind++) {
761 ret++;
762 /* Never pad with zeroes on RHS -- changes the value! */
763 send(' ', send_arg2);
764 }
765 }
766 return ret;
767 }
768
769
770 /* A simple vprintf(). */
771 /* EXPORTED */
772 UInt
VG_(debugLog_vprintf)773 VG_(debugLog_vprintf) (
774 void(*send)(HChar,void*),
775 void* send_arg2,
776 const HChar* format,
777 va_list vargs
778 )
779 {
780 UInt ret = 0;
781 Int i;
782 Int flags;
783 Int width, precision;
784 Int n_ls = 0;
785 Bool is_long, is_sizet, caps;
786
787 /* We assume that vargs has already been initialised by the
788 caller, using va_start, and that the caller will similarly
789 clean up with va_end.
790 */
791
792 for (i = 0; format[i] != 0; i++) {
793 if (format[i] != '%') {
794 send(format[i], send_arg2);
795 ret++;
796 continue;
797 }
798 i++;
799 /* A '%' has been found. Ignore a trailing %. */
800 if (format[i] == 0)
801 break;
802 if (format[i] == '%') {
803 /* '%%' is replaced by '%'. */
804 send('%', send_arg2);
805 ret++;
806 continue;
807 }
808 flags = 0;
809 n_ls = 0;
810 width = 0; /* length of the field. */
811 precision = -1; /* unspecified precision */
812 while (1) {
813 switch (format[i]) {
814 case '(':
815 flags |= VG_MSG_PAREN;
816 break;
817 case ',':
818 case '\'':
819 /* If ',' or '\'' follows '%', commas will be inserted. */
820 flags |= VG_MSG_COMMA;
821 break;
822 case '-':
823 /* If '-' follows '%', justify on the left. */
824 flags |= VG_MSG_LJUSTIFY;
825 break;
826 case '0':
827 /* If '0' follows '%', pads will be inserted. */
828 flags |= VG_MSG_ZJUSTIFY;
829 break;
830 case '#':
831 /* If '#' follows '%', alternative format will be used. */
832 flags |= VG_MSG_ALTFORMAT;
833 break;
834 default:
835 goto parse_fieldwidth;
836 }
837 i++;
838 }
839 parse_fieldwidth:
840 /* Compute the field length. */
841 if (format[i] == '*') {
842 width = va_arg(vargs, Int);
843 ++i;
844 } else {
845 while (format[i] >= '0' && format[i] <= '9') {
846 width *= 10;
847 width += format[i++] - '0';
848 }
849 }
850 /* Parse precision, if any. Only meaningful for %f. For all other
851 format specifiers the precision will be silently ignored. */
852 if (format[i] == '.') {
853 ++i;
854 if (format[i] == '*') {
855 precision = va_arg(vargs, Int);
856 ++i;
857 } else {
858 precision = 0;
859 while (format[i] >= '0' && format[i] <= '9') {
860 precision *= 10;
861 precision += format[i++] - '0';
862 }
863 }
864 }
865
866 is_sizet = False;
867 if (format[i] == 'z') {
868 is_sizet = True;
869 ++i;
870 } else {
871 while (format[i] == 'l') {
872 i++;
873 n_ls++;
874 }
875 }
876
877 // %d means print a 32-bit integer.
878 // %ld means print a word-size integer.
879 // %lld means print a 64-bit integer.
880 if (0 == n_ls) { is_long = False; }
881 else if (1 == n_ls) { is_long = ( sizeof(void*) == sizeof(Long) ); }
882 else { is_long = True; }
883
884 switch (format[i]) {
885 case 'o': /* %o */
886 if (flags & VG_MSG_ALTFORMAT) {
887 ret += 2;
888 send('0',send_arg2);
889 }
890 if (is_sizet)
891 ret += myvprintf_int64(send, send_arg2, flags, 8, width, False,
892 (ULong)(va_arg (vargs, SizeT)));
893 else if (is_long)
894 ret += myvprintf_int64(send, send_arg2, flags, 8, width, False,
895 (ULong)(va_arg (vargs, ULong)));
896 else
897 ret += myvprintf_int64(send, send_arg2, flags, 8, width, False,
898 (ULong)(va_arg (vargs, UInt)));
899 break;
900 case 'd': /* %d */
901 flags |= VG_MSG_SIGNED;
902 if (is_long)
903 ret += myvprintf_int64(send, send_arg2, flags, 10, width, False,
904 (ULong)(va_arg (vargs, Long)));
905 else
906 ret += myvprintf_int64(send, send_arg2, flags, 10, width, False,
907 (ULong)(va_arg (vargs, Int)));
908 break;
909 case 'u': /* %u */
910 if (is_sizet)
911 ret += myvprintf_int64(send, send_arg2, flags, 10, width, False,
912 (ULong)(va_arg (vargs, SizeT)));
913 else if (is_long)
914 ret += myvprintf_int64(send, send_arg2, flags, 10, width, False,
915 (ULong)(va_arg (vargs, ULong)));
916 else
917 ret += myvprintf_int64(send, send_arg2, flags, 10, width, False,
918 (ULong)(va_arg (vargs, UInt)));
919 break;
920 case 'p':
921 if (format[i+1] == 'S') {
922 i++;
923 /* %pS, like %s but escaping chars for XML safety */
924 /* Note: simplistic; ignores field width and flags */
925 const HChar *str = va_arg (vargs, HChar *);
926 if (str == NULL)
927 str = "(null)";
928 ret += myvprintf_str_XML_simplistic(send, send_arg2, str);
929 } else if (format[i+1] == 's') {
930 i++;
931 /* %ps, synonym for %s with --xml=no / %pS with --xml=yes */
932 const HChar *str = va_arg (vargs, HChar *);
933 if (str == NULL)
934 str = "(null)";
935 if (clo_xml)
936 ret += myvprintf_str_XML_simplistic(send, send_arg2, str);
937 else
938 ret += myvprintf_str(send, send_arg2, flags, width, str,
939 False);
940 } else {
941 /* %p */
942 ret += 2;
943 send('0',send_arg2);
944 send('x',send_arg2);
945 ret += myvprintf_int64(send, send_arg2, flags, 16, width, True,
946 (ULong)((UWord)va_arg (vargs, void *)));
947 }
948 break;
949 case 'x': /* %x */
950 case 'X': /* %X */
951 caps = toBool(format[i] == 'X');
952 if (flags & VG_MSG_ALTFORMAT) {
953 ret += 2;
954 send('0',send_arg2);
955 send('x',send_arg2);
956 }
957 if (is_sizet)
958 ret += myvprintf_int64(send, send_arg2, flags, 16, width, False,
959 (ULong)(va_arg (vargs, SizeT)));
960 else if (is_long)
961 ret += myvprintf_int64(send, send_arg2, flags, 16, width, caps,
962 (ULong)(va_arg (vargs, ULong)));
963 else
964 ret += myvprintf_int64(send, send_arg2, flags, 16, width, caps,
965 (ULong)(va_arg (vargs, UInt)));
966 break;
967 case 'c': /* %c */
968 ret++;
969 send(va_arg (vargs, int), send_arg2);
970 break;
971 case 's': case 'S': { /* %s */
972 const HChar *str = va_arg (vargs, HChar *);
973 if (str == NULL) str = "(null)";
974 ret += myvprintf_str(send, send_arg2,
975 flags, width, str, format[i]=='S');
976 break;
977 }
978 case 'f': {
979 /* Print a floating point number in the format x.y without
980 any exponent. Capabilities are extremely limited, basically
981 a joke, but good enough for our needs. */
982 Double val = va_arg (vargs, Double);
983 Bool is_negative = False;
984 Int cnt;
985
986 if (val < 0.0) {
987 is_negative = True;
988 val = - val;
989 }
990 /* If the integral part of the floating point number cannot be
991 represented by an ULONG_MAX, print '*' characters */
992 if (val > (Double)(~0ULL)) {
993 if (width == 0) width = 6; // say
994 for (cnt = 0; cnt < width; ++cnt)
995 send('*', send_arg2);
996 ret += width;
997 break;
998 }
999 /* The integral part of the floating point number is representable
1000 by an ULong. */
1001 ULong ipval = val;
1002 Double frac = val - ipval;
1003
1004 if (precision == -1) precision = 6; // say
1005
1006 /* Silently limit the precision to 10 digits. */
1007 if (precision > 10) precision = 10;
1008
1009 /* Determine fractional part, possibly round up */
1010 ULong factor = 1;
1011 for (cnt = 0; cnt < precision; ++cnt)
1012 factor *= 10;
1013 ULong frval = frac * factor;
1014 if ((frac * factor - frval) > 0.5) // round up
1015 frval += 1;
1016 /* Check rounding. */
1017 if (frval == factor)
1018 ipval += 1;
1019 frval %= factor;
1020
1021 /* Find out how many characters are needed to print the number */
1022
1023 /* The integral part... */
1024 UInt ipwidth, num_digit = 1; // at least one digit
1025 ULong x, old_x = 0;
1026 for (x = 10; ; old_x = x, x *= 10, ++num_digit) {
1027 if (x <= old_x) break; // overflow occurred
1028 if (ipval < x) break;
1029 }
1030 ipwidth = num_digit; // width of integral part.
1031 if (is_negative) ++num_digit;
1032 if (precision != 0)
1033 num_digit += 1 + precision;
1034
1035 // Print the number
1036
1037 // Fill in blanks on the left
1038 if (num_digit < width && (flags & VG_MSG_LJUSTIFY) == 0) {
1039 for (cnt = 0; cnt < width - num_digit; ++cnt)
1040 send(' ', send_arg2);
1041 ret += width - num_digit;
1042 }
1043 // Sign, maybe
1044 if (is_negative) {
1045 send('-', send_arg2);
1046 ret += 1;
1047 }
1048 // Integral part
1049 ret += myvprintf_int64(send, send_arg2, 0, 10, ipwidth, False,
1050 ipval);
1051 // Decimal point and fractional part
1052 if (precision != 0) {
1053 send('.', send_arg2);
1054 ret += 1;
1055
1056 ret += myvprintf_int64(send, send_arg2, VG_MSG_ZJUSTIFY, 10,
1057 precision, False, frval);
1058 }
1059 // Fill in blanks on the right
1060 if (num_digit < width && (flags & VG_MSG_LJUSTIFY) != 0) {
1061 for (cnt = 0; cnt < width - num_digit; ++cnt)
1062 send(' ', send_arg2);
1063 ret += width - num_digit;
1064 }
1065 break;
1066 }
1067
1068 // case 'y': { /* %y - print symbol */
1069 // Addr a = va_arg(vargs, Addr);
1070 //
1071 // HChar *name;
1072 // if (VG_(get_fnname_w_offset)(a, &name)) {
1073 // HChar buf[1 + VG_strlen(name) + 1 + 1];
1074 // if (flags & VG_MSG_PAREN) {
1075 // VG_(sprintf)(str, "(%s)", name):
1076 // } else {
1077 // VG_(sprintf)(str, "%s", name):
1078 // }
1079 // ret += myvprintf_str(send, flags, width, buf, 0);
1080 // }
1081 // break;
1082 // }
1083 default:
1084 break;
1085 }
1086 }
1087 return ret;
1088 }
1089
1090
1091 /*------------------------------------------------------------*/
1092 /*--- Debuglog stuff. ---*/
1093 /*------------------------------------------------------------*/
1094
1095 /* Only print messages whose stated level is less than or equal to
1096 this. By default, it makes this entire subsystem silent. */
1097
1098 static Int loglevel = 0;
1099
1100 /* Module startup. */
1101 /* EXPORTED */
VG_(debugLog_startup)1102 void VG_(debugLog_startup) ( Int level, const HChar* who )
1103 {
1104 if (level < 0) level = 0;
1105 if (level > 10) level = 10;
1106 loglevel = level;
1107 VG_(debugLog)(1, "debuglog",
1108 "DebugLog system started by %s, "
1109 "level %d logging requested\n",
1110 who, loglevel);
1111 }
1112
1113 /* Get the logging threshold level, as set by the most recent call to
1114 VG_(debugLog_startup), or zero if there have been no such calls so
1115 far. */
1116 /* EXPORTED */
VG_(debugLog_getLevel)1117 Int VG_(debugLog_getLevel) ( void )
1118 {
1119 return loglevel;
1120 }
1121
1122
1123 /* ------------ */
1124
1125 typedef
1126 struct {
1127 HChar buf[100];
1128 Int n;
1129 }
1130 printf_buf;
1131
add_to_buf(HChar c,void * p)1132 static void add_to_buf ( HChar c, void* p )
1133 {
1134 printf_buf* buf = (printf_buf*)p;
1135
1136 if (buf->n >= 100-10 /*paranoia*/ ) {
1137 emit( buf->buf, local_strlen(buf->buf) );
1138 buf->n = 0;
1139 buf->buf[buf->n] = 0;
1140 }
1141 buf->buf[buf->n++] = c;
1142 buf->buf[buf->n] = 0;
1143 }
1144
1145 /* Send a logging message. Nothing is output unless 'level'
1146 is <= the current loglevel. */
1147 /* EXPORTED */
VG_(debugLog)1148 void VG_(debugLog) ( Int level, const HChar* modulename,
1149 const HChar* format, ... )
1150 {
1151 UInt pid;
1152 Int indent, depth, i;
1153 va_list vargs;
1154 printf_buf buf;
1155
1156 if (level > loglevel)
1157 return;
1158
1159 indent = 2*level - 1;
1160 if (indent < 1) indent = 1;
1161
1162 buf.n = 0;
1163 buf.buf[0] = 0;
1164 pid = local_sys_getpid();
1165
1166 // Print one '>' in front of the messages for each level of self-hosting
1167 // being performed.
1168 depth = RUNNING_ON_VALGRIND;
1169 for (i = 0; i < depth; i++) {
1170 (void)myvprintf_str ( add_to_buf, &buf, 0, 1, ">", False );
1171 }
1172
1173 (void)myvprintf_str ( add_to_buf, &buf, 0, 2, "--", False );
1174 (void)myvprintf_int64 ( add_to_buf, &buf, 0, 10, 1, False, (ULong)pid );
1175 (void)myvprintf_str ( add_to_buf, &buf, 0, 1, ":", False );
1176 (void)myvprintf_int64 ( add_to_buf, &buf, 0, 10, 1, False, (ULong)level );
1177 (void)myvprintf_str ( add_to_buf, &buf, 0, 1, ":", False );
1178 (void)myvprintf_str ( add_to_buf, &buf, 0, 8, modulename, False );
1179 (void)myvprintf_str ( add_to_buf, &buf, 0, indent, "", False );
1180
1181 va_start(vargs,format);
1182
1183 (void) VG_(debugLog_vprintf) ( add_to_buf, &buf, format, vargs );
1184
1185 if (buf.n > 0) {
1186 emit( buf.buf, local_strlen(buf.buf) );
1187 }
1188
1189 va_end(vargs);
1190 }
1191
1192
1193
1194 /*--------------------------------------------------------------------*/
1195 /*--- end m_debuglog.c ---*/
1196 /*--------------------------------------------------------------------*/
1197