opimport.cpp revision b415faba7482dd7ee3335f0f1518333554e3da0d
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 if (verbose) 118 cerr << hex << "magic = " << (int) head->magic[0] << ":" << (int) head->magic[1] << ":" << (int) head->magic[2] << ":" << (int) head->magic[3] << endl; 119 120 // begin extracting opd header 121 ext.extract(head->version, src, "sizeof_u32", "offsetof_header_version"); 122 ext.extract(head->cpu_type, src, "sizeof_u32", "offsetof_header_cpu_type"); 123 ext.extract(head->ctr_event, src, "sizeof_u32", "offsetof_header_ctr_event"); 124 ext.extract(head->ctr_um, src, "sizeof_u32", "offsetof_header_ctr_um"); 125 ext.extract(head->ctr_count, src, "sizeof_u32", "offsetof_header_ctr_count"); 126 ext.extract(head->is_kernel, src, "sizeof_u32", "offsetof_header_is_kernel"); 127 // "double" extraction is unlikely to work 128 head->cpu_speed = 0.0; 129 ext.extract(head->mtime, src, "sizeof_time_t", "offsetof_header_mtime"); 130 ext.extract(head->cg_to_is_kernel, src, "sizeof_u32", 131 "offsetof_header_cg_to_is_kernel"); 132 ext.extract(head->anon_start, src, "sizeof_u32", 133 "offsetof_header_anon_start"); 134 ext.extract(head->cg_to_anon_start, src, "sizeof_u32", 135 "offsetof_header_cg_to_anon_start"); 136 src += abi.need("sizeof_struct_opd_header"); 137 // done extracting opd header 138 139 // begin extracting necessary parts of descr 140 odb_node_nr_t node_nr; 141 ext.extract(node_nr, src, "sizeof_odb_node_nr_t", "offsetof_descr_current_size"); 142 src += abi.need("sizeof_odb_descr_t"); 143 // done extracting descr 144 145 // skip node zero, it is reserved and contains nothing usefull 146 src += abi.need("sizeof_odb_node_t"); 147 148 // begin extracting nodes 149 unsigned int step = abi.need("sizeof_odb_node_t"); 150 if (verbose) 151 cerr << "extracting " << node_nr << " nodes of " << step << " bytes each " << endl; 152 153 assert(src + (node_nr * step) <= begin + len); 154 155 for (odb_node_nr_t i = 1 ; i < node_nr ; ++i, src += step) { 156 odb_key_t key; 157 odb_value_t val; 158 ext.extract(key, src, "sizeof_odb_key_t", "offsetof_node_key"); 159 ext.extract(val, src, "sizeof_odb_value_t", "offsetof_node_value"); 160 int rc = odb_add_node(dest, key, val); 161 if (rc != EXIT_SUCCESS) { 162 cerr << strerror(rc) << endl; 163 exit(EXIT_FAILURE); 164 } 165 } 166 // done extracting nodes 167} 168 169 170int main(int argc, char const ** argv) 171{ 172 173 vector<string> inputs; 174 popt::parse_options(argc, argv, inputs); 175 176 if (inputs.size() != 1) { 177 cerr << "error: must specify exactly 1 input file" << endl; 178 exit(1); 179 } 180 181 abi current_abi, input_abi; 182 183 { 184 ifstream abi_file(abi_filename.c_str()); 185 if (!abi_file) { 186 cerr << "error: cannot open abi file " 187 << abi_filename << endl; 188 exit(1); 189 } 190 abi_file >> input_abi; 191 } 192 193 if (!force && current_abi == input_abi) { 194 cerr << "input abi is identical to native. " 195 << "no conversion necessary." << endl; 196 exit(1); 197 } 198 199 int in_fd; 200 struct stat statb; 201 void * in; 202 odb_t dest; 203 int rc; 204 205 in_fd = open(inputs[0].c_str(), O_RDONLY); 206 assert(in_fd > 0); 207 rc = fstat(in_fd, &statb); 208 assert(rc == 0); 209 in = mmap(0, statb.st_size, PROT_READ, MAP_PRIVATE, in_fd, 0); 210 assert(in != (void *)-1); 211 212 rc = odb_open(&dest, output_filename.c_str(), ODB_RDWR, 213 sizeof(struct opd_header)); 214 if (rc) { 215 cerr << "odb_open() fail:\n" 216 << strerror(rc) << endl; 217 exit(EXIT_FAILURE); 218 } 219 220 try { 221 import_from_abi(input_abi, in, statb.st_size, &dest); 222 } catch (abi_exception & e) { 223 cerr << "caught abi exception: " << e.desc << endl; 224 } 225 226 odb_close(&dest); 227 228 rc = munmap(in, statb.st_size); 229 assert(rc == 0); 230} 231