1 /* 2 * Copyright (C) 2018 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 NOGROD_DWARF_ABBREV_ 18 #define NOGROD_DWARF_ABBREV_ 19 20 #include <cstddef> 21 #include <cstdint> 22 #include <memory> 23 #include <optional> 24 #include <string> 25 #include <vector> 26 27 #include <berberis/base/macros.h> 28 29 #include "dwarf_context.h" 30 31 namespace nogrod { 32 33 class DwarfAttribute { 34 public: 35 explicit DwarfAttribute(uint32_t name); 36 virtual ~DwarfAttribute() = default; 37 38 DwarfAttribute(const DwarfAttribute&) = delete; 39 const DwarfAttribute& operator=(const DwarfAttribute&) = delete; 40 name()41 [[nodiscard]] uint32_t name() const { return name_; } 42 [[nodiscard]] virtual std::optional<std::string> StringValue() const = 0; 43 [[nodiscard]] virtual std::optional<uint64_t> Uint64Value() const = 0; 44 [[nodiscard]] virtual std::optional<bool> BoolValue() const = 0; 45 46 // Some forms of attributes need to be resolved after reading entire abbrev 47 // The example are string attributes of form DW_FORM_strx? in compilation unit 48 // may come before DW_AT_str_offset_base and have undefined base offset at 49 // the time of reading. These need to be resolved after whole compilation unit 50 // is read. 51 virtual void Resolve(DwarfContext* context) = 0; 52 53 private: 54 uint32_t name_; 55 }; 56 57 template <typename T> 58 class DwarfAttributeValue : public DwarfAttribute { 59 public: DwarfAttributeValue(uint32_t name,T value)60 DwarfAttributeValue(uint32_t name, T value) : DwarfAttribute{name}, value_{std::move(value)} {} 61 62 DwarfAttributeValue(const DwarfAttributeValue&) = delete; 63 const DwarfAttributeValue& operator=(const DwarfAttributeValue&) = delete; 64 value()65 [[nodiscard]] const T& value() const { return value_; } 66 [[nodiscard]] std::optional<std::string> StringValue() const override; 67 [[nodiscard]] std::optional<uint64_t> Uint64Value() const override; 68 [[nodiscard]] std::optional<bool> BoolValue() const override; 69 70 void Resolve(DwarfContext* context) override; 71 72 private: 73 T value_; 74 }; 75 76 class DwarfStrXAttribute : public DwarfAttribute { 77 public: DwarfStrXAttribute(uint32_t name,uint64_t index)78 DwarfStrXAttribute(uint32_t name, uint64_t index) : DwarfAttribute{name}, index_{index} {} 79 80 [[nodiscard]] std::optional<std::string> StringValue() const override; 81 Uint64Value()82 [[nodiscard]] std::optional<uint64_t> Uint64Value() const override { return std::nullopt; } 83 BoolValue()84 [[nodiscard]] std::optional<bool> BoolValue() const override { return std::nullopt; } 85 86 void Resolve(DwarfContext* context) override; 87 88 private: 89 std::optional<std::string> string_; 90 uint64_t index_; 91 }; 92 93 class DwarfCompilationUnitHeader { 94 public: 95 DwarfCompilationUnitHeader(uint64_t unit_offset, 96 uint64_t unit_length, 97 uint16_t version, 98 uint64_t abbrev_offset, 99 uint8_t address_size, 100 bool is_dwarf64); 101 102 DwarfCompilationUnitHeader(const DwarfCompilationUnitHeader&) = delete; 103 const DwarfCompilationUnitHeader& operator=(const DwarfCompilationUnitHeader&) = delete; 104 105 DwarfCompilationUnitHeader(DwarfCompilationUnitHeader&&) = default; 106 DwarfCompilationUnitHeader& operator=(DwarfCompilationUnitHeader&&) = default; 107 unit_offset()108 [[nodiscard]] uint64_t unit_offset() const { return unit_offset_; } unit_length()109 [[nodiscard]] uint64_t unit_length() const { return unit_length_; } version()110 [[nodiscard]] uint16_t version() const { return version_; } abbrev_offset()111 [[nodiscard]] uint64_t abbrev_offset() const { return abbrev_offset_; } address_size()112 [[nodiscard]] uint8_t address_size() const { return address_size_; } is_dwarf64()113 [[nodiscard]] bool is_dwarf64() const { return is_dwarf64_; } 114 115 private: 116 uint64_t unit_offset_; 117 uint64_t unit_length_; 118 uint16_t version_; 119 uint64_t abbrev_offset_; 120 uint8_t address_size_; 121 bool is_dwarf64_; 122 }; 123 124 class DwarfAbbrevAttribute; 125 126 class DwarfClass { 127 public: 128 static const DwarfClass* kAddress; 129 static const DwarfClass* kAddrptr; 130 static const DwarfClass* kBlock; 131 static const DwarfClass* kConstant; 132 static const DwarfClass* kExprloc; 133 static const DwarfClass* kFlag; 134 static const DwarfClass* kLineptr; 135 static const DwarfClass* kLoclist; 136 static const DwarfClass* kLoclistsptr; 137 static const DwarfClass* kMacptr; 138 static const DwarfClass* kRnglist; 139 static const DwarfClass* kRnglistsptr; 140 static const DwarfClass* kReference; 141 static const DwarfClass* kString; 142 static const DwarfClass* kStroffsetsptr; 143 144 DwarfClass() = delete; 145 DwarfClass(const DwarfClass&) = delete; 146 DwarfClass& operator=(const DwarfClass&) = delete; 147 DwarfClass(DwarfClass&&) = delete; 148 DwarfClass& operator=(DwarfClass&&) = delete; 149 150 virtual ~DwarfClass() = default; 151 [[nodiscard]] const char* name() const; 152 [[nodiscard]] virtual std::unique_ptr<DwarfAttribute> ReadAttribute( 153 const DwarfCompilationUnitHeader* cu, 154 const DwarfAbbrevAttribute* abbrev_attr, 155 DwarfContext* context, 156 std::string* error_msg) const = 0; 157 158 protected: 159 explicit DwarfClass(const char* name); 160 161 private: 162 const char* name_; 163 }; 164 165 class DwarfAbbrevAttribute { 166 public: 167 static std::unique_ptr<const DwarfAbbrevAttribute> CreateAbbrevAttribute(uint16_t version, 168 uint32_t name, 169 uint32_t form, 170 int64_t value, 171 std::string* error_msg); 172 173 DwarfAbbrevAttribute(); 174 DwarfAbbrevAttribute(uint32_t name, uint32_t form, int64_t value, const DwarfClass* dwarf_class); 175 name()176 [[nodiscard]] uint32_t name() const { return name_; } form()177 [[nodiscard]] uint32_t form() const { return form_; } value()178 [[nodiscard]] int64_t value() const { return value_; } dwarf_class()179 [[nodiscard]] const DwarfClass* dwarf_class() const { return dwarf_class_; } 180 181 private: 182 uint32_t name_; 183 uint32_t form_; 184 int64_t value_; 185 const DwarfClass* dwarf_class_; 186 }; 187 188 class DwarfAbbrev { 189 public: 190 DwarfAbbrev(); 191 DwarfAbbrev(uint64_t code, uint64_t tag, bool has_children); 192 193 DwarfAbbrev(const DwarfAbbrev&) = delete; 194 const DwarfAbbrev& operator=(const DwarfAbbrev&) = delete; 195 196 DwarfAbbrev(DwarfAbbrev&&) = default; 197 DwarfAbbrev& operator=(DwarfAbbrev&&) = default; 198 199 void AddAttribute(std::unique_ptr<const DwarfAbbrevAttribute>&& abbrev_attribute); 200 tag()201 [[nodiscard]] uint64_t tag() const { return tag_; } code()202 [[nodiscard]] uint64_t code() const { return code_; } has_children()203 [[nodiscard]] bool has_children() const { return has_children_; } attributes()204 [[nodiscard]] const std::vector<std::unique_ptr<const DwarfAbbrevAttribute>>& attributes() const { 205 return attributes_; 206 } 207 208 private: 209 uint64_t code_; 210 uint64_t tag_; 211 bool has_children_; 212 std::vector<std::unique_ptr<const DwarfAbbrevAttribute>> attributes_; 213 }; 214 215 } // namespace nogrod 216 #endif // NOGROD_DWARF_ABBREV_ 217