blob: 2657c3a3548501ddbca055b195f893f33bb61f7a [file] [log] [blame]
sewardj1cf558c2005-04-25 01:36:56 +00001
2/*--------------------------------------------------------------------*/
3/*--- Debug (not-for-user) logging; also vprintf. m_debuglog.c ---*/
4/*--------------------------------------------------------------------*/
5
6/*
7 This file is part of Valgrind, a dynamic binary instrumentation
8 framework.
9
sewardj0f157dd2013-10-18 14:27:36 +000010 Copyright (C) 2000-2013 Julian Seward
sewardj1cf558c2005-04-25 01:36:56 +000011 jseward@acm.org
12
13 This program is free software; you can redistribute it and/or
14 modify it under the terms of the GNU General Public License as
15 published by the Free Software Foundation; either version 2 of the
16 License, or (at your option) any later version.
17
18 This program is distributed in the hope that it will be useful, but
19 WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 General Public License for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software
25 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
26 02111-1307, USA.
27
28 The GNU General Public License is contained in the file COPYING.
29*/
30
31
32/* Performs low-level debug logging that can safely run immediately
33 after startup. To minimise the dependencies on any other parts of
34 the system, the only place the debug output may go is file
35 descriptor 2 (stderr).
36*/
37/* This is the first-initialised module in the entire system!
38 Therefore it is CRITICAL that it does not depend on any other code
39 running first. Hence only the following very limited includes. We
40 cannot depend (directly or indirectly) on any dynamic memory
41 allocation facilities, nor on the m_libc facilities, since the
42 latter depend on this module. DO NOT MESS WITH THESE INCLUDES
43 UNLESS YOU ARE 100% CERTAIN YOU UNDERSTAND THE CONSEQUENCES.
44*/
sewardj1cf558c2005-04-25 01:36:56 +000045
njnc7561b92005-06-19 01:24:32 +000046/* This module is also notable because it is linked into both
47 stage1 and stage2. */
48
njnf76d27a2009-05-28 01:53:07 +000049/* IMPORTANT: on Darwin it is essential to use the _nocancel versions
50 of syscalls rather than the vanilla version, if a _nocancel version
51 is available. See docs/internals/Darwin-notes.txt for the reason
52 why. */
53
njnc7561b92005-06-19 01:24:32 +000054#include "pub_core_basics.h" /* basic types */
sewardj17edf032006-10-17 01:53:34 +000055#include "pub_core_vkiscnums.h" /* for syscall numbers */
njnc7561b92005-06-19 01:24:32 +000056#include "pub_core_debuglog.h" /* our own iface */
florian1a046d52013-09-16 20:56:35 +000057#include "pub_core_clreq.h" /* for RUNNING_ON_VALGRIND */
sewardj1cf558c2005-04-25 01:36:56 +000058
bartdb4384e2011-10-11 18:49:35 +000059static Bool clo_xml;
60
61void VG_(debugLog_setXml)(Bool xml)
62{
63 clo_xml = xml;
64}
65
sewardj1cf558c2005-04-25 01:36:56 +000066/*------------------------------------------------------------*/
67/*--- Stuff to make us completely independent. ---*/
68/*------------------------------------------------------------*/
69
sewardj2c48c7b2005-11-29 13:05:56 +000070/* ----- Platform-specifics ----- */
sewardj1cf558c2005-04-25 01:36:56 +000071
sewardj21c6d0f2005-05-02 10:33:44 +000072#if defined(VGP_x86_linux)
sewardj1cf558c2005-04-25 01:36:56 +000073
floriandbb35842012-10-27 18:39:11 +000074static UInt local_sys_write_stderr ( const HChar* buf, Int n )
sewardj1cf558c2005-04-25 01:36:56 +000075{
bartdf0c09e2012-01-30 15:07:20 +000076 Int result;
77
tom311400b2005-04-27 08:58:53 +000078 __asm__ volatile (
philippe5d5dd8e2012-08-05 00:08:25 +000079 "pushl %%ebx\n"
sewardj17edf032006-10-17 01:53:34 +000080 "movl $"VG_STRINGIFY(__NR_write)", %%eax\n" /* %eax = __NR_write */
njn5ed05a52009-05-20 06:59:19 +000081 "movl $2, %%ebx\n" /* %ebx = stderr */
sewardj55c43762006-04-28 21:01:33 +000082 "int $0x80\n" /* write(stderr, buf, n) */
philippe5d5dd8e2012-08-05 00:08:25 +000083 "popl %%ebx\n"
bartdf0c09e2012-01-30 15:07:20 +000084 : /*wr*/ "=a" (result)
85 : /*rd*/ "c" (buf), "d" (n)
philippe5d5dd8e2012-08-05 00:08:25 +000086 : /*trash*/ "edi", "memory", "cc"
sewardjd4d203b2005-04-27 23:17:48 +000087 );
bartdf0c09e2012-01-30 15:07:20 +000088
89 return result >= 0 ? result : -1;
sewardj1cf558c2005-04-25 01:36:56 +000090}
91
92static UInt local_sys_getpid ( void )
93{
94 UInt __res;
tom311400b2005-04-27 08:58:53 +000095 __asm__ volatile (
sewardj17edf032006-10-17 01:53:34 +000096 "movl $"VG_STRINGIFY(__NR_getpid)", %%eax\n" /* %eax = __NR_getpid */
tom311400b2005-04-27 08:58:53 +000097 "int $0x80\n" /* getpid() */
98 "movl %%eax, %0\n" /* set __res = eax */
sewardjd4d203b2005-04-27 23:17:48 +000099 : "=mr" (__res)
100 :
101 : "eax" );
sewardj1cf558c2005-04-25 01:36:56 +0000102 return __res;
103}
104
sewardj21c6d0f2005-05-02 10:33:44 +0000105#elif defined(VGP_amd64_linux)
sewardjf0c12502014-01-12 12:54:00 +0000106
sewardj7337f922006-05-26 11:31:15 +0000107__attribute__((noinline))
floriandbb35842012-10-27 18:39:11 +0000108static UInt local_sys_write_stderr ( const HChar* buf, Int n )
sewardj601371a2005-04-25 16:21:17 +0000109{
sewardj17edf032006-10-17 01:53:34 +0000110 volatile Long block[2];
sewardj7337f922006-05-26 11:31:15 +0000111 block[0] = (Long)buf;
112 block[1] = n;
tomc6121862005-04-27 09:23:02 +0000113 __asm__ volatile (
sewardj7337f922006-05-26 11:31:15 +0000114 "subq $256, %%rsp\n" /* don't trash the stack redzone */
115 "pushq %%r15\n" /* r15 is callee-save */
116 "movq %0, %%r15\n" /* r15 = &block */
117 "pushq %%r15\n" /* save &block */
sewardj17edf032006-10-17 01:53:34 +0000118 "movq $"VG_STRINGIFY(__NR_write)", %%rax\n" /* rax = __NR_write */
sewardj7337f922006-05-26 11:31:15 +0000119 "movq $2, %%rdi\n" /* rdi = stderr */
120 "movq 0(%%r15), %%rsi\n" /* rsi = buf */
121 "movq 8(%%r15), %%rdx\n" /* rdx = n */
122 "syscall\n" /* write(stderr, buf, n) */
123 "popq %%r15\n" /* reestablish &block */
124 "movq %%rax, 0(%%r15)\n" /* block[0] = result */
125 "popq %%r15\n" /* restore r15 */
126 "addq $256, %%rsp\n" /* restore stack ptr */
127 : /*wr*/
sewardjf068f192011-04-26 07:52:44 +0000128 : /*rd*/ "r" (block)
sewardj7337f922006-05-26 11:31:15 +0000129 : /*trash*/ "rax", "rdi", "rsi", "rdx", "memory", "cc"
130 );
131 if (block[0] < 0)
132 block[0] = -1;
133 return (UInt)block[0];
sewardj601371a2005-04-25 16:21:17 +0000134}
135
136static UInt local_sys_getpid ( void )
137{
tomc6121862005-04-27 09:23:02 +0000138 UInt __res;
139 __asm__ volatile (
sewardj17edf032006-10-17 01:53:34 +0000140 "movq $"VG_STRINGIFY(__NR_getpid)", %%rax\n" /* %rax = __NR_getpid */
tomc6121862005-04-27 09:23:02 +0000141 "syscall\n" /* getpid() */
142 "movl %%eax, %0\n" /* set __res = %eax */
143 : "=mr" (__res)
144 :
145 : "rax" );
146 return __res;
sewardj601371a2005-04-25 16:21:17 +0000147}
sewardj1cf558c2005-04-25 01:36:56 +0000148
cerion85665ca2005-06-20 15:51:07 +0000149#elif defined(VGP_ppc32_linux)
150
floriandbb35842012-10-27 18:39:11 +0000151static UInt local_sys_write_stderr ( const HChar* buf, Int n )
cerion85665ca2005-06-20 15:51:07 +0000152{
sewardj17edf032006-10-17 01:53:34 +0000153 volatile Int block[2];
sewardja2699582006-05-22 13:04:42 +0000154 block[0] = (Int)buf;
155 block[1] = n;
cerion85665ca2005-06-20 15:51:07 +0000156 __asm__ volatile (
sewardja2699582006-05-22 13:04:42 +0000157 "addi 1,1,-256\n\t"
158 "mr 5,%0\n\t" /* r5 = &block[0] */
159 "stw 5,0(1)\n\t" /* stash on stack */
sewardj17edf032006-10-17 01:53:34 +0000160 "li 0,"VG_STRINGIFY(__NR_write)"\n\t" /* set %r0 = __NR_write */
sewardja2699582006-05-22 13:04:42 +0000161 "li 3,2\n\t" /* set %r3 = stderr */
162 "lwz 4,0(5)\n\t" /* set %r4 = buf */
163 "lwz 5,4(5)\n\t" /* set %r5 = n */
164 "sc\n\t" /* write(stderr, buf, n) */
165 "lwz 5,0(1)\n\t"
166 "addi 1,1,256\n\t"
167 "stw 3,0(5)\n" /* block[0] = result */
168 :
169 : "b" (block)
170 : "cc","memory","cr0","ctr",
171 "r0","r2","r3","r4","r5","r6","r7","r8","r9","r10","r11","r12"
172 );
173 if (block[0] < 0)
174 block[0] = -1;
175 return (UInt)block[0];
cerion85665ca2005-06-20 15:51:07 +0000176}
177
178static UInt local_sys_getpid ( void )
179{
sewardja2699582006-05-22 13:04:42 +0000180 register UInt __res __asm__ ("r3");
181 __asm__ volatile (
182 "li 0, %1\n\t"
183 "sc"
184 : "=&r" (__res)
sewardj17edf032006-10-17 01:53:34 +0000185 : "i" (__NR_getpid)
sewardja2699582006-05-22 13:04:42 +0000186 : "cc","memory","cr0","ctr",
187 "r0","r2","r4","r5","r6","r7","r8","r9","r10","r11","r12"
188 );
cerion85665ca2005-06-20 15:51:07 +0000189 return __res;
190}
191
sewardj2c48c7b2005-11-29 13:05:56 +0000192#elif defined(VGP_ppc64_linux)
193
floriandbb35842012-10-27 18:39:11 +0000194static UInt local_sys_write_stderr ( const HChar* buf, Int n )
sewardj2c48c7b2005-11-29 13:05:56 +0000195{
sewardj17edf032006-10-17 01:53:34 +0000196 volatile Long block[2];
sewardja2699582006-05-22 13:04:42 +0000197 block[0] = (Long)buf;
198 block[1] = (Long)n;
sewardj2c48c7b2005-11-29 13:05:56 +0000199 __asm__ volatile (
sewardja2699582006-05-22 13:04:42 +0000200 "addi 1,1,-256\n\t"
201 "mr 5,%0\n\t" /* r5 = &block[0] */
202 "std 5,0(1)\n\t" /* stash on stack */
sewardj17edf032006-10-17 01:53:34 +0000203 "li 0,"VG_STRINGIFY(__NR_write)"\n\t" /* %r0 = __NR_write */
sewardja2699582006-05-22 13:04:42 +0000204 "li 3,2\n\t" /* set %r3 = stderr */
205 "ld 4,0(5)\n\t" /* set %r4 = buf */
206 "ld 5,8(5)\n\t" /* set %r5 = n */
207 "sc\n\t" /* write(stderr, buf, n) */
208 "ld 5,0(1)\n\t"
209 "addi 1,1,256\n\t"
210 "std 3,0(5)\n" /* block[0] = result */
211 :
212 : "b" (block)
213 : "cc","memory","cr0","ctr",
214 "r0","r2","r3","r4","r5","r6","r7","r8","r9","r10","r11","r12"
215 );
216 if (block[0] < 0)
217 block[0] = -1;
218 return (UInt)(Int)block[0];
sewardj2c48c7b2005-11-29 13:05:56 +0000219}
220
221static UInt local_sys_getpid ( void )
222{
sewardja2699582006-05-22 13:04:42 +0000223 register ULong __res __asm__ ("r3");
224 __asm__ volatile (
225 "li 0, %1\n\t"
226 "sc"
227 : "=&r" (__res)
sewardj17edf032006-10-17 01:53:34 +0000228 : "i" (__NR_getpid)
sewardja2699582006-05-22 13:04:42 +0000229 : "cc","memory","cr0","ctr",
230 "r0","r2","r4","r5","r6","r7","r8","r9","r10","r11","r12"
231 );
232 return (UInt)__res;
sewardj2c48c7b2005-11-29 13:05:56 +0000233}
234
sewardj59570ff2010-01-01 11:59:33 +0000235#elif defined(VGP_arm_linux)
236
floriandbb35842012-10-27 18:39:11 +0000237static UInt local_sys_write_stderr ( const HChar* buf, Int n )
sewardj59570ff2010-01-01 11:59:33 +0000238{
239 volatile Int block[2];
240 block[0] = (Int)buf;
241 block[1] = n;
242 __asm__ volatile (
sewardj188a6d72010-08-26 09:40:37 +0000243 "mov r0, #2\n\t" /* stderr */
244 "ldr r1, [%0]\n\t" /* buf */
245 "ldr r2, [%0, #4]\n\t" /* n */
sewardj59570ff2010-01-01 11:59:33 +0000246 "mov r7, #"VG_STRINGIFY(__NR_write)"\n\t"
247 "svc 0x0\n" /* write() */
248 "str r0, [%0]\n\t"
249 :
250 : "r" (block)
251 : "r0","r1","r2","r7"
252 );
253 if (block[0] < 0)
254 block[0] = -1;
255 return (UInt)block[0];
256}
257
258static UInt local_sys_getpid ( void )
259{
260 UInt __res;
261 __asm__ volatile (
262 "mov r7, #"VG_STRINGIFY(__NR_getpid)"\n"
263 "svc 0x0\n" /* getpid() */
264 "mov %0, r0\n"
265 : "=r" (__res)
266 :
267 : "r0", "r7" );
268 return __res;
269}
270
sewardjf0c12502014-01-12 12:54:00 +0000271#elif defined(VGP_arm64_linux)
272
273static UInt local_sys_write_stderr ( const HChar* buf, Int n )
274{
275 volatile ULong block[2];
276 block[0] = (ULong)buf;
277 block[1] = (ULong)n;
278 __asm__ volatile (
279 "mov x0, #2\n\t" /* stderr */
280 "ldr x1, [%0]\n\t" /* buf */
281 "ldr x2, [%0, #8]\n\t" /* n */
282 "mov x8, #"VG_STRINGIFY(__NR_write)"\n\t"
283 "svc 0x0\n" /* write() */
284 "str x0, [%0]\n\t"
285 :
286 : "r" (block)
287 : "x0","x1","x2","x7"
288 );
289 if (block[0] < 0)
290 block[0] = -1;
291 return (UInt)block[0];
292}
293
294static UInt local_sys_getpid ( void )
295{
296 UInt __res;
297 __asm__ volatile (
298 "mov x8, #"VG_STRINGIFY(__NR_getpid)"\n"
299 "svc 0x0\n" /* getpid() */
300 "mov %0, x0\n"
301 : "=r" (__res)
302 :
303 : "x0", "x8" );
304 return (UInt)__res;
305}
306
njnf76d27a2009-05-28 01:53:07 +0000307#elif defined(VGP_x86_darwin)
308
njn1a1e95c2009-06-03 06:50:06 +0000309/* We would use VG_DARWIN_SYSNO_TO_KERNEL instead of VG_DARWIN_SYSNO_INDEX
310 except that the former has a C ternary ?: operator which isn't valid in
311 asm code. Both macros give the same results for Unix-class syscalls (which
312 these all are, as identified by the use of 'int 0x80'). */
njnf76d27a2009-05-28 01:53:07 +0000313__attribute__((noinline))
floriandbb35842012-10-27 18:39:11 +0000314static UInt local_sys_write_stderr ( const HChar* buf, Int n )
njnf76d27a2009-05-28 01:53:07 +0000315{
316 UInt __res;
317 __asm__ volatile (
318 "movl %2, %%eax\n" /* push n */
319 "pushl %%eax\n"
320 "movl %1, %%eax\n" /* push buf */
321 "pushl %%eax\n"
322 "movl $2, %%eax\n" /* push stderr */
323 "pushl %%eax\n"
324 "movl $"VG_STRINGIFY(VG_DARWIN_SYSNO_INDEX(__NR_write_nocancel))
325 ", %%eax\n"
326 "pushl %%eax\n" /* push fake return address */
327 "int $0x80\n" /* write(stderr, buf, n) */
328 "jnc 1f\n" /* jump if no error */
329 "movl $-1, %%eax\n" /* return -1 if error */
330 "1: "
331 "movl %%eax, %0\n" /* __res = eax */
332 "addl $16, %%esp\n" /* pop x4 */
333 : "=mr" (__res)
334 : "g" (buf), "g" (n)
335 : "eax", "edx", "cc"
336 );
337 return __res;
338}
339
340static UInt local_sys_getpid ( void )
341{
342 UInt __res;
343 __asm__ volatile (
344 "movl $"VG_STRINGIFY(VG_DARWIN_SYSNO_INDEX(__NR_getpid))", %%eax\n"
345 "int $0x80\n" /* getpid() */
346 "movl %%eax, %0\n" /* set __res = eax */
347 : "=mr" (__res)
348 :
349 : "eax", "cc" );
350 return __res;
351}
352
353#elif defined(VGP_amd64_darwin)
354
355__attribute__((noinline))
floriandbb35842012-10-27 18:39:11 +0000356static UInt local_sys_write_stderr ( const HChar* buf, Int n )
njnf76d27a2009-05-28 01:53:07 +0000357{
358 UInt __res;
359 __asm__ volatile (
360 "movq $2, %%rdi\n" /* push stderr */
361 "movq %1, %%rsi\n" /* push buf */
362 "movl %2, %%edx\n" /* push n */
njn1a1e95c2009-06-03 06:50:06 +0000363 "movl $"VG_STRINGIFY(VG_DARWIN_SYSNO_FOR_KERNEL(__NR_write_nocancel))
njnf76d27a2009-05-28 01:53:07 +0000364 ", %%eax\n"
365 "syscall\n" /* write(stderr, buf, n) */
366 "jnc 1f\n" /* jump if no error */
367 "movq $-1, %%rax\n" /* return -1 if error */
368 "1: "
369 "movl %%eax, %0\n" /* __res = eax */
370 : "=mr" (__res)
371 : "g" (buf), "g" (n)
372 : "rdi", "rsi", "rdx", "rcx", "rax", "cc" );
373 return __res;
374}
375
376static UInt local_sys_getpid ( void )
377{
378 UInt __res;
379 __asm__ volatile (
njn1a1e95c2009-06-03 06:50:06 +0000380 "movl $"VG_STRINGIFY(VG_DARWIN_SYSNO_FOR_KERNEL(__NR_getpid))", %%eax\n"
njnf76d27a2009-05-28 01:53:07 +0000381 "syscall\n" /* getpid() */
382 "movl %%eax, %0\n" /* set __res = eax */
383 : "=mr" (__res)
384 :
385 : "rax", "rcx", "cc" );
386 return __res;
387}
388
sewardjb5b87402011-03-07 16:05:35 +0000389#elif defined(VGP_s390x_linux)
sewardjf0c12502014-01-12 12:54:00 +0000390
floriandbb35842012-10-27 18:39:11 +0000391static UInt local_sys_write_stderr ( const HChar* buf, Int n )
sewardjb5b87402011-03-07 16:05:35 +0000392{
floriandbb35842012-10-27 18:39:11 +0000393 register Int r2 asm("2") = 2; /* file descriptor STDERR */
394 register const HChar* r3 asm("3") = buf;
395 register ULong r4 asm("4") = n;
396 register ULong r2_res asm("2");
sewardjb5b87402011-03-07 16:05:35 +0000397 ULong __res;
398
399 __asm__ __volatile__ (
400 "svc %b1\n"
401 : "=d" (r2_res)
402 : "i" (__NR_write),
403 "0" (r2),
404 "d" (r3),
405 "d" (r4)
406 : "cc", "memory");
407 __res = r2_res;
408
409 if (__res >= (ULong)(-125))
410 __res = -1;
411 return (UInt)(__res);
412}
413
414static UInt local_sys_getpid ( void )
415{
416 register ULong r2 asm("2");
417 ULong __res;
418
419 __asm__ __volatile__ (
420 "svc %b1\n"
421 : "=d" (r2)
422 : "i" (__NR_getpid)
423 : "cc", "memory");
424 __res = r2;
425
426 if (__res >= (ULong)(-125))
427 __res = -1;
428 return (UInt)(__res);
429}
430
sewardj5db15402012-06-07 09:13:21 +0000431#elif defined(VGP_mips32_linux)
sewardjf0c12502014-01-12 12:54:00 +0000432
floriandbb35842012-10-27 18:39:11 +0000433static UInt local_sys_write_stderr ( const HChar* buf, Int n )
sewardj5db15402012-06-07 09:13:21 +0000434{
435 volatile Int block[2];
436 block[0] = (Int)buf;
437 block[1] = n;
438 __asm__ volatile (
439 "li $4, 2\n\t" /* stderr */
440 "lw $5, 0(%0)\n\t" /* buf */
441 "lw $6, 4(%0)\n\t" /* n */
442 "move $7, $0\n\t"
443 "li $2, %1\n\t" /* set v0 = __NR_write */
444 "syscall\n\t" /* write() */
445 "nop\n\t"
446 :
447 : "r" (block), "n" (__NR_write)
448 : "2", "4", "5", "6", "7"
449 );
450 if (block[0] < 0)
451 block[0] = -1;
452 return (UInt)block[0];
453}
454
455static UInt local_sys_getpid ( void )
456{
457 UInt __res;
458 __asm__ volatile (
459 "li $2, %1\n\t" /* set v0 = __NR_getpid */
460 "syscall\n\t" /* getpid() */
461 "nop\n\t"
462 "move %0, $2\n"
463 : "=r" (__res)
464 : "n" (__NR_getpid)
465 : "$2" );
466 return __res;
467}
468
petarj4df0bfc2013-02-27 23:17:33 +0000469#elif defined(VGP_mips64_linux)
sewardjf0c12502014-01-12 12:54:00 +0000470
petarj4df0bfc2013-02-27 23:17:33 +0000471static UInt local_sys_write_stderr ( const HChar* buf, Int n )
472{
473 volatile Long block[2];
474 block[0] = (Long)buf;
475 block[1] = n;
476 __asm__ volatile (
477 "li $4, 2\n\t" /* std output*/
478 "ld $5, 0(%0)\n\t" /*$5 = buf*/
479 "ld $6, 8(%0)\n\t" /*$6 = n */
480 "move $7, $0\n\t"
481 "li $2, %1\n\t" /* set v0 = __NR_write */
482 "\tsyscall\n"
483 "\tnop\n"
484 : /*wr*/
485 : /*rd*/ "r" (block), "n" (__NR_write)
486 : "2", "4", "5", "6", "7"
487 );
488 if (block[0] < 0)
489 block[0] = -1;
490 return (UInt)(Int)block[0];
491}
492
493static UInt local_sys_getpid ( void )
494{
495 ULong __res;
496 __asm__ volatile (
497 "li $2, %1\n\t" /* set v0 = __NR_getpid */
498 "syscall\n\t" /* getpid() */
499 "nop\n\t"
500 "move %0, $2\n"
501 : "=r" (__res)
502 : "n" (__NR_getpid)
503 : "$2" );
504 return (UInt)(__res);
505}
sewardjb5b87402011-03-07 16:05:35 +0000506
sewardj1cf558c2005-04-25 01:36:56 +0000507#else
sewardj21c6d0f2005-05-02 10:33:44 +0000508# error Unknown platform
sewardj1cf558c2005-04-25 01:36:56 +0000509#endif
510
511
512/* ----- generic ----- */
513
514/* strlen, so we don't need m_libc */
515static Int local_strlen ( const HChar* str )
516{
517 Int i = 0;
518 while (str[i] != 0) i++;
519 return i;
520}
521
522static HChar local_toupper ( HChar c )
523{
524 if (c >= 'a' && c <= 'z')
525 return c + ('A' - 'a');
526 else
527 return c;
528}
529
530/* Emit buf[0 .. n-1] to stderr. Unfortunately platform-specific.
531*/
floriandbb35842012-10-27 18:39:11 +0000532static void emit ( const HChar* buf, Int n )
sewardj1cf558c2005-04-25 01:36:56 +0000533{
534 if (n >= 1)
535 (void)local_sys_write_stderr(buf, n);
536}
537
538
539/*------------------------------------------------------------*/
540/*--- A simple, generic, vprintf implementation. ---*/
541/*------------------------------------------------------------*/
542
543/* -----------------------------------------------
544 Distantly derived from:
545
546 vprintf replacement for Checker.
547 Copyright 1993, 1994, 1995 Tristan Gingold
548 Written September 1993 Tristan Gingold
549 Tristan Gingold, 8 rue Parmentier, F-91120 PALAISEAU, FRANCE
550
551 (Checker itself was GPL'd.)
552 ----------------------------------------------- */
553
554/* Some flags. */
555#define VG_MSG_SIGNED 1 /* The value is signed. */
556#define VG_MSG_ZJUSTIFY 2 /* Must justify with '0'. */
557#define VG_MSG_LJUSTIFY 4 /* Must justify on the left. */
558#define VG_MSG_PAREN 8 /* Parenthesize if present (for %y) */
559#define VG_MSG_COMMA 16 /* Add commas to numbers (for %d, %u) */
barta0b6b2c2008-07-07 06:49:24 +0000560#define VG_MSG_ALTFORMAT 32 /* Convert the value to alternate format */
sewardj1cf558c2005-04-25 01:36:56 +0000561
562/* Copy a string into the buffer. */
563static
564UInt myvprintf_str ( void(*send)(HChar,void*),
565 void* send_arg2,
566 Int flags,
567 Int width,
floriandbb35842012-10-27 18:39:11 +0000568 const HChar* str,
sewardj1cf558c2005-04-25 01:36:56 +0000569 Bool capitalise )
570{
571# define MAYBE_TOUPPER(ch) (capitalise ? local_toupper(ch) : (ch))
572 UInt ret = 0;
573 Int i, extra;
574 Int len = local_strlen(str);
575
576 if (width == 0) {
577 ret += len;
578 for (i = 0; i < len; i++)
579 send(MAYBE_TOUPPER(str[i]), send_arg2);
580 return ret;
581 }
582
583 if (len > width) {
584 ret += width;
585 for (i = 0; i < width; i++)
586 send(MAYBE_TOUPPER(str[i]), send_arg2);
587 return ret;
588 }
589
590 extra = width - len;
591 if (flags & VG_MSG_LJUSTIFY) {
592 ret += extra;
593 for (i = 0; i < extra; i++)
594 send(' ', send_arg2);
595 }
596 ret += len;
597 for (i = 0; i < len; i++)
598 send(MAYBE_TOUPPER(str[i]), send_arg2);
599 if (!(flags & VG_MSG_LJUSTIFY)) {
600 ret += extra;
601 for (i = 0; i < extra; i++)
602 send(' ', send_arg2);
603 }
604
605# undef MAYBE_TOUPPER
606 return ret;
607}
608
609
sewardjdaf77af2005-07-19 14:17:37 +0000610/* Copy a string into the buffer, escaping bad XML chars. */
611static
612UInt myvprintf_str_XML_simplistic ( void(*send)(HChar,void*),
613 void* send_arg2,
floriandbb35842012-10-27 18:39:11 +0000614 const HChar* str )
sewardjdaf77af2005-07-19 14:17:37 +0000615{
616 UInt ret = 0;
617 Int i;
618 Int len = local_strlen(str);
floriandbb35842012-10-27 18:39:11 +0000619 const HChar* alt;
sewardjdaf77af2005-07-19 14:17:37 +0000620
621 for (i = 0; i < len; i++) {
622 switch (str[i]) {
623 case '&': alt = "&amp;"; break;
624 case '<': alt = "&lt;"; break;
625 case '>': alt = "&gt;"; break;
626 default: alt = NULL;
627 }
628
629 if (alt) {
630 while (*alt) {
631 send(*alt, send_arg2);
632 ret++;
633 alt++;
634 }
635 } else {
636 send(str[i], send_arg2);
637 ret++;
638 }
639 }
640
641 return ret;
642}
643
644
sewardj1cf558c2005-04-25 01:36:56 +0000645/* Write P into the buffer according to these args:
646 * If SIGN is true, p is a signed.
647 * BASE is the base.
648 * If WITH_ZERO is true, '0' must be added.
649 * WIDTH is the width of the field.
650 */
651static
652UInt myvprintf_int64 ( void(*send)(HChar,void*),
653 void* send_arg2,
654 Int flags,
655 Int base,
656 Int width,
sewardja44b15f2007-02-16 14:10:24 +0000657 Bool capitalised,
sewardj1cf558c2005-04-25 01:36:56 +0000658 ULong p )
659{
660 HChar buf[40];
661 Int ind = 0;
662 Int i, nc = 0;
663 Bool neg = False;
floriandbb35842012-10-27 18:39:11 +0000664 const HChar* digits = capitalised ? "0123456789ABCDEF" : "0123456789abcdef";
sewardj1cf558c2005-04-25 01:36:56 +0000665 UInt ret = 0;
666
667 if (base < 2 || base > 16)
668 return ret;
669
670 if ((flags & VG_MSG_SIGNED) && (Long)p < 0) {
671 p = - (Long)p;
672 neg = True;
673 }
674
675 if (p == 0)
676 buf[ind++] = '0';
677 else {
678 while (p > 0) {
679 if (flags & VG_MSG_COMMA && 10 == base &&
680 0 == (ind-nc) % 3 && 0 != ind)
681 {
682 buf[ind++] = ',';
683 nc++;
684 }
685 buf[ind++] = digits[p % base];
686 p /= base;
687 }
688 }
689
690 if (neg)
691 buf[ind++] = '-';
692
693 if (width > 0 && !(flags & VG_MSG_LJUSTIFY)) {
694 for(; ind < width; ind++) {
695 /* vg_assert(ind < 39); */
696 if (ind > 39) {
697 buf[39] = 0;
698 break;
699 }
700 buf[ind] = (flags & VG_MSG_ZJUSTIFY) ? '0': ' ';
701 }
702 }
703
704 /* Reverse copy to buffer. */
705 ret += ind;
706 for (i = ind -1; i >= 0; i--) {
707 send(buf[i], send_arg2);
708 }
709 if (width > 0 && (flags & VG_MSG_LJUSTIFY)) {
710 for(; ind < width; ind++) {
711 ret++;
712 /* Never pad with zeroes on RHS -- changes the value! */
713 send(' ', send_arg2);
714 }
715 }
716 return ret;
717}
718
719
720/* A simple vprintf(). */
721/* EXPORTED */
722UInt
723VG_(debugLog_vprintf) (
724 void(*send)(HChar,void*),
725 void* send_arg2,
726 const HChar* format,
727 va_list vargs
728)
729{
730 UInt ret = 0;
731 Int i;
732 Int flags;
733 Int width;
njn68e46592005-08-26 19:42:27 +0000734 Int n_ls = 0;
sewardja44b15f2007-02-16 14:10:24 +0000735 Bool is_long, caps;
sewardj1cf558c2005-04-25 01:36:56 +0000736
737 /* We assume that vargs has already been initialised by the
738 caller, using va_start, and that the caller will similarly
739 clean up with va_end.
740 */
741
742 for (i = 0; format[i] != 0; i++) {
743 if (format[i] != '%') {
744 send(format[i], send_arg2);
745 ret++;
746 continue;
747 }
748 i++;
749 /* A '%' has been found. Ignore a trailing %. */
750 if (format[i] == 0)
751 break;
752 if (format[i] == '%') {
njn02bc4b82005-05-15 17:28:26 +0000753 /* '%%' is replaced by '%'. */
sewardj1cf558c2005-04-25 01:36:56 +0000754 send('%', send_arg2);
755 ret++;
756 continue;
757 }
758 flags = 0;
njn68e46592005-08-26 19:42:27 +0000759 n_ls = 0;
sewardj1cf558c2005-04-25 01:36:56 +0000760 width = 0; /* length of the field. */
barta0b6b2c2008-07-07 06:49:24 +0000761 while (1) {
762 switch (format[i]) {
763 case '(':
764 flags |= VG_MSG_PAREN;
765 break;
766 case ',':
767 case '\'':
768 /* If ',' or '\'' follows '%', commas will be inserted. */
769 flags |= VG_MSG_COMMA;
770 break;
771 case '-':
772 /* If '-' follows '%', justify on the left. */
773 flags |= VG_MSG_LJUSTIFY;
774 break;
775 case '0':
776 /* If '0' follows '%', pads will be inserted. */
777 flags |= VG_MSG_ZJUSTIFY;
778 break;
779 case '#':
780 /* If '#' follows '%', alternative format will be used. */
781 flags |= VG_MSG_ALTFORMAT;
782 break;
783 default:
784 goto parse_fieldwidth;
785 }
sewardj1cf558c2005-04-25 01:36:56 +0000786 i++;
787 }
barta0b6b2c2008-07-07 06:49:24 +0000788 parse_fieldwidth:
sewardj1cf558c2005-04-25 01:36:56 +0000789 /* Compute the field length. */
790 while (format[i] >= '0' && format[i] <= '9') {
791 width *= 10;
792 width += format[i++] - '0';
793 }
794 while (format[i] == 'l') {
795 i++;
njn68e46592005-08-26 19:42:27 +0000796 n_ls++;
sewardj1cf558c2005-04-25 01:36:56 +0000797 }
798
njn68e46592005-08-26 19:42:27 +0000799 // %d means print a 32-bit integer.
800 // %ld means print a word-size integer.
801 // %lld means print a 64-bit integer.
802 if (0 == n_ls) { is_long = False; }
803 else if (1 == n_ls) { is_long = ( sizeof(void*) == sizeof(Long) ); }
804 else { is_long = True; }
805
sewardj1cf558c2005-04-25 01:36:56 +0000806 switch (format[i]) {
bart042257f2009-07-26 08:40:17 +0000807 case 'o': /* %o */
808 if (flags & VG_MSG_ALTFORMAT) {
809 ret += 2;
810 send('0',send_arg2);
811 }
812 if (is_long)
813 ret += myvprintf_int64(send, send_arg2, flags, 8, width, False,
814 (ULong)(va_arg (vargs, ULong)));
815 else
816 ret += myvprintf_int64(send, send_arg2, flags, 8, width, False,
817 (ULong)(va_arg (vargs, UInt)));
818 break;
sewardj1cf558c2005-04-25 01:36:56 +0000819 case 'd': /* %d */
820 flags |= VG_MSG_SIGNED;
821 if (is_long)
sewardja44b15f2007-02-16 14:10:24 +0000822 ret += myvprintf_int64(send, send_arg2, flags, 10, width, False,
sewardj1cf558c2005-04-25 01:36:56 +0000823 (ULong)(va_arg (vargs, Long)));
824 else
sewardja44b15f2007-02-16 14:10:24 +0000825 ret += myvprintf_int64(send, send_arg2, flags, 10, width, False,
sewardj1cf558c2005-04-25 01:36:56 +0000826 (ULong)(va_arg (vargs, Int)));
827 break;
828 case 'u': /* %u */
829 if (is_long)
sewardja44b15f2007-02-16 14:10:24 +0000830 ret += myvprintf_int64(send, send_arg2, flags, 10, width, False,
sewardj1cf558c2005-04-25 01:36:56 +0000831 (ULong)(va_arg (vargs, ULong)));
832 else
sewardja44b15f2007-02-16 14:10:24 +0000833 ret += myvprintf_int64(send, send_arg2, flags, 10, width, False,
sewardj1cf558c2005-04-25 01:36:56 +0000834 (ULong)(va_arg (vargs, UInt)));
835 break;
bartb3af9cf2011-10-06 19:08:37 +0000836 case 'p':
837 if (format[i+1] == 'S') {
838 i++;
839 /* %pS, like %s but escaping chars for XML safety */
840 /* Note: simplistic; ignores field width and flags */
florian6bd9dc12012-11-23 16:17:43 +0000841 const HChar *str = va_arg (vargs, HChar *);
floriandbb35842012-10-27 18:39:11 +0000842 if (str == NULL)
bartb3af9cf2011-10-06 19:08:37 +0000843 str = "(null)";
844 ret += myvprintf_str_XML_simplistic(send, send_arg2, str);
bartdb4384e2011-10-11 18:49:35 +0000845 } else if (format[i+1] == 's') {
846 i++;
847 /* %ps, synonym for %s with --xml=no / %pS with --xml=yes */
florian6bd9dc12012-11-23 16:17:43 +0000848 const HChar *str = va_arg (vargs, HChar *);
floriandbb35842012-10-27 18:39:11 +0000849 if (str == NULL)
bartdb4384e2011-10-11 18:49:35 +0000850 str = "(null)";
851 if (clo_xml)
852 ret += myvprintf_str_XML_simplistic(send, send_arg2, str);
853 else
854 ret += myvprintf_str(send, send_arg2, flags, width, str,
855 False);
bartb3af9cf2011-10-06 19:08:37 +0000856 } else {
857 /* %p */
858 ret += 2;
859 send('0',send_arg2);
860 send('x',send_arg2);
861 ret += myvprintf_int64(send, send_arg2, flags, 16, width, True,
862 (ULong)((UWord)va_arg (vargs, void *)));
863 }
sewardj1cf558c2005-04-25 01:36:56 +0000864 break;
865 case 'x': /* %x */
sewardja44b15f2007-02-16 14:10:24 +0000866 case 'X': /* %X */
867 caps = toBool(format[i] == 'X');
barta0b6b2c2008-07-07 06:49:24 +0000868 if (flags & VG_MSG_ALTFORMAT) {
869 ret += 2;
870 send('0',send_arg2);
871 send('x',send_arg2);
872 }
sewardj1cf558c2005-04-25 01:36:56 +0000873 if (is_long)
sewardja44b15f2007-02-16 14:10:24 +0000874 ret += myvprintf_int64(send, send_arg2, flags, 16, width, caps,
sewardj1cf558c2005-04-25 01:36:56 +0000875 (ULong)(va_arg (vargs, ULong)));
876 else
sewardja44b15f2007-02-16 14:10:24 +0000877 ret += myvprintf_int64(send, send_arg2, flags, 16, width, caps,
sewardj1cf558c2005-04-25 01:36:56 +0000878 (ULong)(va_arg (vargs, UInt)));
879 break;
880 case 'c': /* %c */
881 ret++;
882 send(va_arg (vargs, int), send_arg2);
883 break;
884 case 's': case 'S': { /* %s */
florian6bd9dc12012-11-23 16:17:43 +0000885 const HChar *str = va_arg (vargs, HChar *);
floriandbb35842012-10-27 18:39:11 +0000886 if (str == NULL) str = "(null)";
sewardj1cf558c2005-04-25 01:36:56 +0000887 ret += myvprintf_str(send, send_arg2,
888 flags, width, str, format[i]=='S');
889 break;
890 }
sewardjdaf77af2005-07-19 14:17:37 +0000891
sewardj1cf558c2005-04-25 01:36:56 +0000892// case 'y': { /* %y - print symbol */
florian19f91bb2012-11-10 22:29:54 +0000893// HChar buf[100];
894// HChar *cp = buf;
sewardj1cf558c2005-04-25 01:36:56 +0000895// Addr a = va_arg(vargs, Addr);
896//
897// if (flags & VG_MSG_PAREN)
898// *cp++ = '(';
899// if (VG_(get_fnname_w_offset)(a, cp, sizeof(buf)-4)) {
900// if (flags & VG_MSG_PAREN) {
901// cp += VG_(strlen)(cp);
902// *cp++ = ')';
903// *cp = '\0';
904// }
905// ret += myvprintf_str(send, send_arg2, flags, width, buf, 0);
906// }
907// break;
908// }
909 default:
910 break;
911 }
912 }
913 return ret;
914}
915
916
917/*------------------------------------------------------------*/
918/*--- Debuglog stuff. ---*/
919/*------------------------------------------------------------*/
920
921/* Only print messages whose stated level is less than or equal to
922 this. By default, it makes this entire subsystem silent. */
923
924static Int loglevel = 0;
925
sewardj1cf558c2005-04-25 01:36:56 +0000926/* Module startup. */
sewardj10759312005-05-30 23:52:47 +0000927/* EXPORTED */
floriandbb35842012-10-27 18:39:11 +0000928void VG_(debugLog_startup) ( Int level, const HChar* who )
sewardj1cf558c2005-04-25 01:36:56 +0000929{
930 if (level < 0) level = 0;
931 if (level > 10) level = 10;
932 loglevel = level;
933 VG_(debugLog)(1, "debuglog",
934 "DebugLog system started by %s, "
935 "level %d logging requested\n",
936 who, loglevel);
937}
938
sewardj10759312005-05-30 23:52:47 +0000939/* Get the logging threshold level, as set by the most recent call to
940 VG_(debugLog_startup), or zero if there have been no such calls so
941 far. */
942/* EXPORTED */
943Int VG_(debugLog_getLevel) ( void )
944{
945 return loglevel;
946}
947
948
sewardj1cf558c2005-04-25 01:36:56 +0000949/* ------------ */
950
951typedef
952 struct {
953 HChar buf[100];
954 Int n;
955 }
956 printf_buf;
957
958static void add_to_buf ( HChar c, void* p )
959{
960 printf_buf* buf = (printf_buf*)p;
961
962 if (buf->n >= 100-10 /*paranoia*/ ) {
963 emit( buf->buf, local_strlen(buf->buf) );
964 buf->n = 0;
965 buf->buf[buf->n] = 0;
966 }
967 buf->buf[buf->n++] = c;
968 buf->buf[buf->n] = 0;
969}
970
971/* Send a logging message. Nothing is output unless 'level'
972 is <= the current loglevel. */
973/* EXPORTED */
sewardj1cf558c2005-04-25 01:36:56 +0000974void VG_(debugLog) ( Int level, const HChar* modulename,
975 const HChar* format, ... )
976{
sewardjc7ffc942011-03-28 16:26:42 +0000977 UInt pid;
sewardj45f4e7c2005-09-27 19:20:21 +0000978 Int indent, depth, i;
sewardj1cf558c2005-04-25 01:36:56 +0000979 va_list vargs;
980 printf_buf buf;
sewardja5ebfa92005-04-25 02:04:54 +0000981
sewardj1cf558c2005-04-25 01:36:56 +0000982 if (level > loglevel)
983 return;
984
sewardjd85feff2005-04-25 02:37:56 +0000985 indent = 2*level - 1;
sewardja5ebfa92005-04-25 02:04:54 +0000986 if (indent < 1) indent = 1;
987
sewardj1cf558c2005-04-25 01:36:56 +0000988 buf.n = 0;
989 buf.buf[0] = 0;
990 pid = local_sys_getpid();
sewardj45f4e7c2005-09-27 19:20:21 +0000991
992 // Print one '>' in front of the messages for each level of self-hosting
993 // being performed.
994 depth = RUNNING_ON_VALGRIND;
995 for (i = 0; i < depth; i++) {
996 (void)myvprintf_str ( add_to_buf, &buf, 0, 1, ">", False );
997 }
998
sewardja5ebfa92005-04-25 02:04:54 +0000999 (void)myvprintf_str ( add_to_buf, &buf, 0, 2, "--", False );
sewardja44b15f2007-02-16 14:10:24 +00001000 (void)myvprintf_int64 ( add_to_buf, &buf, 0, 10, 1, False, (ULong)pid );
sewardja5ebfa92005-04-25 02:04:54 +00001001 (void)myvprintf_str ( add_to_buf, &buf, 0, 1, ":", False );
sewardja44b15f2007-02-16 14:10:24 +00001002 (void)myvprintf_int64 ( add_to_buf, &buf, 0, 10, 1, False, (ULong)level );
sewardja5ebfa92005-04-25 02:04:54 +00001003 (void)myvprintf_str ( add_to_buf, &buf, 0, 1, ":", False );
floriandbb35842012-10-27 18:39:11 +00001004 (void)myvprintf_str ( add_to_buf, &buf, 0, 8, modulename, False );
sewardja5ebfa92005-04-25 02:04:54 +00001005 (void)myvprintf_str ( add_to_buf, &buf, 0, indent, "", False );
sewardj1cf558c2005-04-25 01:36:56 +00001006
1007 va_start(vargs,format);
1008
sewardjc7ffc942011-03-28 16:26:42 +00001009 (void) VG_(debugLog_vprintf) ( add_to_buf, &buf, format, vargs );
sewardj1cf558c2005-04-25 01:36:56 +00001010
1011 if (buf.n > 0) {
1012 emit( buf.buf, local_strlen(buf.buf) );
1013 }
1014
1015 va_end(vargs);
1016}
1017
1018
1019
1020/*--------------------------------------------------------------------*/
1021/*--- end m_debuglog.c ---*/
1022/*--------------------------------------------------------------------*/