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