blob: 473771b1c604f12e51c76aa8d6808280d1d1a3e2 [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
sewardj9eecbbb2010-05-03 21:37:12 +000010 Copyright (C) 2000-2010 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
sewardj59570ff2010-01-01 11:59:33 +0000235#elif defined(VGP_arm_linux)
236
237static UInt local_sys_write_stderr ( HChar* buf, Int n )
238{
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
sewardj17edf032006-10-17 01:53:34 +0000271#elif defined(VGP_ppc32_aix5)
272
273static UInt local_sys_write_stderr ( HChar* buf, Int n )
274{
275 /* For some reason gcc-3.3.2 doesn't preserve r31 across the asm
276 even though we state it to be trashed. So use r27 instead. */
277 volatile UInt block[3];
278 block[0] = (UInt)buf;
279 block[1] = n;
280 block[2] = __NR_write;
281 __asm__ __volatile__ (
282 "mr 28,%0\n\t" /* establish base ptr */
283 "mr 27,2\n\t" /* save r2 in r27 */
284 "mflr 30\n\t" /* save lr in r30 */
285
286 "lwz 2,8(28)\n\t" /* set %r2 = __NR_write */
287 "li 3,2\n\t" /* set %r3 = stderr */
288 "lwz 4,0(28)\n\t" /* set %r4 = buf */
289 "lwz 5,4(28)\n\t" /* set %r5 = n */
290
sewardj13552642006-11-10 22:47:27 +0000291 "crorc 6,6,6\n\t"
sewardj17edf032006-10-17 01:53:34 +0000292 ".long 0x48000005\n\t" /* bl .+4 */
293 "mflr 29\n\t"
sewardj13552642006-11-10 22:47:27 +0000294 "addi 29,29,16\n\t"
sewardj17edf032006-10-17 01:53:34 +0000295 "mtlr 29\n\t"
sewardj17edf032006-10-17 01:53:34 +0000296 "sc\n\t" /* write() */
297
298 "stw 3,0(28)\n\t" /* result */
299 "stw 4,4(28)\n\t" /* error? */
300
301 "mr 2,27\n\t" /* restore r2 */
302 "mtlr 30" /* restore lr */
303
304 : /*out*/
305 : /*in*/ "b" (&block[0])
306 : /*trash*/
307 /*temps*/ "r31","r30","r29","r28","r27",
308 /*args*/ "r3","r4","r5","r6","r7","r8","r9","r10",
309 /*paranoia*/ "memory","cc","r0","r1","r11","r12","r13",
310 "xer","ctr","cr0","cr1","cr2","cr3",
311 "cr4","cr5","cr6","cr7"
312 );
313 if (block[1] != 0)
314 return -1;
315 else
316 return block[0];
317}
318
319static UInt local_sys_getpid ( void )
320{
321 /* For some reason gcc-3.3.2 doesn't preserve r31 across the asm
322 even though we state it to be trashed. So use r27 instead. */
323 volatile UInt block[1];
324 block[0] = __NR_getpid;
325 __asm__ __volatile__ (
326 "mr 28,%0\n\t" /* establish base ptr */
327 "mr 27,2\n\t" /* save r2 in r27 */
328 "mflr 30\n\t" /* save lr in r30 */
329
330 "lwz 2,0(28)\n\t" /* set %r2 = __NR_getpid */
331
sewardj13552642006-11-10 22:47:27 +0000332 "crorc 6,6,6\n\t"
sewardj17edf032006-10-17 01:53:34 +0000333 ".long 0x48000005\n\t" /* bl .+4 */
334 "mflr 29\n\t"
sewardj13552642006-11-10 22:47:27 +0000335 "addi 29,29,16\n\t"
sewardj17edf032006-10-17 01:53:34 +0000336 "mtlr 29\n\t"
sewardj17edf032006-10-17 01:53:34 +0000337 "sc\n\t" /* getpid() */
338
339 "stw 3,0(28)\n\t" /* result -> block[0] */
340
341 "mr 2,27\n\t" /* restore r2 */
342 "mtlr 30" /* restore lr */
343
344 : /*out*/
345 : /*in*/ "b" (&block[0])
346 : /*trash*/
347 /*temps*/ "r31","r30","r29","r28","r27",
348 /*args*/ "r3","r4","r5","r6","r7","r8","r9","r10",
349 /*paranoia*/ "memory","cc","r0","r1","r11","r12","r13",
350 "xer","ctr","cr0","cr1","cr2","cr3",
351 "cr4","cr5","cr6","cr7"
352 );
353 return block[0];
354}
355
356#elif defined(VGP_ppc64_aix5)
357
358static UInt local_sys_write_stderr ( HChar* buf, Int n )
359{
360 volatile ULong block[3];
361 block[0] = (ULong)buf;
362 block[1] = n;
363 block[2] = (ULong)__NR_write;
364 __asm__ __volatile__ (
365 "mr 28,%0\n\t" /* establish base ptr */
366 "mr 27,2\n\t" /* save r2 in r27 */
367 "mflr 30\n\t" /* save lr in r30 */
368
369 "ld 2,16(28)\n\t" /* set %r2 = __NR_write */
370 "li 3,2\n\t" /* set %r3 = stderr */
371 "ld 4,0(28)\n\t" /* set %r4 = buf */
372 "ld 5,8(28)\n\t" /* set %r5 = n */
373
sewardj13552642006-11-10 22:47:27 +0000374 "crorc 6,6,6\n\t"
sewardj17edf032006-10-17 01:53:34 +0000375 ".long 0x48000005\n\t" /* bl .+4 */
376 "mflr 29\n\t"
sewardj13552642006-11-10 22:47:27 +0000377 "addi 29,29,16\n\t"
sewardj17edf032006-10-17 01:53:34 +0000378 "mtlr 29\n\t"
sewardj17edf032006-10-17 01:53:34 +0000379 "sc\n\t" /* write() */
380
381 "std 3,0(28)\n\t" /* result */
382 "std 4,8(28)\n\t" /* error? */
383
384 "mr 2,27\n\t" /* restore r2 */
385 "mtlr 30" /* restore lr */
386
387 : /*out*/
388 : /*in*/ "b" (&block[0])
389 : /*trash*/
390 /*temps*/ "r31","r30","r29","r28","r27",
391 /*args*/ "r3","r4","r5","r6","r7","r8","r9","r10",
392 /*paranoia*/ "memory","cc","r0","r1","r11","r12","r13",
393 "xer","ctr","cr0","cr1","cr2","cr3",
394 "cr4","cr5","cr6","cr7"
395 );
396 if (block[1] != 0)
397 return (UInt)-1;
398 else
399 return (UInt)block[0];
400}
401
402static UInt local_sys_getpid ( void )
403{
404 volatile ULong block[1];
405 block[0] = __NR_getpid;
406 __asm__ __volatile__ (
407 "mr 28,%0\n\t" /* establish base ptr */
408 "mr 27,2\n\t" /* save r2 in r27 */
409 "mflr 30\n\t" /* save lr in r30 */
410
411 "ld 2,0(28)\n\t" /* set %r2 = __NR_getpid */
412
sewardj13552642006-11-10 22:47:27 +0000413 "crorc 6,6,6\n\t"
sewardj17edf032006-10-17 01:53:34 +0000414 ".long 0x48000005\n\t" /* bl .+4 */
415 "mflr 29\n\t"
sewardj13552642006-11-10 22:47:27 +0000416 "addi 29,29,16\n\t"
sewardj17edf032006-10-17 01:53:34 +0000417 "mtlr 29\n\t"
sewardj17edf032006-10-17 01:53:34 +0000418 "sc\n\t" /* getpid() */
419
420 "std 3,0(28)\n\t" /* result -> block[0] */
421
422 "mr 2,27\n\t" /* restore r2 */
423 "mtlr 30" /* restore lr */
424
425 : /*out*/
426 : /*in*/ "b" (&block[0])
427 : /*trash*/
428 /*temps*/ "r31","r30","r29","r28","r27",
429 /*args*/ "r3","r4","r5","r6","r7","r8","r9","r10",
430 /*paranoia*/ "memory","cc","r0","r1","r11","r12","r13",
431 "xer","ctr","cr0","cr1","cr2","cr3",
432 "cr4","cr5","cr6","cr7"
433 );
434 return (UInt)block[0];
435}
436
njnf76d27a2009-05-28 01:53:07 +0000437#elif defined(VGP_x86_darwin)
438
njn1a1e95c2009-06-03 06:50:06 +0000439/* We would use VG_DARWIN_SYSNO_TO_KERNEL instead of VG_DARWIN_SYSNO_INDEX
440 except that the former has a C ternary ?: operator which isn't valid in
441 asm code. Both macros give the same results for Unix-class syscalls (which
442 these all are, as identified by the use of 'int 0x80'). */
njnf76d27a2009-05-28 01:53:07 +0000443__attribute__((noinline))
444static UInt local_sys_write_stderr ( HChar* buf, Int n )
445{
446 UInt __res;
447 __asm__ volatile (
448 "movl %2, %%eax\n" /* push n */
449 "pushl %%eax\n"
450 "movl %1, %%eax\n" /* push buf */
451 "pushl %%eax\n"
452 "movl $2, %%eax\n" /* push stderr */
453 "pushl %%eax\n"
454 "movl $"VG_STRINGIFY(VG_DARWIN_SYSNO_INDEX(__NR_write_nocancel))
455 ", %%eax\n"
456 "pushl %%eax\n" /* push fake return address */
457 "int $0x80\n" /* write(stderr, buf, n) */
458 "jnc 1f\n" /* jump if no error */
459 "movl $-1, %%eax\n" /* return -1 if error */
460 "1: "
461 "movl %%eax, %0\n" /* __res = eax */
462 "addl $16, %%esp\n" /* pop x4 */
463 : "=mr" (__res)
464 : "g" (buf), "g" (n)
465 : "eax", "edx", "cc"
466 );
467 return __res;
468}
469
470static UInt local_sys_getpid ( void )
471{
472 UInt __res;
473 __asm__ volatile (
474 "movl $"VG_STRINGIFY(VG_DARWIN_SYSNO_INDEX(__NR_getpid))", %%eax\n"
475 "int $0x80\n" /* getpid() */
476 "movl %%eax, %0\n" /* set __res = eax */
477 : "=mr" (__res)
478 :
479 : "eax", "cc" );
480 return __res;
481}
482
483#elif defined(VGP_amd64_darwin)
484
485__attribute__((noinline))
486static UInt local_sys_write_stderr ( HChar* buf, Int n )
487{
488 UInt __res;
489 __asm__ volatile (
490 "movq $2, %%rdi\n" /* push stderr */
491 "movq %1, %%rsi\n" /* push buf */
492 "movl %2, %%edx\n" /* push n */
njn1a1e95c2009-06-03 06:50:06 +0000493 "movl $"VG_STRINGIFY(VG_DARWIN_SYSNO_FOR_KERNEL(__NR_write_nocancel))
njnf76d27a2009-05-28 01:53:07 +0000494 ", %%eax\n"
495 "syscall\n" /* write(stderr, buf, n) */
496 "jnc 1f\n" /* jump if no error */
497 "movq $-1, %%rax\n" /* return -1 if error */
498 "1: "
499 "movl %%eax, %0\n" /* __res = eax */
500 : "=mr" (__res)
501 : "g" (buf), "g" (n)
502 : "rdi", "rsi", "rdx", "rcx", "rax", "cc" );
503 return __res;
504}
505
506static UInt local_sys_getpid ( void )
507{
508 UInt __res;
509 __asm__ volatile (
njn1a1e95c2009-06-03 06:50:06 +0000510 "movl $"VG_STRINGIFY(VG_DARWIN_SYSNO_FOR_KERNEL(__NR_getpid))", %%eax\n"
njnf76d27a2009-05-28 01:53:07 +0000511 "syscall\n" /* getpid() */
512 "movl %%eax, %0\n" /* set __res = eax */
513 : "=mr" (__res)
514 :
515 : "rax", "rcx", "cc" );
516 return __res;
517}
518
sewardj1cf558c2005-04-25 01:36:56 +0000519#else
sewardj21c6d0f2005-05-02 10:33:44 +0000520# error Unknown platform
sewardj1cf558c2005-04-25 01:36:56 +0000521#endif
522
523
524/* ----- generic ----- */
525
526/* strlen, so we don't need m_libc */
527static Int local_strlen ( const HChar* str )
528{
529 Int i = 0;
530 while (str[i] != 0) i++;
531 return i;
532}
533
534static HChar local_toupper ( HChar c )
535{
536 if (c >= 'a' && c <= 'z')
537 return c + ('A' - 'a');
538 else
539 return c;
540}
541
542/* Emit buf[0 .. n-1] to stderr. Unfortunately platform-specific.
543*/
544static void emit ( HChar* buf, Int n )
545{
546 if (n >= 1)
547 (void)local_sys_write_stderr(buf, n);
548}
549
550
551/*------------------------------------------------------------*/
552/*--- A simple, generic, vprintf implementation. ---*/
553/*------------------------------------------------------------*/
554
555/* -----------------------------------------------
556 Distantly derived from:
557
558 vprintf replacement for Checker.
559 Copyright 1993, 1994, 1995 Tristan Gingold
560 Written September 1993 Tristan Gingold
561 Tristan Gingold, 8 rue Parmentier, F-91120 PALAISEAU, FRANCE
562
563 (Checker itself was GPL'd.)
564 ----------------------------------------------- */
565
566/* Some flags. */
567#define VG_MSG_SIGNED 1 /* The value is signed. */
568#define VG_MSG_ZJUSTIFY 2 /* Must justify with '0'. */
569#define VG_MSG_LJUSTIFY 4 /* Must justify on the left. */
570#define VG_MSG_PAREN 8 /* Parenthesize if present (for %y) */
571#define VG_MSG_COMMA 16 /* Add commas to numbers (for %d, %u) */
barta0b6b2c2008-07-07 06:49:24 +0000572#define VG_MSG_ALTFORMAT 32 /* Convert the value to alternate format */
sewardj1cf558c2005-04-25 01:36:56 +0000573
574/* Copy a string into the buffer. */
575static
576UInt myvprintf_str ( void(*send)(HChar,void*),
577 void* send_arg2,
578 Int flags,
579 Int width,
580 HChar* str,
581 Bool capitalise )
582{
583# define MAYBE_TOUPPER(ch) (capitalise ? local_toupper(ch) : (ch))
584 UInt ret = 0;
585 Int i, extra;
586 Int len = local_strlen(str);
587
588 if (width == 0) {
589 ret += len;
590 for (i = 0; i < len; i++)
591 send(MAYBE_TOUPPER(str[i]), send_arg2);
592 return ret;
593 }
594
595 if (len > width) {
596 ret += width;
597 for (i = 0; i < width; i++)
598 send(MAYBE_TOUPPER(str[i]), send_arg2);
599 return ret;
600 }
601
602 extra = width - len;
603 if (flags & VG_MSG_LJUSTIFY) {
604 ret += extra;
605 for (i = 0; i < extra; i++)
606 send(' ', send_arg2);
607 }
608 ret += len;
609 for (i = 0; i < len; i++)
610 send(MAYBE_TOUPPER(str[i]), send_arg2);
611 if (!(flags & VG_MSG_LJUSTIFY)) {
612 ret += extra;
613 for (i = 0; i < extra; i++)
614 send(' ', send_arg2);
615 }
616
617# undef MAYBE_TOUPPER
618 return ret;
619}
620
621
sewardjdaf77af2005-07-19 14:17:37 +0000622/* Copy a string into the buffer, escaping bad XML chars. */
623static
624UInt myvprintf_str_XML_simplistic ( void(*send)(HChar,void*),
625 void* send_arg2,
626 HChar* str )
627{
628 UInt ret = 0;
629 Int i;
630 Int len = local_strlen(str);
631 HChar* alt;
632
633 for (i = 0; i < len; i++) {
634 switch (str[i]) {
635 case '&': alt = "&amp;"; break;
636 case '<': alt = "&lt;"; break;
637 case '>': alt = "&gt;"; break;
638 default: alt = NULL;
639 }
640
641 if (alt) {
642 while (*alt) {
643 send(*alt, send_arg2);
644 ret++;
645 alt++;
646 }
647 } else {
648 send(str[i], send_arg2);
649 ret++;
650 }
651 }
652
653 return ret;
654}
655
656
sewardj1cf558c2005-04-25 01:36:56 +0000657/* Write P into the buffer according to these args:
658 * If SIGN is true, p is a signed.
659 * BASE is the base.
660 * If WITH_ZERO is true, '0' must be added.
661 * WIDTH is the width of the field.
662 */
663static
664UInt myvprintf_int64 ( void(*send)(HChar,void*),
665 void* send_arg2,
666 Int flags,
667 Int base,
668 Int width,
sewardja44b15f2007-02-16 14:10:24 +0000669 Bool capitalised,
sewardj1cf558c2005-04-25 01:36:56 +0000670 ULong p )
671{
672 HChar buf[40];
673 Int ind = 0;
674 Int i, nc = 0;
675 Bool neg = False;
sewardja44b15f2007-02-16 14:10:24 +0000676 HChar* digits = capitalised ? "0123456789ABCDEF" : "0123456789abcdef";
sewardj1cf558c2005-04-25 01:36:56 +0000677 UInt ret = 0;
678
679 if (base < 2 || base > 16)
680 return ret;
681
682 if ((flags & VG_MSG_SIGNED) && (Long)p < 0) {
683 p = - (Long)p;
684 neg = True;
685 }
686
687 if (p == 0)
688 buf[ind++] = '0';
689 else {
690 while (p > 0) {
691 if (flags & VG_MSG_COMMA && 10 == base &&
692 0 == (ind-nc) % 3 && 0 != ind)
693 {
694 buf[ind++] = ',';
695 nc++;
696 }
697 buf[ind++] = digits[p % base];
698 p /= base;
699 }
700 }
701
702 if (neg)
703 buf[ind++] = '-';
704
705 if (width > 0 && !(flags & VG_MSG_LJUSTIFY)) {
706 for(; ind < width; ind++) {
707 /* vg_assert(ind < 39); */
708 if (ind > 39) {
709 buf[39] = 0;
710 break;
711 }
712 buf[ind] = (flags & VG_MSG_ZJUSTIFY) ? '0': ' ';
713 }
714 }
715
716 /* Reverse copy to buffer. */
717 ret += ind;
718 for (i = ind -1; i >= 0; i--) {
719 send(buf[i], send_arg2);
720 }
721 if (width > 0 && (flags & VG_MSG_LJUSTIFY)) {
722 for(; ind < width; ind++) {
723 ret++;
724 /* Never pad with zeroes on RHS -- changes the value! */
725 send(' ', send_arg2);
726 }
727 }
728 return ret;
729}
730
731
732/* A simple vprintf(). */
733/* EXPORTED */
734UInt
735VG_(debugLog_vprintf) (
736 void(*send)(HChar,void*),
737 void* send_arg2,
738 const HChar* format,
739 va_list vargs
740)
741{
742 UInt ret = 0;
743 Int i;
744 Int flags;
745 Int width;
njn68e46592005-08-26 19:42:27 +0000746 Int n_ls = 0;
sewardja44b15f2007-02-16 14:10:24 +0000747 Bool is_long, caps;
sewardj1cf558c2005-04-25 01:36:56 +0000748
749 /* We assume that vargs has already been initialised by the
750 caller, using va_start, and that the caller will similarly
751 clean up with va_end.
752 */
753
754 for (i = 0; format[i] != 0; i++) {
755 if (format[i] != '%') {
756 send(format[i], send_arg2);
757 ret++;
758 continue;
759 }
760 i++;
761 /* A '%' has been found. Ignore a trailing %. */
762 if (format[i] == 0)
763 break;
764 if (format[i] == '%') {
njn02bc4b82005-05-15 17:28:26 +0000765 /* '%%' is replaced by '%'. */
sewardj1cf558c2005-04-25 01:36:56 +0000766 send('%', send_arg2);
767 ret++;
768 continue;
769 }
770 flags = 0;
njn68e46592005-08-26 19:42:27 +0000771 n_ls = 0;
sewardj1cf558c2005-04-25 01:36:56 +0000772 width = 0; /* length of the field. */
barta0b6b2c2008-07-07 06:49:24 +0000773 while (1) {
774 switch (format[i]) {
775 case '(':
776 flags |= VG_MSG_PAREN;
777 break;
778 case ',':
779 case '\'':
780 /* If ',' or '\'' follows '%', commas will be inserted. */
781 flags |= VG_MSG_COMMA;
782 break;
783 case '-':
784 /* If '-' follows '%', justify on the left. */
785 flags |= VG_MSG_LJUSTIFY;
786 break;
787 case '0':
788 /* If '0' follows '%', pads will be inserted. */
789 flags |= VG_MSG_ZJUSTIFY;
790 break;
791 case '#':
792 /* If '#' follows '%', alternative format will be used. */
793 flags |= VG_MSG_ALTFORMAT;
794 break;
795 default:
796 goto parse_fieldwidth;
797 }
sewardj1cf558c2005-04-25 01:36:56 +0000798 i++;
799 }
barta0b6b2c2008-07-07 06:49:24 +0000800 parse_fieldwidth:
sewardj1cf558c2005-04-25 01:36:56 +0000801 /* Compute the field length. */
802 while (format[i] >= '0' && format[i] <= '9') {
803 width *= 10;
804 width += format[i++] - '0';
805 }
806 while (format[i] == 'l') {
807 i++;
njn68e46592005-08-26 19:42:27 +0000808 n_ls++;
sewardj1cf558c2005-04-25 01:36:56 +0000809 }
810
njn68e46592005-08-26 19:42:27 +0000811 // %d means print a 32-bit integer.
812 // %ld means print a word-size integer.
813 // %lld means print a 64-bit integer.
814 if (0 == n_ls) { is_long = False; }
815 else if (1 == n_ls) { is_long = ( sizeof(void*) == sizeof(Long) ); }
816 else { is_long = True; }
817
sewardj1cf558c2005-04-25 01:36:56 +0000818 switch (format[i]) {
bart042257f2009-07-26 08:40:17 +0000819 case 'o': /* %o */
820 if (flags & VG_MSG_ALTFORMAT) {
821 ret += 2;
822 send('0',send_arg2);
823 }
824 if (is_long)
825 ret += myvprintf_int64(send, send_arg2, flags, 8, width, False,
826 (ULong)(va_arg (vargs, ULong)));
827 else
828 ret += myvprintf_int64(send, send_arg2, flags, 8, width, False,
829 (ULong)(va_arg (vargs, UInt)));
830 break;
sewardj1cf558c2005-04-25 01:36:56 +0000831 case 'd': /* %d */
832 flags |= VG_MSG_SIGNED;
833 if (is_long)
sewardja44b15f2007-02-16 14:10:24 +0000834 ret += myvprintf_int64(send, send_arg2, flags, 10, width, False,
sewardj1cf558c2005-04-25 01:36:56 +0000835 (ULong)(va_arg (vargs, Long)));
836 else
sewardja44b15f2007-02-16 14:10:24 +0000837 ret += myvprintf_int64(send, send_arg2, flags, 10, width, False,
sewardj1cf558c2005-04-25 01:36:56 +0000838 (ULong)(va_arg (vargs, Int)));
839 break;
840 case 'u': /* %u */
841 if (is_long)
sewardja44b15f2007-02-16 14:10:24 +0000842 ret += myvprintf_int64(send, send_arg2, flags, 10, width, False,
sewardj1cf558c2005-04-25 01:36:56 +0000843 (ULong)(va_arg (vargs, ULong)));
844 else
sewardja44b15f2007-02-16 14:10:24 +0000845 ret += myvprintf_int64(send, send_arg2, flags, 10, width, False,
sewardj1cf558c2005-04-25 01:36:56 +0000846 (ULong)(va_arg (vargs, UInt)));
847 break;
848 case 'p': /* %p */
849 ret += 2;
850 send('0',send_arg2);
851 send('x',send_arg2);
sewardja44b15f2007-02-16 14:10:24 +0000852 ret += myvprintf_int64(send, send_arg2, flags, 16, width, True,
sewardj1cf558c2005-04-25 01:36:56 +0000853 (ULong)((UWord)va_arg (vargs, void *)));
854 break;
855 case 'x': /* %x */
sewardja44b15f2007-02-16 14:10:24 +0000856 case 'X': /* %X */
857 caps = toBool(format[i] == 'X');
barta0b6b2c2008-07-07 06:49:24 +0000858 if (flags & VG_MSG_ALTFORMAT) {
859 ret += 2;
860 send('0',send_arg2);
861 send('x',send_arg2);
862 }
sewardj1cf558c2005-04-25 01:36:56 +0000863 if (is_long)
sewardja44b15f2007-02-16 14:10:24 +0000864 ret += myvprintf_int64(send, send_arg2, flags, 16, width, caps,
sewardj1cf558c2005-04-25 01:36:56 +0000865 (ULong)(va_arg (vargs, ULong)));
866 else
sewardja44b15f2007-02-16 14:10:24 +0000867 ret += myvprintf_int64(send, send_arg2, flags, 16, width, caps,
sewardj1cf558c2005-04-25 01:36:56 +0000868 (ULong)(va_arg (vargs, UInt)));
869 break;
870 case 'c': /* %c */
871 ret++;
872 send(va_arg (vargs, int), send_arg2);
873 break;
874 case 's': case 'S': { /* %s */
875 char *str = va_arg (vargs, char *);
876 if (str == (char*) 0) str = "(null)";
877 ret += myvprintf_str(send, send_arg2,
878 flags, width, str, format[i]=='S');
879 break;
880 }
sewardjdaf77af2005-07-19 14:17:37 +0000881 case 't': { /* %t, like %s but escaping chars for XML safety */
882 /* Note: simplistic; ignores field width and flags */
883 char *str = va_arg (vargs, char *);
884 if (str == (char*) 0) str = "(null)";
885 ret += myvprintf_str_XML_simplistic(send, send_arg2, str);
886 break;
887 }
888
sewardj1cf558c2005-04-25 01:36:56 +0000889// case 'y': { /* %y - print symbol */
890// Char buf[100];
891// Char *cp = buf;
892// Addr a = va_arg(vargs, Addr);
893//
894// if (flags & VG_MSG_PAREN)
895// *cp++ = '(';
896// if (VG_(get_fnname_w_offset)(a, cp, sizeof(buf)-4)) {
897// if (flags & VG_MSG_PAREN) {
898// cp += VG_(strlen)(cp);
899// *cp++ = ')';
900// *cp = '\0';
901// }
902// ret += myvprintf_str(send, send_arg2, flags, width, buf, 0);
903// }
904// break;
905// }
906 default:
907 break;
908 }
909 }
910 return ret;
911}
912
913
914/*------------------------------------------------------------*/
915/*--- Debuglog stuff. ---*/
916/*------------------------------------------------------------*/
917
918/* Only print messages whose stated level is less than or equal to
919 this. By default, it makes this entire subsystem silent. */
920
921static Int loglevel = 0;
922
sewardj1cf558c2005-04-25 01:36:56 +0000923/* Module startup. */
sewardj10759312005-05-30 23:52:47 +0000924/* EXPORTED */
sewardj1cf558c2005-04-25 01:36:56 +0000925void VG_(debugLog_startup) ( Int level, HChar* who )
926{
927 if (level < 0) level = 0;
928 if (level > 10) level = 10;
929 loglevel = level;
930 VG_(debugLog)(1, "debuglog",
931 "DebugLog system started by %s, "
932 "level %d logging requested\n",
933 who, loglevel);
934}
935
sewardj10759312005-05-30 23:52:47 +0000936/* Get the logging threshold level, as set by the most recent call to
937 VG_(debugLog_startup), or zero if there have been no such calls so
938 far. */
939/* EXPORTED */
940Int VG_(debugLog_getLevel) ( void )
941{
942 return loglevel;
943}
944
945
sewardj1cf558c2005-04-25 01:36:56 +0000946/* ------------ */
947
948typedef
949 struct {
950 HChar buf[100];
951 Int n;
952 }
953 printf_buf;
954
955static void add_to_buf ( HChar c, void* p )
956{
957 printf_buf* buf = (printf_buf*)p;
958
959 if (buf->n >= 100-10 /*paranoia*/ ) {
960 emit( buf->buf, local_strlen(buf->buf) );
961 buf->n = 0;
962 buf->buf[buf->n] = 0;
963 }
964 buf->buf[buf->n++] = c;
965 buf->buf[buf->n] = 0;
966}
967
968/* Send a logging message. Nothing is output unless 'level'
969 is <= the current loglevel. */
970/* EXPORTED */
sewardj1cf558c2005-04-25 01:36:56 +0000971void VG_(debugLog) ( Int level, const HChar* modulename,
972 const HChar* format, ... )
973{
974 UInt ret, pid;
sewardj45f4e7c2005-09-27 19:20:21 +0000975 Int indent, depth, i;
sewardj1cf558c2005-04-25 01:36:56 +0000976 va_list vargs;
977 printf_buf buf;
sewardja5ebfa92005-04-25 02:04:54 +0000978
sewardj1cf558c2005-04-25 01:36:56 +0000979 if (level > loglevel)
980 return;
981
sewardjd85feff2005-04-25 02:37:56 +0000982 indent = 2*level - 1;
sewardja5ebfa92005-04-25 02:04:54 +0000983 if (indent < 1) indent = 1;
984
sewardj1cf558c2005-04-25 01:36:56 +0000985 buf.n = 0;
986 buf.buf[0] = 0;
987 pid = local_sys_getpid();
sewardj45f4e7c2005-09-27 19:20:21 +0000988
989 // Print one '>' in front of the messages for each level of self-hosting
990 // being performed.
991 depth = RUNNING_ON_VALGRIND;
992 for (i = 0; i < depth; i++) {
993 (void)myvprintf_str ( add_to_buf, &buf, 0, 1, ">", False );
994 }
995
sewardja5ebfa92005-04-25 02:04:54 +0000996 (void)myvprintf_str ( add_to_buf, &buf, 0, 2, "--", False );
sewardja44b15f2007-02-16 14:10:24 +0000997 (void)myvprintf_int64 ( add_to_buf, &buf, 0, 10, 1, False, (ULong)pid );
sewardja5ebfa92005-04-25 02:04:54 +0000998 (void)myvprintf_str ( add_to_buf, &buf, 0, 1, ":", False );
sewardja44b15f2007-02-16 14:10:24 +0000999 (void)myvprintf_int64 ( add_to_buf, &buf, 0, 10, 1, False, (ULong)level );
sewardja5ebfa92005-04-25 02:04:54 +00001000 (void)myvprintf_str ( add_to_buf, &buf, 0, 1, ":", False );
sewardj1cf558c2005-04-25 01:36:56 +00001001 (void)myvprintf_str ( add_to_buf, &buf, 0, 8, (HChar*)modulename, False );
sewardja5ebfa92005-04-25 02:04:54 +00001002 (void)myvprintf_str ( add_to_buf, &buf, 0, indent, "", False );
sewardj1cf558c2005-04-25 01:36:56 +00001003
1004 va_start(vargs,format);
1005
1006 ret = VG_(debugLog_vprintf) ( add_to_buf, &buf, format, vargs );
1007
1008 if (buf.n > 0) {
1009 emit( buf.buf, local_strlen(buf.buf) );
1010 }
1011
1012 va_end(vargs);
1013}
1014
1015
1016
1017/*--------------------------------------------------------------------*/
1018/*--- end m_debuglog.c ---*/
1019/*--------------------------------------------------------------------*/