1 /* 2 * Copyright (C) 2024 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef SRC_TRACE_PROCESSOR_IMPORTERS_PERF_READER_H_ 18 #define SRC_TRACE_PROCESSOR_IMPORTERS_PERF_READER_H_ 19 20 #include <stdint.h> 21 #include <cstddef> 22 #include <cstdint> 23 #include <cstring> 24 #include <optional> 25 #include <string> 26 #include <type_traits> 27 #include <vector> 28 29 #include "perfetto/ext/base/string_view.h" 30 #include "perfetto/trace_processor/trace_blob_view.h" 31 #include "src/trace_processor/importers/perf/perf_event.h" 32 33 namespace perfetto::trace_processor::perf_importer { 34 35 // Helper to read various types of data fields contained in a TraceBlobView. 36 // All methods return a boolean indicating whether the read was successful. A 37 // false value means there was not enough data in the underlying buffer to 38 // satisfy the read. 39 class Reader { 40 public: Reader(TraceBlobView tbv)41 explicit Reader(TraceBlobView tbv) 42 : buffer_(tbv.blob()), 43 current_(tbv.data()), 44 end_(current_ + tbv.size()) {} 45 46 // Data left to be read. The value returned here decrements as read or skip 47 // methods are called. size_left()48 size_t size_left() const { return static_cast<size_t>(end_ - current_); } 49 ReadStringView(base::StringView & str,size_t size)50 bool ReadStringView(base::StringView& str, size_t size) { 51 if (size_left() < size) { 52 return false; 53 } 54 str = base::StringView(reinterpret_cast<const char*>(current_), size); 55 current_ += size; 56 return true; 57 } 58 ReadPerfEventAttr(perf_event_attr & attr,size_t attr_size)59 bool ReadPerfEventAttr(perf_event_attr& attr, size_t attr_size) { 60 const size_t bytes_to_read = std::min(attr_size, sizeof(attr)); 61 const size_t bytes_to_skip = attr_size - bytes_to_read; 62 static_assert(std::has_unique_object_representations_v<perf_event_attr>); 63 64 if (size_left() < bytes_to_read + bytes_to_skip) { 65 return false; 66 } 67 68 memset(&attr, 0, sizeof(attr)); 69 70 return Read(&attr, bytes_to_read) && Skip(bytes_to_skip); 71 } 72 ReadBlob(TraceBlobView & blob,uint32_t size)73 bool ReadBlob(TraceBlobView& blob, uint32_t size) { 74 if (size_left() < size) { 75 return false; 76 } 77 blob = TraceBlobView(buffer_, 78 static_cast<size_t>(current_ - buffer_->data()), size); 79 current_ += size; 80 return true; 81 } 82 ReadStringUntilEndOrNull(std::string & out)83 bool ReadStringUntilEndOrNull(std::string& out) { 84 const uint8_t* ptr = current_; 85 while (ptr != end_ && *ptr != 0) { 86 ++ptr; 87 } 88 out = std::string(reinterpret_cast<const char*>(current_), 89 static_cast<size_t>(ptr - current_)); 90 current_ = ptr; 91 return true; 92 } 93 94 template <typename T> Read(T & obj)95 bool Read(T& obj) { 96 static_assert(std::has_unique_object_representations_v<T>); 97 return Read(&obj, sizeof(T)); 98 } 99 Read(void * dest,size_t size)100 bool Read(void* dest, size_t size) { 101 if (size_left() < size) { 102 return false; 103 } 104 memcpy(dest, current_, size); 105 current_ += size; 106 return true; 107 } 108 Skip(size_t size)109 bool Skip(size_t size) { 110 if (size_left() < size) { 111 return false; 112 } 113 current_ += size; 114 return true; 115 } 116 117 template <typename T> Skip()118 bool Skip() { 119 return Skip(sizeof(T)); 120 } 121 122 // Reads consecutive values and stores them in the given vector. Reads as many 123 // entries as the current vector size. 124 template <typename T> ReadVector(std::vector<T> & vec)125 bool ReadVector(std::vector<T>& vec) { 126 static_assert(std::has_unique_object_representations_v<T>); 127 size_t size = sizeof(T) * vec.size(); 128 if (size_left() < size) { 129 return false; 130 } 131 memcpy(vec.data(), current_, size); 132 current_ += size; 133 return true; 134 } 135 136 // Convenience helper for reading values and storing them in an optional<> 137 // wrapper. 138 template <typename T> ReadOptional(std::optional<T> & obj)139 bool ReadOptional(std::optional<T>& obj) { 140 T val; 141 if (!Read(val)) { 142 return false; 143 } 144 obj = val; 145 return true; 146 } 147 148 // Reads a null terminated string. ReadCString(std::string & out)149 bool ReadCString(std::string& out) { 150 for (const uint8_t* ptr = current_; ptr != end_; ++ptr) { 151 if (*ptr == 0) { 152 out = std::string(reinterpret_cast<const char*>(current_), 153 static_cast<size_t>(ptr - current_)); 154 current_ = ptr; 155 return true; 156 } 157 } 158 159 return false; 160 } 161 162 private: 163 RefPtr<TraceBlob> buffer_; 164 const uint8_t* current_; 165 const uint8_t* end_; 166 }; 167 168 } // namespace perfetto::trace_processor::perf_importer 169 170 #endif // SRC_TRACE_PROCESSOR_IMPORTERS_PERF_READER_H_ 171