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/storage/trace_storage.h"
26 #include "src/trace_processor/trace_blob_view.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