blob: 39473c8c6e6f5510a89946875b601e08a756c4d0 [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
10 Copyright (C) 2000-2005 Julian Seward
11 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
49#include "pub_core_basics.h" /* basic types */
50#include "pub_core_debuglog.h" /* our own iface */
sewardj45f4e7c2005-09-27 19:20:21 +000051#include "valgrind.h" /* for RUNNING_ON_VALGRIND */
sewardj1cf558c2005-04-25 01:36:56 +000052
53/*------------------------------------------------------------*/
54/*--- Stuff to make us completely independent. ---*/
55/*------------------------------------------------------------*/
56
sewardj2c48c7b2005-11-29 13:05:56 +000057/* ----- Platform-specifics ----- */
sewardj1cf558c2005-04-25 01:36:56 +000058
sewardj21c6d0f2005-05-02 10:33:44 +000059#if defined(VGP_x86_linux)
sewardj1cf558c2005-04-25 01:36:56 +000060
61static UInt local_sys_write_stderr ( HChar* buf, Int n )
62{
63 UInt __res;
tom311400b2005-04-27 08:58:53 +000064 __asm__ volatile (
sewardj45f4e7c2005-09-27 19:20:21 +000065 "pushl %%ebx\n" // ebx is callee-save
sewardjd485d692005-04-28 09:40:53 +000066 "movl $4, %%eax\n" /* %eax = __NR_write */
sewardj45f4e7c2005-09-27 19:20:21 +000067 "movl $1, %%ebx\n" /* %ebx = stderr */
sewardjd485d692005-04-28 09:40:53 +000068 "movl %1, %%ecx\n" /* %ecx = buf */
69 "movl %2, %%edx\n" /* %edx = n */
sewardjd485d692005-04-28 09:40:53 +000070 "int $0x80\n" /* write(stderr, buf, n) */
sewardjd485d692005-04-28 09:40:53 +000071 "movl %%eax, %0\n" /* __res = eax */
sewardj45f4e7c2005-09-27 19:20:21 +000072 "popl %%ebx\n" // restore ebx
tom311400b2005-04-27 08:58:53 +000073 : "=mr" (__res)
sewardjd4d203b2005-04-27 23:17:48 +000074 : "g" (buf), "g" (n)
sewardjd485d692005-04-28 09:40:53 +000075 : "eax", "edi", "ecx", "edx"
sewardjd4d203b2005-04-27 23:17:48 +000076 );
sewardj1cf558c2005-04-25 01:36:56 +000077 if (__res < 0)
78 __res = -1;
79 return __res;
80}
81
82static UInt local_sys_getpid ( void )
83{
84 UInt __res;
tom311400b2005-04-27 08:58:53 +000085 __asm__ volatile (
86 "movl $20, %%eax\n" /* set %eax = __NR_getpid */
87 "int $0x80\n" /* getpid() */
88 "movl %%eax, %0\n" /* set __res = eax */
sewardjd4d203b2005-04-27 23:17:48 +000089 : "=mr" (__res)
90 :
91 : "eax" );
sewardj1cf558c2005-04-25 01:36:56 +000092 return __res;
93}
94
sewardj21c6d0f2005-05-02 10:33:44 +000095#elif defined(VGP_amd64_linux)
sewardj601371a2005-04-25 16:21:17 +000096
97static UInt local_sys_write_stderr ( HChar* buf, Int n )
98{
tomc6121862005-04-27 09:23:02 +000099 UInt __res;
100 __asm__ volatile (
101 "movq $1, %%rax\n" /* set %rax = __NR_write */
102 "movq $2, %%rdi\n" /* set %rdi = stderr */
103 "movq %1, %%rsi\n" /* set %rsi = buf */
sewardjd4d203b2005-04-27 23:17:48 +0000104 "movl %2, %%edx\n" /* set %edx = n */
tomc6121862005-04-27 09:23:02 +0000105 "syscall\n" /* write(stderr, buf, n) */
106 "movl %%eax, %0\n" /* set __res = %eax */
107 : "=mr" (__res)
108 : "g" (buf), "g" (n)
109 : "rax", "rdi", "rsi", "rdx" );
110 if (__res < 0)
111 __res = -1;
112 return __res;
sewardj601371a2005-04-25 16:21:17 +0000113}
114
115static UInt local_sys_getpid ( void )
116{
tomc6121862005-04-27 09:23:02 +0000117 UInt __res;
118 __asm__ volatile (
119 "movq $39, %%rax\n" /* set %rax = __NR_getpid */
120 "syscall\n" /* getpid() */
121 "movl %%eax, %0\n" /* set __res = %eax */
122 : "=mr" (__res)
123 :
124 : "rax" );
125 return __res;
sewardj601371a2005-04-25 16:21:17 +0000126}
sewardj1cf558c2005-04-25 01:36:56 +0000127
cerion85665ca2005-06-20 15:51:07 +0000128#elif defined(VGP_ppc32_linux)
129
130static UInt local_sys_write_stderr ( HChar* buf, Int n )
131{
132 UInt __res;
133 __asm__ volatile (
134 "li %%r0,4\n\t" /* set %r0 = __NR_write */
135 "li %%r3,2\n\t" /* set %r3 = stderr */
136 "mr %%r4,%1\n\t" /* set %r4 = buf */
137 "mr %%r5,%2\n\t" /* set %r5 = n */
138 "sc\n\t" /* write(stderr, buf, n) */
139 "mr %0,%%r3\n" /* set __res = r3 */
140 : "=mr" (__res)
141 : "g" (buf), "g" (n)
142 : "r0", "r3", "r4", "r5" );
143 if (__res < 0)
144 __res = -1;
145 return __res;
146}
147
148static UInt local_sys_getpid ( void )
149{
150 UInt __res;
151 __asm__ volatile (
152 "li %%r0,20\n" /* set %r0 = __NR_getpid */
153 "\tsc\n" /* getpid() */
154 "\tmr %0,%%r3\n" /* set __res = r3 */
155 : "=mr" (__res)
156 :
157 : "r0" );
158 return __res;
159}
160
sewardj2c48c7b2005-11-29 13:05:56 +0000161#elif defined(VGP_ppc64_linux)
162
163static UInt local_sys_write_stderr ( HChar* buf, Int n )
164{
165 UInt __res;
166 __asm__ volatile (
167 "li %%r0,4\n\t" /* set %r0 = __NR_write */
168 "li %%r3,2\n\t" /* set %r3 = stderr */
169 "mr %%r4,%1\n\t" /* set %r4 = buf */
170 "mr %%r5,%2\n\t" /* set %r5 = n */
171 "sc\n\t" /* write(stderr, buf, n) */
172 "mr %0,%%r3\n" /* set __res = r3 */
173 : "=mr" (__res)
174 : "g" (buf), "g" (n)
175 : "r0", "r3", "r4", "r5" );
176 if (__res < 0)
177 __res = -1;
178 return __res;
179}
180
181static UInt local_sys_getpid ( void )
182{
183 UInt __res;
184 __asm__ volatile (
185 "li %%r0,20\n" /* set %r0 = __NR_getpid */
186 "\tsc\n" /* getpid() */
187 "\tmr %0,%%r3\n" /* set __res = r3 */
188 : "=mr" (__res)
189 :
190 : "r0" );
191 return __res;
192}
193
sewardj1cf558c2005-04-25 01:36:56 +0000194#else
sewardj21c6d0f2005-05-02 10:33:44 +0000195# error Unknown platform
sewardj1cf558c2005-04-25 01:36:56 +0000196#endif
197
198
199/* ----- generic ----- */
200
201/* strlen, so we don't need m_libc */
202static Int local_strlen ( const HChar* str )
203{
204 Int i = 0;
205 while (str[i] != 0) i++;
206 return i;
207}
208
209static HChar local_toupper ( HChar c )
210{
211 if (c >= 'a' && c <= 'z')
212 return c + ('A' - 'a');
213 else
214 return c;
215}
216
217/* Emit buf[0 .. n-1] to stderr. Unfortunately platform-specific.
218*/
219static void emit ( HChar* buf, Int n )
220{
221 if (n >= 1)
222 (void)local_sys_write_stderr(buf, n);
223}
224
225
226/*------------------------------------------------------------*/
227/*--- A simple, generic, vprintf implementation. ---*/
228/*------------------------------------------------------------*/
229
230/* -----------------------------------------------
231 Distantly derived from:
232
233 vprintf replacement for Checker.
234 Copyright 1993, 1994, 1995 Tristan Gingold
235 Written September 1993 Tristan Gingold
236 Tristan Gingold, 8 rue Parmentier, F-91120 PALAISEAU, FRANCE
237
238 (Checker itself was GPL'd.)
239 ----------------------------------------------- */
240
241/* Some flags. */
242#define VG_MSG_SIGNED 1 /* The value is signed. */
243#define VG_MSG_ZJUSTIFY 2 /* Must justify with '0'. */
244#define VG_MSG_LJUSTIFY 4 /* Must justify on the left. */
245#define VG_MSG_PAREN 8 /* Parenthesize if present (for %y) */
246#define VG_MSG_COMMA 16 /* Add commas to numbers (for %d, %u) */
247
248
249/* Copy a string into the buffer. */
250static
251UInt myvprintf_str ( void(*send)(HChar,void*),
252 void* send_arg2,
253 Int flags,
254 Int width,
255 HChar* str,
256 Bool capitalise )
257{
258# define MAYBE_TOUPPER(ch) (capitalise ? local_toupper(ch) : (ch))
259 UInt ret = 0;
260 Int i, extra;
261 Int len = local_strlen(str);
262
263 if (width == 0) {
264 ret += len;
265 for (i = 0; i < len; i++)
266 send(MAYBE_TOUPPER(str[i]), send_arg2);
267 return ret;
268 }
269
270 if (len > width) {
271 ret += width;
272 for (i = 0; i < width; i++)
273 send(MAYBE_TOUPPER(str[i]), send_arg2);
274 return ret;
275 }
276
277 extra = width - len;
278 if (flags & VG_MSG_LJUSTIFY) {
279 ret += extra;
280 for (i = 0; i < extra; i++)
281 send(' ', send_arg2);
282 }
283 ret += len;
284 for (i = 0; i < len; i++)
285 send(MAYBE_TOUPPER(str[i]), send_arg2);
286 if (!(flags & VG_MSG_LJUSTIFY)) {
287 ret += extra;
288 for (i = 0; i < extra; i++)
289 send(' ', send_arg2);
290 }
291
292# undef MAYBE_TOUPPER
293 return ret;
294}
295
296
sewardjdaf77af2005-07-19 14:17:37 +0000297/* Copy a string into the buffer, escaping bad XML chars. */
298static
299UInt myvprintf_str_XML_simplistic ( void(*send)(HChar,void*),
300 void* send_arg2,
301 HChar* str )
302{
303 UInt ret = 0;
304 Int i;
305 Int len = local_strlen(str);
306 HChar* alt;
307
308 for (i = 0; i < len; i++) {
309 switch (str[i]) {
310 case '&': alt = "&amp;"; break;
311 case '<': alt = "&lt;"; break;
312 case '>': alt = "&gt;"; break;
313 default: alt = NULL;
314 }
315
316 if (alt) {
317 while (*alt) {
318 send(*alt, send_arg2);
319 ret++;
320 alt++;
321 }
322 } else {
323 send(str[i], send_arg2);
324 ret++;
325 }
326 }
327
328 return ret;
329}
330
331
sewardj1cf558c2005-04-25 01:36:56 +0000332/* Write P into the buffer according to these args:
333 * If SIGN is true, p is a signed.
334 * BASE is the base.
335 * If WITH_ZERO is true, '0' must be added.
336 * WIDTH is the width of the field.
337 */
338static
339UInt myvprintf_int64 ( void(*send)(HChar,void*),
340 void* send_arg2,
341 Int flags,
342 Int base,
343 Int width,
344 ULong p )
345{
346 HChar buf[40];
347 Int ind = 0;
348 Int i, nc = 0;
349 Bool neg = False;
350 HChar* digits = "0123456789ABCDEF";
351 UInt ret = 0;
352
353 if (base < 2 || base > 16)
354 return ret;
355
356 if ((flags & VG_MSG_SIGNED) && (Long)p < 0) {
357 p = - (Long)p;
358 neg = True;
359 }
360
361 if (p == 0)
362 buf[ind++] = '0';
363 else {
364 while (p > 0) {
365 if (flags & VG_MSG_COMMA && 10 == base &&
366 0 == (ind-nc) % 3 && 0 != ind)
367 {
368 buf[ind++] = ',';
369 nc++;
370 }
371 buf[ind++] = digits[p % base];
372 p /= base;
373 }
374 }
375
376 if (neg)
377 buf[ind++] = '-';
378
379 if (width > 0 && !(flags & VG_MSG_LJUSTIFY)) {
380 for(; ind < width; ind++) {
381 /* vg_assert(ind < 39); */
382 if (ind > 39) {
383 buf[39] = 0;
384 break;
385 }
386 buf[ind] = (flags & VG_MSG_ZJUSTIFY) ? '0': ' ';
387 }
388 }
389
390 /* Reverse copy to buffer. */
391 ret += ind;
392 for (i = ind -1; i >= 0; i--) {
393 send(buf[i], send_arg2);
394 }
395 if (width > 0 && (flags & VG_MSG_LJUSTIFY)) {
396 for(; ind < width; ind++) {
397 ret++;
398 /* Never pad with zeroes on RHS -- changes the value! */
399 send(' ', send_arg2);
400 }
401 }
402 return ret;
403}
404
405
406/* A simple vprintf(). */
407/* EXPORTED */
408UInt
409VG_(debugLog_vprintf) (
410 void(*send)(HChar,void*),
411 void* send_arg2,
412 const HChar* format,
413 va_list vargs
414)
415{
416 UInt ret = 0;
417 Int i;
418 Int flags;
419 Int width;
njn68e46592005-08-26 19:42:27 +0000420 Int n_ls = 0;
sewardj1cf558c2005-04-25 01:36:56 +0000421 Bool is_long;
422
423 /* We assume that vargs has already been initialised by the
424 caller, using va_start, and that the caller will similarly
425 clean up with va_end.
426 */
427
428 for (i = 0; format[i] != 0; i++) {
429 if (format[i] != '%') {
430 send(format[i], send_arg2);
431 ret++;
432 continue;
433 }
434 i++;
435 /* A '%' has been found. Ignore a trailing %. */
436 if (format[i] == 0)
437 break;
438 if (format[i] == '%') {
njn02bc4b82005-05-15 17:28:26 +0000439 /* '%%' is replaced by '%'. */
sewardj1cf558c2005-04-25 01:36:56 +0000440 send('%', send_arg2);
441 ret++;
442 continue;
443 }
444 flags = 0;
njn68e46592005-08-26 19:42:27 +0000445 n_ls = 0;
sewardj1cf558c2005-04-25 01:36:56 +0000446 width = 0; /* length of the field. */
447 if (format[i] == '(') {
448 flags |= VG_MSG_PAREN;
449 i++;
450 }
451 /* If ',' follows '%', commas will be inserted. */
452 if (format[i] == ',') {
453 flags |= VG_MSG_COMMA;
454 i++;
455 }
456 /* If '-' follows '%', justify on the left. */
457 if (format[i] == '-') {
458 flags |= VG_MSG_LJUSTIFY;
459 i++;
460 }
461 /* If '0' follows '%', pads will be inserted. */
462 if (format[i] == '0') {
463 flags |= VG_MSG_ZJUSTIFY;
464 i++;
465 }
466 /* Compute the field length. */
467 while (format[i] >= '0' && format[i] <= '9') {
468 width *= 10;
469 width += format[i++] - '0';
470 }
471 while (format[i] == 'l') {
472 i++;
njn68e46592005-08-26 19:42:27 +0000473 n_ls++;
sewardj1cf558c2005-04-25 01:36:56 +0000474 }
475
njn68e46592005-08-26 19:42:27 +0000476 // %d means print a 32-bit integer.
477 // %ld means print a word-size integer.
478 // %lld means print a 64-bit integer.
479 if (0 == n_ls) { is_long = False; }
480 else if (1 == n_ls) { is_long = ( sizeof(void*) == sizeof(Long) ); }
481 else { is_long = True; }
482
sewardj1cf558c2005-04-25 01:36:56 +0000483 switch (format[i]) {
484 case 'd': /* %d */
485 flags |= VG_MSG_SIGNED;
486 if (is_long)
487 ret += myvprintf_int64(send, send_arg2, flags, 10, width,
488 (ULong)(va_arg (vargs, Long)));
489 else
490 ret += myvprintf_int64(send, send_arg2, flags, 10, width,
491 (ULong)(va_arg (vargs, Int)));
492 break;
493 case 'u': /* %u */
494 if (is_long)
495 ret += myvprintf_int64(send, send_arg2, flags, 10, width,
496 (ULong)(va_arg (vargs, ULong)));
497 else
498 ret += myvprintf_int64(send, send_arg2, flags, 10, width,
499 (ULong)(va_arg (vargs, UInt)));
500 break;
501 case 'p': /* %p */
502 ret += 2;
503 send('0',send_arg2);
504 send('x',send_arg2);
505 ret += myvprintf_int64(send, send_arg2, flags, 16, width,
506 (ULong)((UWord)va_arg (vargs, void *)));
507 break;
508 case 'x': /* %x */
509 if (is_long)
510 ret += myvprintf_int64(send, send_arg2, flags, 16, width,
511 (ULong)(va_arg (vargs, ULong)));
512 else
513 ret += myvprintf_int64(send, send_arg2, flags, 16, width,
514 (ULong)(va_arg (vargs, UInt)));
515 break;
516 case 'c': /* %c */
517 ret++;
518 send(va_arg (vargs, int), send_arg2);
519 break;
520 case 's': case 'S': { /* %s */
521 char *str = va_arg (vargs, char *);
522 if (str == (char*) 0) str = "(null)";
523 ret += myvprintf_str(send, send_arg2,
524 flags, width, str, format[i]=='S');
525 break;
526 }
sewardjdaf77af2005-07-19 14:17:37 +0000527 case 't': { /* %t, like %s but escaping chars for XML safety */
528 /* Note: simplistic; ignores field width and flags */
529 char *str = va_arg (vargs, char *);
530 if (str == (char*) 0) str = "(null)";
531 ret += myvprintf_str_XML_simplistic(send, send_arg2, str);
532 break;
533 }
534
sewardj1cf558c2005-04-25 01:36:56 +0000535// case 'y': { /* %y - print symbol */
536// Char buf[100];
537// Char *cp = buf;
538// Addr a = va_arg(vargs, Addr);
539//
540// if (flags & VG_MSG_PAREN)
541// *cp++ = '(';
542// if (VG_(get_fnname_w_offset)(a, cp, sizeof(buf)-4)) {
543// if (flags & VG_MSG_PAREN) {
544// cp += VG_(strlen)(cp);
545// *cp++ = ')';
546// *cp = '\0';
547// }
548// ret += myvprintf_str(send, send_arg2, flags, width, buf, 0);
549// }
550// break;
551// }
552 default:
553 break;
554 }
555 }
556 return ret;
557}
558
559
560/*------------------------------------------------------------*/
561/*--- Debuglog stuff. ---*/
562/*------------------------------------------------------------*/
563
564/* Only print messages whose stated level is less than or equal to
565 this. By default, it makes this entire subsystem silent. */
566
567static Int loglevel = 0;
568
sewardj1cf558c2005-04-25 01:36:56 +0000569/* Module startup. */
sewardj10759312005-05-30 23:52:47 +0000570/* EXPORTED */
sewardj1cf558c2005-04-25 01:36:56 +0000571void VG_(debugLog_startup) ( Int level, HChar* who )
572{
573 if (level < 0) level = 0;
574 if (level > 10) level = 10;
575 loglevel = level;
576 VG_(debugLog)(1, "debuglog",
577 "DebugLog system started by %s, "
578 "level %d logging requested\n",
579 who, loglevel);
580}
581
sewardj10759312005-05-30 23:52:47 +0000582/* Get the logging threshold level, as set by the most recent call to
583 VG_(debugLog_startup), or zero if there have been no such calls so
584 far. */
585/* EXPORTED */
586Int VG_(debugLog_getLevel) ( void )
587{
588 return loglevel;
589}
590
591
sewardj1cf558c2005-04-25 01:36:56 +0000592/* ------------ */
593
594typedef
595 struct {
596 HChar buf[100];
597 Int n;
598 }
599 printf_buf;
600
601static void add_to_buf ( HChar c, void* p )
602{
603 printf_buf* buf = (printf_buf*)p;
604
605 if (buf->n >= 100-10 /*paranoia*/ ) {
606 emit( buf->buf, local_strlen(buf->buf) );
607 buf->n = 0;
608 buf->buf[buf->n] = 0;
609 }
610 buf->buf[buf->n++] = c;
611 buf->buf[buf->n] = 0;
612}
613
614/* Send a logging message. Nothing is output unless 'level'
615 is <= the current loglevel. */
616/* EXPORTED */
617__attribute__((format(__printf__, 3, 4)))
618void VG_(debugLog) ( Int level, const HChar* modulename,
619 const HChar* format, ... )
620{
621 UInt ret, pid;
sewardj45f4e7c2005-09-27 19:20:21 +0000622 Int indent, depth, i;
sewardj1cf558c2005-04-25 01:36:56 +0000623 va_list vargs;
624 printf_buf buf;
sewardja5ebfa92005-04-25 02:04:54 +0000625
sewardj1cf558c2005-04-25 01:36:56 +0000626 if (level > loglevel)
627 return;
628
sewardjd85feff2005-04-25 02:37:56 +0000629 indent = 2*level - 1;
sewardja5ebfa92005-04-25 02:04:54 +0000630 if (indent < 1) indent = 1;
631
sewardj1cf558c2005-04-25 01:36:56 +0000632 buf.n = 0;
633 buf.buf[0] = 0;
634 pid = local_sys_getpid();
sewardj45f4e7c2005-09-27 19:20:21 +0000635
636 // Print one '>' in front of the messages for each level of self-hosting
637 // being performed.
638 depth = RUNNING_ON_VALGRIND;
639 for (i = 0; i < depth; i++) {
640 (void)myvprintf_str ( add_to_buf, &buf, 0, 1, ">", False );
641 }
642
sewardja5ebfa92005-04-25 02:04:54 +0000643 (void)myvprintf_str ( add_to_buf, &buf, 0, 2, "--", False );
644 (void)myvprintf_int64 ( add_to_buf, &buf, 0, 10, 1, (ULong)pid );
645 (void)myvprintf_str ( add_to_buf, &buf, 0, 1, ":", False );
sewardj1cf558c2005-04-25 01:36:56 +0000646 (void)myvprintf_int64 ( add_to_buf, &buf, 0, 10, 1, (ULong)level );
sewardja5ebfa92005-04-25 02:04:54 +0000647 (void)myvprintf_str ( add_to_buf, &buf, 0, 1, ":", False );
sewardj1cf558c2005-04-25 01:36:56 +0000648 (void)myvprintf_str ( add_to_buf, &buf, 0, 8, (HChar*)modulename, False );
sewardja5ebfa92005-04-25 02:04:54 +0000649 (void)myvprintf_str ( add_to_buf, &buf, 0, indent, "", False );
sewardj1cf558c2005-04-25 01:36:56 +0000650
651 va_start(vargs,format);
652
653 ret = VG_(debugLog_vprintf) ( add_to_buf, &buf, format, vargs );
654
655 if (buf.n > 0) {
656 emit( buf.buf, local_strlen(buf.buf) );
657 }
658
659 va_end(vargs);
660}
661
662
663
664/*--------------------------------------------------------------------*/
665/*--- end m_debuglog.c ---*/
666/*--------------------------------------------------------------------*/