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