~arosales/test/oprofile

« back to all changes in this revision

Viewing changes to oprofile-0.9.8/libpp/op_header.cpp

  • Committer: Antonio Rosales
  • Date: 2013-03-28 07:58:44 UTC
  • Revision ID: antonio.rosales@canonical.com-20130328075844-06zfzvz4x6imekpx
Initial commit

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/**
 
2
 * @file op_header.cpp
 
3
 * various free function acting on a sample file header
 
4
 *
 
5
 * @remark Copyright 2004 OProfile authors
 
6
 * @remark Read the file COPYING
 
7
 *
 
8
 * @author John Levon
 
9
 * @author Philippe Elie
 
10
 * @Modifications Daniel Hansel
 
11
 */
 
12
 
 
13
#include <cstring>
 
14
#include <iostream>
 
15
#include <cstdlib>
 
16
#include <iomanip>
 
17
#include <set>
 
18
#include <sstream>
 
19
#include <cstring>
 
20
 
 
21
#include <sys/types.h>
 
22
#include <sys/stat.h>
 
23
#include <fcntl.h>
 
24
#include <unistd.h>
 
25
 
 
26
#include "op_config.h"
 
27
#include "op_exception.h"
 
28
#include "odb.h"
 
29
#include "op_cpu_type.h"
 
30
#include "op_file.h"
 
31
#include "op_header.h"
 
32
#include "op_events.h"
 
33
#include "string_manip.h"
 
34
#include "format_output.h"
 
35
#include "xml_utils.h"
 
36
#include "cverb.h"
 
37
 
 
38
using namespace std;
 
39
 
 
40
extern verbose vbfd;
 
41
 
 
42
void op_check_header(opd_header const & h1, opd_header const & h2,
 
43
                     string const & filename)
 
44
{
 
45
        if (h1.mtime != h2.mtime) {
 
46
                ostringstream os;
 
47
                os << "header timestamps are different ("
 
48
                   << h1.mtime << ", " << h2.mtime << ") for "
 
49
                   << filename << "\n";
 
50
                throw op_fatal_error(os.str());
 
51
        }
 
52
 
 
53
        if (h1.is_kernel != h2.is_kernel) {
 
54
                ostringstream os;
 
55
                os << "header is_kernel flags are different for "
 
56
                   << filename << "\n";
 
57
                throw op_fatal_error(os.str());
 
58
        }
 
59
        
 
60
        // Note that in the generated ELF file for anonymous code the vma
 
61
        // of the symbol is exaclty the same vma as the code had during sampling.
 
62
        
 
63
        // Note that we don't check CPU speed since that can vary
 
64
        // freely on the same machine
 
65
}
 
66
 
 
67
 
 
68
namespace {
 
69
 
 
70
set<string> warned_files;
 
71
 
 
72
}
 
73
 
 
74
bool is_jit_sample(string const & filename)
 
75
{
 
76
        // suffix for JIT sample files (see FIXME in check_mtime() below)
 
77
        string suf = ".jo";
 
78
        
 
79
        string::size_type pos;
 
80
        pos = filename.rfind(suf);
 
81
        // for JIT sample files do not output the warning to stderr.
 
82
        if (pos != string::npos && pos == filename.size() - suf.size())
 
83
                return true;
 
84
        else
 
85
                return false;
 
86
}
 
87
 
 
88
void check_mtime(string const & file, opd_header const & header)
 
89
{
 
90
        u64 newmtime = op_get_mtime(file.c_str());
 
91
 
 
92
        if (newmtime == header.mtime)
 
93
                return;
 
94
 
 
95
        if (warned_files.find(file) != warned_files.end())
 
96
                return;
 
97
 
 
98
        warned_files.insert(file);
 
99
 
 
100
        // Files we couldn't get mtime of have zero mtime
 
101
        if (!header.mtime) {
 
102
                // FIXME: header.mtime for JIT sample files is 0. The problem could be that
 
103
                //        in opd_mangling.c:opd_open_sample_file() the call of fill_header()
 
104
                //        think that the JIT sample file is not a binary file.
 
105
                if (is_jit_sample(file)) {
 
106
                        cverb << vbfd << "warning: could not check that the binary file "
 
107
                              << file << " has not been modified since "
 
108
                              "the profile was taken. Results may be inaccurate.\n";
 
109
                } else {
 
110
                        cerr << "warning: could not check that the binary file "
 
111
                             << file << " has not been modified since "
 
112
                             "the profile was taken. Results may be inaccurate.\n";
 
113
                }
 
114
        } else {
 
115
                static bool warned_already = false;
 
116
 
 
117
                cerr << "warning: the last modified time of the binary file "
 
118
                     "does not match that of the sample file for " << file
 
119
                     << "\n";
 
120
 
 
121
                if (!warned_already) {
 
122
                        cerr << "Either this is the wrong binary or the binary "
 
123
                        "has been modified since the sample file was created.\n";
 
124
                        warned_already = true;
 
125
                }
 
126
        }
 
127
}
 
128
 
 
129
 
 
130
opd_header const read_header(string const & sample_filename)
 
