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