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_LINE_WRITER_H_ 18*795d594fSAndroid Build Coastguard Worker #define ART_COMPILER_DEBUG_ELF_DEBUG_LINE_WRITER_H_ 19*795d594fSAndroid Build Coastguard Worker 20*795d594fSAndroid Build Coastguard Worker #include <unordered_set> 21*795d594fSAndroid Build Coastguard Worker #include <vector> 22*795d594fSAndroid Build Coastguard Worker 23*795d594fSAndroid Build Coastguard Worker #include "base/macros.h" 24*795d594fSAndroid Build Coastguard Worker #include "debug/elf_compilation_unit.h" 25*795d594fSAndroid Build Coastguard Worker #include "debug/src_map_elem.h" 26*795d594fSAndroid Build Coastguard Worker #include "dex/dex_file-inl.h" 27*795d594fSAndroid Build Coastguard Worker #include "dwarf/debug_line_opcode_writer.h" 28*795d594fSAndroid Build Coastguard Worker #include "dwarf/headers.h" 29*795d594fSAndroid Build Coastguard Worker #include "elf/elf_builder.h" 30*795d594fSAndroid Build Coastguard Worker #include "oat/oat_file.h" 31*795d594fSAndroid Build Coastguard Worker #include "oat/stack_map.h" 32*795d594fSAndroid Build Coastguard Worker 33*795d594fSAndroid Build Coastguard Worker namespace art HIDDEN { 34*795d594fSAndroid Build Coastguard Worker namespace debug { 35*795d594fSAndroid Build Coastguard Worker 36*795d594fSAndroid Build Coastguard Worker using PositionInfos = std::vector<DexFile::PositionInfo>; 37*795d594fSAndroid Build Coastguard Worker 38*795d594fSAndroid Build Coastguard Worker template<typename ElfTypes> 39*795d594fSAndroid Build Coastguard Worker class ElfDebugLineWriter { 40*795d594fSAndroid Build Coastguard Worker using Elf_Addr = typename ElfTypes::Addr; 41*795d594fSAndroid Build Coastguard Worker 42*795d594fSAndroid Build Coastguard Worker public: ElfDebugLineWriter(ElfBuilder<ElfTypes> * builder)43*795d594fSAndroid Build Coastguard Worker explicit ElfDebugLineWriter(ElfBuilder<ElfTypes>* builder) : builder_(builder) { 44*795d594fSAndroid Build Coastguard Worker } 45*795d594fSAndroid Build Coastguard Worker Start()46*795d594fSAndroid Build Coastguard Worker void Start() { 47*795d594fSAndroid Build Coastguard Worker builder_->GetDebugLine()->Start(); 48*795d594fSAndroid Build Coastguard Worker } 49*795d594fSAndroid Build Coastguard Worker 50*795d594fSAndroid Build Coastguard Worker // Write line table for given set of methods. 51*795d594fSAndroid Build Coastguard Worker // Returns the number of bytes written. WriteCompilationUnit(ElfCompilationUnit & compilation_unit)52*795d594fSAndroid Build Coastguard Worker size_t WriteCompilationUnit(ElfCompilationUnit& compilation_unit) { 53*795d594fSAndroid Build Coastguard Worker const InstructionSet isa = builder_->GetIsa(); 54*795d594fSAndroid Build Coastguard Worker const bool is64bit = Is64BitInstructionSet(isa); 55*795d594fSAndroid Build Coastguard Worker const Elf_Addr base_address = compilation_unit.is_code_address_text_relative 56*795d594fSAndroid Build Coastguard Worker ? builder_->GetText()->GetAddress() 57*795d594fSAndroid Build Coastguard Worker : 0; 58*795d594fSAndroid Build Coastguard Worker 59*795d594fSAndroid Build Coastguard Worker compilation_unit.debug_line_offset = builder_->GetDebugLine()->GetPosition(); 60*795d594fSAndroid Build Coastguard Worker 61*795d594fSAndroid Build Coastguard Worker std::vector<dwarf::FileEntry> files; 62*795d594fSAndroid Build Coastguard Worker std::unordered_map<std::string, size_t> files_map; 63*795d594fSAndroid Build Coastguard Worker std::vector<std::string> directories; 64*795d594fSAndroid Build Coastguard Worker std::unordered_map<std::string, size_t> directories_map; 65*795d594fSAndroid Build Coastguard Worker int code_factor_bits_ = 0; 66*795d594fSAndroid Build Coastguard Worker int dwarf_isa = -1; 67*795d594fSAndroid Build Coastguard Worker switch (isa) { 68*795d594fSAndroid Build Coastguard Worker case InstructionSet::kArm: // arm actually means thumb2. 69*795d594fSAndroid Build Coastguard Worker case InstructionSet::kThumb2: 70*795d594fSAndroid Build Coastguard Worker code_factor_bits_ = 1; // 16-bit instuctions 71*795d594fSAndroid Build Coastguard Worker dwarf_isa = 1; // DW_ISA_ARM_thumb. 72*795d594fSAndroid Build Coastguard Worker break; 73*795d594fSAndroid Build Coastguard Worker case InstructionSet::kArm64: 74*795d594fSAndroid Build Coastguard Worker code_factor_bits_ = 2; // 32-bit instructions 75*795d594fSAndroid Build Coastguard Worker break; 76*795d594fSAndroid Build Coastguard Worker case InstructionSet::kNone: 77*795d594fSAndroid Build Coastguard Worker case InstructionSet::kRiscv64: 78*795d594fSAndroid Build Coastguard Worker case InstructionSet::kX86: 79*795d594fSAndroid Build Coastguard Worker case InstructionSet::kX86_64: 80*795d594fSAndroid Build Coastguard Worker break; 81*795d594fSAndroid Build Coastguard Worker } 82*795d594fSAndroid Build Coastguard Worker std::unordered_set<uint64_t> seen_addresses(compilation_unit.methods.size()); 83*795d594fSAndroid Build Coastguard Worker dwarf::DebugLineOpCodeWriter<> opcodes(is64bit, code_factor_bits_); 84*795d594fSAndroid Build Coastguard Worker for (const MethodDebugInfo* mi : compilation_unit.methods) { 85*795d594fSAndroid Build Coastguard Worker // Ignore function if we have already generated line table for the same address. 86*795d594fSAndroid Build Coastguard Worker // It would confuse the debugger and the DWARF specification forbids it. 87*795d594fSAndroid Build Coastguard Worker // We allow the line table for method to be replicated in different compilation unit. 88*795d594fSAndroid Build Coastguard Worker // This ensures that each compilation unit contains line table for all its methods. 89*795d594fSAndroid Build Coastguard Worker if (!seen_addresses.insert(mi->code_address).second) { 90*795d594fSAndroid Build Coastguard Worker continue; 91*795d594fSAndroid Build Coastguard Worker } 92*795d594fSAndroid Build Coastguard Worker 93*795d594fSAndroid Build Coastguard Worker uint32_t prologue_end = std::numeric_limits<uint32_t>::max(); 94*795d594fSAndroid Build Coastguard Worker std::vector<SrcMapElem> pc2dex_map; 95*795d594fSAndroid Build Coastguard Worker if (mi->code_info != nullptr) { 96*795d594fSAndroid Build Coastguard Worker // Use stack maps to create mapping table from pc to dex. 97*795d594fSAndroid Build Coastguard Worker const CodeInfo code_info(mi->code_info); 98*795d594fSAndroid Build Coastguard Worker pc2dex_map.reserve(code_info.GetNumberOfStackMaps()); 99*795d594fSAndroid Build Coastguard Worker for (StackMap stack_map : code_info.GetStackMaps()) { 100*795d594fSAndroid Build Coastguard Worker const uint32_t pc = stack_map.GetNativePcOffset(isa); 101*795d594fSAndroid Build Coastguard Worker const int32_t dex = stack_map.GetDexPc(); 102*795d594fSAndroid Build Coastguard Worker pc2dex_map.push_back({pc, dex}); 103*795d594fSAndroid Build Coastguard Worker if (stack_map.HasDexRegisterMap()) { 104*795d594fSAndroid Build Coastguard Worker // Guess that the first map with local variables is the end of prologue. 105*795d594fSAndroid Build Coastguard Worker prologue_end = std::min(prologue_end, pc); 106*795d594fSAndroid Build Coastguard Worker } 107*795d594fSAndroid Build Coastguard Worker } 108*795d594fSAndroid Build Coastguard Worker std::sort(pc2dex_map.begin(), pc2dex_map.end()); 109*795d594fSAndroid Build Coastguard Worker } 110*795d594fSAndroid Build Coastguard Worker 111*795d594fSAndroid Build Coastguard Worker if (pc2dex_map.empty()) { 112*795d594fSAndroid Build Coastguard Worker continue; 113*795d594fSAndroid Build Coastguard Worker } 114*795d594fSAndroid Build Coastguard Worker 115*795d594fSAndroid Build Coastguard Worker // Compensate for compiler's off-by-one-instruction error. 116*795d594fSAndroid Build Coastguard Worker // 117*795d594fSAndroid Build Coastguard Worker // The compiler generates stackmap with PC *after* the branch instruction 118*795d594fSAndroid Build Coastguard Worker // (because this is the PC which is easier to obtain when unwinding). 119*795d594fSAndroid Build Coastguard Worker // 120*795d594fSAndroid Build Coastguard Worker // However, the debugger is more clever and it will ask us for line-number 121*795d594fSAndroid Build Coastguard Worker // mapping at the location of the branch instruction (since the following 122*795d594fSAndroid Build Coastguard Worker // instruction could belong to other line, this is the correct thing to do). 123*795d594fSAndroid Build Coastguard Worker // 124*795d594fSAndroid Build Coastguard Worker // So we really want to just decrement the PC by one instruction so that the 125*795d594fSAndroid Build Coastguard Worker // branch instruction is covered as well. However, we do not know the size 126*795d594fSAndroid Build Coastguard Worker // of the previous instruction, and we can not subtract just a fixed amount 127*795d594fSAndroid Build Coastguard Worker // (the debugger would trust us that the PC is valid; it might try to set 128*795d594fSAndroid Build Coastguard Worker // breakpoint there at some point, and setting breakpoint in mid-instruction 129*795d594fSAndroid Build Coastguard Worker // would make the process crash in spectacular way). 130*795d594fSAndroid Build Coastguard Worker // 131*795d594fSAndroid Build Coastguard Worker // Therefore, we say that the PC which the compiler gave us for the stackmap 132*795d594fSAndroid Build Coastguard Worker // is the end of its associated address range, and we use the PC from the 133*795d594fSAndroid Build Coastguard Worker // previous stack map as the start of the range. This ensures that the PC is 134*795d594fSAndroid Build Coastguard Worker // valid and that the branch instruction is covered. 135*795d594fSAndroid Build Coastguard Worker // 136*795d594fSAndroid Build Coastguard Worker // This ensures we have correct line number mapping at call sites (which is 137*795d594fSAndroid Build Coastguard Worker // important for backtraces), but there is nothing we can do for non-call 138*795d594fSAndroid Build Coastguard Worker // sites (so stepping through optimized code in debugger is not possible). 139*795d594fSAndroid Build Coastguard Worker // 140*795d594fSAndroid Build Coastguard Worker // We do not adjust the stackmaps if the code was compiled as debuggable. 141*795d594fSAndroid Build Coastguard Worker // In that case, the stackmaps should accurately cover all instructions. 142*795d594fSAndroid Build Coastguard Worker if (!mi->is_native_debuggable) { 143*795d594fSAndroid Build Coastguard Worker for (size_t i = pc2dex_map.size() - 1; i > 0; --i) { 144*795d594fSAndroid Build Coastguard Worker pc2dex_map[i].from_ = pc2dex_map[i - 1].from_; 145*795d594fSAndroid Build Coastguard Worker } 146*795d594fSAndroid Build Coastguard Worker pc2dex_map[0].from_ = 0; 147*795d594fSAndroid Build Coastguard Worker } 148*795d594fSAndroid Build Coastguard Worker 149*795d594fSAndroid Build Coastguard Worker Elf_Addr method_address = base_address + mi->code_address; 150*795d594fSAndroid Build Coastguard Worker 151*795d594fSAndroid Build Coastguard Worker PositionInfos dex2line_map; 152*795d594fSAndroid Build Coastguard Worker const DexFile* dex = mi->dex_file; 153*795d594fSAndroid Build Coastguard Worker DCHECK(dex != nullptr); 154*795d594fSAndroid Build Coastguard Worker CodeItemDebugInfoAccessor accessor(*dex, mi->code_item, mi->dex_method_index); 155*795d594fSAndroid Build Coastguard Worker if (!accessor.DecodeDebugPositionInfo( 156*795d594fSAndroid Build Coastguard Worker [&](const DexFile::PositionInfo& entry) { 157*795d594fSAndroid Build Coastguard Worker dex2line_map.push_back(entry); 158*795d594fSAndroid Build Coastguard Worker return false; 159*795d594fSAndroid Build Coastguard Worker })) { 160*795d594fSAndroid Build Coastguard Worker continue; 161*795d594fSAndroid Build Coastguard Worker } 162*795d594fSAndroid Build Coastguard Worker 163*795d594fSAndroid Build Coastguard Worker if (dex2line_map.empty()) { 164*795d594fSAndroid Build Coastguard Worker continue; 165*795d594fSAndroid Build Coastguard Worker } 166*795d594fSAndroid Build Coastguard Worker 167*795d594fSAndroid Build Coastguard Worker opcodes.SetAddress(method_address); 168*795d594fSAndroid Build Coastguard Worker if (dwarf_isa != -1) { 169*795d594fSAndroid Build Coastguard Worker opcodes.SetISA(dwarf_isa); 170*795d594fSAndroid Build Coastguard Worker } 171*795d594fSAndroid Build Coastguard Worker 172*795d594fSAndroid Build Coastguard Worker // Get and deduplicate directory and filename. 173*795d594fSAndroid Build Coastguard Worker int file_index = 0; // 0 - primary source file of the compilation. 174*795d594fSAndroid Build Coastguard Worker auto& dex_class_def = dex->GetClassDef(mi->class_def_index); 175*795d594fSAndroid Build Coastguard Worker const char* source_file = dex->GetSourceFile(dex_class_def); 176*795d594fSAndroid Build Coastguard Worker if (source_file != nullptr) { 177*795d594fSAndroid Build Coastguard Worker std::string file_name(source_file); 178*795d594fSAndroid Build Coastguard Worker size_t file_name_slash = file_name.find_last_of('/'); 179*795d594fSAndroid Build Coastguard Worker std::string class_name(dex->GetClassDescriptor(dex_class_def)); 180*795d594fSAndroid Build Coastguard Worker size_t class_name_slash = class_name.find_last_of('/'); 181*795d594fSAndroid Build Coastguard Worker std::string full_path(file_name); 182*795d594fSAndroid Build Coastguard Worker 183*795d594fSAndroid Build Coastguard Worker // Guess directory from package name. 184*795d594fSAndroid Build Coastguard Worker int directory_index = 0; // 0 - current directory of the compilation. 185*795d594fSAndroid Build Coastguard Worker if (file_name_slash == std::string::npos && // Just filename. 186*795d594fSAndroid Build Coastguard Worker class_name.front() == 'L' && // Type descriptor for a class. 187*795d594fSAndroid Build Coastguard Worker class_name_slash != std::string::npos) { // Has package name. 188*795d594fSAndroid Build Coastguard Worker std::string package_name = class_name.substr(1, class_name_slash - 1); 189*795d594fSAndroid Build Coastguard Worker auto it = directories_map.find(package_name); 190*795d594fSAndroid Build Coastguard Worker if (it == directories_map.end()) { 191*795d594fSAndroid Build Coastguard Worker directory_index = 1 + directories.size(); 192*795d594fSAndroid Build Coastguard Worker directories_map.emplace(package_name, directory_index); 193*795d594fSAndroid Build Coastguard Worker directories.push_back(package_name); 194*795d594fSAndroid Build Coastguard Worker } else { 195*795d594fSAndroid Build Coastguard Worker directory_index = it->second; 196*795d594fSAndroid Build Coastguard Worker } 197*795d594fSAndroid Build Coastguard Worker full_path = ART_FORMAT("{}/{}", package_name, file_name); 198*795d594fSAndroid Build Coastguard Worker } 199*795d594fSAndroid Build Coastguard Worker 200*795d594fSAndroid Build Coastguard Worker // Add file entry. 201*795d594fSAndroid Build Coastguard Worker auto it2 = files_map.find(full_path); 202*795d594fSAndroid Build Coastguard Worker if (it2 == files_map.end()) { 203*795d594fSAndroid Build Coastguard Worker file_index = 1 + files.size(); 204*795d594fSAndroid Build Coastguard Worker files_map.emplace(full_path, file_index); 205*795d594fSAndroid Build Coastguard Worker files.push_back(dwarf::FileEntry { 206*795d594fSAndroid Build Coastguard Worker file_name, 207*795d594fSAndroid Build Coastguard Worker directory_index, 208*795d594fSAndroid Build Coastguard Worker 0, // Modification time - NA. 209*795d594fSAndroid Build Coastguard Worker 0, // File size - NA. 210*795d594fSAndroid Build Coastguard Worker }); 211*795d594fSAndroid Build Coastguard Worker } else { 212*795d594fSAndroid Build Coastguard Worker file_index = it2->second; 213*795d594fSAndroid Build Coastguard Worker } 214*795d594fSAndroid Build Coastguard Worker } 215*795d594fSAndroid Build Coastguard Worker opcodes.SetFile(file_index); 216*795d594fSAndroid Build Coastguard Worker 217*795d594fSAndroid Build Coastguard Worker // Generate mapping opcodes from PC to Java lines. 218*795d594fSAndroid Build Coastguard Worker if (file_index != 0) { 219*795d594fSAndroid Build Coastguard Worker // If the method was not compiled as native-debuggable, we still generate all available 220*795d594fSAndroid Build Coastguard Worker // lines, but we try to prevent the debugger from stepping and setting breakpoints since 221*795d594fSAndroid Build Coastguard Worker // the information is too inaccurate for that (breakpoints would be set after the calls). 222*795d594fSAndroid Build Coastguard Worker const bool default_is_stmt = mi->is_native_debuggable; 223*795d594fSAndroid Build Coastguard Worker bool first = true; 224*795d594fSAndroid Build Coastguard Worker for (SrcMapElem pc2dex : pc2dex_map) { 225*795d594fSAndroid Build Coastguard Worker uint32_t pc = pc2dex.from_; 226*795d594fSAndroid Build Coastguard Worker int dex_pc = pc2dex.to_; 227*795d594fSAndroid Build Coastguard Worker // Find mapping with address with is greater than our dex pc; then go back one step. 228*795d594fSAndroid Build Coastguard Worker auto dex2line = std::upper_bound( 229*795d594fSAndroid Build Coastguard Worker dex2line_map.begin(), 230*795d594fSAndroid Build Coastguard Worker dex2line_map.end(), 231*795d594fSAndroid Build Coastguard Worker dex_pc, 232*795d594fSAndroid Build Coastguard Worker [](uint32_t address, const DexFile::PositionInfo& entry) { 233*795d594fSAndroid Build Coastguard Worker return address < entry.address_; 234*795d594fSAndroid Build Coastguard Worker }); 235*795d594fSAndroid Build Coastguard Worker // Look for first valid mapping after the prologue. 236*795d594fSAndroid Build Coastguard Worker if (dex2line != dex2line_map.begin() && pc >= prologue_end) { 237*795d594fSAndroid Build Coastguard Worker int line = (--dex2line)->line_; 238*795d594fSAndroid Build Coastguard Worker if (first) { 239*795d594fSAndroid Build Coastguard Worker first = false; 240*795d594fSAndroid Build Coastguard Worker if (pc > 0) { 241*795d594fSAndroid Build Coastguard Worker // Assume that any preceding code is prologue. 242*795d594fSAndroid Build Coastguard Worker int first_line = dex2line_map.front().line_; 243*795d594fSAndroid Build Coastguard Worker // Prologue is not a sensible place for a breakpoint. 244*795d594fSAndroid Build Coastguard Worker opcodes.SetIsStmt(false); 245*795d594fSAndroid Build Coastguard Worker opcodes.AddRow(method_address, first_line); 246*795d594fSAndroid Build Coastguard Worker opcodes.SetPrologueEnd(); 247*795d594fSAndroid Build Coastguard Worker } 248*795d594fSAndroid Build Coastguard Worker opcodes.SetIsStmt(default_is_stmt); 249*795d594fSAndroid Build Coastguard Worker opcodes.AddRow(method_address + pc, line); 250*795d594fSAndroid Build Coastguard Worker } else if (line != opcodes.CurrentLine()) { 251*795d594fSAndroid Build Coastguard Worker opcodes.SetIsStmt(default_is_stmt); 252*795d594fSAndroid Build Coastguard Worker opcodes.AddRow(method_address + pc, line); 253*795d594fSAndroid Build Coastguard Worker } 254*795d594fSAndroid Build Coastguard Worker } 255*795d594fSAndroid Build Coastguard Worker } 256*795d594fSAndroid Build Coastguard Worker } else { 257*795d594fSAndroid Build Coastguard Worker // line 0 - instruction cannot be attributed to any source line. 258*795d594fSAndroid Build Coastguard Worker opcodes.AddRow(method_address, 0); 259*795d594fSAndroid Build Coastguard Worker } 260*795d594fSAndroid Build Coastguard Worker 261*795d594fSAndroid Build Coastguard Worker opcodes.AdvancePC(method_address + mi->code_size); 262*795d594fSAndroid Build Coastguard Worker opcodes.EndSequence(); 263*795d594fSAndroid Build Coastguard Worker } 264*795d594fSAndroid Build Coastguard Worker std::vector<uint8_t> buffer; 265*795d594fSAndroid Build Coastguard Worker buffer.reserve(opcodes.data()->size() + KB); 266*795d594fSAndroid Build Coastguard Worker WriteDebugLineTable(directories, files, opcodes, &buffer); 267*795d594fSAndroid Build Coastguard Worker builder_->GetDebugLine()->WriteFully(buffer.data(), buffer.size()); 268*795d594fSAndroid Build Coastguard Worker return buffer.size(); 269*795d594fSAndroid Build Coastguard Worker } 270*795d594fSAndroid Build Coastguard Worker End()271*795d594fSAndroid Build Coastguard Worker void End() { 272*795d594fSAndroid Build Coastguard Worker builder_->GetDebugLine()->End(); 273*795d594fSAndroid Build Coastguard Worker } 274*795d594fSAndroid Build Coastguard Worker 275*795d594fSAndroid Build Coastguard Worker private: 276*795d594fSAndroid Build Coastguard Worker ElfBuilder<ElfTypes>* builder_; 277*795d594fSAndroid Build Coastguard Worker }; 278*795d594fSAndroid Build Coastguard Worker 279*795d594fSAndroid Build Coastguard Worker } // namespace debug 280*795d594fSAndroid Build Coastguard Worker } // namespace art 281*795d594fSAndroid Build Coastguard Worker 282*795d594fSAndroid Build Coastguard Worker #endif // ART_COMPILER_DEBUG_ELF_DEBUG_LINE_WRITER_H_ 283*795d594fSAndroid Build Coastguard Worker 284