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