[Lldb-commits] [lldb] r342762 - Move architecture-specific address adjustment to architecture plugins

Tatyana Krasnukha via lldb-commits lldb-commits at lists.llvm.org
Fri Sep 21 11:56:44 PDT 2018


Author: tkrasnukha
Date: Fri Sep 21 11:56:44 2018
New Revision: 342762

URL: http://llvm.org/viewvc/llvm-project?rev=342762&view=rev
Log:
Move architecture-specific address adjustment to architecture plugins

Differential Revision: https://reviews.llvm.org/D48623

Added:
    lldb/trunk/source/Plugins/Architecture/Mips/
    lldb/trunk/source/Plugins/Architecture/Mips/ArchitectureMips.cpp
    lldb/trunk/source/Plugins/Architecture/Mips/ArchitectureMips.h
    lldb/trunk/source/Plugins/Architecture/Mips/CMakeLists.txt
Modified:
    lldb/trunk/include/lldb/Core/Architecture.h
    lldb/trunk/source/Plugins/Architecture/Arm/ArchitectureArm.cpp
    lldb/trunk/source/Plugins/Architecture/Arm/ArchitectureArm.h
    lldb/trunk/source/Plugins/Architecture/CMakeLists.txt
    lldb/trunk/source/Target/Target.cpp

Modified: lldb/trunk/include/lldb/Core/Architecture.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/Architecture.h?rev=342762&r1=342761&r2=342762&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Core/Architecture.h (original)
+++ lldb/trunk/include/lldb/Core/Architecture.h Fri Sep 21 11:56:44 2018
@@ -67,6 +67,51 @@ public:
   virtual void AdjustBreakpointAddress(const Symbol &func,
                                        Address &addr) const {}
 
+
+  //------------------------------------------------------------------
+  /// Get \a load_addr as a callable code load address for this target
+  ///
+  /// Take \a load_addr and potentially add any address bits that are
+  /// needed to make the address callable. For ARM this can set bit
+  /// zero (if it already isn't) if \a load_addr is a thumb function.
+  /// If \a addr_class is set to AddressClass::eInvalid, then the address
+  /// adjustment will always happen. If it is set to an address class
+  /// that doesn't have code in it, LLDB_INVALID_ADDRESS will be
+  /// returned.
+  //------------------------------------------------------------------
+  virtual lldb::addr_t GetCallableLoadAddress(
+      lldb::addr_t addr, AddressClass addr_class = AddressClass::eInvalid) const {
+    return addr;
+  }
+
+  //------------------------------------------------------------------
+  /// Get \a load_addr as an opcode for this target.
+  ///
+  /// Take \a load_addr and potentially strip any address bits that are
+  /// needed to make the address point to an opcode. For ARM this can
+  /// clear bit zero (if it already isn't) if \a load_addr is a
+  /// thumb function and load_addr is in code.
+  /// If \a addr_class is set to AddressClass::eInvalid, then the address
+  /// adjustment will always happen. If it is set to an address class
+  /// that doesn't have code in it, LLDB_INVALID_ADDRESS will be
+  /// returned.
+  //------------------------------------------------------------------
+
+  virtual lldb::addr_t GetOpcodeLoadAddress(
+      lldb::addr_t addr, AddressClass addr_class = AddressClass::eInvalid) const {
+    return addr;
+  }
+
+  // Get load_addr as breakable load address for this target. Take a addr and
+  // check if for any reason there is a better address than this to put a
+  // breakpoint on. If there is then return that address. For MIPS, if
+  // instruction at addr is a delay slot instruction then this method will find
+  // the address of its previous instruction and return that address.
+  virtual lldb::addr_t GetBreakableLoadAddress(lldb::addr_t addr,
+                                               Target &target) const {
+    return addr;
+  }
+
 private:
   Architecture(const Architecture &) = delete;
   void operator=(const Architecture &) = delete;

Modified: lldb/trunk/source/Plugins/Architecture/Arm/ArchitectureArm.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Architecture/Arm/ArchitectureArm.cpp?rev=342762&r1=342761&r2=342762&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Architecture/Arm/ArchitectureArm.cpp (original)
+++ lldb/trunk/source/Plugins/Architecture/Arm/ArchitectureArm.cpp Fri Sep 21 11:56:44 2018
@@ -126,3 +126,33 @@ void ArchitectureArm::OverrideStopInfo(T
     }
   }
 }
