1
2 /*--------------------------------------------------------------------*/
3 /*--- Debug (not-for-user) logging; also vprintf. m_debuglog.c ---*/
4 /*--------------------------------------------------------------------*/
5
6 /*
7 This file is part of Valgrind, a dynamic binary instrumentation
8 framework.
9
10 Copyright (C) 2000-2013 Julian Seward
11 jseward@acm.org
12
13 This program is free software; you can redistribute it and/or
14 modify it under the terms of the GNU General Public License as
15 published by the Free Software Foundation; either version 2 of the
16 License, or (at your option) any later version.
17
18 This program is distributed in the hope that it will be useful, but
19 WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 General Public License for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software
25 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
26 02111-1307, USA.
27
28 The GNU General Public License is contained in the file COPYING.
29 */
30
31
32 /* Performs low-level debug logging that can safely run immediately
33 after startup. To minimise the dependencies on any other parts of
34 the system, the only place the debug output may go is file
35 descriptor 2 (stderr).
36 */
37 /* This is the first-initialised module in the entire system!
38 Therefore it is CRITICAL that it does not depend on any other code
39 running first. Hence only the following very limited includes. We
40 cannot depend (directly or indirectly) on any dynamic memory
41 allocation facilities, nor on the m_libc facilities, since the
42 latter depend on this module. DO NOT MESS WITH THESE INCLUDES
43 UNLESS YOU ARE 100% CERTAIN YOU UNDERSTAND THE CONSEQUENCES.
44 */
45
46 /* This module is also notable because it is linked into both
47 stage1 and stage2. */
48
49 /* IMPORTANT: on Darwin it is essential to use the _nocancel versions
50 of syscalls rather than the vanilla version, if a _nocancel version
51 is available. See docs/internals/Darwin-notes.txt for the reason
52 why. */
53
54 #include "pub_core_basics.h" /* basic types */
55 #include "pub_core_vkiscnums.h" /* for syscall numbers */
56 #include "pub_core_debuglog.h" /* our own iface */
57 #include "pub_core_clreq.h" /* for RUNNING_ON_VALGRIND */
58
59 static Bool clo_xml;
60
VG_(debugLog_setXml)61 void VG_(debugLog_setXml)(Bool xml)
62 {
63 clo_xml = xml;
64 }
65
66 /*------------------------------------------------------------*/
67 /*--- Stuff to make us completely independent. ---*/
68 /*------------------------------------------------------------*/
69
70 /* ----- Platform-specifics ----- */
71
72 #if defined(VGP_x86_linux)
73
local_sys_write_stderr(const HChar * buf,Int n)74 static UInt local_sys_write_stderr ( const HChar* buf, Int n )
75 {
76 Int result;
77
78 __asm__ volatile (
79 "pushl %%ebx\n"
80 "movl $"VG_STRINGIFY(__NR_write)", %%eax\n" /* %eax = __NR_write */
81 "movl $2, %%ebx\n" /* %ebx = stderr */
82 "int $0x80\n" /* write(stderr, buf, n) */
83 "popl %%ebx\n"
84 : /*wr*/ "=a" (result)
85 : /*rd*/ "c" (buf), "d" (n)
86 : /*trash*/ "edi", "memory", "cc"
87 );
88
89 return result >= 0 ? result : -1;
90 }
91
local_sys_getpid(void)92 static UInt local_sys_getpid ( void )
93 {
94 UInt __res;
95 __asm__ volatile (
96 "movl $"VG_STRINGIFY(__NR_getpid)", %%eax\n" /* %eax = __NR_getpid */
97 "int $0x80\n" /* getpid() */
98 "movl %%eax, %0\n" /* set __res = eax */
99 : "=mr" (__res)
100 :
101 : "eax" );
102 return __res;
103 }
104
105 #elif defined(VGP_amd64_linux)
106
107 __attribute__((noinline))
local_sys_write_stderr(const HChar * buf,Int n)108 static UInt local_sys_write_stderr ( const HChar* buf, Int n )
109 {
110 volatile Long block[2];
111 block[0] = (Long)buf;
112 block[1] = n;
113 __asm__ volatile (
114 "subq $256, %%rsp\n" /* don't trash the stack redzone */
115 "pushq %%r15\n" /* r15 is callee-save */
116 "movq %0, %%r15\n" /* r15 = &block */
117 "pushq %%r15\n" /* save &block */
118 "movq $"VG_STRINGIFY(__NR_write)", %%rax\n" /* rax = __NR_write */
119 "movq $2, %%rdi\n" /* rdi = stderr */
120 "movq 0(%%r15), %%rsi\n" /* rsi = buf */
121 "movq 8(%%r15), %%rdx\n" /* rdx = n */
122 "syscall\n" /* write(stderr, buf, n) */
123 "popq %%r15\n" /* reestablish &block */
124 "movq %%rax, 0(%%r15)\n" /* block[0] = result */
125 "popq %%r15\n" /* restore r15 */
126 "addq $256, %%rsp\n" /* restore stack ptr */
127 : /*wr*/
128 : /*rd*/ "r" (block)
129 : /*trash*/ "rax", "rdi", "rsi", "rdx", "memory", "cc"
130 );
131 if (block[0] < 0)
132 block[0] = -1;
133 return (UInt)block[0];
134 }
135
local_sys_getpid(void)136 static UInt local_sys_getpid ( void )
137 {
138 UInt __res;
139 __asm__ volatile (
140 "movq $"VG_STRINGIFY(__NR_getpid)", %%rax\n" /* %rax = __NR_getpid */
141 "syscall\n" /* getpid() */
142 "movl %%eax, %0\n" /* set __res = %eax */
143 : "=mr" (__res)
144 :
145 : "rax" );
146 return __res;
147 }
148
149 #elif defined(VGP_ppc32_linux)
150
local_sys_write_stderr(const HChar * buf,Int n)151 static UInt local_sys_write_stderr ( const HChar* buf, Int n )
152 {
153 volatile Int block[2];
154 block[0] = (Int)buf;
155 block[1] = n;
156 __asm__ volatile (
157 "addi 1,1,-256\n\t"
158 "mr 5,%0\n\t" /* r5 = &block[0] */
159 "stw 5,0(1)\n\t" /* stash on stack */
160 "li 0,"VG_STRINGIFY(__NR_write)"\n\t" /* set %r0 = __NR_write */
161 "li 3,2\n\t" /* set %r3 = stderr */
162 "lwz 4,0(5)\n\t" /* set %r4 = buf */
163 "lwz 5,4(5)\n\t" /* set %r5 = n */
164 "sc\n\t" /* write(stderr, buf, n) */
165 "lwz 5,0(1)\n\t"
166 "addi 1,1,256\n\t"
167 "stw 3,0(5)\n" /* block[0] = result */
168 :
169 : "b" (block)
170 : "cc","memory","cr0","ctr",
171 "r0","r2","r3","r4","r5","r6","r7","r8","r9","r10","r11","r12"
172 );
173 if (block[0] < 0)
174 block[0] = -1;
175 return (UInt)block[0];
176 }
177
local_sys_getpid(void)178 static UInt local_sys_getpid ( void )
179 {
180 register UInt __res __asm__ ("r3");
181 __asm__ volatile (
182 "li 0, %1\n\t"
183 "sc"
184 : "=&r" (__res)
185 : "i" (__NR_getpid)
186 : "cc","memory","cr0","ctr",
187 "r0","r2","r4","r5","r6","r7","r8","r9","r10","r11","r12"
188 );
189 return __res;
190 }
191
192 #elif defined(VGP_ppc64_linux)
193
local_sys_write_stderr(const HChar * buf,Int n)194 static UInt local_sys_write_stderr ( const HChar* buf, Int n )
195 {
196 volatile Long block[2];
197 block[0] = (Long)buf;
198 block[1] = (Long)n;
199 __asm__ volatile (
200 "addi 1,1,-256\n\t"
201 "mr 5,%0\n\t" /* r5 = &block[0] */
202 "std 5,0(1)\n\t" /* stash on stack */
203 "li 0,"VG_STRINGIFY(__NR_write)"\n\t" /* %r0 = __NR_write */
204 "li 3,2\n\t" /* set %r3 = stderr */
205 "ld 4,0(5)\n\t" /* set %r4 = buf */
206 "ld 5,8(5)\n\t" /* set %r5 = n */
207 "sc\n\t" /* write(stderr, buf, n) */
208 "ld 5,0(1)\n\t"
209 "addi 1,1,256\n\t"
210 "std 3,0(5)\n" /* block[0] = result */
211 :
212 : "b" (block)
213 : "cc","memory","cr0","ctr",
214 "r0","r2","r3","r4","r5","r6","r7","r8","r9","r10","r11","r12"
215 );
216 if (block[0] < 0)
217 block[0] = -1;
218 return (UInt)(Int)block[0];
219 }
220
local_sys_getpid(void)221 static UInt local_sys_getpid ( void )
222 {
223 register ULong __res __asm__ ("r3");
224 __asm__ volatile (
225 "li 0, %1\n\t"
226 "sc"
227 : "=&r" (__res)
228 : "i" (__NR_getpid)
229 : "cc","memory","cr0","ctr",
230 "r0","r2","r4","r5","r6","r7","r8","r9","r10","r11","r12"
231 );
232 return (UInt)__res;
233 }
234
235 #elif defined(VGP_arm_linux)
236
local_sys_write_stderr(const HChar * buf,Int n)237 static UInt local_sys_write_stderr ( const HChar* buf, Int n )
238 {
239 volatile Int block[2];
240 block[0] = (Int)buf;
241 block[1] = n;
242 __asm__ volatile (
243 "mov r0, #2\n\t" /* stderr */
244 "ldr r1, [%0]\n\t" /* buf */
245 "ldr r2, [%0, #4]\n\t" /* n */
246 "mov r7, #"VG_STRINGIFY(__NR_write)"\n\t"
247 "svc 0x0\n" /* write() */
248 "str r0, [%0]\n\t"
249 :
250 : "r" (block)
251 : "r0","r1","r2","r7"
252 );
253 if (block[0] < 0)
254 block[0] = -1;
255 return (UInt)block[0];
256 }
257
local_sys_getpid(void)258 static UInt local_sys_getpid ( void )
259 {
260 UInt __res;
261 __asm__ volatile (
262 "mov r7, #"VG_STRINGIFY(__NR_getpid)"\n"
263 "svc 0x0\n" /* getpid() */
264 "mov %0, r0\n"
265 : "=r" (__res)
266 :
267 : "r0", "r7" );
268 return __res;
269 }
270
271 #elif defined(VGP_arm64_linux)
272
local_sys_write_stderr(const HChar * buf,Int n)273 static UInt local_sys_write_stderr ( const HChar* buf, Int n )
274 {
275 volatile ULong block[2];
276 block[0] = (ULong)buf;
277 block[1] = (ULong)n;
278 __asm__ volatile (
279 "mov x0, #2\n\t" /* stderr */
280 "ldr x1, [%0]\n\t" /* buf */
281 "ldr x2, [%0, #8]\n\t" /* n */
282 "mov x8, #"VG_STRINGIFY(__NR_write)"\n\t"
283 "svc 0x0\n" /* write() */
284 "str x0, [%0]\n\t"
285 :
286 : "r" (block)
287 : "x0","x1","x2","x7"
288 );
289 if (block[0] < 0)
290 block[0] = -1;
291 return (UInt)block[0];
292 }
293
local_sys_getpid(void)294 static UInt local_sys_getpid ( void )
295 {
296 UInt __res;
297 __asm__ volatile (
298 "mov x8, #"VG_STRINGIFY(__NR_getpid)"\n"
299 "svc 0x0\n" /* getpid() */
300 "mov %0, x0\n"
301 : "=r" (__res)
302 :
303 : "x0", "x8" );
304 return (UInt)__res;
305 }
306
307 #elif defined(VGP_x86_darwin)
308
309 /* We would use VG_DARWIN_SYSNO_TO_KERNEL instead of VG_DARWIN_SYSNO_INDEX
310 except that the former has a C ternary ?: operator which isn't valid in
311 asm code. Both macros give the same results for Unix-class syscalls (which
312 these all are, as identified by the use of 'int 0x80'). */
313 __attribute__((noinline))
local_sys_write_stderr(const HChar * buf,Int n)314 static UInt local_sys_write_stderr ( const HChar* buf, Int n )
315 {
316 UInt __res;
317 __asm__ volatile (
318 "movl %2, %%eax\n" /* push n */
319 "pushl %%eax\n"
320 "movl %1, %%eax\n" /* push buf */
321 "pushl %%eax\n"
322 "movl $2, %%eax\n" /* push stderr */
323 "pushl %%eax\n"
324 "movl $"VG_STRINGIFY(VG_DARWIN_SYSNO_INDEX(__NR_write_nocancel))
325 ", %%eax\n"
326 "pushl %%eax\n" /* push fake return address */
327 "int $0x80\n" /* write(stderr, buf, n) */
328 "jnc 1f\n" /* jump if no error */
329 "movl $-1, %%eax\n" /* return -1 if error */
330 "1: "
331 "movl %%eax, %0\n" /* __res = eax */
332 "addl $16, %%esp\n" /* pop x4 */
333 : "=mr" (__res)
334 : "g" (buf), "g" (n)
335 : "eax", "edx", "cc"
336 );
337 return __res;
338 }
339
local_sys_getpid(void)340 static UInt local_sys_getpid ( void )
341 {
342 UInt __res;
343 __asm__ volatile (
344 "movl $"VG_STRINGIFY(VG_DARWIN_SYSNO_INDEX(__NR_getpid))", %%eax\n"
345 "int $0x80\n" /* getpid() */
346 "movl %%eax, %0\n" /* set __res = eax */
347 : "=mr" (__res)
348 :
349 : "eax", "cc" );
350 return __res;
351 }
352
353 #elif defined(VGP_amd64_darwin)
354
355 __attribute__((noinline))
local_sys_write_stderr(const HChar * buf,Int n)356 static UInt local_sys_write_stderr ( const HChar* buf, Int n )
357 {
358 UInt __res;
359 __asm__ volatile (
360 "movq $2, %%rdi\n" /* push stderr */
361 "movq %1, %%rsi\n" /* push buf */
362 "movl %2, %%edx\n" /* push n */
363 "movl $"VG_STRINGIFY(VG_DARWIN_SYSNO_FOR_KERNEL(__NR_write_nocancel))
364 ", %%eax\n"
365 "syscall\n" /* write(stderr, buf, n) */
366 "jnc 1f\n" /* jump if no error */
367 "movq $-1, %%rax\n" /* return -1 if error */
368 "1: "
369 "movl %%eax, %0\n" /* __res = eax */
370 : "=mr" (__res)
371 : "g" (buf), "g" (n)
372 : "rdi", "rsi", "rdx", "rcx", "rax", "cc" );
373 return __res;
374 }
375
local_sys_getpid(void)376 static UInt local_sys_getpid ( void )
377 {
378 UInt __res;
379 __asm__ volatile (
380 "movl $"VG_STRINGIFY(VG_DARWIN_SYSNO_FOR_KERNEL(__NR_getpid))", %%eax\n"
381 "syscall\n" /* getpid() */
382 "movl %%eax, %0\n" /* set __res = eax */
383 : "=mr" (__res)
384 :
385 : "rax", "rcx", "cc" );
386 return __res;
387 }
388
389 #elif defined(VGP_s390x_linux)
390
local_sys_write_stderr(const HChar * buf,Int n)391 static UInt local_sys_write_stderr ( const HChar* buf, Int n )
392 {
393 register Int r2 asm("2") = 2; /* file descriptor STDERR */
394 register const HChar* r3 asm("3") = buf;
395 register ULong r4 asm("4") = n;
396 register ULong r2_res asm("2");
397 ULong __res;
398
399 __asm__ __volatile__ (
400 "svc %b1\n"
401 : "=d" (r2_res)
402 : "i" (__NR_write),
403 "0" (r2),
404 "d" (r3),
405 "d" (r4)
406 : "cc", "memory");
407 __res = r2_res;
408
409 if (__res >= (ULong)(-125))
410 __res = -1;
411 return (UInt)(__res);
412 }
413
local_sys_getpid(void)414 static UInt local_sys_getpid ( void )
415 {
416 register ULong r2 asm("2");
417 ULong __res;
418
419 __asm__ __volatile__ (
420 "svc %b1\n"
421 : "=d" (r2)
422 : "i" (__NR_getpid)
423 : "cc", "memory");
424 __res = r2;
425
426 if (__res >= (ULong)(-125))
427 __res = -1;
428 return (UInt)(__res);
429 }
430
431 #elif defined(VGP_mips32_linux)
432
local_sys_write_stderr(const HChar * buf,Int n)433 static UInt local_sys_write_stderr ( const HChar* buf, Int n )
434 {
435 volatile Int block[2];
436 block[0] = (Int)buf;
437 block[1] = n;
438 __asm__ volatile (
439 "li $4, 2\n\t" /* stderr */
440 "lw $5, 0(%0)\n\t" /* buf */
441 "lw $6, 4(%0)\n\t" /* n */
442 "move $7, $0\n\t"
443 "li $2, %1\n\t" /* set v0 = __NR_write */
444 "syscall\n\t" /* write() */
445 "nop\n\t"
446 :
447 : "r" (block), "n" (__NR_write)
448 : "2", "4", "5", "6", "7"
449 );
450 if (block[0] < 0)
451 block[0] = -1;
452 return (UInt)block[0];
453 }
454
local_sys_getpid(void)455 static UInt local_sys_getpid ( void )
456 {
457 UInt __res;
458 __asm__ volatile (
459 "li $2, %1\n\t" /* set v0 = __NR_getpid */
460 "syscall\n\t" /* getpid() */
461 "nop\n\t"
462 "move %0, $2\n"
463 : "=r" (__res)
464 : "n" (__NR_getpid)
465 : "$2" );
466 return __res;
467 }
468
469 #elif defined(VGP_mips64_linux)
470
local_sys_write_stderr(const HChar * buf,Int n)471 static UInt local_sys_write_stderr ( const HChar* buf, Int n )
472 {
473 volatile Long block[2];
474 block[0] = (Long)buf;
475 block[1] = n;
476 __asm__ volatile (
477 "li $4, 2\n\t" /* std output*/
478 "ld $5, 0(%0)\n\t" /*$5 = buf*/
479 "ld $6, 8(%0)\n\t" /*$6 = n */
480 "move $7, $0\n\t"
481 "li $2, %1\n\t" /* set v0 = __NR_write */
482 "\tsyscall\n"
483 "\tnop\n"
484 : /*wr*/
485 : /*rd*/ "r" (block), "n" (__NR_write)
486 : "2", "4", "5", "6", "7"
487 );
488 if (block[0] < 0)
489 block[0] = -1;
490 return (UInt)(Int)block[0];
491 }
492
local_sys_getpid(void)493 static UInt local_sys_getpid ( void )
494 {
495 ULong __res;
496 __asm__ volatile (
497 "li $2, %1\n\t" /* set v0 = __NR_getpid */
498 "syscall\n\t" /* getpid() */
499 "nop\n\t"
500 "move %0, $2\n"
501 : "=r" (__res)
502 : "n" (__NR_getpid)
503 : "$2" );
504 return (UInt)(__res);
505 }
506
507 #else
508 # error Unknown platform
509 #endif
510
511
512 /* ----- generic ----- */
513
514 /* strlen, so we don't need m_libc */
local_strlen(const HChar * str)515 static Int local_strlen ( const HChar* str )
516 {
517 Int i = 0;
518 while (str[i] != 0) i++;
519 return i;
520 }
521
local_toupper(HChar c)522 static HChar local_toupper ( HChar c )
523 {
524 if (c >= 'a' && c <= 'z')
525 return c + ('A' - 'a');
526 else
527 return c;
528 }
529
530 /* Emit buf[0 .. n-1] to stderr. Unfortunately platform-specific.
531 */
emit(const HChar * buf,Int n)532 static void emit ( const HChar* buf, Int n )
533 {
534 if (n >= 1)
535 (void)local_sys_write_stderr(buf, n);
536 }
537
538
539 /*------------------------------------------------------------*/
540 /*--- A simple, generic, vprintf implementation. ---*/
541 /*------------------------------------------------------------*/
542
543 /* -----------------------------------------------
544 Distantly derived from:
545
546 vprintf replacement for Checker.
547 Copyright 1993, 1994, 1995 Tristan Gingold
548 Written September 1993 Tristan Gingold
549 Tristan Gingold, 8 rue Parmentier, F-91120 PALAISEAU, FRANCE
550
551 (Checker itself was GPL'd.)
552 ----------------------------------------------- */
553
554 /* Some flags. */
555 #define VG_MSG_SIGNED 1 /* The value is signed. */
556 #define VG_MSG_ZJUSTIFY 2 /* Must justify with '0'. */
557 #define VG_MSG_LJUSTIFY 4 /* Must justify on the left. */
558 #define VG_MSG_PAREN 8 /* Parenthesize if present (for %y) */
559 #define VG_MSG_COMMA 16 /* Add commas to numbers (for %d, %u) */
560 #define VG_MSG_ALTFORMAT 32 /* Convert the value to alternate format */
561
562 /* Copy a string into the buffer. */
563 static
myvprintf_str(void (* send)(HChar,void *),void * send_arg2,Int flags,Int width,const HChar * str,Bool capitalise)564 UInt myvprintf_str ( void(*send)(HChar,void*),
565 void* send_arg2,
566 Int flags,
567 Int width,
568 const HChar* str,
569 Bool capitalise )
570 {
571 # define MAYBE_TOUPPER(ch) (capitalise ? local_toupper(ch) : (ch))
572 UInt ret = 0;
573 Int i, extra;
574 Int len = local_strlen(str);
575
576 if (width == 0) {
577 ret += len;
578 for (i = 0; i < len; i++)
579 send(MAYBE_TOUPPER(str[i]), send_arg2);
580 return ret;
581 }
582
583 if (len > width) {
584 ret += width;
585 for (i = 0; i < width; i++)
586 send(MAYBE_TOUPPER(str[i]), send_arg2);
587 return ret;
588 }
589
590 extra = width - len;
591 if (flags & VG_MSG_LJUSTIFY) {
592 ret += extra;
593 for (i = 0; i < extra; i++)
594 send(' ', send_arg2);
595 }
596 ret += len;
597 for (i = 0; i < len; i++)
598 send(MAYBE_TOUPPER(str[i]), send_arg2);
599 if (!(flags & VG_MSG_LJUSTIFY)) {
600 ret += extra;
601 for (i = 0; i < extra; i++)
602 send(' ', send_arg2);
603 }
604
605 # undef MAYBE_TOUPPER
606 return ret;
607 }
608
609
610 /* Copy a string into the buffer, escaping bad XML chars. */
611 static
myvprintf_str_XML_simplistic(void (* send)(HChar,void *),void * send_arg2,const HChar * str)612 UInt myvprintf_str_XML_simplistic ( void(*send)(HChar,void*),
613 void* send_arg2,
614 const HChar* str )
615 {
616 UInt ret = 0;
617 Int i;
618 Int len = local_strlen(str);
619 const HChar* alt;
620
621 for (i = 0; i < len; i++) {
622 switch (str[i]) {
623 case '&': alt = "&"; break;
624 case '<': alt = "<"; break;
625 case '>': alt = ">"; break;
626 default: alt = NULL;
627 }
628
629 if (alt) {
630 while (*alt) {
631 send(*alt, send_arg2);
632 ret++;
633 alt++;
634 }
635 } else {
636 send(str[i], send_arg2);
637 ret++;
638 }
639 }
640
641 return ret;
642 }
643
644
645 /* Write P into the buffer according to these args:
646 * If SIGN is true, p is a signed.
647 * BASE is the base.
648 * If WITH_ZERO is true, '0' must be added.
649 * WIDTH is the width of the field.
650 */
651 static
myvprintf_int64(void (* send)(HChar,void *),void * send_arg2,Int flags,Int base,Int width,Bool capitalised,ULong p)652 UInt myvprintf_int64 ( void(*send)(HChar,void*),
653 void* send_arg2,
654 Int flags,
655 Int base,
656 Int width,
657 Bool capitalised,
658 ULong p )
659 {
660 HChar buf[40];
661 Int ind = 0;
662 Int i, nc = 0;
663 Bool neg = False;
664 const HChar* digits = capitalised ? "0123456789ABCDEF" : "0123456789abcdef";
665 UInt ret = 0;
666
667 if (base < 2 || base > 16)
668 return ret;
669
670 if ((flags & VG_MSG_SIGNED) && (Long)p < 0) {
671 p = - (Long)p;
672 neg = True;
673 }
674
675 if (p == 0)
676 buf[ind++] = '0';
677 else {
678 while (p > 0) {
679 if (flags & VG_MSG_COMMA && 10 == base &&
680 0 == (ind-nc) % 3 && 0 != ind)
681 {
682 buf[ind++] = ',';
683 nc++;
684 }
685 buf[ind++] = digits[p % base];
686 p /= base;
687 }
688 }
689
690 if (neg)
691 buf[ind++] = '-';
692
693 if (width > 0 && !(flags & VG_MSG_LJUSTIFY)) {
694 for(; ind < width; ind++) {
695 /* vg_assert(ind < 39); */
696 if (ind > 39) {
697 buf[39] = 0;
698 break;
699 }
700 buf[ind] = (flags & VG_MSG_ZJUSTIFY) ? '0': ' ';
701 }
702 }
703
704 /* Reverse copy to buffer. */
705 ret += ind;
706 for (i = ind -1; i >= 0; i--) {
707 send(buf[i], send_arg2);
708 }
709 if (width > 0 && (flags & VG_MSG_LJUSTIFY)) {
710 for(; ind < width; ind++) {
711 ret++;
712 /* Never pad with zeroes on RHS -- changes the value! */
713 send(' ', send_arg2);
714 }
715 }
716 return ret;
717 }
718
719
720 /* A simple vprintf(). */
721 /* EXPORTED */
722 UInt
VG_(debugLog_vprintf)723 VG_(debugLog_vprintf) (
724 void(*send)(HChar,void*),
725 void* send_arg2,
726 const HChar* format,
727 va_list vargs
728 )
729 {
730 UInt ret = 0;
731 Int i;
732 Int flags;
733 Int width;
734 Int n_ls = 0;
735 Bool is_long, caps;
736
737 /* We assume that vargs has already been initialised by the
738 caller, using va_start, and that the caller will similarly
739 clean up with va_end.
740 */
741
742 for (i = 0; format[i] != 0; i++) {
743 if (format[i] != '%') {
744 send(format[i], send_arg2);
745 ret++;
746 continue;
747 }
748 i++;
749 /* A '%' has been found. Ignore a trailing %. */
750 if (format[i] == 0)
751 break;
752 if (format[i] == '%') {
753 /* '%%' is replaced by '%'. */
754 send('%', send_arg2);
755 ret++;
756 continue;
757 }
758 flags = 0;
759 n_ls = 0;
760 width = 0; /* length of the field. */
761 while (1) {
762 switch (format[i]) {
763 case '(':
764 flags |= VG_MSG_PAREN;
765 break;
766 case ',':
767 case '\'':
768 /* If ',' or '\'' follows '%', commas will be inserted. */
769 flags |= VG_MSG_COMMA;
770 break;
771 case '-':
772 /* If '-' follows '%', justify on the left. */
773 flags |= VG_MSG_LJUSTIFY;
774 break;
775 case '0':
776 /* If '0' follows '%', pads will be inserted. */
777 flags |= VG_MSG_ZJUSTIFY;
778 break;
779 case '#':
780 /* If '#' follows '%', alternative format will be used. */
781 flags |= VG_MSG_ALTFORMAT;
782 break;
783 default:
784 goto parse_fieldwidth;
785 }
786 i++;
787 }
788 parse_fieldwidth:
789 /* Compute the field length. */
790 while (format[i] >= '0' && format[i] <= '9') {
791 width *= 10;
792 width += format[i++] - '0';
793 }
794 while (format[i] == 'l') {
795 i++;
796 n_ls++;
797 }
798
799 // %d means print a 32-bit integer.
800 // %ld means print a word-size integer.
801 // %lld means print a 64-bit integer.
802 if (0 == n_ls) { is_long = False; }
803 else if (1 == n_ls) { is_long = ( sizeof(void*) == sizeof(Long) ); }
804 else { is_long = True; }
805
806 switch (format[i]) {
807 case 'o': /* %o */
808 if (flags & VG_MSG_ALTFORMAT) {
809 ret += 2;
810 send('0',send_arg2);
811 }
812 if (is_long)
813 ret += myvprintf_int64(send, send_arg2, flags, 8, width, False,
814 (ULong)(va_arg (vargs, ULong)));
815 else
816 ret += myvprintf_int64(send, send_arg2, flags, 8, width, False,
817 (ULong)(va_arg (vargs, UInt)));
818 break;
819 case 'd': /* %d */
820 flags |= VG_MSG_SIGNED;
821 if (is_long)
822 ret += myvprintf_int64(send, send_arg2, flags, 10, width, False,
823 (ULong)(va_arg (vargs, Long)));
824 else
825 ret += myvprintf_int64(send, send_arg2, flags, 10, width, False,
826 (ULong)(va_arg (vargs, Int)));
827 break;
828 case 'u': /* %u */
829 if (is_long)
830 ret += myvprintf_int64(send, send_arg2, flags, 10, width, False,
831 (ULong)(va_arg (vargs, ULong)));
832 else
833 ret += myvprintf_int64(send, send_arg2, flags, 10, width, False,
834 (ULong)(va_arg (vargs, UInt)));
835 break;
836 case 'p':
837 if (format[i+1] == 'S') {
838 i++;
839 /* %pS, like %s but escaping chars for XML safety */
840 /* Note: simplistic; ignores field width and flags */
841 const HChar *str = va_arg (vargs, HChar *);
842 if (str == NULL)
843 str = "(null)";
844 ret += myvprintf_str_XML_simplistic(send, send_arg2, str);
845 } else if (format[i+1] == 's') {
846 i++;
847 /* %ps, synonym for %s with --xml=no / %pS with --xml=yes */
848 const HChar *str = va_arg (vargs, HChar *);
849 if (str == NULL)
850 str = "(null)";
851 if (clo_xml)
852 ret += myvprintf_str_XML_simplistic(send, send_arg2, str);
853 else
854 ret += myvprintf_str(send, send_arg2, flags, width, str,
855 False);
856 } else {
857 /* %p */
858 ret += 2;
859 send('0',send_arg2);
860 send('x',send_arg2);
861 ret += myvprintf_int64(send, send_arg2, flags, 16, width, True,
862 (ULong)((UWord)va_arg (vargs, void *)));
863 }
864 break;
865 case 'x': /* %x */
866 case 'X': /* %X */
867 caps = toBool(format[i] == 'X');
868 if (flags & VG_MSG_ALTFORMAT) {
869 ret += 2;
870 send('0',send_arg2);
871 send('x',send_arg2);
872 }
873 if (is_long)
874 ret += myvprintf_int64(send, send_arg2, flags, 16, width, caps,
875 (ULong)(va_arg (vargs, ULong)));
876 else
877 ret += myvprintf_int64(send, send_arg2, flags, 16, width, caps,
878 (ULong)(va_arg (vargs, UInt)));
879 break;
880 case 'c': /* %c */
881 ret++;
882 send(va_arg (vargs, int), send_arg2);
883 break;
884 case 's': case 'S': { /* %s */
885 const HChar *str = va_arg (vargs, HChar *);
886 if (str == NULL) str = "(null)";
887 ret += myvprintf_str(send, send_arg2,
888 flags, width, str, format[i]=='S');
889 break;
890 }
891
892 // case 'y': { /* %y - print symbol */
893 // HChar buf[100];
894 // HChar *cp = buf;
895 // Addr a = va_arg(vargs, Addr);
896 //
897 // if (flags & VG_MSG_PAREN)
898 // *cp++ = '(';
899 // if (VG_(get_fnname_w_offset)(a, cp, sizeof(buf)-4)) {
900 // if (flags & VG_MSG_PAREN) {
901 // cp += VG_(strlen)(cp);
902 // *cp++ = ')';
903 // *cp = '\0';
904 // }
905 // ret += myvprintf_str(send, send_arg2, flags, width, buf, 0);
906 // }
907 // break;
908 // }
909 default:
910 break;
911 }
912 }
913 return ret;
914 }
915
916
917 /*------------------------------------------------------------*/
918 /*--- Debuglog stuff. ---*/
919 /*------------------------------------------------------------*/
920
921 /* Only print messages whose stated level is less than or equal to
922 this. By default, it makes this entire subsystem silent. */
923
924 static Int loglevel = 0;
925
926 /* Module startup. */
927 /* EXPORTED */
VG_(debugLog_startup)928 void VG_(debugLog_startup) ( Int level, const HChar* who )
929 {
930 if (level < 0) level = 0;
931 if (level > 10) level = 10;
932 loglevel = level;
933 VG_(debugLog)(1, "debuglog",
934 "DebugLog system started by %s, "
935 "level %d logging requested\n",
936 who, loglevel);
937 }
938
939 /* Get the logging threshold level, as set by the most recent call to
940 VG_(debugLog_startup), or zero if there have been no such calls so
941 far. */
942 /* EXPORTED */
VG_(debugLog_getLevel)943 Int VG_(debugLog_getLevel) ( void )
944 {
945 return loglevel;
946 }
947
948
949 /* ------------ */
950
951 typedef
952 struct {
953 HChar buf[100];
954 Int n;
955 }
956 printf_buf;
957
add_to_buf(HChar c,void * p)958 static void add_to_buf ( HChar c, void* p )
959 {
960 printf_buf* buf = (printf_buf*)p;
961
962 if (buf->n >= 100-10 /*paranoia*/ ) {
963 emit( buf->buf, local_strlen(buf->buf) );
964 buf->n = 0;
965 buf->buf[buf->n] = 0;
966 }
967 buf->buf[buf->n++] = c;
968 buf->buf[buf->n] = 0;
969 }
970
971 /* Send a logging message. Nothing is output unless 'level'
972 is <= the current loglevel. */
973 /* EXPORTED */
VG_(debugLog)974 void VG_(debugLog) ( Int level, const HChar* modulename,
975 const HChar* format, ... )
976 {
977 UInt pid;
978 Int indent, depth, i;
979 va_list vargs;
980 printf_buf buf;
981
982 if (level > loglevel)
983 return;
984
985 indent = 2*level - 1;
986 if (indent < 1) indent = 1;
987
988 buf.n = 0;
989 buf.buf[0] = 0;
990 pid = local_sys_getpid();
991
992 // Print one '>' in front of the messages for each level of self-hosting
993 // being performed.
994 depth = RUNNING_ON_VALGRIND;
995 for (i = 0; i < depth; i++) {
996 (void)myvprintf_str ( add_to_buf, &buf, 0, 1, ">", False );
997 }
998
999 (void)myvprintf_str ( add_to_buf, &buf, 0, 2, "--", False );
1000 (void)myvprintf_int64 ( add_to_buf, &buf, 0, 10, 1, False, (ULong)pid );
1001 (void)myvprintf_str ( add_to_buf, &buf, 0, 1, ":", False );
1002 (void)myvprintf_int64 ( add_to_buf, &buf, 0, 10, 1, False, (ULong)level );
1003 (void)myvprintf_str ( add_to_buf, &buf, 0, 1, ":", False );
1004 (void)myvprintf_str ( add_to_buf, &buf, 0, 8, modulename, False );
1005 (void)myvprintf_str ( add_to_buf, &buf, 0, indent, "", False );
1006
1007 va_start(vargs,format);
1008
1009 (void) VG_(debugLog_vprintf) ( add_to_buf, &buf, format, vargs );
1010
1011 if (buf.n > 0) {
1012 emit( buf.buf, local_strlen(buf.buf) );
1013 }
1014
1015 va_end(vargs);
1016 }
1017
1018
1019
1020 /*--------------------------------------------------------------------*/
1021 /*--- end m_debuglog.c ---*/
1022 /*--------------------------------------------------------------------*/
1023