blob: d82d38248671f9fbfad493b3363f521474bf3e0a [file] [log] [blame]
weidendoa17f2a32006-03-20 10:27:30 +00001
2/*--------------------------------------------------------------------*/
3/*--- Callgrind ---*/
4/*--- main.c ---*/
5/*--------------------------------------------------------------------*/
6
7/*
8 This file is part of Callgrind, a Valgrind tool for call graph
9 profiling programs.
10
sewardj03f8d3f2012-08-05 15:46:46 +000011 Copyright (C) 2002-2012, Josef Weidendorfer (Josef.Weidendorfer@gmx.de)
weidendoa17f2a32006-03-20 10:27:30 +000012
njn9a0cba42007-04-15 22:15:57 +000013 This tool is derived from and contains code from Cachegrind
sewardj03f8d3f2012-08-05 15:46:46 +000014 Copyright (C) 2002-2012 Nicholas Nethercote (njn@valgrind.org)
weidendoa17f2a32006-03-20 10:27:30 +000015
16 This program is free software; you can redistribute it and/or
17 modify it under the terms of the GNU General Public License as
18 published by the Free Software Foundation; either version 2 of the
19 License, or (at your option) any later version.
20
21 This program is distributed in the hope that it will be useful, but
22 WITHOUT ANY WARRANTY; without even the implied warranty of
23 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
24 General Public License for more details.
25
26 You should have received a copy of the GNU General Public License
27 along with this program; if not, write to the Free Software
28 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
29 02111-1307, USA.
30
31 The GNU General Public License is contained in the file COPYING.
32*/
33
34#include "config.h"
35#include "callgrind.h"
36#include "global.h"
37
sewardje7a50822011-04-20 11:54:32 +000038#include "pub_tool_threadstate.h"
sewardj3b290482011-05-06 21:02:55 +000039#include "pub_tool_gdbserver.h"
weidendoa17f2a32006-03-20 10:27:30 +000040
weidendo320705f2010-07-02 19:56:23 +000041#include "cg_branchpred.c"
42
weidendoa17f2a32006-03-20 10:27:30 +000043/*------------------------------------------------------------*/
44/*--- Global variables ---*/
45/*------------------------------------------------------------*/
46
47/* for all threads */
48CommandLineOptions CLG_(clo);
49Statistics CLG_(stat);
50Bool CLG_(instrument_state) = True; /* Instrumentation on ? */
51
52/* thread and signal handler specific */
53exec_state CLG_(current_state);
54
sewardjc4ebde32012-06-03 23:10:55 +000055/* min of L1 and LL cache line sizes. This only gets set to a
56 non-zero value if we are doing cache simulation. */
57Int CLG_(min_line_size) = 0;
58
weidendoa17f2a32006-03-20 10:27:30 +000059
60/*------------------------------------------------------------*/
61/*--- Statistics ---*/
62/*------------------------------------------------------------*/
63
64static void CLG_(init_statistics)(Statistics* s)
65{
66 s->call_counter = 0;
67 s->jcnd_counter = 0;
68 s->jump_counter = 0;
69 s->rec_call_counter = 0;
70 s->ret_counter = 0;
71 s->bb_executions = 0;
72
73 s->context_counter = 0;
74 s->bb_retranslations = 0;
75
76 s->distinct_objs = 0;
77 s->distinct_files = 0;
78 s->distinct_fns = 0;
79 s->distinct_contexts = 0;
80 s->distinct_bbs = 0;
81 s->distinct_bbccs = 0;
82 s->distinct_instrs = 0;
83 s->distinct_skips = 0;
84
85 s->bb_hash_resizes = 0;
86 s->bbcc_hash_resizes = 0;
87 s->jcc_hash_resizes = 0;
88 s->cxt_hash_resizes = 0;
89 s->fn_array_resizes = 0;
90 s->call_stack_resizes = 0;
91 s->fn_stack_resizes = 0;
92
93 s->full_debug_BBs = 0;
94 s->file_line_debug_BBs = 0;
95 s->fn_name_debug_BBs = 0;
96 s->no_debug_BBs = 0;
97 s->bbcc_lru_misses = 0;
98 s->jcc_lru_misses = 0;
99 s->cxt_lru_misses = 0;
100 s->bbcc_clones = 0;
101}
102
103
weidendoa17f2a32006-03-20 10:27:30 +0000104/*------------------------------------------------------------*/
weidendoaeb86222010-06-09 22:33:02 +0000105/*--- Simple callbacks (not cache similator) ---*/
106/*------------------------------------------------------------*/
107
108VG_REGPARM(1)
109static void log_global_event(InstrInfo* ii)
110{
111 ULong* cost_Bus;
112
weidendo320705f2010-07-02 19:56:23 +0000113 CLG_DEBUG(6, "log_global_event: Ir %#lx/%u\n",
weidendoaeb86222010-06-09 22:33:02 +0000114 CLG_(bb_base) + ii->instr_offset, ii->instr_size);
115
116 if (!CLG_(current_state).collect) return;
117
weidendo320705f2010-07-02 19:56:23 +0000118 CLG_ASSERT( (ii->eventset->mask & (1u<<EG_BUS))>0 );
119
weidendoaeb86222010-06-09 22:33:02 +0000120 CLG_(current_state).cost[ fullOffset(EG_BUS) ]++;
121
122 if (CLG_(current_state).nonskipped)
123 cost_Bus = CLG_(current_state).nonskipped->skipped + fullOffset(EG_BUS);
124 else
125 cost_Bus = CLG_(cost_base) + ii->cost_offset + ii->eventset->offset[EG_BUS];
126 cost_Bus[0]++;
127}
128
129
weidendo320705f2010-07-02 19:56:23 +0000130/* For branches, we consult two different predictors, one which
131 predicts taken/untaken for conditional branches, and the other
132 which predicts the branch target address for indirect branches
133 (jump-to-register style ones). */
134
135static VG_REGPARM(2)
136void log_cond_branch(InstrInfo* ii, Word taken)
137{
138 Bool miss;
139 Int fullOffset_Bc;
140 ULong* cost_Bc;
141
142 CLG_DEBUG(6, "log_cond_branch: Ir %#lx, taken %lu\n",
143 CLG_(bb_base) + ii->instr_offset, taken);
144
145 miss = 1 & do_cond_branch_predict(CLG_(bb_base) + ii->instr_offset, taken);
146
147 if (!CLG_(current_state).collect) return;
148
149 CLG_ASSERT( (ii->eventset->mask & (1u<<EG_BC))>0 );
150
151 if (CLG_(current_state).nonskipped)
152 cost_Bc = CLG_(current_state).nonskipped->skipped + fullOffset(EG_BC);
153 else
154 cost_Bc = CLG_(cost_base) + ii->cost_offset + ii->eventset->offset[EG_BC];
155
156 fullOffset_Bc = fullOffset(EG_BC);
157 CLG_(current_state).cost[ fullOffset_Bc ]++;
158 cost_Bc[0]++;
159 if (miss) {
160 CLG_(current_state).cost[ fullOffset_Bc+1 ]++;
161 cost_Bc[1]++;
162 }
163}
164
165static VG_REGPARM(2)
166void log_ind_branch(InstrInfo* ii, UWord actual_dst)
167{
168 Bool miss;
169 Int fullOffset_Bi;
170 ULong* cost_Bi;
171
172 CLG_DEBUG(6, "log_ind_branch: Ir %#lx, dst %#lx\n",
173 CLG_(bb_base) + ii->instr_offset, actual_dst);
174
175 miss = 1 & do_ind_branch_predict(CLG_(bb_base) + ii->instr_offset, actual_dst);
176
177 if (!CLG_(current_state).collect) return;
178
179 CLG_ASSERT( (ii->eventset->mask & (1u<<EG_BI))>0 );
180
181 if (CLG_(current_state).nonskipped)
182 cost_Bi = CLG_(current_state).nonskipped->skipped + fullOffset(EG_BI);
183 else
184 cost_Bi = CLG_(cost_base) + ii->cost_offset + ii->eventset->offset[EG_BI];
185
186 fullOffset_Bi = fullOffset(EG_BI);
187 CLG_(current_state).cost[ fullOffset_Bi ]++;
188 cost_Bi[0]++;
189 if (miss) {
190 CLG_(current_state).cost[ fullOffset_Bi+1 ]++;
191 cost_Bi[1]++;
192 }
193}
194
weidendoaeb86222010-06-09 22:33:02 +0000195/*------------------------------------------------------------*/
weidendo0a1951d2009-06-15 00:16:36 +0000196/*--- Instrumentation structures and event queue handling ---*/
weidendoa17f2a32006-03-20 10:27:30 +0000197/*------------------------------------------------------------*/
198
weidendo0a1951d2009-06-15 00:16:36 +0000199/* Maintain an ordered list of memory events which are outstanding, in
200 the sense that no IR has yet been generated to do the relevant
201 helper calls. The BB is scanned top to bottom and memory events
202 are added to the end of the list, merging with the most recent
203 notified event where possible (Dw immediately following Dr and
204 having the same size and EA can be merged).
weidendoa17f2a32006-03-20 10:27:30 +0000205
weidendo0a1951d2009-06-15 00:16:36 +0000206 This merging is done so that for architectures which have
207 load-op-store instructions (x86, amd64), the insn is treated as if
208 it makes just one memory reference (a modify), rather than two (a
209 read followed by a write at the same address).
210
211 At various points the list will need to be flushed, that is, IR
212 generated from it. That must happen before any possible exit from
213 the block (the end, or an IRStmt_Exit). Flushing also takes place
214 when there is no space to add a new event.
215
216 If we require the simulation statistics to be up to date with
217 respect to possible memory exceptions, then the list would have to
218 be flushed before each memory reference. That would however lose
219 performance by inhibiting event-merging during flushing.
220
221 Flushing the list consists of walking it start to end and emitting
222 instrumentation IR for each event, in the order in which they
223 appear. It may be possible to emit a single call for two adjacent
224 events in order to reduce the number of helper function calls made.
225 For example, it could well be profitable to handle two adjacent Ir
226 events with a single helper call. */
227
228typedef
229 IRExpr
230 IRAtom;
231
232typedef
233 enum {
234 Ev_Ir, // Instruction read
235 Ev_Dr, // Data read
236 Ev_Dw, // Data write
237 Ev_Dm, // Data modify (read then write)
weidendo320705f2010-07-02 19:56:23 +0000238 Ev_Bc, // branch conditional
239 Ev_Bi, // branch indirect (to unknown destination)
weidendoaeb86222010-06-09 22:33:02 +0000240 Ev_G // Global bus event
weidendo0a1951d2009-06-15 00:16:36 +0000241 }
242 EventTag;
243
244typedef
245 struct {
246 EventTag tag;
247 InstrInfo* inode;
248 union {
249 struct {
250 } Ir;
251 struct {
252 IRAtom* ea;
253 Int szB;
254 } Dr;
255 struct {
256 IRAtom* ea;
257 Int szB;
258 } Dw;
259 struct {
260 IRAtom* ea;
261 Int szB;
262 } Dm;
weidendo320705f2010-07-02 19:56:23 +0000263 struct {
264 IRAtom* taken; /* :: Ity_I1 */
265 } Bc;
266 struct {
267 IRAtom* dst;
268 } Bi;
weidendoaeb86222010-06-09 22:33:02 +0000269 struct {
270 } G;
weidendo0a1951d2009-06-15 00:16:36 +0000271 } Ev;
272 }
273 Event;
274
275static void init_Event ( Event* ev ) {
276 VG_(memset)(ev, 0, sizeof(Event));
weidendoa17f2a32006-03-20 10:27:30 +0000277}
278
weidendo0a1951d2009-06-15 00:16:36 +0000279static IRAtom* get_Event_dea ( Event* ev ) {
280 switch (ev->tag) {
281 case Ev_Dr: return ev->Ev.Dr.ea;
282 case Ev_Dw: return ev->Ev.Dw.ea;
283 case Ev_Dm: return ev->Ev.Dm.ea;
284 default: tl_assert(0);
285 }
286}
weidendoa17f2a32006-03-20 10:27:30 +0000287
weidendo0a1951d2009-06-15 00:16:36 +0000288static Int get_Event_dszB ( Event* ev ) {
289 switch (ev->tag) {
290 case Ev_Dr: return ev->Ev.Dr.szB;
291 case Ev_Dw: return ev->Ev.Dw.szB;
292 case Ev_Dm: return ev->Ev.Dm.szB;
293 default: tl_assert(0);
294 }
295}
296
297
298/* Up to this many unnotified events are allowed. Number is
299 arbitrary. Larger numbers allow more event merging to occur, but
300 potentially induce more spilling due to extending live ranges of
301 address temporaries. */
302#define N_EVENTS 16
303
304
305/* A struct which holds all the running state during instrumentation.
306 Mostly to avoid passing loads of parameters everywhere. */
307typedef struct {
308 /* The current outstanding-memory-event list. */
309 Event events[N_EVENTS];
310 Int events_used;
311
312 /* The array of InstrInfo's is part of BB struct. */
313 BB* bb;
314
315 /* BB seen before (ie. re-instrumentation) */
316 Bool seen_before;
317
318 /* Number InstrInfo bins 'used' so far. */
319 UInt ii_index;
320
321 // current offset of guest instructions from BB start
322 UInt instr_offset;
323
324 /* The output SB being constructed. */
325 IRSB* sbOut;
326} ClgState;
327
328
329static void showEvent ( Event* ev )
330{
331 switch (ev->tag) {
332 case Ev_Ir:
333 VG_(printf)("Ir (InstrInfo %p) at +%d\n",
334 ev->inode, ev->inode->instr_offset);
335 break;
336 case Ev_Dr:
337 VG_(printf)("Dr (InstrInfo %p) at +%d %d EA=",
338 ev->inode, ev->inode->instr_offset, ev->Ev.Dr.szB);
339 ppIRExpr(ev->Ev.Dr.ea);
340 VG_(printf)("\n");
341 break;
342 case Ev_Dw:
343 VG_(printf)("Dw (InstrInfo %p) at +%d %d EA=",
344 ev->inode, ev->inode->instr_offset, ev->Ev.Dw.szB);
345 ppIRExpr(ev->Ev.Dw.ea);
346 VG_(printf)("\n");
347 break;
348 case Ev_Dm:
349 VG_(printf)("Dm (InstrInfo %p) at +%d %d EA=",
350 ev->inode, ev->inode->instr_offset, ev->Ev.Dm.szB);
351 ppIRExpr(ev->Ev.Dm.ea);
352 VG_(printf)("\n");
353 break;
weidendo320705f2010-07-02 19:56:23 +0000354 case Ev_Bc:
355 VG_(printf)("Bc %p GA=", ev->inode);
356 ppIRExpr(ev->Ev.Bc.taken);
357 VG_(printf)("\n");
358 break;
359 case Ev_Bi:
360 VG_(printf)("Bi %p DST=", ev->inode);
361 ppIRExpr(ev->Ev.Bi.dst);
362 VG_(printf)("\n");
363 break;
weidendoaeb86222010-06-09 22:33:02 +0000364 case Ev_G:
365 VG_(printf)("G %p\n", ev->inode);
366 break;
weidendo0a1951d2009-06-15 00:16:36 +0000367 default:
368 tl_assert(0);
369 break;
370 }
371}
372
373/* Generate code for all outstanding memory events, and mark the queue
374 empty. Code is generated into cgs->sbOut, and this activity
375 'consumes' slots in cgs->bb. */
376
377static void flushEvents ( ClgState* clgs )
378{
379 Int i, regparms, inew;
florian25f6c572012-10-21 02:55:56 +0000380 const HChar* helperName;
weidendo0a1951d2009-06-15 00:16:36 +0000381 void* helperAddr;
382 IRExpr** argv;
383 IRExpr* i_node_expr;
384 IRDirty* di;
385 Event* ev;
386 Event* ev2;
387 Event* ev3;
388
389 if (!clgs->seen_before) {
390 // extend event sets as needed
391 // available sets: D0 Dr
392 for(i=0; i<clgs->events_used; i++) {
393 ev = &clgs->events[i];
394 switch(ev->tag) {
395 case Ev_Ir:
396 // Ir event always is first for a guest instruction
397 CLG_ASSERT(ev->inode->eventset == 0);
weidendo5bba5252010-06-09 22:32:53 +0000398 ev->inode->eventset = CLG_(sets).base;
weidendo0a1951d2009-06-15 00:16:36 +0000399 break;
400 case Ev_Dr:
weidendo320705f2010-07-02 19:56:23 +0000401 // extend event set by Dr counters
weidendo5bba5252010-06-09 22:32:53 +0000402 ev->inode->eventset = CLG_(add_event_group)(ev->inode->eventset,
403 EG_DR);
weidendo0a1951d2009-06-15 00:16:36 +0000404 break;
405 case Ev_Dw:
406 case Ev_Dm:
weidendo320705f2010-07-02 19:56:23 +0000407 // extend event set by Dw counters
weidendo5bba5252010-06-09 22:32:53 +0000408 ev->inode->eventset = CLG_(add_event_group)(ev->inode->eventset,
409 EG_DW);
weidendo0a1951d2009-06-15 00:16:36 +0000410 break;
weidendo320705f2010-07-02 19:56:23 +0000411 case Ev_Bc:
412 // extend event set by Bc counters
413 ev->inode->eventset = CLG_(add_event_group)(ev->inode->eventset,
414 EG_BC);
415 break;
416 case Ev_Bi:
417 // extend event set by Bi counters
418 ev->inode->eventset = CLG_(add_event_group)(ev->inode->eventset,
419 EG_BI);
420 break;
weidendoaeb86222010-06-09 22:33:02 +0000421 case Ev_G:
weidendo320705f2010-07-02 19:56:23 +0000422 // extend event set by Bus counter
weidendoaeb86222010-06-09 22:33:02 +0000423 ev->inode->eventset = CLG_(add_event_group)(ev->inode->eventset,
424 EG_BUS);
425 break;
weidendo0a1951d2009-06-15 00:16:36 +0000426 default:
427 tl_assert(0);
428 }
429 }
430 }
431
432 for(i = 0; i < clgs->events_used; i = inew) {
433
434 helperName = NULL;
435 helperAddr = NULL;
436 argv = NULL;
437 regparms = 0;
438
439 /* generate IR to notify event i and possibly the ones
440 immediately following it. */
441 tl_assert(i >= 0 && i < clgs->events_used);
442
443 ev = &clgs->events[i];
444 ev2 = ( i < clgs->events_used-1 ? &clgs->events[i+1] : NULL );
445 ev3 = ( i < clgs->events_used-2 ? &clgs->events[i+2] : NULL );
446
447 CLG_DEBUGIF(5) {
448 VG_(printf)(" flush ");
449 showEvent( ev );
450 }
451
452 i_node_expr = mkIRExpr_HWord( (HWord)ev->inode );
453
454 /* Decide on helper fn to call and args to pass it, and advance
455 i appropriately.
456 Dm events have same effect as Dw events */
457 switch (ev->tag) {
458 case Ev_Ir:
459 /* Merge an Ir with a following Dr. */
460 if (ev2 && ev2->tag == Ev_Dr) {
461 /* Why is this true? It's because we're merging an Ir
462 with a following Dr. The Ir derives from the
463 instruction's IMark and the Dr from data
464 references which follow it. In short it holds
465 because each insn starts with an IMark, hence an
466 Ev_Ir, and so these Dr must pertain to the
467 immediately preceding Ir. Same applies to analogous
468 assertions in the subsequent cases. */
469 tl_assert(ev2->inode == ev->inode);
470 helperName = CLG_(cachesim).log_1I1Dr_name;
471 helperAddr = CLG_(cachesim).log_1I1Dr;
472 argv = mkIRExprVec_3( i_node_expr,
473 get_Event_dea(ev2),
474 mkIRExpr_HWord( get_Event_dszB(ev2) ) );
475 regparms = 3;
476 inew = i+2;
477 }
478 /* Merge an Ir with a following Dw/Dm. */
479 else
480 if (ev2 && (ev2->tag == Ev_Dw || ev2->tag == Ev_Dm)) {
481 tl_assert(ev2->inode == ev->inode);
482 helperName = CLG_(cachesim).log_1I1Dw_name;
483 helperAddr = CLG_(cachesim).log_1I1Dw;
484 argv = mkIRExprVec_3( i_node_expr,
485 get_Event_dea(ev2),
486 mkIRExpr_HWord( get_Event_dszB(ev2) ) );
487 regparms = 3;
488 inew = i+2;
489 }
490 /* Merge an Ir with two following Irs. */
491 else
492 if (ev2 && ev3 && ev2->tag == Ev_Ir && ev3->tag == Ev_Ir) {
493 helperName = CLG_(cachesim).log_3I0D_name;
494 helperAddr = CLG_(cachesim).log_3I0D;
495 argv = mkIRExprVec_3( i_node_expr,
496 mkIRExpr_HWord( (HWord)ev2->inode ),
497 mkIRExpr_HWord( (HWord)ev3->inode ) );
498 regparms = 3;
499 inew = i+3;
500 }
501 /* Merge an Ir with one following Ir. */
502 else
503 if (ev2 && ev2->tag == Ev_Ir) {
504 helperName = CLG_(cachesim).log_2I0D_name;
505 helperAddr = CLG_(cachesim).log_2I0D;
506 argv = mkIRExprVec_2( i_node_expr,
507 mkIRExpr_HWord( (HWord)ev2->inode ) );
508 regparms = 2;
509 inew = i+2;
510 }
511 /* No merging possible; emit as-is. */
512 else {
513 helperName = CLG_(cachesim).log_1I0D_name;
514 helperAddr = CLG_(cachesim).log_1I0D;
515 argv = mkIRExprVec_1( i_node_expr );
516 regparms = 1;
517 inew = i+1;
518 }
519 break;
520 case Ev_Dr:
521 /* Data read or modify */
weidendoa17f2a32006-03-20 10:27:30 +0000522 helperName = CLG_(cachesim).log_0I1Dr_name;
523 helperAddr = CLG_(cachesim).log_0I1Dr;
weidendo0a1951d2009-06-15 00:16:36 +0000524 argv = mkIRExprVec_3( i_node_expr,
525 get_Event_dea(ev),
526 mkIRExpr_HWord( get_Event_dszB(ev) ) );
527 regparms = 3;
528 inew = i+1;
529 break;
530 case Ev_Dw:
531 case Ev_Dm:
532 /* Data write */
weidendoa17f2a32006-03-20 10:27:30 +0000533 helperName = CLG_(cachesim).log_0I1Dw_name;
534 helperAddr = CLG_(cachesim).log_0I1Dw;
weidendo0a1951d2009-06-15 00:16:36 +0000535 argv = mkIRExprVec_3( i_node_expr,
536 get_Event_dea(ev),
537 mkIRExpr_HWord( get_Event_dszB(ev) ) );
538 regparms = 3;
539 inew = i+1;
540 break;
weidendo320705f2010-07-02 19:56:23 +0000541 case Ev_Bc:
542 /* Conditional branch */
543 helperName = "log_cond_branch";
544 helperAddr = &log_cond_branch;
545 argv = mkIRExprVec_2( i_node_expr, ev->Ev.Bc.taken );
546 regparms = 2;
547 inew = i+1;
548 break;
549 case Ev_Bi:
550 /* Branch to an unknown destination */
551 helperName = "log_ind_branch";
552 helperAddr = &log_ind_branch;
553 argv = mkIRExprVec_2( i_node_expr, ev->Ev.Bi.dst );
554 regparms = 2;
555 inew = i+1;
556 break;
weidendoaeb86222010-06-09 22:33:02 +0000557 case Ev_G:
558 /* Global bus event (CAS, LOCK-prefix, LL-SC, etc) */
559 helperName = "log_global_event";
560 helperAddr = &log_global_event;
561 argv = mkIRExprVec_1( i_node_expr );
562 regparms = 1;
563 inew = i+1;
564 break;
weidendo0a1951d2009-06-15 00:16:36 +0000565 default:
566 tl_assert(0);
567 }
weidendoa17f2a32006-03-20 10:27:30 +0000568
weidendo0a1951d2009-06-15 00:16:36 +0000569 CLG_DEBUGIF(5) {
570 if (inew > i+1) {
571 VG_(printf)(" merge ");
572 showEvent( ev2 );
573 }
574 if (inew > i+2) {
575 VG_(printf)(" merge ");
576 showEvent( ev3 );
577 }
578 if (helperAddr)
579 VG_(printf)(" call %s (%p)\n",
580 helperName, helperAddr);
581 }
weidendoa17f2a32006-03-20 10:27:30 +0000582
weidendo0a1951d2009-06-15 00:16:36 +0000583 /* helper could be unset depending on the simulator used */
584 if (helperAddr == 0) continue;
weidendoa17f2a32006-03-20 10:27:30 +0000585
weidendo0a1951d2009-06-15 00:16:36 +0000586 /* Add the helper. */
587 tl_assert(helperName);
588 tl_assert(helperAddr);
589 tl_assert(argv);
590 di = unsafeIRDirty_0_N( regparms,
591 helperName, VG_(fnptr_to_fnentry)( helperAddr ),
592 argv );
593 addStmtToIRSB( clgs->sbOut, IRStmt_Dirty(di) );
weidendoa17f2a32006-03-20 10:27:30 +0000594 }
595
weidendo0a1951d2009-06-15 00:16:36 +0000596 clgs->events_used = 0;
597}
weidendoa17f2a32006-03-20 10:27:30 +0000598
weidendo0a1951d2009-06-15 00:16:36 +0000599static void addEvent_Ir ( ClgState* clgs, InstrInfo* inode )
600{
601 Event* evt;
602 tl_assert(clgs->seen_before || (inode->eventset == 0));
603 if (!CLG_(clo).simulate_cache) return;
weidendoa17f2a32006-03-20 10:27:30 +0000604
weidendo0a1951d2009-06-15 00:16:36 +0000605 if (clgs->events_used == N_EVENTS)
606 flushEvents(clgs);
607 tl_assert(clgs->events_used >= 0 && clgs->events_used < N_EVENTS);
608 evt = &clgs->events[clgs->events_used];
609 init_Event(evt);
610 evt->tag = Ev_Ir;
611 evt->inode = inode;
612 clgs->events_used++;
613}
weidendoa17f2a32006-03-20 10:27:30 +0000614
weidendo0a1951d2009-06-15 00:16:36 +0000615static
616void addEvent_Dr ( ClgState* clgs, InstrInfo* inode, Int datasize, IRAtom* ea )
617{
618 Event* evt;
619 tl_assert(isIRAtom(ea));
sewardjc4ebde32012-06-03 23:10:55 +0000620 tl_assert(datasize >= 1);
weidendo0a1951d2009-06-15 00:16:36 +0000621 if (!CLG_(clo).simulate_cache) return;
sewardjc4ebde32012-06-03 23:10:55 +0000622 tl_assert(datasize <= CLG_(min_line_size));
weidendoc8e76152006-05-27 15:30:58 +0000623
weidendo0a1951d2009-06-15 00:16:36 +0000624 if (clgs->events_used == N_EVENTS)
625 flushEvents(clgs);
626 tl_assert(clgs->events_used >= 0 && clgs->events_used < N_EVENTS);
627 evt = &clgs->events[clgs->events_used];
628 init_Event(evt);
629 evt->tag = Ev_Dr;
630 evt->inode = inode;
631 evt->Ev.Dr.szB = datasize;
632 evt->Ev.Dr.ea = ea;
633 clgs->events_used++;
634}
weidendoc8e76152006-05-27 15:30:58 +0000635
weidendo0a1951d2009-06-15 00:16:36 +0000636static
637void addEvent_Dw ( ClgState* clgs, InstrInfo* inode, Int datasize, IRAtom* ea )
638{
639 Event* lastEvt;
640 Event* evt;
641 tl_assert(isIRAtom(ea));
sewardjc4ebde32012-06-03 23:10:55 +0000642 tl_assert(datasize >= 1);
weidendo0a1951d2009-06-15 00:16:36 +0000643 if (!CLG_(clo).simulate_cache) return;
sewardjc4ebde32012-06-03 23:10:55 +0000644 tl_assert(datasize <= CLG_(min_line_size));
weidendoc8e76152006-05-27 15:30:58 +0000645
weidendo0a1951d2009-06-15 00:16:36 +0000646 /* Is it possible to merge this write with the preceding read? */
647 lastEvt = &clgs->events[clgs->events_used-1];
648 if (clgs->events_used > 0
649 && lastEvt->tag == Ev_Dr
650 && lastEvt->Ev.Dr.szB == datasize
651 && lastEvt->inode == inode
652 && eqIRAtom(lastEvt->Ev.Dr.ea, ea))
653 {
654 lastEvt->tag = Ev_Dm;
655 return;
656 }
weidendoc8e76152006-05-27 15:30:58 +0000657
weidendo0a1951d2009-06-15 00:16:36 +0000658 /* No. Add as normal. */
659 if (clgs->events_used == N_EVENTS)
660 flushEvents(clgs);
661 tl_assert(clgs->events_used >= 0 && clgs->events_used < N_EVENTS);
662 evt = &clgs->events[clgs->events_used];
663 init_Event(evt);
664 evt->tag = Ev_Dw;
665 evt->inode = inode;
666 evt->Ev.Dw.szB = datasize;
667 evt->Ev.Dw.ea = ea;
668 clgs->events_used++;
669}
670
weidendoaeb86222010-06-09 22:33:02 +0000671static
weidendo320705f2010-07-02 19:56:23 +0000672void addEvent_Bc ( ClgState* clgs, InstrInfo* inode, IRAtom* guard )
673{
674 Event* evt;
675 tl_assert(isIRAtom(guard));
676 tl_assert(typeOfIRExpr(clgs->sbOut->tyenv, guard)
677 == (sizeof(HWord)==4 ? Ity_I32 : Ity_I64));
678 if (!CLG_(clo).simulate_branch) return;
679
680 if (clgs->events_used == N_EVENTS)
681 flushEvents(clgs);
682 tl_assert(clgs->events_used >= 0 && clgs->events_used < N_EVENTS);
683 evt = &clgs->events[clgs->events_used];
684 init_Event(evt);
685 evt->tag = Ev_Bc;
686 evt->inode = inode;
687 evt->Ev.Bc.taken = guard;
688 clgs->events_used++;
689}
690
691static
692void addEvent_Bi ( ClgState* clgs, InstrInfo* inode, IRAtom* whereTo )
693{
694 Event* evt;
695 tl_assert(isIRAtom(whereTo));
696 tl_assert(typeOfIRExpr(clgs->sbOut->tyenv, whereTo)
697 == (sizeof(HWord)==4 ? Ity_I32 : Ity_I64));
698 if (!CLG_(clo).simulate_branch) return;
699
700 if (clgs->events_used == N_EVENTS)
701 flushEvents(clgs);
702 tl_assert(clgs->events_used >= 0 && clgs->events_used < N_EVENTS);
703 evt = &clgs->events[clgs->events_used];
704 init_Event(evt);
705 evt->tag = Ev_Bi;
706 evt->inode = inode;
707 evt->Ev.Bi.dst = whereTo;
708 clgs->events_used++;
709}
710
711static
weidendoaeb86222010-06-09 22:33:02 +0000712void addEvent_G ( ClgState* clgs, InstrInfo* inode )
713{
714 Event* evt;
715 if (!CLG_(clo).collect_bus) return;
weidendo320705f2010-07-02 19:56:23 +0000716
weidendoaeb86222010-06-09 22:33:02 +0000717 if (clgs->events_used == N_EVENTS)
718 flushEvents(clgs);
719 tl_assert(clgs->events_used >= 0 && clgs->events_used < N_EVENTS);
720 evt = &clgs->events[clgs->events_used];
721 init_Event(evt);
722 evt->tag = Ev_G;
723 evt->inode = inode;
724 clgs->events_used++;
725}
726
weidendo0a1951d2009-06-15 00:16:36 +0000727/* Initialise or check (if already seen before) an InstrInfo for next insn.
728 We only can set instr_offset/instr_size here. The required event set and
729 resulting cost offset depend on events (Ir/Dr/Dw/Dm) in guest
730 instructions. The event set is extended as required on flush of the event
731 queue (when Dm events were determined), cost offsets are determined at
732 end of BB instrumentation. */
733static
734InstrInfo* next_InstrInfo ( ClgState* clgs, UInt instr_size )
735{
736 InstrInfo* ii;
737 tl_assert(clgs->ii_index >= 0);
738 tl_assert(clgs->ii_index < clgs->bb->instr_count);
739 ii = &clgs->bb->instr[ clgs->ii_index ];
740
741 if (clgs->seen_before) {
742 CLG_ASSERT(ii->instr_offset == clgs->instr_offset);
743 CLG_ASSERT(ii->instr_size == instr_size);
weidendoa17f2a32006-03-20 10:27:30 +0000744 }
745 else {
weidendo0a1951d2009-06-15 00:16:36 +0000746 ii->instr_offset = clgs->instr_offset;
747 ii->instr_size = instr_size;
748 ii->cost_offset = 0;
749 ii->eventset = 0;
weidendoa17f2a32006-03-20 10:27:30 +0000750 }
751
weidendo0a1951d2009-06-15 00:16:36 +0000752 clgs->ii_index++;
753 clgs->instr_offset += instr_size;
754 CLG_(stat).distinct_instrs++;
weidendoa17f2a32006-03-20 10:27:30 +0000755
weidendo0a1951d2009-06-15 00:16:36 +0000756 return ii;
weidendoa17f2a32006-03-20 10:27:30 +0000757}
758
weidendo0a1951d2009-06-15 00:16:36 +0000759// return total number of cost values needed for this BB
760static
761UInt update_cost_offsets( ClgState* clgs )
762{
763 Int i;
764 InstrInfo* ii;
765 UInt cost_offset = 0;
766
767 CLG_ASSERT(clgs->bb->instr_count == clgs->ii_index);
768 for(i=0; i<clgs->ii_index; i++) {
769 ii = &clgs->bb->instr[i];
770 if (clgs->seen_before) {
771 CLG_ASSERT(ii->cost_offset == cost_offset);
772 } else
773 ii->cost_offset = cost_offset;
774 cost_offset += ii->eventset ? ii->eventset->size : 0;
775 }
776
777 return cost_offset;
778}
779
780/*------------------------------------------------------------*/
781/*--- Instrumentation ---*/
782/*------------------------------------------------------------*/
783
weidendoa17f2a32006-03-20 10:27:30 +0000784#if defined(VG_BIGENDIAN)
785# define CLGEndness Iend_BE
786#elif defined(VG_LITTLEENDIAN)
787# define CLGEndness Iend_LE
788#else
789# error "Unknown endianness"
790#endif
791
792static
793Addr IRConst2Addr(IRConst* con)
794{
795 Addr addr;
796
797 if (sizeof(Addr) == 4) {
798 CLG_ASSERT( con->tag == Ico_U32 );
799 addr = con->Ico.U32;
800 }
801 else if (sizeof(Addr) == 8) {
802 CLG_ASSERT( con->tag == Ico_U64 );
803 addr = con->Ico.U64;
804 }
805 else
806 VG_(tool_panic)("Callgrind: invalid Addr type");
807
808 return addr;
809}
810
811/* First pass over a BB to instrument, counting instructions and jumps
812 * This is needed for the size of the BB struct to allocate
813 *
814 * Called from CLG_(get_bb)
815 */
weidendo0a1951d2009-06-15 00:16:36 +0000816void CLG_(collectBlockInfo)(IRSB* sbIn,
weidendoa17f2a32006-03-20 10:27:30 +0000817 /*INOUT*/ UInt* instrs,
818 /*INOUT*/ UInt* cjmps,
819 /*INOUT*/ Bool* cjmp_inverted)
820{
821 Int i;
822 IRStmt* st;
823 Addr instrAddr =0, jumpDst;
824 UInt instrLen = 0;
825 Bool toNextInstr = False;
826
827 // Ist_Exit has to be ignored in preamble code, before first IMark:
828 // preamble code is added by VEX for self modifying code, and has
829 // nothing to do with client code
830 Bool inPreamble = True;
831
weidendo0a1951d2009-06-15 00:16:36 +0000832 if (!sbIn) return;
weidendoa17f2a32006-03-20 10:27:30 +0000833
weidendo0a1951d2009-06-15 00:16:36 +0000834 for (i = 0; i < sbIn->stmts_used; i++) {
835 st = sbIn->stmts[i];
weidendoa17f2a32006-03-20 10:27:30 +0000836 if (Ist_IMark == st->tag) {
837 inPreamble = False;
838
839 instrAddr = (Addr)ULong_to_Ptr(st->Ist.IMark.addr);
840 instrLen = st->Ist.IMark.len;
841
842 (*instrs)++;
843 toNextInstr = False;
844 }
845 if (inPreamble) continue;
846 if (Ist_Exit == st->tag) {
847 jumpDst = IRConst2Addr(st->Ist.Exit.dst);
848 toNextInstr = (jumpDst == instrAddr + instrLen);
weidendo0a1951d2009-06-15 00:16:36 +0000849
weidendoa17f2a32006-03-20 10:27:30 +0000850 (*cjmps)++;
851 }
852 }
853
854 /* if the last instructions of BB conditionally jumps to next instruction
855 * (= first instruction of next BB in memory), this is a inverted by VEX.
856 */
857 *cjmp_inverted = toNextInstr;
858}
859
860static
sewardj0b9d74a2006-12-24 02:24:11 +0000861void addConstMemStoreStmt( IRSB* bbOut, UWord addr, UInt val, IRType hWordTy)
weidendoa17f2a32006-03-20 10:27:30 +0000862{
sewardj0b9d74a2006-12-24 02:24:11 +0000863 addStmtToIRSB( bbOut,
weidendoa17f2a32006-03-20 10:27:30 +0000864 IRStmt_Store(CLGEndness,
865 IRExpr_Const(hWordTy == Ity_I32 ?
866 IRConst_U32( addr ) :
867 IRConst_U64( addr )),
868 IRExpr_Const(IRConst_U32(val)) ));
869}
870
weidendo0a1951d2009-06-15 00:16:36 +0000871
872/* add helper call to setup_bbcc, with pointer to BB struct as argument
873 *
874 * precondition for setup_bbcc:
875 * - jmps_passed has number of cond.jumps passed in last executed BB
876 * - current_bbcc has a pointer to the BBCC of the last executed BB
877 * Thus, if bbcc_jmpkind is != -1 (JmpNone),
878 * current_bbcc->bb->jmp_addr
879 * gives the address of the jump source.
880 *
881 * the setup does 2 things:
882 * - trace call:
883 * * Unwind own call stack, i.e sync our ESP with real ESP
884 * This is for ESP manipulation (longjmps, C++ exec handling) and RET
885 * * For CALLs or JMPs crossing objects, record call arg +
886 * push are on own call stack
887 *
888 * - prepare for cache log functions:
889 * set current_bbcc to BBCC that gets the costs for this BB execution
890 * attached
891 */
892static
893void addBBSetupCall(ClgState* clgs)
894{
895 IRDirty* di;
896 IRExpr *arg1, **argv;
897
898 arg1 = mkIRExpr_HWord( (HWord)clgs->bb );
899 argv = mkIRExprVec_1(arg1);
900 di = unsafeIRDirty_0_N( 1, "setup_bbcc",
901 VG_(fnptr_to_fnentry)( & CLG_(setup_bbcc) ),
902 argv);
903 addStmtToIRSB( clgs->sbOut, IRStmt_Dirty(di) );
904}
905
906
weidendoa17f2a32006-03-20 10:27:30 +0000907static
sewardj0b9d74a2006-12-24 02:24:11 +0000908IRSB* CLG_(instrument)( VgCallbackClosure* closure,
weidendo0a1951d2009-06-15 00:16:36 +0000909 IRSB* sbIn,
weidendoa17f2a32006-03-20 10:27:30 +0000910 VexGuestLayout* layout,
911 VexGuestExtents* vge,
florianca503be2012-10-07 21:59:42 +0000912 VexArchInfo* archinfo_host,
weidendoa17f2a32006-03-20 10:27:30 +0000913 IRType gWordTy, IRType hWordTy )
914{
sewardj6ab7f2d2011-11-08 19:32:57 +0000915 Int i;
weidendo0a1951d2009-06-15 00:16:36 +0000916 IRStmt* st;
917 Addr origAddr;
918 InstrInfo* curr_inode = NULL;
919 ClgState clgs;
920 UInt cJumps = 0;
weidendoa17f2a32006-03-20 10:27:30 +0000921
weidendoa17f2a32006-03-20 10:27:30 +0000922
923 if (gWordTy != hWordTy) {
924 /* We don't currently support this case. */
925 VG_(tool_panic)("host/guest word size mismatch");
926 }
927
928 // No instrumentation if it is switched off
929 if (! CLG_(instrument_state)) {
barta0b6b2c2008-07-07 06:49:24 +0000930 CLG_DEBUG(5, "instrument(BB %#lx) [Instrumentation OFF]\n",
weidendoa17f2a32006-03-20 10:27:30 +0000931 (Addr)closure->readdr);
weidendo0a1951d2009-06-15 00:16:36 +0000932 return sbIn;
weidendoa17f2a32006-03-20 10:27:30 +0000933 }
934
barta0b6b2c2008-07-07 06:49:24 +0000935 CLG_DEBUG(3, "+ instrument(BB %#lx)\n", (Addr)closure->readdr);
weidendoa17f2a32006-03-20 10:27:30 +0000936
sewardj0b9d74a2006-12-24 02:24:11 +0000937 /* Set up SB for instrumented IR */
weidendo0a1951d2009-06-15 00:16:36 +0000938 clgs.sbOut = deepCopyIRSBExceptStmts(sbIn);
weidendoa17f2a32006-03-20 10:27:30 +0000939
940 // Copy verbatim any IR preamble preceding the first IMark
941 i = 0;
weidendo0a1951d2009-06-15 00:16:36 +0000942 while (i < sbIn->stmts_used && sbIn->stmts[i]->tag != Ist_IMark) {
943 addStmtToIRSB( clgs.sbOut, sbIn->stmts[i] );
weidendoa17f2a32006-03-20 10:27:30 +0000944 i++;
945 }
946
947 // Get the first statement, and origAddr from it
weidendo0a1951d2009-06-15 00:16:36 +0000948 CLG_ASSERT(sbIn->stmts_used >0);
949 CLG_ASSERT(i < sbIn->stmts_used);
950 st = sbIn->stmts[i];
weidendoa17f2a32006-03-20 10:27:30 +0000951 CLG_ASSERT(Ist_IMark == st->tag);
weidendo0a1951d2009-06-15 00:16:36 +0000952
sewardj6ab7f2d2011-11-08 19:32:57 +0000953 origAddr = (Addr)st->Ist.IMark.addr + (Addr)st->Ist.IMark.delta;
954 CLG_ASSERT(origAddr == st->Ist.IMark.addr
955 + st->Ist.IMark.delta); // XXX: check no overflow
weidendoa17f2a32006-03-20 10:27:30 +0000956
weidendo0a1951d2009-06-15 00:16:36 +0000957 /* Get BB struct (creating if necessary).
weidendoa17f2a32006-03-20 10:27:30 +0000958 * JS: The hash table is keyed with orig_addr_noredir -- important!
959 * JW: Why? If it is because of different chasing of the redirection,
960 * this is not needed, as chasing is switched off in callgrind
961 */
weidendo0a1951d2009-06-15 00:16:36 +0000962 clgs.bb = CLG_(get_bb)(origAddr, sbIn, &(clgs.seen_before));
weidendoa17f2a32006-03-20 10:27:30 +0000963
weidendo0a1951d2009-06-15 00:16:36 +0000964 addBBSetupCall(&clgs);
weidendoa17f2a32006-03-20 10:27:30 +0000965
weidendo0a1951d2009-06-15 00:16:36 +0000966 // Set up running state
967 clgs.events_used = 0;
968 clgs.ii_index = 0;
969 clgs.instr_offset = 0;
weidendoa17f2a32006-03-20 10:27:30 +0000970
weidendo0a1951d2009-06-15 00:16:36 +0000971 for (/*use current i*/; i < sbIn->stmts_used; i++) {
weidendoa17f2a32006-03-20 10:27:30 +0000972
weidendo0a1951d2009-06-15 00:16:36 +0000973 st = sbIn->stmts[i];
974 CLG_ASSERT(isFlatIRStmt(st));
weidendoa17f2a32006-03-20 10:27:30 +0000975
weidendo0a1951d2009-06-15 00:16:36 +0000976 switch (st->tag) {
977 case Ist_NoOp:
978 case Ist_AbiHint:
979 case Ist_Put:
980 case Ist_PutI:
981 case Ist_MBE:
982 break;
weidendoa17f2a32006-03-20 10:27:30 +0000983
weidendo0a1951d2009-06-15 00:16:36 +0000984 case Ist_IMark: {
sewardj6ab7f2d2011-11-08 19:32:57 +0000985 Addr64 cia = st->Ist.IMark.addr + st->Ist.IMark.delta;
986 Int isize = st->Ist.IMark.len;
weidendo320705f2010-07-02 19:56:23 +0000987 CLG_ASSERT(clgs.instr_offset == (Addr)cia - origAddr);
weidendo0a1951d2009-06-15 00:16:36 +0000988 // If Vex fails to decode an instruction, the size will be zero.
989 // Pretend otherwise.
990 if (isize == 0) isize = VG_MIN_INSTR_SZB;
weidendoa17f2a32006-03-20 10:27:30 +0000991
weidendo0a1951d2009-06-15 00:16:36 +0000992 // Sanity-check size.
993 tl_assert( (VG_MIN_INSTR_SZB <= isize && isize <= VG_MAX_INSTR_SZB)
994 || VG_CLREQ_SZB == isize );
weidendoa17f2a32006-03-20 10:27:30 +0000995
weidendo0a1951d2009-06-15 00:16:36 +0000996 // Init the inode, record it as the current one.
997 // Subsequent Dr/Dw/Dm events from the same instruction will
998 // also use it.
999 curr_inode = next_InstrInfo (&clgs, isize);
weidendoa17f2a32006-03-20 10:27:30 +00001000
weidendo0a1951d2009-06-15 00:16:36 +00001001 addEvent_Ir( &clgs, curr_inode );
1002 break;
1003 }
weidendoa17f2a32006-03-20 10:27:30 +00001004
weidendo0a1951d2009-06-15 00:16:36 +00001005 case Ist_WrTmp: {
1006 IRExpr* data = st->Ist.WrTmp.data;
1007 if (data->tag == Iex_Load) {
1008 IRExpr* aexpr = data->Iex.Load.addr;
1009 // Note also, endianness info is ignored. I guess
1010 // that's not interesting.
1011 addEvent_Dr( &clgs, curr_inode,
1012 sizeofIRType(data->Iex.Load.ty), aexpr );
1013 }
1014 break;
1015 }
weidendoa17f2a32006-03-20 10:27:30 +00001016
weidendo0a1951d2009-06-15 00:16:36 +00001017 case Ist_Store: {
1018 IRExpr* data = st->Ist.Store.data;
1019 IRExpr* aexpr = st->Ist.Store.addr;
1020 addEvent_Dw( &clgs, curr_inode,
1021 sizeofIRType(typeOfIRExpr(sbIn->tyenv, data)), aexpr );
1022 break;
1023 }
weidendoa17f2a32006-03-20 10:27:30 +00001024
weidendo0a1951d2009-06-15 00:16:36 +00001025 case Ist_Dirty: {
1026 Int dataSize;
1027 IRDirty* d = st->Ist.Dirty.details;
1028 if (d->mFx != Ifx_None) {
1029 /* This dirty helper accesses memory. Collect the details. */
1030 tl_assert(d->mAddr != NULL);
1031 tl_assert(d->mSize != 0);
1032 dataSize = d->mSize;
1033 // Large (eg. 28B, 108B, 512B on x86) data-sized
1034 // instructions will be done inaccurately, but they're
1035 // very rare and this avoids errors from hitting more
1036 // than two cache lines in the simulation.
sewardjc4ebde32012-06-03 23:10:55 +00001037 if (CLG_(clo).simulate_cache && dataSize > CLG_(min_line_size))
1038 dataSize = CLG_(min_line_size);
weidendo0a1951d2009-06-15 00:16:36 +00001039 if (d->mFx == Ifx_Read || d->mFx == Ifx_Modify)
1040 addEvent_Dr( &clgs, curr_inode, dataSize, d->mAddr );
1041 if (d->mFx == Ifx_Write || d->mFx == Ifx_Modify)
1042 addEvent_Dw( &clgs, curr_inode, dataSize, d->mAddr );
1043 } else {
1044 tl_assert(d->mAddr == NULL);
1045 tl_assert(d->mSize == 0);
1046 }
1047 break;
1048 }
weidendoa17f2a32006-03-20 10:27:30 +00001049
sewardj1c0ce7a2009-07-01 08:10:49 +00001050 case Ist_CAS: {
1051 /* We treat it as a read and a write of the location. I
1052 think that is the same behaviour as it was before IRCAS
1053 was introduced, since prior to that point, the Vex
1054 front ends would translate a lock-prefixed instruction
1055 into a (normal) read followed by a (normal) write. */
1056 Int dataSize;
1057 IRCAS* cas = st->Ist.CAS.details;
1058 CLG_ASSERT(cas->addr && isIRAtom(cas->addr));
1059 CLG_ASSERT(cas->dataLo);
1060 dataSize = sizeofIRType(typeOfIRExpr(sbIn->tyenv, cas->dataLo));
1061 if (cas->dataHi != NULL)
1062 dataSize *= 2; /* since this is a doubleword-cas */
1063 addEvent_Dr( &clgs, curr_inode, dataSize, cas->addr );
1064 addEvent_Dw( &clgs, curr_inode, dataSize, cas->addr );
weidendoaeb86222010-06-09 22:33:02 +00001065 addEvent_G( &clgs, curr_inode );
sewardj1c0ce7a2009-07-01 08:10:49 +00001066 break;
1067 }
sewardjdb5907d2009-11-26 17:20:21 +00001068
1069 case Ist_LLSC: {
1070 IRType dataTy;
1071 if (st->Ist.LLSC.storedata == NULL) {
1072 /* LL */
1073 dataTy = typeOfIRTemp(sbIn->tyenv, st->Ist.LLSC.result);
1074 addEvent_Dr( &clgs, curr_inode,
1075 sizeofIRType(dataTy), st->Ist.LLSC.addr );
petarjad1162a2012-11-23 00:01:36 +00001076 /* flush events before LL, should help SC to succeed */
1077 flushEvents( &clgs );
sewardjdb5907d2009-11-26 17:20:21 +00001078 } else {
1079 /* SC */
1080 dataTy = typeOfIRExpr(sbIn->tyenv, st->Ist.LLSC.storedata);
1081 addEvent_Dw( &clgs, curr_inode,
1082 sizeofIRType(dataTy), st->Ist.LLSC.addr );
weidendoaeb86222010-06-09 22:33:02 +00001083 /* I don't know whether the global-bus-lock cost should
1084 be attributed to the LL or the SC, but it doesn't
1085 really matter since they always have to be used in
1086 pairs anyway. Hence put it (quite arbitrarily) on
1087 the SC. */
1088 addEvent_G( &clgs, curr_inode );
sewardjdb5907d2009-11-26 17:20:21 +00001089 }
1090 break;
1091 }
1092
1093 case Ist_Exit: {
weidendo320705f2010-07-02 19:56:23 +00001094 Bool guest_exit, inverted;
1095
1096 /* VEX code generation sometimes inverts conditional branches.
1097 * As Callgrind counts (conditional) jumps, it has to correct
1098 * inversions. The heuristic is the following:
1099 * (1) Callgrind switches off SB chasing and unrolling, and
1100 * therefore it assumes that a candidate for inversion only is
1101 * the last conditional branch in an SB.
1102 * (2) inversion is assumed if the branch jumps to the address of
1103 * the next guest instruction in memory.
1104 * This heuristic is precalculated in CLG_(collectBlockInfo)().
1105 *
1106 * Branching behavior is also used for branch prediction. Note that
1107 * above heuristic is different from what Cachegrind does.
1108 * Cachegrind uses (2) for all branches.
1109 */
1110 if (cJumps+1 == clgs.bb->cjmp_count)
1111 inverted = clgs.bb->cjmp_inverted;
1112 else
1113 inverted = False;
1114
1115 // call branch predictor only if this is a branch in guest code
1116 guest_exit = (st->Ist.Exit.jk == Ijk_Boring) ||
1117 (st->Ist.Exit.jk == Ijk_Call) ||
1118 (st->Ist.Exit.jk == Ijk_Ret);
1119
1120 if (guest_exit) {
1121 /* Stuff to widen the guard expression to a host word, so
1122 we can pass it to the branch predictor simulation
1123 functions easily. */
1124 IRType tyW = hWordTy;
1125 IROp widen = tyW==Ity_I32 ? Iop_1Uto32 : Iop_1Uto64;
1126 IROp opXOR = tyW==Ity_I32 ? Iop_Xor32 : Iop_Xor64;
1127 IRTemp guard1 = newIRTemp(clgs.sbOut->tyenv, Ity_I1);
1128 IRTemp guardW = newIRTemp(clgs.sbOut->tyenv, tyW);
1129 IRTemp guard = newIRTemp(clgs.sbOut->tyenv, tyW);
1130 IRExpr* one = tyW==Ity_I32 ? IRExpr_Const(IRConst_U32(1))
1131 : IRExpr_Const(IRConst_U64(1));
1132
1133 /* Widen the guard expression. */
1134 addStmtToIRSB( clgs.sbOut,
1135 IRStmt_WrTmp( guard1, st->Ist.Exit.guard ));
1136 addStmtToIRSB( clgs.sbOut,
1137 IRStmt_WrTmp( guardW,
1138 IRExpr_Unop(widen,
1139 IRExpr_RdTmp(guard1))) );
1140 /* If the exit is inverted, invert the sense of the guard. */
1141 addStmtToIRSB(
1142 clgs.sbOut,
1143 IRStmt_WrTmp(
1144 guard,
1145 inverted ? IRExpr_Binop(opXOR, IRExpr_RdTmp(guardW), one)
1146 : IRExpr_RdTmp(guardW)
1147 ));
1148 /* And post the event. */
1149 addEvent_Bc( &clgs, curr_inode, IRExpr_RdTmp(guard) );
1150 }
weidendoa17f2a32006-03-20 10:27:30 +00001151
weidendo0a1951d2009-06-15 00:16:36 +00001152 /* We may never reach the next statement, so need to flush
1153 all outstanding transactions now. */
1154 flushEvents( &clgs );
weidendoa17f2a32006-03-20 10:27:30 +00001155
weidendo0a1951d2009-06-15 00:16:36 +00001156 CLG_ASSERT(clgs.ii_index>0);
1157 if (!clgs.seen_before) {
weidendo28a23c02011-11-14 21:16:25 +00001158 ClgJumpKind jk;
1159
1160 if (st->Ist.Exit.jk == Ijk_Call) jk = jk_Call;
1161 else if (st->Ist.Exit.jk == Ijk_Ret) jk = jk_Return;
1162 else {
1163 if (IRConst2Addr(st->Ist.Exit.dst) ==
1164 origAddr + curr_inode->instr_offset + curr_inode->instr_size)
1165 jk = jk_None;
1166 else
1167 jk = jk_Jump;
1168 }
1169
1170 clgs.bb->jmp[cJumps].instr = clgs.ii_index-1;
1171 clgs.bb->jmp[cJumps].jmpkind = jk;
weidendo0a1951d2009-06-15 00:16:36 +00001172 }
1173
1174 /* Update global variable jmps_passed before the jump
1175 * A correction is needed if VEX inverted the last jump condition
1176 */
weidendo0a1951d2009-06-15 00:16:36 +00001177 addConstMemStoreStmt( clgs.sbOut,
1178 (UWord) &CLG_(current_state).jmps_passed,
weidendo320705f2010-07-02 19:56:23 +00001179 inverted ? cJumps+1 : cJumps, hWordTy);
weidendo0a1951d2009-06-15 00:16:36 +00001180 cJumps++;
1181
1182 break;
1183 }
1184
1185 default:
1186 tl_assert(0);
1187 break;
1188 }
1189
1190 /* Copy the original statement */
1191 addStmtToIRSB( clgs.sbOut, st );
1192
1193 CLG_DEBUGIF(5) {
1194 VG_(printf)(" pass ");
1195 ppIRStmt(st);
1196 VG_(printf)("\n");
1197 }
weidendoa17f2a32006-03-20 10:27:30 +00001198 }
weidendoa17f2a32006-03-20 10:27:30 +00001199
weidendo320705f2010-07-02 19:56:23 +00001200 /* Deal with branches to unknown destinations. Except ignore ones
1201 which are function returns as we assume the return stack
1202 predictor never mispredicts. */
weidendocb3ccf32010-07-07 18:51:59 +00001203 if ((sbIn->jumpkind == Ijk_Boring) || (sbIn->jumpkind == Ijk_Call)) {
weidendo320705f2010-07-02 19:56:23 +00001204 if (0) { ppIRExpr( sbIn->next ); VG_(printf)("\n"); }
1205 switch (sbIn->next->tag) {
1206 case Iex_Const:
1207 break; /* boring - branch to known address */
1208 case Iex_RdTmp:
1209 /* looks like an indirect branch (branch to unknown) */
1210 addEvent_Bi( &clgs, curr_inode, sbIn->next );
1211 break;
1212 default:
1213 /* shouldn't happen - if the incoming IR is properly
1214 flattened, should only have tmp and const cases to
1215 consider. */
1216 tl_assert(0);
1217 }
1218 }
1219
weidendo0a1951d2009-06-15 00:16:36 +00001220 /* At the end of the bb. Flush outstandings. */
1221 flushEvents( &clgs );
1222
1223 /* Always update global variable jmps_passed at end of bb.
weidendoa17f2a32006-03-20 10:27:30 +00001224 * A correction is needed if VEX inverted the last jump condition
1225 */
weidendo0a1951d2009-06-15 00:16:36 +00001226 {
1227 UInt jmps_passed = cJumps;
1228 if (clgs.bb->cjmp_inverted) jmps_passed--;
1229 addConstMemStoreStmt( clgs.sbOut,
1230 (UWord) &CLG_(current_state).jmps_passed,
1231 jmps_passed, hWordTy);
1232 }
1233 CLG_ASSERT(clgs.bb->cjmp_count == cJumps);
1234 CLG_ASSERT(clgs.bb->instr_count = clgs.ii_index);
weidendoa17f2a32006-03-20 10:27:30 +00001235
weidendo28a23c02011-11-14 21:16:25 +00001236 /* Info for final exit from BB */
1237 {
1238 ClgJumpKind jk;
1239
1240 if (sbIn->jumpkind == Ijk_Call) jk = jk_Call;
1241 else if (sbIn->jumpkind == Ijk_Ret) jk = jk_Return;
1242 else {
1243 jk = jk_Jump;
1244 if ((sbIn->next->tag == Iex_Const) &&
1245 (IRConst2Addr(sbIn->next->Iex.Const.con) ==
1246 origAddr + clgs.instr_offset))
1247 jk = jk_None;
1248 }
1249 clgs.bb->jmp[cJumps].jmpkind = jk;
1250 /* Instruction index of the call/ret at BB end
1251 * (it is wrong for fall-through, but does not matter) */
1252 clgs.bb->jmp[cJumps].instr = clgs.ii_index-1;
1253 }
1254
1255 /* swap information of last exit with final exit if inverted */
1256 if (clgs.bb->cjmp_inverted) {
1257 ClgJumpKind jk;
1258 UInt instr;
1259
1260 jk = clgs.bb->jmp[cJumps].jmpkind;
1261 clgs.bb->jmp[cJumps].jmpkind = clgs.bb->jmp[cJumps-1].jmpkind;
1262 clgs.bb->jmp[cJumps-1].jmpkind = jk;
1263 instr = clgs.bb->jmp[cJumps].instr;
1264 clgs.bb->jmp[cJumps].instr = clgs.bb->jmp[cJumps-1].instr;
1265 clgs.bb->jmp[cJumps-1].instr = instr;
1266 }
weidendoa17f2a32006-03-20 10:27:30 +00001267
weidendo0a1951d2009-06-15 00:16:36 +00001268 if (clgs.seen_before) {
1269 CLG_ASSERT(clgs.bb->cost_count == update_cost_offsets(&clgs));
1270 CLG_ASSERT(clgs.bb->instr_len = clgs.instr_offset);
weidendoa17f2a32006-03-20 10:27:30 +00001271 }
1272 else {
weidendo0a1951d2009-06-15 00:16:36 +00001273 clgs.bb->cost_count = update_cost_offsets(&clgs);
1274 clgs.bb->instr_len = clgs.instr_offset;
weidendoa17f2a32006-03-20 10:27:30 +00001275 }
weidendo0a1951d2009-06-15 00:16:36 +00001276
barta0b6b2c2008-07-07 06:49:24 +00001277 CLG_DEBUG(3, "- instrument(BB %#lx): byteLen %u, CJumps %u, CostLen %u\n",
weidendo0a1951d2009-06-15 00:16:36 +00001278 origAddr, clgs.bb->instr_len,
1279 clgs.bb->cjmp_count, clgs.bb->cost_count);
weidendoa17f2a32006-03-20 10:27:30 +00001280 if (cJumps>0) {
1281 CLG_DEBUG(3, " [ ");
1282 for (i=0;i<cJumps;i++)
weidendo0a1951d2009-06-15 00:16:36 +00001283 CLG_DEBUG(3, "%d ", clgs.bb->jmp[i].instr);
1284 CLG_DEBUG(3, "], last inverted: %s \n",
1285 clgs.bb->cjmp_inverted ? "yes":"no");
weidendoa17f2a32006-03-20 10:27:30 +00001286 }
1287
weidendo0a1951d2009-06-15 00:16:36 +00001288 return clgs.sbOut;
weidendoa17f2a32006-03-20 10:27:30 +00001289}
1290
1291/*--------------------------------------------------------------------*/
1292/*--- Discarding BB info ---*/
1293/*--------------------------------------------------------------------*/
1294
1295// Called when a translation is removed from the translation cache for
1296// any reason at all: to free up space, because the guest code was
1297// unmapped or modified, or for any arbitrary reason.
1298static
sewardj0b9d74a2006-12-24 02:24:11 +00001299void clg_discard_superblock_info ( Addr64 orig_addr64, VexGuestExtents vge )
weidendoa17f2a32006-03-20 10:27:30 +00001300{
1301 Addr orig_addr = (Addr)orig_addr64;
1302
1303 tl_assert(vge.n_used > 0);
1304
1305 if (0)
sewardj0b9d74a2006-12-24 02:24:11 +00001306 VG_(printf)( "discard_superblock_info: %p, %p, %llu\n",
weidendoa17f2a32006-03-20 10:27:30 +00001307 (void*)(Addr)orig_addr,
1308 (void*)(Addr)vge.base[0], (ULong)vge.len[0]);
1309
1310 // Get BB info, remove from table, free BB info. Simple! Note that we
1311 // use orig_addr, not the first instruction address in vge.
1312 CLG_(delete_bb)(orig_addr);
1313}
1314
1315
1316/*------------------------------------------------------------*/
1317/*--- CLG_(fini)() and related function ---*/
1318/*------------------------------------------------------------*/
1319
1320
1321
1322static void zero_thread_cost(thread_info* t)
1323{
1324 Int i;
1325
1326 for(i = 0; i < CLG_(current_call_stack).sp; i++) {
1327 if (!CLG_(current_call_stack).entry[i].jcc) continue;
1328
1329 /* reset call counters to current for active calls */
1330 CLG_(copy_cost)( CLG_(sets).full,
1331 CLG_(current_call_stack).entry[i].enter_cost,
1332 CLG_(current_state).cost );
weidendoceb06de2009-08-11 20:53:57 +00001333 CLG_(current_call_stack).entry[i].jcc->call_counter = 0;
weidendoa17f2a32006-03-20 10:27:30 +00001334 }
1335
1336 CLG_(forall_bbccs)(CLG_(zero_bbcc));
1337
1338 /* set counter for last dump */
1339 CLG_(copy_cost)( CLG_(sets).full,
1340 t->lastdump_cost, CLG_(current_state).cost );
1341}
1342
1343void CLG_(zero_all_cost)(Bool only_current_thread)
1344{
1345 if (VG_(clo_verbosity) > 1)
sewardj0f33adf2009-07-15 14:51:03 +00001346 VG_(message)(Vg_DebugMsg, " Zeroing costs...\n");
weidendoa17f2a32006-03-20 10:27:30 +00001347
1348 if (only_current_thread)
1349 zero_thread_cost(CLG_(get_current_thread)());
1350 else
1351 CLG_(forall_threads)(zero_thread_cost);
1352
1353 if (VG_(clo_verbosity) > 1)
sewardj0f33adf2009-07-15 14:51:03 +00001354 VG_(message)(Vg_DebugMsg, " ...done\n");
weidendoa17f2a32006-03-20 10:27:30 +00001355}
1356
1357static
1358void unwind_thread(thread_info* t)
1359{
1360 /* unwind signal handlers */
1361 while(CLG_(current_state).sig !=0)
1362 CLG_(post_signal)(CLG_(current_tid),CLG_(current_state).sig);
1363
1364 /* unwind regular call stack */
1365 while(CLG_(current_call_stack).sp>0)
1366 CLG_(pop_call_stack)();
weidendof3e0b492006-09-10 22:34:20 +00001367
1368 /* reset context and function stack for context generation */
1369 CLG_(init_exec_state)( &CLG_(current_state) );
1370 CLG_(current_fn_stack).top = CLG_(current_fn_stack).bottom;
weidendoa17f2a32006-03-20 10:27:30 +00001371}
1372
weidendoe8914872009-08-11 20:53:59 +00001373static
1374void zero_state_cost(thread_info* t)
1375{
1376 CLG_(zero_cost)( CLG_(sets).full, CLG_(current_state).cost );
1377}
1378
weidendo722be392011-07-21 20:24:54 +00001379/* Ups, this can go very wrong... */
1380extern void VG_(discard_translations) ( Addr64 start, ULong range, HChar* who );
weidendoa17f2a32006-03-20 10:27:30 +00001381
florian25f6c572012-10-21 02:55:56 +00001382void CLG_(set_instrument_state)(const HChar* reason, Bool state)
weidendoa17f2a32006-03-20 10:27:30 +00001383{
1384 if (CLG_(instrument_state) == state) {
1385 CLG_DEBUG(2, "%s: instrumentation already %s\n",
1386 reason, state ? "ON" : "OFF");
1387 return;
1388 }
1389 CLG_(instrument_state) = state;
1390 CLG_DEBUG(2, "%s: Switching instrumentation %s ...\n",
1391 reason, state ? "ON" : "OFF");
1392
weidendo722be392011-07-21 20:24:54 +00001393 VG_(discard_translations)( (Addr64)0x1000, (ULong) ~0xfffl, "callgrind");
weidendoa17f2a32006-03-20 10:27:30 +00001394
1395 /* reset internal state: call stacks, simulator */
1396 CLG_(forall_threads)(unwind_thread);
weidendoe8914872009-08-11 20:53:59 +00001397 CLG_(forall_threads)(zero_state_cost);
weidendoa17f2a32006-03-20 10:27:30 +00001398 (*CLG_(cachesim).clear)();
weidendoa17f2a32006-03-20 10:27:30 +00001399
weidendoa17f2a32006-03-20 10:27:30 +00001400 if (VG_(clo_verbosity) > 1)
sewardj0f33adf2009-07-15 14:51:03 +00001401 VG_(message)(Vg_DebugMsg, "%s: instrumentation switched %s\n",
weidendoa17f2a32006-03-20 10:27:30 +00001402 reason, state ? "ON" : "OFF");
1403}
weidendo584c9ef2011-07-11 14:46:41 +00001404
1405/* helper for dump_state_togdb */
1406static void dump_state_of_thread_togdb(thread_info* ti)
1407{
floriandbb35842012-10-27 18:39:11 +00001408 static HChar buf[512];
weidendo584c9ef2011-07-11 14:46:41 +00001409 static FullCost sum = 0, tmp = 0;
1410 Int t, p, i;
1411 BBCC *from, *to;
1412 call_entry* ce;
1413
1414 t = CLG_(current_tid);
1415 CLG_(init_cost_lz)( CLG_(sets).full, &sum );
1416 CLG_(copy_cost_lz)( CLG_(sets).full, &tmp, ti->lastdump_cost );
1417 CLG_(add_diff_cost)( CLG_(sets).full, sum, ti->lastdump_cost,
1418 ti->states.entry[0]->cost);
1419 CLG_(copy_cost)( CLG_(sets).full, ti->lastdump_cost, tmp );
1420 CLG_(sprint_mappingcost)(buf, CLG_(dumpmap), sum);
1421 VG_(gdb_printf)("events-%d: %s\n", t, buf);
1422 VG_(gdb_printf)("frames-%d: %d\n", t, CLG_(current_call_stack).sp);
1423
1424 ce = 0;
1425 for(i = 0; i < CLG_(current_call_stack).sp; i++) {
1426 ce = CLG_(get_call_entry)(i);
1427 /* if this frame is skipped, we don't have counters */
1428 if (!ce->jcc) continue;
1429
1430 from = ce->jcc->from;
1431 VG_(gdb_printf)("function-%d-%d: %s\n",t, i, from->cxt->fn[0]->name);
1432 VG_(gdb_printf)("calls-%d-%d: %llu\n",t, i, ce->jcc->call_counter);
1433
1434 /* FIXME: EventSets! */
1435 CLG_(copy_cost)( CLG_(sets).full, sum, ce->jcc->cost );
1436 CLG_(copy_cost)( CLG_(sets).full, tmp, ce->enter_cost );
1437 CLG_(add_diff_cost)( CLG_(sets).full, sum,
1438 ce->enter_cost, CLG_(current_state).cost );
1439 CLG_(copy_cost)( CLG_(sets).full, ce->enter_cost, tmp );
1440
1441 p = VG_(sprintf)(buf, "events-%d-%d: ",t, i);
1442 CLG_(sprint_mappingcost)(buf + p, CLG_(dumpmap), sum );
1443 VG_(gdb_printf)("%s\n", buf);
1444 }
1445 if (ce && ce->jcc) {
1446 to = ce->jcc->to;
1447 VG_(gdb_printf)("function-%d-%d: %s\n",t, i, to->cxt->fn[0]->name );
1448 }
1449}
1450
1451/* Dump current state */
1452static void dump_state_togdb(void)
1453{
floriandbb35842012-10-27 18:39:11 +00001454 static HChar buf[512];
weidendo584c9ef2011-07-11 14:46:41 +00001455 thread_info** th;
1456 int t, p;
1457 Int orig_tid = CLG_(current_tid);
1458
1459 VG_(gdb_printf)("instrumentation: %s\n",
1460 CLG_(instrument_state) ? "on":"off");
1461 if (!CLG_(instrument_state)) return;
1462
1463 VG_(gdb_printf)("executed-bbs: %llu\n", CLG_(stat).bb_executions);
1464 VG_(gdb_printf)("executed-calls: %llu\n", CLG_(stat).call_counter);
1465 VG_(gdb_printf)("distinct-bbs: %d\n", CLG_(stat).distinct_bbs);
1466 VG_(gdb_printf)("distinct-calls: %d\n", CLG_(stat).distinct_jccs);
1467 VG_(gdb_printf)("distinct-functions: %d\n", CLG_(stat).distinct_fns);
1468 VG_(gdb_printf)("distinct-contexts: %d\n", CLG_(stat).distinct_contexts);
1469
1470 /* "events:" line. Given here because it will be dynamic in the future */
1471 p = VG_(sprintf)(buf, "events: ");
1472 CLG_(sprint_eventmapping)(buf+p, CLG_(dumpmap));
1473 VG_(gdb_printf)("%s\n", buf);
1474 /* "part:" line (number of last part. Is 0 at start */
1475 VG_(gdb_printf)("part: %d\n", CLG_(get_dump_counter)());
1476
1477 /* threads */
1478 th = CLG_(get_threads)();
1479 p = VG_(sprintf)(buf, "threads:");
1480 for(t=1;t<VG_N_THREADS;t++) {
1481 if (!th[t]) continue;
1482 p += VG_(sprintf)(buf+p, " %d", t);
1483 }
1484 VG_(gdb_printf)("%s\n", buf);
1485 VG_(gdb_printf)("current-tid: %d\n", orig_tid);
1486 CLG_(forall_threads)(dump_state_of_thread_togdb);
1487}
1488
weidendoa17f2a32006-03-20 10:27:30 +00001489
sewardj3b290482011-05-06 21:02:55 +00001490static void print_monitor_help ( void )
1491{
1492 VG_(gdb_printf) ("\n");
1493 VG_(gdb_printf) ("callgrind monitor commands:\n");
sewardj30b3eca2011-06-28 08:20:39 +00001494 VG_(gdb_printf) (" dump [<dump_hint>]\n");
sewardj3b290482011-05-06 21:02:55 +00001495 VG_(gdb_printf) (" dump counters\n");
sewardj30b3eca2011-06-28 08:20:39 +00001496 VG_(gdb_printf) (" zero\n");
sewardj3b290482011-05-06 21:02:55 +00001497 VG_(gdb_printf) (" zero counters\n");
weidendo584c9ef2011-07-11 14:46:41 +00001498 VG_(gdb_printf) (" status\n");
weidendoce6489f2011-09-06 19:08:35 +00001499 VG_(gdb_printf) (" print status\n");
weidendo584c9ef2011-07-11 14:46:41 +00001500 VG_(gdb_printf) (" instrumentation [on|off]\n");
1501 VG_(gdb_printf) (" get/set (if on/off given) instrumentation state\n");
sewardj3b290482011-05-06 21:02:55 +00001502 VG_(gdb_printf) ("\n");
1503}
1504
1505/* return True if request recognised, False otherwise */
florian19f91bb2012-11-10 22:29:54 +00001506static Bool handle_gdb_monitor_command (ThreadId tid, const HChar *req)
sewardj3b290482011-05-06 21:02:55 +00001507{
florian19f91bb2012-11-10 22:29:54 +00001508 HChar* wcmd;
1509 HChar s[VG_(strlen(req))]; /* copy for strtok_r */
1510 HChar *ssaveptr;
sewardj3b290482011-05-06 21:02:55 +00001511
1512 VG_(strcpy) (s, req);
1513
1514 wcmd = VG_(strtok_r) (s, " ", &ssaveptr);
weidendo584c9ef2011-07-11 14:46:41 +00001515 switch (VG_(keyword_id) ("help dump zero status instrumentation",
sewardj3b290482011-05-06 21:02:55 +00001516 wcmd, kwd_report_duplicated_matches)) {
1517 case -2: /* multiple matches */
1518 return True;
1519 case -1: /* not found */
1520 return False;
1521 case 0: /* help */
1522 print_monitor_help();
1523 return True;
sewardj30b3eca2011-06-28 08:20:39 +00001524 case 1: { /* dump */
sewardj3b290482011-05-06 21:02:55 +00001525 CLG_(dump_profile)(req, False);
1526 return True;
1527 }
sewardj30b3eca2011-06-28 08:20:39 +00001528 case 2: { /* zero */
sewardj3b290482011-05-06 21:02:55 +00001529 CLG_(zero_all_cost)(False);
1530 return True;
1531 }
weidendoce6489f2011-09-06 19:08:35 +00001532
weidendo584c9ef2011-07-11 14:46:41 +00001533 case 3: { /* status */
florian19f91bb2012-11-10 22:29:54 +00001534 HChar* arg = VG_(strtok_r) (0, " ", &ssaveptr);
weidendoce6489f2011-09-06 19:08:35 +00001535 if (arg && (VG_(strcmp)(arg, "internal") == 0)) {
1536 /* internal interface to callgrind_control */
1537 dump_state_togdb();
1538 return True;
1539 }
1540
1541 if (!CLG_(instrument_state)) {
1542 VG_(gdb_printf)("No status available as instrumentation is switched off\n");
1543 } else {
1544 // Status information to be improved ...
1545 thread_info** th = CLG_(get_threads)();
1546 Int t, tcount = 0;
1547 for(t=1;t<VG_N_THREADS;t++)
1548 if (th[t]) tcount++;
1549 VG_(gdb_printf)("%d thread(s) running.\n", tcount);
1550 }
weidendo584c9ef2011-07-11 14:46:41 +00001551 return True;
1552 }
weidendoce6489f2011-09-06 19:08:35 +00001553
weidendo584c9ef2011-07-11 14:46:41 +00001554 case 4: { /* instrumentation */
florian19f91bb2012-11-10 22:29:54 +00001555 HChar* arg = VG_(strtok_r) (0, " ", &ssaveptr);
weidendo584c9ef2011-07-11 14:46:41 +00001556 if (!arg) {
1557 VG_(gdb_printf)("instrumentation: %s\n",
1558 CLG_(instrument_state) ? "on":"off");
1559 }
1560 else
1561 CLG_(set_instrument_state)("Command", VG_(strcmp)(arg,"off")!=0);
1562 return True;
1563 }
sewardj3b290482011-05-06 21:02:55 +00001564
1565 default:
1566 tl_assert(0);
1567 return False;
1568 }
1569}
weidendoa17f2a32006-03-20 10:27:30 +00001570
1571static
1572Bool CLG_(handle_client_request)(ThreadId tid, UWord *args, UWord *ret)
1573{
sewardj3b290482011-05-06 21:02:55 +00001574 if (!VG_IS_TOOL_USERREQ('C','T',args[0])
1575 && VG_USERREQ__GDB_MONITOR_COMMAND != args[0])
weidendoa17f2a32006-03-20 10:27:30 +00001576 return False;
1577
1578 switch(args[0]) {
1579 case VG_USERREQ__DUMP_STATS:
1580 CLG_(dump_profile)("Client Request", True);
1581 *ret = 0; /* meaningless */
1582 break;
1583
1584 case VG_USERREQ__DUMP_STATS_AT:
1585 {
florian25f6c572012-10-21 02:55:56 +00001586 HChar buf[512];
florian19f91bb2012-11-10 22:29:54 +00001587 VG_(sprintf)(buf,"Client Request: %s", (HChar*)args[1]);
weidendoa17f2a32006-03-20 10:27:30 +00001588 CLG_(dump_profile)(buf, True);
1589 *ret = 0; /* meaningless */
1590 }
1591 break;
1592
1593 case VG_USERREQ__ZERO_STATS:
1594 CLG_(zero_all_cost)(True);
1595 *ret = 0; /* meaningless */
1596 break;
1597
1598 case VG_USERREQ__TOGGLE_COLLECT:
1599 CLG_(current_state).collect = !CLG_(current_state).collect;
1600 CLG_DEBUG(2, "Client Request: toggled collection state to %s\n",
1601 CLG_(current_state).collect ? "ON" : "OFF");
1602 *ret = 0; /* meaningless */
1603 break;
1604
1605 case VG_USERREQ__START_INSTRUMENTATION:
1606 CLG_(set_instrument_state)("Client Request", True);
1607 *ret = 0; /* meaningless */
1608 break;
1609
1610 case VG_USERREQ__STOP_INSTRUMENTATION:
1611 CLG_(set_instrument_state)("Client Request", False);
1612 *ret = 0; /* meaningless */
1613 break;
1614
sewardj3b290482011-05-06 21:02:55 +00001615 case VG_USERREQ__GDB_MONITOR_COMMAND: {
florian19f91bb2012-11-10 22:29:54 +00001616 Bool handled = handle_gdb_monitor_command (tid, (HChar*)args[1]);
sewardj3b290482011-05-06 21:02:55 +00001617 if (handled)
1618 *ret = 1;
1619 else
1620 *ret = 0;
1621 return handled;
1622 }
weidendoa17f2a32006-03-20 10:27:30 +00001623 default:
1624 return False;
1625 }
1626
1627 return True;
1628}
1629
1630
1631/* Syscall Timing */
1632
1633/* struct timeval syscalltime[VG_N_THREADS]; */
1634#if CLG_MICROSYSTIME
1635#include <sys/time.h>
1636#include <sys/syscall.h>
1637extern Int VG_(do_syscall) ( UInt, ... );
1638
1639ULong syscalltime[VG_N_THREADS];
1640#else
1641UInt syscalltime[VG_N_THREADS];
1642#endif
1643
1644static
sewardj1c0ce7a2009-07-01 08:10:49 +00001645void CLG_(pre_syscalltime)(ThreadId tid, UInt syscallno,
1646 UWord* args, UInt nArgs)
weidendoa17f2a32006-03-20 10:27:30 +00001647{
1648 if (CLG_(clo).collect_systime) {
1649#if CLG_MICROSYSTIME
1650 struct vki_timeval tv_now;
1651 VG_(do_syscall)(__NR_gettimeofday, (UInt)&tv_now, (UInt)NULL);
1652 syscalltime[tid] = tv_now.tv_sec * 1000000ULL + tv_now.tv_usec;
1653#else
1654 syscalltime[tid] = VG_(read_millisecond_timer)();
1655#endif
1656 }
1657}
1658
1659static
sewardj1c0ce7a2009-07-01 08:10:49 +00001660void CLG_(post_syscalltime)(ThreadId tid, UInt syscallno,
1661 UWord* args, UInt nArgs, SysRes res)
weidendoa17f2a32006-03-20 10:27:30 +00001662{
weidendoae0bb6f2007-02-16 13:12:43 +00001663 if (CLG_(clo).collect_systime &&
1664 CLG_(current_state).bbcc) {
weidendo5bba5252010-06-09 22:32:53 +00001665 Int o;
weidendoa17f2a32006-03-20 10:27:30 +00001666#if CLG_MICROSYSTIME
1667 struct vki_timeval tv_now;
1668 ULong diff;
1669
1670 VG_(do_syscall)(__NR_gettimeofday, (UInt)&tv_now, (UInt)NULL);
1671 diff = (tv_now.tv_sec * 1000000ULL + tv_now.tv_usec) - syscalltime[tid];
1672#else
1673 UInt diff = VG_(read_millisecond_timer)() - syscalltime[tid];
1674#endif
weidendo5bba5252010-06-09 22:32:53 +00001675
1676 /* offset o is for "SysCount", o+1 for "SysTime" */
1677 o = fullOffset(EG_SYS);
1678 CLG_ASSERT(o>=0);
weidendoa17f2a32006-03-20 10:27:30 +00001679 CLG_DEBUG(0," Time (Off %d) for Syscall %d: %ull\n", o, syscallno, diff);
1680
weidendoa17f2a32006-03-20 10:27:30 +00001681 CLG_(current_state).cost[o] ++;
1682 CLG_(current_state).cost[o+1] += diff;
1683 if (!CLG_(current_state).bbcc->skipped)
1684 CLG_(init_cost_lz)(CLG_(sets).full,
1685 &(CLG_(current_state).bbcc->skipped));
1686 CLG_(current_state).bbcc->skipped[o] ++;
1687 CLG_(current_state).bbcc->skipped[o+1] += diff;
1688 }
1689}
1690
weidendo320705f2010-07-02 19:56:23 +00001691static UInt ULong_width(ULong n)
1692{
1693 UInt w = 0;
1694 while (n > 0) {
1695 n = n / 10;
1696 w++;
1697 }
1698 if (w == 0) w = 1;
1699 return w + (w-1)/3; // add space for commas
1700}
1701
1702static
1703void branchsim_printstat(int l1, int l2, int l3)
1704{
floriandbb35842012-10-27 18:39:11 +00001705 static HChar buf1[128], buf2[128], buf3[128];
florian25f6c572012-10-21 02:55:56 +00001706 static HChar fmt[128];
weidendo320705f2010-07-02 19:56:23 +00001707 FullCost total;
1708 ULong Bc_total_b, Bc_total_mp, Bi_total_b, Bi_total_mp;
1709 ULong B_total_b, B_total_mp;
1710
1711 total = CLG_(total_cost);
1712 Bc_total_b = total[ fullOffset(EG_BC) ];
1713 Bc_total_mp = total[ fullOffset(EG_BC)+1 ];
1714 Bi_total_b = total[ fullOffset(EG_BI) ];
1715 Bi_total_mp = total[ fullOffset(EG_BI)+1 ];
1716
1717 /* Make format string, getting width right for numbers */
1718 VG_(sprintf)(fmt, "%%s %%,%dllu (%%,%dllu cond + %%,%dllu ind)\n",
1719 l1, l2, l3);
1720
1721 if (0 == Bc_total_b) Bc_total_b = 1;
1722 if (0 == Bi_total_b) Bi_total_b = 1;
1723 B_total_b = Bc_total_b + Bi_total_b;
1724 B_total_mp = Bc_total_mp + Bi_total_mp;
1725
1726 VG_(umsg)("\n");
1727 VG_(umsg)(fmt, "Branches: ",
1728 B_total_b, Bc_total_b, Bi_total_b);
1729
1730 VG_(umsg)(fmt, "Mispredicts: ",
1731 B_total_mp, Bc_total_mp, Bi_total_mp);
1732
1733 VG_(percentify)(B_total_mp, B_total_b, 1, l1+1, buf1);
1734 VG_(percentify)(Bc_total_mp, Bc_total_b, 1, l2+1, buf2);
1735 VG_(percentify)(Bi_total_mp, Bi_total_b, 1, l3+1, buf3);
1736
1737 VG_(umsg)("Mispred rate: %s (%s + %s )\n", buf1, buf2,buf3);
1738}
1739
1740
weidendoa17f2a32006-03-20 10:27:30 +00001741static
1742void finish(void)
1743{
florian19f91bb2012-11-10 22:29:54 +00001744 HChar buf[32+COSTS_LEN];
florian25f6c572012-10-21 02:55:56 +00001745 HChar fmt[128];
weidendo320705f2010-07-02 19:56:23 +00001746 Int l1, l2, l3;
1747 FullCost total;
weidendoa17f2a32006-03-20 10:27:30 +00001748
1749 CLG_DEBUG(0, "finish()\n");
1750
1751 (*CLG_(cachesim).finish)();
1752
1753 /* pop all remaining items from CallStack for correct sum
1754 */
1755 CLG_(forall_threads)(unwind_thread);
sewardje45a7992006-10-17 02:24:18 +00001756
weidendoa17f2a32006-03-20 10:27:30 +00001757 CLG_(dump_profile)(0, False);
sewardje45a7992006-10-17 02:24:18 +00001758
weidendoa17f2a32006-03-20 10:27:30 +00001759 if (VG_(clo_verbosity) == 0) return;
1760
1761 /* Hash table stats */
sewardj2d9e8742009-08-07 15:46:56 +00001762 if (VG_(clo_stats)) {
weidendoa17f2a32006-03-20 10:27:30 +00001763 int BB_lookups =
1764 CLG_(stat).full_debug_BBs +
1765 CLG_(stat).fn_name_debug_BBs +
1766 CLG_(stat).file_line_debug_BBs +
1767 CLG_(stat).no_debug_BBs;
1768
sewardj0f33adf2009-07-15 14:51:03 +00001769 VG_(message)(Vg_DebugMsg, "\n");
1770 VG_(message)(Vg_DebugMsg, "Distinct objects: %d\n",
weidendoa17f2a32006-03-20 10:27:30 +00001771 CLG_(stat).distinct_objs);
sewardj0f33adf2009-07-15 14:51:03 +00001772 VG_(message)(Vg_DebugMsg, "Distinct files: %d\n",
weidendoa17f2a32006-03-20 10:27:30 +00001773 CLG_(stat).distinct_files);
sewardj0f33adf2009-07-15 14:51:03 +00001774 VG_(message)(Vg_DebugMsg, "Distinct fns: %d\n",
weidendoa17f2a32006-03-20 10:27:30 +00001775 CLG_(stat).distinct_fns);
sewardj0f33adf2009-07-15 14:51:03 +00001776 VG_(message)(Vg_DebugMsg, "Distinct contexts:%d\n",
weidendoa17f2a32006-03-20 10:27:30 +00001777 CLG_(stat).distinct_contexts);
sewardj0f33adf2009-07-15 14:51:03 +00001778 VG_(message)(Vg_DebugMsg, "Distinct BBs: %d\n",
weidendoa17f2a32006-03-20 10:27:30 +00001779 CLG_(stat).distinct_bbs);
sewardj0f33adf2009-07-15 14:51:03 +00001780 VG_(message)(Vg_DebugMsg, "Cost entries: %d (Chunks %d)\n",
weidendoa17f2a32006-03-20 10:27:30 +00001781 CLG_(costarray_entries), CLG_(costarray_chunks));
sewardj0f33adf2009-07-15 14:51:03 +00001782 VG_(message)(Vg_DebugMsg, "Distinct BBCCs: %d\n",
weidendoa17f2a32006-03-20 10:27:30 +00001783 CLG_(stat).distinct_bbccs);
sewardj0f33adf2009-07-15 14:51:03 +00001784 VG_(message)(Vg_DebugMsg, "Distinct JCCs: %d\n",
weidendoa17f2a32006-03-20 10:27:30 +00001785 CLG_(stat).distinct_jccs);
sewardj0f33adf2009-07-15 14:51:03 +00001786 VG_(message)(Vg_DebugMsg, "Distinct skips: %d\n",
weidendoa17f2a32006-03-20 10:27:30 +00001787 CLG_(stat).distinct_skips);
sewardj0f33adf2009-07-15 14:51:03 +00001788 VG_(message)(Vg_DebugMsg, "BB lookups: %d\n",
weidendoa17f2a32006-03-20 10:27:30 +00001789 BB_lookups);
1790 if (BB_lookups>0) {
sewardj0f33adf2009-07-15 14:51:03 +00001791 VG_(message)(Vg_DebugMsg, "With full debug info:%3d%% (%d)\n",
weidendoa17f2a32006-03-20 10:27:30 +00001792 CLG_(stat).full_debug_BBs * 100 / BB_lookups,
1793 CLG_(stat).full_debug_BBs);
sewardj0f33adf2009-07-15 14:51:03 +00001794 VG_(message)(Vg_DebugMsg, "With file/line debug info:%3d%% (%d)\n",
weidendoa17f2a32006-03-20 10:27:30 +00001795 CLG_(stat).file_line_debug_BBs * 100 / BB_lookups,
1796 CLG_(stat).file_line_debug_BBs);
sewardj0f33adf2009-07-15 14:51:03 +00001797 VG_(message)(Vg_DebugMsg, "With fn name debug info:%3d%% (%d)\n",
weidendoa17f2a32006-03-20 10:27:30 +00001798 CLG_(stat).fn_name_debug_BBs * 100 / BB_lookups,
1799 CLG_(stat).fn_name_debug_BBs);
sewardj0f33adf2009-07-15 14:51:03 +00001800 VG_(message)(Vg_DebugMsg, "With no debug info:%3d%% (%d)\n",
weidendoa17f2a32006-03-20 10:27:30 +00001801 CLG_(stat).no_debug_BBs * 100 / BB_lookups,
1802 CLG_(stat).no_debug_BBs);
1803 }
sewardj0f33adf2009-07-15 14:51:03 +00001804 VG_(message)(Vg_DebugMsg, "BBCC Clones: %d\n",
weidendoa17f2a32006-03-20 10:27:30 +00001805 CLG_(stat).bbcc_clones);
sewardj0f33adf2009-07-15 14:51:03 +00001806 VG_(message)(Vg_DebugMsg, "BBs Retranslated: %d\n",
weidendoa17f2a32006-03-20 10:27:30 +00001807 CLG_(stat).bb_retranslations);
sewardj0f33adf2009-07-15 14:51:03 +00001808 VG_(message)(Vg_DebugMsg, "Distinct instrs: %d\n",
weidendoa17f2a32006-03-20 10:27:30 +00001809 CLG_(stat).distinct_instrs);
1810 VG_(message)(Vg_DebugMsg, "");
1811
sewardj0f33adf2009-07-15 14:51:03 +00001812 VG_(message)(Vg_DebugMsg, "LRU Contxt Misses: %d\n",
weidendoa17f2a32006-03-20 10:27:30 +00001813 CLG_(stat).cxt_lru_misses);
sewardj0f33adf2009-07-15 14:51:03 +00001814 VG_(message)(Vg_DebugMsg, "LRU BBCC Misses: %d\n",
weidendoa17f2a32006-03-20 10:27:30 +00001815 CLG_(stat).bbcc_lru_misses);
sewardj0f33adf2009-07-15 14:51:03 +00001816 VG_(message)(Vg_DebugMsg, "LRU JCC Misses: %d\n",
weidendoa17f2a32006-03-20 10:27:30 +00001817 CLG_(stat).jcc_lru_misses);
sewardj0f33adf2009-07-15 14:51:03 +00001818 VG_(message)(Vg_DebugMsg, "BBs Executed: %llu\n",
weidendoa17f2a32006-03-20 10:27:30 +00001819 CLG_(stat).bb_executions);
sewardj0f33adf2009-07-15 14:51:03 +00001820 VG_(message)(Vg_DebugMsg, "Calls: %llu\n",
weidendoa17f2a32006-03-20 10:27:30 +00001821 CLG_(stat).call_counter);
sewardj0f33adf2009-07-15 14:51:03 +00001822 VG_(message)(Vg_DebugMsg, "CondJMP followed: %llu\n",
weidendoa17f2a32006-03-20 10:27:30 +00001823 CLG_(stat).jcnd_counter);
sewardj0f33adf2009-07-15 14:51:03 +00001824 VG_(message)(Vg_DebugMsg, "Boring JMPs: %llu\n",
weidendoa17f2a32006-03-20 10:27:30 +00001825 CLG_(stat).jump_counter);
sewardj0f33adf2009-07-15 14:51:03 +00001826 VG_(message)(Vg_DebugMsg, "Recursive calls: %llu\n",
weidendoa17f2a32006-03-20 10:27:30 +00001827 CLG_(stat).rec_call_counter);
sewardj0f33adf2009-07-15 14:51:03 +00001828 VG_(message)(Vg_DebugMsg, "Returns: %llu\n",
weidendoa17f2a32006-03-20 10:27:30 +00001829 CLG_(stat).ret_counter);
1830
1831 VG_(message)(Vg_DebugMsg, "");
1832 }
1833
1834 CLG_(sprint_eventmapping)(buf, CLG_(dumpmap));
sewardj0f33adf2009-07-15 14:51:03 +00001835 VG_(message)(Vg_UserMsg, "Events : %s\n", buf);
weidendoa17f2a32006-03-20 10:27:30 +00001836 CLG_(sprint_mappingcost)(buf, CLG_(dumpmap), CLG_(total_cost));
sewardj0f33adf2009-07-15 14:51:03 +00001837 VG_(message)(Vg_UserMsg, "Collected : %s\n", buf);
1838 VG_(message)(Vg_UserMsg, "\n");
weidendoa17f2a32006-03-20 10:27:30 +00001839
weidendo320705f2010-07-02 19:56:23 +00001840 /* determine value widths for statistics */
1841 total = CLG_(total_cost);
1842 l1 = ULong_width( total[fullOffset(EG_IR)] );
1843 l2 = l3 = 0;
1844 if (CLG_(clo).simulate_cache) {
1845 l2 = ULong_width( total[fullOffset(EG_DR)] );
1846 l3 = ULong_width( total[fullOffset(EG_DW)] );
1847 }
1848 if (CLG_(clo).simulate_branch) {
1849 int l2b = ULong_width( total[fullOffset(EG_BC)] );
1850 int l3b = ULong_width( total[fullOffset(EG_BI)] );
1851 if (l2b > l2) l2 = l2b;
1852 if (l3b > l3) l3 = l3b;
1853 }
1854
1855 /* Make format string, getting width right for numbers */
1856 VG_(sprintf)(fmt, "%%s %%,%dllu\n", l1);
1857
1858 /* Always print this */
1859 VG_(umsg)(fmt, "I refs: ", total[fullOffset(EG_IR)] );
1860
1861 if (CLG_(clo).simulate_cache)
1862 (*CLG_(cachesim).printstat)(l1, l2, l3);
1863
1864 if (CLG_(clo).simulate_branch)
1865 branchsim_printstat(l1, l2, l3);
1866
weidendoa17f2a32006-03-20 10:27:30 +00001867}
1868
1869
1870void CLG_(fini)(Int exitcode)
1871{
1872 finish();
1873}
1874
1875
1876/*--------------------------------------------------------------------*/
1877/*--- Setup ---*/
1878/*--------------------------------------------------------------------*/
1879
njn3e32c872006-12-24 07:51:17 +00001880static void clg_start_client_code_callback ( ThreadId tid, ULong blocks_done )
sewardj97561812006-12-23 01:21:12 +00001881{
weidendo134657c2006-12-23 23:11:20 +00001882 static ULong last_blocks_done = 0;
1883
sewardj97561812006-12-23 01:21:12 +00001884 if (0)
njn3e32c872006-12-24 07:51:17 +00001885 VG_(printf)("%d R %llu\n", (Int)tid, blocks_done);
weidendo134657c2006-12-23 23:11:20 +00001886
1887 /* throttle calls to CLG_(run_thread) by number of BBs executed */
1888 if (blocks_done - last_blocks_done < 5000) return;
1889 last_blocks_done = blocks_done;
1890
1891 CLG_(run_thread)( tid );
sewardj97561812006-12-23 01:21:12 +00001892}
1893
weidendoa17f2a32006-03-20 10:27:30 +00001894static
1895void CLG_(post_clo_init)(void)
1896{
philippe5b240c22012-08-14 22:28:31 +00001897 if (VG_(clo_vex_control).iropt_register_updates
1898 != VexRegUpdSpAtMemAccess) {
1899 CLG_DEBUG(1, " Using user specified value for "
1900 "--vex-iropt-register-updates\n");
1901 } else {
1902 CLG_DEBUG(1,
1903 " Using default --vex-iropt-register-updates="
1904 "sp-at-mem-access\n");
1905 }
weidendoa17f2a32006-03-20 10:27:30 +00001906
philippe5b240c22012-08-14 22:28:31 +00001907 if (VG_(clo_vex_control).iropt_unroll_thresh != 0) {
1908 VG_(message)(Vg_UserMsg,
1909 "callgrind only works with --vex-iropt-unroll-thresh=0\n"
1910 "=> resetting it back to 0\n");
1911 VG_(clo_vex_control).iropt_unroll_thresh = 0; // cannot be overriden.
1912 }
1913 if (VG_(clo_vex_control).guest_chase_thresh != 0) {
1914 VG_(message)(Vg_UserMsg,
1915 "callgrind only works with --vex-guest-chase-thresh=0\n"
1916 "=> resetting it back to 0\n");
1917 VG_(clo_vex_control).guest_chase_thresh = 0; // cannot be overriden.
1918 }
1919
weidendoa17f2a32006-03-20 10:27:30 +00001920 CLG_DEBUG(1, " dump threads: %s\n", CLG_(clo).separate_threads ? "Yes":"No");
1921 CLG_DEBUG(1, " call sep. : %d\n", CLG_(clo).separate_callers);
1922 CLG_DEBUG(1, " rec. sep. : %d\n", CLG_(clo).separate_recursions);
1923
1924 if (!CLG_(clo).dump_line && !CLG_(clo).dump_instr && !CLG_(clo).dump_bb) {
sewardj0f33adf2009-07-15 14:51:03 +00001925 VG_(message)(Vg_UserMsg, "Using source line as position.\n");
weidendoa17f2a32006-03-20 10:27:30 +00001926 CLG_(clo).dump_line = True;
1927 }
1928
weidendo4ce5e792006-09-20 21:29:39 +00001929 CLG_(init_dumps)();
weidendoa17f2a32006-03-20 10:27:30 +00001930
1931 (*CLG_(cachesim).post_clo_init)();
1932
weidendo5bba5252010-06-09 22:32:53 +00001933 CLG_(init_eventsets)();
weidendoa17f2a32006-03-20 10:27:30 +00001934 CLG_(init_statistics)(& CLG_(stat));
1935 CLG_(init_cost_lz)( CLG_(sets).full, &CLG_(total_cost) );
1936
1937 /* initialize hash tables */
1938 CLG_(init_obj_table)();
1939 CLG_(init_cxt_table)();
1940 CLG_(init_bb_hash)();
1941
1942 CLG_(init_threads)();
1943 CLG_(run_thread)(1);
1944
1945 CLG_(instrument_state) = CLG_(clo).instrument_atstart;
1946
weidendoca472c52006-03-31 19:34:51 +00001947 if (VG_(clo_verbosity > 0)) {
weidendoca472c52006-03-31 19:34:51 +00001948 VG_(message)(Vg_UserMsg,
sewardj0f33adf2009-07-15 14:51:03 +00001949 "For interactive control, run 'callgrind_control -h'.\n");
weidendoca472c52006-03-31 19:34:51 +00001950 }
weidendoa17f2a32006-03-20 10:27:30 +00001951}
1952
1953static
1954void CLG_(pre_clo_init)(void)
1955{
1956 VG_(details_name) ("Callgrind");
weidendoca472c52006-03-31 19:34:51 +00001957 VG_(details_version) (NULL);
weidendoa17f2a32006-03-20 10:27:30 +00001958 VG_(details_description) ("a call-graph generating cache profiler");
sewardj03f8d3f2012-08-05 15:46:46 +00001959 VG_(details_copyright_author)("Copyright (C) 2002-2012, and GNU GPL'd, "
weidendoca472c52006-03-31 19:34:51 +00001960 "by Josef Weidendorfer et al.");
weidendodb70ed72006-05-27 15:39:45 +00001961 VG_(details_bug_reports_to) (VG_BUGS_TO);
sewardje45a7992006-10-17 02:24:18 +00001962 VG_(details_avg_translation_sizeB) ( 500 );
weidendoa17f2a32006-03-20 10:27:30 +00001963
philippe5b240c22012-08-14 22:28:31 +00001964 VG_(clo_vex_control).iropt_register_updates
1965 = VexRegUpdSpAtMemAccess; // overridable by the user.
1966 VG_(clo_vex_control).iropt_unroll_thresh = 0; // cannot be overriden.
1967 VG_(clo_vex_control).guest_chase_thresh = 0; // cannot be overriden.
1968
weidendoa17f2a32006-03-20 10:27:30 +00001969 VG_(basic_tool_funcs) (CLG_(post_clo_init),
1970 CLG_(instrument),
1971 CLG_(fini));
1972
sewardj0b9d74a2006-12-24 02:24:11 +00001973 VG_(needs_superblock_discards)(clg_discard_superblock_info);
weidendoa17f2a32006-03-20 10:27:30 +00001974
1975
1976 VG_(needs_command_line_options)(CLG_(process_cmd_line_option),
1977 CLG_(print_usage),
1978 CLG_(print_debug_usage));
1979
1980 VG_(needs_client_requests)(CLG_(handle_client_request));
1981 VG_(needs_syscall_wrapper)(CLG_(pre_syscalltime),
1982 CLG_(post_syscalltime));
1983
njn3e32c872006-12-24 07:51:17 +00001984 VG_(track_start_client_code) ( & clg_start_client_code_callback );
1985 VG_(track_pre_deliver_signal) ( & CLG_(pre_signal) );
1986 VG_(track_post_deliver_signal)( & CLG_(post_signal) );
weidendoa17f2a32006-03-20 10:27:30 +00001987
1988 CLG_(set_clo_defaults)();
1989}
1990
1991VG_DETERMINE_INTERFACE_VERSION(CLG_(pre_clo_init))
1992
1993/*--------------------------------------------------------------------*/
1994/*--- end main.c ---*/
1995/*--------------------------------------------------------------------*/