blob: f9bb820c169afd98a2ba49342ba8d6025f0409df [file] [log] [blame]
weidendoa17f2a32006-03-20 10:27:30 +00001/*
njn9a0cba42007-04-15 22:15:57 +00002 This file is part of Callgrind, a Valgrind tool for call graph
weidendoa17f2a32006-03-20 10:27:30 +00003 profiling programs.
4
sewardj4d474d02008-02-11 11:34:59 +00005 Copyright (C) 2002-2008, Josef Weidendorfer (Josef.Weidendorfer@gmx.de)
weidendoa17f2a32006-03-20 10:27:30 +00006
njn9a0cba42007-04-15 22:15:57 +00007 This tool is derived from and contains lot of code from Cachegrind
8 Copyright (C) 2002 Nicholas Nethercote (njn@valgrind.org)
weidendoa17f2a32006-03-20 10:27:30 +00009
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.
14
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.
19
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
23 02111-1307, USA.
24
25 The GNU General Public License is contained in the file COPYING.
26*/
27
28#include "global.h"
29#include "events.h"
30
31/* If debugging mode of, dummy functions are provided (see below)
32 */
33#if CLG_ENABLE_DEBUG
34
35/*------------------------------------------------------------*/
36/*--- Debug output helpers ---*/
37/*------------------------------------------------------------*/
38
39static void print_indent(int s)
40{
41 /* max of 40 spaces */
42 char sp[] = " ";
43 if (s>40) s=40;
44 VG_(printf)(sp+40-s);
45}
46
47void CLG_(print_bb)(int s, BB* bb)
48{
49 if (s<0) {
50 s = -s;
51 print_indent(s);
52 }
53
barta0b6b2c2008-07-07 06:49:24 +000054 VG_(printf)("BB %#lx (Obj '%s')", bb_addr(bb), bb->obj->name);
weidendoa17f2a32006-03-20 10:27:30 +000055}
56
57static
58void print_mangled_cxt(Context* cxt, int rec_index)
59{
60 int i;
61
62 if (!cxt)
63 VG_(printf)("(none)");
64 else {
65 VG_(printf)("%s", cxt->fn[0]->name);
66 if (rec_index >0)
67 VG_(printf)("'%d", rec_index +1);
68 for(i=1;i<cxt->size;i++)
69 VG_(printf)("'%s", cxt->fn[i]->name);
70 }
71}
72
73
74
75void CLG_(print_cxt)(int s, Context* cxt, int rec_index)
76{
77 if (s<0) {
78 s = -s;
79 print_indent(s);
80 }
81
82 if (cxt) {
83 UInt *pactive = CLG_(get_fn_entry)(cxt->fn[0]->number);
84 CLG_ASSERT(rec_index < cxt->fn[0]->separate_recursions);
85
86 VG_(printf)("Cxt %d" ,cxt->base_number + rec_index);
87 if (*pactive>0)
88 VG_(printf)(" [active=%d]", *pactive);
89 VG_(printf)(": ");
90 print_mangled_cxt(cxt, rec_index);
91 VG_(printf)("\n");
92 }
93 else
94 VG_(printf)("(no context)\n");
95}
96
97void CLG_(print_execstate)(int s, exec_state* es)
98{
99 if (s<0) {
100 s = -s;
101 print_indent(s);
102 }
103
104 if (!es) {
105 VG_(printf)("ExecState 0x0\n");
106 return;
107 }
108
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);
112}
113
114
115void CLG_(print_bbcc)(int s, BBCC* bbcc, Bool jumpaddr)
116{
117 BB* bb;
118
119 if (s<0) {
120 s = -s;
121 print_indent(s);
122 }
123
124 if (!bbcc) {
125 VG_(printf)("BBCC 0x0\n");
126 return;
127 }
128
129 bb = bbcc->bb;
130 CLG_ASSERT(bb!=0);
131
132#if 0
133 if (jumpaddr)
134 VG_(printf)("%s +%p=%p, ",
135 bb->obj->name + bb->obj->last_slash_pos,
136 bb->jmp_offset, bb_jmpaddr(bb));
137 else
138#endif
barta0b6b2c2008-07-07 06:49:24 +0000139 VG_(printf)("%s +%#lx=%#lx, ",
weidendoa17f2a32006-03-20 10:27:30 +0000140 bb->obj->name + bb->obj->last_slash_pos,
141 bb->offset, bb_addr(bb));
142 CLG_(print_cxt)(s+8, bbcc->cxt, bbcc->rec_index);
143}
144
145void CLG_(print_eventset)(int s, EventSet* es)
146{
147 int i;
148
149 if (s<0) {
150 s = -s;
151 print_indent(s);
152 }
153
154 if (!es) {
155 VG_(printf)("(EventSet not set)\n");
156 return;
157 }
158
159 VG_(printf)("%5s (Size/Cap %d/%d): ",
160 es->name, es->size, es->capacity);
161
162 if (es->size == 0)
163 VG_(printf)("-");
164 else {
165 for(i=0; i< es->size; i++) {
166 if (i>0) {
167 VG_(printf)(" ");
168 if (es->e[i-1].nextTop == i)
169 VG_(printf)("| ");
170 }
171 VG_(printf)(es->e[i].type->name);
172 }
173 }
174 VG_(printf)("\n");
175}
176
177
178void CLG_(print_cost)(int s, EventSet* es, ULong* c)
179{
180 Int i, pos;
181
182 if (s<0) {
183 s = -s;
184 print_indent(s);
185 }
186
187 if (!es) {
188 VG_(printf)("Cost (Nothing, EventSet not set)\n");
189 return;
190 }
191 if (!c) {
192 VG_(printf)("Cost (Null, EventSet %s)\n", es->name);
193 return;
194 }
195
196 if (es->size == 0) {
197 VG_(printf)("Cost (Nothing, EventSet %s with len 0)\n", es->name);
198 return;
199 }
200
201 pos = s;
202 pos += VG_(printf)("Cost %s [%p]: %s %llu", es->name, c, es->e[0].type->name, c[0]);
203
204 i = 1;
205 while(i<es->size) {
206 if (pos > 70) {
207 VG_(printf)(",\n");
208 print_indent(s+5);
209 pos = s+5;
210 }
211 else
212 pos += VG_(printf)(", ");
213 pos += VG_(printf)("%s %llu", es->e[i].type->name, c[i]);
214 i++;
215 }
216 VG_(printf)("\n");
217}
218
219
220void CLG_(print_short_jcc)(jCC* jcc)
221{
222 if (jcc)
barta0b6b2c2008-07-07 06:49:24 +0000223 VG_(printf)("%#lx => %#lx [%llu/%llu,%llu,%llu]",
weidendoa17f2a32006-03-20 10:27:30 +0000224 bb_jmpaddr(jcc->from->bb),
225 bb_addr(jcc->to->bb),
226 jcc->call_counter,
227 jcc->cost ? jcc->cost[CLG_(sets).off_sim_Ir]:0,
228 jcc->cost ? jcc->cost[CLG_(sets).off_sim_Dr]:0,
229 jcc->cost ? jcc->cost[CLG_(sets).off_sim_Dw]:0);
230 else
231 VG_(printf)("[Skipped JCC]");
232}
233
234void CLG_(print_jcc)(int s, jCC* jcc)
235{
236 if (s<0) {
237 s = -s;
238 print_indent(s);
239 }
240
241 if (!jcc) {
242 VG_(printf)("JCC to skipped function\n");
243 return;
244 }
245 VG_(printf)("JCC %p from ", jcc);
246 CLG_(print_bbcc)(s+9, jcc->from, True);
247 print_indent(s+4);
248 VG_(printf)("to ");
249 CLG_(print_bbcc)(s+9, jcc->to, False);
250 print_indent(s+4);
251 VG_(printf)("Calls %llu\n", jcc->call_counter);
252 print_indent(s+4);
253 CLG_(print_cost)(s+9, CLG_(sets).full, jcc->cost);
254}
255
256/* dump out the current call stack */
257void CLG_(print_stackentry)(int s, int sp)
258{
259 call_entry* ce;
260
261 if (s<0) {
262 s = -s;
263 print_indent(s);
264 }
265
266 ce = CLG_(get_call_entry)(sp);
barta0b6b2c2008-07-07 06:49:24 +0000267 VG_(printf)("[%-2d] SP %#lx, RA %#lx", sp, ce->sp, ce->ret_addr);
weidendoa17f2a32006-03-20 10:27:30 +0000268 if (ce->nonskipped)
barta0b6b2c2008-07-07 06:49:24 +0000269 VG_(printf)(" NonSkipped BB %#lx / %s",
weidendoa17f2a32006-03-20 10:27:30 +0000270 bb_addr(ce->nonskipped->bb),
271 ce->nonskipped->cxt->fn[0]->name);
272 VG_(printf)("\n");
273 print_indent(s+5);
274 CLG_(print_jcc)(5,ce->jcc);
275}
276
277/* debug output */
278#if 0
279static void print_call_stack()
280{
281 int c;
282
283 VG_(printf)("Call Stack:\n");
284 for(c=0;c<CLG_(current_call_stack).sp;c++)
285 CLG_(print_stackentry)(-2, c);
286}
287#endif
288
289void CLG_(print_bbcc_fn)(BBCC* bbcc)
290{
291 obj_node* obj;
292
293 if (!bbcc) {
294 VG_(printf)("%08x", 0);
295 return;
296 }
297
njn8a7b41b2007-09-23 00:51:24 +0000298 VG_(printf)("%08lx/%c %d:", bb_addr(bbcc->bb),
weidendoa17f2a32006-03-20 10:27:30 +0000299 (bbcc->bb->sect_kind == Vg_SectText) ? 'T' :
300 (bbcc->bb->sect_kind == Vg_SectData) ? 'D' :
301 (bbcc->bb->sect_kind == Vg_SectBSS) ? 'B' :
302 (bbcc->bb->sect_kind == Vg_SectGOT) ? 'G' :
303 (bbcc->bb->sect_kind == Vg_SectPLT) ? 'P' : 'U',
304 bbcc->cxt->base_number+bbcc->rec_index);
305 print_mangled_cxt(bbcc->cxt, bbcc->rec_index);
306
307 obj = bbcc->cxt->fn[0]->file->obj;
308 if (obj->name[0])
309 VG_(printf)(" %s", obj->name+obj->last_slash_pos);
310
311 if (VG_(strcmp)(bbcc->cxt->fn[0]->file->name, "???") !=0) {
312 VG_(printf)(" %s", bbcc->cxt->fn[0]->file->name);
313 if ((bbcc->cxt->fn[0] == bbcc->bb->fn) && (bbcc->bb->line>0))
314 VG_(printf)(":%d", bbcc->bb->line);
315 }
316}
317
318void CLG_(print_bbcc_cost)(int s, BBCC* bbcc)
319{
320 BB* bb;
321 Int i, cjmpNo;
322 ULong ecounter;
323
324 if (s<0) {
325 s = -s;
326 print_indent(s);
327 }
328
329 if (!bbcc) {
330 VG_(printf)("BBCC 0x0\n");
331 return;
332 }
333
334 bb = bbcc->bb;
335 CLG_ASSERT(bb!=0);
336
337 CLG_(print_bbcc)(s, bbcc, False);
338
339 ecounter = bbcc->ecounter_sum;
340
341 print_indent(s+2);
njn8a7b41b2007-09-23 00:51:24 +0000342 VG_(printf)("ECounter: sum %llu ", ecounter);
weidendoa17f2a32006-03-20 10:27:30 +0000343 for(i=0; i<bb->cjmp_count; i++) {
njn8a7b41b2007-09-23 00:51:24 +0000344 VG_(printf)("[%d]=%llu ",
weidendoa17f2a32006-03-20 10:27:30 +0000345 bb->jmp[i].instr, bbcc->jmp[i].ecounter);
346 }
347 VG_(printf)("\n");
348
349 cjmpNo = 0;
350 for(i=0; i<bb->instr_count; i++) {
351 InstrInfo* ii = &(bb->instr[i]);
352 print_indent(s+2);
njn8a7b41b2007-09-23 00:51:24 +0000353 VG_(printf)("[%2d] IOff %2d ecnt %3llu ",
weidendoa17f2a32006-03-20 10:27:30 +0000354 i, ii->instr_offset, ecounter);
355 CLG_(print_cost)(s+5, ii->eventset, bbcc->cost + ii->cost_offset);
356
357 /* update execution counter */
358 if (cjmpNo < bb->cjmp_count)
359 if (bb->jmp[cjmpNo].instr == i) {
360 ecounter -= bbcc->jmp[cjmpNo].ecounter;
361 cjmpNo++;
362 }
363 }
364}
365
366
367/* dump out an address with source info if available */
368void CLG_(print_addr)(Addr addr)
369{
370 Char fl_buf[FILENAME_LEN];
371 Char fn_buf[FN_NAME_LEN];
372 const UChar* obj_name;
sewardjb8b79ad2008-03-03 01:35:41 +0000373 DebugInfo* di;
weidendoa17f2a32006-03-20 10:27:30 +0000374 int ln, i=0, opos=0;
375
376 if (addr == 0) {
njn8a7b41b2007-09-23 00:51:24 +0000377 VG_(printf)("%08lx", addr);
weidendoa17f2a32006-03-20 10:27:30 +0000378 return;
379 }
380
sewardjb8b79ad2008-03-03 01:35:41 +0000381 CLG_(get_debug_info)(addr, fl_buf, fn_buf, &ln, &di);
weidendoa17f2a32006-03-20 10:27:30 +0000382
383 if (VG_(strcmp)(fn_buf,"???")==0)
barta0b6b2c2008-07-07 06:49:24 +0000384 VG_(printf)("%#lx", addr);
weidendoa17f2a32006-03-20 10:27:30 +0000385 else
barta0b6b2c2008-07-07 06:49:24 +0000386 VG_(printf)("%#lx %s", addr, fn_buf);
weidendoa17f2a32006-03-20 10:27:30 +0000387
sewardjb8b79ad2008-03-03 01:35:41 +0000388 if (di) {
389 obj_name = VG_(seginfo_filename)(di);
weidendoa17f2a32006-03-20 10:27:30 +0000390 if (obj_name) {
391 while(obj_name[i]) {
392 if (obj_name[i]=='/') opos = i+1;
393 i++;
394 }
395 if (obj_name[0])
396 VG_(printf)(" %s", obj_name+opos);
397 }
398 }
399
400 if (ln>0)
401 VG_(printf)(" (%s:%u)", fl_buf,ln);
402}
403
404void CLG_(print_addr_ln)(Addr addr)
405{
406 CLG_(print_addr)(addr);
407 VG_(printf)("\n");
408}
409
410static ULong bb_written = 0;
411
412void CLG_(print_bbno)(void)
413{
414 if (bb_written != CLG_(stat).bb_executions) {
415 bb_written = CLG_(stat).bb_executions;
416 VG_(printf)("BB# %llu\n",CLG_(stat).bb_executions);
417 }
418}
419
420void CLG_(print_context)(void)
421{
422 BBCC* bbcc;
423
424 CLG_DEBUG(0,"In tid %d [%d] ",
425 CLG_(current_tid), CLG_(current_call_stack).sp);
426 bbcc = CLG_(current_state).bbcc;
427 print_mangled_cxt(CLG_(current_state).cxt,
428 bbcc ? bbcc->rec_index : 0);
429 VG_(printf)("\n");
430}
431
sewardj9c606bd2008-09-18 18:12:50 +0000432void* CLG_(malloc)(HChar* cc, UWord s, char* f)
weidendoa17f2a32006-03-20 10:27:30 +0000433{
njn8a7b41b2007-09-23 00:51:24 +0000434 CLG_DEBUG(3, "Malloc(%lu) in %s.\n", s, f);
sewardj9c606bd2008-09-18 18:12:50 +0000435 return VG_(malloc)(cc,s);
weidendoa17f2a32006-03-20 10:27:30 +0000436}
437
438#else /* CLG_ENABLE_DEBUG */
439
440void CLG_(print_bbno)(void) {}
441void CLG_(print_context)(void) {}
442void CLG_(print_jcc)(int s, jCC* jcc) {}
443void CLG_(print_bbcc)(int s, BBCC* bbcc, Bool b) {}
444void CLG_(print_bbcc_fn)(BBCC* bbcc) {}
445void CLG_(print_cost)(int s, EventSet* es, ULong* cost) {}
446void CLG_(print_bb)(int s, BB* bb) {}
447void CLG_(print_cxt)(int s, Context* cxt, int rec_index) {}
448void CLG_(print_short_jcc)(jCC* jcc) {}
449void CLG_(print_stackentry)(int s, int sp) {}
450void CLG_(print_addr)(Addr addr) {}
451void CLG_(print_addr_ln)(Addr addr) {}
452
453#endif