1 /*
2 * Copyright (C) 2019 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_FUCHSIA_FUCHSIA_TRACE_UTILS_H_
18 #define SRC_TRACE_PROCESSOR_IMPORTERS_FUCHSIA_FUCHSIA_TRACE_UTILS_H_
19
20 #include <cstddef>
21 #include <cstdint>
22
23 #include "perfetto/base/logging.h"
24 #include "perfetto/ext/base/string_view.h"
25 #include "src/trace_processor/importers/fuchsia/fuchsia_record.h"
26 #include "src/trace_processor/storage/trace_storage.h"
27 #include "src/trace_processor/types/variadic.h"
28
29 namespace perfetto::trace_processor::fuchsia_trace_utils {
30
31 template <class T>
ReadField(uint64_t word,size_t begin,size_t end)32 T ReadField(uint64_t word, size_t begin, size_t end) {
33 return static_cast<T>((word >> begin) &
34 ((uint64_t(1) << (end - begin + 1)) - 1));
35 }
36
37 bool IsInlineString(uint32_t);
38 bool IsInlineThread(uint32_t);
39 int64_t TicksToNs(uint64_t ticks, uint64_t ticks_per_second);
40
41 class ArgValue {
42 public:
43 enum ArgType {
44 kNull,
45 kInt32,
46 kUint32,
47 kInt64,
48 kUint64,
49 kDouble,
50 kString,
51 kPointer,
52 kKoid,
53 kBool,
54 kUnknown,
55 };
56
Null()57 static ArgValue Null() {
58 ArgValue v;
59 v.type_ = ArgType::kNull;
60 v.int32_ = 0;
61 return v;
62 }
63
Int32(int32_t value)64 static ArgValue Int32(int32_t value) {
65 ArgValue v;
66 v.type_ = ArgType::kInt32;
67 v.int32_ = value;
68 return v;
69 }
70
Uint32(uint32_t value)71 static ArgValue Uint32(uint32_t value) {
72 ArgValue v;
73 v.type_ = ArgType::kUint32;
74 v.uint32_ = value;
75 return v;
76 }
77
Int64(int64_t value)78 static ArgValue Int64(int64_t value) {
79 ArgValue v;
80 v.type_ = ArgType::kInt64;
81 v.int64_ = value;
82 return v;
83 }
84
Uint64(uint64_t value)85 static ArgValue Uint64(uint64_t value) {
86 ArgValue v;
87 v.type_ = ArgType::kUint64;
88 v.uint64_ = value;
89 return v;
90 }
91
Double(double value)92 static ArgValue Double(double value) {
93 ArgValue v;
94 v.type_ = ArgType::kDouble;
95 v.double_ = value;
96 return v;
97 }
98
String(StringId value)99 static ArgValue String(StringId value) {
100 ArgValue v;
101 v.type_ = ArgType::kString;
102 v.string_ = value;
103 return v;
104 }
105
Pointer(uint64_t value)106 static ArgValue Pointer(uint64_t value) {
107 ArgValue v;
108 v.type_ = ArgType::kPointer;
109 v.pointer_ = value;
110 return v;
111 }
112
Koid(uint64_t value)113 static ArgValue Koid(uint64_t value) {
114 ArgValue v;
115 v.type_ = ArgType::kKoid;
116 v.koid_ = value;
117 return v;
118 }
119
Bool(bool value)120 static ArgValue Bool(bool value) {
121 ArgValue v;
122 v.type_ = ArgType::kBool;
123 v.bool_ = value;
124 return v;
125 }
126
Unknown()127 static ArgValue Unknown() {
128 ArgValue v;
129 v.type_ = ArgType::kUnknown;
130 v.int32_ = 0;
131 return v;
132 }
133
Type()134 ArgType Type() const { return type_; }
135
Int32()136 int32_t Int32() const {
137 PERFETTO_DCHECK(type_ == ArgType::kInt32);
138 return int32_;
139 }
140
Uint32()141 uint32_t Uint32() const {
142 PERFETTO_DCHECK(type_ == ArgType::kUint32);
143 return uint32_;
144 }
145
Int64()146 int64_t Int64() const {
147 PERFETTO_DCHECK(type_ == ArgType::kInt64);
148 return int64_;
149 }
150
Uint64()151 uint64_t Uint64() const {
152 PERFETTO_DCHECK(type_ == ArgType::kUint64);
153 return uint64_;
154 }
155
Double()156 double Double() const {
157 PERFETTO_DCHECK(type_ == ArgType::kDouble);
158 return double_;
159 }
160
String()161 StringId String() const {
162 PERFETTO_DCHECK(type_ == ArgType::kString);
163 return string_;
164 }
165
Pointer()166 uint64_t Pointer() const {
167 PERFETTO_DCHECK(type_ == ArgType::kPointer);
168 return pointer_;
169 }
170
Koid()171 uint64_t Koid() const {
172 PERFETTO_DCHECK(type_ == ArgType::kKoid);
173 return koid_;
174 }
175
Bool()176 uint64_t Bool() const {
177 PERFETTO_DCHECK(type_ == ArgType::kBool);
178 return bool_;
179 }
180
181 Variadic ToStorageVariadic(TraceStorage*) const;
182
183 private:
184 ArgType type_;
185 union {
186 int32_t int32_;
187 uint32_t uint32_;
188 int64_t int64_;
189 uint64_t uint64_;
190 double double_;
191 StringId string_;
192 uint64_t pointer_;
193 uint64_t koid_;
194 bool bool_;
195 };
196 };
197
198 // This class maintains a location into the record, with helper functions to
199 // read various trace data from the current location in a safe manner.
200 //
201 // In the context of Fuchsia trace records, a "word" is defined as 64 bits
202 // regardless of platform. For more information, see
203 // https://fuchsia.googlesource.com/fuchsia/+/refs/heads/master/docs/development/tracing/trace-format/
204 class RecordCursor {
205 public:
RecordCursor(const uint8_t * begin,size_t length)206 RecordCursor(const uint8_t* begin, size_t length)
207 : begin_(begin), end_(begin + length) {}
208
209 size_t WordIndex();
210 void SetWordIndex(size_t index);
211
212 bool ReadTimestamp(uint64_t ticks_per_second, int64_t* ts_out);
213 bool ReadInlineString(uint32_t string_ref_or_len,
214 base::StringView* string_out);
215 bool ReadInlineThread(FuchsiaThreadInfo* thread_out);
216
217 bool ReadInt64(int64_t* out);
218 bool ReadUint64(uint64_t* out);
219 bool ReadDouble(double* out);
220 bool ReadBlob(size_t num_bytes, std::vector<uint8_t>& out);
221
222 private:
223 bool ReadWords(size_t num_words, const uint8_t** data_out);
224
225 const uint8_t* begin_;
226 const uint8_t* end_;
227 size_t word_index_{};
228 };
229
230 } // namespace perfetto::trace_processor::fuchsia_trace_utils
231
232 #endif // SRC_TRACE_PROCESSOR_IMPORTERS_FUCHSIA_FUCHSIA_TRACE_UTILS_H_
233