blob: 1e298595a161b2bcbfd171f5f3a18a94d466a860 [file] [log] [blame]
David Srbeckyb5362472015-04-08 19:37:39 +01001/*
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_DWARF_DEBUG_INFO_ENTRY_WRITER_H_
18#define ART_COMPILER_DWARF_DEBUG_INFO_ENTRY_WRITER_H_
19
David Srbecky2f6cdb02015-04-11 00:17:53 +010020#include <cstdint>
David Srbeckyb5362472015-04-08 19:37:39 +010021#include <unordered_map>
22
David Srbecky04b05262015-11-09 18:05:48 +000023#include "base/casts.h"
David Srbecky24868a12016-01-29 18:59:56 +000024#include "dwarf/debug_abbrev_writer.h"
David Srbecky7c869b32015-04-12 08:47:47 +010025#include "dwarf/dwarf_constants.h"
David Srbecky91cb54e2016-01-15 13:47:59 +000026#include "dwarf/expression.h"
David Srbecky7c869b32015-04-12 08:47:47 +010027#include "dwarf/writer.h"
David Srbeckyb5362472015-04-08 19:37:39 +010028#include "leb128.h"
David Srbeckyb5362472015-04-08 19:37:39 +010029
30namespace art {
31namespace dwarf {
32
David Srbeckyb5362472015-04-08 19:37:39 +010033/*
34 * Writer for debug information entries (DIE).
David Srbeckyb5362472015-04-08 19:37:39 +010035 *
36 * Usage:
David Srbecky04b05262015-11-09 18:05:48 +000037 * StartTag(DW_TAG_compile_unit);
David Srbeckyb5362472015-04-08 19:37:39 +010038 * WriteStrp(DW_AT_producer, "Compiler name", debug_str);
David Srbecky04b05262015-11-09 18:05:48 +000039 * StartTag(DW_TAG_subprogram);
David Srbeckyb5362472015-04-08 19:37:39 +010040 * WriteStrp(DW_AT_name, "Foo", debug_str);
41 * EndTag();
42 * EndTag();
43 */
Vladimir Markoec7802a2015-10-01 20:57:57 +010044template <typename Vector = std::vector<uint8_t>>
45class DebugInfoEntryWriter FINAL : private Writer<Vector> {
46 static_assert(std::is_same<typename Vector::value_type, uint8_t>::value, "Invalid value type");
47
David Srbeckyb5362472015-04-08 19:37:39 +010048 public:
David Srbecky04b05262015-11-09 18:05:48 +000049 static constexpr size_t kCompilationUnitHeaderSize = 11;
50
David Srbeckyb5362472015-04-08 19:37:39 +010051 // Start debugging information entry.
David Srbecky04b05262015-11-09 18:05:48 +000052 // Returns offset of the entry in compilation unit.
53 size_t StartTag(Tag tag) {
David Srbeckyb5362472015-04-08 19:37:39 +010054 if (inside_entry_) {
55 // Write abbrev code for the previous entry.
David Srbecky04b05262015-11-09 18:05:48 +000056 // Parent entry is finalized before any children are written.
David Srbecky24868a12016-01-29 18:59:56 +000057 this->UpdateUleb128(abbrev_code_offset_, debug_abbrev_->EndAbbrev(DW_CHILDREN_yes));
David Srbeckyb5362472015-04-08 19:37:39 +010058 inside_entry_ = false;
59 }
David Srbecky24868a12016-01-29 18:59:56 +000060 debug_abbrev_->StartAbbrev(tag);
David Srbeckyb5362472015-04-08 19:37:39 +010061 // Abbrev code placeholder of sufficient size.
62 abbrev_code_offset_ = this->data()->size();
David Srbecky24868a12016-01-29 18:59:56 +000063 this->PushUleb128(debug_abbrev_->NextAbbrevCode());
David Srbeckyb5362472015-04-08 19:37:39 +010064 depth_++;
65 inside_entry_ = true;
David Srbecky04b05262015-11-09 18:05:48 +000066 return abbrev_code_offset_ + kCompilationUnitHeaderSize;
David Srbeckyb5362472015-04-08 19:37:39 +010067 }
68
69 // End debugging information entry.
70 void EndTag() {
71 DCHECK_GT(depth_, 0);
72 if (inside_entry_) {
David Srbecky04b05262015-11-09 18:05:48 +000073 // Write abbrev code for this entry.
David Srbecky24868a12016-01-29 18:59:56 +000074 this->UpdateUleb128(abbrev_code_offset_, debug_abbrev_->EndAbbrev(DW_CHILDREN_no));
David Srbeckyb5362472015-04-08 19:37:39 +010075 inside_entry_ = false;
David Srbecky04b05262015-11-09 18:05:48 +000076 // 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);
David Srbeckyb5362472015-04-08 19:37:39 +010081 }
82 depth_--;
David Srbeckyb5362472015-04-08 19:37:39 +010083 }
84
85 void WriteAddr(Attribute attrib, uint64_t value) {
David Srbecky24868a12016-01-29 18:59:56 +000086 debug_abbrev_->AddAbbrevAttribute(attrib, DW_FORM_addr);
David Srbecky2f6cdb02015-04-11 00:17:53 +010087 patch_locations_.push_back(this->data()->size());
David Srbeckyb5362472015-04-08 19:37:39 +010088 if (is64bit_) {
89 this->PushUint64(value);
90 } else {
91 this->PushUint32(value);
92 }
93 }
94
David Srbecky91cb54e2016-01-15 13:47:59 +000095 void WriteBlock(Attribute attrib, const uint8_t* ptr, size_t num_bytes) {
David Srbecky24868a12016-01-29 18:59:56 +000096 debug_abbrev_->AddAbbrevAttribute(attrib, DW_FORM_block);
David Srbecky04b05262015-11-09 18:05:48 +000097 this->PushUleb128(num_bytes);
98 this->PushData(ptr, num_bytes);
David Srbeckyb5362472015-04-08 19:37:39 +010099 }
100
David Srbecky91cb54e2016-01-15 13:47:59 +0000101 void WriteExprLoc(Attribute attrib, const Expression& expr) {
David Srbecky24868a12016-01-29 18:59:56 +0000102 debug_abbrev_->AddAbbrevAttribute(attrib, DW_FORM_exprloc);
David Srbecky91cb54e2016-01-15 13:47:59 +0000103 this->PushUleb128(dchecked_integral_cast<uint32_t>(expr.size()));
104 this->PushData(expr.data());
David Srbecky0fd295f2015-11-16 16:39:10 +0000105 }
106
David Srbeckyb5362472015-04-08 19:37:39 +0100107 void WriteData1(Attribute attrib, uint8_t value) {
David Srbecky24868a12016-01-29 18:59:56 +0000108 debug_abbrev_->AddAbbrevAttribute(attrib, DW_FORM_data1);
David Srbeckyb5362472015-04-08 19:37:39 +0100109 this->PushUint8(value);
110 }
111
112 void WriteData2(Attribute attrib, uint16_t value) {
David Srbecky24868a12016-01-29 18:59:56 +0000113 debug_abbrev_->AddAbbrevAttribute(attrib, DW_FORM_data2);
David Srbeckyb5362472015-04-08 19:37:39 +0100114 this->PushUint16(value);
115 }
116
117 void WriteData4(Attribute attrib, uint32_t value) {
David Srbecky24868a12016-01-29 18:59:56 +0000118 debug_abbrev_->AddAbbrevAttribute(attrib, DW_FORM_data4);
David Srbeckyb5362472015-04-08 19:37:39 +0100119 this->PushUint32(value);
120 }
121
122 void WriteData8(Attribute attrib, uint64_t value) {
David Srbecky24868a12016-01-29 18:59:56 +0000123 debug_abbrev_->AddAbbrevAttribute(attrib, DW_FORM_data8);
David Srbeckyb5362472015-04-08 19:37:39 +0100124 this->PushUint64(value);
125 }
126
David Srbecky0fd295f2015-11-16 16:39:10 +0000127 void WriteSecOffset(Attribute attrib, uint32_t offset) {
David Srbecky24868a12016-01-29 18:59:56 +0000128 debug_abbrev_->AddAbbrevAttribute(attrib, DW_FORM_sec_offset);
David Srbecky0fd295f2015-11-16 16:39:10 +0000129 this->PushUint32(offset);
130 }
131
David Srbeckyb5362472015-04-08 19:37:39 +0100132 void WriteSdata(Attribute attrib, int value) {
David Srbecky24868a12016-01-29 18:59:56 +0000133 debug_abbrev_->AddAbbrevAttribute(attrib, DW_FORM_sdata);
David Srbeckyb5362472015-04-08 19:37:39 +0100134 this->PushSleb128(value);
135 }
136
137 void WriteUdata(Attribute attrib, int value) {
David Srbecky24868a12016-01-29 18:59:56 +0000138 debug_abbrev_->AddAbbrevAttribute(attrib, DW_FORM_udata);
David Srbeckyb5362472015-04-08 19:37:39 +0100139 this->PushUleb128(value);
140 }
141
142 void WriteUdata(Attribute attrib, uint32_t value) {
David Srbecky24868a12016-01-29 18:59:56 +0000143 debug_abbrev_->AddAbbrevAttribute(attrib, DW_FORM_udata);
David Srbeckyb5362472015-04-08 19:37:39 +0100144 this->PushUleb128(value);
145 }
146
147 void WriteFlag(Attribute attrib, bool value) {
David Srbecky24868a12016-01-29 18:59:56 +0000148 debug_abbrev_->AddAbbrevAttribute(attrib, DW_FORM_flag);
David Srbeckyb5362472015-04-08 19:37:39 +0100149 this->PushUint8(value ? 1 : 0);
150 }
151
David Srbeckyfa5ec2b2016-01-29 15:13:19 +0000152 void WriteFlagPresent(Attribute attrib) {
David Srbecky24868a12016-01-29 18:59:56 +0000153 debug_abbrev_->AddAbbrevAttribute(attrib, DW_FORM_flag_present);
David Srbeckyfa5ec2b2016-01-29 15:13:19 +0000154 }
155
David Srbecky04b05262015-11-09 18:05:48 +0000156 void WriteRef4(Attribute attrib, uint32_t cu_offset) {
David Srbecky24868a12016-01-29 18:59:56 +0000157 debug_abbrev_->AddAbbrevAttribute(attrib, DW_FORM_ref4);
David Srbeckyb5362472015-04-08 19:37:39 +0100158 this->PushUint32(cu_offset);
159 }
160
David Srbecky04b05262015-11-09 18:05:48 +0000161 void WriteRef(Attribute attrib, uint32_t cu_offset) {
David Srbecky24868a12016-01-29 18:59:56 +0000162 debug_abbrev_->AddAbbrevAttribute(attrib, DW_FORM_ref_udata);
David Srbeckyb5362472015-04-08 19:37:39 +0100163 this->PushUleb128(cu_offset);
164 }
165
166 void WriteString(Attribute attrib, const char* value) {
David Srbecky24868a12016-01-29 18:59:56 +0000167 debug_abbrev_->AddAbbrevAttribute(attrib, DW_FORM_string);
David Srbeckyb5362472015-04-08 19:37:39 +0100168 this->PushString(value);
169 }
170
David Srbecky04b05262015-11-09 18:05:48 +0000171 void WriteStrp(Attribute attrib, size_t debug_str_offset) {
David Srbecky24868a12016-01-29 18:59:56 +0000172 debug_abbrev_->AddAbbrevAttribute(attrib, DW_FORM_strp);
David Srbecky04b05262015-11-09 18:05:48 +0000173 this->PushUint32(dchecked_integral_cast<uint32_t>(debug_str_offset));
David Srbeckyb5362472015-04-08 19:37:39 +0100174 }
175
David Srbecky04b05262015-11-09 18:05:48 +0000176 void WriteStrp(Attribute attrib, const char* str, size_t len,
177 std::vector<uint8_t>* debug_str) {
David Srbecky24868a12016-01-29 18:59:56 +0000178 debug_abbrev_->AddAbbrevAttribute(attrib, DW_FORM_strp);
David Srbecky04b05262015-11-09 18:05:48 +0000179 this->PushUint32(debug_str->size());
180 debug_str->insert(debug_str->end(), str, str + len);
181 debug_str->push_back(0);
182 }
183
184 void WriteStrp(Attribute attrib, const char* str, std::vector<uint8_t>* debug_str) {
185 WriteStrp(attrib, str, strlen(str), debug_str);
David Srbeckyb5362472015-04-08 19:37:39 +0100186 }
187
David Srbecky2f6cdb02015-04-11 00:17:53 +0100188 bool Is64bit() const { return is64bit_; }
189
190 const std::vector<uintptr_t>& GetPatchLocations() const {
191 return patch_locations_;
192 }
David Srbeckyb5362472015-04-08 19:37:39 +0100193
David Srbecky04b05262015-11-09 18:05:48 +0000194 int Depth() const { return depth_; }
195
Vladimir Markoec7802a2015-10-01 20:57:57 +0100196 using Writer<Vector>::data;
David Srbecky04b05262015-11-09 18:05:48 +0000197 using Writer<Vector>::size;
198 using Writer<Vector>::UpdateUint32;
David Srbeckyb5362472015-04-08 19:37:39 +0100199
200 DebugInfoEntryWriter(bool is64bitArch,
David Srbecky24868a12016-01-29 18:59:56 +0000201 DebugAbbrevWriter<Vector>* debug_abbrev,
Vladimir Markoec7802a2015-10-01 20:57:57 +0100202 const typename Vector::allocator_type& alloc =
203 typename Vector::allocator_type())
204 : Writer<Vector>(&entries_),
David Srbeckyb5362472015-04-08 19:37:39 +0100205 debug_abbrev_(debug_abbrev),
David Srbeckyb5362472015-04-08 19:37:39 +0100206 entries_(alloc),
207 is64bit_(is64bitArch) {
David Srbeckyb5362472015-04-08 19:37:39 +0100208 }
209
210 ~DebugInfoEntryWriter() {
David Srbecky04b05262015-11-09 18:05:48 +0000211 DCHECK(!inside_entry_);
David Srbeckyb5362472015-04-08 19:37:39 +0100212 DCHECK_EQ(depth_, 0);
213 }
214
215 private:
David Srbecky24868a12016-01-29 18:59:56 +0000216 DebugAbbrevWriter<Vector>* debug_abbrev_;
Vladimir Markoec7802a2015-10-01 20:57:57 +0100217 Vector entries_;
David Srbeckyb5362472015-04-08 19:37:39 +0100218 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).
David Srbecky2f6cdb02015-04-11 00:17:53 +0100222 std::vector<uintptr_t> patch_locations_;
David Srbeckyb5362472015-04-08 19:37:39 +0100223};
224
225} // namespace dwarf
226} // namespace art
227
228#endif // ART_COMPILER_DWARF_DEBUG_INFO_ENTRY_WRITER_H_