Home | History | Annotate | Download | only in coregrind
      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 (at) 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 
     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 
     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 
     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))
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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))
    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 
    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))
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 */
    515 static Int local_strlen ( const HChar* str )
    516 {
    517    Int i = 0;
    518    while (str[i] != 0) i++;
    519    return i;
    520 }
    521 
    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 */
    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
    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
    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
    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
    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 */
    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 */
    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 
    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 */
    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