• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_UTIL_DESCRIPTORS_H_
18 #define SRC_TRACE_PROCESSOR_UTIL_DESCRIPTORS_H_
19 
20 #include <algorithm>
21 #include <set>
22 #include <string>
23 #include <unordered_map>
24 #include <vector>
25 
26 #include "perfetto/base/status.h"
27 #include "perfetto/ext/base/optional.h"
28 #include "protos/perfetto/common/descriptor.pbzero.h"
29 
30 namespace protozero {
31 struct ConstBytes;
32 }
33 
34 namespace perfetto {
35 namespace trace_processor {
36 
37 class FieldDescriptor {
38  public:
39   FieldDescriptor(std::string name,
40                   uint32_t number,
41                   uint32_t type,
42                   std::string raw_type_name,
43                   bool is_repeated,
44                   bool is_extension = false);
45 
name()46   const std::string& name() const { return name_; }
number()47   uint32_t number() const { return number_; }
type()48   uint32_t type() const { return type_; }
raw_type_name()49   const std::string& raw_type_name() const { return raw_type_name_; }
resolved_type_name()50   const std::string& resolved_type_name() const { return resolved_type_name_; }
is_repeated()51   bool is_repeated() const { return is_repeated_; }
is_extension()52   bool is_extension() const { return is_extension_; }
53 
set_resolved_type_name(const std::string & resolved_type_name)54   void set_resolved_type_name(const std::string& resolved_type_name) {
55     resolved_type_name_ = resolved_type_name;
56   }
57 
58  private:
59   std::string name_;
60   uint32_t number_;
61   uint32_t type_;
62   std::string raw_type_name_;
63   std::string resolved_type_name_;
64   bool is_repeated_;
65   bool is_extension_;
66 };
67 
68 FieldDescriptor CreateFieldFromDecoder(
69     const protos::pbzero::FieldDescriptorProto::Decoder& f_decoder,
70     bool is_extension);
71 
72 class ProtoDescriptor {
73  public:
74   enum class Type { kEnum = 0, kMessage = 1 };
75 
76   ProtoDescriptor(std::string file_name,
77                   std::string package_name,
78                   std::string full_name,
79                   Type type,
80                   base::Optional<uint32_t> parent_id);
81 
AddField(FieldDescriptor descriptor)82   void AddField(FieldDescriptor descriptor) {
83     PERFETTO_DCHECK(type_ == Type::kMessage);
84     fields_.emplace(descriptor.number(), std::move(descriptor));
85   }
86 
AddEnumValue(int32_t integer_representation,std::string string_representation)87   void AddEnumValue(int32_t integer_representation,
88                     std::string string_representation) {
89     PERFETTO_DCHECK(type_ == Type::kEnum);
90     enum_values_[integer_representation] = std::move(string_representation);
91   }
92 
FindFieldByName(const std::string & name)93   const FieldDescriptor* FindFieldByName(const std::string& name) const {
94     PERFETTO_DCHECK(type_ == Type::kMessage);
95     auto it =
96         std::find_if(fields_.begin(), fields_.end(),
97                      [name](std::pair<int32_t, const FieldDescriptor&> p) {
98                        return p.second.name() == name;
99                      });
100     if (it == fields_.end()) {
101       return nullptr;
102     }
103     return &it->second;
104   }
105 
FindFieldByTag(const uint32_t tag_number)106   const FieldDescriptor* FindFieldByTag(const uint32_t tag_number) const {
107     PERFETTO_DCHECK(type_ == Type::kMessage);
108     auto it = fields_.find(tag_number);
109     if (it == fields_.end()) {
110       return nullptr;
111     }
112     return &it->second;
113   }
114 
FindEnumString(const int32_t value)115   base::Optional<std::string> FindEnumString(const int32_t value) const {
116     PERFETTO_DCHECK(type_ == Type::kEnum);
117     auto it = enum_values_.find(value);
118     return it == enum_values_.end() ? base::nullopt
119                                     : base::Optional<std::string>(it->second);
120   }
121 
file_name()122   const std::string& file_name() const { return file_name_; }
123 
package_name()124   const std::string& package_name() const { return package_name_; }
125 
full_name()126   const std::string& full_name() const { return full_name_; }
127 
type()128   Type type() const { return type_; }
129 
fields()130   const std::unordered_map<uint32_t, FieldDescriptor>& fields() const {
131     return fields_;
132   }
mutable_fields()133   std::unordered_map<uint32_t, FieldDescriptor>* mutable_fields() {
134     return &fields_;
135   }
136 
137  private:
138   std::string file_name_;  // File in which descriptor was originally defined.
139   std::string package_name_;
140   std::string full_name_;
141   const Type type_;
142   base::Optional<uint32_t> parent_id_;
143   std::unordered_map<uint32_t, FieldDescriptor> fields_;
144   std::unordered_map<int32_t, std::string> enum_values_;
145 };
146 
147 using ExtensionInfo = std::pair<std::string, protozero::ConstBytes>;
148 
149 class DescriptorPool {
150  public:
151   base::Status AddFromFileDescriptorSet(
152       const uint8_t* file_descriptor_set_proto,
153       size_t size,
154       bool merge_existing_messages = false);
155 
156   base::Optional<uint32_t> FindDescriptorIdx(
157       const std::string& full_name) const;
158 
descriptors()159   const std::vector<ProtoDescriptor>& descriptors() const {
160     return descriptors_;
161   }
162 
163   std::vector<uint8_t> SerializeAsDescriptorSet();
164 
165  private:
166   base::Status AddNestedProtoDescriptors(const std::string& file_name,
167                                          const std::string& package_name,
168                                          base::Optional<uint32_t> parent_idx,
169                                          protozero::ConstBytes descriptor_proto,
170                                          std::vector<ExtensionInfo>* extensions,
171                                          bool merge_existing_messages);
172   base::Status AddEnumProtoDescriptors(const std::string& file_name,
173                                        const std::string& package_name,
174                                        base::Optional<uint32_t> parent_idx,
175                                        protozero::ConstBytes descriptor_proto,
176                                        bool merge_existing_messages);
177 
178   base::Status AddExtensionField(const std::string& package_name,
179                                  protozero::ConstBytes field_desc_proto);
180 
181   // Recursively searches for the given short type in all parent messages
182   // and packages.
183   base::Optional<uint32_t> ResolveShortType(const std::string& parent_path,
184                                             const std::string& short_type);
185 
186   std::vector<ProtoDescriptor> descriptors_;
187   std::set<std::string> processed_files_;
188 };
189 
190 }  // namespace trace_processor
191 }  // namespace perfetto
192 
193 #endif  // SRC_TRACE_PROCESSOR_UTIL_DESCRIPTORS_H_
194