00001
00011 #include "abi.h"
00012 #include "odb.h"
00013 #include "popt_options.h"
00014 #include "op_sample_file.h"
00015
00016 #include <fstream>
00017 #include <iostream>
00018 #include <vector>
00019 #include <cassert>
00020 #include <cstring>
00021 #include <cstdlib>
00022
00023 #include <sys/types.h>
00024 #include <sys/stat.h>
00025 #include <fcntl.h>
00026 #include <unistd.h>
00027 #include <sys/mman.h>
00028 #include <cstdlib>
00029 #include <cstring>
00030
00031 using namespace std;
00032
00033 namespace {
00034 string output_filename;
00035 string abi_filename;
00036 bool verbose;
00037 bool force;
00038 };
00039
00040
00041 popt::option options_array[] = {
00042 popt::option(verbose, "verbose", 'V', "verbose output"),
00043 popt::option(output_filename, "output", 'o', "output to file", "filename"),
00044 popt::option(abi_filename, "abi", 'a', "abi description", "filename"),
00045 popt::option(force, "force", 'f', "force conversion, even if identical")
00046 };
00047
00048
00049 struct extractor {
00050
00051 abi const & theabi;
00052
00053 unsigned char const * begin;
00054 unsigned char const * end;
00055 bool little_endian;
00056
00057 explicit
00058 extractor(abi const & a, unsigned char const * src, size_t len)
00059 : theabi(a), begin(src), end(src + len) {
00060 little_endian = theabi.need(string("little_endian")) == 1;
00061 if (verbose) {
00062 cerr << "source byte order is: "
00063 << string(little_endian ? "little" : "big")
00064 << " endian" << endl;
00065 }
00066 }
00067
00068 template <typename T>
00069 void extract(T & targ, void const * src_,
00070 char const * sz, char const * off);
00071 };
00072
00073
00074 template <typename T>
00075 void extractor::extract(T & targ, void const * src_,
00076 char const * sz, char const * off)
00077 {
00078 unsigned char const * src = static_cast<unsigned char const *>(src_)
00079 + theabi.need(off);
00080 size_t nbytes = theabi.need(sz);
00081
00082 targ = 0;
00083 if (nbytes == 0)
00084 return;
00085
00086 assert(nbytes <= sizeof(T));
00087 assert(src >= begin);
00088 assert(src + nbytes <= end);
00089
00090 if (verbose)
00091 cerr << hex << "get " << sz << " = " << nbytes
00092 << " bytes @ " << off << " = " << (src - begin)
00093 << " : ";
00094
00095 if (little_endian)
00096 while(nbytes--)
00097 targ = (targ << 8) | src[nbytes];
00098 else
00099 for(size_t i = 0; i < nbytes; ++i)
00100 targ = (targ << 8) | src[i];
00101
00102 if (verbose)
00103 cerr << " = " << targ << endl;
00104 }
00105
00106
00107 void import_from_abi(abi const & abi, void const * srcv,
00108 size_t len, odb_t * dest) throw (abi_exception)
00109 {
00110 struct opd_header * head =
00111 static_cast<opd_header *>(odb_get_data(dest));
00112 unsigned char const * src = static_cast<unsigned char const *>(srcv);
00113 unsigned char const * const begin = src;
00114 extractor ext(abi, src, len);
00115
00116 memcpy(head->magic, src + abi.need("offsetof_header_magic"), 4);
00117
00118
00119 ext.extract(head->version, src, "sizeof_u32", "offsetof_header_version");
00120 ext.extract(head->cpu_type, src, "sizeof_u32", "offsetof_header_cpu_type");
00121 ext.extract(head->ctr_event, src, "sizeof_u32", "offsetof_header_ctr_event");
00122 ext.extract(head->ctr_um, src, "sizeof_u32", "offsetof_header_ctr_um");
00123 ext.extract(head->ctr_count, src, "sizeof_u32", "offsetof_header_ctr_count");
00124 ext.extract(head->is_kernel, src, "sizeof_u32", "offsetof_header_is_kernel");
00125
00126 head->cpu_speed = 0.0;
00127 ext.extract(head->mtime, src, "sizeof_u64", "offsetof_header_mtime");
00128 ext.extract(head->cg_to_is_kernel, src, "sizeof_u32",
00129 "offsetof_header_cg_to_is_kernel");
00130 ext.extract(head->anon_start, src, "sizeof_u32",
00131 "offsetof_header_anon_start");
00132 ext.extract(head->cg_to_anon_start, src, "sizeof_u32",
00133 "offsetof_header_cg_to_anon_start");
00134 src += abi.need("sizeof_struct_opd_header");
00135
00136
00137
00138 odb_node_nr_t node_nr;
00139 ext.extract(node_nr, src, "sizeof_odb_node_nr_t", "offsetof_descr_current_size");
00140 src += abi.need("sizeof_odb_descr_t");
00141
00142
00143
00144 src += abi.need("sizeof_odb_node_t");
00145
00146
00147 unsigned int step = abi.need("sizeof_odb_node_t");
00148 if (verbose)
00149 cerr << "extracting " << node_nr << " nodes of " << step << " bytes each " << endl;
00150
00151 assert(src + (node_nr * step) <= begin + len);
00152
00153 for (odb_node_nr_t i = 1 ; i < node_nr ; ++i, src += step) {
00154 odb_key_t key;
00155 odb_value_t val;
00156 ext.extract(key, src, "sizeof_odb_key_t", "offsetof_node_key");
00157 ext.extract(val, src, "sizeof_odb_value_t", "offsetof_node_value");
00158 int rc = odb_add_node(dest, key, val);
00159 if (rc != EXIT_SUCCESS) {
00160 cerr << strerror(rc) << endl;
00161 exit(EXIT_FAILURE);
00162 }
00163 }
00164
00165 }
00166
00167
00168 int main(int argc, char const ** argv)
00169 {
00170
00171 vector<string> inputs;
00172 popt::parse_options(argc, argv, inputs);
00173
00174 if (inputs.size() != 1) {
00175 cerr << "error: must specify exactly 1 input file" << endl;
00176 exit(1);
00177 }
00178
00179 if (inputs[0].rfind(".jo") == inputs[0].size() - 3) {
00180 if (verbose) {
00181 cerr << "Found a .jo file. Import is not allowed or necessary. Done." << endl;
00182 cerr << inputs[0] << endl;
00183 }
00184
00185 exit(EXIT_SUCCESS);
00186 }
00187
00188 abi current_abi, input_abi;
00189
00190 {
00191 ifstream abi_file(abi_filename.c_str());
00192 if (!abi_file) {
00193 cerr << "error: cannot open abi file "
00194 << abi_filename << endl;
00195 exit(1);
00196 }
00197 abi_file >> input_abi;
00198 }
00199
00200 if (!force && current_abi == input_abi) {
00201 cerr << "input abi is identical to native. "
00202 << "no conversion necessary." << endl;
00203 exit(1);
00204 }
00205
00206 int in_fd;
00207 struct stat statb;
00208 void * in;
00209 odb_t dest;
00210 int rc;
00211
00212 assert((in_fd = open(inputs[0].c_str(), O_RDONLY)) > 0);
00213 assert(fstat(in_fd, &statb) == 0);
00214 assert((in = mmap(0, statb.st_size, PROT_READ,
00215 MAP_PRIVATE, in_fd, 0)) != (void *)-1);
00216
00217 rc = odb_open(&dest, output_filename.c_str(), ODB_RDWR,
00218 sizeof(struct opd_header));
00219 if (rc) {
00220 cerr << "odb_open() fail:\n"
00221 << strerror(rc) << endl;
00222 exit(EXIT_FAILURE);
00223 }
00224
00225 try {
00226 import_from_abi(input_abi, in, statb.st_size, &dest);
00227 } catch (abi_exception & e) {
00228 cerr << "caught abi exception: " << e.desc << endl;
00229 }
00230
00231 odb_close(&dest);
00232
00233 assert(munmap(in, statb.st_size) == 0);
00234 }