Commit | Line | Data |
---|---|---|
920dae64 AT |
1 | /* |
2 | * ========== Copyright Header Begin ========================================== | |
3 | * | |
4 | * OpenSPARC T2 Processor File: coverage_dump.c | |
5 | * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. | |
6 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES. | |
7 | * | |
8 | * The above named program is free software; you can redistribute it and/or | |
9 | * modify it under the terms of the GNU General Public | |
10 | * License version 2 as published by the Free Software Foundation. | |
11 | * | |
12 | * The above named program is distributed in the hope that it will be | |
13 | * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
15 | * General Public License for more details. | |
16 | * | |
17 | * You should have received a copy of the GNU General Public | |
18 | * License along with this work; if not, write to the Free Software | |
19 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. | |
20 | * | |
21 | * ========== Copyright Header End ============================================ | |
22 | */ | |
23 | /* | |
24 | * Copyright 2006 Sun Microsystems, Inc. All rights reserved. | |
25 | * Use is subject to license terms. | |
26 | */ | |
27 | #pragma ident "@(#)coverage_dump.c 1.6 06/10/25 SMI" | |
28 | ||
29 | #include <stdio.h> | |
30 | #include <stdlib.h> | |
31 | #include <unistd.h> | |
32 | #include <sys/types.h> | |
33 | #include <sys/stat.h> | |
34 | #include <assert.h> | |
35 | #include <string.h> | |
36 | #include <strings.h> | |
37 | #include <fcntl.h> | |
38 | ||
39 | #include "basics.h" | |
40 | #include "fatal.h" | |
41 | #include "coverage.h" | |
42 | ||
43 | #if 1 | |
44 | #define DBGP(s) do { s } while (0) | |
45 | #endif | |
46 | ||
47 | void | |
48 | usage(void) | |
49 | { | |
50 | printf("\nUsage: coverage_dump [- a] [-z] [-c num_samples] "\ | |
51 | "[-r] [-v] [-t] filename" \ | |
52 | "\n [-a | --all]" \ | |
53 | "\n - dump all samples (zero and non-zero)" \ | |
54 | "\n [-z | --zero]" \ | |
55 | "\n - dump only zero samples (%%pc never hit)" \ | |
56 | "\n [-c | --count num_of_samples]" \ | |
57 | "\n - dump first num_of_samples %%pc samples" \ | |
58 | "\n - if this option is not given, all non-zero "\ | |
59 | "samples are dumped " \ | |
60 | "\n [-r | --ref]" \ | |
61 | "\n - don't increment the ref count for each "\ | |
62 | "access to a %%pc "\ | |
63 | "\n instead print 0x1 (if it was ever executed) "\ | |
64 | "\n or a 0x0 (if it was never executed) "\ | |
65 | "\n [-v | --verbose]" \ | |
66 | "\n - decode and display the raw instns" \ | |
67 | "\n by default, only the raw instn gets dumped" \ | |
68 | "\n [-t | --titles]" \ | |
69 | "\n - print titles and footer " \ | |
70 | "\n " \ | |
71 | "\n filename" \ | |
72 | "\n The name of file with legion coverage data" \ | |
73 | "\n " \ | |
74 | "\n When run with no options, dump all non-zero samples" \ | |
75 | "\n " \ | |
76 | "\n This tool is meant to work with the debug_hook feature" \ | |
77 | "\n for gathering coverage data. You need to" \ | |
78 | "\n specify a range of %%pc addresses in the conf file " \ | |
79 | "\n under the cpu directive as follows:" \ | |
80 | "\n " \ | |
81 | "\n debug_hook coverage 0x100000 0x800000;" \ | |
82 | "\n " \ | |
83 | "\n"); | |
84 | } | |
85 | ||
86 | bool_t | |
87 | streq(char *a, char *b) | |
88 | { | |
89 | return (strcmp(a, b) == 0); | |
90 | } | |
91 | ||
92 | /* | |
93 | * Attach to shared memory created by legion and | |
94 | * dump out coverage statistics from the running | |
95 | * system. | |
96 | */ | |
97 | int | |
98 | main(int argc, char ** argv) | |
99 | { | |
100 | uint64_t buf_size; | |
101 | uint64_t dump_count = 0; | |
102 | uint64_t sample_count; | |
103 | uint64_t low_pc = 0; | |
104 | uint64_t high_pc = 0; | |
105 | uint64_t i; | |
106 | bool_t dump_all_samples = false; | |
107 | bool_t dump_zero_samples = false; | |
108 | bool_t verbose = false; | |
109 | bool_t titles = false; | |
110 | bool_t ref_only = false; | |
111 | char instn_buf[160]; | |
112 | bool_t print_it = false; | |
113 | char filename[256]; | |
114 | int fd; | |
115 | struct stat sb; | |
116 | uint64_t num_of_pcs = 0; | |
117 | coverage_info_t coverage_buf; | |
118 | ||
119 | ||
120 | ||
121 | for (i = 1; i < argc && argv[i][0] == '-'; i++) { | |
122 | char *p; | |
123 | ||
124 | p = &(argv[i][1]); | |
125 | ||
126 | if (streq(p, "a") || streq(p, "-all")) { | |
127 | if (dump_zero_samples) { | |
128 | printf("\nERROR: Cannot use both -a and -z"); | |
129 | usage(); | |
130 | exit(1); | |
131 | } | |
132 | dump_all_samples = true; | |
133 | } else | |
134 | if (streq(p, "z") || streq(p, "-zero")) { | |
135 | if (dump_all_samples) { | |
136 | printf("\nERROR: Cannot use both -a and -z"); | |
137 | usage(); | |
138 | exit(1); | |
139 | } | |
140 | dump_zero_samples = true; | |
141 | } else | |
142 | if (streq(p, "c") || streq(p, "-count")) { | |
143 | if (++i >= argc) { | |
144 | usage(); | |
145 | exit(1); | |
146 | } | |
147 | dump_count = atol(argv[i]); | |
148 | if (dump_count == 0) { | |
149 | printf("\nERROR: Invalid value for count"); | |
150 | usage(); | |
151 | exit(1); | |
152 | } | |
153 | } else | |
154 | if (streq(p, "r") || streq(p, "-ref")) { | |
155 | ref_only = true; | |
156 | } else | |
157 | if (streq(p, "v") || streq(p, "-verbose")) { | |
158 | verbose = true; | |
159 | } else | |
160 | if (streq(p, "t") || streq(p, "-titles")) { | |
161 | titles = true; | |
162 | } else { | |
163 | printf("\nERROR: Illegal option %s", p); | |
164 | usage(); | |
165 | exit(1); | |
166 | } | |
167 | } | |
168 | ||
169 | /* | |
170 | * Assume any non option provided is the name of the coverage | |
171 | * data file. | |
172 | */ | |
173 | if (i == (argc - 1)) { | |
174 | strcpy(filename, argv[i]); | |
175 | } else { | |
176 | printf("\nERROR: no filename specified"); | |
177 | usage(); | |
178 | exit(1); | |
179 | } | |
180 | ||
181 | ||
182 | /* | |
183 | * Open the dump_file and get it's size. | |
184 | * | |
185 | * In order to figure out how many samples are in this file | |
186 | * we divide the file size by the size of this struct. | |
187 | * We can then then either dump them all, or dump just the first n | |
188 | * if the -c flag is specified. | |
189 | */ | |
190 | if (stat(filename, &sb) == -1) | |
191 | fatal("Error: dump_file %s does not exist.", filename); | |
192 | ||
193 | sample_count = (sb.st_size / (sizeof (coverage_info_t))); | |
194 | ||
195 | if ((fd = open(filename, O_RDONLY)) == -1) | |
196 | fatal("Could not open dump_file %s\n", filename); | |
197 | ||
198 | /* | |
199 | * Depending on whether a specific number of samples was | |
200 | * given at the command line or not, we either dump them | |
201 | * all or just the first n samples. | |
202 | * The -a flag determines whether we print the zero samples. | |
203 | * The -z flag determines whether we only print the zero samples. | |
204 | */ | |
205 | if (dump_count != 0) { | |
206 | num_of_pcs = dump_count; /* value from command line */ | |
207 | } else { | |
208 | num_of_pcs = sample_count; | |
209 | } | |
210 | ||
211 | if (titles) { | |
212 | printf("\nOpened data file : [%s] ", filename); | |
213 | printf("\nSize of file in bytes : [0x%llx] ", sb.st_size); | |
214 | printf("\nNumber of %%pc samples : [0x%llx] ", sample_count); | |
215 | printf("\nIndx:%%pc:Ref_Cnt:Raw_Instn Decoded_Inst\n"); | |
216 | } | |
217 | ||
218 | for (i = 0; i < num_of_pcs; i++) { | |
219 | ||
220 | /* Read from the file */ | |
221 | if (read(fd, &coverage_buf, sizeof (coverage_info_t)) != | |
222 | sizeof (coverage_info_t)) { | |
223 | perror("read"); | |
224 | fatal("Error reading from file %s\n", filename); | |
225 | } | |
226 | ||
227 | /* Gather stats for the end */ | |
228 | if (coverage_buf.count != 0) { | |
229 | /* save the last non-zero count %pc */ | |
230 | high_pc = coverage_buf.pc; | |
231 | if (low_pc == 0) { | |
232 | /* save the first non-zero count %pc */ | |
233 | low_pc = coverage_buf.pc; | |
234 | } | |
235 | } | |
236 | ||
237 | /* Figure out whether to print this sample or not */ | |
238 | print_it = false; | |
239 | ||
240 | if (dump_all_samples) { | |
241 | print_it = true; | |
242 | } else if (dump_zero_samples) { | |
243 | if (coverage_buf.count == 0) | |
244 | print_it = true; | |
245 | } else if (coverage_buf.count != 0) { | |
246 | print_it = true; | |
247 | } | |
248 | ||
249 | if (print_it) { | |
250 | ||
251 | if (ref_only) { | |
252 | if (coverage_buf.count > 0x1) | |
253 | coverage_buf.count = 0x1; /* reset to 0x1 */ | |
254 | } | |
255 | ||
256 | printf("0x%llx:0x%llx:0x%x:0x%08x", | |
257 | i, coverage_buf.pc, coverage_buf.count, | |
258 | coverage_buf.rawi); | |
259 | ||
260 | if (verbose) { | |
261 | if (coverage_buf.count != 0) { | |
262 | sparcv9_idis(instn_buf, sizeof (instn_buf), | |
263 | coverage_buf.rawi, coverage_buf.pc); | |
264 | } else { | |
265 | sprintf(instn_buf, ":N/A", "%s"); | |
266 | } | |
267 | printf(":%s", instn_buf); | |
268 | } | |
269 | printf("\n"); | |
270 | } | |
271 | ||
272 | } | |
273 | ||
274 | if (titles) { | |
275 | printf("\nLoweset/Highest %%pc : [0x%llx] [0x%llx]\n", | |
276 | low_pc, high_pc); | |
277 | } | |
278 | ||
279 | close(fd); | |
280 | ||
281 | return (0); | |
282 | } |