1 /* 2 * Copyright (C) 2014 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_COMPILER_DEBUG_DWARF_DEBUG_INFO_ENTRY_WRITER_H_ 18 #define ART_COMPILER_DEBUG_DWARF_DEBUG_INFO_ENTRY_WRITER_H_ 19 20 #include <cstdint> 21 #include <unordered_map> 22 23 #include "base/casts.h" 24 #include "base/leb128.h" 25 #include "debug/dwarf/debug_abbrev_writer.h" 26 #include "debug/dwarf/dwarf_constants.h" 27 #include "debug/dwarf/expression.h" 28 #include "debug/dwarf/writer.h" 29 30 namespace art { 31 namespace dwarf { 32 33 /* 34 * Writer for debug information entries (DIE). 35 * 36 * Usage: 37 * StartTag(DW_TAG_compile_unit); 38 * WriteStrp(DW_AT_producer, "Compiler name", debug_str); 39 * StartTag(DW_TAG_subprogram); 40 * WriteStrp(DW_AT_name, "Foo", debug_str); 41 * EndTag(); 42 * EndTag(); 43 */ 44 template <typename Vector = std::vector<uint8_t>> 45 class DebugInfoEntryWriter FINAL : private Writer<Vector> { 46 static_assert(std::is_same<typename Vector::value_type, uint8_t>::value, "Invalid value type"); 47 48 public: 49 static constexpr size_t kCompilationUnitHeaderSize = 11; 50 51 // Start debugging information entry. 52 // Returns offset of the entry in compilation unit. StartTag(Tag tag)53 size_t StartTag(Tag tag) { 54 if (inside_entry_) { 55 // Write abbrev code for the previous entry. 56 // Parent entry is finalized before any children are written. 57 this->UpdateUleb128(abbrev_code_offset_, debug_abbrev_->EndAbbrev(DW_CHILDREN_yes)); 58 inside_entry_ = false; 59 } 60 debug_abbrev_->StartAbbrev(tag); 61 // Abbrev code placeholder of sufficient size. 62 abbrev_code_offset_ = this->data()->size(); 63 this->PushUleb128(debug_abbrev_->NextAbbrevCode()); 64 depth_++; 65 inside_entry_ = true; 66 return abbrev_code_offset_ + kCompilationUnitHeaderSize; 67 } 68 69 // End debugging information entry. EndTag()70 void EndTag() { 71 DCHECK_GT(depth_, 0); 72 if (inside_entry_) { 73 // Write abbrev code for this entry. 74 this->UpdateUleb128(abbrev_code_offset_, debug_abbrev_->EndAbbrev(DW_CHILDREN_no)); 75 inside_entry_ = false; 76 // This entry has no children and so there is no terminator. 77 } else { 78 // The entry has been already finalized so it must be parent entry 79 // and we need to write the terminator required by DW_CHILDREN_yes. 80 this->PushUint8(0); 81 } 82 depth_--; 83 } 84 WriteAddr(Attribute attrib,uint64_t value)85 void WriteAddr(Attribute attrib, uint64_t value) { 86 debug_abbrev_->AddAbbrevAttribute(attrib, DW_FORM_addr); 87 patch_locations_.push_back(this->data()->size()); 88 if (is64bit_) { 89 this->PushUint64(value); 90 } else { 91 this->PushUint32(value); 92 } 93 } 94 WriteBlock(Attribute attrib,const uint8_t * ptr,size_t num_bytes)95 void WriteBlock(Attribute attrib, const uint8_t* ptr, size_t num_bytes) { 96 debug_abbrev_->AddAbbrevAttribute(attrib, DW_FORM_block); 97 this->PushUleb128(num_bytes); 98 this->PushData(ptr, num_bytes); 99 } 100 WriteExprLoc(Attribute attrib,const Expression & expr)101 void WriteExprLoc(Attribute attrib, const Expression& expr) { 102 debug_abbrev_->AddAbbrevAttribute(attrib, DW_FORM_exprloc); 103 this->PushUleb128(dchecked_integral_cast<uint32_t>(expr.size())); 104 this->PushData(expr.data()); 105 } 106 WriteData1(Attribute attrib,uint8_t value)107 void WriteData1(Attribute attrib, uint8_t value) { 108 debug_abbrev_->AddAbbrevAttribute(attrib, DW_FORM_data1); 109 this->PushUint8(value); 110 } 111 WriteData2(Attribute attrib,uint16_t value)112 void WriteData2(Attribute attrib, uint16_t value) { 113 debug_abbrev_->AddAbbrevAttribute(attrib, DW_FORM_data2); 114 this->PushUint16(value); 115 } 116 WriteData4(Attribute attrib,uint32_t value)117 void WriteData4(Attribute attrib, uint32_t value) { 118 debug_abbrev_->AddAbbrevAttribute(attrib, DW_FORM_data4); 119 this->PushUint32(value); 120 } 121 WriteData8(Attribute attrib,uint64_t value)122 void WriteData8(Attribute attrib, uint64_t value) { 123 debug_abbrev_->AddAbbrevAttribute(attrib, DW_FORM_data8); 124 this->PushUint64(value); 125 } 126 WriteSecOffset(Attribute attrib,uint32_t offset)127 void WriteSecOffset(Attribute attrib, uint32_t offset) { 128 debug_abbrev_->AddAbbrevAttribute(attrib, DW_FORM_sec_offset); 129 this->PushUint32(offset); 130 } 131 WriteSdata(Attribute attrib,int value)132 void WriteSdata(Attribute attrib, int value) { 133 debug_abbrev_->AddAbbrevAttribute(attrib, DW_FORM_sdata); 134 this->PushSleb128(value); 135 } 136 WriteUdata(Attribute attrib,int value)137 void WriteUdata(Attribute attrib, int value) { 138 debug_abbrev_->AddAbbrevAttribute(attrib, DW_FORM_udata); 139 this->PushUleb128(value); 140 } 141 WriteUdata(Attribute attrib,uint32_t value)142 void WriteUdata(Attribute attrib, uint32_t value) { 143 debug_abbrev_->AddAbbrevAttribute(attrib, DW_FORM_udata); 144 this->PushUleb128(value); 145 } 146 WriteFlag(Attribute attrib,bool value)147 void WriteFlag(Attribute attrib, bool value) { 148 debug_abbrev_->AddAbbrevAttribute(attrib, DW_FORM_flag); 149 this->PushUint8(value ? 1 : 0); 150 } 151 WriteFlagPresent(Attribute attrib)152 void WriteFlagPresent(Attribute attrib) { 153 debug_abbrev_->AddAbbrevAttribute(attrib, DW_FORM_flag_present); 154 } 155 WriteRef4(Attribute attrib,uint32_t cu_offset)156 void WriteRef4(Attribute attrib, uint32_t cu_offset) { 157 debug_abbrev_->AddAbbrevAttribute(attrib, DW_FORM_ref4); 158 this->PushUint32(cu_offset); 159 } 160 WriteRef(Attribute attrib,uint32_t cu_offset)161 void WriteRef(Attribute attrib, uint32_t cu_offset) { 162 debug_abbrev_->AddAbbrevAttribute(attrib, DW_FORM_ref_udata); 163 this->PushUleb128(cu_offset); 164 } 165 WriteString(Attribute attrib,const char * value)166 void WriteString(Attribute attrib, const char* value) { 167 debug_abbrev_->AddAbbrevAttribute(attrib, DW_FORM_string); 168 this->PushString(value); 169 } 170 WriteStrp(Attribute attrib,size_t debug_str_offset)171 void WriteStrp(Attribute attrib, size_t debug_str_offset) { 172 debug_abbrev_->AddAbbrevAttribute(attrib, DW_FORM_strp); 173 this->PushUint32(dchecked_integral_cast<uint32_t>(debug_str_offset)); 174 } 175 WriteStrp(Attribute attrib,const char * str,size_t len,std::vector<uint8_t> * debug_str)176 void WriteStrp(Attribute attrib, const char* str, size_t len, 177 std::vector<uint8_t>* debug_str) { 178 debug_abbrev_->AddAbbrevAttribute(attrib, DW_FORM_strp); 179 this->PushUint32(debug_str->size()); 180 debug_str->insert(debug_str->end(), str, str + len); 181 debug_str->push_back(0); 182 } 183 WriteStrp(Attribute attrib,const char * str,std::vector<uint8_t> * debug_str)184 void WriteStrp(Attribute attrib, const char* str, std::vector<uint8_t>* debug_str) { 185 WriteStrp(attrib, str, strlen(str), debug_str); 186 } 187 Is64bit()188 bool Is64bit() const { return is64bit_; } 189 GetPatchLocations()190 const std::vector<uintptr_t>& GetPatchLocations() const { 191 return patch_locations_; 192 } 193 Depth()194 int Depth() const { return depth_; } 195 196 using Writer<Vector>::data; 197 using Writer<Vector>::size; 198 using Writer<Vector>::UpdateUint32; 199 200 DebugInfoEntryWriter(bool is64bitArch, 201 DebugAbbrevWriter<Vector>* debug_abbrev, 202 const typename Vector::allocator_type& alloc = 203 typename Vector::allocator_type()) 204 : Writer<Vector>(&entries_), 205 debug_abbrev_(debug_abbrev), 206 entries_(alloc), 207 is64bit_(is64bitArch) { 208 } 209 ~DebugInfoEntryWriter()210 ~DebugInfoEntryWriter() { 211 DCHECK(!inside_entry_); 212 DCHECK_EQ(depth_, 0); 213 } 214 215 private: 216 DebugAbbrevWriter<Vector>* debug_abbrev_; 217 Vector entries_; 218 bool is64bit_; 219 int depth_ = 0; 220 size_t abbrev_code_offset_ = 0; // Location to patch once we know the code. 221 bool inside_entry_ = false; // Entry ends at first child (if any). 222 std::vector<uintptr_t> patch_locations_; 223 }; 224 225 } // namespace dwarf 226 } // namespace art 227 228 #endif // ART_COMPILER_DEBUG_DWARF_DEBUG_INFO_ENTRY_WRITER_H_ 229