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-2015 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","r2","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","r2","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_tilegx_linux)
516 
local_sys_write_stderr(const HChar * buf,Int n)517 static UInt local_sys_write_stderr ( const HChar* buf, Int n )
518 {
519    volatile Long block[2];
520    block[0] = (Long)buf;
521    block[1] = n;
522    Long __res = 0;
523    __asm__ volatile (
524       "movei  r0,  2    \n\t"    /* stderr */
525       "move   r1,  %1   \n\t"    /* buf */
526       "move   r2,  %2   \n\t"    /* n */
527       "move   r3,  zero \n\t"
528       "moveli r10, %3   \n\t"    /* set r10 = __NR_write */
529       "swint1           \n\t"    /* write() */
530       "nop              \n\t"
531       "move   %0, r0    \n\t"    /* save return into block[0] */
532       : "=r"(__res)
533       : "r" (block[0]), "r"(block[1]), "n" (__NR_write)
534       : "r0", "r1", "r2", "r3", "r4", "r5");
535    if (__res < 0)
536       __res = -1;
537    return (UInt)__res;
538 }
539 
local_sys_getpid(void)540 static UInt local_sys_getpid ( void )
541 {
542    UInt __res, __err;
543    __res = 0;
544    __err = 0;
545    __asm__ volatile (
546       "moveli r10, %2\n\t"    /* set r10 = __NR_getpid */
547       "swint1\n\t"            /* getpid() */
548       "nop\n\t"
549       "move  %0, r0\n"
550       "move  %1, r1\n"
551       : "=r" (__res), "=r"(__err)
552       : "n" (__NR_getpid)
553       : "r0", "r1", "r2", "r3", "r4",
554         "r5", "r6", "r7", "r8", "r9",
555         "r10", "r11", "r12", "r13", "r14",
556         "r15", "r16", "r17", "r18", "r19",
557         "r20", "r21", "r22", "r23", "r24",
558         "r25", "r26", "r27", "r28", "r29");
559   return __res;
560 }
561 
562 #elif defined(VGP_x86_solaris)
local_sys_write_stderr(const HChar * buf,Int n)563 static UInt local_sys_write_stderr ( const HChar* buf, Int n )
564 {
565    UInt res, err;
566    Bool restart;
567 
568    do {
569       /* The Solaris kernel does not restart syscalls automatically so it is
570          done here. */
571       __asm__ __volatile__ (
572          "movl  %[n], %%eax\n"          /* push n */
573          "pushl %%eax\n"
574          "movl  %[buf], %%eax\n"        /* push buf */
575          "pushl %%eax\n"
576          "movl  $2, %%eax\n"            /* push stderr */
577          "pushl %%eax\n"
578          "movl  $"VG_STRINGIFY(__NR_write)", %%eax\n"
579          "pushl %%eax\n"                /* push fake return address */
580          "int   $0x91\n"                /* write(stderr, buf, n) */
581          "movl  $0, %%edx\n"            /* assume no error */
582          "jnc   1f\n"                   /* jump if no error */
583          "movl  $1, %%edx\n"            /* set error flag */
584          "1: "
585          "addl  $16, %%esp\n"           /* pop x4 */
586          : "=&a" (res), "=d" (err)
587          : [buf] "g" (buf), [n] "g" (n)
588          : "cc");
589       restart = err && (res == VKI_EINTR || res == VKI_ERESTART);
590    } while (restart);
591 
592    return res;
593 }
594 
local_sys_getpid(void)595 static UInt local_sys_getpid ( void )
596 {
597    UInt res;
598 
599    /* The getpid() syscall never returns EINTR or ERESTART so there is no need
600       for restarting it. */
601    __asm__ __volatile__ (
602       "movl $"VG_STRINGIFY(__NR_getpid)", %%eax\n"
603       "int  $0x91\n"                    /* getpid() */
604       : "=a" (res)
605       :
606       : "edx", "cc");
607 
608    return res;
609 }
610 
611 #elif defined(VGP_amd64_solaris)
local_sys_write_stderr(const HChar * buf,Int n)612 static UInt local_sys_write_stderr ( const HChar* buf, Int n )
613 {
614    ULong res, err;
615    Bool restart;
616 
617    do {
618       /* The Solaris kernel does not restart syscalls automatically so it is
619          done here. */
620       __asm__ __volatile__ (
621          "movq  $2, %%rdi\n"            /* push stderr */
622          "movq  $"VG_STRINGIFY(__NR_write)", %%rax\n"
623          "syscall\n"                    /* write(stderr, buf, n) */
624          "movq  $0, %%rdx\n"            /* assume no error */
625          "jnc   1f\n"                   /* jump if no error */
626          "movq  $1, %%rdx\n"            /* set error flag */
627          "1: "
628          : "=a" (res), "=d" (err)
629          : "S" (buf), "d" (n)
630          : "cc");
631       restart = err && (res == VKI_EINTR || res == VKI_ERESTART);
632    } while (restart);
633 
634    return res;
635 }
636 
local_sys_getpid(void)637 static UInt local_sys_getpid ( void )
638 {
639    UInt res;
640 
641    /* The getpid() syscall never returns EINTR or ERESTART so there is no need
642       for restarting it. */
643    __asm__ __volatile__ (
644       "movq $"VG_STRINGIFY(__NR_getpid)", %%rax\n"
645       "syscall\n"                       /* getpid() */
646       : "=a" (res)
647       :
648       : "edx", "cc");
649 
650    return res;
651 }
652 
653 #else
654 # error Unknown platform
655 #endif
656 
657 
658 /* ----- generic ----- */
659 
660 /* strlen, so we don't need m_libc */
local_strlen(const HChar * str)661 static Int local_strlen ( const HChar* str )
662 {
663    Int i = 0;
664    while (str[i] != 0) i++;
665    return i;
666 }
667 
local_toupper(HChar c)668 static HChar local_toupper ( HChar c )
669 {
670    if (c >= 'a' && c <= 'z')
671       return c + ('A' - 'a');
672    else
673       return c;
674 }
675 
676 /* Emit buf[0 .. n-1] to stderr.  Unfortunately platform-specific.
677 */
emit(const HChar * buf,Int n)678 static void emit ( const HChar* buf, Int n )
679 {
680    if (n >= 1)
681       (void)local_sys_write_stderr(buf, n);
682 }
683 
684 
685 /*------------------------------------------------------------*/
686 /*--- A simple, generic, vprintf implementation.           ---*/
687 /*------------------------------------------------------------*/
688 
689 /* -----------------------------------------------
690    Distantly derived from:
691 
692       vprintf replacement for Checker.
693       Copyright 1993, 1994, 1995 Tristan Gingold
694       Written September 1993 Tristan Gingold
695       Tristan Gingold, 8 rue Parmentier, F-91120 PALAISEAU, FRANCE
696 
697    (Checker itself was GPL'd.)
698    ----------------------------------------------- */
699 
700 /* Some flags.  */
701 #define VG_MSG_SIGNED    1 /* The value is signed. */
702 #define VG_MSG_ZJUSTIFY  2 /* Must justify with '0'. */
703 #define VG_MSG_LJUSTIFY  4 /* Must justify on the left. */
704 #define VG_MSG_PAREN     8 /* Parenthesize if present (for %y) */
705 #define VG_MSG_COMMA    16 /* Add commas to numbers (for %d, %u) */
706 #define VG_MSG_ALTFORMAT 32 /* Convert the value to alternate format */
707 
708 /* Copy a string into the buffer. */
709 static
myvprintf_str(void (* send)(HChar,void *),void * send_arg2,Int flags,Int width,const HChar * str,Bool capitalise)710 UInt myvprintf_str ( void(*send)(HChar,void*),
711                      void* send_arg2,
712                      Int flags,
713                      Int width,
714                      const HChar* str,
715                      Bool capitalise )
716 {
717 #  define MAYBE_TOUPPER(ch) (capitalise ? local_toupper(ch) : (ch))
718    UInt ret = 0;
719    Int i, extra;
720    Int len = local_strlen(str);
721 
722    if (width == 0) {
723       ret += len;
724       for (i = 0; i < len; i++)
725           send(MAYBE_TOUPPER(str[i]), send_arg2);
726       return ret;
727    }
728 
729    if (len > width) {
730       ret += width;
731       for (i = 0; i < width; i++)
732          send(MAYBE_TOUPPER(str[i]), send_arg2);
733       return ret;
734    }
735 
736    extra = width - len;
737    if (! (flags & VG_MSG_LJUSTIFY)) {
738       ret += extra;
739       for (i = 0; i < extra; i++)
740          send(' ', send_arg2);
741    }
742    ret += len;
743    for (i = 0; i < len; i++)
744       send(MAYBE_TOUPPER(str[i]), send_arg2);
745    if (flags & VG_MSG_LJUSTIFY) {
746       ret += extra;
747       for (i = 0; i < extra; i++)
748          send(' ', send_arg2);
749    }
750 
751 #  undef MAYBE_TOUPPER
752    return ret;
753 }
754 
755 
756 /* Copy a string into the buffer, escaping bad XML chars. */
757 static
myvprintf_str_XML_simplistic(void (* send)(HChar,void *),void * send_arg2,const HChar * str)758 UInt myvprintf_str_XML_simplistic ( void(*send)(HChar,void*),
759                                     void* send_arg2,
760                                     const HChar* str )
761 {
762    UInt   ret = 0;
763    Int    i;
764    Int    len = local_strlen(str);
765    const HChar* alt;
766 
767    for (i = 0; i < len; i++) {
768       switch (str[i]) {
769          case '&': alt = "&amp;"; break;
770          case '<': alt = "&lt;"; break;
771          case '>': alt = "&gt;"; break;
772          default:  alt = NULL;
773       }
774 
775       if (alt) {
776          while (*alt) {
777             send(*alt, send_arg2);
778             ret++;
779             alt++;
780          }
781       } else {
782          send(str[i], send_arg2);
783          ret++;
784       }
785    }
786 
787    return ret;
788 }
789 
790 
791 /* Write P into the buffer according to these args:
792  *  If SIGN is true, p is a signed.
793  *  BASE is the base.
794  *  If WITH_ZERO is true, '0' must be added.
795  *  WIDTH is the width of the field.
796  */
797 static
myvprintf_int64(void (* send)(HChar,void *),void * send_arg2,Int flags,Int base,Int width,Bool capitalised,ULong p)798 UInt myvprintf_int64 ( void(*send)(HChar,void*),
799                        void* send_arg2,
800                        Int flags,
801                        Int base,
802                        Int width,
803                        Bool capitalised,
804                        ULong p )
805 {
806    /* To print an ULong base 2 needs 64 characters. If commas are requested,
807       add 21. Plus 1 for a possible sign plus 1 for \0. Makes 87 -- so let's
808       say 90. The size of BUF needs to be max(90, WIDTH + 1) */
809    HChar  buf[width + 1 > 90 ? width + 1 : 90];
810    Int    ind = 0;
811    Int    i, nc = 0;
812    Bool   neg = False;
813    const HChar* digits = capitalised ? "0123456789ABCDEF" : "0123456789abcdef";
814    UInt   ret = 0;
815 
816    if (base < 2 || base > 16)
817       return ret;
818 
819    if ((flags & VG_MSG_SIGNED) && (Long)p < 0) {
820       p   = - (Long)p;
821       neg = True;
822    }
823 
824    if (p == 0)
825       buf[ind++] = '0';
826    else {
827       while (p > 0) {
828          if (flags & VG_MSG_COMMA && 10 == base &&
829              0 == (ind-nc) % 3 && 0 != ind)
830          {
831             buf[ind++] = ',';
832             nc++;
833          }
834          buf[ind++] = digits[p % base];
835          p /= base;
836       }
837    }
838 
839    if (neg)
840       buf[ind++] = '-';
841 
842    if (width > 0 && !(flags & VG_MSG_LJUSTIFY)) {
843       for(; ind < width; ind++) {
844          buf[ind] = (flags & VG_MSG_ZJUSTIFY) ? '0': ' ';
845       }
846    }
847 
848    /* Reverse copy to buffer.  */
849    ret += ind;
850    for (i = ind -1; i >= 0; i--) {
851       send(buf[i], send_arg2);
852    }
853    if (width > 0 && (flags & VG_MSG_LJUSTIFY)) {
854       for(; ind < width; ind++) {
855          ret++;
856          /* Never pad with zeroes on RHS -- changes the value! */
857          send(' ', send_arg2);
858       }
859    }
860    return ret;
861 }
862 
863 
864 /* A simple vprintf().  */
865 /* EXPORTED */
866 UInt
VG_(debugLog_vprintf)867 VG_(debugLog_vprintf) (
868    void(*send)(HChar,void*),
869    void* send_arg2,
870    const HChar* format,
871    va_list vargs
872 )
873 {
874    UInt ret = 0;
875    Int  i;
876    Int  flags;
877    Int  width, precision;
878    Int  n_ls = 0;
879    Bool is_long, is_sizet, caps;
880 
881    /* We assume that vargs has already been initialised by the
882       caller, using va_start, and that the caller will similarly
883       clean up with va_end.
884    */
885 
886    for (i = 0; format[i] != 0; i++) {
887       if (format[i] != '%') {
888          send(format[i], send_arg2);
889          ret++;
890          continue;
891       }
892       i++;
893       /* A '%' has been found.  Ignore a trailing %. */
894       if (format[i] == 0)
895          break;
896       if (format[i] == '%') {
897          /* '%%' is replaced by '%'. */
898          send('%', send_arg2);
899          ret++;
900          continue;
901       }
902       flags = 0;
903       n_ls  = 0;
904       width = 0; /* length of the field. */
905       precision = -1;  /* unspecified precision */
906       while (1) {
907          switch (format[i]) {
908          case '(':
909             flags |= VG_MSG_PAREN;
910             break;
911          case ',':
912          case '\'':
913             /* If ',' or '\'' follows '%', commas will be inserted. */
914             flags |= VG_MSG_COMMA;
915             break;
916          case '-':
917             /* If '-' follows '%', justify on the left. */
918             flags |= VG_MSG_LJUSTIFY;
919             break;
920          case '0':
921             /* If '0' follows '%', pads will be inserted. */
922             flags |= VG_MSG_ZJUSTIFY;
923             break;
924          case '#':
925             /* If '#' follows '%', alternative format will be used. */
926             flags |= VG_MSG_ALTFORMAT;
927             break;
928          default:
929             goto parse_fieldwidth;
930          }
931          i++;
932       }
933      parse_fieldwidth:
934       /* Compute the field length. */
935       if (format[i] == '*') {
936          width = va_arg(vargs, Int);
937          ++i;
938       } else {
939          while (format[i] >= '0' && format[i] <= '9') {
940             width *= 10;
941             width += format[i++] - '0';
942          }
943       }
944       /* Parse precision, if any. Only meaningful for %f. For all other
945          format specifiers the precision will be silently ignored. */
946       if (format[i] == '.') {
947          ++i;
948          if (format[i] == '*') {
949             precision = va_arg(vargs, Int);
950             ++i;
951          } else {
952             precision = 0;
953             while (format[i] >= '0' && format[i] <= '9') {
954                precision *= 10;
955                precision += format[i++] - '0';
956             }
957          }
958       }
959 
960       is_sizet = False;
961       if (format[i] == 'z') {
962          is_sizet = True;
963          ++i;
964       } else {
965          while (format[i] == 'l') {
966             i++;
967             n_ls++;
968          }
969       }
970 
971       //   %d means print a 32-bit integer.
972       //  %ld means print a word-size integer.
973       // %lld means print a 64-bit integer.
974       if      (0 == n_ls) { is_long = False; }
975       else if (1 == n_ls) { is_long = ( sizeof(void*) == sizeof(Long) ); }
976       else                { is_long = True; }
977 
978       switch (format[i]) {
979          case 'o': /* %o */
980             if (flags & VG_MSG_ALTFORMAT) {
981                ret += 2;
982                send('0',send_arg2);
983             }
984             if (is_sizet)
985                ret += myvprintf_int64(send, send_arg2, flags, 8, width, False,
986                                       (ULong)(va_arg (vargs, SizeT)));
987             else if (is_long)
988                ret += myvprintf_int64(send, send_arg2, flags, 8, width, False,
989                                       (ULong)(va_arg (vargs, ULong)));
990             else
991                ret += myvprintf_int64(send, send_arg2, flags, 8, width, False,
992                                       (ULong)(va_arg (vargs, UInt)));
993             break;
994          case 'd': /* %d */
995             flags |= VG_MSG_SIGNED;
996             if (is_long)
997                ret += myvprintf_int64(send, send_arg2, flags, 10, width, False,
998                                       (ULong)(va_arg (vargs, Long)));
999             else
1000                ret += myvprintf_int64(send, send_arg2, flags, 10, width, False,
1001                                       (ULong)(va_arg (vargs, Int)));
1002             break;
1003          case 'u': /* %u */
1004             if (is_sizet)
1005                ret += myvprintf_int64(send, send_arg2, flags, 10, width, False,
1006                                       (ULong)(va_arg (vargs, SizeT)));
1007             else if (is_long)
1008                ret += myvprintf_int64(send, send_arg2, flags, 10, width, False,
1009                                       (ULong)(va_arg (vargs, ULong)));
1010             else
1011                ret += myvprintf_int64(send, send_arg2, flags, 10, width, False,
1012                                       (ULong)(va_arg (vargs, UInt)));
1013             break;
1014          case 'p':
1015             if (format[i+1] == 'S') {
1016                i++;
1017                /* %pS, like %s but escaping chars for XML safety */
1018                /* Note: simplistic; ignores field width and flags */
1019                const HChar *str = va_arg (vargs, HChar *);
1020                if (str == NULL)
1021                   str = "(null)";
1022                ret += myvprintf_str_XML_simplistic(send, send_arg2, str);
1023             } else if (format[i+1] == 's') {
1024                i++;
1025                /* %ps, synonym for %s with --xml=no / %pS with --xml=yes */
1026                const HChar *str = va_arg (vargs, HChar *);
1027                if (str == NULL)
1028                   str = "(null)";
1029                if (clo_xml)
1030                   ret += myvprintf_str_XML_simplistic(send, send_arg2, str);
1031                else
1032                   ret += myvprintf_str(send, send_arg2, flags, width, str,
1033                                        False);
1034             } else {
1035                /* %p */
1036                ret += 2;
1037                send('0',send_arg2);
1038                send('x',send_arg2);
1039                ret += myvprintf_int64(send, send_arg2, flags, 16, width, True,
1040                                       (ULong)((UWord)va_arg (vargs, void *)));
1041             }
1042             break;
1043          case 'x': /* %x */
1044          case 'X': /* %X */
1045             caps = toBool(format[i] == 'X');
1046             if (flags & VG_MSG_ALTFORMAT) {
1047                ret += 2;
1048                send('0',send_arg2);
1049                send('x',send_arg2);
1050             }
1051             if (is_sizet)
1052                ret += myvprintf_int64(send, send_arg2, flags, 16, width, False,
1053                                       (ULong)(va_arg (vargs, SizeT)));
1054             else if (is_long)
1055                ret += myvprintf_int64(send, send_arg2, flags, 16, width, caps,
1056                                       (ULong)(va_arg (vargs, ULong)));
1057             else
1058                ret += myvprintf_int64(send, send_arg2, flags, 16, width, caps,
1059                                       (ULong)(va_arg (vargs, UInt)));
1060             break;
1061          case 'c': /* %c */
1062             ret++;
1063             send(va_arg (vargs, int), send_arg2);
1064             break;
1065          case 's': case 'S': { /* %s */
1066             const HChar *str = va_arg (vargs, HChar *);
1067             if (str == NULL) str = "(null)";
1068             ret += myvprintf_str(send, send_arg2,
1069                                  flags, width, str, format[i]=='S');
1070             break;
1071          }
1072          case 'f': {
1073             /* Print a floating point number in the format x.y without
1074                any exponent. Capabilities are extremely limited, basically
1075                a joke, but good enough for our needs. */
1076             Double val = va_arg (vargs, Double);
1077             Bool is_negative = False;
1078             Int cnt;
1079 
1080             if (val < 0.0) {
1081                is_negative = True;
1082                val = - val;
1083             }
1084             /* If the integral part of the floating point number cannot be
1085                represented by an ULONG_MAX, print '*' characters */
1086             if (val > (Double)(~0ULL)) {
1087                if (width == 0) width = 6;    // say
1088                for (cnt = 0; cnt < width; ++cnt)
1089                   send('*', send_arg2);
1090                ret += width;
1091                break;
1092             }
1093             /* The integral part of the floating point number is representable
1094                by an ULong. */
1095             ULong ipval = val;
1096             Double frac = val - ipval;
1097 
1098             if (precision == -1) precision = 6;   // say
1099 
1100             /* Silently limit the precision to 10 digits. */
1101             if (precision > 10) precision = 10;
1102 
1103             /* Determine fractional part, possibly round up */
1104             ULong factor = 1;
1105             for (cnt = 0; cnt < precision; ++cnt)
1106                factor *= 10;
1107             ULong frval = frac * factor;
1108             if ((frac * factor - frval) > 0.5)    // round up
1109                frval += 1;
1110             /* Check rounding. */
1111             if (frval == factor)
1112                ipval += 1;
1113             frval %= factor;
1114 
1115             /* Find out how many characters are needed to print the number */
1116 
1117             /* The integral part... */
1118             UInt ipwidth, num_digit = 1;   // at least one digit
1119             ULong x, old_x = 0;
1120             for (x = 10; ; old_x = x, x *= 10, ++num_digit) {
1121                if (x <= old_x) break;    // overflow occurred
1122                if (ipval < x) break;
1123             }
1124             ipwidth = num_digit;   // width of integral part.
1125             if (is_negative) ++num_digit;
1126             if (precision != 0)
1127                num_digit += 1 + precision;
1128 
1129             // Print the number
1130 
1131             // Fill in blanks on the left
1132             if (num_digit < width && (flags & VG_MSG_LJUSTIFY) == 0) {
1133                for (cnt = 0; cnt < width - num_digit; ++cnt)
1134                   send(' ', send_arg2);
1135                ret += width - num_digit;
1136             }
1137             // Sign, maybe
1138             if (is_negative) {
1139                send('-', send_arg2);
1140                ret += 1;
1141             }
1142             // Integral part
1143             ret += myvprintf_int64(send, send_arg2, 0, 10, ipwidth, False,
1144                                    ipval);
1145             // Decimal point and fractional part
1146             if (precision != 0) {
1147                send('.', send_arg2);
1148                ret += 1;
1149 
1150                ret += myvprintf_int64(send, send_arg2, VG_MSG_ZJUSTIFY, 10,
1151                                       precision, False, frval);
1152             }
1153             // Fill in blanks on the right
1154             if (num_digit < width && (flags & VG_MSG_LJUSTIFY) != 0) {
1155                for (cnt = 0; cnt < width - num_digit; ++cnt)
1156                   send(' ', send_arg2);
1157                ret += width - num_digit;
1158             }
1159             break;
1160          }
1161 
1162 //         case 'y': { /* %y - print symbol */
1163 //            Addr a = va_arg(vargs, Addr);
1164 //
1165 //            HChar *name;
1166 // 	      if (VG_(get_fnname_w_offset)(a, &name)) {
1167 //               HChar buf[1 + VG_strlen(name) + 1 + 1];
1168 // 	         if (flags & VG_MSG_PAREN) {
1169 //                  VG_(sprintf)(str, "(%s)", name):
1170 // 	         } else {
1171 //                  VG_(sprintf)(str, "%s", name):
1172 //               }
1173 // 	         ret += myvprintf_str(send, flags, width, buf, 0);
1174 // 	      }
1175 //            break;
1176 //         }
1177          default:
1178             break;
1179       }
1180    }
1181    return ret;
1182 }
1183 
1184 
1185 /*------------------------------------------------------------*/
1186 /*--- Debuglog stuff.                                      ---*/
1187 /*------------------------------------------------------------*/
1188 
1189 /* Only print messages whose stated level is less than or equal to
1190    this.  By default, it makes this entire subsystem silent. */
1191 
1192 static Int loglevel = 0;
1193 
1194 /* Module startup. */
1195 /* EXPORTED */
VG_(debugLog_startup)1196 void VG_(debugLog_startup) ( Int level, const HChar* who )
1197 {
1198    if (level < 0)  level = 0;
1199    if (level > 10) level = 10;
1200    loglevel = level;
1201    VG_(debugLog)(1, "debuglog",
1202                  "DebugLog system started by %s, "
1203                  "level %d logging requested\n",
1204                  who, loglevel);
1205 }
1206 
1207 /* Get the logging threshold level, as set by the most recent call to
1208    VG_(debugLog_startup), or zero if there have been no such calls so
1209    far. */
1210 /* EXPORTED */
VG_(debugLog_getLevel)1211 Int VG_(debugLog_getLevel) ( void )
1212 {
1213    return loglevel;
1214 }
1215 
1216 
1217 /* ------------ */
1218 
1219 typedef
1220    struct {
1221       HChar buf[100];
1222       Int   n;
1223    }
1224    printf_buf;
1225 
add_to_buf(HChar c,void * p)1226 static void add_to_buf ( HChar c, void* p )
1227 {
1228    printf_buf* buf = (printf_buf*)p;
1229 
1230    if (buf->n >= 100-10 /*paranoia*/ ) {
1231       emit( buf->buf, local_strlen(buf->buf) );
1232       buf->n = 0;
1233       buf->buf[buf->n] = 0;
1234    }
1235    buf->buf[buf->n++] = c;
1236    buf->buf[buf->n] = 0;
1237 }
1238 
1239 /* Send a logging message.  Nothing is output unless 'level'
1240    is <= the current loglevel. */
1241 /* EXPORTED */
VG_(debugLog)1242 void VG_(debugLog) ( Int level, const HChar* modulename,
1243                                 const HChar* format, ... )
1244 {
1245    UInt pid;
1246    Int indent, depth, i;
1247    va_list vargs;
1248    printf_buf buf;
1249 
1250    if (level > loglevel)
1251       return;
1252 
1253    indent = 2*level - 1;
1254    if (indent < 1) indent = 1;
1255 
1256    buf.n = 0;
1257    buf.buf[0] = 0;
1258    pid = local_sys_getpid();
1259 
1260    // Print one '>' in front of the messages for each level of self-hosting
1261    // being performed.
1262    depth = RUNNING_ON_VALGRIND;
1263    for (i = 0; i < depth; i++) {
1264       (void)myvprintf_str ( add_to_buf, &buf, 0, 1, ">", False );
1265    }
1266 
1267    (void)myvprintf_str ( add_to_buf, &buf, 0, 2, "--", False );
1268    (void)myvprintf_int64 ( add_to_buf, &buf, 0, 10, 1, False, (ULong)pid );
1269    (void)myvprintf_str ( add_to_buf, &buf, 0, 1, ":", False );
1270    (void)myvprintf_int64 ( add_to_buf, &buf, 0, 10, 1, False, (ULong)level );
1271    (void)myvprintf_str ( add_to_buf, &buf, 0, 1, ":", False );
1272    (void)myvprintf_str ( add_to_buf, &buf, 0, 8, modulename, False );
1273    (void)myvprintf_str ( add_to_buf, &buf, 0, indent, "", False );
1274 
1275    va_start(vargs,format);
1276 
1277    (void) VG_(debugLog_vprintf) ( add_to_buf, &buf, format, vargs );
1278 
1279    if (buf.n > 0) {
1280       emit( buf.buf, local_strlen(buf.buf) );
1281    }
1282 
1283    va_end(vargs);
1284 }
1285 
1286 
1287 
1288 /*--------------------------------------------------------------------*/
1289 /*--- end                                           m_debuglog.c ---*/
1290 /*--------------------------------------------------------------------*/
1291