+
+addr_t ArchitectureArm::GetCallableLoadAddress(addr_t code_addr,
+                                               AddressClass addr_class) const {
+  bool is_alternate_isa = false;
+
+  switch (addr_class) {
+  case AddressClass::eData:
+  case AddressClass::eDebug:
+    return LLDB_INVALID_ADDRESS;
+  case AddressClass::eCodeAlternateISA:
+    is_alternate_isa = true;
+    break;
+  default: break;
+  }
+
+  if ((code_addr & 2u) || is_alternate_isa)
+    return code_addr | 1u;
+  return code_addr;
+}
+
+addr_t ArchitectureArm::GetOpcodeLoadAddress(addr_t opcode_addr,
+                                             AddressClass addr_class) const {
+  switch (addr_class) {
+  case AddressClass::eData:
+  case AddressClass::eDebug:
+    return LLDB_INVALID_ADDRESS;
+  default: break;
+  }
+  return opcode_addr & ~(1ull);
+}
\ No newline at end of file

Modified: lldb/trunk/source/Plugins/Architecture/Arm/ArchitectureArm.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Architecture/Arm/ArchitectureArm.h?rev=342762&r1=342761&r2=342762&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Architecture/Arm/ArchitectureArm.h (original)
+++ lldb/trunk/source/Plugins/Architecture/Arm/ArchitectureArm.h Fri Sep 21 11:56:44 2018
@@ -25,6 +25,12 @@ public:
 
   void OverrideStopInfo(Thread &thread) const override;
 
+  lldb::addr_t GetCallableLoadAddress(lldb::addr_t load_addr,
+                                      AddressClass addr_class) const override;
+
+  lldb::addr_t GetOpcodeLoadAddress(lldb::addr_t load_addr,
+                                    AddressClass addr_class) const override;
+
 private:
   static std::unique_ptr<Architecture> Create(const ArchSpec &arch);
   ArchitectureArm() = default;

Modified: lldb/trunk/source/Plugins/Architecture/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Architecture/CMakeLists.txt?rev=342762&r1=342761&r2=342762&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Architecture/CMakeLists.txt (original)
+++ lldb/trunk/source/Plugins/Architecture/CMakeLists.txt Fri Sep 21 11:56:44 2018
@@ -1,2 +1,3 @@
 add_subdirectory(Arm)
+add_subdirectory(Mips)
 add_subdirectory(PPC64)

Added: lldb/trunk/source/Plugins/Architecture/Mips/ArchitectureMips.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Architecture/Mips/ArchitectureMips.cpp?rev=342762&view=auto
==============================================================================
--- lldb/trunk/source/Plugins/Architecture/Mips/ArchitectureMips.cpp (added)
+++ lldb/trunk/source/Plugins/Architecture/Mips/ArchitectureMips.cpp Fri Sep 21 11:56:44 2018
@@ -0,0 +1,240 @@
+//===-- ArchitectureMips.cpp -------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Plugins/Architecture/Mips/ArchitectureMips.h"
+#include "lldb/Core/Address.h"
+#include "lldb/Core/Disassembler.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Symbol/Function.h"
+#include "lldb/Symbol/SymbolContext.h"
+#include "lldb/Target/SectionLoadList.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Utility/ArchSpec.h"
+#include "lldb/Utility/Log.h"
+
+using namespace lldb_private;
+using namespace lldb;
+
+ConstString ArchitectureMips::GetPluginNameStatic() {
+  return ConstString("mips");
+}
+
+void ArchitectureMips::Initialize() {
+  PluginManager::RegisterPlugin(GetPluginNameStatic(),
+                                "Mips-specific algorithms",
+                                &ArchitectureMips::Create);
+}
+
+void ArchitectureMips::Terminate() {
+  PluginManager::UnregisterPlugin(&ArchitectureMips::Create);
+}
+
+std::unique_ptr<Architecture> ArchitectureMips::Create(const ArchSpec &arch) {
+  return arch.IsMIPS() ?
+      std::unique_ptr<Architecture>(new ArchitectureMips(arch)) : nullptr;
+}
+
+ConstString ArchitectureMips::GetPluginName() { return GetPluginNameStatic(); }
+uint32_t ArchitectureMips::GetPluginVersion() { return 1; }
+
+addr_t ArchitectureMips::GetCallableLoadAddress(addr_t code_addr,
+                                                AddressClass addr_class) const {
+  bool is_alternate_isa = false;
+
+  switch (addr_class) {
+  case AddressClass::eData:
+  case AddressClass::eDebug:
+    return LLDB_INVALID_ADDRESS;
+  case AddressClass::eCodeAlternateISA:
+    is_alternate_isa = true;
+    break;
+  default: break;
+  }
+
+  if ((code_addr & 2ull) || is_alternate_isa)
+    return code_addr | 1u;
+  return code_addr;
+}
+
+addr_t ArchitectureMips::GetOpcodeLoadAddress(addr_t opcode_addr,
+                                              AddressClass addr_class) const {
+  switch (addr_class) {
+  case AddressClass::eData:
+  case AddressClass::eDebug:
+    return LLDB_INVALID_ADDRESS;
+  default: break;
+  }
+  return opcode_addr & ~(1ull);
+}
+
+lldb::addr_t ArchitectureMips::GetBreakableLoadAddress(lldb::addr_t addr,
+                                                       Target &target) const {
+
+  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_BREAKPOINTS));
+
+  Address resolved_addr;
+
+  SectionLoadList &section_load_list = target.GetSectionLoadList();
+  if (section_load_list.IsEmpty())
+    // No sections are loaded, so we must assume we are not running yet and
+    // need to operate only on file address.
+    target.ResolveFileAddress(addr, resolved_addr);
+  else
+    target.ResolveLoadAddress(addr, resolved_addr);
+
+  addr_t current_offset = 0;
+
+  // Get the function boundaries to make sure we don't scan back before the
+  // beginning of the current function.
+  ModuleSP temp_addr_module_sp(resolved_addr.GetModule());
+  if (temp_addr_module_sp) {
+    SymbolContext sc;
+    uint32_t resolve_scope = eSymbolContextFunction | eSymbolContextSymbol;
+    temp_addr_module_sp->ResolveSymbolContextForAddress(resolved_addr,
+      resolve_scope, sc);
+    Address sym_addr;
+    if (sc.function)
+      sym_addr = sc.function->GetAddressRange().GetBaseAddress();
+    else if (sc.symbol)
+      sym_addr = sc.symbol->GetAddress();
+
+    addr_t function_start = sym_addr.GetLoadAddress(&target);
+    if (function_start == LLDB_INVALID_ADDRESS)
+      function_start = sym_addr.GetFileAddress();
+
+    if (function_start)
+      current_offset = addr - function_start;
+  }
+
+  // If breakpoint address is start of function then we dont have to do
+  // anything.
+  if (current_offset == 0)
+    return addr;
+
+  ExecutionContext ctx;
+  target.CalculateExecutionContext(ctx);
+  auto insn = GetInstructionAtAddress(ctx, current_offset, addr);
+
+  if (nullptr == insn || !insn->HasDelaySlot())
+    return addr;
+
+  // Adjust the breakable address
+  auto breakable_addr = addr - insn->GetOpcode().GetByteSize();
+  if (log)
+    log->Printf("Target::%s Breakpoint at 0x%8.8" PRIx64
+      " is adjusted to 0x%8.8" PRIx64 " due to delay slot\n",
+      __FUNCTION__, addr, breakable_addr);
+
+  return breakable_addr;
+}
+
+Instruction *ArchitectureMips::GetInstructionAtAddress(
+    const ExecutionContext &exe_ctx, const Address &resolved_addr,
+    addr_t symbol_offset) const {
+
+  auto loop_count = symbol_offset / 2;
+
+  uint32_t arch_flags = m_arch.GetFlags();
+  bool IsMips16 = arch_flags & ArchSpec::eMIPSAse_mips16;
+  bool IsMicromips = arch_flags & ArchSpec::eMIPSAse_micromips;
+
+  if (loop_count > 3) {
+    // Scan previous 6 bytes
+    if (IsMips16 | IsMicromips)
+      loop_count = 3;
+    // For mips-only, instructions are always 4 bytes, so scan previous 4
+    // bytes only.
+    else
+      loop_count = 2;
+  }
+
+  // Create Disassembler Instance
+  lldb::DisassemblerSP disasm_sp(
+    Disassembler::FindPlugin(m_arch, nullptr, nullptr));
+
+  InstructionList instruction_list;
+  InstructionSP prev_insn;
+  bool prefer_file_cache = true; // Read from file
+  uint32_t inst_to_choose = 0;
+
+  Address addr = resolved_addr;
+
+  for (uint32_t i = 1; i <= loop_count; i++) {
+    // Adjust the address to read from.
+    addr.Slide(-2);
+    AddressRange range(addr, i * 2);
+    uint32_t insn_size = 0;
+
+    disasm_sp->ParseInstructions(&exe_ctx, range, nullptr, prefer_file_cache);
+
+    uint32_t num_insns = disasm_sp->GetInstructionList().GetSize();
+    if (num_insns) {
+      prev_insn = disasm_sp->GetInstructionList().GetInstructionAtIndex(0);
+      insn_size = prev_insn->GetOpcode().GetByteSize();
+      if (i == 1 && insn_size == 2) {
+        // This looks like a valid 2-byte instruction (but it could be a part
+        // of upper 4 byte instruction).
+        instruction_list.Append(prev_insn);
+        inst_to_choose = 1;
+      }
+      else if (i == 2) {
+        // Here we may get one 4-byte instruction or two 2-byte instructions.
+        if (num_insns == 2) {
+          // Looks like there are two 2-byte instructions above our
+          // breakpoint target address. Now the upper 2-byte instruction is
+          // either a valid 2-byte instruction or could be a part of it's
+          // upper 4-byte instruction. In both cases we don't care because in
+          // this case lower 2-byte instruction is definitely a valid
+          // instruction and whatever i=1 iteration has found out is true.
+          inst_to_choose = 1;
+          break;
+        }
+        else if (insn_size == 4) {
+          // This instruction claims its a valid 4-byte instruction. But it
+          // could be a part of it's upper 4-byte instruction. Lets try
+          // scanning upper 2 bytes to verify this.
+          instruction_list.Append(prev_insn);
+          inst_to_choose = 2;
+        }
+      }
+      else if (i == 3) {
+        if (insn_size == 4)
+          // FIXME: We reached here that means instruction at [target - 4] has
+          // already claimed to be a 4-byte instruction, and now instruction
+          // at [target - 6] is also claiming that it's a 4-byte instruction.
+          // This can not be true. In this case we can not decide the valid
+          // previous instruction so we let lldb set the breakpoint at the
+          // address given by user.
+          inst_to_choose = 0;
+        else
+          // This is straight-forward
+          inst_to_choose = 2;
+        break;
+      }
+    }
+    else {
+      // Decode failed, bytes do not form a valid instruction. So whatever
+      // previous iteration has found out is true.
+      if (i > 1) {
+        inst_to_choose = i - 1;
+        break;
+      }
+    }
+  }
+
+  // Check if we are able to find any valid instruction.
+  if (inst_to_choose) {
+    if (inst_to_choose > instruction_list.GetSize())
+      inst_to_choose--;
+    return instruction_list.GetInstructionAtIndex(inst_to_choose - 1).get();
+  }
+
+  return nullptr;
+}

