[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 §ion_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 §ion_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