1 // Copyright (c) 2013 The Chromium OS Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "conversion_utils.h" 6 7 #include <stdlib.h> 8 #include <unistd.h> 9 10 #include <string> 11 #include <vector> 12 13 #include "base/logging.h" 14 15 #include "compat/proto.h" 16 #include "compat/string.h" 17 #include "file_utils.h" 18 #include "perf_parser.h" 19 #include "perf_protobuf_io.h" 20 #include "perf_reader.h" 21 22 namespace quipper { 23 24 namespace { 25 26 // Parse options from the format strings, set the options, and return the base 27 // format. Returns the empty string if options are not recognized. 28 string ParseFormatOptions(string format, PerfParserOptions* options) { 29 auto dot = format.find('.'); 30 if (dot != string::npos) { 31 string opt = format.substr(dot + 1); 32 format = format.substr(0, dot); 33 if (opt == "remap") { 34 options->do_remap = true; 35 } else if (opt == "discard") { 36 options->discard_unused_events = true; 37 } else if (opt == "remap.discard") { 38 options->do_remap = true; 39 options->discard_unused_events = true; 40 } else { 41 LOG(ERROR) << "Unknown option: " << opt; 42 return ""; 43 } 44 } 45 return format; 46 } 47 48 // ReadInput reads the input and stores it within |reader|. 49 bool ReadInput(const FormatAndFile& input, PerfReader* reader, 50 PerfParserOptions* options) { 51 LOG(INFO) << "Reading input."; 52 53 string format = ParseFormatOptions(input.format, options); 54 if (format == kPerfFormat) { 55 return reader->ReadFile(input.filename); 56 } 57 58 if (format == kProtoTextFormat) { 59 PerfDataProto perf_data_proto; 60 std::vector<char> data; 61 if (!FileToBuffer(input.filename, &data)) return false; 62 string text(data.begin(), data.end()); 63 if (!TextFormat::ParseFromString(text, &perf_data_proto)) return false; 64 65 return reader->Deserialize(perf_data_proto); 66 } 67 68 LOG(ERROR) << "Unimplemented read format: " << input.format; 69 return false; 70 } 71 72 // WriteOutput reads from |reader| and writes the output to the file 73 // within |output|. 74 bool WriteOutput(const FormatAndFile& output, const PerfParserOptions& options, 75 PerfReader* reader) { 76 LOG(INFO) << "Writing output."; 77 78 // Apply use PerfParser to modify data in reader, applying hacks all hacks, 79 // regardless of output format. 80 PerfParser parser(reader, options); 81 if (!parser.ParseRawEvents()) return false; 82 83 string output_string; 84 if (output.format == kPerfFormat) { 85 return reader->WriteFile(output.filename); 86 } 87 88 if (output.format == kProtoTextFormat) { 89 PerfDataProto perf_data_proto; 90 reader->Serialize(&perf_data_proto); 91 92 // Serialize the parser stats as well. 93 PerfSerializer::SerializeParserStats(parser.stats(), &perf_data_proto); 94 95 // Reset the timestamp field since it causes reproducability issues when 96 // testing. 97 perf_data_proto.set_timestamp_sec(0); 98 if (!TextFormat::PrintToString(perf_data_proto, &output_string)) 99 return false; 100 std::vector<char> data(output_string.begin(), output_string.end()); 101 return BufferToFile(output.filename, data); 102 } 103 104 LOG(ERROR) << "Unimplemented write format: " << output.format; 105 return false; 106 } 107 108 } // namespace 109 110 // Format string for perf.data. 111 const char kPerfFormat[] = "perf"; 112 113 // Format string for protobuf text format. 114 const char kProtoTextFormat[] = "text"; 115 116 bool ConvertFile(const FormatAndFile& input, const FormatAndFile& output) { 117 PerfReader reader; 118 PerfParserOptions options; 119 if (!ReadInput(input, &reader, &options)) return false; 120 if (!WriteOutput(output, options, &reader)) return false; 121 return true; 122 } 123 124 } // namespace quipper 125