Added: lldb/trunk/source/Plugins/Architecture/Mips/ArchitectureMips.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Architecture/Mips/ArchitectureMips.h?rev=342762&view=auto
==============================================================================
--- lldb/trunk/source/Plugins/Architecture/Mips/ArchitectureMips.h (added)
+++ lldb/trunk/source/Plugins/Architecture/Mips/ArchitectureMips.h Fri Sep 21 11:56:44 2018
@@ -0,0 +1,52 @@
+//===-- ArchitectureMips.h ---------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_PLUGIN_ARCHITECTURE_MIPS_H
+#define LLDB_PLUGIN_ARCHITECTURE_MIPS_H
+
+#include "lldb/Core/Architecture.h"
+#include "lldb/Utility/ArchSpec.h"
+
+namespace lldb_private {
+
+class ArchitectureMips : public Architecture {
+public:
+  static ConstString GetPluginNameStatic();
+  static void Initialize();
+  static void Terminate();
+
+  ConstString GetPluginName() override;
+  uint32_t GetPluginVersion() override;
+
+  void OverrideStopInfo(Thread &thread) const override {}
+
+  lldb::addr_t GetBreakableLoadAddress(lldb::addr_t addr,
+                                       Target &) const override;
+
+  lldb::addr_t GetCallableLoadAddress(lldb::addr_t load_addr,
+                                      AddressClass addr_class) const override;
+
+  lldb::addr_t GetOpcodeLoadAddress(lldb::addr_t load_addr,
+                                    AddressClass addr_class) const override;
+
+private:
+  Instruction *GetInstructionAtAddress(const ExecutionContext &exe_ctx,
+                                       const Address &resolved_addr,
+                                       lldb::addr_t symbol_offset) const;
+
+
+  static std::unique_ptr<Architecture> Create(const ArchSpec &arch);
+  ArchitectureMips(const ArchSpec &arch) : m_arch(arch) {}
+
+  ArchSpec m_arch;
+};
+
+} // namespace lldb_private
+
+#endif // LLDB_PLUGIN_ARCHITECTURE_MIPS_H

