2 This file is part of Callgrind, a Valgrind tool for call graph
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.
29 /* If debugging mode of, dummy functions are provided (see below)
33 /*------------------------------------------------------------*/
34 /*--- Debug output helpers ---*/
35 /*------------------------------------------------------------*/
37 static void print_indent(int s
)
39 /* max of 40 spaces */
40 const HChar sp
[] = " ";
42 VG_(printf
)("%s", sp
+40-s
);
45 void CLG_(print_bb
)(int s
, BB
* bb
)
52 VG_(printf
)("BB %#lx (Obj '%s')", bb_addr(bb
), bb
->obj
->name
);
56 void print_mangled_cxt(Context
* cxt
, int rec_index
)
61 VG_(printf
)("(none)");
63 VG_(printf
)("%s", cxt
->fn
[0]->name
);
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
)
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
);
86 VG_(printf
)(" [active=%u]", *pactive
);
88 print_mangled_cxt(cxt
, rec_index
);
92 VG_(printf
)("(no context)\n");
95 void CLG_(print_execstate
)(int s
, exec_state
* es
)
103 VG_(printf
)("ExecState 0x0\n");
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
)
123 VG_(printf
)("BBCC 0x0\n");
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
)
148 VG_(printf
)("(EventSet not set)\n");
152 VG_(printf
)("EventSet %u (%d groups, size %d):",
153 es
->mask
, es
->count
, es
->size
);
155 if (es
->count
== 0) {
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
);
164 VG_(printf
)(" (%d: %s", i
, eg
->name
[0]);
165 for(j
=1; j
<eg
->size
; j
++)
166 VG_(printf
)(" %s", eg
->name
[j
]);
173 void CLG_(print_cost
)(int s
, EventSet
* es
, ULong
* c
)
185 VG_(printf
)("Cost (Nothing, EventSet not set)\n");
189 VG_(printf
)("Cost (Null, EventSet %u)\n", es
->mask
);
194 VG_(printf
)("Cost (Nothing, EventSet with len 0)\n");
199 pos
+= VG_(printf
)("Cost [%p]: ", c
);
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
);
205 for(j
=0; j
<eg
->size
; j
++) {
214 pos
+= VG_(printf
)(", ");
217 pos
+= VG_(printf
)("%s %llu", eg
->name
[j
], c
[off
++]);
224 void CLG_(print_short_jcc
)(jCC
* 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
),
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);
235 VG_(printf
)("[Skipped JCC]");
238 void CLG_(print_jcc
)(int s
, jCC
* jcc
)
246 VG_(printf
)("JCC to skipped function\n");
249 VG_(printf
)("JCC %p from ", jcc
);
250 CLG_(print_bbcc
)(s
+9, jcc
->from
);
253 CLG_(print_bbcc
)(s
+9, jcc
->to
);
255 VG_(printf
)("Calls %llu\n", jcc
->call_counter
);
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
)
270 ce
= CLG_(get_call_entry
)(sp
);
271 VG_(printf
)("[%-2d] SP %#lx, RA %#lx", sp
, ce
->sp
, ce
->ret_addr
);
273 VG_(printf
)(" NonSkipped BB %#lx / %s",
274 bb_addr(ce
->nonskipped
->bb
),
275 ce
->nonskipped
->cxt
->fn
[0]->name
);
278 CLG_(print_jcc
)(5,ce
->jcc
);
283 static void print_call_stack()
287 VG_(printf
)("Call Stack:\n");
288 for(c
=0;c
<CLG_(current_call_stack
).sp
;c
++)
289 CLG_(print_stackentry
)(-2, c
);
293 void CLG_(print_bbcc_fn
)(BBCC
* bbcc
)
298 VG_(printf
)("%08x", 0u);
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
;
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
)
334 VG_(printf
)("BBCC 0x0\n");
341 CLG_(print_bbcc
)(s
, bbcc
);
343 ecounter
= bbcc
->ecounter_sum
;
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
);
354 for(i
=0; i
<bb
->instr_count
; i
++) {
355 InstrInfo
* ii
= &(bb
->instr
[i
]);
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
;
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
;
377 UInt ln
, i
=0, opos
=0;
380 VG_(printf
)("%08lx", addr
);
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
);
389 VG_(printf
)("%#lx %s", addr
, fn_buf
);
392 obj_name
= VG_(DebugInfo_get_filename
)(di
);
395 if (obj_name
[i
]=='/') opos
= i
+1;
399 VG_(printf
)(" %s", obj_name
+opos
);
405 VG_(printf
)(" (%s/%s:%u)", dir_buf
, fl_buf
, ln
);
407 VG_(printf
)(" (%s:%u)", fl_buf
, ln
);
411 void CLG_(print_addr_ln
)(Addr addr
)
413 CLG_(print_addr
)(addr
);
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)
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);
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
) {}