blob: 8907995e5529362f854efef0d1d3db0454168a4c [file] [log] [blame]
weidendoa17f2a32006-03-20 10:27:30 +00001/*--------------------------------------------------------------------*/
2/*--- Callgrind ---*/
3/*--- dump.c ---*/
4/*--------------------------------------------------------------------*/
5
6/*
7 This file is part of Callgrind, a Valgrind tool for call tracing.
8
sewardjb3a1e4b2015-08-21 11:32:26 +00009 Copyright (C) 2002-2015, Josef Weidendorfer (Josef.Weidendorfer@gmx.de)
weidendoa17f2a32006-03-20 10:27:30 +000010
11 This program is free software; you can redistribute it and/or
12 modify it under the terms of the GNU General Public License as
13 published by the Free Software Foundation; either version 2 of the
14 License, or (at your option) any later version.
15
16 This program is distributed in the hope that it will be useful, but
17 WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 General Public License for more details.
20
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
24 02111-1307, USA.
25
26 The GNU General Public License is contained in the file COPYING.
27*/
28
29#include "config.h"
30#include "global.h"
31
sewardje7a50822011-04-20 11:54:32 +000032#include "pub_tool_threadstate.h"
33#include "pub_tool_libcfile.h"
weidendoa17f2a32006-03-20 10:27:30 +000034
weidendoa17f2a32006-03-20 10:27:30 +000035
36/* Dump Part Counter */
37static Int out_counter = 0;
38
florian19f91bb2012-11-10 22:29:54 +000039static HChar* out_file = 0;
weidendo4ce5e792006-09-20 21:29:39 +000040static Bool dumps_initialized = False;
weidendoa17f2a32006-03-20 10:27:30 +000041
42/* Command */
florian2f088e72014-10-01 14:16:05 +000043static HChar *cmdbuf;
weidendoa17f2a32006-03-20 10:27:30 +000044
45/* Total reads/writes/misses sum over all dumps and threads.
46 * Updated during CC traversal at dump time.
47 */
48FullCost CLG_(total_cost) = 0;
49static FullCost dump_total_cost = 0;
50
51EventMapping* CLG_(dumpmap) = 0;
52
weidendoa17f2a32006-03-20 10:27:30 +000053Int CLG_(get_dump_counter)(void)
54{
55 return out_counter;
56}
57
weidendoa17f2a32006-03-20 10:27:30 +000058/*------------------------------------------------------------*/
59/*--- Output file related stuff ---*/
60/*------------------------------------------------------------*/
61
62/* Boolean dumping array */
63static Bool* dump_array = 0;
64static Int dump_array_size = 0;
65static Bool* obj_dumped = 0;
66static Bool* file_dumped = 0;
67static Bool* fn_dumped = 0;
68static Bool* cxt_dumped = 0;
69
70static
71void reset_dump_array(void)
72{
73 int i;
74
75 CLG_ASSERT(dump_array != 0);
76
77 for(i=0;i<dump_array_size;i++)
78 dump_array[i] = False;
79}
80
81static
82void init_dump_array(void)
83{
84 dump_array_size = CLG_(stat).distinct_objs +
85 CLG_(stat).distinct_files +
86 CLG_(stat).distinct_fns +
87 CLG_(stat).context_counter;
88 CLG_ASSERT(dump_array == 0);
sewardj9c606bd2008-09-18 18:12:50 +000089 dump_array = (Bool*) CLG_MALLOC("cl.dump.ida.1",
90 dump_array_size * sizeof(Bool));
weidendoa17f2a32006-03-20 10:27:30 +000091 obj_dumped = dump_array;
92 file_dumped = obj_dumped + CLG_(stat).distinct_objs;
93 fn_dumped = file_dumped + CLG_(stat).distinct_files;
94 cxt_dumped = fn_dumped + CLG_(stat).distinct_fns;
95
96 reset_dump_array();
97
98 CLG_DEBUG(1, " init_dump_array: size %d\n", dump_array_size);
99}
100
101static __inline__
102void free_dump_array(void)
103{
104 CLG_ASSERT(dump_array != 0);
105 VG_(free)(dump_array);
106
107 dump_array = 0;
108 obj_dumped = 0;
109 file_dumped = 0;
110 fn_dumped = 0;
111 cxt_dumped = 0;
112}
113
114
115/* Initialize to an invalid position */
116static __inline__
117void init_fpos(FnPos* p)
118 {
119 p->file = 0;
120 p->fn = 0;
121 p->obj = 0;
122 p->cxt = 0;
123 p->rec_index = 0;
124}
125
126
floriancc9480f2014-11-11 20:46:34 +0000127static void print_obj(VgFile *fp, const HChar* prefix, obj_node* obj)
weidendoa17f2a32006-03-20 10:27:30 +0000128{
weidendoa17f2a32006-03-20 10:27:30 +0000129 if (CLG_(clo).compress_strings) {
130 CLG_ASSERT(obj_dumped != 0);
131 if (obj_dumped[obj->number])
florianb7876db2015-08-05 19:04:51 +0000132 VG_(fprintf)(fp, "%s(%u)\n", prefix, obj->number);
weidendoa17f2a32006-03-20 10:27:30 +0000133 else {
florianb7876db2015-08-05 19:04:51 +0000134 VG_(fprintf)(fp, "%s(%u) %s\n", prefix, obj->number, obj->name);
weidendoa17f2a32006-03-20 10:27:30 +0000135 }
136 }
137 else
floriancc9480f2014-11-11 20:46:34 +0000138 VG_(fprintf)(fp, "%s%s\n", prefix, obj->name);
weidendoa17f2a32006-03-20 10:27:30 +0000139
140#if 0
141 /* add mapping parameters the first time a object is dumped
142 * format: mp=0xSTART SIZE 0xOFFSET */
143 if (!obj_dumped[obj->number]) {
144 obj_dumped[obj->number];
floriancc9480f2014-11-11 20:46:34 +0000145 VG_(fprintf)(fp, "mp=%p %p %p\n",
weidendoa17f2a32006-03-20 10:27:30 +0000146 pos->obj->start, pos->obj->size, pos->obj->offset);
147 }
148#else
149 obj_dumped[obj->number] = True;
150#endif
151}
152
floriancc9480f2014-11-11 20:46:34 +0000153static void print_file(VgFile *fp, const char *prefix, const file_node* file)
weidendoa17f2a32006-03-20 10:27:30 +0000154{
155 if (CLG_(clo).compress_strings) {
156 CLG_ASSERT(file_dumped != 0);
157 if (file_dumped[file->number])
florianb7876db2015-08-05 19:04:51 +0000158 VG_(fprintf)(fp, "%s(%u)\n", prefix, file->number);
weidendoa17f2a32006-03-20 10:27:30 +0000159 else {
florianb7876db2015-08-05 19:04:51 +0000160 VG_(fprintf)(fp, "%s(%u) %s\n", prefix, file->number, file->name);
weidendoa17f2a32006-03-20 10:27:30 +0000161 file_dumped[file->number] = True;
162 }
163 }
164 else
floriancc9480f2014-11-11 20:46:34 +0000165 VG_(fprintf)(fp, "%s%s\n", prefix, file->name);
weidendoa17f2a32006-03-20 10:27:30 +0000166}
167
168/*
169 * tag can be "fn", "cfn", "jfn"
170 */
floriancc9480f2014-11-11 20:46:34 +0000171static void print_fn(VgFile *fp, const HChar* tag, const fn_node* fn)
weidendoa17f2a32006-03-20 10:27:30 +0000172{
floriancc9480f2014-11-11 20:46:34 +0000173 VG_(fprintf)(fp, "%s=",tag);
weidendoa17f2a32006-03-20 10:27:30 +0000174 if (CLG_(clo).compress_strings) {
175 CLG_ASSERT(fn_dumped != 0);
176 if (fn_dumped[fn->number])
florianb7876db2015-08-05 19:04:51 +0000177 VG_(fprintf)(fp, "(%u)\n", fn->number);
weidendoa17f2a32006-03-20 10:27:30 +0000178 else {
florianb7876db2015-08-05 19:04:51 +0000179 VG_(fprintf)(fp, "(%u) %s\n", fn->number, fn->name);
weidendoa17f2a32006-03-20 10:27:30 +0000180 fn_dumped[fn->number] = True;
181 }
182 }
183 else
floriancc9480f2014-11-11 20:46:34 +0000184 VG_(fprintf)(fp, "%s\n", fn->name);
weidendoa17f2a32006-03-20 10:27:30 +0000185}
186
floriancc9480f2014-11-11 20:46:34 +0000187static void print_mangled_fn(VgFile *fp, const HChar* tag,
weidendoa17f2a32006-03-20 10:27:30 +0000188 Context* cxt, int rec_index)
189{
floriancc9480f2014-11-11 20:46:34 +0000190 int i;
weidendoa17f2a32006-03-20 10:27:30 +0000191
192 if (CLG_(clo).compress_strings && CLG_(clo).compress_mangled) {
193
194 int n;
195 Context* last;
196
197 CLG_ASSERT(cxt_dumped != 0);
198 if (cxt_dumped[cxt->base_number+rec_index]) {
florianb7876db2015-08-05 19:04:51 +0000199 VG_(fprintf)(fp, "%s=(%u)\n",
weidendoa17f2a32006-03-20 10:27:30 +0000200 tag, cxt->base_number + rec_index);
weidendoa17f2a32006-03-20 10:27:30 +0000201 return;
202 }
203
204 last = 0;
205 /* make sure that for all context parts compressed data is written */
206 for(i=cxt->size;i>0;i--) {
207 CLG_ASSERT(cxt->fn[i-1]->pure_cxt != 0);
208 n = cxt->fn[i-1]->pure_cxt->base_number;
209 if (cxt_dumped[n]) continue;
floriancc9480f2014-11-11 20:46:34 +0000210 VG_(fprintf)(fp, "%s=(%d) %s\n",
weidendoa17f2a32006-03-20 10:27:30 +0000211 tag, n, cxt->fn[i-1]->name);
weidendoa17f2a32006-03-20 10:27:30 +0000212
213 cxt_dumped[n] = True;
214 last = cxt->fn[i-1]->pure_cxt;
215 }
216 /* If the last context was the context to print, we are finished */
217 if ((last == cxt) && (rec_index == 0)) return;
218
florianb7876db2015-08-05 19:04:51 +0000219 VG_(fprintf)(fp, "%s=(%u) (%u)", tag,
weidendoa17f2a32006-03-20 10:27:30 +0000220 cxt->base_number + rec_index,
221 cxt->fn[0]->pure_cxt->base_number);
222 if (rec_index >0)
floriancc9480f2014-11-11 20:46:34 +0000223 VG_(fprintf)(fp, "'%d", rec_index +1);
weidendoa17f2a32006-03-20 10:27:30 +0000224 for(i=1;i<cxt->size;i++)
florianb7876db2015-08-05 19:04:51 +0000225 VG_(fprintf)(fp, "'(%u)",
weidendoa17f2a32006-03-20 10:27:30 +0000226 cxt->fn[i]->pure_cxt->base_number);
floriancc9480f2014-11-11 20:46:34 +0000227 VG_(fprintf)(fp, "\n");
weidendoa17f2a32006-03-20 10:27:30 +0000228
229 cxt_dumped[cxt->base_number+rec_index] = True;
230 return;
231 }
232
233
floriancc9480f2014-11-11 20:46:34 +0000234 VG_(fprintf)(fp, "%s=", tag);
weidendoa17f2a32006-03-20 10:27:30 +0000235 if (CLG_(clo).compress_strings) {
236 CLG_ASSERT(cxt_dumped != 0);
237 if (cxt_dumped[cxt->base_number+rec_index]) {
florianb7876db2015-08-05 19:04:51 +0000238 VG_(fprintf)(fp, "(%u)\n", cxt->base_number + rec_index);
weidendoa17f2a32006-03-20 10:27:30 +0000239 return;
240 }
241 else {
florianb7876db2015-08-05 19:04:51 +0000242 VG_(fprintf)(fp, "(%u) ", cxt->base_number + rec_index);
weidendoa17f2a32006-03-20 10:27:30 +0000243 cxt_dumped[cxt->base_number+rec_index] = True;
244 }
245 }
246
floriancc9480f2014-11-11 20:46:34 +0000247 VG_(fprintf)(fp, "%s", cxt->fn[0]->name);
weidendoa17f2a32006-03-20 10:27:30 +0000248 if (rec_index >0)
floriancc9480f2014-11-11 20:46:34 +0000249 VG_(fprintf)(fp, "'%d", rec_index +1);
weidendoa17f2a32006-03-20 10:27:30 +0000250 for(i=1;i<cxt->size;i++)
floriancc9480f2014-11-11 20:46:34 +0000251 VG_(fprintf)(fp, "'%s", cxt->fn[i]->name);
weidendoa17f2a32006-03-20 10:27:30 +0000252
floriancc9480f2014-11-11 20:46:34 +0000253 VG_(fprintf)(fp, "\n");
weidendoa17f2a32006-03-20 10:27:30 +0000254}
255
256
257
258/**
259 * Print function position of the BBCC, but only print info differing to
260 * the <last> position, update <last>
261 * Return True if something changes.
262 */
floriancc9480f2014-11-11 20:46:34 +0000263static Bool print_fn_pos(VgFile *fp, FnPos* last, BBCC* bbcc)
weidendoa17f2a32006-03-20 10:27:30 +0000264{
265 Bool res = False;
266
weidendo061f0792011-05-11 12:28:01 +0000267 CLG_ASSERT(bbcc && bbcc->cxt);
268
weidendoa17f2a32006-03-20 10:27:30 +0000269 CLG_DEBUGIF(3) {
270 CLG_DEBUG(2, "+ print_fn_pos: ");
271 CLG_(print_cxt)(16, bbcc->cxt, bbcc->rec_index);
272 }
273
274 if (!CLG_(clo).mangle_names) {
275 if (last->rec_index != bbcc->rec_index) {
florianb7876db2015-08-05 19:04:51 +0000276 VG_(fprintf)(fp, "rec=%u\n\n", bbcc->rec_index);
weidendoa17f2a32006-03-20 10:27:30 +0000277 last->rec_index = bbcc->rec_index;
278 last->cxt = 0; /* reprint context */
279 res = True;
280 }
281
282 if (last->cxt != bbcc->cxt) {
weidendo061f0792011-05-11 12:28:01 +0000283 fn_node* last_from = (last->cxt && last->cxt->size >1) ?
weidendoa17f2a32006-03-20 10:27:30 +0000284 last->cxt->fn[1] : 0;
weidendo061f0792011-05-11 12:28:01 +0000285 fn_node* curr_from = (bbcc->cxt->size >1) ?
weidendoa17f2a32006-03-20 10:27:30 +0000286 bbcc->cxt->fn[1] : 0;
287 if (curr_from == 0) {
288 if (last_from != 0) {
289 /* switch back to no context */
floriancc9480f2014-11-11 20:46:34 +0000290 VG_(fprintf)(fp, "frfn=(spontaneous)\n");
weidendoa17f2a32006-03-20 10:27:30 +0000291 res = True;
292 }
293 }
294 else if (last_from != curr_from) {
floriancc9480f2014-11-11 20:46:34 +0000295 print_fn(fp, "frfn", curr_from);
weidendoa17f2a32006-03-20 10:27:30 +0000296 res = True;
297 }
298 last->cxt = bbcc->cxt;
299 }
300 }
301
302 if (last->obj != bbcc->cxt->fn[0]->file->obj) {
floriancc9480f2014-11-11 20:46:34 +0000303 print_obj(fp, "ob=", bbcc->cxt->fn[0]->file->obj);
weidendoa17f2a32006-03-20 10:27:30 +0000304 last->obj = bbcc->cxt->fn[0]->file->obj;
305 res = True;
306 }
307
308 if (last->file != bbcc->cxt->fn[0]->file) {
floriancc9480f2014-11-11 20:46:34 +0000309 print_file(fp, "fl=", bbcc->cxt->fn[0]->file);
weidendoa17f2a32006-03-20 10:27:30 +0000310 last->file = bbcc->cxt->fn[0]->file;
311 res = True;
312 }
313
314 if (!CLG_(clo).mangle_names) {
315 if (last->fn != bbcc->cxt->fn[0]) {
floriancc9480f2014-11-11 20:46:34 +0000316 print_fn(fp, "fn", bbcc->cxt->fn[0]);
weidendoa17f2a32006-03-20 10:27:30 +0000317 last->fn = bbcc->cxt->fn[0];
318 res = True;
319 }
320 }
321 else {
322 /* Print mangled name if context or rec_index changes */
323 if ((last->rec_index != bbcc->rec_index) ||
324 (last->cxt != bbcc->cxt)) {
325
floriancc9480f2014-11-11 20:46:34 +0000326 print_mangled_fn(fp, "fn", bbcc->cxt, bbcc->rec_index);
weidendoa17f2a32006-03-20 10:27:30 +0000327 last->fn = bbcc->cxt->fn[0];
328 last->rec_index = bbcc->rec_index;
329 res = True;
330 }
331 }
332
333 last->cxt = bbcc->cxt;
334
335 CLG_DEBUG(2, "- print_fn_pos: %s\n", res ? "changed" : "");
336
337 return res;
338}
339
340/* the debug lookup cache is useful if BBCC for same BB are
341 * dumped directly in a row. This is a direct mapped cache.
342 */
343#define DEBUG_CACHE_SIZE 1777
344
345static Addr debug_cache_addr[DEBUG_CACHE_SIZE];
346static file_node* debug_cache_file[DEBUG_CACHE_SIZE];
347static int debug_cache_line[DEBUG_CACHE_SIZE];
348static Bool debug_cache_info[DEBUG_CACHE_SIZE];
349
350static __inline__
351void init_debug_cache(void)
352{
353 int i;
354 for(i=0;i<DEBUG_CACHE_SIZE;i++) {
355 debug_cache_addr[i] = 0;
356 debug_cache_file[i] = 0;
357 debug_cache_line[i] = 0;
358 debug_cache_info[i] = 0;
359 }
360}
361
sewardj8cd42de2007-11-16 12:31:27 +0000362static /* __inline__ */
weidendoa17f2a32006-03-20 10:27:30 +0000363Bool get_debug_pos(BBCC* bbcc, Addr addr, AddrPos* p)
364{
florian10ef7252014-10-27 12:06:35 +0000365 const HChar *file, *dir;
florianf4384f42014-12-16 20:55:58 +0000366 Bool found_file_line;
weidendoa17f2a32006-03-20 10:27:30 +0000367
368 int cachepos = addr % DEBUG_CACHE_SIZE;
369
370 if (debug_cache_addr[cachepos] == addr) {
371 p->line = debug_cache_line[cachepos];
372 p->file = debug_cache_file[cachepos];
weidendo3db43222007-09-17 12:52:10 +0000373 found_file_line = debug_cache_info[cachepos];
weidendoa17f2a32006-03-20 10:27:30 +0000374 }
375 else {
weidendo3db43222007-09-17 12:52:10 +0000376 found_file_line = VG_(get_filename_linenum)(addr,
florian10ef7252014-10-27 12:06:35 +0000377 &file,
378 &dir,
weidendo3db43222007-09-17 12:52:10 +0000379 &(p->line));
380 if (!found_file_line) {
florian10ef7252014-10-27 12:06:35 +0000381 file = "???";
weidendoa17f2a32006-03-20 10:27:30 +0000382 p->line = 0;
383 }
florian536e3d72014-10-26 19:16:14 +0000384 p->file = CLG_(get_file_node)(bbcc->bb->obj, dir, file);
weidendoa17f2a32006-03-20 10:27:30 +0000385
weidendo3db43222007-09-17 12:52:10 +0000386 debug_cache_info[cachepos] = found_file_line;
weidendoa17f2a32006-03-20 10:27:30 +0000387 debug_cache_addr[cachepos] = addr;
388 debug_cache_line[cachepos] = p->line;
389 debug_cache_file[cachepos] = p->file;
390 }
391
392 /* Address offset from bbcc start address */
393 p->addr = addr - bbcc->bb->obj->offset;
394 p->bb_addr = bbcc->bb->offset;
395
barta0b6b2c2008-07-07 06:49:24 +0000396 CLG_DEBUG(3, " get_debug_pos(%#lx): BB %#lx, fn '%s', file '%s', line %u\n",
weidendoa17f2a32006-03-20 10:27:30 +0000397 addr, bb_addr(bbcc->bb), bbcc->cxt->fn[0]->name,
398 p->file->name, p->line);
399
weidendo3db43222007-09-17 12:52:10 +0000400 return found_file_line;
weidendoa17f2a32006-03-20 10:27:30 +0000401}
402
403
404/* copy file position and init cost */
405static void init_apos(AddrPos* p, Addr addr, Addr bbaddr, file_node* file)
406{
407 p->addr = addr;
408 p->bb_addr = bbaddr;
409 p->file = file;
410 p->line = 0;
411}
412
413static void copy_apos(AddrPos* dst, AddrPos* src)
414{
415 dst->addr = src->addr;
416 dst->bb_addr = src->bb_addr;
417 dst->file = src->file;
418 dst->line = src->line;
419}
420
421/* copy file position and init cost */
422static void init_fcost(AddrCost* c, Addr addr, Addr bbaddr, file_node* file)
423{
424 init_apos( &(c->p), addr, bbaddr, file);
425 /* FIXME: This is a memory leak as a AddrCost is inited multiple times */
426 c->cost = CLG_(get_eventset_cost)( CLG_(sets).full );
427 CLG_(init_cost)( CLG_(sets).full, c->cost );
428}
429
430
431/**
432 * print position change inside of a BB (last -> curr)
433 * this doesn't update last to curr!
434 */
floriancc9480f2014-11-11 20:46:34 +0000435static void fprint_apos(VgFile *fp, AddrPos* curr, AddrPos* last,
436 file_node* func_file)
weidendoa17f2a32006-03-20 10:27:30 +0000437{
438 CLG_ASSERT(curr->file != 0);
florianb7876db2015-08-05 19:04:51 +0000439 CLG_DEBUG(2, " print_apos(file '%s', line %u, bb %#lx, addr %#lx) fnFile '%s'\n",
weidendoa17f2a32006-03-20 10:27:30 +0000440 curr->file->name, curr->line, curr->bb_addr, curr->addr,
441 func_file->name);
442
443 if (curr->file != last->file) {
444
445 /* if we switch back to orig file, use fe=... */
446 if (curr->file == func_file)
floriancc9480f2014-11-11 20:46:34 +0000447 print_file(fp, "fe=", curr->file);
weidendoa17f2a32006-03-20 10:27:30 +0000448 else
floriancc9480f2014-11-11 20:46:34 +0000449 print_file(fp, "fi=", curr->file);
weidendoa17f2a32006-03-20 10:27:30 +0000450 }
451
452 if (CLG_(clo).dump_bbs) {
453 if (curr->line != last->line) {
florianb7876db2015-08-05 19:04:51 +0000454 VG_(fprintf)(fp, "ln=%u\n", curr->line);
weidendoa17f2a32006-03-20 10:27:30 +0000455 }
456 }
457}
458
459
460
461/**
462 * Print a position.
463 * This prints out differences if allowed
464 *
465 * This doesn't set last to curr afterwards!
466 */
467static
floriancc9480f2014-11-11 20:46:34 +0000468void fprint_pos(VgFile *fp, const AddrPos* curr, const AddrPos* last)
weidendoa17f2a32006-03-20 10:27:30 +0000469{
470 if (0) //CLG_(clo).dump_bbs)
floriancc9480f2014-11-11 20:46:34 +0000471 VG_(fprintf)(fp, "%lu ", curr->addr - curr->bb_addr);
weidendoa17f2a32006-03-20 10:27:30 +0000472 else {
weidendoa17f2a32006-03-20 10:27:30 +0000473 if (CLG_(clo).dump_instr) {
474 int diff = curr->addr - last->addr;
475 if ( CLG_(clo).compress_pos && (last->addr >0) &&
476 (diff > -100) && (diff < 100)) {
477 if (diff >0)
floriancc9480f2014-11-11 20:46:34 +0000478 VG_(fprintf)(fp, "+%d ", diff);
weidendoa17f2a32006-03-20 10:27:30 +0000479 else if (diff==0)
floriancc9480f2014-11-11 20:46:34 +0000480 VG_(fprintf)(fp, "* ");
weidendoa17f2a32006-03-20 10:27:30 +0000481 else
floriancc9480f2014-11-11 20:46:34 +0000482 VG_(fprintf)(fp, "%d ", diff);
weidendoa17f2a32006-03-20 10:27:30 +0000483 }
484 else
floriancc9480f2014-11-11 20:46:34 +0000485 VG_(fprintf)(fp, "%#lx ", curr->addr);
weidendoa17f2a32006-03-20 10:27:30 +0000486 }
487
488 if (CLG_(clo).dump_bb) {
489 int diff = curr->bb_addr - last->bb_addr;
490 if ( CLG_(clo).compress_pos && (last->bb_addr >0) &&
491 (diff > -100) && (diff < 100)) {
492 if (diff >0)
floriancc9480f2014-11-11 20:46:34 +0000493 VG_(fprintf)(fp, "+%d ", diff);
weidendoa17f2a32006-03-20 10:27:30 +0000494 else if (diff==0)
floriancc9480f2014-11-11 20:46:34 +0000495 VG_(fprintf)(fp, "* ");
weidendoa17f2a32006-03-20 10:27:30 +0000496 else
floriancc9480f2014-11-11 20:46:34 +0000497 VG_(fprintf)(fp, "%d ", diff);
weidendoa17f2a32006-03-20 10:27:30 +0000498 }
499 else
floriancc9480f2014-11-11 20:46:34 +0000500 VG_(fprintf)(fp, "%#lx ", curr->bb_addr);
weidendoa17f2a32006-03-20 10:27:30 +0000501 }
502
503 if (CLG_(clo).dump_line) {
504 int diff = curr->line - last->line;
505 if ( CLG_(clo).compress_pos && (last->line >0) &&
506 (diff > -100) && (diff < 100)) {
507
508 if (diff >0)
floriancc9480f2014-11-11 20:46:34 +0000509 VG_(fprintf)(fp, "+%d ", diff);
weidendoa17f2a32006-03-20 10:27:30 +0000510 else if (diff==0)
floriancc9480f2014-11-11 20:46:34 +0000511 VG_(fprintf)(fp, "* ");
weidendoa17f2a32006-03-20 10:27:30 +0000512 else
floriancc9480f2014-11-11 20:46:34 +0000513 VG_(fprintf)(fp, "%d ", diff);
weidendoa17f2a32006-03-20 10:27:30 +0000514 }
515 else
floriancc9480f2014-11-11 20:46:34 +0000516 VG_(fprintf)(fp, "%u ", curr->line);
weidendoa17f2a32006-03-20 10:27:30 +0000517 }
518 }
weidendoa17f2a32006-03-20 10:27:30 +0000519}
520
521
522/**
523 * Print events.
524 */
525
526static
floriancc9480f2014-11-11 20:46:34 +0000527void fprint_cost(VgFile *fp, const EventMapping* es, const ULong* cost)
weidendoa17f2a32006-03-20 10:27:30 +0000528{
florian5ee42a42014-11-06 21:43:44 +0000529 HChar *mcost = CLG_(mappingcost_as_string)(es, cost);
floriancc9480f2014-11-11 20:46:34 +0000530 VG_(fprintf)(fp, "%s\n", mcost);
florian5ee42a42014-11-06 21:43:44 +0000531 CLG_FREE(mcost);
weidendoa17f2a32006-03-20 10:27:30 +0000532}
533
534
535
536/* Write the cost of a source line; only that parts of the source
537 * position are written that changed relative to last written position.
538 * funcPos is the source position of the first line of actual function.
539 * Something is written only if cost != 0; returns True in this case.
540 */
floriancc9480f2014-11-11 20:46:34 +0000541static void fprint_fcost(VgFile *fp, AddrCost* c, AddrPos* last)
weidendoa17f2a32006-03-20 10:27:30 +0000542{
543 CLG_DEBUGIF(3) {
florianb7876db2015-08-05 19:04:51 +0000544 CLG_DEBUG(2, " print_fcost(file '%s', line %u, bb %#lx, addr %#lx):\n",
weidendoa17f2a32006-03-20 10:27:30 +0000545 c->p.file->name, c->p.line, c->p.bb_addr, c->p.addr);
546 CLG_(print_cost)(-5, CLG_(sets).full, c->cost);
547 }
548
floriancc9480f2014-11-11 20:46:34 +0000549 fprint_pos(fp, &(c->p), last);
weidendoa17f2a32006-03-20 10:27:30 +0000550 copy_apos( last, &(c->p) ); /* update last to current position */
551
floriancc9480f2014-11-11 20:46:34 +0000552 fprint_cost(fp, CLG_(dumpmap), c->cost);
weidendoa17f2a32006-03-20 10:27:30 +0000553
554 /* add cost to total */
555 CLG_(add_and_zero_cost)( CLG_(sets).full, dump_total_cost, c->cost );
556}
557
558
559/* Write out the calls from jcc (at pos)
560 */
floriancc9480f2014-11-11 20:46:34 +0000561static void fprint_jcc(VgFile *fp, jCC* jcc, AddrPos* curr, AddrPos* last,
562 ULong ecounter)
weidendoa17f2a32006-03-20 10:27:30 +0000563{
564 static AddrPos target;
565 file_node* file;
566 obj_node* obj;
567
568 CLG_DEBUGIF(2) {
florianb7876db2015-08-05 19:04:51 +0000569 CLG_DEBUG(2, " fprint_jcc (jkind %d)\n", (Int)jcc->jmpkind);
weidendoa17f2a32006-03-20 10:27:30 +0000570 CLG_(print_jcc)(-10, jcc);
571 }
572
weidendo061f0792011-05-11 12:28:01 +0000573 CLG_ASSERT(jcc->to !=0);
574 CLG_ASSERT(jcc->from !=0);
575
weidendoa17f2a32006-03-20 10:27:30 +0000576 if (!get_debug_pos(jcc->to, bb_addr(jcc->to->bb), &target)) {
577 /* if we don't have debug info, don't switch to file "???" */
578 target.file = last->file;
579 }
580
weidendo28a23c02011-11-14 21:16:25 +0000581 if ((jcc->jmpkind == jk_CondJump) || (jcc->jmpkind == jk_Jump)) {
weidendoa17f2a32006-03-20 10:27:30 +0000582
583 /* this is a JCC for a followed conditional or boring jump. */
584 CLG_ASSERT(CLG_(is_zero_cost)( CLG_(sets).full, jcc->cost));
585
586 /* objects among jumps should be the same.
587 * Otherwise this jump would have been changed to a call
588 * (see setup_bbcc)
589 */
590 CLG_ASSERT(jcc->from->bb->obj == jcc->to->bb->obj);
591
florianad4e9792015-07-05 21:53:33 +0000592 /* only print if target position info is useful */
weidendoa17f2a32006-03-20 10:27:30 +0000593 if (!CLG_(clo).dump_instr && !CLG_(clo).dump_bb && target.line==0) {
594 jcc->call_counter = 0;
595 return;
596 }
597
598 /* Different files/functions are possible e.g. with longjmp's
599 * which change the stack, and thus context
600 */
601 if (last->file != target.file) {
floriancc9480f2014-11-11 20:46:34 +0000602 print_file(fp, "jfi=", target.file);
weidendoa17f2a32006-03-20 10:27:30 +0000603 }
604
605 if (jcc->from->cxt != jcc->to->cxt) {
606 if (CLG_(clo).mangle_names)
floriancc9480f2014-11-11 20:46:34 +0000607 print_mangled_fn(fp, "jfn",
weidendoa17f2a32006-03-20 10:27:30 +0000608 jcc->to->cxt, jcc->to->rec_index);
609 else
floriancc9480f2014-11-11 20:46:34 +0000610 print_fn(fp, "jfn", jcc->to->cxt->fn[0]);
weidendoa17f2a32006-03-20 10:27:30 +0000611 }
612
weidendo28a23c02011-11-14 21:16:25 +0000613 if (jcc->jmpkind == jk_CondJump) {
weidendoa17f2a32006-03-20 10:27:30 +0000614 /* format: jcnd=<followed>/<executions> <target> */
floriancc9480f2014-11-11 20:46:34 +0000615 VG_(fprintf)(fp, "jcnd=%llu/%llu ",
weidendoa17f2a32006-03-20 10:27:30 +0000616 jcc->call_counter, ecounter);
617 }
618 else {
619 /* format: jump=<jump count> <target> */
floriancc9480f2014-11-11 20:46:34 +0000620 VG_(fprintf)(fp, "jump=%llu ",
weidendoa17f2a32006-03-20 10:27:30 +0000621 jcc->call_counter);
622 }
weidendoa17f2a32006-03-20 10:27:30 +0000623
floriancc9480f2014-11-11 20:46:34 +0000624 fprint_pos(fp, &target, last);
625 VG_(fprintf)(fp, "\n");
626 fprint_pos(fp, curr, last);
627 VG_(fprintf)(fp, "\n");
weidendoa17f2a32006-03-20 10:27:30 +0000628
629 jcc->call_counter = 0;
630 return;
631 }
632
weidendoa17f2a32006-03-20 10:27:30 +0000633 file = jcc->to->cxt->fn[0]->file;
634 obj = jcc->to->bb->obj;
635
636 /* object of called position different to object of this function?*/
637 if (jcc->from->cxt->fn[0]->file->obj != obj) {
floriancc9480f2014-11-11 20:46:34 +0000638 print_obj(fp, "cob=", obj);
weidendoa17f2a32006-03-20 10:27:30 +0000639 }
640
641 /* file of called position different to current file? */
642 if (last->file != file) {
floriancc9480f2014-11-11 20:46:34 +0000643 print_file(fp, "cfi=", file);
weidendoa17f2a32006-03-20 10:27:30 +0000644 }
645
646 if (CLG_(clo).mangle_names)
floriancc9480f2014-11-11 20:46:34 +0000647 print_mangled_fn(fp, "cfn", jcc->to->cxt, jcc->to->rec_index);
weidendoa17f2a32006-03-20 10:27:30 +0000648 else
floriancc9480f2014-11-11 20:46:34 +0000649 print_fn(fp, "cfn", jcc->to->cxt->fn[0]);
weidendoa17f2a32006-03-20 10:27:30 +0000650
651 if (!CLG_(is_zero_cost)( CLG_(sets).full, jcc->cost)) {
floriancc9480f2014-11-11 20:46:34 +0000652 VG_(fprintf)(fp, "calls=%llu ",
weidendoa17f2a32006-03-20 10:27:30 +0000653 jcc->call_counter);
weidendoa17f2a32006-03-20 10:27:30 +0000654
floriancc9480f2014-11-11 20:46:34 +0000655 fprint_pos(fp, &target, last);
656 VG_(fprintf)(fp, "\n");
657 fprint_pos(fp, curr, last);
658 fprint_cost(fp, CLG_(dumpmap), jcc->cost);
weidendoa17f2a32006-03-20 10:27:30 +0000659
660 CLG_(init_cost)( CLG_(sets).full, jcc->cost );
661
662 jcc->call_counter = 0;
663 }
664}
665
666
667
668/* Cost summation of functions.We use alternately ccSum[0/1], thus
669 * ssSum[currSum] for recently read lines with same line number.
670 */
671static AddrCost ccSum[2];
672static int currSum;
673
674/*
675 * Print all costs of a BBCC:
676 * - FCCs of instructions
677 * - JCCs of the unique jump of this BB
678 * returns True if something was written
679 */
floriancc9480f2014-11-11 20:46:34 +0000680static Bool fprint_bbcc(VgFile *fp, BBCC* bbcc, AddrPos* last)
weidendoa17f2a32006-03-20 10:27:30 +0000681{
682 InstrInfo* instr_info;
683 ULong ecounter;
684 Bool something_written = False;
685 jCC* jcc;
686 AddrCost *currCost, *newCost;
687 Int jcc_count = 0, instr, i, jmp;
688 BB* bb = bbcc->bb;
689
690 CLG_ASSERT(bbcc->cxt != 0);
691 CLG_DEBUGIF(1) {
florianb7876db2015-08-05 19:04:51 +0000692 VG_(printf)("+ fprint_bbcc (Instr %u): ", bb->instr_count);
weidendo09ee78e2009-02-24 12:26:53 +0000693 CLG_(print_bbcc)(15, bbcc);
weidendoa17f2a32006-03-20 10:27:30 +0000694 }
695
696 CLG_ASSERT(currSum == 0 || currSum == 1);
697 currCost = &(ccSum[currSum]);
698 newCost = &(ccSum[1-currSum]);
699
700 ecounter = bbcc->ecounter_sum;
701 jmp = 0;
702 instr_info = &(bb->instr[0]);
703 for(instr=0; instr<bb->instr_count; instr++, instr_info++) {
704
705 /* get debug info of current instruction address and dump cost
706 * if CLG_(clo).dump_bbs or file/line has changed
707 */
708 if (!get_debug_pos(bbcc, bb_addr(bb) + instr_info->instr_offset,
709 &(newCost->p))) {
710 /* if we don't have debug info, don't switch to file "???" */
711 newCost->p.file = bbcc->cxt->fn[0]->file;
712 }
713
714 if (CLG_(clo).dump_bbs || CLG_(clo).dump_instr ||
715 (newCost->p.line != currCost->p.line) ||
716 (newCost->p.file != currCost->p.file)) {
717
718 if (!CLG_(is_zero_cost)( CLG_(sets).full, currCost->cost )) {
719 something_written = True;
720
floriancc9480f2014-11-11 20:46:34 +0000721 fprint_apos(fp, &(currCost->p), last, bbcc->cxt->fn[0]->file);
722 fprint_fcost(fp, currCost, last);
weidendoa17f2a32006-03-20 10:27:30 +0000723 }
724
725 /* switch buffers */
726 currSum = 1 - currSum;
727 currCost = &(ccSum[currSum]);
728 newCost = &(ccSum[1-currSum]);
729 }
730
731 /* add line cost to current cost sum */
732 (*CLG_(cachesim).add_icost)(currCost->cost, bbcc, instr_info, ecounter);
733
734 /* print jcc's if there are: only jumps */
735 if (bb->jmp[jmp].instr == instr) {
736 jcc_count=0;
737 for(jcc=bbcc->jmp[jmp].jcc_list; jcc; jcc=jcc->next_from)
weidendo28a23c02011-11-14 21:16:25 +0000738 if (((jcc->jmpkind != jk_Call) && (jcc->call_counter >0)) ||
weidendo5af96f52009-08-11 19:21:25 +0000739 (!CLG_(is_zero_cost)( CLG_(sets).full, jcc->cost )))
weidendoa17f2a32006-03-20 10:27:30 +0000740 jcc_count++;
741
742 if (jcc_count>0) {
743 if (!CLG_(is_zero_cost)( CLG_(sets).full, currCost->cost )) {
744 /* no need to switch buffers, as position is the same */
floriancc9480f2014-11-11 20:46:34 +0000745 fprint_apos(fp, &(currCost->p), last, bbcc->cxt->fn[0]->file);
746 fprint_fcost(fp, currCost, last);
weidendoa17f2a32006-03-20 10:27:30 +0000747 }
748 get_debug_pos(bbcc, bb_addr(bb)+instr_info->instr_offset, &(currCost->p));
floriancc9480f2014-11-11 20:46:34 +0000749 fprint_apos(fp, &(currCost->p), last, bbcc->cxt->fn[0]->file);
weidendoa17f2a32006-03-20 10:27:30 +0000750 something_written = True;
751 for(jcc=bbcc->jmp[jmp].jcc_list; jcc; jcc=jcc->next_from) {
weidendo28a23c02011-11-14 21:16:25 +0000752 if (((jcc->jmpkind != jk_Call) && (jcc->call_counter >0)) ||
weidendo5af96f52009-08-11 19:21:25 +0000753 (!CLG_(is_zero_cost)( CLG_(sets).full, jcc->cost )))
floriancc9480f2014-11-11 20:46:34 +0000754 fprint_jcc(fp, jcc, &(currCost->p), last, ecounter);
weidendoa17f2a32006-03-20 10:27:30 +0000755 }
756 }
757 }
758
759 /* update execution counter */
760 if (jmp < bb->cjmp_count)
761 if (bb->jmp[jmp].instr == instr) {
762 ecounter -= bbcc->jmp[jmp].ecounter;
763 jmp++;
764 }
765 }
766
767 /* jCCs at end? If yes, dump cumulated line info first */
768 jcc_count = 0;
769 for(jcc=bbcc->jmp[jmp].jcc_list; jcc; jcc=jcc->next_from) {
770 /* yes, if JCC only counts jmp arcs or cost >0 */
weidendo28a23c02011-11-14 21:16:25 +0000771 if ( ((jcc->jmpkind != jk_Call) && (jcc->call_counter >0)) ||
weidendoa17f2a32006-03-20 10:27:30 +0000772 (!CLG_(is_zero_cost)( CLG_(sets).full, jcc->cost )))
773 jcc_count++;
774 }
775
776 if ( (bbcc->skipped &&
777 !CLG_(is_zero_cost)(CLG_(sets).full, bbcc->skipped)) ||
778 (jcc_count>0) ) {
779
780 if (!CLG_(is_zero_cost)( CLG_(sets).full, currCost->cost )) {
781 /* no need to switch buffers, as position is the same */
floriancc9480f2014-11-11 20:46:34 +0000782 fprint_apos(fp, &(currCost->p), last, bbcc->cxt->fn[0]->file);
783 fprint_fcost(fp, currCost, last);
weidendoa17f2a32006-03-20 10:27:30 +0000784 }
785
786 get_debug_pos(bbcc, bb_jmpaddr(bb), &(currCost->p));
floriancc9480f2014-11-11 20:46:34 +0000787 fprint_apos(fp, &(currCost->p), last, bbcc->cxt->fn[0]->file);
weidendoa17f2a32006-03-20 10:27:30 +0000788 something_written = True;
789
790 /* first, print skipped costs for calls */
791 if (bbcc->skipped && !CLG_(is_zero_cost)( CLG_(sets).full,
792 bbcc->skipped )) {
793 CLG_(add_and_zero_cost)( CLG_(sets).full,
794 currCost->cost, bbcc->skipped );
795#if 0
floriancc9480f2014-11-11 20:46:34 +0000796 VG_(fprintf)(fp, "# Skipped\n");
weidendoa17f2a32006-03-20 10:27:30 +0000797#endif
floriancc9480f2014-11-11 20:46:34 +0000798 fprint_fcost(fp, currCost, last);
weidendoa17f2a32006-03-20 10:27:30 +0000799 }
800
801 if (jcc_count > 0)
802 for(jcc=bbcc->jmp[jmp].jcc_list; jcc; jcc=jcc->next_from) {
803 CLG_ASSERT(jcc->jmp == jmp);
weidendo28a23c02011-11-14 21:16:25 +0000804 if ( ((jcc->jmpkind != jk_Call) && (jcc->call_counter >0)) ||
weidendoa17f2a32006-03-20 10:27:30 +0000805 (!CLG_(is_zero_cost)( CLG_(sets).full, jcc->cost )))
806
floriancc9480f2014-11-11 20:46:34 +0000807 fprint_jcc(fp, jcc, &(currCost->p), last, ecounter);
weidendoa17f2a32006-03-20 10:27:30 +0000808 }
809 }
810
811 if (CLG_(clo).dump_bbs || CLG_(clo).dump_bb) {
812 if (!CLG_(is_zero_cost)( CLG_(sets).full, currCost->cost )) {
813 something_written = True;
814
floriancc9480f2014-11-11 20:46:34 +0000815 fprint_apos(fp, &(currCost->p), last, bbcc->cxt->fn[0]->file);
816 fprint_fcost(fp, currCost, last);
weidendoa17f2a32006-03-20 10:27:30 +0000817 }
floriancc9480f2014-11-11 20:46:34 +0000818 if (CLG_(clo).dump_bbs) VG_(fprintf)(fp, "\n");
weidendoa17f2a32006-03-20 10:27:30 +0000819
florianad4e9792015-07-05 21:53:33 +0000820 /* when every cost was immediately written, we must have done so,
weidendoa17f2a32006-03-20 10:27:30 +0000821 * as this function is only called when there's cost in a BBCC
822 */
823 CLG_ASSERT(something_written);
824 }
825
826 bbcc->ecounter_sum = 0;
827 for(i=0; i<=bbcc->bb->cjmp_count; i++)
828 bbcc->jmp[i].ecounter = 0;
829 bbcc->ret_counter = 0;
830
831 CLG_DEBUG(1, "- fprint_bbcc: JCCs %d\n", jcc_count);
832
833 return something_written;
834}
835
836/* order by
837 * recursion,
838 * from->bb->obj, from->bb->fn
839 * obj, fn[0]->file, fn
840 * address
841 */
842static int my_cmp(BBCC** pbbcc1, BBCC** pbbcc2)
843{
844#if 0
845 return (*pbbcc1)->bb->offset - (*pbbcc2)->bb->offset;
846#else
847 BBCC *bbcc1 = *pbbcc1;
848 BBCC *bbcc2 = *pbbcc2;
849 Context* cxt1 = bbcc1->cxt;
850 Context* cxt2 = bbcc2->cxt;
851 int off = 1;
852
853 if (cxt1->fn[0]->file->obj != cxt2->fn[0]->file->obj)
854 return cxt1->fn[0]->file->obj - cxt2->fn[0]->file->obj;
855
856 if (cxt1->fn[0]->file != cxt2->fn[0]->file)
857 return cxt1->fn[0]->file - cxt2->fn[0]->file;
858
859 if (cxt1->fn[0] != cxt2->fn[0])
860 return cxt1->fn[0] - cxt2->fn[0];
861
862 if (bbcc1->rec_index != bbcc2->rec_index)
863 return bbcc1->rec_index - bbcc2->rec_index;
864
865 while((off < cxt1->size) && (off < cxt2->size)) {
866 fn_node* ffn1 = cxt1->fn[off];
867 fn_node* ffn2 = cxt2->fn[off];
868 if (ffn1->file->obj != ffn2->file->obj)
869 return ffn1->file->obj - ffn2->file->obj;
870 if (ffn1 != ffn2)
871 return ffn1 - ffn2;
872 off++;
873 }
874 if (cxt1->size > cxt2->size) return 1;
875 else if (cxt1->size < cxt2->size) return -1;
876
877 return bbcc1->bb->offset - bbcc2->bb->offset;
878#endif
879}
880
881
882
883
884
885/* modified version of:
886 *
887 * qsort -- qsort interface implemented by faster quicksort.
888 * J. L. Bentley and M. D. McIlroy, SPE 23 (1993) 1249-1265.
889 * Copyright 1993, John Wiley.
890*/
891
892static __inline__
weidendoa17f2a32006-03-20 10:27:30 +0000893void swap(BBCC** a, BBCC** b)
894{
895 BBCC* t;
896 t = *a; *a = *b; *b = t;
897}
898
899#define min(x, y) ((x)<=(y) ? (x) : (y))
900
901static
902BBCC** med3(BBCC **a, BBCC **b, BBCC **c, int (*cmp)(BBCC**,BBCC**))
903{ return cmp(a, b) < 0 ?
904 (cmp(b, c) < 0 ? b : cmp(a, c) < 0 ? c : a)
905 : (cmp(b, c) > 0 ? b : cmp(a, c) > 0 ? c : a);
906}
907
908static BBCC** qsort_start = 0;
909
sewardj8eb8bab2015-07-21 14:44:28 +0000910static void CLG_(qsort)(BBCC **a, int n, int (*cmp)(BBCC**,BBCC**))
weidendoa17f2a32006-03-20 10:27:30 +0000911{
912 BBCC **pa, **pb, **pc, **pd, **pl, **pm, **pn, **pv;
913 int s, r;
914 BBCC* v;
915
barta0b6b2c2008-07-07 06:49:24 +0000916 CLG_DEBUG(8, " qsort(%ld,%ld)\n", a-qsort_start + 0L, n + 0L);
weidendoa17f2a32006-03-20 10:27:30 +0000917
918 if (n < 7) { /* Insertion sort on smallest arrays */
919 for (pm = a+1; pm < a+n; pm++)
920 for (pl = pm; pl > a && cmp(pl-1, pl) > 0; pl --)
921 swap(pl, pl-1);
922
923 CLG_DEBUGIF(8) {
924 for (pm = a; pm < a+n; pm++) {
barta0b6b2c2008-07-07 06:49:24 +0000925 VG_(printf)(" %3ld BB %#lx, ",
926 pm - qsort_start + 0L,
weidendoa17f2a32006-03-20 10:27:30 +0000927 bb_addr((*pm)->bb));
928 CLG_(print_cxt)(9, (*pm)->cxt, (*pm)->rec_index);
929 }
930 }
931 return;
932 }
933 pm = a + n/2; /* Small arrays, middle element */
934 if (n > 7) {
935 pl = a;
936 pn = a + (n-1);
937 if (n > 40) { /* Big arrays, pseudomedian of 9 */
938 s = n/8;
939 pl = med3(pl, pl+s, pl+2*s, cmp);
940 pm = med3(pm-s, pm, pm+s, cmp);
941 pn = med3(pn-2*s, pn-s, pn, cmp);
942 }
943 pm = med3(pl, pm, pn, cmp); /* Mid-size, med of 3 */
944 }
945
946
947 v = *pm;
948 pv = &v;
949 pa = pb = a;
950 pc = pd = a + (n-1);
951 for (;;) {
952 while ((pb <= pc) && ((r=cmp(pb, pv)) <= 0)) {
953 if (r==0) {
954 /* same as pivot, to start */
955 swap(pa,pb); pa++;
956 }
957 pb ++;
958 }
959 while ((pb <= pc) && ((r=cmp(pc, pv)) >= 0)) {
960 if (r==0) {
961 /* same as pivot, to end */
962 swap(pc,pd); pd--;
963 }
964 pc --;
965 }
966 if (pb > pc) { break; }
967 swap(pb, pc);
968 pb ++;
969 pc --;
970 }
971 pb--;
972 pc++;
973
974 /* put pivot from start into middle */
975 if ((s = pa-a)>0) { for(r=0;r<s;r++) swap(a+r, pb+1-s+r); }
976 /* put pivot from end into middle */
977 if ((s = a+n-1-pd)>0) { for(r=0;r<s;r++) swap(pc+r, a+n-s+r); }
978
979 CLG_DEBUGIF(8) {
barta0b6b2c2008-07-07 06:49:24 +0000980 VG_(printf)(" PV BB %#lx, ", bb_addr((*pv)->bb));
weidendoa17f2a32006-03-20 10:27:30 +0000981 CLG_(print_cxt)(9, (*pv)->cxt, (*pv)->rec_index);
982
983 s = pb-pa+1;
barta0b6b2c2008-07-07 06:49:24 +0000984 VG_(printf)(" Lower %ld - %ld:\n",
985 a-qsort_start + 0L,
986 a+s-1-qsort_start + 0L);
weidendoa17f2a32006-03-20 10:27:30 +0000987 for (r=0;r<s;r++) {
988 pm = a+r;
barta0b6b2c2008-07-07 06:49:24 +0000989 VG_(printf)(" %3ld BB %#lx, ",
990 pm-qsort_start + 0L,
991 bb_addr((*pm)->bb));
weidendoa17f2a32006-03-20 10:27:30 +0000992 CLG_(print_cxt)(9, (*pm)->cxt, (*pm)->rec_index);
993 }
994
995 s = pd-pc+1;
barta0b6b2c2008-07-07 06:49:24 +0000996 VG_(printf)(" Upper %ld - %ld:\n",
997 a+n-s-qsort_start + 0L,
998 a+n-1-qsort_start + 0L);
weidendoa17f2a32006-03-20 10:27:30 +0000999 for (r=0;r<s;r++) {
1000 pm = a+n-s+r;
barta0b6b2c2008-07-07 06:49:24 +00001001 VG_(printf)(" %3ld BB %#lx, ",
1002 pm-qsort_start + 0L,
1003 bb_addr((*pm)->bb));
weidendoa17f2a32006-03-20 10:27:30 +00001004 CLG_(print_cxt)(9, (*pm)->cxt, (*pm)->rec_index);
1005 }
1006 }
1007
sewardj8eb8bab2015-07-21 14:44:28 +00001008 if ((s = pb+1-pa) > 1) CLG_(qsort)(a, s, cmp);
1009 if ((s = pd+1-pc) > 1) CLG_(qsort)(a+n-s, s, cmp);
weidendoa17f2a32006-03-20 10:27:30 +00001010}
1011
1012
1013/* Helpers for prepare_dump */
1014
1015static Int prepare_count;
1016static BBCC** prepare_ptr;
1017
1018
1019static void hash_addCount(BBCC* bbcc)
1020{
1021 if ((bbcc->ecounter_sum > 0) || (bbcc->ret_counter>0))
1022 prepare_count++;
1023}
1024
1025static void hash_addPtr(BBCC* bbcc)
1026{
1027 if ((bbcc->ecounter_sum == 0) &&
1028 (bbcc->ret_counter == 0)) return;
1029
1030 *prepare_ptr = bbcc;
1031 prepare_ptr++;
1032}
1033
1034
1035static void cs_addCount(thread_info* ti)
1036{
1037 Int i;
1038 BBCC* bbcc;
1039
1040 /* add BBCCs with active call in call stack of current thread.
1041 * update cost sums for active calls
1042 */
1043
1044 for(i = 0; i < CLG_(current_call_stack).sp; i++) {
1045 call_entry* e = &(CLG_(current_call_stack).entry[i]);
1046 if (e->jcc == 0) continue;
1047
1048 CLG_(add_diff_cost_lz)( CLG_(sets).full, &(e->jcc->cost),
1049 e->enter_cost, CLG_(current_state).cost);
1050 bbcc = e->jcc->from;
1051
florianb7876db2015-08-05 19:04:51 +00001052 CLG_DEBUG(1, " [%2d] (tid %u), added active: %s\n",
weidendoa17f2a32006-03-20 10:27:30 +00001053 i,CLG_(current_tid),bbcc->cxt->fn[0]->name);
1054
1055 if (bbcc->ecounter_sum>0 || bbcc->ret_counter>0) {
1056 /* already counted */
1057 continue;
1058 }
1059 prepare_count++;
1060 }
1061}
1062
1063static void cs_addPtr(thread_info* ti)
1064{
1065 Int i;
1066 BBCC* bbcc;
1067
1068 /* add BBCCs with active call in call stack of current thread.
1069 * update cost sums for active calls
1070 */
1071
1072 for(i = 0; i < CLG_(current_call_stack).sp; i++) {
1073 call_entry* e = &(CLG_(current_call_stack).entry[i]);
1074 if (e->jcc == 0) continue;
1075
1076 bbcc = e->jcc->from;
1077
1078 if (bbcc->ecounter_sum>0 || bbcc->ret_counter>0) {
1079 /* already counted */
1080 continue;
1081 }
1082
1083 *prepare_ptr = bbcc;
1084 prepare_ptr++;
1085 }
1086}
1087
1088
1089/**
1090 * Put all BBCCs with costs into a sorted array.
1091 * The returned arrays ends with a null pointer.
1092 * Must be freed after dumping.
1093 */
1094static
1095BBCC** prepare_dump(void)
1096{
1097 BBCC **array;
1098
1099 prepare_count = 0;
1100
1101 /* if we do not separate among threads, this gives all */
1102 /* count number of BBCCs with >0 executions */
1103 CLG_(forall_bbccs)(hash_addCount);
1104
1105 /* even if we do not separate among threads,
1106 * call stacks are separated */
1107 if (CLG_(clo).separate_threads)
1108 cs_addCount(0);
1109 else
1110 CLG_(forall_threads)(cs_addCount);
1111
1112 CLG_DEBUG(0, "prepare_dump: %d BBCCs\n", prepare_count);
1113
1114 /* allocate bbcc array, insert BBCCs and sort */
1115 prepare_ptr = array =
sewardj9c606bd2008-09-18 18:12:50 +00001116 (BBCC**) CLG_MALLOC("cl.dump.pd.1",
1117 (prepare_count+1) * sizeof(BBCC*));
weidendoa17f2a32006-03-20 10:27:30 +00001118
1119 CLG_(forall_bbccs)(hash_addPtr);
1120
1121 if (CLG_(clo).separate_threads)
1122 cs_addPtr(0);
1123 else
1124 CLG_(forall_threads)(cs_addPtr);
1125
1126 CLG_ASSERT(array + prepare_count == prepare_ptr);
1127
1128 /* end mark */
1129 *prepare_ptr = 0;
1130
1131 CLG_DEBUG(0," BBCCs inserted\n");
1132
1133 qsort_start = array;
sewardj8eb8bab2015-07-21 14:44:28 +00001134 CLG_(qsort)(array, prepare_count, my_cmp);
weidendoa17f2a32006-03-20 10:27:30 +00001135
1136 CLG_DEBUG(0," BBCCs sorted\n");
1137
1138 return array;
1139}
1140
1141
1142
1143
floriancc9480f2014-11-11 20:46:34 +00001144static void fprint_cost_ln(VgFile *fp, const HChar* prefix,
1145 const EventMapping* em, const ULong* cost)
weidendoa17f2a32006-03-20 10:27:30 +00001146{
florian5ee42a42014-11-06 21:43:44 +00001147 HChar *mcost = CLG_(mappingcost_as_string)(em, cost);
floriancc9480f2014-11-11 20:46:34 +00001148 VG_(fprintf)(fp, "%s%s\n", prefix, mcost);
florian5ee42a42014-11-06 21:43:44 +00001149 CLG_FREE(mcost);
weidendoa17f2a32006-03-20 10:27:30 +00001150}
1151
1152static ULong bbs_done = 0;
floriandbb35842012-10-27 18:39:11 +00001153static HChar* filename = 0;
weidendoa17f2a32006-03-20 10:27:30 +00001154
1155static
1156void file_err(void)
1157{
1158 VG_(message)(Vg_UserMsg,
sewardj0f33adf2009-07-15 14:51:03 +00001159 "Error: can not open cache simulation output file `%s'\n",
weidendoa17f2a32006-03-20 10:27:30 +00001160 filename );
1161 VG_(exit)(1);
1162}
1163
1164/**
1165 * Create a new dump file and write header.
1166 *
1167 * Naming: <CLG_(clo).filename_base>.<pid>[.<part>][-<tid>]
1168 * <part> is skipped for final dump (trigger==0)
1169 * <tid> is skipped for thread 1 with CLG_(clo).separate_threads=no
1170 *
1171 * Returns the file descriptor, and -1 on error (no write permission)
1172 */
floriancc9480f2014-11-11 20:46:34 +00001173static VgFile *new_dumpfile(int tid, const HChar* trigger)
weidendoa17f2a32006-03-20 10:27:30 +00001174{
1175 Bool appending = False;
floriancc9480f2014-11-11 20:46:34 +00001176 int i;
weidendoa17f2a32006-03-20 10:27:30 +00001177 FullCost sum = 0;
floriancc9480f2014-11-11 20:46:34 +00001178 VgFile *fp;
weidendoa17f2a32006-03-20 10:27:30 +00001179
weidendo4ce5e792006-09-20 21:29:39 +00001180 CLG_ASSERT(dumps_initialized);
weidendoa17f2a32006-03-20 10:27:30 +00001181 CLG_ASSERT(filename != 0);
1182
1183 if (!CLG_(clo).combine_dumps) {
weidendocbf4e192007-11-27 01:27:12 +00001184 i = VG_(sprintf)(filename, "%s", out_file);
weidendoa17f2a32006-03-20 10:27:30 +00001185
1186 if (trigger)
1187 i += VG_(sprintf)(filename+i, ".%d", out_counter);
1188
1189 if (CLG_(clo).separate_threads)
njn4c245e52009-03-15 23:25:38 +00001190 VG_(sprintf)(filename+i, "-%02d", tid);
weidendoa17f2a32006-03-20 10:27:30 +00001191
floriancc9480f2014-11-11 20:46:34 +00001192 fp = VG_(fopen)(filename, VKI_O_WRONLY|VKI_O_TRUNC, 0);
weidendoa17f2a32006-03-20 10:27:30 +00001193 }
1194 else {
weidendocbf4e192007-11-27 01:27:12 +00001195 VG_(sprintf)(filename, "%s", out_file);
floriancc9480f2014-11-11 20:46:34 +00001196 fp = VG_(fopen)(filename, VKI_O_WRONLY|VKI_O_APPEND, 0);
1197 if (fp && out_counter>1)
weidendoa17f2a32006-03-20 10:27:30 +00001198 appending = True;
1199 }
1200
floriancc9480f2014-11-11 20:46:34 +00001201 if (fp == NULL) {
1202 fp = VG_(fopen)(filename, VKI_O_CREAT|VKI_O_WRONLY,
1203 VKI_S_IRUSR|VKI_S_IWUSR);
1204 if (fp == NULL) {
weidendoa17f2a32006-03-20 10:27:30 +00001205 /* If the file can not be opened for whatever reason (conflict
1206 between multiple supervised processes?), give up now. */
1207 file_err();
1208 }
1209 }
weidendoa17f2a32006-03-20 10:27:30 +00001210
1211 CLG_DEBUG(2, " new_dumpfile '%s'\n", filename);
1212
1213 if (!appending)
1214 reset_dump_array();
1215
1216
1217 if (!appending) {
1218 /* version */
floriancc9480f2014-11-11 20:46:34 +00001219 VG_(fprintf)(fp, "version: 1\n");
weidendoa17f2a32006-03-20 10:27:30 +00001220
1221 /* creator */
floriancc9480f2014-11-11 20:46:34 +00001222 VG_(fprintf)(fp, "creator: callgrind-" VERSION "\n");
weidendoa17f2a32006-03-20 10:27:30 +00001223
1224 /* "pid:" line */
floriancc9480f2014-11-11 20:46:34 +00001225 VG_(fprintf)(fp, "pid: %d\n", VG_(getpid)());
weidendoa17f2a32006-03-20 10:27:30 +00001226
1227 /* "cmd:" line */
floriancc9480f2014-11-11 20:46:34 +00001228 VG_(fprintf)(fp, "cmd: %s", cmdbuf);
weidendoa17f2a32006-03-20 10:27:30 +00001229 }
1230
floriancc9480f2014-11-11 20:46:34 +00001231 VG_(fprintf)(fp, "\npart: %d\n", out_counter);
weidendoa17f2a32006-03-20 10:27:30 +00001232 if (CLG_(clo).separate_threads) {
floriancc9480f2014-11-11 20:46:34 +00001233 VG_(fprintf)(fp, "thread: %d\n", tid);
weidendoa17f2a32006-03-20 10:27:30 +00001234 }
1235
1236 /* "desc:" lines */
1237 if (!appending) {
floriancc9480f2014-11-11 20:46:34 +00001238 VG_(fprintf)(fp, "\n");
weidendoa17f2a32006-03-20 10:27:30 +00001239
1240#if 0
1241 /* Global options changing the tracing behaviour */
floriancc9480f2014-11-11 20:46:34 +00001242 VG_(fprintf)(fp, "\ndesc: Option: --skip-plt=%s\n",
weidendoa17f2a32006-03-20 10:27:30 +00001243 CLG_(clo).skip_plt ? "yes" : "no");
floriancc9480f2014-11-11 20:46:34 +00001244 VG_(fprintf)(fp, "desc: Option: --collect-jumps=%s\n",
weidendoa17f2a32006-03-20 10:27:30 +00001245 CLG_(clo).collect_jumps ? "yes" : "no");
floriancc9480f2014-11-11 20:46:34 +00001246 VG_(fprintf)(fp, "desc: Option: --separate-recs=%d\n",
weidendoa17f2a32006-03-20 10:27:30 +00001247 CLG_(clo).separate_recursions);
floriancc9480f2014-11-11 20:46:34 +00001248 VG_(fprintf)(fp, "desc: Option: --separate-callers=%d\n",
weidendoa17f2a32006-03-20 10:27:30 +00001249 CLG_(clo).separate_callers);
weidendoa17f2a32006-03-20 10:27:30 +00001250
floriancc9480f2014-11-11 20:46:34 +00001251 VG_(fprintf)(fp, "desc: Option: --dump-bbs=%s\n",
weidendoa17f2a32006-03-20 10:27:30 +00001252 CLG_(clo).dump_bbs ? "yes" : "no");
floriancc9480f2014-11-11 20:46:34 +00001253 VG_(fprintf)(fp, "desc: Option: --separate-threads=%s\n",
weidendoa17f2a32006-03-20 10:27:30 +00001254 CLG_(clo).separate_threads ? "yes" : "no");
weidendoa17f2a32006-03-20 10:27:30 +00001255#endif
1256
floriancc9480f2014-11-11 20:46:34 +00001257 (*CLG_(cachesim).dump_desc)(fp);
weidendoa17f2a32006-03-20 10:27:30 +00001258 }
1259
floriancc9480f2014-11-11 20:46:34 +00001260 VG_(fprintf)(fp, "\ndesc: Timerange: Basic block %llu - %llu\n",
weidendoa17f2a32006-03-20 10:27:30 +00001261 bbs_done, CLG_(stat).bb_executions);
1262
floriancc9480f2014-11-11 20:46:34 +00001263 VG_(fprintf)(fp, "desc: Trigger: %s\n",
florian25f6c572012-10-21 02:55:56 +00001264 trigger ? trigger : "Program termination");
weidendoa17f2a32006-03-20 10:27:30 +00001265
1266#if 0
1267 /* Output function specific config
1268 * FIXME */
1269 for (i = 0; i < N_FNCONFIG_ENTRIES; i++) {
1270 fnc = fnc_table[i];
1271 while (fnc) {
1272 if (fnc->skip) {
floriancc9480f2014-11-11 20:46:34 +00001273 VG_(fprintf)(fp, "desc: Option: --fn-skip=%s\n", fnc->name);
weidendoa17f2a32006-03-20 10:27:30 +00001274 }
1275 if (fnc->dump_at_enter) {
floriancc9480f2014-11-11 20:46:34 +00001276 VG_(fprintf)(fp, "desc: Option: --fn-dump-at-enter=%s\n",
weidendoa17f2a32006-03-20 10:27:30 +00001277 fnc->name);
weidendoa17f2a32006-03-20 10:27:30 +00001278 }
1279 if (fnc->dump_at_leave) {
floriancc9480f2014-11-11 20:46:34 +00001280 VG_(fprintf)(fp, "desc: Option: --fn-dump-at-leave=%s\n",
weidendoa17f2a32006-03-20 10:27:30 +00001281 fnc->name);
weidendoa17f2a32006-03-20 10:27:30 +00001282 }
1283 if (fnc->separate_callers != CLG_(clo).separate_callers) {
floriancc9480f2014-11-11 20:46:34 +00001284 VG_(fprintf)(fp, "desc: Option: --separate-callers%d=%s\n",
weidendoa17f2a32006-03-20 10:27:30 +00001285 fnc->separate_callers, fnc->name);
weidendoa17f2a32006-03-20 10:27:30 +00001286 }
1287 if (fnc->separate_recursions != CLG_(clo).separate_recursions) {
floriancc9480f2014-11-11 20:46:34 +00001288 VG_(fprintf)(fp, "desc: Option: --separate-recs%d=%s\n",
weidendoa17f2a32006-03-20 10:27:30 +00001289 fnc->separate_recursions, fnc->name);
weidendoa17f2a32006-03-20 10:27:30 +00001290 }
1291 fnc = fnc->next;
1292 }
1293 }
1294#endif
1295
1296 /* "positions:" line */
floriancc9480f2014-11-11 20:46:34 +00001297 VG_(fprintf)(fp, "\npositions:%s%s%s\n",
weidendoa17f2a32006-03-20 10:27:30 +00001298 CLG_(clo).dump_instr ? " instr" : "",
1299 CLG_(clo).dump_bb ? " bb" : "",
1300 CLG_(clo).dump_line ? " line" : "");
weidendoa17f2a32006-03-20 10:27:30 +00001301
1302 /* "events:" line */
florian5ee42a42014-11-06 21:43:44 +00001303 HChar *evmap = CLG_(eventmapping_as_string)(CLG_(dumpmap));
floriancc9480f2014-11-11 20:46:34 +00001304 VG_(fprintf)(fp, "events: %s\n", evmap);
florian5ee42a42014-11-06 21:43:44 +00001305 VG_(free)(evmap);
weidendoa17f2a32006-03-20 10:27:30 +00001306
1307 /* summary lines */
1308 sum = CLG_(get_eventset_cost)( CLG_(sets).full );
1309 CLG_(zero_cost)(CLG_(sets).full, sum);
1310 if (CLG_(clo).separate_threads) {
1311 thread_info* ti = CLG_(get_current_thread)();
1312 CLG_(add_diff_cost)(CLG_(sets).full, sum, ti->lastdump_cost,
1313 ti->states.entry[0]->cost);
1314 }
1315 else {
1316 /* This function is called once for thread 1, where
1317 * all costs are summed up when not dumping separate per thread.
1318 * But this is not true for summary: we need to add all threads.
1319 */
1320 int t;
1321 thread_info** thr = CLG_(get_threads)();
1322 for(t=1;t<VG_N_THREADS;t++) {
1323 if (!thr[t]) continue;
1324 CLG_(add_diff_cost)(CLG_(sets).full, sum,
1325 thr[t]->lastdump_cost,
1326 thr[t]->states.entry[0]->cost);
1327 }
1328 }
floriancc9480f2014-11-11 20:46:34 +00001329 fprint_cost_ln(fp, "summary: ", CLG_(dumpmap), sum);
weidendoa17f2a32006-03-20 10:27:30 +00001330
1331 /* all dumped cost will be added to total_fcc */
1332 CLG_(init_cost_lz)( CLG_(sets).full, &dump_total_cost );
1333
floriancc9480f2014-11-11 20:46:34 +00001334 VG_(fprintf)(fp, "\n\n");
weidendoa17f2a32006-03-20 10:27:30 +00001335
1336 if (VG_(clo_verbosity) > 1)
sewardj0f33adf2009-07-15 14:51:03 +00001337 VG_(message)(Vg_DebugMsg, "Dump to %s\n", filename);
weidendoa17f2a32006-03-20 10:27:30 +00001338
floriancc9480f2014-11-11 20:46:34 +00001339 return fp;
weidendoa17f2a32006-03-20 10:27:30 +00001340}
1341
1342
floriancc9480f2014-11-11 20:46:34 +00001343static void close_dumpfile(VgFile *fp)
weidendoa17f2a32006-03-20 10:27:30 +00001344{
floriancc9480f2014-11-11 20:46:34 +00001345 if (fp == NULL) return;
weidendoa17f2a32006-03-20 10:27:30 +00001346
floriancc9480f2014-11-11 20:46:34 +00001347 fprint_cost_ln(fp, "totals: ", CLG_(dumpmap),
weidendoa17f2a32006-03-20 10:27:30 +00001348 dump_total_cost);
floriancc9480f2014-11-11 20:46:34 +00001349 //fprint_fcc_ln(fp, "summary: ", &dump_total_fcc);
weidendoa17f2a32006-03-20 10:27:30 +00001350 CLG_(add_cost_lz)(CLG_(sets).full,
1351 &CLG_(total_cost), dump_total_cost);
1352
floriancc9480f2014-11-11 20:46:34 +00001353 VG_(fclose)(fp);
weidendoa17f2a32006-03-20 10:27:30 +00001354
1355 if (filename[0] == '.') {
1356 if (-1 == VG_(rename) (filename, filename+1)) {
1357 /* Can not rename to correct file name: give out warning */
sewardj0f33adf2009-07-15 14:51:03 +00001358 VG_(message)(Vg_DebugMsg, "Warning: Can not rename .%s to %s\n",
weidendoa17f2a32006-03-20 10:27:30 +00001359 filename, filename);
1360 }
1361 }
1362}
1363
1364
1365/* Helper for print_bbccs */
1366
florian25f6c572012-10-21 02:55:56 +00001367static const HChar* print_trigger;
weidendoa17f2a32006-03-20 10:27:30 +00001368
1369static void print_bbccs_of_thread(thread_info* ti)
1370{
1371 BBCC **p, **array;
1372 FnPos lastFnPos;
1373 AddrPos lastAPos;
1374
florianb7876db2015-08-05 19:04:51 +00001375 CLG_DEBUG(1, "+ print_bbccs(tid %u)\n", CLG_(current_tid));
weidendoa17f2a32006-03-20 10:27:30 +00001376
floriancc9480f2014-11-11 20:46:34 +00001377 VgFile *print_fp = new_dumpfile(CLG_(current_tid), print_trigger);
1378 if (print_fp == NULL) {
florianb7876db2015-08-05 19:04:51 +00001379 CLG_DEBUG(1, "- print_bbccs(tid %u): No output...\n", CLG_(current_tid));
weidendoa17f2a32006-03-20 10:27:30 +00001380 return;
1381 }
1382
1383 p = array = prepare_dump();
1384 init_fpos(&lastFnPos);
1385 init_apos(&lastAPos, 0, 0, 0);
1386
florianf5d8e652014-09-11 22:15:39 +00001387 while(1) {
weidendoa17f2a32006-03-20 10:27:30 +00001388
1389 /* on context/function change, print old cost buffer before */
1390 if (lastFnPos.cxt && ((*p==0) ||
1391 (lastFnPos.cxt != (*p)->cxt) ||
1392 (lastFnPos.rec_index != (*p)->rec_index))) {
1393 if (!CLG_(is_zero_cost)( CLG_(sets).full, ccSum[currSum].cost )) {
1394 /* no need to switch buffers, as position is the same */
floriancc9480f2014-11-11 20:46:34 +00001395 fprint_apos(print_fp, &(ccSum[currSum].p), &lastAPos,
weidendoa17f2a32006-03-20 10:27:30 +00001396 lastFnPos.cxt->fn[0]->file);
floriancc9480f2014-11-11 20:46:34 +00001397 fprint_fcost(print_fp, &ccSum[currSum], &lastAPos);
weidendoa17f2a32006-03-20 10:27:30 +00001398 }
1399
1400 if (ccSum[currSum].p.file != lastFnPos.cxt->fn[0]->file) {
1401 /* switch back to file of function */
floriancc9480f2014-11-11 20:46:34 +00001402 print_file(print_fp, "fe=", lastFnPos.cxt->fn[0]->file);
weidendoa17f2a32006-03-20 10:27:30 +00001403 }
floriancc9480f2014-11-11 20:46:34 +00001404 VG_(fprintf)(print_fp, "\n");
weidendoa17f2a32006-03-20 10:27:30 +00001405 }
1406
1407 if (*p == 0) break;
1408
floriancc9480f2014-11-11 20:46:34 +00001409 if (print_fn_pos(print_fp, &lastFnPos, *p)) {
weidendoa17f2a32006-03-20 10:27:30 +00001410
1411 /* new function */
1412 init_apos(&lastAPos, 0, 0, (*p)->cxt->fn[0]->file);
1413 init_fcost(&ccSum[0], 0, 0, 0);
1414 init_fcost(&ccSum[1], 0, 0, 0);
1415 currSum = 0;
1416 }
1417
1418 if (CLG_(clo).dump_bbs) {
1419 /* FIXME: Specify Object of BB if different to object of fn */
floriancc9480f2014-11-11 20:46:34 +00001420 int i;
weidendoa17f2a32006-03-20 10:27:30 +00001421 ULong ecounter = (*p)->ecounter_sum;
florianb7876db2015-08-05 19:04:51 +00001422 VG_(fprintf)(print_fp, "bb=%#lx ", (UWord)(*p)->bb->offset);
weidendoa17f2a32006-03-20 10:27:30 +00001423 for(i = 0; i<(*p)->bb->cjmp_count;i++) {
florianb7876db2015-08-05 19:04:51 +00001424 VG_(fprintf)(print_fp, "%u %llu ",
weidendoa17f2a32006-03-20 10:27:30 +00001425 (*p)->bb->jmp[i].instr,
1426 ecounter);
1427 ecounter -= (*p)->jmp[i].ecounter;
1428 }
florianb7876db2015-08-05 19:04:51 +00001429 VG_(fprintf)(print_fp, "%u %llu\n",
weidendoa17f2a32006-03-20 10:27:30 +00001430 (*p)->bb->instr_count,
1431 ecounter);
weidendoa17f2a32006-03-20 10:27:30 +00001432 }
1433
floriancc9480f2014-11-11 20:46:34 +00001434 fprint_bbcc(print_fp, *p, &lastAPos);
weidendoa17f2a32006-03-20 10:27:30 +00001435
1436 p++;
1437 }
sewardje8089302006-10-17 02:15:17 +00001438
floriancc9480f2014-11-11 20:46:34 +00001439 close_dumpfile(print_fp);
florianf5d8e652014-09-11 22:15:39 +00001440 VG_(free)(array);
weidendoa17f2a32006-03-20 10:27:30 +00001441
1442 /* set counters of last dump */
1443 CLG_(copy_cost)( CLG_(sets).full, ti->lastdump_cost,
1444 CLG_(current_state).cost );
1445
florianb7876db2015-08-05 19:04:51 +00001446 CLG_DEBUG(1, "- print_bbccs(tid %u)\n", CLG_(current_tid));
weidendoa17f2a32006-03-20 10:27:30 +00001447}
1448
1449
florian25f6c572012-10-21 02:55:56 +00001450static void print_bbccs(const HChar* trigger, Bool only_current_thread)
weidendoa17f2a32006-03-20 10:27:30 +00001451{
1452 init_dump_array();
1453 init_debug_cache();
1454
weidendoa17f2a32006-03-20 10:27:30 +00001455 print_trigger = trigger;
1456
1457 if (!CLG_(clo).separate_threads) {
1458 /* All BBCC/JCC costs is stored for thread 1 */
1459 Int orig_tid = CLG_(current_tid);
1460
1461 CLG_(switch_thread)(1);
1462 print_bbccs_of_thread( CLG_(get_current_thread)() );
1463 CLG_(switch_thread)(orig_tid);
1464 }
1465 else if (only_current_thread)
1466 print_bbccs_of_thread( CLG_(get_current_thread)() );
1467 else
1468 CLG_(forall_threads)(print_bbccs_of_thread);
1469
1470 free_dump_array();
1471}
1472
1473
florian25f6c572012-10-21 02:55:56 +00001474void CLG_(dump_profile)(const HChar* trigger, Bool only_current_thread)
weidendoa17f2a32006-03-20 10:27:30 +00001475{
1476 CLG_DEBUG(2, "+ dump_profile(Trigger '%s')\n",
florian25f6c572012-10-21 02:55:56 +00001477 trigger ? trigger : "Prg.Term.");
weidendoa17f2a32006-03-20 10:27:30 +00001478
weidendod74d9f72008-10-24 18:50:00 +00001479 CLG_(init_dumps)();
1480
weidendoa17f2a32006-03-20 10:27:30 +00001481 if (VG_(clo_verbosity) > 1)
sewardj0f33adf2009-07-15 14:51:03 +00001482 VG_(message)(Vg_DebugMsg, "Start dumping at BB %llu (%s)...\n",
weidendoa17f2a32006-03-20 10:27:30 +00001483 CLG_(stat).bb_executions,
florian25f6c572012-10-21 02:55:56 +00001484 trigger ? trigger : "Prg.Term.");
weidendoa17f2a32006-03-20 10:27:30 +00001485
1486 out_counter++;
1487
1488 print_bbccs(trigger, only_current_thread);
1489
weidendoa17f2a32006-03-20 10:27:30 +00001490 bbs_done = CLG_(stat).bb_executions++;
1491
1492 if (VG_(clo_verbosity) > 1)
sewardj0f33adf2009-07-15 14:51:03 +00001493 VG_(message)(Vg_DebugMsg, "Dumping done.\n");
weidendoa17f2a32006-03-20 10:27:30 +00001494}
1495
weidendo061f0792011-05-11 12:28:01 +00001496/* Copy command to cmd buffer. We want to original command line
1497 * (can change at runtime)
1498 */
weidendoa17f2a32006-03-20 10:27:30 +00001499static
1500void init_cmdbuf(void)
1501{
florian2f088e72014-10-01 14:16:05 +00001502 SizeT size;
1503 Int i,j;
weidendoa17f2a32006-03-20 10:27:30 +00001504
florian2f088e72014-10-01 14:16:05 +00001505 /* Pass #1: How many bytes do we need? */
1506 size = 1; // leading ' '
1507 size += VG_(strlen)( VG_(args_the_exename) );
1508 for (i = 0; i < VG_(sizeXA)( VG_(args_for_client) ); i++) {
1509 const HChar *arg = *(HChar**)VG_(indexXA)( VG_(args_for_client), i );
1510 size += 1; // separator ' '
weidendo85774c72015-02-18 16:28:58 +00001511 // escape NL in arguments to not break dump format
1512 for(j=0; arg[j]; j++)
1513 switch(arg[j]) {
1514 case '\n':
1515 case '\\':
1516 size++; // fall through
1517 default:
1518 size++;
1519 }
florian2f088e72014-10-01 14:16:05 +00001520 }
1521
1522 cmdbuf = CLG_MALLOC("cl.dump.ic.1", size + 1); // +1 for '\0'
1523
1524 /* Pass #2: Build up the string */
florianb16609b2014-08-20 21:04:14 +00001525 size = VG_(sprintf)(cmdbuf, " %s", VG_(args_the_exename));
weidendoa17f2a32006-03-20 10:27:30 +00001526
sewardj14c7cc52007-02-25 15:08:24 +00001527 for(i = 0; i < VG_(sizeXA)( VG_(args_for_client) ); i++) {
florian2f088e72014-10-01 14:16:05 +00001528 const HChar *arg = * (HChar**) VG_(indexXA)( VG_(args_for_client), i );
1529 cmdbuf[size++] = ' ';
1530 for(j=0; arg[j]; j++)
weidendo85774c72015-02-18 16:28:58 +00001531 switch(arg[j]) {
1532 case '\n':
1533 cmdbuf[size++] = '\\';
1534 cmdbuf[size++] = 'n';
1535 break;
1536 case '\\':
1537 cmdbuf[size++] = '\\';
1538 cmdbuf[size++] = '\\';
1539 break;
1540 default:
1541 cmdbuf[size++] = arg[j];
1542 break;
1543 }
weidendoa17f2a32006-03-20 10:27:30 +00001544 }
florian2f088e72014-10-01 14:16:05 +00001545 cmdbuf[size] = '\0';
weidendoa17f2a32006-03-20 10:27:30 +00001546}
1547
weidendo4ce5e792006-09-20 21:29:39 +00001548/*
florian055c7f52014-08-20 20:37:33 +00001549 * Set up file names for dump output: <out_file>.
weidendocbf4e192007-11-27 01:27:12 +00001550 * <out_file> is derived from the output format string, which defaults
1551 * to "callgrind.out.%p", where %p is replaced with the PID.
1552 * For the final file name, on intermediate dumps a counter is appended,
1553 * and further, if separate dumps per thread are requested, the thread ID.
weidendo4ce5e792006-09-20 21:29:39 +00001554 *
weidendocbf4e192007-11-27 01:27:12 +00001555 * <out_file> always starts with a full absolute path.
1556 * If the output format string represents a relative path, the current
1557 * working directory at program start is used.
weidendod74d9f72008-10-24 18:50:00 +00001558 *
1559 * This function has to be called every time a profile dump is generated
1560 * to be able to react on PID changes.
weidendo4ce5e792006-09-20 21:29:39 +00001561 */
1562void CLG_(init_dumps)()
weidendoa17f2a32006-03-20 10:27:30 +00001563{
weidendo4ce5e792006-09-20 21:29:39 +00001564 SysRes res;
weidendoa17f2a32006-03-20 10:27:30 +00001565
weidendod74d9f72008-10-24 18:50:00 +00001566 static int thisPID = 0;
1567 int currentPID = VG_(getpid)();
1568 if (currentPID == thisPID) {
1569 /* already initialized, and no PID change */
1570 CLG_ASSERT(out_file != 0);
1571 return;
1572 }
1573 thisPID = currentPID;
1574
weidendocbf4e192007-11-27 01:27:12 +00001575 if (!CLG_(clo).out_format)
1576 CLG_(clo).out_format = DEFAULT_OUTFORMAT;
1577
weidendod74d9f72008-10-24 18:50:00 +00001578 /* If a file name was already set, clean up before */
1579 if (out_file) {
1580 VG_(free)(out_file);
weidendod74d9f72008-10-24 18:50:00 +00001581 VG_(free)(filename);
1582 out_counter = 0;
1583 }
1584
weidendocbf4e192007-11-27 01:27:12 +00001585 // Setup output filename.
1586 out_file =
1587 VG_(expand_file_name)("--callgrind-out-file", CLG_(clo).out_format);
weidendoa17f2a32006-03-20 10:27:30 +00001588
weidendoa17f2a32006-03-20 10:27:30 +00001589 /* allocate space big enough for final filenames */
florian19f91bb2012-11-10 22:29:54 +00001590 filename = (HChar*) CLG_MALLOC("cl.dump.init_dumps.2",
sewardj9c606bd2008-09-18 18:12:50 +00001591 VG_(strlen)(out_file)+32);
weidendoa17f2a32006-03-20 10:27:30 +00001592
1593 /* Make sure the output base file can be written.
1594 * This is used for the dump at program termination.
1595 * We stop with an error here if we can not create the
1596 * file: This is probably because of missing rights,
1597 * and trace parts wouldn't be allowed to be written, too.
1598 */
weidendocbf4e192007-11-27 01:27:12 +00001599 VG_(strcpy)(filename, out_file);
weidendoa17f2a32006-03-20 10:27:30 +00001600 res = VG_(open)(filename, VKI_O_WRONLY|VKI_O_TRUNC, 0);
njncda2f0f2009-05-18 02:12:08 +00001601 if (sr_isError(res)) {
weidendoa17f2a32006-03-20 10:27:30 +00001602 res = VG_(open)(filename, VKI_O_CREAT|VKI_O_WRONLY,
1603 VKI_S_IRUSR|VKI_S_IWUSR);
njncda2f0f2009-05-18 02:12:08 +00001604 if (sr_isError(res)) {
weidendoa17f2a32006-03-20 10:27:30 +00001605 file_err();
1606 }
1607 }
njncda2f0f2009-05-18 02:12:08 +00001608 if (!sr_isError(res)) VG_(close)( (Int)sr_Res(res) );
weidendoa17f2a32006-03-20 10:27:30 +00001609
weidendod74d9f72008-10-24 18:50:00 +00001610 if (!dumps_initialized)
1611 init_cmdbuf();
weidendo4ce5e792006-09-20 21:29:39 +00001612
1613 dumps_initialized = True;
weidendoa17f2a32006-03-20 10:27:30 +00001614}