Index: include/lldb/Core/Architecture.h =================================================================== --- include/lldb/Core/Architecture.h +++ include/lldb/Core/Architecture.h @@ -33,6 +33,35 @@ //------------------------------------------------------------------ virtual void OverrideStopInfo(Thread &thread) = 0; + //------------------------------------------------------------------ + /// This method is used to get the number of bytes that should be + /// skipped, from function start address, to reach the first + /// instruction after the prologue. + /// + /// This is called only if the standard platform-independent + /// code fails to get the number of bytes to skip, giving the plugin + /// a chance to try to find the missing info. + /// + /// This is specifically used for PPC64, where functions may have + /// more than one entry point, global and local, so both should + /// be compared with current PC, in order to find out the number of + /// bytes that should be skipped, in case we are stopped at either + /// function entry point. + //------------------------------------------------------------------ + virtual size_t GetBytesToSkip(Thread &thread) const { return 0; } + + //------------------------------------------------------------------ + /// Adjust function breakpoint address, if needed. In some cases, + /// the function start address is not the right place to set the + /// breakpoint, specially in functions with multiple entry points. + /// + /// This is specifically used for PPC64, for functions that have + /// both a global and a local entry point. In this case, the + /// breakpoint is adjusted to the first function address reached + /// by both entry points. + //------------------------------------------------------------------ + virtual void AdjustBreakpointAddress(Symbol *func, Address &addr) const {} + private: Architecture(const Architecture &) = delete; void operator=(const Architecture &) = delete; Index: source/API/SystemInitializerFull.cpp =================================================================== --- source/API/SystemInitializerFull.cpp +++ source/API/SystemInitializerFull.cpp @@ -43,6 +43,7 @@ #include "Plugins/ABI/SysV-s390x/ABISysV_s390x.h" #include "Plugins/ABI/SysV-x86_64/ABISysV_x86_64.h" #include "Plugins/Architecture/Arm/ArchitectureArm.h" +#include "Plugins/Architecture/PPC64/ArchitecturePPC64.h" #include "Plugins/Disassembler/llvm/DisassemblerLLVMC.h" #include "Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOS.h" #include "Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.h" @@ -307,6 +308,7 @@ ABISysV_s390x::Initialize(); ArchitectureArm::Initialize(); + ArchitecturePPC64::Initialize(); DisassemblerLLVMC::Initialize(); Index: source/Breakpoint/BreakpointResolverName.cpp =================================================================== --- source/Breakpoint/BreakpointResolverName.cpp +++ source/Breakpoint/BreakpointResolverName.cpp @@ -16,11 +16,13 @@ #include "Plugins/Language/CPlusPlus/CPlusPlusLanguage.h" #include "Plugins/Language/ObjC/ObjCLanguage.h" #include "lldb/Breakpoint/BreakpointLocation.h" +#include "lldb/Core/Architecture.h" #include "lldb/Core/Module.h" #include "lldb/Symbol/Block.h" #include "lldb/Symbol/Function.h" #include "lldb/Symbol/Symbol.h" #include "lldb/Symbol/SymbolContext.h" +#include "lldb/Target/Target.h" #include "lldb/Utility/Log.h" #include "lldb/Utility/StreamString.h" @@ -365,6 +367,12 @@ sc.symbol->GetPrologueByteSize(); if (prologue_byte_size) break_addr.SetOffset(break_addr.GetOffset() + prologue_byte_size); + else { + Architecture *arch = + m_breakpoint->GetTarget().GetArchitecturePlugin(); + if (arch) + arch->AdjustBreakpointAddress(sc.symbol, break_addr); + } } } Index: source/Plugins/Architecture/CMakeLists.txt =================================================================== --- source/Plugins/Architecture/CMakeLists.txt +++ source/Plugins/Architecture/CMakeLists.txt @@ -1 +1,2 @@ add_subdirectory(Arm) +add_subdirectory(PPC64) Index: source/Plugins/Architecture/PPC64/ArchitecturePPC64.h =================================================================== --- /dev/null +++ source/Plugins/Architecture/PPC64/ArchitecturePPC64.h @@ -0,0 +1,43 @@ +//===-- ArchitecturePPC64.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_PPC64_H +#define LLDB_PLUGIN_ARCHITECTURE_PPC64_H + +#include "lldb/Core/Architecture.h" + +namespace lldb_private { + +class ArchitecturePPC64 : public Architecture { +public: + static ConstString GetPluginNameStatic(); + static void Initialize(); + static void Terminate(); + + ConstString GetPluginName() override; + uint32_t GetPluginVersion() override; + + void OverrideStopInfo(Thread &thread) override {} + + //------------------------------------------------------------------ + /// This method compares the current PC with the current function's + /// local entry point, returning the bytes to skip if they match. + //------------------------------------------------------------------ + size_t GetBytesToSkip(Thread &thread) const override; + + void AdjustBreakpointAddress(Symbol *func, Address &addr) const override; + +private: + static std::unique_ptr Create(const ArchSpec &arch); + ArchitecturePPC64() = default; +}; + +} // namespace lldb_private + +#endif // LLDB_PLUGIN_ARCHITECTURE_PPC64_H Index: source/Plugins/Architecture/PPC64/ArchitecturePPC64.cpp =================================================================== --- /dev/null +++ source/Plugins/Architecture/PPC64/ArchitecturePPC64.cpp @@ -0,0 +1,84 @@ +//===-- ArchitecturePPC64.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/PPC64/ArchitecturePPC64.h" +#include "lldb/Core/PluginManager.h" +#include "lldb/Symbol/Function.h" +#include "lldb/Symbol/Symbol.h" +#include "lldb/Target/RegisterContext.h" +#include "lldb/Target/Target.h" +#include "lldb/Target/Thread.h" +#include "lldb/Utility/ArchSpec.h" + +#include "llvm/BinaryFormat/ELF.h" + +using namespace lldb_private; +using namespace lldb; + +ConstString ArchitecturePPC64::GetPluginNameStatic() { + return ConstString("ppc64"); +} + +void ArchitecturePPC64::Initialize() { + PluginManager::RegisterPlugin(GetPluginNameStatic(), + "PPC64-specific algorithms", + &ArchitecturePPC64::Create); +} + +void ArchitecturePPC64::Terminate() { + PluginManager::UnregisterPlugin(&ArchitecturePPC64::Create); +} + +std::unique_ptr ArchitecturePPC64::Create(const ArchSpec &arch) { + if (arch.GetMachine() != llvm::Triple::ppc64 && + arch.GetMachine() != llvm::Triple::ppc64le) + return nullptr; + return std::unique_ptr(new ArchitecturePPC64()); +} + +ConstString ArchitecturePPC64::GetPluginName() { return GetPluginNameStatic(); } +uint32_t ArchitecturePPC64::GetPluginVersion() { return 1; } + +static int32_t GetLocalEntryOffset(Symbol *sym) { + uint32_t flags = sym->GetFlags(); + unsigned char other = flags >> 8 & 0xFF; + return llvm::ELF::decodePPC64LocalEntryOffset(other); +} + +size_t ArchitecturePPC64::GetBytesToSkip(Thread &thread) const { + TargetSP target = thread.CalculateTarget(); + + // This code handles only ELF files + if (target->GetArchitecture().GetTriple().getObjectFormat() != + llvm::Triple::ObjectFormatType::ELF) + return 0; + + lldb::StackFrameSP curr_frame = thread.GetStackFrameAtIndex(0); + SymbolContext sc = curr_frame->GetSymbolContext(eSymbolContextSymbol); + + if (!sc.symbol) + return 0; + + addr_t curr_addr = thread.GetRegisterContext()->GetPC(); + addr_t lep = + sc.symbol->GetLoadAddress(target.get()) + GetLocalEntryOffset(sc.symbol); + if (curr_addr == lep) + return sc.symbol->GetPrologueByteSize(); + + return 0; +} + +void ArchitecturePPC64::AdjustBreakpointAddress(Symbol *func, + Address &addr) const { + int32_t loffs = GetLocalEntryOffset(func); + if (!loffs) + return; + + addr.SetOffset(addr.GetOffset() + loffs); +} Index: source/Plugins/Architecture/PPC64/CMakeLists.txt =================================================================== --- /dev/null +++ source/Plugins/Architecture/PPC64/CMakeLists.txt @@ -0,0 +1,11 @@ +add_lldb_library(lldbPluginArchitecturePPC64 PLUGIN + ArchitecturePPC64.cpp + + LINK_LIBS + lldbPluginProcessUtility + lldbCore + lldbTarget + lldbUtility + LINK_COMPONENTS + Support + ) Index: source/Target/ThreadPlanStepInRange.cpp =================================================================== --- source/Target/ThreadPlanStepInRange.cpp +++ source/Target/ThreadPlanStepInRange.cpp @@ -12,6 +12,7 @@ // Other libraries and framework includes // Project includes #include "lldb/Target/ThreadPlanStepInRange.h" +#include "lldb/Core/Architecture.h" #include "lldb/Core/Module.h" #include "lldb/Symbol/Function.h" #include "lldb/Symbol/Symbol.h" @@ -277,6 +278,13 @@ bytes_to_skip = sc.symbol->GetPrologueByteSize(); } + if (bytes_to_skip == 0) { + Architecture *arch = + m_thread.CalculateTarget()->GetArchitecturePlugin(); + if (arch) + bytes_to_skip = arch->GetBytesToSkip(m_thread); + } + if (bytes_to_skip != 0) { func_start_address.Slide(bytes_to_skip); log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP);