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