1
2/*--------------------------------------------------------------------*/
3/*--- For printing superblock profiles               m_sbprofile.c ---*/
4/*--------------------------------------------------------------------*/
5
6/*
7   This file is part of Valgrind, a dynamic binary instrumentation
8   framework.
9
10   Copyright (C) 2012-2013 Mozilla Foundation
11
12   This program is free software; you can redistribute it and/or
13   modify it under the terms of the GNU General Public License as
14   published by the Free Software Foundation; either version 2 of the
15   License, or (at your option) any later version.
16
17   This program is distributed in the hope that it will be useful, but
18   WITHOUT ANY WARRANTY; without even the implied warranty of
19   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
20   General Public License for more details.
21
22   You should have received a copy of the GNU General Public License
23   along with this program; if not, write to the Free Software
24   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
25   02111-1307, USA.
26
27   The GNU General Public License is contained in the file COPYING.
28*/
29
30/* Contributed by Julian Seward <jseward@acm.org> */
31
32#include "pub_core_basics.h"
33#include "pub_core_transtab.h"
34#include "pub_core_libcbase.h"
35#include "pub_core_libcprint.h"
36#include "pub_core_libcassert.h"
37#include "pub_core_debuginfo.h"
38#include "pub_core_translate.h"
39#include "pub_core_options.h"
40#include "pub_core_sbprofile.h"    // self
41
42/*====================================================================*/
43/*=== SB profiling                                                 ===*/
44/*====================================================================*/
45
46static UInt n_profiles = 0;
47
48static
49void show_SB_profile ( SBProfEntry tops[], UInt n_tops,
50                       ULong score_total, ULong ecs_done )
51{
52   ULong score_cumul, score_cumul_saved, score_here;
53   HChar buf_cumul[10], buf_here[10];
54   HChar name[64];
55   Int   r; /* must be signed */
56
57   HChar ecs_txt[50];
58   if (ecs_done > 0) {
59      VG_(sprintf)(ecs_txt, "%'llu ecs done", ecs_done);
60   } else {
61      VG_(strcpy)(ecs_txt, "for the entire run");
62   }
63
64   vg_assert(VG_(clo_profyle_sbs));
65
66   VG_(printf)("\n");
67   VG_(printf)("<<<---<<<---<<<---<<<---<<<---<<<---<<<---"
68               "<<<---<<<---<<<---<<<---<<<---<<<\n");
69   VG_(printf)("<<<---<<<---<<<---<<<---<<<---<<<---<<<---"
70               "<<<---<<<---<<<---<<<---<<<---<<<\n");
71   VG_(printf)("\n");
72   VG_(printf)("<<< BEGIN SB Profile #%u (%s)\n",
73               ++n_profiles, ecs_txt);
74   VG_(printf)("<<<\n");
75   VG_(printf)("\n");
76
77   VG_(printf)("Total score = %'lld\n\n", score_total);
78
79   /* Print an initial per-block summary. */
80   VG_(printf)("rank  ---cumulative---      -----self-----\n");
81   score_cumul = 0;
82   for (r = 0; r < n_tops; r++) {
83      if (tops[r].addr == 0)
84         continue;
85      if (tops[r].score == 0)
86         continue;
87      name[0] = 0;
88      VG_(get_fnname_w_offset)(tops[r].addr, name, 64);
89      name[63] = 0;
90      score_here = tops[r].score;
91      score_cumul += score_here;
92      VG_(percentify)(score_cumul, score_total, 2, 6, buf_cumul);
93      VG_(percentify)(score_here,  score_total, 2, 6, buf_here);
94      VG_(printf)("%3d: (%9lld %s)   %9lld %s      0x%llx %s\n",
95                  r,
96                  score_cumul, buf_cumul,
97                  score_here,  buf_here, tops[r].addr, name );
98   }
99   score_cumul_saved = score_cumul;
100
101   if (VG_(clo_profyle_flags) > 0) {
102
103      /* Show the details, if requested. */
104      VG_(printf)("\n");
105      VG_(printf)("-----------------------------"
106                  "------------------------------\n");
107      VG_(printf)("--- SB Profile (SB details)  "
108                  "                           ---\n");
109      VG_(printf)("-----------------------------"
110                  "------------------------------\n");
111      VG_(printf)("\n");
112
113      score_cumul = 0;
114      for (r = 0; r < n_tops; r++) {
115         if (tops[r].addr == 0)
116            continue;
117         if (tops[r].score == 0)
118            continue;
119         name[0] = 0;
120         VG_(get_fnname_w_offset)(tops[r].addr, name, 64);
121         name[63] = 0;
122         score_here = tops[r].score;
123         score_cumul += score_here;
124         VG_(percentify)(score_cumul, score_total, 2, 6, buf_cumul);
125         VG_(percentify)(score_here,  score_total, 2, 6, buf_here);
126         VG_(printf)("\n");
127         VG_(printf)("=-=-=-=-=-=-=-=-=-=-=-=-=-= begin SB rank %d "
128                     "=-=-=-=-=-=-=-=-=-=-=-=-=-=\n\n", r);
129         VG_(printf)("%3d: (%9lld %s)   %9lld %s      0x%llx %s\n",
130                     r,
131                     score_cumul, buf_cumul,
132                     score_here,  buf_here, tops[r].addr, name );
133         VG_(printf)("\n");
134         VG_(discard_translations)(tops[r].addr, 1, "bb profile");
135         VG_(translate)(0, tops[r].addr, True, VG_(clo_profyle_flags), 0, True);
136         VG_(printf)("=-=-=-=-=-=-=-=-=-=-=-=-=-=  end SB rank %d  "
137                     "=-=-=-=-=-=-=-=-=-=-=-=-=-=\n\n", r);
138      }
139
140      /* Print a final per-block summary, in reverse order, for the
141         convenience of people reading up from the end. */
142      score_cumul = score_cumul_saved;
143      for (r = n_tops-1; r >= 0; r--) {
144         if (tops[r].addr == 0)
145            continue;
146         if (tops[r].score == 0)
147            continue;
148         name[0] = 0;
149         VG_(get_fnname_w_offset)(tops[r].addr, name, 64);
150         name[63] = 0;
151         score_here = tops[r].score;
152         VG_(percentify)(score_cumul, score_total, 2, 6, buf_cumul);
153         VG_(percentify)(score_here,  score_total, 2, 6, buf_here);
154         VG_(printf)("%3d: (%9lld %s)   %9lld %s      0x%llx %s\n",
155                     r,
156                     score_cumul, buf_cumul,
157                     score_here,  buf_here, tops[r].addr, name );
158         score_cumul -= score_here;
159      }
160      VG_(printf)("rank  ---cumulative---      -----self-----\n");
161
162   }
163
164   VG_(printf)("\n");
165   VG_(printf)(">>>\n");
166   VG_(printf)(">>> END SB Profile #%u (%s)\n",
167               n_profiles, ecs_txt);
168   VG_(printf)(">>>\n");
169   VG_(printf)(">>>--->>>--->>>--->>>--->>>--->>>--->>>---"
170               ">>>--->>>--->>>--->>>--->>>--->>>\n");
171   VG_(printf)(">>>--->>>--->>>--->>>--->>>--->>>--->>>---"
172               ">>>--->>>--->>>--->>>--->>>--->>>\n");
173   VG_(printf)("\n");
174}
175
176
177/* Get and print a profile.  Also, zero out the counters so that if we
178   call it again later, the second call will only show new work done
179   since the first call.  ecs_done == 0 is taken to mean this is a
180   run-end profile. */
181void VG_(get_and_show_SB_profile) ( ULong ecs_done )
182{
183   /* The number of blocks to show for a end-of-run profile */
184#  define N_MAX_END 200
185   /* The number of blocks to show for a mid-run profile. */
186#  define N_MAX_INTERVAL 20
187   vg_assert(N_MAX_INTERVAL <= N_MAX_END);
188   SBProfEntry tops[N_MAX_END];
189   Int nToShow = ecs_done == 0  ? N_MAX_END  : N_MAX_INTERVAL;
190   ULong score_total = VG_(get_SB_profile)(tops, nToShow);
191   show_SB_profile(tops, nToShow, score_total, ecs_done);
192#  undef N_MAX_END
193#  undef N_MAX_INTERVAL
194}
195
196
197/*--------------------------------------------------------------------*/
198/*--- end                                            m_sbprofile.c ---*/
199/*--------------------------------------------------------------------*/
200