1/* 2 * Copyright (C) 2016 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#ifndef ART_COMPILER_DEBUG_ELF_DEBUG_FRAME_WRITER_H_ 18#define ART_COMPILER_DEBUG_ELF_DEBUG_FRAME_WRITER_H_ 19 20#include <vector> 21 22#include "arch/instruction_set.h" 23#include "debug/dwarf/debug_frame_opcode_writer.h" 24#include "debug/dwarf/dwarf_constants.h" 25#include "debug/dwarf/headers.h" 26#include "debug/method_debug_info.h" 27#include "elf_builder.h" 28 29namespace art { 30namespace debug { 31 32static void WriteCIE(InstructionSet isa, 33 dwarf::CFIFormat format, 34 std::vector<uint8_t>* buffer) { 35 using Reg = dwarf::Reg; 36 // Scratch registers should be marked as undefined. This tells the 37 // debugger that its value in the previous frame is not recoverable. 38 bool is64bit = Is64BitInstructionSet(isa); 39 switch (isa) { 40 case kArm: 41 case kThumb2: { 42 dwarf::DebugFrameOpCodeWriter<> opcodes; 43 opcodes.DefCFA(Reg::ArmCore(13), 0); // R13(SP). 44 // core registers. 45 for (int reg = 0; reg < 13; reg++) { 46 if (reg < 4 || reg == 12) { 47 opcodes.Undefined(Reg::ArmCore(reg)); 48 } else { 49 opcodes.SameValue(Reg::ArmCore(reg)); 50 } 51 } 52 // fp registers. 53 for (int reg = 0; reg < 32; reg++) { 54 if (reg < 16) { 55 opcodes.Undefined(Reg::ArmFp(reg)); 56 } else { 57 opcodes.SameValue(Reg::ArmFp(reg)); 58 } 59 } 60 auto return_reg = Reg::ArmCore(14); // R14(LR). 61 WriteCIE(is64bit, return_reg, opcodes, format, buffer); 62 return; 63 } 64 case kArm64: { 65 dwarf::DebugFrameOpCodeWriter<> opcodes; 66 opcodes.DefCFA(Reg::Arm64Core(31), 0); // R31(SP). 67 // core registers. 68 for (int reg = 0; reg < 30; reg++) { 69 if (reg < 8 || reg == 16 || reg == 17) { 70 opcodes.Undefined(Reg::Arm64Core(reg)); 71 } else { 72 opcodes.SameValue(Reg::Arm64Core(reg)); 73 } 74 } 75 // fp registers. 76 for (int reg = 0; reg < 32; reg++) { 77 if (reg < 8 || reg >= 16) { 78 opcodes.Undefined(Reg::Arm64Fp(reg)); 79 } else { 80 opcodes.SameValue(Reg::Arm64Fp(reg)); 81 } 82 } 83 auto return_reg = Reg::Arm64Core(30); // R30(LR). 84 WriteCIE(is64bit, return_reg, opcodes, format, buffer); 85 return; 86 } 87 case kMips: 88 case kMips64: { 89 dwarf::DebugFrameOpCodeWriter<> opcodes; 90 opcodes.DefCFA(Reg::MipsCore(29), 0); // R29(SP). 91 // core registers. 92 for (int reg = 1; reg < 26; reg++) { 93 if (reg < 16 || reg == 24 || reg == 25) { // AT, V*, A*, T*. 94 opcodes.Undefined(Reg::MipsCore(reg)); 95 } else { 96 opcodes.SameValue(Reg::MipsCore(reg)); 97 } 98 } 99 // fp registers. 100 for (int reg = 0; reg < 32; reg++) { 101 if (reg < 24) { 102 opcodes.Undefined(Reg::Mips64Fp(reg)); 103 } else { 104 opcodes.SameValue(Reg::Mips64Fp(reg)); 105 } 106 } 107 auto return_reg = Reg::MipsCore(31); // R31(RA). 108 WriteCIE(is64bit, return_reg, opcodes, format, buffer); 109 return; 110 } 111 case kX86: { 112 // FIXME: Add fp registers once libunwind adds support for them. Bug: 20491296 113 constexpr bool generate_opcodes_for_x86_fp = false; 114 dwarf::DebugFrameOpCodeWriter<> opcodes; 115 opcodes.DefCFA(Reg::X86Core(4), 4); // R4(ESP). 116 opcodes.Offset(Reg::X86Core(8), -4); // R8(EIP). 117 // core registers. 118 for (int reg = 0; reg < 8; reg++) { 119 if (reg <= 3) { 120 opcodes.Undefined(Reg::X86Core(reg)); 121 } else if (reg == 4) { 122 // Stack pointer. 123 } else { 124 opcodes.SameValue(Reg::X86Core(reg)); 125 } 126 } 127 // fp registers. 128 if (generate_opcodes_for_x86_fp) { 129 for (int reg = 0; reg < 8; reg++) { 130 opcodes.Undefined(Reg::X86Fp(reg)); 131 } 132 } 133 auto return_reg = Reg::X86Core(8); // R8(EIP). 134 WriteCIE(is64bit, return_reg, opcodes, format, buffer); 135 return; 136 } 137 case kX86_64: { 138 dwarf::DebugFrameOpCodeWriter<> opcodes; 139 opcodes.DefCFA(Reg::X86_64Core(4), 8); // R4(RSP). 140 opcodes.Offset(Reg::X86_64Core(16), -8); // R16(RIP). 141 // core registers. 142 for (int reg = 0; reg < 16; reg++) { 143 if (reg == 4) { 144 // Stack pointer. 145 } else if (reg < 12 && reg != 3 && reg != 5) { // except EBX and EBP. 146 opcodes.Undefined(Reg::X86_64Core(reg)); 147 } else { 148 opcodes.SameValue(Reg::X86_64Core(reg)); 149 } 150 } 151 // fp registers. 152 for (int reg = 0; reg < 16; reg++) { 153 if (reg < 12) { 154 opcodes.Undefined(Reg::X86_64Fp(reg)); 155 } else { 156 opcodes.SameValue(Reg::X86_64Fp(reg)); 157 } 158 } 159 auto return_reg = Reg::X86_64Core(16); // R16(RIP). 160 WriteCIE(is64bit, return_reg, opcodes, format, buffer); 161 return; 162 } 163 case kNone: 164 break; 165 } 166 LOG(FATAL) << "Cannot write CIE frame for ISA " << isa; 167 UNREACHABLE(); 168} 169 170template<typename ElfTypes> 171void WriteCFISection(ElfBuilder<ElfTypes>* builder, 172 const ArrayRef<const MethodDebugInfo>& method_infos, 173 dwarf::CFIFormat format, 174 bool write_oat_patches) { 175 CHECK(format == dwarf::DW_DEBUG_FRAME_FORMAT || format == dwarf::DW_EH_FRAME_FORMAT); 176 typedef typename ElfTypes::Addr Elf_Addr; 177 178 // The methods can be written in any order. 179 // Let's therefore sort them in the lexicographical order of the opcodes. 180 // This has no effect on its own. However, if the final .debug_frame section is 181 // compressed it reduces the size since similar opcodes sequences are grouped. 182 std::vector<const MethodDebugInfo*> sorted_method_infos; 183 sorted_method_infos.reserve(method_infos.size()); 184 for (size_t i = 0; i < method_infos.size(); i++) { 185 if (!method_infos[i].cfi.empty() && !method_infos[i].deduped) { 186 sorted_method_infos.push_back(&method_infos[i]); 187 } 188 } 189 if (sorted_method_infos.empty()) { 190 return; 191 } 192 std::stable_sort( 193 sorted_method_infos.begin(), 194 sorted_method_infos.end(), 195 [](const MethodDebugInfo* lhs, const MethodDebugInfo* rhs) { 196 ArrayRef<const uint8_t> l = lhs->cfi; 197 ArrayRef<const uint8_t> r = rhs->cfi; 198 return std::lexicographical_compare(l.begin(), l.end(), r.begin(), r.end()); 199 }); 200 201 std::vector<uint32_t> binary_search_table; 202 std::vector<uintptr_t> patch_locations; 203 if (format == dwarf::DW_EH_FRAME_FORMAT) { 204 binary_search_table.reserve(2 * sorted_method_infos.size()); 205 } else { 206 patch_locations.reserve(sorted_method_infos.size()); 207 } 208 209 // Write .eh_frame/.debug_frame section. 210 auto* cfi_section = (format == dwarf::DW_DEBUG_FRAME_FORMAT 211 ? builder->GetDebugFrame() 212 : builder->GetEhFrame()); 213 { 214 cfi_section->Start(); 215 const bool is64bit = Is64BitInstructionSet(builder->GetIsa()); 216 const Elf_Addr cfi_address = cfi_section->GetAddress(); 217 const Elf_Addr cie_address = cfi_address; 218 Elf_Addr buffer_address = cfi_address; 219 std::vector<uint8_t> buffer; // Small temporary buffer. 220 WriteCIE(builder->GetIsa(), format, &buffer); 221 cfi_section->WriteFully(buffer.data(), buffer.size()); 222 buffer_address += buffer.size(); 223 buffer.clear(); 224 for (const MethodDebugInfo* mi : sorted_method_infos) { 225 DCHECK(!mi->deduped); 226 DCHECK(!mi->cfi.empty()); 227 const Elf_Addr code_address = mi->code_address + 228 (mi->is_code_address_text_relative ? builder->GetText()->GetAddress() : 0); 229 if (format == dwarf::DW_EH_FRAME_FORMAT) { 230 binary_search_table.push_back(dchecked_integral_cast<uint32_t>(code_address)); 231 binary_search_table.push_back(dchecked_integral_cast<uint32_t>(buffer_address)); 232 } 233 WriteFDE(is64bit, cfi_address, cie_address, 234 code_address, mi->code_size, 235 mi->cfi, format, buffer_address, &buffer, 236 &patch_locations); 237 cfi_section->WriteFully(buffer.data(), buffer.size()); 238 buffer_address += buffer.size(); 239 buffer.clear(); 240 } 241 cfi_section->End(); 242 } 243 244 if (format == dwarf::DW_EH_FRAME_FORMAT) { 245 auto* header_section = builder->GetEhFrameHdr(); 246 header_section->Start(); 247 uint32_t header_address = dchecked_integral_cast<int32_t>(header_section->GetAddress()); 248 // Write .eh_frame_hdr section. 249 std::vector<uint8_t> buffer; 250 dwarf::Writer<> header(&buffer); 251 header.PushUint8(1); // Version. 252 // Encoding of .eh_frame pointer - libunwind does not honor datarel here, 253 // so we have to use pcrel which means relative to the pointer's location. 254 header.PushUint8(dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4); 255 // Encoding of binary search table size. 256 header.PushUint8(dwarf::DW_EH_PE_udata4); 257 // Encoding of binary search table addresses - libunwind supports only this 258 // specific combination, which means relative to the start of .eh_frame_hdr. 259 header.PushUint8(dwarf::DW_EH_PE_datarel | dwarf::DW_EH_PE_sdata4); 260 // .eh_frame pointer 261 header.PushInt32(cfi_section->GetAddress() - (header_address + 4u)); 262 // Binary search table size (number of entries). 263 header.PushUint32(dchecked_integral_cast<uint32_t>(binary_search_table.size()/2)); 264 header_section->WriteFully(buffer.data(), buffer.size()); 265 // Binary search table. 266 for (size_t i = 0; i < binary_search_table.size(); i++) { 267 // Make addresses section-relative since we know the header address now. 268 binary_search_table[i] -= header_address; 269 } 270 header_section->WriteFully(binary_search_table.data(), binary_search_table.size()); 271 header_section->End(); 272 } else { 273 if (write_oat_patches) { 274 builder->WritePatches(".debug_frame.oat_patches", 275 ArrayRef<const uintptr_t>(patch_locations)); 276 } 277 } 278} 279 280} // namespace debug 281} // namespace art 282 283#endif // ART_COMPILER_DEBUG_ELF_DEBUG_FRAME_WRITER_H_ 284 285