~ubuntu-branches/ubuntu/trusty/eclipse-linuxtools/trusty

« back to all changes in this revision

Viewing changes to gprof/org.eclipse.linuxtools.gprof/src/org/eclipse/linuxtools/internal/gprof/parser/HistogramDecoder.java

  • Committer: Package Import Robot
  • Author(s): Jakub Adam
  • Date: 2012-06-29 12:07:30 UTC
  • Revision ID: package-import@ubuntu.com-20120629120730-bfri1xys1i71dpn6
Tags: upstream-1.0.0
Import upstream version 1.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*******************************************************************************
 
2
 * Copyright (c) 2009 STMicroelectronics.
 
3
 * All rights reserved. This program and the accompanying materials
 
4
 * are made available under the terms of the Eclipse Public License v1.0
 
5
 * which accompanies this distribution, and is available at
 
6
 * http://www.eclipse.org/legal/epl-v10.html
 
7
 *
 
8
 * Contributors:
 
9
 *   Xavier Raynaud <xavier.raynaud@st.com> - initial API and implementation
 
10
 *******************************************************************************/
 
11
package org.eclipse.linuxtools.internal.gprof.parser;
 
12
 
 
13
import java.io.DataInput;
 
14
import java.io.IOException;
 
15
import java.io.PrintStream;
 
16
 
 
17
import org.eclipse.cdt.core.IBinaryParser.ISymbol;
 
18
import org.eclipse.linuxtools.internal.gprof.symbolManager.Bucket;
 
19
import org.eclipse.linuxtools.internal.gprof.view.histogram.HistRoot;
 
20
 
 
21
 
 
22
/**
 
23
 * Reads the histogram in gmon files
 
24
 * @author Xavier Raynaud <xavier.raynaud@st.com>
 
25
 */
 
