1 //===-- ArchitectureMips.cpp ----------------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
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"
22 using namespace lldb_private
;
25 LLDB_PLUGIN_DEFINE(ArchitectureMips
)
27 void ArchitectureMips::Initialize() {
28 PluginManager::RegisterPlugin(GetPluginNameStatic(),
29 "Mips-specific algorithms",
30 &ArchitectureMips::Create
);
33 void ArchitectureMips::Terminate() {
34 PluginManager::UnregisterPlugin(&ArchitectureMips::Create
);
37 std::unique_ptr
<Architecture
> ArchitectureMips::Create(const ArchSpec
&arch
) {
38 return arch
.IsMIPS() ?
39 std::unique_ptr
<Architecture
>(new ArchitectureMips(arch
)) : nullptr;
42 addr_t
ArchitectureMips::GetCallableLoadAddress(addr_t code_addr
,
43 AddressClass addr_class
) const {
44 bool is_alternate_isa
= false;
47 case AddressClass::eData
:
48 case AddressClass::eDebug
:
49 return LLDB_INVALID_ADDRESS
;
50 case AddressClass::eCodeAlternateISA
:
51 is_alternate_isa
= true;
56 if ((code_addr
& 2ull) || is_alternate_isa
)
57 return code_addr
| 1u;
61 addr_t
ArchitectureMips::GetOpcodeLoadAddress(addr_t opcode_addr
,
62 AddressClass addr_class
) const {
64 case AddressClass::eData
:
65 case AddressClass::eDebug
:
66 return LLDB_INVALID_ADDRESS
;
69 return opcode_addr
& ~(1ull);
72 lldb::addr_t
ArchitectureMips::GetBreakableLoadAddress(lldb::addr_t addr
,
73 Target
&target
) const {
75 Log
*log
= GetLog(LLDBLog::Breakpoints
);
77 Address resolved_addr
;
79 SectionLoadList
§ion_load_list
= target
.GetSectionLoadList();
80 if (section_load_list
.IsEmpty())
81 // No sections are loaded, so we must assume we are not running yet and
82 // need to operate only on file address.
83 target
.ResolveFileAddress(addr
, resolved_addr
);
85 target
.ResolveLoadAddress(addr
, resolved_addr
);
87 addr_t current_offset
= 0;
89 // Get the function boundaries to make sure we don't scan back before the
90 // beginning of the current function.
91 ModuleSP
temp_addr_module_sp(resolved_addr
.GetModule());
92 if (temp_addr_module_sp
) {
94 SymbolContextItem resolve_scope
=
95 eSymbolContextFunction
| eSymbolContextSymbol
;
96 temp_addr_module_sp
->ResolveSymbolContextForAddress(resolved_addr
,
100 sym_addr
= sc
.function
->GetAddressRange().GetBaseAddress();
102 sym_addr
= sc
.symbol
->GetAddress();
104 addr_t function_start
= sym_addr
.GetLoadAddress(&target
);
105 if (function_start
== LLDB_INVALID_ADDRESS
)
106 function_start
= sym_addr
.GetFileAddress();
109 current_offset
= addr
- function_start
;
112 // If breakpoint address is start of function then we dont have to do
114 if (current_offset
== 0)
117 auto insn
= GetInstructionAtAddress(target
, current_offset
, addr
);
119 if (nullptr == insn
|| !insn
->HasDelaySlot())
122 // Adjust the breakable address
123 uint64_t breakable_addr
= addr
- insn
->GetOpcode().GetByteSize();
125 "Target::%s Breakpoint at 0x%8.8" PRIx64
126 " is adjusted to 0x%8.8" PRIx64
" due to delay slot\n",
127 __FUNCTION__
, addr
, breakable_addr
);
129 return breakable_addr
;
132 Instruction
*ArchitectureMips::GetInstructionAtAddress(
133 Target
&target
, const Address
&resolved_addr
, addr_t symbol_offset
) const {
135 auto loop_count
= symbol_offset
/ 2;
137 uint32_t arch_flags
= m_arch
.GetFlags();
138 bool IsMips16
= arch_flags
& ArchSpec::eMIPSAse_mips16
;
139 bool IsMicromips
= arch_flags
& ArchSpec::eMIPSAse_micromips
;
141 if (loop_count
> 3) {
142 // Scan previous 6 bytes
143 if (IsMips16
| IsMicromips
)
145 // For mips-only, instructions are always 4 bytes, so scan previous 4
151 // Create Disassembler Instance
152 lldb::DisassemblerSP
disasm_sp(
153 Disassembler::FindPlugin(m_arch
, nullptr, nullptr, nullptr, nullptr));
155 InstructionList instruction_list
;
156 InstructionSP prev_insn
;
157 uint32_t inst_to_choose
= 0;
159 Address addr
= resolved_addr
;
161 for (uint32_t i
= 1; i
<= loop_count
; i
++) {
162 // Adjust the address to read from.
164 uint32_t insn_size
= 0;
166 disasm_sp
->ParseInstructions(target
, addr
,
167 {Disassembler::Limit::Bytes
, i
* 2}, nullptr);
169 uint32_t num_insns
= disasm_sp
->GetInstructionList().GetSize();
171 prev_insn
= disasm_sp
->GetInstructionList().GetInstructionAtIndex(0);
172 insn_size
= prev_insn
->GetOpcode().GetByteSize();
173 if (i
== 1 && insn_size
== 2) {
174 // This looks like a valid 2-byte instruction (but it could be a part
175 // of upper 4 byte instruction).
176 instruction_list
.Append(prev_insn
);
180 // Here we may get one 4-byte instruction or two 2-byte instructions.
181 if (num_insns
== 2) {
182 // Looks like there are two 2-byte instructions above our
183 // breakpoint target address. Now the upper 2-byte instruction is
184 // either a valid 2-byte instruction or could be a part of it's
185 // upper 4-byte instruction. In both cases we don't care because in
186 // this case lower 2-byte instruction is definitely a valid
187 // instruction and whatever i=1 iteration has found out is true.
191 else if (insn_size
== 4) {
192 // This instruction claims its a valid 4-byte instruction. But it
193 // could be a part of it's upper 4-byte instruction. Lets try
194 // scanning upper 2 bytes to verify this.
195 instruction_list
.Append(prev_insn
);
201 // FIXME: We reached here that means instruction at [target - 4] has
202 // already claimed to be a 4-byte instruction, and now instruction
203 // at [target - 6] is also claiming that it's a 4-byte instruction.
204 // This can not be true. In this case we can not decide the valid
205 // previous instruction so we let lldb set the breakpoint at the
206 // address given by user.
209 // This is straight-forward
215 // Decode failed, bytes do not form a valid instruction. So whatever
216 // previous iteration has found out is true.
218 inst_to_choose
= i
- 1;
224 // Check if we are able to find any valid instruction.
225 if (inst_to_choose
) {
226 if (inst_to_choose
> instruction_list
.GetSize())
228 return instruction_list
.GetInstructionAtIndex(inst_to_choose
- 1).get();