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