blob: 257d9468483d8f4b236483d48de761c36b3394cf [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
sewardjb5b87402011-03-07 16:05:35 +0000519#elif defined(VGP_s390x_linux)
520static UInt local_sys_write_stderr ( HChar* buf, Int n )
521{
522 register Int r2 asm("2") = 2; /* file descriptor STDERR */
523 register HChar* r3 asm("3") = buf;
524 register ULong r4 asm("4") = n;
525 register ULong r2_res asm("2");
526 ULong __res;
527
528 __asm__ __volatile__ (
529 "svc %b1\n"
530 : "=d" (r2_res)
531 : "i" (__NR_write),
532 "0" (r2),
533 "d" (r3),
534 "d" (r4)
535 : "cc", "memory");
536 __res = r2_res;
537
538 if (__res >= (ULong)(-125))
539 __res = -1;
540 return (UInt)(__res);
541}
542
543static UInt local_sys_getpid ( void )
544{
545 register ULong r2 asm("2");
546 ULong __res;
547
548 __asm__ __volatile__ (
549 "svc %b1\n"
550 : "=d" (r2)
551 : "i" (__NR_getpid)
552 : "cc", "memory");
553 __res = r2;
554
555 if (__res >= (ULong)(-125))
556 __res = -1;
557 return (UInt)(__res);
558}
559
560
sewardj1cf558c2005-04-25 01:36:56 +0000561#else
sewardj21c6d0f2005-05-02 10:33:44 +0000562# error Unknown platform
sewardj1cf558c2005-04-25 01:36:56 +0000563#endif
564
565
566/* ----- generic ----- */
567
568/* strlen, so we don't need m_libc */
569static Int local_strlen ( const HChar* str )
570{
571 Int i = 0;
572 while (str[i] != 0) i++;
573 return i;
574}
575
576static HChar local_toupper ( HChar c )
577{
578 if (c >= 'a' && c <= 'z')
579 return c + ('A' - 'a');
580 else
581 return c;
582}
583
584/* Emit buf[0 .. n-1] to stderr. Unfortunately platform-specific.
585*/
586static void emit ( HChar* buf, Int n )
587{
588 if (n >= 1)
589 (void)local_sys_write_stderr(buf, n);
590}
591
592
593/*------------------------------------------------------------*/
594/*--- A simple, generic, vprintf implementation. ---*/
595/*------------------------------------------------------------*/
596
597/* -----------------------------------------------
598 Distantly derived from:
599
600 vprintf replacement for Checker.
601 Copyright 1993, 1994, 1995 Tristan Gingold
602 Written September 1993 Tristan Gingold
603 Tristan Gingold, 8 rue Parmentier, F-91120 PALAISEAU, FRANCE
604
605 (Checker itself was GPL'd.)
606 ----------------------------------------------- */
607
608/* Some flags. */
609#define VG_MSG_SIGNED 1 /* The value is signed. */
610#define VG_MSG_ZJUSTIFY 2 /* Must justify with '0'. */
611#define VG_MSG_LJUSTIFY 4 /* Must justify on the left. */
612#define VG_MSG_PAREN 8 /* Parenthesize if present (for %y) */
613#define VG_MSG_COMMA 16 /* Add commas to numbers (for %d, %u) */
barta0b6b2c2008-07-07 06:49:24 +0000614#define VG_MSG_ALTFORMAT 32 /* Convert the value to alternate format */
sewardj1cf558c2005-04-25 01:36:56 +0000615
616/* Copy a string into the buffer. */
617static
618UInt myvprintf_str ( void(*send)(HChar,void*),
619 void* send_arg2,
620 Int flags,
621 Int width,
622 HChar* str,
623 Bool capitalise )
624{
625# define MAYBE_TOUPPER(ch) (capitalise ? local_toupper(ch) : (ch))
626 UInt ret = 0;
627 Int i, extra;
628 Int len = local_strlen(str);
629
630 if (width == 0) {
631 ret += len;
632 for (i = 0; i < len; i++)
633 send(MAYBE_TOUPPER(str[i]), send_arg2);
634 return ret;
635 }
636
637 if (len > width) {
638 ret += width;
639 for (i = 0; i < width; i++)
640 send(MAYBE_TOUPPER(str[i]), send_arg2);
641 return ret;
642 }
643
644 extra = width - len;
645 if (flags & VG_MSG_LJUSTIFY) {
646 ret += extra;
647 for (i = 0; i < extra; i++)
648 send(' ', send_arg2);
649 }
650 ret += len;
651 for (i = 0; i < len; i++)
652 send(MAYBE_TOUPPER(str[i]), send_arg2);
653 if (!(flags & VG_MSG_LJUSTIFY)) {
654 ret += extra;
655 for (i = 0; i < extra; i++)
656 send(' ', send_arg2);
657 }
658
659# undef MAYBE_TOUPPER
660 return ret;
661}
662
663
sewardjdaf77af2005-07-19 14:17:37 +0000664/* Copy a string into the buffer, escaping bad XML chars. */
665static
666UInt myvprintf_str_XML_simplistic ( void(*send)(HChar,void*),
667 void* send_arg2,
668 HChar* str )
669{
670 UInt ret = 0;
671 Int i;
672 Int len = local_strlen(str);
673 HChar* alt;
674
675 for (i = 0; i < len; i++) {
676 switch (str[i]) {
677 case '&': alt = "&amp;"; break;
678 case '<': alt = "&lt;"; break;
679 case '>': alt = "&gt;"; break;
680 default: alt = NULL;
681 }
682
683 if (alt) {
684 while (*alt) {
685 send(*alt, send_arg2);
686 ret++;
687 alt++;
688 }
689 } else {
690 send(str[i], send_arg2);
691 ret++;
692 }
693 }
694
695 return ret;
696}
697
698
sewardj1cf558c2005-04-25 01:36:56 +0000699/* Write P into the buffer according to these args:
700 * If SIGN is true, p is a signed.
701 * BASE is the base.
702 * If WITH_ZERO is true, '0' must be added.
703 * WIDTH is the width of the field.
704 */
705static
706UInt myvprintf_int64 ( void(*send)(HChar,void*),
707 void* send_arg2,
708 Int flags,
709 Int base,
710 Int width,
sewardja44b15f2007-02-16 14:10:24 +0000711 Bool capitalised,
sewardj1cf558c2005-04-25 01:36:56 +0000712 ULong p )
713{
714 HChar buf[40];
715 Int ind = 0;
716 Int i, nc = 0;
717 Bool neg = False;
sewardja44b15f2007-02-16 14:10:24 +0000718 HChar* digits = capitalised ? "0123456789ABCDEF" : "0123456789abcdef";
sewardj1cf558c2005-04-25 01:36:56 +0000719 UInt ret = 0;
720
721 if (base < 2 || base > 16)
722 return ret;
723
724 if ((flags & VG_MSG_SIGNED) && (Long)p < 0) {
725 p = - (Long)p;
726 neg = True;
727 }
728
729 if (p == 0)
730 buf[ind++] = '0';
731 else {
732 while (p > 0) {
733 if (flags & VG_MSG_COMMA && 10 == base &&
734 0 == (ind-nc) % 3 && 0 != ind)
735 {
736 buf[ind++] = ',';
737 nc++;
738 }
739 buf[ind++] = digits[p % base];
740 p /= base;
741 }
742 }
743
744 if (neg)
745 buf[ind++] = '-';
746
747 if (width > 0 && !(flags & VG_MSG_LJUSTIFY)) {
748 for(; ind < width; ind++) {
749 /* vg_assert(ind < 39); */
750 if (ind > 39) {
751 buf[39] = 0;
752 break;
753 }
754 buf[ind] = (flags & VG_MSG_ZJUSTIFY) ? '0': ' ';
755 }
756 }
757
758 /* Reverse copy to buffer. */
759 ret += ind;
760 for (i = ind -1; i >= 0; i--) {
761 send(buf[i], send_arg2);
762 }
763 if (width > 0 && (flags & VG_MSG_LJUSTIFY)) {
764 for(; ind < width; ind++) {
765 ret++;
766 /* Never pad with zeroes on RHS -- changes the value! */
767 send(' ', send_arg2);
768 }
769 }
770 return ret;
771}
772
773
774/* A simple vprintf(). */
775/* EXPORTED */
776UInt
777VG_(debugLog_vprintf) (
778 void(*send)(HChar,void*),
779 void* send_arg2,
780 const HChar* format,
781 va_list vargs
782)
783{
784 UInt ret = 0;
785 Int i;
786 Int flags;
787 Int width;
njn68e46592005-08-26 19:42:27 +0000788 Int n_ls = 0;
sewardja44b15f2007-02-16 14:10:24 +0000789 Bool is_long, caps;
sewardj1cf558c2005-04-25 01:36:56 +0000790
791 /* We assume that vargs has already been initialised by the
792 caller, using va_start, and that the caller will similarly
793 clean up with va_end.
794 */
795
796 for (i = 0; format[i] != 0; i++) {
797 if (format[i] != '%') {
798 send(format[i], send_arg2);
799 ret++;
800 continue;
801 }
802 i++;
803 /* A '%' has been found. Ignore a trailing %. */
804 if (format[i] == 0)
805 break;
806 if (format[i] == '%') {
njn02bc4b82005-05-15 17:28:26 +0000807 /* '%%' is replaced by '%'. */
sewardj1cf558c2005-04-25 01:36:56 +0000808 send('%', send_arg2);
809 ret++;
810 continue;
811 }
812 flags = 0;
njn68e46592005-08-26 19:42:27 +0000813 n_ls = 0;
sewardj1cf558c2005-04-25 01:36:56 +0000814 width = 0; /* length of the field. */
barta0b6b2c2008-07-07 06:49:24 +0000815 while (1) {
816 switch (format[i]) {
817 case '(':
818 flags |= VG_MSG_PAREN;
819 break;
820 case ',':
821 case '\'':
822 /* If ',' or '\'' follows '%', commas will be inserted. */
823 flags |= VG_MSG_COMMA;
824 break;
825 case '-':
826 /* If '-' follows '%', justify on the left. */
827 flags |= VG_MSG_LJUSTIFY;
828 break;
829 case '0':
830 /* If '0' follows '%', pads will be inserted. */
831 flags |= VG_MSG_ZJUSTIFY;
832 break;
833 case '#':
834 /* If '#' follows '%', alternative format will be used. */
835 flags |= VG_MSG_ALTFORMAT;
836 break;
837 default:
838 goto parse_fieldwidth;
839 }
sewardj1cf558c2005-04-25 01:36:56 +0000840 i++;
841 }
barta0b6b2c2008-07-07 06:49:24 +0000842 parse_fieldwidth:
sewardj1cf558c2005-04-25 01:36:56 +0000843 /* Compute the field length. */
844 while (format[i] >= '0' && format[i] <= '9') {
845 width *= 10;
846 width += format[i++] - '0';
847 }
848 while (format[i] == 'l') {
849 i++;
njn68e46592005-08-26 19:42:27 +0000850 n_ls++;
sewardj1cf558c2005-04-25 01:36:56 +0000851 }
852
njn68e46592005-08-26 19:42:27 +0000853 // %d means print a 32-bit integer.
854 // %ld means print a word-size integer.
855 // %lld means print a 64-bit integer.
856 if (0 == n_ls) { is_long = False; }
857 else if (1 == n_ls) { is_long = ( sizeof(void*) == sizeof(Long) ); }
858 else { is_long = True; }
859
sewardj1cf558c2005-04-25 01:36:56 +0000860 switch (format[i]) {
bart042257f2009-07-26 08:40:17 +0000861 case 'o': /* %o */
862 if (flags & VG_MSG_ALTFORMAT) {
863 ret += 2;
864 send('0',send_arg2);
865 }
866 if (is_long)
867 ret += myvprintf_int64(send, send_arg2, flags, 8, width, False,
868 (ULong)(va_arg (vargs, ULong)));
869 else
870 ret += myvprintf_int64(send, send_arg2, flags, 8, width, False,
871 (ULong)(va_arg (vargs, UInt)));
872 break;
sewardj1cf558c2005-04-25 01:36:56 +0000873 case 'd': /* %d */
874 flags |= VG_MSG_SIGNED;
875 if (is_long)
sewardja44b15f2007-02-16 14:10:24 +0000876 ret += myvprintf_int64(send, send_arg2, flags, 10, width, False,
sewardj1cf558c2005-04-25 01:36:56 +0000877 (ULong)(va_arg (vargs, Long)));
878 else
sewardja44b15f2007-02-16 14:10:24 +0000879 ret += myvprintf_int64(send, send_arg2, flags, 10, width, False,
sewardj1cf558c2005-04-25 01:36:56 +0000880 (ULong)(va_arg (vargs, Int)));
881 break;
882 case 'u': /* %u */
883 if (is_long)
sewardja44b15f2007-02-16 14:10:24 +0000884 ret += myvprintf_int64(send, send_arg2, flags, 10, width, False,
sewardj1cf558c2005-04-25 01:36:56 +0000885 (ULong)(va_arg (vargs, ULong)));
886 else
sewardja44b15f2007-02-16 14:10:24 +0000887 ret += myvprintf_int64(send, send_arg2, flags, 10, width, False,
sewardj1cf558c2005-04-25 01:36:56 +0000888 (ULong)(va_arg (vargs, UInt)));
889 break;
890 case 'p': /* %p */
891 ret += 2;
892 send('0',send_arg2);
893 send('x',send_arg2);
sewardja44b15f2007-02-16 14:10:24 +0000894 ret += myvprintf_int64(send, send_arg2, flags, 16, width, True,
sewardj1cf558c2005-04-25 01:36:56 +0000895 (ULong)((UWord)va_arg (vargs, void *)));
896 break;
897 case 'x': /* %x */
sewardja44b15f2007-02-16 14:10:24 +0000898 case 'X': /* %X */
899 caps = toBool(format[i] == 'X');
barta0b6b2c2008-07-07 06:49:24 +0000900 if (flags & VG_MSG_ALTFORMAT) {
901 ret += 2;
902 send('0',send_arg2);
903 send('x',send_arg2);
904 }
sewardj1cf558c2005-04-25 01:36:56 +0000905 if (is_long)
sewardja44b15f2007-02-16 14:10:24 +0000906 ret += myvprintf_int64(send, send_arg2, flags, 16, width, caps,
sewardj1cf558c2005-04-25 01:36:56 +0000907 (ULong)(va_arg (vargs, ULong)));
908 else
sewardja44b15f2007-02-16 14:10:24 +0000909 ret += myvprintf_int64(send, send_arg2, flags, 16, width, caps,
sewardj1cf558c2005-04-25 01:36:56 +0000910 (ULong)(va_arg (vargs, UInt)));
911 break;
912 case 'c': /* %c */
913 ret++;
914 send(va_arg (vargs, int), send_arg2);
915 break;
916 case 's': case 'S': { /* %s */
917 char *str = va_arg (vargs, char *);
918 if (str == (char*) 0) str = "(null)";
919 ret += myvprintf_str(send, send_arg2,
920 flags, width, str, format[i]=='S');
921 break;
922 }
sewardjdaf77af2005-07-19 14:17:37 +0000923 case 't': { /* %t, like %s but escaping chars for XML safety */
924 /* Note: simplistic; ignores field width and flags */
925 char *str = va_arg (vargs, char *);
926 if (str == (char*) 0) str = "(null)";
927 ret += myvprintf_str_XML_simplistic(send, send_arg2, str);
928 break;
929 }
930
sewardj1cf558c2005-04-25 01:36:56 +0000931// case 'y': { /* %y - print symbol */
932// Char buf[100];
933// Char *cp = buf;
934// Addr a = va_arg(vargs, Addr);
935//
936// if (flags & VG_MSG_PAREN)
937// *cp++ = '(';
938// if (VG_(get_fnname_w_offset)(a, cp, sizeof(buf)-4)) {
939// if (flags & VG_MSG_PAREN) {
940// cp += VG_(strlen)(cp);
941// *cp++ = ')';
942// *cp = '\0';
943// }
944// ret += myvprintf_str(send, send_arg2, flags, width, buf, 0);
945// }
946// break;
947// }
948 default:
949 break;
950 }
951 }
952 return ret;
953}
954
955
956/*------------------------------------------------------------*/
957/*--- Debuglog stuff. ---*/
958/*------------------------------------------------------------*/
959
960/* Only print messages whose stated level is less than or equal to
961 this. By default, it makes this entire subsystem silent. */
962
963static Int loglevel = 0;
964
sewardj1cf558c2005-04-25 01:36:56 +0000965/* Module startup. */
sewardj10759312005-05-30 23:52:47 +0000966/* EXPORTED */
sewardj1cf558c2005-04-25 01:36:56 +0000967void VG_(debugLog_startup) ( Int level, HChar* who )
968{
969 if (level < 0) level = 0;
970 if (level > 10) level = 10;
971 loglevel = level;
972 VG_(debugLog)(1, "debuglog",
973 "DebugLog system started by %s, "
974 "level %d logging requested\n",
975 who, loglevel);
976}
977
sewardj10759312005-05-30 23:52:47 +0000978/* Get the logging threshold level, as set by the most recent call to
979 VG_(debugLog_startup), or zero if there have been no such calls so
980 far. */
981/* EXPORTED */
982Int VG_(debugLog_getLevel) ( void )
983{
984 return loglevel;
985}
986
987
sewardj1cf558c2005-04-25 01:36:56 +0000988/* ------------ */
989
990typedef
991 struct {
992 HChar buf[100];
993 Int n;
994 }
995 printf_buf;
996
997static void add_to_buf ( HChar c, void* p )
998{
999 printf_buf* buf = (printf_buf*)p;
1000
1001 if (buf->n >= 100-10 /*paranoia*/ ) {
1002 emit( buf->buf, local_strlen(buf->buf) );
1003 buf->n = 0;
1004 buf->buf[buf->n] = 0;
1005 }
1006 buf->buf[buf->n++] = c;
1007 buf->buf[buf->n] = 0;
1008}
1009
1010/* Send a logging message. Nothing is output unless 'level'
1011 is <= the current loglevel. */
1012/* EXPORTED */
sewardj1cf558c2005-04-25 01:36:56 +00001013void VG_(debugLog) ( Int level, const HChar* modulename,
1014 const HChar* format, ... )
1015{
sewardjc7ffc942011-03-28 16:26:42 +00001016 UInt pid;
sewardj45f4e7c2005-09-27 19:20:21 +00001017 Int indent, depth, i;
sewardj1cf558c2005-04-25 01:36:56 +00001018 va_list vargs;
1019 printf_buf buf;
sewardja5ebfa92005-04-25 02:04:54 +00001020
sewardj1cf558c2005-04-25 01:36:56 +00001021 if (level > loglevel)
1022 return;
1023
sewardjd85feff2005-04-25 02:37:56 +00001024 indent = 2*level - 1;
sewardja5ebfa92005-04-25 02:04:54 +00001025 if (indent < 1) indent = 1;
1026
sewardj1cf558c2005-04-25 01:36:56 +00001027 buf.n = 0;
1028 buf.buf[0] = 0;
1029 pid = local_sys_getpid();
sewardj45f4e7c2005-09-27 19:20:21 +00001030
1031 // Print one '>' in front of the messages for each level of self-hosting
1032 // being performed.
1033 depth = RUNNING_ON_VALGRIND;
1034 for (i = 0; i < depth; i++) {
1035 (void)myvprintf_str ( add_to_buf, &buf, 0, 1, ">", False );
1036 }
1037
sewardja5ebfa92005-04-25 02:04:54 +00001038 (void)myvprintf_str ( add_to_buf, &buf, 0, 2, "--", False );
sewardja44b15f2007-02-16 14:10:24 +00001039 (void)myvprintf_int64 ( add_to_buf, &buf, 0, 10, 1, False, (ULong)pid );
sewardja5ebfa92005-04-25 02:04:54 +00001040 (void)myvprintf_str ( add_to_buf, &buf, 0, 1, ":", False );
sewardja44b15f2007-02-16 14:10:24 +00001041 (void)myvprintf_int64 ( add_to_buf, &buf, 0, 10, 1, False, (ULong)level );
sewardja5ebfa92005-04-25 02:04:54 +00001042 (void)myvprintf_str ( add_to_buf, &buf, 0, 1, ":", False );
sewardj1cf558c2005-04-25 01:36:56 +00001043 (void)myvprintf_str ( add_to_buf, &buf, 0, 8, (HChar*)modulename, False );
sewardja5ebfa92005-04-25 02:04:54 +00001044 (void)myvprintf_str ( add_to_buf, &buf, 0, indent, "", False );
sewardj1cf558c2005-04-25 01:36:56 +00001045
1046 va_start(vargs,format);
1047
sewardjc7ffc942011-03-28 16:26:42 +00001048 (void) VG_(debugLog_vprintf) ( add_to_buf, &buf, format, vargs );
sewardj1cf558c2005-04-25 01:36:56 +00001049
1050 if (buf.n > 0) {
1051 emit( buf.buf, local_strlen(buf.buf) );
1052 }
1053
1054 va_end(vargs);
1055}
1056
1057
1058
1059/*--------------------------------------------------------------------*/
1060/*--- end m_debuglog.c ---*/
1061/*--------------------------------------------------------------------*/