/** * @file opimport.cpp * Import sample files from other ABI * * @remark Copyright 2002 OProfile authors * @remark Read the file COPYING * * @author Graydon Hoare */ #include "abi.h" #include "odb.h" #include "popt_options.h" #include "op_sample_file.h" #include <fstream> #include <iostream> #include <vector> #include <cassert> #include <cstring> #include <cstdlib> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> #include <sys/mman.h> #include <cstdlib> #include <cstring> using namespace std; namespace { string output_filename; string abi_filename; bool verbose; bool force; }; popt::option options_array[] = { popt::option(verbose, "verbose", 'V', "verbose output"), popt::option(output_filename, "output", 'o', "output to file", "filename"), popt::option(abi_filename, "abi", 'a', "abi description", "filename"), popt::option(force, "force", 'f', "force conversion, even if identical") }; struct extractor { abi const & theabi; unsigned char const * begin; unsigned char const * end; bool little_endian; explicit extractor(abi const & a, unsigned char const * src, size_t len) : theabi(a), begin(src), end(src + len) { little_endian = theabi.need(string("little_endian")) == 1; if (verbose) { cerr << "source byte order is: " << string(little_endian ? "little" : "big") << " endian" << endl; } } template <typename T> void extract(T & targ, void const * src_, char const * sz, char const * off); }; template <typename T> void extractor::extract(T & targ, void const * src_, char const * sz, char const * off) { unsigned char const * src = static_cast<unsigned char const *>(src_) + theabi.need(off); size_t nbytes = theabi.need(sz); if (nbytes == 0) return; assert(nbytes <= sizeof(T)); assert(src >= begin); assert(src + nbytes <= end); if (verbose) cerr << hex << "get " << sz << " = " << nbytes << " bytes @ " << off << " = " << (src - begin) << " : "; targ = 0; if (little_endian) while(nbytes--) targ = (targ << 8) | src[nbytes]; else for(size_t i = 0; i < nbytes; ++i) targ = (targ << 8) | src[i]; if (verbose) cerr << " = " << targ << endl; } void import_from_abi(abi const & abi, void const * srcv, size_t len, odb_t * dest) throw (abi_exception) { struct opd_header * head = static_cast<opd_header *>(odb_get_data(dest)); unsigned char const * src = static_cast<unsigned char const *>(srcv); unsigned char const * const begin = src; extractor ext(abi, src, len); memcpy(head->magic, src + abi.need("offsetof_header_magic"), 4); // begin extracting opd header ext.extract(head->version, src, "sizeof_u32", "offsetof_header_version"); ext.extract(head->cpu_type, src, "sizeof_u32", "offsetof_header_cpu_type"); ext.extract(head->ctr_event, src, "sizeof_u32", "offsetof_header_ctr_event"); ext.extract(head->ctr_um, src, "sizeof_u32", "offsetof_header_ctr_um"); ext.extract(head->ctr_count, src, "sizeof_u32", "offsetof_header_ctr_count"); ext.extract(head->is_kernel, src, "sizeof_u32", "offsetof_header_is_kernel"); // "double" extraction is unlikely to work head->cpu_speed = 0.0; ext.extract(head->mtime, src, "sizeof_time_t", "offsetof_header_mtime"); ext.extract(head->cg_to_is_kernel, src, "sizeof_u32", "offsetof_header_cg_to_is_kernel"); ext.extract(head->anon_start, src, "sizeof_u32", "offsetof_header_anon_start"); ext.extract(head->cg_to_anon_start, src, "sizeof_u32", "offsetof_header_cg_to_anon_start"); src += abi.need("sizeof_struct_opd_header"); // done extracting opd header // begin extracting necessary parts of descr odb_node_nr_t node_nr; ext.extract(node_nr, src, "sizeof_odb_node_nr_t", "offsetof_descr_current_size"); src += abi.need("sizeof_odb_descr_t"); // done extracting descr // skip node zero, it is reserved and contains nothing usefull src += abi.need("sizeof_odb_node_t"); // begin extracting nodes unsigned int step = abi.need("sizeof_odb_node_t"); if (verbose) cerr << "extracting " << node_nr << " nodes of " << step << " bytes each " << endl; assert(src + (node_nr * step) <= begin + len); for (odb_node_nr_t i = 1 ; i < node_nr ; ++i, src += step) { odb_key_t key; odb_value_t val; ext.extract(key, src, "sizeof_odb_key_t", "offsetof_node_key"); ext.extract(val, src, "sizeof_odb_value_t", "offsetof_node_value"); int rc = odb_add_node(dest, key, val); if (rc != EXIT_SUCCESS) { cerr << strerror(rc) << endl; exit(EXIT_FAILURE); } } // done extracting nodes } int main(int argc, char const ** argv) { vector<string> inputs; popt::parse_options(argc, argv, inputs); if (inputs.size() != 1) { cerr << "error: must specify exactly 1 input file" << endl; exit(1); } abi current_abi, input_abi; { ifstream abi_file(abi_filename.c_str()); if (!abi_file) { cerr << "error: cannot open abi file " << abi_filename << endl; exit(1); } abi_file >> input_abi; } if (!force && current_abi == input_abi) { cerr << "input abi is identical to native. " << "no conversion necessary." << endl; exit(1); } int in_fd; struct stat statb; void * in; odb_t dest; int rc; assert((in_fd = open(inputs[0].c_str(), O_RDONLY)) > 0); assert(fstat(in_fd, &statb) == 0); assert((in = mmap(0, statb.st_size, PROT_READ, MAP_PRIVATE, in_fd, 0)) != (void *)-1); rc = odb_open(&dest, output_filename.c_str(), ODB_RDWR, sizeof(struct opd_header)); if (rc) { cerr << "odb_open() fail:\n" << strerror(rc) << endl; exit(EXIT_FAILURE); } try { import_from_abi(input_abi, in, statb.st_size, &dest); } catch (abi_exception & e) { cerr << "caught abi exception: " << e.desc << endl; } odb_close(&dest); assert(munmap(in, statb.st_size) == 0); }