• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 = "&amp;"; break;
624          case '<': alt = "&lt;"; break;
625          case '>': alt = "&gt;"; 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