auto import from //depot/cupcake/@135843
diff --git a/libabi/opimport.cpp b/libabi/opimport.cpp
new file mode 100644
index 0000000..57f74a7
--- /dev/null
+++ b/libabi/opimport.cpp
@@ -0,0 +1,225 @@
+/**
+ * @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);
+}