blob: bb9aa1b3025f2a09ba9dab0eb0348d5db51ebeaf [file] [log] [blame]
florian227a1ec2014-12-12 19:32:10 +00001/* -*- mode: C; c-basic-offset: 3; -*- */
sewardj1cf558c2005-04-25 01:36:56 +00002
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
Elliott Hughesed398002017-06-21 14:41:24 -070011 Copyright (C) 2000-2017 Julian Seward
sewardj1cf558c2005-04-25 01:36:56 +000012 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*/
sewardj1cf558c2005-04-25 01:36:56 +000046
njnc7561b92005-06-19 01:24:32 +000047/* This module is also notable because it is linked into both
48 stage1 and stage2. */
49
njnf76d27a2009-05-28 01:53:07 +000050/* 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
njnc7561b92005-06-19 01:24:32 +000055#include "pub_core_basics.h" /* basic types */
sewardj17edf032006-10-17 01:53:34 +000056#include "pub_core_vkiscnums.h" /* for syscall numbers */
njnc7561b92005-06-19 01:24:32 +000057#include "pub_core_debuglog.h" /* our own iface */
florian1a046d52013-09-16 20:56:35 +000058#include "pub_core_clreq.h" /* for RUNNING_ON_VALGRIND */
sewardj8eb8bab2015-07-21 14:44:28 +000059#if defined(VGO_solaris)
60#include "pub_core_vki.h" /* for EINTR and ERESTART */
61#endif
sewardj1cf558c2005-04-25 01:36:56 +000062
bartdb4384e2011-10-11 18:49:35 +000063static Bool clo_xml;
64
65void VG_(debugLog_setXml)(Bool xml)
66{
67 clo_xml = xml;
68}
69
sewardj1cf558c2005-04-25 01:36:56 +000070/*------------------------------------------------------------*/
71/*--- Stuff to make us completely independent. ---*/
72/*------------------------------------------------------------*/
73
sewardj2c48c7b2005-11-29 13:05:56 +000074/* ----- Platform-specifics ----- */
sewardj1cf558c2005-04-25 01:36:56 +000075
sewardj21c6d0f2005-05-02 10:33:44 +000076#if defined(VGP_x86_linux)
sewardj1cf558c2005-04-25 01:36:56 +000077
floriandbb35842012-10-27 18:39:11 +000078static UInt local_sys_write_stderr ( const HChar* buf, Int n )
sewardj1cf558c2005-04-25 01:36:56 +000079{
bartdf0c09e2012-01-30 15:07:20 +000080 Int result;
81
tom311400b2005-04-27 08:58:53 +000082 __asm__ volatile (
philippe5d5dd8e2012-08-05 00:08:25 +000083 "pushl %%ebx\n"
sewardj17edf032006-10-17 01:53:34 +000084 "movl $"VG_STRINGIFY(__NR_write)", %%eax\n" /* %eax = __NR_write */
njn5ed05a52009-05-20 06:59:19 +000085 "movl $2, %%ebx\n" /* %ebx = stderr */
sewardj55c43762006-04-28 21:01:33 +000086 "int $0x80\n" /* write(stderr, buf, n) */
philippe5d5dd8e2012-08-05 00:08:25 +000087 "popl %%ebx\n"
bartdf0c09e2012-01-30 15:07:20 +000088 : /*wr*/ "=a" (result)
89 : /*rd*/ "c" (buf), "d" (n)
philippe5d5dd8e2012-08-05 00:08:25 +000090 : /*trash*/ "edi", "memory", "cc"
sewardjd4d203b2005-04-27 23:17:48 +000091 );
bartdf0c09e2012-01-30 15:07:20 +000092
93 return result >= 0 ? result : -1;
sewardj1cf558c2005-04-25 01:36:56 +000094}
95
96static UInt local_sys_getpid ( void )
97{
98 UInt __res;
tom311400b2005-04-27 08:58:53 +000099 __asm__ volatile (
sewardj17edf032006-10-17 01:53:34 +0000100 "movl $"VG_STRINGIFY(__NR_getpid)", %%eax\n" /* %eax = __NR_getpid */
tom311400b2005-04-27 08:58:53 +0000101 "int $0x80\n" /* getpid() */
102 "movl %%eax, %0\n" /* set __res = eax */
sewardjd4d203b2005-04-27 23:17:48 +0000103 : "=mr" (__res)
104 :
105 : "eax" );
sewardj1cf558c2005-04-25 01:36:56 +0000106 return __res;
107}
108
sewardj21c6d0f2005-05-02 10:33:44 +0000109#elif defined(VGP_amd64_linux)
sewardjf0c12502014-01-12 12:54:00 +0000110
sewardj7337f922006-05-26 11:31:15 +0000111__attribute__((noinline))
floriandbb35842012-10-27 18:39:11 +0000112static UInt local_sys_write_stderr ( const HChar* buf, Int n )
sewardj601371a2005-04-25 16:21:17 +0000113{
sewardj17edf032006-10-17 01:53:34 +0000114 volatile Long block[2];
sewardj7337f922006-05-26 11:31:15 +0000115 block[0] = (Long)buf;
116 block[1] = n;
tomc6121862005-04-27 09:23:02 +0000117 __asm__ volatile (
sewardj7337f922006-05-26 11:31:15 +0000118 "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 */
sewardj17edf032006-10-17 01:53:34 +0000122 "movq $"VG_STRINGIFY(__NR_write)", %%rax\n" /* rax = __NR_write */
sewardj7337f922006-05-26 11:31:15 +0000123 "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*/
sewardjf068f192011-04-26 07:52:44 +0000132 : /*rd*/ "r" (block)
sewardj7337f922006-05-26 11:31:15 +0000133 : /*trash*/ "rax", "rdi", "rsi", "rdx", "memory", "cc"
134 );
135 if (block[0] < 0)
136 block[0] = -1;
137 return (UInt)block[0];
sewardj601371a2005-04-25 16:21:17 +0000138}
139
140static UInt local_sys_getpid ( void )
141{
tomc6121862005-04-27 09:23:02 +0000142 UInt __res;
143 __asm__ volatile (
sewardj17edf032006-10-17 01:53:34 +0000144 "movq $"VG_STRINGIFY(__NR_getpid)", %%rax\n" /* %rax = __NR_getpid */
tomc6121862005-04-27 09:23:02 +0000145 "syscall\n" /* getpid() */
146 "movl %%eax, %0\n" /* set __res = %eax */
147 : "=mr" (__res)
148 :
149 : "rax" );
150 return __res;
sewardj601371a2005-04-25 16:21:17 +0000151}
sewardj1cf558c2005-04-25 01:36:56 +0000152
cerion85665ca2005-06-20 15:51:07 +0000153#elif defined(VGP_ppc32_linux)
154
floriandbb35842012-10-27 18:39:11 +0000155static UInt local_sys_write_stderr ( const HChar* buf, Int n )
cerion85665ca2005-06-20 15:51:07 +0000156{
sewardj17edf032006-10-17 01:53:34 +0000157 volatile Int block[2];
sewardja2699582006-05-22 13:04:42 +0000158 block[0] = (Int)buf;
159 block[1] = n;
cerion85665ca2005-06-20 15:51:07 +0000160 __asm__ volatile (
sewardja2699582006-05-22 13:04:42 +0000161 "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 */
sewardj17edf032006-10-17 01:53:34 +0000164 "li 0,"VG_STRINGIFY(__NR_write)"\n\t" /* set %r0 = __NR_write */
sewardja2699582006-05-22 13:04:42 +0000165 "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];
cerion85665ca2005-06-20 15:51:07 +0000180}
181
182static UInt local_sys_getpid ( void )
183{
sewardja2699582006-05-22 13:04:42 +0000184 register UInt __res __asm__ ("r3");
185 __asm__ volatile (
186 "li 0, %1\n\t"
187 "sc"
188 : "=&r" (__res)
sewardj17edf032006-10-17 01:53:34 +0000189 : "i" (__NR_getpid)
sewardja2699582006-05-22 13:04:42 +0000190 : "cc","memory","cr0","ctr",
191 "r0","r2","r4","r5","r6","r7","r8","r9","r10","r11","r12"
192 );
cerion85665ca2005-06-20 15:51:07 +0000193 return __res;
194}
195
carllcae0cc22014-08-07 23:17:29 +0000196#elif defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux)
sewardj2c48c7b2005-11-29 13:05:56 +0000197
floriandbb35842012-10-27 18:39:11 +0000198static UInt local_sys_write_stderr ( const HChar* buf, Int n )
sewardj2c48c7b2005-11-29 13:05:56 +0000199{
sewardj17edf032006-10-17 01:53:34 +0000200 volatile Long block[2];
sewardja2699582006-05-22 13:04:42 +0000201 block[0] = (Long)buf;
202 block[1] = (Long)n;
sewardj2c48c7b2005-11-29 13:05:56 +0000203 __asm__ volatile (
sewardja2699582006-05-22 13:04:42 +0000204 "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 */
sewardj17edf032006-10-17 01:53:34 +0000207 "li 0,"VG_STRINGIFY(__NR_write)"\n\t" /* %r0 = __NR_write */
sewardja2699582006-05-22 13:04:42 +0000208 "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",
Elliott Hughesed398002017-06-21 14:41:24 -0700218 "r0","r3","r4","r5","r6","r7","r8","r9","r10","r11","r12"
sewardja2699582006-05-22 13:04:42 +0000219 );
220 if (block[0] < 0)
221 block[0] = -1;
222 return (UInt)(Int)block[0];
sewardj2c48c7b2005-11-29 13:05:56 +0000223}
224
225static UInt local_sys_getpid ( void )
226{
sewardja2699582006-05-22 13:04:42 +0000227 register ULong __res __asm__ ("r3");
228 __asm__ volatile (
229 "li 0, %1\n\t"
230 "sc"
231 : "=&r" (__res)
sewardj17edf032006-10-17 01:53:34 +0000232 : "i" (__NR_getpid)
sewardja2699582006-05-22 13:04:42 +0000233 : "cc","memory","cr0","ctr",
Elliott Hughesed398002017-06-21 14:41:24 -0700234 "r0","r4","r5","r6","r7","r8","r9","r10","r11","r12"
sewardja2699582006-05-22 13:04:42 +0000235 );
236 return (UInt)__res;
sewardj2c48c7b2005-11-29 13:05:56 +0000237}
238
sewardj59570ff2010-01-01 11:59:33 +0000239#elif defined(VGP_arm_linux)
240
floriandbb35842012-10-27 18:39:11 +0000241static UInt local_sys_write_stderr ( const HChar* buf, Int n )
sewardj59570ff2010-01-01 11:59:33 +0000242{
243 volatile Int block[2];
244 block[0] = (Int)buf;
245 block[1] = n;
246 __asm__ volatile (
sewardj188a6d72010-08-26 09:40:37 +0000247 "mov r0, #2\n\t" /* stderr */
248 "ldr r1, [%0]\n\t" /* buf */
249 "ldr r2, [%0, #4]\n\t" /* n */
sewardj3143d2d2015-02-11 00:41:48 +0000250 "push {r6,r7}\n\t"
sewardj59570ff2010-01-01 11:59:33 +0000251 "mov r7, #"VG_STRINGIFY(__NR_write)"\n\t"
252 "svc 0x0\n" /* write() */
sewardj3143d2d2015-02-11 00:41:48 +0000253 "pop {r6,r7}\n\t"
sewardj59570ff2010-01-01 11:59:33 +0000254 "str r0, [%0]\n\t"
255 :
256 : "r" (block)
sewardj3143d2d2015-02-11 00:41:48 +0000257 : "r0","r1","r2"
sewardj59570ff2010-01-01 11:59:33 +0000258 );
259 if (block[0] < 0)
260 block[0] = -1;
261 return (UInt)block[0];
262}
263
264static UInt local_sys_getpid ( void )
265{
266 UInt __res;
267 __asm__ volatile (
sewardj3143d2d2015-02-11 00:41:48 +0000268 "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"
sewardj59570ff2010-01-01 11:59:33 +0000273 : "=r" (__res)
274 :
sewardj3143d2d2015-02-11 00:41:48 +0000275 : "r0" );
sewardj59570ff2010-01-01 11:59:33 +0000276 return __res;
277}
278
sewardjf0c12502014-01-12 12:54:00 +0000279#elif defined(VGP_arm64_linux)
280
281static 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
302static 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
njnf76d27a2009-05-28 01:53:07 +0000315#elif defined(VGP_x86_darwin)
316
njn1a1e95c2009-06-03 06:50:06 +0000317/* 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'). */
njnf76d27a2009-05-28 01:53:07 +0000321__attribute__((noinline))
floriandbb35842012-10-27 18:39:11 +0000322static UInt local_sys_write_stderr ( const HChar* buf, Int n )
njnf76d27a2009-05-28 01:53:07 +0000323{
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
348static 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))
floriandbb35842012-10-27 18:39:11 +0000364static UInt local_sys_write_stderr ( const HChar* buf, Int n )
njnf76d27a2009-05-28 01:53:07 +0000365{
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 */
njn1a1e95c2009-06-03 06:50:06 +0000371 "movl $"VG_STRINGIFY(VG_DARWIN_SYSNO_FOR_KERNEL(__NR_write_nocancel))
njnf76d27a2009-05-28 01:53:07 +0000372 ", %%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
384static UInt local_sys_getpid ( void )
385{
386 UInt __res;
387 __asm__ volatile (
njn1a1e95c2009-06-03 06:50:06 +0000388 "movl $"VG_STRINGIFY(VG_DARWIN_SYSNO_FOR_KERNEL(__NR_getpid))", %%eax\n"
njnf76d27a2009-05-28 01:53:07 +0000389 "syscall\n" /* getpid() */
390 "movl %%eax, %0\n" /* set __res = eax */
391 : "=mr" (__res)
392 :
393 : "rax", "rcx", "cc" );
394 return __res;
395}
396
sewardjb5b87402011-03-07 16:05:35 +0000397#elif defined(VGP_s390x_linux)
sewardjf0c12502014-01-12 12:54:00 +0000398
floriandbb35842012-10-27 18:39:11 +0000399static UInt local_sys_write_stderr ( const HChar* buf, Int n )
sewardjb5b87402011-03-07 16:05:35 +0000400{
floriandbb35842012-10-27 18:39:11 +0000401 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");
sewardjb5b87402011-03-07 16:05:35 +0000405 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
422static 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
sewardj5db15402012-06-07 09:13:21 +0000439#elif defined(VGP_mips32_linux)
sewardjf0c12502014-01-12 12:54:00 +0000440
floriandbb35842012-10-27 18:39:11 +0000441static UInt local_sys_write_stderr ( const HChar* buf, Int n )
sewardj5db15402012-06-07 09:13:21 +0000442{
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
463static 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
petarj4df0bfc2013-02-27 23:17:33 +0000477#elif defined(VGP_mips64_linux)
sewardjf0c12502014-01-12 12:54:00 +0000478
petarj4df0bfc2013-02-27 23:17:33 +0000479static 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
501static 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}
zliu62cee7a2015-04-15 02:33:09 +0000514
sewardj8eb8bab2015-07-21 14:44:28 +0000515#elif defined(VGP_x86_solaris)
516static 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
548static 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)
565static 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
590static 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
sewardj1cf558c2005-04-25 01:36:56 +0000606#else
sewardj21c6d0f2005-05-02 10:33:44 +0000607# error Unknown platform
sewardj1cf558c2005-04-25 01:36:56 +0000608#endif
609
610
611/* ----- generic ----- */
612
613/* strlen, so we don't need m_libc */
614static Int local_strlen ( const HChar* str )
615{
616 Int i = 0;
617 while (str[i] != 0) i++;
618 return i;
619}
620
621static 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*/
floriandbb35842012-10-27 18:39:11 +0000631static void emit ( const HChar* buf, Int n )
sewardj1cf558c2005-04-25 01:36:56 +0000632{
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) */
barta0b6b2c2008-07-07 06:49:24 +0000659#define VG_MSG_ALTFORMAT 32 /* Convert the value to alternate format */
sewardj1cf558c2005-04-25 01:36:56 +0000660
661/* Copy a string into the buffer. */
662static
663UInt myvprintf_str ( void(*send)(HChar,void*),
664 void* send_arg2,
665 Int flags,
666 Int width,
floriandbb35842012-10-27 18:39:11 +0000667 const HChar* str,
sewardj1cf558c2005-04-25 01:36:56 +0000668 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;
florian866862a2014-12-13 18:35:00 +0000690 if (! (flags & VG_MSG_LJUSTIFY)) {
sewardj1cf558c2005-04-25 01:36:56 +0000691 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);
florian866862a2014-12-13 18:35:00 +0000698 if (flags & VG_MSG_LJUSTIFY) {
sewardj1cf558c2005-04-25 01:36:56 +0000699 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
sewardjdaf77af2005-07-19 14:17:37 +0000709/* Copy a string into the buffer, escaping bad XML chars. */
710static
711UInt myvprintf_str_XML_simplistic ( void(*send)(HChar,void*),
712 void* send_arg2,
floriandbb35842012-10-27 18:39:11 +0000713 const HChar* str )
sewardjdaf77af2005-07-19 14:17:37 +0000714{
715 UInt ret = 0;
716 Int i;
717 Int len = local_strlen(str);
floriandbb35842012-10-27 18:39:11 +0000718 const HChar* alt;
sewardjdaf77af2005-07-19 14:17:37 +0000719
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
sewardj1cf558c2005-04-25 01:36:56 +0000744/* 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 */
750static
751UInt myvprintf_int64 ( void(*send)(HChar,void*),
752 void* send_arg2,
753 Int flags,
754 Int base,
755 Int width,
sewardja44b15f2007-02-16 14:10:24 +0000756 Bool capitalised,
sewardj1cf558c2005-04-25 01:36:56 +0000757 ULong p )
758{
florian866862a2014-12-13 18:35:00 +0000759 /* 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];
sewardj1cf558c2005-04-25 01:36:56 +0000763 Int ind = 0;
764 Int i, nc = 0;
765 Bool neg = False;
floriandbb35842012-10-27 18:39:11 +0000766 const HChar* digits = capitalised ? "0123456789ABCDEF" : "0123456789abcdef";
sewardj1cf558c2005-04-25 01:36:56 +0000767 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++) {
sewardj1cf558c2005-04-25 01:36:56 +0000797 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 */
819UInt
820VG_(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;
florian227a1ec2014-12-12 19:32:10 +0000830 Int width, precision;
njn68e46592005-08-26 19:42:27 +0000831 Int n_ls = 0;
florianaf930422014-12-29 19:06:40 +0000832 Bool is_long, is_sizet, caps;
sewardj1cf558c2005-04-25 01:36:56 +0000833
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] == '%') {
njn02bc4b82005-05-15 17:28:26 +0000850 /* '%%' is replaced by '%'. */
sewardj1cf558c2005-04-25 01:36:56 +0000851 send('%', send_arg2);
852 ret++;
853 continue;
854 }
855 flags = 0;
njn68e46592005-08-26 19:42:27 +0000856 n_ls = 0;
sewardj1cf558c2005-04-25 01:36:56 +0000857 width = 0; /* length of the field. */
florian227a1ec2014-12-12 19:32:10 +0000858 precision = -1; /* unspecified precision */
barta0b6b2c2008-07-07 06:49:24 +0000859 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 }
sewardj1cf558c2005-04-25 01:36:56 +0000884 i++;
885 }
barta0b6b2c2008-07-07 06:49:24 +0000886 parse_fieldwidth:
sewardj1cf558c2005-04-25 01:36:56 +0000887 /* Compute the field length. */
florian227a1ec2014-12-12 19:32:10 +0000888 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 }
sewardj1cf558c2005-04-25 01:36:56 +0000911 }
florianaf930422014-12-29 19:06:40 +0000912
913 is_sizet = False;
914 if (format[i] == 'z') {
915 is_sizet = True;
florian93cb28b2015-03-20 16:45:02 +0000916 ++i;
florianaf930422014-12-29 19:06:40 +0000917 } else {
918 while (format[i] == 'l') {
919 i++;
920 n_ls++;
921 }
sewardj1cf558c2005-04-25 01:36:56 +0000922 }
923
njn68e46592005-08-26 19:42:27 +0000924 // %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
sewardj1cf558c2005-04-25 01:36:56 +0000931 switch (format[i]) {
bart042257f2009-07-26 08:40:17 +0000932 case 'o': /* %o */
933 if (flags & VG_MSG_ALTFORMAT) {
934 ret += 2;
935 send('0',send_arg2);
936 }
florianaf930422014-12-29 19:06:40 +0000937 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)
bart042257f2009-07-26 08:40:17 +0000941 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;
sewardj1cf558c2005-04-25 01:36:56 +0000947 case 'd': /* %d */
948 flags |= VG_MSG_SIGNED;
949 if (is_long)
sewardja44b15f2007-02-16 14:10:24 +0000950 ret += myvprintf_int64(send, send_arg2, flags, 10, width, False,
sewardj1cf558c2005-04-25 01:36:56 +0000951 (ULong)(va_arg (vargs, Long)));
952 else
sewardja44b15f2007-02-16 14:10:24 +0000953 ret += myvprintf_int64(send, send_arg2, flags, 10, width, False,
sewardj1cf558c2005-04-25 01:36:56 +0000954 (ULong)(va_arg (vargs, Int)));
955 break;
956 case 'u': /* %u */
florianaf930422014-12-29 19:06:40 +0000957 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)
sewardja44b15f2007-02-16 14:10:24 +0000961 ret += myvprintf_int64(send, send_arg2, flags, 10, width, False,
sewardj1cf558c2005-04-25 01:36:56 +0000962 (ULong)(va_arg (vargs, ULong)));
963 else
sewardja44b15f2007-02-16 14:10:24 +0000964 ret += myvprintf_int64(send, send_arg2, flags, 10, width, False,
sewardj1cf558c2005-04-25 01:36:56 +0000965 (ULong)(va_arg (vargs, UInt)));
966 break;
bartb3af9cf2011-10-06 19:08:37 +0000967 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 */
florian6bd9dc12012-11-23 16:17:43 +0000972 const HChar *str = va_arg (vargs, HChar *);
floriandbb35842012-10-27 18:39:11 +0000973 if (str == NULL)
bartb3af9cf2011-10-06 19:08:37 +0000974 str = "(null)";
975 ret += myvprintf_str_XML_simplistic(send, send_arg2, str);
bartdb4384e2011-10-11 18:49:35 +0000976 } else if (format[i+1] == 's') {
977 i++;
978 /* %ps, synonym for %s with --xml=no / %pS with --xml=yes */
florian6bd9dc12012-11-23 16:17:43 +0000979 const HChar *str = va_arg (vargs, HChar *);
floriandbb35842012-10-27 18:39:11 +0000980 if (str == NULL)
bartdb4384e2011-10-11 18:49:35 +0000981 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);
bartb3af9cf2011-10-06 19:08:37 +0000987 } 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 }
sewardj1cf558c2005-04-25 01:36:56 +0000995 break;
996 case 'x': /* %x */
sewardja44b15f2007-02-16 14:10:24 +0000997 case 'X': /* %X */
998 caps = toBool(format[i] == 'X');
barta0b6b2c2008-07-07 06:49:24 +0000999 if (flags & VG_MSG_ALTFORMAT) {
1000 ret += 2;
1001 send('0',send_arg2);
1002 send('x',send_arg2);
1003 }
florianaf930422014-12-29 19:06:40 +00001004 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)
sewardja44b15f2007-02-16 14:10:24 +00001008 ret += myvprintf_int64(send, send_arg2, flags, 16, width, caps,
sewardj1cf558c2005-04-25 01:36:56 +00001009 (ULong)(va_arg (vargs, ULong)));
1010 else
sewardja44b15f2007-02-16 14:10:24 +00001011 ret += myvprintf_int64(send, send_arg2, flags, 16, width, caps,
sewardj1cf558c2005-04-25 01:36:56 +00001012 (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 */
florian6bd9dc12012-11-23 16:17:43 +00001019 const HChar *str = va_arg (vargs, HChar *);
floriandbb35842012-10-27 18:39:11 +00001020 if (str == NULL) str = "(null)";
sewardj1cf558c2005-04-25 01:36:56 +00001021 ret += myvprintf_str(send, send_arg2,
1022 flags, width, str, format[i]=='S');
1023 break;
1024 }
florian227a1ec2014-12-12 19:32:10 +00001025 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
floriane72941d2015-05-20 15:14:00 +00001056 /* 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)
florian227a1ec2014-12-12 19:32:10 +00001065 ipval += 1;
floriane72941d2015-05-20 15:14:00 +00001066 frval %= factor;
florian227a1ec2014-12-12 19:32:10 +00001067
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
florian227a1ec2014-12-12 19:32:10 +00001103 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 }
sewardjdaf77af2005-07-19 14:17:37 +00001114
sewardj1cf558c2005-04-25 01:36:56 +00001115// case 'y': { /* %y - print symbol */
sewardj1cf558c2005-04-25 01:36:56 +00001116// Addr a = va_arg(vargs, Addr);
1117//
florian46cc0452014-10-25 19:20:38 +00001118// 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):
sewardj1cf558c2005-04-25 01:36:56 +00001125// }
florian46cc0452014-10-25 19:20:38 +00001126// ret += myvprintf_str(send, flags, width, buf, 0);
1127// }
sewardj1cf558c2005-04-25 01:36:56 +00001128// 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
1145static Int loglevel = 0;
1146
sewardj1cf558c2005-04-25 01:36:56 +00001147/* Module startup. */
sewardj10759312005-05-30 23:52:47 +00001148/* EXPORTED */
floriandbb35842012-10-27 18:39:11 +00001149void VG_(debugLog_startup) ( Int level, const HChar* who )
sewardj1cf558c2005-04-25 01:36:56 +00001150{
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
sewardj10759312005-05-30 23:52:47 +00001160/* 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 */
1164Int VG_(debugLog_getLevel) ( void )
1165{
1166 return loglevel;
1167}
1168
1169
sewardj1cf558c2005-04-25 01:36:56 +00001170/* ------------ */
1171
1172typedef
1173 struct {
1174 HChar buf[100];
1175 Int n;
1176 }
1177 printf_buf;
1178
1179static 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 */
sewardj1cf558c2005-04-25 01:36:56 +00001195void VG_(debugLog) ( Int level, const HChar* modulename,
1196 const HChar* format, ... )
1197{
sewardjc7ffc942011-03-28 16:26:42 +00001198 UInt pid;
sewardj45f4e7c2005-09-27 19:20:21 +00001199 Int indent, depth, i;
sewardj1cf558c2005-04-25 01:36:56 +00001200 va_list vargs;
1201 printf_buf buf;
sewardja5ebfa92005-04-25 02:04:54 +00001202
sewardj1cf558c2005-04-25 01:36:56 +00001203 if (level > loglevel)
1204 return;
1205
sewardjd85feff2005-04-25 02:37:56 +00001206 indent = 2*level - 1;
sewardja5ebfa92005-04-25 02:04:54 +00001207 if (indent < 1) indent = 1;
1208
sewardj1cf558c2005-04-25 01:36:56 +00001209 buf.n = 0;
1210 buf.buf[0] = 0;
1211 pid = local_sys_getpid();
sewardj45f4e7c2005-09-27 19:20:21 +00001212
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
sewardja5ebfa92005-04-25 02:04:54 +00001220 (void)myvprintf_str ( add_to_buf, &buf, 0, 2, "--", False );
sewardja44b15f2007-02-16 14:10:24 +00001221 (void)myvprintf_int64 ( add_to_buf, &buf, 0, 10, 1, False, (ULong)pid );
sewardja5ebfa92005-04-25 02:04:54 +00001222 (void)myvprintf_str ( add_to_buf, &buf, 0, 1, ":", False );
sewardja44b15f2007-02-16 14:10:24 +00001223 (void)myvprintf_int64 ( add_to_buf, &buf, 0, 10, 1, False, (ULong)level );
sewardja5ebfa92005-04-25 02:04:54 +00001224 (void)myvprintf_str ( add_to_buf, &buf, 0, 1, ":", False );
floriandbb35842012-10-27 18:39:11 +00001225 (void)myvprintf_str ( add_to_buf, &buf, 0, 8, modulename, False );
sewardja5ebfa92005-04-25 02:04:54 +00001226 (void)myvprintf_str ( add_to_buf, &buf, 0, indent, "", False );
sewardj1cf558c2005-04-25 01:36:56 +00001227
1228 va_start(vargs,format);
1229
sewardjc7ffc942011-03-28 16:26:42 +00001230 (void) VG_(debugLog_vprintf) ( add_to_buf, &buf, format, vargs );
sewardj1cf558c2005-04-25 01:36:56 +00001231
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/*--------------------------------------------------------------------*/