opimport.cpp revision 10e23eebca4175a8dfe3a788b2bebacb1fcfce54
1/**
2 * @file opimport.cpp
3 * Import sample files from other ABI
4 *
5 * @remark Copyright 2002 OProfile authors
6 * @remark Read the file COPYING
7 *
8 * @author Graydon Hoare
9 */
10
11#include "abi.h"
12#include "odb.h"
13#include "popt_options.h"
14#include "op_sample_file.h"
15
16#include <fstream>
17#include <iostream>
18#include <vector>
19#include <cassert>
20#include <cstring>
21#include <cstdlib>
22
23#include <sys/types.h>
24#include <sys/stat.h>
25#include <fcntl.h>
26#include <unistd.h>
27#include <sys/mman.h>
28#include <cstdlib>
29#include <cstring>
30
31using namespace std;
32
33namespace {
34	string output_filename;
35	string abi_filename;
36	bool verbose;
37	bool force;
38};
39
40
41popt::option options_array[] = {
42	popt::option(verbose, "verbose", 'V', "verbose output"),
43	popt::option(output_filename, "output", 'o', "output to file", "filename"),
44	popt::option(abi_filename, "abi", 'a', "abi description", "filename"),
45	popt::option(force, "force", 'f', "force conversion, even if identical")
46};
47
48
49struct extractor {
50
51	abi const & theabi;
52
53	unsigned char const * begin;
54	unsigned char const * end;
55	bool little_endian;
56
57	explicit
58	extractor(abi const & a, unsigned char const * src, size_t len)
59		: theabi(a), begin(src), end(src + len) {
60		little_endian = theabi.need(string("little_endian")) == 1;
61		if (verbose) {
62			cerr << "source byte order is: "
63			     << string(little_endian ? "little" : "big")
64			     << " endian" << endl;
65		}
66	}
67
68	template <typename T>
69	void extract(T & targ, void const * src_,
70	             char const * sz, char const * off);
71};
72
73
74template <typename T>
75void extractor::extract(T & targ, void const * src_,
76                        char const * sz, char const * off)
77{
78	unsigned char const * src = static_cast<unsigned char const *>(src_)
79		+ theabi.need(off);
80	size_t nbytes = theabi.need(sz);
81
82	if (nbytes == 0)
83		return;
84
85	assert(nbytes <= sizeof(T));
86	assert(src >= begin);
87	assert(src + nbytes <= end);
88
89	if (verbose)
90		cerr << hex << "get " << sz << " = " << nbytes
91		     << " bytes @ " << off << " = " << (src - begin)
92		     << " : ";
93
94	targ = 0;
95	if (little_endian)
96		while(nbytes--)
97			targ = (targ << 8) | src[nbytes];
98	else
99		for(size_t i = 0; i < nbytes; ++i)
100			targ = (targ << 8) | src[i];
101
102	if (verbose)
103		cerr << " = " << targ << endl;
104}
105
106
107void import_from_abi(abi const & abi, void const * srcv,
108                     size_t len, odb_t * dest) throw (abi_exception)
109{
110	struct opd_header * head =
111		static_cast<opd_header *>(odb_get_data(dest));
112	unsigned char const * src = static_cast<unsigned char const *>(srcv);
113	unsigned char const * const begin = src;
114	extractor ext(abi, src, len);
115
116	memcpy(head->magic, src + abi.need("offsetof_header_magic"), 4);
117
118	// begin extracting opd header
119	ext.extract(head->version, src, "sizeof_u32", "offsetof_header_version");
120	ext.extract(head->cpu_type, src, "sizeof_u32", "offsetof_header_cpu_type");
121	ext.extract(head->ctr_event, src, "sizeof_u32", "offsetof_header_ctr_event");
122	ext.extract(head->ctr_um, src, "sizeof_u32", "offsetof_header_ctr_um");
123	ext.extract(head->ctr_count, src, "sizeof_u32", "offsetof_header_ctr_count");
124	ext.extract(head->is_kernel, src, "sizeof_u32", "offsetof_header_is_kernel");
125	// "double" extraction is unlikely to work
126	head->cpu_speed = 0.0;
127	ext.extract(head->mtime, src, "sizeof_time_t", "offsetof_header_mtime");
128	ext.extract(head->cg_to_is_kernel, src, "sizeof_u32",
129		"offsetof_header_cg_to_is_kernel");
130	ext.extract(head->anon_start, src, "sizeof_u32",
131		"offsetof_header_anon_start");
132	ext.extract(head->cg_to_anon_start, src, "sizeof_u32",
133		"offsetof_header_cg_to_anon_start");
134	src += abi.need("sizeof_struct_opd_header");
135	// done extracting opd header
136
137	// begin extracting necessary parts of descr
138	odb_node_nr_t node_nr;
139	ext.extract(node_nr, src, "sizeof_odb_node_nr_t", "offsetof_descr_current_size");
140	src += abi.need("sizeof_odb_descr_t");
141	// done extracting descr
142
143	// skip node zero, it is reserved and contains nothing usefull
144	src += abi.need("sizeof_odb_node_t");
145
146	// begin extracting nodes
147	unsigned int step = abi.need("sizeof_odb_node_t");
148	if (verbose)
149		cerr << "extracting " << node_nr << " nodes of " << step << " bytes each " << endl;
150
151	assert(src + (node_nr * step) <= begin + len);
152
153	for (odb_node_nr_t i = 1 ; i < node_nr ; ++i, src += step) {
154		odb_key_t key;
155		odb_value_t val;
156		ext.extract(key, src, "sizeof_odb_key_t", "offsetof_node_key");
157		ext.extract(val, src, "sizeof_odb_value_t", "offsetof_node_value");
158		int rc = odb_add_node(dest, key, val);
159		if (rc != EXIT_SUCCESS) {
160			cerr << strerror(rc) << endl;
161			exit(EXIT_FAILURE);
162		}
163	}
164	// done extracting nodes
165}
166
167
168int main(int argc, char const ** argv)
169{
170
171	vector<string> inputs;
172	popt::parse_options(argc, argv, inputs);
173
174	if (inputs.size() != 1) {
175		cerr << "error: must specify exactly 1 input file" << endl;
176		exit(1);
177	}
178
179	abi current_abi, input_abi;
180
181	{
182		ifstream abi_file(abi_filename.c_str());
183		if (!abi_file) {
184			cerr << "error: cannot open abi file "
185			     << abi_filename << endl;
186			exit(1);
187		}
188		abi_file >> input_abi;
189	}
190
191	if (!force && current_abi == input_abi) {
192		cerr << "input abi is identical to native. "
193		     << "no conversion necessary." << endl;
194		exit(1);
195	}
196
197	int in_fd;
198	struct stat statb;
199	void * in;
200	odb_t dest;
201	int rc;
202
203	assert((in_fd = open(inputs[0].c_str(), O_RDONLY)) > 0);
204	assert(fstat(in_fd, &statb) == 0);
205	assert((in = mmap(0, statb.st_size, PROT_READ,
206			  MAP_PRIVATE, in_fd, 0)) != (void *)-1);
207
208	rc = odb_open(&dest, output_filename.c_str(), ODB_RDWR,
209		      sizeof(struct opd_header));
210	if (rc) {
211		cerr << "odb_open() fail:\n"
212		     << strerror(rc) << endl;
213		exit(EXIT_FAILURE);
214	}
215
216	try {
217		import_from_abi(input_abi, in, statb.st_size, &dest);
218	} catch (abi_exception & e) {
219		cerr << "caught abi exception: " << e.desc << endl;
220	}
221
222	odb_close(&dest);
223
224	assert(munmap(in, statb.st_size) == 0);
225}
226