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
22#include "llvm/Support/Endian.h"
23
24using namespace lldb_private;
25using namespace lldb;
26
28
34
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
45 AddressClass addr_class) const {
46 bool is_alternate_isa = false;
47
48 switch (addr_class) {
53 is_alternate_isa = true;
54 break;
55 default: break;
56 }
57
58 if ((code_addr & 2ull) || is_alternate_isa)
59 return code_addr | 1u;
60 return code_addr;
61}
62
64 AddressClass addr_class) const {
65 switch (addr_class) {
69 default: break;
70 }
71 return opcode_addr & ~(1ull);
72}
73
75 Target &target) const {
76
78
79 Address resolved_addr;
80
81 if (!target.HasLoadedSections())
82 // No sections are loaded, so we must assume we are not running yet and
83 // need to operate only on file address.
84 target.ResolveFileAddress(addr, resolved_addr);
85 else
86 target.ResolveLoadAddress(addr, resolved_addr);
87
88 addr_t current_offset = 0;
89
90 // Get the function boundaries to make sure we don't scan back before the
91 // beginning of the current function.
92 ModuleSP temp_addr_module_sp(resolved_addr.GetModule());
93 if (temp_addr_module_sp) {
95 SymbolContextItem resolve_scope =
96 eSymbolContextFunction | eSymbolContextSymbol;
97 temp_addr_module_sp->ResolveSymbolContextForAddress(resolved_addr,
98 resolve_scope, sc);
99 Address sym_addr;
100 if (sc.function)
101 sym_addr = sc.function->GetAddress();
102 else if (sc.symbol)
103 sym_addr = sc.symbol->GetAddress();
104
105 addr_t function_start = sym_addr.GetLoadAddress(&target);
106 if (function_start == LLDB_INVALID_ADDRESS)
107 function_start = sym_addr.GetFileAddress();
108
109 if (function_start)
110 current_offset = addr - function_start;
111 }
112
113 // If breakpoint address is start of function then we dont have to do
114 // anything.
115 if (current_offset == 0)
116 return addr;
117
118 auto insn = GetInstructionAtAddress(target, Address(current_offset), addr);
119
120 if (nullptr == insn || !insn->HasDelaySlot())
121 return addr;
122
123 // Adjust the breakable address
124 uint64_t breakable_addr = addr - insn->GetOpcode().GetByteSize();
125 LLDB_LOGF(log,
126 "Target::%s Breakpoint at 0x%8.8" PRIx64
127 " is adjusted to 0x%8.8" PRIx64 " due to delay slot\n",
128 __FUNCTION__, addr, breakable_addr);
129
130 return breakable_addr;
131}
132
134 Target &target, const Address &resolved_addr, addr_t symbol_offset) const {
135
136 auto loop_count = symbol_offset / 2;
137
138 uint32_t arch_flags = m_arch.GetFlags();
139 bool IsMips16 = arch_flags & ArchSpec::eMIPSAse_mips16;
140 bool IsMicromips = arch_flags & ArchSpec::eMIPSAse_micromips;
141
142 if (loop_count > 3) {
143 // Scan previous 6 bytes
144 if (IsMips16 | IsMicromips)
145 loop_count = 3;
146 // For mips-only, instructions are always 4 bytes, so scan previous 4
147 // bytes only.
148 else
149 loop_count = 2;
150 }
151
152 // Create Disassembler Instance
153 lldb::DisassemblerSP disasm_sp(
154 Disassembler::FindPlugin(m_arch, nullptr, nullptr, nullptr, nullptr));
155
156 InstructionList instruction_list;
157 InstructionSP prev_insn;
158 uint32_t inst_to_choose = 0;
159
160 Address addr = resolved_addr;
161
162 for (uint32_t i = 1; i <= loop_count; i++) {
163 // Adjust the address to read from.
164 addr.Slide(-2);
165 uint32_t insn_size = 0;
166
167 disasm_sp->ParseInstructions(target, addr,
168 {Disassembler::Limit::Bytes, i * 2}, nullptr);
169
170 uint32_t num_insns = disasm_sp->GetInstructionList().GetSize();
171 if (num_insns) {
172 prev_insn = disasm_sp->GetInstructionList().GetInstructionAtIndex(0);
173 insn_size = prev_insn->GetOpcode().GetByteSize();
174 if (i == 1 && insn_size == 2) {
175 // This looks like a valid 2-byte instruction (but it could be a part
176 // of upper 4 byte instruction).
177 instruction_list.Append(prev_insn);
178 inst_to_choose = 1;
179 }
180 else if (i == 2) {
181 // Here we may get one 4-byte instruction or two 2-byte instructions.
182 if (num_insns == 2) {
183 // Looks like there are two 2-byte instructions above our
184 // breakpoint target address. Now the upper 2-byte instruction is
185 // either a valid 2-byte instruction or could be a part of it's
186 // upper 4-byte instruction. In both cases we don't care because in
187 // this case lower 2-byte instruction is definitely a valid
188 // instruction and whatever i=1 iteration has found out is true.
189 inst_to_choose = 1;
190 break;
191 }
192 else if (insn_size == 4) {
193 // This instruction claims its a valid 4-byte instruction. But it
194 // could be a part of it's upper 4-byte instruction. Lets try
195 // scanning upper 2 bytes to verify this.
196 instruction_list.Append(prev_insn);
197 inst_to_choose = 2;
198 }
199 }
200 else if (i == 3) {
201 if (insn_size == 4)
202 // FIXME: We reached here that means instruction at [target - 4] has
203 // already claimed to be a 4-byte instruction, and now instruction
204 // at [target - 6] is also claiming that it's a 4-byte instruction.
205 // This can not be true. In this case we can not decide the valid
206 // previous instruction so we let lldb set the breakpoint at the
207 // address given by user.
208 inst_to_choose = 0;
209 else
210 // This is straight-forward
211 inst_to_choose = 2;
212 break;
213 }
214 }
215 else {
216 // Decode failed, bytes do not form a valid instruction. So whatever
217 // previous iteration has found out is true.
218 if (i > 1) {
219 inst_to_choose = i - 1;
220 break;
221 }
222 }
223 }
224
225 // Check if we are able to find any valid instruction.
226 if (inst_to_choose) {
227 if (inst_to_choose > instruction_list.GetSize())
228 inst_to_choose--;
229 return instruction_list.GetInstructionAtIndex(inst_to_choose - 1).get();
230 }
231
232 return nullptr;
233}
234
236 llvm::ArrayRef<uint8_t> reference, llvm::ArrayRef<uint8_t> observed) const {
237 // The middle twenty bits of BREAK can be anything, so zero them
238 uint32_t mask = 0xFC00003F;
239 auto ref_bytes = llvm::support::endian::read32le(reference.data());
240 auto bytes = llvm::support::endian::read32le(observed.data());
241 return (ref_bytes & mask) == (bytes & mask);
242}
#define LLDB_LOGF(log,...)
Definition Log.h:378
#define LLDB_PLUGIN_DEFINE(PluginName)
A section + offset based address class.
Definition Address.h:62
lldb::addr_t GetLoadAddress(Target *target) const
Get the load address.
Definition Address.cpp:301
bool Slide(int64_t offset)
Definition Address.h:452
lldb::ModuleSP GetModule() const
Get accessor for the module for this address.
Definition Address.cpp:273
lldb::addr_t GetFileAddress() const
Get the file address.
Definition Address.cpp:281
An architecture specification class.
Definition ArchSpec.h:32
bool IsMIPS() const
if MIPS architecture return true.
Definition ArchSpec.cpp:564
lldb::addr_t GetOpcodeLoadAddress(lldb::addr_t load_addr, AddressClass addr_class) const override
Get load_addr as an opcode for this target.
static llvm::StringRef GetPluginNameStatic()
bool IsValidTrapInstruction(llvm::ArrayRef< uint8_t > reference, llvm::ArrayRef< uint8_t > observed) const override
Returns whether a given byte sequence is a valid trap instruction for the architecture.
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.
ArchitectureMips(const ArchSpec &arch)
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:445
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.
Function * function
The Function for a given query.
Symbol * symbol
The Symbol for a given query.
Address GetAddress() const
Definition Symbol.h:89
bool ResolveFileAddress(lldb::addr_t load_addr, Address &so_addr)
Definition Target.cpp:3454
bool ResolveLoadAddress(lldb::addr_t load_addr, Address &so_addr, uint32_t stop_id=SectionLoadHistory::eStopIDNow, bool allow_section_end=false)
Definition Target.cpp:3448
#define LLDB_INVALID_ADDRESS
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:327
std::shared_ptr< lldb_private::Instruction > InstructionSP
std::shared_ptr< lldb_private::Disassembler > DisassemblerSP
uint64_t addr_t
Definition lldb-types.h:80
std::shared_ptr< lldb_private::Module > ModuleSP