xref: /aosp_15_r20/art/compiler/debug/elf_debug_info_writer.h (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
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_COMPILER_DEBUG_ELF_DEBUG_INFO_WRITER_H_
18*795d594fSAndroid Build Coastguard Worker #define ART_COMPILER_DEBUG_ELF_DEBUG_INFO_WRITER_H_
19*795d594fSAndroid Build Coastguard Worker 
20*795d594fSAndroid Build Coastguard Worker #include <map>
21*795d594fSAndroid Build Coastguard Worker #include <unordered_set>
22*795d594fSAndroid Build Coastguard Worker #include <vector>
23*795d594fSAndroid Build Coastguard Worker 
24*795d594fSAndroid Build Coastguard Worker #include "art_field-inl.h"
25*795d594fSAndroid Build Coastguard Worker #include "base/macros.h"
26*795d594fSAndroid Build Coastguard Worker #include "debug/elf_compilation_unit.h"
27*795d594fSAndroid Build Coastguard Worker #include "debug/elf_debug_loc_writer.h"
28*795d594fSAndroid Build Coastguard Worker #include "debug/method_debug_info.h"
29*795d594fSAndroid Build Coastguard Worker #include "dex/code_item_accessors-inl.h"
30*795d594fSAndroid Build Coastguard Worker #include "dex/dex_file-inl.h"
31*795d594fSAndroid Build Coastguard Worker #include "dex/dex_file.h"
32*795d594fSAndroid Build Coastguard Worker #include "dwarf/debug_abbrev_writer.h"
33*795d594fSAndroid Build Coastguard Worker #include "dwarf/debug_info_entry_writer.h"
34*795d594fSAndroid Build Coastguard Worker #include "elf/elf_builder.h"
35*795d594fSAndroid Build Coastguard Worker #include "heap_poisoning.h"
36*795d594fSAndroid Build Coastguard Worker #include "linear_alloc-inl.h"
37*795d594fSAndroid Build Coastguard Worker #include "mirror/array.h"
38*795d594fSAndroid Build Coastguard Worker #include "mirror/class-inl.h"
39*795d594fSAndroid Build Coastguard Worker #include "mirror/class.h"
40*795d594fSAndroid Build Coastguard Worker #include "oat/oat_file.h"
41*795d594fSAndroid Build Coastguard Worker #include "obj_ptr-inl.h"
42*795d594fSAndroid Build Coastguard Worker 
43*795d594fSAndroid Build Coastguard Worker namespace art HIDDEN {
44*795d594fSAndroid Build Coastguard Worker namespace debug {
45*795d594fSAndroid Build Coastguard Worker 
GetParamNames(const MethodDebugInfo * mi)46*795d594fSAndroid Build Coastguard Worker static std::vector<const char*> GetParamNames(const MethodDebugInfo* mi) {
47*795d594fSAndroid Build Coastguard Worker   std::vector<const char*> names;
48*795d594fSAndroid Build Coastguard Worker   DCHECK(mi->dex_file != nullptr);
49*795d594fSAndroid Build Coastguard Worker   CodeItemDebugInfoAccessor accessor(*mi->dex_file, mi->code_item, mi->dex_method_index);
50*795d594fSAndroid Build Coastguard Worker   if (accessor.HasCodeItem()) {
51*795d594fSAndroid Build Coastguard Worker     accessor.VisitParameterNames([&](dex::StringIndex string_idx) {
52*795d594fSAndroid Build Coastguard Worker       names.push_back(string_idx.IsValid() ? mi->dex_file->GetStringData(string_idx) : nullptr);
53*795d594fSAndroid Build Coastguard Worker     });
54*795d594fSAndroid Build Coastguard Worker   }
55*795d594fSAndroid Build Coastguard Worker   return names;
56*795d594fSAndroid Build Coastguard Worker }
57*795d594fSAndroid Build Coastguard Worker 
58*795d594fSAndroid Build Coastguard Worker // Helper class to write .debug_info and its supporting sections.
59*795d594fSAndroid Build Coastguard Worker template<typename ElfTypes>
60*795d594fSAndroid Build Coastguard Worker class ElfDebugInfoWriter {
61*795d594fSAndroid Build Coastguard Worker   using Elf_Addr = typename ElfTypes::Addr;
62*795d594fSAndroid Build Coastguard Worker 
63*795d594fSAndroid Build Coastguard Worker  public:
ElfDebugInfoWriter(ElfBuilder<ElfTypes> * builder)64*795d594fSAndroid Build Coastguard Worker   explicit ElfDebugInfoWriter(ElfBuilder<ElfTypes>* builder)
65*795d594fSAndroid Build Coastguard Worker       : builder_(builder),
66*795d594fSAndroid Build Coastguard Worker         debug_abbrev_(&debug_abbrev_buffer_) {
67*795d594fSAndroid Build Coastguard Worker   }
68*795d594fSAndroid Build Coastguard Worker 
Start()69*795d594fSAndroid Build Coastguard Worker   void Start() {
70*795d594fSAndroid Build Coastguard Worker     builder_->GetDebugInfo()->Start();
71*795d594fSAndroid Build Coastguard Worker   }
72*795d594fSAndroid Build Coastguard Worker 
End()73*795d594fSAndroid Build Coastguard Worker   void End() {
74*795d594fSAndroid Build Coastguard Worker     builder_->GetDebugInfo()->End();
75*795d594fSAndroid Build Coastguard Worker     builder_->WriteSection(".debug_abbrev", &debug_abbrev_buffer_);
76*795d594fSAndroid Build Coastguard Worker     if (!debug_loc_.empty()) {
77*795d594fSAndroid Build Coastguard Worker       builder_->WriteSection(".debug_loc", &debug_loc_);
78*795d594fSAndroid Build Coastguard Worker     }
79*795d594fSAndroid Build Coastguard Worker     if (!debug_ranges_.empty()) {
80*795d594fSAndroid Build Coastguard Worker       builder_->WriteSection(".debug_ranges", &debug_ranges_);
81*795d594fSAndroid Build Coastguard Worker     }
82*795d594fSAndroid Build Coastguard Worker   }
83*795d594fSAndroid Build Coastguard Worker 
84*795d594fSAndroid Build Coastguard Worker  private:
85*795d594fSAndroid Build Coastguard Worker   ElfBuilder<ElfTypes>* builder_;
86*795d594fSAndroid Build Coastguard Worker   std::vector<uint8_t> debug_abbrev_buffer_;
87*795d594fSAndroid Build Coastguard Worker   dwarf::DebugAbbrevWriter<> debug_abbrev_;
88*795d594fSAndroid Build Coastguard Worker   std::vector<uint8_t> debug_loc_;
89*795d594fSAndroid Build Coastguard Worker   std::vector<uint8_t> debug_ranges_;
90*795d594fSAndroid Build Coastguard Worker 
91*795d594fSAndroid Build Coastguard Worker   std::unordered_set<const char*> defined_dex_classes_;  // For CHECKs only.
92*795d594fSAndroid Build Coastguard Worker 
93*795d594fSAndroid Build Coastguard Worker   template<typename ElfTypes2>
94*795d594fSAndroid Build Coastguard Worker   friend class ElfCompilationUnitWriter;
95*795d594fSAndroid Build Coastguard Worker };
96*795d594fSAndroid Build Coastguard Worker 
97*795d594fSAndroid Build Coastguard Worker // Helper class to write one compilation unit.
98*795d594fSAndroid Build Coastguard Worker // It holds helper methods and temporary state.
99*795d594fSAndroid Build Coastguard Worker template<typename ElfTypes>
100*795d594fSAndroid Build Coastguard Worker class ElfCompilationUnitWriter {
101*795d594fSAndroid Build Coastguard Worker   using Elf_Addr = typename ElfTypes::Addr;
102*795d594fSAndroid Build Coastguard Worker 
103*795d594fSAndroid Build Coastguard Worker  public:
ElfCompilationUnitWriter(ElfDebugInfoWriter<ElfTypes> * owner)104*795d594fSAndroid Build Coastguard Worker   explicit ElfCompilationUnitWriter(ElfDebugInfoWriter<ElfTypes>* owner)
105*795d594fSAndroid Build Coastguard Worker     : owner_(owner),
106*795d594fSAndroid Build Coastguard Worker       info_(Is64BitInstructionSet(owner_->builder_->GetIsa()), &owner->debug_abbrev_) {
107*795d594fSAndroid Build Coastguard Worker   }
108*795d594fSAndroid Build Coastguard Worker 
Write(const ElfCompilationUnit & compilation_unit)109*795d594fSAndroid Build Coastguard Worker   void Write(const ElfCompilationUnit& compilation_unit) {
110*795d594fSAndroid Build Coastguard Worker     CHECK(!compilation_unit.methods.empty());
111*795d594fSAndroid Build Coastguard Worker     const Elf_Addr base_address = compilation_unit.is_code_address_text_relative
112*795d594fSAndroid Build Coastguard Worker         ? owner_->builder_->GetText()->GetAddress()
113*795d594fSAndroid Build Coastguard Worker         : 0;
114*795d594fSAndroid Build Coastguard Worker     const bool is64bit = Is64BitInstructionSet(owner_->builder_->GetIsa());
115*795d594fSAndroid Build Coastguard Worker     using namespace dwarf;  // NOLINT. For easy access to DWARF constants.
116*795d594fSAndroid Build Coastguard Worker 
117*795d594fSAndroid Build Coastguard Worker     info_.StartTag(DW_TAG_compile_unit);
118*795d594fSAndroid Build Coastguard Worker     info_.WriteString(DW_AT_producer, "Android dex2oat");
119*795d594fSAndroid Build Coastguard Worker     info_.WriteData1(DW_AT_language, DW_LANG_Java);
120*795d594fSAndroid Build Coastguard Worker     info_.WriteString(DW_AT_comp_dir, "$JAVA_SRC_ROOT");
121*795d594fSAndroid Build Coastguard Worker     // The low_pc acts as base address for several other addresses/ranges.
122*795d594fSAndroid Build Coastguard Worker     info_.WriteAddr(DW_AT_low_pc, base_address + compilation_unit.code_address);
123*795d594fSAndroid Build Coastguard Worker     info_.WriteSecOffset(DW_AT_stmt_list, compilation_unit.debug_line_offset);
124*795d594fSAndroid Build Coastguard Worker 
125*795d594fSAndroid Build Coastguard Worker     // Write .debug_ranges entries covering code ranges of the whole compilation unit.
126*795d594fSAndroid Build Coastguard Worker     dwarf::Writer<> debug_ranges(&owner_->debug_ranges_);
127*795d594fSAndroid Build Coastguard Worker     info_.WriteSecOffset(DW_AT_ranges, owner_->debug_ranges_.size());
128*795d594fSAndroid Build Coastguard Worker     for (auto mi : compilation_unit.methods) {
129*795d594fSAndroid Build Coastguard Worker       uint64_t low_pc = mi->code_address - compilation_unit.code_address;
130*795d594fSAndroid Build Coastguard Worker       uint64_t high_pc = low_pc + mi->code_size;
131*795d594fSAndroid Build Coastguard Worker       if (is64bit) {
132*795d594fSAndroid Build Coastguard Worker         debug_ranges.PushUint64(low_pc);
133*795d594fSAndroid Build Coastguard Worker         debug_ranges.PushUint64(high_pc);
134*795d594fSAndroid Build Coastguard Worker       } else {
135*795d594fSAndroid Build Coastguard Worker         debug_ranges.PushUint32(low_pc);
136*795d594fSAndroid Build Coastguard Worker         debug_ranges.PushUint32(high_pc);
137*795d594fSAndroid Build Coastguard Worker       }
138*795d594fSAndroid Build Coastguard Worker     }
139*795d594fSAndroid Build Coastguard Worker     if (is64bit) {
140*795d594fSAndroid Build Coastguard Worker       debug_ranges.PushUint64(0);  // End of list.
141*795d594fSAndroid Build Coastguard Worker       debug_ranges.PushUint64(0);
142*795d594fSAndroid Build Coastguard Worker     } else {
143*795d594fSAndroid Build Coastguard Worker       debug_ranges.PushUint32(0);  // End of list.
144*795d594fSAndroid Build Coastguard Worker       debug_ranges.PushUint32(0);
145*795d594fSAndroid Build Coastguard Worker     }
146*795d594fSAndroid Build Coastguard Worker 
147*795d594fSAndroid Build Coastguard Worker     const char* last_dex_class_desc = nullptr;
148*795d594fSAndroid Build Coastguard Worker     for (auto mi : compilation_unit.methods) {
149*795d594fSAndroid Build Coastguard Worker       DCHECK(mi->dex_file != nullptr);
150*795d594fSAndroid Build Coastguard Worker       const DexFile* dex = mi->dex_file;
151*795d594fSAndroid Build Coastguard Worker       CodeItemDebugInfoAccessor accessor(*dex, mi->code_item, mi->dex_method_index);
152*795d594fSAndroid Build Coastguard Worker       const dex::MethodId& dex_method = dex->GetMethodId(mi->dex_method_index);
153*795d594fSAndroid Build Coastguard Worker       const dex::ProtoId& dex_proto = dex->GetMethodPrototype(dex_method);
154*795d594fSAndroid Build Coastguard Worker       const dex::TypeList* dex_params = dex->GetProtoParameters(dex_proto);
155*795d594fSAndroid Build Coastguard Worker       const char* dex_class_desc = dex->GetMethodDeclaringClassDescriptor(dex_method);
156*795d594fSAndroid Build Coastguard Worker       const bool is_static = (mi->access_flags & kAccStatic) != 0;
157*795d594fSAndroid Build Coastguard Worker 
158*795d594fSAndroid Build Coastguard Worker       // Enclose the method in correct class definition.
159*795d594fSAndroid Build Coastguard Worker       if (last_dex_class_desc != dex_class_desc) {
160*795d594fSAndroid Build Coastguard Worker         if (last_dex_class_desc != nullptr) {
161*795d594fSAndroid Build Coastguard Worker           EndClassTag();
162*795d594fSAndroid Build Coastguard Worker         }
163*795d594fSAndroid Build Coastguard Worker         // Write reference tag for the class we are about to declare.
164*795d594fSAndroid Build Coastguard Worker         size_t reference_tag_offset = info_.StartTag(DW_TAG_reference_type);
165*795d594fSAndroid Build Coastguard Worker         type_cache_.emplace(std::string(dex_class_desc), reference_tag_offset);
166*795d594fSAndroid Build Coastguard Worker         size_t type_attrib_offset = info_.size();
167*795d594fSAndroid Build Coastguard Worker         info_.WriteRef4(DW_AT_type, 0);
168*795d594fSAndroid Build Coastguard Worker         info_.EndTag();
169*795d594fSAndroid Build Coastguard Worker         // Declare the class that owns this method.
170*795d594fSAndroid Build Coastguard Worker         size_t class_offset = StartClassTag(dex_class_desc);
171*795d594fSAndroid Build Coastguard Worker         info_.UpdateUint32(type_attrib_offset, class_offset);
172*795d594fSAndroid Build Coastguard Worker         info_.WriteFlagPresent(DW_AT_declaration);
173*795d594fSAndroid Build Coastguard Worker         // Check that each class is defined only once.
174*795d594fSAndroid Build Coastguard Worker         bool unique = owner_->defined_dex_classes_.insert(dex_class_desc).second;
175*795d594fSAndroid Build Coastguard Worker         CHECK(unique) << "Redefinition of " << dex_class_desc;
176*795d594fSAndroid Build Coastguard Worker         last_dex_class_desc = dex_class_desc;
177*795d594fSAndroid Build Coastguard Worker       }
178*795d594fSAndroid Build Coastguard Worker 
179*795d594fSAndroid Build Coastguard Worker       int start_depth = info_.Depth();
180*795d594fSAndroid Build Coastguard Worker       info_.StartTag(DW_TAG_subprogram);
181*795d594fSAndroid Build Coastguard Worker       WriteName(dex->GetMethodName(dex_method));
182*795d594fSAndroid Build Coastguard Worker       info_.WriteAddr(DW_AT_low_pc, base_address + mi->code_address);
183*795d594fSAndroid Build Coastguard Worker       info_.WriteUdata(DW_AT_high_pc, mi->code_size);
184*795d594fSAndroid Build Coastguard Worker       std::vector<uint8_t> expr_buffer;
185*795d594fSAndroid Build Coastguard Worker       Expression expr(&expr_buffer);
186*795d594fSAndroid Build Coastguard Worker       expr.WriteOpCallFrameCfa();
187*795d594fSAndroid Build Coastguard Worker       info_.WriteExprLoc(DW_AT_frame_base, expr);
188*795d594fSAndroid Build Coastguard Worker       WriteLazyType(dex->GetReturnTypeDescriptor(dex_proto));
189*795d594fSAndroid Build Coastguard Worker 
190*795d594fSAndroid Build Coastguard Worker       // Decode dex register locations for all stack maps.
191*795d594fSAndroid Build Coastguard Worker       // It might be expensive, so do it just once and reuse the result.
192*795d594fSAndroid Build Coastguard Worker       std::unique_ptr<const CodeInfo> code_info;
193*795d594fSAndroid Build Coastguard Worker       std::vector<DexRegisterMap> dex_reg_maps;
194*795d594fSAndroid Build Coastguard Worker       if (accessor.HasCodeItem() && mi->code_info != nullptr) {
195*795d594fSAndroid Build Coastguard Worker         code_info.reset(new CodeInfo(mi->code_info));
196*795d594fSAndroid Build Coastguard Worker         for (StackMap stack_map : code_info->GetStackMaps()) {
197*795d594fSAndroid Build Coastguard Worker           dex_reg_maps.push_back(code_info->GetDexRegisterMapOf(stack_map));
198*795d594fSAndroid Build Coastguard Worker         }
199*795d594fSAndroid Build Coastguard Worker       }
200*795d594fSAndroid Build Coastguard Worker 
201*795d594fSAndroid Build Coastguard Worker       // Write parameters. DecodeDebugLocalInfo returns them as well, but it does not
202*795d594fSAndroid Build Coastguard Worker       // guarantee order or uniqueness so it is safer to iterate over them manually.
203*795d594fSAndroid Build Coastguard Worker       // DecodeDebugLocalInfo might not also be available if there is no debug info.
204*795d594fSAndroid Build Coastguard Worker       std::vector<const char*> param_names = GetParamNames(mi);
205*795d594fSAndroid Build Coastguard Worker       uint32_t arg_reg = 0;
206*795d594fSAndroid Build Coastguard Worker       if (!is_static) {
207*795d594fSAndroid Build Coastguard Worker         info_.StartTag(DW_TAG_formal_parameter);
208*795d594fSAndroid Build Coastguard Worker         WriteName("this");
209*795d594fSAndroid Build Coastguard Worker         info_.WriteFlagPresent(DW_AT_artificial);
210*795d594fSAndroid Build Coastguard Worker         WriteLazyType(dex_class_desc);
211*795d594fSAndroid Build Coastguard Worker         if (accessor.HasCodeItem()) {
212*795d594fSAndroid Build Coastguard Worker           // Write the stack location of the parameter.
213*795d594fSAndroid Build Coastguard Worker           const uint32_t vreg = accessor.RegistersSize() - accessor.InsSize() + arg_reg;
214*795d594fSAndroid Build Coastguard Worker           const bool is64bitValue = false;
215*795d594fSAndroid Build Coastguard Worker           WriteRegLocation(mi, dex_reg_maps, vreg, is64bitValue, compilation_unit.code_address);
216*795d594fSAndroid Build Coastguard Worker         }
217*795d594fSAndroid Build Coastguard Worker         arg_reg++;
218*795d594fSAndroid Build Coastguard Worker         info_.EndTag();
219*795d594fSAndroid Build Coastguard Worker       }
220*795d594fSAndroid Build Coastguard Worker       if (dex_params != nullptr) {
221*795d594fSAndroid Build Coastguard Worker         for (uint32_t i = 0; i < dex_params->Size(); ++i) {
222*795d594fSAndroid Build Coastguard Worker           info_.StartTag(DW_TAG_formal_parameter);
223*795d594fSAndroid Build Coastguard Worker           // Parameter names may not be always available.
224*795d594fSAndroid Build Coastguard Worker           if (i < param_names.size()) {
225*795d594fSAndroid Build Coastguard Worker             WriteName(param_names[i]);
226*795d594fSAndroid Build Coastguard Worker           }
227*795d594fSAndroid Build Coastguard Worker           // Write the type.
228*795d594fSAndroid Build Coastguard Worker           const char* type_desc = dex->GetTypeDescriptor(dex_params->GetTypeItem(i).type_idx_);
229*795d594fSAndroid Build Coastguard Worker           WriteLazyType(type_desc);
230*795d594fSAndroid Build Coastguard Worker           const bool is64bitValue = type_desc[0] == 'D' || type_desc[0] == 'J';
231*795d594fSAndroid Build Coastguard Worker           if (accessor.HasCodeItem()) {
232*795d594fSAndroid Build Coastguard Worker             // Write the stack location of the parameter.
233*795d594fSAndroid Build Coastguard Worker             const uint32_t vreg = accessor.RegistersSize() - accessor.InsSize() + arg_reg;
234*795d594fSAndroid Build Coastguard Worker             WriteRegLocation(mi, dex_reg_maps, vreg, is64bitValue, compilation_unit.code_address);
235*795d594fSAndroid Build Coastguard Worker           }
236*795d594fSAndroid Build Coastguard Worker           arg_reg += is64bitValue ? 2 : 1;
237*795d594fSAndroid Build Coastguard Worker           info_.EndTag();
238*795d594fSAndroid Build Coastguard Worker         }
239*795d594fSAndroid Build Coastguard Worker         if (accessor.HasCodeItem()) {
240*795d594fSAndroid Build Coastguard Worker           DCHECK_EQ(arg_reg, accessor.InsSize());
241*795d594fSAndroid Build Coastguard Worker         }
242*795d594fSAndroid Build Coastguard Worker       }
243*795d594fSAndroid Build Coastguard Worker 
244*795d594fSAndroid Build Coastguard Worker       // Write local variables.
245*795d594fSAndroid Build Coastguard Worker       std::vector<DexFile::LocalInfo> local_infos;
246*795d594fSAndroid Build Coastguard Worker       if (accessor.DecodeDebugLocalInfo(is_static,
247*795d594fSAndroid Build Coastguard Worker                                         mi->dex_method_index,
248*795d594fSAndroid Build Coastguard Worker                                         [&](const DexFile::LocalInfo& entry) {
249*795d594fSAndroid Build Coastguard Worker                                           local_infos.push_back(entry);
250*795d594fSAndroid Build Coastguard Worker                                         })) {
251*795d594fSAndroid Build Coastguard Worker         for (const DexFile::LocalInfo& var : local_infos) {
252*795d594fSAndroid Build Coastguard Worker           if (var.reg_ < accessor.RegistersSize() - accessor.InsSize()) {
253*795d594fSAndroid Build Coastguard Worker             info_.StartTag(DW_TAG_variable);
254*795d594fSAndroid Build Coastguard Worker             WriteName(var.name_);
255*795d594fSAndroid Build Coastguard Worker             WriteLazyType(var.descriptor_);
256*795d594fSAndroid Build Coastguard Worker             bool is64bitValue = var.descriptor_[0] == 'D' || var.descriptor_[0] == 'J';
257*795d594fSAndroid Build Coastguard Worker             WriteRegLocation(mi,
258*795d594fSAndroid Build Coastguard Worker                              dex_reg_maps,
259*795d594fSAndroid Build Coastguard Worker                              var.reg_,
260*795d594fSAndroid Build Coastguard Worker                              is64bitValue,
261*795d594fSAndroid Build Coastguard Worker                              compilation_unit.code_address,
262*795d594fSAndroid Build Coastguard Worker                              var.start_address_,
263*795d594fSAndroid Build Coastguard Worker                              var.end_address_);
264*795d594fSAndroid Build Coastguard Worker             info_.EndTag();
265*795d594fSAndroid Build Coastguard Worker           }
266*795d594fSAndroid Build Coastguard Worker         }
267*795d594fSAndroid Build Coastguard Worker       }
268*795d594fSAndroid Build Coastguard Worker 
269*795d594fSAndroid Build Coastguard Worker       info_.EndTag();
270*795d594fSAndroid Build Coastguard Worker       CHECK_EQ(info_.Depth(), start_depth);  // Balanced start/end.
271*795d594fSAndroid Build Coastguard Worker     }
272*795d594fSAndroid Build Coastguard Worker     if (last_dex_class_desc != nullptr) {
273*795d594fSAndroid Build Coastguard Worker       EndClassTag();
274*795d594fSAndroid Build Coastguard Worker     }
275*795d594fSAndroid Build Coastguard Worker     FinishLazyTypes();
276*795d594fSAndroid Build Coastguard Worker     CloseNamespacesAboveDepth(0);
277*795d594fSAndroid Build Coastguard Worker     info_.EndTag();  // DW_TAG_compile_unit
278*795d594fSAndroid Build Coastguard Worker     CHECK_EQ(info_.Depth(), 0);
279*795d594fSAndroid Build Coastguard Worker     std::vector<uint8_t> buffer;
280*795d594fSAndroid Build Coastguard Worker     buffer.reserve(info_.data()->size() + KB);
281*795d594fSAndroid Build Coastguard Worker     // All compilation units share single table which is at the start of .debug_abbrev.
282*795d594fSAndroid Build Coastguard Worker     const size_t debug_abbrev_offset = 0;
283*795d594fSAndroid Build Coastguard Worker     WriteDebugInfoCU(debug_abbrev_offset, info_, &buffer);
284*795d594fSAndroid Build Coastguard Worker     owner_->builder_->GetDebugInfo()->WriteFully(buffer.data(), buffer.size());
285*795d594fSAndroid Build Coastguard Worker   }
286*795d594fSAndroid Build Coastguard Worker 
Write(const ArrayRef<mirror::Class * > & types)287*795d594fSAndroid Build Coastguard Worker   void Write(const ArrayRef<mirror::Class*>& types) REQUIRES_SHARED(Locks::mutator_lock_) {
288*795d594fSAndroid Build Coastguard Worker     using namespace dwarf;  // NOLINT. For easy access to DWARF constants.
289*795d594fSAndroid Build Coastguard Worker 
290*795d594fSAndroid Build Coastguard Worker     info_.StartTag(DW_TAG_compile_unit);
291*795d594fSAndroid Build Coastguard Worker     info_.WriteString(DW_AT_producer, "Android dex2oat");
292*795d594fSAndroid Build Coastguard Worker     info_.WriteData1(DW_AT_language, DW_LANG_Java);
293*795d594fSAndroid Build Coastguard Worker 
294*795d594fSAndroid Build Coastguard Worker     // Base class references to be patched at the end.
295*795d594fSAndroid Build Coastguard Worker     std::map<size_t, mirror::Class*> base_class_references;
296*795d594fSAndroid Build Coastguard Worker 
297*795d594fSAndroid Build Coastguard Worker     // Already written declarations or definitions.
298*795d594fSAndroid Build Coastguard Worker     std::map<mirror::Class*, size_t> class_declarations;
299*795d594fSAndroid Build Coastguard Worker 
300*795d594fSAndroid Build Coastguard Worker     std::vector<uint8_t> expr_buffer;
301*795d594fSAndroid Build Coastguard Worker     for (mirror::Class* type : types) {
302*795d594fSAndroid Build Coastguard Worker       if (type->IsPrimitive()) {
303*795d594fSAndroid Build Coastguard Worker         // For primitive types the definition and the declaration is the same.
304*795d594fSAndroid Build Coastguard Worker         if (type->GetPrimitiveType() != Primitive::kPrimVoid) {
305*795d594fSAndroid Build Coastguard Worker           WriteTypeDeclaration(type->GetDescriptor(nullptr));
306*795d594fSAndroid Build Coastguard Worker         }
307*795d594fSAndroid Build Coastguard Worker       } else if (type->IsArrayClass()) {
308*795d594fSAndroid Build Coastguard Worker         ObjPtr<mirror::Class> element_type = type->GetComponentType();
309*795d594fSAndroid Build Coastguard Worker         uint32_t component_size = type->GetComponentSize();
310*795d594fSAndroid Build Coastguard Worker         uint32_t data_offset = mirror::Array::DataOffset(component_size).Uint32Value();
311*795d594fSAndroid Build Coastguard Worker         uint32_t length_offset = mirror::Array::LengthOffset().Uint32Value();
312*795d594fSAndroid Build Coastguard Worker 
313*795d594fSAndroid Build Coastguard Worker         CloseNamespacesAboveDepth(0);  // Declare in root namespace.
314*795d594fSAndroid Build Coastguard Worker         info_.StartTag(DW_TAG_array_type);
315*795d594fSAndroid Build Coastguard Worker         std::string descriptor_string;
316*795d594fSAndroid Build Coastguard Worker         WriteLazyType(element_type->GetDescriptor(&descriptor_string));
317*795d594fSAndroid Build Coastguard Worker         WriteLinkageName(type);
318*795d594fSAndroid Build Coastguard Worker         info_.WriteUdata(DW_AT_data_member_location, data_offset);
319*795d594fSAndroid Build Coastguard Worker         info_.StartTag(DW_TAG_subrange_type);
320*795d594fSAndroid Build Coastguard Worker         Expression count_expr(&expr_buffer);
321*795d594fSAndroid Build Coastguard Worker         count_expr.WriteOpPushObjectAddress();
322*795d594fSAndroid Build Coastguard Worker         count_expr.WriteOpPlusUconst(length_offset);
323*795d594fSAndroid Build Coastguard Worker         count_expr.WriteOpDerefSize(4);  // Array length is always 32-bit wide.
324*795d594fSAndroid Build Coastguard Worker         info_.WriteExprLoc(DW_AT_count, count_expr);
325*795d594fSAndroid Build Coastguard Worker         info_.EndTag();  // DW_TAG_subrange_type.
326*795d594fSAndroid Build Coastguard Worker         info_.EndTag();  // DW_TAG_array_type.
327*795d594fSAndroid Build Coastguard Worker       } else if (type->IsInterface()) {
328*795d594fSAndroid Build Coastguard Worker         // Skip.  Variables cannot have an interface as a dynamic type.
329*795d594fSAndroid Build Coastguard Worker         // We do not expose the interface information to the debugger in any way.
330*795d594fSAndroid Build Coastguard Worker       } else {
331*795d594fSAndroid Build Coastguard Worker         std::string descriptor_string;
332*795d594fSAndroid Build Coastguard Worker         const char* desc = type->GetDescriptor(&descriptor_string);
333*795d594fSAndroid Build Coastguard Worker         size_t class_offset = StartClassTag(desc);
334*795d594fSAndroid Build Coastguard Worker         class_declarations.emplace(type, class_offset);
335*795d594fSAndroid Build Coastguard Worker 
336*795d594fSAndroid Build Coastguard Worker         if (!type->IsVariableSize()) {
337*795d594fSAndroid Build Coastguard Worker           info_.WriteUdata(DW_AT_byte_size, type->GetObjectSize());
338*795d594fSAndroid Build Coastguard Worker         }
339*795d594fSAndroid Build Coastguard Worker 
340*795d594fSAndroid Build Coastguard Worker         WriteLinkageName(type);
341*795d594fSAndroid Build Coastguard Worker 
342*795d594fSAndroid Build Coastguard Worker         if (type->IsObjectClass()) {
343*795d594fSAndroid Build Coastguard Worker           // Generate artificial member which is used to get the dynamic type of variable.
344*795d594fSAndroid Build Coastguard Worker           // The run-time value of this field will correspond to linkage name of some type.
345*795d594fSAndroid Build Coastguard Worker           // We need to do it only once in j.l.Object since all other types inherit it.
346*795d594fSAndroid Build Coastguard Worker           info_.StartTag(DW_TAG_member);
347*795d594fSAndroid Build Coastguard Worker           WriteName(".dynamic_type");
348*795d594fSAndroid Build Coastguard Worker           WriteLazyType(sizeof(uintptr_t) == 8 ? "J" : "I");
349*795d594fSAndroid Build Coastguard Worker           info_.WriteFlagPresent(DW_AT_artificial);
350*795d594fSAndroid Build Coastguard Worker           // Create DWARF expression to get the value of the methods_ field.
351*795d594fSAndroid Build Coastguard Worker           Expression expr(&expr_buffer);
352*795d594fSAndroid Build Coastguard Worker           // The address of the object has been implicitly pushed on the stack.
353*795d594fSAndroid Build Coastguard Worker           // Dereference the klass_ field of Object (32-bit; possibly poisoned).
354*795d594fSAndroid Build Coastguard Worker           DCHECK_EQ(type->ClassOffset().Uint32Value(), 0u);
355*795d594fSAndroid Build Coastguard Worker           DCHECK_EQ(sizeof(mirror::HeapReference<mirror::Class>), 4u);
356*795d594fSAndroid Build Coastguard Worker           expr.WriteOpDerefSize(4);
357*795d594fSAndroid Build Coastguard Worker           if (kPoisonHeapReferences) {
358*795d594fSAndroid Build Coastguard Worker             expr.WriteOpNeg();
359*795d594fSAndroid Build Coastguard Worker             // DWARF stack is pointer sized. Ensure that the high bits are clear.
360*795d594fSAndroid Build Coastguard Worker             expr.WriteOpConstu(0xFFFFFFFF);
361*795d594fSAndroid Build Coastguard Worker             expr.WriteOpAnd();
362*795d594fSAndroid Build Coastguard Worker           }
363*795d594fSAndroid Build Coastguard Worker           // Add offset to the methods_ field.
364*795d594fSAndroid Build Coastguard Worker           expr.WriteOpPlusUconst(mirror::Class::MethodsOffset().Uint32Value());
365*795d594fSAndroid Build Coastguard Worker           // Top of stack holds the location of the field now.
366*795d594fSAndroid Build Coastguard Worker           info_.WriteExprLoc(DW_AT_data_member_location, expr);
367*795d594fSAndroid Build Coastguard Worker           info_.EndTag();  // DW_TAG_member.
368*795d594fSAndroid Build Coastguard Worker         }
369*795d594fSAndroid Build Coastguard Worker 
370*795d594fSAndroid Build Coastguard Worker         // Base class.
371*795d594fSAndroid Build Coastguard Worker         ObjPtr<mirror::Class> base_class = type->GetSuperClass();
372*795d594fSAndroid Build Coastguard Worker         if (base_class != nullptr) {
373*795d594fSAndroid Build Coastguard Worker           info_.StartTag(DW_TAG_inheritance);
374*795d594fSAndroid Build Coastguard Worker           base_class_references.emplace(info_.size(), base_class.Ptr());
375*795d594fSAndroid Build Coastguard Worker           info_.WriteRef4(DW_AT_type, 0);
376*795d594fSAndroid Build Coastguard Worker           info_.WriteUdata(DW_AT_data_member_location, 0);
377*795d594fSAndroid Build Coastguard Worker           info_.WriteSdata(DW_AT_accessibility, DW_ACCESS_public);
378*795d594fSAndroid Build Coastguard Worker           info_.EndTag();  // DW_TAG_inheritance.
379*795d594fSAndroid Build Coastguard Worker         }
380*795d594fSAndroid Build Coastguard Worker 
381*795d594fSAndroid Build Coastguard Worker         // Member variables.
382*795d594fSAndroid Build Coastguard Worker         for (uint32_t i = 0, count = type->NumInstanceFields(); i < count; ++i) {
383*795d594fSAndroid Build Coastguard Worker           ArtField* field = type->GetInstanceField(i);
384*795d594fSAndroid Build Coastguard Worker           info_.StartTag(DW_TAG_member);
385*795d594fSAndroid Build Coastguard Worker           WriteName(field->GetName());
386*795d594fSAndroid Build Coastguard Worker           WriteLazyType(field->GetTypeDescriptor());
387*795d594fSAndroid Build Coastguard Worker           info_.WriteUdata(DW_AT_data_member_location, field->GetOffset().Uint32Value());
388*795d594fSAndroid Build Coastguard Worker           uint32_t access_flags = field->GetAccessFlags();
389*795d594fSAndroid Build Coastguard Worker           if (access_flags & kAccPublic) {
390*795d594fSAndroid Build Coastguard Worker             info_.WriteSdata(DW_AT_accessibility, DW_ACCESS_public);
391*795d594fSAndroid Build Coastguard Worker           } else if (access_flags & kAccProtected) {
392*795d594fSAndroid Build Coastguard Worker             info_.WriteSdata(DW_AT_accessibility, DW_ACCESS_protected);
393*795d594fSAndroid Build Coastguard Worker           } else if (access_flags & kAccPrivate) {
394*795d594fSAndroid Build Coastguard Worker             info_.WriteSdata(DW_AT_accessibility, DW_ACCESS_private);
395*795d594fSAndroid Build Coastguard Worker           }
396*795d594fSAndroid Build Coastguard Worker           info_.EndTag();  // DW_TAG_member.
397*795d594fSAndroid Build Coastguard Worker         }
398*795d594fSAndroid Build Coastguard Worker 
399*795d594fSAndroid Build Coastguard Worker         if (type->IsStringClass()) {
400*795d594fSAndroid Build Coastguard Worker           // Emit debug info about an artifical class member for java.lang.String which represents
401*795d594fSAndroid Build Coastguard Worker           // the first element of the data stored in a string instance. Consumers of the debug
402*795d594fSAndroid Build Coastguard Worker           // info will be able to read the content of java.lang.String based on the count (real
403*795d594fSAndroid Build Coastguard Worker           // field) and based on the location of this data member.
404*795d594fSAndroid Build Coastguard Worker           info_.StartTag(DW_TAG_member);
405*795d594fSAndroid Build Coastguard Worker           WriteName("value");
406*795d594fSAndroid Build Coastguard Worker           // We don't support fields with C like array types so we just say its type is java char.
407*795d594fSAndroid Build Coastguard Worker           WriteLazyType("C");  // char.
408*795d594fSAndroid Build Coastguard Worker           info_.WriteUdata(DW_AT_data_member_location,
409*795d594fSAndroid Build Coastguard Worker                            mirror::String::ValueOffset().Uint32Value());
410*795d594fSAndroid Build Coastguard Worker           info_.WriteSdata(DW_AT_accessibility, DW_ACCESS_private);
411*795d594fSAndroid Build Coastguard Worker           info_.EndTag();  // DW_TAG_member.
412*795d594fSAndroid Build Coastguard Worker         }
413*795d594fSAndroid Build Coastguard Worker 
414*795d594fSAndroid Build Coastguard Worker         EndClassTag();
415*795d594fSAndroid Build Coastguard Worker       }
416*795d594fSAndroid Build Coastguard Worker     }
417*795d594fSAndroid Build Coastguard Worker 
418*795d594fSAndroid Build Coastguard Worker     // Write base class declarations.
419*795d594fSAndroid Build Coastguard Worker     for (const auto& base_class_reference : base_class_references) {
420*795d594fSAndroid Build Coastguard Worker       size_t reference_offset = base_class_reference.first;
421*795d594fSAndroid Build Coastguard Worker       mirror::Class* base_class = base_class_reference.second;
422*795d594fSAndroid Build Coastguard Worker       const auto it = class_declarations.find(base_class);
423*795d594fSAndroid Build Coastguard Worker       if (it != class_declarations.end()) {
424*795d594fSAndroid Build Coastguard Worker         info_.UpdateUint32(reference_offset, it->second);
425*795d594fSAndroid Build Coastguard Worker       } else {
426*795d594fSAndroid Build Coastguard Worker         // Declare base class.  We can not use the standard WriteLazyType
427*795d594fSAndroid Build Coastguard Worker         // since we want to avoid the DW_TAG_reference_tag wrapping.
428*795d594fSAndroid Build Coastguard Worker         std::string tmp_storage;
429*795d594fSAndroid Build Coastguard Worker         const char* base_class_desc = base_class->GetDescriptor(&tmp_storage);
430*795d594fSAndroid Build Coastguard Worker         size_t base_class_declaration_offset = StartClassTag(base_class_desc);
431*795d594fSAndroid Build Coastguard Worker         info_.WriteFlagPresent(DW_AT_declaration);
432*795d594fSAndroid Build Coastguard Worker         WriteLinkageName(base_class);
433*795d594fSAndroid Build Coastguard Worker         EndClassTag();
434*795d594fSAndroid Build Coastguard Worker         class_declarations.emplace(base_class, base_class_declaration_offset);
435*795d594fSAndroid Build Coastguard Worker         info_.UpdateUint32(reference_offset, base_class_declaration_offset);
436*795d594fSAndroid Build Coastguard Worker       }
437*795d594fSAndroid Build Coastguard Worker     }
438*795d594fSAndroid Build Coastguard Worker 
439*795d594fSAndroid Build Coastguard Worker     FinishLazyTypes();
440*795d594fSAndroid Build Coastguard Worker     CloseNamespacesAboveDepth(0);
441*795d594fSAndroid Build Coastguard Worker     info_.EndTag();  // DW_TAG_compile_unit.
442*795d594fSAndroid Build Coastguard Worker     CHECK_EQ(info_.Depth(), 0);
443*795d594fSAndroid Build Coastguard Worker     std::vector<uint8_t> buffer;
444*795d594fSAndroid Build Coastguard Worker     buffer.reserve(info_.data()->size() + KB);
445*795d594fSAndroid Build Coastguard Worker     // All compilation units share single table which is at the start of .debug_abbrev.
446*795d594fSAndroid Build Coastguard Worker     const size_t debug_abbrev_offset = 0;
447*795d594fSAndroid Build Coastguard Worker     WriteDebugInfoCU(debug_abbrev_offset, info_, &buffer);
448*795d594fSAndroid Build Coastguard Worker     owner_->builder_->GetDebugInfo()->WriteFully(buffer.data(), buffer.size());
449*795d594fSAndroid Build Coastguard Worker   }
450*795d594fSAndroid Build Coastguard Worker 
451*795d594fSAndroid Build Coastguard Worker   // Write table into .debug_loc which describes location of dex register.
452*795d594fSAndroid Build Coastguard Worker   // The dex register might be valid only at some points and it might
453*795d594fSAndroid Build Coastguard Worker   // move between machine registers and stack.
454*795d594fSAndroid Build Coastguard Worker   void WriteRegLocation(const MethodDebugInfo* method_info,
455*795d594fSAndroid Build Coastguard Worker                         const std::vector<DexRegisterMap>& dex_register_maps,
456*795d594fSAndroid Build Coastguard Worker                         uint16_t vreg,
457*795d594fSAndroid Build Coastguard Worker                         bool is64bitValue,
458*795d594fSAndroid Build Coastguard Worker                         uint64_t compilation_unit_code_address,
459*795d594fSAndroid Build Coastguard Worker                         uint32_t dex_pc_low = 0,
460*795d594fSAndroid Build Coastguard Worker                         uint32_t dex_pc_high = 0xFFFFFFFF) {
461*795d594fSAndroid Build Coastguard Worker     WriteDebugLocEntry(method_info,
462*795d594fSAndroid Build Coastguard Worker                        dex_register_maps,
463*795d594fSAndroid Build Coastguard Worker                        vreg,
464*795d594fSAndroid Build Coastguard Worker                        is64bitValue,
465*795d594fSAndroid Build Coastguard Worker                        compilation_unit_code_address,
466*795d594fSAndroid Build Coastguard Worker                        dex_pc_low,
467*795d594fSAndroid Build Coastguard Worker                        dex_pc_high,
468*795d594fSAndroid Build Coastguard Worker                        owner_->builder_->GetIsa(),
469*795d594fSAndroid Build Coastguard Worker                        &info_,
470*795d594fSAndroid Build Coastguard Worker                        &owner_->debug_loc_,
471*795d594fSAndroid Build Coastguard Worker                        &owner_->debug_ranges_);
472*795d594fSAndroid Build Coastguard Worker   }
473*795d594fSAndroid Build Coastguard Worker 
474*795d594fSAndroid Build Coastguard Worker   // Linkage name uniquely identifies type.
475*795d594fSAndroid Build Coastguard Worker   // It is used to determine the dynamic type of objects.
476*795d594fSAndroid Build Coastguard Worker   // We use the methods_ field of class since it is unique and it is not moved by the GC.
WriteLinkageName(mirror::Class * type)477*795d594fSAndroid Build Coastguard Worker   void WriteLinkageName(mirror::Class* type) REQUIRES_SHARED(Locks::mutator_lock_) {
478*795d594fSAndroid Build Coastguard Worker     auto* methods_ptr = type->GetMethodsPtr();
479*795d594fSAndroid Build Coastguard Worker     if (methods_ptr == nullptr) {
480*795d594fSAndroid Build Coastguard Worker       // Some types might have no methods.  Allocate empty array instead.
481*795d594fSAndroid Build Coastguard Worker       LinearAlloc* allocator = Runtime::Current()->GetLinearAlloc();
482*795d594fSAndroid Build Coastguard Worker       void* storage = allocator->Alloc(Thread::Current(),
483*795d594fSAndroid Build Coastguard Worker                                        sizeof(LengthPrefixedArray<ArtMethod>),
484*795d594fSAndroid Build Coastguard Worker                                        LinearAllocKind::kNoGCRoots);
485*795d594fSAndroid Build Coastguard Worker       methods_ptr = new (storage) LengthPrefixedArray<ArtMethod>(0);
486*795d594fSAndroid Build Coastguard Worker       type->SetMethodsPtr(methods_ptr, 0, 0);
487*795d594fSAndroid Build Coastguard Worker       DCHECK(type->GetMethodsPtr() != nullptr);
488*795d594fSAndroid Build Coastguard Worker     }
489*795d594fSAndroid Build Coastguard Worker     char name[32];
490*795d594fSAndroid Build Coastguard Worker     snprintf(name, sizeof(name), "0x%" PRIXPTR, reinterpret_cast<uintptr_t>(methods_ptr));
491*795d594fSAndroid Build Coastguard Worker     info_.WriteString(dwarf::DW_AT_linkage_name, name);
492*795d594fSAndroid Build Coastguard Worker   }
493*795d594fSAndroid Build Coastguard Worker 
494*795d594fSAndroid Build Coastguard Worker   // Some types are difficult to define as we go since they need
495*795d594fSAndroid Build Coastguard Worker   // to be enclosed in the right set of namespaces. Therefore we
496*795d594fSAndroid Build Coastguard Worker   // just define all types lazily at the end of compilation unit.
WriteLazyType(const char * type_descriptor)497*795d594fSAndroid Build Coastguard Worker   void WriteLazyType(const char* type_descriptor) {
498*795d594fSAndroid Build Coastguard Worker     if (type_descriptor != nullptr && type_descriptor[0] != 'V') {
499*795d594fSAndroid Build Coastguard Worker       lazy_types_.emplace(std::string(type_descriptor), info_.size());
500*795d594fSAndroid Build Coastguard Worker       info_.WriteRef4(dwarf::DW_AT_type, 0);
501*795d594fSAndroid Build Coastguard Worker     }
502*795d594fSAndroid Build Coastguard Worker   }
503*795d594fSAndroid Build Coastguard Worker 
FinishLazyTypes()504*795d594fSAndroid Build Coastguard Worker   void FinishLazyTypes() {
505*795d594fSAndroid Build Coastguard Worker     for (const auto& lazy_type : lazy_types_) {
506*795d594fSAndroid Build Coastguard Worker       info_.UpdateUint32(lazy_type.second, WriteTypeDeclaration(lazy_type.first));
507*795d594fSAndroid Build Coastguard Worker     }
508*795d594fSAndroid Build Coastguard Worker     lazy_types_.clear();
509*795d594fSAndroid Build Coastguard Worker   }
510*795d594fSAndroid Build Coastguard Worker 
511*795d594fSAndroid Build Coastguard Worker  private:
WriteName(const char * name)512*795d594fSAndroid Build Coastguard Worker   void WriteName(const char* name) {
513*795d594fSAndroid Build Coastguard Worker     if (name != nullptr) {
514*795d594fSAndroid Build Coastguard Worker       info_.WriteString(dwarf::DW_AT_name, name);
515*795d594fSAndroid Build Coastguard Worker     }
516*795d594fSAndroid Build Coastguard Worker   }
517*795d594fSAndroid Build Coastguard Worker 
518*795d594fSAndroid Build Coastguard Worker   // Convert dex type descriptor to DWARF.
519*795d594fSAndroid Build Coastguard Worker   // Returns offset in the compilation unit.
WriteTypeDeclaration(const std::string & desc)520*795d594fSAndroid Build Coastguard Worker   size_t WriteTypeDeclaration(const std::string& desc) {
521*795d594fSAndroid Build Coastguard Worker     using namespace dwarf;  // NOLINT. For easy access to DWARF constants.
522*795d594fSAndroid Build Coastguard Worker 
523*795d594fSAndroid Build Coastguard Worker     DCHECK(!desc.empty());
524*795d594fSAndroid Build Coastguard Worker     const auto it = type_cache_.find(desc);
525*795d594fSAndroid Build Coastguard Worker     if (it != type_cache_.end()) {
526*795d594fSAndroid Build Coastguard Worker       return it->second;
527*795d594fSAndroid Build Coastguard Worker     }
528*795d594fSAndroid Build Coastguard Worker 
529*795d594fSAndroid Build Coastguard Worker     size_t offset;
530*795d594fSAndroid Build Coastguard Worker     if (desc[0] == 'L') {
531*795d594fSAndroid Build Coastguard Worker       // Class type. For example: Lpackage/name;
532*795d594fSAndroid Build Coastguard Worker       size_t class_offset = StartClassTag(desc.c_str());
533*795d594fSAndroid Build Coastguard Worker       info_.WriteFlagPresent(DW_AT_declaration);
534*795d594fSAndroid Build Coastguard Worker       EndClassTag();
535*795d594fSAndroid Build Coastguard Worker       // Reference to the class type.
536*795d594fSAndroid Build Coastguard Worker       offset = info_.StartTag(DW_TAG_reference_type);
537*795d594fSAndroid Build Coastguard Worker       info_.WriteRef(DW_AT_type, class_offset);
538*795d594fSAndroid Build Coastguard Worker       info_.EndTag();
539*795d594fSAndroid Build Coastguard Worker     } else if (desc[0] == '[') {
540*795d594fSAndroid Build Coastguard Worker       // Array type.
541*795d594fSAndroid Build Coastguard Worker       size_t element_type = WriteTypeDeclaration(desc.substr(1));
542*795d594fSAndroid Build Coastguard Worker       CloseNamespacesAboveDepth(0);  // Declare in root namespace.
543*795d594fSAndroid Build Coastguard Worker       size_t array_type = info_.StartTag(DW_TAG_array_type);
544*795d594fSAndroid Build Coastguard Worker       info_.WriteFlagPresent(DW_AT_declaration);
545*795d594fSAndroid Build Coastguard Worker       info_.WriteRef(DW_AT_type, element_type);
546*795d594fSAndroid Build Coastguard Worker       info_.EndTag();
547*795d594fSAndroid Build Coastguard Worker       offset = info_.StartTag(DW_TAG_reference_type);
548*795d594fSAndroid Build Coastguard Worker       info_.WriteRef4(DW_AT_type, array_type);
549*795d594fSAndroid Build Coastguard Worker       info_.EndTag();
550*795d594fSAndroid Build Coastguard Worker     } else {
551*795d594fSAndroid Build Coastguard Worker       // Primitive types.
552*795d594fSAndroid Build Coastguard Worker       DCHECK_EQ(desc.size(), 1u);
553*795d594fSAndroid Build Coastguard Worker 
554*795d594fSAndroid Build Coastguard Worker       const char* name;
555*795d594fSAndroid Build Coastguard Worker       uint32_t encoding;
556*795d594fSAndroid Build Coastguard Worker       uint32_t byte_size;
557*795d594fSAndroid Build Coastguard Worker       switch (desc[0]) {
558*795d594fSAndroid Build Coastguard Worker       case 'B':
559*795d594fSAndroid Build Coastguard Worker         name = "byte";
560*795d594fSAndroid Build Coastguard Worker         encoding = DW_ATE_signed;
561*795d594fSAndroid Build Coastguard Worker         byte_size = 1;
562*795d594fSAndroid Build Coastguard Worker         break;
563*795d594fSAndroid Build Coastguard Worker       case 'C':
564*795d594fSAndroid Build Coastguard Worker         name = "char";
565*795d594fSAndroid Build Coastguard Worker         encoding = DW_ATE_UTF;
566*795d594fSAndroid Build Coastguard Worker         byte_size = 2;
567*795d594fSAndroid Build Coastguard Worker         break;
568*795d594fSAndroid Build Coastguard Worker       case 'D':
569*795d594fSAndroid Build Coastguard Worker         name = "double";
570*795d594fSAndroid Build Coastguard Worker         encoding = DW_ATE_float;
571*795d594fSAndroid Build Coastguard Worker         byte_size = 8;
572*795d594fSAndroid Build Coastguard Worker         break;
573*795d594fSAndroid Build Coastguard Worker       case 'F':
574*795d594fSAndroid Build Coastguard Worker         name = "float";
575*795d594fSAndroid Build Coastguard Worker         encoding = DW_ATE_float;
576*795d594fSAndroid Build Coastguard Worker         byte_size = 4;
577*795d594fSAndroid Build Coastguard Worker         break;
578*795d594fSAndroid Build Coastguard Worker       case 'I':
579*795d594fSAndroid Build Coastguard Worker         name = "int";
580*795d594fSAndroid Build Coastguard Worker         encoding = DW_ATE_signed;
581*795d594fSAndroid Build Coastguard Worker         byte_size = 4;
582*795d594fSAndroid Build Coastguard Worker         break;
583*795d594fSAndroid Build Coastguard Worker       case 'J':
584*795d594fSAndroid Build Coastguard Worker         name = "long";
585*795d594fSAndroid Build Coastguard Worker         encoding = DW_ATE_signed;
586*795d594fSAndroid Build Coastguard Worker         byte_size = 8;
587*795d594fSAndroid Build Coastguard Worker         break;
588*795d594fSAndroid Build Coastguard Worker       case 'S':
589*795d594fSAndroid Build Coastguard Worker         name = "short";
590*795d594fSAndroid Build Coastguard Worker         encoding = DW_ATE_signed;
591*795d594fSAndroid Build Coastguard Worker         byte_size = 2;
592*795d594fSAndroid Build Coastguard Worker         break;
593*795d594fSAndroid Build Coastguard Worker       case 'Z':
594*795d594fSAndroid Build Coastguard Worker         name = "boolean";
595*795d594fSAndroid Build Coastguard Worker         encoding = DW_ATE_boolean;
596*795d594fSAndroid Build Coastguard Worker         byte_size = 1;
597*795d594fSAndroid Build Coastguard Worker         break;
598*795d594fSAndroid Build Coastguard Worker       case 'V':
599*795d594fSAndroid Build Coastguard Worker         LOG(FATAL) << "Void type should not be encoded";
600*795d594fSAndroid Build Coastguard Worker         UNREACHABLE();
601*795d594fSAndroid Build Coastguard Worker       default:
602*795d594fSAndroid Build Coastguard Worker         LOG(FATAL) << "Unknown dex type descriptor: \"" << desc << "\"";
603*795d594fSAndroid Build Coastguard Worker         UNREACHABLE();
604*795d594fSAndroid Build Coastguard Worker       }
605*795d594fSAndroid Build Coastguard Worker       CloseNamespacesAboveDepth(0);  // Declare in root namespace.
606*795d594fSAndroid Build Coastguard Worker       offset = info_.StartTag(DW_TAG_base_type);
607*795d594fSAndroid Build Coastguard Worker       WriteName(name);
608*795d594fSAndroid Build Coastguard Worker       info_.WriteData1(DW_AT_encoding, encoding);
609*795d594fSAndroid Build Coastguard Worker       info_.WriteData1(DW_AT_byte_size, byte_size);
610*795d594fSAndroid Build Coastguard Worker       info_.EndTag();
611*795d594fSAndroid Build Coastguard Worker     }
612*795d594fSAndroid Build Coastguard Worker 
613*795d594fSAndroid Build Coastguard Worker     type_cache_.emplace(desc, offset);
614*795d594fSAndroid Build Coastguard Worker     return offset;
615*795d594fSAndroid Build Coastguard Worker   }
616*795d594fSAndroid Build Coastguard Worker 
617*795d594fSAndroid Build Coastguard Worker   // Start DW_TAG_class_type tag nested in DW_TAG_namespace tags.
618*795d594fSAndroid Build Coastguard Worker   // Returns offset of the class tag in the compilation unit.
StartClassTag(const char * desc)619*795d594fSAndroid Build Coastguard Worker   size_t StartClassTag(const char* desc) {
620*795d594fSAndroid Build Coastguard Worker     std::string name = SetNamespaceForClass(desc);
621*795d594fSAndroid Build Coastguard Worker     size_t offset = info_.StartTag(dwarf::DW_TAG_class_type);
622*795d594fSAndroid Build Coastguard Worker     WriteName(name.c_str());
623*795d594fSAndroid Build Coastguard Worker     return offset;
624*795d594fSAndroid Build Coastguard Worker   }
625*795d594fSAndroid Build Coastguard Worker 
EndClassTag()626*795d594fSAndroid Build Coastguard Worker   void EndClassTag() {
627*795d594fSAndroid Build Coastguard Worker     info_.EndTag();
628*795d594fSAndroid Build Coastguard Worker   }
629*795d594fSAndroid Build Coastguard Worker 
630*795d594fSAndroid Build Coastguard Worker   // Set the current namespace nesting to one required by the given class.
631*795d594fSAndroid Build Coastguard Worker   // Returns the class name with namespaces, 'L', and ';' stripped.
SetNamespaceForClass(const char * desc)632*795d594fSAndroid Build Coastguard Worker   std::string SetNamespaceForClass(const char* desc) {
633*795d594fSAndroid Build Coastguard Worker     DCHECK(desc != nullptr && desc[0] == 'L');
634*795d594fSAndroid Build Coastguard Worker     desc++;  // Skip the initial 'L'.
635*795d594fSAndroid Build Coastguard Worker     size_t depth = 0;
636*795d594fSAndroid Build Coastguard Worker     for (const char* end; (end = strchr(desc, '/')) != nullptr; desc = end + 1, ++depth) {
637*795d594fSAndroid Build Coastguard Worker       // Check whether the name at this depth is already what we need.
638*795d594fSAndroid Build Coastguard Worker       if (depth < current_namespace_.size()) {
639*795d594fSAndroid Build Coastguard Worker         const std::string& name = current_namespace_[depth];
640*795d594fSAndroid Build Coastguard Worker         if (name.compare(0, name.size(), desc, end - desc) == 0) {
641*795d594fSAndroid Build Coastguard Worker           continue;
642*795d594fSAndroid Build Coastguard Worker         }
643*795d594fSAndroid Build Coastguard Worker       }
644*795d594fSAndroid Build Coastguard Worker       // Otherwise we need to open a new namespace tag at this depth.
645*795d594fSAndroid Build Coastguard Worker       CloseNamespacesAboveDepth(depth);
646*795d594fSAndroid Build Coastguard Worker       info_.StartTag(dwarf::DW_TAG_namespace);
647*795d594fSAndroid Build Coastguard Worker       std::string name(desc, end - desc);
648*795d594fSAndroid Build Coastguard Worker       WriteName(name.c_str());
649*795d594fSAndroid Build Coastguard Worker       current_namespace_.push_back(std::move(name));
650*795d594fSAndroid Build Coastguard Worker     }
651*795d594fSAndroid Build Coastguard Worker     CloseNamespacesAboveDepth(depth);
652*795d594fSAndroid Build Coastguard Worker     return std::string(desc, strchr(desc, ';') - desc);
653*795d594fSAndroid Build Coastguard Worker   }
654*795d594fSAndroid Build Coastguard Worker 
655*795d594fSAndroid Build Coastguard Worker   // Close namespace tags to reach the given nesting depth.
CloseNamespacesAboveDepth(size_t depth)656*795d594fSAndroid Build Coastguard Worker   void CloseNamespacesAboveDepth(size_t depth) {
657*795d594fSAndroid Build Coastguard Worker     DCHECK_LE(depth, current_namespace_.size());
658*795d594fSAndroid Build Coastguard Worker     while (current_namespace_.size() > depth) {
659*795d594fSAndroid Build Coastguard Worker       info_.EndTag();
660*795d594fSAndroid Build Coastguard Worker       current_namespace_.pop_back();
661*795d594fSAndroid Build Coastguard Worker     }
662*795d594fSAndroid Build Coastguard Worker   }
663*795d594fSAndroid Build Coastguard Worker 
664*795d594fSAndroid Build Coastguard Worker   // For access to the ELF sections.
665*795d594fSAndroid Build Coastguard Worker   ElfDebugInfoWriter<ElfTypes>* owner_;
666*795d594fSAndroid Build Coastguard Worker   // Temporary buffer to create and store the entries.
667*795d594fSAndroid Build Coastguard Worker   dwarf::DebugInfoEntryWriter<> info_;
668*795d594fSAndroid Build Coastguard Worker   // Cache of already translated type descriptors.
669*795d594fSAndroid Build Coastguard Worker   std::map<std::string, size_t> type_cache_;  // type_desc -> definition_offset.
670*795d594fSAndroid Build Coastguard Worker   // 32-bit references which need to be resolved to a type later.
671*795d594fSAndroid Build Coastguard Worker   // Given type may be used multiple times.  Therefore we need a multimap.
672*795d594fSAndroid Build Coastguard Worker   std::multimap<std::string, size_t> lazy_types_;  // type_desc -> patch_offset.
673*795d594fSAndroid Build Coastguard Worker   // The current set of open namespace tags which are active and not closed yet.
674*795d594fSAndroid Build Coastguard Worker   std::vector<std::string> current_namespace_;
675*795d594fSAndroid Build Coastguard Worker };
676*795d594fSAndroid Build Coastguard Worker 
677*795d594fSAndroid Build Coastguard Worker }  // namespace debug
678*795d594fSAndroid Build Coastguard Worker }  // namespace art
679*795d594fSAndroid Build Coastguard Worker 
680*795d594fSAndroid Build Coastguard Worker #endif  // ART_COMPILER_DEBUG_ELF_DEBUG_INFO_WRITER_H_
681*795d594fSAndroid Build Coastguard Worker 
682