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 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 74 template <typename T> 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 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 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