Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/lldb/source/Plugins/Architecture/Mips/ArchitectureMips.cpp
39644 views
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
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"
21
22
using namespace lldb_private;
23
using namespace lldb;
24
25
LLDB_PLUGIN_DEFINE(ArchitectureMips)
26
27
void ArchitectureMips::Initialize() {
28
PluginManager::RegisterPlugin(GetPluginNameStatic(),
29
"Mips-specific algorithms",
30
&ArchitectureMips::Create);
31
}
32
33
void ArchitectureMips::Terminate() {
34
PluginManager::UnregisterPlugin(&ArchitectureMips::Create);
35
}
36
37
std::unique_ptr<Architecture> ArchitectureMips::Create(const ArchSpec &arch) {
38
return arch.IsMIPS() ?
39
std::unique_ptr<Architecture>(new ArchitectureMips(arch)) : nullptr;
40
}
41
42
addr_t ArchitectureMips::GetCallableLoadAddress(addr_t code_addr,
43
AddressClass addr_class) const {
44
bool is_alternate_isa = false;
45
46
switch (addr_class) {
47
case AddressClass::eData:
48
case AddressClass::eDebug:
49
return LLDB_INVALID_ADDRESS;
50
case AddressClass::eCodeAlternateISA:
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
61
addr_t ArchitectureMips::GetOpcodeLoadAddress(addr_t opcode_addr,
62
AddressClass addr_class) const {
63
switch (addr_class) {
64
case AddressClass::eData:
65
case AddressClass::eDebug:
66
return LLDB_INVALID_ADDRESS;
67
default: break;
68
}
69
return opcode_addr & ~(1ull);
70
}
71
72
lldb::addr_t ArchitectureMips::GetBreakableLoadAddress(lldb::addr_t addr,
73
Target &target) const {
74
75
Log *log = GetLog(LLDBLog::Breakpoints);
76
77
Address resolved_addr;
78
79
SectionLoadList &section_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);
84
else
85
target.ResolveLoadAddress(addr, resolved_addr);
86
87
addr_t current_offset = 0;
88
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) {
93
SymbolContext sc;
94
SymbolContextItem resolve_scope =
95
eSymbolContextFunction | eSymbolContextSymbol;
96
temp_addr_module_sp->ResolveSymbolContextForAddress(resolved_addr,
97
resolve_scope, sc);
98
Address sym_addr;
99
if (sc.function)
100
sym_addr = sc.function->GetAddressRange().GetBaseAddress();
101
else if (sc.symbol)
102
sym_addr = sc.symbol->GetAddress();
103
104
addr_t function_start = sym_addr.GetLoadAddress(&target);
105
if (function_start == LLDB_INVALID_ADDRESS)
106
function_start = sym_addr.GetFileAddress();
107
108
if (function_start)
109
current_offset = addr - function_start;
110
}
111
112
// If breakpoint address is start of function then we dont have to do
113
// anything.
114
if (current_offset == 0)
115
return addr;
116
117
auto insn = GetInstructionAtAddress(target, current_offset, addr);
118
119
if (nullptr == insn || !insn->HasDelaySlot())
120
return addr;
121
122
// Adjust the breakable address
123
uint64_t breakable_addr = addr - insn->GetOpcode().GetByteSize();
124
LLDB_LOGF(log,
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);
128
129
return breakable_addr;
130
}
131
132
Instruction *ArchitectureMips::GetInstructionAtAddress(
133
Target &target, const Address &resolved_addr, addr_t symbol_offset) const {
134
135
auto loop_count = symbol_offset / 2;
136
137
uint32_t arch_flags = m_arch.GetFlags();
138
bool IsMips16 = arch_flags & ArchSpec::eMIPSAse_mips16;
139
bool IsMicromips = arch_flags & ArchSpec::eMIPSAse_micromips;
140
141
if (loop_count > 3) {
142
// Scan previous 6 bytes
143
if (IsMips16 | IsMicromips)
144
loop_count = 3;
145
// For mips-only, instructions are always 4 bytes, so scan previous 4
146
// bytes only.
147
else
148
loop_count = 2;
149
}
150
151
// Create Disassembler Instance
152
lldb::DisassemblerSP disasm_sp(
153
Disassembler::FindPlugin(m_arch, nullptr, nullptr));
154
155
InstructionList instruction_list;
156
InstructionSP prev_insn;
157
uint32_t inst_to_choose = 0;
158
159
Address addr = resolved_addr;
160
161
for (uint32_t i = 1; i <= loop_count; i++) {
162
// Adjust the address to read from.
163
addr.Slide(-2);
164
uint32_t insn_size = 0;
165
166
disasm_sp->ParseInstructions(target, addr,
167
{Disassembler::Limit::Bytes, i * 2}, nullptr);
168
169
uint32_t num_insns = disasm_sp->GetInstructionList().GetSize();
170
if (num_insns) {
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);
177
inst_to_choose = 1;
178
}
179
else if (i == 2) {
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.
188
inst_to_choose = 1;
189
break;
190
}
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);
196
inst_to_choose = 2;
197
}
198
}
199
else if (i == 3) {
200
if (insn_size == 4)
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.
207
inst_to_choose = 0;
208
else
209
// This is straight-forward
210
inst_to_choose = 2;
211
break;
212
}
213
}
214
else {
215
// Decode failed, bytes do not form a valid instruction. So whatever
216
// previous iteration has found out is true.
217
if (i > 1) {
218
inst_to_choose = i - 1;
219
break;
220
}
221
}
222
}
223
224
// Check if we are able to find any valid instruction.
225
if (inst_to_choose) {
226
if (inst_to_choose > instruction_list.GetSize())
227
inst_to_choose--;
228
return instruction_list.GetInstructionAtIndex(inst_to_choose - 1).get();
229
}
230
231
return nullptr;
232
}
233
234