1*795d594fSAndroid Build Coastguard Worker /* 2*795d594fSAndroid Build Coastguard Worker * Copyright (C) 2016 The Android Open Source Project 3*795d594fSAndroid Build Coastguard Worker * 4*795d594fSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License"); 5*795d594fSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License. 6*795d594fSAndroid Build Coastguard Worker * You may obtain a copy of the License at 7*795d594fSAndroid Build Coastguard Worker * 8*795d594fSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0 9*795d594fSAndroid Build Coastguard Worker * 10*795d594fSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software 11*795d594fSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS, 12*795d594fSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13*795d594fSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and 14*795d594fSAndroid Build Coastguard Worker * limitations under the License. 15*795d594fSAndroid Build Coastguard Worker */ 16*795d594fSAndroid Build Coastguard Worker 17*795d594fSAndroid Build Coastguard Worker #ifndef ART_LIBELFFILE_DWARF_DEBUG_ABBREV_WRITER_H_ 18*795d594fSAndroid Build Coastguard Worker #define ART_LIBELFFILE_DWARF_DEBUG_ABBREV_WRITER_H_ 19*795d594fSAndroid Build Coastguard Worker 20*795d594fSAndroid Build Coastguard Worker #include <cstdint> 21*795d594fSAndroid Build Coastguard Worker #include <type_traits> 22*795d594fSAndroid Build Coastguard Worker #include <unordered_map> 23*795d594fSAndroid Build Coastguard Worker 24*795d594fSAndroid Build Coastguard Worker #include "base/casts.h" 25*795d594fSAndroid Build Coastguard Worker #include "base/leb128.h" 26*795d594fSAndroid Build Coastguard Worker #include "base/stl_util.h" 27*795d594fSAndroid Build Coastguard Worker #include "dwarf/dwarf_constants.h" 28*795d594fSAndroid Build Coastguard Worker #include "dwarf/writer.h" 29*795d594fSAndroid Build Coastguard Worker 30*795d594fSAndroid Build Coastguard Worker namespace art { 31*795d594fSAndroid Build Coastguard Worker namespace dwarf { 32*795d594fSAndroid Build Coastguard Worker 33*795d594fSAndroid Build Coastguard Worker // Writer for the .debug_abbrev. 34*795d594fSAndroid Build Coastguard Worker // 35*795d594fSAndroid Build Coastguard Worker // Abbreviations specify the format of entries in .debug_info. 36*795d594fSAndroid Build Coastguard Worker // Each entry specifies abbreviation code, which in turns 37*795d594fSAndroid Build Coastguard Worker // determines all the attributes and their format. 38*795d594fSAndroid Build Coastguard Worker // It is possible to think of them as type definitions. 39*795d594fSAndroid Build Coastguard Worker template <typename Vector = std::vector<uint8_t>> 40*795d594fSAndroid Build Coastguard Worker class DebugAbbrevWriter final : private Writer<Vector> { 41*795d594fSAndroid Build Coastguard Worker static_assert(std::is_same<typename Vector::value_type, uint8_t>::value, "Invalid value type"); 42*795d594fSAndroid Build Coastguard Worker 43*795d594fSAndroid Build Coastguard Worker public: DebugAbbrevWriter(Vector * buffer)44*795d594fSAndroid Build Coastguard Worker explicit DebugAbbrevWriter(Vector* buffer) 45*795d594fSAndroid Build Coastguard Worker : Writer<Vector>(buffer), 46*795d594fSAndroid Build Coastguard Worker current_abbrev_(buffer->get_allocator()) { 47*795d594fSAndroid Build Coastguard Worker this->PushUint8(0); // Add abbrev table terminator. 48*795d594fSAndroid Build Coastguard Worker } 49*795d594fSAndroid Build Coastguard Worker 50*795d594fSAndroid Build Coastguard Worker // Start abbreviation declaration. StartAbbrev(Tag tag)51*795d594fSAndroid Build Coastguard Worker void StartAbbrev(Tag tag) { 52*795d594fSAndroid Build Coastguard Worker DCHECK(current_abbrev_.empty()); 53*795d594fSAndroid Build Coastguard Worker EncodeUnsignedLeb128(¤t_abbrev_, tag); 54*795d594fSAndroid Build Coastguard Worker has_children_offset_ = current_abbrev_.size(); 55*795d594fSAndroid Build Coastguard Worker current_abbrev_.push_back(0); // Place-holder for DW_CHILDREN. 56*795d594fSAndroid Build Coastguard Worker } 57*795d594fSAndroid Build Coastguard Worker 58*795d594fSAndroid Build Coastguard Worker // Add attribute specification. AddAbbrevAttribute(Attribute name,Form type)59*795d594fSAndroid Build Coastguard Worker void AddAbbrevAttribute(Attribute name, Form type) { 60*795d594fSAndroid Build Coastguard Worker EncodeUnsignedLeb128(¤t_abbrev_, name); 61*795d594fSAndroid Build Coastguard Worker EncodeUnsignedLeb128(¤t_abbrev_, type); 62*795d594fSAndroid Build Coastguard Worker } 63*795d594fSAndroid Build Coastguard Worker 64*795d594fSAndroid Build Coastguard Worker // End abbreviation declaration and return its code. 65*795d594fSAndroid Build Coastguard Worker // This will deduplicate abbreviations. EndAbbrev(Children has_children)66*795d594fSAndroid Build Coastguard Worker uint32_t EndAbbrev(Children has_children) { 67*795d594fSAndroid Build Coastguard Worker DCHECK(!current_abbrev_.empty()); 68*795d594fSAndroid Build Coastguard Worker current_abbrev_[has_children_offset_] = has_children; 69*795d594fSAndroid Build Coastguard Worker auto it = abbrev_codes_.insert(std::make_pair(std::move(current_abbrev_), NextAbbrevCode())); 70*795d594fSAndroid Build Coastguard Worker uint32_t abbrev_code = it.first->second; 71*795d594fSAndroid Build Coastguard Worker if (UNLIKELY(it.second)) { // Inserted new entry. 72*795d594fSAndroid Build Coastguard Worker const Vector& abbrev = it.first->first; 73*795d594fSAndroid Build Coastguard Worker this->Pop(); // Remove abbrev table terminator. 74*795d594fSAndroid Build Coastguard Worker this->PushUleb128(abbrev_code); 75*795d594fSAndroid Build Coastguard Worker this->PushData(abbrev.data(), abbrev.size()); 76*795d594fSAndroid Build Coastguard Worker this->PushUint8(0); // Attribute list end. 77*795d594fSAndroid Build Coastguard Worker this->PushUint8(0); // Attribute list end. 78*795d594fSAndroid Build Coastguard Worker this->PushUint8(0); // Add abbrev table terminator. 79*795d594fSAndroid Build Coastguard Worker } 80*795d594fSAndroid Build Coastguard Worker current_abbrev_.clear(); 81*795d594fSAndroid Build Coastguard Worker return abbrev_code; 82*795d594fSAndroid Build Coastguard Worker } 83*795d594fSAndroid Build Coastguard Worker 84*795d594fSAndroid Build Coastguard Worker // Get the next free abbrev code. NextAbbrevCode()85*795d594fSAndroid Build Coastguard Worker uint32_t NextAbbrevCode() { 86*795d594fSAndroid Build Coastguard Worker return dchecked_integral_cast<uint32_t>(1 + abbrev_codes_.size()); 87*795d594fSAndroid Build Coastguard Worker } 88*795d594fSAndroid Build Coastguard Worker 89*795d594fSAndroid Build Coastguard Worker private: 90*795d594fSAndroid Build Coastguard Worker Vector current_abbrev_; 91*795d594fSAndroid Build Coastguard Worker size_t has_children_offset_ = 0; 92*795d594fSAndroid Build Coastguard Worker std::unordered_map<Vector, uint32_t, FNVHash<Vector> > abbrev_codes_; 93*795d594fSAndroid Build Coastguard Worker }; 94*795d594fSAndroid Build Coastguard Worker 95*795d594fSAndroid Build Coastguard Worker } // namespace dwarf 96*795d594fSAndroid Build Coastguard Worker } // namespace art 97*795d594fSAndroid Build Coastguard Worker 98*795d594fSAndroid Build Coastguard Worker #endif // ART_LIBELFFILE_DWARF_DEBUG_ABBREV_WRITER_H_ 99