Update copyright to LGPL on all files
[dyninst.git] / dyninstAPI / src / debug.C
1 /*
2  * Copyright (c) 1996-2009 Barton P. Miller
3  * 
4  * We provide the Paradyn Parallel Performance Tools (below
5  * described as "Paradyn") on an AS IS basis, and do not warrant its
6  * validity or performance.  We reserve the right to update, modify,
7  * or discontinue this software at any time.  We shall have no
8  * obligation to supply such updates or modifications or any other
9  * form of support to you.
10  * 
11  * By your use of Paradyn, you understand and agree that we (or any
12  * other person or entity with proprietary rights in Paradyn) are
13  * under no obligation to provide either maintenance services,
14  * update services, notices of latent defects, or correction of
15  * defects for Paradyn.
16  * 
17  * This library is free software; you can redistribute it and/or
18  * modify it under the terms of the GNU Lesser General Public
19  * License as published by the Free Software Foundation; either
20  * version 2.1 of the License, or (at your option) any later version.
21  * 
22  * This library is distributed in the hope that it will be useful,
23  * but WITHOUT ANY WARRANTY; without even the implied warranty of
24  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
25  * Lesser General Public License for more details.
26  * 
27  * You should have received a copy of the GNU Lesser General Public
28  * License along with this library; if not, write to the Free Software
29  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
30  */
31
32 // $Id: debug.C,v 1.6 2008/02/23 02:09:05 jaw Exp $
33
34 #include <stdio.h>
35 #include <stdarg.h>
36 #include <assert.h>
37 #include <string>
38 #include "common/h/Pair.h"
39 #include "common/h/Vector.h"
40 #include "util.h"
41 #include "BPatch.h"
42 #include "dyninstAPI/src/debug.h"
43 #include "EventHandler.h"
44
45 // Make a lock.
46
47 eventLock *debugPrintLock = NULL;
48
49 void BPatch_reportError(int errLevel, int num, const char *str) {
50     BPatch::reportError((BPatchErrorLevel) errLevel, num, str);
51 }
52
53 void
54 dyninst_log_perror(const char* msg) {
55     sprintf(errorLine, "%s: %s\n", msg, strerror(errno));
56     logLine(errorLine);
57     // fprintf(stderr, "%s", log_buffer);
58 }
59 void showInfoCallback(std::string msg)
60 {
61     BPatch::reportError(BPatchWarning, 0, msg.c_str());
62 }
63
64 char errorLine[1024];
65
66 void showErrorCallback(int num, std::string msg)
67 {
68     BPatch::reportError(BPatchSerious, num, msg.c_str());
69 }
70
71 void logLine(const char *line)
72 {
73     BPatch::reportError(BPatchWarning, 0, line);
74 }
75
76 // The unused parameter is used by Paradyn's version of this function.
77 void statusLine(const char *line, bool /* unused */ )
78 {
79     BPatch::reportError(BPatchInfo, 0, line);
80 }
81
82 //  bpfatal, bpsevere, bpwarn, and bpinfo are intended as drop-in 
83 //  replacements for printf.
84 #define ERR_BUF_SIZE 2048 // egad -- 1024 is not large enough
85
86 int bpfatal(const char *format, ...)
87 {
88   if (NULL == format) return -1;
89
90   char errbuf[ERR_BUF_SIZE];
91
92   va_list va;
93   va_start(va, format);
94 #if defined (i386_unknown_nt4_0)
95   _vsnprintf(errbuf, ERR_BUF_SIZE,format, va);
96 #else
97   vsnprintf(errbuf, ERR_BUF_SIZE,format, va);
98 #endif
99   va_end(va);
100
101   BPatch::reportError(BPatchFatal, 0, errbuf);
102
103   return 0;
104 }
105
106
107 int bpfatal_lf(const char *__file__, unsigned int __line__, const char *format, ...)
108 {
109   fprintf(stderr, "%s[%d]\n", __FILE__, __LINE__);
110   if (NULL == format) return -1;
111
112   char errbuf[ERR_BUF_SIZE];
113
114   fprintf(stderr, "%s[%d]\n", __FILE__, __LINE__);
115   int header_len = sprintf(errbuf, "[%s]%s[%d]: ", getThreadStr(getExecThreadID()), __file__, __line__);
116
117   fprintf(stderr, "%s[%d]\n", __FILE__, __LINE__);
118   va_list va;
119   va_start(va, format);
120   VSNPRINTF(errbuf + header_len, ERR_BUF_SIZE,format, va);
121   va_end(va);
122
123   fprintf(stderr, "%s[%d]\n", __FILE__, __LINE__);
124   BPatch::reportError(BPatchFatal, 0, errbuf);
125
126   fprintf(stderr, "%s[%d]\n", __FILE__, __LINE__);
127   return 0;
128 }
129
130 int bperr(const char *format, ...)
131 {
132   if (NULL == format) return -1;
133
134   char errbuf[ERR_BUF_SIZE];
135
136   va_list va;
137   va_start(va, format);
138 #if defined (i386_unknown_nt4_0)
139   int errbuflen = _vsnprintf(errbuf, ERR_BUF_SIZE, format, va);
140 #else
141   int errbuflen = vsnprintf(errbuf, ERR_BUF_SIZE, format, va);
142 #endif
143   va_end(va);
144
145   char syserr[128];
146   if (errno) {
147 #if defined (i386_unknown_nt4_0)
148     int syserrlen = _snprintf(syserr, 128," [%d: %s]", errno, strerror(errno));
149 #else
150     int syserrlen = snprintf(syserr, 128," [%d: %s]", errno, strerror(errno));
151 #endif
152     /* reset errno so that future calls to this function don't report same error */
153     errno = 0; 
154
155     if ((errbuflen + syserrlen) < ERR_BUF_SIZE)
156       strcat(errbuf, syserr);
157     else {
158       BPatch::reportError(BPatchSerious, 0, errbuf);
159       BPatch::reportError(BPatchSerious, 0, syserr);
160       return 0;
161     }
162   }
163   BPatch::reportError(BPatchSerious, 0, errbuf);
164
165   return 0;
166 }
167
168 int bpwarn(const char *format, ...)
169 {
170   if (NULL == format) return -1;
171
172   char errbuf[ERR_BUF_SIZE];
173
174   va_list va;
175   va_start(va, format);
176 #if defined (i386_unknown_nt4_0)
177   _vsnprintf(errbuf, ERR_BUF_SIZE,format, va);
178 #else
179   vsnprintf(errbuf, ERR_BUF_SIZE,format, va);
180 #endif
181   va_end(va);
182
183   BPatch::reportError(BPatchWarning, 0, errbuf);
184
185   return 0;
186 }
187
188 int bpinfo(const char *format, ...)
189 {
190   if (NULL == format) return -1;
191
192   char errbuf[ERR_BUF_SIZE];
193
194   va_list va;
195   va_start(va, format);
196 #if defined (i386_unknown_nt4_0)
197   _vsnprintf(errbuf, ERR_BUF_SIZE, format, va);
198 #else
199   vsnprintf(errbuf, ERR_BUF_SIZE, format, va);
200 #endif
201   va_end(va);
202
203   BPatch::reportError(BPatchInfo, 0, errbuf);
204
205   return 0;
206 }
207
208
209 // Internal debugging
210
211 int dyn_debug_signal = 0;
212 int dyn_debug_infrpc = 0;
213 int dyn_debug_startup = 0;
214 int dyn_debug_parsing = 0;
215 int dyn_debug_forkexec = 0;
216 int dyn_debug_proccontrol = 0;
217 int dyn_debug_stackwalk = 0;
218 int dyn_debug_dbi = 0;
219 int dyn_debug_inst = 0;
220 int dyn_debug_reloc = 0;
221 int dyn_debug_dyn_unw = 0;
222 int dyn_debug_dyn_dbi = 0;
223 int dyn_debug_mutex = 0;
224 int dyn_debug_mailbox = 0;
225 int dyn_debug_async = 0;
226 int dyn_debug_dwarf = 0;
227 int dyn_debug_thread = 0;
228 int dyn_debug_rtlib = 0;
229 int dyn_debug_catchup = 0;
230 int dyn_debug_bpatch = 0;
231 int dyn_debug_regalloc = 0;
232 int dyn_debug_ast = 0;
233 int dyn_debug_write = 0;
234 int dyn_debug_liveness = 0;
235 int dyn_debug_infmalloc = 0;
236 int dyn_debug_crash = 0;
237 char *dyn_debug_crash_debugger = NULL;
238 int dyn_debug_stackanalysis = 0;
239
240 static char *dyn_debug_write_filename = NULL;
241 static FILE *dyn_debug_write_file = NULL;
242
243 bool init_debug() {
244   char *p;
245   if ( (p=getenv("DYNINST_DEBUG_SIGNAL"))) {
246     fprintf(stderr, "Enabling DyninstAPI signal debug\n");
247     dyn_debug_signal = 1;
248   }
249   if ( (p=getenv("DYNINST_DEBUG_INFRPC"))) {
250     fprintf(stderr, "Enabling DyninstAPI inferior RPC debug\n");
251     dyn_debug_infrpc = 1;
252   }
253   if ( (p=getenv("DYNINST_DEBUG_INFERIORRPC"))) {
254     fprintf(stderr, "Enabling DyninstAPI inferior RPC debug\n");
255     dyn_debug_infrpc = 1;
256   }
257   if ( (p=getenv("DYNINST_DEBUG_STARTUP"))) {
258     fprintf(stderr, "Enabling DyninstAPI startup debug\n");
259     dyn_debug_startup = 1;
260   }
261   if ( (p=getenv("DYNINST_DEBUG_PARSING"))) {
262           if(p[0] != '0') {
263                 fprintf(stderr, "Enabling DyninstAPI parsing debug\n");
264             dyn_debug_parsing = 1;
265           }
266   }
267   if ( (p=getenv("DYNINST_DEBUG_PARSE"))) {
268           if(p[0] != '0') {
269                 fprintf(stderr, "Enabling DyninstAPI parsing debug\n");
270             dyn_debug_parsing = 1;
271           }
272   }
273   if ( (p=getenv("DYNINST_DEBUG_FORKEXEC"))) {
274     fprintf(stderr, "Enabling DyninstAPI forkexec debug\n");
275     dyn_debug_forkexec = 1;
276   }
277   if ( (p=getenv("DYNINST_DEBUG_PROCCONTROL"))) {
278     fprintf(stderr, "Enabling DyninstAPI process control debug\n");
279     dyn_debug_proccontrol = 1;
280   }
281   if ( (p=getenv("DYNINST_DEBUG_STACKWALK"))) {
282     fprintf(stderr, "Enabling DyninstAPI stack walking debug\n");
283     dyn_debug_stackwalk = 1;
284   }
285   if ( (p=getenv("DYNINST_DEBUG_INST"))) {
286     fprintf(stderr, "Enabling DyninstAPI inst debug\n");
287     dyn_debug_inst = 1;
288   }
289   if ( (p=getenv("DYNINST_DEBUG_RELOC"))) {
290     fprintf(stderr, "Enabling DyninstAPI relocation debug\n");
291     dyn_debug_reloc = 1;
292   }
293   if ( (p=getenv("DYNINST_DEBUG_RELOCATION"))) {
294     fprintf(stderr, "Enabling DyninstAPI relocation debug\n");
295     dyn_debug_reloc = 1;
296   }
297   if ( (p=getenv("DYNINST_DEBUG_DYN_UNW"))) {
298     fprintf(stderr, "Enabling DyninstAPI dynamic unwind debug\n");
299     dyn_debug_dyn_unw = 1;
300     }
301   if ( (p=getenv("DYNINST_DEBUG_DBI"))) {
302     fprintf(stderr, "Enabling DyninstAPI debugger interface debug\n");
303     dyn_debug_dyn_dbi = 1;
304     }
305   if ( (p=getenv("DYNINST_DEBUG_MUTEX"))) {
306     fprintf(stderr, "Enabling DyninstAPI mutex debug\n");
307     dyn_debug_mutex = 1;
308     }
309   if ( (p=getenv("DYNINST_DEBUG_MAILBOX"))) {
310     fprintf(stderr, "Enabling DyninstAPI callbacks debug\n");
311     dyn_debug_mailbox= 1;
312     }
313   if ( (p=getenv("DYNINST_DEBUG_DWARF"))) {
314     fprintf(stderr, "Enabling DyninstAPI dwarf debug\n");
315     dyn_debug_dwarf= 1;
316     }
317   if ( (p=getenv("DYNINST_DEBUG_ASYNC"))) {
318     fprintf(stderr, "Enabling DyninstAPI async debug\n");
319     dyn_debug_async= 1;
320     }
321   if ( (p=getenv("DYNINST_DEBUG_THREAD"))) {
322       fprintf(stderr, "Enabling DyninstAPI thread debug\n");
323       dyn_debug_thread = 1;
324   }
325   if ( (p=getenv("DYNINST_DEBUG_RTLIB"))) {
326       fprintf(stderr, "Enabling DyninstAPI RTlib debug\n");
327       dyn_debug_rtlib = 1;
328   }
329   if ( (p=getenv("DYNINST_DEBUG_CATCHUP"))) {
330       fprintf(stderr, "Enabling DyninstAPI catchup debug\n");
331       dyn_debug_catchup = 1;
332   }
333   if ( (p=getenv("DYNINST_DEBUG_BPATCH"))) {
334       fprintf(stderr, "Enabling DyninstAPI bpatch debug\n");
335       dyn_debug_bpatch = 1;
336   }
337   if ( (p=getenv("DYNINST_DEBUG_REGALLOC"))) {
338       fprintf(stderr, "Enabling DyninstAPI register allocation debug\n");
339       dyn_debug_regalloc = 1;
340   }
341   if ( (p=getenv("DYNINST_DEBUG_AST"))) {
342       fprintf(stderr, "Enabling DyninstAPI ast debug\n");
343       dyn_debug_ast = 1;
344   }
345   if ( (p=getenv("DYNINST_DEBUG_WRITE"))) {
346     fprintf(stderr, "Enabling DyninstAPI process write debugging\n");
347     dyn_debug_write = 1;
348     dyn_debug_write_filename = p;
349   }
350   if ( (p=getenv("DYNINST_DEBUG_LIVENESS"))) {
351     fprintf(stderr, "Enabling DyninstAPI liveness debugging\n");
352     dyn_debug_liveness = 1;
353   }
354   if ( (p=getenv("DYNINST_DEBUG_INFMALLOC")) ||
355        (p=getenv("DYNINST_DEBUG_INFERIORMALLOC"))) {
356     fprintf(stderr, "Enabling DyninstAPI inferior malloc debugging\n");
357     dyn_debug_infmalloc = 1;
358   }
359   if ((p=getenv("DYNINST_DEBUG_CRASH"))) {
360      fprintf(stderr, "Enable DyninstAPI crash debugging\n");
361      dyn_debug_crash = 1;
362      dyn_debug_crash_debugger = p;
363   }
364   if ((p=getenv("DYNINST_DEBUG_STACKANALYSIS"))) {
365     fprintf(stderr, "Enabling DyninstAPI stack analysis debugging\n");
366     dyn_debug_stackanalysis = 1;
367   }
368
369   debugPrintLock = new eventLock();
370
371   return true;
372 }
373
374 int signal_printf_int(const char *format, ...)
375 {
376   if (!dyn_debug_signal) return 0;
377   if (NULL == format) return -1;
378
379   debugPrintLock->_Lock(FILE__, __LINE__);
380
381   fprintf(stderr, "[%s]", getThreadStr(getExecThreadID()));
382   va_list va;
383   va_start(va, format);
384   int ret = vfprintf(stderr, format, va);
385   va_end(va);
386
387   debugPrintLock->_Unlock(FILE__, __LINE__);
388
389   return ret;
390 }
391
392 int inferiorrpc_printf_int(const char *format, ...)
393 {
394   if (!dyn_debug_infrpc) return 0;
395   if (NULL == format) return -1;
396
397   debugPrintLock->_Lock(FILE__, __LINE__);
398
399   fprintf(stderr, "[%s]", getThreadStr(getExecThreadID()));
400   va_list va;
401   va_start(va, format);
402   int ret = vfprintf(stderr, format, va);
403   va_end(va);
404
405   debugPrintLock->_Unlock(FILE__, __LINE__);
406
407   return ret;
408 }
409
410 int startup_printf_int(const char *format, ...)
411 {
412   if (!dyn_debug_startup) return 0;
413   if (NULL == format) return -1;
414
415   debugPrintLock->_Lock(FILE__, __LINE__);
416
417   fprintf(stderr, "[%s]", getThreadStr(getExecThreadID()));
418   va_list va;
419   va_start(va, format);
420   int ret = vfprintf(stderr, format, va);
421   va_end(va);
422
423   debugPrintLock->_Unlock(FILE__, __LINE__);
424
425   return ret;
426 }
427
428 int parsing_printf_int(const char *format, ...)
429 {
430   if (!dyn_debug_parsing) return 0;
431   if (NULL == format) return -1;
432
433   debugPrintLock->_Lock(FILE__, __LINE__);
434
435   //fprintf(stderr, "[%s]", getThreadStr(getExecThreadID()));
436   va_list va;
437   va_start(va, format);
438
439   int ret = vfprintf(stderr, format, va);
440
441   va_end(va);
442
443   debugPrintLock->_Unlock(FILE__, __LINE__);
444
445   return ret;
446 }
447
448 int forkexec_printf_int(const char *format, ...)
449 {
450   if (!dyn_debug_forkexec) return 0;
451   if (NULL == format) return -1;
452
453   debugPrintLock->_Lock(FILE__, __LINE__);
454
455   fprintf(stderr, "[%s]", getThreadStr(getExecThreadID()));
456   va_list va;
457   va_start(va, format);
458   int ret = vfprintf(stderr, format, va);
459   va_end(va);
460
461   debugPrintLock->_Unlock(FILE__, __LINE__);
462
463   return ret;
464 }
465
466 int proccontrol_printf_int(const char *format, ...)
467 {
468   if (!dyn_debug_proccontrol) return 0;
469   if (NULL == format) return -1;
470
471   debugPrintLock->_Lock(FILE__, __LINE__);
472
473   fprintf(stderr, "[%s]", getThreadStr(getExecThreadID()));
474   va_list va;
475   va_start(va, format);
476   int ret = vfprintf(stderr, format, va);
477   va_end(va);
478
479   debugPrintLock->_Unlock(FILE__, __LINE__);
480
481   return ret;
482 }
483
484 int stackwalk_printf_int(const char *format, ...)
485 {
486   if (!dyn_debug_stackwalk) return 0;
487   if (NULL == format) return -1;
488
489   debugPrintLock->_Lock(FILE__, __LINE__);
490
491   fprintf(stderr, "[%s]", getThreadStr(getExecThreadID()));
492   va_list va;
493   va_start(va, format);
494   int ret = vfprintf(stderr, format, va);
495   va_end(va);
496
497   debugPrintLock->_Unlock(FILE__, __LINE__);
498
499   return ret;
500 }
501
502
503
504 int inst_printf_int(const char *format, ...)
505 {
506   if (!dyn_debug_inst) return 0;
507   if (NULL == format) return -1;
508
509   debugPrintLock->_Lock(FILE__, __LINE__);
510
511   fprintf(stderr, "[%s]", getThreadStr(getExecThreadID()));
512   va_list va;
513   va_start(va, format);
514   int ret = vfprintf(stderr, format, va);
515   va_end(va);
516
517   debugPrintLock->_Unlock(FILE__, __LINE__);
518
519   return ret;
520 }
521
522 int reloc_printf_int(const char *format, ...)
523 {
524   if (!dyn_debug_reloc) return 0;
525   if (NULL == format) return -1;
526
527   debugPrintLock->_Lock(FILE__, __LINE__);
528   
529   fprintf(stderr, "[%s]", getThreadStr(getExecThreadID()));
530   va_list va;
531   va_start(va, format);
532   int ret = vfprintf(stderr, format, va);
533   va_end(va);
534
535   debugPrintLock->_Unlock(FILE__, __LINE__);
536
537   return ret;
538 }
539
540 int dyn_unw_printf_int(const char *format, ...)
541 {
542   if (!dyn_debug_dyn_unw ) return 0;
543   if (NULL == format) return -1;
544
545   debugPrintLock->_Lock(FILE__, __LINE__);
546   
547   fprintf(stderr, "[%s]", getThreadStr(getExecThreadID()));
548   va_list va;
549   va_start(va, format);
550   int ret = vfprintf(stderr, format, va);
551   va_end(va);
552
553   debugPrintLock->_Unlock(FILE__, __LINE__);
554
555   return ret;
556 }
557
558 int dbi_printf_int(const char *format, ...)
559 {
560   if (!dyn_debug_dyn_dbi ) return 0;
561   if (NULL == format) return -1;
562
563   debugPrintLock->_Lock(FILE__, __LINE__);
564   
565   fprintf(stderr, "[%s]", getThreadStr(getExecThreadID()));
566   va_list va;
567   va_start(va, format);
568   int ret = vfprintf(stderr, format, va);
569   va_end(va);
570
571   debugPrintLock->_Unlock(FILE__, __LINE__);
572
573   return ret;
574 }
575
576 int mutex_printf_int(const char *format, ...)
577 {
578   if (!dyn_debug_mutex ) return 0;
579   if (NULL == format) return -1;
580
581   debugPrintLock->_Lock(FILE__, __LINE__);
582   
583   fprintf(stderr, "[%s]", getThreadStr(getExecThreadID()));
584   va_list va;
585   va_start(va, format);
586   int ret = vfprintf(stderr, format, va);
587   va_end(va);
588
589   debugPrintLock->_Unlock(FILE__, __LINE__);
590
591   return ret;
592 }
593
594 int mailbox_printf_int(const char *format, ...)
595 {
596   if (!dyn_debug_mailbox ) return 0;
597   if (NULL == format) return -1;
598
599   debugPrintLock->_Lock(FILE__, __LINE__);
600   
601   fprintf(stderr, "[%s]", getThreadStr(getExecThreadID()));
602   va_list va;
603   va_start(va, format);
604   int ret = vfprintf(stderr, format, va);
605   va_end(va);
606
607   debugPrintLock->_Unlock(FILE__, __LINE__);
608
609   return ret;
610 }
611
612 int async_printf_int(const char *format, ...)
613 {
614   if (!dyn_debug_async ) return 0;
615   if (NULL == format) return -1;
616
617   debugPrintLock->_Lock(FILE__, __LINE__);
618   
619   fprintf(stderr, "[%s]", getThreadStr(getExecThreadID()));
620   va_list va;
621   va_start(va, format);
622   int ret = vfprintf(stderr, format, va);
623   va_end(va);
624
625   debugPrintLock->_Unlock(FILE__, __LINE__);
626
627   return ret;
628 }
629
630 int dwarf_printf_int(const char *format, ...)
631 {
632   if (!dyn_debug_dwarf ) return 0;
633   if (NULL == format) return -1;
634
635   debugPrintLock->_Lock(FILE__, __LINE__);
636   
637   fprintf(stderr, "(dwarf) [thread %s]: ", getThreadStr(getExecThreadID()));
638   va_list va;
639   va_start(va, format);
640   int ret = vfprintf(stderr, format, va);
641   va_end(va);
642
643   debugPrintLock->_Unlock(FILE__, __LINE__);
644
645   return ret;
646 }
647
648
649 int thread_printf_int(const char *format, ...)
650 {
651   if (!dyn_debug_thread) return 0;
652   if (NULL == format) return -1;
653
654   debugPrintLock->_Lock(FILE__, __LINE__);
655   
656   fprintf(stderr, "[%s]: ", getThreadStr(getExecThreadID()));
657   va_list va;
658   va_start(va, format);
659   int ret = vfprintf(stderr, format, va);
660   va_end(va);
661
662   debugPrintLock->_Unlock(FILE__, __LINE__);
663
664   return ret;
665 }
666
667
668 int catchup_printf_int(const char *format, ...)
669 {
670
671     if (!dyn_debug_catchup) return 0;
672     if (NULL == format) return -1;
673     
674     debugPrintLock->_Lock(FILE__, __LINE__);
675     
676     fprintf(stderr, "[%s]: ", getThreadStr(getExecThreadID()));
677     va_list va;
678     va_start(va, format);
679     int ret = vfprintf(stderr, format, va);
680     va_end(va);
681     
682     debugPrintLock->_Unlock(FILE__, __LINE__);
683     
684     return ret;
685 }
686
687 int bpatch_printf(const char *format, ...)
688 {
689   if (!dyn_debug_bpatch) return 0;
690   if (NULL == format) return -1;
691
692   debugPrintLock->_Lock(FILE__, __LINE__);
693   
694   fprintf(stderr, "[%s]: ", getThreadStr(getExecThreadID()));
695   va_list va;
696   va_start(va, format);
697   int ret = vfprintf(stderr, format, va);
698   va_end(va);
699
700   debugPrintLock->_Unlock(FILE__, __LINE__);
701
702   return ret;
703 }
704
705 int regalloc_printf_int(const char *format, ...)
706 {
707   if (!dyn_debug_regalloc) return 0;
708   if (NULL == format) return -1;
709
710   debugPrintLock->_Lock(FILE__, __LINE__);
711   
712   fprintf(stderr, "[%s]: ", getThreadStr(getExecThreadID()));
713   va_list va;
714   va_start(va, format);
715   int ret = vfprintf(stderr, format, va);
716   va_end(va);
717
718   debugPrintLock->_Unlock(FILE__, __LINE__);
719
720   return ret;
721 }
722
723 int ast_printf_int(const char *format, ...)
724 {
725   if (!dyn_debug_ast) return 0;
726   if (NULL == format) return -1;
727
728   debugPrintLock->_Lock(FILE__, __LINE__);
729   
730   fprintf(stderr, "[%s]: ", getThreadStr(getExecThreadID()));
731   va_list va;
732   va_start(va, format);
733   int ret = vfprintf(stderr, format, va);
734   va_end(va);
735
736   debugPrintLock->_Unlock(FILE__, __LINE__);
737
738   return ret;
739 }
740
741 int write_printf_int(const char *format, ...)
742 {
743   if (!dyn_debug_write) return 0;
744   if (NULL == format) return -1;
745
746   debugPrintLock->_Lock(FILE__, __LINE__);
747   
748   if (!dyn_debug_write_file) {
749     if (dyn_debug_write_filename && strlen(dyn_debug_write_filename)) {
750       dyn_debug_write_file = fopen(dyn_debug_write_filename, "w");
751     }
752     if (!dyn_debug_write_file) {
753       dyn_debug_write_file = stderr;
754     }
755   }
756
757   va_list va;
758   va_start(va, format);
759   int ret = vfprintf(dyn_debug_write_file, format, va);
760   va_end(va);
761   fflush(dyn_debug_write_file);
762   
763   debugPrintLock->_Unlock(FILE__, __LINE__);
764
765   return ret;
766 }
767
768 int liveness_printf_int(const char *format, ...)
769 {
770   if (!dyn_debug_liveness) return 0;
771   if (NULL == format) return -1;
772
773   debugPrintLock->_Lock(FILE__, __LINE__);
774   
775   fprintf(stderr, "[%s]: ", getThreadStr(getExecThreadID()));
776   va_list va;
777   va_start(va, format);
778   int ret = vfprintf(stderr, format, va);
779   va_end(va);
780
781   debugPrintLock->_Unlock(FILE__, __LINE__);
782
783   return ret;
784 }
785
786 int infmalloc_printf_int(const char *format, ...)
787 {
788   if (!dyn_debug_infmalloc) return 0;
789   if (NULL == format) return -1;
790
791   debugPrintLock->_Lock(FILE__, __LINE__);
792   
793   fprintf(stderr, "[%s]: ", getThreadStr(getExecThreadID()));
794   va_list va;
795   va_start(va, format);
796   int ret = vfprintf(stderr, format, va);
797   va_end(va);
798
799   debugPrintLock->_Unlock(FILE__, __LINE__);
800
801   return ret;
802 }
803
804
805 int stackanalysis_printf_int(const char *format, ...)
806 {
807   if (!dyn_debug_stackanalysis) return 0;
808   if (NULL == format) return -1;
809
810   debugPrintLock->_Lock(FILE__, __LINE__);
811   
812   fprintf(stderr, "[%s]: ", getThreadStr(getExecThreadID()));
813   va_list va;
814   va_start(va, format);
815   int ret = vfprintf(stderr, format, va);
816   va_end(va);
817
818   debugPrintLock->_Unlock(FILE__, __LINE__);
819
820   return ret;
821 }
822
823 StatContainer stats_instru;
824 StatContainer stats_ptrace;
825 StatContainer stats_parse;
826 StatContainer stats_codegen;
827
828 TimeStatistic running_time;
829
830 bool have_stats = 0;
831
832 bool init_stats() {
833     char *p;
834     running_time.start();
835
836     if ((p = getenv("DYNINST_STATS_INST"))) {
837         fprintf(stderr, "Enabling DyninstAPI instrumentation statistics\n");
838         stats_instru.add(INST_GENERATE_TIMER, TimerStat);
839         stats_instru.add(INST_INSTALL_TIMER, TimerStat);
840         stats_instru.add(INST_LINK_TIMER, TimerStat);
841         stats_instru.add(INST_REMOVE_TIMER, TimerStat);
842         stats_instru.add(INST_GENERATE_COUNTER, CountStat);
843         stats_instru.add(INST_INSTALL_COUNTER, CountStat);
844         stats_instru.add(INST_LINK_COUNTER, CountStat);
845         stats_instru.add(INST_REMOVE_COUNTER, CountStat);
846         have_stats = true;
847     }
848     
849
850     if ((p = getenv("DYNINST_STATS_PTRACE"))) {
851         fprintf(stderr, "Enabling DyninstAPI ptrace statistics\n");
852         stats_ptrace.add(PTRACE_WRITE_TIMER, TimerStat);
853         stats_ptrace.add(PTRACE_READ_TIMER, TimerStat);
854
855         stats_ptrace.add(PTRACE_WRITE_COUNTER, CountStat);
856         stats_ptrace.add(PTRACE_READ_COUNTER, CountStat);
857
858         stats_ptrace.add(PTRACE_WRITE_AMOUNT, CountStat);
859         stats_ptrace.add(PTRACE_READ_AMOUNT, CountStat);
860         have_stats = true;
861     }
862     
863     if ((p = getenv("DYNINST_STATS_PARSING"))) {
864         fprintf(stderr, "Enabling DyninstAPI parsing statistics\n");
865         stats_parse.add(PARSE_SYMTAB_TIMER, TimerStat);
866         stats_parse.add(PARSE_ANALYZE_TIMER, TimerStat);
867         have_stats = true;
868     }
869
870     if ((p = getenv("DYNINST_STATS_CODEGEN"))) {
871         fprintf(stderr, "Enabling DyninstAPI code generation statistics\n");
872
873         stats_codegen.add(CODEGEN_AST_TIMER, TimerStat);
874         stats_codegen.add(CODEGEN_AST_COUNTER, CountStat);
875         stats_codegen.add(CODEGEN_REGISTER_TIMER, TimerStat);
876         stats_codegen.add(CODEGEN_LIVENESS_TIMER, TimerStat);
877         have_stats = true;
878     }
879     return have_stats;
880 }
881
882 bool print_stats() {
883     char *p;
884
885     running_time.stop();
886     if (have_stats) 
887         fprintf(stderr, "Running time: %f sec (user), %f sec (system), %f sec (wall)\n",
888                 running_time.usecs(),
889                 running_time.ssecs(),
890                 running_time.wsecs());
891     running_time.start();
892
893     if ((p = getenv("DYNINST_STATS_INST"))) {
894         fprintf(stderr, "Printing DyninstAPI instrumentation statistics\n");
895         fprintf(stderr, "  Generation: %ld calls, %f sec (user), %f sec (system), %f sec (wall)\n",
896                 stats_instru[INST_GENERATE_COUNTER]->value(),
897                 stats_instru[INST_GENERATE_TIMER]->usecs(),
898                 stats_instru[INST_GENERATE_TIMER]->ssecs(),
899                 stats_instru[INST_GENERATE_TIMER]->wsecs());
900         fprintf(stderr, "  Installation: %ld calls, %f sec (user), %f sec (system), %f sec (wall)\n",
901                 stats_instru[INST_INSTALL_COUNTER]->value(),
902                 stats_instru[INST_INSTALL_TIMER]->usecs(),
903                 stats_instru[INST_INSTALL_TIMER]->ssecs(),
904                 stats_instru[INST_INSTALL_TIMER]->wsecs());
905         fprintf(stderr, "  Linking: %ld calls, %f sec (user), %f sec (system), %f sec (wall)\n",
906                 stats_instru[INST_LINK_COUNTER]->value(),
907                 stats_instru[INST_LINK_TIMER]->usecs(),
908                 stats_instru[INST_LINK_TIMER]->ssecs(),
909                 stats_instru[INST_LINK_TIMER]->wsecs());
910         fprintf(stderr, "  Removal: %ld calls, %f sec (user), %f sec (system), %f sec (wall)\n",
911                 stats_instru[INST_REMOVE_COUNTER]->value(),
912                 stats_instru[INST_REMOVE_TIMER]->usecs(),
913                 stats_instru[INST_REMOVE_TIMER]->ssecs(),
914                 stats_instru[INST_REMOVE_TIMER]->wsecs());
915     }
916
917     if ((p = getenv("DYNINST_STATS_PTRACE"))) {
918         fprintf(stderr, "Printing DyninstAPI ptrace statistics\n");
919         fprintf(stderr, "  Write: %ld calls, %ld bytes, %f sec (user), %f sec (system), %f sec (wall)\n",
920                 stats_ptrace[PTRACE_WRITE_COUNTER]->value(),
921                 stats_ptrace[PTRACE_WRITE_AMOUNT]->value(),
922                 stats_ptrace[PTRACE_WRITE_TIMER]->usecs(),
923                 stats_ptrace[PTRACE_WRITE_TIMER]->ssecs(),
924                 stats_ptrace[PTRACE_WRITE_TIMER]->wsecs());
925
926         fprintf(stderr, "  Read: %ld calls, %ld bytes, %f sec (user), %f sec (system), %f sec (wall)\n",
927                 stats_ptrace[PTRACE_READ_COUNTER]->value(),
928                 stats_ptrace[PTRACE_READ_AMOUNT]->value(),
929                 stats_ptrace[PTRACE_READ_TIMER]->usecs(),
930                 stats_ptrace[PTRACE_READ_TIMER]->ssecs(),
931                 stats_ptrace[PTRACE_READ_TIMER]->wsecs());
932     }
933
934     if ((p = getenv("DYNINST_STATS_PARSING"))) {
935         fprintf(stderr, "Printing DyninstAPI parsing statistics\n");
936         fprintf(stderr, "  Symtab parsing:  %f sec (user), %f sec (system), %f sec (wall)\n",
937                 stats_parse[PARSE_SYMTAB_TIMER]->usecs(),
938                 stats_parse[PARSE_SYMTAB_TIMER]->ssecs(),
939                 stats_parse[PARSE_SYMTAB_TIMER]->wsecs());
940         fprintf(stderr, "  Analysis:  %f sec (user), %f sec (system), %f sec (wall)\n",
941                 stats_parse[PARSE_ANALYZE_TIMER]->usecs(),
942                 stats_parse[PARSE_ANALYZE_TIMER]->ssecs(),
943                 stats_parse[PARSE_ANALYZE_TIMER]->wsecs());
944     }
945
946     if ((p = getenv("DYNINST_STATS_CODEGEN"))) {
947         fprintf(stderr, "Printing DyninstAPI code generation statistics\n");
948         fprintf(stderr, "  AST generation: %ld calls, %f sec (user), %f sec (system), %f sec (wall)\n",
949                 stats_codegen[CODEGEN_AST_COUNTER]->value(),
950                 stats_codegen[CODEGEN_AST_TIMER]->usecs(),
951                 stats_codegen[CODEGEN_AST_TIMER]->ssecs(),
952                 stats_codegen[CODEGEN_AST_TIMER]->wsecs());
953
954         fprintf(stderr, "  Register allocation: %f sec (user), %f sec (system), %f sec (wall)\n",
955                 stats_codegen[CODEGEN_REGISTER_TIMER]->usecs(),
956                 stats_codegen[CODEGEN_REGISTER_TIMER]->ssecs(),
957                 stats_codegen[CODEGEN_REGISTER_TIMER]->wsecs());
958         
959         fprintf(stderr, "  Liveness analysis: %f sec (user), %f sec (system), %f sec (wall)\n",
960                 stats_codegen[CODEGEN_LIVENESS_TIMER]->usecs(),
961                 stats_codegen[CODEGEN_LIVENESS_TIMER]->ssecs(),
962                 stats_codegen[CODEGEN_LIVENESS_TIMER]->wsecs());
963     }
964     return true;
965 }
966