124868a16c71d9a024101cce3b9ecc4b5ad038d07David Srbecky/* 224868a16c71d9a024101cce3b9ecc4b5ad038d07David Srbecky * Copyright (C) 2016 The Android Open Source Project 324868a16c71d9a024101cce3b9ecc4b5ad038d07David Srbecky * 424868a16c71d9a024101cce3b9ecc4b5ad038d07David Srbecky * Licensed under the Apache License, Version 2.0 (the "License"); 524868a16c71d9a024101cce3b9ecc4b5ad038d07David Srbecky * you may not use this file except in compliance with the License. 624868a16c71d9a024101cce3b9ecc4b5ad038d07David Srbecky * You may obtain a copy of the License at 724868a16c71d9a024101cce3b9ecc4b5ad038d07David Srbecky * 824868a16c71d9a024101cce3b9ecc4b5ad038d07David Srbecky * http://www.apache.org/licenses/LICENSE-2.0 924868a16c71d9a024101cce3b9ecc4b5ad038d07David Srbecky * 1024868a16c71d9a024101cce3b9ecc4b5ad038d07David Srbecky * Unless required by applicable law or agreed to in writing, software 1124868a16c71d9a024101cce3b9ecc4b5ad038d07David Srbecky * distributed under the License is distributed on an "AS IS" BASIS, 1224868a16c71d9a024101cce3b9ecc4b5ad038d07David Srbecky * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1324868a16c71d9a024101cce3b9ecc4b5ad038d07David Srbecky * See the License for the specific language governing permissions and 1424868a16c71d9a024101cce3b9ecc4b5ad038d07David Srbecky * limitations under the License. 1524868a16c71d9a024101cce3b9ecc4b5ad038d07David Srbecky */ 1624868a16c71d9a024101cce3b9ecc4b5ad038d07David Srbecky 174fda4eb799c95be266f52aaf3461a440ea86b841David Srbecky#ifndef ART_COMPILER_DEBUG_DWARF_DEBUG_ABBREV_WRITER_H_ 184fda4eb799c95be266f52aaf3461a440ea86b841David Srbecky#define ART_COMPILER_DEBUG_DWARF_DEBUG_ABBREV_WRITER_H_ 1924868a16c71d9a024101cce3b9ecc4b5ad038d07David Srbecky 2024868a16c71d9a024101cce3b9ecc4b5ad038d07David Srbecky#include <cstdint> 2124868a16c71d9a024101cce3b9ecc4b5ad038d07David Srbecky#include <type_traits> 2224868a16c71d9a024101cce3b9ecc4b5ad038d07David Srbecky#include <unordered_map> 2324868a16c71d9a024101cce3b9ecc4b5ad038d07David Srbecky 2424868a16c71d9a024101cce3b9ecc4b5ad038d07David Srbecky#include "base/casts.h" 2524868a16c71d9a024101cce3b9ecc4b5ad038d07David Srbecky#include "base/stl_util.h" 264fda4eb799c95be266f52aaf3461a440ea86b841David Srbecky#include "debug/dwarf/dwarf_constants.h" 274fda4eb799c95be266f52aaf3461a440ea86b841David Srbecky#include "debug/dwarf/writer.h" 2824868a16c71d9a024101cce3b9ecc4b5ad038d07David Srbecky#include "leb128.h" 2924868a16c71d9a024101cce3b9ecc4b5ad038d07David Srbecky 3024868a16c71d9a024101cce3b9ecc4b5ad038d07David Srbeckynamespace art { 3124868a16c71d9a024101cce3b9ecc4b5ad038d07David Srbeckynamespace dwarf { 3224868a16c71d9a024101cce3b9ecc4b5ad038d07David Srbecky 3324868a16c71d9a024101cce3b9ecc4b5ad038d07David Srbecky// Writer for the .debug_abbrev. 3424868a16c71d9a024101cce3b9ecc4b5ad038d07David Srbecky// 3524868a16c71d9a024101cce3b9ecc4b5ad038d07David Srbecky// Abbreviations specify the format of entries in .debug_info. 3624868a16c71d9a024101cce3b9ecc4b5ad038d07David Srbecky// Each entry specifies abbreviation code, which in turns 3724868a16c71d9a024101cce3b9ecc4b5ad038d07David Srbecky// determines all the attributes and their format. 3824868a16c71d9a024101cce3b9ecc4b5ad038d07David Srbecky// It is possible to think of them as type definitions. 3924868a16c71d9a024101cce3b9ecc4b5ad038d07David Srbeckytemplate <typename Vector = std::vector<uint8_t>> 4024868a16c71d9a024101cce3b9ecc4b5ad038d07David Srbeckyclass DebugAbbrevWriter FINAL : private Writer<Vector> { 4124868a16c71d9a024101cce3b9ecc4b5ad038d07David Srbecky static_assert(std::is_same<typename Vector::value_type, uint8_t>::value, "Invalid value type"); 4224868a16c71d9a024101cce3b9ecc4b5ad038d07David Srbecky 4324868a16c71d9a024101cce3b9ecc4b5ad038d07David Srbecky public: 4424868a16c71d9a024101cce3b9ecc4b5ad038d07David Srbecky explicit DebugAbbrevWriter(Vector* buffer) 4524868a16c71d9a024101cce3b9ecc4b5ad038d07David Srbecky : Writer<Vector>(buffer), 4624868a16c71d9a024101cce3b9ecc4b5ad038d07David Srbecky current_abbrev_(buffer->get_allocator()) { 4724868a16c71d9a024101cce3b9ecc4b5ad038d07David Srbecky this->PushUint8(0); // Add abbrev table terminator. 4824868a16c71d9a024101cce3b9ecc4b5ad038d07David Srbecky } 4924868a16c71d9a024101cce3b9ecc4b5ad038d07David Srbecky 5024868a16c71d9a024101cce3b9ecc4b5ad038d07David Srbecky // Start abbreviation declaration. 5124868a16c71d9a024101cce3b9ecc4b5ad038d07David Srbecky void StartAbbrev(Tag tag) { 5224868a16c71d9a024101cce3b9ecc4b5ad038d07David Srbecky DCHECK(current_abbrev_.empty()); 5324868a16c71d9a024101cce3b9ecc4b5ad038d07David Srbecky EncodeUnsignedLeb128(¤t_abbrev_, tag); 5424868a16c71d9a024101cce3b9ecc4b5ad038d07David Srbecky has_children_offset_ = current_abbrev_.size(); 5524868a16c71d9a024101cce3b9ecc4b5ad038d07David Srbecky current_abbrev_.push_back(0); // Place-holder for DW_CHILDREN. 5624868a16c71d9a024101cce3b9ecc4b5ad038d07David Srbecky } 5724868a16c71d9a024101cce3b9ecc4b5ad038d07David Srbecky 5824868a16c71d9a024101cce3b9ecc4b5ad038d07David Srbecky // Add attribute specification. 5924868a16c71d9a024101cce3b9ecc4b5ad038d07David Srbecky void AddAbbrevAttribute(Attribute name, Form type) { 6024868a16c71d9a024101cce3b9ecc4b5ad038d07David Srbecky EncodeUnsignedLeb128(¤t_abbrev_, name); 6124868a16c71d9a024101cce3b9ecc4b5ad038d07David Srbecky EncodeUnsignedLeb128(¤t_abbrev_, type); 6224868a16c71d9a024101cce3b9ecc4b5ad038d07David Srbecky } 6324868a16c71d9a024101cce3b9ecc4b5ad038d07David Srbecky 6424868a16c71d9a024101cce3b9ecc4b5ad038d07David Srbecky // End abbreviation declaration and return its code. 6524868a16c71d9a024101cce3b9ecc4b5ad038d07David Srbecky // This will deduplicate abbreviations. 6624868a16c71d9a024101cce3b9ecc4b5ad038d07David Srbecky uint32_t EndAbbrev(Children has_children) { 6724868a16c71d9a024101cce3b9ecc4b5ad038d07David Srbecky DCHECK(!current_abbrev_.empty()); 6824868a16c71d9a024101cce3b9ecc4b5ad038d07David Srbecky current_abbrev_[has_children_offset_] = has_children; 6924868a16c71d9a024101cce3b9ecc4b5ad038d07David Srbecky auto it = abbrev_codes_.insert(std::make_pair(std::move(current_abbrev_), NextAbbrevCode())); 7024868a16c71d9a024101cce3b9ecc4b5ad038d07David Srbecky uint32_t abbrev_code = it.first->second; 7124868a16c71d9a024101cce3b9ecc4b5ad038d07David Srbecky if (UNLIKELY(it.second)) { // Inserted new entry. 7224868a16c71d9a024101cce3b9ecc4b5ad038d07David Srbecky const Vector& abbrev = it.first->first; 7324868a16c71d9a024101cce3b9ecc4b5ad038d07David Srbecky this->Pop(); // Remove abbrev table terminator. 7424868a16c71d9a024101cce3b9ecc4b5ad038d07David Srbecky this->PushUleb128(abbrev_code); 7524868a16c71d9a024101cce3b9ecc4b5ad038d07David Srbecky this->PushData(abbrev.data(), abbrev.size()); 7624868a16c71d9a024101cce3b9ecc4b5ad038d07David Srbecky this->PushUint8(0); // Attribute list end. 7724868a16c71d9a024101cce3b9ecc4b5ad038d07David Srbecky this->PushUint8(0); // Attribute list end. 7824868a16c71d9a024101cce3b9ecc4b5ad038d07David Srbecky this->PushUint8(0); // Add abbrev table terminator. 7924868a16c71d9a024101cce3b9ecc4b5ad038d07David Srbecky } 8024868a16c71d9a024101cce3b9ecc4b5ad038d07David Srbecky current_abbrev_.clear(); 8124868a16c71d9a024101cce3b9ecc4b5ad038d07David Srbecky return abbrev_code; 8224868a16c71d9a024101cce3b9ecc4b5ad038d07David Srbecky } 8324868a16c71d9a024101cce3b9ecc4b5ad038d07David Srbecky 8424868a16c71d9a024101cce3b9ecc4b5ad038d07David Srbecky // Get the next free abbrev code. 8524868a16c71d9a024101cce3b9ecc4b5ad038d07David Srbecky uint32_t NextAbbrevCode() { 8624868a16c71d9a024101cce3b9ecc4b5ad038d07David Srbecky return dchecked_integral_cast<uint32_t>(1 + abbrev_codes_.size()); 8724868a16c71d9a024101cce3b9ecc4b5ad038d07David Srbecky } 8824868a16c71d9a024101cce3b9ecc4b5ad038d07David Srbecky 8924868a16c71d9a024101cce3b9ecc4b5ad038d07David Srbecky private: 9024868a16c71d9a024101cce3b9ecc4b5ad038d07David Srbecky Vector current_abbrev_; 9124868a16c71d9a024101cce3b9ecc4b5ad038d07David Srbecky size_t has_children_offset_ = 0; 9224868a16c71d9a024101cce3b9ecc4b5ad038d07David Srbecky std::unordered_map<Vector, uint32_t, FNVHash<Vector> > abbrev_codes_; 9324868a16c71d9a024101cce3b9ecc4b5ad038d07David Srbecky}; 9424868a16c71d9a024101cce3b9ecc4b5ad038d07David Srbecky 9524868a16c71d9a024101cce3b9ecc4b5ad038d07David Srbecky} // namespace dwarf 9624868a16c71d9a024101cce3b9ecc4b5ad038d07David Srbecky} // namespace art 9724868a16c71d9a024101cce3b9ecc4b5ad038d07David Srbecky 984fda4eb799c95be266f52aaf3461a440ea86b841David Srbecky#endif // ART_COMPILER_DEBUG_DWARF_DEBUG_ABBREV_WRITER_H_ 99