ArchitectureMips.cpp revision 343181
1122394Sharti//===-- ArchitectureMips.cpp -------------------------------------*- C++ -*-===//
2122394Sharti//
3122394Sharti//                     The LLVM Compiler Infrastructure
4122394Sharti//
5122394Sharti// This file is distributed under the University of Illinois Open Source
6122394Sharti// License. See LICENSE.TXT for details.
7216594Ssyrinx//
8216594Ssyrinx//===----------------------------------------------------------------------===//
9216594Ssyrinx
10216594Ssyrinx#include "Plugins/Architecture/Mips/ArchitectureMips.h"
11216594Ssyrinx#include "lldb/Core/Address.h"
12216594Ssyrinx#include "lldb/Core/Disassembler.h"
13216594Ssyrinx#include "lldb/Core/Module.h"
14133211Sharti#include "lldb/Core/PluginManager.h"
15133211Sharti#include "lldb/Symbol/Function.h"
16133211Sharti#include "lldb/Symbol/SymbolContext.h"
17133211Sharti#include "lldb/Target/SectionLoadList.h"
18133211Sharti#include "lldb/Target/Target.h"
19122394Sharti#include "lldb/Utility/ArchSpec.h"
20122394Sharti#include "lldb/Utility/Log.h"
21122394Sharti
22133211Shartiusing namespace lldb_private;
23133211Shartiusing namespace lldb;
24133211Sharti
25133211ShartiConstString ArchitectureMips::GetPluginNameStatic() {
26133211Sharti  return ConstString("mips");
27133211Sharti}
28133211Sharti
29133211Shartivoid ArchitectureMips::Initialize() {
30133211Sharti  PluginManager::RegisterPlugin(GetPluginNameStatic(),
31133211Sharti                                "Mips-specific algorithms",
32133211Sharti                                &ArchitectureMips::Create);
33133211Sharti}
34122394Sharti
35150920Shartivoid ArchitectureMips::Terminate() {
36122394Sharti  PluginManager::UnregisterPlugin(&ArchitectureMips::Create);
37122394Sharti}
38122394Sharti
39122394Shartistd::unique_ptr<Architecture> ArchitectureMips::Create(const ArchSpec &arch) {
40216294Ssyrinx  return arch.IsMIPS() ?
41122394Sharti      std::unique_ptr<Architecture>(new ArchitectureMips(arch)) : nullptr;
42122394Sharti}
43216594Ssyrinx
44122394ShartiConstString ArchitectureMips::GetPluginName() { return GetPluginNameStatic(); }
45122394Shartiuint32_t ArchitectureMips::GetPluginVersion() { return 1; }
46122394Sharti
47122394Shartiaddr_t ArchitectureMips::GetCallableLoadAddress(addr_t code_addr,
48122394Sharti                                                AddressClass addr_class) const {
49122394Sharti  bool is_alternate_isa = false;
50122394Sharti
51122394Sharti  switch (addr_class) {
52122394Sharti  case AddressClass::eData:
53122394Sharti  case AddressClass::eDebug:
54122394Sharti    return LLDB_INVALID_ADDRESS;
55122394Sharti  case AddressClass::eCodeAlternateISA:
56122394Sharti    is_alternate_isa = true;
57122394Sharti    break;
58122394Sharti  default: break;
59122394Sharti  }
60122394Sharti
61122394Sharti  if ((code_addr & 2ull) || is_alternate_isa)
62216594Ssyrinx    return code_addr | 1u;
63216594Ssyrinx  return code_addr;
64216594Ssyrinx}
65216594Ssyrinx
66216594Ssyrinxaddr_t ArchitectureMips::GetOpcodeLoadAddress(addr_t opcode_addr,
67216594Ssyrinx                                              AddressClass addr_class) const {
68216594Ssyrinx  switch (addr_class) {
69216594Ssyrinx  case AddressClass::eData:
70216594Ssyrinx  case AddressClass::eDebug:
71216594Ssyrinx    return LLDB_INVALID_ADDRESS;
72216594Ssyrinx  default: break;
73216594Ssyrinx  }
74122394Sharti  return opcode_addr & ~(1ull);
75122394Sharti}
76122394Sharti
77122394Shartilldb::addr_t ArchitectureMips::GetBreakableLoadAddress(lldb::addr_t addr,
78122394Sharti                                                       Target &target) const {
79122394Sharti
80122394Sharti  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_BREAKPOINTS));
81122394Sharti
82122394Sharti  Address resolved_addr;
83122394Sharti
84122394Sharti  SectionLoadList &section_load_list = target.GetSectionLoadList();
85122394Sharti  if (section_load_list.IsEmpty())
86122394Sharti    // No sections are loaded, so we must assume we are not running yet and
87122394Sharti    // need to operate only on file address.
88122394Sharti    target.ResolveFileAddress(addr, resolved_addr);
89122394Sharti  else
90122394Sharti    target.ResolveLoadAddress(addr, resolved_addr);
91122394Sharti
92122394Sharti  addr_t current_offset = 0;
93122394Sharti
94122394Sharti  // Get the function boundaries to make sure we don't scan back before the
95122394Sharti  // beginning of the current function.
96122394Sharti  ModuleSP temp_addr_module_sp(resolved_addr.GetModule());
97122394Sharti  if (temp_addr_module_sp) {
98122394Sharti    SymbolContext sc;
99122394Sharti    SymbolContextItem resolve_scope =
100122394Sharti        eSymbolContextFunction | eSymbolContextSymbol;
101122394Sharti    temp_addr_module_sp->ResolveSymbolContextForAddress(resolved_addr,
102122394Sharti      resolve_scope, sc);
103122394Sharti    Address sym_addr;
104122394Sharti    if (sc.function)
105122394Sharti      sym_addr = sc.function->GetAddressRange().GetBaseAddress();
106122394Sharti    else if (sc.symbol)
107122394Sharti      sym_addr = sc.symbol->GetAddress();
108122394Sharti
109122394Sharti    addr_t function_start = sym_addr.GetLoadAddress(&target);
110122394Sharti    if (function_start == LLDB_INVALID_ADDRESS)
111122394Sharti      function_start = sym_addr.GetFileAddress();
112122394Sharti
113122394Sharti    if (function_start)
114122394Sharti      current_offset = addr - function_start;
115122394Sharti  }
116122394Sharti
117122394Sharti  // If breakpoint address is start of function then we dont have to do
118122394Sharti  // anything.
119122394Sharti  if (current_offset == 0)
120122394Sharti    return addr;
121122394Sharti
122122394Sharti  ExecutionContext ctx;
123122394Sharti  target.CalculateExecutionContext(ctx);
124122394Sharti  auto insn = GetInstructionAtAddress(ctx, current_offset, addr);
125122394Sharti
126122394Sharti  if (nullptr == insn || !insn->HasDelaySlot())
127122394Sharti    return addr;
128122394Sharti
129122394Sharti  // Adjust the breakable address
130150920Sharti  uint64_t breakable_addr = addr - insn->GetOpcode().GetByteSize();
131122394Sharti  if (log)
132122394Sharti    log->Printf("Target::%s Breakpoint at 0x%8.8" PRIx64
133122394Sharti      " is adjusted to 0x%8.8" PRIx64 " due to delay slot\n",
134122394Sharti      __FUNCTION__, addr, breakable_addr);
135122394Sharti
136122394Sharti  return breakable_addr;
137122394Sharti}
138122394Sharti
139122394ShartiInstruction *ArchitectureMips::GetInstructionAtAddress(
140122394Sharti    const ExecutionContext &exe_ctx, const Address &resolved_addr,
141122394Sharti    addr_t symbol_offset) const {
142122394Sharti
143122394Sharti  auto loop_count = symbol_offset / 2;
144122394Sharti
145122394Sharti  uint32_t arch_flags = m_arch.GetFlags();
146122394Sharti  bool IsMips16 = arch_flags & ArchSpec::eMIPSAse_mips16;
147122394Sharti  bool IsMicromips = arch_flags & ArchSpec::eMIPSAse_micromips;
148122394Sharti
149122394Sharti  if (loop_count > 3) {
150122394Sharti    // Scan previous 6 bytes
151122394Sharti    if (IsMips16 | IsMicromips)
152122394Sharti      loop_count = 3;
153122394Sharti    // For mips-only, instructions are always 4 bytes, so scan previous 4
154122394Sharti    // bytes only.
155122394Sharti    else
156122394Sharti      loop_count = 2;
157122394Sharti  }
158122394Sharti
159122394Sharti  // Create Disassembler Instance
160122394Sharti  lldb::DisassemblerSP disasm_sp(
161122394Sharti    Disassembler::FindPlugin(m_arch, nullptr, nullptr));
162122394Sharti
163122394Sharti  InstructionList instruction_list;
164122394Sharti  InstructionSP prev_insn;
165122394Sharti  bool prefer_file_cache = true; // Read from file
166122394Sharti  uint32_t inst_to_choose = 0;
167122394Sharti
168122394Sharti  Address addr = resolved_addr;
169122394Sharti
170122394Sharti  for (uint32_t i = 1; i <= loop_count; i++) {
171122394Sharti    // Adjust the address to read from.
172122394Sharti    addr.Slide(-2);
173122394Sharti    AddressRange range(addr, i * 2);
174122394Sharti    uint32_t insn_size = 0;
175122394Sharti
176122394Sharti    disasm_sp->ParseInstructions(&exe_ctx, range, nullptr, prefer_file_cache);
177122394Sharti
178122394Sharti    uint32_t num_insns = disasm_sp->GetInstructionList().GetSize();
179122394Sharti    if (num_insns) {
180122394Sharti      prev_insn = disasm_sp->GetInstructionList().GetInstructionAtIndex(0);
181122394Sharti      insn_size = prev_insn->GetOpcode().GetByteSize();
182122394Sharti      if (i == 1 && insn_size == 2) {
183122394Sharti        // This looks like a valid 2-byte instruction (but it could be a part
184122394Sharti        // of upper 4 byte instruction).
185122394Sharti        instruction_list.Append(prev_insn);
186122394Sharti        inst_to_choose = 1;
187122394Sharti      }
188122394Sharti      else if (i == 2) {
189122394Sharti        // Here we may get one 4-byte instruction or two 2-byte instructions.
190122394Sharti        if (num_insns == 2) {
191122394Sharti          // Looks like there are two 2-byte instructions above our
192122394Sharti          // breakpoint target address. Now the upper 2-byte instruction is
193122394Sharti          // either a valid 2-byte instruction or could be a part of it's
194122394Sharti          // upper 4-byte instruction. In both cases we don't care because in
195122394Sharti          // this case lower 2-byte instruction is definitely a valid
196122394Sharti          // instruction and whatever i=1 iteration has found out is true.
197122394Sharti          inst_to_choose = 1;
198122394Sharti          break;
199122394Sharti        }
200122394Sharti        else if (insn_size == 4) {
201122394Sharti          // This instruction claims its a valid 4-byte instruction. But it
202122394Sharti          // could be a part of it's upper 4-byte instruction. Lets try
203122394Sharti          // scanning upper 2 bytes to verify this.
204122394Sharti          instruction_list.Append(prev_insn);
205122394Sharti          inst_to_choose = 2;
206122394Sharti        }
207122394Sharti      }
208122394Sharti      else if (i == 3) {
209122394Sharti        if (insn_size == 4)
210122394Sharti          // FIXME: We reached here that means instruction at [target - 4] has
211122394Sharti          // already claimed to be a 4-byte instruction, and now instruction
212122394Sharti          // at [target - 6] is also claiming that it's a 4-byte instruction.
213122394Sharti          // This can not be true. In this case we can not decide the valid
214122394Sharti          // previous instruction so we let lldb set the breakpoint at the
215122394Sharti          // address given by user.
216122394Sharti          inst_to_choose = 0;
217122394Sharti        else
218122394Sharti          // This is straight-forward
219122394Sharti          inst_to_choose = 2;
220122394Sharti        break;
221122394Sharti      }
222128237Sharti    }
223122394Sharti    else {
224122394Sharti      // Decode failed, bytes do not form a valid instruction. So whatever
225122394Sharti      // previous iteration has found out is true.
226122394Sharti      if (i > 1) {
227122394Sharti        inst_to_choose = i - 1;
228122394Sharti        break;
229122394Sharti      }
230122394Sharti    }
231122394Sharti  }
232122394Sharti
233122394Sharti  // Check if we are able to find any valid instruction.
234122394Sharti  if (inst_to_choose) {
235122394Sharti    if (inst_to_choose > instruction_list.GetSize())
236122394Sharti      inst_to_choose--;
237122394Sharti    return instruction_list.GetInstructionAtIndex(inst_to_choose - 1).get();
238122394Sharti  }
239122394Sharti
240122394Sharti  return nullptr;
241122394Sharti}
242122394Sharti