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