26
public class HistogramDecoder {
 
27
 
 
28
        private static final int GMON_HDRSIZE_BSD44 = (3 * 4);
 
29
 
 
30
        private static final int GMON_HDRSIZE_BSD44_32 = (4 + 4 + 4 + 4 + 4 + GMON_HDRSIZE_BSD44);
 
31
        private static final int GMON_HDRSIZE_BSD44_64 = (8 + 8 + 4 + 4 + 4 + GMON_HDRSIZE_BSD44);
 
32
        private static final int GMON_HDRSIZE_OLDBSD_32 = (4 + 4 + 4) ;
 
33
        private static final int GMON_HDRSIZE_OLDBSD_64 = (8 + 8 + 4);
 
34
 
 
35
        
 
36
        /** the decoder */
 
37
        protected final GmonDecoder decoder;
 
38
 
 
39
        // histogram header
 
40
        /** Base pc address of sampled buffer */
 
41
        protected long lowpc;
 
42
        /** Max pc address of sampled buffer */
 
43
        protected long highpc;
 
44
        /** Profiling clock rate */
 
45
        protected int prof_rate;
 
46
        /** physical dimension - usually "seconds" */
 
47
        protected String dimen;
 
48
        /** usually 's' for seconds, 'm' for milliseconds... */
 
49
        protected char dimen_abbrev;
 
50
        /** used when aggregate several gmon files */
 
51
        protected boolean initialized = false;
 
52
 
 
53
 
 
54
        /** Histogram samples (shorts in the file!). */
 
55
        protected int[] hist_sample;
 
56
        /** Total time for all routines.  */
 
57
        protected double total_time;
 
58
 
 
59
        protected long bucketSize;
 
60
 
 
61
 
 
62
        /**
 
63
         * Constructor 
 
64
         * @param decoder the Gmon decoder
 
65
         */
 
66
        public HistogramDecoder(GmonDecoder decoder) {
 
67
                this.decoder = decoder;
 
68
        }
 
69
        
 
70
        protected long readAddress(DataInput stream) throws IOException {
 
71
                long ret = stream.readInt() & 0xFFFFFFFFL;
 
72
                return ret;
 
73
        }
 
74
 
 
75
        public boolean hasValues() {
 
76
                return (this.hist_sample != null && this.hist_sample.length > 0);
 
77
        }
 
78
 
 
79
        /**
 
80
         * Decode the given stream
 
81
         * @param stream a DataInputStream, pointing on a histogram header in a gmon file.
 
82
         * @throws IOException if an IO error occurs
 
83
         */
 
84
        public void decodeHeader(DataInput stream) throws IOException {
 
85
                long lowpc        = readAddress(stream);
 
86
                long highpc       = readAddress(stream);
 
87
                int hist_num_bins = stream.readInt();
 
88
                int prof_rate     = stream.readInt();
 
89
                byte[] bytes      = new byte[15];
 
90
                stream.readFully(bytes);
 
91
                byte b            = stream.readByte();
 
92
 
 
93
                if (!isCompatible(lowpc, highpc, prof_rate, hist_num_bins))
 
94
                {
 
95
                        // TODO exception to normalize
 
96
                        throw new RuntimeException("Histogram header's incompatibility among gmon files");
 
97
                }
 
98
                this.lowpc     = lowpc;
 
99
                this.highpc    = highpc;
 
100
                this.prof_rate = prof_rate;
 
101
                hist_sample    = new int[hist_num_bins]; // Impl note: JVM sets all integers to 0
 
102
                dimen          = new String(bytes);
 
103
                dimen_abbrev   = (char) b;
 
104
                long temp = highpc - lowpc;
 
105
                bucketSize = Math.round(temp/(double)hist_num_bins);
 
106
        }
 
107
 
 
108
        /**
 
109
         * Decode the given stream
 
110
         * @param stream a DataInputStream, pointing on a histogram header in a gmon file.
 
111
         * @throws IOException if an IO error occurs
 
112
         */
 
113
        public void decodeOldHeader(DataInput stream) throws IOException {
 
114
                long low_pc = readAddress(stream);
 
115
                long high_pc = readAddress(stream);
 
116
                int ncnt = stream.readInt();
 
117
                int version = stream.readInt();
 
118
                int header_size;
 
119
                int profrate = 0;
 
120
                if (version == GmonDecoder.GMONVERSION)
 
121
                {
 
122
                        profrate = stream.readInt();
 
123
                        stream.skipBytes(GMON_HDRSIZE_BSD44);
 
124
                        if (decoder._32_bit_platform) {
 
125
                      header_size = GMON_HDRSIZE_BSD44_32;
 
126
                        } else {
 
127
                      header_size = GMON_HDRSIZE_BSD44_64;
 
128
                    }
 
129
                } else {
 
130
                  /* Old style BSD format.  */
 
131
                        if (decoder._32_bit_platform) {
 
132
                                header_size = GMON_HDRSIZE_OLDBSD_32;
 
133
                        } else {
 
134
                                header_size = GMON_HDRSIZE_OLDBSD_64;
 
135
                        }
 
136
                }
 
137
 
 
138
                int samp_bytes = ncnt - header_size;
 
139
                int hist_num_bins = samp_bytes / 2;
 
140
 
 
141
                if (!isCompatible(low_pc, high_pc, profrate, hist_num_bins))
 
142
                {
 
143
                        // TODO exception to normalize
 
144
                        throw new RuntimeException("Histogram header's incompatibility among gmon files");
 
145
                }
 
146
 
 
147
 
 
148
                this.lowpc     = low_pc;
 
149
                this.highpc    = high_pc;
 
150
                this.prof_rate = profrate;
 
151
                hist_sample    = new int[hist_num_bins]; // Impl note: JVM sets all integers to 0
 
152
                dimen          = "s";
 
153
                dimen_abbrev   = 's';
 
154
                long temp = highpc - lowpc;
 
155
                bucketSize = Math.round(temp/(double)hist_num_bins);
 
156
        }
 
157
        
 
158
 
 
159
        /**
 
160
         * Checks whether the gmon file currently parsed is compatible with the previous one (if any).
 
161
         * @param lowpc
 
162
         * @param highpc
 
163
         * @param profrate
 
164
         * @param sample_count
 
165
         * @return whether the gmon file currently parsed is compatible with the previous one (if any).
 
166
         */
 
167
        public boolean isCompatible(long lowpc, long highpc, int profrate, int sample_count) {
 
168
                if (!initialized) return true;
 
169
                return (
 
170
                                (this.lowpc     == lowpc) &&
 
171
                                (this.highpc    == highpc) &&
 
172
                                (this.prof_rate == profrate) &&
 
173
                                (this.hist_sample.length == sample_count)
 
174
                );
 
175
        }
 
176
 
 
177
 
 
178
 
 
179
        /**
 
180
         * Reads hitogram record
 
181
         * @param stream a DataInputStream, pointing just after histogram header in a gmon file.
 
182
         * @throws IOException if an IO error occurs
 
183
         */
 
184
        public void decodeHistRecord(DataInput stream) throws IOException {
 
185
                for (int i = 0; i<hist_sample.length; i++) {
 
186
                        short _rv = stream.readShort();
 
187
                        if (_rv != 0) {
 
188
                                int hist_size = (_rv & 0xFFFF);
 
189
                                hist_sample[i] += hist_size;
 
190
                        }
 
191
                }
 
192
        }
 
193
 
 
194
 
 
195
        /**
 
196
         * Print the histogram header, for debug usage.
 
197
         * @param ps a printstream (typically System.out)
 
198
         */
 
199
        public void printHistHeader(PrintStream ps)
 
200
        {
 
201
                ps.println(" \nHistogram Header : \n");
 
202
                ps.print("  Base pc address of sample buffer = 0x");
 
203
                ps.println(Long.toHexString(lowpc));
 
204
                ps.print("  Max pc address of sampled buffer = 0x");
 
205
                ps.println(Long.toHexString(highpc));
 
206
                ps.print("  Number of histogram samples      = ");
 
207
                ps.println(hist_sample.length);
 
208
                ps.print("  Profiling clock rate             = ");
 
209
                ps.println(prof_rate);
 
210
//              ps.print("  Physical dimension usually \"seconds\" = ");
 
211
//              ps.println(dimen);
 
212
                ps.print("  Physical dimension abreviation : 's' for \"seconds\"  'm' for \"milliseconds\" = ");
 
213
                ps.println(dimen_abbrev);
 
214
        }
 
215
 
 
216
        /**
 
217
         * Print the histogram, for debug usage.
 
218
         * @param ps a printstream (typically System.out)
 
219
         */
 
220
        public void printHistRecords(PrintStream ps) {
 
221
                ps.println();
 
222
                ps.println(" ==  HISTOGRAM RECORDS  == ");
 
223
                ps.println(" ========================= ");
 
224
 
 
225
                printHistHeader(ps);
 
226
 
 
227
                /*ps.println(" \nHistogram Samples : ");
 
228
        ISymbol[] symbols = this.decoder.getProgram().getSymbols();
 
229
        for (ISymbol iSymbol : symbols) {
 
230
                        ps.println(iSymbol.getName() + "\t" + iSymbol.getAddress());
 
231
                }
 
232
        for (int i = 0; i<hist_sample.length; i++) {
 
233
                ps.println("histSample[" + i + "]\t" + hist_sample[i]);
 
234
        }*/
 
235
        }
 
236
 
 
237
        /**
 
238
         * Assign the hits to the given symbols
 
239
         * @param symblist 
 
240
         */
 
241
        public void AssignSamplesSymbol()
 
242
        {
 
243
                if (hist_sample == null || hist_sample.length == 0) return;
 
244
                ISymbol[] symblist = this.decoder.getProgram().getSymbols();
 
245
                /* read samples and assign to namelist symbols */
 
246
                int j = 1;
 
247
                for (int i = 0; i < hist_sample.length; i++)
 
248
                {
 
249
                        int ccnt = hist_sample[i];
 
250
                        if (ccnt != 0)
 
251
                        {
 
252
                                long pcl = lowpc + (bucketSize*i);
 
253
                                long pch = pcl+bucketSize;
 
254
                                total_time += ccnt;
 
255
                                long svalue0;
 
256
                                long svalue1 = symblist[j-1].getAddress().getValue().longValue();
 
257
                                for (j = j-1; j < symblist.length - 1; j++)
 
258
                                {
 
259
                                        svalue0 = svalue1;
 
260
                                        svalue1 = symblist[j+1].getAddress().getValue().longValue();
 
261
                                        /* if high end of tick is below entry address,
 
262
                                         * go for next tick. */
 
263
                                        if(pch < svalue0)
 
264
                                                break;
 
265
                                        /* if low end of tick into next routine,
 
266
                                         * go for next routine. */
 
267
                                        if(pcl < svalue1)
 
268
                                        {   
 
269
                                                long start_addr = pcl>svalue0?pcl:svalue0;
 
270
                                                long end_addr   = pch<svalue1?pch:svalue1;
 
271
                                                long overlap = end_addr - start_addr;
 
272
                                                if(overlap > 0)
 
273
                                                {
 
274
                                                        ISymbol symbol = symblist[j];
 
275
                                                        int time = (int) ((overlap * ccnt) / bucketSize);
 
276
                                                        Bucket   bck = new Bucket(start_addr, end_addr, time);
 
277
                                                        addBucket(bck,symbol);
 
278
                                                }
 
279
                                        }
 
280
                                }
 
281
                        }
 
282
                }
 
283
        }
 
284
 
 
285
        private void addBucket(Bucket b, ISymbol s) {
 
286
                HistRoot root = this.decoder.getRootNode();
 
287
                root.addBucket(b, s, decoder.getProgram());
 
288
        }
 
289
 
 
290
        /**
 
291
         * @return the prof_rate
 
292
         */
 
293
        public int getProf_rate() {
 
294
                return prof_rate;
 
295
        }
 
296
 
 
297
        /**
 
298
         * 
 
299
         * @return 's' for seconds, 'm' for ms, 'u' for �s....
 
300
         */
 
301
        public char getTimeDimension() {
 
302
                return dimen_abbrev;
 
303
        }
 
304
 
 
305
        /**
 
306
         * get the bucket size
 
307
         */
 
308
        public long getBucketSize(){
 
309
                return bucketSize;
 
310
        }
 
311
        
 
312
        
 
313
        
 
314
        
 
315
}