]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/lldb/source/Plugins/Architecture/Mips/ArchitectureMips.cpp
Merge llvm, clang, compiler-rt, libc++, libunwind, lld, lldb and openmp
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / lldb / source / Plugins / Architecture / Mips / ArchitectureMips.cpp
1 //===-- ArchitectureMips.cpp -------------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
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"
21
22 using namespace lldb_private;
23 using namespace lldb;
24
25 ConstString ArchitectureMips::GetPluginNameStatic() {
26   return ConstString("mips");
27 }
28
29 void ArchitectureMips::Initialize() {
30   PluginManager::RegisterPlugin(GetPluginNameStatic(),
31                                 "Mips-specific algorithms",
32                                 &ArchitectureMips::Create);
33 }
34
35 void ArchitectureMips::Terminate() {
36   PluginManager::UnregisterPlugin(&ArchitectureMips::Create);
37 }
38
39 std::unique_ptr<Architecture> ArchitectureMips::Create(const ArchSpec &arch) {
40   return arch.IsMIPS() ?
41       std::unique_ptr<Architecture>(new ArchitectureMips(arch)) : nullptr;
42 }
43
44 ConstString ArchitectureMips::GetPluginName() { return GetPluginNameStatic(); }
45 uint32_t ArchitectureMips::GetPluginVersion() { return 1; }
46
47 addr_t ArchitectureMips::GetCallableLoadAddress(addr_t code_addr,
48                                                 AddressClass addr_class) const {
49   bool is_alternate_isa = false;
50
51   switch (addr_class) {
52   case AddressClass::eData:
53   case AddressClass::eDebug:
54     return LLDB_INVALID_ADDRESS;
55   case AddressClass::eCodeAlternateISA:
56     is_alternate_isa = true;
57     break;
58   default: break;
59   }
60
61   if ((code_addr & 2ull) || is_alternate_isa)
62     return code_addr | 1u;
63   return code_addr;
64 }
65
66 addr_t ArchitectureMips::GetOpcodeLoadAddress(addr_t opcode_addr,
67                                               AddressClass addr_class) const {
68   switch (addr_class) {
69   case AddressClass::eData:
70   case AddressClass::eDebug:
71     return LLDB_INVALID_ADDRESS;
72   default: break;
73   }
74   return opcode_addr & ~(1ull);
75 }
76
77 lldb::addr_t ArchitectureMips::GetBreakableLoadAddress(lldb::addr_t addr,
78                                                        Target &target) const {
79
80   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_BREAKPOINTS));
81
82   Address resolved_addr;
83
84   SectionLoadList &section_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);
89   else
90     target.ResolveLoadAddress(addr, resolved_addr);
91
92   addr_t current_offset = 0;
93
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) {
98     SymbolContext sc;
99     SymbolContextItem resolve_scope =
100         eSymbolContextFunction | eSymbolContextSymbol;
101     temp_addr_module_sp->ResolveSymbolContextForAddress(resolved_addr,
102       resolve_scope, sc);
103     Address sym_addr;
104     if (sc.function)
105       sym_addr = sc.function->GetAddressRange().GetBaseAddress();
106     else if (sc.symbol)
107       sym_addr = sc.symbol->GetAddress();
108
109     addr_t function_start = sym_addr.GetLoadAddress(&target);
110     if (function_start == LLDB_INVALID_ADDRESS)
111       function_start = sym_addr.GetFileAddress();
112
113     if (function_start)
114       current_offset = addr - function_start;
115   }
116
117   // If breakpoint address is start of function then we dont have to do
118   // anything.
119   if (current_offset == 0)
120     return addr;
121
122   ExecutionContext ctx;
123   target.CalculateExecutionContext(ctx);
124   auto insn = GetInstructionAtAddress(ctx, current_offset, addr);
125
126   if (nullptr == insn || !insn->HasDelaySlot())
127     return addr;
128
129   // Adjust the breakable address
130   uint64_t breakable_addr = addr - insn->GetOpcode().GetByteSize();
131   if (log)
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);
135
136   return breakable_addr;
137 }
138
139 Instruction *ArchitectureMips::GetInstructionAtAddress(
140     const ExecutionContext &exe_ctx, const Address &resolved_addr,
141     addr_t symbol_offset) const {
142
143   auto loop_count = symbol_offset / 2;
144
145   uint32_t arch_flags = m_arch.GetFlags();
146   bool IsMips16 = arch_flags & ArchSpec::eMIPSAse_mips16;
147   bool IsMicromips = arch_flags & ArchSpec::eMIPSAse_micromips;
148
149   if (loop_count > 3) {
150     // Scan previous 6 bytes
151     if (IsMips16 | IsMicromips)
152       loop_count = 3;
153     // For mips-only, instructions are always 4 bytes, so scan previous 4
154     // bytes only.
155     else
156       loop_count = 2;
157   }
158
159   // Create Disassembler Instance
160   lldb::DisassemblerSP disasm_sp(
161     Disassembler::FindPlugin(m_arch, nullptr, nullptr));
162
163   InstructionList instruction_list;
164   InstructionSP prev_insn;
165   bool prefer_file_cache = true; // Read from file
166   uint32_t inst_to_choose = 0;
167
168   Address addr = resolved_addr;
169
170   for (uint32_t i = 1; i <= loop_count; i++) {
171     // Adjust the address to read from.
172     addr.Slide(-2);
173     AddressRange range(addr, i * 2);
174     uint32_t insn_size = 0;
175
176     disasm_sp->ParseInstructions(&exe_ctx, range, nullptr, prefer_file_cache);
177
178     uint32_t num_insns = disasm_sp->GetInstructionList().GetSize();
179     if (num_insns) {
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);
186         inst_to_choose = 1;
187       }
188       else if (i == 2) {
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.
197           inst_to_choose = 1;
198           break;
199         }
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);
205           inst_to_choose = 2;
206         }
207       }
208       else if (i == 3) {
209         if (insn_size == 4)
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.
216           inst_to_choose = 0;
217         else
218           // This is straight-forward
219           inst_to_choose = 2;
220         break;
221       }
222     }
223     else {
224       // Decode failed, bytes do not form a valid instruction. So whatever
225       // previous iteration has found out is true.
226       if (i > 1) {
227         inst_to_choose = i - 1;
228         break;
229       }
230     }
231   }
232
233   // Check if we are able to find any valid instruction.
234   if (inst_to_choose) {
235     if (inst_to_choose > instruction_list.GetSize())
236       inst_to_choose--;
237     return instruction_list.GetInstructionAtIndex(inst_to_choose - 1).get();
238   }
239
240   return nullptr;
241 }