blob: cf61731831ff099208760700ab1bab145dc7513d [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
njn9f207462009-03-10 22:02:09 +000010 Copyright (C) 2000-2009 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 */
sewardj45f4e7c2005-09-27 19:20:21 +000057#include "valgrind.h" /* for RUNNING_ON_VALGRIND */
sewardj1cf558c2005-04-25 01:36:56 +000058
59/*------------------------------------------------------------*/
60/*--- Stuff to make us completely independent. ---*/
61/*------------------------------------------------------------*/
62
sewardj2c48c7b2005-11-29 13:05:56 +000063/* ----- Platform-specifics ----- */
sewardj1cf558c2005-04-25 01:36:56 +000064
sewardj21c6d0f2005-05-02 10:33:44 +000065#if defined(VGP_x86_linux)
sewardj1cf558c2005-04-25 01:36:56 +000066
67static UInt local_sys_write_stderr ( HChar* buf, Int n )
68{
sewardj17edf032006-10-17 01:53:34 +000069 volatile Int block[2];
sewardj55c43762006-04-28 21:01:33 +000070 block[0] = (Int)buf;
71 block[1] = n;
tom311400b2005-04-27 08:58:53 +000072 __asm__ volatile (
sewardj55c43762006-04-28 21:01:33 +000073 "pushl %%ebx\n" /* ebx is callee-save */
74 "movl %0, %%ebx\n" /* ebx = &block */
75 "pushl %%ebx\n" /* save &block */
76 "movl 0(%%ebx), %%ecx\n" /* %ecx = buf */
77 "movl 4(%%ebx), %%edx\n" /* %edx = n */
sewardj17edf032006-10-17 01:53:34 +000078 "movl $"VG_STRINGIFY(__NR_write)", %%eax\n" /* %eax = __NR_write */
njn5ed05a52009-05-20 06:59:19 +000079 "movl $2, %%ebx\n" /* %ebx = stderr */
sewardj55c43762006-04-28 21:01:33 +000080 "int $0x80\n" /* write(stderr, buf, n) */
81 "popl %%ebx\n" /* reestablish &block */
82 "movl %%eax, 0(%%ebx)\n" /* block[0] = result */
83 "popl %%ebx\n" /* restore ebx */
84 : /*wr*/
85 : /*rd*/ "g" (block)
86 : /*trash*/ "eax", "edi", "ecx", "edx", "memory", "cc"
sewardjd4d203b2005-04-27 23:17:48 +000087 );
sewardj55c43762006-04-28 21:01:33 +000088 if (block[0] < 0)
89 block[0] = -1;
90 return block[0];
sewardj1cf558c2005-04-25 01:36:56 +000091}
92
93static UInt local_sys_getpid ( void )
94{
95 UInt __res;
tom311400b2005-04-27 08:58:53 +000096 __asm__ volatile (
sewardj17edf032006-10-17 01:53:34 +000097 "movl $"VG_STRINGIFY(__NR_getpid)", %%eax\n" /* %eax = __NR_getpid */
tom311400b2005-04-27 08:58:53 +000098 "int $0x80\n" /* getpid() */
99 "movl %%eax, %0\n" /* set __res = eax */
sewardjd4d203b2005-04-27 23:17:48 +0000100 : "=mr" (__res)
101 :
102 : "eax" );
sewardj1cf558c2005-04-25 01:36:56 +0000103 return __res;
104}
105
sewardj21c6d0f2005-05-02 10:33:44 +0000106#elif defined(VGP_amd64_linux)
sewardj7337f922006-05-26 11:31:15 +0000107__attribute__((noinline))
sewardj601371a2005-04-25 16:21:17 +0000108static UInt local_sys_write_stderr ( HChar* buf, Int n )
109{
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*/
128 : /*rd*/ "g" (block)
129 : /*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
151static UInt local_sys_write_stderr ( HChar* buf, Int n )
152{
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
194static UInt local_sys_write_stderr ( HChar* buf, Int n )
195{
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
sewardj17edf032006-10-17 01:53:34 +0000235#elif defined(VGP_ppc32_aix5)
236
237static UInt local_sys_write_stderr ( HChar* buf, Int n )
238{
239 /* For some reason gcc-3.3.2 doesn't preserve r31 across the asm
240 even though we state it to be trashed. So use r27 instead. */
241 volatile UInt block[3];
242 block[0] = (UInt)buf;
243 block[1] = n;
244 block[2] = __NR_write;
245 __asm__ __volatile__ (
246 "mr 28,%0\n\t" /* establish base ptr */
247 "mr 27,2\n\t" /* save r2 in r27 */
248 "mflr 30\n\t" /* save lr in r30 */
249
250 "lwz 2,8(28)\n\t" /* set %r2 = __NR_write */
251 "li 3,2\n\t" /* set %r3 = stderr */
252 "lwz 4,0(28)\n\t" /* set %r4 = buf */
253 "lwz 5,4(28)\n\t" /* set %r5 = n */
254
sewardj13552642006-11-10 22:47:27 +0000255 "crorc 6,6,6\n\t"
sewardj17edf032006-10-17 01:53:34 +0000256 ".long 0x48000005\n\t" /* bl .+4 */
257 "mflr 29\n\t"
sewardj13552642006-11-10 22:47:27 +0000258 "addi 29,29,16\n\t"
sewardj17edf032006-10-17 01:53:34 +0000259 "mtlr 29\n\t"
sewardj17edf032006-10-17 01:53:34 +0000260 "sc\n\t" /* write() */
261
262 "stw 3,0(28)\n\t" /* result */
263 "stw 4,4(28)\n\t" /* error? */
264
265 "mr 2,27\n\t" /* restore r2 */
266 "mtlr 30" /* restore lr */
267
268 : /*out*/
269 : /*in*/ "b" (&block[0])
270 : /*trash*/
271 /*temps*/ "r31","r30","r29","r28","r27",
272 /*args*/ "r3","r4","r5","r6","r7","r8","r9","r10",
273 /*paranoia*/ "memory","cc","r0","r1","r11","r12","r13",
274 "xer","ctr","cr0","cr1","cr2","cr3",
275 "cr4","cr5","cr6","cr7"
276 );
277 if (block[1] != 0)
278 return -1;
279 else
280 return block[0];
281}
282
283static UInt local_sys_getpid ( void )
284{
285 /* For some reason gcc-3.3.2 doesn't preserve r31 across the asm
286 even though we state it to be trashed. So use r27 instead. */
287 volatile UInt block[1];
288 block[0] = __NR_getpid;
289 __asm__ __volatile__ (
290 "mr 28,%0\n\t" /* establish base ptr */
291 "mr 27,2\n\t" /* save r2 in r27 */
292 "mflr 30\n\t" /* save lr in r30 */
293
294 "lwz 2,0(28)\n\t" /* set %r2 = __NR_getpid */
295
sewardj13552642006-11-10 22:47:27 +0000296 "crorc 6,6,6\n\t"
sewardj17edf032006-10-17 01:53:34 +0000297 ".long 0x48000005\n\t" /* bl .+4 */
298 "mflr 29\n\t"
sewardj13552642006-11-10 22:47:27 +0000299 "addi 29,29,16\n\t"
sewardj17edf032006-10-17 01:53:34 +0000300 "mtlr 29\n\t"
sewardj17edf032006-10-17 01:53:34 +0000301 "sc\n\t" /* getpid() */
302
303 "stw 3,0(28)\n\t" /* result -> block[0] */
304
305 "mr 2,27\n\t" /* restore r2 */
306 "mtlr 30" /* restore lr */
307
308 : /*out*/
309 : /*in*/ "b" (&block[0])
310 : /*trash*/
311 /*temps*/ "r31","r30","r29","r28","r27",
312 /*args*/ "r3","r4","r5","r6","r7","r8","r9","r10",
313 /*paranoia*/ "memory","cc","r0","r1","r11","r12","r13",
314 "xer","ctr","cr0","cr1","cr2","cr3",
315 "cr4","cr5","cr6","cr7"
316 );
317 return block[0];
318}
319
320#elif defined(VGP_ppc64_aix5)
321
322static UInt local_sys_write_stderr ( HChar* buf, Int n )
323{
324 volatile ULong block[3];
325 block[0] = (ULong)buf;
326 block[1] = n;
327 block[2] = (ULong)__NR_write;
328 __asm__ __volatile__ (
329 "mr 28,%0\n\t" /* establish base ptr */
330 "mr 27,2\n\t" /* save r2 in r27 */
331 "mflr 30\n\t" /* save lr in r30 */
332
333 "ld 2,16(28)\n\t" /* set %r2 = __NR_write */
334 "li 3,2\n\t" /* set %r3 = stderr */
335 "ld 4,0(28)\n\t" /* set %r4 = buf */
336 "ld 5,8(28)\n\t" /* set %r5 = n */
337
sewardj13552642006-11-10 22:47:27 +0000338 "crorc 6,6,6\n\t"
sewardj17edf032006-10-17 01:53:34 +0000339 ".long 0x48000005\n\t" /* bl .+4 */
340 "mflr 29\n\t"
sewardj13552642006-11-10 22:47:27 +0000341 "addi 29,29,16\n\t"
sewardj17edf032006-10-17 01:53:34 +0000342 "mtlr 29\n\t"
sewardj17edf032006-10-17 01:53:34 +0000343 "sc\n\t" /* write() */
344
345 "std 3,0(28)\n\t" /* result */
346 "std 4,8(28)\n\t" /* error? */
347
348 "mr 2,27\n\t" /* restore r2 */
349 "mtlr 30" /* restore lr */
350
351 : /*out*/
352 : /*in*/ "b" (&block[0])
353 : /*trash*/
354 /*temps*/ "r31","r30","r29","r28","r27",
355 /*args*/ "r3","r4","r5","r6","r7","r8","r9","r10",
356 /*paranoia*/ "memory","cc","r0","r1","r11","r12","r13",
357 "xer","ctr","cr0","cr1","cr2","cr3",
358 "cr4","cr5","cr6","cr7"
359 );
360 if (block[1] != 0)
361 return (UInt)-1;
362 else
363 return (UInt)block[0];
364}
365
366static UInt local_sys_getpid ( void )
367{
368 volatile ULong block[1];
369 block[0] = __NR_getpid;
370 __asm__ __volatile__ (
371 "mr 28,%0\n\t" /* establish base ptr */
372 "mr 27,2\n\t" /* save r2 in r27 */
373 "mflr 30\n\t" /* save lr in r30 */
374
375 "ld 2,0(28)\n\t" /* set %r2 = __NR_getpid */
376
sewardj13552642006-11-10 22:47:27 +0000377 "crorc 6,6,6\n\t"
sewardj17edf032006-10-17 01:53:34 +0000378 ".long 0x48000005\n\t" /* bl .+4 */
379 "mflr 29\n\t"
sewardj13552642006-11-10 22:47:27 +0000380 "addi 29,29,16\n\t"
sewardj17edf032006-10-17 01:53:34 +0000381 "mtlr 29\n\t"
sewardj17edf032006-10-17 01:53:34 +0000382 "sc\n\t" /* getpid() */
383
384 "std 3,0(28)\n\t" /* result -> block[0] */
385
386 "mr 2,27\n\t" /* restore r2 */
387 "mtlr 30" /* restore lr */
388
389 : /*out*/
390 : /*in*/ "b" (&block[0])
391 : /*trash*/
392 /*temps*/ "r31","r30","r29","r28","r27",
393 /*args*/ "r3","r4","r5","r6","r7","r8","r9","r10",
394 /*paranoia*/ "memory","cc","r0","r1","r11","r12","r13",
395 "xer","ctr","cr0","cr1","cr2","cr3",
396 "cr4","cr5","cr6","cr7"
397 );
398 return (UInt)block[0];
399}
400
njnf76d27a2009-05-28 01:53:07 +0000401#elif defined(VGP_x86_darwin)
402
njn1a1e95c2009-06-03 06:50:06 +0000403/* We would use VG_DARWIN_SYSNO_TO_KERNEL instead of VG_DARWIN_SYSNO_INDEX
404 except that the former has a C ternary ?: operator which isn't valid in
405 asm code. Both macros give the same results for Unix-class syscalls (which
406 these all are, as identified by the use of 'int 0x80'). */
njnf76d27a2009-05-28 01:53:07 +0000407__attribute__((noinline))
408static UInt local_sys_write_stderr ( HChar* buf, Int n )
409{
410 UInt __res;
411 __asm__ volatile (
412 "movl %2, %%eax\n" /* push n */
413 "pushl %%eax\n"
414 "movl %1, %%eax\n" /* push buf */
415 "pushl %%eax\n"
416 "movl $2, %%eax\n" /* push stderr */
417 "pushl %%eax\n"
418 "movl $"VG_STRINGIFY(VG_DARWIN_SYSNO_INDEX(__NR_write_nocancel))
419 ", %%eax\n"
420 "pushl %%eax\n" /* push fake return address */
421 "int $0x80\n" /* write(stderr, buf, n) */
422 "jnc 1f\n" /* jump if no error */
423 "movl $-1, %%eax\n" /* return -1 if error */
424 "1: "
425 "movl %%eax, %0\n" /* __res = eax */
426 "addl $16, %%esp\n" /* pop x4 */
427 : "=mr" (__res)
428 : "g" (buf), "g" (n)
429 : "eax", "edx", "cc"
430 );
431 return __res;
432}
433
434static UInt local_sys_getpid ( void )
435{
436 UInt __res;
437 __asm__ volatile (
438 "movl $"VG_STRINGIFY(VG_DARWIN_SYSNO_INDEX(__NR_getpid))", %%eax\n"
439 "int $0x80\n" /* getpid() */
440 "movl %%eax, %0\n" /* set __res = eax */
441 : "=mr" (__res)
442 :
443 : "eax", "cc" );
444 return __res;
445}
446
447#elif defined(VGP_amd64_darwin)
448
449__attribute__((noinline))
450static UInt local_sys_write_stderr ( HChar* buf, Int n )
451{
452 UInt __res;
453 __asm__ volatile (
454 "movq $2, %%rdi\n" /* push stderr */
455 "movq %1, %%rsi\n" /* push buf */
456 "movl %2, %%edx\n" /* push n */
njn1a1e95c2009-06-03 06:50:06 +0000457 "movl $"VG_STRINGIFY(VG_DARWIN_SYSNO_FOR_KERNEL(__NR_write_nocancel))
njnf76d27a2009-05-28 01:53:07 +0000458 ", %%eax\n"
459 "syscall\n" /* write(stderr, buf, n) */
460 "jnc 1f\n" /* jump if no error */
461 "movq $-1, %%rax\n" /* return -1 if error */
462 "1: "
463 "movl %%eax, %0\n" /* __res = eax */
464 : "=mr" (__res)
465 : "g" (buf), "g" (n)
466 : "rdi", "rsi", "rdx", "rcx", "rax", "cc" );
467 return __res;
468}
469
470static UInt local_sys_getpid ( void )
471{
472 UInt __res;
473 __asm__ volatile (
njn1a1e95c2009-06-03 06:50:06 +0000474 "movl $"VG_STRINGIFY(VG_DARWIN_SYSNO_FOR_KERNEL(__NR_getpid))", %%eax\n"
njnf76d27a2009-05-28 01:53:07 +0000475 "syscall\n" /* getpid() */
476 "movl %%eax, %0\n" /* set __res = eax */
477 : "=mr" (__res)
478 :
479 : "rax", "rcx", "cc" );
480 return __res;
481}
482
sewardj1cf558c2005-04-25 01:36:56 +0000483#else
sewardj21c6d0f2005-05-02 10:33:44 +0000484# error Unknown platform
sewardj1cf558c2005-04-25 01:36:56 +0000485#endif
486
487
488/* ----- generic ----- */
489
490/* strlen, so we don't need m_libc */
491static Int local_strlen ( const HChar* str )
492{
493 Int i = 0;
494 while (str[i] != 0) i++;
495 return i;
496}
497
498static HChar local_toupper ( HChar c )
499{
500 if (c >= 'a' && c <= 'z')
501 return c + ('A' - 'a');
502 else
503 return c;
504}
505
506/* Emit buf[0 .. n-1] to stderr. Unfortunately platform-specific.
507*/
508static void emit ( HChar* buf, Int n )
509{
510 if (n >= 1)
511 (void)local_sys_write_stderr(buf, n);
512}
513
514
515/*------------------------------------------------------------*/
516/*--- A simple, generic, vprintf implementation. ---*/
517/*------------------------------------------------------------*/
518
519/* -----------------------------------------------
520 Distantly derived from:
521
522 vprintf replacement for Checker.
523 Copyright 1993, 1994, 1995 Tristan Gingold
524 Written September 1993 Tristan Gingold
525 Tristan Gingold, 8 rue Parmentier, F-91120 PALAISEAU, FRANCE
526
527 (Checker itself was GPL'd.)
528 ----------------------------------------------- */
529
530/* Some flags. */
531#define VG_MSG_SIGNED 1 /* The value is signed. */
532#define VG_MSG_ZJUSTIFY 2 /* Must justify with '0'. */
533#define VG_MSG_LJUSTIFY 4 /* Must justify on the left. */
534#define VG_MSG_PAREN 8 /* Parenthesize if present (for %y) */
535#define VG_MSG_COMMA 16 /* Add commas to numbers (for %d, %u) */
barta0b6b2c2008-07-07 06:49:24 +0000536#define VG_MSG_ALTFORMAT 32 /* Convert the value to alternate format */
sewardj1cf558c2005-04-25 01:36:56 +0000537
538/* Copy a string into the buffer. */
539static
540UInt myvprintf_str ( void(*send)(HChar,void*),
541 void* send_arg2,
542 Int flags,
543 Int width,
544 HChar* str,
545 Bool capitalise )
546{
547# define MAYBE_TOUPPER(ch) (capitalise ? local_toupper(ch) : (ch))
548 UInt ret = 0;
549 Int i, extra;
550 Int len = local_strlen(str);
551
552 if (width == 0) {
553 ret += len;
554 for (i = 0; i < len; i++)
555 send(MAYBE_TOUPPER(str[i]), send_arg2);
556 return ret;
557 }
558
559 if (len > width) {
560 ret += width;
561 for (i = 0; i < width; i++)
562 send(MAYBE_TOUPPER(str[i]), send_arg2);
563 return ret;
564 }
565
566 extra = width - len;
567 if (flags & VG_MSG_LJUSTIFY) {
568 ret += extra;
569 for (i = 0; i < extra; i++)
570 send(' ', send_arg2);
571 }
572 ret += len;
573 for (i = 0; i < len; i++)
574 send(MAYBE_TOUPPER(str[i]), send_arg2);
575 if (!(flags & VG_MSG_LJUSTIFY)) {
576 ret += extra;
577 for (i = 0; i < extra; i++)
578 send(' ', send_arg2);
579 }
580
581# undef MAYBE_TOUPPER
582 return ret;
583}
584
585
sewardjdaf77af2005-07-19 14:17:37 +0000586/* Copy a string into the buffer, escaping bad XML chars. */
587static
588UInt myvprintf_str_XML_simplistic ( void(*send)(HChar,void*),
589 void* send_arg2,
590 HChar* str )
591{
592 UInt ret = 0;
593 Int i;
594 Int len = local_strlen(str);
595 HChar* alt;
596
597 for (i = 0; i < len; i++) {
598 switch (str[i]) {
599 case '&': alt = "&amp;"; break;
600 case '<': alt = "&lt;"; break;
601 case '>': alt = "&gt;"; break;
602 default: alt = NULL;
603 }
604
605 if (alt) {
606 while (*alt) {
607 send(*alt, send_arg2);
608 ret++;
609 alt++;
610 }
611 } else {
612 send(str[i], send_arg2);
613 ret++;
614 }
615 }
616
617 return ret;
618}
619
620
sewardj1cf558c2005-04-25 01:36:56 +0000621/* Write P into the buffer according to these args:
622 * If SIGN is true, p is a signed.
623 * BASE is the base.
624 * If WITH_ZERO is true, '0' must be added.
625 * WIDTH is the width of the field.
626 */
627static
628UInt myvprintf_int64 ( void(*send)(HChar,void*),
629 void* send_arg2,
630 Int flags,
631 Int base,
632 Int width,
sewardja44b15f2007-02-16 14:10:24 +0000633 Bool capitalised,
sewardj1cf558c2005-04-25 01:36:56 +0000634 ULong p )
635{
636 HChar buf[40];
637 Int ind = 0;
638 Int i, nc = 0;
639 Bool neg = False;
sewardja44b15f2007-02-16 14:10:24 +0000640 HChar* digits = capitalised ? "0123456789ABCDEF" : "0123456789abcdef";
sewardj1cf558c2005-04-25 01:36:56 +0000641 UInt ret = 0;
642
643 if (base < 2 || base > 16)
644 return ret;
645
646 if ((flags & VG_MSG_SIGNED) && (Long)p < 0) {
647 p = - (Long)p;
648 neg = True;
649 }
650
651 if (p == 0)
652 buf[ind++] = '0';
653 else {
654 while (p > 0) {
655 if (flags & VG_MSG_COMMA && 10 == base &&
656 0 == (ind-nc) % 3 && 0 != ind)
657 {
658 buf[ind++] = ',';
659 nc++;
660 }
661 buf[ind++] = digits[p % base];
662 p /= base;
663 }
664 }
665
666 if (neg)
667 buf[ind++] = '-';
668
669 if (width > 0 && !(flags & VG_MSG_LJUSTIFY)) {
670 for(; ind < width; ind++) {
671 /* vg_assert(ind < 39); */
672 if (ind > 39) {
673 buf[39] = 0;
674 break;
675 }
676 buf[ind] = (flags & VG_MSG_ZJUSTIFY) ? '0': ' ';
677 }
678 }
679
680 /* Reverse copy to buffer. */
681 ret += ind;
682 for (i = ind -1; i >= 0; i--) {
683 send(buf[i], send_arg2);
684 }
685 if (width > 0 && (flags & VG_MSG_LJUSTIFY)) {
686 for(; ind < width; ind++) {
687 ret++;
688 /* Never pad with zeroes on RHS -- changes the value! */
689 send(' ', send_arg2);
690 }
691 }
692 return ret;
693}
694
695
696/* A simple vprintf(). */
697/* EXPORTED */
698UInt
699VG_(debugLog_vprintf) (
700 void(*send)(HChar,void*),
701 void* send_arg2,
702 const HChar* format,
703 va_list vargs
704)
705{
706 UInt ret = 0;
707 Int i;
708 Int flags;
709 Int width;
njn68e46592005-08-26 19:42:27 +0000710 Int n_ls = 0;
sewardja44b15f2007-02-16 14:10:24 +0000711 Bool is_long, caps;
sewardj1cf558c2005-04-25 01:36:56 +0000712
713 /* We assume that vargs has already been initialised by the
714 caller, using va_start, and that the caller will similarly
715 clean up with va_end.
716 */
717
718 for (i = 0; format[i] != 0; i++) {
719 if (format[i] != '%') {
720 send(format[i], send_arg2);
721 ret++;
722 continue;
723 }
724 i++;
725 /* A '%' has been found. Ignore a trailing %. */
726 if (format[i] == 0)
727 break;
728 if (format[i] == '%') {
njn02bc4b82005-05-15 17:28:26 +0000729 /* '%%' is replaced by '%'. */
sewardj1cf558c2005-04-25 01:36:56 +0000730 send('%', send_arg2);
731 ret++;
732 continue;
733 }
734 flags = 0;
njn68e46592005-08-26 19:42:27 +0000735 n_ls = 0;
sewardj1cf558c2005-04-25 01:36:56 +0000736 width = 0; /* length of the field. */
barta0b6b2c2008-07-07 06:49:24 +0000737 while (1) {
738 switch (format[i]) {
739 case '(':
740 flags |= VG_MSG_PAREN;
741 break;
742 case ',':
743 case '\'':
744 /* If ',' or '\'' follows '%', commas will be inserted. */
745 flags |= VG_MSG_COMMA;
746 break;
747 case '-':
748 /* If '-' follows '%', justify on the left. */
749 flags |= VG_MSG_LJUSTIFY;
750 break;
751 case '0':
752 /* If '0' follows '%', pads will be inserted. */
753 flags |= VG_MSG_ZJUSTIFY;
754 break;
755 case '#':
756 /* If '#' follows '%', alternative format will be used. */
757 flags |= VG_MSG_ALTFORMAT;
758 break;
759 default:
760 goto parse_fieldwidth;
761 }
sewardj1cf558c2005-04-25 01:36:56 +0000762 i++;
763 }
barta0b6b2c2008-07-07 06:49:24 +0000764 parse_fieldwidth:
sewardj1cf558c2005-04-25 01:36:56 +0000765 /* Compute the field length. */
766 while (format[i] >= '0' && format[i] <= '9') {
767 width *= 10;
768 width += format[i++] - '0';
769 }
770 while (format[i] == 'l') {
771 i++;
njn68e46592005-08-26 19:42:27 +0000772 n_ls++;
sewardj1cf558c2005-04-25 01:36:56 +0000773 }
774
njn68e46592005-08-26 19:42:27 +0000775 // %d means print a 32-bit integer.
776 // %ld means print a word-size integer.
777 // %lld means print a 64-bit integer.
778 if (0 == n_ls) { is_long = False; }
779 else if (1 == n_ls) { is_long = ( sizeof(void*) == sizeof(Long) ); }
780 else { is_long = True; }
781
sewardj1cf558c2005-04-25 01:36:56 +0000782 switch (format[i]) {
bart042257f2009-07-26 08:40:17 +0000783 case 'o': /* %o */
784 if (flags & VG_MSG_ALTFORMAT) {
785 ret += 2;
786 send('0',send_arg2);
787 }
788 if (is_long)
789 ret += myvprintf_int64(send, send_arg2, flags, 8, width, False,
790 (ULong)(va_arg (vargs, ULong)));
791 else
792 ret += myvprintf_int64(send, send_arg2, flags, 8, width, False,
793 (ULong)(va_arg (vargs, UInt)));
794 break;
sewardj1cf558c2005-04-25 01:36:56 +0000795 case 'd': /* %d */
796 flags |= VG_MSG_SIGNED;
797 if (is_long)
sewardja44b15f2007-02-16 14:10:24 +0000798 ret += myvprintf_int64(send, send_arg2, flags, 10, width, False,
sewardj1cf558c2005-04-25 01:36:56 +0000799 (ULong)(va_arg (vargs, Long)));
800 else
sewardja44b15f2007-02-16 14:10:24 +0000801 ret += myvprintf_int64(send, send_arg2, flags, 10, width, False,
sewardj1cf558c2005-04-25 01:36:56 +0000802 (ULong)(va_arg (vargs, Int)));
803 break;
804 case 'u': /* %u */
805 if (is_long)
sewardja44b15f2007-02-16 14:10:24 +0000806 ret += myvprintf_int64(send, send_arg2, flags, 10, width, False,
sewardj1cf558c2005-04-25 01:36:56 +0000807 (ULong)(va_arg (vargs, ULong)));
808 else
sewardja44b15f2007-02-16 14:10:24 +0000809 ret += myvprintf_int64(send, send_arg2, flags, 10, width, False,
sewardj1cf558c2005-04-25 01:36:56 +0000810 (ULong)(va_arg (vargs, UInt)));
811 break;
812 case 'p': /* %p */
813 ret += 2;
814 send('0',send_arg2);
815 send('x',send_arg2);
sewardja44b15f2007-02-16 14:10:24 +0000816 ret += myvprintf_int64(send, send_arg2, flags, 16, width, True,
sewardj1cf558c2005-04-25 01:36:56 +0000817 (ULong)((UWord)va_arg (vargs, void *)));
818 break;
819 case 'x': /* %x */
sewardja44b15f2007-02-16 14:10:24 +0000820 case 'X': /* %X */
821 caps = toBool(format[i] == 'X');
barta0b6b2c2008-07-07 06:49:24 +0000822 if (flags & VG_MSG_ALTFORMAT) {
823 ret += 2;
824 send('0',send_arg2);
825 send('x',send_arg2);
826 }
sewardj1cf558c2005-04-25 01:36:56 +0000827 if (is_long)
sewardja44b15f2007-02-16 14:10:24 +0000828 ret += myvprintf_int64(send, send_arg2, flags, 16, width, caps,
sewardj1cf558c2005-04-25 01:36:56 +0000829 (ULong)(va_arg (vargs, ULong)));
830 else
sewardja44b15f2007-02-16 14:10:24 +0000831 ret += myvprintf_int64(send, send_arg2, flags, 16, width, caps,
sewardj1cf558c2005-04-25 01:36:56 +0000832 (ULong)(va_arg (vargs, UInt)));
833 break;
834 case 'c': /* %c */
835 ret++;
836 send(va_arg (vargs, int), send_arg2);
837 break;
838 case 's': case 'S': { /* %s */
839 char *str = va_arg (vargs, char *);
840 if (str == (char*) 0) str = "(null)";
841 ret += myvprintf_str(send, send_arg2,
842 flags, width, str, format[i]=='S');
843 break;
844 }
sewardjdaf77af2005-07-19 14:17:37 +0000845 case 't': { /* %t, like %s but escaping chars for XML safety */
846 /* Note: simplistic; ignores field width and flags */
847 char *str = va_arg (vargs, char *);
848 if (str == (char*) 0) str = "(null)";
849 ret += myvprintf_str_XML_simplistic(send, send_arg2, str);
850 break;
851 }
852
sewardj1cf558c2005-04-25 01:36:56 +0000853// case 'y': { /* %y - print symbol */
854// Char buf[100];
855// Char *cp = buf;
856// Addr a = va_arg(vargs, Addr);
857//
858// if (flags & VG_MSG_PAREN)
859// *cp++ = '(';
860// if (VG_(get_fnname_w_offset)(a, cp, sizeof(buf)-4)) {
861// if (flags & VG_MSG_PAREN) {
862// cp += VG_(strlen)(cp);
863// *cp++ = ')';
864// *cp = '\0';
865// }
866// ret += myvprintf_str(send, send_arg2, flags, width, buf, 0);
867// }
868// break;
869// }
870 default:
871 break;
872 }
873 }
874 return ret;
875}
876
877
878/*------------------------------------------------------------*/
879/*--- Debuglog stuff. ---*/
880/*------------------------------------------------------------*/
881
882/* Only print messages whose stated level is less than or equal to
883 this. By default, it makes this entire subsystem silent. */
884
885static Int loglevel = 0;
886
sewardj1cf558c2005-04-25 01:36:56 +0000887/* Module startup. */
sewardj10759312005-05-30 23:52:47 +0000888/* EXPORTED */
sewardj1cf558c2005-04-25 01:36:56 +0000889void VG_(debugLog_startup) ( Int level, HChar* who )
890{
891 if (level < 0) level = 0;
892 if (level > 10) level = 10;
893 loglevel = level;
894 VG_(debugLog)(1, "debuglog",
895 "DebugLog system started by %s, "
896 "level %d logging requested\n",
897 who, loglevel);
898}
899
sewardj10759312005-05-30 23:52:47 +0000900/* Get the logging threshold level, as set by the most recent call to
901 VG_(debugLog_startup), or zero if there have been no such calls so
902 far. */
903/* EXPORTED */
904Int VG_(debugLog_getLevel) ( void )
905{
906 return loglevel;
907}
908
909
sewardj1cf558c2005-04-25 01:36:56 +0000910/* ------------ */
911
912typedef
913 struct {
914 HChar buf[100];
915 Int n;
916 }
917 printf_buf;
918
919static void add_to_buf ( HChar c, void* p )
920{
921 printf_buf* buf = (printf_buf*)p;
922
923 if (buf->n >= 100-10 /*paranoia*/ ) {
924 emit( buf->buf, local_strlen(buf->buf) );
925 buf->n = 0;
926 buf->buf[buf->n] = 0;
927 }
928 buf->buf[buf->n++] = c;
929 buf->buf[buf->n] = 0;
930}
931
932/* Send a logging message. Nothing is output unless 'level'
933 is <= the current loglevel. */
934/* EXPORTED */
935__attribute__((format(__printf__, 3, 4)))
936void VG_(debugLog) ( Int level, const HChar* modulename,
937 const HChar* format, ... )
938{
939 UInt ret, pid;
sewardj45f4e7c2005-09-27 19:20:21 +0000940 Int indent, depth, i;
sewardj1cf558c2005-04-25 01:36:56 +0000941 va_list vargs;
942 printf_buf buf;
sewardja5ebfa92005-04-25 02:04:54 +0000943
sewardj1cf558c2005-04-25 01:36:56 +0000944 if (level > loglevel)
945 return;
946
sewardjd85feff2005-04-25 02:37:56 +0000947 indent = 2*level - 1;
sewardja5ebfa92005-04-25 02:04:54 +0000948 if (indent < 1) indent = 1;
949
sewardj1cf558c2005-04-25 01:36:56 +0000950 buf.n = 0;
951 buf.buf[0] = 0;
952 pid = local_sys_getpid();
sewardj45f4e7c2005-09-27 19:20:21 +0000953
954 // Print one '>' in front of the messages for each level of self-hosting
955 // being performed.
956 depth = RUNNING_ON_VALGRIND;
957 for (i = 0; i < depth; i++) {
958 (void)myvprintf_str ( add_to_buf, &buf, 0, 1, ">", False );
959 }
960
sewardja5ebfa92005-04-25 02:04:54 +0000961 (void)myvprintf_str ( add_to_buf, &buf, 0, 2, "--", False );
sewardja44b15f2007-02-16 14:10:24 +0000962 (void)myvprintf_int64 ( add_to_buf, &buf, 0, 10, 1, False, (ULong)pid );
sewardja5ebfa92005-04-25 02:04:54 +0000963 (void)myvprintf_str ( add_to_buf, &buf, 0, 1, ":", False );
sewardja44b15f2007-02-16 14:10:24 +0000964 (void)myvprintf_int64 ( add_to_buf, &buf, 0, 10, 1, False, (ULong)level );
sewardja5ebfa92005-04-25 02:04:54 +0000965 (void)myvprintf_str ( add_to_buf, &buf, 0, 1, ":", False );
sewardj1cf558c2005-04-25 01:36:56 +0000966 (void)myvprintf_str ( add_to_buf, &buf, 0, 8, (HChar*)modulename, False );
sewardja5ebfa92005-04-25 02:04:54 +0000967 (void)myvprintf_str ( add_to_buf, &buf, 0, indent, "", False );
sewardj1cf558c2005-04-25 01:36:56 +0000968
969 va_start(vargs,format);
970
971 ret = VG_(debugLog_vprintf) ( add_to_buf, &buf, format, vargs );
972
973 if (buf.n > 0) {
974 emit( buf.buf, local_strlen(buf.buf) );
975 }
976
977 va_end(vargs);
978}
979
980
981
982/*--------------------------------------------------------------------*/
983/*--- end m_debuglog.c ---*/
984/*--------------------------------------------------------------------*/