blob: 5576a6dd6fb5483b797d3d448e237fdb1944670e [file] [log] [blame]
njnc9539842002-10-02 13:26:35 +00001
njn25e49d8e72002-09-23 09:36:25 +00002/*--------------------------------------------------------------------*/
3/*--- Simple skin for counting UInstrs, using a C helper. ---*/
njn25cac76cb2002-09-23 11:21:57 +00004/*--- lk_main.c ---*/
njn25e49d8e72002-09-23 09:36:25 +00005/*--------------------------------------------------------------------*/
6
7/*
njnc9539842002-10-02 13:26:35 +00008 This file is part of Lackey, an example Valgrind skin that does
9 some simple program measurement.
njn25e49d8e72002-09-23 09:36:25 +000010
11 Copyright (C) 2002 Nicholas Nethercote
12 njn25@cam.ac.uk
13
14 This program is free software; you can redistribute it and/or
15 modify it under the terms of the GNU General Public License as
16 published by the Free Software Foundation; either version 2 of the
17 License, or (at your option) any later version.
18
19 This program is distributed in the hope that it will be useful, but
20 WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 General Public License for more details.
23
24 You should have received a copy of the GNU General Public License
25 along with this program; if not, write to the Free Software
26 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
27 02111-1307, USA.
28
29 The GNU General Public License is contained in the file COPYING.
30*/
31
32#include "vg_skin.h"
33
njn27f1a382002-11-08 15:48:16 +000034VG_DETERMINE_INTERFACE_VERSION
35
njn25e49d8e72002-09-23 09:36:25 +000036/* Nb: use ULongs because the numbers can get very big */
37static ULong n_dlrr_calls = 0;
38static ULong n_BBs = 0;
39static ULong n_UInstrs = 0;
40static ULong n_x86_instrs = 0;
41static ULong n_Jccs = 0;
42static ULong n_Jccs_untaken = 0;
43
44static void add_one_dlrr_call(void)
45{
46 n_dlrr_calls++;
47}
48
49/* See comment above SK_(instrument) for reason why n_x86_instrs is
50 incremented here. */
51static void add_one_BB(void)
52{
53 n_BBs++;
54 n_x86_instrs++;
55}
56
57static void add_one_UInstr(void)
58{
59 n_UInstrs++;
60}
61
62static void add_one_x86_instr(void)
63{
64 n_x86_instrs++;
65}
66
67static void add_one_Jcc(void)
68{
69 n_Jccs++;
70}
71
72static void add_one_Jcc_untaken(void)
73{
74 n_Jccs_untaken++;
75}
76
njn810086f2002-11-14 12:42:47 +000077void SK_(pre_clo_init)(void)
njn25e49d8e72002-09-23 09:36:25 +000078{
njn810086f2002-11-14 12:42:47 +000079 VG_(details_name) ("Lackey");
80 VG_(details_version) (NULL);
81 VG_(details_description) ("an example Valgrind skin");
82 VG_(details_copyright_author)(
83 "Copyright (C) 2002, and GNU GPL'd, by Nicholas Nethercote.");
84 VG_(details_bug_reports_to) ("njn25@cam.ac.uk");
sewardjc0d8f682002-11-30 00:49:43 +000085 VG_(details_avg_translation_sizeB) ( 175 );
njn25e49d8e72002-09-23 09:36:25 +000086
njn25cac76cb2002-09-23 11:21:57 +000087 VG_(register_compact_helper)((Addr) & add_one_dlrr_call);
njn25e49d8e72002-09-23 09:36:25 +000088 VG_(register_compact_helper)((Addr) & add_one_BB);
89 VG_(register_compact_helper)((Addr) & add_one_x86_instr);
90 VG_(register_compact_helper)((Addr) & add_one_UInstr);
91 VG_(register_compact_helper)((Addr) & add_one_Jcc);
92 VG_(register_compact_helper)((Addr) & add_one_Jcc_untaken);
93}
94
95void SK_(post_clo_init)(void)
96{
97}
98
99/* Note: x86 instructions are marked by an INCEIP at the end of each one,
100 except for the final one in the basic block which ends in an
101 unconditional JMP. Sometimes the final unconditional JMP is preceded by
102 a conditional JMP (Jcc), and thus it isn't reached. Eg:
103
104 <code a>
105 INCEIP ...
106
107 <code b>
108 Jcc ...
109 JMP ... (will not be reached if Jcc succeeds)
110
111 If we simplemindedly added calls to add_one_x86_instr() before INCEIPs
112 and unconditional JMPs, we'd sometimes miss the final call (when a
113 preceding conditional JMP succeeds), underestimating the x86 instruction
114 count.
115
116 <code a>
117 call add_one_x86_instr()
118 INCEIP ...
119
120 <code b>
121 Jcc ...
122 call add_one_x86_instr()
123 JMP ...
124
125 Instead we add a call before each INCEIP, and also one at the start of the
126 block, but not one at the end, viz:
127
128 call add_one_x86_instr()
129
130 <code a>
131 call add_one_x86_instr()
132 INCEIP ...
133
134 <code b>
135 Jcc ...
136 JMP ...
137
138 Which gives us the right answer. And just to avoid two C calls, we fold
139 the basic-block-beginning call in with add_one_BB(). Phew.
140*/
141UCodeBlock* SK_(instrument)(UCodeBlock* cb_in, Addr orig_addr)
142{
143 UCodeBlock* cb;
144 Int i;
145 UInstr* u;
146 Char fnname[100];
147
njn810086f2002-11-14 12:42:47 +0000148 cb = VG_(setup_UCodeBlock)(cb_in);
njn25e49d8e72002-09-23 09:36:25 +0000149
150 /* Count call to dlrr(), if this BB is dlrr()'s entry point */
151 if (VG_(get_fnname_if_entry)(orig_addr, fnname, 100) &&
152 0 == VG_(strcmp)(fnname, "_dl_runtime_resolve"))
153 {
njn4ba5a792002-09-30 10:23:54 +0000154 VG_(call_helper_0_0)(cb, (Addr) & add_one_dlrr_call);
njn25e49d8e72002-09-23 09:36:25 +0000155 }
156
157 /* Count basic block */
njn4ba5a792002-09-30 10:23:54 +0000158 VG_(call_helper_0_0)(cb, (Addr) & add_one_BB);
njn25e49d8e72002-09-23 09:36:25 +0000159
njn810086f2002-11-14 12:42:47 +0000160 for (i = 0; i < VG_(get_num_instrs)(cb_in); i++) {
161 u = VG_(get_instr)(cb_in, i);
njn25e49d8e72002-09-23 09:36:25 +0000162
163 switch (u->opcode) {
sewardj7a5ebcf2002-11-13 22:42:13 +0000164 case NOP: case LOCK: case CALLM_S: case CALLM_E:
njn25e49d8e72002-09-23 09:36:25 +0000165 break;
166
167 case INCEIP:
168 /* Count x86 instr */
njn4ba5a792002-09-30 10:23:54 +0000169 VG_(call_helper_0_0)(cb, (Addr) & add_one_x86_instr);
170 VG_(copy_UInstr)(cb, u);
njn25e49d8e72002-09-23 09:36:25 +0000171 break;
172
173 case JMP:
174 if (u->cond != CondAlways) {
175 /* Count Jcc */
njn4ba5a792002-09-30 10:23:54 +0000176 VG_(call_helper_0_0)(cb, (Addr) & add_one_Jcc);
177 VG_(copy_UInstr)(cb, u);
njn25e49d8e72002-09-23 09:36:25 +0000178 /* Count non-taken Jcc */
njn4ba5a792002-09-30 10:23:54 +0000179 VG_(call_helper_0_0)(cb, (Addr) & add_one_Jcc_untaken);
njn25e49d8e72002-09-23 09:36:25 +0000180 } else {
njn4ba5a792002-09-30 10:23:54 +0000181 VG_(copy_UInstr)(cb, u);
njn25e49d8e72002-09-23 09:36:25 +0000182 }
183 break;
sewardj3d7c9c82003-03-26 21:08:13 +0000184
185 case MMX1: case MMX2: case MMX3:
186 case MMX2_MemRd: case MMX2_MemWr:
187 case MMX2_RegRd: case MMX2_RegWr:
188 VG_(skin_panic)(
189 "I don't know how to instrument MMXish stuff (yet)");
190 break;
191
njn25e49d8e72002-09-23 09:36:25 +0000192 default:
193 /* Count UInstr */
njn4ba5a792002-09-30 10:23:54 +0000194 VG_(call_helper_0_0)(cb, (Addr) & add_one_UInstr);
195 VG_(copy_UInstr)(cb, u);
njn25e49d8e72002-09-23 09:36:25 +0000196 break;
197 }
198 }
199
njn4ba5a792002-09-30 10:23:54 +0000200 VG_(free_UCodeBlock)(cb_in);
njn25e49d8e72002-09-23 09:36:25 +0000201 return cb;
202}
203
204void SK_(fini)(void)
205{
206 VG_(message)(Vg_UserMsg,
207 "Counted %d calls to _dl_runtime_resolve()", n_dlrr_calls);
208
209 VG_(message)(Vg_UserMsg, "");
210 VG_(message)(Vg_UserMsg, "Executed:");
211 VG_(message)(Vg_UserMsg, " BBs: %u", n_BBs);
212 VG_(message)(Vg_UserMsg, " x86 instrs: %u", n_x86_instrs);
213 VG_(message)(Vg_UserMsg, " UInstrs: %u", n_UInstrs);
214
215 VG_(message)(Vg_UserMsg, "");
216 VG_(message)(Vg_UserMsg, "Jccs:");
217 VG_(message)(Vg_UserMsg, " total: %u", n_Jccs);
218 VG_(message)(Vg_UserMsg, " %% taken: %u%%",
219 (n_Jccs - n_Jccs_untaken)*100 / n_Jccs);
220
221 VG_(message)(Vg_UserMsg, "");
222 VG_(message)(Vg_UserMsg, "Ratios:");
223 VG_(message)(Vg_UserMsg, " x86 instrs : BB = %3u : 10",
224 10 * n_x86_instrs / n_BBs);
225 VG_(message)(Vg_UserMsg, " UInstrs : BB = %3u : 10",
226 10 * n_UInstrs / n_BBs);
227 VG_(message)(Vg_UserMsg, " UInstrs : x86_instr = %3u : 10",
228 10 * n_UInstrs / n_x86_instrs);
229
230}
231
232/*--------------------------------------------------------------------*/
njn25cac76cb2002-09-23 11:21:57 +0000233/*--- end lk_main.c ---*/
njn25e49d8e72002-09-23 09:36:25 +0000234/*--------------------------------------------------------------------*/
235