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