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