Added: lldb/trunk/source/Plugins/Architecture/Mips/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Architecture/Mips/CMakeLists.txt?rev=342762&view=auto
==============================================================================
--- lldb/trunk/source/Plugins/Architecture/Mips/CMakeLists.txt (added)
+++ lldb/trunk/source/Plugins/Architecture/Mips/CMakeLists.txt Fri Sep 21 11:56:44 2018
@@ -0,0 +1,10 @@
+add_lldb_library(lldbPluginArchitectureMips PLUGIN
+  ArchitectureMips.cpp
+
+  LINK_LIBS
+    lldbCore
+    lldbTarget
+    lldbUtility
+  LINK_COMPONENTS
+    Support
+  )

Modified: lldb/trunk/source/Target/Target.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/Target.cpp?rev=342762&r1=342761&r2=342762&view=diff
==============================================================================
--- lldb/trunk/source/Target/Target.cpp (original)
+++ lldb/trunk/source/Target/Target.cpp Fri Sep 21 11:56:44 2018
@@ -2428,249 +2428,22 @@ lldb::addr_t Target::GetPersistentSymbol
 
 lldb::addr_t Target::GetCallableLoadAddress(lldb::addr_t load_addr,
                                             AddressClass addr_class) const {
-  addr_t code_addr = load_addr;
-  switch (m_arch.GetSpec().GetMachine()) {
-  case llvm::Triple::mips:
-  case llvm::Triple::mipsel:
-  case llvm::Triple::mips64:
-  case llvm::Triple::mips64el:
-    switch (addr_class) {
-    case AddressClass::eData:
-    case AddressClass::eDebug:
-      return LLDB_INVALID_ADDRESS;
-
-    case AddressClass::eUnknown:
-    case AddressClass::eInvalid:
-    case AddressClass::eCode:
-    case AddressClass::eCodeAlternateISA:
-    case AddressClass::eRuntime:
-      if ((code_addr & 2ull) || (addr_class == AddressClass::eCodeAlternateISA))
-        code_addr |= 1ull;
-      break;
-    }
-    break;
-
-  case llvm::Triple::arm:
-  case llvm::Triple::thumb:
-    switch (addr_class) {
-    case AddressClass::eData:
-    case AddressClass::eDebug:
-      return LLDB_INVALID_ADDRESS;
-
-    case AddressClass::eUnknown:
-    case AddressClass::eInvalid:
-    case AddressClass::eCode:
-    case AddressClass::eCodeAlternateISA:
-    case AddressClass::eRuntime:
-      // Check if bit zero it no set?
-      if ((code_addr & 1ull) == 0) {
-        // Bit zero isn't set, check if the address is a multiple of 2?
-        if (code_addr & 2ull) {
-          // The address is a multiple of 2 so it must be thumb, set bit zero
-          code_addr |= 1ull;
-        } else if (addr_class == AddressClass::eCodeAlternateISA) {
-          // We checked the address and the address claims to be the alternate
-          // ISA which means thumb, so set bit zero.
-          code_addr |= 1ull;
-        }
-      }
-      break;
-    }
-    break;
-
-  default:
-    break;
-  }
-  return code_addr;
+  auto arch_plugin = GetArchitecturePlugin();
+  return arch_plugin ?
+      arch_plugin->GetCallableLoadAddress(load_addr, addr_class) : load_addr;
 }
 
 lldb::addr_t Target::GetOpcodeLoadAddress(lldb::addr_t load_addr,
                                           AddressClass addr_class) const {
-  addr_t opcode_addr = load_addr;
-  switch (m_arch.GetSpec().GetMachine()) {
-  case llvm::Triple::mips:
-  case llvm::Triple::mipsel:
-  case llvm::Triple::mips64:
-  case llvm::Triple::mips64el:
-  case llvm::Triple::arm:
-  case llvm::Triple::thumb:
-    switch (addr_class) {
-    case AddressClass::eData:
-    case AddressClass::eDebug:
-      return LLDB_INVALID_ADDRESS;
-
-    case AddressClass::eInvalid:
-    case AddressClass::eUnknown:
-    case AddressClass::eCode:
-    case AddressClass::eCodeAlternateISA:
-    case AddressClass::eRuntime:
-      opcode_addr &= ~(1ull);
-      break;
-    }
-    break;
-
-  default:
-    break;
-  }
-  return opcode_addr;
+  auto arch_plugin = GetArchitecturePlugin();
+  return arch_plugin ?
+      arch_plugin->GetOpcodeLoadAddress(load_addr, addr_class) : load_addr;
 }
 
 lldb::addr_t Target::GetBreakableLoadAddress(lldb::addr_t addr) {
-  addr_t breakable_addr = addr;
-  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_BREAKPOINTS));
-
-  switch (m_arch.GetSpec().GetMachine()) {
-  default:
-    break;
-  case llvm::Triple::mips:
-  case llvm::Triple::mipsel:
-  case llvm::Triple::mips64:
-  case llvm::Triple::mips64el: {
-    addr_t function_start = 0;
-    addr_t current_offset = 0;
-    uint32_t loop_count = 0;
-    Address resolved_addr;
-    uint32_t arch_flags = m_arch.GetSpec().GetFlags();
-    bool IsMips16 = arch_flags & ArchSpec::eMIPSAse_mips16;
-    bool IsMicromips = arch_flags & ArchSpec::eMIPSAse_micromips;
-    SectionLoadList &section_load_list = GetSectionLoadList();
-
-    if (section_load_list.IsEmpty())
-      // No sections are loaded, so we must assume we are not running yet and
-      // need to operate only on file address.
-      m_images.ResolveFileAddress(addr, resolved_addr);
-    else
-      section_load_list.ResolveLoadAddress(addr, resolved_addr);
-
-    // Get the function boundaries to make sure we don't scan back before the
-    // beginning of the current function.
-    ModuleSP temp_addr_module_sp(resolved_addr.GetModule());
-    if (temp_addr_module_sp) {
-      SymbolContext sc;
-      uint32_t resolve_scope = eSymbolContextFunction | eSymbolContextSymbol;
-      temp_addr_module_sp->ResolveSymbolContextForAddress(resolved_addr,
-                                                          resolve_scope, sc);
-      Address sym_addr;
-      if (sc.function)
-        sym_addr = sc.function->GetAddressRange().GetBaseAddress();
-      else if (sc.symbol)
-        sym_addr = sc.symbol->GetAddress();
-
-      function_start = sym_addr.GetLoadAddress(this);
-      if (function_start == LLDB_INVALID_ADDRESS)
-        function_start = sym_addr.GetFileAddress();
-
-      if (function_start)
-        current_offset = addr - function_start;
-    }
-
-    // If breakpoint address is start of function then we dont have to do
-    // anything.
-    if (current_offset == 0)
-      return breakable_addr;
-    else
-      loop_count = current_offset / 2;
-
-    if (loop_count > 3) {
-      // Scan previous 6 bytes
-      if (IsMips16 | IsMicromips)
-        loop_count = 3;
-      // For mips-only, instructions are always 4 bytes, so scan previous 4
-      // bytes only.
-      else
-        loop_count = 2;
-    }
-
-    // Create Disassembler Instance
-    lldb::DisassemblerSP disasm_sp(
-        Disassembler::FindPlugin(m_arch.GetSpec(), nullptr, nullptr));
-
-    ExecutionContext exe_ctx;
-    CalculateExecutionContext(exe_ctx);
-    InstructionList instruction_list;
-    InstructionSP prev_insn;
-    bool prefer_file_cache = true; // Read from file
-    uint32_t inst_to_choose = 0;
-
-    for (uint32_t i = 1; i <= loop_count; i++) {
-      // Adjust the address to read from.
-      resolved_addr.Slide(-2);
-      AddressRange range(resolved_addr, i * 2);
-      uint32_t insn_size = 0;
-
-      disasm_sp->ParseInstructions(&exe_ctx, range, nullptr, prefer_file_cache);
-
-      uint32_t num_insns = disasm_sp->GetInstructionList().GetSize();
-      if (num_insns) {
-        prev_insn = disasm_sp->GetInstructionList().GetInstructionAtIndex(0);
-        insn_size = prev_insn->GetOpcode().GetByteSize();
-        if (i == 1 && insn_size == 2) {
-          // This looks like a valid 2-byte instruction (but it could be a part
-          // of upper 4 byte instruction).
-          instruction_list.Append(prev_insn);
-          inst_to_choose = 1;
-        } else if (i == 2) {
-          // Here we may get one 4-byte instruction or two 2-byte instructions.
-          if (num_insns == 2) {
-            // Looks like there are two 2-byte instructions above our
-            // breakpoint target address. Now the upper 2-byte instruction is
-            // either a valid 2-byte instruction or could be a part of it's
-            // upper 4-byte instruction. In both cases we don't care because in
-            // this case lower 2-byte instruction is definitely a valid
-            // instruction and whatever i=1 iteration has found out is true.
-            inst_to_choose = 1;
-            break;
-          } else if (insn_size == 4) {
-            // This instruction claims its a valid 4-byte instruction. But it
-            // could be a part of it's upper 4-byte instruction. Lets try
-            // scanning upper 2 bytes to verify this.
-            instruction_list.Append(prev_insn);
-            inst_to_choose = 2;
-          }
-        } else if (i == 3) {
-          if (insn_size == 4)
-            // FIXME: We reached here that means instruction at [target - 4] has
-            // already claimed to be a 4-byte instruction, and now instruction
-            // at [target - 6] is also claiming that it's a 4-byte instruction.
-            // This can not be true. In this case we can not decide the valid
-            // previous instruction so we let lldb set the breakpoint at the
-            // address given by user.
-            inst_to_choose = 0;
-          else
-            // This is straight-forward
-            inst_to_choose = 2;
-          break;
-        }
-      } else {
-        // Decode failed, bytes do not form a valid instruction. So whatever
-        // previous iteration has found out is true.
-        if (i > 1) {
-          inst_to_choose = i - 1;
-          break;
-        }
-      }
-    }
-
-    // Check if we are able to find any valid instruction.
-    if (inst_to_choose) {
-      if (inst_to_choose > instruction_list.GetSize())
-        inst_to_choose--;
-      prev_insn = instruction_list.GetInstructionAtIndex(inst_to_choose - 1);
-
-      if (prev_insn->HasDelaySlot()) {
-        uint32_t shift_size = prev_insn->GetOpcode().GetByteSize();
-        // Adjust the breakable address
-        breakable_addr = addr - shift_size;
-        if (log)
-          log->Printf("Target::%s Breakpoint at 0x%8.8" PRIx64
-                      " is adjusted to 0x%8.8" PRIx64 " due to delay slot\n",
-                      __FUNCTION__, addr, breakable_addr);
-      }
-    }
-    break;
-  }
-  }
-  return breakable_addr;
+  auto arch_plugin = GetArchitecturePlugin();
+  return arch_plugin ?
+      arch_plugin->GetBreakableLoadAddress(addr, *this) : addr;
 }
 
 SourceManager &Target::GetSourceManager() {




More information about the lldb-commits mailing list