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 <cstddef> 22 #include <cstdint> 23 #include <optional> 24 #include <set> 25 #include <string> 26 #include <unordered_map> 27 #include <utility> 28 #include <vector> 29 30 #include "perfetto/base/logging.h" 31 #include "perfetto/base/status.h" 32 33 namespace protozero { 34 struct ConstBytes; 35 } 36 37 namespace perfetto::trace_processor { 38 39 class FieldDescriptor { 40 public: 41 FieldDescriptor(std::string name, 42 uint32_t number, 43 uint32_t type, 44 std::string raw_type_name, 45 std::vector<uint8_t> options, 46 std::optional<std::string> default_value, 47 bool is_repeated, 48 bool is_packed, 49 bool is_extension = false); 50 name()51 const std::string& name() const { return name_; } number()52 uint32_t number() const { return number_; } type()53 uint32_t type() const { return type_; } raw_type_name()54 const std::string& raw_type_name() const { return raw_type_name_; } resolved_type_name()55 const std::string& resolved_type_name() const { return resolved_type_name_; } is_repeated()56 bool is_repeated() const { return is_repeated_; } is_packed()57 bool is_packed() const { return is_packed_; } is_extension()58 bool is_extension() const { return is_extension_; } 59 options()60 const std::vector<uint8_t>& options() const { return options_; } mutable_options()61 std::vector<uint8_t>* mutable_options() { return &options_; } default_value()62 const std::optional<std::string>& default_value() const { 63 return default_value_; 64 } 65 set_resolved_type_name(const std::string & resolved_type_name)66 void set_resolved_type_name(const std::string& resolved_type_name) { 67 resolved_type_name_ = resolved_type_name; 68 } 69 70 private: 71 std::string name_; 72 uint32_t number_; 73 uint32_t type_; 74 std::string raw_type_name_; 75 std::string resolved_type_name_; 76 std::vector<uint8_t> options_; 77 std::optional<std::string> default_value_; 78 bool is_repeated_; 79 bool is_packed_; 80 bool is_extension_; 81 }; 82 83 class ProtoDescriptor { 84 public: 85 enum class Type { kEnum = 0, kMessage = 1 }; 86 87 ProtoDescriptor(std::string file_name, 88 std::string package_name, 89 std::string full_name, 90 Type type, 91 std::optional<uint32_t> parent_id); 92 AddField(FieldDescriptor descriptor)93 void AddField(FieldDescriptor descriptor) { 94 PERFETTO_DCHECK(type_ == Type::kMessage); 95 fields_.emplace(descriptor.number(), std::move(descriptor)); 96 } 97 AddEnumValue(int32_t integer_representation,std::string string_representation)98 void AddEnumValue(int32_t integer_representation, 99 std::string string_representation) { 100 PERFETTO_DCHECK(type_ == Type::kEnum); 101 enum_values_by_name_[string_representation] = integer_representation; 102 enum_names_by_value_[integer_representation] = 103 std::move(string_representation); 104 } 105 FindFieldByName(const std::string & name)106 const FieldDescriptor* FindFieldByName(const std::string& name) const { 107 PERFETTO_DCHECK(type_ == Type::kMessage); 108 auto it = std::find_if( 109 fields_.begin(), fields_.end(), 110 [name](const std::pair<const uint32_t, FieldDescriptor>& p) { 111 return p.second.name() == name; 112 }); 113 if (it == fields_.end()) { 114 return nullptr; 115 } 116 return &it->second; 117 } 118 FindFieldByTag(const uint32_t tag_number)119 const FieldDescriptor* FindFieldByTag(const uint32_t tag_number) const { 120 PERFETTO_DCHECK(type_ == Type::kMessage); 121 auto it = fields_.find(tag_number); 122 if (it == fields_.end()) { 123 return nullptr; 124 } 125 return &it->second; 126 } 127 FindEnumString(const int32_t value)128 std::optional<std::string> FindEnumString(const int32_t value) const { 129 PERFETTO_DCHECK(type_ == Type::kEnum); 130 auto it = enum_names_by_value_.find(value); 131 return it == enum_names_by_value_.end() ? std::nullopt 132 : std::make_optional(it->second); 133 } 134 FindEnumValue(const std::string & value)135 std::optional<int32_t> FindEnumValue(const std::string& value) const { 136 PERFETTO_DCHECK(type_ == Type::kEnum); 137 auto it = enum_values_by_name_.find(value); 138 return it == enum_values_by_name_.end() ? std::nullopt 139 : std::make_optional(it->second); 140 } 141 file_name()142 const std::string& file_name() const { return file_name_; } 143 package_name()144 const std::string& package_name() const { return package_name_; } 145 full_name()146 const std::string& full_name() const { return full_name_; } 147 type()148 Type type() const { return type_; } 149 fields()150 const std::unordered_map<uint32_t, FieldDescriptor>& fields() const { 151 return fields_; 152 } mutable_fields()153 std::unordered_map<uint32_t, FieldDescriptor>* mutable_fields() { 154 return &fields_; 155 } 156 157 private: 158 std::string file_name_; // File in which descriptor was originally defined. 159 std::string package_name_; 160 std::string full_name_; 161 const Type type_; 162 std::optional<uint32_t> parent_id_; 163 std::unordered_map<uint32_t, FieldDescriptor> fields_; 164 std::unordered_map<int32_t, std::string> enum_names_by_value_; 165 std::unordered_map<std::string, int32_t> enum_values_by_name_; 166 }; 167 168 using ExtensionInfo = std::pair<std::string, protozero::ConstBytes>; 169 170 class DescriptorPool { 171 public: 172 // Adds Descriptors from file_descriptor_set_proto. Ignores any FileDescriptor 173 // with name matching a prefix in |skip_prefixes|. 174 base::Status AddFromFileDescriptorSet( 175 const uint8_t* file_descriptor_set_proto, 176 size_t size, 177 const std::vector<std::string>& skip_prefixes = {}, 178 bool merge_existing_messages = false); 179 180 std::optional<uint32_t> FindDescriptorIdx(const std::string& full_name) const; 181 182 std::vector<uint8_t> SerializeAsDescriptorSet() const; 183 AddProtoDescriptorForTesting(ProtoDescriptor descriptor)184 void AddProtoDescriptorForTesting(ProtoDescriptor descriptor) { 185 AddProtoDescriptor(std::move(descriptor)); 186 } 187 descriptors()188 const std::vector<ProtoDescriptor>& descriptors() const { 189 return descriptors_; 190 } 191 192 private: 193 base::Status AddNestedProtoDescriptors(const std::string& file_name, 194 const std::string& package_name, 195 std::optional<uint32_t> parent_idx, 196 protozero::ConstBytes descriptor_proto, 197 std::vector<ExtensionInfo>* extensions, 198 bool merge_existing_messages); 199 base::Status AddEnumProtoDescriptors(const std::string& file_name, 200 const std::string& package_name, 201 std::optional<uint32_t> parent_idx, 202 protozero::ConstBytes descriptor_proto, 203 bool merge_existing_messages); 204 205 base::Status AddExtensionField(const std::string& package_name, 206 protozero::ConstBytes field_desc_proto); 207 208 // Recursively searches for the given short type in all parent messages 209 // and packages. 210 std::optional<uint32_t> ResolveShortType(const std::string& parent_path, 211 const std::string& short_type); 212 213 base::Status ResolveUninterpretedOption(const ProtoDescriptor&, 214 const FieldDescriptor&, 215 std::vector<uint8_t>&); 216 217 // Adds a new descriptor to the pool and returns its index. There must not be 218 // already a descriptor with the same full_name in the pool. 219 uint32_t AddProtoDescriptor(ProtoDescriptor descriptor); 220 221 std::vector<ProtoDescriptor> descriptors_; 222 // full_name -> index in the descriptors_ vector. 223 std::unordered_map<std::string, uint32_t> full_name_to_descriptor_index_; 224 std::set<std::string> processed_files_; 225 }; 226 227 } // namespace perfetto::trace_processor 228 229 #endif // SRC_TRACE_PROCESSOR_UTIL_DESCRIPTORS_H_ 230