1 /* 2 * Copyright (C) 2016 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 ART_LIBELFFILE_DWARF_DEBUG_ABBREV_WRITER_H_ 18 #define ART_LIBELFFILE_DWARF_DEBUG_ABBREV_WRITER_H_ 19 20 #include <cstdint> 21 #include <type_traits> 22 #include <unordered_map> 23 24 #include "base/casts.h" 25 #include "base/leb128.h" 26 #include "base/stl_util.h" 27 #include "dwarf/dwarf_constants.h" 28 #include "dwarf/writer.h" 29 30 namespace art { 31 namespace dwarf { 32 33 // Writer for the .debug_abbrev. 34 // 35 // Abbreviations specify the format of entries in .debug_info. 36 // Each entry specifies abbreviation code, which in turns 37 // determines all the attributes and their format. 38 // It is possible to think of them as type definitions. 39 template <typename Vector = std::vector<uint8_t>> 40 class DebugAbbrevWriter final : private Writer<Vector> { 41 static_assert(std::is_same<typename Vector::value_type, uint8_t>::value, "Invalid value type"); 42 43 public: DebugAbbrevWriter(Vector * buffer)44 explicit DebugAbbrevWriter(Vector* buffer) 45 : Writer<Vector>(buffer), 46 current_abbrev_(buffer->get_allocator()) { 47 this->PushUint8(0); // Add abbrev table terminator. 48 } 49 50 // Start abbreviation declaration. StartAbbrev(Tag tag)51 void StartAbbrev(Tag tag) { 52 DCHECK(current_abbrev_.empty()); 53 EncodeUnsignedLeb128(¤t_abbrev_, tag); 54 has_children_offset_ = current_abbrev_.size(); 55 current_abbrev_.push_back(0); // Place-holder for DW_CHILDREN. 56 } 57 58 // Add attribute specification. AddAbbrevAttribute(Attribute name,Form type)59 void AddAbbrevAttribute(Attribute name, Form type) { 60 EncodeUnsignedLeb128(¤t_abbrev_, name); 61 EncodeUnsignedLeb128(¤t_abbrev_, type); 62 } 63 64 // End abbreviation declaration and return its code. 65 // This will deduplicate abbreviations. EndAbbrev(Children has_children)66 uint32_t EndAbbrev(Children has_children) { 67 DCHECK(!current_abbrev_.empty()); 68 current_abbrev_[has_children_offset_] = has_children; 69 auto it = abbrev_codes_.insert(std::make_pair(std::move(current_abbrev_), NextAbbrevCode())); 70 uint32_t abbrev_code = it.first->second; 71 if (UNLIKELY(it.second)) { // Inserted new entry. 72 const Vector& abbrev = it.first->first; 73 this->Pop(); // Remove abbrev table terminator. 74 this->PushUleb128(abbrev_code); 75 this->PushData(abbrev.data(), abbrev.size()); 76 this->PushUint8(0); // Attribute list end. 77 this->PushUint8(0); // Attribute list end. 78 this->PushUint8(0); // Add abbrev table terminator. 79 } 80 current_abbrev_.clear(); 81 return abbrev_code; 82 } 83 84 // Get the next free abbrev code. NextAbbrevCode()85 uint32_t NextAbbrevCode() { 86 return dchecked_integral_cast<uint32_t>(1 + abbrev_codes_.size()); 87 } 88 89 private: 90 Vector current_abbrev_; 91 size_t has_children_offset_ = 0; 92 std::unordered_map<Vector, uint32_t, FNVHash<Vector> > abbrev_codes_; 93 }; 94 95 } // namespace dwarf 96 } // namespace art 97 98 #endif // ART_LIBELFFILE_DWARF_DEBUG_ABBREV_WRITER_H_ 99