/* * Copyright (C) 2018 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 NOGROD_DWARF_ABBREV_ #define NOGROD_DWARF_ABBREV_ #include #include #include #include #include #include #include #include "dwarf_context.h" namespace nogrod { class DwarfAttribute { public: explicit DwarfAttribute(uint32_t name); virtual ~DwarfAttribute() = default; DwarfAttribute(const DwarfAttribute&) = delete; const DwarfAttribute& operator=(const DwarfAttribute&) = delete; [[nodiscard]] uint32_t name() const { return name_; } [[nodiscard]] virtual std::optional StringValue() const = 0; [[nodiscard]] virtual std::optional Uint64Value() const = 0; [[nodiscard]] virtual std::optional BoolValue() const = 0; // Some forms of attributes need to be resolved after reading entire abbrev // The example are string attributes of form DW_FORM_strx? in compilation unit // may come before DW_AT_str_offset_base and have undefined base offset at // the time of reading. These need to be resolved after whole compilation unit // is read. virtual void Resolve(DwarfContext* context) = 0; private: uint32_t name_; }; template class DwarfAttributeValue : public DwarfAttribute { public: DwarfAttributeValue(uint32_t name, T value) : DwarfAttribute{name}, value_{std::move(value)} {} DwarfAttributeValue(const DwarfAttributeValue&) = delete; const DwarfAttributeValue& operator=(const DwarfAttributeValue&) = delete; [[nodiscard]] const T& value() const { return value_; } [[nodiscard]] std::optional StringValue() const override; [[nodiscard]] std::optional Uint64Value() const override; [[nodiscard]] std::optional BoolValue() const override; void Resolve(DwarfContext* context) override; private: T value_; }; class DwarfStrXAttribute : public DwarfAttribute { public: DwarfStrXAttribute(uint32_t name, uint64_t index) : DwarfAttribute{name}, index_{index} {} [[nodiscard]] std::optional StringValue() const override; [[nodiscard]] std::optional Uint64Value() const override { return std::nullopt; } [[nodiscard]] std::optional BoolValue() const override { return std::nullopt; } void Resolve(DwarfContext* context) override; private: std::optional string_; uint64_t index_; }; class DwarfCompilationUnitHeader { public: DwarfCompilationUnitHeader(uint64_t unit_offset, uint64_t unit_length, uint16_t version, uint64_t abbrev_offset, uint8_t address_size, bool is_dwarf64); DwarfCompilationUnitHeader(const DwarfCompilationUnitHeader&) = delete; const DwarfCompilationUnitHeader& operator=(const DwarfCompilationUnitHeader&) = delete; DwarfCompilationUnitHeader(DwarfCompilationUnitHeader&&) = default; DwarfCompilationUnitHeader& operator=(DwarfCompilationUnitHeader&&) = default; [[nodiscard]] uint64_t unit_offset() const { return unit_offset_; } [[nodiscard]] uint64_t unit_length() const { return unit_length_; } [[nodiscard]] uint16_t version() const { return version_; } [[nodiscard]] uint64_t abbrev_offset() const { return abbrev_offset_; } [[nodiscard]] uint8_t address_size() const { return address_size_; } [[nodiscard]] bool is_dwarf64() const { return is_dwarf64_; } private: uint64_t unit_offset_; uint64_t unit_length_; uint16_t version_; uint64_t abbrev_offset_; uint8_t address_size_; bool is_dwarf64_; }; class DwarfAbbrevAttribute; class DwarfClass { public: static const DwarfClass* kAddress; static const DwarfClass* kAddrptr; static const DwarfClass* kBlock; static const DwarfClass* kConstant; static const DwarfClass* kExprloc; static const DwarfClass* kFlag; static const DwarfClass* kLineptr; static const DwarfClass* kLoclist; static const DwarfClass* kLoclistsptr; static const DwarfClass* kMacptr; static const DwarfClass* kRnglist; static const DwarfClass* kRnglistsptr; static const DwarfClass* kReference; static const DwarfClass* kString; static const DwarfClass* kStroffsetsptr; DwarfClass() = delete; DwarfClass(const DwarfClass&) = delete; DwarfClass& operator=(const DwarfClass&) = delete; DwarfClass(DwarfClass&&) = delete; DwarfClass& operator=(DwarfClass&&) = delete; virtual ~DwarfClass() = default; [[nodiscard]] const char* name() const; [[nodiscard]] virtual std::unique_ptr ReadAttribute( const DwarfCompilationUnitHeader* cu, const DwarfAbbrevAttribute* abbrev_attr, DwarfContext* context, std::string* error_msg) const = 0; protected: explicit DwarfClass(const char* name); private: const char* name_; }; class DwarfAbbrevAttribute { public: static std::unique_ptr CreateAbbrevAttribute(uint16_t version, uint32_t name, uint32_t form, int64_t value, std::string* error_msg); DwarfAbbrevAttribute(); DwarfAbbrevAttribute(uint32_t name, uint32_t form, int64_t value, const DwarfClass* dwarf_class); [[nodiscard]] uint32_t name() const { return name_; } [[nodiscard]] uint32_t form() const { return form_; } [[nodiscard]] int64_t value() const { return value_; } [[nodiscard]] const DwarfClass* dwarf_class() const { return dwarf_class_; } private: uint32_t name_; uint32_t form_; int64_t value_; const DwarfClass* dwarf_class_; }; class DwarfAbbrev { public: DwarfAbbrev(); DwarfAbbrev(uint64_t code, uint64_t tag, bool has_children); DwarfAbbrev(const DwarfAbbrev&) = delete; const DwarfAbbrev& operator=(const DwarfAbbrev&) = delete; DwarfAbbrev(DwarfAbbrev&&) = default; DwarfAbbrev& operator=(DwarfAbbrev&&) = default; void AddAttribute(std::unique_ptr&& abbrev_attribute); [[nodiscard]] uint64_t tag() const { return tag_; } [[nodiscard]] uint64_t code() const { return code_; } [[nodiscard]] bool has_children() const { return has_children_; } [[nodiscard]] const std::vector>& attributes() const { return attributes_; } private: uint64_t code_; uint64_t tag_; bool has_children_; std::vector> attributes_; }; } // namespace nogrod #endif // NOGROD_DWARF_ABBREV_