ArchitectureMips.cpp revision 343181
1122394Sharti//===-- ArchitectureMips.cpp -------------------------------------*- C++ -*-===// 2122394Sharti// 3122394Sharti// The LLVM Compiler Infrastructure 4122394Sharti// 5122394Sharti// This file is distributed under the University of Illinois Open Source 6122394Sharti// License. See LICENSE.TXT for details. 7216594Ssyrinx// 8216594Ssyrinx//===----------------------------------------------------------------------===// 9216594Ssyrinx 10216594Ssyrinx#include "Plugins/Architecture/Mips/ArchitectureMips.h" 11216594Ssyrinx#include "lldb/Core/Address.h" 12216594Ssyrinx#include "lldb/Core/Disassembler.h" 13216594Ssyrinx#include "lldb/Core/Module.h" 14133211Sharti#include "lldb/Core/PluginManager.h" 15133211Sharti#include "lldb/Symbol/Function.h" 16133211Sharti#include "lldb/Symbol/SymbolContext.h" 17133211Sharti#include "lldb/Target/SectionLoadList.h" 18133211Sharti#include "lldb/Target/Target.h" 19122394Sharti#include "lldb/Utility/ArchSpec.h" 20122394Sharti#include "lldb/Utility/Log.h" 21122394Sharti 22133211Shartiusing namespace lldb_private; 23133211Shartiusing namespace lldb; 24133211Sharti 25133211ShartiConstString ArchitectureMips::GetPluginNameStatic() { 26133211Sharti return ConstString("mips"); 27133211Sharti} 28133211Sharti 29133211Shartivoid ArchitectureMips::Initialize() { 30133211Sharti PluginManager::RegisterPlugin(GetPluginNameStatic(), 31133211Sharti "Mips-specific algorithms", 32133211Sharti &ArchitectureMips::Create); 33133211Sharti} 34122394Sharti 35150920Shartivoid ArchitectureMips::Terminate() { 36122394Sharti PluginManager::UnregisterPlugin(&ArchitectureMips::Create); 37122394Sharti} 38122394Sharti 39122394Shartistd::unique_ptr<Architecture> ArchitectureMips::Create(const ArchSpec &arch) { 40216294Ssyrinx return arch.IsMIPS() ? 41122394Sharti std::unique_ptr<Architecture>(new ArchitectureMips(arch)) : nullptr; 42122394Sharti} 43216594Ssyrinx 44122394ShartiConstString ArchitectureMips::GetPluginName() { return GetPluginNameStatic(); } 45122394Shartiuint32_t ArchitectureMips::GetPluginVersion() { return 1; } 46122394Sharti 47122394Shartiaddr_t ArchitectureMips::GetCallableLoadAddress(addr_t code_addr, 48122394Sharti AddressClass addr_class) const { 49122394Sharti bool is_alternate_isa = false; 50122394Sharti 51122394Sharti switch (addr_class) { 52122394Sharti case AddressClass::eData: 53122394Sharti case AddressClass::eDebug: 54122394Sharti return LLDB_INVALID_ADDRESS; 55122394Sharti case AddressClass::eCodeAlternateISA: 56122394Sharti is_alternate_isa = true; 57122394Sharti break; 58122394Sharti default: break; 59122394Sharti } 60122394Sharti 61122394Sharti if ((code_addr & 2ull) || is_alternate_isa) 62216594Ssyrinx return code_addr | 1u; 63216594Ssyrinx return code_addr; 64216594Ssyrinx} 65216594Ssyrinx 66216594Ssyrinxaddr_t ArchitectureMips::GetOpcodeLoadAddress(addr_t opcode_addr, 67216594Ssyrinx AddressClass addr_class) const { 68216594Ssyrinx switch (addr_class) { 69216594Ssyrinx case AddressClass::eData: 70216594Ssyrinx case AddressClass::eDebug: 71216594Ssyrinx return LLDB_INVALID_ADDRESS; 72216594Ssyrinx default: break; 73216594Ssyrinx } 74122394Sharti return opcode_addr & ~(1ull); 75122394Sharti} 76122394Sharti 77122394Shartilldb::addr_t ArchitectureMips::GetBreakableLoadAddress(lldb::addr_t addr, 78122394Sharti Target &target) const { 79122394Sharti 80122394Sharti Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_BREAKPOINTS)); 81122394Sharti 82122394Sharti Address resolved_addr; 83122394Sharti 84122394Sharti SectionLoadList §ion_load_list = target.GetSectionLoadList(); 85122394Sharti if (section_load_list.IsEmpty()) 86122394Sharti // No sections are loaded, so we must assume we are not running yet and 87122394Sharti // need to operate only on file address. 88122394Sharti target.ResolveFileAddress(addr, resolved_addr); 89122394Sharti else 90122394Sharti target.ResolveLoadAddress(addr, resolved_addr); 91122394Sharti 92122394Sharti addr_t current_offset = 0; 93122394Sharti 94122394Sharti // Get the function boundaries to make sure we don't scan back before the 95122394Sharti // beginning of the current function. 96122394Sharti ModuleSP temp_addr_module_sp(resolved_addr.GetModule()); 97122394Sharti if (temp_addr_module_sp) { 98122394Sharti SymbolContext sc; 99122394Sharti SymbolContextItem resolve_scope = 100122394Sharti eSymbolContextFunction | eSymbolContextSymbol; 101122394Sharti temp_addr_module_sp->ResolveSymbolContextForAddress(resolved_addr, 102122394Sharti resolve_scope, sc); 103122394Sharti Address sym_addr; 104122394Sharti if (sc.function) 105122394Sharti sym_addr = sc.function->GetAddressRange().GetBaseAddress(); 106122394Sharti else if (sc.symbol) 107122394Sharti sym_addr = sc.symbol->GetAddress(); 108122394Sharti 109122394Sharti addr_t function_start = sym_addr.GetLoadAddress(&target); 110122394Sharti if (function_start == LLDB_INVALID_ADDRESS) 111122394Sharti function_start = sym_addr.GetFileAddress(); 112122394Sharti 113122394Sharti if (function_start) 114122394Sharti current_offset = addr - function_start; 115122394Sharti } 116122394Sharti 117122394Sharti // If breakpoint address is start of function then we dont have to do 118122394Sharti // anything. 119122394Sharti if (current_offset == 0) 120122394Sharti return addr; 121122394Sharti 122122394Sharti ExecutionContext ctx; 123122394Sharti target.CalculateExecutionContext(ctx); 124122394Sharti auto insn = GetInstructionAtAddress(ctx, current_offset, addr); 125122394Sharti 126122394Sharti if (nullptr == insn || !insn->HasDelaySlot()) 127122394Sharti return addr; 128122394Sharti 129122394Sharti // Adjust the breakable address 130150920Sharti uint64_t breakable_addr = addr - insn->GetOpcode().GetByteSize(); 131122394Sharti if (log) 132122394Sharti log->Printf("Target::%s Breakpoint at 0x%8.8" PRIx64 133122394Sharti " is adjusted to 0x%8.8" PRIx64 " due to delay slot\n", 134122394Sharti __FUNCTION__, addr, breakable_addr); 135122394Sharti 136122394Sharti return breakable_addr; 137122394Sharti} 138122394Sharti 139122394ShartiInstruction *ArchitectureMips::GetInstructionAtAddress( 140122394Sharti const ExecutionContext &exe_ctx, const Address &resolved_addr, 141122394Sharti addr_t symbol_offset) const { 142122394Sharti 143122394Sharti auto loop_count = symbol_offset / 2; 144122394Sharti 145122394Sharti uint32_t arch_flags = m_arch.GetFlags(); 146122394Sharti bool IsMips16 = arch_flags & ArchSpec::eMIPSAse_mips16; 147122394Sharti bool IsMicromips = arch_flags & ArchSpec::eMIPSAse_micromips; 148122394Sharti 149122394Sharti if (loop_count > 3) { 150122394Sharti // Scan previous 6 bytes 151122394Sharti if (IsMips16 | IsMicromips) 152122394Sharti loop_count = 3; 153122394Sharti // For mips-only, instructions are always 4 bytes, so scan previous 4 154122394Sharti // bytes only. 155122394Sharti else 156122394Sharti loop_count = 2; 157122394Sharti } 158122394Sharti 159122394Sharti // Create Disassembler Instance 160122394Sharti lldb::DisassemblerSP disasm_sp( 161122394Sharti Disassembler::FindPlugin(m_arch, nullptr, nullptr)); 162122394Sharti 163122394Sharti InstructionList instruction_list; 164122394Sharti InstructionSP prev_insn; 165122394Sharti bool prefer_file_cache = true; // Read from file 166122394Sharti uint32_t inst_to_choose = 0; 167122394Sharti 168122394Sharti Address addr = resolved_addr; 169122394Sharti 170122394Sharti for (uint32_t i = 1; i <= loop_count; i++) { 171122394Sharti // Adjust the address to read from. 172122394Sharti addr.Slide(-2); 173122394Sharti AddressRange range(addr, i * 2); 174122394Sharti uint32_t insn_size = 0; 175122394Sharti 176122394Sharti disasm_sp->ParseInstructions(&exe_ctx, range, nullptr, prefer_file_cache); 177122394Sharti 178122394Sharti uint32_t num_insns = disasm_sp->GetInstructionList().GetSize(); 179122394Sharti if (num_insns) { 180122394Sharti prev_insn = disasm_sp->GetInstructionList().GetInstructionAtIndex(0); 181122394Sharti insn_size = prev_insn->GetOpcode().GetByteSize(); 182122394Sharti if (i == 1 && insn_size == 2) { 183122394Sharti // This looks like a valid 2-byte instruction (but it could be a part 184122394Sharti // of upper 4 byte instruction). 185122394Sharti instruction_list.Append(prev_insn); 186122394Sharti inst_to_choose = 1; 187122394Sharti } 188122394Sharti else if (i == 2) { 189122394Sharti // Here we may get one 4-byte instruction or two 2-byte instructions. 190122394Sharti if (num_insns == 2) { 191122394Sharti // Looks like there are two 2-byte instructions above our 192122394Sharti // breakpoint target address. Now the upper 2-byte instruction is 193122394Sharti // either a valid 2-byte instruction or could be a part of it's 194122394Sharti // upper 4-byte instruction. In both cases we don't care because in 195122394Sharti // this case lower 2-byte instruction is definitely a valid 196122394Sharti // instruction and whatever i=1 iteration has found out is true. 197122394Sharti inst_to_choose = 1; 198122394Sharti break; 199122394Sharti } 200122394Sharti else if (insn_size == 4) { 201122394Sharti // This instruction claims its a valid 4-byte instruction. But it 202122394Sharti // could be a part of it's upper 4-byte instruction. Lets try 203122394Sharti // scanning upper 2 bytes to verify this. 204122394Sharti instruction_list.Append(prev_insn); 205122394Sharti inst_to_choose = 2; 206122394Sharti } 207122394Sharti } 208122394Sharti else if (i == 3) { 209122394Sharti if (insn_size == 4) 210122394Sharti // FIXME: We reached here that means instruction at [target - 4] has 211122394Sharti // already claimed to be a 4-byte instruction, and now instruction 212122394Sharti // at [target - 6] is also claiming that it's a 4-byte instruction. 213122394Sharti // This can not be true. In this case we can not decide the valid 214122394Sharti // previous instruction so we let lldb set the breakpoint at the 215122394Sharti // address given by user. 216122394Sharti inst_to_choose = 0; 217122394Sharti else 218122394Sharti // This is straight-forward 219122394Sharti inst_to_choose = 2; 220122394Sharti break; 221122394Sharti } 222128237Sharti } 223122394Sharti else { 224122394Sharti // Decode failed, bytes do not form a valid instruction. So whatever 225122394Sharti // previous iteration has found out is true. 226122394Sharti if (i > 1) { 227122394Sharti inst_to_choose = i - 1; 228122394Sharti break; 229122394Sharti } 230122394Sharti } 231122394Sharti } 232122394Sharti 233122394Sharti // Check if we are able to find any valid instruction. 234122394Sharti if (inst_to_choose) { 235122394Sharti if (inst_to_choose > instruction_list.GetSize()) 236122394Sharti inst_to_choose--; 237122394Sharti return instruction_list.GetInstructionAtIndex(inst_to_choose - 1).get(); 238122394Sharti } 239122394Sharti 240122394Sharti return nullptr; 241122394Sharti} 242122394Sharti