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