1 /* 2 * Copyright (C) 2015 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include "elf_writer_debug.h" 18 19 #include <unordered_set> 20 21 #include "base/casts.h" 22 #include "compiled_method.h" 23 #include "driver/compiler_driver.h" 24 #include "dex_file-inl.h" 25 #include "dwarf/headers.h" 26 #include "dwarf/register.h" 27 #include "oat_writer.h" 28 #include "utils.h" 29 30 namespace art { 31 namespace dwarf { 32 33 static void WriteDebugFrameCIE(InstructionSet isa, 34 ExceptionHeaderValueApplication addr_type, 35 CFIFormat format, 36 std::vector<uint8_t>* eh_frame) { 37 // Scratch registers should be marked as undefined. This tells the 38 // debugger that its value in the previous frame is not recoverable. 39 bool is64bit = Is64BitInstructionSet(isa); 40 switch (isa) { 41 case kArm: 42 case kThumb2: { 43 DebugFrameOpCodeWriter<> opcodes; 44 opcodes.DefCFA(Reg::ArmCore(13), 0); // R13(SP). 45 // core registers. 46 for (int reg = 0; reg < 13; reg++) { 47 if (reg < 4 || reg == 12) { 48 opcodes.Undefined(Reg::ArmCore(reg)); 49 } else { 50 opcodes.SameValue(Reg::ArmCore(reg)); 51 } 52 } 53 // fp registers. 54 for (int reg = 0; reg < 32; reg++) { 55 if (reg < 16) { 56 opcodes.Undefined(Reg::ArmFp(reg)); 57 } else { 58 opcodes.SameValue(Reg::ArmFp(reg)); 59 } 60 } 61 auto return_reg = Reg::ArmCore(14); // R14(LR). 62 WriteDebugFrameCIE(is64bit, addr_type, return_reg, 63 opcodes, format, eh_frame); 64 return; 65 } 66 case kArm64: { 67 DebugFrameOpCodeWriter<> opcodes; 68 opcodes.DefCFA(Reg::Arm64Core(31), 0); // R31(SP). 69 // core registers. 70 for (int reg = 0; reg < 30; reg++) { 71 if (reg < 8 || reg == 16 || reg == 17) { 72 opcodes.Undefined(Reg::Arm64Core(reg)); 73 } else { 74 opcodes.SameValue(Reg::Arm64Core(reg)); 75 } 76 } 77 // fp registers. 78 for (int reg = 0; reg < 32; reg++) { 79 if (reg < 8 || reg >= 16) { 80 opcodes.Undefined(Reg::Arm64Fp(reg)); 81 } else { 82 opcodes.SameValue(Reg::Arm64Fp(reg)); 83 } 84 } 85 auto return_reg = Reg::Arm64Core(30); // R30(LR). 86 WriteDebugFrameCIE(is64bit, addr_type, return_reg, 87 opcodes, format, eh_frame); 88 return; 89 } 90 case kMips: 91 case kMips64: { 92 DebugFrameOpCodeWriter<> opcodes; 93 opcodes.DefCFA(Reg::MipsCore(29), 0); // R29(SP). 94 // core registers. 95 for (int reg = 1; reg < 26; reg++) { 96 if (reg < 16 || reg == 24 || reg == 25) { // AT, V*, A*, T*. 97 opcodes.Undefined(Reg::MipsCore(reg)); 98 } else { 99 opcodes.SameValue(Reg::MipsCore(reg)); 100 } 101 } 102 auto return_reg = Reg::MipsCore(31); // R31(RA). 103 WriteDebugFrameCIE(is64bit, addr_type, return_reg, 104 opcodes, format, eh_frame); 105 return; 106 } 107 case kX86: { 108 // FIXME: Add fp registers once libunwind adds support for them. Bug: 20491296 109 constexpr bool generate_opcodes_for_x86_fp = false; 110 DebugFrameOpCodeWriter<> opcodes; 111 opcodes.DefCFA(Reg::X86Core(4), 4); // R4(ESP). 112 opcodes.Offset(Reg::X86Core(8), -4); // R8(EIP). 113 // core registers. 114 for (int reg = 0; reg < 8; reg++) { 115 if (reg <= 3) { 116 opcodes.Undefined(Reg::X86Core(reg)); 117 } else if (reg == 4) { 118 // Stack pointer. 119 } else { 120 opcodes.SameValue(Reg::X86Core(reg)); 121 } 122 } 123 // fp registers. 124 if (generate_opcodes_for_x86_fp) { 125 for (int reg = 0; reg < 8; reg++) { 126 opcodes.Undefined(Reg::X86Fp(reg)); 127 } 128 } 129 auto return_reg = Reg::X86Core(8); // R8(EIP). 130 WriteDebugFrameCIE(is64bit, addr_type, return_reg, 131 opcodes, format, eh_frame); 132 return; 133 } 134 case kX86_64: { 135 DebugFrameOpCodeWriter<> opcodes; 136 opcodes.DefCFA(Reg::X86_64Core(4), 8); // R4(RSP). 137 opcodes.Offset(Reg::X86_64Core(16), -8); // R16(RIP). 138 // core registers. 139 for (int reg = 0; reg < 16; reg++) { 140 if (reg == 4) { 141 // Stack pointer. 142 } else if (reg < 12 && reg != 3 && reg != 5) { // except EBX and EBP. 143 opcodes.Undefined(Reg::X86_64Core(reg)); 144 } else { 145 opcodes.SameValue(Reg::X86_64Core(reg)); 146 } 147 } 148 // fp registers. 149 for (int reg = 0; reg < 16; reg++) { 150 if (reg < 12) { 151 opcodes.Undefined(Reg::X86_64Fp(reg)); 152 } else { 153 opcodes.SameValue(Reg::X86_64Fp(reg)); 154 } 155 } 156 auto return_reg = Reg::X86_64Core(16); // R16(RIP). 157 WriteDebugFrameCIE(is64bit, addr_type, return_reg, 158 opcodes, format, eh_frame); 159 return; 160 } 161 case kNone: 162 break; 163 } 164 LOG(FATAL) << "Can not write CIE frame for ISA " << isa; 165 UNREACHABLE(); 166 } 167 168 void WriteCFISection(const CompilerDriver* compiler, 169 const OatWriter* oat_writer, 170 ExceptionHeaderValueApplication address_type, 171 CFIFormat format, 172 std::vector<uint8_t>* debug_frame, 173 std::vector<uintptr_t>* debug_frame_patches, 174 std::vector<uint8_t>* eh_frame_hdr, 175 std::vector<uintptr_t>* eh_frame_hdr_patches) { 176 const auto& method_infos = oat_writer->GetMethodDebugInfo(); 177 const InstructionSet isa = compiler->GetInstructionSet(); 178 179 // Write .eh_frame/.debug_frame section. 180 std::map<uint32_t, size_t> address_to_fde_offset_map; 181 size_t cie_offset = debug_frame->size(); 182 WriteDebugFrameCIE(isa, address_type, format, debug_frame); 183 for (const OatWriter::DebugInfo& mi : method_infos) { 184 if (!mi.deduped_) { // Only one FDE per unique address. 185 const SwapVector<uint8_t>* opcodes = mi.compiled_method_->GetCFIInfo(); 186 if (opcodes != nullptr) { 187 address_to_fde_offset_map.emplace(mi.low_pc_, debug_frame->size()); 188 WriteDebugFrameFDE(Is64BitInstructionSet(isa), cie_offset, 189 mi.low_pc_, mi.high_pc_ - mi.low_pc_, 190 opcodes, format, debug_frame, debug_frame_patches); 191 } 192 } 193 } 194 195 if (format == DW_EH_FRAME_FORMAT) { 196 // Write .eh_frame_hdr section. 197 Writer<> header(eh_frame_hdr); 198 header.PushUint8(1); // Version. 199 // Encoding of .eh_frame pointer - libunwind does not honor datarel here, 200 // so we have to use pcrel which means relative to the pointer's location. 201 header.PushUint8(DW_EH_PE_pcrel | DW_EH_PE_sdata4); 202 // Encoding of binary search table size. 203 header.PushUint8(DW_EH_PE_udata4); 204 // Encoding of binary search table addresses - libunwind supports only this 205 // specific combination, which means relative to the start of .eh_frame_hdr. 206 header.PushUint8(DW_EH_PE_datarel | DW_EH_PE_sdata4); 207 // .eh_frame pointer - .eh_frame_hdr section is after .eh_frame section 208 const int32_t relative_eh_frame_begin = -static_cast<int32_t>(debug_frame->size()); 209 header.PushInt32(relative_eh_frame_begin - 4U); 210 // Binary search table size (number of entries). 211 header.PushUint32(dchecked_integral_cast<uint32_t>(address_to_fde_offset_map.size())); 212 // Binary search table. 213 for (const auto& address_to_fde_offset : address_to_fde_offset_map) { 214 u_int32_t code_address = address_to_fde_offset.first; 215 int32_t fde_address = dchecked_integral_cast<int32_t>(address_to_fde_offset.second); 216 eh_frame_hdr_patches->push_back(header.data()->size()); 217 header.PushUint32(code_address); 218 // We know the exact layout (eh_frame is immediately before eh_frame_hdr) 219 // and the data is relative to the start of the eh_frame_hdr, 220 // so patching isn't necessary (in contrast to the code address above). 221 header.PushInt32(relative_eh_frame_begin + fde_address); 222 } 223 } 224 } 225 226 /* 227 * @brief Generate the DWARF sections. 228 * @param oat_writer The Oat file Writer. 229 * @param eh_frame Call Frame Information. 230 * @param debug_info Compilation unit information. 231 * @param debug_info_patches Address locations to be patched. 232 * @param debug_abbrev Abbreviations used to generate dbg_info. 233 * @param debug_str Debug strings. 234 * @param debug_line Line number table. 235 * @param debug_line_patches Address locations to be patched. 236 */ 237 void WriteDebugSections(const CompilerDriver* compiler, 238 const OatWriter* oat_writer, 239 std::vector<uint8_t>* debug_info, 240 std::vector<uintptr_t>* debug_info_patches, 241 std::vector<uint8_t>* debug_abbrev, 242 std::vector<uint8_t>* debug_str, 243 std::vector<uint8_t>* debug_line, 244 std::vector<uintptr_t>* debug_line_patches) { 245 const std::vector<OatWriter::DebugInfo>& method_infos = oat_writer->GetMethodDebugInfo(); 246 const InstructionSet isa = compiler->GetInstructionSet(); 247 const bool is64bit = Is64BitInstructionSet(isa); 248 249 // Find all addresses (low_pc) which contain deduped methods. 250 // The first instance of method is not marked deduped_, but the rest is. 251 std::unordered_set<uint32_t> deduped_addresses; 252 for (auto it = method_infos.begin(); it != method_infos.end(); ++it) { 253 if (it->deduped_) { 254 deduped_addresses.insert(it->low_pc_); 255 } 256 } 257 258 // Group the methods into compilation units based on source file. 259 std::vector<std::vector<const OatWriter::DebugInfo*>> compilation_units; 260 const char* last_source_file = nullptr; 261 for (const auto& mi : method_infos) { 262 // Attribute given instruction range only to single method. 263 // Otherwise the debugger might get really confused. 264 if (!mi.deduped_) { 265 auto& dex_class_def = mi.dex_file_->GetClassDef(mi.class_def_index_); 266 const char* source_file = mi.dex_file_->GetSourceFile(dex_class_def); 267 if (compilation_units.empty() || source_file != last_source_file) { 268 compilation_units.push_back(std::vector<const OatWriter::DebugInfo*>()); 269 } 270 compilation_units.back().push_back(&mi); 271 last_source_file = source_file; 272 } 273 } 274 275 // Write .debug_info section. 276 for (const auto& compilation_unit : compilation_units) { 277 uint32_t cunit_low_pc = 0xFFFFFFFFU; 278 uint32_t cunit_high_pc = 0; 279 for (auto method_info : compilation_unit) { 280 cunit_low_pc = std::min(cunit_low_pc, method_info->low_pc_); 281 cunit_high_pc = std::max(cunit_high_pc, method_info->high_pc_); 282 } 283 284 size_t debug_abbrev_offset = debug_abbrev->size(); 285 DebugInfoEntryWriter<> info(is64bit, debug_abbrev); 286 info.StartTag(DW_TAG_compile_unit, DW_CHILDREN_yes); 287 info.WriteStrp(DW_AT_producer, "Android dex2oat", debug_str); 288 info.WriteData1(DW_AT_language, DW_LANG_Java); 289 info.WriteAddr(DW_AT_low_pc, cunit_low_pc); 290 info.WriteAddr(DW_AT_high_pc, cunit_high_pc); 291 info.WriteData4(DW_AT_stmt_list, debug_line->size()); 292 for (auto method_info : compilation_unit) { 293 std::string method_name = PrettyMethod(method_info->dex_method_index_, 294 *method_info->dex_file_, true); 295 if (deduped_addresses.find(method_info->low_pc_) != deduped_addresses.end()) { 296 method_name += " [DEDUPED]"; 297 } 298 info.StartTag(DW_TAG_subprogram, DW_CHILDREN_no); 299 info.WriteStrp(DW_AT_name, method_name.data(), debug_str); 300 info.WriteAddr(DW_AT_low_pc, method_info->low_pc_); 301 info.WriteAddr(DW_AT_high_pc, method_info->high_pc_); 302 info.EndTag(); // DW_TAG_subprogram 303 } 304 info.EndTag(); // DW_TAG_compile_unit 305 WriteDebugInfoCU(debug_abbrev_offset, info, debug_info, debug_info_patches); 306 307 // Write .debug_line section. 308 std::vector<FileEntry> files; 309 std::unordered_map<std::string, size_t> files_map; 310 std::vector<std::string> directories; 311 std::unordered_map<std::string, size_t> directories_map; 312 int code_factor_bits_ = 0; 313 int dwarf_isa = -1; 314 switch (isa) { 315 case kArm: // arm actually means thumb2. 316 case kThumb2: 317 code_factor_bits_ = 1; // 16-bit instuctions 318 dwarf_isa = 1; // DW_ISA_ARM_thumb. 319 break; 320 case kArm64: 321 case kMips: 322 case kMips64: 323 code_factor_bits_ = 2; // 32-bit instructions 324 break; 325 case kNone: 326 case kX86: 327 case kX86_64: 328 break; 329 } 330 DebugLineOpCodeWriter<> opcodes(is64bit, code_factor_bits_); 331 opcodes.SetAddress(cunit_low_pc); 332 if (dwarf_isa != -1) { 333 opcodes.SetISA(dwarf_isa); 334 } 335 for (const OatWriter::DebugInfo* mi : compilation_unit) { 336 struct DebugInfoCallbacks { 337 static bool NewPosition(void* ctx, uint32_t address, uint32_t line) { 338 auto* context = reinterpret_cast<DebugInfoCallbacks*>(ctx); 339 context->dex2line_.push_back({address, static_cast<int32_t>(line)}); 340 return false; 341 } 342 DefaultSrcMap dex2line_; 343 } debug_info_callbacks; 344 345 const DexFile* dex = mi->dex_file_; 346 if (mi->code_item_ != nullptr) { 347 dex->DecodeDebugInfo(mi->code_item_, 348 (mi->access_flags_ & kAccStatic) != 0, 349 mi->dex_method_index_, 350 DebugInfoCallbacks::NewPosition, 351 nullptr, 352 &debug_info_callbacks); 353 } 354 355 // Get and deduplicate directory and filename. 356 int file_index = 0; // 0 - primary source file of the compilation. 357 auto& dex_class_def = dex->GetClassDef(mi->class_def_index_); 358 const char* source_file = dex->GetSourceFile(dex_class_def); 359 if (source_file != nullptr) { 360 std::string file_name(source_file); 361 size_t file_name_slash = file_name.find_last_of('/'); 362 std::string class_name(dex->GetClassDescriptor(dex_class_def)); 363 size_t class_name_slash = class_name.find_last_of('/'); 364 std::string full_path(file_name); 365 366 // Guess directory from package name. 367 int directory_index = 0; // 0 - current directory of the compilation. 368 if (file_name_slash == std::string::npos && // Just filename. 369 class_name.front() == 'L' && // Type descriptor for a class. 370 class_name_slash != std::string::npos) { // Has package name. 371 std::string package_name = class_name.substr(1, class_name_slash - 1); 372 auto it = directories_map.find(package_name); 373 if (it == directories_map.end()) { 374 directory_index = 1 + directories.size(); 375 directories_map.emplace(package_name, directory_index); 376 directories.push_back(package_name); 377 } else { 378 directory_index = it->second; 379 } 380 full_path = package_name + "/" + file_name; 381 } 382 383 // Add file entry. 384 auto it2 = files_map.find(full_path); 385 if (it2 == files_map.end()) { 386 file_index = 1 + files.size(); 387 files_map.emplace(full_path, file_index); 388 files.push_back(FileEntry { 389 file_name, 390 directory_index, 391 0, // Modification time - NA. 392 0, // File size - NA. 393 }); 394 } else { 395 file_index = it2->second; 396 } 397 } 398 opcodes.SetFile(file_index); 399 400 // Generate mapping opcodes from PC to Java lines. 401 const DefaultSrcMap& dex2line_map = debug_info_callbacks.dex2line_; 402 if (file_index != 0 && !dex2line_map.empty()) { 403 bool first = true; 404 for (SrcMapElem pc2dex : mi->compiled_method_->GetSrcMappingTable()) { 405 uint32_t pc = pc2dex.from_; 406 int dex_pc = pc2dex.to_; 407 auto dex2line = dex2line_map.Find(static_cast<uint32_t>(dex_pc)); 408 if (dex2line.first) { 409 int line = dex2line.second; 410 if (first) { 411 first = false; 412 if (pc > 0) { 413 // Assume that any preceding code is prologue. 414 int first_line = dex2line_map.front().to_; 415 // Prologue is not a sensible place for a breakpoint. 416 opcodes.NegateStmt(); 417 opcodes.AddRow(mi->low_pc_, first_line); 418 opcodes.NegateStmt(); 419 opcodes.SetPrologueEnd(); 420 } 421 opcodes.AddRow(mi->low_pc_ + pc, line); 422 } else if (line != opcodes.CurrentLine()) { 423 opcodes.AddRow(mi->low_pc_ + pc, line); 424 } 425 } 426 } 427 } else { 428 // line 0 - instruction cannot be attributed to any source line. 429 opcodes.AddRow(mi->low_pc_, 0); 430 } 431 } 432 opcodes.AdvancePC(cunit_high_pc); 433 opcodes.EndSequence(); 434 WriteDebugLineTable(directories, files, opcodes, debug_line, debug_line_patches); 435 } 436 } 437 438 } // namespace dwarf 439 } // namespace art 440