blob: 36c26ba6cf3be7f95bc1dcbb5db428c23122e7b7 [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{
sewardj55c43762006-04-28 21:01:33 +000063 Int block[2];
64 block[0] = (Int)buf;
65 block[1] = n;
tom311400b2005-04-27 08:58:53 +000066 __asm__ volatile (
sewardj55c43762006-04-28 21:01:33 +000067 "pushl %%ebx\n" /* ebx is callee-save */
68 "movl %0, %%ebx\n" /* ebx = &block */
69 "pushl %%ebx\n" /* save &block */
70 "movl 0(%%ebx), %%ecx\n" /* %ecx = buf */
71 "movl 4(%%ebx), %%edx\n" /* %edx = n */
72 "movl $4, %%eax\n" /* %eax = __NR_write */
73 "movl $1, %%ebx\n" /* %ebx = stderr */
74 "int $0x80\n" /* write(stderr, buf, n) */
75 "popl %%ebx\n" /* reestablish &block */
76 "movl %%eax, 0(%%ebx)\n" /* block[0] = result */
77 "popl %%ebx\n" /* restore ebx */
78 : /*wr*/
79 : /*rd*/ "g" (block)
80 : /*trash*/ "eax", "edi", "ecx", "edx", "memory", "cc"
sewardjd4d203b2005-04-27 23:17:48 +000081 );
sewardj55c43762006-04-28 21:01:33 +000082 if (block[0] < 0)
83 block[0] = -1;
84 return block[0];
sewardj1cf558c2005-04-25 01:36:56 +000085}
86
87static UInt local_sys_getpid ( void )
88{
89 UInt __res;
tom311400b2005-04-27 08:58:53 +000090 __asm__ volatile (
91 "movl $20, %%eax\n" /* set %eax = __NR_getpid */
92 "int $0x80\n" /* getpid() */
93 "movl %%eax, %0\n" /* set __res = eax */
sewardjd4d203b2005-04-27 23:17:48 +000094 : "=mr" (__res)
95 :
96 : "eax" );
sewardj1cf558c2005-04-25 01:36:56 +000097 return __res;
98}
99
sewardj21c6d0f2005-05-02 10:33:44 +0000100#elif defined(VGP_amd64_linux)
sewardj601371a2005-04-25 16:21:17 +0000101
102static UInt local_sys_write_stderr ( HChar* buf, Int n )
103{
tomc6121862005-04-27 09:23:02 +0000104 UInt __res;
105 __asm__ volatile (
106 "movq $1, %%rax\n" /* set %rax = __NR_write */
107 "movq $2, %%rdi\n" /* set %rdi = stderr */
108 "movq %1, %%rsi\n" /* set %rsi = buf */
sewardjd4d203b2005-04-27 23:17:48 +0000109 "movl %2, %%edx\n" /* set %edx = n */
tomc6121862005-04-27 09:23:02 +0000110 "syscall\n" /* write(stderr, buf, n) */
111 "movl %%eax, %0\n" /* set __res = %eax */
112 : "=mr" (__res)
113 : "g" (buf), "g" (n)
114 : "rax", "rdi", "rsi", "rdx" );
115 if (__res < 0)
116 __res = -1;
117 return __res;
sewardj601371a2005-04-25 16:21:17 +0000118}
119
120static UInt local_sys_getpid ( void )
121{
tomc6121862005-04-27 09:23:02 +0000122 UInt __res;
123 __asm__ volatile (
124 "movq $39, %%rax\n" /* set %rax = __NR_getpid */
125 "syscall\n" /* getpid() */
126 "movl %%eax, %0\n" /* set __res = %eax */
127 : "=mr" (__res)
128 :
129 : "rax" );
130 return __res;
sewardj601371a2005-04-25 16:21:17 +0000131}
sewardj1cf558c2005-04-25 01:36:56 +0000132
cerion85665ca2005-06-20 15:51:07 +0000133#elif defined(VGP_ppc32_linux)
134
135static UInt local_sys_write_stderr ( HChar* buf, Int n )
136{
137 UInt __res;
138 __asm__ volatile (
139 "li %%r0,4\n\t" /* set %r0 = __NR_write */
140 "li %%r3,2\n\t" /* set %r3 = stderr */
141 "mr %%r4,%1\n\t" /* set %r4 = buf */
142 "mr %%r5,%2\n\t" /* set %r5 = n */
143 "sc\n\t" /* write(stderr, buf, n) */
144 "mr %0,%%r3\n" /* set __res = r3 */
145 : "=mr" (__res)
146 : "g" (buf), "g" (n)
147 : "r0", "r3", "r4", "r5" );
148 if (__res < 0)
149 __res = -1;
150 return __res;
151}
152
153static UInt local_sys_getpid ( void )
154{
155 UInt __res;
156 __asm__ volatile (
157 "li %%r0,20\n" /* set %r0 = __NR_getpid */
158 "\tsc\n" /* getpid() */
159 "\tmr %0,%%r3\n" /* set __res = r3 */
160 : "=mr" (__res)
161 :
162 : "r0" );
163 return __res;
164}
165
sewardj2c48c7b2005-11-29 13:05:56 +0000166#elif defined(VGP_ppc64_linux)
167
168static UInt local_sys_write_stderr ( HChar* buf, Int n )
169{
170 UInt __res;
171 __asm__ volatile (
172 "li %%r0,4\n\t" /* set %r0 = __NR_write */
173 "li %%r3,2\n\t" /* set %r3 = stderr */
174 "mr %%r4,%1\n\t" /* set %r4 = buf */
175 "mr %%r5,%2\n\t" /* set %r5 = n */
176 "sc\n\t" /* write(stderr, buf, n) */
177 "mr %0,%%r3\n" /* set __res = r3 */
178 : "=mr" (__res)
179 : "g" (buf), "g" (n)
180 : "r0", "r3", "r4", "r5" );
181 if (__res < 0)
182 __res = -1;
183 return __res;
184}
185
186static UInt local_sys_getpid ( void )
187{
188 UInt __res;
189 __asm__ volatile (
190 "li %%r0,20\n" /* set %r0 = __NR_getpid */
191 "\tsc\n" /* getpid() */
192 "\tmr %0,%%r3\n" /* set __res = r3 */
193 : "=mr" (__res)
194 :
195 : "r0" );
196 return __res;
197}
198
sewardj1cf558c2005-04-25 01:36:56 +0000199#else
sewardj21c6d0f2005-05-02 10:33:44 +0000200# error Unknown platform
sewardj1cf558c2005-04-25 01:36:56 +0000201#endif
202
203
204/* ----- generic ----- */
205
206/* strlen, so we don't need m_libc */
207static Int local_strlen ( const HChar* str )
208{
209 Int i = 0;
210 while (str[i] != 0) i++;
211 return i;
212}
213
214static HChar local_toupper ( HChar c )
215{
216 if (c >= 'a' && c <= 'z')
217 return c + ('A' - 'a');
218 else
219 return c;
220}
221
222/* Emit buf[0 .. n-1] to stderr. Unfortunately platform-specific.
223*/
224static void emit ( HChar* buf, Int n )
225{
226 if (n >= 1)
227 (void)local_sys_write_stderr(buf, n);
228}
229
230
231/*------------------------------------------------------------*/
232/*--- A simple, generic, vprintf implementation. ---*/
233/*------------------------------------------------------------*/
234
235/* -----------------------------------------------
236 Distantly derived from:
237
238 vprintf replacement for Checker.
239 Copyright 1993, 1994, 1995 Tristan Gingold
240 Written September 1993 Tristan Gingold
241 Tristan Gingold, 8 rue Parmentier, F-91120 PALAISEAU, FRANCE
242
243 (Checker itself was GPL'd.)
244 ----------------------------------------------- */
245
246/* Some flags. */
247#define VG_MSG_SIGNED 1 /* The value is signed. */
248#define VG_MSG_ZJUSTIFY 2 /* Must justify with '0'. */
249#define VG_MSG_LJUSTIFY 4 /* Must justify on the left. */
250#define VG_MSG_PAREN 8 /* Parenthesize if present (for %y) */
251#define VG_MSG_COMMA 16 /* Add commas to numbers (for %d, %u) */
252
253
254/* Copy a string into the buffer. */
255static
256UInt myvprintf_str ( void(*send)(HChar,void*),
257 void* send_arg2,
258 Int flags,
259 Int width,
260 HChar* str,
261 Bool capitalise )
262{
263# define MAYBE_TOUPPER(ch) (capitalise ? local_toupper(ch) : (ch))
264 UInt ret = 0;
265 Int i, extra;
266 Int len = local_strlen(str);
267
268 if (width == 0) {
269 ret += len;
270 for (i = 0; i < len; i++)
271 send(MAYBE_TOUPPER(str[i]), send_arg2);
272 return ret;
273 }
274
275 if (len > width) {
276 ret += width;
277 for (i = 0; i < width; i++)
278 send(MAYBE_TOUPPER(str[i]), send_arg2);
279 return ret;
280 }
281
282 extra = width - len;
283 if (flags & VG_MSG_LJUSTIFY) {
284 ret += extra;
285 for (i = 0; i < extra; i++)
286 send(' ', send_arg2);
287 }
288 ret += len;
289 for (i = 0; i < len; i++)
290 send(MAYBE_TOUPPER(str[i]), send_arg2);
291 if (!(flags & VG_MSG_LJUSTIFY)) {
292 ret += extra;
293 for (i = 0; i < extra; i++)
294 send(' ', send_arg2);
295 }
296
297# undef MAYBE_TOUPPER
298 return ret;
299}
300
301
sewardjdaf77af2005-07-19 14:17:37 +0000302/* Copy a string into the buffer, escaping bad XML chars. */
303static
304UInt myvprintf_str_XML_simplistic ( void(*send)(HChar,void*),
305 void* send_arg2,
306 HChar* str )
307{
308 UInt ret = 0;
309 Int i;
310 Int len = local_strlen(str);
311 HChar* alt;
312
313 for (i = 0; i < len; i++) {
314 switch (str[i]) {
315 case '&': alt = "&amp;"; break;
316 case '<': alt = "&lt;"; break;
317 case '>': alt = "&gt;"; break;
318 default: alt = NULL;
319 }
320
321 if (alt) {
322 while (*alt) {
323 send(*alt, send_arg2);
324 ret++;
325 alt++;
326 }
327 } else {
328 send(str[i], send_arg2);
329 ret++;
330 }
331 }
332
333 return ret;
334}
335
336
sewardj1cf558c2005-04-25 01:36:56 +0000337/* Write P into the buffer according to these args:
338 * If SIGN is true, p is a signed.
339 * BASE is the base.
340 * If WITH_ZERO is true, '0' must be added.
341 * WIDTH is the width of the field.
342 */
343static
344UInt myvprintf_int64 ( void(*send)(HChar,void*),
345 void* send_arg2,
346 Int flags,
347 Int base,
348 Int width,
349 ULong p )
350{
351 HChar buf[40];
352 Int ind = 0;
353 Int i, nc = 0;
354 Bool neg = False;
355 HChar* digits = "0123456789ABCDEF";
356 UInt ret = 0;
357
358 if (base < 2 || base > 16)
359 return ret;
360
361 if ((flags & VG_MSG_SIGNED) && (Long)p < 0) {
362 p = - (Long)p;
363 neg = True;
364 }
365
366 if (p == 0)
367 buf[ind++] = '0';
368 else {
369 while (p > 0) {
370 if (flags & VG_MSG_COMMA && 10 == base &&
371 0 == (ind-nc) % 3 && 0 != ind)
372 {
373 buf[ind++] = ',';
374 nc++;
375 }
376 buf[ind++] = digits[p % base];
377 p /= base;
378 }
379 }
380
381 if (neg)
382 buf[ind++] = '-';
383
384 if (width > 0 && !(flags & VG_MSG_LJUSTIFY)) {
385 for(; ind < width; ind++) {
386 /* vg_assert(ind < 39); */
387 if (ind > 39) {
388 buf[39] = 0;
389 break;
390 }
391 buf[ind] = (flags & VG_MSG_ZJUSTIFY) ? '0': ' ';
392 }
393 }
394
395 /* Reverse copy to buffer. */
396 ret += ind;
397 for (i = ind -1; i >= 0; i--) {
398 send(buf[i], send_arg2);
399 }
400 if (width > 0 && (flags & VG_MSG_LJUSTIFY)) {
401 for(; ind < width; ind++) {
402 ret++;
403 /* Never pad with zeroes on RHS -- changes the value! */
404 send(' ', send_arg2);
405 }
406 }
407 return ret;
408}
409
410
411/* A simple vprintf(). */
412/* EXPORTED */
413UInt
414VG_(debugLog_vprintf) (
415 void(*send)(HChar,void*),
416 void* send_arg2,
417 const HChar* format,
418 va_list vargs
419)
420{
421 UInt ret = 0;
422 Int i;
423 Int flags;
424 Int width;
njn68e46592005-08-26 19:42:27 +0000425 Int n_ls = 0;
sewardj1cf558c2005-04-25 01:36:56 +0000426 Bool is_long;
427
428 /* We assume that vargs has already been initialised by the
429 caller, using va_start, and that the caller will similarly
430 clean up with va_end.
431 */
432
433 for (i = 0; format[i] != 0; i++) {
434 if (format[i] != '%') {
435 send(format[i], send_arg2);
436 ret++;
437 continue;
438 }
439 i++;
440 /* A '%' has been found. Ignore a trailing %. */
441 if (format[i] == 0)
442 break;
443 if (format[i] == '%') {
njn02bc4b82005-05-15 17:28:26 +0000444 /* '%%' is replaced by '%'. */
sewardj1cf558c2005-04-25 01:36:56 +0000445 send('%', send_arg2);
446 ret++;
447 continue;
448 }
449 flags = 0;
njn68e46592005-08-26 19:42:27 +0000450 n_ls = 0;
sewardj1cf558c2005-04-25 01:36:56 +0000451 width = 0; /* length of the field. */
452 if (format[i] == '(') {
453 flags |= VG_MSG_PAREN;
454 i++;
455 }
456 /* If ',' follows '%', commas will be inserted. */
457 if (format[i] == ',') {
458 flags |= VG_MSG_COMMA;
459 i++;
460 }
461 /* If '-' follows '%', justify on the left. */
462 if (format[i] == '-') {
463 flags |= VG_MSG_LJUSTIFY;
464 i++;
465 }
466 /* If '0' follows '%', pads will be inserted. */
467 if (format[i] == '0') {
468 flags |= VG_MSG_ZJUSTIFY;
469 i++;
470 }
471 /* Compute the field length. */
472 while (format[i] >= '0' && format[i] <= '9') {
473 width *= 10;
474 width += format[i++] - '0';
475 }
476 while (format[i] == 'l') {
477 i++;
njn68e46592005-08-26 19:42:27 +0000478 n_ls++;
sewardj1cf558c2005-04-25 01:36:56 +0000479 }
480
njn68e46592005-08-26 19:42:27 +0000481 // %d means print a 32-bit integer.
482 // %ld means print a word-size integer.
483 // %lld means print a 64-bit integer.
484 if (0 == n_ls) { is_long = False; }
485 else if (1 == n_ls) { is_long = ( sizeof(void*) == sizeof(Long) ); }
486 else { is_long = True; }
487
sewardj1cf558c2005-04-25 01:36:56 +0000488 switch (format[i]) {
489 case 'd': /* %d */
490 flags |= VG_MSG_SIGNED;
491 if (is_long)
492 ret += myvprintf_int64(send, send_arg2, flags, 10, width,
493 (ULong)(va_arg (vargs, Long)));
494 else
495 ret += myvprintf_int64(send, send_arg2, flags, 10, width,
496 (ULong)(va_arg (vargs, Int)));
497 break;
498 case 'u': /* %u */
499 if (is_long)
500 ret += myvprintf_int64(send, send_arg2, flags, 10, width,
501 (ULong)(va_arg (vargs, ULong)));
502 else
503 ret += myvprintf_int64(send, send_arg2, flags, 10, width,
504 (ULong)(va_arg (vargs, UInt)));
505 break;
506 case 'p': /* %p */
507 ret += 2;
508 send('0',send_arg2);
509 send('x',send_arg2);
510 ret += myvprintf_int64(send, send_arg2, flags, 16, width,
511 (ULong)((UWord)va_arg (vargs, void *)));
512 break;
513 case 'x': /* %x */
514 if (is_long)
515 ret += myvprintf_int64(send, send_arg2, flags, 16, width,
516 (ULong)(va_arg (vargs, ULong)));
517 else
518 ret += myvprintf_int64(send, send_arg2, flags, 16, width,
519 (ULong)(va_arg (vargs, UInt)));
520 break;
521 case 'c': /* %c */
522 ret++;
523 send(va_arg (vargs, int), send_arg2);
524 break;
525 case 's': case 'S': { /* %s */
526 char *str = va_arg (vargs, char *);
527 if (str == (char*) 0) str = "(null)";
528 ret += myvprintf_str(send, send_arg2,
529 flags, width, str, format[i]=='S');
530 break;
531 }
sewardjdaf77af2005-07-19 14:17:37 +0000532 case 't': { /* %t, like %s but escaping chars for XML safety */
533 /* Note: simplistic; ignores field width and flags */
534 char *str = va_arg (vargs, char *);
535 if (str == (char*) 0) str = "(null)";
536 ret += myvprintf_str_XML_simplistic(send, send_arg2, str);
537 break;
538 }
539
sewardj1cf558c2005-04-25 01:36:56 +0000540// case 'y': { /* %y - print symbol */
541// Char buf[100];
542// Char *cp = buf;
543// Addr a = va_arg(vargs, Addr);
544//
545// if (flags & VG_MSG_PAREN)
546// *cp++ = '(';
547// if (VG_(get_fnname_w_offset)(a, cp, sizeof(buf)-4)) {
548// if (flags & VG_MSG_PAREN) {
549// cp += VG_(strlen)(cp);
550// *cp++ = ')';
551// *cp = '\0';
552// }
553// ret += myvprintf_str(send, send_arg2, flags, width, buf, 0);
554// }
555// break;
556// }
557 default:
558 break;
559 }
560 }
561 return ret;
562}
563
564
565/*------------------------------------------------------------*/
566/*--- Debuglog stuff. ---*/
567/*------------------------------------------------------------*/
568
569/* Only print messages whose stated level is less than or equal to
570 this. By default, it makes this entire subsystem silent. */
571
572static Int loglevel = 0;
573
sewardj1cf558c2005-04-25 01:36:56 +0000574/* Module startup. */
sewardj10759312005-05-30 23:52:47 +0000575/* EXPORTED */
sewardj1cf558c2005-04-25 01:36:56 +0000576void VG_(debugLog_startup) ( Int level, HChar* who )
577{
578 if (level < 0) level = 0;
579 if (level > 10) level = 10;
580 loglevel = level;
581 VG_(debugLog)(1, "debuglog",
582 "DebugLog system started by %s, "
583 "level %d logging requested\n",
584 who, loglevel);
585}
586
sewardj10759312005-05-30 23:52:47 +0000587/* Get the logging threshold level, as set by the most recent call to
588 VG_(debugLog_startup), or zero if there have been no such calls so
589 far. */
590/* EXPORTED */
591Int VG_(debugLog_getLevel) ( void )
592{
593 return loglevel;
594}
595
596
sewardj1cf558c2005-04-25 01:36:56 +0000597/* ------------ */
598
599typedef
600 struct {
601 HChar buf[100];
602 Int n;
603 }
604 printf_buf;
605
606static void add_to_buf ( HChar c, void* p )
607{
608 printf_buf* buf = (printf_buf*)p;
609
610 if (buf->n >= 100-10 /*paranoia*/ ) {
611 emit( buf->buf, local_strlen(buf->buf) );
612 buf->n = 0;
613 buf->buf[buf->n] = 0;
614 }
615 buf->buf[buf->n++] = c;
616 buf->buf[buf->n] = 0;
617}
618
619/* Send a logging message. Nothing is output unless 'level'
620 is <= the current loglevel. */
621/* EXPORTED */
622__attribute__((format(__printf__, 3, 4)))
623void VG_(debugLog) ( Int level, const HChar* modulename,
624 const HChar* format, ... )
625{
626 UInt ret, pid;
sewardj45f4e7c2005-09-27 19:20:21 +0000627 Int indent, depth, i;
sewardj1cf558c2005-04-25 01:36:56 +0000628 va_list vargs;
629 printf_buf buf;
sewardja5ebfa92005-04-25 02:04:54 +0000630
sewardj1cf558c2005-04-25 01:36:56 +0000631 if (level > loglevel)
632 return;
633
sewardjd85feff2005-04-25 02:37:56 +0000634 indent = 2*level - 1;
sewardja5ebfa92005-04-25 02:04:54 +0000635 if (indent < 1) indent = 1;
636
sewardj1cf558c2005-04-25 01:36:56 +0000637 buf.n = 0;
638 buf.buf[0] = 0;
639 pid = local_sys_getpid();
sewardj45f4e7c2005-09-27 19:20:21 +0000640
641 // Print one '>' in front of the messages for each level of self-hosting
642 // being performed.
643 depth = RUNNING_ON_VALGRIND;
644 for (i = 0; i < depth; i++) {
645 (void)myvprintf_str ( add_to_buf, &buf, 0, 1, ">", False );
646 }
647
sewardja5ebfa92005-04-25 02:04:54 +0000648 (void)myvprintf_str ( add_to_buf, &buf, 0, 2, "--", False );
649 (void)myvprintf_int64 ( add_to_buf, &buf, 0, 10, 1, (ULong)pid );
650 (void)myvprintf_str ( add_to_buf, &buf, 0, 1, ":", False );
sewardj1cf558c2005-04-25 01:36:56 +0000651 (void)myvprintf_int64 ( add_to_buf, &buf, 0, 10, 1, (ULong)level );
sewardja5ebfa92005-04-25 02:04:54 +0000652 (void)myvprintf_str ( add_to_buf, &buf, 0, 1, ":", False );
sewardj1cf558c2005-04-25 01:36:56 +0000653 (void)myvprintf_str ( add_to_buf, &buf, 0, 8, (HChar*)modulename, False );
sewardja5ebfa92005-04-25 02:04:54 +0000654 (void)myvprintf_str ( add_to_buf, &buf, 0, indent, "", False );
sewardj1cf558c2005-04-25 01:36:56 +0000655
656 va_start(vargs,format);
657
658 ret = VG_(debugLog_vprintf) ( add_to_buf, &buf, format, vargs );
659
660 if (buf.n > 0) {
661 emit( buf.buf, local_strlen(buf.buf) );
662 }
663
664 va_end(vargs);
665}
666
667
668
669/*--------------------------------------------------------------------*/
670/*--- end m_debuglog.c ---*/
671/*--------------------------------------------------------------------*/