131
{
 
132
        int fd = open(sample_filename.c_str(), O_RDONLY);
 
133
        if (fd < 0)
 
134
                throw op_fatal_error("Can't open sample file:" +
 
135
                                     sample_filename);
 
136
 
 
137
        opd_header header;
 
138
        if (read(fd, &header, sizeof(header)) != sizeof(header)) {
 
139
                close(fd);
 
140
                throw op_fatal_error("Can't read sample file header:" +
 
141
                                     sample_filename);
 
142
        }
 
143
 
 
144
        if (memcmp(header.magic, OPD_MAGIC, sizeof(header.magic))) {
 
145
                close(fd);
 
146
                throw op_fatal_error("Invalid sample file, "
 
147
                                     "bad magic number: " +
 
148
                                     sample_filename);
 
149
        }
 
150
 
 
151
        close(fd);
 
152
 
 
153
        return header;
 
154
}
 
155
 
 
156
 
 
157
namespace {
 
158
 
 
159
string const op_print_event(op_cpu cpu_type, u32 type, u32 um, u32 count)
 
160
{
 
161
        string str;
 
162
 
 
163
        if (cpu_type == CPU_TIMER_INT) {
 
164
                str += "Profiling through timer interrupt";
 
165
                return str;
 
166
        }
 
167
 
 
168
        struct op_event * event = op_find_event(cpu_type, type, um);
 
169
 
 
170
        if (!event) {
 
171
                event = op_find_event_any(cpu_type, type);
 
172
                if (!event) { 
 
173
                        cerr << "Could not locate event " << int(type) << endl;
 
174
                        str = "Unknown event";
 
175
                        return str;
 
176
                }
 
177
        }
 
178
 
 
179
        char const * um_desc = 0;
 
180
 
 
181
        for (size_t i = 0; i < event->unit->num; ++i) {
 
182
                if (event->unit->um[i].value == um)
 
183
                        um_desc = event->unit->um[i].desc;
 
184
        }
 
185
 
 
186
        str += string("Counted ") + event->name;
 
187
        str += string(" events (") + event->desc + ")";
 
188
 
 
189
        if (cpu_type != CPU_RTC) {
 
190
                str += " with a unit mask of 0x";
 
191
 
 
192
                ostringstream ss;
 
193
                ss << hex << setw(2) << setfill('0') << unsigned(um);
 
194
                str += ss.str();
 
195
 
 
196
                str += " (";
 
197
                str += um_desc ? um_desc : "multiple flags";
 
198
                str += ")";
 
199
        }
 
200
 
 
201
        str += " count " + op_lexical_cast<string>(count);
 
202
        return str;
 
203
}
 
204
 
 
205
string const op_xml_print_event(op_cpu cpu_type, u32 type, u32 um, u32 count)
 
206
{
 
207
        string unit_mask;
 
208
 
 
209
        if (cpu_type == CPU_TIMER_INT || cpu_type == CPU_RTC)
 
210
                return xml_utils::get_timer_setup((size_t)count);
 
211
 
 
212
        struct op_event * event = op_find_event(cpu_type, type, um);
 
213
        if (!event) {
 
214
                event = op_find_event_any(cpu_type, type);
 
215
                if (!event) { 
 
216
                        cerr << "Could not locate event " << int(type) << endl;
 
217
                        return "";
 
218
                }
 
219
        }
 
220
 
 
221
        if (cpu_type != CPU_RTC) {
 
222
                ostringstream str_out;
 
223
                str_out << um;
 
224
                unit_mask = str_out.str();
 
225
        }
 
226
 
 
227
        return xml_utils::get_event_setup(string(event->name),
 
228
                (size_t)count, unit_mask);
 
229
}
 
230
 
 
231
}
 
232
 
 
233
string const describe_header(opd_header const & header)
 
234
{
 
235
        op_cpu cpu = static_cast<op_cpu>(header.cpu_type);
 
236
 
 
237
        if (want_xml)
 
238
                return op_xml_print_event(cpu, header.ctr_event,
 
239
                              header.ctr_um, header.ctr_count);
 
240
        else
 
241
                return op_print_event(cpu, header.ctr_event,
 
242
                              header.ctr_um, header.ctr_count);
 
243
}
 
244
 
 
245
 
 
246
string const describe_cpu(opd_header const & header)
 
247
{
 
248
        op_cpu cpu = static_cast<op_cpu>(header.cpu_type);
 
249
 
 
250
        string str;
 
251
        if (want_xml) {
 
252
                string cpu_name = op_get_cpu_name(cpu);
 
253
 
 
254
                str = xml_utils::get_profile_header(cpu_name, header.cpu_speed);
 
255
        } else {
 
256
                str += string("CPU: ") + op_get_cpu_type_str(cpu);
 
257
                if (header.cpu_speed > 0) {
 
258
                        ostringstream ss;
 
259
 
 
260
                        str += ", speed ";
 
261
                        ss << header.cpu_speed;
 
262
                        str += ss.str() + " MHz (estimated)";
 
263
                }
 
264
        }
 
265
        return str;
 
266
}