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-2017 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","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","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_x86_solaris)
local_sys_write_stderr(const HChar * buf,Int n)516 static UInt local_sys_write_stderr ( const HChar* buf, Int n )
517 {
518 UInt res, err;
519 Bool restart;
520
521 do {
522 /* The Solaris kernel does not restart syscalls automatically so it is
523 done here. */
524 __asm__ __volatile__ (
525 "movl %[n], %%eax\n" /* push n */
526 "pushl %%eax\n"
527 "movl %[buf], %%eax\n" /* push buf */
528 "pushl %%eax\n"
529 "movl $2, %%eax\n" /* push stderr */
530 "pushl %%eax\n"
531 "movl $"VG_STRINGIFY(__NR_write)", %%eax\n"
532 "pushl %%eax\n" /* push fake return address */
533 "int $0x91\n" /* write(stderr, buf, n) */
534 "movl $0, %%edx\n" /* assume no error */
535 "jnc 1f\n" /* jump if no error */
536 "movl $1, %%edx\n" /* set error flag */
537 "1: "
538 "addl $16, %%esp\n" /* pop x4 */
539 : "=&a" (res), "=d" (err)
540 : [buf] "g" (buf), [n] "g" (n)
541 : "cc");
542 restart = err && (res == VKI_EINTR || res == VKI_ERESTART);
543 } while (restart);
544
545 return res;
546 }
547
local_sys_getpid(void)548 static UInt local_sys_getpid ( void )
549 {
550 UInt res;
551
552 /* The getpid() syscall never returns EINTR or ERESTART so there is no need
553 for restarting it. */
554 __asm__ __volatile__ (
555 "movl $"VG_STRINGIFY(__NR_getpid)", %%eax\n"
556 "int $0x91\n" /* getpid() */
557 : "=a" (res)
558 :
559 : "edx", "cc");
560
561 return res;
562 }
563
564 #elif defined(VGP_amd64_solaris)
local_sys_write_stderr(const HChar * buf,Int n)565 static UInt local_sys_write_stderr ( const HChar* buf, Int n )
566 {
567 ULong res, err;
568 Bool restart;
569
570 do {
571 /* The Solaris kernel does not restart syscalls automatically so it is
572 done here. */
573 __asm__ __volatile__ (
574 "movq $2, %%rdi\n" /* push stderr */
575 "movq $"VG_STRINGIFY(__NR_write)", %%rax\n"
576 "syscall\n" /* write(stderr, buf, n) */
577 "movq $0, %%rdx\n" /* assume no error */
578 "jnc 1f\n" /* jump if no error */
579 "movq $1, %%rdx\n" /* set error flag */
580 "1: "
581 : "=a" (res), "=d" (err)
582 : "S" (buf), "d" (n)
583 : "cc");
584 restart = err && (res == VKI_EINTR || res == VKI_ERESTART);
585 } while (restart);
586
587 return res;
588 }
589
local_sys_getpid(void)590 static UInt local_sys_getpid ( void )
591 {
592 UInt res;
593
594 /* The getpid() syscall never returns EINTR or ERESTART so there is no need
595 for restarting it. */
596 __asm__ __volatile__ (
597 "movq $"VG_STRINGIFY(__NR_getpid)", %%rax\n"
598 "syscall\n" /* getpid() */
599 : "=a" (res)
600 :
601 : "edx", "cc");
602
603 return res;
604 }
605
606 #else
607 # error Unknown platform
608 #endif
609
610
611 /* ----- generic ----- */
612
613 /* strlen, so we don't need m_libc */
local_strlen(const HChar * str)614 static Int local_strlen ( const HChar* str )
615 {
616 Int i = 0;
617 while (str[i] != 0) i++;
618 return i;
619 }
620
local_toupper(HChar c)621 static HChar local_toupper ( HChar c )
622 {
623 if (c >= 'a' && c <= 'z')
624 return c + ('A' - 'a');
625 else
626 return c;
627 }
628
629 /* Emit buf[0 .. n-1] to stderr. Unfortunately platform-specific.
630 */
emit(const HChar * buf,Int n)631 static void emit ( const HChar* buf, Int n )
632 {
633 if (n >= 1)
634 (void)local_sys_write_stderr(buf, n);
635 }
636
637
638 /*------------------------------------------------------------*/
639 /*--- A simple, generic, vprintf implementation. ---*/
640 /*------------------------------------------------------------*/
641
642 /* -----------------------------------------------
643 Distantly derived from:
644
645 vprintf replacement for Checker.
646 Copyright 1993, 1994, 1995 Tristan Gingold
647 Written September 1993 Tristan Gingold
648 Tristan Gingold, 8 rue Parmentier, F-91120 PALAISEAU, FRANCE
649
650 (Checker itself was GPL'd.)
651 ----------------------------------------------- */
652
653 /* Some flags. */
654 #define VG_MSG_SIGNED 1 /* The value is signed. */
655 #define VG_MSG_ZJUSTIFY 2 /* Must justify with '0'. */
656 #define VG_MSG_LJUSTIFY 4 /* Must justify on the left. */
657 #define VG_MSG_PAREN 8 /* Parenthesize if present (for %y) */
658 #define VG_MSG_COMMA 16 /* Add commas to numbers (for %d, %u) */
659 #define VG_MSG_ALTFORMAT 32 /* Convert the value to alternate format */
660
661 /* Copy a string into the buffer. */
662 static
myvprintf_str(void (* send)(HChar,void *),void * send_arg2,Int flags,Int width,const HChar * str,Bool capitalise)663 UInt myvprintf_str ( void(*send)(HChar,void*),
664 void* send_arg2,
665 Int flags,
666 Int width,
667 const HChar* str,
668 Bool capitalise )
669 {
670 # define MAYBE_TOUPPER(ch) (capitalise ? local_toupper(ch) : (ch))
671 UInt ret = 0;
672 Int i, extra;
673 Int len = local_strlen(str);
674
675 if (width == 0) {
676 ret += len;
677 for (i = 0; i < len; i++)
678 send(MAYBE_TOUPPER(str[i]), send_arg2);
679 return ret;
680 }
681
682 if (len > width) {
683 ret += width;
684 for (i = 0; i < width; i++)
685 send(MAYBE_TOUPPER(str[i]), send_arg2);
686 return ret;
687 }
688
689 extra = width - len;
690 if (! (flags & VG_MSG_LJUSTIFY)) {
691 ret += extra;
692 for (i = 0; i < extra; i++)
693 send(' ', send_arg2);
694 }
695 ret += len;
696 for (i = 0; i < len; i++)
697 send(MAYBE_TOUPPER(str[i]), send_arg2);
698 if (flags & VG_MSG_LJUSTIFY) {
699 ret += extra;
700 for (i = 0; i < extra; i++)
701 send(' ', send_arg2);
702 }
703
704 # undef MAYBE_TOUPPER
705 return ret;
706 }
707
708
709 /* Copy a string into the buffer, escaping bad XML chars. */
710 static
myvprintf_str_XML_simplistic(void (* send)(HChar,void *),void * send_arg2,const HChar * str)711 UInt myvprintf_str_XML_simplistic ( void(*send)(HChar,void*),
712 void* send_arg2,
713 const HChar* str )
714 {
715 UInt ret = 0;
716 Int i;
717 Int len = local_strlen(str);
718 const HChar* alt;
719
720 for (i = 0; i < len; i++) {
721 switch (str[i]) {
722 case '&': alt = "&"; break;
723 case '<': alt = "<"; break;
724 case '>': alt = ">"; break;
725 default: alt = NULL;
726 }
727
728 if (alt) {
729 while (*alt) {
730 send(*alt, send_arg2);
731 ret++;
732 alt++;
733 }
734 } else {
735 send(str[i], send_arg2);
736 ret++;
737 }
738 }
739
740 return ret;
741 }
742
743
744 /* Write P into the buffer according to these args:
745 * If SIGN is true, p is a signed.
746 * BASE is the base.
747 * If WITH_ZERO is true, '0' must be added.
748 * WIDTH is the width of the field.
749 */
750 static
myvprintf_int64(void (* send)(HChar,void *),void * send_arg2,Int flags,Int base,Int width,Bool capitalised,ULong p)751 UInt myvprintf_int64 ( void(*send)(HChar,void*),
752 void* send_arg2,
753 Int flags,
754 Int base,
755 Int width,
756 Bool capitalised,
757 ULong p )
758 {
759 /* To print an ULong base 2 needs 64 characters. If commas are requested,
760 add 21. Plus 1 for a possible sign plus 1 for \0. Makes 87 -- so let's
761 say 90. The size of BUF needs to be max(90, WIDTH + 1) */
762 HChar buf[width + 1 > 90 ? width + 1 : 90];
763 Int ind = 0;
764 Int i, nc = 0;
765 Bool neg = False;
766 const HChar* digits = capitalised ? "0123456789ABCDEF" : "0123456789abcdef";
767 UInt ret = 0;
768
769 if (base < 2 || base > 16)
770 return ret;
771
772 if ((flags & VG_MSG_SIGNED) && (Long)p < 0) {
773 p = - (Long)p;
774 neg = True;
775 }
776
777 if (p == 0)
778 buf[ind++] = '0';
779 else {
780 while (p > 0) {
781 if (flags & VG_MSG_COMMA && 10 == base &&
782 0 == (ind-nc) % 3 && 0 != ind)
783 {
784 buf[ind++] = ',';
785 nc++;
786 }
787 buf[ind++] = digits[p % base];
788 p /= base;
789 }
790 }
791
792 if (neg)
793 buf[ind++] = '-';
794
795 if (width > 0 && !(flags & VG_MSG_LJUSTIFY)) {
796 for(; ind < width; ind++) {
797 buf[ind] = (flags & VG_MSG_ZJUSTIFY) ? '0': ' ';
798 }
799 }
800
801 /* Reverse copy to buffer. */
802 ret += ind;
803 for (i = ind -1; i >= 0; i--) {
804 send(buf[i], send_arg2);
805 }
806 if (width > 0 && (flags & VG_MSG_LJUSTIFY)) {
807 for(; ind < width; ind++) {
808 ret++;
809 /* Never pad with zeroes on RHS -- changes the value! */
810 send(' ', send_arg2);
811 }
812 }
813 return ret;
814 }
815
816
817 /* A simple vprintf(). */
818 /* EXPORTED */
819 UInt
VG_(debugLog_vprintf)820 VG_(debugLog_vprintf) (
821 void(*send)(HChar,void*),
822 void* send_arg2,
823 const HChar* format,
824 va_list vargs
825 )
826 {
827 UInt ret = 0;
828 Int i;
829 Int flags;
830 Int width, precision;
831 Int n_ls = 0;
832 Bool is_long, is_sizet, caps;
833
834 /* We assume that vargs has already been initialised by the
835 caller, using va_start, and that the caller will similarly
836 clean up with va_end.
837 */
838
839 for (i = 0; format[i] != 0; i++) {
840 if (format[i] != '%') {
841 send(format[i], send_arg2);
842 ret++;
843 continue;
844 }
845 i++;
846 /* A '%' has been found. Ignore a trailing %. */
847 if (format[i] == 0)
848 break;
849 if (format[i] == '%') {
850 /* '%%' is replaced by '%'. */
851 send('%', send_arg2);
852 ret++;
853 continue;
854 }
855 flags = 0;
856 n_ls = 0;
857 width = 0; /* length of the field. */
858 precision = -1; /* unspecified precision */
859 while (1) {
860 switch (format[i]) {
861 case '(':
862 flags |= VG_MSG_PAREN;
863 break;
864 case ',':
865 case '\'':
866 /* If ',' or '\'' follows '%', commas will be inserted. */
867 flags |= VG_MSG_COMMA;
868 break;
869 case '-':
870 /* If '-' follows '%', justify on the left. */
871 flags |= VG_MSG_LJUSTIFY;
872 break;
873 case '0':
874 /* If '0' follows '%', pads will be inserted. */
875 flags |= VG_MSG_ZJUSTIFY;
876 break;
877 case '#':
878 /* If '#' follows '%', alternative format will be used. */
879 flags |= VG_MSG_ALTFORMAT;
880 break;
881 default:
882 goto parse_fieldwidth;
883 }
884 i++;
885 }
886 parse_fieldwidth:
887 /* Compute the field length. */
888 if (format[i] == '*') {
889 width = va_arg(vargs, Int);
890 ++i;
891 } else {
892 while (format[i] >= '0' && format[i] <= '9') {
893 width *= 10;
894 width += format[i++] - '0';
895 }
896 }
897 /* Parse precision, if any. Only meaningful for %f. For all other
898 format specifiers the precision will be silently ignored. */
899 if (format[i] == '.') {
900 ++i;
901 if (format[i] == '*') {
902 precision = va_arg(vargs, Int);
903 ++i;
904 } else {
905 precision = 0;
906 while (format[i] >= '0' && format[i] <= '9') {
907 precision *= 10;
908 precision += format[i++] - '0';
909 }
910 }
911 }
912
913 is_sizet = False;
914 if (format[i] == 'z') {
915 is_sizet = True;
916 ++i;
917 } else {
918 while (format[i] == 'l') {
919 i++;
920 n_ls++;
921 }
922 }
923
924 // %d means print a 32-bit integer.
925 // %ld means print a word-size integer.
926 // %lld means print a 64-bit integer.
927 if (0 == n_ls) { is_long = False; }
928 else if (1 == n_ls) { is_long = ( sizeof(void*) == sizeof(Long) ); }
929 else { is_long = True; }
930
931 switch (format[i]) {
932 case 'o': /* %o */
933 if (flags & VG_MSG_ALTFORMAT) {
934 ret += 2;
935 send('0',send_arg2);
936 }
937 if (is_sizet)
938 ret += myvprintf_int64(send, send_arg2, flags, 8, width, False,
939 (ULong)(va_arg (vargs, SizeT)));
940 else if (is_long)
941 ret += myvprintf_int64(send, send_arg2, flags, 8, width, False,
942 (ULong)(va_arg (vargs, ULong)));
943 else
944 ret += myvprintf_int64(send, send_arg2, flags, 8, width, False,
945 (ULong)(va_arg (vargs, UInt)));
946 break;
947 case 'd': /* %d */
948 flags |= VG_MSG_SIGNED;
949 if (is_long)
950 ret += myvprintf_int64(send, send_arg2, flags, 10, width, False,
951 (ULong)(va_arg (vargs, Long)));
952 else
953 ret += myvprintf_int64(send, send_arg2, flags, 10, width, False,
954 (ULong)(va_arg (vargs, Int)));
955 break;
956 case 'u': /* %u */
957 if (is_sizet)
958 ret += myvprintf_int64(send, send_arg2, flags, 10, width, False,
959 (ULong)(va_arg (vargs, SizeT)));
960 else if (is_long)
961 ret += myvprintf_int64(send, send_arg2, flags, 10, width, False,
962 (ULong)(va_arg (vargs, ULong)));
963 else
964 ret += myvprintf_int64(send, send_arg2, flags, 10, width, False,
965 (ULong)(va_arg (vargs, UInt)));
966 break;
967 case 'p':
968 if (format[i+1] == 'S') {
969 i++;
970 /* %pS, like %s but escaping chars for XML safety */
971 /* Note: simplistic; ignores field width and flags */
972 const HChar *str = va_arg (vargs, HChar *);
973 if (str == NULL)
974 str = "(null)";
975 ret += myvprintf_str_XML_simplistic(send, send_arg2, str);
976 } else if (format[i+1] == 's') {
977 i++;
978 /* %ps, synonym for %s with --xml=no / %pS with --xml=yes */
979 const HChar *str = va_arg (vargs, HChar *);
980 if (str == NULL)
981 str = "(null)";
982 if (clo_xml)
983 ret += myvprintf_str_XML_simplistic(send, send_arg2, str);
984 else
985 ret += myvprintf_str(send, send_arg2, flags, width, str,
986 False);
987 } else {
988 /* %p */
989 ret += 2;
990 send('0',send_arg2);
991 send('x',send_arg2);
992 ret += myvprintf_int64(send, send_arg2, flags, 16, width, True,
993 (ULong)((UWord)va_arg (vargs, void *)));
994 }
995 break;
996 case 'x': /* %x */
997 case 'X': /* %X */
998 caps = toBool(format[i] == 'X');
999 if (flags & VG_MSG_ALTFORMAT) {
1000 ret += 2;
1001 send('0',send_arg2);
1002 send('x',send_arg2);
1003 }
1004 if (is_sizet)
1005 ret += myvprintf_int64(send, send_arg2, flags, 16, width, False,
1006 (ULong)(va_arg (vargs, SizeT)));
1007 else if (is_long)
1008 ret += myvprintf_int64(send, send_arg2, flags, 16, width, caps,
1009 (ULong)(va_arg (vargs, ULong)));
1010 else
1011 ret += myvprintf_int64(send, send_arg2, flags, 16, width, caps,
1012 (ULong)(va_arg (vargs, UInt)));
1013 break;
1014 case 'c': /* %c */
1015 ret++;
1016 send(va_arg (vargs, int), send_arg2);
1017 break;
1018 case 's': case 'S': { /* %s */
1019 const HChar *str = va_arg (vargs, HChar *);
1020 if (str == NULL) str = "(null)";
1021 ret += myvprintf_str(send, send_arg2,
1022 flags, width, str, format[i]=='S');
1023 break;
1024 }
1025 case 'f': {
1026 /* Print a floating point number in the format x.y without
1027 any exponent. Capabilities are extremely limited, basically
1028 a joke, but good enough for our needs. */
1029 Double val = va_arg (vargs, Double);
1030 Bool is_negative = False;
1031 Int cnt;
1032
1033 if (val < 0.0) {
1034 is_negative = True;
1035 val = - val;
1036 }
1037 /* If the integral part of the floating point number cannot be
1038 represented by an ULONG_MAX, print '*' characters */
1039 if (val > (Double)(~0ULL)) {
1040 if (width == 0) width = 6; // say
1041 for (cnt = 0; cnt < width; ++cnt)
1042 send('*', send_arg2);
1043 ret += width;
1044 break;
1045 }
1046 /* The integral part of the floating point number is representable
1047 by an ULong. */
1048 ULong ipval = val;
1049 Double frac = val - ipval;
1050
1051 if (precision == -1) precision = 6; // say
1052
1053 /* Silently limit the precision to 10 digits. */
1054 if (precision > 10) precision = 10;
1055
1056 /* Determine fractional part, possibly round up */
1057 ULong factor = 1;
1058 for (cnt = 0; cnt < precision; ++cnt)
1059 factor *= 10;
1060 ULong frval = frac * factor;
1061 if ((frac * factor - frval) > 0.5) // round up
1062 frval += 1;
1063 /* Check rounding. */
1064 if (frval == factor)
1065 ipval += 1;
1066 frval %= factor;
1067
1068 /* Find out how many characters are needed to print the number */
1069
1070 /* The integral part... */
1071 UInt ipwidth, num_digit = 1; // at least one digit
1072 ULong x, old_x = 0;
1073 for (x = 10; ; old_x = x, x *= 10, ++num_digit) {
1074 if (x <= old_x) break; // overflow occurred
1075 if (ipval < x) break;
1076 }
1077 ipwidth = num_digit; // width of integral part.
1078 if (is_negative) ++num_digit;
1079 if (precision != 0)
1080 num_digit += 1 + precision;
1081
1082 // Print the number
1083
1084 // Fill in blanks on the left
1085 if (num_digit < width && (flags & VG_MSG_LJUSTIFY) == 0) {
1086 for (cnt = 0; cnt < width - num_digit; ++cnt)
1087 send(' ', send_arg2);
1088 ret += width - num_digit;
1089 }
1090 // Sign, maybe
1091 if (is_negative) {
1092 send('-', send_arg2);
1093 ret += 1;
1094 }
1095 // Integral part
1096 ret += myvprintf_int64(send, send_arg2, 0, 10, ipwidth, False,
1097 ipval);
1098 // Decimal point and fractional part
1099 if (precision != 0) {
1100 send('.', send_arg2);
1101 ret += 1;
1102
1103 ret += myvprintf_int64(send, send_arg2, VG_MSG_ZJUSTIFY, 10,
1104 precision, False, frval);
1105 }
1106 // Fill in blanks on the right
1107 if (num_digit < width && (flags & VG_MSG_LJUSTIFY) != 0) {
1108 for (cnt = 0; cnt < width - num_digit; ++cnt)
1109 send(' ', send_arg2);
1110 ret += width - num_digit;
1111 }
1112 break;
1113 }
1114
1115 // case 'y': { /* %y - print symbol */
1116 // Addr a = va_arg(vargs, Addr);
1117 //
1118 // HChar *name;
1119 // if (VG_(get_fnname_w_offset)(a, &name)) {
1120 // HChar buf[1 + VG_strlen(name) + 1 + 1];
1121 // if (flags & VG_MSG_PAREN) {
1122 // VG_(sprintf)(str, "(%s)", name):
1123 // } else {
1124 // VG_(sprintf)(str, "%s", name):
1125 // }
1126 // ret += myvprintf_str(send, flags, width, buf, 0);
1127 // }
1128 // break;
1129 // }
1130 default:
1131 break;
1132 }
1133 }
1134 return ret;
1135 }
1136
1137
1138 /*------------------------------------------------------------*/
1139 /*--- Debuglog stuff. ---*/
1140 /*------------------------------------------------------------*/
1141
1142 /* Only print messages whose stated level is less than or equal to
1143 this. By default, it makes this entire subsystem silent. */
1144
1145 static Int loglevel = 0;
1146
1147 /* Module startup. */
1148 /* EXPORTED */
VG_(debugLog_startup)1149 void VG_(debugLog_startup) ( Int level, const HChar* who )
1150 {
1151 if (level < 0) level = 0;
1152 if (level > 10) level = 10;
1153 loglevel = level;
1154 VG_(debugLog)(1, "debuglog",
1155 "DebugLog system started by %s, "
1156 "level %d logging requested\n",
1157 who, loglevel);
1158 }
1159
1160 /* Get the logging threshold level, as set by the most recent call to
1161 VG_(debugLog_startup), or zero if there have been no such calls so
1162 far. */
1163 /* EXPORTED */
VG_(debugLog_getLevel)1164 Int VG_(debugLog_getLevel) ( void )
1165 {
1166 return loglevel;
1167 }
1168
1169
1170 /* ------------ */
1171
1172 typedef
1173 struct {
1174 HChar buf[100];
1175 Int n;
1176 }
1177 printf_buf;
1178
add_to_buf(HChar c,void * p)1179 static void add_to_buf ( HChar c, void* p )
1180 {
1181 printf_buf* buf = (printf_buf*)p;
1182
1183 if (buf->n >= 100-10 /*paranoia*/ ) {
1184 emit( buf->buf, local_strlen(buf->buf) );
1185 buf->n = 0;
1186 buf->buf[buf->n] = 0;
1187 }
1188 buf->buf[buf->n++] = c;
1189 buf->buf[buf->n] = 0;
1190 }
1191
1192 /* Send a logging message. Nothing is output unless 'level'
1193 is <= the current loglevel. */
1194 /* EXPORTED */
VG_(debugLog)1195 void VG_(debugLog) ( Int level, const HChar* modulename,
1196 const HChar* format, ... )
1197 {
1198 UInt pid;
1199 Int indent, depth, i;
1200 va_list vargs;
1201 printf_buf buf;
1202
1203 if (level > loglevel)
1204 return;
1205
1206 indent = 2*level - 1;
1207 if (indent < 1) indent = 1;
1208
1209 buf.n = 0;
1210 buf.buf[0] = 0;
1211 pid = local_sys_getpid();
1212
1213 // Print one '>' in front of the messages for each level of self-hosting
1214 // being performed.
1215 depth = RUNNING_ON_VALGRIND;
1216 for (i = 0; i < depth; i++) {
1217 (void)myvprintf_str ( add_to_buf, &buf, 0, 1, ">", False );
1218 }
1219
1220 (void)myvprintf_str ( add_to_buf, &buf, 0, 2, "--", False );
1221 (void)myvprintf_int64 ( add_to_buf, &buf, 0, 10, 1, False, (ULong)pid );
1222 (void)myvprintf_str ( add_to_buf, &buf, 0, 1, ":", False );
1223 (void)myvprintf_int64 ( add_to_buf, &buf, 0, 10, 1, False, (ULong)level );
1224 (void)myvprintf_str ( add_to_buf, &buf, 0, 1, ":", False );
1225 (void)myvprintf_str ( add_to_buf, &buf, 0, 8, modulename, False );
1226 (void)myvprintf_str ( add_to_buf, &buf, 0, indent, "", False );
1227
1228 va_start(vargs,format);
1229
1230 (void) VG_(debugLog_vprintf) ( add_to_buf, &buf, format, vargs );
1231
1232 if (buf.n > 0) {
1233 emit( buf.buf, local_strlen(buf.buf) );
1234 }
1235
1236 va_end(vargs);
1237 }
1238
1239
1240
1241 /*--------------------------------------------------------------------*/
1242 /*--- end m_debuglog.c ---*/
1243 /*--------------------------------------------------------------------*/
1244