1 //===-- ArchitectureMips.cpp -------------------------------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
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"
22 using namespace lldb_private;
25 ConstString ArchitectureMips::GetPluginNameStatic() {
26 return ConstString("mips");
29 void ArchitectureMips::Initialize() {
30 PluginManager::RegisterPlugin(GetPluginNameStatic(),
31 "Mips-specific algorithms",
32 &ArchitectureMips::Create);
35 void ArchitectureMips::Terminate() {
36 PluginManager::UnregisterPlugin(&ArchitectureMips::Create);
39 std::unique_ptr<Architecture> ArchitectureMips::Create(const ArchSpec &arch) {
40 return arch.IsMIPS() ?
41 std::unique_ptr<Architecture>(new ArchitectureMips(arch)) : nullptr;
44 ConstString ArchitectureMips::GetPluginName() { return GetPluginNameStatic(); }
45 uint32_t ArchitectureMips::GetPluginVersion() { return 1; }
47 addr_t ArchitectureMips::GetCallableLoadAddress(addr_t code_addr,
48 AddressClass addr_class) const {
49 bool is_alternate_isa = false;
52 case AddressClass::eData:
53 case AddressClass::eDebug:
54 return LLDB_INVALID_ADDRESS;
55 case AddressClass::eCodeAlternateISA:
56 is_alternate_isa = true;
61 if ((code_addr & 2ull) || is_alternate_isa)
62 return code_addr | 1u;
66 addr_t ArchitectureMips::GetOpcodeLoadAddress(addr_t opcode_addr,
67 AddressClass addr_class) const {
69 case AddressClass::eData:
70 case AddressClass::eDebug:
71 return LLDB_INVALID_ADDRESS;
74 return opcode_addr & ~(1ull);
77 lldb::addr_t ArchitectureMips::GetBreakableLoadAddress(lldb::addr_t addr,
78 Target &target) const {
80 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_BREAKPOINTS));
82 Address resolved_addr;
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);
90 target.ResolveLoadAddress(addr, resolved_addr);
92 addr_t current_offset = 0;
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) {
99 SymbolContextItem resolve_scope =
100 eSymbolContextFunction | eSymbolContextSymbol;
101 temp_addr_module_sp->ResolveSymbolContextForAddress(resolved_addr,
105 sym_addr = sc.function->GetAddressRange().GetBaseAddress();
107 sym_addr = sc.symbol->GetAddress();
109 addr_t function_start = sym_addr.GetLoadAddress(&target);
110 if (function_start == LLDB_INVALID_ADDRESS)
111 function_start = sym_addr.GetFileAddress();
114 current_offset = addr - function_start;
117 // If breakpoint address is start of function then we dont have to do
119 if (current_offset == 0)
122 ExecutionContext ctx;
123 target.CalculateExecutionContext(ctx);
124 auto insn = GetInstructionAtAddress(ctx, current_offset, addr);
126 if (nullptr == insn || !insn->HasDelaySlot())
129 // Adjust the breakable address
130 uint64_t breakable_addr = addr - insn->GetOpcode().GetByteSize();
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);
136 return breakable_addr;
139 Instruction *ArchitectureMips::GetInstructionAtAddress(
140 const ExecutionContext &exe_ctx, const Address &resolved_addr,
141 addr_t symbol_offset) const {
143 auto loop_count = symbol_offset / 2;
145 uint32_t arch_flags = m_arch.GetFlags();
146 bool IsMips16 = arch_flags & ArchSpec::eMIPSAse_mips16;
147 bool IsMicromips = arch_flags & ArchSpec::eMIPSAse_micromips;
149 if (loop_count > 3) {
150 // Scan previous 6 bytes
151 if (IsMips16 | IsMicromips)
153 // For mips-only, instructions are always 4 bytes, so scan previous 4
159 // Create Disassembler Instance
160 lldb::DisassemblerSP disasm_sp(
161 Disassembler::FindPlugin(m_arch, nullptr, nullptr));
163 InstructionList instruction_list;
164 InstructionSP prev_insn;
165 bool prefer_file_cache = true; // Read from file
166 uint32_t inst_to_choose = 0;
168 Address addr = resolved_addr;
170 for (uint32_t i = 1; i <= loop_count; i++) {
171 // Adjust the address to read from.
173 AddressRange range(addr, i * 2);
174 uint32_t insn_size = 0;
176 disasm_sp->ParseInstructions(&exe_ctx, range, nullptr, prefer_file_cache);
178 uint32_t num_insns = disasm_sp->GetInstructionList().GetSize();
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);
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.
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);
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.
218 // This is straight-forward
224 // Decode failed, bytes do not form a valid instruction. So whatever
225 // previous iteration has found out is true.
227 inst_to_choose = i - 1;
233 // Check if we are able to find any valid instruction.
234 if (inst_to_choose) {
235 if (inst_to_choose > instruction_list.GetSize())
237 return instruction_list.GetInstructionAtIndex(inst_to_choose - 1).get();