Path: blob/main/contrib/llvm-project/lldb/source/Plugins/Architecture/Mips/ArchitectureMips.cpp
39644 views
//===-- ArchitectureMips.cpp ----------------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "Plugins/Architecture/Mips/ArchitectureMips.h"9#include "lldb/Core/Address.h"10#include "lldb/Core/Disassembler.h"11#include "lldb/Core/Module.h"12#include "lldb/Core/PluginManager.h"13#include "lldb/Symbol/Function.h"14#include "lldb/Symbol/SymbolContext.h"15#include "lldb/Target/SectionLoadList.h"16#include "lldb/Target/Target.h"17#include "lldb/Utility/ArchSpec.h"18#include "lldb/Utility/LLDBLog.h"19#include "lldb/Utility/Log.h"2021using namespace lldb_private;22using namespace lldb;2324LLDB_PLUGIN_DEFINE(ArchitectureMips)2526void ArchitectureMips::Initialize() {27PluginManager::RegisterPlugin(GetPluginNameStatic(),28"Mips-specific algorithms",29&ArchitectureMips::Create);30}3132void ArchitectureMips::Terminate() {33PluginManager::UnregisterPlugin(&ArchitectureMips::Create);34}3536std::unique_ptr<Architecture> ArchitectureMips::Create(const ArchSpec &arch) {37return arch.IsMIPS() ?38std::unique_ptr<Architecture>(new ArchitectureMips(arch)) : nullptr;39}4041addr_t ArchitectureMips::GetCallableLoadAddress(addr_t code_addr,42AddressClass addr_class) const {43bool is_alternate_isa = false;4445switch (addr_class) {46case AddressClass::eData:47case AddressClass::eDebug:48return LLDB_INVALID_ADDRESS;49case AddressClass::eCodeAlternateISA:50is_alternate_isa = true;51break;52default: break;53}5455if ((code_addr & 2ull) || is_alternate_isa)56return code_addr | 1u;57return code_addr;58}5960addr_t ArchitectureMips::GetOpcodeLoadAddress(addr_t opcode_addr,61AddressClass addr_class) const {62switch (addr_class) {63case AddressClass::eData:64case AddressClass::eDebug:65return LLDB_INVALID_ADDRESS;66default: break;67}68return opcode_addr & ~(1ull);69}7071lldb::addr_t ArchitectureMips::GetBreakableLoadAddress(lldb::addr_t addr,72Target &target) const {7374Log *log = GetLog(LLDBLog::Breakpoints);7576Address resolved_addr;7778SectionLoadList §ion_load_list = target.GetSectionLoadList();79if (section_load_list.IsEmpty())80// No sections are loaded, so we must assume we are not running yet and81// need to operate only on file address.82target.ResolveFileAddress(addr, resolved_addr);83else84target.ResolveLoadAddress(addr, resolved_addr);8586addr_t current_offset = 0;8788// Get the function boundaries to make sure we don't scan back before the89// beginning of the current function.90ModuleSP temp_addr_module_sp(resolved_addr.GetModule());91if (temp_addr_module_sp) {92SymbolContext sc;93SymbolContextItem resolve_scope =94eSymbolContextFunction | eSymbolContextSymbol;95temp_addr_module_sp->ResolveSymbolContextForAddress(resolved_addr,96resolve_scope, sc);97Address sym_addr;98if (sc.function)99sym_addr = sc.function->GetAddressRange().GetBaseAddress();100else if (sc.symbol)101sym_addr = sc.symbol->GetAddress();102103addr_t function_start = sym_addr.GetLoadAddress(&target);104if (function_start == LLDB_INVALID_ADDRESS)105function_start = sym_addr.GetFileAddress();106107if (function_start)108current_offset = addr - function_start;109}110111// If breakpoint address is start of function then we dont have to do112// anything.113if (current_offset == 0)114return addr;115116auto insn = GetInstructionAtAddress(target, current_offset, addr);117118if (nullptr == insn || !insn->HasDelaySlot())119return addr;120121// Adjust the breakable address122uint64_t breakable_addr = addr - insn->GetOpcode().GetByteSize();123LLDB_LOGF(log,124"Target::%s Breakpoint at 0x%8.8" PRIx64125" is adjusted to 0x%8.8" PRIx64 " due to delay slot\n",126__FUNCTION__, addr, breakable_addr);127128return breakable_addr;129}130131Instruction *ArchitectureMips::GetInstructionAtAddress(132Target &target, const Address &resolved_addr, addr_t symbol_offset) const {133134auto loop_count = symbol_offset / 2;135136uint32_t arch_flags = m_arch.GetFlags();137bool IsMips16 = arch_flags & ArchSpec::eMIPSAse_mips16;138bool IsMicromips = arch_flags & ArchSpec::eMIPSAse_micromips;139140if (loop_count > 3) {141// Scan previous 6 bytes142if (IsMips16 | IsMicromips)143loop_count = 3;144// For mips-only, instructions are always 4 bytes, so scan previous 4145// bytes only.146else147loop_count = 2;148}149150// Create Disassembler Instance151lldb::DisassemblerSP disasm_sp(152Disassembler::FindPlugin(m_arch, nullptr, nullptr));153154InstructionList instruction_list;155InstructionSP prev_insn;156uint32_t inst_to_choose = 0;157158Address addr = resolved_addr;159160for (uint32_t i = 1; i <= loop_count; i++) {161// Adjust the address to read from.162addr.Slide(-2);163uint32_t insn_size = 0;164165disasm_sp->ParseInstructions(target, addr,166{Disassembler::Limit::Bytes, i * 2}, nullptr);167168uint32_t num_insns = disasm_sp->GetInstructionList().GetSize();169if (num_insns) {170prev_insn = disasm_sp->GetInstructionList().GetInstructionAtIndex(0);171insn_size = prev_insn->GetOpcode().GetByteSize();172if (i == 1 && insn_size == 2) {173// This looks like a valid 2-byte instruction (but it could be a part174// of upper 4 byte instruction).175instruction_list.Append(prev_insn);176inst_to_choose = 1;177}178else if (i == 2) {179// Here we may get one 4-byte instruction or two 2-byte instructions.180if (num_insns == 2) {181// Looks like there are two 2-byte instructions above our182// breakpoint target address. Now the upper 2-byte instruction is183// either a valid 2-byte instruction or could be a part of it's184// upper 4-byte instruction. In both cases we don't care because in185// this case lower 2-byte instruction is definitely a valid186// instruction and whatever i=1 iteration has found out is true.187inst_to_choose = 1;188break;189}190else if (insn_size == 4) {191// This instruction claims its a valid 4-byte instruction. But it192// could be a part of it's upper 4-byte instruction. Lets try193// scanning upper 2 bytes to verify this.194instruction_list.Append(prev_insn);195inst_to_choose = 2;196}197}198else if (i == 3) {199if (insn_size == 4)200// FIXME: We reached here that means instruction at [target - 4] has201// already claimed to be a 4-byte instruction, and now instruction202// at [target - 6] is also claiming that it's a 4-byte instruction.203// This can not be true. In this case we can not decide the valid204// previous instruction so we let lldb set the breakpoint at the205// address given by user.206inst_to_choose = 0;207else208// This is straight-forward209inst_to_choose = 2;210break;211}212}213else {214// Decode failed, bytes do not form a valid instruction. So whatever215// previous iteration has found out is true.216if (i > 1) {217inst_to_choose = i - 1;218break;219}220}221}222223// Check if we are able to find any valid instruction.224if (inst_to_choose) {225if (inst_to_choose > instruction_list.GetSize())226inst_to_choose--;227return instruction_list.GetInstructionAtIndex(inst_to_choose - 1).get();228}229230return nullptr;231}232233234