1 // Copyright (c) 2012 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 #ifndef CHROMIUMOS_WIDE_PROFILING_PERF_READER_H_ 6 #define CHROMIUMOS_WIDE_PROFILING_PERF_READER_H_ 7 8 #include <stdint.h> 9 10 #include <map> 11 #include <memory> 12 #include <set> 13 #include <string> 14 #include <unordered_set> 15 #include <vector> 16 17 #include "base/macros.h" 18 19 #include "compat/proto.h" 20 #include "compat/string.h" 21 #include "kernel/perf_event.h" 22 #include "perf_serializer.h" 23 #include "sample_info_reader.h" 24 25 namespace quipper { 26 27 // Based on code in tools/perf/util/header.c, the metadata are of the following 28 // formats: 29 30 typedef u32 num_siblings_type; 31 32 class DataReader; 33 class DataWriter; 34 35 struct PerfFileAttr; 36 37 class PerfReader { 38 public: 39 PerfReader(); 40 ~PerfReader(); 41 42 // Copy stored contents to |*perf_data_proto|. Appends a timestamp. Returns 43 // true on success. 44 bool Serialize(PerfDataProto* perf_data_proto) const; 45 // Read in contents from a protobuf. Returns true on success. 46 bool Deserialize(const PerfDataProto& perf_data_proto); 47 48 bool ReadFile(const string& filename); 49 bool ReadFromVector(const std::vector<char>& data); 50 bool ReadFromString(const string& str); 51 bool ReadFromPointer(const char* data, size_t size); 52 bool ReadFromData(DataReader* data); 53 54 bool WriteFile(const string& filename); 55 bool WriteToVector(std::vector<char>* data); 56 bool WriteToString(string* str); 57 bool WriteToPointer(char* buffer, size_t size); 58 59 // Stores the mapping from filenames to build ids in build_id_events_. 60 // Returns true on success. 61 // Note: If |filenames_to_build_ids| contains a mapping for a filename for 62 // which there is already a build_id_event in build_id_events_, a duplicate 63 // build_id_event will be created, and the old build_id_event will NOT be 64 // deleted. 65 bool InjectBuildIDs(const std::map<string, string>& filenames_to_build_ids); 66 67 // Replaces existing filenames with filenames from |build_ids_to_filenames| 68 // by joining on build ids. If a build id in |build_ids_to_filenames| is not 69 // present in this parser, it is ignored. 70 bool Localize(const std::map<string, string>& build_ids_to_filenames); 71 72 // Same as Localize, but joins on filenames instead of build ids. 73 bool LocalizeUsingFilenames(const std::map<string, string>& filename_map); 74 75 // Stores a list of unique filenames found in MMAP/MMAP2 events into 76 // |filenames|. Any existing data in |filenames| will be lost. 77 void GetFilenames(std::vector<string>* filenames) const; 78 void GetFilenamesAsSet(std::set<string>* filenames) const; 79 80 // Uses build id events to populate |filenames_to_build_ids|. 81 // Any existing data in |filenames_to_build_ids| will be lost. 82 // Note: A filename returned by GetFilenames need not be present in this map, 83 // since there may be no build id event corresponding to the MMAP/MMAP2. 84 void GetFilenamesToBuildIDs( 85 std::map<string, string>* filenames_to_build_ids) const; 86 87 // Sort all events in |proto_| by timestamps if they are available. Otherwise 88 // event order is unchanged. 89 void MaybeSortEventsByTime(); 90 91 // Accessors and mutators. 92 93 // This is a plain accessor for the internal protobuf storage. It is meant for 94 // exposing the internals. This is not initialized until Read*() or 95 // Deserialize() has been called. 96 // 97 // Call Serialize() instead of this function to acquire an "official" protobuf 98 // with a timestamp. proto()99 const PerfDataProto& proto() const { return *proto_; } 100 attrs()101 const RepeatedPtrField<PerfDataProto_PerfFileAttr>& attrs() const { 102 return proto_->file_attrs(); 103 } event_types()104 const RepeatedPtrField<PerfDataProto_PerfEventType>& event_types() const { 105 return proto_->event_types(); 106 } 107 events()108 const RepeatedPtrField<PerfDataProto_PerfEvent>& events() const { 109 return proto_->events(); 110 } 111 // WARNING: Modifications to the protobuf events may change the amount of 112 // space required to store the corresponding raw event. If that happens, the 113 // caller is responsible for correctly updating the size in the event header. mutable_events()114 RepeatedPtrField<PerfDataProto_PerfEvent>* mutable_events() { 115 return proto_->mutable_events(); 116 } 117 build_ids()118 const RepeatedPtrField<PerfDataProto_PerfBuildID>& build_ids() const { 119 return proto_->build_ids(); 120 } mutable_build_ids()121 RepeatedPtrField<PerfDataProto_PerfBuildID>* mutable_build_ids() { 122 return proto_->mutable_build_ids(); 123 } 124 tracing_data()125 const string& tracing_data() const { 126 return proto_->tracing_data().tracing_data(); 127 } 128 string_metadata()129 const PerfDataProto_StringMetadata& string_metadata() const { 130 return proto_->string_metadata(); 131 } 132 metadata_mask()133 uint64_t metadata_mask() const { return proto_->metadata_mask().Get(0); } 134 135 private: 136 bool ReadHeader(DataReader* data); 137 bool ReadAttrsSection(DataReader* data); 138 bool ReadAttr(DataReader* data); 139 bool ReadEventAttr(DataReader* data, perf_event_attr* attr); 140 bool ReadUniqueIDs(DataReader* data, size_t num_ids, std::vector<u64>* ids); 141 142 bool ReadEventTypesSection(DataReader* data); 143 // if event_size == 0, then not in an event. 144 bool ReadEventType(DataReader* data, int attr_idx, size_t event_size); 145 146 bool ReadDataSection(DataReader* data); 147 148 // Reads metadata in normal mode. 149 bool ReadMetadata(DataReader* data); 150 151 // The following functions read various types of metadata. 152 bool ReadTracingMetadata(DataReader* data, size_t size); 153 bool ReadBuildIDMetadata(DataReader* data, size_t size); 154 // Reads contents of a build ID event or block beyond the header. Useful for 155 // reading build IDs in piped mode, where the header must be read first in 156 // order to determine that it is a build ID event. 157 bool ReadBuildIDMetadataWithoutHeader(DataReader* data, 158 const perf_event_header& header); 159 160 // Reads and serializes trace data following PERF_RECORD_AUXTRACE event. 161 bool ReadAuxtraceTraceData(DataReader* data, 162 PerfDataProto_PerfEvent* proto_event); 163 164 // Reads a singular string metadata field (with preceding size field) from 165 // |data| and writes the string and its Md5sum prefix into |dest|. 166 bool ReadSingleStringMetadata( 167 DataReader* data, size_t max_readable_size, 168 PerfDataProto_StringMetadata_StringAndMd5sumPrefix* dest) const; 169 // Reads a string metadata with multiple string fields (each with preceding 170 // size field) from |data|. Writes each string field and its Md5sum prefix 171 // into |dest_array|. Writes the combined string fields (joined into one 172 // string into |dest_single|. 173 bool ReadRepeatedStringMetadata( 174 DataReader* data, size_t max_readable_size, 175 RepeatedPtrField<PerfDataProto_StringMetadata_StringAndMd5sumPrefix>* 176 dest_array, 177 PerfDataProto_StringMetadata_StringAndMd5sumPrefix* dest_single) const; 178 179 bool ReadUint32Metadata(DataReader* data, u32 type, size_t size); 180 bool ReadUint64Metadata(DataReader* data, u32 type, size_t size); 181 bool ReadCPUTopologyMetadata(DataReader* data); 182 bool ReadNUMATopologyMetadata(DataReader* data); 183 bool ReadPMUMappingsMetadata(DataReader* data, size_t size); 184 bool ReadGroupDescMetadata(DataReader* data); 185 bool ReadEventDescMetadata(DataReader* data); 186 187 // Read perf data from file perf output data. 188 bool ReadFileData(DataReader* data); 189 190 // Read perf data from piped perf output data. 191 bool ReadPipedData(DataReader* data); 192 193 // Returns the size in bytes that would be written by any of the methods that 194 // write the entire perf data file (WriteFile, WriteToPointer, etc). 195 size_t GetSize() const; 196 197 // Populates |*header| with the proper contents based on the perf data that 198 // has been read. 199 void GenerateHeader(struct perf_file_header* header) const; 200 201 // Like WriteToPointer, but does not check if the buffer is large enough. 202 bool WriteToPointerWithoutCheckingSize(char* buffer, size_t size); 203 204 bool WriteHeader(const struct perf_file_header& header, 205 DataWriter* data) const; 206 bool WriteAttrs(const struct perf_file_header& header, 207 DataWriter* data) const; 208 bool WriteData(const struct perf_file_header& header, DataWriter* data) const; 209 bool WriteMetadata(const struct perf_file_header& header, 210 DataWriter* data) const; 211 212 // For writing the various types of metadata. 213 bool WriteBuildIDMetadata(u32 type, DataWriter* data) const; 214 bool WriteSingleStringMetadata( 215 const PerfDataProto_StringMetadata_StringAndMd5sumPrefix& src, 216 DataWriter* data) const; 217 bool WriteRepeatedStringMetadata( 218 const RepeatedPtrField< 219 PerfDataProto_StringMetadata_StringAndMd5sumPrefix>& src_array, 220 DataWriter* data) const; 221 bool WriteUint32Metadata(u32 type, DataWriter* data) const; 222 bool WriteUint64Metadata(u32 type, DataWriter* data) const; 223 bool WriteEventDescMetadata(DataWriter* data) const; 224 bool WriteCPUTopologyMetadata(DataWriter* data) const; 225 bool WriteNUMATopologyMetadata(DataWriter* data) const; 226 bool WritePMUMappingsMetadata(DataWriter* data) const; 227 bool WriteGroupDescMetadata(DataWriter* data) const; 228 229 // For reading event blocks within piped perf data. 230 bool ReadAttrEventBlock(DataReader* data, size_t size); 231 232 // Swaps byte order for non-header fields of the data structure pointed to by 233 // |event|, if |is_cross_endian| is true. Otherwise leaves the data the same. 234 void MaybeSwapEventFields(event_t* event, bool is_cross_endian); 235 236 // Returns the number of types of metadata stored and written to output data. 237 size_t GetNumSupportedMetadata() const; 238 239 // For computing the sizes of the various types of metadata. 240 size_t GetBuildIDMetadataSize() const; 241 size_t GetStringMetadataSize() const; 242 size_t GetUint32MetadataSize() const; 243 size_t GetUint64MetadataSize() const; 244 size_t GetEventDescMetadataSize() const; 245 size_t GetCPUTopologyMetadataSize() const; 246 size_t GetNUMATopologyMetadataSize() const; 247 size_t GetPMUMappingsMetadataSize() const; 248 size_t GetGroupDescMetadataSize() const; 249 250 // Returns true if we should write the number of strings for the string 251 // metadata of type |type|. 252 bool NeedsNumberOfStringData(u32 type) const; 253 254 // Replaces existing filenames in MMAP/MMAP2 events based on |filename_map|. 255 // This method does not change |build_id_events_|. 256 bool LocalizeMMapFilenames(const std::map<string, string>& filename_map); 257 258 // Stores a PerfFileAttr in |proto_| and updates |serializer_|. 259 void AddPerfFileAttr(const PerfFileAttr& attr); 260 get_metadata_mask_bit(uint32_t bit)261 bool get_metadata_mask_bit(uint32_t bit) const { 262 return metadata_mask() & (1 << bit); 263 } set_metadata_mask_bit(uint32_t bit)264 void set_metadata_mask_bit(uint32_t bit) { 265 proto_->set_metadata_mask(0, metadata_mask() | (1 << bit)); 266 } 267 268 // The file header is either a normal header or a piped header. 269 union { 270 struct perf_file_header header_; 271 struct perf_pipe_file_header piped_header_; 272 }; 273 274 // Store the perf data as a protobuf. 275 Arena arena_; 276 PerfDataProto* proto_; 277 // Attribute ids that have been added to |proto_|, for deduplication. 278 std::unordered_set<u64> file_attrs_seen_; 279 280 // Whether the incoming data is from a machine with a different endianness. We 281 // got rid of this flag in the past but now we need to store this so it can be 282 // passed to |serializer_|. 283 bool is_cross_endian_; 284 285 // For serializing individual events. 286 PerfSerializer serializer_; 287 288 // When writing to a new perf data file, this is used to hold the generated 289 // file header, which may differ from the input file header, if any. 290 struct perf_file_header out_header_; 291 292 DISALLOW_COPY_AND_ASSIGN(PerfReader); 293 }; 294 295 } // namespace quipper 296 297 #endif // CHROMIUMOS_WIDE_PROFILING_PERF_READER_H_ 298