13b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky/* 23b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky * Copyright (C) 2015 The Android Open Source Project 33b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky * 43b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky * Licensed under the Apache License, Version 2.0 (the "License"); 53b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky * you may not use this file except in compliance with the License. 63b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky * You may obtain a copy of the License at 73b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky * 83b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky * http://www.apache.org/licenses/LICENSE-2.0 93b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky * 103b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky * Unless required by applicable law or agreed to in writing, software 113b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky * distributed under the License is distributed on an "AS IS" BASIS, 123b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 133b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky * See the License for the specific language governing permissions and 143b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky * limitations under the License. 153b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky */ 163b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky 173b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky#include "elf_writer_debug.h" 183b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky 19626a1666015b0fa201e979870baf06afa93b65e7David Srbecky#include <unordered_set> 20626a1666015b0fa201e979870baf06afa93b65e7David Srbecky 21e3d623e54c0640b0594eabaa3c3b176dd577927cAndreas Gampe#include "base/casts.h" 223b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky#include "compiled_method.h" 233b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky#include "driver/compiler_driver.h" 243b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky#include "dex_file-inl.h" 253b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky#include "dwarf/headers.h" 263b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky#include "dwarf/register.h" 273b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky#include "oat_writer.h" 2841b175aba41c9365a1c53b8a1afbd17129c87c14Vladimir Marko#include "utils.h" 293b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky 303b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbeckynamespace art { 313b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbeckynamespace dwarf { 323b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky 33a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbeckystatic void WriteDebugFrameCIE(InstructionSet isa, 34a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky ExceptionHeaderValueApplication addr_type, 35a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky CFIFormat format, 36a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky std::vector<uint8_t>* eh_frame) { 373b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky // Scratch registers should be marked as undefined. This tells the 383b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky // debugger that its value in the previous frame is not recoverable. 393b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky bool is64bit = Is64BitInstructionSet(isa); 403b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky switch (isa) { 413b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky case kArm: 423b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky case kThumb2: { 433b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky DebugFrameOpCodeWriter<> opcodes; 443b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky opcodes.DefCFA(Reg::ArmCore(13), 0); // R13(SP). 453b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky // core registers. 463b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky for (int reg = 0; reg < 13; reg++) { 473b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky if (reg < 4 || reg == 12) { 483b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky opcodes.Undefined(Reg::ArmCore(reg)); 493b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky } else { 503b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky opcodes.SameValue(Reg::ArmCore(reg)); 513b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky } 523b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky } 533b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky // fp registers. 543b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky for (int reg = 0; reg < 32; reg++) { 553b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky if (reg < 16) { 563b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky opcodes.Undefined(Reg::ArmFp(reg)); 573b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky } else { 583b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky opcodes.SameValue(Reg::ArmFp(reg)); 593b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky } 603b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky } 61527c9c71f0c6e2f9943ac028e7c050500699a44bDavid Srbecky auto return_reg = Reg::ArmCore(14); // R14(LR). 62a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky WriteDebugFrameCIE(is64bit, addr_type, return_reg, 63a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky opcodes, format, eh_frame); 643b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky return; 653b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky } 663b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky case kArm64: { 673b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky DebugFrameOpCodeWriter<> opcodes; 683b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky opcodes.DefCFA(Reg::Arm64Core(31), 0); // R31(SP). 693b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky // core registers. 703b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky for (int reg = 0; reg < 30; reg++) { 713b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky if (reg < 8 || reg == 16 || reg == 17) { 723b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky opcodes.Undefined(Reg::Arm64Core(reg)); 733b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky } else { 743b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky opcodes.SameValue(Reg::Arm64Core(reg)); 753b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky } 763b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky } 773b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky // fp registers. 783b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky for (int reg = 0; reg < 32; reg++) { 793b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky if (reg < 8 || reg >= 16) { 803b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky opcodes.Undefined(Reg::Arm64Fp(reg)); 813b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky } else { 823b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky opcodes.SameValue(Reg::Arm64Fp(reg)); 833b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky } 843b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky } 85527c9c71f0c6e2f9943ac028e7c050500699a44bDavid Srbecky auto return_reg = Reg::Arm64Core(30); // R30(LR). 86a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky WriteDebugFrameCIE(is64bit, addr_type, return_reg, 87a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky opcodes, format, eh_frame); 883b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky return; 893b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky } 903b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky case kMips: 913b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky case kMips64: { 923b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky DebugFrameOpCodeWriter<> opcodes; 933b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky opcodes.DefCFA(Reg::MipsCore(29), 0); // R29(SP). 943b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky // core registers. 953b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky for (int reg = 1; reg < 26; reg++) { 963b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky if (reg < 16 || reg == 24 || reg == 25) { // AT, V*, A*, T*. 973b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky opcodes.Undefined(Reg::MipsCore(reg)); 983b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky } else { 993b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky opcodes.SameValue(Reg::MipsCore(reg)); 1003b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky } 1013b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky } 102527c9c71f0c6e2f9943ac028e7c050500699a44bDavid Srbecky auto return_reg = Reg::MipsCore(31); // R31(RA). 103a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky WriteDebugFrameCIE(is64bit, addr_type, return_reg, 104a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky opcodes, format, eh_frame); 1053b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky return; 1063b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky } 1073b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky case kX86: { 1088a813f72d21dea87b9e94b686fb35868ad4a88c4David Srbecky // FIXME: Add fp registers once libunwind adds support for them. Bug: 20491296 1098a813f72d21dea87b9e94b686fb35868ad4a88c4David Srbecky constexpr bool generate_opcodes_for_x86_fp = false; 1103b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky DebugFrameOpCodeWriter<> opcodes; 1113b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky opcodes.DefCFA(Reg::X86Core(4), 4); // R4(ESP). 1123b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky opcodes.Offset(Reg::X86Core(8), -4); // R8(EIP). 1133b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky // core registers. 1143b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky for (int reg = 0; reg < 8; reg++) { 1153b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky if (reg <= 3) { 1163b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky opcodes.Undefined(Reg::X86Core(reg)); 1173b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky } else if (reg == 4) { 1183b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky // Stack pointer. 1193b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky } else { 1203b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky opcodes.SameValue(Reg::X86Core(reg)); 1213b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky } 1223b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky } 1233b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky // fp registers. 1248a813f72d21dea87b9e94b686fb35868ad4a88c4David Srbecky if (generate_opcodes_for_x86_fp) { 1258a813f72d21dea87b9e94b686fb35868ad4a88c4David Srbecky for (int reg = 0; reg < 8; reg++) { 1268a813f72d21dea87b9e94b686fb35868ad4a88c4David Srbecky opcodes.Undefined(Reg::X86Fp(reg)); 1278a813f72d21dea87b9e94b686fb35868ad4a88c4David Srbecky } 1283b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky } 129527c9c71f0c6e2f9943ac028e7c050500699a44bDavid Srbecky auto return_reg = Reg::X86Core(8); // R8(EIP). 130a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky WriteDebugFrameCIE(is64bit, addr_type, return_reg, 131a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky opcodes, format, eh_frame); 1323b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky return; 1333b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky } 1343b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky case kX86_64: { 1353b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky DebugFrameOpCodeWriter<> opcodes; 1363b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky opcodes.DefCFA(Reg::X86_64Core(4), 8); // R4(RSP). 1373b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky opcodes.Offset(Reg::X86_64Core(16), -8); // R16(RIP). 1383b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky // core registers. 1393b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky for (int reg = 0; reg < 16; reg++) { 1403b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky if (reg == 4) { 1413b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky // Stack pointer. 1423b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky } else if (reg < 12 && reg != 3 && reg != 5) { // except EBX and EBP. 1433b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky opcodes.Undefined(Reg::X86_64Core(reg)); 1443b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky } else { 1453b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky opcodes.SameValue(Reg::X86_64Core(reg)); 1463b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky } 1473b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky } 1483b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky // fp registers. 1493b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky for (int reg = 0; reg < 16; reg++) { 1503b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky if (reg < 12) { 1513b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky opcodes.Undefined(Reg::X86_64Fp(reg)); 1523b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky } else { 1533b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky opcodes.SameValue(Reg::X86_64Fp(reg)); 1543b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky } 1553b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky } 156527c9c71f0c6e2f9943ac028e7c050500699a44bDavid Srbecky auto return_reg = Reg::X86_64Core(16); // R16(RIP). 157a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky WriteDebugFrameCIE(is64bit, addr_type, return_reg, 158a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky opcodes, format, eh_frame); 1593b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky return; 1603b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky } 1613b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky case kNone: 1623b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky break; 1633b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky } 1643b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky LOG(FATAL) << "Can not write CIE frame for ISA " << isa; 1653b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky UNREACHABLE(); 1663b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky} 1673b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky 168a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbeckyvoid WriteCFISection(const CompilerDriver* compiler, 169a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky const OatWriter* oat_writer, 170a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky ExceptionHeaderValueApplication address_type, 171a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky CFIFormat format, 172a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky std::vector<uint8_t>* debug_frame, 173a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky std::vector<uintptr_t>* debug_frame_patches, 174a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky std::vector<uint8_t>* eh_frame_hdr, 175a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky std::vector<uintptr_t>* eh_frame_hdr_patches) { 1768dc7324da5bd0f2afd2ab558ab04882329a61fe8David Srbecky const auto& method_infos = oat_writer->GetMethodDebugInfo(); 1778dc7324da5bd0f2afd2ab558ab04882329a61fe8David Srbecky const InstructionSet isa = compiler->GetInstructionSet(); 178527c9c71f0c6e2f9943ac028e7c050500699a44bDavid Srbecky 179a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky // Write .eh_frame/.debug_frame section. 180033d745bb9412c9b546d29395cc9efbbb4fa306eDavid Srbecky std::map<uint32_t, size_t> address_to_fde_offset_map; 181a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky size_t cie_offset = debug_frame->size(); 182a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky WriteDebugFrameCIE(isa, address_type, format, debug_frame); 1838dc7324da5bd0f2afd2ab558ab04882329a61fe8David Srbecky for (const OatWriter::DebugInfo& mi : method_infos) { 1846d73c9d06bc0fc6b32825ca0a8224010933a026eDavid Srbecky if (!mi.deduped_) { // Only one FDE per unique address. 1856d73c9d06bc0fc6b32825ca0a8224010933a026eDavid Srbecky const SwapVector<uint8_t>* opcodes = mi.compiled_method_->GetCFIInfo(); 1866d73c9d06bc0fc6b32825ca0a8224010933a026eDavid Srbecky if (opcodes != nullptr) { 187a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky address_to_fde_offset_map.emplace(mi.low_pc_, debug_frame->size()); 188a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky WriteDebugFrameFDE(Is64BitInstructionSet(isa), cie_offset, 189a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky mi.low_pc_, mi.high_pc_ - mi.low_pc_, 190a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky opcodes, format, debug_frame, debug_frame_patches); 1916d73c9d06bc0fc6b32825ca0a8224010933a026eDavid Srbecky } 1928dc7324da5bd0f2afd2ab558ab04882329a61fe8David Srbecky } 1938dc7324da5bd0f2afd2ab558ab04882329a61fe8David Srbecky } 194527c9c71f0c6e2f9943ac028e7c050500699a44bDavid Srbecky 195a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky if (format == DW_EH_FRAME_FORMAT) { 196a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky // Write .eh_frame_hdr section. 197a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky Writer<> header(eh_frame_hdr); 198a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky header.PushUint8(1); // Version. 199a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky // Encoding of .eh_frame pointer - libunwind does not honor datarel here, 200a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky // so we have to use pcrel which means relative to the pointer's location. 201a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky header.PushUint8(DW_EH_PE_pcrel | DW_EH_PE_sdata4); 202a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky // Encoding of binary search table size. 203a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky header.PushUint8(DW_EH_PE_udata4); 204a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky // Encoding of binary search table addresses - libunwind supports only this 205a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky // specific combination, which means relative to the start of .eh_frame_hdr. 206a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky header.PushUint8(DW_EH_PE_datarel | DW_EH_PE_sdata4); 207a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky // .eh_frame pointer - .eh_frame_hdr section is after .eh_frame section 208a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky const int32_t relative_eh_frame_begin = -static_cast<int32_t>(debug_frame->size()); 209a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky header.PushInt32(relative_eh_frame_begin - 4U); 210a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky // Binary search table size (number of entries). 211a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky header.PushUint32(dchecked_integral_cast<uint32_t>(address_to_fde_offset_map.size())); 212a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky // Binary search table. 213a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky for (const auto& address_to_fde_offset : address_to_fde_offset_map) { 214a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky u_int32_t code_address = address_to_fde_offset.first; 215a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky int32_t fde_address = dchecked_integral_cast<int32_t>(address_to_fde_offset.second); 216a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky eh_frame_hdr_patches->push_back(header.data()->size()); 217a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky header.PushUint32(code_address); 218a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky // We know the exact layout (eh_frame is immediately before eh_frame_hdr) 219a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky // and the data is relative to the start of the eh_frame_hdr, 220a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky // so patching isn't necessary (in contrast to the code address above). 221a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky header.PushInt32(relative_eh_frame_begin + fde_address); 222a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky } 223033d745bb9412c9b546d29395cc9efbbb4fa306eDavid Srbecky } 2248dc7324da5bd0f2afd2ab558ab04882329a61fe8David Srbecky} 2258dc7324da5bd0f2afd2ab558ab04882329a61fe8David Srbecky 2263b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky/* 2273b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky * @brief Generate the DWARF sections. 2283b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky * @param oat_writer The Oat file Writer. 2293b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky * @param eh_frame Call Frame Information. 2303b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky * @param debug_info Compilation unit information. 231527c9c71f0c6e2f9943ac028e7c050500699a44bDavid Srbecky * @param debug_info_patches Address locations to be patched. 2323b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky * @param debug_abbrev Abbreviations used to generate dbg_info. 2333b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky * @param debug_str Debug strings. 2343b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky * @param debug_line Line number table. 235527c9c71f0c6e2f9943ac028e7c050500699a44bDavid Srbecky * @param debug_line_patches Address locations to be patched. 2363b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky */ 2373b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbeckyvoid WriteDebugSections(const CompilerDriver* compiler, 238527c9c71f0c6e2f9943ac028e7c050500699a44bDavid Srbecky const OatWriter* oat_writer, 2393b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky std::vector<uint8_t>* debug_info, 240527c9c71f0c6e2f9943ac028e7c050500699a44bDavid Srbecky std::vector<uintptr_t>* debug_info_patches, 2413b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky std::vector<uint8_t>* debug_abbrev, 2423b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky std::vector<uint8_t>* debug_str, 243527c9c71f0c6e2f9943ac028e7c050500699a44bDavid Srbecky std::vector<uint8_t>* debug_line, 244527c9c71f0c6e2f9943ac028e7c050500699a44bDavid Srbecky std::vector<uintptr_t>* debug_line_patches) { 2453b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky const std::vector<OatWriter::DebugInfo>& method_infos = oat_writer->GetMethodDebugInfo(); 2463b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky const InstructionSet isa = compiler->GetInstructionSet(); 247a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky const bool is64bit = Is64BitInstructionSet(isa); 2483b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky 249626a1666015b0fa201e979870baf06afa93b65e7David Srbecky // Find all addresses (low_pc) which contain deduped methods. 250626a1666015b0fa201e979870baf06afa93b65e7David Srbecky // The first instance of method is not marked deduped_, but the rest is. 251626a1666015b0fa201e979870baf06afa93b65e7David Srbecky std::unordered_set<uint32_t> deduped_addresses; 252626a1666015b0fa201e979870baf06afa93b65e7David Srbecky for (auto it = method_infos.begin(); it != method_infos.end(); ++it) { 253626a1666015b0fa201e979870baf06afa93b65e7David Srbecky if (it->deduped_) { 254626a1666015b0fa201e979870baf06afa93b65e7David Srbecky deduped_addresses.insert(it->low_pc_); 255626a1666015b0fa201e979870baf06afa93b65e7David Srbecky } 256626a1666015b0fa201e979870baf06afa93b65e7David Srbecky } 257626a1666015b0fa201e979870baf06afa93b65e7David Srbecky 258799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky // Group the methods into compilation units based on source file. 259799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky std::vector<std::vector<const OatWriter::DebugInfo*>> compilation_units; 260799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky const char* last_source_file = nullptr; 261799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky for (const auto& mi : method_infos) { 262799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky // Attribute given instruction range only to single method. 263799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky // Otherwise the debugger might get really confused. 264799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky if (!mi.deduped_) { 265799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky auto& dex_class_def = mi.dex_file_->GetClassDef(mi.class_def_index_); 266799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky const char* source_file = mi.dex_file_->GetSourceFile(dex_class_def); 267799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky if (compilation_units.empty() || source_file != last_source_file) { 268799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky compilation_units.push_back(std::vector<const OatWriter::DebugInfo*>()); 269799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky } 270799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky compilation_units.back().push_back(&mi); 271799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky last_source_file = source_file; 2723b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky } 2733b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky } 2743b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky 275799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky // Write .debug_info section. 276799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky for (const auto& compilation_unit : compilation_units) { 277799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky uint32_t cunit_low_pc = 0xFFFFFFFFU; 278799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky uint32_t cunit_high_pc = 0; 279799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky for (auto method_info : compilation_unit) { 280799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky cunit_low_pc = std::min(cunit_low_pc, method_info->low_pc_); 281799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky cunit_high_pc = std::max(cunit_high_pc, method_info->high_pc_); 2823b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky } 2833b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky 284799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky size_t debug_abbrev_offset = debug_abbrev->size(); 285a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky DebugInfoEntryWriter<> info(is64bit, debug_abbrev); 286799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky info.StartTag(DW_TAG_compile_unit, DW_CHILDREN_yes); 287799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky info.WriteStrp(DW_AT_producer, "Android dex2oat", debug_str); 288799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky info.WriteData1(DW_AT_language, DW_LANG_Java); 289527c9c71f0c6e2f9943ac028e7c050500699a44bDavid Srbecky info.WriteAddr(DW_AT_low_pc, cunit_low_pc); 290527c9c71f0c6e2f9943ac028e7c050500699a44bDavid Srbecky info.WriteAddr(DW_AT_high_pc, cunit_high_pc); 291799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky info.WriteData4(DW_AT_stmt_list, debug_line->size()); 292799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky for (auto method_info : compilation_unit) { 293799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky std::string method_name = PrettyMethod(method_info->dex_method_index_, 294799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky *method_info->dex_file_, true); 295799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky if (deduped_addresses.find(method_info->low_pc_) != deduped_addresses.end()) { 296799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky method_name += " [DEDUPED]"; 2973b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky } 298799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky info.StartTag(DW_TAG_subprogram, DW_CHILDREN_no); 299799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky info.WriteStrp(DW_AT_name, method_name.data(), debug_str); 300527c9c71f0c6e2f9943ac028e7c050500699a44bDavid Srbecky info.WriteAddr(DW_AT_low_pc, method_info->low_pc_); 301527c9c71f0c6e2f9943ac028e7c050500699a44bDavid Srbecky info.WriteAddr(DW_AT_high_pc, method_info->high_pc_); 302799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky info.EndTag(); // DW_TAG_subprogram 303799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky } 304799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky info.EndTag(); // DW_TAG_compile_unit 305799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky WriteDebugInfoCU(debug_abbrev_offset, info, debug_info, debug_info_patches); 3063b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky 307799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky // Write .debug_line section. 308799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky std::vector<FileEntry> files; 309799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky std::unordered_map<std::string, size_t> files_map; 310799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky std::vector<std::string> directories; 311799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky std::unordered_map<std::string, size_t> directories_map; 312799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky int code_factor_bits_ = 0; 313799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky int dwarf_isa = -1; 314799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky switch (isa) { 315799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky case kArm: // arm actually means thumb2. 316799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky case kThumb2: 317799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky code_factor_bits_ = 1; // 16-bit instuctions 318799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky dwarf_isa = 1; // DW_ISA_ARM_thumb. 319799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky break; 320799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky case kArm64: 321799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky case kMips: 322799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky case kMips64: 323799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky code_factor_bits_ = 2; // 32-bit instructions 324799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky break; 325799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky case kNone: 326799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky case kX86: 327799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky case kX86_64: 328799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky break; 329799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky } 330a26cb57f46fd3f27a930d9d688fe8670c1f24754David Srbecky DebugLineOpCodeWriter<> opcodes(is64bit, code_factor_bits_); 331527c9c71f0c6e2f9943ac028e7c050500699a44bDavid Srbecky opcodes.SetAddress(cunit_low_pc); 332799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky if (dwarf_isa != -1) { 333799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky opcodes.SetISA(dwarf_isa); 3343b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky } 335799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky for (const OatWriter::DebugInfo* mi : compilation_unit) { 336799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky struct DebugInfoCallbacks { 337799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky static bool NewPosition(void* ctx, uint32_t address, uint32_t line) { 338799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky auto* context = reinterpret_cast<DebugInfoCallbacks*>(ctx); 339799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky context->dex2line_.push_back({address, static_cast<int32_t>(line)}); 340799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky return false; 341799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky } 342799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky DefaultSrcMap dex2line_; 343799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky } debug_info_callbacks; 3443b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky 345799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky const DexFile* dex = mi->dex_file_; 346799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky if (mi->code_item_ != nullptr) { 347799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky dex->DecodeDebugInfo(mi->code_item_, 348799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky (mi->access_flags_ & kAccStatic) != 0, 349799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky mi->dex_method_index_, 350799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky DebugInfoCallbacks::NewPosition, 351799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky nullptr, 352799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky &debug_info_callbacks); 353799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky } 3543b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky 355799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky // Get and deduplicate directory and filename. 356799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky int file_index = 0; // 0 - primary source file of the compilation. 357799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky auto& dex_class_def = dex->GetClassDef(mi->class_def_index_); 358799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky const char* source_file = dex->GetSourceFile(dex_class_def); 359799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky if (source_file != nullptr) { 360799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky std::string file_name(source_file); 361799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky size_t file_name_slash = file_name.find_last_of('/'); 362799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky std::string class_name(dex->GetClassDescriptor(dex_class_def)); 363799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky size_t class_name_slash = class_name.find_last_of('/'); 364799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky std::string full_path(file_name); 365799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky 366799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky // Guess directory from package name. 367799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky int directory_index = 0; // 0 - current directory of the compilation. 368799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky if (file_name_slash == std::string::npos && // Just filename. 369799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky class_name.front() == 'L' && // Type descriptor for a class. 370799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky class_name_slash != std::string::npos) { // Has package name. 371799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky std::string package_name = class_name.substr(1, class_name_slash - 1); 372799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky auto it = directories_map.find(package_name); 373799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky if (it == directories_map.end()) { 374799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky directory_index = 1 + directories.size(); 375799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky directories_map.emplace(package_name, directory_index); 376799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky directories.push_back(package_name); 377799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky } else { 378799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky directory_index = it->second; 379799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky } 380799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky full_path = package_name + "/" + file_name; 3813b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky } 3823b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky 383799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky // Add file entry. 384799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky auto it2 = files_map.find(full_path); 385799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky if (it2 == files_map.end()) { 386799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky file_index = 1 + files.size(); 387799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky files_map.emplace(full_path, file_index); 388799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky files.push_back(FileEntry { 389799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky file_name, 390799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky directory_index, 391799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky 0, // Modification time - NA. 392799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky 0, // File size - NA. 393799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky }); 394799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky } else { 395799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky file_index = it2->second; 396799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky } 3973b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky } 398799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky opcodes.SetFile(file_index); 3993b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky 400799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky // Generate mapping opcodes from PC to Java lines. 401799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky const DefaultSrcMap& dex2line_map = debug_info_callbacks.dex2line_; 402799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky if (file_index != 0 && !dex2line_map.empty()) { 403799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky bool first = true; 404799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky for (SrcMapElem pc2dex : mi->compiled_method_->GetSrcMappingTable()) { 405799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky uint32_t pc = pc2dex.from_; 406799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky int dex_pc = pc2dex.to_; 407799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky auto dex2line = dex2line_map.Find(static_cast<uint32_t>(dex_pc)); 408799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky if (dex2line.first) { 409799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky int line = dex2line.second; 410799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky if (first) { 411799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky first = false; 412799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky if (pc > 0) { 413799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky // Assume that any preceding code is prologue. 414799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky int first_line = dex2line_map.front().to_; 415799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky // Prologue is not a sensible place for a breakpoint. 416799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky opcodes.NegateStmt(); 417527c9c71f0c6e2f9943ac028e7c050500699a44bDavid Srbecky opcodes.AddRow(mi->low_pc_, first_line); 418799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky opcodes.NegateStmt(); 419799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky opcodes.SetPrologueEnd(); 420799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky } 421527c9c71f0c6e2f9943ac028e7c050500699a44bDavid Srbecky opcodes.AddRow(mi->low_pc_ + pc, line); 422799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky } else if (line != opcodes.CurrentLine()) { 423527c9c71f0c6e2f9943ac028e7c050500699a44bDavid Srbecky opcodes.AddRow(mi->low_pc_ + pc, line); 4243b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky } 4253b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky } 4263b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky } 427799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky } else { 428799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky // line 0 - instruction cannot be attributed to any source line. 429527c9c71f0c6e2f9943ac028e7c050500699a44bDavid Srbecky opcodes.AddRow(mi->low_pc_, 0); 4303b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky } 4313b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky } 432527c9c71f0c6e2f9943ac028e7c050500699a44bDavid Srbecky opcodes.AdvancePC(cunit_high_pc); 433799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky opcodes.EndSequence(); 434799b8c4cba128d13bab63c28800d1eed4e3bd243David Srbecky WriteDebugLineTable(directories, files, opcodes, debug_line, debug_line_patches); 4353b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky } 4363b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky} 4373b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky 4383b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky} // namespace dwarf 4393b9d57ab580a0593635a7dbe3dd2e2c76274f9faDavid Srbecky} // namespace art 440