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