/* * Copyright (C) 2019 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef SRC_TRACE_PROCESSOR_UTIL_DESCRIPTORS_H_ #define SRC_TRACE_PROCESSOR_UTIL_DESCRIPTORS_H_ #include #include #include #include #include #include "perfetto/base/status.h" #include "perfetto/ext/base/optional.h" #include "protos/perfetto/common/descriptor.pbzero.h" namespace protozero { struct ConstBytes; } namespace perfetto { namespace trace_processor { class FieldDescriptor { public: FieldDescriptor(std::string name, uint32_t number, uint32_t type, std::string raw_type_name, bool is_repeated, bool is_extension = false); const std::string& name() const { return name_; } uint32_t number() const { return number_; } uint32_t type() const { return type_; } const std::string& raw_type_name() const { return raw_type_name_; } const std::string& resolved_type_name() const { return resolved_type_name_; } bool is_repeated() const { return is_repeated_; } bool is_extension() const { return is_extension_; } void set_resolved_type_name(const std::string& resolved_type_name) { resolved_type_name_ = resolved_type_name; } private: std::string name_; uint32_t number_; uint32_t type_; std::string raw_type_name_; std::string resolved_type_name_; bool is_repeated_; bool is_extension_; }; FieldDescriptor CreateFieldFromDecoder( const protos::pbzero::FieldDescriptorProto::Decoder& f_decoder, bool is_extension); class ProtoDescriptor { public: enum class Type { kEnum = 0, kMessage = 1 }; ProtoDescriptor(std::string file_name, std::string package_name, std::string full_name, Type type, base::Optional parent_id); void AddField(FieldDescriptor descriptor) { PERFETTO_DCHECK(type_ == Type::kMessage); fields_.emplace(descriptor.number(), std::move(descriptor)); } void AddEnumValue(int32_t integer_representation, std::string string_representation) { PERFETTO_DCHECK(type_ == Type::kEnum); enum_values_[integer_representation] = std::move(string_representation); } const FieldDescriptor* FindFieldByName(const std::string& name) const { PERFETTO_DCHECK(type_ == Type::kMessage); auto it = std::find_if(fields_.begin(), fields_.end(), [name](std::pair p) { return p.second.name() == name; }); if (it == fields_.end()) { return nullptr; } return &it->second; } const FieldDescriptor* FindFieldByTag(const uint32_t tag_number) const { PERFETTO_DCHECK(type_ == Type::kMessage); auto it = fields_.find(tag_number); if (it == fields_.end()) { return nullptr; } return &it->second; } base::Optional FindEnumString(const int32_t value) const { PERFETTO_DCHECK(type_ == Type::kEnum); auto it = enum_values_.find(value); return it == enum_values_.end() ? base::nullopt : base::Optional(it->second); } const std::string& file_name() const { return file_name_; } const std::string& package_name() const { return package_name_; } const std::string& full_name() const { return full_name_; } Type type() const { return type_; } const std::unordered_map& fields() const { return fields_; } std::unordered_map* mutable_fields() { return &fields_; } private: std::string file_name_; // File in which descriptor was originally defined. std::string package_name_; std::string full_name_; const Type type_; base::Optional parent_id_; std::unordered_map fields_; std::unordered_map enum_values_; }; using ExtensionInfo = std::pair; class DescriptorPool { public: base::Status AddFromFileDescriptorSet( const uint8_t* file_descriptor_set_proto, size_t size, bool merge_existing_messages = false); base::Optional FindDescriptorIdx( const std::string& full_name) const; const std::vector& descriptors() const { return descriptors_; } std::vector SerializeAsDescriptorSet(); private: base::Status AddNestedProtoDescriptors(const std::string& file_name, const std::string& package_name, base::Optional parent_idx, protozero::ConstBytes descriptor_proto, std::vector* extensions, bool merge_existing_messages); base::Status AddEnumProtoDescriptors(const std::string& file_name, const std::string& package_name, base::Optional parent_idx, protozero::ConstBytes descriptor_proto, bool merge_existing_messages); base::Status AddExtensionField(const std::string& package_name, protozero::ConstBytes field_desc_proto); // Recursively searches for the given short type in all parent messages // and packages. base::Optional ResolveShortType(const std::string& parent_path, const std::string& short_type); std::vector descriptors_; std::set processed_files_; }; } // namespace trace_processor } // namespace perfetto #endif // SRC_TRACE_PROCESSOR_UTIL_DESCRIPTORS_H_