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"
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/LLDBLog.h"
20 #include "lldb/Utility/Log.h"
21 
22 using namespace lldb_private;
23 using namespace lldb;
24 
26 
27 void ArchitectureMips::Initialize() {
28  PluginManager::RegisterPlugin(GetPluginNameStatic(),
29  "Mips-specific algorithms",
31 }
32 
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 
43  AddressClass addr_class) const {
44  bool is_alternate_isa = false;
45 
46  switch (addr_class) {
49  return LLDB_INVALID_ADDRESS;
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) {
66  return LLDB_INVALID_ADDRESS;
67  default: break;
68  }
69  return opcode_addr & ~(1ull);
70 }
71 
73  Target &target) const {
74 
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 
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 }
lldb_private::AddressClass::eData
@ eData
lldb_private::AddressRange::GetBaseAddress
Address & GetBaseAddress()
Get accessor for the base address of the range.
Definition: AddressRange.h:209
lldb_private::ArchitectureMips::GetBreakableLoadAddress
lldb::addr_t GetBreakableLoadAddress(lldb::addr_t addr, Target &) const override
Definition: ArchitectureMips.cpp:72
lldb_private::ArchSpec
Definition: ArchSpec.h:33
lldb_private::ArchSpec::IsMIPS
bool IsMIPS() const
if MIPS architecture return true.
Definition: ArchSpec.cpp:546
lldb_private::Function::GetAddressRange
const AddressRange & GetAddressRange()
Definition: Function.h:457
lldb_private::AddressClass
AddressClass
Definition: lldb-private-enumerations.h:48
lldb_private::Disassembler::FindPlugin
static lldb::DisassemblerSP FindPlugin(const ArchSpec &arch, const char *flavor, const char *plugin_name)
Definition: Disassembler.cpp:58
LLDB_LOGF
#define LLDB_LOGF(log,...)
Definition: Log.h:343
lldb_private::ArchitectureMips::GetOpcodeLoadAddress
lldb::addr_t GetOpcodeLoadAddress(lldb::addr_t load_addr, AddressClass addr_class) const override
Get load_addr as an opcode for this target.
Definition: ArchitectureMips.cpp:61
Module.h
lldb_private::Disassembler::Limit::Bytes
@ Bytes
Definition: Disassembler.h:418
SectionLoadList.h
Disassembler.h
lldb_private::InstructionList::GetInstructionAtIndex
lldb::InstructionSP GetInstructionAtIndex(size_t idx) const
Definition: Disassembler.cpp:981
lldb_private::Instruction
Definition: Disassembler.h:58
lldb::addr_t
uint64_t addr_t
Definition: lldb-types.h:83
lldb_private::Target::ResolveLoadAddress
bool ResolveLoadAddress(lldb::addr_t load_addr, Address &so_addr, uint32_t stop_id=SectionLoadHistory::eStopIDNow)
Definition: Target.cpp:2908
ArchitectureMips.h
lldb_private::SymbolContext
Definition: SymbolContext.h:33
lldb_private::Target
Definition: Target.h:467
lldb_private::ArchitectureMips
Definition: ArchitectureMips.h:17
lldb_private::ArchitectureMips::Create
static std::unique_ptr< Architecture > Create(const ArchSpec &arch)
Definition: ArchitectureMips.cpp:37
Target.h
lldb_private::SymbolContext::symbol
Symbol * symbol
The Symbol for a given query.
Definition: SymbolContext.h:323
lldb_private::InstructionList
Definition: Disassembler.h:283
lldb_private::PluginManager::UnregisterPlugin
static bool UnregisterPlugin(ABICreateInstance create_callback)
Definition: PluginManager.cpp:293
Log.h
lldb_private::ArchitectureMips::GetInstructionAtAddress
Instruction * GetInstructionAtAddress(Target &target, const Address &resolved_addr, lldb::addr_t symbol_offset) const
Definition: ArchitectureMips.cpp:132
lldb_private::SymbolContext::function
Function * function
The Function for a given query.
Definition: SymbolContext.h:320
lldb_private::Address::GetFileAddress
lldb::addr_t GetFileAddress() const
Get the file address.
Definition: Address.cpp:291
lldb_private::Target::ResolveFileAddress
bool ResolveFileAddress(lldb::addr_t load_addr, Address &so_addr)
Definition: Target.cpp:2913
lldb_private::LLDBLog::Breakpoints
@ Breakpoints
lldb_private::SectionLoadList
Definition: SectionLoadList.h:22
Address.h
lldb_private::SectionLoadList::IsEmpty
bool IsEmpty() const
Definition: SectionLoadList.cpp:38
uint32_t
lldb_private::Address
Definition: Address.h:59
lldb_private::Address::GetLoadAddress
lldb::addr_t GetLoadAddress(Target *target) const
Get the load address.
Definition: Address.cpp:311
ArchSpec.h
lldb_private::ArchitectureMips::Terminate
static void Terminate()
Definition: ArchitectureMips.cpp:33
PluginManager.h
lldb_private::Target::GetSectionLoadList
SectionLoadList & GetSectionLoadList()
Definition: Target.h:1092
LLDB_INVALID_ADDRESS
#define LLDB_INVALID_ADDRESS
Definition: lldb-defines.h:74
lldb_private::ArchSpec::eMIPSAse_mips16
@ eMIPSAse_mips16
Definition: ArchSpec.h:63
Function.h
lldb_private::AddressClass::eDebug
@ eDebug
lldb_private::InstructionList::GetSize
size_t GetSize() const
Definition: Disassembler.cpp:967
lldb_private::AddressClass::eCodeAlternateISA
@ eCodeAlternateISA
lldb_private::PluginManager::RegisterPlugin
static bool RegisterPlugin(llvm::StringRef name, llvm::StringRef description, ABICreateInstance create_callback)
Definition: PluginManager.cpp:287
SymbolContext.h
lldb_private
A class that represents a running process on the host machine.
Definition: SBCommandInterpreterRunOptions.h:16
lldb_private::ArchitectureMips::GetCallableLoadAddress
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.
Definition: ArchitectureMips.cpp:42
lldb_private::ArchSpec::eMIPSAse_micromips
@ eMIPSAse_micromips
Definition: ArchSpec.h:64
lldb_private::Address::GetModule
lldb::ModuleSP GetModule() const
Get accessor for the module for this address.
Definition: Address.cpp:283
lldb_private::InstructionList::Append
void Append(lldb::InstructionSP &inst_sp)
Definition: Disassembler.cpp:1023
LLDB_PLUGIN_DEFINE
#define LLDB_PLUGIN_DEFINE(PluginName)
Definition: PluginManager.h:31
lldb_private::Log
Definition: Log.h:115
lldb_private::GetLog
Log * GetLog(Cat mask)
Retrieve the Log object for the channel associated with the given log enum.
Definition: Log.h:308
lldb_private::Address::Slide
bool Slide(int64_t offset)
Definition: Address.h:449
lldb
Definition: SBAddress.h:15
LLDBLog.h
lldb_private::Symbol::GetAddress
Address GetAddress() const
Definition: Symbol.h:73