LLDB mainline
ArchitectureMips.cpp
Go to the documentation of this file.
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
10#include "lldb/Core/Address.h"
12#include "lldb/Core/Module.h"
17#include "lldb/Target/Target.h"
20#include "lldb/Utility/Log.h"
21
22using namespace lldb_private;
23using namespace lldb;
24
26
27void ArchitectureMips::Initialize() {
28 PluginManager::RegisterPlugin(GetPluginNameStatic(),
29 "Mips-specific algorithms",
31}
32
35}
36
37std::unique_ptr<Architecture> ArchitectureMips::Create(const ArchSpec &arch) {
38 return arch.IsMIPS() ?
39 std::unique_ptr<Architecture>(new ArchitectureMips(arch)) : nullptr;
40}
41
43 AddressClass addr_class) const {
44 bool is_alternate_isa = false;
45
46 switch (addr_class) {
51 is_alternate_isa = true;
52 break;
53 default: break;
54 }
55
56 if ((code_addr & 2ull) || is_alternate_isa)
57 return code_addr | 1u;
58 return code_addr;
59}
60
62 AddressClass addr_class) const {
63 switch (addr_class) {
67 default: break;
68 }
69 return opcode_addr & ~(1ull);
70}
71
73 Target &target) const {
74
76
77 Address resolved_addr;
78
79 if (!target.HasLoadedSections())
80 // No sections are loaded, so we must assume we are not running yet and
81 // need to operate only on file address.
82 target.ResolveFileAddress(addr, resolved_addr);
83 else
84 target.ResolveLoadAddress(addr, resolved_addr);
85
86 addr_t current_offset = 0;
87
88 // Get the function boundaries to make sure we don't scan back before the
89 // beginning of the current function.
90 ModuleSP temp_addr_module_sp(resolved_addr.GetModule());
91 if (temp_addr_module_sp) {
93 SymbolContextItem resolve_scope =
94 eSymbolContextFunction | eSymbolContextSymbol;
95 temp_addr_module_sp->ResolveSymbolContextForAddress(resolved_addr,
96 resolve_scope, sc);
97 Address sym_addr;
98 if (sc.function)
99 sym_addr = sc.function->GetAddress();
100 else if (sc.symbol)
101 sym_addr = sc.symbol->GetAddress();
102
103 addr_t function_start = sym_addr.GetLoadAddress(&target);
104 if (function_start == LLDB_INVALID_ADDRESS)
105 function_start = sym_addr.GetFileAddress();
106
107 if (function_start)
108 current_offset = addr - function_start;
109 }
110
111 // If breakpoint address is start of function then we dont have to do
112 // anything.
113 if (current_offset == 0)
114 return addr;
115
116 auto insn = GetInstructionAtAddress(target, current_offset, addr);
117
118 if (nullptr == insn || !insn->HasDelaySlot())
119 return addr;
120
121 // Adjust the breakable address
122 uint64_t breakable_addr = addr - insn->GetOpcode().GetByteSize();
123 LLDB_LOGF(log,
124 "Target::%s Breakpoint at 0x%8.8" PRIx64
125 " is adjusted to 0x%8.8" PRIx64 " due to delay slot\n",
126 __FUNCTION__, addr, breakable_addr);
127
128 return breakable_addr;
129}
130
132 Target &target, const Address &resolved_addr, addr_t symbol_offset) const {
133
134 auto loop_count = symbol_offset / 2;
135
136 uint32_t arch_flags = m_arch.GetFlags();
137 bool IsMips16 = arch_flags & ArchSpec::eMIPSAse_mips16;
138 bool IsMicromips = arch_flags & ArchSpec::eMIPSAse_micromips;
139
140 if (loop_count > 3) {
141 // Scan previous 6 bytes
142 if (IsMips16 | IsMicromips)
143 loop_count = 3;
144 // For mips-only, instructions are always 4 bytes, so scan previous 4
145 // bytes only.
146 else
147 loop_count = 2;
148 }
149
150 // Create Disassembler Instance
151 lldb::DisassemblerSP disasm_sp(
152 Disassembler::FindPlugin(m_arch, nullptr, nullptr, nullptr, nullptr));
153
154 InstructionList instruction_list;
155 InstructionSP prev_insn;
156 uint32_t inst_to_choose = 0;
157
158 Address addr = resolved_addr;
159
160 for (uint32_t i = 1; i <= loop_count; i++) {
161 // Adjust the address to read from.
162 addr.Slide(-2);
163 uint32_t insn_size = 0;
164
165 disasm_sp->ParseInstructions(target, addr,
166 {Disassembler::Limit::Bytes, i * 2}, nullptr);
167
168 uint32_t num_insns = disasm_sp->GetInstructionList().GetSize();
169 if (num_insns) {
170 prev_insn = disasm_sp->GetInstructionList().GetInstructionAtIndex(0);
171 insn_size = prev_insn->GetOpcode().GetByteSize();
172 if (i == 1 && insn_size == 2) {
173 // This looks like a valid 2-byte instruction (but it could be a part
174 // of upper 4 byte instruction).
175 instruction_list.Append(prev_insn);
176 inst_to_choose = 1;
177 }
178 else if (i == 2) {
179 // Here we may get one 4-byte instruction or two 2-byte instructions.
180 if (num_insns == 2) {
181 // Looks like there are two 2-byte instructions above our
182 // breakpoint target address. Now the upper 2-byte instruction is
183 // either a valid 2-byte instruction or could be a part of it's
184 // upper 4-byte instruction. In both cases we don't care because in
185 // this case lower 2-byte instruction is definitely a valid
186 // instruction and whatever i=1 iteration has found out is true.
187 inst_to_choose = 1;
188 break;
189 }
190 else if (insn_size == 4) {
191 // This instruction claims its a valid 4-byte instruction. But it
192 // could be a part of it's upper 4-byte instruction. Lets try
193 // scanning upper 2 bytes to verify this.
194 instruction_list.Append(prev_insn);
195 inst_to_choose = 2;
196 }
197 }
198 else if (i == 3) {
199 if (insn_size == 4)
200 // FIXME: We reached here that means instruction at [target - 4] has
201 // already claimed to be a 4-byte instruction, and now instruction
202 // at [target - 6] is also claiming that it's a 4-byte instruction.
203 // This can not be true. In this case we can not decide the valid
204 // previous instruction so we let lldb set the breakpoint at the
205 // address given by user.
206 inst_to_choose = 0;
207 else
208 // This is straight-forward
209 inst_to_choose = 2;
210 break;
211 }
212 }
213 else {
214 // Decode failed, bytes do not form a valid instruction. So whatever
215 // previous iteration has found out is true.
216 if (i > 1) {
217 inst_to_choose = i - 1;
218 break;
219 }
220 }
221 }
222
223 // Check if we are able to find any valid instruction.
224 if (inst_to_choose) {
225 if (inst_to_choose > instruction_list.GetSize())
226 inst_to_choose--;
227 return instruction_list.GetInstructionAtIndex(inst_to_choose - 1).get();
228 }
229
230 return nullptr;
231}
#define LLDB_LOGF(log,...)
Definition: Log.h:376
#define LLDB_PLUGIN_DEFINE(PluginName)
Definition: PluginManager.h:32
A section + offset based address class.
Definition: Address.h:62
lldb::addr_t GetLoadAddress(Target *target) const
Get the load address.
Definition: Address.cpp:312
bool Slide(int64_t offset)
Definition: Address.h:459
lldb::ModuleSP GetModule() const
Get accessor for the module for this address.
Definition: Address.cpp:284
lldb::addr_t GetFileAddress() const
Get the file address.
Definition: Address.cpp:292
An architecture specification class.
Definition: ArchSpec.h:31
bool IsMIPS() const
if MIPS architecture return true.
Definition: ArchSpec.cpp:580
uint32_t GetFlags() const
Definition: ArchSpec.h:534
lldb::addr_t GetOpcodeLoadAddress(lldb::addr_t load_addr, AddressClass addr_class) const override
Get load_addr as an opcode for this target.
Instruction * GetInstructionAtAddress(Target &target, const Address &resolved_addr, lldb::addr_t symbol_offset) const
static std::unique_ptr< Architecture > Create(const ArchSpec &arch)
lldb::addr_t GetBreakableLoadAddress(lldb::addr_t addr, Target &) const override
lldb::addr_t GetCallableLoadAddress(lldb::addr_t load_addr, AddressClass addr_class) const override
Get load_addr as a callable code load address for this target.
static lldb::DisassemblerSP FindPlugin(const ArchSpec &arch, const char *flavor, const char *cpu, const char *features, const char *plugin_name)
const Address & GetAddress() const
Return the address of the function (its entry point).
Definition: Function.h:455
void Append(lldb::InstructionSP &inst_sp)
lldb::InstructionSP GetInstructionAtIndex(size_t idx) const
static bool RegisterPlugin(llvm::StringRef name, llvm::StringRef description, ABICreateInstance create_callback)
static bool UnregisterPlugin(ABICreateInstance create_callback)
Defines a symbol context baton that can be handed other debug core functions.
Definition: SymbolContext.h:34
Function * function
The Function for a given query.
Symbol * symbol
The Symbol for a given query.
Address GetAddress() const
Definition: Symbol.h:88
bool ResolveFileAddress(lldb::addr_t load_addr, Address &so_addr)
Definition: Target.cpp:3231
bool HasLoadedSections()
Definition: Target.cpp:5158
bool ResolveLoadAddress(lldb::addr_t load_addr, Address &so_addr, uint32_t stop_id=SectionLoadHistory::eStopIDNow, bool allow_section_end=false)
Definition: Target.cpp:3225
#define LLDB_INVALID_ADDRESS
Definition: lldb-defines.h:82
A class that represents a running process on the host machine.
Log * GetLog(Cat mask)
Retrieve the Log object for the channel associated with the given log enum.
Definition: Log.h:332
Definition: SBAddress.h:15
std::shared_ptr< lldb_private::Instruction > InstructionSP
Definition: lldb-forward.h:358
std::shared_ptr< lldb_private::Disassembler > DisassemblerSP
Definition: lldb-forward.h:341
uint64_t addr_t
Definition: lldb-types.h:80
std::shared_ptr< lldb_private::Module > ModuleSP
Definition: lldb-forward.h:373