2 This file is part of Callgrind, a Valgrind tool for call graph
5 Copyright (C) 2002-2010, Josef Weidendorfer (Josef.Weidendorfer@gmx.de)
7 This tool is derived from and contains lot of code from Cachegrind
8 Copyright (C) 2002 Nicholas Nethercote (njn@valgrind.org)
10 This program is free software; you can redistribute it and/or
11 modify it under the terms of the GNU General Public License as
12 published by the Free Software Foundation; either version 2 of the
13 License, or (at your option) any later version.
15 This program is distributed in the hope that it will be useful, but
16 WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
25 The GNU General Public License is contained in the file COPYING.
31 /* If debugging mode of, dummy functions are provided (see below)
35 /*------------------------------------------------------------*/
36 /*--- Debug output helpers ---*/
37 /*------------------------------------------------------------*/
39 static void print_indent(int s)
41 /* max of 40 spaces */
44 VG_(printf)("%s", sp+40-s);
47 void CLG_(print_bb)(int s, BB* bb)
54 VG_(printf)("BB %#lx (Obj '%s')", bb_addr(bb), bb->obj->name);
58 void print_mangled_cxt(Context* cxt, int rec_index)
63 VG_(printf)("(none)");
65 VG_(printf)("%s", cxt->fn[0]->name);
67 VG_(printf)("'%d", rec_index +1);
68 for(i=1;i<cxt->size;i++)
69 VG_(printf)("'%s", cxt->fn[i]->name);
75 void CLG_(print_cxt)(int s, Context* cxt, int rec_index)
83 UInt *pactive = CLG_(get_fn_entry)(cxt->fn[0]->number);
84 CLG_ASSERT(rec_index < cxt->fn[0]->separate_recursions);
86 VG_(printf)("Cxt %d" ,cxt->base_number + rec_index);
88 VG_(printf)(" [active=%d]", *pactive);
90 print_mangled_cxt(cxt, rec_index);
94 VG_(printf)("(no context)\n");
97 void CLG_(print_execstate)(int s, exec_state* es)
105 VG_(printf)("ExecState 0x0\n");
109 VG_(printf)("ExecState [Sig %d, collect %s, nonskipped %p]: jmps_passed %d\n",
110 es->sig, es->collect?"yes":"no",
111 es->nonskipped, es->jmps_passed);
115 void CLG_(print_bbcc)(int s, BBCC* bbcc)
125 VG_(printf)("BBCC 0x0\n");
132 VG_(printf)("%s +%#lx=%#lx, ",
133 bb->obj->name + bb->obj->last_slash_pos,
134 bb->offset, bb_addr(bb));
135 CLG_(print_cxt)(s+8, bbcc->cxt, bbcc->rec_index);
138 void CLG_(print_eventset)(int s, EventSet* es)
148 VG_(printf)("(EventSet not set)\n");
152 VG_(printf)("%5s (Size/Cap %d/%d): ",
153 es->name, es->size, es->capacity);
158 for(i=0; i< es->size; i++) {
161 if (es->e[i-1].nextTop == i)
164 VG_(printf)("%s", es->e[i].type->name);
171 void CLG_(print_cost)(int s, EventSet* es, ULong* c)
181 VG_(printf)("Cost (Nothing, EventSet not set)\n");
185 VG_(printf)("Cost (Null, EventSet %s)\n", es->name);
190 VG_(printf)("Cost (Nothing, EventSet %s with len 0)\n", es->name);
195 pos += VG_(printf)("Cost %s [%p]: %s %llu", es->name, c, es->e[0].type->name, c[0]);
205 pos += VG_(printf)(", ");
206 pos += VG_(printf)("%s %llu", es->e[i].type->name, c[i]);
213 void CLG_(print_short_jcc)(jCC* jcc)
216 VG_(printf)("%#lx => %#lx [%llu/%llu,%llu,%llu]",
217 bb_jmpaddr(jcc->from->bb),
218 bb_addr(jcc->to->bb),
220 jcc->cost ? jcc->cost[CLG_(sets).off_full_Ir]:0,
221 jcc->cost ? jcc->cost[CLG_(sets).off_full_Dr]:0,
222 jcc->cost ? jcc->cost[CLG_(sets).off_full_Dw]:0);
224 VG_(printf)("[Skipped JCC]");
227 void CLG_(print_jcc)(int s, jCC* jcc)
235 VG_(printf)("JCC to skipped function\n");
238 VG_(printf)("JCC %p from ", jcc);
239 CLG_(print_bbcc)(s+9, jcc->from);
242 CLG_(print_bbcc)(s+9, jcc->to);
244 VG_(printf)("Calls %llu\n", jcc->call_counter);
246 CLG_(print_cost)(s+9, CLG_(sets).full, jcc->cost);
249 /* dump out the current call stack */
250 void CLG_(print_stackentry)(int s, int sp)
259 ce = CLG_(get_call_entry)(sp);
260 VG_(printf)("[%-2d] SP %#lx, RA %#lx", sp, ce->sp, ce->ret_addr);
262 VG_(printf)(" NonSkipped BB %#lx / %s",
263 bb_addr(ce->nonskipped->bb),
264 ce->nonskipped->cxt->fn[0]->name);
267 CLG_(print_jcc)(5,ce->jcc);
272 static void print_call_stack()
276 VG_(printf)("Call Stack:\n");
277 for(c=0;c<CLG_(current_call_stack).sp;c++)
278 CLG_(print_stackentry)(-2, c);
282 void CLG_(print_bbcc_fn)(BBCC* bbcc)
287 VG_(printf)("%08x", 0);
291 VG_(printf)("%08lx/%c %d:", bb_addr(bbcc->bb),
292 (bbcc->bb->sect_kind == Vg_SectText) ? 'T' :
293 (bbcc->bb->sect_kind == Vg_SectData) ? 'D' :
294 (bbcc->bb->sect_kind == Vg_SectBSS) ? 'B' :
295 (bbcc->bb->sect_kind == Vg_SectGOT) ? 'G' :
296 (bbcc->bb->sect_kind == Vg_SectPLT) ? 'P' : 'U',
297 bbcc->cxt->base_number+bbcc->rec_index);
298 print_mangled_cxt(bbcc->cxt, bbcc->rec_index);
300 obj = bbcc->cxt->fn[0]->file->obj;
302 VG_(printf)(" %s", obj->name+obj->last_slash_pos);
304 if (VG_(strcmp)(bbcc->cxt->fn[0]->file->name, "???") !=0) {
305 VG_(printf)(" %s", bbcc->cxt->fn[0]->file->name);
306 if ((bbcc->cxt->fn[0] == bbcc->bb->fn) && (bbcc->bb->line>0))
307 VG_(printf)(":%d", bbcc->bb->line);
311 void CLG_(print_bbcc_cost)(int s, BBCC* bbcc)
323 VG_(printf)("BBCC 0x0\n");
330 CLG_(print_bbcc)(s, bbcc);
332 ecounter = bbcc->ecounter_sum;
335 VG_(printf)("ECounter: sum %llu ", ecounter);
336 for(i=0; i<bb->cjmp_count; i++) {
337 VG_(printf)("[%d]=%llu ",
338 bb->jmp[i].instr, bbcc->jmp[i].ecounter);
343 for(i=0; i<bb->instr_count; i++) {
344 InstrInfo* ii = &(bb->instr[i]);
346 VG_(printf)("[%2d] IOff %2d ecnt %3llu ",
347 i, ii->instr_offset, ecounter);
348 CLG_(print_cost)(s+5, ii->eventset, bbcc->cost + ii->cost_offset);
350 /* update execution counter */
351 if (cjmpNo < bb->cjmp_count)
352 if (bb->jmp[cjmpNo].instr == i) {
353 ecounter -= bbcc->jmp[cjmpNo].ecounter;
360 /* dump out an address with source info if available */
361 void CLG_(print_addr)(Addr addr)
363 Char fl_buf[FILENAME_LEN];
364 Char fn_buf[FN_NAME_LEN];
365 const UChar* obj_name;
370 VG_(printf)("%08lx", addr);
374 CLG_(get_debug_info)(addr, fl_buf, fn_buf, &ln, &di);
376 if (VG_(strcmp)(fn_buf,"???")==0)
377 VG_(printf)("%#lx", addr);
379 VG_(printf)("%#lx %s", addr, fn_buf);
382 obj_name = VG_(DebugInfo_get_filename)(di);
385 if (obj_name[i]=='/') opos = i+1;
389 VG_(printf)(" %s", obj_name+opos);
394 VG_(printf)(" (%s:%u)", fl_buf,ln);
397 void CLG_(print_addr_ln)(Addr addr)
399 CLG_(print_addr)(addr);
403 static ULong bb_written = 0;
405 void CLG_(print_bbno)(void)
407 if (bb_written != CLG_(stat).bb_executions) {
408 bb_written = CLG_(stat).bb_executions;
409 VG_(printf)("BB# %llu\n",CLG_(stat).bb_executions);
413 void CLG_(print_context)(void)
417 CLG_DEBUG(0,"In tid %d [%d] ",
418 CLG_(current_tid), CLG_(current_call_stack).sp);
419 bbcc = CLG_(current_state).bbcc;
420 print_mangled_cxt(CLG_(current_state).cxt,
421 bbcc ? bbcc->rec_index : 0);
425 void* CLG_(malloc)(HChar* cc, UWord s, char* f)
427 CLG_DEBUG(3, "Malloc(%lu) in %s.\n", s, f);
428 return VG_(malloc)(cc,s);
431 #else /* CLG_ENABLE_DEBUG */
433 void CLG_(print_bbno)(void) {}
434 void CLG_(print_context)(void) {}
435 void CLG_(print_jcc)(int s, jCC* jcc) {}
436 void CLG_(print_bbcc)(int s, BBCC* bbcc) {}
437 void CLG_(print_bbcc_fn)(BBCC* bbcc) {}
438 void CLG_(print_cost)(int s, EventSet* es, ULong* cost) {}
439 void CLG_(print_bb)(int s, BB* bb) {}
440 void CLG_(print_cxt)(int s, Context* cxt, int rec_index) {}
441 void CLG_(print_short_jcc)(jCC* jcc) {}
442 void CLG_(print_stackentry)(int s, int sp) {}
443 void CLG_(print_addr)(Addr addr) {}
444 void CLG_(print_addr_ln)(Addr addr) {}