1c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky/* 2c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky * Copyright (C) 2016 The Android Open Source Project 3c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky * 4c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky * Licensed under the Apache License, Version 2.0 (the "License"); 5c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky * you may not use this file except in compliance with the License. 6c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky * You may obtain a copy of the License at 7c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky * 8c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky * http://www.apache.org/licenses/LICENSE-2.0 9c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky * 10c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky * Unless required by applicable law or agreed to in writing, software 11c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky * distributed under the License is distributed on an "AS IS" BASIS, 12c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky * See the License for the specific language governing permissions and 14c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky * limitations under the License. 15c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky */ 16c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky 17c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky#ifndef ART_COMPILER_DEBUG_ELF_DEBUG_LOC_WRITER_H_ 18c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky#define ART_COMPILER_DEBUG_ELF_DEBUG_LOC_WRITER_H_ 19c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky 20b396c735e0de984ab0dcbeed06765c75a75e8352David Srbecky#include <cstring> 21c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky#include <map> 22c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky 23c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky#include "arch/instruction_set.h" 24c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky#include "compiled_method.h" 25c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky#include "debug/dwarf/debug_info_entry_writer.h" 26c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky#include "debug/dwarf/register.h" 27c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky#include "debug/method_debug_info.h" 28c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky#include "stack_map.h" 29c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky 30c5bfa97c47d656b76f297af8abcd5f7502987399David Srbeckynamespace art { 31c5bfa97c47d656b76f297af8abcd5f7502987399David Srbeckynamespace debug { 32c5bfa97c47d656b76f297af8abcd5f7502987399David Srbeckyusing Reg = dwarf::Reg; 33c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky 34c5bfa97c47d656b76f297af8abcd5f7502987399David Srbeckystatic Reg GetDwarfCoreReg(InstructionSet isa, int machine_reg) { 35c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky switch (isa) { 36c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky case kArm: 37c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky case kThumb2: 38c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky return Reg::ArmCore(machine_reg); 39c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky case kArm64: 40c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky return Reg::Arm64Core(machine_reg); 41c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky case kX86: 42c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky return Reg::X86Core(machine_reg); 43c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky case kX86_64: 44c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky return Reg::X86_64Core(machine_reg); 45c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky case kMips: 46c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky return Reg::MipsCore(machine_reg); 47c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky case kMips64: 48c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky return Reg::Mips64Core(machine_reg); 49c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky case kNone: 50c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky LOG(FATAL) << "No instruction set"; 51c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky } 52c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky UNREACHABLE(); 53c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky} 54c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky 55c5bfa97c47d656b76f297af8abcd5f7502987399David Srbeckystatic Reg GetDwarfFpReg(InstructionSet isa, int machine_reg) { 56c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky switch (isa) { 57c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky case kArm: 58c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky case kThumb2: 59c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky return Reg::ArmFp(machine_reg); 60c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky case kArm64: 61c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky return Reg::Arm64Fp(machine_reg); 62c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky case kX86: 63c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky return Reg::X86Fp(machine_reg); 64c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky case kX86_64: 65c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky return Reg::X86_64Fp(machine_reg); 66c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky case kMips: 67c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky return Reg::MipsFp(machine_reg); 68c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky case kMips64: 69c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky return Reg::Mips64Fp(machine_reg); 70c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky case kNone: 71c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky LOG(FATAL) << "No instruction set"; 72c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky } 73c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky UNREACHABLE(); 74c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky} 75c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky 76c5bfa97c47d656b76f297af8abcd5f7502987399David Srbeckystruct VariableLocation { 77197160d47f34238cb5e7444fa4c2de300db8e2c6David Srbecky uint32_t low_pc; // Relative to compilation unit. 78197160d47f34238cb5e7444fa4c2de300db8e2c6David Srbecky uint32_t high_pc; // Relative to compilation unit. 79c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky DexRegisterLocation reg_lo; // May be None if the location is unknown. 80c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky DexRegisterLocation reg_hi; // Most significant bits of 64-bit value. 81c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky}; 82c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky 83c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky// Get the location of given dex register (e.g. stack or machine register). 84c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky// Note that the location might be different based on the current pc. 85c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky// The result will cover all ranges where the variable is in scope. 86bfd26cdd6f8273618a3a3137ada579b03f96ae82David Srbecky// PCs corresponding to stackmap with dex register map are accurate, 87bfd26cdd6f8273618a3a3137ada579b03f96ae82David Srbecky// all other PCs are best-effort only. 882ed15b61105b0f8ce811c32725bb9a1b6142c3a7David Srbeckystd::vector<VariableLocation> GetVariableLocations( 892ed15b61105b0f8ce811c32725bb9a1b6142c3a7David Srbecky const MethodDebugInfo* method_info, 902ed15b61105b0f8ce811c32725bb9a1b6142c3a7David Srbecky const std::vector<DexRegisterMap>& dex_register_maps, 912ed15b61105b0f8ce811c32725bb9a1b6142c3a7David Srbecky uint16_t vreg, 922ed15b61105b0f8ce811c32725bb9a1b6142c3a7David Srbecky bool is64bitValue, 93197160d47f34238cb5e7444fa4c2de300db8e2c6David Srbecky uint64_t compilation_unit_code_address, 942ed15b61105b0f8ce811c32725bb9a1b6142c3a7David Srbecky uint32_t dex_pc_low, 952ed15b61105b0f8ce811c32725bb9a1b6142c3a7David Srbecky uint32_t dex_pc_high) { 96c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky std::vector<VariableLocation> variable_locations; 97c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky 98c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky // Get stack maps sorted by pc (they might not be sorted internally). 99d89f605b1de929ae158b3844e44a5d57f7aad72dDavid Srbecky // TODO(dsrbecky) Remove this once stackmaps get sorted by pc. 100197160d47f34238cb5e7444fa4c2de300db8e2c6David Srbecky const CodeInfo code_info(method_info->code_info); 10109ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky const CodeInfoEncoding encoding = code_info.ExtractEncoding(); 1022ed15b61105b0f8ce811c32725bb9a1b6142c3a7David Srbecky std::map<uint32_t, uint32_t> stack_maps; // low_pc -> stack_map_index. 10309ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky for (uint32_t s = 0; s < code_info.GetNumberOfStackMaps(encoding); s++) { 104c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky StackMap stack_map = code_info.GetStackMapAt(s, encoding); 105c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky DCHECK(stack_map.IsValid()); 10609ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky if (!stack_map.HasDexRegisterMap(encoding.stack_map_encoding)) { 107d89f605b1de929ae158b3844e44a5d57f7aad72dDavid Srbecky // The compiler creates stackmaps without register maps at the start of 108d89f605b1de929ae158b3844e44a5d57f7aad72dDavid Srbecky // basic blocks in order to keep instruction-accurate line number mapping. 109d89f605b1de929ae158b3844e44a5d57f7aad72dDavid Srbecky // However, we never stop at those (breakpoint locations always have map). 110d89f605b1de929ae158b3844e44a5d57f7aad72dDavid Srbecky // Therefore, for the purpose of local variables, we ignore them. 111d89f605b1de929ae158b3844e44a5d57f7aad72dDavid Srbecky // The main reason for this is to save space by avoiding undefined gaps. 112d89f605b1de929ae158b3844e44a5d57f7aad72dDavid Srbecky continue; 113d89f605b1de929ae158b3844e44a5d57f7aad72dDavid Srbecky } 11409ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky const uint32_t pc_offset = stack_map.GetNativePcOffset(encoding.stack_map_encoding); 115197160d47f34238cb5e7444fa4c2de300db8e2c6David Srbecky DCHECK_LE(pc_offset, method_info->code_size); 116197160d47f34238cb5e7444fa4c2de300db8e2c6David Srbecky DCHECK_LE(compilation_unit_code_address, method_info->code_address); 117197160d47f34238cb5e7444fa4c2de300db8e2c6David Srbecky const uint32_t low_pc = dchecked_integral_cast<uint32_t>( 118197160d47f34238cb5e7444fa4c2de300db8e2c6David Srbecky method_info->code_address + pc_offset - compilation_unit_code_address); 1192ed15b61105b0f8ce811c32725bb9a1b6142c3a7David Srbecky stack_maps.emplace(low_pc, s); 120c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky } 121c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky 122c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky // Create entries for the requested register based on stack map data. 123c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky for (auto it = stack_maps.begin(); it != stack_maps.end(); it++) { 124c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky const uint32_t low_pc = it->first; 1252ed15b61105b0f8ce811c32725bb9a1b6142c3a7David Srbecky const uint32_t stack_map_index = it->second; 1262ed15b61105b0f8ce811c32725bb9a1b6142c3a7David Srbecky const StackMap& stack_map = code_info.GetStackMapAt(stack_map_index, encoding); 127c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky auto next_it = it; 128c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky next_it++; 129197160d47f34238cb5e7444fa4c2de300db8e2c6David Srbecky const uint32_t high_pc = next_it != stack_maps.end() 130197160d47f34238cb5e7444fa4c2de300db8e2c6David Srbecky ? next_it->first 131197160d47f34238cb5e7444fa4c2de300db8e2c6David Srbecky : method_info->code_address + method_info->code_size - compilation_unit_code_address; 132c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky DCHECK_LE(low_pc, high_pc); 133c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky if (low_pc == high_pc) { 134c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky continue; // Ignore if the address range is empty. 135c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky } 136c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky 137c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky // Check that the stack map is in the requested range. 13809ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky uint32_t dex_pc = stack_map.GetDexPc(encoding.stack_map_encoding); 139c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky if (!(dex_pc_low <= dex_pc && dex_pc < dex_pc_high)) { 140d89f605b1de929ae158b3844e44a5d57f7aad72dDavid Srbecky // The variable is not in scope at this PC. Therefore omit the entry. 141d89f605b1de929ae158b3844e44a5d57f7aad72dDavid Srbecky // Note that this is different to None() entry which means in scope, but unknown location. 142c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky continue; 143c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky } 144c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky 145c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky // Find the location of the dex register. 146c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky DexRegisterLocation reg_lo = DexRegisterLocation::None(); 147c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky DexRegisterLocation reg_hi = DexRegisterLocation::None(); 1482ed15b61105b0f8ce811c32725bb9a1b6142c3a7David Srbecky DCHECK_LT(stack_map_index, dex_register_maps.size()); 1492ed15b61105b0f8ce811c32725bb9a1b6142c3a7David Srbecky DexRegisterMap dex_register_map = dex_register_maps[stack_map_index]; 150d89f605b1de929ae158b3844e44a5d57f7aad72dDavid Srbecky DCHECK(dex_register_map.IsValid()); 151d89f605b1de929ae158b3844e44a5d57f7aad72dDavid Srbecky reg_lo = dex_register_map.GetDexRegisterLocation( 152d89f605b1de929ae158b3844e44a5d57f7aad72dDavid Srbecky vreg, method_info->code_item->registers_size_, code_info, encoding); 153d89f605b1de929ae158b3844e44a5d57f7aad72dDavid Srbecky if (is64bitValue) { 154d89f605b1de929ae158b3844e44a5d57f7aad72dDavid Srbecky reg_hi = dex_register_map.GetDexRegisterLocation( 155d89f605b1de929ae158b3844e44a5d57f7aad72dDavid Srbecky vreg + 1, method_info->code_item->registers_size_, code_info, encoding); 156c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky } 157c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky 158c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky // Add location entry for this address range. 159c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky if (!variable_locations.empty() && 160c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky variable_locations.back().reg_lo == reg_lo && 161c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky variable_locations.back().reg_hi == reg_hi && 162c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky variable_locations.back().high_pc == low_pc) { 163c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky // Merge with the previous entry (extend its range). 164c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky variable_locations.back().high_pc = high_pc; 165c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky } else { 166c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky variable_locations.push_back({low_pc, high_pc, reg_lo, reg_hi}); 167c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky } 168c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky } 169c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky 170c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky return variable_locations; 171c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky} 172c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky 173c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky// Write table into .debug_loc which describes location of dex register. 174c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky// The dex register might be valid only at some points and it might 175c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky// move between machine registers and stack. 176c5bfa97c47d656b76f297af8abcd5f7502987399David Srbeckystatic void WriteDebugLocEntry(const MethodDebugInfo* method_info, 1772ed15b61105b0f8ce811c32725bb9a1b6142c3a7David Srbecky const std::vector<DexRegisterMap>& dex_register_maps, 178c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky uint16_t vreg, 179c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky bool is64bitValue, 180197160d47f34238cb5e7444fa4c2de300db8e2c6David Srbecky uint64_t compilation_unit_code_address, 181c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky uint32_t dex_pc_low, 182c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky uint32_t dex_pc_high, 183c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky InstructionSet isa, 184c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky dwarf::DebugInfoEntryWriter<>* debug_info, 185c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky std::vector<uint8_t>* debug_loc_buffer, 186c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky std::vector<uint8_t>* debug_ranges_buffer) { 187c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky using Kind = DexRegisterLocation::Kind; 188197160d47f34238cb5e7444fa4c2de300db8e2c6David Srbecky if (method_info->code_info == nullptr || dex_register_maps.empty()) { 189c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky return; 190c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky } 191c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky 192c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky std::vector<VariableLocation> variable_locations = GetVariableLocations( 193c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky method_info, 1942ed15b61105b0f8ce811c32725bb9a1b6142c3a7David Srbecky dex_register_maps, 195c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky vreg, 196c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky is64bitValue, 197197160d47f34238cb5e7444fa4c2de300db8e2c6David Srbecky compilation_unit_code_address, 198c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky dex_pc_low, 199c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky dex_pc_high); 200c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky 201c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky // Write .debug_loc entries. 202b396c735e0de984ab0dcbeed06765c75a75e8352David Srbecky dwarf::Writer<> debug_loc(debug_loc_buffer); 203b396c735e0de984ab0dcbeed06765c75a75e8352David Srbecky const size_t debug_loc_offset = debug_loc.size(); 204c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky const bool is64bit = Is64BitInstructionSet(isa); 205c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky std::vector<uint8_t> expr_buffer; 206c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky for (const VariableLocation& variable_location : variable_locations) { 207c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky // Translate dex register location to DWARF expression. 208c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky // Note that 64-bit value might be split to two distinct locations. 209c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky // (for example, two 32-bit machine registers, or even stack and register) 210c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky dwarf::Expression expr(&expr_buffer); 211c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky DexRegisterLocation reg_lo = variable_location.reg_lo; 212c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky DexRegisterLocation reg_hi = variable_location.reg_hi; 213c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky for (int piece = 0; piece < (is64bitValue ? 2 : 1); piece++) { 214c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky DexRegisterLocation reg_loc = (piece == 0 ? reg_lo : reg_hi); 215c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky const Kind kind = reg_loc.GetKind(); 216c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky const int32_t value = reg_loc.GetValue(); 217c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky if (kind == Kind::kInStack) { 218c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky // The stack offset is relative to SP. Make it relative to CFA. 219197160d47f34238cb5e7444fa4c2de300db8e2c6David Srbecky expr.WriteOpFbreg(value - method_info->frame_size_in_bytes); 220c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky if (piece == 0 && reg_hi.GetKind() == Kind::kInStack && 221c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky reg_hi.GetValue() == value + 4) { 222c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky break; // the high word is correctly implied by the low word. 223c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky } 224c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky } else if (kind == Kind::kInRegister) { 225c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky expr.WriteOpReg(GetDwarfCoreReg(isa, value).num()); 226c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky if (piece == 0 && reg_hi.GetKind() == Kind::kInRegisterHigh && 227c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky reg_hi.GetValue() == value) { 228c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky break; // the high word is correctly implied by the low word. 229c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky } 230c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky } else if (kind == Kind::kInFpuRegister) { 231c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky if ((isa == kArm || isa == kThumb2) && 232c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky piece == 0 && reg_hi.GetKind() == Kind::kInFpuRegister && 233c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky reg_hi.GetValue() == value + 1 && value % 2 == 0) { 234c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky // Translate S register pair to D register (e.g. S4+S5 to D2). 235c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky expr.WriteOpReg(Reg::ArmDp(value / 2).num()); 236c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky break; 237c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky } 238c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky expr.WriteOpReg(GetDwarfFpReg(isa, value).num()); 239c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky if (piece == 0 && reg_hi.GetKind() == Kind::kInFpuRegisterHigh && 240c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky reg_hi.GetValue() == reg_lo.GetValue()) { 241c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky break; // the high word is correctly implied by the low word. 242c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky } 243c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky } else if (kind == Kind::kConstant) { 244c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky expr.WriteOpConsts(value); 245c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky expr.WriteOpStackValue(); 246c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky } else if (kind == Kind::kNone) { 247c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky break; 248c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky } else { 249c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky // kInStackLargeOffset and kConstantLargeValue are hidden by GetKind(). 250c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky // kInRegisterHigh and kInFpuRegisterHigh should be handled by 251c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky // the special cases above and they should not occur alone. 2527dc11782ff0a5dffcd8108f256f8975f0b3e8076David Srbecky LOG(ERROR) << "Unexpected register location kind: " << kind; 253c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky break; 254c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky } 255c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky if (is64bitValue) { 256c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky // Write the marker which is needed by split 64-bit values. 257c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky // This code is skipped by the special cases. 258c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky expr.WriteOpPiece(4); 259c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky } 260c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky } 261c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky 262c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky if (expr.size() > 0) { 263c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky if (is64bit) { 264197160d47f34238cb5e7444fa4c2de300db8e2c6David Srbecky debug_loc.PushUint64(variable_location.low_pc); 265197160d47f34238cb5e7444fa4c2de300db8e2c6David Srbecky debug_loc.PushUint64(variable_location.high_pc); 266c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky } else { 267197160d47f34238cb5e7444fa4c2de300db8e2c6David Srbecky debug_loc.PushUint32(variable_location.low_pc); 268197160d47f34238cb5e7444fa4c2de300db8e2c6David Srbecky debug_loc.PushUint32(variable_location.high_pc); 269c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky } 270c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky // Write the expression. 271c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky debug_loc.PushUint16(expr.size()); 272c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky debug_loc.PushData(expr.data()); 273c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky } else { 274c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky // Do not generate .debug_loc if the location is not known. 275c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky } 276c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky } 277c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky // Write end-of-list entry. 278c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky if (is64bit) { 279c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky debug_loc.PushUint64(0); 280c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky debug_loc.PushUint64(0); 281c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky } else { 282c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky debug_loc.PushUint32(0); 283c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky debug_loc.PushUint32(0); 284c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky } 285c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky 286c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky // Write .debug_ranges entries. 287c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky // This includes ranges where the variable is in scope but the location is not known. 288b396c735e0de984ab0dcbeed06765c75a75e8352David Srbecky dwarf::Writer<> debug_ranges(debug_ranges_buffer); 289b396c735e0de984ab0dcbeed06765c75a75e8352David Srbecky size_t debug_ranges_offset = debug_ranges.size(); 290c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky for (size_t i = 0; i < variable_locations.size(); i++) { 291c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky uint32_t low_pc = variable_locations[i].low_pc; 292c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky uint32_t high_pc = variable_locations[i].high_pc; 293c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky while (i + 1 < variable_locations.size() && variable_locations[i+1].low_pc == high_pc) { 294c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky // Merge address range with the next entry. 295c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky high_pc = variable_locations[++i].high_pc; 296c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky } 297c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky if (is64bit) { 298197160d47f34238cb5e7444fa4c2de300db8e2c6David Srbecky debug_ranges.PushUint64(low_pc); 299197160d47f34238cb5e7444fa4c2de300db8e2c6David Srbecky debug_ranges.PushUint64(high_pc); 300c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky } else { 301197160d47f34238cb5e7444fa4c2de300db8e2c6David Srbecky debug_ranges.PushUint32(low_pc); 302197160d47f34238cb5e7444fa4c2de300db8e2c6David Srbecky debug_ranges.PushUint32(high_pc); 303c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky } 304c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky } 305c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky // Write end-of-list entry. 306c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky if (is64bit) { 307c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky debug_ranges.PushUint64(0); 308c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky debug_ranges.PushUint64(0); 309c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky } else { 310c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky debug_ranges.PushUint32(0); 311c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky debug_ranges.PushUint32(0); 312c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky } 313b396c735e0de984ab0dcbeed06765c75a75e8352David Srbecky 314b396c735e0de984ab0dcbeed06765c75a75e8352David Srbecky // Simple de-duplication - check whether this entry is same as the last one (or tail of it). 315b396c735e0de984ab0dcbeed06765c75a75e8352David Srbecky size_t debug_ranges_entry_size = debug_ranges.size() - debug_ranges_offset; 316b396c735e0de984ab0dcbeed06765c75a75e8352David Srbecky if (debug_ranges_offset >= debug_ranges_entry_size) { 317b396c735e0de984ab0dcbeed06765c75a75e8352David Srbecky size_t previous_offset = debug_ranges_offset - debug_ranges_entry_size; 318b396c735e0de984ab0dcbeed06765c75a75e8352David Srbecky if (memcmp(debug_ranges_buffer->data() + previous_offset, 319b396c735e0de984ab0dcbeed06765c75a75e8352David Srbecky debug_ranges_buffer->data() + debug_ranges_offset, 320b396c735e0de984ab0dcbeed06765c75a75e8352David Srbecky debug_ranges_entry_size) == 0) { 321b396c735e0de984ab0dcbeed06765c75a75e8352David Srbecky // Remove what we have just written and use the last entry instead. 322b396c735e0de984ab0dcbeed06765c75a75e8352David Srbecky debug_ranges_buffer->resize(debug_ranges_offset); 323b396c735e0de984ab0dcbeed06765c75a75e8352David Srbecky debug_ranges_offset = previous_offset; 324b396c735e0de984ab0dcbeed06765c75a75e8352David Srbecky } 325b396c735e0de984ab0dcbeed06765c75a75e8352David Srbecky } 326b396c735e0de984ab0dcbeed06765c75a75e8352David Srbecky 327b396c735e0de984ab0dcbeed06765c75a75e8352David Srbecky // Write attributes to .debug_info. 328b396c735e0de984ab0dcbeed06765c75a75e8352David Srbecky debug_info->WriteSecOffset(dwarf::DW_AT_location, debug_loc_offset); 329b396c735e0de984ab0dcbeed06765c75a75e8352David Srbecky debug_info->WriteSecOffset(dwarf::DW_AT_start_scope, debug_ranges_offset); 330c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky} 331c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky 332c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky} // namespace debug 333c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky} // namespace art 334c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky 335c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky#endif // ART_COMPILER_DEBUG_ELF_DEBUG_LOC_WRITER_H_ 336c5bfa97c47d656b76f297af8abcd5f7502987399David Srbecky 337