Add bug 467036 Add time cost statistics for Regtest to NEWS
[valgrind.git] / callgrind / debug.c
blob58af44a66477fad0ac334a72b06febafa760450d
1 /*
2 This file is part of Callgrind, a Valgrind tool for call graph
3 profiling programs.
5 Copyright (C) 2002-2017, Josef Weidendorfer (Josef.Weidendorfer@gmx.de)
7 This tool is derived from and contains lot of code from Cachegrind
8 Copyright (C) 2002-2017 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, see <http://www.gnu.org/licenses/>.
23 The GNU General Public License is contained in the file COPYING.
26 #include "global.h"
27 #include "events.h"
29 /* If debugging mode of, dummy functions are provided (see below)
31 #if CLG_ENABLE_DEBUG
33 /*------------------------------------------------------------*/
34 /*--- Debug output helpers ---*/
35 /*------------------------------------------------------------*/
37 static void print_indent(int s)
39 /* max of 40 spaces */
40 const HChar sp[] = " ";
41 if (s>40) s=40;
42 VG_(printf)("%s", sp+40-s);
45 void CLG_(print_bb)(int s, BB* bb)
47 if (s<0) {
48 s = -s;
49 print_indent(s);
52 VG_(printf)("BB %#lx (Obj '%s')", bb_addr(bb), bb->obj->name);
55 static
56 void print_mangled_cxt(Context* cxt, int rec_index)
58 int i;
60 if (!cxt)
61 VG_(printf)("(none)");
62 else {
63 VG_(printf)("%s", cxt->fn[0]->name);
64 if (rec_index >0)
65 VG_(printf)("'%d", rec_index +1);
66 for(i=1;i<cxt->size;i++)
67 VG_(printf)("'%s", cxt->fn[i]->name);
73 void CLG_(print_cxt)(Int s, Context* cxt, int rec_index)
75 if (s<0) {
76 s = -s;
77 print_indent(s);
80 if (cxt) {
81 UInt *pactive = CLG_(get_fn_entry)(cxt->fn[0]->number);
82 CLG_ASSERT(rec_index < cxt->fn[0]->separate_recursions);
84 VG_(printf)("Cxt %u" ,cxt->base_number + rec_index);
85 if (*pactive>0)
86 VG_(printf)(" [active=%u]", *pactive);
87 VG_(printf)(": ");
88 print_mangled_cxt(cxt, rec_index);
89 VG_(printf)("\n");
91 else
92 VG_(printf)("(no context)\n");
95 void CLG_(print_execstate)(int s, exec_state* es)
97 if (s<0) {
98 s = -s;
99 print_indent(s);
102 if (!es) {
103 VG_(printf)("ExecState 0x0\n");
104 return;
107 VG_(printf)("ExecState [Sig %d, collect %s, nonskipped %p]: jmps_passed %d\n",
108 es->sig, es->collect?"yes":"no",
109 es->nonskipped, es->jmps_passed);
113 void CLG_(print_bbcc)(int s, BBCC* bbcc)
115 BB* bb;
117 if (s<0) {
118 s = -s;
119 print_indent(s);
122 if (!bbcc) {
123 VG_(printf)("BBCC 0x0\n");
124 return;
127 bb = bbcc->bb;
128 CLG_ASSERT(bb!=0);
130 VG_(printf)("%s +%#lx=%#lx, ",
131 bb->obj->name + bb->obj->last_slash_pos,
132 (UWord)bb->offset, bb_addr(bb));
133 CLG_(print_cxt)(s+8, bbcc->cxt, bbcc->rec_index);
136 void CLG_(print_eventset)(int s, EventSet* es)
138 int i, j;
139 UInt mask;
140 EventGroup* eg;
142 if (s<0) {
143 s = -s;
144 print_indent(s);
147 if (!es) {
148 VG_(printf)("(EventSet not set)\n");
149 return;
152 VG_(printf)("EventSet %u (%d groups, size %d):",
153 es->mask, es->count, es->size);
155 if (es->count == 0) {
156 VG_(printf)("-\n");
157 return;
160 for(i=0, mask=1; i<MAX_EVENTGROUP_COUNT; i++, mask=mask<<1) {
161 if ((es->mask & mask)==0) continue;
162 eg = CLG_(get_event_group)(i);
163 if (!eg) continue;
164 VG_(printf)(" (%d: %s", i, eg->name[0]);
165 for(j=1; j<eg->size; j++)
166 VG_(printf)(" %s", eg->name[j]);
167 VG_(printf)(")");
169 VG_(printf)("\n");
173 void CLG_(print_cost)(int s, EventSet* es, ULong* c)
175 Int i, j, pos, off;
176 UInt mask;
177 EventGroup* eg;
179 if (s<0) {
180 s = -s;
181 print_indent(s);
184 if (!es) {
185 VG_(printf)("Cost (Nothing, EventSet not set)\n");
186 return;
188 if (!c) {
189 VG_(printf)("Cost (Null, EventSet %u)\n", es->mask);
190 return;
193 if (es->size == 0) {
194 VG_(printf)("Cost (Nothing, EventSet with len 0)\n");
195 return;
198 pos = s;
199 pos += VG_(printf)("Cost [%p]: ", c);
200 off = 0;
201 for(i=0, mask=1; i<MAX_EVENTGROUP_COUNT; i++, mask=mask<<1) {
202 if ((es->mask & mask)==0) continue;
203 eg = CLG_(get_event_group)(i);
204 if (!eg) continue;
205 for(j=0; j<eg->size; j++) {
207 if (off>0) {
208 if (pos > 70) {
209 VG_(printf)(",\n");
210 print_indent(s+5);
211 pos = s+5;
213 else
214 pos += VG_(printf)(", ");
217 pos += VG_(printf)("%s %llu", eg->name[j], c[off++]);
220 VG_(printf)("\n");
224 void CLG_(print_short_jcc)(jCC* jcc)
226 if (jcc)
227 VG_(printf)("%#lx => %#lx [calls %llu/Ir %llu, Dr %llu, Dw %llu]",
228 bb_jmpaddr(jcc->from->bb),
229 bb_addr(jcc->to->bb),
230 jcc->call_counter,
231 jcc->cost ? jcc->cost[fullOffset(EG_IR)]:0,
232 jcc->cost ? jcc->cost[fullOffset(EG_DR)]:0,
233 jcc->cost ? jcc->cost[fullOffset(EG_DW)]:0);
234 else
235 VG_(printf)("[Skipped JCC]");
238 void CLG_(print_jcc)(int s, jCC* jcc)
240 if (s<0) {
241 s = -s;
242 print_indent(s);
245 if (!jcc) {
246 VG_(printf)("JCC to skipped function\n");
247 return;
249 VG_(printf)("JCC %p from ", jcc);
250 CLG_(print_bbcc)(s+9, jcc->from);
251 print_indent(s+4);
252 VG_(printf)("to ");
253 CLG_(print_bbcc)(s+9, jcc->to);
254 print_indent(s+4);
255 VG_(printf)("Calls %llu\n", jcc->call_counter);
256 print_indent(s+4);
257 CLG_(print_cost)(s+9, CLG_(sets).full, jcc->cost);
260 /* dump out the current call stack */
261 void CLG_(print_stackentry)(int s, int sp)
263 call_entry* ce;
265 if (s<0) {
266 s = -s;
267 print_indent(s);
270 ce = CLG_(get_call_entry)(sp);
271 VG_(printf)("[%-2d] SP %#lx, RA %#lx", sp, ce->sp, ce->ret_addr);
272 if (ce->nonskipped)
273 VG_(printf)(" NonSkipped BB %#lx / %s",
274 bb_addr(ce->nonskipped->bb),
275 ce->nonskipped->cxt->fn[0]->name);
276 VG_(printf)("\n");
277 print_indent(s+5);
278 CLG_(print_jcc)(5,ce->jcc);
281 /* debug output */
282 #if 0
283 static void print_call_stack()
285 int c;
287 VG_(printf)("Call Stack:\n");
288 for(c=0;c<CLG_(current_call_stack).sp;c++)
289 CLG_(print_stackentry)(-2, c);
291 #endif
293 void CLG_(print_bbcc_fn)(BBCC* bbcc)
295 obj_node* obj;
297 if (!bbcc) {
298 VG_(printf)("%08x", 0u);
299 return;
302 VG_(printf)("%08lx/%c %u:", bb_addr(bbcc->bb),
303 (bbcc->bb->sect_kind == Vg_SectText) ? 'T' :
304 (bbcc->bb->sect_kind == Vg_SectData) ? 'D' :
305 (bbcc->bb->sect_kind == Vg_SectBSS) ? 'B' :
306 (bbcc->bb->sect_kind == Vg_SectGOT) ? 'G' :
307 (bbcc->bb->sect_kind == Vg_SectPLT) ? 'P' : 'U',
308 bbcc->cxt->base_number+bbcc->rec_index);
309 print_mangled_cxt(bbcc->cxt, bbcc->rec_index);
311 obj = bbcc->cxt->fn[0]->file->obj;
312 if (obj->name[0])
313 VG_(printf)(" %s", obj->name+obj->last_slash_pos);
315 if (VG_(strcmp)(bbcc->cxt->fn[0]->file->name, "???") !=0) {
316 VG_(printf)(" %s", bbcc->cxt->fn[0]->file->name);
317 if ((bbcc->cxt->fn[0] == bbcc->bb->fn) && (bbcc->bb->line>0))
318 VG_(printf)(":%u", bbcc->bb->line);
322 void CLG_(print_bbcc_cost)(int s, BBCC* bbcc)
324 BB* bb;
325 Int i, cjmpNo;
326 ULong ecounter;
328 if (s<0) {
329 s = -s;
330 print_indent(s);
333 if (!bbcc) {
334 VG_(printf)("BBCC 0x0\n");
335 return;
338 bb = bbcc->bb;
339 CLG_ASSERT(bb!=0);
341 CLG_(print_bbcc)(s, bbcc);
343 ecounter = bbcc->ecounter_sum;
345 print_indent(s+2);
346 VG_(printf)("ECounter: sum %llu ", ecounter);
347 for(i=0; i<bb->cjmp_count; i++) {
348 VG_(printf)("[%u]=%llu ",
349 bb->jmp[i].instr, bbcc->jmp[i].ecounter);
351 VG_(printf)("\n");
353 cjmpNo = 0;
354 for(i=0; i<bb->instr_count; i++) {
355 InstrInfo* ii = &(bb->instr[i]);
356 print_indent(s+2);
357 VG_(printf)("[%2d] IOff %2u ecnt %3llu ",
358 i, ii->instr_offset, ecounter);
359 CLG_(print_cost)(s+5, ii->eventset, bbcc->cost + ii->cost_offset);
361 /* update execution counter */
362 if (cjmpNo < bb->cjmp_count)
363 if (bb->jmp[cjmpNo].instr == i) {
364 ecounter -= bbcc->jmp[cjmpNo].ecounter;
365 cjmpNo++;
371 /* dump out an address with source info if available */
372 void CLG_(print_addr)(Addr addr)
374 const HChar *fn_buf, *fl_buf, *dir_buf;
375 const HChar* obj_name;
376 DebugInfo* di;
377 UInt ln, i=0, opos=0;
379 if (addr == 0) {
380 VG_(printf)("%08lx", addr);
381 return;
384 CLG_(get_debug_info)(addr, &dir_buf, &fl_buf, &fn_buf, &ln, &di);
386 if (VG_(strcmp)(fn_buf,"???")==0)
387 VG_(printf)("%#lx", addr);
388 else
389 VG_(printf)("%#lx %s", addr, fn_buf);
391 if (di) {
392 obj_name = VG_(DebugInfo_get_filename)(di);
393 if (obj_name) {
394 while(obj_name[i]) {
395 if (obj_name[i]=='/') opos = i+1;
396 i++;
398 if (obj_name[0])
399 VG_(printf)(" %s", obj_name+opos);
403 if (ln>0) {
404 if (dir_buf[0])
405 VG_(printf)(" (%s/%s:%u)", dir_buf, fl_buf, ln);
406 else
407 VG_(printf)(" (%s:%u)", fl_buf, ln);
411 void CLG_(print_addr_ln)(Addr addr)
413 CLG_(print_addr)(addr);
414 VG_(printf)("\n");
417 static ULong bb_written = 0;
419 void CLG_(print_bbno)(void)
421 if (bb_written != CLG_(stat).bb_executions) {
422 bb_written = CLG_(stat).bb_executions;
423 VG_(printf)("BB# %llu\n",CLG_(stat).bb_executions);
427 void CLG_(print_context)(void)
429 BBCC* bbcc;
431 CLG_DEBUG(0,"In tid %u [%d] ",
432 CLG_(current_tid), CLG_(current_call_stack).sp);
433 bbcc = CLG_(current_state).bbcc;
434 print_mangled_cxt(CLG_(current_state).cxt,
435 bbcc ? bbcc->rec_index : 0);
436 VG_(printf)("\n");
439 void* CLG_(malloc)(const HChar* cc, UWord s, const HChar* f)
441 CLG_DEBUG(3, "Malloc(%lu) in %s.\n", s, f);
442 return VG_(malloc)(cc,s);
445 #else /* CLG_ENABLE_DEBUG */
447 void CLG_(print_bbno)(void) {}
448 void CLG_(print_context)(void) {}
449 void CLG_(print_jcc)(int s, jCC* jcc) {}
450 void CLG_(print_bbcc)(int s, BBCC* bbcc) {}
451 void CLG_(print_bbcc_fn)(BBCC* bbcc) {}
452 void CLG_(print_cost)(int s, EventSet* es, ULong* cost) {}
453 void CLG_(print_bb)(int s, BB* bb) {}
454 void CLG_(print_cxt)(int s, Context* cxt, int rec_index) {}
455 void CLG_(print_short_jcc)(jCC* jcc) {}
456 void CLG_(print_stackentry)(int s, int sp) {}
457 void CLG_(print_addr)(Addr addr) {}
458 void CLG_(print_addr_ln)(Addr addr) {}
460 #endif