ArchitectureMips.cpp revision 353358
1//===-- ArchitectureMips.cpp -------------------------------------*- C++ -*-===// 2// 3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4// See https://llvm.org/LICENSE.txt for license information. 5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6// 7//===----------------------------------------------------------------------===// 8 9#include "Plugins/Architecture/Mips/ArchitectureMips.h" 10#include "lldb/Core/Address.h" 11#include "lldb/Core/Disassembler.h" 12#include "lldb/Core/Module.h" 13#include "lldb/Core/PluginManager.h" 14#include "lldb/Symbol/Function.h" 15#include "lldb/Symbol/SymbolContext.h" 16#include "lldb/Target/SectionLoadList.h" 17#include "lldb/Target/Target.h" 18#include "lldb/Utility/ArchSpec.h" 19#include "lldb/Utility/Log.h" 20 21using namespace lldb_private; 22using namespace lldb; 23 24ConstString ArchitectureMips::GetPluginNameStatic() { 25 return ConstString("mips"); 26} 27 28void ArchitectureMips::Initialize() { 29 PluginManager::RegisterPlugin(GetPluginNameStatic(), 30 "Mips-specific algorithms", 31 &ArchitectureMips::Create); 32} 33 34void ArchitectureMips::Terminate() { 35 PluginManager::UnregisterPlugin(&ArchitectureMips::Create); 36} 37 38std::unique_ptr<Architecture> ArchitectureMips::Create(const ArchSpec &arch) { 39 return arch.IsMIPS() ? 40 std::unique_ptr<Architecture>(new ArchitectureMips(arch)) : nullptr; 41} 42 43ConstString ArchitectureMips::GetPluginName() { return GetPluginNameStatic(); } 44uint32_t ArchitectureMips::GetPluginVersion() { return 1; } 45 46addr_t ArchitectureMips::GetCallableLoadAddress(addr_t code_addr, 47 AddressClass addr_class) const { 48 bool is_alternate_isa = false; 49 50 switch (addr_class) { 51 case AddressClass::eData: 52 case AddressClass::eDebug: 53 return LLDB_INVALID_ADDRESS; 54 case AddressClass::eCodeAlternateISA: 55 is_alternate_isa = true; 56 break; 57 default: break; 58 } 59 60 if ((code_addr & 2ull) || is_alternate_isa) 61 return code_addr | 1u; 62 return code_addr; 63} 64 65addr_t ArchitectureMips::GetOpcodeLoadAddress(addr_t opcode_addr, 66 AddressClass addr_class) const { 67 switch (addr_class) { 68 case AddressClass::eData: 69 case AddressClass::eDebug: 70 return LLDB_INVALID_ADDRESS; 71 default: break; 72 } 73 return opcode_addr & ~(1ull); 74} 75 76lldb::addr_t ArchitectureMips::GetBreakableLoadAddress(lldb::addr_t addr, 77 Target &target) const { 78 79 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_BREAKPOINTS)); 80 81 Address resolved_addr; 82 83 SectionLoadList §ion_load_list = target.GetSectionLoadList(); 84 if (section_load_list.IsEmpty()) 85 // No sections are loaded, so we must assume we are not running yet and 86 // need to operate only on file address. 87 target.ResolveFileAddress(addr, resolved_addr); 88 else 89 target.ResolveLoadAddress(addr, resolved_addr); 90 91 addr_t current_offset = 0; 92 93 // Get the function boundaries to make sure we don't scan back before the 94 // beginning of the current function. 95 ModuleSP temp_addr_module_sp(resolved_addr.GetModule()); 96 if (temp_addr_module_sp) { 97 SymbolContext sc; 98 SymbolContextItem resolve_scope = 99 eSymbolContextFunction | eSymbolContextSymbol; 100 temp_addr_module_sp->ResolveSymbolContextForAddress(resolved_addr, 101 resolve_scope, sc); 102 Address sym_addr; 103 if (sc.function) 104 sym_addr = sc.function->GetAddressRange().GetBaseAddress(); 105 else if (sc.symbol) 106 sym_addr = sc.symbol->GetAddress(); 107 108 addr_t function_start = sym_addr.GetLoadAddress(&target); 109 if (function_start == LLDB_INVALID_ADDRESS) 110 function_start = sym_addr.GetFileAddress(); 111 112 if (function_start) 113 current_offset = addr - function_start; 114 } 115 116 // If breakpoint address is start of function then we dont have to do 117 // anything. 118 if (current_offset == 0) 119 return addr; 120 121 ExecutionContext ctx; 122 target.CalculateExecutionContext(ctx); 123 auto insn = GetInstructionAtAddress(ctx, current_offset, addr); 124 125 if (nullptr == insn || !insn->HasDelaySlot()) 126 return addr; 127 128 // Adjust the breakable address 129 uint64_t breakable_addr = addr - insn->GetOpcode().GetByteSize(); 130 if (log) 131 log->Printf("Target::%s Breakpoint at 0x%8.8" PRIx64 132 " is adjusted to 0x%8.8" PRIx64 " due to delay slot\n", 133 __FUNCTION__, addr, breakable_addr); 134 135 return breakable_addr; 136} 137 138Instruction *ArchitectureMips::GetInstructionAtAddress( 139 const ExecutionContext &exe_ctx, const Address &resolved_addr, 140 addr_t symbol_offset) const { 141 142 auto loop_count = symbol_offset / 2; 143 144 uint32_t arch_flags = m_arch.GetFlags(); 145 bool IsMips16 = arch_flags & ArchSpec::eMIPSAse_mips16; 146 bool IsMicromips = arch_flags & ArchSpec::eMIPSAse_micromips; 147 148 if (loop_count > 3) { 149 // Scan previous 6 bytes 150 if (IsMips16 | IsMicromips) 151 loop_count = 3; 152 // For mips-only, instructions are always 4 bytes, so scan previous 4 153 // bytes only. 154 else 155 loop_count = 2; 156 } 157 158 // Create Disassembler Instance 159 lldb::DisassemblerSP disasm_sp( 160 Disassembler::FindPlugin(m_arch, nullptr, nullptr)); 161 162 InstructionList instruction_list; 163 InstructionSP prev_insn; 164 bool prefer_file_cache = true; // Read from file 165 uint32_t inst_to_choose = 0; 166 167 Address addr = resolved_addr; 168 169 for (uint32_t i = 1; i <= loop_count; i++) { 170 // Adjust the address to read from. 171 addr.Slide(-2); 172 AddressRange range(addr, i * 2); 173 uint32_t insn_size = 0; 174 175 disasm_sp->ParseInstructions(&exe_ctx, range, nullptr, prefer_file_cache); 176 177 uint32_t num_insns = disasm_sp->GetInstructionList().GetSize(); 178 if (num_insns) { 179 prev_insn = disasm_sp->GetInstructionList().GetInstructionAtIndex(0); 180 insn_size = prev_insn->GetOpcode().GetByteSize(); 181 if (i == 1 && insn_size == 2) { 182 // This looks like a valid 2-byte instruction (but it could be a part 183 // of upper 4 byte instruction). 184 instruction_list.Append(prev_insn); 185 inst_to_choose = 1; 186 } 187 else if (i == 2) { 188 // Here we may get one 4-byte instruction or two 2-byte instructions. 189 if (num_insns == 2) { 190 // Looks like there are two 2-byte instructions above our 191 // breakpoint target address. Now the upper 2-byte instruction is 192 // either a valid 2-byte instruction or could be a part of it's 193 // upper 4-byte instruction. In both cases we don't care because in 194 // this case lower 2-byte instruction is definitely a valid 195 // instruction and whatever i=1 iteration has found out is true. 196 inst_to_choose = 1; 197 break; 198 } 199 else if (insn_size == 4) { 200 // This instruction claims its a valid 4-byte instruction. But it 201 // could be a part of it's upper 4-byte instruction. Lets try 202 // scanning upper 2 bytes to verify this. 203 instruction_list.Append(prev_insn); 204 inst_to_choose = 2; 205 } 206 } 207 else if (i == 3) { 208 if (insn_size == 4) 209 // FIXME: We reached here that means instruction at [target - 4] has 210 // already claimed to be a 4-byte instruction, and now instruction 211 // at [target - 6] is also claiming that it's a 4-byte instruction. 212 // This can not be true. In this case we can not decide the valid 213 // previous instruction so we let lldb set the breakpoint at the 214 // address given by user. 215 inst_to_choose = 0; 216 else 217 // This is straight-forward 218 inst_to_choose = 2; 219 break; 220 } 221 } 222 else { 223 // Decode failed, bytes do not form a valid instruction. So whatever 224 // previous iteration has found out is true. 225 if (i > 1) { 226 inst_to_choose = i - 1; 227 break; 228 } 229 } 230 } 231 232 // Check if we are able to find any valid instruction. 233 if (inst_to_choose) { 234 if (inst_to_choose > instruction_list.GetSize()) 235 inst_to_choose--; 236 return instruction_list.GetInstructionAtIndex(inst_to_choose - 1).get(); 237 } 238 239 return nullptr; 240} 241