xref: /aosp_15_r20/external/perfetto/src/trace_processor/importers/perf/reader.h (revision 6dbdd20afdafa5e3ca9b8809fa73465d530080dc)
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