• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
31 using namespace std;
32 
33 namespace {
34 	string output_filename;
35 	string abi_filename;
36 	bool verbose;
37 	bool force;
38 };
39 
40 
41 popt::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 
49 struct extractor {
50 
51 	abi const & theabi;
52 
53 	unsigned char const * begin;
54 	unsigned char const * end;
55 	bool little_endian;
56 
57 	explicit
extractorextractor58 	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 
74 template <typename T>
extract(T & targ,void const * src_,char const * sz,char const * off)75 void 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 	targ = 0;
83 	if (nbytes == 0)
84 		return;
85 
86 	assert(nbytes <= sizeof(T));
87 	assert(src >= begin);
88 	assert(src + nbytes <= end);
89 
90 	if (verbose)
91 		cerr << hex << "get " << sz << " = " << nbytes
92 		     << " bytes @ " << off << " = " << (src - begin)
93 		     << " : ";
94 
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 
import_from_abi(abi const & abi,void const * srcv,size_t len,odb_t * dest)107 void 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 
main(int argc,char const ** argv)168 int 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 	in_fd = open(inputs[0].c_str(), O_RDONLY);
204 	assert(in_fd > 0);
205 	rc = fstat(in_fd, &statb);
206 	assert(rc == 0);
207 	in = mmap(0, statb.st_size, PROT_READ, MAP_PRIVATE, in_fd, 0);
208 	assert(in != (void *)-1);
209 
210 	rc = odb_open(&dest, output_filename.c_str(), ODB_RDWR,
211 		      sizeof(struct opd_header));
212 	if (rc) {
213 		cerr << "odb_open() fail:\n"
214 		     << strerror(rc) << endl;
215 		exit(EXIT_FAILURE);
216 	}
217 
218 	try {
219 		import_from_abi(input_abi, in, statb.st_size, &dest);
220 	} catch (abi_exception & e) {
221 		cerr << "caught abi exception: " << e.desc << endl;
222 	}
223 
224 	odb_close(&dest);
225 
226 	rc = munmap(in, statb.st_size);
227 	assert(rc == 0);
228 }
229