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, 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 */
42 const HChar sp
[] = " ";
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 %u" ,cxt
->base_number
+ rec_index
);
88 VG_(printf
)(" [active=%u]", *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 (UWord
)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
)
150 VG_(printf
)("(EventSet not set)\n");
154 VG_(printf
)("EventSet %u (%d groups, size %d):",
155 es
->mask
, es
->count
, es
->size
);
157 if (es
->count
== 0) {
162 for(i
=0, mask
=1; i
<MAX_EVENTGROUP_COUNT
; i
++, mask
=mask
<<1) {
163 if ((es
->mask
& mask
)==0) continue;
164 eg
= CLG_(get_event_group
)(i
);
166 VG_(printf
)(" (%d: %s", i
, eg
->name
[0]);
167 for(j
=1; j
<eg
->size
; j
++)
168 VG_(printf
)(" %s", eg
->name
[j
]);
175 void CLG_(print_cost
)(int s
, EventSet
* es
, ULong
* c
)
187 VG_(printf
)("Cost (Nothing, EventSet not set)\n");
191 VG_(printf
)("Cost (Null, EventSet %u)\n", es
->mask
);
196 VG_(printf
)("Cost (Nothing, EventSet with len 0)\n");
201 pos
+= VG_(printf
)("Cost [%p]: ", c
);
203 for(i
=0, mask
=1; i
<MAX_EVENTGROUP_COUNT
; i
++, mask
=mask
<<1) {
204 if ((es
->mask
& mask
)==0) continue;
205 eg
= CLG_(get_event_group
)(i
);
207 for(j
=0; j
<eg
->size
; j
++) {
216 pos
+= VG_(printf
)(", ");
219 pos
+= VG_(printf
)("%s %llu", eg
->name
[j
], c
[off
++]);
226 void CLG_(print_short_jcc
)(jCC
* jcc
)
229 VG_(printf
)("%#lx => %#lx [calls %llu/Ir %llu, Dr %llu, Dw %llu]",
230 bb_jmpaddr(jcc
->from
->bb
),
231 bb_addr(jcc
->to
->bb
),
233 jcc
->cost
? jcc
->cost
[fullOffset(EG_IR
)]:0,
234 jcc
->cost
? jcc
->cost
[fullOffset(EG_DR
)]:0,
235 jcc
->cost
? jcc
->cost
[fullOffset(EG_DW
)]:0);
237 VG_(printf
)("[Skipped JCC]");
240 void CLG_(print_jcc
)(int s
, jCC
* jcc
)
248 VG_(printf
)("JCC to skipped function\n");
251 VG_(printf
)("JCC %p from ", jcc
);
252 CLG_(print_bbcc
)(s
+9, jcc
->from
);
255 CLG_(print_bbcc
)(s
+9, jcc
->to
);
257 VG_(printf
)("Calls %llu\n", jcc
->call_counter
);
259 CLG_(print_cost
)(s
+9, CLG_(sets
).full
, jcc
->cost
);
262 /* dump out the current call stack */
263 void CLG_(print_stackentry
)(int s
, int sp
)
272 ce
= CLG_(get_call_entry
)(sp
);
273 VG_(printf
)("[%-2d] SP %#lx, RA %#lx", sp
, ce
->sp
, ce
->ret_addr
);
275 VG_(printf
)(" NonSkipped BB %#lx / %s",
276 bb_addr(ce
->nonskipped
->bb
),
277 ce
->nonskipped
->cxt
->fn
[0]->name
);
280 CLG_(print_jcc
)(5,ce
->jcc
);
285 static void print_call_stack()
289 VG_(printf
)("Call Stack:\n");
290 for(c
=0;c
<CLG_(current_call_stack
).sp
;c
++)
291 CLG_(print_stackentry
)(-2, c
);
295 void CLG_(print_bbcc_fn
)(BBCC
* bbcc
)
300 VG_(printf
)("%08x", 0u);
304 VG_(printf
)("%08lx/%c %u:", bb_addr(bbcc
->bb
),
305 (bbcc
->bb
->sect_kind
== Vg_SectText
) ? 'T' :
306 (bbcc
->bb
->sect_kind
== Vg_SectData
) ? 'D' :
307 (bbcc
->bb
->sect_kind
== Vg_SectBSS
) ? 'B' :
308 (bbcc
->bb
->sect_kind
== Vg_SectGOT
) ? 'G' :
309 (bbcc
->bb
->sect_kind
== Vg_SectPLT
) ? 'P' : 'U',
310 bbcc
->cxt
->base_number
+bbcc
->rec_index
);
311 print_mangled_cxt(bbcc
->cxt
, bbcc
->rec_index
);
313 obj
= bbcc
->cxt
->fn
[0]->file
->obj
;
315 VG_(printf
)(" %s", obj
->name
+obj
->last_slash_pos
);
317 if (VG_(strcmp
)(bbcc
->cxt
->fn
[0]->file
->name
, "???") !=0) {
318 VG_(printf
)(" %s", bbcc
->cxt
->fn
[0]->file
->name
);
319 if ((bbcc
->cxt
->fn
[0] == bbcc
->bb
->fn
) && (bbcc
->bb
->line
>0))
320 VG_(printf
)(":%u", bbcc
->bb
->line
);
324 void CLG_(print_bbcc_cost
)(int s
, BBCC
* bbcc
)
336 VG_(printf
)("BBCC 0x0\n");
343 CLG_(print_bbcc
)(s
, bbcc
);
345 ecounter
= bbcc
->ecounter_sum
;
348 VG_(printf
)("ECounter: sum %llu ", ecounter
);
349 for(i
=0; i
<bb
->cjmp_count
; i
++) {
350 VG_(printf
)("[%u]=%llu ",
351 bb
->jmp
[i
].instr
, bbcc
->jmp
[i
].ecounter
);
356 for(i
=0; i
<bb
->instr_count
; i
++) {
357 InstrInfo
* ii
= &(bb
->instr
[i
]);
359 VG_(printf
)("[%2d] IOff %2u ecnt %3llu ",
360 i
, ii
->instr_offset
, ecounter
);
361 CLG_(print_cost
)(s
+5, ii
->eventset
, bbcc
->cost
+ ii
->cost_offset
);
363 /* update execution counter */
364 if (cjmpNo
< bb
->cjmp_count
)
365 if (bb
->jmp
[cjmpNo
].instr
== i
) {
366 ecounter
-= bbcc
->jmp
[cjmpNo
].ecounter
;
373 /* dump out an address with source info if available */
374 void CLG_(print_addr
)(Addr addr
)
376 const HChar
*fn_buf
, *fl_buf
, *dir_buf
;
377 const HChar
* obj_name
;
379 UInt ln
, i
=0, opos
=0;
382 VG_(printf
)("%08lx", addr
);
386 CLG_(get_debug_info
)(addr
, &dir_buf
, &fl_buf
, &fn_buf
, &ln
, &di
);
388 if (VG_(strcmp
)(fn_buf
,"???")==0)
389 VG_(printf
)("%#lx", addr
);
391 VG_(printf
)("%#lx %s", addr
, fn_buf
);
394 obj_name
= VG_(DebugInfo_get_filename
)(di
);
397 if (obj_name
[i
]=='/') opos
= i
+1;
401 VG_(printf
)(" %s", obj_name
+opos
);
407 VG_(printf
)(" (%s/%s:%u)", dir_buf
, fl_buf
, ln
);
409 VG_(printf
)(" (%s:%u)", fl_buf
, ln
);
413 void CLG_(print_addr_ln
)(Addr addr
)
415 CLG_(print_addr
)(addr
);
419 static ULong bb_written
= 0;
421 void CLG_(print_bbno
)(void)
423 if (bb_written
!= CLG_(stat
).bb_executions
) {
424 bb_written
= CLG_(stat
).bb_executions
;
425 VG_(printf
)("BB# %llu\n",CLG_(stat
).bb_executions
);
429 void CLG_(print_context
)(void)
433 CLG_DEBUG(0,"In tid %u [%d] ",
434 CLG_(current_tid
), CLG_(current_call_stack
).sp
);
435 bbcc
= CLG_(current_state
).bbcc
;
436 print_mangled_cxt(CLG_(current_state
).cxt
,
437 bbcc
? bbcc
->rec_index
: 0);
441 void* CLG_(malloc
)(const HChar
* cc
, UWord s
, const HChar
* f
)
443 CLG_DEBUG(3, "Malloc(%lu) in %s.\n", s
, f
);
444 return VG_(malloc
)(cc
,s
);
447 #else /* CLG_ENABLE_DEBUG */
449 void CLG_(print_bbno
)(void) {}
450 void CLG_(print_context
)(void) {}
451 void CLG_(print_jcc
)(int s
, jCC
* jcc
) {}
452 void CLG_(print_bbcc
)(int s
, BBCC
* bbcc
) {}
453 void CLG_(print_bbcc_fn
)(BBCC
* bbcc
) {}
454 void CLG_(print_cost
)(int s
, EventSet
* es
, ULong
* cost
) {}
455 void CLG_(print_bb
)(int s
, BB
* bb
) {}
456 void CLG_(print_cxt
)(int s
, Context
* cxt
, int rec_index
) {}
457 void CLG_(print_short_jcc
)(jCC
* jcc
) {}
458 void CLG_(print_stackentry
)(int s
, int sp
) {}
459 void CLG_(print_addr
)(Addr addr
) {}
460 void CLG_(print_addr_ln
)(Addr addr
) {}