blob: dc6e26d2e8735accd67b3a492fb1772a6a04e524 [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
sewardjb3a1e4b2015-08-21 11:32:26 +000011 Copyright (C) 2000-2015 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",
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];
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",
234 "r0","r2","r4","r5","r6","r7","r8","r9","r10","r11","r12"
235 );
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
sewardj112711a2015-04-10 12:30:09 +0000515#elif defined(VGP_tilegx_linux)
zliu62cee7a2015-04-15 02:33:09 +0000516
sewardj112711a2015-04-10 12:30:09 +0000517static 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;
zliu62cee7a2015-04-15 02:33:09 +0000522 Long __res = 0;
sewardj112711a2015-04-10 12:30:09 +0000523 __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
540static 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}
sewardjb5b87402011-03-07 16:05:35 +0000561
sewardj8eb8bab2015-07-21 14:44:28 +0000562#elif defined(VGP_x86_solaris)
563static 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
595static 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)
612static 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
637static 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
sewardj1cf558c2005-04-25 01:36:56 +0000653#else
sewardj21c6d0f2005-05-02 10:33:44 +0000654# error Unknown platform
sewardj1cf558c2005-04-25 01:36:56 +0000655#endif
656
657
658/* ----- generic ----- */
659
660/* strlen, so we don't need m_libc */
661static Int local_strlen ( const HChar* str )
662{
663 Int i = 0;
664 while (str[i] != 0) i++;
665 return i;
666}
667
668static 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*/
floriandbb35842012-10-27 18:39:11 +0000678static void emit ( const HChar* buf, Int n )
sewardj1cf558c2005-04-25 01:36:56 +0000679{
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) */
barta0b6b2c2008-07-07 06:49:24 +0000706#define VG_MSG_ALTFORMAT 32 /* Convert the value to alternate format */
sewardj1cf558c2005-04-25 01:36:56 +0000707
708/* Copy a string into the buffer. */
709static
710UInt myvprintf_str ( void(*send)(HChar,void*),
711 void* send_arg2,
712 Int flags,
713 Int width,
floriandbb35842012-10-27 18:39:11 +0000714 const HChar* str,
sewardj1cf558c2005-04-25 01:36:56 +0000715 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;
florian866862a2014-12-13 18:35:00 +0000737 if (! (flags & VG_MSG_LJUSTIFY)) {
sewardj1cf558c2005-04-25 01:36:56 +0000738 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);
florian866862a2014-12-13 18:35:00 +0000745 if (flags & VG_MSG_LJUSTIFY) {
sewardj1cf558c2005-04-25 01:36:56 +0000746 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
sewardjdaf77af2005-07-19 14:17:37 +0000756/* Copy a string into the buffer, escaping bad XML chars. */
757static
758UInt myvprintf_str_XML_simplistic ( void(*send)(HChar,void*),
759 void* send_arg2,
floriandbb35842012-10-27 18:39:11 +0000760 const HChar* str )
sewardjdaf77af2005-07-19 14:17:37 +0000761{
762 UInt ret = 0;
763 Int i;
764 Int len = local_strlen(str);
floriandbb35842012-10-27 18:39:11 +0000765 const HChar* alt;
sewardjdaf77af2005-07-19 14:17:37 +0000766
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
sewardj1cf558c2005-04-25 01:36:56 +0000791/* 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 */
797static
798UInt myvprintf_int64 ( void(*send)(HChar,void*),
799 void* send_arg2,
800 Int flags,
801 Int base,
802 Int width,
sewardja44b15f2007-02-16 14:10:24 +0000803 Bool capitalised,
sewardj1cf558c2005-04-25 01:36:56 +0000804 ULong p )
805{
florian866862a2014-12-13 18:35:00 +0000806 /* 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];
sewardj1cf558c2005-04-25 01:36:56 +0000810 Int ind = 0;
811 Int i, nc = 0;
812 Bool neg = False;
floriandbb35842012-10-27 18:39:11 +0000813 const HChar* digits = capitalised ? "0123456789ABCDEF" : "0123456789abcdef";
sewardj1cf558c2005-04-25 01:36:56 +0000814 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++) {
sewardj1cf558c2005-04-25 01:36:56 +0000844 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 */
866UInt
867VG_(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;
florian227a1ec2014-12-12 19:32:10 +0000877 Int width, precision;
njn68e46592005-08-26 19:42:27 +0000878 Int n_ls = 0;
florianaf930422014-12-29 19:06:40 +0000879 Bool is_long, is_sizet, caps;
sewardj1cf558c2005-04-25 01:36:56 +0000880
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] == '%') {
njn02bc4b82005-05-15 17:28:26 +0000897 /* '%%' is replaced by '%'. */
sewardj1cf558c2005-04-25 01:36:56 +0000898 send('%', send_arg2);
899 ret++;
900 continue;
901 }
902 flags = 0;
njn68e46592005-08-26 19:42:27 +0000903 n_ls = 0;
sewardj1cf558c2005-04-25 01:36:56 +0000904 width = 0; /* length of the field. */
florian227a1ec2014-12-12 19:32:10 +0000905 precision = -1; /* unspecified precision */
barta0b6b2c2008-07-07 06:49:24 +0000906 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 }
sewardj1cf558c2005-04-25 01:36:56 +0000931 i++;
932 }
barta0b6b2c2008-07-07 06:49:24 +0000933 parse_fieldwidth:
sewardj1cf558c2005-04-25 01:36:56 +0000934 /* Compute the field length. */
florian227a1ec2014-12-12 19:32:10 +0000935 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 }
sewardj1cf558c2005-04-25 01:36:56 +0000958 }
florianaf930422014-12-29 19:06:40 +0000959
960 is_sizet = False;
961 if (format[i] == 'z') {
962 is_sizet = True;
florian93cb28b2015-03-20 16:45:02 +0000963 ++i;
florianaf930422014-12-29 19:06:40 +0000964 } else {
965 while (format[i] == 'l') {
966 i++;
967 n_ls++;
968 }
sewardj1cf558c2005-04-25 01:36:56 +0000969 }
970
njn68e46592005-08-26 19:42:27 +0000971 // %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
sewardj1cf558c2005-04-25 01:36:56 +0000978 switch (format[i]) {
bart042257f2009-07-26 08:40:17 +0000979 case 'o': /* %o */
980 if (flags & VG_MSG_ALTFORMAT) {
981 ret += 2;
982 send('0',send_arg2);
983 }
florianaf930422014-12-29 19:06:40 +0000984 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)
bart042257f2009-07-26 08:40:17 +0000988 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;
sewardj1cf558c2005-04-25 01:36:56 +0000994 case 'd': /* %d */
995 flags |= VG_MSG_SIGNED;
996 if (is_long)
sewardja44b15f2007-02-16 14:10:24 +0000997 ret += myvprintf_int64(send, send_arg2, flags, 10, width, False,
sewardj1cf558c2005-04-25 01:36:56 +0000998 (ULong)(va_arg (vargs, Long)));
999 else
sewardja44b15f2007-02-16 14:10:24 +00001000 ret += myvprintf_int64(send, send_arg2, flags, 10, width, False,
sewardj1cf558c2005-04-25 01:36:56 +00001001 (ULong)(va_arg (vargs, Int)));
1002 break;
1003 case 'u': /* %u */
florianaf930422014-12-29 19:06:40 +00001004 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)
sewardja44b15f2007-02-16 14:10:24 +00001008 ret += myvprintf_int64(send, send_arg2, flags, 10, width, False,
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, 10, width, False,
sewardj1cf558c2005-04-25 01:36:56 +00001012 (ULong)(va_arg (vargs, UInt)));
1013 break;
bartb3af9cf2011-10-06 19:08:37 +00001014 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 */
florian6bd9dc12012-11-23 16:17:43 +00001019 const HChar *str = va_arg (vargs, HChar *);
floriandbb35842012-10-27 18:39:11 +00001020 if (str == NULL)
bartb3af9cf2011-10-06 19:08:37 +00001021 str = "(null)";
1022 ret += myvprintf_str_XML_simplistic(send, send_arg2, str);
bartdb4384e2011-10-11 18:49:35 +00001023 } else if (format[i+1] == 's') {
1024 i++;
1025 /* %ps, synonym for %s with --xml=no / %pS with --xml=yes */
florian6bd9dc12012-11-23 16:17:43 +00001026 const HChar *str = va_arg (vargs, HChar *);
floriandbb35842012-10-27 18:39:11 +00001027 if (str == NULL)
bartdb4384e2011-10-11 18:49:35 +00001028 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);
bartb3af9cf2011-10-06 19:08:37 +00001034 } 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 }
sewardj1cf558c2005-04-25 01:36:56 +00001042 break;
1043 case 'x': /* %x */
sewardja44b15f2007-02-16 14:10:24 +00001044 case 'X': /* %X */
1045 caps = toBool(format[i] == 'X');
barta0b6b2c2008-07-07 06:49:24 +00001046 if (flags & VG_MSG_ALTFORMAT) {
1047 ret += 2;
1048 send('0',send_arg2);
1049 send('x',send_arg2);
1050 }
florianaf930422014-12-29 19:06:40 +00001051 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)
sewardja44b15f2007-02-16 14:10:24 +00001055 ret += myvprintf_int64(send, send_arg2, flags, 16, width, caps,
sewardj1cf558c2005-04-25 01:36:56 +00001056 (ULong)(va_arg (vargs, ULong)));
1057 else
sewardja44b15f2007-02-16 14:10:24 +00001058 ret += myvprintf_int64(send, send_arg2, flags, 16, width, caps,
sewardj1cf558c2005-04-25 01:36:56 +00001059 (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 */
florian6bd9dc12012-11-23 16:17:43 +00001066 const HChar *str = va_arg (vargs, HChar *);
floriandbb35842012-10-27 18:39:11 +00001067 if (str == NULL) str = "(null)";
sewardj1cf558c2005-04-25 01:36:56 +00001068 ret += myvprintf_str(send, send_arg2,
1069 flags, width, str, format[i]=='S');
1070 break;
1071 }
florian227a1ec2014-12-12 19:32:10 +00001072 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
floriane72941d2015-05-20 15:14:00 +00001103 /* 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)
florian227a1ec2014-12-12 19:32:10 +00001112 ipval += 1;
floriane72941d2015-05-20 15:14:00 +00001113 frval %= factor;
florian227a1ec2014-12-12 19:32:10 +00001114
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
florian227a1ec2014-12-12 19:32:10 +00001150 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 }
sewardjdaf77af2005-07-19 14:17:37 +00001161
sewardj1cf558c2005-04-25 01:36:56 +00001162// case 'y': { /* %y - print symbol */
sewardj1cf558c2005-04-25 01:36:56 +00001163// Addr a = va_arg(vargs, Addr);
1164//
florian46cc0452014-10-25 19:20:38 +00001165// 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):
sewardj1cf558c2005-04-25 01:36:56 +00001172// }
florian46cc0452014-10-25 19:20:38 +00001173// ret += myvprintf_str(send, flags, width, buf, 0);
1174// }
sewardj1cf558c2005-04-25 01:36:56 +00001175// 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
1192static Int loglevel = 0;
1193
sewardj1cf558c2005-04-25 01:36:56 +00001194/* Module startup. */
sewardj10759312005-05-30 23:52:47 +00001195/* EXPORTED */
floriandbb35842012-10-27 18:39:11 +00001196void VG_(debugLog_startup) ( Int level, const HChar* who )
sewardj1cf558c2005-04-25 01:36:56 +00001197{
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
sewardj10759312005-05-30 23:52:47 +00001207/* 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 */
1211Int VG_(debugLog_getLevel) ( void )
1212{
1213 return loglevel;
1214}
1215
1216
sewardj1cf558c2005-04-25 01:36:56 +00001217/* ------------ */
1218
1219typedef
1220 struct {
1221 HChar buf[100];
1222 Int n;
1223 }
1224 printf_buf;
1225
1226static 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 */
sewardj1cf558c2005-04-25 01:36:56 +00001242void VG_(debugLog) ( Int level, const HChar* modulename,
1243 const HChar* format, ... )
1244{
sewardjc7ffc942011-03-28 16:26:42 +00001245 UInt pid;
sewardj45f4e7c2005-09-27 19:20:21 +00001246 Int indent, depth, i;
sewardj1cf558c2005-04-25 01:36:56 +00001247 va_list vargs;
1248 printf_buf buf;
sewardja5ebfa92005-04-25 02:04:54 +00001249
sewardj1cf558c2005-04-25 01:36:56 +00001250 if (level > loglevel)
1251 return;
1252
sewardjd85feff2005-04-25 02:37:56 +00001253 indent = 2*level - 1;
sewardja5ebfa92005-04-25 02:04:54 +00001254 if (indent < 1) indent = 1;
1255
sewardj1cf558c2005-04-25 01:36:56 +00001256 buf.n = 0;
1257 buf.buf[0] = 0;
1258 pid = local_sys_getpid();
sewardj45f4e7c2005-09-27 19:20:21 +00001259
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
sewardja5ebfa92005-04-25 02:04:54 +00001267 (void)myvprintf_str ( add_to_buf, &buf, 0, 2, "--", False );
sewardja44b15f2007-02-16 14:10:24 +00001268 (void)myvprintf_int64 ( add_to_buf, &buf, 0, 10, 1, False, (ULong)pid );
sewardja5ebfa92005-04-25 02:04:54 +00001269 (void)myvprintf_str ( add_to_buf, &buf, 0, 1, ":", False );
sewardja44b15f2007-02-16 14:10:24 +00001270 (void)myvprintf_int64 ( add_to_buf, &buf, 0, 10, 1, False, (ULong)level );
sewardja5ebfa92005-04-25 02:04:54 +00001271 (void)myvprintf_str ( add_to_buf, &buf, 0, 1, ":", False );
floriandbb35842012-10-27 18:39:11 +00001272 (void)myvprintf_str ( add_to_buf, &buf, 0, 8, modulename, False );
sewardja5ebfa92005-04-25 02:04:54 +00001273 (void)myvprintf_str ( add_to_buf, &buf, 0, indent, "", False );
sewardj1cf558c2005-04-25 01:36:56 +00001274
1275 va_start(vargs,format);
1276
sewardjc7ffc942011-03-28 16:26:42 +00001277 (void) VG_(debugLog_vprintf) ( add_to_buf, &buf, format, vargs );
sewardj1cf558c2005-04-25 01:36:56 +00001278
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/*--------------------------------------------------------------------*/