From 39d395f75c306a0d932a783eef039fd93d66e246 Mon Sep 17 00:00:00 2001 From: Dhruv-Srivastava Date: Wed, 7 Aug 2024 12:10:43 -0500 Subject: [PATCH 01/31] LLDB Support for AIX --- clang/lib/CodeGen/CGObjCMac.cpp | 6 +- lldb/CMakeLists.txt | 4 + lldb/cmake/modules/LLDBConfig.cmake | 2 +- lldb/include/lldb/Core/Module.h | 3 + lldb/include/lldb/Core/ModuleSpec.h | 23 +- lldb/include/lldb/Host/HostGetOpt.h | 2 +- lldb/include/lldb/Host/HostInfo.h | 3 + lldb/include/lldb/Host/HostInfoBase.h | 2 +- lldb/include/lldb/Host/XML.h | 5 + lldb/include/lldb/Host/aix/AbstractSocket.h | 25 + lldb/include/lldb/Host/aix/Host.h | 22 + lldb/include/lldb/Host/aix/HostInfoAIX.h | 42 + lldb/include/lldb/Host/aix/Ptrace.h | 62 + lldb/include/lldb/Host/aix/Support.h | 29 + lldb/include/lldb/Host/aix/Uio.h | 23 + lldb/include/lldb/Host/common/GetOptInc.h | 6 +- lldb/include/lldb/Symbol/ObjectFile.h | 5 + lldb/include/lldb/Target/ABI.h | 6 + lldb/include/lldb/Target/DynamicLoader.h | 6 + lldb/include/lldb/Target/Process.h | 14 + .../lldb/Target/RegisterContextUnwind.h | 4 + .../lldb/Target/ThreadPlanCallFunction.h | 6 + .../lldb/Utility/StringExtractorGDBRemote.h | 1 + lldb/include/lldb/lldb-private-enumerations.h | 1 + lldb/source/API/CMakeLists.txt | 108 + lldb/source/API/SBBreakpoint.cpp | 6 +- lldb/source/API/SBBreakpointLocation.cpp | 6 +- lldb/source/API/SBBreakpointName.cpp | 4 +- lldb/source/Core/DynamicLoader.cpp | 10 + lldb/source/Core/Mangled.cpp | 2 + lldb/source/Core/Module.cpp | 12 + lldb/source/Core/Section.cpp | 4 + lldb/source/Expression/DWARFExpression.cpp | 10 +- lldb/source/Host/CMakeLists.txt | 13 + lldb/source/Host/aix/AbstractSocket.cpp | 21 + lldb/source/Host/aix/Host.cpp | 304 +++ lldb/source/Host/aix/HostInfoAIX.cpp | 215 ++ lldb/source/Host/aix/Support.cpp | 44 + lldb/source/Host/common/GetOptInc.cpp | 2 +- lldb/source/Host/common/Host.cpp | 180 +- .../source/Host/common/LICENSE.aix-netbsd.txt | 125 + lldb/source/Host/common/XML.cpp | 3 + .../posix/ConnectionFileDescriptorPosix.cpp | 2 + lldb/source/Host/posix/FileSystemPosix.cpp | 2 + lldb/source/Host/posix/MainLoopPosix.cpp | 17 + .../Host/posix/ProcessLauncherPosixFork.cpp | 5 + lldb/source/Initialization/CMakeLists.txt | 2 +- .../SystemInitializerCommon.cpp | 4 +- .../Plugins/ABI/PowerPC/ABISysV_ppc64.cpp | 131 +- .../Plugins/ABI/PowerPC/ABISysV_ppc64.h | 6 + .../DynamicLoader/AIX-DYLD/CMakeLists.txt | 11 + .../AIX-DYLD/DynamicLoaderAIXDYLD.cpp | 272 +++ .../AIX-DYLD/DynamicLoaderAIXDYLD.h | 55 + .../Plugins/DynamicLoader/CMakeLists.txt | 1 + .../DynamicLoaderDarwinKernel.cpp | 4 +- .../MacOSX-DYLD/DynamicLoaderDarwin.cpp | 2 +- .../PPC64/EmulateInstructionPPC64.cpp | 196 +- .../PPC64/EmulateInstructionPPC64.h | 14 + ...nstrumentationRuntimeMainThreadChecker.cpp | 2 +- .../TSan/InstrumentationRuntimeTSan.cpp | 14 +- .../UBSan/InstrumentationRuntimeUBSan.cpp | 2 +- .../Plugins/JITLoader/GDB/JITLoaderGDB.cpp | 4 + lldb/source/Plugins/Language/ObjC/Cocoa.cpp | 2 + .../MemoryHistory/asan/MemoryHistoryASan.cpp | 2 +- .../BSD-Archive/ObjectContainerBSDArchive.cpp | 2 +- .../Big-Archive/CMakeLists.txt | 10 + .../Big-Archive/ObjectContainerBigArchive.cpp | 522 +++++ .../Big-Archive/ObjectContainerBigArchive.h | 177 ++ .../Plugins/ObjectContainer/CMakeLists.txt | 1 + lldb/source/Plugins/ObjectFile/CMakeLists.txt | 1 + .../ObjectFile/Mach-O/ObjectFileMachO.cpp | 6 +- .../Minidump/ObjectFileMinidump.cpp | 2 + .../Plugins/ObjectFile/PDB/ObjectFilePDB.cpp | 15 +- .../ObjectFile/PECOFF/ObjectFilePECOFF.cpp | 18 +- .../Plugins/ObjectFile/XCOFF/CMakeLists.txt | 13 + .../ObjectFile/XCOFF/ObjectFileXCOFF.cpp | 780 +++++++ .../ObjectFile/XCOFF/ObjectFileXCOFF.h | 243 ++ .../Python/OperatingSystemPython.cpp | 2 +- .../Plugins/Platform/AIX/CMakeLists.txt | 13 + .../Plugins/Platform/AIX/PlatformAIX.cpp | 471 ++++ .../source/Plugins/Platform/AIX/PlatformAIX.h | 74 + lldb/source/Plugins/Platform/CMakeLists.txt | 1 + .../source/Plugins/Process/AIX/CMakeLists.txt | 19 + .../Plugins/Process/AIX/NativeProcessAIX.cpp | 2048 +++++++++++++++++ .../Plugins/Process/AIX/NativeProcessAIX.h | 283 +++ .../Process/AIX/NativeRegisterContextAIX.cpp | 157 ++ .../Process/AIX/NativeRegisterContextAIX.h | 133 ++ .../AIX/NativeRegisterContextAIX_ppc64.cpp | 744 ++++++ .../AIX/NativeRegisterContextAIX_ppc64.h | 138 ++ .../Plugins/Process/AIX/NativeThreadAIX.cpp | 526 +++++ .../Plugins/Process/AIX/NativeThreadAIX.h | 126 + lldb/source/Plugins/Process/CMakeLists.txt | 3 + .../Process/Utility/InferiorCallPOSIX.cpp | 33 + .../Utility/RegisterInfoPOSIX_ppc64le.cpp | 4 + .../Plugins/Process/Utility/ThreadMemory.cpp | 2 +- .../Plugins/Process/gdb-remote/CMakeLists.txt | 5 + .../GDBRemoteCommunicationClient.cpp | 30 + .../gdb-remote/GDBRemoteCommunicationClient.h | 7 + .../GDBRemoteCommunicationServerLLGS.cpp | 28 + .../GDBRemoteCommunicationServerLLGS.h | 2 + .../Process/gdb-remote/ProcessGDBRemote.cpp | 13 +- .../Process/gdb-remote/ProcessGDBRemote.h | 8 + .../Process/mach-core/ProcessMachCore.cpp | 8 +- .../ScriptInterpreter/Python/CMakeLists.txt | 5 + .../SymbolFile/DWARF/DWARFFormValue.cpp | 4 + .../Plugins/SymbolFile/DWARF/DWARFUnit.cpp | 12 +- .../MacOSX/AppleGetThreadItemInfoHandler.cpp | 2 +- lldb/source/Symbol/DWARFCallFrameInfo.cpp | 4 +- lldb/source/Target/ABI.cpp | 9 + lldb/source/Target/CMakeLists.txt | 5 + lldb/source/Target/Process.cpp | 10 + lldb/source/Target/RegisterContextUnwind.cpp | 46 + lldb/source/Target/ThreadPlanCallFunction.cpp | 34 + lldb/source/Target/UnwindLLDB.cpp | 15 + lldb/source/Utility/ArchSpec.cpp | 18 +- .../Utility/StringExtractorGDBRemote.cpp | 2 + lldb/test/CMakeLists.txt | 2 +- lldb/test/Shell/Expr/TestIRMemoryMap.test | 2 +- lldb/test/Shell/Process/TestEnvironment.test | 2 +- lldb/tools/driver/CMakeLists.txt | 5 + lldb/tools/driver/Driver.cpp | 5 +- lldb/tools/lldb-dap/CMakeLists.txt | 4 + lldb/tools/lldb-server/CMakeLists.txt | 7 + .../lldb-server/SystemInitializerLLGS.cpp | 15 + lldb/tools/lldb-server/lldb-gdbserver.cpp | 4 + lldb/unittests/Host/FileSystemTest.cpp | 2 +- lldb/unittests/Host/posix/TerminalTest.cpp | 4 + llvm/include/llvm/Object/XCOFFObjectFile.h | 4 +- llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp | 15 +- 129 files changed, 8950 insertions(+), 76 deletions(-) create mode 100644 lldb/include/lldb/Host/aix/AbstractSocket.h create mode 100644 lldb/include/lldb/Host/aix/Host.h create mode 100644 lldb/include/lldb/Host/aix/HostInfoAIX.h create mode 100644 lldb/include/lldb/Host/aix/Ptrace.h create mode 100644 lldb/include/lldb/Host/aix/Support.h create mode 100644 lldb/include/lldb/Host/aix/Uio.h create mode 100644 lldb/source/Host/aix/AbstractSocket.cpp create mode 100644 lldb/source/Host/aix/Host.cpp create mode 100644 lldb/source/Host/aix/HostInfoAIX.cpp create mode 100644 lldb/source/Host/aix/Support.cpp create mode 100644 lldb/source/Host/common/LICENSE.aix-netbsd.txt create mode 100644 lldb/source/Plugins/DynamicLoader/AIX-DYLD/CMakeLists.txt create mode 100644 lldb/source/Plugins/DynamicLoader/AIX-DYLD/DynamicLoaderAIXDYLD.cpp create mode 100644 lldb/source/Plugins/DynamicLoader/AIX-DYLD/DynamicLoaderAIXDYLD.h create mode 100644 lldb/source/Plugins/ObjectContainer/Big-Archive/CMakeLists.txt create mode 100644 lldb/source/Plugins/ObjectContainer/Big-Archive/ObjectContainerBigArchive.cpp create mode 100644 lldb/source/Plugins/ObjectContainer/Big-Archive/ObjectContainerBigArchive.h create mode 100644 lldb/source/Plugins/ObjectFile/XCOFF/CMakeLists.txt create mode 100644 lldb/source/Plugins/ObjectFile/XCOFF/ObjectFileXCOFF.cpp create mode 100644 lldb/source/Plugins/ObjectFile/XCOFF/ObjectFileXCOFF.h create mode 100644 lldb/source/Plugins/Platform/AIX/CMakeLists.txt create mode 100644 lldb/source/Plugins/Platform/AIX/PlatformAIX.cpp create mode 100644 lldb/source/Plugins/Platform/AIX/PlatformAIX.h create mode 100644 lldb/source/Plugins/Process/AIX/CMakeLists.txt create mode 100644 lldb/source/Plugins/Process/AIX/NativeProcessAIX.cpp create mode 100644 lldb/source/Plugins/Process/AIX/NativeProcessAIX.h create mode 100644 lldb/source/Plugins/Process/AIX/NativeRegisterContextAIX.cpp create mode 100644 lldb/source/Plugins/Process/AIX/NativeRegisterContextAIX.h create mode 100644 lldb/source/Plugins/Process/AIX/NativeRegisterContextAIX_ppc64.cpp create mode 100644 lldb/source/Plugins/Process/AIX/NativeRegisterContextAIX_ppc64.h create mode 100644 lldb/source/Plugins/Process/AIX/NativeThreadAIX.cpp create mode 100644 lldb/source/Plugins/Process/AIX/NativeThreadAIX.h diff --git a/clang/lib/CodeGen/CGObjCMac.cpp b/clang/lib/CodeGen/CGObjCMac.cpp index 30f3911a8b03c2d..fc91981db68c120 100644 --- a/clang/lib/CodeGen/CGObjCMac.cpp +++ b/clang/lib/CodeGen/CGObjCMac.cpp @@ -5052,10 +5052,14 @@ std::string CGObjCCommonMac::GetSectionName(StringRef Section, case llvm::Triple::COFF: assert(Section.starts_with("__") && "expected the name to begin with __"); return ("." + Section.substr(2) + "$B").str(); + case llvm::Triple::XCOFF: + // Hack to allow "p 10+1" on AIX for lldb + assert(Section.substr(0, 2) == "__" && + "expected the name to begin with __"); + return Section.substr(2).str(); case llvm::Triple::Wasm: case llvm::Triple::GOFF: case llvm::Triple::SPIRV: - case llvm::Triple::XCOFF: case llvm::Triple::DXContainer: llvm::report_fatal_error( "Objective-C support is unimplemented for object file format"); diff --git a/lldb/CMakeLists.txt b/lldb/CMakeLists.txt index 59cdc4593463c1a..2e9ae0d0b3221c4 100644 --- a/lldb/CMakeLists.txt +++ b/lldb/CMakeLists.txt @@ -38,6 +38,10 @@ endif() include(LLDBConfig) include(AddLLDB) +if (UNIX AND ${CMAKE_SYSTEM_NAME} MATCHES "AIX") + add_definitions("-D__AIX__") +endif() + # Define the LLDB_CONFIGURATION_xxx matching the build type. if(uppercase_CMAKE_BUILD_TYPE STREQUAL "DEBUG" ) add_definitions(-DLLDB_CONFIGURATION_DEBUG) diff --git a/lldb/cmake/modules/LLDBConfig.cmake b/lldb/cmake/modules/LLDBConfig.cmake index a60921990cf775a..a0f118a11984c21 100644 --- a/lldb/cmake/modules/LLDBConfig.cmake +++ b/lldb/cmake/modules/LLDBConfig.cmake @@ -299,7 +299,7 @@ endif() # Figure out if lldb could use lldb-server. If so, then we'll # ensure we build lldb-server when an lldb target is being built. -if (CMAKE_SYSTEM_NAME MATCHES "Android|Darwin|FreeBSD|Linux|NetBSD|Windows") +if (CMAKE_SYSTEM_NAME MATCHES "Android|Darwin|FreeBSD|Linux|NetBSD|Windows|AIX") set(LLDB_CAN_USE_LLDB_SERVER ON) else() set(LLDB_CAN_USE_LLDB_SERVER OFF) diff --git a/lldb/include/lldb/Core/Module.h b/lldb/include/lldb/Core/Module.h index 5589c1c9a350dc1..3829386562795c7 100644 --- a/lldb/include/lldb/Core/Module.h +++ b/lldb/include/lldb/Core/Module.h @@ -196,6 +196,9 @@ class Module : public std::enable_shared_from_this, bool SetLoadAddress(Target &target, lldb::addr_t value, bool value_is_offset, bool &changed); + bool SetLoadAddressByType(Target &target, lldb::addr_t value, + bool value_is_offset, bool &changed, int type_id); + /// \copydoc SymbolContextScope::CalculateSymbolContext(SymbolContext*) /// /// \see SymbolContextScope diff --git a/lldb/include/lldb/Core/ModuleSpec.h b/lldb/include/lldb/Core/ModuleSpec.h index 4cbbbfa8a26e13a..4fe06412b6b0b8b 100644 --- a/lldb/include/lldb/Core/ModuleSpec.h +++ b/lldb/include/lldb/Core/ModuleSpec.h @@ -21,6 +21,7 @@ #include #include +#include namespace lldb_private { @@ -41,8 +42,26 @@ class ModuleSpec { } ModuleSpec(const FileSpec &file_spec, const ArchSpec &arch) - : m_file(file_spec), m_arch(arch), m_object_offset(0), - m_object_size(FileSystem::Instance().GetByteSize(file_spec)) {} + : m_arch(arch), m_object_offset(0) { + // parse object inside module format for example: /usr/ccs/lib/libc.a(shr_64.o) + llvm::SmallString<256> path_with_object; + file_spec.GetPath(path_with_object); + if (strstr(path_with_object.c_str(), "(") != nullptr) { + char *part; + char *str = (char *)path_with_object.c_str(); + part = strtok(str, "()"); + assert(part); + llvm::StringRef file_name(part); + part = strtok(nullptr, "()"); + assert(part); + m_object_name = ConstString(part); + m_file = FileSpec(file_name); + m_object_size = FileSystem::Instance().GetByteSize(m_file); + } else { + m_file = file_spec; + m_object_size = FileSystem::Instance().GetByteSize(file_spec); + } + } FileSpec *GetFileSpecPtr() { return (m_file ? &m_file : nullptr); } diff --git a/lldb/include/lldb/Host/HostGetOpt.h b/lldb/include/lldb/Host/HostGetOpt.h index 52cfdf4dbb89c22..f450e561d6afb19 100644 --- a/lldb/include/lldb/Host/HostGetOpt.h +++ b/lldb/include/lldb/Host/HostGetOpt.h @@ -9,7 +9,7 @@ #ifndef LLDB_HOST_HOSTGETOPT_H #define LLDB_HOST_HOSTGETOPT_H -#if !defined(_MSC_VER) && !defined(__NetBSD__) +#if !defined(_MSC_VER) && !defined(__NetBSD__) && !defined(__AIX__) #include #include diff --git a/lldb/include/lldb/Host/HostInfo.h b/lldb/include/lldb/Host/HostInfo.h index b7010d69d88e7fc..156df8cf6901df7 100644 --- a/lldb/include/lldb/Host/HostInfo.h +++ b/lldb/include/lldb/Host/HostInfo.h @@ -55,6 +55,9 @@ #elif defined(__APPLE__) #include "lldb/Host/macosx/HostInfoMacOSX.h" #define HOST_INFO_TYPE HostInfoMacOSX +#elif defined(__AIX__) +#include "lldb/Host/aix/HostInfoAIX.h" +#define HOST_INFO_TYPE HostInfoAIX #else #include "lldb/Host/posix/HostInfoPosix.h" #define HOST_INFO_TYPE HostInfoPosix diff --git a/lldb/include/lldb/Host/HostInfoBase.h b/lldb/include/lldb/Host/HostInfoBase.h index 705aad559f3b78b..29e6acf39bfb246 100644 --- a/lldb/include/lldb/Host/HostInfoBase.h +++ b/lldb/include/lldb/Host/HostInfoBase.h @@ -149,6 +149,7 @@ class HostInfoBase { return {}; } + static bool ComputeSharedLibraryDirectory(FileSpec &file_spec); /// Returns the distribution id of the host /// /// This will be something like "ubuntu", "fedora", etc. on Linux. @@ -158,7 +159,6 @@ class HostInfoBase { static llvm::StringRef GetDistributionId() { return llvm::StringRef(); } protected: - static bool ComputeSharedLibraryDirectory(FileSpec &file_spec); static bool ComputeSupportExeDirectory(FileSpec &file_spec); static bool ComputeProcessTempFileDirectory(FileSpec &file_spec); static bool ComputeGlobalTempFileDirectory(FileSpec &file_spec); diff --git a/lldb/include/lldb/Host/XML.h b/lldb/include/lldb/Host/XML.h index da0f9cd7aa8c065..cf359f7726d5d6b 100644 --- a/lldb/include/lldb/Host/XML.h +++ b/lldb/include/lldb/Host/XML.h @@ -11,6 +11,11 @@ #include "lldb/Host/Config.h" +#if defined(__AIX__) +//FIXME for AIX +#undef LLDB_ENABLE_LIBXML2 +#endif + #if LLDB_ENABLE_LIBXML2 #include #endif diff --git a/lldb/include/lldb/Host/aix/AbstractSocket.h b/lldb/include/lldb/Host/aix/AbstractSocket.h new file mode 100644 index 000000000000000..78a567a6b909532 --- /dev/null +++ b/lldb/include/lldb/Host/aix/AbstractSocket.h @@ -0,0 +1,25 @@ +//===-- AbstractSocket.h ----------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_AbstractSocket_h_ +#define liblldb_AbstractSocket_h_ + +#include "lldb/Host/posix/DomainSocket.h" + +namespace lldb_private { +class AbstractSocket : public DomainSocket { +public: + AbstractSocket(bool child_processes_inherit); + +protected: + size_t GetNameOffset() const override; + void DeleteSocketFile(llvm::StringRef name) override; +}; +} + +#endif // ifndef liblldb_AbstractSocket_h_ diff --git a/lldb/include/lldb/Host/aix/Host.h b/lldb/include/lldb/Host/aix/Host.h new file mode 100644 index 000000000000000..1e3487752995fba --- /dev/null +++ b/lldb/include/lldb/Host/aix/Host.h @@ -0,0 +1,22 @@ +//===-- Host.h --------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLDB_HOST_AIX_HOST_H +#define LLDB_HOST_AIX_HOST_H + +#include "lldb/lldb-types.h" +#include + +namespace lldb_private { + +// Get PID (i.e. the primary thread ID) corresponding to the specified TID. +std::optional getPIDForTID(lldb::pid_t tid); + +} // namespace lldb_private + +#endif // #ifndef LLDB_HOST_AIX_HOST_H diff --git a/lldb/include/lldb/Host/aix/HostInfoAIX.h b/lldb/include/lldb/Host/aix/HostInfoAIX.h new file mode 100644 index 000000000000000..ced4cf34d38a817 --- /dev/null +++ b/lldb/include/lldb/Host/aix/HostInfoAIX.h @@ -0,0 +1,42 @@ +//===-- HostInfoAIX.h -----------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef lldb_Host_aix_HostInfoAIX_h_ +#define lldb_Host_aix_HostInfoAIX_h_ + +#include "lldb/Host/posix/HostInfoPosix.h" +#include "lldb/Utility/FileSpec.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/VersionTuple.h" + +#include + +namespace lldb_private { + +class HostInfoAIX : public HostInfoPosix { + friend class HostInfoBase; + +public: + static void Initialize(SharedLibraryDirectoryHelper *helper = nullptr); + static void Terminate(); + + static llvm::VersionTuple GetOSVersion(); + static std::optional GetOSBuildString(); + static llvm::StringRef GetDistributionId(); + static FileSpec GetProgramFileSpec(); + +protected: + static bool ComputeSupportExeDirectory(FileSpec &file_spec); + static bool ComputeSystemPluginsDirectory(FileSpec &file_spec); + static bool ComputeUserPluginsDirectory(FileSpec &file_spec); + static void ComputeHostArchitectureSupport(ArchSpec &arch_32, + ArchSpec &arch_64); +}; +} + +#endif diff --git a/lldb/include/lldb/Host/aix/Ptrace.h b/lldb/include/lldb/Host/aix/Ptrace.h new file mode 100644 index 000000000000000..88928f18102d7c8 --- /dev/null +++ b/lldb/include/lldb/Host/aix/Ptrace.h @@ -0,0 +1,62 @@ +//===-- Ptrace.h ------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// This file defines ptrace functions & structures + +#ifndef liblldb_Host_aix_Ptrace_h_ +#define liblldb_Host_aix_Ptrace_h_ + +#include + +#define DEBUG_PTRACE_MAXBYTES 20 + +// Support ptrace extensions even when compiled without required kernel support +#ifndef PTRACE_GETREGS +#define PTRACE_GETREGS (PT_COMMAND_MAX+1) +#endif +#ifndef PTRACE_SETREGS +#define PTRACE_SETREGS (PT_COMMAND_MAX+2) +#endif +#ifndef PTRACE_GETFPREGS +#define PTRACE_GETFPREGS (PT_COMMAND_MAX+3) +#endif +#ifndef PTRACE_SETFPREGS +#define PTRACE_SETFPREGS (PT_COMMAND_MAX+4) +#endif +#ifndef PTRACE_GETREGSET +#define PTRACE_GETREGSET 0x4204 +#endif +#ifndef PTRACE_SETREGSET +#define PTRACE_SETREGSET 0x4205 +#endif +#ifndef PTRACE_GET_THREAD_AREA +#define PTRACE_GET_THREAD_AREA (PT_COMMAND_MAX+5) +#endif +#ifndef PTRACE_ARCH_PRCTL +#define PTRACE_ARCH_PRCTL (PT_COMMAND_MAX+6) +#endif +#ifndef ARCH_GET_FS +#define ARCH_SET_GS 0x1001 +#define ARCH_SET_FS 0x1002 +#define ARCH_GET_FS 0x1003 +#define ARCH_GET_GS 0x1004 +#endif +#ifndef PTRACE_PEEKMTETAGS +#define PTRACE_PEEKMTETAGS (PT_COMMAND_MAX+7) +#endif +#ifndef PTRACE_POKEMTETAGS +#define PTRACE_POKEMTETAGS (PT_COMMAND_MAX+8) +#endif +#ifndef PTRACE_GETVRREGS +#define PTRACE_GETVRREGS (PT_COMMAND_MAX+9) +#endif +#ifndef PTRACE_GETVSRREGS +#define PTRACE_GETVSRREGS (PT_COMMAND_MAX+10) +#endif + +#endif // liblldb_Host_aix_Ptrace_h_ diff --git a/lldb/include/lldb/Host/aix/Support.h b/lldb/include/lldb/Host/aix/Support.h new file mode 100644 index 000000000000000..27d6c2b50a35b01 --- /dev/null +++ b/lldb/include/lldb/Host/aix/Support.h @@ -0,0 +1,29 @@ +//===-- Support.h -----------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLDB_HOST_AIX_SUPPORT_H +#define LLDB_HOST_AIX_SUPPORT_H + +#include "llvm/Support/ErrorOr.h" +#include "llvm/Support/MemoryBuffer.h" +#include + +namespace lldb_private { + +llvm::ErrorOr> +getProcFile(::pid_t pid, ::pid_t tid, const llvm::Twine &file); + +llvm::ErrorOr> +getProcFile(::pid_t pid, const llvm::Twine &file); + +llvm::ErrorOr> +getProcFile(const llvm::Twine &file); + +} // namespace lldb_private + +#endif // #ifndef LLDB_HOST_AIX_SUPPORT_H diff --git a/lldb/include/lldb/Host/aix/Uio.h b/lldb/include/lldb/Host/aix/Uio.h new file mode 100644 index 000000000000000..acf79ecc6a1d0d8 --- /dev/null +++ b/lldb/include/lldb/Host/aix/Uio.h @@ -0,0 +1,23 @@ +//===-- Uio.h ---------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_Host_aix_Uio_h_ +#define liblldb_Host_aix_Uio_h_ + +#include "lldb/Host/Config.h" +#include + +// We shall provide our own implementation of process_vm_readv if it is not +// present +#if !HAVE_PROCESS_VM_READV +ssize_t process_vm_readv(::pid_t pid, const struct iovec *local_iov, + unsigned long liovcnt, const struct iovec *remote_iov, + unsigned long riovcnt, unsigned long flags); +#endif + +#endif // liblldb_Host_aix_Uio_h_ diff --git a/lldb/include/lldb/Host/common/GetOptInc.h b/lldb/include/lldb/Host/common/GetOptInc.h index 3fb9add47954173..ebb475bfaf6b8d2 100644 --- a/lldb/include/lldb/Host/common/GetOptInc.h +++ b/lldb/include/lldb/Host/common/GetOptInc.h @@ -11,11 +11,11 @@ #include "lldb/lldb-defines.h" -#if defined(_MSC_VER) +#if defined(_MSC_VER) || defined(__AIX__) #define REPLACE_GETOPT #define REPLACE_GETOPT_LONG #endif -#if defined(_MSC_VER) || defined(__NetBSD__) +#if defined(_MSC_VER) || defined(__NetBSD__) || defined(__AIX__) #define REPLACE_GETOPT_LONG_ONLY #endif @@ -35,7 +35,7 @@ struct option { int val; }; -int getopt(int argc, char *const argv[], const char *optstring); +int getopt(int argc, char *const argv[], const char *optstring) throw(); // from getopt.h extern char *optarg; diff --git a/lldb/include/lldb/Symbol/ObjectFile.h b/lldb/include/lldb/Symbol/ObjectFile.h index 8592323322e383e..bf66ccec263d247 100644 --- a/lldb/include/lldb/Symbol/ObjectFile.h +++ b/lldb/include/lldb/Symbol/ObjectFile.h @@ -401,6 +401,11 @@ class ObjectFile : public std::enable_shared_from_this, return false; } + virtual bool SetLoadAddressByType(Target &target, lldb::addr_t value, + bool value_is_offset, int type_id) { + return false; + } + /// Gets whether endian swapping should occur when extracting data from this /// object file. /// diff --git a/lldb/include/lldb/Target/ABI.h b/lldb/include/lldb/Target/ABI.h index 7b646d743346b77..281a89951ef8854 100644 --- a/lldb/include/lldb/Target/ABI.h +++ b/lldb/include/lldb/Target/ABI.h @@ -47,6 +47,12 @@ class ABI : public PluginInterface { lldb::addr_t returnAddress, llvm::ArrayRef args) const = 0; + virtual bool PrepareTrivialCall(lldb_private::Thread &thread, lldb::addr_t sp, + lldb::addr_t functionAddress, + lldb::addr_t tocAddress, + lldb::addr_t returnAddress, + llvm::ArrayRef args) const; + // Prepare trivial call used from ThreadPlanFunctionCallUsingABI // AD: // . Because i don't want to change other ABI's this is not declared pure diff --git a/lldb/include/lldb/Target/DynamicLoader.h b/lldb/include/lldb/Target/DynamicLoader.h index 0629e2faae7e9e2..7dccd317c2dca1d 100644 --- a/lldb/include/lldb/Target/DynamicLoader.h +++ b/lldb/include/lldb/Target/DynamicLoader.h @@ -359,6 +359,12 @@ class DynamicLoader : public PluginInterface { lldb::addr_t base_addr, bool base_addr_is_offset); + virtual void UpdateLoadedSectionsByType(lldb::ModuleSP module, + lldb::addr_t link_map_addr, + lldb::addr_t base_addr, + bool base_addr_is_offset, + int type_id); + // Utility method so base classes can share implementation of // UpdateLoadedSections void UpdateLoadedSectionsCommon(lldb::ModuleSP module, lldb::addr_t base_addr, diff --git a/lldb/include/lldb/Target/Process.h b/lldb/include/lldb/Target/Process.h index cf16fbc812aa48d..886ca766112c8d1 100644 --- a/lldb/include/lldb/Target/Process.h +++ b/lldb/include/lldb/Target/Process.h @@ -63,6 +63,10 @@ #include "llvm/Support/Threading.h" #include "llvm/Support/VersionTuple.h" +#if defined(__AIX__) +struct ld_xinfo; +#endif + namespace lldb_private { template struct Range; @@ -1915,6 +1919,10 @@ class Process : public std::enable_shared_from_this, Status GetMemoryRegionInfo(lldb::addr_t load_addr, MemoryRegionInfo &range_info); +#if defined(__AIX__) + Status GetLDXINFO(struct ld_xinfo *info_ptr); +#endif + /// Obtain all the mapped memory regions within this process. /// /// \param[out] region_list @@ -2855,6 +2863,12 @@ void PruneThreadPlans(); return Status("Process::DoGetMemoryRegionInfo() not supported"); } +#if defined(__AIX__) + virtual Status DoGetLDXINFO(struct ld_xinfo *info_ptr) { + return Status("Process::DoGetLDXINFO() not supported"); + } +#endif + /// Provide an override value in the subclass for lldb's /// CPU-based logic for whether watchpoint exceptions are /// received before or after an instruction executes. diff --git a/lldb/include/lldb/Target/RegisterContextUnwind.h b/lldb/include/lldb/Target/RegisterContextUnwind.h index ef8ae8840386632..00a95853800edd1 100644 --- a/lldb/include/lldb/Target/RegisterContextUnwind.h +++ b/lldb/include/lldb/Target/RegisterContextUnwind.h @@ -67,6 +67,10 @@ class RegisterContextUnwind : public lldb_private::RegisterContext { bool ReadPC(lldb::addr_t &start_pc); +#ifdef __AIX__ + bool ReadLR(lldb::addr_t &lr); +#endif + // Indicates whether this frame *behaves* like frame zero -- the currently // executing frame -- or not. This can be true in the middle of the stack // above asynchronous trap handlers (sigtramp) for instance. diff --git a/lldb/include/lldb/Target/ThreadPlanCallFunction.h b/lldb/include/lldb/Target/ThreadPlanCallFunction.h index cb6e7caebb4adfe..7880db1592e04a2 100644 --- a/lldb/include/lldb/Target/ThreadPlanCallFunction.h +++ b/lldb/include/lldb/Target/ThreadPlanCallFunction.h @@ -27,6 +27,12 @@ class ThreadPlanCallFunction : public ThreadPlan { llvm::ArrayRef args, const EvaluateExpressionOptions &options); + ThreadPlanCallFunction(Thread &thread, const Address &function, + const Address &toc, + const CompilerType &return_type, + llvm::ArrayRef args, + const EvaluateExpressionOptions &options); + ThreadPlanCallFunction(Thread &thread, const Address &function, const EvaluateExpressionOptions &options); diff --git a/lldb/include/lldb/Utility/StringExtractorGDBRemote.h b/lldb/include/lldb/Utility/StringExtractorGDBRemote.h index dd468ef5bddef08..9953bd6c24588c6 100644 --- a/lldb/include/lldb/Utility/StringExtractorGDBRemote.h +++ b/lldb/include/lldb/Utility/StringExtractorGDBRemote.h @@ -61,6 +61,7 @@ class StringExtractorGDBRemote : public StringExtractor { eServerPacketType_qQueryGDBServer, eServerPacketType_qKillSpawnedProcess, eServerPacketType_qLaunchSuccess, + eServerPacketType_qLDXINFO, eServerPacketType_qModuleInfo, eServerPacketType_qProcessInfoPID, eServerPacketType_qSpeedTest, diff --git a/lldb/include/lldb/lldb-private-enumerations.h b/lldb/include/lldb/lldb-private-enumerations.h index c24a3538f58dac5..98c1e956bf8f7b6 100644 --- a/lldb/include/lldb/lldb-private-enumerations.h +++ b/lldb/include/lldb/lldb-private-enumerations.h @@ -65,6 +65,7 @@ enum ArchitectureType { eArchTypeMachO, eArchTypeELF, eArchTypeCOFF, + eArchTypeXCOFF, kNumArchTypes }; diff --git a/lldb/source/API/CMakeLists.txt b/lldb/source/API/CMakeLists.txt index a32bc58507d8eb6..3ecdb11daef7dc8 100644 --- a/lldb/source/API/CMakeLists.txt +++ b/lldb/source/API/CMakeLists.txt @@ -40,6 +40,113 @@ add_custom_target(lldb-sbapi-dwarf-enums DEPENDS ${sb_languages_file}) set_target_properties(lldb-sbapi-dwarf-enums PROPERTIES FOLDER "LLDB/Tablegenning") +if(CMAKE_SYSTEM_NAME MATCHES "AIX") +add_lldb_library(liblldb STATIC ${option_framework} + SBAddress.cpp + SBAddressRange.cpp + SBAddressRangeList.cpp + SBAttachInfo.cpp + SBBlock.cpp + SBBreakpoint.cpp + SBBreakpointLocation.cpp + SBBreakpointName.cpp + SBBreakpointOptionCommon.cpp + SBBroadcaster.cpp + SBCommandInterpreter.cpp + SBCommandInterpreterRunOptions.cpp + SBCommandReturnObject.cpp + SBCommunication.cpp + SBCompileUnit.cpp + SBSaveCoreOptions.cpp + SBData.cpp + SBDebugger.cpp + SBDeclaration.cpp + SBEnvironment.cpp + SBError.cpp + SBEvent.cpp + SBExecutionContext.cpp + SBExpressionOptions.cpp + SBFileSpec.cpp + SBFile.cpp + SBFileSpecList.cpp + SBFormat.cpp + SBFrame.cpp + SBFunction.cpp + SBHostOS.cpp + SBInstruction.cpp + SBInstructionList.cpp + SBLanguageRuntime.cpp + SBLaunchInfo.cpp + SBLineEntry.cpp + SBListener.cpp + SBMemoryRegionInfo.cpp + SBMemoryRegionInfoList.cpp + SBModule.cpp + SBModuleSpec.cpp + SBPlatform.cpp + SBProcess.cpp + SBProcessInfo.cpp + SBProcessInfoList.cpp + SBQueue.cpp + SBQueueItem.cpp + SBReproducer.cpp + SBScriptObject.cpp + SBSection.cpp + SBSourceManager.cpp + SBStatisticsOptions.cpp + SBStream.cpp + SBStringList.cpp + SBStructuredData.cpp + SBSymbol.cpp + SBSymbolContext.cpp + SBSymbolContextList.cpp + SBTarget.cpp + SBThread.cpp + SBThreadCollection.cpp + SBThreadPlan.cpp + SBTrace.cpp + SBTraceCursor.cpp + SBType.cpp + SBTypeCategory.cpp + SBTypeEnumMember.cpp + SBTypeFilter.cpp + SBTypeFormat.cpp + SBTypeNameSpecifier.cpp + SBTypeSummary.cpp + SBTypeSynthetic.cpp + SBValue.cpp + SBValueList.cpp + SBVariablesOptions.cpp + SBWatchpoint.cpp + SBWatchpointOptions.cpp + SBUnixSignals.cpp + SystemInitializerFull.cpp + ${lldb_python_wrapper} + ${lldb_lua_wrapper} + + DEPENDS + lldb-sbapi-dwarf-enums + + LINK_LIBS + lldbBreakpoint + lldbCore + lldbDataFormatters + lldbExpression + lldbHost + lldbInitialization + lldbInterpreter + lldbSymbol + lldbTarget + lldbUtility + lldbVersion + ${LLDB_ALL_PLUGINS} + LINK_COMPONENTS + Support + + ${option_install_prefix} +) + +else() add_lldb_library(liblldb SHARED ${option_framework} SBAddress.cpp SBAddressRange.cpp @@ -144,6 +251,7 @@ add_lldb_library(liblldb SHARED ${option_framework} ${option_install_prefix} ) +endif() # lib/pythonX.Y/dist-packages/lldb/_lldb.so is a symlink to lib/liblldb.so, # which depends on lib/libLLVM*.so (BUILD_SHARED_LIBS) or lib/libLLVM-10git.so diff --git a/lldb/source/API/SBBreakpoint.cpp b/lldb/source/API/SBBreakpoint.cpp index 3d908047f9455b5..728fe04d14d927b 100644 --- a/lldb/source/API/SBBreakpoint.cpp +++ b/lldb/source/API/SBBreakpoint.cpp @@ -342,7 +342,7 @@ uint32_t SBBreakpoint::GetIgnoreCount() const { return count; } -void SBBreakpoint::SetThreadID(tid_t tid) { +void SBBreakpoint::SetThreadID(lldb::tid_t tid) { LLDB_INSTRUMENT_VA(this, tid); BreakpointSP bkpt_sp = GetSP(); @@ -353,10 +353,10 @@ void SBBreakpoint::SetThreadID(tid_t tid) { } } -tid_t SBBreakpoint::GetThreadID() { +lldb::tid_t SBBreakpoint::GetThreadID() { LLDB_INSTRUMENT_VA(this); - tid_t tid = LLDB_INVALID_THREAD_ID; + lldb::tid_t tid = LLDB_INVALID_THREAD_ID; BreakpointSP bkpt_sp = GetSP(); if (bkpt_sp) { std::lock_guard guard( diff --git a/lldb/source/API/SBBreakpointLocation.cpp b/lldb/source/API/SBBreakpointLocation.cpp index 75b66364d4f1ae2..fad9a4076a54fbd 100644 --- a/lldb/source/API/SBBreakpointLocation.cpp +++ b/lldb/source/API/SBBreakpointLocation.cpp @@ -302,7 +302,7 @@ bool SBBreakpointLocation::GetCommandLineCommands(SBStringList &commands) { return has_commands; } -void SBBreakpointLocation::SetThreadID(tid_t thread_id) { +void SBBreakpointLocation::SetThreadID(lldb::tid_t thread_id) { LLDB_INSTRUMENT_VA(this, thread_id); BreakpointLocationSP loc_sp = GetSP(); @@ -313,10 +313,10 @@ void SBBreakpointLocation::SetThreadID(tid_t thread_id) { } } -tid_t SBBreakpointLocation::GetThreadID() { +lldb::tid_t SBBreakpointLocation::GetThreadID() { LLDB_INSTRUMENT_VA(this); - tid_t tid = LLDB_INVALID_THREAD_ID; + lldb::tid_t tid = LLDB_INVALID_THREAD_ID; BreakpointLocationSP loc_sp = GetSP(); if (loc_sp) { std::lock_guard guard( diff --git a/lldb/source/API/SBBreakpointName.cpp b/lldb/source/API/SBBreakpointName.cpp index 7f63aaf6fa7d5eb..5c7c0a8f6504b04 100644 --- a/lldb/source/API/SBBreakpointName.cpp +++ b/lldb/source/API/SBBreakpointName.cpp @@ -347,7 +347,7 @@ bool SBBreakpointName::GetAutoContinue() { return bp_name->GetOptions().IsAutoContinue(); } -void SBBreakpointName::SetThreadID(tid_t tid) { +void SBBreakpointName::SetThreadID(lldb::tid_t tid) { LLDB_INSTRUMENT_VA(this, tid); BreakpointName *bp_name = GetBreakpointName(); @@ -361,7 +361,7 @@ void SBBreakpointName::SetThreadID(tid_t tid) { UpdateName(*bp_name); } -tid_t SBBreakpointName::GetThreadID() { +lldb::tid_t SBBreakpointName::GetThreadID() { LLDB_INSTRUMENT_VA(this); BreakpointName *bp_name = GetBreakpointName(); diff --git a/lldb/source/Core/DynamicLoader.cpp b/lldb/source/Core/DynamicLoader.cpp index 7758a87403b5a3b..ea43a7f98b69f44 100644 --- a/lldb/source/Core/DynamicLoader.cpp +++ b/lldb/source/Core/DynamicLoader.cpp @@ -113,6 +113,16 @@ void DynamicLoader::UpdateLoadedSections(ModuleSP module, addr_t link_map_addr, UpdateLoadedSectionsCommon(module, base_addr, base_addr_is_offset); } +void DynamicLoader::UpdateLoadedSectionsByType(lldb::ModuleSP module, + lldb::addr_t link_map_addr, + lldb::addr_t base_addr, + bool base_addr_is_offset, + int type_id) { + bool changed; + module->SetLoadAddressByType(m_process->GetTarget(), base_addr, base_addr_is_offset, + changed, type_id); +} + void DynamicLoader::UpdateLoadedSectionsCommon(ModuleSP module, addr_t base_addr, bool base_addr_is_offset) { diff --git a/lldb/source/Core/Mangled.cpp b/lldb/source/Core/Mangled.cpp index 387c4fac6b0f8c3..43c5b043ef7a288 100644 --- a/lldb/source/Core/Mangled.cpp +++ b/lldb/source/Core/Mangled.cpp @@ -167,12 +167,14 @@ static char *GetItaniumDemangledStr(const char *M) { "Expected demangled_size to return length including trailing null"); } +#if !defined(__AIX__) if (Log *log = GetLog(LLDBLog::Demangle)) { if (demangled_cstr) LLDB_LOGF(log, "demangled itanium: %s -> \"%s\"", M, demangled_cstr); else LLDB_LOGF(log, "demangled itanium: %s -> error: failed to demangle", M); } +#endif return demangled_cstr; } diff --git a/lldb/source/Core/Module.cpp b/lldb/source/Core/Module.cpp index f9d7832254f4643..044a5d29978e847 100644 --- a/lldb/source/Core/Module.cpp +++ b/lldb/source/Core/Module.cpp @@ -1510,6 +1510,18 @@ bool Module::SetLoadAddress(Target &target, lldb::addr_t value, return false; } +bool Module::SetLoadAddressByType(Target &target, lldb::addr_t value, + bool value_is_offset, bool &changed, int type_id) { + ObjectFile *object_file = GetObjectFile(); + if (object_file != nullptr) { + changed = object_file->SetLoadAddressByType(target, value, value_is_offset, type_id); + return true; + } else { + changed = false; + } + return false; +} + bool Module::MatchesModuleSpec(const ModuleSpec &module_ref) { const UUID &uuid = module_ref.GetUUID(); diff --git a/lldb/source/Core/Section.cpp b/lldb/source/Core/Section.cpp index 0763e88d4608f40..9ed55853930a674 100644 --- a/lldb/source/Core/Section.cpp +++ b/lldb/source/Core/Section.cpp @@ -263,6 +263,10 @@ bool Section::ResolveContainedAddress(addr_t offset, Address &so_addr, bool Section::ContainsFileAddress(addr_t vm_addr) const { const addr_t file_addr = GetFileAddress(); +#ifdef __AIX__ + if (file_addr == 0) + return false; +#endif if (file_addr != LLDB_INVALID_ADDRESS && !IsThreadSpecific()) { if (file_addr <= vm_addr) { const addr_t offset = (vm_addr - file_addr) * m_target_byte_size; diff --git a/lldb/source/Expression/DWARFExpression.cpp b/lldb/source/Expression/DWARFExpression.cpp index 444e44b3928919f..c1feec990f989d0 100644 --- a/lldb/source/Expression/DWARFExpression.cpp +++ b/lldb/source/Expression/DWARFExpression.cpp @@ -130,7 +130,7 @@ static llvm::Error ReadRegisterValueAsScalar(RegisterContext *reg_ctx, /// Return the length in bytes of the set of operands for \p op. No guarantees /// are made on the state of \p data after this call. -static offset_t GetOpcodeDataSize(const DataExtractor &data, +static lldb::offset_t GetOpcodeDataSize(const DataExtractor &data, const lldb::offset_t data_offset, const uint8_t op, const DWARFUnit *dwarf_cu) { lldb::offset_t offset = data_offset; @@ -358,7 +358,7 @@ lldb::addr_t DWARFExpression::GetLocation_DW_OP_addr(const DWARFUnit *dwarf_cu, error = true; break; } - const offset_t op_arg_size = + const lldb::offset_t op_arg_size = GetOpcodeDataSize(m_data, offset, op, dwarf_cu); if (op_arg_size == LLDB_INVALID_OFFSET) { error = true; @@ -418,7 +418,7 @@ bool DWARFExpression::Update_DW_OP_addr(const DWARFUnit *dwarf_cu, m_data.SetData(encoder.GetDataBuffer()); return true; } - const offset_t op_arg_size = + const lldb::offset_t op_arg_size = GetOpcodeDataSize(m_data, offset, op, dwarf_cu); if (op_arg_size == LLDB_INVALID_OFFSET) break; @@ -435,7 +435,7 @@ bool DWARFExpression::ContainsThreadLocalStorage( if (op == DW_OP_form_tls_address || op == DW_OP_GNU_push_tls_address) return true; - const offset_t op_arg_size = + const lldb::offset_t op_arg_size = GetOpcodeDataSize(m_data, offset, op, dwarf_cu); if (op_arg_size == LLDB_INVALID_OFFSET) return false; @@ -515,7 +515,7 @@ bool DWARFExpression::LinkThreadLocalStorage( } if (!decoded_data) { - const offset_t op_arg_size = + const lldb::offset_t op_arg_size = GetOpcodeDataSize(m_data, offset, op, dwarf_cu); if (op_arg_size == LLDB_INVALID_OFFSET) return false; diff --git a/lldb/source/Host/CMakeLists.txt b/lldb/source/Host/CMakeLists.txt index c2e091ee8555b74..5374b1688195082 100644 --- a/lldb/source/Host/CMakeLists.txt +++ b/lldb/source/Host/CMakeLists.txt @@ -7,6 +7,11 @@ if (APPLE AND LLVM_ENABLE_LOCAL_SUBMODULE_VISIBILITY) endif() endif() +if (UNIX AND ${CMAKE_SYSTEM_NAME} MATCHES "AIX") + remove_definitions("-D_XOPEN_SOURCE=700") + add_definitions("-D_ALL_SOURCE") +endif() + macro(add_host_subdirectory group) list(APPEND HOST_SOURCES ${ARGN}) source_group(${group} FILES ${ARGN}) @@ -133,6 +138,14 @@ else() openbsd/Host.cpp openbsd/HostInfoOpenBSD.cpp ) + + elseif (CMAKE_SYSTEM_NAME MATCHES "AIX") + add_host_subdirectory(aix + aix/AbstractSocket.cpp + aix/Host.cpp + aix/HostInfoAIX.cpp + aix/Support.cpp + ) endif() endif() diff --git a/lldb/source/Host/aix/AbstractSocket.cpp b/lldb/source/Host/aix/AbstractSocket.cpp new file mode 100644 index 000000000000000..bfb67d452f7ec07 --- /dev/null +++ b/lldb/source/Host/aix/AbstractSocket.cpp @@ -0,0 +1,21 @@ +//===-- AbstractSocket.cpp ------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "lldb/Host/aix/AbstractSocket.h" + +#include "llvm/ADT/StringRef.h" + +using namespace lldb; +using namespace lldb_private; + +AbstractSocket::AbstractSocket(bool child_processes_inherit) + : DomainSocket(ProtocolUnixAbstract, child_processes_inherit) {} + +size_t AbstractSocket::GetNameOffset() const { return 1; } + +void AbstractSocket::DeleteSocketFile(llvm::StringRef name) {} diff --git a/lldb/source/Host/aix/Host.cpp b/lldb/source/Host/aix/Host.cpp new file mode 100644 index 000000000000000..d82cb9049d389f9 --- /dev/null +++ b/lldb/source/Host/aix/Host.cpp @@ -0,0 +1,304 @@ +//===-- source/Host/aix/Host.cpp ----------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "llvm/ADT/StringSwitch.h" +#include "llvm/Object/ELF.h" +#include "llvm/Support/ScopedPrinter.h" + +#include "lldb/Utility/LLDBLog.h" +#include "lldb/Utility/Log.h" +#include "lldb/Utility/ProcessInfo.h" +#include "lldb/Utility/Status.h" + +#include "lldb/Host/FileSystem.h" +#include "lldb/Host/Host.h" +#include "lldb/Host/HostInfo.h" +#include "lldb/Host/aix/Host.h" +#include "lldb/Host/aix/Support.h" +#include "lldb/Utility/DataExtractor.h" +#include "llvm/BinaryFormat/XCOFF.h" + +#include +#include + +using namespace llvm; +using namespace lldb; +using namespace lldb_private; + +namespace { +enum class ProcessState { + Unknown, + Dead, + DiskSleep, + Idle, + Paging, + Parked, + Running, + Sleeping, + TracedOrStopped, + Zombie, +}; +} + +namespace lldb_private { +class ProcessLaunchInfo; +} + +static bool GetStatusInfo(::pid_t Pid, ProcessInstanceInfo &ProcessInfo, + ProcessState &State, ::pid_t &TracerPid, + ::pid_t &Tgid) { + Log *log = GetLog(LLDBLog::Host); + + auto BufferOrError = getProcFile(Pid, "status"); + if (!BufferOrError) + return false; + + llvm::StringRef Rest = BufferOrError.get()->getBuffer(); + while (!Rest.empty()) { + llvm::StringRef Line; + std::tie(Line, Rest) = Rest.split('\n'); + + if (Line.consume_front("Gid:")) { + // Real, effective, saved set, and file system GIDs. Read the first two. + Line = Line.ltrim(); + uint32_t RGid, EGid; + Line.consumeInteger(10, RGid); + Line = Line.ltrim(); + Line.consumeInteger(10, EGid); + + ProcessInfo.SetGroupID(RGid); + ProcessInfo.SetEffectiveGroupID(EGid); + } else if (Line.consume_front("Uid:")) { + // Real, effective, saved set, and file system UIDs. Read the first two. + Line = Line.ltrim(); + uint32_t RUid, EUid; + Line.consumeInteger(10, RUid); + Line = Line.ltrim(); + Line.consumeInteger(10, EUid); + + ProcessInfo.SetUserID(RUid); + ProcessInfo.SetEffectiveUserID(EUid); + } else if (Line.consume_front("PPid:")) { + ::pid_t PPid; + Line.ltrim().consumeInteger(10, PPid); + ProcessInfo.SetParentProcessID(PPid); + } else if (Line.consume_front("State:")) { + State = llvm::StringSwitch(Line.ltrim().take_front(1)) + .Case("D", ProcessState::DiskSleep) + .Case("I", ProcessState::Idle) + .Case("R", ProcessState::Running) + .Case("S", ProcessState::Sleeping) + .CaseLower("T", ProcessState::TracedOrStopped) + .Case("W", ProcessState::Paging) + .Case("P", ProcessState::Parked) + .Case("X", ProcessState::Dead) + .Case("Z", ProcessState::Zombie) + .Default(ProcessState::Unknown); + if (State == ProcessState::Unknown) { + LLDB_LOG(log, "Unknown process state {0}", Line); + } + } else if (Line.consume_front("TracerPid:")) { + Line = Line.ltrim(); + Line.consumeInteger(10, TracerPid); + } else if (Line.consume_front("Tgid:")) { + Line = Line.ltrim(); + Line.consumeInteger(10, Tgid); + } + } + return true; +} + +static bool IsDirNumeric(const char *dname) { + for (; *dname; dname++) { + if (!isdigit(*dname)) + return false; + } + return true; +} + +static void GetProcessArgs(::pid_t pid, ProcessInstanceInfo &process_info) { + auto BufferOrError = getProcFile(pid, "cmdline"); + if (!BufferOrError) + return; + std::unique_ptr Cmdline = std::move(*BufferOrError); + + llvm::StringRef Arg0, Rest; + std::tie(Arg0, Rest) = Cmdline->getBuffer().split('\0'); + process_info.SetArg0(Arg0); + while (!Rest.empty()) { + llvm::StringRef Arg; + std::tie(Arg, Rest) = Rest.split('\0'); + process_info.GetArguments().AppendArgument(Arg); + } +} + +static void GetExePathAndArch(::pid_t pid, ProcessInstanceInfo &process_info) { + Log *log = GetLog(LLDBLog::Process); + std::string ExePath(PATH_MAX, '\0'); + std::string Basename(PATH_MAX, '\0'); + struct psinfo psinfoData; + + // We can't use getProcFile here because proc/[pid]/exe is a symbolic link. + llvm::SmallString<64> ProcExe; + (llvm::Twine("/proc/") + llvm::Twine(pid) + "/cwd").toVector(ProcExe); + + ssize_t len = readlink(ProcExe.c_str(), &ExePath[0], PATH_MAX); + if (len > 0) { + ExePath.resize(len); + + //FIXME: hack to get basename + struct stat statData; + + std::ostringstream oss; + + oss << "/proc/" << std::dec << pid << "/psinfo"; + assert(stat(oss.str().c_str(), &statData) == 0); + + const int fd = open(oss.str().c_str(), O_RDONLY); + assert (fd >= 0); + + ssize_t readNum = read(fd, &psinfoData, sizeof(psinfoData)); + assert (readNum >= 0); + + close (fd); + } else { + LLDB_LOG(log, "failed to read link exe link for {0}: {1}", pid, + Status(errno, eErrorTypePOSIX)); + ExePath.resize(0); + } + + llvm::StringRef PathRef = std::string(&(psinfoData.pr_psargs[0])); + + if (!PathRef.empty()) { + process_info.GetExecutableFile().SetFile(PathRef, FileSpec::Style::native); + ArchSpec arch_spec = ArchSpec(); + arch_spec.SetArchitecture(eArchTypeXCOFF, XCOFF::TCPU_PPC64, LLDB_INVALID_CPUTYPE, llvm::Triple::AIX); + process_info.SetArchitecture(arch_spec); + } +} + +static void GetProcessEnviron(::pid_t pid, ProcessInstanceInfo &process_info) { + // Get the process environment. + auto BufferOrError = getProcFile(pid, "environ"); + if (!BufferOrError) + return; + + std::unique_ptr Environ = std::move(*BufferOrError); + llvm::StringRef Rest = Environ->getBuffer(); + while (!Rest.empty()) { + llvm::StringRef Var; + std::tie(Var, Rest) = Rest.split('\0'); + process_info.GetEnvironment().insert(Var); + } +} + +static bool GetProcessAndStatInfo(::pid_t pid, + ProcessInstanceInfo &process_info, + ProcessState &State, ::pid_t &tracerpid) { + ::pid_t tgid; + tracerpid = 0; + process_info.Clear(); + + process_info.SetProcessID(pid); + + GetExePathAndArch(pid, process_info); + GetProcessArgs(pid, process_info); + GetProcessEnviron(pid, process_info); + + // Get User and Group IDs and get tracer pid. + if (!GetStatusInfo(pid, process_info, State, tracerpid, tgid)) + return false; + + return true; +} + +uint32_t Host::FindProcessesImpl(const ProcessInstanceInfoMatch &match_info, + ProcessInstanceInfoList &process_infos) { + static const char procdir[] = "/proc/"; + + DIR *dirproc = opendir(procdir); + if (dirproc) { + struct dirent *direntry = nullptr; + const uid_t our_uid = getuid(); + const lldb::pid_t our_pid = getpid(); + bool all_users = match_info.GetMatchAllUsers(); + + while ((direntry = readdir(dirproc)) != nullptr) { + /* + if (direntry->d_type != DT_DIR || !IsDirNumeric(direntry->d_name)) + continue; + */ + + lldb::pid_t pid = atoi(direntry->d_name); + + // Skip this process. + if (pid == our_pid) + continue; + + ::pid_t tracerpid; + ProcessState State; + ProcessInstanceInfo process_info; + + if (!GetProcessAndStatInfo(pid, process_info, State, tracerpid)) + continue; + + // Skip if process is being debugged. + if (tracerpid != 0) + continue; + + if (State == ProcessState::Zombie) + continue; + + // Check for user match if we're not matching all users and not running + // as root. + if (!all_users && (our_uid != 0) && (process_info.GetUserID() != our_uid)) + continue; + + if (match_info.Matches(process_info)) { + process_infos.push_back(process_info); + } + } + + closedir(dirproc); + } + + return process_infos.size(); +} + +bool Host::GetProcessInfo(lldb::pid_t pid, ProcessInstanceInfo &process_info) { + ::pid_t tracerpid; + ProcessState State; + return GetProcessAndStatInfo(pid, process_info, State, tracerpid); +} + +Environment Host::GetEnvironment() { return Environment(environ); } + +Status Host::ShellExpandArguments(ProcessLaunchInfo &launch_info) { + return Status("unimplemented"); +} + +std::optional lldb_private::getPIDForTID(lldb::pid_t tid) { + ::pid_t tracerpid, tgid = LLDB_INVALID_PROCESS_ID; + ProcessInstanceInfo process_info; + ProcessState state; + + if (!GetStatusInfo(tid, process_info, state, tracerpid, tgid) || + tgid == LLDB_INVALID_PROCESS_ID) + return std::nullopt; + return tgid; +} diff --git a/lldb/source/Host/aix/HostInfoAIX.cpp b/lldb/source/Host/aix/HostInfoAIX.cpp new file mode 100644 index 000000000000000..8bda09e01741b6a --- /dev/null +++ b/lldb/source/Host/aix/HostInfoAIX.cpp @@ -0,0 +1,215 @@ +//===-- HostInfoAIX.cpp -------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "lldb/Host/aix/HostInfoAIX.h" +#include "lldb/Host/Config.h" +#include "lldb/Host/FileSystem.h" +#include "lldb/Utility/LLDBLog.h" +#include "lldb/Utility/Log.h" + +#include "llvm/Support/Threading.h" + +#include +#include +#include +#include +#include + +#include +#include + +using namespace lldb_private; + +namespace { +struct HostInfoAIXFields { + llvm::once_flag m_distribution_once_flag; + std::string m_distribution_id; + llvm::once_flag m_os_version_once_flag; + llvm::VersionTuple m_os_version; +}; +} // namespace + +static HostInfoAIXFields *g_fields = nullptr; + +void HostInfoAIX::Initialize(SharedLibraryDirectoryHelper *helper) { + HostInfoPosix::Initialize(helper); + + g_fields = new HostInfoAIXFields(); +} + +void HostInfoAIX::Terminate() { + assert(g_fields && "Missing call to Initialize?"); + delete g_fields; + g_fields = nullptr; + HostInfoBase::Terminate(); +} + +llvm::VersionTuple HostInfoAIX::GetOSVersion() { + assert(g_fields && "Missing call to Initialize?"); + llvm::call_once(g_fields->m_os_version_once_flag, []() { + struct utsname un; + if (uname(&un) != 0) + return; + + llvm::StringRef release = un.release; + // The kernel release string can include a lot of stuff (e.g. + // 4.9.0-6-amd64). We're only interested in the numbered prefix. + release = release.substr(0, release.find_first_not_of("0123456789.")); + g_fields->m_os_version.tryParse(release); + }); + + return g_fields->m_os_version; +} + +std::optional HostInfoAIX::GetOSBuildString() { + struct utsname un; + ::memset(&un, 0, sizeof(utsname)); + + if (uname(&un) < 0) + return std::nullopt; + + return std::string(un.release); +} + +llvm::StringRef HostInfoAIX::GetDistributionId() { + assert(g_fields && "Missing call to Initialize?"); + // Try to run 'lbs_release -i', and use that response for the distribution + // id. + llvm::call_once(g_fields->m_distribution_once_flag, []() { + Log *log = GetLog(LLDBLog::Host); + LLDB_LOGF(log, "attempting to determine AIX distribution..."); + + // check if the lsb_release command exists at one of the following paths + const char *const exe_paths[] = {"/bin/lsb_release", + "/usr/bin/lsb_release"}; + + for (size_t exe_index = 0; + exe_index < sizeof(exe_paths) / sizeof(exe_paths[0]); ++exe_index) { + const char *const get_distribution_info_exe = exe_paths[exe_index]; + if (access(get_distribution_info_exe, F_OK)) { + // this exe doesn't exist, move on to next exe + LLDB_LOGF(log, "executable doesn't exist: %s", + get_distribution_info_exe); + continue; + } + + // execute the distribution-retrieval command, read output + std::string get_distribution_id_command(get_distribution_info_exe); + get_distribution_id_command += " -i"; + + FILE *file = popen(get_distribution_id_command.c_str(), "r"); + if (!file) { + LLDB_LOGF(log, + "failed to run command: \"%s\", cannot retrieve " + "platform information", + get_distribution_id_command.c_str()); + break; + } + + // retrieve the distribution id string. + char distribution_id[256] = {'\0'}; + if (fgets(distribution_id, sizeof(distribution_id) - 1, file) != + nullptr) { + LLDB_LOGF(log, "distribution id command returned \"%s\"", + distribution_id); + + const char *const distributor_id_key = "Distributor ID:\t"; + if (strstr(distribution_id, distributor_id_key)) { + // strip newlines + std::string id_string(distribution_id + strlen(distributor_id_key)); + id_string.erase(std::remove(id_string.begin(), id_string.end(), '\n'), + id_string.end()); + + // lower case it and convert whitespace to underscores + std::transform( + id_string.begin(), id_string.end(), id_string.begin(), + [](char ch) { return tolower(isspace(ch) ? '_' : ch); }); + + g_fields->m_distribution_id = id_string; + LLDB_LOGF(log, "distribution id set to \"%s\"", + g_fields->m_distribution_id.c_str()); + } else { + LLDB_LOGF(log, "failed to find \"%s\" field in \"%s\"", + distributor_id_key, distribution_id); + } + } else { + LLDB_LOGF(log, + "failed to retrieve distribution id, \"%s\" returned no" + " lines", + get_distribution_id_command.c_str()); + } + + // clean up the file + pclose(file); + } + }); + + return g_fields->m_distribution_id; +} + +FileSpec HostInfoAIX::GetProgramFileSpec() { + static FileSpec g_program_filespec; + + if (!g_program_filespec) { + char exe_path[PATH_MAX]; + ssize_t len = readlink("/proc/self/exe", exe_path, sizeof(exe_path) - 1); + if (len > 0) { + exe_path[len] = 0; + g_program_filespec.SetFile(exe_path, FileSpec::Style::native); + } + } + + return g_program_filespec; +} + +bool HostInfoAIX::ComputeSupportExeDirectory(FileSpec &file_spec) { + if (HostInfoPosix::ComputeSupportExeDirectory(file_spec) && + file_spec.IsAbsolute() && FileSystem::Instance().Exists(file_spec)) + return true; + file_spec.SetDirectory(GetProgramFileSpec().GetDirectory()); + return !file_spec.GetDirectory().IsEmpty(); +} + +bool HostInfoAIX::ComputeSystemPluginsDirectory(FileSpec &file_spec) { + FileSpec temp_file("/usr/" LLDB_INSTALL_LIBDIR_BASENAME "/lldb/plugins"); + FileSystem::Instance().Resolve(temp_file); + file_spec.SetDirectory(temp_file.GetPath()); + return true; +} + +bool HostInfoAIX::ComputeUserPluginsDirectory(FileSpec &file_spec) { + // XDG Base Directory Specification + // http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html If + // XDG_DATA_HOME exists, use that, otherwise use ~/.local/share/lldb. + const char *xdg_data_home = getenv("XDG_DATA_HOME"); + if (xdg_data_home && xdg_data_home[0]) { + std::string user_plugin_dir(xdg_data_home); + user_plugin_dir += "/lldb"; + file_spec.SetDirectory(user_plugin_dir.c_str()); + } else + file_spec.SetDirectory("~/.local/share/lldb"); + return true; +} + +void HostInfoAIX::ComputeHostArchitectureSupport(ArchSpec &arch_32, + ArchSpec &arch_64) { + HostInfoPosix::ComputeHostArchitectureSupport(arch_32, arch_64); + + const char *distribution_id = GetDistributionId().data(); + + // On Linux, "unknown" in the vendor slot isn't what we want for the default + // triple. It's probably an artifact of config.guess. + if (arch_32.IsValid()) { + if (arch_32.GetTriple().getVendor() == llvm::Triple::UnknownVendor) + arch_32.GetTriple().setVendorName(llvm::StringRef()); + } + if (arch_64.IsValid()) { + if (arch_64.GetTriple().getVendor() == llvm::Triple::UnknownVendor) + arch_64.GetTriple().setVendorName(llvm::StringRef()); + } +} diff --git a/lldb/source/Host/aix/Support.cpp b/lldb/source/Host/aix/Support.cpp new file mode 100644 index 000000000000000..1bf26621901270c --- /dev/null +++ b/lldb/source/Host/aix/Support.cpp @@ -0,0 +1,44 @@ +//===-- Support.cpp -------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "lldb/Host/aix/Support.h" +#include "lldb/Utility/LLDBLog.h" +#include "lldb/Utility/Log.h" +#include "llvm/Support/MemoryBuffer.h" + +llvm::ErrorOr> +lldb_private::getProcFile(::pid_t pid, ::pid_t tid, const llvm::Twine &file) { + Log *log = GetLog(LLDBLog::Host); + std::string File = + ("/proc/" + llvm::Twine(pid) + "/task/" + llvm::Twine(tid) + "/" + file) + .str(); + auto Ret = llvm::MemoryBuffer::getFileAsStream(File); + if (!Ret) + LLDB_LOG(log, "Failed to open {0}: {1}", File, Ret.getError().message()); + return Ret; +} + +llvm::ErrorOr> +lldb_private::getProcFile(::pid_t pid, const llvm::Twine &file) { + Log *log = GetLog(LLDBLog::Host); + std::string File = ("/proc/" + llvm::Twine(pid) + "/" + file).str(); + auto Ret = llvm::MemoryBuffer::getFileAsStream(File); + if (!Ret) + LLDB_LOG(log, "Failed to open {0}: {1}", File, Ret.getError().message()); + return Ret; +} + +llvm::ErrorOr> +lldb_private::getProcFile(const llvm::Twine &file) { + Log *log = GetLog(LLDBLog::Host); + std::string File = ("/proc/" + file).str(); + auto Ret = llvm::MemoryBuffer::getFileAsStream(File); + if (!Ret) + LLDB_LOG(log, "Failed to open {0}: {1}", File, Ret.getError().message()); + return Ret; +} diff --git a/lldb/source/Host/common/GetOptInc.cpp b/lldb/source/Host/common/GetOptInc.cpp index c2044b68732215a..e0ae2aa1774b3f0 100644 --- a/lldb/source/Host/common/GetOptInc.cpp +++ b/lldb/source/Host/common/GetOptInc.cpp @@ -409,7 +409,7 @@ static int getopt_internal(int nargc, char *const *nargv, const char *options, * [eventually this will replace the BSD getopt] */ #if defined(REPLACE_GETOPT) -int getopt(int nargc, char *const *nargv, const char *options) { +int getopt(int nargc, char *const *nargv, const char *options) throw() { /* * We don't pass FLAG_PERMUTE to getopt_internal() since diff --git a/lldb/source/Host/common/Host.cpp b/lldb/source/Host/common/Host.cpp index e03d36e9cad4a0e..2fd7111a94fb20f 100644 --- a/lldb/source/Host/common/Host.cpp +++ b/lldb/source/Host/common/Host.cpp @@ -357,9 +357,183 @@ bool Host::ResolveExecutableInBundle(FileSpec &file) { return false; } #ifndef _WIN32 +#if defined(__AIX__) + +#include +extern char **p_xargv; + +/* Fix missing Dl_info & dladdr in AIX + * The code is taken from netbsd.org (src/crypto/external/bsd/openssl/dist/crypto/dso/dso_dlfcn.c) + * except strlcpy & strlcat (those are taken from openbsd.org (src/lib/libc/string)) + */ +/*- + * See IBM's AIX Version 7.2, Technical Reference: + * Base Operating System and Extensions, Volume 1 and 2 + * https://www.ibm.com/support/knowledgecenter/ssw_aix_72/com.ibm.aix.base/technicalreferences.htm + */ +#include +#include + +/* strlcpy: + * Copy string src to buffer dst of size dsize. At most dsize-1 + * chars will be copied. Always NUL terminates (unless dsize == 0). + * Returns strlen(src); if retval >= dsize, truncation occurred. + */ +size_t strlcpy(char *dst, const char *src, size_t dsize) +{ + const char *osrc = src; + size_t nleft = dsize; + + /* Copy as many bytes as will fit. */ + if (nleft != 0) { + while (--nleft != 0) { + if ((*dst++ = *src++) == '\0') { + break; + } + } + } + + /* Not enough room in dst, add NUL and traverse rest of src. */ + if (nleft == 0) { + if (dsize != 0) { + *dst = '\0'; /* NUL-terminate dst */ + } + while (*src++) { + ; + } + } + + return src - osrc - 1; /* count does not include NUL */ +} + +/* strlcat: + * Appends src to string dst of size dsize (unlike strncat, dsize is the + * full size of dst, not space left). At most dsize-1 characters + * will be copied. Always NUL terminates (unless dsize <= strlen(dst)). + * Returns strlen(src) + MIN(dsize, strlen(initial dst)). + * If retval >= dsize, truncation occurred. + */ +size_t strlcat(char *dst, const char *src, size_t dsize) +{ + const char *odst = dst; + const char *osrc = src; + size_t n = dsize; + size_t dlen; + + /* Find the end of dst and adjust bytes left but don't go past end. */ + while (n-- != 0 && *dst != '\0') { + dst++; + } + dlen = dst - odst; + n = dsize - dlen; + + if (n-- == 0) { + return dlen + strlen(src); + } + while (*src != '\0') { + if (n != 0) { + *dst++ = *src; + n--; + } + src++; + } + *dst = '\0'; + + return dlen + src - osrc; /* count does not include NUL */ +} + +/* ~ 64 * (sizeof(struct ld_info) + _XOPEN_PATH_MAX + _XOPEN_NAME_MAX) */ +# define DLFCN_LDINFO_SIZE 86976 +typedef struct Dl_info { + const char *dli_fname; +} Dl_info; +/* + * This dladdr()-implementation will also find the ptrgl (Pointer Glue) virtual + * address of a function, which is just located in the DATA segment instead of + * the TEXT segment. + */ +static int dladdr(const void *ptr, Dl_info *dl) +{ + uintptr_t addr = (uintptr_t)ptr; + struct ld_info *ldinfos; + struct ld_info *next_ldi; + struct ld_info *this_ldi; + + if ((ldinfos = (struct ld_info *)malloc(DLFCN_LDINFO_SIZE)) == NULL) { + dl->dli_fname = NULL; + return 0; + } + + if ((loadquery(L_GETINFO, (void *)ldinfos, DLFCN_LDINFO_SIZE)) < 0) { + /*- + * Error handling is done through errno and dlerror() reading errno: + * ENOMEM (ldinfos buffer is too small), + * EINVAL (invalid flags), + * EFAULT (invalid ldinfos ptr) + */ + free((void *)ldinfos); + dl->dli_fname = NULL; + return 0; + } + next_ldi = ldinfos; + + do { + this_ldi = next_ldi; + if (((addr >= (uintptr_t)this_ldi->ldinfo_textorg) + && (addr < ((uintptr_t)this_ldi->ldinfo_textorg + + this_ldi->ldinfo_textsize))) + || ((addr >= (uintptr_t)this_ldi->ldinfo_dataorg) + && (addr < ((uintptr_t)this_ldi->ldinfo_dataorg + + this_ldi->ldinfo_datasize)))) { + char *buffer = NULL; + char *member = NULL; + size_t buffer_sz; + size_t member_len; + + buffer_sz = strlen(this_ldi->ldinfo_filename) + 1; + member = this_ldi->ldinfo_filename + buffer_sz; + if ((member_len = strlen(member)) > 0) { + buffer_sz += 1 + member_len + 1; + } + if ((buffer = (char *)malloc(buffer_sz)) != NULL) { + strlcpy(buffer, this_ldi->ldinfo_filename, buffer_sz); + if (member_len > 0) { + /* + * Need to respect a possible member name and not just + * returning the path name in this case. See docs: + * sys/ldr.h, loadquery() and dlopen()/RTLD_MEMBER. + */ + strlcat(buffer, "(", buffer_sz); + strlcat(buffer, member, buffer_sz); + strlcat(buffer, ")", buffer_sz); + } + dl->dli_fname = buffer; + } + break; + } else { + next_ldi = (struct ld_info *)((uintptr_t)this_ldi + + this_ldi->ldinfo_next); + } + } while (this_ldi->ldinfo_next); + free((void *)ldinfos); + return dl->dli_fname != NULL; +} + +#endif + FileSpec Host::GetModuleFileSpecForHostAddress(const void *host_addr) { FileSpec module_filespec; #if !defined(__ANDROID__) +#ifdef __AIX__ + if (host_addr == reinterpret_cast(HostInfoBase::ComputeSharedLibraryDirectory)) { + // FIXME: AIX dladdr return "lldb" for this case + if (p_xargv[0]) { + module_filespec.SetFile(p_xargv[0], FileSpec::Style::native); + FileSystem::Instance().Resolve(module_filespec); + return module_filespec; + } + } +#endif Dl_info info; if (::dladdr(host_addr, &info)) { if (info.dli_fname) { @@ -373,12 +547,6 @@ FileSpec Host::GetModuleFileSpecForHostAddress(const void *host_addr) { #endif -#if !defined(__linux__) -bool Host::FindProcessThreads(const lldb::pid_t pid, TidMap &tids_to_attach) { - return false; -} -#endif - struct ShellInfo { ShellInfo() : process_reaped(false) {} diff --git a/lldb/source/Host/common/LICENSE.aix-netbsd.txt b/lldb/source/Host/common/LICENSE.aix-netbsd.txt new file mode 100644 index 000000000000000..9601ab43575f971 --- /dev/null +++ b/lldb/source/Host/common/LICENSE.aix-netbsd.txt @@ -0,0 +1,125 @@ + + LICENSE ISSUES + ============== + + The OpenSSL toolkit stays under a double license, i.e. both the conditions of + the OpenSSL License and the original SSLeay license apply to the toolkit. + See below for the actual license texts. + + OpenSSL License + --------------- + +/* ==================================================================== + * Copyright (c) 1998-2019 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + + Original SSLeay License + ----------------------- + +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + diff --git a/lldb/source/Host/common/XML.cpp b/lldb/source/Host/common/XML.cpp index f480ef3166a4439..62cac78aaac230f 100644 --- a/lldb/source/Host/common/XML.cpp +++ b/lldb/source/Host/common/XML.cpp @@ -10,6 +10,9 @@ #include "lldb/Host/XML.h" #include "llvm/ADT/StringExtras.h" +#if defined(__AIX__) +#undef LLDB_ENABLE_LIBXML2 +#endif using namespace lldb; using namespace lldb_private; diff --git a/lldb/source/Host/posix/ConnectionFileDescriptorPosix.cpp b/lldb/source/Host/posix/ConnectionFileDescriptorPosix.cpp index fceeff08ed9d36f..143254bb1290146 100644 --- a/lldb/source/Host/posix/ConnectionFileDescriptorPosix.cpp +++ b/lldb/source/Host/posix/ConnectionFileDescriptorPosix.cpp @@ -721,6 +721,7 @@ ConnectionFileDescriptor::ConnectFD(llvm::StringRef s, ConnectionStatus ConnectionFileDescriptor::ConnectFile( llvm::StringRef s, socket_id_callback_type socket_id_callback, Status *error_ptr) { +#if !defined(__AIX__) #if LLDB_ENABLE_POSIX std::string addr_str = s.str(); // file:///PATH @@ -753,6 +754,7 @@ ConnectionStatus ConnectionFileDescriptor::ConnectFile( m_io_sp = std::make_shared(fd, File::eOpenOptionReadWrite, true); return eConnectionStatusSuccess; #endif // LLDB_ENABLE_POSIX +#endif llvm_unreachable("this function should be only called w/ LLDB_ENABLE_POSIX"); } diff --git a/lldb/source/Host/posix/FileSystemPosix.cpp b/lldb/source/Host/posix/FileSystemPosix.cpp index cdb76da626bc9f5..a7c50f6a3c83531 100644 --- a/lldb/source/Host/posix/FileSystemPosix.cpp +++ b/lldb/source/Host/posix/FileSystemPosix.cpp @@ -11,7 +11,9 @@ // C includes #include #include +#if !defined(__AIX__) #include +#endif #include #include #include diff --git a/lldb/source/Host/posix/MainLoopPosix.cpp b/lldb/source/Host/posix/MainLoopPosix.cpp index 5fe4d015251c8a6..e5be0db4cf19b59 100644 --- a/lldb/source/Host/posix/MainLoopPosix.cpp +++ b/lldb/source/Host/posix/MainLoopPosix.cpp @@ -179,9 +179,21 @@ Status MainLoopPosix::RunImpl::Poll() { read_fds.push_back(pfd); } +#if defined(__AIX__) + sigset_t origmask; + int timeout; + + timeout = -1; + pthread_sigmask(SIG_SETMASK, &sigmask, &origmask); + int ready = poll(read_fds.data(), read_fds.size(), timeout); + pthread_sigmask(SIG_SETMASK, &origmask, nullptr); + if (ready == -1 && errno != EINTR) + return Status(errno, eErrorTypePOSIX); +#else if (ppoll(read_fds.data(), read_fds.size(), nullptr, &sigmask) == -1 && errno != EINTR) return Status(errno, eErrorTypePOSIX); +#endif return Status(); } @@ -312,8 +324,13 @@ MainLoopPosix::RegisterSignal(int signo, const Callback &callback, // If we're using kqueue, the signal needs to be unblocked in order to // receive it. If using pselect/ppoll, we need to block it, and later unblock // it as a part of the system call. +#if defined(__AIX__) + //FIXME: where is signal unblocked? + ret = pthread_sigmask(SIG_UNBLOCK, &new_action.sa_mask, &old_set); +#else ret = pthread_sigmask(HAVE_SYS_EVENT_H ? SIG_UNBLOCK : SIG_BLOCK, &new_action.sa_mask, &old_set); +#endif assert(ret == 0 && "pthread_sigmask failed"); info.was_blocked = sigismember(&old_set, signo); auto insert_ret = m_signals.insert({signo, info}); diff --git a/lldb/source/Host/posix/ProcessLauncherPosixFork.cpp b/lldb/source/Host/posix/ProcessLauncherPosixFork.cpp index 0a832ebad13a75a..cd106f605b1f420 100644 --- a/lldb/source/Host/posix/ProcessLauncherPosixFork.cpp +++ b/lldb/source/Host/posix/ProcessLauncherPosixFork.cpp @@ -193,8 +193,13 @@ struct ForkLaunchInfo { } // Start tracing this child that is about to exec. +#if !defined(__AIX__) if (ptrace(PT_TRACE_ME, 0, nullptr, 0) == -1) ExitWithError(error_fd, "ptrace"); +#else + if (ptrace64(PT_TRACE_ME, 0, 0, 0, nullptr) == -1) + ExitWithError(error_fd, "ptrace"); +#endif } // Execute. We should never return... diff --git a/lldb/source/Initialization/CMakeLists.txt b/lldb/source/Initialization/CMakeLists.txt index c1a167826f76fde..9f94830c8509fc4 100644 --- a/lldb/source/Initialization/CMakeLists.txt +++ b/lldb/source/Initialization/CMakeLists.txt @@ -1,4 +1,4 @@ -if ( CMAKE_SYSTEM_NAME MATCHES "Linux|Android|FreeBSD|NetBSD" ) +if ( CMAKE_SYSTEM_NAME MATCHES "Linux|Android|FreeBSD|NetBSD|AIX" ) list(APPEND EXTRA_PLUGINS lldbPluginProcessPOSIX) endif() diff --git a/lldb/source/Initialization/SystemInitializerCommon.cpp b/lldb/source/Initialization/SystemInitializerCommon.cpp index 1a172a95aa1471e..4b01442a94bacfa 100644 --- a/lldb/source/Initialization/SystemInitializerCommon.cpp +++ b/lldb/source/Initialization/SystemInitializerCommon.cpp @@ -19,7 +19,7 @@ #include "lldb/Version/Version.h" #if defined(__linux__) || defined(__FreeBSD__) || defined(__NetBSD__) || \ - defined(__OpenBSD__) + defined(__OpenBSD__) || defined(__AIX__) #include "Plugins/Process/POSIX/ProcessPOSIXLog.h" #endif @@ -79,7 +79,7 @@ llvm::Error SystemInitializerCommon::Initialize() { process_gdb_remote::ProcessGDBRemoteLog::Initialize(); #if defined(__linux__) || defined(__FreeBSD__) || defined(__NetBSD__) || \ - defined(__OpenBSD__) + defined(__OpenBSD__) || defined(__AIX__) ProcessPOSIXLog::Initialize(); #endif #if defined(_WIN32) diff --git a/lldb/source/Plugins/ABI/PowerPC/ABISysV_ppc64.cpp b/lldb/source/Plugins/ABI/PowerPC/ABISysV_ppc64.cpp index eac058701313b88..feb0d7c0e09bec5 100644 --- a/lldb/source/Plugins/ABI/PowerPC/ABISysV_ppc64.cpp +++ b/lldb/source/Plugins/ABI/PowerPC/ABISysV_ppc64.cpp @@ -156,6 +156,9 @@ bool ABISysV_ppc64::PrepareTrivialCall(Thread &thread, addr_t sp, if (!reg_ctx->WriteRegisterFromUnsigned(r12_reg_info, func_addr)) return false; +#if defined(__AIX__) + assert(0); +#else // Read TOC pointer value. reg_value = reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0); @@ -171,6 +174,132 @@ bool ABISysV_ppc64::PrepareTrivialCall(Thread &thread, addr_t sp, (uint64_t)reg_value); if (!process_sp->WritePointerToMemory(sp + stack_offset, reg_value, error)) return false; +#endif + + // Read the current SP value. + reg_value = reg_ctx->ReadRegisterAsUnsigned(sp_reg_info, 0); + + // Save current SP onto the stack. + LLDB_LOGF(log, "Writing SP at SP(0x%" PRIx64 ")+0: 0x%" PRIx64, (uint64_t)sp, + (uint64_t)reg_value); + if (!process_sp->WritePointerToMemory(sp, reg_value, error)) + return false; + + // %r1 is set to the actual stack value. + LLDB_LOGF(log, "Writing SP: 0x%" PRIx64, (uint64_t)sp); + + if (!reg_ctx->WriteRegisterFromUnsigned(sp_reg_info, sp)) + return false; + + // %pc is set to the address of the called function. + + LLDB_LOGF(log, "Writing IP: 0x%" PRIx64, (uint64_t)func_addr); + + if (!reg_ctx->WriteRegisterFromUnsigned(pc_reg_info, func_addr)) + return false; + + return true; +} + +bool ABISysV_ppc64::PrepareTrivialCall(Thread &thread, addr_t sp, + addr_t func_addr, addr_t toc_addr, + addr_t return_addr, + llvm::ArrayRef args) const { + Log *log = GetLog(LLDBLog::Expressions); + + if (log) { + StreamString s; + s.Printf("ABISysV_ppc64::PrepareTrivialCall (tid = 0x%" PRIx64 + ", sp = 0x%" PRIx64 ", func_addr = 0x%" PRIx64 + ", return_addr = 0x%" PRIx64, + thread.GetID(), (uint64_t)sp, (uint64_t)func_addr, + (uint64_t)return_addr); + + for (size_t i = 0; i < args.size(); ++i) + s.Printf(", arg%" PRIu64 " = 0x%" PRIx64, static_cast(i + 1), + args[i]); + s.PutCString(")"); + log->PutString(s.GetString()); + } + + RegisterContext *reg_ctx = thread.GetRegisterContext().get(); + if (!reg_ctx) + return false; + + const RegisterInfo *reg_info = nullptr; + + if (args.size() > 8) // TODO handle more than 8 arguments + return false; + + for (size_t i = 0; i < args.size(); ++i) { + reg_info = reg_ctx->GetRegisterInfo(eRegisterKindGeneric, + LLDB_REGNUM_GENERIC_ARG1 + i); + LLDB_LOGF(log, "About to write arg%" PRIu64 " (0x%" PRIx64 ") into %s", + static_cast(i + 1), args[i], reg_info->name); + if (!reg_ctx->WriteRegisterFromUnsigned(reg_info, args[i])) + return false; + } + + // First, align the SP + + LLDB_LOGF(log, "16-byte aligning SP: 0x%" PRIx64 " to 0x%" PRIx64, + (uint64_t)sp, (uint64_t)(sp & ~0xfull)); + + sp &= ~(0xfull); // 16-byte alignment + + sp -= 544; // allocate frame to save TOC, RA and SP. + + Status error; + uint64_t reg_value; + const RegisterInfo *pc_reg_info = + reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC); + const RegisterInfo *sp_reg_info = + reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP); + ProcessSP process_sp(thread.GetProcess()); + const RegisterInfo *lr_reg_info = + reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA); + const RegisterInfo *r2_reg_info = reg_ctx->GetRegisterInfoAtIndex(2); + const RegisterInfo *r12_reg_info = reg_ctx->GetRegisterInfoAtIndex(12); + + // Save return address onto the stack. + LLDB_LOGF(log, + "Pushing the return address onto the stack: 0x%" PRIx64 + "(+16): 0x%" PRIx64, + (uint64_t)sp, (uint64_t)return_addr); + if (!process_sp->WritePointerToMemory(sp + 16, return_addr, error)) + return false; + + // Write the return address to link register. + LLDB_LOGF(log, "Writing LR: 0x%" PRIx64, (uint64_t)return_addr); + if (!reg_ctx->WriteRegisterFromUnsigned(lr_reg_info, return_addr)) + return false; + + // Write target address to %r12 register. + LLDB_LOGF(log, "Writing R12: 0x%" PRIx64, (uint64_t)func_addr); + if (!reg_ctx->WriteRegisterFromUnsigned(r12_reg_info, func_addr)) + return false; + +#if defined(__AIX__) + LLDB_LOGF(log, "Writing R2: 0x%" PRIx64, (uint64_t)toc_addr); + if (!reg_ctx->WriteRegisterFromUnsigned(r2_reg_info, toc_addr)) + return false; +#else + // Read TOC pointer value. + reg_value = reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0); + + // Write TOC pointer onto the stack. + uint64_t stack_offset; + if (GetByteOrder() == lldb::eByteOrderLittle) + stack_offset = 24; + else + stack_offset = 40; + + LLDB_LOGF(log, "Writing R2 (TOC) at SP(0x%" PRIx64 ")+%d: 0x%" PRIx64, + (uint64_t)(sp + stack_offset), (int)stack_offset, + (uint64_t)reg_value); + if (!process_sp->WritePointerToMemory(sp + stack_offset, reg_value, error)) + return false; +#endif // Read the current SP value. reg_value = reg_ctx->ReadRegisterAsUnsigned(sp_reg_info, 0); @@ -641,7 +770,7 @@ class ReturnValueExtractor { DataExtractor de(&raw_data, sizeof(raw_data), m_byte_order, m_addr_size); - offset_t offset = 0; + lldb::offset_t offset = 0; std::optional byte_size = type.GetByteSize(m_process_sp.get()); if (!byte_size) return {}; diff --git a/lldb/source/Plugins/ABI/PowerPC/ABISysV_ppc64.h b/lldb/source/Plugins/ABI/PowerPC/ABISysV_ppc64.h index bfa96cc0df703a1..d752a8ded97483c 100644 --- a/lldb/source/Plugins/ABI/PowerPC/ABISysV_ppc64.h +++ b/lldb/source/Plugins/ABI/PowerPC/ABISysV_ppc64.h @@ -23,6 +23,12 @@ class ABISysV_ppc64 : public lldb_private::RegInfoBasedABI { lldb::addr_t returnAddress, llvm::ArrayRef args) const override; + bool PrepareTrivialCall(lldb_private::Thread &thread, lldb::addr_t sp, + lldb::addr_t functionAddress, + lldb::addr_t tocAddress, + lldb::addr_t returnAddress, + llvm::ArrayRef args) const override; + bool GetArgumentValues(lldb_private::Thread &thread, lldb_private::ValueList &values) const override; diff --git a/lldb/source/Plugins/DynamicLoader/AIX-DYLD/CMakeLists.txt b/lldb/source/Plugins/DynamicLoader/AIX-DYLD/CMakeLists.txt new file mode 100644 index 000000000000000..02fe0d617955a0a --- /dev/null +++ b/lldb/source/Plugins/DynamicLoader/AIX-DYLD/CMakeLists.txt @@ -0,0 +1,11 @@ +add_definitions("-D_ALL_SOURCE") + +add_lldb_library(lldbPluginDynamicLoaderAIXDYLD PLUGIN + DynamicLoaderAIXDYLD.cpp + + LINK_LIBS + lldbCore + lldbTarget + LINK_COMPONENTS + Support + ) diff --git a/lldb/source/Plugins/DynamicLoader/AIX-DYLD/DynamicLoaderAIXDYLD.cpp b/lldb/source/Plugins/DynamicLoader/AIX-DYLD/DynamicLoaderAIXDYLD.cpp new file mode 100644 index 000000000000000..62663974134b077 --- /dev/null +++ b/lldb/source/Plugins/DynamicLoader/AIX-DYLD/DynamicLoaderAIXDYLD.cpp @@ -0,0 +1,272 @@ +//===-- DynamicLoaderAIXDYLD.cpp --------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "DynamicLoaderAIXDYLD.h" + +#include "lldb/Core/Module.h" +#include "lldb/Core/PluginManager.h" +#include "lldb/Target/ExecutionContext.h" +#include "lldb/Target/Platform.h" +#include "lldb/Target/Process.h" +#include "lldb/Target/RegisterContext.h" +#include "lldb/Target/Target.h" +#include "lldb/Target/ThreadPlanStepInstruction.h" +#include "lldb/Utility/LLDBLog.h" +#include "lldb/Utility/Log.h" +#if defined(__AIX__) +#include +#endif + +/*#include "llvm/ADT/Triple.h" +*/ + +using namespace lldb; +using namespace lldb_private; + +LLDB_PLUGIN_DEFINE(DynamicLoaderAIXDYLD) + +DynamicLoaderAIXDYLD::DynamicLoaderAIXDYLD(Process *process) + : DynamicLoader(process) {} + +DynamicLoaderAIXDYLD::~DynamicLoaderAIXDYLD() = default; + +void DynamicLoaderAIXDYLD::Initialize() { + PluginManager::RegisterPlugin(GetPluginNameStatic(), + GetPluginDescriptionStatic(), CreateInstance); +} + +void DynamicLoaderAIXDYLD::Terminate() {} + +llvm::StringRef DynamicLoaderAIXDYLD::GetPluginDescriptionStatic() { + return "Dynamic loader plug-in that watches for shared library " + "loads/unloads in AIX processes."; +} + +DynamicLoader *DynamicLoaderAIXDYLD::CreateInstance(Process *process, + bool force) { + bool should_create = force; + if (!should_create) { + const llvm::Triple &triple_ref = + process->GetTarget().GetArchitecture().GetTriple(); + if (triple_ref.getOS() == llvm::Triple::AIX) + should_create = true; + } + + if (should_create) + return new DynamicLoaderAIXDYLD(process); + + return nullptr; +} + +void DynamicLoaderAIXDYLD::OnLoadModule(lldb::ModuleSP module_sp, + const ModuleSpec module_spec, + lldb::addr_t module_addr) { + + // Resolve the module unless we already have one. + if (!module_sp) { + Status error; + module_sp = m_process->GetTarget().GetOrCreateModule(module_spec, + true /* notify */, &error); + if (error.Fail()) + return; + } + + m_loaded_modules[module_sp] = module_addr; + UpdateLoadedSectionsCommon(module_sp, module_addr, false); + ModuleList module_list; + module_list.Append(module_sp); + m_process->GetTarget().ModulesDidLoad(module_list); +} + +void DynamicLoaderAIXDYLD::OnUnloadModule(lldb::addr_t module_addr) { + Address resolved_addr; + if (!m_process->GetTarget().ResolveLoadAddress(module_addr, resolved_addr)) + return; + + ModuleSP module_sp = resolved_addr.GetModule(); + if (module_sp) { + m_loaded_modules.erase(module_sp); + UnloadSectionsCommon(module_sp); + ModuleList module_list; + module_list.Append(module_sp); + m_process->GetTarget().ModulesDidUnload(module_list, false); + } +} + +lldb::addr_t DynamicLoaderAIXDYLD::GetLoadAddress(ModuleSP executable) { + // First, see if the load address is already cached. + auto it = m_loaded_modules.find(executable); + if (it != m_loaded_modules.end() && it->second != LLDB_INVALID_ADDRESS) + return it->second; + + lldb::addr_t load_addr = LLDB_INVALID_ADDRESS; + + // Second, try to get it through the process plugins. For a remote process, + // the remote platform will be responsible for providing it. + FileSpec file_spec(executable->GetPlatformFileSpec()); + bool is_loaded = false; + Status status = + m_process->GetFileLoadAddress(file_spec, is_loaded, load_addr); + // Servers other than lldb server could respond with a bogus address. + if (status.Success() && is_loaded && load_addr != LLDB_INVALID_ADDRESS) { + m_loaded_modules[executable] = load_addr; + return load_addr; + } + + //// Hack to try set breakpoint + //Breakpoint *dyld_break = m_process->GetTarget().CreateBreakpoint(0x100000638, true, false).get(); + //dyld_break->SetCallback(DynamicLoaderAIXDYLD::NotifyBreakpointHit, this, true); + //dyld_break->SetBreakpointKind("hack-debug"); + + return LLDB_INVALID_ADDRESS; +} + +bool DynamicLoaderAIXDYLD::NotifyBreakpointHit( + void *baton, StoppointCallbackContext *context, lldb::user_id_t break_id, + lldb::user_id_t break_loc_id) { +} + +void DynamicLoaderAIXDYLD::DidAttach() { + Log *log = GetLog(LLDBLog::DynamicLoader); + LLDB_LOGF(log, "DynamicLoaderAIXDYLD::%s()", __FUNCTION__); + + ModuleSP executable = GetTargetExecutable(); + + if (!executable.get()) + return; + + // Try to fetch the load address of the file from the process, since there + // could be randomization of the load address. + lldb::addr_t load_addr = GetLoadAddress(executable); + if (load_addr == LLDB_INVALID_ADDRESS) + return; + + // Request the process base address. + lldb::addr_t image_base = m_process->GetImageInfoAddress(); + if (image_base == load_addr) + return; + + // Rebase the process's modules if there is a mismatch. + UpdateLoadedSections(executable, LLDB_INVALID_ADDRESS, load_addr, false); + + ModuleList module_list; + module_list.Append(executable); + m_process->GetTarget().ModulesDidLoad(module_list); + auto error = m_process->LoadModules(); + LLDB_LOG_ERROR(log, std::move(error), "failed to load modules: {0}"); + +#if defined(__AIX__) + // Get struct ld_xinfo (FIXME) + struct ld_xinfo ldinfo[64]; + Status status = m_process->GetLDXINFO(&(ldinfo[0])); + if (status.Fail()) { + Log *log = GetLog(LLDBLog::DynamicLoader); + LLDB_LOG(log, "LDXINFO failed: {0}", status); + return; + } + struct ld_xinfo *ptr = &(ldinfo[0]); + bool skip_current = true; + while (ptr != nullptr) { + char *pathName = (char *)ptr + ptr->ldinfo_filename; + char *memberName = pathName + (strlen(pathName) + 1); + if (!skip_current) { + // FIXME: buffer size + char pathWithMember[128] = {0}; + if (strlen(memberName) > 0) { + sprintf(pathWithMember, "%s(%s)", pathName, memberName); + } else { + sprintf(pathWithMember, "%s", pathName); + } + FileSpec file(pathWithMember); + ModuleSpec module_spec(file, m_process->GetTarget().GetArchitecture()); + if (ModuleSP module_sp = m_process->GetTarget().GetOrCreateModule(module_spec, true /* notify */)) { + UpdateLoadedSectionsByType(module_sp, LLDB_INVALID_ADDRESS, (lldb::addr_t)ptr->ldinfo_textorg, false, 1); + UpdateLoadedSectionsByType(module_sp, LLDB_INVALID_ADDRESS, (lldb::addr_t)ptr->ldinfo_dataorg, false, 2); + // FIXME: .tdata, .bss + } + } else { + skip_current = false; + } + if (ptr->ldinfo_next == 0) { + ptr = nullptr; + } else { + ptr = (struct ld_xinfo *)((char *)ptr + ptr->ldinfo_next); + } + } +#endif +} + +void DynamicLoaderAIXDYLD::DidLaunch() { + Log *log = GetLog(LLDBLog::DynamicLoader); + LLDB_LOGF(log, "DynamicLoaderAIXDYLD::%s()", __FUNCTION__); + + ModuleSP executable = GetTargetExecutable(); + if (!executable.get()) + return; + + lldb::addr_t load_addr = GetLoadAddress(executable); + if (load_addr != LLDB_INVALID_ADDRESS) { + // Update the loaded sections so that the breakpoints can be resolved. + UpdateLoadedSections(executable, LLDB_INVALID_ADDRESS, load_addr, false); + + ModuleList module_list; + module_list.Append(executable); + m_process->GetTarget().ModulesDidLoad(module_list); + auto error = m_process->LoadModules(); + LLDB_LOG_ERROR(log, std::move(error), "failed to load modules: {0}"); + } + +#if defined(__AIX__) + // Get struct ld_xinfo (FIXME) + struct ld_xinfo ldinfo[64]; + Status status = m_process->GetLDXINFO(&(ldinfo[0])); + if (status.Fail()) { + Log *log = GetLog(LLDBLog::DynamicLoader); + LLDB_LOG(log, "LDXINFO failed: {0}", status); + return; + } + struct ld_xinfo *ptr = &(ldinfo[0]); + bool skip_current = true; + while (ptr != nullptr) { + char *pathName = (char *)ptr + ptr->ldinfo_filename; + char *memberName = pathName + (strlen(pathName) + 1); + if (!skip_current) { + // FIXME: buffer size + char pathWithMember[128] = {0}; + if (strlen(memberName) > 0) { + sprintf(pathWithMember, "%s(%s)", pathName, memberName); + } else { + sprintf(pathWithMember, "%s", pathName); + } + FileSpec file(pathWithMember); + ModuleSpec module_spec(file, m_process->GetTarget().GetArchitecture()); + if (ModuleSP module_sp = m_process->GetTarget().GetOrCreateModule(module_spec, true /* notify */)) { + UpdateLoadedSectionsByType(module_sp, LLDB_INVALID_ADDRESS, (lldb::addr_t)ptr->ldinfo_textorg, false, 1); + UpdateLoadedSectionsByType(module_sp, LLDB_INVALID_ADDRESS, (lldb::addr_t)ptr->ldinfo_dataorg, false, 2); + // FIXME: .tdata, .bss + } + } else { + skip_current = false; + } + if (ptr->ldinfo_next == 0) { + ptr = nullptr; + } else { + ptr = (struct ld_xinfo *)((char *)ptr + ptr->ldinfo_next); + } + } +#endif +} + +Status DynamicLoaderAIXDYLD::CanLoadImage() { return Status(); } + +ThreadPlanSP +DynamicLoaderAIXDYLD::GetStepThroughTrampolinePlan(Thread &thread, + bool stop) { + //FIXME + return ThreadPlanSP(); +} diff --git a/lldb/source/Plugins/DynamicLoader/AIX-DYLD/DynamicLoaderAIXDYLD.h b/lldb/source/Plugins/DynamicLoader/AIX-DYLD/DynamicLoaderAIXDYLD.h new file mode 100644 index 000000000000000..ae4b7aca66dcc5f --- /dev/null +++ b/lldb/source/Plugins/DynamicLoader/AIX-DYLD/DynamicLoaderAIXDYLD.h @@ -0,0 +1,55 @@ +//===-- DynamicLoaderAIXDYLD.h ------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLDB_SOURCE_PLUGINS_DYNAMICLOADER_AIX_DYLD_DYNAMICLOADERAIXDYLD_H +#define LLDB_SOURCE_PLUGINS_DYNAMICLOADER_AIX_DYLD_DYNAMICLOADERAIXDYLD_H + +#include "lldb/Target/DynamicLoader.h" +#include "lldb/lldb-forward.h" + +#include + +namespace lldb_private { + +class DynamicLoaderAIXDYLD : public DynamicLoader { +public: + DynamicLoaderAIXDYLD(Process *process); + + ~DynamicLoaderAIXDYLD() override; + + static void Initialize(); + static void Terminate(); + static llvm::StringRef GetPluginNameStatic() { return "windows-dyld"; } + static llvm::StringRef GetPluginDescriptionStatic(); + + static DynamicLoader *CreateInstance(Process *process, bool force); + + void OnLoadModule(lldb::ModuleSP module_sp, const ModuleSpec module_spec, + lldb::addr_t module_addr); + void OnUnloadModule(lldb::addr_t module_addr); + + void DidAttach() override; + void DidLaunch() override; + Status CanLoadImage() override; + lldb::ThreadPlanSP GetStepThroughTrampolinePlan(Thread &thread, + bool stop) override; + + llvm::StringRef GetPluginName() override { return GetPluginNameStatic(); } + + static bool NotifyBreakpointHit(void *baton, StoppointCallbackContext *context, lldb::user_id_t break_id, lldb::user_id_t break_loc_id); + +protected: + lldb::addr_t GetLoadAddress(lldb::ModuleSP executable); + +private: + std::map m_loaded_modules; +}; + +} // namespace lldb_private + +#endif // LLDB_SOURCE_PLUGINS_DYNAMICLOADER_AIX_DYLD_DYNAMICLOADERWAIXDYLD_H diff --git a/lldb/source/Plugins/DynamicLoader/CMakeLists.txt b/lldb/source/Plugins/DynamicLoader/CMakeLists.txt index 30607159acdc088..4f3fb693faae185 100644 --- a/lldb/source/Plugins/DynamicLoader/CMakeLists.txt +++ b/lldb/source/Plugins/DynamicLoader/CMakeLists.txt @@ -5,4 +5,5 @@ add_subdirectory(POSIX-DYLD) add_subdirectory(Static) add_subdirectory(Hexagon-DYLD) add_subdirectory(Windows-DYLD) +add_subdirectory(AIX-DYLD) add_subdirectory(wasm-DYLD) diff --git a/lldb/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp b/lldb/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp index 20e5652c65bf88a..26abea0fdd24d69 100644 --- a/lldb/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp +++ b/lldb/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp @@ -256,7 +256,7 @@ DynamicLoaderDarwinKernel::SearchForKernelWithDebugHints(Process *process) { if (process->ReadMemoryFromInferior (kernel_addresses_64[i], uval, 8, read_err) == 8) { DataExtractor data (&uval, 8, process->GetByteOrder(), process->GetAddressByteSize()); - offset_t offset = 0; + lldb::offset_t offset = 0; uint64_t addr = data.GetU64 (&offset); if (CheckForKernelImageAtAddress(addr, process).IsValid()) { return addr; @@ -270,7 +270,7 @@ DynamicLoaderDarwinKernel::SearchForKernelWithDebugHints(Process *process) { if (process->ReadMemoryFromInferior (kernel_addresses_32[i], uval, 4, read_err) == 4) { DataExtractor data (&uval, 4, process->GetByteOrder(), process->GetAddressByteSize()); - offset_t offset = 0; + lldb::offset_t offset = 0; uint32_t addr = data.GetU32 (&offset); if (CheckForKernelImageAtAddress(addr, process).IsValid()) { return addr; diff --git a/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderDarwin.cpp b/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderDarwin.cpp index 3863b6b3520db4e..624848dee6ec33f 100644 --- a/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderDarwin.cpp +++ b/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderDarwin.cpp @@ -1151,7 +1151,7 @@ DynamicLoaderDarwin::GetThreadLocalData(const lldb::ModuleSP module_sp, // TLS data for the pthread_key on a specific thread yet. If we have we // can re-use it since its location will not change unless the process // execs. - const tid_t tid = thread_sp->GetID(); + const lldb::tid_t tid = thread_sp->GetID(); auto tid_pos = m_tid_to_tls_map.find(tid); if (tid_pos != m_tid_to_tls_map.end()) { auto tls_pos = tid_pos->second.find(key); diff --git a/lldb/source/Plugins/Instruction/PPC64/EmulateInstructionPPC64.cpp b/lldb/source/Plugins/Instruction/PPC64/EmulateInstructionPPC64.cpp index 3035c5134177804..d14ae2daeb47d8e 100644 --- a/lldb/source/Plugins/Instruction/PPC64/EmulateInstructionPPC64.cpp +++ b/lldb/source/Plugins/Instruction/PPC64/EmulateInstructionPPC64.cpp @@ -146,7 +146,25 @@ EmulateInstructionPPC64::GetOpcodeForInstruction(uint32_t opcode) { {0xfc000000, 0x38000000, &EmulateInstructionPPC64::EmulateADDI, "addi RT, RA, SI"}, {0xfc000003, 0xe8000000, &EmulateInstructionPPC64::EmulateLD, - "ld RT, DS(RA)"}}; + "ld RT, DS(RA)"}, +// {0xffff0003, 0x40820000, &EmulateInstructionPPC64::EmulateBNE, +// "bne TARGET"}, + {0xfc000002, 0x48000000, &EmulateInstructionPPC64::EmulateB, + "b TARGET"}, + {0xfc000003, 0x48000002, &EmulateInstructionPPC64::EmulateBA, + "ba TARGET"}, + {0xfc000003, 0x48000003, &EmulateInstructionPPC64::EmulateBLA, + "bla TARGET"}, + {0xfc000002, 0x40000000, &EmulateInstructionPPC64::EmulateBC, + "bc BO,BI,TARGET"}, + {0xfc000002, 0x40000002, &EmulateInstructionPPC64::EmulateBCA, + "bca BO,BI,TARGET"}, + {0xfc0007fe, 0x4c000020, &EmulateInstructionPPC64::EmulateBCLR, + "bclr BO,BI,BH"}, + {0xfc0007fe, 0x4c000420, &EmulateInstructionPPC64::EmulateBCCTR, + "bcctr BO,BI,BH"}, + {0xfc0007fe, 0x4c000460, &EmulateInstructionPPC64::EmulateBCTAR, + "bctar BO,BI,BH"}}; static const size_t k_num_ppc_opcodes = std::size(g_opcodes); for (size_t i = 0; i < k_num_ppc_opcodes; ++i) { @@ -169,12 +187,13 @@ bool EmulateInstructionPPC64::EvaluateInstruction(uint32_t evaluate_options) { bool success = false; - uint32_t orig_pc_value = 0; + uint64_t orig_pc_value = 0; if (auto_advance_pc) { orig_pc_value = ReadRegisterUnsigned(eRegisterKindLLDB, gpr_pc_ppc64le, 0, &success); if (!success) return false; + LLDB_LOG(GetLog(LLDBLog::Unwind), "orig_pc_value:{0}", orig_pc_value); } // Call the Emulate... function. @@ -183,11 +202,13 @@ bool EmulateInstructionPPC64::EvaluateInstruction(uint32_t evaluate_options) { return false; if (auto_advance_pc) { - uint32_t new_pc_value = + uint64_t new_pc_value = ReadRegisterUnsigned(eRegisterKindLLDB, gpr_pc_ppc64le, 0, &success); if (!success) return false; + LLDB_LOG(GetLog(LLDBLog::Unwind), "new_pc_value:{0}", new_pc_value); + if (new_pc_value == orig_pc_value) { EmulateInstruction::Context context; context.type = eContextAdvancePC; @@ -389,5 +410,174 @@ bool EmulateInstructionPPC64::EmulateADDI(uint32_t opcode) { return false; WriteRegisterUnsigned(ctx, eRegisterKindLLDB, gpr_r1_ppc64le, r1 + si_val); LLDB_LOG(log, "EmulateADDI: success!"); + + // FIX the next-pc + uint64_t pc_value = ReadRegisterUnsigned(eRegisterKindLLDB, gpr_pc_ppc64le, 0, &success); + uint64_t next_pc = pc_value + 4; + ctx.type = eContextAdjustPC; + WriteRegisterUnsigned(ctx, eRegisterKindLLDB, gpr_pc_ppc64le, next_pc); + + return true; +} + +bool EmulateInstructionPPC64::EmulateBC(uint32_t opcode) { + // FIXME:32bit M + uint32_t M = 0; + uint32_t target32 = Bits32(opcode, 15, 2) << 2; + uint64_t target = (uint64_t)target32 + ((target32 & 0x8000) ? 0xffffffffffff0000UL : 0); + uint32_t BO = Bits32(opcode, 25, 21); + bool success; + uint64_t ctr_value = ReadRegisterUnsigned(eRegisterKindLLDB, gpr_ctr_ppc64le, 0, &success); + if ((~BO) & (1U << 2)) + ctr_value = ctr_value - 1; + bool ctr_ok = (bool)(BO & (1U << 2)) | ((bool)(ctr_value != 0) ^ (bool)(BO & (1U << 1))); + uint64_t cr_value = ReadRegisterUnsigned(eRegisterKindLLDB, gpr_cr_ppc64le, 0, &success); + uint32_t BI = Bits32(opcode, 20, 16); + bool cond_ok = (bool)(BO & (1U << 4)) | (bool)(((cr_value >> (63 - (BI + 32))) & 1U) == ((BO >> 3) & 1U)); + + uint64_t pc_value = ReadRegisterUnsigned(eRegisterKindLLDB, gpr_pc_ppc64le, 0, &success); + uint64_t next_pc = pc_value + 4; + if (ctr_ok & cond_ok) + next_pc = pc_value + target; + + Context ctx; + ctx.type = eContextAdjustPC; + WriteRegisterUnsigned(ctx, eRegisterKindLLDB, gpr_pc_ppc64le, next_pc); + Log *log = GetLog(LLDBLog::Unwind); + LLDB_LOG(log, "EmulateBC: success!"); + return true; +} + +bool EmulateInstructionPPC64::EmulateBCA(uint32_t opcode) { + // FIXME:32bit M + uint32_t M = 0; + uint32_t target32 = Bits32(opcode, 15, 2) << 2; + uint64_t target = (uint64_t)target32 + ((target32 & 0x8000) ? 0xffffffffffff0000UL : 0); + uint32_t BO = Bits32(opcode, 25, 21); + bool success; + uint64_t ctr_value = ReadRegisterUnsigned(eRegisterKindLLDB, gpr_ctr_ppc64le, 0, &success); + if ((~BO) & (1U << 2)) + ctr_value = ctr_value - 1; + bool ctr_ok = (bool)(BO & (1U << 2)) | ((bool)(ctr_value != 0) ^ (bool)(BO & (1U << 1))); + uint64_t cr_value = ReadRegisterUnsigned(eRegisterKindLLDB, gpr_cr_ppc64le, 0, &success); + uint32_t BI = Bits32(opcode, 20, 16); + bool cond_ok = (bool)(BO & (1U << 4)) | (bool)(((cr_value >> (63 - (BI + 32))) & 1U) == ((BO >> 3) & 1U)); + + uint64_t pc_value = ReadRegisterUnsigned(eRegisterKindLLDB, gpr_pc_ppc64le, 0, &success); + uint64_t next_pc = pc_value + 4; + if (ctr_ok & cond_ok) + next_pc = target; + + Context ctx; + ctx.type = eContextAdjustPC; + WriteRegisterUnsigned(ctx, eRegisterKindLLDB, gpr_pc_ppc64le, next_pc); + Log *log = GetLog(LLDBLog::Unwind); + LLDB_LOG(log, "EmulateBCA: success!"); + return true; +} + +bool EmulateInstructionPPC64::EmulateBCLR(uint32_t opcode) { + // FIXME:32bit M + uint32_t M = 0; + uint32_t BO = Bits32(opcode, 25, 21); + bool success; + uint64_t ctr_value = ReadRegisterUnsigned(eRegisterKindLLDB, gpr_ctr_ppc64le, 0, &success); + if ((~BO) & (1U << 2)) + ctr_value = ctr_value - 1; + bool ctr_ok = (bool)(BO & (1U << 2)) | ((bool)(ctr_value != 0) ^ (bool)(BO & (1U << 1))); + uint64_t cr_value = ReadRegisterUnsigned(eRegisterKindLLDB, gpr_cr_ppc64le, 0, &success); + uint32_t BI = Bits32(opcode, 20, 16); + bool cond_ok = (bool)(BO & (1U << 4)) | (bool)(((cr_value >> (63 - (BI + 32))) & 1U) == ((BO >> 3) & 1U)); + + uint64_t pc_value = ReadRegisterUnsigned(eRegisterKindLLDB, gpr_pc_ppc64le, 0, &success); + uint64_t next_pc = pc_value + 4; + if (ctr_ok & cond_ok) { + next_pc = ReadRegisterUnsigned(eRegisterKindLLDB, gpr_lr_ppc64le, 0, &success); + next_pc &= ~((1UL << 2) - 1); + } + + Context ctx; + ctx.type = eContextAdjustPC; + WriteRegisterUnsigned(ctx, eRegisterKindLLDB, gpr_pc_ppc64le, next_pc); + Log *log = GetLog(LLDBLog::Unwind); + LLDB_LOG(log, "EmulateBCLR: success!"); + return true; +} + +bool EmulateInstructionPPC64::EmulateBCCTR(uint32_t opcode) { + // FIXME:32bit M + uint32_t M = 0; + uint32_t BO = Bits32(opcode, 25, 21); + bool success; + uint64_t cr_value = ReadRegisterUnsigned(eRegisterKindLLDB, gpr_cr_ppc64le, 0, &success); + uint32_t BI = Bits32(opcode, 20, 16); + bool cond_ok = (bool)(BO & (1U << 4)) | (bool)(((cr_value >> (63 - (BI + 32))) & 1U) == ((BO >> 3) & 1U)); + + Log *log = GetLog(LLDBLog::Unwind); + uint64_t pc_value = ReadRegisterUnsigned(eRegisterKindLLDB, gpr_pc_ppc64le, 0, &success); + uint64_t next_pc = pc_value + 4; + if (cond_ok) { + next_pc = ReadRegisterUnsigned(eRegisterKindLLDB, gpr_ctr_ppc64le, 0, &success); + next_pc &= ~((1UL << 2) - 1); + if (next_pc < 0x4000000) { + LLDB_LOGF(log, "EmulateBCCTR: next address %lx out of range, emulate by goto LR!"); + next_pc = ReadRegisterUnsigned(eRegisterKindLLDB, gpr_lr_ppc64le, 0, &success); + } + } + + Context ctx; + ctx.type = eContextAdjustPC; + WriteRegisterUnsigned(ctx, eRegisterKindLLDB, gpr_pc_ppc64le, next_pc); + LLDB_LOG(log, "EmulateBCCTR: success!"); + return true; +} + +bool EmulateInstructionPPC64::EmulateBCTAR(uint32_t opcode) { + // Not supported yet. + LLDB_LOG(GetLog(LLDBLog::Unwind), "EmulateBCTAR: not supported!"); + assert(0); + return false; +} + +bool EmulateInstructionPPC64::EmulateB(uint32_t opcode) { + uint32_t target32 = Bits32(opcode, 25, 2) << 2; + uint64_t target = (uint64_t)target32 + ((target32 & 0x2000000) ? 0xfffffffffc000000UL : 0); + + bool success; + uint64_t pc_value = ReadRegisterUnsigned(eRegisterKindLLDB, gpr_pc_ppc64le, 0, &success); + uint64_t next_pc = pc_value + target; + + Context ctx; + ctx.type = eContextAdjustPC; + WriteRegisterUnsigned(ctx, eRegisterKindLLDB, gpr_pc_ppc64le, next_pc); + Log *log = GetLog(LLDBLog::Unwind); + LLDB_LOG(log, "EmulateB: success!"); + return true; +} + +bool EmulateInstructionPPC64::EmulateBA(uint32_t opcode) { + Log *log = GetLog(LLDBLog::Unwind); + + bool success; + uint64_t next_pc = ReadRegisterUnsigned(eRegisterKindLLDB, gpr_lr_ppc64le, 0, &success); + + Context ctx; + ctx.type = eContextAdjustPC; + WriteRegisterUnsigned(ctx, eRegisterKindLLDB, gpr_pc_ppc64le, next_pc); + LLDB_LOG(log, "EmulateBA: emulate by branch to lr!"); + return true; +} + +bool EmulateInstructionPPC64::EmulateBLA(uint32_t opcode) { + Log *log = GetLog(LLDBLog::Unwind); + + bool success; + uint64_t pc_value = ReadRegisterUnsigned(eRegisterKindLLDB, gpr_pc_ppc64le, 0, &success); + uint64_t next_pc = pc_value + 4; + + Context ctx; + ctx.type = eContextAdjustPC; + WriteRegisterUnsigned(ctx, eRegisterKindLLDB, gpr_pc_ppc64le, next_pc); + LLDB_LOG(log, "EmulateBLA: emulate by branch to lr!"); return true; } diff --git a/lldb/source/Plugins/Instruction/PPC64/EmulateInstructionPPC64.h b/lldb/source/Plugins/Instruction/PPC64/EmulateInstructionPPC64.h index a9424f16b0ad01e..1576c9700e55724 100644 --- a/lldb/source/Plugins/Instruction/PPC64/EmulateInstructionPPC64.h +++ b/lldb/source/Plugins/Instruction/PPC64/EmulateInstructionPPC64.h @@ -39,6 +39,12 @@ class EmulateInstructionPPC64 : public EmulateInstruction { return true; case eInstructionTypePCModifying: +#if defined(__AIX__) + return true; +#else + return false; +#endif + case eInstructionTypeAll: return false; } @@ -84,6 +90,14 @@ class EmulateInstructionPPC64 : public EmulateInstruction { bool EmulateSTD(uint32_t opcode); bool EmulateOR(uint32_t opcode); bool EmulateADDI(uint32_t opcode); + bool EmulateB(uint32_t opcode); + bool EmulateBA(uint32_t opcode); + bool EmulateBLA(uint32_t opcode); + bool EmulateBC(uint32_t opcode); + bool EmulateBCA(uint32_t opcode); + bool EmulateBCLR(uint32_t opcode); + bool EmulateBCCTR(uint32_t opcode); + bool EmulateBCTAR(uint32_t opcode); }; } // namespace lldb_private diff --git a/lldb/source/Plugins/InstrumentationRuntime/MainThreadChecker/InstrumentationRuntimeMainThreadChecker.cpp b/lldb/source/Plugins/InstrumentationRuntime/MainThreadChecker/InstrumentationRuntimeMainThreadChecker.cpp index b7cd2b1ac6bf6d0..876e74056facebd 100644 --- a/lldb/source/Plugins/InstrumentationRuntime/MainThreadChecker/InstrumentationRuntimeMainThreadChecker.cpp +++ b/lldb/source/Plugins/InstrumentationRuntime/MainThreadChecker/InstrumentationRuntimeMainThreadChecker.cpp @@ -261,7 +261,7 @@ InstrumentationRuntimeMainThreadChecker::GetBacktracesFromExtendedStopInfo( StructuredData::ObjectSP thread_id_obj = info->GetObjectForDotSeparatedPath("tid"); - tid_t tid = thread_id_obj ? thread_id_obj->GetUnsignedIntegerValue() : 0; + lldb::tid_t tid = thread_id_obj ? thread_id_obj->GetUnsignedIntegerValue() : 0; // We gather symbolication addresses above, so no need for HistoryThread to // try to infer the call addresses. diff --git a/lldb/source/Plugins/InstrumentationRuntime/TSan/InstrumentationRuntimeTSan.cpp b/lldb/source/Plugins/InstrumentationRuntime/TSan/InstrumentationRuntimeTSan.cpp index b2781aa5e7db150..7a827a3ea76f9ca 100644 --- a/lldb/source/Plugins/InstrumentationRuntime/TSan/InstrumentationRuntimeTSan.cpp +++ b/lldb/source/Plugins/InstrumentationRuntime/TSan/InstrumentationRuntimeTSan.cpp @@ -770,13 +770,13 @@ std::string InstrumentationRuntimeTSan::GetLocationDescription( Sprintf("Location is a %ld-byte heap object at 0x%llx", size, addr); } } else if (type == "stack") { - tid_t tid = loc->GetAsDictionary() + lldb::tid_t tid = loc->GetAsDictionary() ->GetValueForKey("thread_id") ->GetUnsignedIntegerValue(); result = Sprintf("Location is stack of thread %d", tid); } else if (type == "tls") { - tid_t tid = loc->GetAsDictionary() + lldb::tid_t tid = loc->GetAsDictionary() ->GetValueForKey("thread_id") ->GetUnsignedIntegerValue(); @@ -948,7 +948,7 @@ static std::string GenerateThreadName(const std::string &path, if (path == "mops") { size_t size = o->GetObjectForDotSeparatedPath("size")->GetUnsignedIntegerValue(); - tid_t thread_id = + lldb::tid_t thread_id = o->GetObjectForDotSeparatedPath("thread_id")->GetUnsignedIntegerValue(); bool is_write = o->GetObjectForDotSeparatedPath("is_write")->GetBooleanValue(); @@ -979,7 +979,7 @@ static std::string GenerateThreadName(const std::string &path, } if (path == "threads") { - tid_t thread_id = + lldb::tid_t thread_id = o->GetObjectForDotSeparatedPath("thread_id")->GetUnsignedIntegerValue(); result = Sprintf("Thread %zu created", thread_id); } @@ -987,7 +987,7 @@ static std::string GenerateThreadName(const std::string &path, if (path == "locs") { std::string type = std::string( o->GetAsDictionary()->GetValueForKey("type")->GetStringValue()); - tid_t thread_id = + lldb::tid_t thread_id = o->GetObjectForDotSeparatedPath("thread_id")->GetUnsignedIntegerValue(); int fd = o->GetObjectForDotSeparatedPath("file_descriptor") ->GetSignedIntegerValue(); @@ -1007,7 +1007,7 @@ static std::string GenerateThreadName(const std::string &path, } if (path == "stacks") { - tid_t thread_id = + lldb::tid_t thread_id = o->GetObjectForDotSeparatedPath("thread_id")->GetUnsignedIntegerValue(); result = Sprintf("Thread %" PRIu64, thread_id); } @@ -1034,7 +1034,7 @@ static void AddThreadsForPath(const std::string &path, StructuredData::ObjectSP thread_id_obj = o->GetObjectForDotSeparatedPath("thread_os_id"); - tid_t tid = + lldb::tid_t tid = thread_id_obj ? thread_id_obj->GetUnsignedIntegerValue() : 0; ThreadSP new_thread_sp = diff --git a/lldb/source/Plugins/InstrumentationRuntime/UBSan/InstrumentationRuntimeUBSan.cpp b/lldb/source/Plugins/InstrumentationRuntime/UBSan/InstrumentationRuntimeUBSan.cpp index 1c58922e8d36c8b..de9719ad4a89ef4 100644 --- a/lldb/source/Plugins/InstrumentationRuntime/UBSan/InstrumentationRuntimeUBSan.cpp +++ b/lldb/source/Plugins/InstrumentationRuntime/UBSan/InstrumentationRuntimeUBSan.cpp @@ -321,7 +321,7 @@ InstrumentationRuntimeUBSan::GetBacktracesFromExtendedStopInfo( StructuredData::ObjectSP thread_id_obj = info->GetObjectForDotSeparatedPath("tid"); - tid_t tid = thread_id_obj ? thread_id_obj->GetUnsignedIntegerValue() : 0; + lldb::tid_t tid = thread_id_obj ? thread_id_obj->GetUnsignedIntegerValue() : 0; // We gather symbolication addresses above, so no need for HistoryThread to // try to infer the call addresses. diff --git a/lldb/source/Plugins/JITLoader/GDB/JITLoaderGDB.cpp b/lldb/source/Plugins/JITLoader/GDB/JITLoaderGDB.cpp index 1688fb27430a7a3..690fb0d60a09a9a 100644 --- a/lldb/source/Plugins/JITLoader/GDB/JITLoaderGDB.cpp +++ b/lldb/source/Plugins/JITLoader/GDB/JITLoaderGDB.cpp @@ -194,6 +194,10 @@ void JITLoaderGDB::SetJITBreakpoint(lldb_private::ModuleList &module_list) { if (jit_addr == LLDB_INVALID_ADDRESS) return; +#if defined(__AIX__) + return; +#endif + m_jit_descriptor_addr = GetSymbolAddress( module_list, ConstString("__jit_debug_descriptor"), eSymbolTypeData); if (m_jit_descriptor_addr == LLDB_INVALID_ADDRESS) { diff --git a/lldb/source/Plugins/Language/ObjC/Cocoa.cpp b/lldb/source/Plugins/Language/ObjC/Cocoa.cpp index 341923108e3216e..fb5bc2c58e6fb8b 100644 --- a/lldb/source/Plugins/Language/ObjC/Cocoa.cpp +++ b/lldb/source/Plugins/Language/ObjC/Cocoa.cpp @@ -1227,6 +1227,7 @@ bool lldb_private::formatters::ObjCSELSummaryProvider( time_t lldb_private::formatters::GetOSXEpoch() { static time_t epoch = 0; if (!epoch) { +#if !defined(__AIX__) #ifndef _WIN32 tzset(); tm tm_epoch; @@ -1240,6 +1241,7 @@ time_t lldb_private::formatters::GetOSXEpoch() { tm_epoch.tm_gmtoff = 0; tm_epoch.tm_zone = nullptr; epoch = timegm(&tm_epoch); +#endif #endif } return epoch; diff --git a/lldb/source/Plugins/MemoryHistory/asan/MemoryHistoryASan.cpp b/lldb/source/Plugins/MemoryHistory/asan/MemoryHistoryASan.cpp index 6efd2516578ff26..fe6c5a0544be327 100644 --- a/lldb/source/Plugins/MemoryHistory/asan/MemoryHistoryASan.cpp +++ b/lldb/source/Plugins/MemoryHistory/asan/MemoryHistoryASan.cpp @@ -107,7 +107,7 @@ static void CreateHistoryThreadFromValueObject(ProcessSP process_sp, return; int count = count_sp->GetValueAsUnsigned(0); - tid_t tid = tid_sp->GetValueAsUnsigned(0) + 1; + lldb::tid_t tid = tid_sp->GetValueAsUnsigned(0) + 1; if (count <= 0) return; diff --git a/lldb/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp b/lldb/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp index 7aa5b8d81890aee..5ea55772c3aba1b 100644 --- a/lldb/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp +++ b/lldb/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp @@ -8,7 +8,7 @@ #include "ObjectContainerBSDArchive.h" -#if defined(_WIN32) || defined(__ANDROID__) +#if defined(_WIN32) || defined(__ANDROID__) || defined(__AIX__) // Defines from ar, missing on Windows #define SARMAG 8 #define ARFMAG "`\n" diff --git a/lldb/source/Plugins/ObjectContainer/Big-Archive/CMakeLists.txt b/lldb/source/Plugins/ObjectContainer/Big-Archive/CMakeLists.txt new file mode 100644 index 000000000000000..612a36265b53664 --- /dev/null +++ b/lldb/source/Plugins/ObjectContainer/Big-Archive/CMakeLists.txt @@ -0,0 +1,10 @@ +add_lldb_library(lldbPluginObjectContainerBigArchive PLUGIN + ObjectContainerBigArchive.cpp + + LINK_LIBS + lldbCore + lldbHost + lldbSymbol + LINK_COMPONENTS + Support + ) diff --git a/lldb/source/Plugins/ObjectContainer/Big-Archive/ObjectContainerBigArchive.cpp b/lldb/source/Plugins/ObjectContainer/Big-Archive/ObjectContainerBigArchive.cpp new file mode 100644 index 000000000000000..050ad73f1d19af4 --- /dev/null +++ b/lldb/source/Plugins/ObjectContainer/Big-Archive/ObjectContainerBigArchive.cpp @@ -0,0 +1,522 @@ +//===-- ObjectContainerBigArchive.cpp -------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "ObjectContainerBigArchive.h" + +#if defined(_WIN32) || defined(__ANDROID__) || defined(__AIX__) +// Defines from ar, missing on Windows +#define ARMAG "!\n" +#define SARMAG 8 +#define ARFMAG "`\n" + +typedef struct ar_hdr { + char ar_name[16]; + char ar_date[12]; + char ar_uid[6], ar_gid[6]; + char ar_mode[8]; + char ar_size[10]; + char ar_fmag[2]; +} ar_hdr; +#else +#include +#endif + +#include "lldb/Core/Module.h" +#include "lldb/Core/ModuleSpec.h" +#include "lldb/Core/PluginManager.h" +#include "lldb/Host/FileSystem.h" +#include "lldb/Symbol/ObjectFile.h" +#include "lldb/Utility/ArchSpec.h" +#include "lldb/Utility/Stream.h" +#include "lldb/Utility/Timer.h" + +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Object/Archive.h" +#include "llvm/Support/Chrono.h" + +using namespace lldb; +using namespace lldb_private; + +LLDB_PLUGIN_DEFINE(ObjectContainerBigArchive) + +ObjectContainerBigArchive::Object::Object() : ar_name() {} + +void ObjectContainerBigArchive::Object::Clear() { + ar_name.Clear(); + modification_time = 0; + uid = 0; + gid = 0; + mode = 0; + size = 0; + file_offset = 0; + file_size = 0; +} + +lldb::offset_t +ObjectContainerBigArchive::Object::Extract(const DataExtractor &data, + lldb::offset_t offset) { + size_t ar_name_len = 0; + std::string str; + char *err; + + // File header + // + // The common format is as follows. + // + // Offset Length Name Format + // 0 16 File name ASCII right padded with spaces (no spaces + // allowed in file name) + // 16 12 File mod Decimal as cstring right padded with + // spaces + // 28 6 Owner ID Decimal as cstring right padded with + // spaces + // 34 6 Group ID Decimal as cstring right padded with + // spaces + // 40 8 File mode Octal as cstring right padded with + // spaces + // 48 10 File byte size Decimal as cstring right padded with + // spaces + // 58 2 File magic 0x60 0x0A + + // Make sure there is enough data for the file header and bail if not + if (!data.ValidOffsetForDataOfSize(offset, 60)) + return LLDB_INVALID_OFFSET; + + str.assign((const char *)data.GetData(&offset, 16), 16); + if (llvm::StringRef(str).starts_with("#1/")) { + // If the name is longer than 16 bytes, or contains an embedded space then + // it will use this format where the length of the name is here and the + // name characters are after this header. + ar_name_len = strtoul(str.c_str() + 3, &err, 10); + } else { + // Strip off any trailing spaces. + const size_t last_pos = str.find_last_not_of(' '); + if (last_pos != std::string::npos) { + if (last_pos + 1 < 16) + str.erase(last_pos + 1); + } + ar_name.SetCString(str.c_str()); + } + + str.assign((const char *)data.GetData(&offset, 12), 12); + modification_time = strtoul(str.c_str(), &err, 10); + + str.assign((const char *)data.GetData(&offset, 6), 6); + uid = strtoul(str.c_str(), &err, 10); + + str.assign((const char *)data.GetData(&offset, 6), 6); + gid = strtoul(str.c_str(), &err, 10); + + str.assign((const char *)data.GetData(&offset, 8), 8); + mode = strtoul(str.c_str(), &err, 8); + + str.assign((const char *)data.GetData(&offset, 10), 10); + size = strtoul(str.c_str(), &err, 10); + + str.assign((const char *)data.GetData(&offset, 2), 2); + if (str == ARFMAG) { + if (ar_name_len > 0) { + const void *ar_name_ptr = data.GetData(&offset, ar_name_len); + // Make sure there was enough data for the string value and bail if not + if (ar_name_ptr == nullptr) + return LLDB_INVALID_OFFSET; + str.assign((const char *)ar_name_ptr, ar_name_len); + ar_name.SetCString(str.c_str()); + } + file_offset = offset; + file_size = size - ar_name_len; + return offset; + } + return LLDB_INVALID_OFFSET; +} + +ObjectContainerBigArchive::Archive::Archive(const lldb_private::ArchSpec &arch, + const llvm::sys::TimePoint<> &time, + lldb::offset_t file_offset, + lldb_private::DataExtractor &data) + : m_arch(arch), m_modification_time(time), m_file_offset(file_offset), + m_objects(), m_data(data) {} + +ObjectContainerBigArchive::Archive::~Archive() = default; + +size_t ObjectContainerBigArchive::Archive::ParseObjects() { + DataExtractor &data = m_data; + std::string str; + lldb::offset_t offset = 0; + str.assign((const char *)data.GetData(&offset, (sizeof(llvm::object::BigArchiveMagic) - 1)), + (sizeof(llvm::object::BigArchiveMagic) - 1)); + if (str == llvm::object::BigArchiveMagic) { + llvm::Error err = llvm::Error::success(); + llvm::object::BigArchive bigAr(llvm::MemoryBufferRef(toStringRef(m_data.GetData()), llvm::StringRef("")), err); + if (err) + return 0; + + for (const llvm::object::Archive::Child &child : bigAr.children(err)) { + if (err) + continue; + if (!child.getParent()) + continue; + Object obj; + obj.Clear(); + // FIXME: check errors + llvm::Expected childNameOrErr = child.getName(); + if (!childNameOrErr) + continue; + obj.ar_name.SetCString(childNameOrErr->str().c_str()); + llvm::Expected> lastModifiedOrErr = child.getLastModified(); + if (!lastModifiedOrErr) + continue; + obj.modification_time = (uint32_t)llvm::sys::toTimeT(*(lastModifiedOrErr)); + llvm::Expected getUIDOrErr = child.getUID(); + if (!getUIDOrErr) + continue; + obj.uid = (uint16_t)*getUIDOrErr; + llvm::Expected getGIDOrErr = child.getGID(); + if (!getGIDOrErr) + continue; + obj.gid = (uint16_t)*getGIDOrErr; + llvm::Expected getAccessModeOrErr = child.getAccessMode(); + if (!getAccessModeOrErr) + continue; + obj.mode = (uint16_t)*getAccessModeOrErr; + llvm::Expected getRawSizeOrErr = child.getRawSize(); + if (!getRawSizeOrErr) + continue; + obj.size = (uint32_t)*getRawSizeOrErr; + + obj.file_offset = (lldb::offset_t)child.getDataOffset(); + + llvm::Expected getSizeOrErr = child.getSize(); + if (!getSizeOrErr) + continue; + obj.file_size = (lldb::offset_t)*getSizeOrErr; + + size_t obj_idx = m_objects.size(); + m_objects.push_back(obj); + // Insert all of the C strings out of order for now... + m_object_name_to_index_map.Append(obj.ar_name, obj_idx); + } + if (err) + return 0; + + // Now sort all of the object name pointers + m_object_name_to_index_map.Sort(); + } + return m_objects.size(); +} + +ObjectContainerBigArchive::Object * +ObjectContainerBigArchive::Archive::FindObject( + ConstString object_name, const llvm::sys::TimePoint<> &object_mod_time) { + const ObjectNameToIndexMap::Entry *match = + m_object_name_to_index_map.FindFirstValueForName(object_name); + if (!match) + return nullptr; + if (object_mod_time == llvm::sys::TimePoint<>()) + return &m_objects[match->value]; + + const uint64_t object_modification_date = llvm::sys::toTimeT(object_mod_time); + if (m_objects[match->value].modification_time == object_modification_date) + return &m_objects[match->value]; + + const ObjectNameToIndexMap::Entry *next_match = + m_object_name_to_index_map.FindNextValueForName(match); + while (next_match) { + if (m_objects[next_match->value].modification_time == + object_modification_date) + return &m_objects[next_match->value]; + next_match = m_object_name_to_index_map.FindNextValueForName(next_match); + } + + return nullptr; +} + +ObjectContainerBigArchive::Archive::shared_ptr +ObjectContainerBigArchive::Archive::FindCachedArchive( + const FileSpec &file, const ArchSpec &arch, + const llvm::sys::TimePoint<> &time, lldb::offset_t file_offset) { + std::lock_guard guard(Archive::GetArchiveCacheMutex()); + shared_ptr archive_sp; + Archive::Map &archive_map = Archive::GetArchiveCache(); + Archive::Map::iterator pos = archive_map.find(file); + // Don't cache a value for "archive_map.end()" below since we might delete an + // archive entry... + while (pos != archive_map.end() && pos->first == file) { + bool match = true; + if (arch.IsValid() && + !pos->second->GetArchitecture().IsCompatibleMatch(arch)) + match = false; + else if (file_offset != LLDB_INVALID_OFFSET && + pos->second->GetFileOffset() != file_offset) + match = false; + if (match) { + if (pos->second->GetModificationTime() == time) { + return pos->second; + } else { + // We have a file at the same path with the same architecture whose + // modification time doesn't match. It doesn't make sense for us to + // continue to use this Big archive since we cache only the object info + // which consists of file time info and also the file offset and file + // size of any contained objects. Since this information is now out of + // date, we won't get the correct information if we go and extract the + // file data, so we should remove the old and outdated entry. + archive_map.erase(pos); + pos = archive_map.find(file); + continue; // Continue to next iteration so we don't increment pos + // below... + } + } + ++pos; + } + return archive_sp; +} + +ObjectContainerBigArchive::Archive::shared_ptr +ObjectContainerBigArchive::Archive::ParseAndCacheArchiveForFile( + const FileSpec &file, const ArchSpec &arch, + const llvm::sys::TimePoint<> &time, lldb::offset_t file_offset, + DataExtractor &data) { + shared_ptr archive_sp(new Archive(arch, time, file_offset, data)); + if (archive_sp) { + const size_t num_objects = archive_sp->ParseObjects(); + if (num_objects > 0) { + std::lock_guard guard( + Archive::GetArchiveCacheMutex()); + Archive::GetArchiveCache().insert(std::make_pair(file, archive_sp)); + } else { + archive_sp.reset(); + } + } + return archive_sp; +} + +ObjectContainerBigArchive::Archive::Map & +ObjectContainerBigArchive::Archive::GetArchiveCache() { + static Archive::Map g_archive_map; + return g_archive_map; +} + +std::recursive_mutex & +ObjectContainerBigArchive::Archive::GetArchiveCacheMutex() { + static std::recursive_mutex g_archive_map_mutex; + return g_archive_map_mutex; +} + +void ObjectContainerBigArchive::Initialize() { + PluginManager::RegisterPlugin(GetPluginNameStatic(), + GetPluginDescriptionStatic(), CreateInstance, + GetModuleSpecifications); +} + +void ObjectContainerBigArchive::Terminate() { + PluginManager::UnregisterPlugin(CreateInstance); +} + +ObjectContainer *ObjectContainerBigArchive::CreateInstance( + const lldb::ModuleSP &module_sp, DataBufferSP &data_sp, + lldb::offset_t data_offset, const FileSpec *file, + lldb::offset_t file_offset, lldb::offset_t length) { + ConstString object_name(module_sp->GetObjectName()); + if (!object_name) + return nullptr; + + if (data_sp) { + // We have data, which means this is the first 512 bytes of the file Check + // to see if the magic bytes match and if they do, read the entire table of + // contents for the archive and cache it + DataExtractor data; + data.SetData(data_sp, data_offset, length); + if (file && data_sp && ObjectContainerBigArchive::MagicBytesMatch(data)) { + LLDB_SCOPED_TIMERF( + "ObjectContainerBigArchive::CreateInstance (module = %s, file = " + "%p, file_offset = 0x%8.8" PRIx64 ", file_size = 0x%8.8" PRIx64 ")", + module_sp->GetFileSpec().GetPath().c_str(), + static_cast(file), static_cast(file_offset), + static_cast(length)); + + // Map the entire .a file to be sure that we don't lose any data if the + // file gets updated by a new build while this .a file is being used for + // debugging + DataBufferSP archive_data_sp = + FileSystem::Instance().CreateDataBuffer(*file, length, file_offset); + if (!archive_data_sp) + return nullptr; + + lldb::offset_t archive_data_offset = 0; + + Archive::shared_ptr archive_sp(Archive::FindCachedArchive( + *file, module_sp->GetArchitecture(), module_sp->GetModificationTime(), + file_offset)); + std::unique_ptr container_up( + new ObjectContainerBigArchive(module_sp, archive_data_sp, + archive_data_offset, file, file_offset, + length)); + + if (container_up) { + if (archive_sp) { + // We already have this archive in our cache, use it + container_up->SetArchive(archive_sp); + return container_up.release(); + } else if (container_up->ParseHeader()) + return container_up.release(); + } + } + } else { + // No data, just check for a cached archive + Archive::shared_ptr archive_sp(Archive::FindCachedArchive( + *file, module_sp->GetArchitecture(), module_sp->GetModificationTime(), + file_offset)); + if (archive_sp) { + std::unique_ptr container_up( + new ObjectContainerBigArchive(module_sp, data_sp, data_offset, file, + file_offset, length)); + + if (container_up) { + // We already have this archive in our cache, use it + container_up->SetArchive(archive_sp); + return container_up.release(); + } + } + } + return nullptr; +} + +bool ObjectContainerBigArchive::MagicBytesMatch(const DataExtractor &data) { + uint32_t offset = 0; + const char *armag = (const char *)data.PeekData(offset, (sizeof(llvm::object::BigArchiveMagic) - 1)); + if (armag && ::strncmp(armag, llvm::object::BigArchiveMagic, (sizeof(llvm::object::BigArchiveMagic) - 1)) == 0) + return true; + return false; +} + +ObjectContainerBigArchive::ObjectContainerBigArchive( + const lldb::ModuleSP &module_sp, DataBufferSP &data_sp, + lldb::offset_t data_offset, const lldb_private::FileSpec *file, + lldb::offset_t file_offset, lldb::offset_t size) + : ObjectContainer(module_sp, file, file_offset, size, data_sp, data_offset), + m_archive_sp() {} +void ObjectContainerBigArchive::SetArchive(Archive::shared_ptr &archive_sp) { + m_archive_sp = archive_sp; +} + +ObjectContainerBigArchive::~ObjectContainerBigArchive() = default; + +bool ObjectContainerBigArchive::ParseHeader() { + if (m_archive_sp.get() == nullptr) { + if (m_data.GetByteSize() > 0) { + ModuleSP module_sp(GetModule()); + if (module_sp) { + m_archive_sp = Archive::ParseAndCacheArchiveForFile( + m_file, module_sp->GetArchitecture(), + module_sp->GetModificationTime(), m_offset, m_data); + } + // Clear the m_data that contains the entire archive data and let our + // m_archive_sp hold onto the data. + m_data.Clear(); + } + } + return m_archive_sp.get() != nullptr; +} + +void ObjectContainerBigArchive::Object::Dump(Stream *s) const { + printf("name = \"%s\"\n", ar_name.GetCString()); + printf("mtime = 0x%8.8" PRIx32 "\n", modification_time); + printf("size = 0x%8.8" PRIx32 " (%" PRIu32 ")\n", size, size); + printf("file_offset = 0x%16.16" PRIx64 " (%" PRIu64 ")\n", file_offset, + file_offset); + printf("file_size = 0x%16.16" PRIx64 " (%" PRIu64 ")\n\n", file_size, + file_size); +} + +ObjectFileSP ObjectContainerBigArchive::GetObjectFile(const FileSpec *file) { + ModuleSP module_sp(GetModule()); + if (module_sp) { + if (module_sp->GetObjectName() && m_archive_sp) { + Object *object = m_archive_sp->FindObject( + module_sp->GetObjectName(), module_sp->GetObjectModificationTime()); + if (object) { + lldb::offset_t data_offset = object->file_offset; + return ObjectFile::FindPlugin( + module_sp, file, m_offset + object->file_offset, object->file_size, + m_archive_sp->GetData().GetSharedDataBuffer(), data_offset); + } + } + } + return ObjectFileSP(); +} + +size_t ObjectContainerBigArchive::GetModuleSpecifications( + const lldb_private::FileSpec &file, lldb::DataBufferSP &data_sp, + lldb::offset_t data_offset, lldb::offset_t file_offset, + lldb::offset_t file_size, lldb_private::ModuleSpecList &specs) { + + // We have data, which means this is the first 512 bytes of the file Check to + // see if the magic bytes match and if they do, read the entire table of + // contents for the archive and cache it + DataExtractor data; + data.SetData(data_sp, data_offset, data_sp->GetByteSize()); + if (!file || !data_sp || !ObjectContainerBigArchive::MagicBytesMatch(data)) + return 0; + + const size_t initial_count = specs.GetSize(); + llvm::sys::TimePoint<> file_mod_time = FileSystem::Instance().GetModificationTime(file); + Archive::shared_ptr archive_sp( + Archive::FindCachedArchive(file, ArchSpec(), file_mod_time, file_offset)); + bool set_archive_arch = false; + if (!archive_sp) { + set_archive_arch = true; + data_sp = + FileSystem::Instance().CreateDataBuffer(file, file_size, file_offset); + if (data_sp) { + data.SetData(data_sp, 0, data_sp->GetByteSize()); + archive_sp = Archive::ParseAndCacheArchiveForFile( + file, ArchSpec(), file_mod_time, file_offset, data); + } + } + + if (archive_sp) { + const size_t num_objects = archive_sp->GetNumObjects(); + for (size_t idx = 0; idx < num_objects; ++idx) { + const Object *object = archive_sp->GetObjectAtIndex(idx); + if (object) { + const lldb::offset_t object_file_offset = + file_offset + object->file_offset; + if (object->file_offset < file_size && file_size > object_file_offset) { + if (ObjectFile::GetModuleSpecifications( + file, object_file_offset, file_size - object_file_offset, + specs)) { + ModuleSpec &spec = + specs.GetModuleSpecRefAtIndex(specs.GetSize() - 1); + llvm::sys::TimePoint<> object_mod_time( + std::chrono::seconds(object->modification_time)); + spec.GetObjectName() = object->ar_name; + spec.SetObjectOffset(object_file_offset); + spec.SetObjectSize(file_size - object_file_offset); + spec.GetObjectModificationTime() = object_mod_time; + } + } + } + } + } + const size_t end_count = specs.GetSize(); + size_t num_specs_added = end_count - initial_count; + if (set_archive_arch && num_specs_added > 0) { + // The archive was created but we didn't have an architecture so we need to + // set it + for (size_t i = initial_count; i < end_count; ++i) { + ModuleSpec module_spec; + if (specs.GetModuleSpecAtIndex(i, module_spec)) { + if (module_spec.GetArchitecture().IsValid()) { + archive_sp->SetArchitecture(module_spec.GetArchitecture()); + break; + } + } + } + } + return num_specs_added; +} diff --git a/lldb/source/Plugins/ObjectContainer/Big-Archive/ObjectContainerBigArchive.h b/lldb/source/Plugins/ObjectContainer/Big-Archive/ObjectContainerBigArchive.h new file mode 100644 index 000000000000000..ad9b814048a87de --- /dev/null +++ b/lldb/source/Plugins/ObjectContainer/Big-Archive/ObjectContainerBigArchive.h @@ -0,0 +1,177 @@ +//===-- ObjectContainerBigArchive.h -----------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLDB_SOURCE_PLUGINS_OBJECTCONTAINER_BIG_ARCHIVE_OBJECTCONTAINERBIGARCHIVE_H +#define LLDB_SOURCE_PLUGINS_OBJECTCONTAINER_BIG_ARCHIVE_OBJECTCONTAINERBIGARCHIVE_H + +#include "lldb/Core/UniqueCStringMap.h" +#include "lldb/Symbol/ObjectContainer.h" +#include "lldb/Utility/ArchSpec.h" +#include "lldb/Utility/ConstString.h" +#include "lldb/Utility/FileSpec.h" + +#include "llvm/Support/Chrono.h" + +#include +#include +#include + +class ObjectContainerBigArchive : public lldb_private::ObjectContainer { +public: + ObjectContainerBigArchive(const lldb::ModuleSP &module_sp, + lldb::DataBufferSP &data_sp, + lldb::offset_t data_offset, + const lldb_private::FileSpec *file, + lldb::offset_t offset, lldb::offset_t length); + + ~ObjectContainerBigArchive() override; + + // Static Functions + static void Initialize(); + + static void Terminate(); + + static llvm::StringRef GetPluginNameStatic() { return "big-archive"; } + + static llvm::StringRef GetPluginDescriptionStatic() { + return "Big Archive object container reader."; + } + + static lldb_private::ObjectContainer * + CreateInstance(const lldb::ModuleSP &module_sp, lldb::DataBufferSP &data_sp, + lldb::offset_t data_offset, const lldb_private::FileSpec *file, + lldb::offset_t offset, lldb::offset_t length); + + static size_t GetModuleSpecifications(const lldb_private::FileSpec &file, + lldb::DataBufferSP &data_sp, + lldb::offset_t data_offset, + lldb::offset_t file_offset, + lldb::offset_t length, + lldb_private::ModuleSpecList &specs); + + static bool MagicBytesMatch(const lldb_private::DataExtractor &data); + + // Member Functions + bool ParseHeader() override; + + size_t GetNumObjects() const override { + if (m_archive_sp) + return m_archive_sp->GetNumObjects(); + return 0; + } + + lldb::ObjectFileSP GetObjectFile(const lldb_private::FileSpec *file) override; + + // PluginInterface protocol + llvm::StringRef GetPluginName() override { return GetPluginNameStatic(); } + +protected: + struct Object { + Object(); + + void Clear(); + + lldb::offset_t Extract(const lldb_private::DataExtractor &data, + lldb::offset_t offset); + /// Object name in the archive. + lldb_private::ConstString ar_name; + + /// Object modification time in the archive. + uint32_t modification_time = 0; + + /// Object user id in the archive. + uint16_t uid = 0; + + /// Object group id in the archive. + uint16_t gid = 0; + + /// Object octal file permissions in the archive. + uint16_t mode = 0; + + /// Object size in bytes in the archive. + uint32_t size = 0; + + /// File offset in bytes from the beginning of the file of the object data. + lldb::offset_t file_offset = 0; + + /// Length of the object data. + lldb::offset_t file_size = 0; + + void Dump(lldb_private::Stream *s) const; + }; + + class Archive { + public: + typedef std::shared_ptr shared_ptr; + typedef std::multimap Map; + + Archive(const lldb_private::ArchSpec &arch, + const llvm::sys::TimePoint<> &mod_time, lldb::offset_t file_offset, + lldb_private::DataExtractor &data); + + ~Archive(); + + static Map &GetArchiveCache(); + + static std::recursive_mutex &GetArchiveCacheMutex(); + + static Archive::shared_ptr FindCachedArchive( + const lldb_private::FileSpec &file, const lldb_private::ArchSpec &arch, + const llvm::sys::TimePoint<> &mod_time, lldb::offset_t file_offset); + + static Archive::shared_ptr ParseAndCacheArchiveForFile( + const lldb_private::FileSpec &file, const lldb_private::ArchSpec &arch, + const llvm::sys::TimePoint<> &mod_time, lldb::offset_t file_offset, + lldb_private::DataExtractor &data); + + size_t GetNumObjects() const { return m_objects.size(); } + + const Object *GetObjectAtIndex(size_t idx) { + if (idx < m_objects.size()) + return &m_objects[idx]; + return nullptr; + } + + size_t ParseObjects(); + + Object *FindObject(lldb_private::ConstString object_name, + const llvm::sys::TimePoint<> &object_mod_time); + + lldb::offset_t GetFileOffset() const { return m_file_offset; } + + const llvm::sys::TimePoint<> &GetModificationTime() { + return m_modification_time; + } + + const lldb_private::ArchSpec &GetArchitecture() const { return m_arch; } + + void SetArchitecture(const lldb_private::ArchSpec &arch) { m_arch = arch; } + + bool HasNoExternalReferences() const; + + lldb_private::DataExtractor &GetData() { return m_data; } + + protected: + typedef lldb_private::UniqueCStringMap ObjectNameToIndexMap; + // Member Variables + lldb_private::ArchSpec m_arch; + llvm::sys::TimePoint<> m_modification_time; + lldb::offset_t m_file_offset; + std::vector m_objects; + ObjectNameToIndexMap m_object_name_to_index_map; + lldb_private::DataExtractor m_data; ///< The data for this object container + ///so we don't lose data if the .a files + ///gets modified + }; + + void SetArchive(Archive::shared_ptr &archive_sp); + + Archive::shared_ptr m_archive_sp; +}; + +#endif // LLDB_SOURCE_PLUGINS_OBJECTCONTAINER_BIG_ARCHIVE_OBJECTCONTAINERBIGARCHIVE_H diff --git a/lldb/source/Plugins/ObjectContainer/CMakeLists.txt b/lldb/source/Plugins/ObjectContainer/CMakeLists.txt index cda0c8151dd8a7e..2492798bb13ef22 100644 --- a/lldb/source/Plugins/ObjectContainer/CMakeLists.txt +++ b/lldb/source/Plugins/ObjectContainer/CMakeLists.txt @@ -1,3 +1,4 @@ add_subdirectory(BSD-Archive) +add_subdirectory(Big-Archive) add_subdirectory(Universal-Mach-O) add_subdirectory(Mach-O-Fileset) diff --git a/lldb/source/Plugins/ObjectFile/CMakeLists.txt b/lldb/source/Plugins/ObjectFile/CMakeLists.txt index 773241c8944c8ac..7abd0c96f4fd74e 100644 --- a/lldb/source/Plugins/ObjectFile/CMakeLists.txt +++ b/lldb/source/Plugins/ObjectFile/CMakeLists.txt @@ -6,5 +6,6 @@ add_subdirectory(Mach-O) add_subdirectory(Minidump) add_subdirectory(PDB) add_subdirectory(PECOFF) +add_subdirectory(XCOFF) add_subdirectory(Placeholder) add_subdirectory(wasm) diff --git a/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp b/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp index ce095bcc48374b2..bcb6330cbb1f9c0 100644 --- a/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp +++ b/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp @@ -5673,7 +5673,7 @@ bool ObjectFileMachO::GetCorefileMainBinaryInfo(addr_t &value, return false; } -bool ObjectFileMachO::GetCorefileThreadExtraInfos(std::vector &tids) { +bool ObjectFileMachO::GetCorefileThreadExtraInfos(std::vector &tids) { tids.clear(); ModuleSP module_sp(GetModule()); if (module_sp) { @@ -5724,8 +5724,8 @@ bool ObjectFileMachO::GetCorefileThreadExtraInfos(std::vector &tids) { return false; } StructuredData::Dictionary *thread = *maybe_thread; - tid_t tid = LLDB_INVALID_THREAD_ID; - if (thread->GetValueForKeyAsInteger("thread_id", tid)) + lldb::tid_t tid = LLDB_INVALID_THREAD_ID; + if (thread->GetValueForKeyAsInteger("thread_id", tid)) if (tid == 0) tid = LLDB_INVALID_THREAD_ID; tids.push_back(tid); diff --git a/lldb/source/Plugins/ObjectFile/Minidump/ObjectFileMinidump.cpp b/lldb/source/Plugins/ObjectFile/Minidump/ObjectFileMinidump.cpp index faa144bfb5f6a5b..d27cdfc60de8593 100644 --- a/lldb/source/Plugins/ObjectFile/Minidump/ObjectFileMinidump.cpp +++ b/lldb/source/Plugins/ObjectFile/Minidump/ObjectFileMinidump.cpp @@ -51,7 +51,9 @@ size_t ObjectFileMinidump::GetModuleSpecifications( const lldb_private::FileSpec &file, lldb::DataBufferSP &data_sp, lldb::offset_t data_offset, lldb::offset_t file_offset, lldb::offset_t length, lldb_private::ModuleSpecList &specs) { +#if !defined(__AIX__) specs.Clear(); +#endif return 0; } diff --git a/lldb/source/Plugins/ObjectFile/PDB/ObjectFilePDB.cpp b/lldb/source/Plugins/ObjectFile/PDB/ObjectFilePDB.cpp index f0832dbf07347a7..75cc54e4f0d484f 100644 --- a/lldb/source/Plugins/ObjectFile/PDB/ObjectFilePDB.cpp +++ b/lldb/source/Plugins/ObjectFile/PDB/ObjectFilePDB.cpp @@ -116,18 +116,31 @@ size_t ObjectFilePDB::GetModuleSpecifications( ModuleSpec module_spec(file); llvm::BumpPtrAllocator allocator; std::unique_ptr pdb_file = loadPDBFile(file.GetPath(), allocator); - if (!pdb_file) + if (!pdb_file){ +#if !defined(__AIX__) return initial_count; +#else + return specs.GetSize() - initial_count; +#endif + } auto info_stream = pdb_file->getPDBInfoStream(); if (!info_stream) { llvm::consumeError(info_stream.takeError()); +#if !defined(__AIX__) return initial_count; +#else + return specs.GetSize() - initial_count; +#endif } auto dbi_stream = pdb_file->getPDBDbiStream(); if (!dbi_stream) { llvm::consumeError(dbi_stream.takeError()); +#if !defined(__AIX__) return initial_count; +#else + return specs.GetSize() - initial_count; +#endif } lldb_private::UUID &uuid = module_spec.GetUUID(); diff --git a/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp b/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp index bda691ade8af025..db8fa78043fdca6 100644 --- a/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp +++ b/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp @@ -252,8 +252,13 @@ size_t ObjectFilePECOFF::GetModuleSpecifications( lldb::offset_t data_offset, lldb::offset_t file_offset, lldb::offset_t length, lldb_private::ModuleSpecList &specs) { const size_t initial_count = specs.GetSize(); - if (!data_sp || !ObjectFilePECOFF::MagicBytesMatch(data_sp)) + if (!data_sp || !ObjectFilePECOFF::MagicBytesMatch(data_sp)){ +#if !defined(__AIX__) return initial_count; +#else + return specs.GetSize() - initial_count; +#endif + } Log *log = GetLog(LLDBLog::Object); @@ -266,12 +271,21 @@ size_t ObjectFilePECOFF::GetModuleSpecifications( if (!binary) { LLDB_LOG_ERROR(log, binary.takeError(), "Failed to create binary for file ({1}): {0}", file); +#if !defined(__AIX__) return initial_count; +#else + return specs.GetSize() - initial_count; +#endif } auto *COFFObj = llvm::dyn_cast(binary->get()); - if (!COFFObj) + if (!COFFObj){ +#if !defined(__AIX__) return initial_count; +#else + return specs.GetSize() - initial_count; +#endif + } ModuleSpec module_spec(file); ArchSpec &spec = module_spec.GetArchitecture(); diff --git a/lldb/source/Plugins/ObjectFile/XCOFF/CMakeLists.txt b/lldb/source/Plugins/ObjectFile/XCOFF/CMakeLists.txt new file mode 100644 index 000000000000000..8840248574c886b --- /dev/null +++ b/lldb/source/Plugins/ObjectFile/XCOFF/CMakeLists.txt @@ -0,0 +1,13 @@ +add_lldb_library(lldbPluginObjectFileXCOFF PLUGIN + ObjectFileXCOFF.cpp + + LINK_LIBS + lldbCore + lldbHost + lldbSymbol + lldbTarget + LINK_COMPONENTS + BinaryFormat + Object + Support + ) diff --git a/lldb/source/Plugins/ObjectFile/XCOFF/ObjectFileXCOFF.cpp b/lldb/source/Plugins/ObjectFile/XCOFF/ObjectFileXCOFF.cpp new file mode 100644 index 000000000000000..a4d9ea295b4c393 --- /dev/null +++ b/lldb/source/Plugins/ObjectFile/XCOFF/ObjectFileXCOFF.cpp @@ -0,0 +1,780 @@ +//===-- ObjectFileXCOFF.cpp -------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "ObjectFileXCOFF.h" + +#include +#include +#include +#include + +#include "lldb/Utility/FileSpecList.h" +#include "lldb/Core/Module.h" +#include "lldb/Core/ModuleSpec.h" +#include "lldb/Core/PluginManager.h" +#include "lldb/Core/Progress.h" +#include "lldb/Core/Section.h" +#include "lldb/Host/FileSystem.h" +#include "lldb/Host/LZMA.h" +#include "lldb/Symbol/DWARFCallFrameInfo.h" +#include "lldb/Symbol/SymbolContext.h" +#include "lldb/Target/SectionLoadList.h" +#include "lldb/Target/Process.h" +#include "lldb/Target/Target.h" +#include "lldb/Utility/ArchSpec.h" +#include "lldb/Utility/DataBufferHeap.h" +#include "lldb/Utility/LLDBLog.h" +#include "lldb/Utility/Log.h" +#include "lldb/Utility/RangeMap.h" +#include "lldb/Utility/Status.h" +#include "lldb/Utility/Stream.h" +#include "lldb/Utility/Timer.h" +#include "llvm/ADT/IntervalMap.h" +#include "llvm/ADT/PointerUnion.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/BinaryFormat/XCOFF.h" +#include "llvm/Object/Decompressor.h" +#include "llvm/Support/CRC.h" +#include "llvm/Support/FormatVariadic.h" +#include "llvm/Support/MathExtras.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Object/XCOFFObjectFile.h" + +using namespace llvm; +using namespace lldb; +using namespace lldb_private; + +LLDB_PLUGIN_DEFINE(ObjectFileXCOFF) + +char ObjectFileXCOFF::ID; + +// FIXME: target 64bit at this moment. + +// Static methods. +void ObjectFileXCOFF::Initialize() { + PluginManager::RegisterPlugin(GetPluginNameStatic(), + GetPluginDescriptionStatic(), CreateInstance, + CreateMemoryInstance, GetModuleSpecifications); +} + +void ObjectFileXCOFF::Terminate() { + PluginManager::UnregisterPlugin(CreateInstance); +} + +bool UGLY_FLAG_FOR_AIX __attribute__((weak)) = false; + +ObjectFile *ObjectFileXCOFF::CreateInstance(const lldb::ModuleSP &module_sp, + DataBufferSP data_sp, + lldb::offset_t data_offset, + const lldb_private::FileSpec *file, + lldb::offset_t file_offset, + lldb::offset_t length) { + if (!data_sp) { + data_sp = MapFileData(*file, length, file_offset); + if (!data_sp) + return nullptr; + data_offset = 0; + } + + if (!ObjectFileXCOFF::MagicBytesMatch(data_sp, data_offset, length)) + return nullptr; + + // Update the data to contain the entire file if it doesn't already + if (data_sp->GetByteSize() < length) { + data_sp = MapFileData(*file, length, file_offset); + if (!data_sp) + return nullptr; + data_offset = 0; + } + auto objfile_up = std::make_unique( + module_sp, data_sp, data_offset, file, file_offset, length); + if (!objfile_up) + return nullptr; + + // Cache xcoff binary. + if (!objfile_up->CreateBinary()) + return nullptr; + + if (!objfile_up->ParseHeader()) + //FIXME objfile leak + return nullptr; + + UGLY_FLAG_FOR_AIX = true; + return objfile_up.release(); +} + +bool ObjectFileXCOFF::CreateBinary() { + if (m_binary) + return true; + + Log *log = GetLog(LLDBLog::Object); + + auto binary = llvm::object::XCOFFObjectFile::createObjectFile(llvm::MemoryBufferRef( + toStringRef(m_data.GetData()), m_file.GetFilename().GetStringRef()), + file_magic::xcoff_object_64); + if (!binary) { + LLDB_LOG_ERROR(log, binary.takeError(), + "Failed to create binary for file ({1}): {0}", m_file); + return false; + } + + // Make sure we only handle COFF format. + m_binary = + llvm::unique_dyn_cast(std::move(*binary)); + if (!m_binary) + return false; + + LLDB_LOG(log, "this = {0}, module = {1} ({2}), file = {3}, binary = {4}", + this, GetModule().get(), GetModule()->GetSpecificationDescription(), + m_file.GetPath(), m_binary.get()); + return true; +} + +ObjectFile *ObjectFileXCOFF::CreateMemoryInstance( + const lldb::ModuleSP &module_sp, WritableDataBufferSP data_sp, + const lldb::ProcessSP &process_sp, lldb::addr_t header_addr) { + return nullptr; +} + +size_t ObjectFileXCOFF::GetModuleSpecifications( + const lldb_private::FileSpec &file, lldb::DataBufferSP &data_sp, + lldb::offset_t data_offset, lldb::offset_t file_offset, + lldb::offset_t length, lldb_private::ModuleSpecList &specs) { + const size_t initial_count = specs.GetSize(); + + if (ObjectFileXCOFF::MagicBytesMatch(data_sp, 0, data_sp->GetByteSize())) { + ArchSpec arch_spec = ArchSpec(eArchTypeXCOFF, XCOFF::TCPU_PPC64, LLDB_INVALID_CPUTYPE); + ModuleSpec spec(file, arch_spec); + spec.GetArchitecture().SetArchitecture(eArchTypeXCOFF, XCOFF::TCPU_PPC64, LLDB_INVALID_CPUTYPE, llvm::Triple::AIX); + specs.Append(spec); + } + return specs.GetSize() - initial_count; +} + +static uint32_t XCOFFHeaderSizeFromMagic(uint32_t magic) { + switch (magic) { + /* TODO: 32bit not supported yet + case XCOFF::XCOFF32: + return sizeof(struct llvm::object::XCOFFFileHeader32); + */ + + case XCOFF::XCOFF64: + return sizeof(struct llvm::object::XCOFFFileHeader64); + break; + + default: + break; + } + return 0; +} + +bool ObjectFileXCOFF::MagicBytesMatch(DataBufferSP &data_sp, + lldb::addr_t data_offset, + lldb::addr_t data_length) { + lldb_private::DataExtractor data; + data.SetData(data_sp, data_offset, data_length); + lldb::offset_t offset = 0; + uint16_t magic = data.GetU16(&offset); + return XCOFFHeaderSizeFromMagic(magic) != 0; +} + +bool ObjectFileXCOFF::ParseHeader() { + ModuleSP module_sp(GetModule()); + if (module_sp) { + std::lock_guard guard(module_sp->GetMutex()); + m_sect_headers.clear(); + lldb::offset_t offset = 0; + + if (ParseXCOFFHeader(m_data, &offset, m_xcoff_header)) { + m_data.SetAddressByteSize(GetAddressByteSize()); + if (m_xcoff_header.auxhdrsize > 0) + ParseXCOFFOptionalHeader(m_data, &offset); + ParseSectionHeaders(offset); + } + return true; + } + + return false; +} + +bool ObjectFileXCOFF::ParseXCOFFHeader(lldb_private::DataExtractor &data, + lldb::offset_t *offset_ptr, + xcoff_header_t &xcoff_header) { + //FIXME: data.ValidOffsetForDataOfSize + xcoff_header.magic = data.GetU16(offset_ptr); + xcoff_header.nsects = data.GetU16(offset_ptr); + xcoff_header.modtime = data.GetU32(offset_ptr); + xcoff_header.symoff = data.GetU64(offset_ptr); + xcoff_header.auxhdrsize = data.GetU16(offset_ptr); + xcoff_header.flags = data.GetU16(offset_ptr); + xcoff_header.nsyms = data.GetU32(offset_ptr); + return true; +} + +bool ObjectFileXCOFF::ParseXCOFFOptionalHeader(lldb_private::DataExtractor &data, + lldb::offset_t *offset_ptr) { + lldb::offset_t init_offset = *offset_ptr; + //FIXME: data.ValidOffsetForDataOfSize + m_xcoff_aux_header.AuxMagic = data.GetU16(offset_ptr); + m_xcoff_aux_header.Version = data.GetU16(offset_ptr); + m_xcoff_aux_header.ReservedForDebugger = data.GetU32(offset_ptr); + m_xcoff_aux_header.TextStartAddr = data.GetU64(offset_ptr); + m_xcoff_aux_header.DataStartAddr = data.GetU64(offset_ptr); + m_xcoff_aux_header.TOCAnchorAddr = data.GetU64(offset_ptr); + m_xcoff_aux_header.SecNumOfEntryPoint = data.GetU16(offset_ptr); + m_xcoff_aux_header.SecNumOfText = data.GetU16(offset_ptr); + m_xcoff_aux_header.SecNumOfData = data.GetU16(offset_ptr); + m_xcoff_aux_header.SecNumOfTOC = data.GetU16(offset_ptr); + m_xcoff_aux_header.SecNumOfLoader = data.GetU16(offset_ptr); + m_xcoff_aux_header.SecNumOfBSS = data.GetU16(offset_ptr); + m_xcoff_aux_header.MaxAlignOfText = data.GetU16(offset_ptr); + m_xcoff_aux_header.MaxAlignOfData = data.GetU16(offset_ptr); + m_xcoff_aux_header.ModuleType = data.GetU16(offset_ptr); + m_xcoff_aux_header.CpuFlag = data.GetU8(offset_ptr); + m_xcoff_aux_header.CpuType = data.GetU8(offset_ptr); + m_xcoff_aux_header.TextPageSize = data.GetU8(offset_ptr); + m_xcoff_aux_header.DataPageSize = data.GetU8(offset_ptr); + m_xcoff_aux_header.StackPageSize = data.GetU8(offset_ptr); + m_xcoff_aux_header.FlagAndTDataAlignment = data.GetU8(offset_ptr); + m_xcoff_aux_header.TextSize = data.GetU64(offset_ptr); + m_xcoff_aux_header.InitDataSize = data.GetU64(offset_ptr); + m_xcoff_aux_header.BssDataSize = data.GetU64(offset_ptr); + m_xcoff_aux_header.EntryPointAddr = data.GetU64(offset_ptr); + m_xcoff_aux_header.MaxStackSize = data.GetU64(offset_ptr); + m_xcoff_aux_header.MaxDataSize = data.GetU64(offset_ptr); + m_xcoff_aux_header.SecNumOfTData = data.GetU16(offset_ptr); + m_xcoff_aux_header.SecNumOfTBSS = data.GetU16(offset_ptr); + m_xcoff_aux_header.XCOFF64Flag = data.GetU16(offset_ptr); + lldb::offset_t last_offset = *offset_ptr; + if ((last_offset - init_offset) < m_xcoff_header.auxhdrsize) + *offset_ptr += (m_xcoff_header.auxhdrsize - (last_offset - init_offset)); + return true; +} + +bool ObjectFileXCOFF::ParseSectionHeaders( + uint32_t section_header_data_offset) { + const uint32_t nsects = m_xcoff_header.nsects; + m_sect_headers.clear(); + + if (nsects > 0) { + const size_t section_header_byte_size = nsects * m_binary->getSectionHeaderSize(); + lldb_private::DataExtractor section_header_data = + ReadImageData(section_header_data_offset, section_header_byte_size); + + lldb::offset_t offset = 0; + //FIXME: section_header_data.ValidOffsetForDataOfSize + m_sect_headers.resize(nsects); + + for (uint32_t idx = 0; idx < nsects; ++idx) { + const void *name_data = section_header_data.GetData(&offset, 8); + if (name_data) { + memcpy(m_sect_headers[idx].name, name_data, 8); + m_sect_headers[idx].phyaddr = section_header_data.GetU64(&offset); + m_sect_headers[idx].vmaddr = section_header_data.GetU64(&offset); + m_sect_headers[idx].size = section_header_data.GetU64(&offset); + m_sect_headers[idx].offset = section_header_data.GetU64(&offset); + m_sect_headers[idx].reloff = section_header_data.GetU64(&offset); + m_sect_headers[idx].lineoff = section_header_data.GetU64(&offset); + m_sect_headers[idx].nreloc = section_header_data.GetU32(&offset); + m_sect_headers[idx].nline = section_header_data.GetU32(&offset); + m_sect_headers[idx].flags = section_header_data.GetU32(&offset); + offset += 4; + } else { + offset += (m_binary->getSectionHeaderSize() - 8); + } + } + } + + return !m_sect_headers.empty(); +} + +lldb_private::DataExtractor ObjectFileXCOFF::ReadImageData(uint32_t offset, size_t size) { + if (!size) + return {}; + + if (m_data.ValidOffsetForDataOfSize(offset, size)) + return lldb_private::DataExtractor(m_data, offset, size); + + assert(0); + ProcessSP process_sp(m_process_wp.lock()); + lldb_private::DataExtractor data; + if (process_sp) { + auto data_up = std::make_unique(size, 0); + Status readmem_error; + size_t bytes_read = + process_sp->ReadMemory(offset, data_up->GetBytes(), + data_up->GetByteSize(), readmem_error); + if (bytes_read == size) { + DataBufferSP buffer_sp(data_up.release()); + data.SetData(buffer_sp, 0, buffer_sp->GetByteSize()); + } + } + return data; +} + +bool ObjectFileXCOFF::SetLoadAddress(Target &target, lldb::addr_t value, + bool value_is_offset) { + bool changed = false; + ModuleSP module_sp = GetModule(); + if (module_sp) { + size_t num_loaded_sections = 0; + SectionList *section_list = GetSectionList(); + if (section_list) { + const size_t num_sections = section_list->GetSize(); + size_t sect_idx = 0; + + for (sect_idx = 0; sect_idx < num_sections; ++sect_idx) { + // Iterate through the object file sections to find all of the sections + // that have SHF_ALLOC in their flag bits. + SectionSP section_sp(section_list->GetSectionAtIndex(sect_idx)); + if (section_sp && !section_sp->IsThreadSpecific()) { + bool use_offset = false; + if (strcmp(section_sp->GetName().AsCString(), ".text") == 0 || + strcmp(section_sp->GetName().AsCString(), ".data") == 0 || + strcmp(section_sp->GetName().AsCString(), ".bss") == 0) + use_offset = true; + + if (target.GetSectionLoadList().SetSectionLoadAddress( + section_sp, (use_offset ? + (section_sp->GetFileOffset() + value) : (section_sp->GetFileAddress() + value)))) + ++num_loaded_sections; + } + } + changed = num_loaded_sections > 0; + } + } + return changed; +} + +bool ObjectFileXCOFF::SetLoadAddressByType(Target &target, lldb::addr_t value, + bool value_is_offset, int type_id) { + bool changed = false; + ModuleSP module_sp = GetModule(); + if (module_sp) { + size_t num_loaded_sections = 0; + SectionList *section_list = GetSectionList(); + if (section_list) { + const size_t num_sections = section_list->GetSize(); + size_t sect_idx = 0; + + for (sect_idx = 0; sect_idx < num_sections; ++sect_idx) { + // Iterate through the object file sections to find all of the sections + // that have SHF_ALLOC in their flag bits. + SectionSP section_sp(section_list->GetSectionAtIndex(sect_idx)); + if (type_id == 1 && section_sp && strcmp(section_sp->GetName().AsCString(), ".text") == 0) { + if (!section_sp->IsThreadSpecific()) { + if (target.GetSectionLoadList().SetSectionLoadAddress( + section_sp, section_sp->GetFileOffset() + value)) + ++num_loaded_sections; + } + } else if (type_id == 2 && section_sp && strcmp(section_sp->GetName().AsCString(), ".data") == 0) { + if (!section_sp->IsThreadSpecific()) { + if (target.GetSectionLoadList().SetSectionLoadAddress( + section_sp, section_sp->GetFileAddress() + value)) + ++num_loaded_sections; + } + } + } + changed = num_loaded_sections > 0; + } + } + return changed; +} + +ByteOrder ObjectFileXCOFF::GetByteOrder() const { + return eByteOrderBig; +} + +bool ObjectFileXCOFF::IsExecutable() const { + return true; +} + +uint32_t ObjectFileXCOFF::GetAddressByteSize() const { + if (m_xcoff_header.magic == XCOFF::XCOFF64) + return 8; + else if (m_xcoff_header.magic == XCOFF::XCOFF32) + return 4; + return 4; +} + +AddressClass ObjectFileXCOFF::GetAddressClass(addr_t file_addr) { + return AddressClass::eUnknown; +} + +lldb::SymbolType ObjectFileXCOFF::MapSymbolType(llvm::object::SymbolRef::Type sym_type) { + if (sym_type == llvm::object::SymbolRef::ST_Function) + return lldb::eSymbolTypeCode; + else if (sym_type == llvm::object::SymbolRef::ST_Data) + return lldb::eSymbolTypeData; + return lldb::eSymbolTypeInvalid; +} + +void ObjectFileXCOFF::ParseSymtab(Symtab &lldb_symtab) { + SectionList *sect_list = GetSectionList(); + const uint32_t num_syms = m_xcoff_header.nsyms; + uint32_t sidx = 0; + if (num_syms > 0 && m_xcoff_header.symoff > 0) { + const uint32_t symbol_size = XCOFF::SymbolTableEntrySize; + const size_t symbol_data_size = num_syms * symbol_size; + lldb_private::DataExtractor symtab_data = + ReadImageData(m_xcoff_header.symoff, symbol_data_size); + + lldb::offset_t offset = 0; + std::string symbol_name; + Symbol *symbols = lldb_symtab.Resize(num_syms); + llvm::object::symbol_iterator SI = m_binary->symbol_begin(); + for (uint32_t i = 0; i < num_syms; ++i, ++SI) { + xcoff_symbol_t symbol; + const uint32_t symbol_offset = offset; + symbol.value = symtab_data.GetU64(&offset); + symbol.offset = symtab_data.GetU32(&offset); + Expected symbol_name_or_err = m_binary->getStringTableEntry(symbol.offset); + if (!symbol_name_or_err) { + consumeError(symbol_name_or_err.takeError()); + return; + } + StringRef symbol_name_str = symbol_name_or_err.get(); + symbol_name.assign(symbol_name_str.data()); + symbol.sect = symtab_data.GetU16(&offset); + symbol.type = symtab_data.GetU16(&offset); + symbol.storage = symtab_data.GetU8(&offset); + symbol.naux = symtab_data.GetU8(&offset); + // Allow C_HIDEXT TOC symbol, and check others. + if (symbol.storage == XCOFF::C_HIDEXT && strcmp(symbol_name.c_str(), "TOC") != 0) { + if (symbol.naux == 0) + continue; + if (symbol.naux > 1) { + i += symbol.naux; + offset += symbol.naux * symbol_size; + continue; + } + /* Allow XCOFF::C_HIDEXT with following SMC and AT: + StorageMappingClass: XMC_PR (0x0) + Auxiliary Type: AUX_CSECT (0xFB) + */ + xcoff_sym_csect_aux_entry_t symbol_aux; + symbol_aux.section_or_len_low_byte = symtab_data.GetU32(&offset); + symbol_aux.parameter_hash_index = symtab_data.GetU32(&offset); + symbol_aux.type_check_sect_num = symtab_data.GetU16(&offset); + symbol_aux.symbol_alignment_and_type = symtab_data.GetU8(&offset); + symbol_aux.storage_mapping_class = symtab_data.GetU8(&offset); + symbol_aux.section_or_len_high_byte = symtab_data.GetU32(&offset); + symbol_aux.pad = symtab_data.GetU8(&offset); + symbol_aux.aux_type = symtab_data.GetU8(&offset); + offset -= symbol.naux * symbol_size; + if (symbol_aux.storage_mapping_class != XCOFF::XMC_PR || symbol_aux.aux_type != XCOFF::AUX_CSECT) { + i += symbol.naux; + offset += symbol.naux * symbol_size; + continue; + } + } + // Remove the dot prefix for demangle + if (symbol_name_str.size() > 1 && symbol_name_str.data()[0] == '.') { + symbols[sidx].GetMangled().SetValue(ConstString(symbol_name.c_str() + 1)); + } else { + symbols[sidx].GetMangled().SetValue(ConstString(symbol_name.c_str())); + } + if ((int16_t)symbol.sect >= 1) { + Address symbol_addr(sect_list->GetSectionAtIndex((size_t)(symbol.sect - 1)), + (symbol.value - sect_list->GetSectionAtIndex((size_t)(symbol.sect - 1))->GetFileAddress())); + symbols[sidx].GetAddressRef() = symbol_addr; + + Expected sym_type_or_err = SI->getType(); + if (!sym_type_or_err) { + consumeError(sym_type_or_err.takeError()); + return; + } + symbols[sidx].SetType(MapSymbolType(sym_type_or_err.get())); + } + ++sidx; + + if (symbol.naux > 0) { + i += symbol.naux; + offset += symbol.naux * symbol_size; + } + } + lldb_symtab.Resize(sidx); + } +} + +bool ObjectFileXCOFF::IsStripped() { + return false; +} + +void ObjectFileXCOFF::CreateSections(SectionList &unified_section_list) { + if (m_sections_up) + return; + m_sections_up = std::make_unique(); + ModuleSP module_sp(GetModule()); + if (module_sp) { + std::lock_guard guard(module_sp->GetMutex()); + + const uint32_t nsects = m_sect_headers.size(); + ModuleSP module_sp(GetModule()); + for (uint32_t idx = 0; idx < nsects; ++idx) { + llvm::StringRef sect_name = GetSectionName(m_sect_headers[idx]); + ConstString const_sect_name(sect_name); + SectionType section_type = GetSectionType(sect_name, m_sect_headers[idx]); + + SectionSP section_sp(new Section( + module_sp, // Module to which this section belongs + this, // Object file to which this section belongs + idx + 1, // Section ID is the 1 based section index. + const_sect_name, // Name of this section + section_type, + m_sect_headers[idx].vmaddr, // File VM address == addresses as + // they are found in the object file + m_sect_headers[idx].size, // VM size in bytes of this section + m_sect_headers[idx].offset, // Offset to the data for this section in the file + m_sect_headers[idx].size, // Size in bytes of this section as found in the file + 0, // FIXME: alignment + m_sect_headers[idx].flags)); // Flags for this section + + // FIXME + uint32_t permissions = 0; + permissions |= ePermissionsReadable; + if (m_sect_headers[idx].flags & (XCOFF::STYP_DATA | XCOFF::STYP_BSS)) + permissions |= ePermissionsWritable; + if (m_sect_headers[idx].flags & XCOFF::STYP_TEXT) + permissions |= ePermissionsExecutable; + section_sp->SetPermissions(permissions); + + m_sections_up->AddSection(section_sp); + unified_section_list.AddSection(section_sp); + } + } +} + +llvm::StringRef ObjectFileXCOFF::GetSectionName(const section_header_t §) { + llvm::StringRef hdr_name(sect.name, std::size(sect.name)); + hdr_name = hdr_name.split('\0').first; + if (hdr_name.consume_front("/")) { + lldb::offset_t stroff; + if (!to_integer(hdr_name, stroff, 10)) + return ""; + lldb::offset_t string_file_offset = + m_xcoff_header.symoff + (m_xcoff_header.nsyms * static_cast(XCOFF::SymbolTableEntrySize)) + stroff; + if (const char *name = m_data.GetCStr(&string_file_offset)) + return name; + return ""; + } + return hdr_name; +} + +SectionType ObjectFileXCOFF::GetSectionType(llvm::StringRef sect_name, + const section_header_t §) { + if (sect.flags & XCOFF::STYP_TEXT) + return eSectionTypeCode; + if (sect.flags & XCOFF::STYP_DATA) + return eSectionTypeData; + if (sect.flags & XCOFF::STYP_BSS) + return eSectionTypeZeroFill; + if (sect.flags & XCOFF::STYP_DWARF) { + SectionType section_type = + llvm::StringSwitch(sect_name) + .Case(".dwinfo", eSectionTypeDWARFDebugInfo) + .Case(".dwline", eSectionTypeDWARFDebugLine) + .Case(".dwabrev", eSectionTypeDWARFDebugAbbrev) + .Default(eSectionTypeInvalid); + + if (section_type != eSectionTypeInvalid) + return section_type; + } + return eSectionTypeOther; +} + +void ObjectFileXCOFF::Dump(Stream *s) { +} + +ArchSpec ObjectFileXCOFF::GetArchitecture() { + ArchSpec arch_spec = ArchSpec(eArchTypeXCOFF, XCOFF::TCPU_PPC64, LLDB_INVALID_CPUTYPE); + return arch_spec; +} + +UUID ObjectFileXCOFF::GetUUID() { + return UUID(); +} + +std::optional ObjectFileXCOFF::GetDebugLink() { + return std::nullopt; +} + +uint32_t ObjectFileXCOFF::ParseDependentModules() { + ModuleSP module_sp(GetModule()); + if (!module_sp) + return 0; + + std::lock_guard guard(module_sp->GetMutex()); + if (m_deps_filespec) + return m_deps_filespec->GetSize(); + + // Cache coff binary if it is not done yet. + if (!CreateBinary()) + return 0; + + Log *log = GetLog(LLDBLog::Object); + LLDB_LOG(log, "this = {0}, module = {1} ({2}), file = {3}, binary = {4}", + this, GetModule().get(), GetModule()->GetSpecificationDescription(), + m_file.GetPath(), m_binary.get()); + + m_deps_filespec = FileSpecList(); + + auto ImportFilesOrError = m_binary->getImportFileTable(); + if (!ImportFilesOrError) { + consumeError(ImportFilesOrError.takeError()); + return 0; + } + +#if 0 + StringRef ImportFileTable = ImportFilesOrError.get(); + const char *CurrentStr = ImportFileTable.data(); + const char *TableEnd = ImportFileTable.end(); + const char *Basename = nullptr; + + for (size_t StrIndex = 0; CurrentStr < TableEnd; + ++StrIndex, CurrentStr += strlen(CurrentStr) + 1) { + if (StrIndex >= 3 && StrIndex % 3 == 1) { + // base_name + llvm::StringRef dll_name(CurrentStr); + Basename = CurrentStr; + + // At this moment we only have the base name of the DLL. The full path can + // only be seen after the dynamic loading. Our best guess is Try to get it + // with the help of the object file's directory. + llvm::SmallString<128> dll_fullpath; + FileSpec dll_specs(dll_name); + // FIXME: hack to get libc.a loaded + if (strcmp(CurrentStr, "libc.a") == 0) { + dll_specs.GetDirectory().SetString("/usr/lib"); + } else { + dll_specs.GetDirectory().SetString(m_file.GetDirectory().GetCString()); + } + + if (!llvm::sys::fs::real_path(dll_specs.GetPath(), dll_fullpath)) + //m_deps_filespec->EmplaceBack(dll_fullpath); + m_deps_filespec->EmplaceBack("/usr/lib/libc.a(shr_64.o)"); + else { + // Known DLLs or DLL not found in the object file directory. + m_deps_filespec->EmplaceBack(dll_name); + } + } else if (StrIndex >= 3 && StrIndex % 3 == 2) { + // archive_member_name + if (strcmp(CurrentStr, "") == 0) { + continue; + } + assert(strcmp(Basename, "") != 0); + std::map>::iterator iter = m_deps_base_members.find(std::string(Basename)); + if (iter == m_deps_base_members.end()) { + m_deps_base_members[std::string(Basename)] = std::vector(); + iter = m_deps_base_members.find(std::string(Basename)); + } + iter->second.push_back(std::string(CurrentStr)); + } + } +#endif + return m_deps_filespec->GetSize(); +} + +uint32_t ObjectFileXCOFF::GetDependentModules(FileSpecList &files) { + auto num_modules = ParseDependentModules(); + auto original_size = files.GetSize(); + + for (unsigned i = 0; i < num_modules; ++i) + files.AppendIfUnique(m_deps_filespec->GetFileSpecAtIndex(i)); + + return files.GetSize() - original_size; +} + +Address ObjectFileXCOFF::GetImageInfoAddress(Target *target) { + return Address(); +} + +lldb_private::Address ObjectFileXCOFF::GetEntryPointAddress() { + if (m_entry_point_address.IsValid()) + return m_entry_point_address; + + if (!ParseHeader() || !IsExecutable()) + return m_entry_point_address; + + SectionList *section_list = GetSectionList(); + addr_t vm_addr = m_xcoff_aux_header.EntryPointAddr; + SectionSP section_sp( + section_list->FindSectionContainingFileAddress(vm_addr)); + if (section_sp) { + lldb::offset_t offset_ptr = section_sp->GetFileOffset() + (vm_addr - section_sp->GetFileAddress()); + vm_addr = m_data.GetU64(&offset_ptr); + } + + if (!section_list) + m_entry_point_address.SetOffset(vm_addr); + else + m_entry_point_address.ResolveAddressUsingFileSections(vm_addr, + section_list); + + return m_entry_point_address; +} + +lldb_private::Address ObjectFileXCOFF::GetBaseAddress() { + return lldb_private::Address(); +} + +ObjectFile::Type ObjectFileXCOFF::CalculateType() { + if (m_xcoff_header.flags & XCOFF::F_EXEC) + return eTypeExecutable; + else if (m_xcoff_header.flags & XCOFF::F_SHROBJ) + return eTypeSharedLibrary; + return eTypeUnknown; +} + +ObjectFile::Strata ObjectFileXCOFF::CalculateStrata() { + return eStrataUnknown; +} + +llvm::StringRef +ObjectFileXCOFF::StripLinkerSymbolAnnotations(llvm::StringRef symbol_name) const { + return llvm::StringRef(); +} + +void ObjectFileXCOFF::RelocateSection(lldb_private::Section *section) +{ +} + +std::vector +ObjectFileXCOFF::GetLoadableData(Target &target) { + std::vector loadables; + return loadables; +} + +lldb::WritableDataBufferSP +ObjectFileXCOFF::MapFileDataWritable(const FileSpec &file, uint64_t Size, + uint64_t Offset) { + return FileSystem::Instance().CreateWritableDataBuffer(file.GetPath(), Size, + Offset); +} + +ObjectFileXCOFF::ObjectFileXCOFF(const lldb::ModuleSP &module_sp, + DataBufferSP data_sp, lldb::offset_t data_offset, + const FileSpec *file, lldb::offset_t file_offset, + lldb::offset_t length) + : ObjectFile(module_sp, file, file_offset, length, data_sp, data_offset), + m_xcoff_header(), m_sect_headers(), m_deps_filespec(), m_deps_base_members(), + m_entry_point_address() { + ::memset(&m_xcoff_header, 0, sizeof(m_xcoff_header)); + if (file) + m_file = *file; +} + +ObjectFileXCOFF::ObjectFileXCOFF(const lldb::ModuleSP &module_sp, + DataBufferSP header_data_sp, + const lldb::ProcessSP &process_sp, + addr_t header_addr) + : ObjectFile(module_sp, process_sp, header_addr, header_data_sp), + m_xcoff_header(), m_sect_headers(), m_deps_filespec(), m_deps_base_members(), + m_entry_point_address() { + ::memset(&m_xcoff_header, 0, sizeof(m_xcoff_header)); +} diff --git a/lldb/source/Plugins/ObjectFile/XCOFF/ObjectFileXCOFF.h b/lldb/source/Plugins/ObjectFile/XCOFF/ObjectFileXCOFF.h new file mode 100644 index 000000000000000..5a12d16886489d5 --- /dev/null +++ b/lldb/source/Plugins/ObjectFile/XCOFF/ObjectFileXCOFF.h @@ -0,0 +1,243 @@ +//===-- ObjectFileXCOFF.h --------------------------------------- -*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLDB_SOURCE_PLUGINS_OBJECTFILE_XCOFF_OBJECTFILEXCOFF_H +#define LLDB_SOURCE_PLUGINS_OBJECTFILE_XCOFF_OBJECTFILEXCOFF_H + +#include + +#include + +#include "lldb/Symbol/ObjectFile.h" +#include "lldb/Utility/ArchSpec.h" +#include "lldb/Utility/FileSpec.h" +#include "lldb/Utility/UUID.h" +#include "lldb/lldb-private.h" +#include "llvm/Object/XCOFFObjectFile.h" + +/// \class ObjectFileXCOFF +/// Generic XCOFF object file reader. +/// +/// This class provides a generic XCOFF (32/64 bit) reader plugin implementing +/// the ObjectFile protocol. +class ObjectFileXCOFF : public lldb_private::ObjectFile { +public: + // Static Functions + static void Initialize(); + + static void Terminate(); + + static llvm::StringRef GetPluginNameStatic() { return "xcoff"; } + + static llvm::StringRef GetPluginDescriptionStatic() { + return "XCOFF object file reader."; + } + + static lldb_private::ObjectFile * + CreateInstance(const lldb::ModuleSP &module_sp, lldb::DataBufferSP data_sp, + lldb::offset_t data_offset, const lldb_private::FileSpec *file, + lldb::offset_t file_offset, lldb::offset_t length); + + static lldb_private::ObjectFile *CreateMemoryInstance( + const lldb::ModuleSP &module_sp, lldb::WritableDataBufferSP data_sp, + const lldb::ProcessSP &process_sp, lldb::addr_t header_addr); + + static size_t GetModuleSpecifications(const lldb_private::FileSpec &file, + lldb::DataBufferSP &data_sp, + lldb::offset_t data_offset, + lldb::offset_t file_offset, + lldb::offset_t length, + lldb_private::ModuleSpecList &specs); + + static bool MagicBytesMatch(lldb::DataBufferSP &data_sp, lldb::addr_t offset, + lldb::addr_t length); + + static lldb::SymbolType MapSymbolType(llvm::object::SymbolRef::Type sym_type); + + // PluginInterface protocol + llvm::StringRef GetPluginName() override { return GetPluginNameStatic(); } + + // LLVM RTTI support + static char ID; + bool isA(const void *ClassID) const override { + return ClassID == &ID || ObjectFile::isA(ClassID); + } + static bool classof(const ObjectFile *obj) { return obj->isA(&ID); } + + // ObjectFile Protocol. + bool ParseHeader() override; + + bool SetLoadAddress(lldb_private::Target &target, lldb::addr_t value, + bool value_is_offset) override; + + bool SetLoadAddressByType(lldb_private::Target &target, lldb::addr_t value, + bool value_is_offset, int type_id) override; + + lldb::ByteOrder GetByteOrder() const override; + + bool IsExecutable() const override; + + uint32_t GetAddressByteSize() const override; + + lldb_private::AddressClass GetAddressClass(lldb::addr_t file_addr) override; + + void ParseSymtab(lldb_private::Symtab &symtab) override; + + bool IsStripped() override; + + void CreateSections(lldb_private::SectionList &unified_section_list) override; + + void Dump(lldb_private::Stream *s) override; + + lldb_private::ArchSpec GetArchitecture() override; + + lldb_private::UUID GetUUID() override; + + /// Return the contents of the .gnu_debuglink section, if the object file + /// contains it. + std::optional GetDebugLink(); + + uint32_t GetDependentModules(lldb_private::FileSpecList &files) override; + + lldb_private::Address + GetImageInfoAddress(lldb_private::Target *target) override; + + lldb_private::Address GetEntryPointAddress() override; + + lldb_private::Address GetBaseAddress() override; + + ObjectFile::Type CalculateType() override; + + ObjectFile::Strata CalculateStrata() override; + + llvm::StringRef + StripLinkerSymbolAnnotations(llvm::StringRef symbol_name) const override; + + void RelocateSection(lldb_private::Section *section) override; + + lldb_private::DataExtractor ReadImageData(uint32_t offset, size_t size); + + ObjectFileXCOFF(const lldb::ModuleSP &module_sp, lldb::DataBufferSP data_sp, + lldb::offset_t data_offset, const lldb_private::FileSpec *file, + lldb::offset_t offset, lldb::offset_t length); + + ObjectFileXCOFF(const lldb::ModuleSP &module_sp, + lldb::DataBufferSP header_data_sp, + const lldb::ProcessSP &process_sp, lldb::addr_t header_addr); + +protected: + + typedef struct xcoff_header { + uint16_t magic; + uint16_t nsects; + uint32_t modtime; + uint64_t symoff; + uint32_t nsyms; + uint16_t auxhdrsize; + uint16_t flags; + } xcoff_header_t; + + typedef struct xcoff_aux_header { + uint16_t AuxMagic; + uint16_t Version; + uint32_t ReservedForDebugger; + uint64_t TextStartAddr; + uint64_t DataStartAddr; + uint64_t TOCAnchorAddr; + uint16_t SecNumOfEntryPoint; + uint16_t SecNumOfText; + uint16_t SecNumOfData; + uint16_t SecNumOfTOC; + uint16_t SecNumOfLoader; + uint16_t SecNumOfBSS; + uint16_t MaxAlignOfText; + uint16_t MaxAlignOfData; + uint16_t ModuleType; + uint8_t CpuFlag; + uint8_t CpuType; + uint8_t TextPageSize; + uint8_t DataPageSize; + uint8_t StackPageSize; + uint8_t FlagAndTDataAlignment; + uint64_t TextSize; + uint64_t InitDataSize; + uint64_t BssDataSize; + uint64_t EntryPointAddr; + uint64_t MaxStackSize; + uint64_t MaxDataSize; + uint16_t SecNumOfTData; + uint16_t SecNumOfTBSS; + uint16_t XCOFF64Flag; + } xcoff_aux_header_t; + + typedef struct section_header { + char name[8]; + uint64_t phyaddr; // Physical Addr + uint64_t vmaddr; // Virtual Addr + uint64_t size; // Section size + uint64_t offset; // File offset to raw data + uint64_t reloff; // Offset to relocations + uint64_t lineoff; // Offset to line table entries + uint32_t nreloc; // Number of relocation entries + uint32_t nline; // Number of line table entries + uint32_t flags; + } section_header_t; + + typedef struct xcoff_symbol { + uint64_t value; + uint32_t offset; + uint16_t sect; + uint16_t type; + uint8_t storage; + uint8_t naux; + } xcoff_symbol_t; + + typedef struct xcoff_sym_csect_aux_entry { + uint32_t section_or_len_low_byte; + uint32_t parameter_hash_index; + uint16_t type_check_sect_num; + uint8_t symbol_alignment_and_type; + uint8_t storage_mapping_class; + uint32_t section_or_len_high_byte; + uint8_t pad; + uint8_t aux_type; + } xcoff_sym_csect_aux_entry_t; + + static bool ParseXCOFFHeader(lldb_private::DataExtractor &data, + lldb::offset_t *offset_ptr, + xcoff_header_t &xcoff_header); + bool ParseXCOFFOptionalHeader(lldb_private::DataExtractor &data, + lldb::offset_t *offset_ptr); + bool ParseSectionHeaders(uint32_t offset); + + std::vector + GetLoadableData(lldb_private::Target &target) override; + + static lldb::WritableDataBufferSP + MapFileDataWritable(const lldb_private::FileSpec &file, uint64_t Size, + uint64_t Offset); + llvm::StringRef GetSectionName(const section_header_t §); + static lldb::SectionType GetSectionType(llvm::StringRef sect_name, + const section_header_t §); + + uint32_t ParseDependentModules(); + typedef std::vector SectionHeaderColl; + +private: + bool CreateBinary(); + + xcoff_header_t m_xcoff_header; + xcoff_aux_header_t m_xcoff_aux_header; + SectionHeaderColl m_sect_headers; + std::unique_ptr m_binary; + lldb_private::Address m_entry_point_address; + std::optional m_deps_filespec; + std::map> m_deps_base_members; +}; + +#endif // LLDB_SOURCE_PLUGINS_OBJECTFILE_ELF_OBJECTFILEELF_H diff --git a/lldb/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp b/lldb/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp index e026ffefd645eed..106e38b6e25ae36 100644 --- a/lldb/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp +++ b/lldb/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp @@ -227,7 +227,7 @@ ThreadSP OperatingSystemPython::CreateThreadFromThreadInfo( ThreadList &old_thread_list, std::vector &core_used_map, bool *did_create_ptr) { ThreadSP thread_sp; - tid_t tid = LLDB_INVALID_THREAD_ID; + lldb::tid_t tid = LLDB_INVALID_THREAD_ID; if (!thread_dict.GetValueForKeyAsInteger("tid", tid)) return ThreadSP(); diff --git a/lldb/source/Plugins/Platform/AIX/CMakeLists.txt b/lldb/source/Plugins/Platform/AIX/CMakeLists.txt new file mode 100644 index 000000000000000..85ff0a315eabd54 --- /dev/null +++ b/lldb/source/Plugins/Platform/AIX/CMakeLists.txt @@ -0,0 +1,13 @@ +add_definitions("-D_ALL_SOURCE") + +add_lldb_library(lldbPluginPlatformAIX PLUGIN + PlatformAIX.cpp + + LINK_LIBS + lldbBreakpoint + lldbCore + lldbHost + lldbInterpreter + lldbTarget + lldbPluginPlatformPOSIX + ) diff --git a/lldb/source/Plugins/Platform/AIX/PlatformAIX.cpp b/lldb/source/Plugins/Platform/AIX/PlatformAIX.cpp new file mode 100644 index 000000000000000..b6b08b73bec4137 --- /dev/null +++ b/lldb/source/Plugins/Platform/AIX/PlatformAIX.cpp @@ -0,0 +1,471 @@ +//===-- PlatformAIX.cpp -------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "PlatformAIX.h" +#include "lldb/Host/Config.h" + +#include +#if LLDB_ENABLE_POSIX +#include +#endif + +#include "Utility/ARM64_DWARF_Registers.h" +#include "lldb/Core/Debugger.h" +#include "lldb/Core/PluginManager.h" +#include "lldb/Host/HostInfo.h" +#include "lldb/Symbol/UnwindPlan.h" +#include "lldb/Target/Process.h" +#include "lldb/Target/Target.h" +#include "lldb/Utility/FileSpec.h" +#include "lldb/Utility/LLDBLog.h" +#include "lldb/Utility/Log.h" +#include "lldb/Utility/State.h" +#include "lldb/Utility/Status.h" +#include "lldb/Utility/StreamString.h" + +// Define these constants from AIX mman.h for use when targeting remote aix +// systems even when host has different values. + +#if defined(__AIX__) +#include +#endif + +using namespace lldb; +using namespace lldb_private; +using namespace lldb_private::platform_aix; + +LLDB_PLUGIN_DEFINE(PlatformAIX) + +static uint32_t g_initialize_count = 0; + + +PlatformSP PlatformAIX::CreateInstance(bool force, const ArchSpec *arch) { + Log *log = GetLog(LLDBLog::Platform); + LLDB_LOG(log, "force = {0}, arch=({1}, {2})", force, + arch ? arch->GetArchitectureName() : "", + arch ? arch->GetTriple().getTriple() : ""); + + bool create = force; + if (!create && arch && arch->IsValid()) { + const llvm::Triple &triple = arch->GetTriple(); + switch (triple.getOS()) { + case llvm::Triple::AIX: + create = true; + break; + + default: + break; + } + } + + LLDB_LOG(log, "create = {0}", create); + if (create) { + return PlatformSP(new PlatformAIX(false)); + } + return PlatformSP(); +} + +llvm::StringRef PlatformAIX::GetPluginDescriptionStatic(bool is_host) { + if (is_host) + return "Local AIX user platform plug-in."; + return "Remote AIX user platform plug-in."; +} + +void PlatformAIX::Initialize() { + PlatformPOSIX::Initialize(); + + if (g_initialize_count++ == 0) { +#if defined(__AIX__) + PlatformSP default_platform_sp(new PlatformAIX(true)); + default_platform_sp->SetSystemArchitecture(HostInfo::GetArchitecture()); + Platform::SetHostPlatform(default_platform_sp); +#endif + PluginManager::RegisterPlugin( + PlatformAIX::GetPluginNameStatic(false), + PlatformAIX::GetPluginDescriptionStatic(false), + PlatformAIX::CreateInstance, nullptr); + } +} + +void PlatformAIX::Terminate() { + if (g_initialize_count > 0) { + if (--g_initialize_count == 0) { + PluginManager::UnregisterPlugin(PlatformAIX::CreateInstance); + } + } + + PlatformPOSIX::Terminate(); +} + +/// Default Constructor +PlatformAIX::PlatformAIX(bool is_host) + : PlatformPOSIX(is_host) // This is the local host platform +{ + if (is_host) { + ArchSpec hostArch = HostInfo::GetArchitecture(HostInfo::eArchKindDefault); + m_supported_architectures.push_back(hostArch); + if (hostArch.GetTriple().isArch64Bit()) { + m_supported_architectures.push_back( + HostInfo::GetArchitecture(HostInfo::eArchKind32)); + } + } else { + m_supported_architectures = CreateArchList( + {llvm::Triple::x86_64, llvm::Triple::x86, llvm::Triple::arm, + llvm::Triple::aarch64, llvm::Triple::mips64, llvm::Triple::mips64, + llvm::Triple::hexagon, llvm::Triple::mips, llvm::Triple::mips64el, + llvm::Triple::mipsel, llvm::Triple::systemz}, + llvm::Triple::AIX); + } +} + +std::vector +PlatformAIX::GetSupportedArchitectures(const ArchSpec &process_host_arch) { + if (m_remote_platform_sp) + return m_remote_platform_sp->GetSupportedArchitectures(process_host_arch); + return m_supported_architectures; +} + +void PlatformAIX::GetStatus(Stream &strm) { + Platform::GetStatus(strm); + +#if LLDB_ENABLE_POSIX + // Display local kernel information only when we are running in host mode. + // Otherwise, we would end up printing non-AIX information (when running on + // Mac OS for example). + if (IsHost()) { + struct utsname un; + + if (uname(&un)) + return; + + strm.Printf(" Kernel: %s\n", un.sysname); + strm.Printf(" Release: %s\n", un.release); + strm.Printf(" Version: %s\n", un.version); + } +#endif +} + +uint32_t +PlatformAIX::GetResumeCountForLaunchInfo(ProcessLaunchInfo &launch_info) { + uint32_t resume_count = 0; + + // Always resume past the initial stop when we use eLaunchFlagDebug + if (launch_info.GetFlags().Test(eLaunchFlagDebug)) { + // Resume past the stop for the final exec into the true inferior. + ++resume_count; + } + + // If we're not launching a shell, we're done. + const FileSpec &shell = launch_info.GetShell(); + if (!shell) + return resume_count; + + std::string shell_string = shell.GetPath(); + // We're in a shell, so for sure we have to resume past the shell exec. + ++resume_count; + + // Figure out what shell we're planning on using. + const char *shell_name = strrchr(shell_string.c_str(), '/'); + if (shell_name == nullptr) + shell_name = shell_string.c_str(); + else + shell_name++; + + if (strcmp(shell_name, "csh") == 0 || strcmp(shell_name, "tcsh") == 0 || + strcmp(shell_name, "zsh") == 0 || strcmp(shell_name, "sh") == 0) { + // These shells seem to re-exec themselves. Add another resume. + ++resume_count; + } + + return resume_count; +} + +bool PlatformAIX::CanDebugProcess() { + if (IsHost()) { + return true; + } else { + // If we're connected, we can debug. + return IsConnected(); + } +} + +void PlatformAIX::CalculateTrapHandlerSymbolNames() { + m_trap_handlers.push_back(ConstString("_sigtramp")); + m_trap_handlers.push_back(ConstString("__kernel_rt_sigreturn")); + m_trap_handlers.push_back(ConstString("__restore_rt")); +} + +static lldb::UnwindPlanSP GetAArch64TrapHanlderUnwindPlan(ConstString name) { + UnwindPlanSP unwind_plan_sp; + if (name != "__kernel_rt_sigreturn") + return unwind_plan_sp; + + UnwindPlan::RowSP row = std::make_shared(); + row->SetOffset(0); + + // In the signal trampoline frame, sp points to an rt_sigframe[1], which is: + // - 128-byte siginfo struct + // - ucontext struct: + // - 8-byte long (uc_flags) + // - 8-byte pointer (uc_link) + // - 24-byte stack_t + // - 128-byte signal set + // - 8 bytes of padding because sigcontext has 16-byte alignment + // - sigcontext/mcontext_t + // [1] + // https://github.com/torvalds/linux/blob/master/arch/arm64/kernel/signal.c + int32_t offset = 128 + 8 + 8 + 24 + 128 + 8; + // Then sigcontext[2] is: + // - 8 byte fault address + // - 31 8 byte registers + // - 8 byte sp + // - 8 byte pc + // [2] + // https://github.com/torvalds/linux/blob/master/arch/arm64/include/uapi/asm/sigcontext.h + + // Skip fault address + offset += 8; + row->GetCFAValue().SetIsRegisterPlusOffset(arm64_dwarf::sp, offset); + + row->SetRegisterLocationToAtCFAPlusOffset(arm64_dwarf::x0, 0 * 8, false); + row->SetRegisterLocationToAtCFAPlusOffset(arm64_dwarf::x1, 1 * 8, false); + row->SetRegisterLocationToAtCFAPlusOffset(arm64_dwarf::x2, 2 * 8, false); + row->SetRegisterLocationToAtCFAPlusOffset(arm64_dwarf::x3, 3 * 8, false); + row->SetRegisterLocationToAtCFAPlusOffset(arm64_dwarf::x4, 4 * 8, false); + row->SetRegisterLocationToAtCFAPlusOffset(arm64_dwarf::x5, 5 * 8, false); + row->SetRegisterLocationToAtCFAPlusOffset(arm64_dwarf::x6, 6 * 8, false); + row->SetRegisterLocationToAtCFAPlusOffset(arm64_dwarf::x7, 7 * 8, false); + row->SetRegisterLocationToAtCFAPlusOffset(arm64_dwarf::x8, 8 * 8, false); + row->SetRegisterLocationToAtCFAPlusOffset(arm64_dwarf::x9, 9 * 8, false); + row->SetRegisterLocationToAtCFAPlusOffset(arm64_dwarf::x10, 10 * 8, false); + row->SetRegisterLocationToAtCFAPlusOffset(arm64_dwarf::x11, 11 * 8, false); + row->SetRegisterLocationToAtCFAPlusOffset(arm64_dwarf::x12, 12 * 8, false); + row->SetRegisterLocationToAtCFAPlusOffset(arm64_dwarf::x13, 13 * 8, false); + row->SetRegisterLocationToAtCFAPlusOffset(arm64_dwarf::x14, 14 * 8, false); + row->SetRegisterLocationToAtCFAPlusOffset(arm64_dwarf::x15, 15 * 8, false); + row->SetRegisterLocationToAtCFAPlusOffset(arm64_dwarf::x16, 16 * 8, false); + row->SetRegisterLocationToAtCFAPlusOffset(arm64_dwarf::x17, 17 * 8, false); + row->SetRegisterLocationToAtCFAPlusOffset(arm64_dwarf::x18, 18 * 8, false); + row->SetRegisterLocationToAtCFAPlusOffset(arm64_dwarf::x19, 19 * 8, false); + row->SetRegisterLocationToAtCFAPlusOffset(arm64_dwarf::x20, 20 * 8, false); + row->SetRegisterLocationToAtCFAPlusOffset(arm64_dwarf::x21, 21 * 8, false); + row->SetRegisterLocationToAtCFAPlusOffset(arm64_dwarf::x22, 22 * 8, false); + row->SetRegisterLocationToAtCFAPlusOffset(arm64_dwarf::x23, 23 * 8, false); + row->SetRegisterLocationToAtCFAPlusOffset(arm64_dwarf::x24, 24 * 8, false); + row->SetRegisterLocationToAtCFAPlusOffset(arm64_dwarf::x25, 25 * 8, false); + row->SetRegisterLocationToAtCFAPlusOffset(arm64_dwarf::x26, 26 * 8, false); + row->SetRegisterLocationToAtCFAPlusOffset(arm64_dwarf::x27, 27 * 8, false); + row->SetRegisterLocationToAtCFAPlusOffset(arm64_dwarf::x28, 28 * 8, false); + row->SetRegisterLocationToAtCFAPlusOffset(arm64_dwarf::fp, 29 * 8, false); + row->SetRegisterLocationToAtCFAPlusOffset(arm64_dwarf::x30, 30 * 8, false); + row->SetRegisterLocationToAtCFAPlusOffset(arm64_dwarf::sp, 31 * 8, false); + row->SetRegisterLocationToAtCFAPlusOffset(arm64_dwarf::pc, 32 * 8, false); + + // The sigcontext may also contain floating point and SVE registers. + // However this would require a dynamic unwind plan so they are not included + // here. + + unwind_plan_sp = std::make_shared(eRegisterKindDWARF); + unwind_plan_sp->AppendRow(row); + unwind_plan_sp->SetSourceName("AArch64 AIX sigcontext"); + unwind_plan_sp->SetSourcedFromCompiler(eLazyBoolYes); + // Because sp is the same throughout the function + unwind_plan_sp->SetUnwindPlanValidAtAllInstructions(eLazyBoolYes); + unwind_plan_sp->SetUnwindPlanForSignalTrap(eLazyBoolYes); + + return unwind_plan_sp; +} + +lldb::UnwindPlanSP +PlatformAIX::GetTrapHandlerUnwindPlan(const llvm::Triple &triple, + ConstString name) { + if (triple.isAArch64()) + return GetAArch64TrapHanlderUnwindPlan(name); + + return {}; +} + +MmapArgList PlatformAIX::GetMmapArgumentList(const ArchSpec &arch, + addr_t addr, addr_t length, + unsigned prot, unsigned flags, + addr_t fd, addr_t offset) { +#if defined(__AIX__) + unsigned flags_platform = MAP_VARIABLE | MAP_PRIVATE | MAP_ANONYMOUS; +#else + unsigned flags_platform = 0; +#endif + MmapArgList args({addr, length, prot, flags_platform, fd, offset}); + return args; +} + +CompilerType PlatformAIX::GetSiginfoType(const llvm::Triple &triple) { + if (!m_type_system_up) + m_type_system_up.reset(new TypeSystemClang("siginfo", triple)); + TypeSystemClang *ast = m_type_system_up.get(); + + bool si_errno_then_code = true; + + switch (triple.getArch()) { + case llvm::Triple::mips: + case llvm::Triple::mipsel: + case llvm::Triple::mips64: + case llvm::Triple::mips64el: + // mips has si_code and si_errno swapped + si_errno_then_code = false; + break; + default: + break; + } + + // generic types + CompilerType int_type = ast->GetBasicType(eBasicTypeInt); + CompilerType uint_type = ast->GetBasicType(eBasicTypeUnsignedInt); + CompilerType short_type = ast->GetBasicType(eBasicTypeShort); + CompilerType long_type = ast->GetBasicType(eBasicTypeLong); + CompilerType voidp_type = ast->GetBasicType(eBasicTypeVoid).GetPointerType(); + + // platform-specific types + CompilerType &pid_type = int_type; + CompilerType &uid_type = uint_type; + CompilerType &clock_type = long_type; + CompilerType &band_type = long_type; + + CompilerType sigval_type = ast->CreateRecordType( + nullptr, OptionalClangModuleID(), lldb::eAccessPublic, "__lldb_sigval_t", + llvm::to_underlying(clang::TagTypeKind::Union), lldb::eLanguageTypeC); + ast->StartTagDeclarationDefinition(sigval_type); + ast->AddFieldToRecordType(sigval_type, "sival_int", int_type, + lldb::eAccessPublic, 0); + ast->AddFieldToRecordType(sigval_type, "sival_ptr", voidp_type, + lldb::eAccessPublic, 0); + ast->CompleteTagDeclarationDefinition(sigval_type); + + CompilerType sigfault_bounds_type = ast->CreateRecordType( + nullptr, OptionalClangModuleID(), lldb::eAccessPublic, "", + llvm::to_underlying(clang::TagTypeKind::Union), lldb::eLanguageTypeC); + ast->StartTagDeclarationDefinition(sigfault_bounds_type); + ast->AddFieldToRecordType(sigfault_bounds_type, "_addr_bnd", + ast->CreateStructForIdentifier(ConstString(), + { + {"_lower", voidp_type}, + {"_upper", voidp_type}, + }), + lldb::eAccessPublic, 0); + ast->AddFieldToRecordType(sigfault_bounds_type, "_pkey", uint_type, + lldb::eAccessPublic, 0); + ast->CompleteTagDeclarationDefinition(sigfault_bounds_type); + + // siginfo_t + CompilerType siginfo_type = ast->CreateRecordType( + nullptr, OptionalClangModuleID(), lldb::eAccessPublic, "__lldb_siginfo_t", + llvm::to_underlying(clang::TagTypeKind::Struct), lldb::eLanguageTypeC); + ast->StartTagDeclarationDefinition(siginfo_type); + ast->AddFieldToRecordType(siginfo_type, "si_signo", int_type, + lldb::eAccessPublic, 0); + + if (si_errno_then_code) { + ast->AddFieldToRecordType(siginfo_type, "si_errno", int_type, + lldb::eAccessPublic, 0); + ast->AddFieldToRecordType(siginfo_type, "si_code", int_type, + lldb::eAccessPublic, 0); + } else { + ast->AddFieldToRecordType(siginfo_type, "si_code", int_type, + lldb::eAccessPublic, 0); + ast->AddFieldToRecordType(siginfo_type, "si_errno", int_type, + lldb::eAccessPublic, 0); + } + + // the structure is padded on 64-bit arches to fix alignment + if (triple.isArch64Bit()) + ast->AddFieldToRecordType(siginfo_type, "__pad0", int_type, + lldb::eAccessPublic, 0); + + // union used to hold the signal data + CompilerType union_type = ast->CreateRecordType( + nullptr, OptionalClangModuleID(), lldb::eAccessPublic, "", + llvm::to_underlying(clang::TagTypeKind::Union), lldb::eLanguageTypeC); + ast->StartTagDeclarationDefinition(union_type); + + ast->AddFieldToRecordType( + union_type, "_kill", + ast->CreateStructForIdentifier(ConstString(), + { + {"si_pid", pid_type}, + {"si_uid", uid_type}, + }), + lldb::eAccessPublic, 0); + + ast->AddFieldToRecordType( + union_type, "_timer", + ast->CreateStructForIdentifier(ConstString(), + { + {"si_tid", int_type}, + {"si_overrun", int_type}, + {"si_sigval", sigval_type}, + }), + lldb::eAccessPublic, 0); + + ast->AddFieldToRecordType( + union_type, "_rt", + ast->CreateStructForIdentifier(ConstString(), + { + {"si_pid", pid_type}, + {"si_uid", uid_type}, + {"si_sigval", sigval_type}, + }), + lldb::eAccessPublic, 0); + + ast->AddFieldToRecordType( + union_type, "_sigchld", + ast->CreateStructForIdentifier(ConstString(), + { + {"si_pid", pid_type}, + {"si_uid", uid_type}, + {"si_status", int_type}, + {"si_utime", clock_type}, + {"si_stime", clock_type}, + }), + lldb::eAccessPublic, 0); + + ast->AddFieldToRecordType( + union_type, "_sigfault", + ast->CreateStructForIdentifier(ConstString(), + { + {"si_addr", voidp_type}, + {"si_addr_lsb", short_type}, + {"_bounds", sigfault_bounds_type}, + }), + lldb::eAccessPublic, 0); + + ast->AddFieldToRecordType( + union_type, "_sigpoll", + ast->CreateStructForIdentifier(ConstString(), + { + {"si_band", band_type}, + {"si_fd", int_type}, + }), + lldb::eAccessPublic, 0); + + // NB: SIGSYS is not present on ia64 but we don't seem to support that + ast->AddFieldToRecordType( + union_type, "_sigsys", + ast->CreateStructForIdentifier(ConstString(), + { + {"_call_addr", voidp_type}, + {"_syscall", int_type}, + {"_arch", uint_type}, + }), + lldb::eAccessPublic, 0); + + ast->CompleteTagDeclarationDefinition(union_type); + ast->AddFieldToRecordType(siginfo_type, "_sifields", union_type, + lldb::eAccessPublic, 0); + + ast->CompleteTagDeclarationDefinition(siginfo_type); + return siginfo_type; +} diff --git a/lldb/source/Plugins/Platform/AIX/PlatformAIX.h b/lldb/source/Plugins/Platform/AIX/PlatformAIX.h new file mode 100644 index 000000000000000..3ae8089a48d7137 --- /dev/null +++ b/lldb/source/Plugins/Platform/AIX/PlatformAIX.h @@ -0,0 +1,74 @@ +//===-- PlatformAIX.h -----------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLDB_SOURCE_PLUGINS_PLATFORM_AIX_PLATFORMAIX_H +#define LLDB_SOURCE_PLUGINS_PLATFORM_AIX_PLATFORMAIX_H + +#include "Plugins/Platform/POSIX/PlatformPOSIX.h" +#include "Plugins/TypeSystem/Clang/TypeSystemClang.h" + +namespace lldb_private { +namespace platform_aix { + +class PlatformAIX : public PlatformPOSIX { +public: + PlatformAIX(bool is_host); + + static void Initialize(); + + static void Terminate(); + + // lldb_private::PluginInterface functions + static lldb::PlatformSP CreateInstance(bool force, const ArchSpec *arch); + + static llvm::StringRef GetPluginNameStatic(bool is_host) { + return is_host ? Platform::GetHostPlatformName() : "remote-AIX"; + } + + static llvm::StringRef GetPluginDescriptionStatic(bool is_host); + + llvm::StringRef GetPluginName() override { + return GetPluginNameStatic(IsHost()); + } + + // lldb_private::Platform functions + llvm::StringRef GetDescription() override { + return GetPluginDescriptionStatic(IsHost()); + } + + void GetStatus(Stream &strm) override; + + std::vector + GetSupportedArchitectures(const ArchSpec &process_host_arch) override; + + uint32_t GetResumeCountForLaunchInfo(ProcessLaunchInfo &launch_info) override; + + bool CanDebugProcess() override; + + void CalculateTrapHandlerSymbolNames() override; + + lldb::UnwindPlanSP GetTrapHandlerUnwindPlan(const llvm::Triple &triple, + ConstString name) override; + + MmapArgList GetMmapArgumentList(const ArchSpec &arch, lldb::addr_t addr, + lldb::addr_t length, unsigned prot, + unsigned flags, lldb::addr_t fd, + lldb::addr_t offset) override; + + CompilerType GetSiginfoType(const llvm::Triple &triple) override; + + std::vector m_supported_architectures; + +private: + std::unique_ptr m_type_system_up; +}; + +} // namespace platform_AIX +} // namespace lldb_private + +#endif // LLDB_SOURCE_PLUGINS_PLATFORM_AIX_PLATFORMAIX_H diff --git a/lldb/source/Plugins/Platform/CMakeLists.txt b/lldb/source/Plugins/Platform/CMakeLists.txt index 6869587f917ebab..9d0afd97cff853f 100644 --- a/lldb/source/Plugins/Platform/CMakeLists.txt +++ b/lldb/source/Plugins/Platform/CMakeLists.txt @@ -8,3 +8,4 @@ add_subdirectory(OpenBSD) add_subdirectory(POSIX) add_subdirectory(QemuUser) add_subdirectory(Windows) +add_subdirectory(AIX) diff --git a/lldb/source/Plugins/Process/AIX/CMakeLists.txt b/lldb/source/Plugins/Process/AIX/CMakeLists.txt new file mode 100644 index 000000000000000..e9d83266f5857cd --- /dev/null +++ b/lldb/source/Plugins/Process/AIX/CMakeLists.txt @@ -0,0 +1,19 @@ +add_definitions("-D_ALL_SOURCE") + +add_lldb_library(lldbPluginProcessAIX + NativeProcessAIX.cpp + NativeRegisterContextAIX.cpp + NativeRegisterContextAIX_ppc64.cpp + NativeThreadAIX.cpp + + LINK_LIBS + lldbCore + lldbHost + lldbSymbol + lldbTarget + lldbUtility + lldbPluginProcessPOSIX + lldbPluginProcessUtility + LINK_COMPONENTS + Support + ) diff --git a/lldb/source/Plugins/Process/AIX/NativeProcessAIX.cpp b/lldb/source/Plugins/Process/AIX/NativeProcessAIX.cpp new file mode 100644 index 000000000000000..882f20d30a3bf7a --- /dev/null +++ b/lldb/source/Plugins/Process/AIX/NativeProcessAIX.cpp @@ -0,0 +1,2048 @@ +//===-- NativeProcessAIX.cpp --------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "NativeProcessAIX.h" + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "NativeThreadAIX.h" +#include "Plugins/Process/POSIX/ProcessPOSIXLog.h" +//#include "Plugins/Process/Utility/LinuxProcMaps.h" +//#include "Procfs.h" +#include "lldb/Core/ModuleSpec.h" +#include "lldb/Host/Host.h" +#include "lldb/Host/HostProcess.h" +#include "lldb/Host/ProcessLaunchInfo.h" +#include "lldb/Host/PseudoTerminal.h" +#include "lldb/Host/ThreadLauncher.h" +#include "lldb/Host/common/NativeRegisterContext.h" +#include "lldb/Host/aix/Ptrace.h" +//#include "lldb/Host/linux/Host.h" +//#include "lldb/Host/linux/Uio.h" +#include "lldb/Host/posix/ProcessLauncherPosixFork.h" +#include "lldb/Symbol/ObjectFile.h" +#include "lldb/Target/Process.h" +#include "lldb/Target/Target.h" +#include "lldb/Utility/LLDBAssert.h" +#include "lldb/Utility/LLDBLog.h" +#include "lldb/Utility/RegisterValue.h" +#include "lldb/Utility/State.h" +#include "lldb/Utility/Status.h" +#include "lldb/Utility/StringExtractor.h" +#include "llvm/ADT/ScopeExit.h" +#include "llvm/Support/Errno.h" +#include "llvm/Support/Error.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/Threading.h" + +#include +#include +#include +#include +//#include +#include +#include +#include +#include + +#ifdef __aarch64__ +#include +#include +#endif + +// Support hardware breakpoints in case it has not been defined +#ifndef TRAP_HWBKPT +#define TRAP_HWBKPT 4 +#endif + +#ifndef HWCAP2_MTE +#define HWCAP2_MTE (1 << 18) +#endif + +using namespace lldb; +using namespace lldb_private; +using namespace lldb_private::process_aix; +using namespace llvm; + +// Private bits we only need internally. + +static bool ProcessVmReadvSupported() { + static bool is_supported; + static llvm::once_flag flag; + + llvm::call_once(flag, [] { + Log *log = GetLog(POSIXLog::Process); + + uint32_t source = 0x47424742; + uint32_t dest = 0; + + struct iovec local, remote; + remote.iov_base = &source; + local.iov_base = &dest; + remote.iov_len = local.iov_len = sizeof source; + +#if 0 + // We shall try if cross-process-memory reads work by attempting to read a + // value from our own process. + ssize_t res = process_vm_readv(getpid(), &local, 1, &remote, 1, 0); + is_supported = (res == sizeof(source) && source == dest); + if (is_supported) + LLDB_LOG(log, + "Detected kernel support for process_vm_readv syscall. " + "Fast memory reads enabled."); + else + LLDB_LOG(log, + "syscall process_vm_readv failed (error: {0}). Fast memory " + "reads disabled.", + llvm::sys::StrError()); +#endif + }); + + return is_supported; +} + +static void MaybeLogLaunchInfo(const ProcessLaunchInfo &info) { + Log *log = GetLog(POSIXLog::Process); + if (!log) + return; + + if (const FileAction *action = info.GetFileActionForFD(STDIN_FILENO)) + LLDB_LOG(log, "setting STDIN to '{0}'", action->GetFileSpec()); + else + LLDB_LOG(log, "leaving STDIN as is"); + + if (const FileAction *action = info.GetFileActionForFD(STDOUT_FILENO)) + LLDB_LOG(log, "setting STDOUT to '{0}'", action->GetFileSpec()); + else + LLDB_LOG(log, "leaving STDOUT as is"); + + if (const FileAction *action = info.GetFileActionForFD(STDERR_FILENO)) + LLDB_LOG(log, "setting STDERR to '{0}'", action->GetFileSpec()); + else + LLDB_LOG(log, "leaving STDERR as is"); + + int i = 0; + for (const char **args = info.GetArguments().GetConstArgumentVector(); *args; + ++args, ++i) + LLDB_LOG(log, "arg {0}: '{1}'", i, *args); +} + +static void DisplayBytes(StreamString &s, void *bytes, uint32_t count) { + uint8_t *ptr = (uint8_t *)bytes; + const uint32_t loop_count = std::min(DEBUG_PTRACE_MAXBYTES, count); + for (uint32_t i = 0; i < loop_count; i++) { + s.Printf("[%x]", *ptr); + ptr++; + } +} + +static void PtraceDisplayBytes(int &req, void *data, size_t data_size) { + Log *log = GetLog(POSIXLog::Ptrace); + if (!log) + return; + StreamString buf; + + switch (req) { + case PTRACE_POKETEXT: { + DisplayBytes(buf, &data, 8); + LLDB_LOGV(log, "PTRACE_POKETEXT {0}", buf.GetData()); + break; + } + case PTRACE_POKEDATA: { + DisplayBytes(buf, &data, 8); + LLDB_LOGV(log, "PTRACE_POKEDATA {0}", buf.GetData()); + break; + } + case PTRACE_POKEUSER: { + DisplayBytes(buf, &data, 8); + LLDB_LOGV(log, "PTRACE_POKEUSER {0}", buf.GetData()); + break; + } + case PTRACE_SETREGS: { + DisplayBytes(buf, data, data_size); + LLDB_LOGV(log, "PTRACE_SETREGS {0}", buf.GetData()); + break; + } + case PTRACE_SETFPREGS: { + DisplayBytes(buf, data, data_size); + LLDB_LOGV(log, "PTRACE_SETFPREGS {0}", buf.GetData()); + break; + } +#if 0 + case PTRACE_SETSIGINFO: { + DisplayBytes(buf, data, sizeof(siginfo_t)); + LLDB_LOGV(log, "PTRACE_SETSIGINFO {0}", buf.GetData()); + break; + } +#endif + case PTRACE_SETREGSET: { + // Extract iov_base from data, which is a pointer to the struct iovec + DisplayBytes(buf, *(void **)data, data_size); + LLDB_LOGV(log, "PTRACE_SETREGSET {0}", buf.GetData()); + break; + } + default: {} + } +} + +static constexpr unsigned k_ptrace_word_size = sizeof(void *); +static_assert(sizeof(long) >= k_ptrace_word_size, + "Size of long must be larger than ptrace word size"); + +// Simple helper function to ensure flags are enabled on the given file +// descriptor. +static Status EnsureFDFlags(int fd, int flags) { + Status error; + + int status = fcntl(fd, F_GETFL); + if (status == -1) { + error.SetErrorToErrno(); + return error; + } + + if (fcntl(fd, F_SETFL, status | flags) == -1) { + error.SetErrorToErrno(); + return error; + } + + return error; +} + +#if 0 +static llvm::Error AddPtraceScopeNote(llvm::Error original_error) { + Expected ptrace_scope = GetPtraceScope(); + if (auto E = ptrace_scope.takeError()) { + Log *log = GetLog(POSIXLog::Process); + LLDB_LOG(log, "error reading value of ptrace_scope: {0}", E); + + // The original error is probably more interesting than not being able to + // read or interpret ptrace_scope. + return original_error; + } + + // We only have suggestions to provide for 1-3. + switch (*ptrace_scope) { + case 1: + case 2: + return llvm::createStringError( + std::error_code(errno, std::generic_category()), + "The current value of ptrace_scope is %d, which can cause ptrace to " + "fail to attach to a running process. To fix this, run:\n" + "\tsudo sysctl -w kernel.yama.ptrace_scope=0\n" + "For more information, see: " + "https://www.kernel.org/doc/Documentation/security/Yama.txt.", + *ptrace_scope); + case 3: + return llvm::createStringError( + std::error_code(errno, std::generic_category()), + "The current value of ptrace_scope is 3, which will cause ptrace to " + "fail to attach to a running process. This value cannot be changed " + "without rebooting.\n" + "For more information, see: " + "https://www.kernel.org/doc/Documentation/security/Yama.txt."); + case 0: + default: + return original_error; + } +} +#endif + +NativeProcessAIX::Manager::Manager(MainLoop &mainloop) + : NativeProcessProtocol::Manager(mainloop) { + Status status; + m_sigchld_handle = mainloop.RegisterSignal( + SIGCHLD, [this](MainLoopBase &) { SigchldHandler(); }, status); + assert(m_sigchld_handle && status.Success()); +} + +// Public Static Methods + +llvm::Expected> +NativeProcessAIX::Manager::Launch(ProcessLaunchInfo &launch_info, + NativeDelegate &native_delegate) { + Log *log = GetLog(POSIXLog::Process); + + MaybeLogLaunchInfo(launch_info); + + Status status; + ::pid_t pid = ProcessLauncherPosixFork() + .LaunchProcess(launch_info, status) + .GetProcessId(); + LLDB_LOG(log, "pid = {0:x}", pid); + if (status.Fail()) { + LLDB_LOG(log, "failed to launch process: {0}", status); + return status.ToError(); + } + + // Wait for the child process to trap on its call to execve. + int wstatus = 0; + ::pid_t wpid = llvm::sys::RetryAfterSignal(-1, ::waitpid, pid, &wstatus, 0); + assert(wpid == pid); + UNUSED_IF_ASSERT_DISABLED(wpid); + if (!WIFSTOPPED(wstatus)) { + LLDB_LOG(log, "Could not sync with inferior process: wstatus={1}", + WaitStatus::Decode(wstatus)); + return llvm::make_error("Could not sync with inferior process", + llvm::inconvertibleErrorCode()); + } + LLDB_LOG(log, "inferior started, now in stopped state"); + + ProcessInstanceInfo Info; + if (!Host::GetProcessInfo(pid, Info)) { + return llvm::make_error("Cannot get process architectrue", + llvm::inconvertibleErrorCode()); + } + /*llvm::Expected arch_or = + NativeRegisterContextAIX::DetermineArchitecture(pid); + if (!arch_or) + return arch_or.takeError();*/ + + // Set the architecture to the exe architecture. + LLDB_LOG(log, "pid = {0}, detected architecture {1}", pid, + Info.GetArchitecture().GetArchitectureName()); + + return std::unique_ptr(new NativeProcessAIX( + pid, launch_info.GetPTY().ReleasePrimaryFileDescriptor(), native_delegate, + Info.GetArchitecture(), *this, {pid})); +} + +llvm::Expected> +NativeProcessAIX::Manager::Attach( + lldb::pid_t pid, NativeProcessProtocol::NativeDelegate &native_delegate) { + Log *log = GetLog(POSIXLog::Process); + LLDB_LOG(log, "pid = {0:x}", pid); + + ProcessInstanceInfo Info; + if (!Host::GetProcessInfo(pid, Info)) { + return llvm::make_error("Cannot get process architectrue", + llvm::inconvertibleErrorCode()); + } + auto tids_or = NativeProcessAIX::Attach(pid); + if (!tids_or) + return tids_or.takeError(); +#if 0 + ArrayRef<::pid_t> tids = *tids_or; + llvm::Expected arch_or = + NativeRegisterContextAIX::DetermineArchitecture(tids[0]); + if (!arch_or) + return arch_or.takeError(); +#endif + + return std::unique_ptr( + new NativeProcessAIX(pid, -1, native_delegate, Info.GetArchitecture(), *this, *tids_or)); +} + +lldb::addr_t NativeProcessAIX::GetSharedLibraryInfoAddress() { + // punt on this for now + return LLDB_INVALID_ADDRESS; +} + +NativeProcessAIX::Extension +NativeProcessAIX::Manager::GetSupportedExtensions() const { + NativeProcessAIX::Extension supported = + Extension::multiprocess | Extension::fork | Extension::vfork | + Extension::pass_signals | Extension::auxv | Extension::libraries_svr4 | + Extension::siginfo_read; + +#ifdef __aarch64__ + // At this point we do not have a process so read auxv directly. + if ((getauxval(AT_HWCAP2) & HWCAP2_MTE)) + supported |= Extension::memory_tagging; +#endif + + return supported; +} + +static std::optional> WaitPid() { + Log *log = GetLog(POSIXLog::Process); + + int status; + ::pid_t wait_pid = llvm::sys::RetryAfterSignal( + -1, ::waitpid, -1, &status, /*__WALL | __WNOTHREAD |*/ WNOHANG); + + if (wait_pid == 0) + return std::nullopt; + + if (wait_pid == -1) { + Status error(errno, eErrorTypePOSIX); + LLDB_LOG(log, "waitpid(-1, &status, _) failed: {1}", error); + return std::nullopt; + } + + WaitStatus wait_status = WaitStatus::Decode(status); + + LLDB_LOG(log, "waitpid(-1, &status, _) = {0}, status = {1}", wait_pid, + wait_status); + return std::make_pair(wait_pid, wait_status); +} + +void NativeProcessAIX::Manager::SigchldHandler() { + Log *log = GetLog(POSIXLog::Process); + while (true) { + auto wait_result = WaitPid(); + if (!wait_result) + return; + lldb::pid_t pid = wait_result->first; + WaitStatus status = wait_result->second; + + // Ask each process whether it wants to handle the event. Each event should + // be handled by exactly one process, but thread creation events require + // special handling. + // Thread creation consists of two events (one on the parent and one on the + // child thread) and they can arrive in any order nondeterministically. The + // parent event carries the information about the child thread, but not + // vice-versa. This means that if the child event arrives first, it may not + // be handled by any process (because it doesn't know the thread belongs to + // it). + bool handled = llvm::any_of(m_processes, [&](NativeProcessAIX *process) { + return process->TryHandleWaitStatus(pid, status); + }); + if (!handled) { + if (status.type == WaitStatus::Stop && status.status == SIGSTOP) { + // Store the thread creation event for later collection. + m_unowned_threads.insert(pid); + } else { + LLDB_LOG(log, "Ignoring waitpid event {0} for pid {1}", status, pid); + } + } + } +} + +void NativeProcessAIX::Manager::CollectThread(::pid_t tid) { + Log *log = GetLog(POSIXLog::Process); + + if (m_unowned_threads.erase(tid)) + return; // We've encountered this thread already. + + // The TID is not tracked yet, let's wait for it to appear. + int status = -1; + LLDB_LOG(log, + "received clone event for tid {0}. tid not tracked yet, " + "waiting for it to appear...", + tid); + ::pid_t wait_pid = + llvm::sys::RetryAfterSignal(-1, ::waitpid, tid, &status, P_ALL/*__WALL*/); + + // It's theoretically possible to get other events if the entire process was + // SIGKILLed before we got a chance to check this. In that case, we'll just + // clean everything up when we get the process exit event. + + LLDB_LOG(log, + "waitpid({0}, &status, __WALL) => {1} (errno: {2}, status = {3})", + tid, wait_pid, errno, WaitStatus::Decode(status)); +} + +// Public Instance Methods + +NativeProcessAIX::NativeProcessAIX(::pid_t pid, int terminal_fd, + NativeDelegate &delegate, + const ArchSpec &arch, Manager &manager, + llvm::ArrayRef<::pid_t> tids) + : NativeProcessProtocol(pid, terminal_fd, delegate), m_manager(manager), + m_arch(arch) { + manager.AddProcess(*this); + if (m_terminal_fd != -1) { + Status status = EnsureFDFlags(m_terminal_fd, O_NONBLOCK); + assert(status.Success()); + } + + for (const auto &tid : tids) { + NativeThreadAIX &thread = AddThread(tid, /*resume*/ false); + ThreadWasCreated(thread); + } + + // Let our process instance know the thread has stopped. + SetCurrentThreadID(tids[0]); + SetState(StateType::eStateStopped, false); +} + +llvm::Expected> NativeProcessAIX::Attach(::pid_t pid) { + Log *log = GetLog(POSIXLog::Process); + + Status status; + if ((status = PtraceWrapper(PT_ATTACH, pid)).Fail()) { + return status.ToError(); + } + + int wpid = + llvm::sys::RetryAfterSignal(-1, ::waitpid, pid, nullptr, WNOHANG); + if (wpid <= 0) { + return llvm::errorCodeToError( + std::error_code(errno, std::generic_category())); + } + + LLDB_LOG(log, "adding pid = {0}", pid); + + std::vector<::pid_t> tids; + tids.push_back(pid); + return std::move(tids); +} + +bool NativeProcessAIX::TryHandleWaitStatus(lldb::pid_t pid, + WaitStatus status) { + if (pid == GetID() && + (status.type == WaitStatus::Exit || status.type == WaitStatus::Signal)) { + // The process exited. We're done monitoring. Report to delegate. + SetExitStatus(status, true); + return true; + } + if (NativeThreadAIX *thread = GetThreadByID(pid)) { + MonitorCallback(*thread, status); + return true; + } + return false; +} + +// Handles all waitpid events from the inferior process. +void NativeProcessAIX::MonitorCallback(NativeThreadAIX &thread, + WaitStatus status) { + Log *log = GetLog(LLDBLog::Process); + + // Certain activities differ based on whether the pid is the tid of the main + // thread. + const bool is_main_thread = (thread.GetID() == GetID()); + + // Handle when the thread exits. + if (status.type == WaitStatus::Exit || status.type == WaitStatus::Signal) { + LLDB_LOG(log, + "got exit status({0}) , tid = {1} ({2} main thread), process " + "state = {3}", + status, thread.GetID(), is_main_thread ? "is" : "is not", + GetState()); + + // This is a thread that exited. Ensure we're not tracking it anymore. + StopTrackingThread(thread); + + assert(!is_main_thread && "Main thread exits handled elsewhere"); + return; + } + + int8_t signo = GetSignalInfo(status); + + // Get details on the signal raised. + if (signo) { + // We have retrieved the signal info. Dispatch appropriately. + if (signo == SIGTRAP) + MonitorSIGTRAP(status, thread); + else + MonitorSignal(status, thread); + } else { + assert(0); + } +} + + +void NativeProcessAIX::MonitorSIGTRAP(const WaitStatus status, + NativeThreadAIX &thread) { + Log *log = GetLog(POSIXLog::Process); + const bool is_main_thread = (thread.GetID() == GetID()); + + NativeRegisterContextAIX ®_ctx = thread.GetRegisterContext(); + const RegisterInfo *pc_info = reg_ctx.GetRegisterInfoByName("pc", 0); + RegisterValue pc_value; + + switch (status.status) { + case SIGTRAP: + // Determine the source of SIGTRAP by checking current instruction: + // if that is trap instruction, then this is breakpoint, otherwise + // this is watchpoint. + reg_ctx.ReadRegister(pc_info, pc_value); + + MonitorBreakpoint(thread); + break; + default: + LLDB_LOG(log, "received unknown SIGTRAP stop event ({0}, pid {1} tid {2}", + status.status, GetID(), thread.GetID()); + MonitorSignal(status, thread); + break; + } +} + +void NativeProcessAIX::MonitorTrace(NativeThreadAIX &thread) { + Log *log = GetLog(POSIXLog::Process); + LLDB_LOG(log, "received trace event, pid = {0}", thread.GetID()); + + // This thread is currently stopped. + thread.SetStoppedByTrace(); + + StopRunningThreads(thread.GetID()); +} + +void NativeProcessAIX::MonitorBreakpoint(NativeThreadAIX &thread) { + Log *log = GetLog(LLDBLog::Process | LLDBLog::Breakpoints); + LLDB_LOG(log, "received breakpoint event, pid = {0}", thread.GetID()); + + // Mark the thread as stopped at breakpoint. + thread.SetStoppedByBreakpoint(); + FixupBreakpointPCAsNeeded(thread); + + if (m_threads_stepping_with_breakpoint.find(thread.GetID()) != + m_threads_stepping_with_breakpoint.end()) + thread.SetStoppedByTrace(); + + StopRunningThreads(thread.GetID()); +} + +void NativeProcessAIX::MonitorWatchpoint(NativeThreadAIX &thread, + uint32_t wp_index) { + Log *log = GetLog(LLDBLog::Process | LLDBLog::Watchpoints); + LLDB_LOG(log, "received watchpoint event, pid = {0}, wp_index = {1}", + thread.GetID(), wp_index); + + // Mark the thread as stopped at watchpoint. The address is at + // (lldb::addr_t)info->si_addr if we need it. + thread.SetStoppedByWatchpoint(wp_index); + + // We need to tell all other running threads before we notify the delegate + // about this stop. + StopRunningThreads(thread.GetID()); +} + +void NativeProcessAIX::MonitorSignal(const WaitStatus status, + NativeThreadAIX &thread) { + int8_t signo = GetSignalInfo(status); +#if 0 + const bool is_from_llgs = info.si_pid == getpid(); +#endif + + Log *log = GetLog(POSIXLog::Process); + + // POSIX says that process behaviour is undefined after it ignores a SIGFPE, + // SIGILL, SIGSEGV, or SIGBUS *unless* that signal was generated by a kill(2) + // or raise(3). Similarly for tgkill(2) on AIX. + // + // IOW, user generated signals never generate what we consider to be a + // "crash". + // + // Similarly, ACK signals generated by this monitor. + + // Handle the signal. + LLDB_LOG(log, + "received signal {0} ({1}) with code NA, (siginfo pid = {2}, " + "waitpid pid = {3})", + Host::GetSignalAsCString(signo), signo, thread.GetID(), GetID()); + +#if 0 + // Check for thread stop notification. + // FIXME + if (is_from_llgs /*&& (info.si_code == SI_TKILL)*/ && (signo == SIGSTOP)) { + // This is a tgkill()-based stop. + LLDB_LOG(log, "pid {0} tid {1}, thread stopped", GetID(), thread.GetID()); + + // Check that we're not already marked with a stop reason. Note this thread + // really shouldn't already be marked as stopped - if we were, that would + // imply that the kernel signaled us with the thread stopping which we + // handled and marked as stopped, and that, without an intervening resume, + // we received another stop. It is more likely that we are missing the + // marking of a run state somewhere if we find that the thread was marked + // as stopped. + const StateType thread_state = thread.GetState(); + if (!StateIsStoppedState(thread_state, false)) { + // An inferior thread has stopped because of a SIGSTOP we have sent it. + // Generally, these are not important stops and we don't want to report + // them as they are just used to stop other threads when one thread (the + // one with the *real* stop reason) hits a breakpoint (watchpoint, + // etc...). However, in the case of an asynchronous Interrupt(), this + // *is* the real stop reason, so we leave the signal intact if this is + // the thread that was chosen as the triggering thread. + if (m_pending_notification_tid != LLDB_INVALID_THREAD_ID) { + if (m_pending_notification_tid == thread.GetID()) + thread.SetStoppedBySignal(SIGSTOP, &info); + else + thread.SetStoppedWithNoReason(); + + SetCurrentThreadID(thread.GetID()); + SignalIfAllThreadsStopped(); + } else { + // We can end up here if stop was initiated by LLGS but by this time a + // thread stop has occurred - maybe initiated by another event. + Status error = ResumeThread(thread, thread.GetState(), 0); + if (error.Fail()) + LLDB_LOG(log, "failed to resume thread {0}: {1}", thread.GetID(), + error); + } + } else { + LLDB_LOG(log, + "pid {0} tid {1}, thread was already marked as a stopped " + "state (state={2}), leaving stop signal as is", + GetID(), thread.GetID(), thread_state); + SignalIfAllThreadsStopped(); + } + + // Done handling. + return; + } +#endif + + // Check if debugger should stop at this signal or just ignore it and resume + // the inferior. + if (m_signals_to_ignore.contains(signo) || signo == SIGCHLD) { + ResumeThread(thread, thread.GetState(), signo); + return; + } + + // This thread is stopped. + LLDB_LOG(log, "received signal {0}", Host::GetSignalAsCString(signo)); + thread.SetStoppedBySignal(signo); + + // Send a stop to the debugger after we get all other threads to stop. + StopRunningThreads(thread.GetID()); +} + +bool NativeProcessAIX::MonitorClone(NativeThreadAIX &parent, + lldb::pid_t child_pid, int event) { + Log *log = GetLog(POSIXLog::Process); + LLDB_LOG(log, "parent_tid={0}, child_pid={1}, event={2}", parent.GetID(), + child_pid, event); + + // WaitForCloneNotification(child_pid); + + switch (event) { +#if 0 + case PTRACE_EVENT_CLONE: { + // PTRACE_EVENT_CLONE can either mean a new thread or a new process. + // Try to grab the new process' PGID to figure out which one it is. + // If PGID is the same as the PID, then it's a new process. Otherwise, + // it's a thread. + auto tgid_ret = getPIDForTID(child_pid); + if (tgid_ret != child_pid) { + // A new thread should have PGID matching our process' PID. + assert(!tgid_ret || tgid_ret.getValue() == GetID()); + + NativeThreadAIX &child_thread = AddThread(child_pid, /*resume*/ true); + ThreadWasCreated(child_thread); + + // Resume the parent. + ResumeThread(parent, parent.GetState(), LLDB_INVALID_SIGNAL_NUMBER); + break; + } + } + LLVM_FALLTHROUGH; + case PTRACE_EVENT_FORK: + case PTRACE_EVENT_VFORK: { + bool is_vfork = event == PTRACE_EVENT_VFORK; + std::unique_ptr child_process{new NativeProcessAIX( + static_cast<::pid_t>(child_pid), m_terminal_fd, m_delegate, m_arch, + m_main_loop, {static_cast<::pid_t>(child_pid)})}; + if (!is_vfork) + child_process->m_software_breakpoints = m_software_breakpoints; + + Extension expected_ext = is_vfork ? Extension::vfork : Extension::fork; + if (bool(m_enabled_extensions & expected_ext)) { + m_delegate.NewSubprocess(this, std::move(child_process)); + // NB: non-vfork clone() is reported as fork + parent.SetStoppedByFork(is_vfork, child_pid); + StopRunningThreads(parent.GetID()); + } else { + child_process->Detach(); + ResumeThread(parent, parent.GetState(), LLDB_INVALID_SIGNAL_NUMBER); + } + break; + } +#endif + default: + llvm_unreachable("unknown clone_info.event"); + } + + return true; +} + +bool NativeProcessAIX::SupportHardwareSingleStepping() const { + return false; +} + +Status NativeProcessAIX::Resume(const ResumeActionList &resume_actions) { + Log *log = GetLog(POSIXLog::Process); + LLDB_LOG(log, "pid {0}", GetID()); + + bool software_single_step = !SupportHardwareSingleStepping(); + + if (software_single_step) { + for (const auto &thread : m_threads) { + assert(thread && "thread list should not contain NULL threads"); + + const ResumeAction *const action = + resume_actions.GetActionForThread(thread->GetID(), true); + if (action == nullptr) + continue; + + if (action->state == eStateStepping) { + Status error = SetupSoftwareSingleStepping( + static_cast(*thread)); + if (error.Fail()) + return error; + } + } + } + + for (const auto &thread : m_threads) { + assert(thread && "thread list should not contain NULL threads"); + + const ResumeAction *const action = + resume_actions.GetActionForThread(thread->GetID(), true); + + if (action == nullptr) { + LLDB_LOG(log, "no action specified for pid {0} tid {1}", GetID(), + thread->GetID()); + continue; + } + + LLDB_LOG(log, "processing resume action state {0} for pid {1} tid {2}", + action->state, GetID(), thread->GetID()); + + switch (action->state) { + case eStateRunning: + case eStateStepping: { + // Run the thread, possibly feeding it the signal. + const int signo = action->signal; + Status error = ResumeThread(static_cast(*thread), + action->state, signo); + if (error.Fail()) + return Status("NativeProcessAIX::%s: failed to resume thread " + "for pid %" PRIu64 ", tid %" PRIu64 ", error = %s", + __FUNCTION__, GetID(), thread->GetID(), + error.AsCString()); + + break; + } + + case eStateSuspended: + case eStateStopped: + break; + + default: + return Status("NativeProcessAIX::%s (): unexpected state %s specified " + "for pid %" PRIu64 ", tid %" PRIu64, + __FUNCTION__, StateAsCString(action->state), GetID(), + thread->GetID()); + } + } + + return Status(); +} + +Status NativeProcessAIX::Halt() { + Status error; + + if (kill(GetID(), SIGSTOP) != 0) + error.SetErrorToErrno(); + + return error; +} + +Status NativeProcessAIX::Detach() { + Status error; + + // Tell ptrace to detach from the process. + if (GetID() == LLDB_INVALID_PROCESS_ID) + return error; + + // Cancel out any SIGSTOPs we may have sent while stopping the process. + // Otherwise, the process may stop as soon as we detach from it. + kill(GetID(), SIGCONT); + + for (const auto &thread : m_threads) { + Status e = Detach(thread->GetID()); + if (e.Fail()) + error = + e; // Save the error, but still attempt to detach from other threads. + } + + return error; +} + +Status NativeProcessAIX::Signal(int signo) { + Status error; + + Log *log = GetLog(POSIXLog::Process); + LLDB_LOG(log, "sending signal {0} ({1}) to pid {1}", signo, + Host::GetSignalAsCString(signo), GetID()); + + if (kill(GetID(), signo)) + error.SetErrorToErrno(); + + return error; +} + +Status NativeProcessAIX::Interrupt() { + // Pick a running thread (or if none, a not-dead stopped thread) as the + // chosen thread that will be the stop-reason thread. + Log *log = GetLog(POSIXLog::Process); + + NativeThreadProtocol *running_thread = nullptr; + NativeThreadProtocol *stopped_thread = nullptr; + + LLDB_LOG(log, "selecting running thread for interrupt target"); + for (const auto &thread : m_threads) { + // If we have a running or stepping thread, we'll call that the target of + // the interrupt. + const auto thread_state = thread->GetState(); + if (thread_state == eStateRunning || thread_state == eStateStepping) { + running_thread = thread.get(); + break; + } else if (!stopped_thread && StateIsStoppedState(thread_state, true)) { + // Remember the first non-dead stopped thread. We'll use that as a + // backup if there are no running threads. + stopped_thread = thread.get(); + } + } + + if (!running_thread && !stopped_thread) { + Status error("found no running/stepping or live stopped threads as target " + "for interrupt"); + LLDB_LOG(log, "skipping due to error: {0}", error); + + return error; + } + + NativeThreadProtocol *deferred_signal_thread = + running_thread ? running_thread : stopped_thread; + + LLDB_LOG(log, "pid {0} {1} tid {2} chosen for interrupt target", GetID(), + running_thread ? "running" : "stopped", + deferred_signal_thread->GetID()); + + StopRunningThreads(deferred_signal_thread->GetID()); + + return Status(); +} + +Status NativeProcessAIX::Kill() { + Log *log = GetLog(POSIXLog::Process); + LLDB_LOG(log, "pid {0}", GetID()); + + Status error; + + switch (m_state) { + case StateType::eStateInvalid: + case StateType::eStateExited: + case StateType::eStateCrashed: + case StateType::eStateDetached: + case StateType::eStateUnloaded: + // Nothing to do - the process is already dead. + LLDB_LOG(log, "ignored for PID {0} due to current state: {1}", GetID(), + m_state); + return error; + + case StateType::eStateConnected: + case StateType::eStateAttaching: + case StateType::eStateLaunching: + case StateType::eStateStopped: + case StateType::eStateRunning: + case StateType::eStateStepping: + case StateType::eStateSuspended: + // We can try to kill a process in these states. + break; + } + + if (kill(GetID(), SIGKILL) != 0) { + error.SetErrorToErrno(); + return error; + } + + return error; +} + +Status NativeProcessAIX::GetMemoryRegionInfo(lldb::addr_t load_addr, + MemoryRegionInfo &range_info) { + // FIXME review that the final memory region returned extends to the end of + // the virtual address space, + // with no perms if it is not mapped. + + // Use an approach that reads memory regions from /proc/{pid}/maps. Assume + // proc maps entries are in ascending order. + // FIXME assert if we find differently. + + if (m_supports_mem_region == LazyBool::eLazyBoolNo) { + // We're done. + return Status("unsupported"); + } + + Status error = PopulateMemoryRegionCache(); + if (error.Fail()) { + return error; + } + + lldb::addr_t prev_base_address = 0; + + // FIXME start by finding the last region that is <= target address using + // binary search. Data is sorted. + // There can be a ton of regions on pthreads apps with lots of threads. + for (auto it = m_mem_region_cache.begin(); it != m_mem_region_cache.end(); + ++it) { + MemoryRegionInfo &proc_entry_info = it->first; + + // Sanity check assumption that /proc/{pid}/maps entries are ascending. + assert((proc_entry_info.GetRange().GetRangeBase() >= prev_base_address) && + "descending /proc/pid/maps entries detected, unexpected"); + prev_base_address = proc_entry_info.GetRange().GetRangeBase(); + UNUSED_IF_ASSERT_DISABLED(prev_base_address); + + // If the target address comes before this entry, indicate distance to next + // region. + if (load_addr < proc_entry_info.GetRange().GetRangeBase()) { + range_info.GetRange().SetRangeBase(load_addr); + range_info.GetRange().SetByteSize( + proc_entry_info.GetRange().GetRangeBase() - load_addr); + range_info.SetReadable(MemoryRegionInfo::OptionalBool::eNo); + range_info.SetWritable(MemoryRegionInfo::OptionalBool::eNo); + range_info.SetExecutable(MemoryRegionInfo::OptionalBool::eNo); + range_info.SetMapped(MemoryRegionInfo::OptionalBool::eNo); + + return error; + } else if (proc_entry_info.GetRange().Contains(load_addr)) { + // The target address is within the memory region we're processing here. + range_info = proc_entry_info; + return error; + } + + // The target memory address comes somewhere after the region we just + // parsed. + } + + // If we made it here, we didn't find an entry that contained the given + // address. Return the load_addr as start and the amount of bytes betwwen + // load address and the end of the memory as size. + range_info.GetRange().SetRangeBase(load_addr); + range_info.GetRange().SetRangeEnd(LLDB_INVALID_ADDRESS); + range_info.SetReadable(MemoryRegionInfo::OptionalBool::eNo); + range_info.SetWritable(MemoryRegionInfo::OptionalBool::eNo); + range_info.SetExecutable(MemoryRegionInfo::OptionalBool::eNo); + range_info.SetMapped(MemoryRegionInfo::OptionalBool::eNo); + return error; +} + +Status NativeProcessAIX::PopulateMemoryRegionCache() { + Log *log = GetLog(POSIXLog::Process); + + // If our cache is empty, pull the latest. There should always be at least + // one memory region if memory region handling is supported. + if (!m_mem_region_cache.empty()) { + LLDB_LOG(log, "reusing {0} cached memory region entries", + m_mem_region_cache.size()); + return Status(); + } + + Status Result; +#if 0 + AIXMapCallback callback = [&](llvm::Expected Info) { + if (Info) { + FileSpec file_spec(Info->GetName().GetCString()); + FileSystem::Instance().Resolve(file_spec); + m_mem_region_cache.emplace_back(*Info, file_spec); + return true; + } + + Result = Info.takeError(); + m_supports_mem_region = LazyBool::eLazyBoolNo; + LLDB_LOG(log, "failed to parse proc maps: {0}", Result); + return false; + }; + + // AIX kernel since 2.6.14 has /proc/{pid}/smaps + // if CONFIG_PROC_PAGE_MONITOR is enabled + auto BufferOrError = getProcFile(GetID(), GetCurrentThreadID(), "smaps"); + if (BufferOrError) + ParseAIXSMapRegions(BufferOrError.get()->getBuffer(), callback); + else { + BufferOrError = getProcFile(GetID(), GetCurrentThreadID(), "maps"); + if (!BufferOrError) { + m_supports_mem_region = LazyBool::eLazyBoolNo; + return BufferOrError.getError(); + } + + ParseAIXMapRegions(BufferOrError.get()->getBuffer(), callback); + } + + if (Result.Fail()) + return Result; + + if (m_mem_region_cache.empty()) { + // No entries after attempting to read them. This shouldn't happen if + // /proc/{pid}/maps is supported. Assume we don't support map entries via + // procfs. + m_supports_mem_region = LazyBool::eLazyBoolNo; + LLDB_LOG(log, + "failed to find any procfs maps entries, assuming no support " + "for memory region metadata retrieval"); + return Status("not supported"); + } + + LLDB_LOG(log, "read {0} memory region entries from /proc/{1}/maps", + m_mem_region_cache.size(), GetID()); + + // We support memory retrieval, remember that. + m_supports_mem_region = LazyBool::eLazyBoolYes; +#endif + return Status(); +} + +void NativeProcessAIX::DoStopIDBumped(uint32_t newBumpId) { + Log *log = GetLog(POSIXLog::Process); + LLDB_LOG(log, "newBumpId={0}", newBumpId); + LLDB_LOG(log, "clearing {0} entries from memory region cache", + m_mem_region_cache.size()); + m_mem_region_cache.clear(); +} + +llvm::Expected +NativeProcessAIX::Syscall(llvm::ArrayRef args) { + PopulateMemoryRegionCache(); + auto region_it = llvm::find_if(m_mem_region_cache, [](const auto &pair) { + return pair.first.GetExecutable() == MemoryRegionInfo::eYes && + pair.first.GetShared() != MemoryRegionInfo::eYes; + }); + if (region_it == m_mem_region_cache.end()) + return llvm::createStringError(llvm::inconvertibleErrorCode(), + "No executable memory region found!"); + + addr_t exe_addr = region_it->first.GetRange().GetRangeBase(); + + NativeThreadAIX &thread = *GetCurrentThread(); + assert(thread.GetState() == eStateStopped); + NativeRegisterContextAIX ®_ctx = thread.GetRegisterContext(); + + NativeRegisterContextAIX::SyscallData syscall_data = + *reg_ctx.GetSyscallData(); + + WritableDataBufferSP registers_sp; + if (llvm::Error Err = reg_ctx.ReadAllRegisterValues(registers_sp).ToError()) + return std::move(Err); + auto restore_regs = llvm::make_scope_exit( + [&] { reg_ctx.WriteAllRegisterValues(registers_sp); }); + + llvm::SmallVector memory(syscall_data.Insn.size()); + size_t bytes_read; + if (llvm::Error Err = + ReadMemory(exe_addr, memory.data(), memory.size(), bytes_read) + .ToError()) { + return std::move(Err); + } + + auto restore_mem = llvm::make_scope_exit( + [&] { WriteMemory(exe_addr, memory.data(), memory.size(), bytes_read); }); + + if (llvm::Error Err = reg_ctx.SetPC(exe_addr).ToError()) + return std::move(Err); + + for (const auto &zip : llvm::zip_first(args, syscall_data.Args)) { + if (llvm::Error Err = + reg_ctx + .WriteRegisterFromUnsigned(std::get<1>(zip), std::get<0>(zip)) + .ToError()) { + return std::move(Err); + } + } + if (llvm::Error Err = WriteMemory(exe_addr, syscall_data.Insn.data(), + syscall_data.Insn.size(), bytes_read) + .ToError()) + return std::move(Err); + + m_mem_region_cache.clear(); + + // With software single stepping the syscall insn buffer must also include a + // trap instruction to stop the process. + int req = SupportHardwareSingleStepping() ? PTRACE_SINGLESTEP : PTRACE_CONT; + if (llvm::Error Err = + PtraceWrapper(req, thread.GetID(), nullptr, nullptr).ToError()) + return std::move(Err); + + //FIXME + int status; + ::pid_t wait_pid = llvm::sys::RetryAfterSignal(-1, ::waitpid, thread.GetID(), + &status, P_ALL/*__WALL*/); + if (wait_pid == -1) { + return llvm::errorCodeToError( + std::error_code(errno, std::generic_category())); + } + assert((unsigned)wait_pid == thread.GetID()); + + uint64_t result = reg_ctx.ReadRegisterAsUnsigned(syscall_data.Result, -ESRCH); + + // Values larger than this are actually negative errno numbers. + uint64_t errno_threshold = + (uint64_t(-1) >> (64 - 8 * m_arch.GetAddressByteSize())) - 0x1000; + if (result > errno_threshold) { + return llvm::errorCodeToError( + std::error_code(-result & 0xfff, std::generic_category())); + } + + return result; +} + +llvm::Expected +NativeProcessAIX::AllocateMemory(size_t size, uint32_t permissions) { + + std::optional mmap_data = + GetCurrentThread()->GetRegisterContext().GetMmapData(); + if (!mmap_data) + return llvm::make_error(); + + unsigned prot = PROT_NONE; + assert((permissions & (ePermissionsReadable | ePermissionsWritable | + ePermissionsExecutable)) == permissions && + "Unknown permission!"); + if (permissions & ePermissionsReadable) + prot |= PROT_READ; + if (permissions & ePermissionsWritable) + prot |= PROT_WRITE; + if (permissions & ePermissionsExecutable) + prot |= PROT_EXEC; + + llvm::Expected Result = + Syscall({mmap_data->SysMmap, 0, size, prot, MAP_ANONYMOUS | MAP_PRIVATE, + uint64_t(-1), 0}); + if (Result) + m_allocated_memory.try_emplace(*Result, size); + return Result; +} + +llvm::Error NativeProcessAIX::DeallocateMemory(lldb::addr_t addr) { + std::optional mmap_data = + GetCurrentThread()->GetRegisterContext().GetMmapData(); + if (!mmap_data) + return llvm::make_error(); + + auto it = m_allocated_memory.find(addr); + if (it == m_allocated_memory.end()) + return llvm::createStringError(llvm::errc::invalid_argument, + "Memory not allocated by the debugger."); + + llvm::Expected Result = + Syscall({mmap_data->SysMunmap, addr, it->second}); + if (!Result) + return Result.takeError(); + + m_allocated_memory.erase(it); + return llvm::Error::success(); +} + +Status NativeProcessAIX::ReadMemoryTags(int32_t type, lldb::addr_t addr, + size_t len, + std::vector &tags) { + llvm::Expected details = + GetCurrentThread()->GetRegisterContext().GetMemoryTaggingDetails(type); + if (!details) + return Status(details.takeError()); + + // Ignore 0 length read + if (!len) + return Status(); + + // lldb will align the range it requests but it is not required to by + // the protocol so we'll do it again just in case. + // Remove tag bits too. Ptrace calls may work regardless but that + // is not a guarantee. + MemoryTagManager::TagRange range(details->manager->RemoveTagBits(addr), len); + range = details->manager->ExpandToGranule(range); + + // Allocate enough space for all tags to be read + size_t num_tags = range.GetByteSize() / details->manager->GetGranuleSize(); + tags.resize(num_tags * details->manager->GetTagSizeInBytes()); + + struct iovec tags_iovec; + uint8_t *dest = tags.data(); + lldb::addr_t read_addr = range.GetRangeBase(); + + // This call can return partial data so loop until we error or + // get all tags back. + while (num_tags) { + tags_iovec.iov_base = dest; + tags_iovec.iov_len = num_tags; + + Status error = NativeProcessAIX::PtraceWrapper( + details->ptrace_read_req, GetCurrentThreadID(), + reinterpret_cast(read_addr), static_cast(&tags_iovec), + 0, nullptr); + + if (error.Fail()) { + // Discard partial reads + tags.resize(0); + return error; + } + + size_t tags_read = tags_iovec.iov_len; + assert(tags_read && (tags_read <= num_tags)); + + dest += tags_read * details->manager->GetTagSizeInBytes(); + read_addr += details->manager->GetGranuleSize() * tags_read; + num_tags -= tags_read; + } + + return Status(); +} + +Status NativeProcessAIX::WriteMemoryTags(int32_t type, lldb::addr_t addr, + size_t len, + const std::vector &tags) { + llvm::Expected details = + GetCurrentThread()->GetRegisterContext().GetMemoryTaggingDetails(type); + if (!details) + return Status(details.takeError()); + + // Ignore 0 length write + if (!len) + return Status(); + + // lldb will align the range it requests but it is not required to by + // the protocol so we'll do it again just in case. + // Remove tag bits too. Ptrace calls may work regardless but that + // is not a guarantee. + MemoryTagManager::TagRange range(details->manager->RemoveTagBits(addr), len); + range = details->manager->ExpandToGranule(range); + + // Not checking number of tags here, we may repeat them below + llvm::Expected> unpacked_tags_or_err = + details->manager->UnpackTagsData(tags); + if (!unpacked_tags_or_err) + return Status(unpacked_tags_or_err.takeError()); + + llvm::Expected> repeated_tags_or_err = + details->manager->RepeatTagsForRange(*unpacked_tags_or_err, range); + if (!repeated_tags_or_err) + return Status(repeated_tags_or_err.takeError()); + + // Repack them for ptrace to use + llvm::Expected> final_tag_data = + details->manager->PackTags(*repeated_tags_or_err); + if (!final_tag_data) + return Status(final_tag_data.takeError()); + + struct iovec tags_vec; + uint8_t *src = final_tag_data->data(); + lldb::addr_t write_addr = range.GetRangeBase(); + // unpacked tags size because the number of bytes per tag might not be 1 + size_t num_tags = repeated_tags_or_err->size(); + + // This call can partially write tags, so we loop until we + // error or all tags have been written. + while (num_tags > 0) { + tags_vec.iov_base = src; + tags_vec.iov_len = num_tags; + + Status error = NativeProcessAIX::PtraceWrapper( + details->ptrace_write_req, GetCurrentThreadID(), + reinterpret_cast(write_addr), static_cast(&tags_vec), 0, + nullptr); + + if (error.Fail()) { + // Don't attempt to restore the original values in the case of a partial + // write + return error; + } + + size_t tags_written = tags_vec.iov_len; + assert(tags_written && (tags_written <= num_tags)); + + src += tags_written * details->manager->GetTagSizeInBytes(); + write_addr += details->manager->GetGranuleSize() * tags_written; + num_tags -= tags_written; + } + + return Status(); +} + +size_t NativeProcessAIX::UpdateThreads() { + // The NativeProcessAIX monitoring threads are always up to date with + // respect to thread state and they keep the thread list populated properly. + // All this method needs to do is return the thread count. + return m_threads.size(); +} + +Status NativeProcessAIX::SetBreakpoint(lldb::addr_t addr, uint32_t size, + bool hardware) { + if (hardware) + return SetHardwareBreakpoint(addr, size); + else + return SetSoftwareBreakpoint(addr, size); +} + +Status NativeProcessAIX::RemoveBreakpoint(lldb::addr_t addr, bool hardware) { + if (hardware) + return RemoveHardwareBreakpoint(addr); + else + return NativeProcessProtocol::RemoveBreakpoint(addr); +} + +llvm::Expected> +NativeProcessAIX::GetSoftwareBreakpointTrapOpcode(size_t size_hint) { + // The ARM reference recommends the use of 0xe7fddefe and 0xdefe but the + // linux kernel does otherwise. + static const uint8_t g_arm_opcode[] = {0xf0, 0x01, 0xf0, 0xe7}; + static const uint8_t g_thumb_opcode[] = {0x01, 0xde}; + + switch (GetArchitecture().GetMachine()) { + case llvm::Triple::arm: + switch (size_hint) { + case 2: + return llvm::ArrayRef(g_thumb_opcode); + case 4: + return llvm::ArrayRef(g_arm_opcode); + default: + return llvm::createStringError(llvm::inconvertibleErrorCode(), + "Unrecognised trap opcode size hint!"); + } + default: + return NativeProcessProtocol::GetSoftwareBreakpointTrapOpcode(size_hint); + } +} + +Status NativeProcessAIX::ReadMemory(lldb::addr_t addr, void *buf, size_t size, + size_t &bytes_read) { + unsigned char *dst = static_cast(buf); + size_t remainder; + long data; + + Log *log = GetLog(POSIXLog::Memory); + LLDB_LOG(log, "addr = {0}, buf = {1}, size = {2}", addr, buf, size); + + for (bytes_read = 0; bytes_read < size; bytes_read += remainder) { + Status error = NativeProcessAIX::PtraceWrapper( + PT_READ_BLOCK, GetCurrentThreadID(), (void *)addr, nullptr, sizeof(data), &data); + if (error.Fail()) + return error; + + remainder = size - bytes_read; + remainder = remainder > k_ptrace_word_size ? k_ptrace_word_size : remainder; + + // Copy the data into our buffer + memcpy(dst, &data, remainder); + + LLDB_LOG(log, "[{0:x}]:{1:x}", addr, data); + addr += k_ptrace_word_size; + dst += k_ptrace_word_size; + } + return Status(); +} + +Status NativeProcessAIX::WriteMemory(lldb::addr_t addr, const void *buf, + size_t size, size_t &bytes_written) { + const unsigned char *src = static_cast(buf); + size_t remainder; + Status error; + + Log *log = GetLog(POSIXLog::Memory); + LLDB_LOG(log, "addr = {0}, buf = {1}, size = {2}", addr, buf, size); + + error = NativeProcessAIX::PtraceWrapper( + PT_WRITE_BLOCK, GetCurrentThreadID(), (void *)addr, nullptr, (int)size, (long *)buf); + if (error.Fail()) + return error; + + bytes_written = size; + return error; +} + +int8_t NativeProcessAIX::GetSignalInfo(WaitStatus wstatus) const { + return wstatus.status; +} + +Status NativeProcessAIX::GetEventMessage(lldb::tid_t tid, + unsigned long *message) { + //FIXME + return PtraceWrapper(PT_CLEAR/*PTRACE_GETEVENTMSG*/, tid, nullptr, message); +} + +Status NativeProcessAIX::Detach(lldb::tid_t tid) { + if (tid == LLDB_INVALID_THREAD_ID) + return Status(); + + return PtraceWrapper(PT_DETACH, tid); +} + +bool NativeProcessAIX::HasThreadNoLock(lldb::tid_t thread_id) { + for (const auto &thread : m_threads) { + assert(thread && "thread list should not contain NULL threads"); + if (thread->GetID() == thread_id) { + // We have this thread. + return true; + } + } + + // We don't have this thread. + return false; +} + +void NativeProcessAIX::StopTrackingThread(NativeThreadAIX &thread) { + Log *const log = GetLog(POSIXLog::Thread); + lldb::tid_t thread_id = thread.GetID(); + LLDB_LOG(log, "tid: {0}", thread_id); + + auto it = llvm::find_if(m_threads, [&](const auto &thread_up) { + return thread_up.get() == &thread; + }); + assert(it != m_threads.end()); + m_threads.erase(it); + + NotifyTracersOfThreadDestroyed(thread_id); + SignalIfAllThreadsStopped(); +} + +void NativeProcessAIX::NotifyTracersProcessDidStop() { +} + +void NativeProcessAIX::NotifyTracersProcessWillResume() { +} + +Status NativeProcessAIX::NotifyTracersOfNewThread(lldb::tid_t tid) { + Log *log = GetLog(POSIXLog::Thread); + Status error; + return error; +} + +Status NativeProcessAIX::NotifyTracersOfThreadDestroyed(lldb::tid_t tid) { + Log *log = GetLog(POSIXLog::Thread); + Status error; + return error; +} + +NativeThreadAIX &NativeProcessAIX::AddThread(lldb::tid_t thread_id, + bool resume) { + Log *log = GetLog(POSIXLog::Thread); + LLDB_LOG(log, "pid {0} adding thread with tid {1}", GetID(), thread_id); + + assert(!HasThreadNoLock(thread_id) && + "attempted to add a thread by id that already exists"); + + // If this is the first thread, save it as the current thread + if (m_threads.empty()) + SetCurrentThreadID(thread_id); + + m_threads.push_back(std::make_unique(*this, thread_id)); + NativeThreadAIX &thread = + static_cast(*m_threads.back()); + + Status tracing_error = NotifyTracersOfNewThread(thread.GetID()); + if (tracing_error.Fail()) { + thread.SetStoppedByProcessorTrace(tracing_error.AsCString()); + StopRunningThreads(thread.GetID()); + } else if (resume) + ResumeThread(thread, eStateRunning, LLDB_INVALID_SIGNAL_NUMBER); + else + thread.SetStoppedBySignal(SIGSTOP); + + return thread; +} + +Status NativeProcessAIX::GetLoadedModuleFileSpec(const char *module_path, + FileSpec &file_spec) { + Status error = PopulateMemoryRegionCache(); + if (error.Fail()) + return error; + + FileSpec module_file_spec(module_path); + FileSystem::Instance().Resolve(module_file_spec); + + file_spec.Clear(); + for (const auto &it : m_mem_region_cache) { + if (it.second.GetFilename() == module_file_spec.GetFilename()) { + file_spec = it.second; + return Status(); + } + } + return Status("Module file (%s) not found in /proc/%" PRIu64 "/maps file!", + module_file_spec.GetFilename().AsCString(), GetID()); +} + +Status NativeProcessAIX::GetFileLoadAddress(const llvm::StringRef &file_name, + lldb::addr_t &load_addr) { + load_addr = LLDB_INVALID_ADDRESS; + + NativeThreadAIX &thread = *GetCurrentThread(); + NativeRegisterContextAIX ®_ctx = thread.GetRegisterContext(); + + // FIXME: buffer size + struct ld_xinfo info[64]; + if (ptrace64(PT_LDXINFO, reg_ctx.GetThread().GetID(), (long long)&(info[0]), sizeof(info), nullptr) == 0) { + load_addr = (unsigned long)info[0].ldinfo_textorg; + return Status(); + } + return Status("No load address found for specified file."); +} + +NativeThreadAIX *NativeProcessAIX::GetThreadByID(lldb::tid_t tid) { + return static_cast( + NativeProcessProtocol::GetThreadByID(tid)); +} + +NativeThreadAIX *NativeProcessAIX::GetCurrentThread() { + return static_cast( + NativeProcessProtocol::GetCurrentThread()); +} + +Status NativeProcessAIX::ResumeThread(NativeThreadAIX &thread, + lldb::StateType state, int signo) { + Log *const log = GetLog(POSIXLog::Thread); + LLDB_LOG(log, "tid: {0}", thread.GetID()); + + // Before we do the resume below, first check if we have a pending stop + // notification that is currently waiting for all threads to stop. This is + // potentially a buggy situation since we're ostensibly waiting for threads + // to stop before we send out the pending notification, and here we are + // resuming one before we send out the pending stop notification. + if (m_pending_notification_tid != LLDB_INVALID_THREAD_ID) { + LLDB_LOG(log, + "about to resume tid {0} per explicit request but we have a " + "pending stop notification (tid {1}) that is actively " + "waiting for this thread to stop. Valid sequence of events?", + thread.GetID(), m_pending_notification_tid); + } + + // Request a resume. We expect this to be synchronous and the system to + // reflect it is running after this completes. + switch (state) { + case eStateRunning: { + const auto resume_result = thread.Resume(signo); + if (resume_result.Success()) + SetState(eStateRunning, true); + return resume_result; + } + case eStateStepping: { + const auto step_result = thread.SingleStep(signo); + if (step_result.Success()) + SetState(eStateRunning, true); + return step_result; + } + default: + LLDB_LOG(log, "Unhandled state {0}.", state); + llvm_unreachable("Unhandled state for resume"); + } +} + +//===----------------------------------------------------------------------===// + +void NativeProcessAIX::StopRunningThreads(const lldb::tid_t triggering_tid) { + Log *const log = GetLog(POSIXLog::Thread); + LLDB_LOG(log, "about to process event: (triggering_tid: {0})", + triggering_tid); + + m_pending_notification_tid = triggering_tid; + + // Request a stop for all the thread stops that need to be stopped and are + // not already known to be stopped. + for (const auto &thread : m_threads) { + if (StateIsRunningState(thread->GetState())) + static_cast(thread.get())->RequestStop(); + } + + SignalIfAllThreadsStopped(); + LLDB_LOG(log, "event processing done"); +} + +void NativeProcessAIX::SignalIfAllThreadsStopped() { + if (m_pending_notification_tid == LLDB_INVALID_THREAD_ID) + return; // No pending notification. Nothing to do. + + for (const auto &thread_sp : m_threads) { + if (StateIsRunningState(thread_sp->GetState())) + return; // Some threads are still running. Don't signal yet. + } + + // We have a pending notification and all threads have stopped. + Log *log = GetLog(LLDBLog::Process | LLDBLog::Breakpoints); + + // Clear any temporary breakpoints we used to implement software single + // stepping. + for (const auto &thread_info : m_threads_stepping_with_breakpoint) { + Status error = RemoveBreakpoint(thread_info.second); + if (error.Fail()) + LLDB_LOG(log, "pid = {0} remove stepping breakpoint: {1}", + thread_info.first, error); + } + m_threads_stepping_with_breakpoint.clear(); + + // Notify the delegate about the stop + SetCurrentThreadID(m_pending_notification_tid); + SetState(StateType::eStateStopped, true); + m_pending_notification_tid = LLDB_INVALID_THREAD_ID; +} + +void NativeProcessAIX::ThreadWasCreated(NativeThreadAIX &thread) { + Log *const log = GetLog(POSIXLog::Thread); + LLDB_LOG(log, "tid: {0}", thread.GetID()); + + if (m_pending_notification_tid != LLDB_INVALID_THREAD_ID && + StateIsRunningState(thread.GetState())) { + // We will need to wait for this new thread to stop as well before firing + // the notification. + thread.RequestStop(); + } +} + +#define DECLARE_REGISTER_INFOS_PPC64LE_STRUCT +#include "Plugins/Process/Utility/RegisterInfos_ppc64le.h" +#undef DECLARE_REGISTER_INFOS_PPC64LE_STRUCT + +static void GetRegister(lldb::pid_t pid, long long addr, void *buf) { + uint64_t val = 0; + ptrace64(PT_READ_GPR, pid, addr, 0, (int *)&val); + *(uint64_t *)buf = llvm::byteswap(val); +} + +static void SetRegister(lldb::pid_t pid, long long addr, void *buf) { + uint64_t val = llvm::byteswap(*(uint64_t *)buf); + ptrace64(PT_WRITE_GPR, pid, addr, 0, (int *)&val); +} + +static void GetFPRegister(lldb::pid_t pid, long long addr, void *buf) { + uint64_t val = 0; + ptrace64(PT_READ_FPR, pid, addr, 0, (int *)&val); + *(uint64_t *)buf = llvm::byteswap(val); +} + +static void GetVMRegister(lldb::tid_t tid, long long addr, void *buf) { + uint64_t val = 0; + ptrace64(PTT_READ_VEC, tid, addr, 0, (int *)&val); + //*(uint64_t *)buf = llvm::byteswap(val); +} + +static void GetVSRegister(lldb::tid_t tid, long long addr, void *buf) { + uint64_t val = 0; + ptrace64(PTT_READ_VSX, tid, addr, 0, (int *)&val); + //*(uint64_t *)buf = llvm::byteswap(val); +} + +// Wrapper for ptrace to catch errors and log calls. Note that ptrace sets +// errno on error because -1 can be a valid result (i.e. for PTRACE_PEEK*) +Status NativeProcessAIX::PtraceWrapper(int req, lldb::pid_t pid, void *addr, + void *data, size_t data_size, + long *result) { + Status error; + long int ret; + + Log *log = GetLog(POSIXLog::Ptrace); + + PtraceDisplayBytes(req, data, data_size); + + errno = 0; + + // for PTT_* + const char procdir[] = "/proc/"; + const char lwpdir[] = "/lwp/"; + std::string process_task_dir = procdir + std::to_string(pid) + lwpdir; + DIR *dirproc = opendir(process_task_dir.c_str()); + + lldb::tid_t tid = 0; + if (dirproc) { + struct dirent *direntry = nullptr; + while ((direntry = readdir(dirproc)) != nullptr) { + if (strcmp(direntry->d_name, ".") == 0 || strcmp(direntry->d_name, "..") == 0) { + continue; + } + tid = atoi(direntry->d_name); + break; + } + closedir(dirproc); + } + + if (req == PTRACE_GETREGS) { + GetRegister(pid, GPR0, &(((GPR *)data)->r0)); + GetRegister(pid, GPR1, &(((GPR *)data)->r1)); + GetRegister(pid, GPR2, &(((GPR *)data)->r2)); + GetRegister(pid, GPR3, &(((GPR *)data)->r3)); + GetRegister(pid, GPR4, &(((GPR *)data)->r4)); + GetRegister(pid, GPR5, &(((GPR *)data)->r5)); + GetRegister(pid, GPR6, &(((GPR *)data)->r6)); + GetRegister(pid, GPR7, &(((GPR *)data)->r7)); + GetRegister(pid, GPR8, &(((GPR *)data)->r8)); + GetRegister(pid, GPR9, &(((GPR *)data)->r9)); + GetRegister(pid, GPR10, &(((GPR *)data)->r10)); + GetRegister(pid, GPR11, &(((GPR *)data)->r11)); + GetRegister(pid, GPR12, &(((GPR *)data)->r12)); + GetRegister(pid, GPR13, &(((GPR *)data)->r13)); + GetRegister(pid, GPR14, &(((GPR *)data)->r14)); + GetRegister(pid, GPR15, &(((GPR *)data)->r15)); + GetRegister(pid, GPR16, &(((GPR *)data)->r16)); + GetRegister(pid, GPR17, &(((GPR *)data)->r17)); + GetRegister(pid, GPR18, &(((GPR *)data)->r18)); + GetRegister(pid, GPR19, &(((GPR *)data)->r19)); + GetRegister(pid, GPR20, &(((GPR *)data)->r20)); + GetRegister(pid, GPR21, &(((GPR *)data)->r21)); + GetRegister(pid, GPR22, &(((GPR *)data)->r22)); + GetRegister(pid, GPR23, &(((GPR *)data)->r23)); + GetRegister(pid, GPR24, &(((GPR *)data)->r24)); + GetRegister(pid, GPR25, &(((GPR *)data)->r25)); + GetRegister(pid, GPR26, &(((GPR *)data)->r26)); + GetRegister(pid, GPR27, &(((GPR *)data)->r27)); + GetRegister(pid, GPR28, &(((GPR *)data)->r28)); + GetRegister(pid, GPR29, &(((GPR *)data)->r29)); + GetRegister(pid, GPR30, &(((GPR *)data)->r30)); + GetRegister(pid, GPR31, &(((GPR *)data)->r31)); + GetRegister(pid, IAR, &(((GPR *)data)->pc)); + GetRegister(pid, MSR, &(((GPR *)data)->msr)); + //FIXME: origr3/softe/trap on AIX? + GetRegister(pid, CTR, &(((GPR *)data)->ctr)); + GetRegister(pid, LR, &(((GPR *)data)->lr)); + GetRegister(pid, XER, &(((GPR *)data)->xer)); + GetRegister(pid, CR, &(((GPR *)data)->cr)); + } else if (req == PTRACE_SETREGS) { + SetRegister(pid, GPR0, &(((GPR *)data)->r0)); + SetRegister(pid, GPR1, &(((GPR *)data)->r1)); + SetRegister(pid, GPR2, &(((GPR *)data)->r2)); + SetRegister(pid, GPR3, &(((GPR *)data)->r3)); + SetRegister(pid, GPR4, &(((GPR *)data)->r4)); + SetRegister(pid, GPR5, &(((GPR *)data)->r5)); + SetRegister(pid, GPR6, &(((GPR *)data)->r6)); + SetRegister(pid, GPR7, &(((GPR *)data)->r7)); + SetRegister(pid, GPR8, &(((GPR *)data)->r8)); + SetRegister(pid, GPR9, &(((GPR *)data)->r9)); + SetRegister(pid, GPR10, &(((GPR *)data)->r10)); + SetRegister(pid, GPR11, &(((GPR *)data)->r11)); + SetRegister(pid, GPR12, &(((GPR *)data)->r12)); + SetRegister(pid, GPR13, &(((GPR *)data)->r13)); + SetRegister(pid, GPR14, &(((GPR *)data)->r14)); + SetRegister(pid, GPR15, &(((GPR *)data)->r15)); + SetRegister(pid, GPR16, &(((GPR *)data)->r16)); + SetRegister(pid, GPR17, &(((GPR *)data)->r17)); + SetRegister(pid, GPR18, &(((GPR *)data)->r18)); + SetRegister(pid, GPR19, &(((GPR *)data)->r19)); + SetRegister(pid, GPR20, &(((GPR *)data)->r20)); + SetRegister(pid, GPR21, &(((GPR *)data)->r21)); + SetRegister(pid, GPR22, &(((GPR *)data)->r22)); + SetRegister(pid, GPR23, &(((GPR *)data)->r23)); + SetRegister(pid, GPR24, &(((GPR *)data)->r24)); + SetRegister(pid, GPR25, &(((GPR *)data)->r25)); + SetRegister(pid, GPR26, &(((GPR *)data)->r26)); + SetRegister(pid, GPR27, &(((GPR *)data)->r27)); + SetRegister(pid, GPR28, &(((GPR *)data)->r28)); + SetRegister(pid, GPR29, &(((GPR *)data)->r29)); + SetRegister(pid, GPR30, &(((GPR *)data)->r30)); + SetRegister(pid, GPR31, &(((GPR *)data)->r31)); + SetRegister(pid, IAR, &(((GPR *)data)->pc)); + SetRegister(pid, MSR, &(((GPR *)data)->msr)); + //FIXME: origr3/softe/trap on AIX? + SetRegister(pid, CTR, &(((GPR *)data)->ctr)); + SetRegister(pid, LR, &(((GPR *)data)->lr)); + SetRegister(pid, XER, &(((GPR *)data)->xer)); + SetRegister(pid, CR, &(((GPR *)data)->cr)); + } else if (req == PTRACE_GETFPREGS) { + GetFPRegister(pid, FPR0, &(((FPR *)data)->f0)); + GetFPRegister(pid, FPR1, &(((FPR *)data)->f1)); + GetFPRegister(pid, FPR2, &(((FPR *)data)->f2)); + GetFPRegister(pid, FPR3, &(((FPR *)data)->f3)); + GetFPRegister(pid, FPR4, &(((FPR *)data)->f4)); + GetFPRegister(pid, FPR5, &(((FPR *)data)->f5)); + GetFPRegister(pid, FPR6, &(((FPR *)data)->f6)); + GetFPRegister(pid, FPR7, &(((FPR *)data)->f7)); + GetFPRegister(pid, FPR8, &(((FPR *)data)->f8)); + GetFPRegister(pid, FPR9, &(((FPR *)data)->f9)); + GetFPRegister(pid, FPR10, &(((FPR *)data)->f10)); + GetFPRegister(pid, FPR11, &(((FPR *)data)->f11)); + GetFPRegister(pid, FPR12, &(((FPR *)data)->f12)); + GetFPRegister(pid, FPR13, &(((FPR *)data)->f13)); + GetFPRegister(pid, FPR14, &(((FPR *)data)->f14)); + GetFPRegister(pid, FPR15, &(((FPR *)data)->f15)); + GetFPRegister(pid, FPR16, &(((FPR *)data)->f16)); + GetFPRegister(pid, FPR17, &(((FPR *)data)->f17)); + GetFPRegister(pid, FPR18, &(((FPR *)data)->f18)); + GetFPRegister(pid, FPR19, &(((FPR *)data)->f19)); + GetFPRegister(pid, FPR20, &(((FPR *)data)->f20)); + GetFPRegister(pid, FPR21, &(((FPR *)data)->f21)); + GetFPRegister(pid, FPR22, &(((FPR *)data)->f22)); + GetFPRegister(pid, FPR23, &(((FPR *)data)->f23)); + GetFPRegister(pid, FPR24, &(((FPR *)data)->f24)); + GetFPRegister(pid, FPR25, &(((FPR *)data)->f25)); + GetFPRegister(pid, FPR26, &(((FPR *)data)->f26)); + GetFPRegister(pid, FPR27, &(((FPR *)data)->f27)); + GetFPRegister(pid, FPR28, &(((FPR *)data)->f28)); + GetFPRegister(pid, FPR29, &(((FPR *)data)->f29)); + GetFPRegister(pid, FPR30, &(((FPR *)data)->f30)); + GetFPRegister(pid, FPR31, &(((FPR *)data)->f31)); + GetFPRegister(pid, FPSCR, &(((FPR *)data)->fpscr)); + } else if (req == PTRACE_GETVRREGS && tid) { + GetVMRegister(tid, VR0, &(((VMX *)data)->vr0[0])); + GetVMRegister(tid, VR1, &(((VMX *)data)->vr1[0])); + GetVMRegister(tid, VR2, &(((VMX *)data)->vr2[0])); + GetVMRegister(tid, VR3, &(((VMX *)data)->vr3[0])); + GetVMRegister(tid, VR4, &(((VMX *)data)->vr4[0])); + GetVMRegister(tid, VR5, &(((VMX *)data)->vr5[0])); + GetVMRegister(tid, VR6, &(((VMX *)data)->vr6[0])); + GetVMRegister(tid, VR7, &(((VMX *)data)->vr7[0])); + GetVMRegister(tid, VR8, &(((VMX *)data)->vr8[0])); + GetVMRegister(tid, VR9, &(((VMX *)data)->vr9[0])); + GetVMRegister(tid, VR10, &(((VMX *)data)->vr10[0])); + GetVMRegister(tid, VR11, &(((VMX *)data)->vr11[0])); + GetVMRegister(tid, VR12, &(((VMX *)data)->vr12[0])); + GetVMRegister(tid, VR13, &(((VMX *)data)->vr13[0])); + GetVMRegister(tid, VR14, &(((VMX *)data)->vr14[0])); + GetVMRegister(tid, VR15, &(((VMX *)data)->vr15[0])); + GetVMRegister(tid, VR16, &(((VMX *)data)->vr16[0])); + GetVMRegister(tid, VR17, &(((VMX *)data)->vr17[0])); + GetVMRegister(tid, VR18, &(((VMX *)data)->vr18[0])); + GetVMRegister(tid, VR19, &(((VMX *)data)->vr19[0])); + GetVMRegister(tid, VR20, &(((VMX *)data)->vr20[0])); + GetVMRegister(tid, VR21, &(((VMX *)data)->vr21[0])); + GetVMRegister(tid, VR22, &(((VMX *)data)->vr22[0])); + GetVMRegister(tid, VR23, &(((VMX *)data)->vr23[0])); + GetVMRegister(tid, VR24, &(((VMX *)data)->vr24[0])); + GetVMRegister(tid, VR25, &(((VMX *)data)->vr25[0])); + GetVMRegister(tid, VR26, &(((VMX *)data)->vr26[0])); + GetVMRegister(tid, VR27, &(((VMX *)data)->vr27[0])); + GetVMRegister(tid, VR28, &(((VMX *)data)->vr28[0])); + GetVMRegister(tid, VR29, &(((VMX *)data)->vr29[0])); + GetVMRegister(tid, VR30, &(((VMX *)data)->vr30[0])); + GetVMRegister(tid, VR31, &(((VMX *)data)->vr31[0])); + GetVMRegister(tid, VSCR, &(((VMX *)data)->vscr[0])); + GetVMRegister(tid, VRSAVE, &(((VMX *)data)->vrsave)); + } else if (req == PTRACE_GETVSRREGS && tid) { + GetVSRegister(tid, VSR0, &(((VSX *)data)->vs0[0])); + GetVSRegister(tid, VSR1, &(((VSX *)data)->vs1[0])); + GetVSRegister(tid, VSR2, &(((VSX *)data)->vs2[0])); + GetVSRegister(tid, VSR3, &(((VSX *)data)->vs3[0])); + GetVSRegister(tid, VSR4, &(((VSX *)data)->vs4[0])); + GetVSRegister(tid, VSR5, &(((VSX *)data)->vs5[0])); + GetVSRegister(tid, VSR6, &(((VSX *)data)->vs6[0])); + GetVSRegister(tid, VSR7, &(((VSX *)data)->vs7[0])); + GetVSRegister(tid, VSR8, &(((VSX *)data)->vs8[0])); + GetVSRegister(tid, VSR9, &(((VSX *)data)->vs9[0])); + GetVSRegister(tid, VSR10, &(((VSX *)data)->vs10[0])); + GetVSRegister(tid, VSR11, &(((VSX *)data)->vs11[0])); + GetVSRegister(tid, VSR12, &(((VSX *)data)->vs12[0])); + GetVSRegister(tid, VSR13, &(((VSX *)data)->vs13[0])); + GetVSRegister(tid, VSR14, &(((VSX *)data)->vs14[0])); + GetVSRegister(tid, VSR15, &(((VSX *)data)->vs15[0])); + GetVSRegister(tid, VSR16, &(((VSX *)data)->vs16[0])); + GetVSRegister(tid, VSR17, &(((VSX *)data)->vs17[0])); + GetVSRegister(tid, VSR18, &(((VSX *)data)->vs18[0])); + GetVSRegister(tid, VSR19, &(((VSX *)data)->vs19[0])); + GetVSRegister(tid, VSR20, &(((VSX *)data)->vs20[0])); + GetVSRegister(tid, VSR21, &(((VSX *)data)->vs21[0])); + GetVSRegister(tid, VSR22, &(((VSX *)data)->vs22[0])); + GetVSRegister(tid, VSR23, &(((VSX *)data)->vs23[0])); + GetVSRegister(tid, VSR24, &(((VSX *)data)->vs24[0])); + GetVSRegister(tid, VSR25, &(((VSX *)data)->vs25[0])); + GetVSRegister(tid, VSR26, &(((VSX *)data)->vs26[0])); + GetVSRegister(tid, VSR27, &(((VSX *)data)->vs27[0])); + GetVSRegister(tid, VSR28, &(((VSX *)data)->vs28[0])); + GetVSRegister(tid, VSR29, &(((VSX *)data)->vs29[0])); + GetVSRegister(tid, VSR30, &(((VSX *)data)->vs30[0])); + GetVSRegister(tid, VSR31, &(((VSX *)data)->vs31[0])); + GetVSRegister(tid, VSR32, &(((VSX *)data)->vs32[0])); + GetVSRegister(tid, VSR33, &(((VSX *)data)->vs33[0])); + GetVSRegister(tid, VSR34, &(((VSX *)data)->vs34[0])); + GetVSRegister(tid, VSR35, &(((VSX *)data)->vs35[0])); + GetVSRegister(tid, VSR36, &(((VSX *)data)->vs36[0])); + GetVSRegister(tid, VSR37, &(((VSX *)data)->vs37[0])); + GetVSRegister(tid, VSR38, &(((VSX *)data)->vs38[0])); + GetVSRegister(tid, VSR39, &(((VSX *)data)->vs39[0])); + GetVSRegister(tid, VSR40, &(((VSX *)data)->vs40[0])); + GetVSRegister(tid, VSR41, &(((VSX *)data)->vs41[0])); + GetVSRegister(tid, VSR42, &(((VSX *)data)->vs42[0])); + GetVSRegister(tid, VSR43, &(((VSX *)data)->vs43[0])); + GetVSRegister(tid, VSR44, &(((VSX *)data)->vs44[0])); + GetVSRegister(tid, VSR45, &(((VSX *)data)->vs45[0])); + GetVSRegister(tid, VSR46, &(((VSX *)data)->vs46[0])); + GetVSRegister(tid, VSR47, &(((VSX *)data)->vs47[0])); + GetVSRegister(tid, VSR48, &(((VSX *)data)->vs48[0])); + GetVSRegister(tid, VSR49, &(((VSX *)data)->vs49[0])); + GetVSRegister(tid, VSR50, &(((VSX *)data)->vs50[0])); + GetVSRegister(tid, VSR51, &(((VSX *)data)->vs51[0])); + GetVSRegister(tid, VSR52, &(((VSX *)data)->vs52[0])); + GetVSRegister(tid, VSR53, &(((VSX *)data)->vs53[0])); + GetVSRegister(tid, VSR54, &(((VSX *)data)->vs54[0])); + GetVSRegister(tid, VSR55, &(((VSX *)data)->vs55[0])); + GetVSRegister(tid, VSR56, &(((VSX *)data)->vs56[0])); + GetVSRegister(tid, VSR57, &(((VSX *)data)->vs57[0])); + GetVSRegister(tid, VSR58, &(((VSX *)data)->vs58[0])); + GetVSRegister(tid, VSR59, &(((VSX *)data)->vs59[0])); + GetVSRegister(tid, VSR60, &(((VSX *)data)->vs60[0])); + GetVSRegister(tid, VSR61, &(((VSX *)data)->vs61[0])); + GetVSRegister(tid, VSR62, &(((VSX *)data)->vs62[0])); + GetVSRegister(tid, VSR63, &(((VSX *)data)->vs63[0])); + } else if (req < PT_COMMAND_MAX) { + if (req == PT_CONTINUE) { +#if 0 + // Use PTT_CONTINUE + const char procdir[] = "/proc/"; + const char lwpdir[] = "/lwp/"; + std::string process_task_dir = procdir + std::to_string(pid) + lwpdir; + DIR *dirproc = opendir(process_task_dir.c_str()); + + struct ptthreads64 pts; + int idx = 0; + lldb::tid_t tid = 0; + if (dirproc) { + struct dirent *direntry = nullptr; + while ((direntry = readdir(dirproc)) != nullptr) { + if (strcmp(direntry->d_name, ".") == 0 || strcmp(direntry->d_name, "..") == 0) { + continue; + } + tid = atoi(direntry->d_name); + pts.th[idx++] = tid; + } + closedir(dirproc); + } + pts.th[idx] = 0; + ret = ptrace64(PTT_CONTINUE, tid, (long long)1, (int)(size_t)data, (int *)&pts); +#else + int buf; + ptrace64(req, pid, 1, (int)(size_t)data, &buf); +#endif + } else if (req == PT_READ_BLOCK) { + ptrace64(req, pid, (long long)addr, (int)data_size, (int *)result); + } else if (req == PT_WRITE_BLOCK) { + ptrace64(req, pid, (long long)addr, (int)data_size, (int *)result); + } else if (req == PT_ATTACH) { + ptrace64(req, pid, 0, 0, nullptr); + } else if (req == PT_WATCH) { + ptrace64(req, pid, (long long)addr, (int)data_size, nullptr); + } else if (req == PT_DETACH) { + ptrace64(req, pid, 0, 0, nullptr); + } else { + assert(0 && "Not supported yet."); + } + } else { + assert(0 && "Not supported yet."); + } + + if (errno) { + error.SetErrorToErrno(); + ret = -1; + } + + LLDB_LOG(log, "ptrace({0}, {1}, {2}, {3}, {4})={5:x}", req, pid, addr, data, + data_size, ret); + + PtraceDisplayBytes(req, data, data_size); + + if (error.Fail()) + LLDB_LOG(log, "ptrace() failed: {0}", error); + + return error; +} + +llvm::Expected NativeProcessAIX::TraceSupported() { + return NativeProcessProtocol::TraceSupported(); +} + +Error NativeProcessAIX::TraceStart(StringRef json_request, StringRef type) { + return NativeProcessProtocol::TraceStart(json_request, type); +} + +Error NativeProcessAIX::TraceStop(const TraceStopRequest &request) { + return NativeProcessProtocol::TraceStop(request); +} + +Expected NativeProcessAIX::TraceGetState(StringRef type) { + return NativeProcessProtocol::TraceGetState(type); +} + +Expected> NativeProcessAIX::TraceGetBinaryData( + const TraceGetBinaryDataRequest &request) { + return NativeProcessProtocol::TraceGetBinaryData(request); +} diff --git a/lldb/source/Plugins/Process/AIX/NativeProcessAIX.h b/lldb/source/Plugins/Process/AIX/NativeProcessAIX.h new file mode 100644 index 000000000000000..bdb6f7c500885a5 --- /dev/null +++ b/lldb/source/Plugins/Process/AIX/NativeProcessAIX.h @@ -0,0 +1,283 @@ +//===-- NativeProcessAIX.h ---------------------------------- -*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_NativeProcessAIX_H_ +#define liblldb_NativeProcessAIX_H_ + +#include +#include + +#include "lldb/Host/Debug.h" +#include "lldb/Host/HostThread.h" +#include "lldb/Target/MemoryRegionInfo.h" +#include "lldb/Utility/ArchSpec.h" +#include "lldb/Utility/FileSpec.h" +#include "lldb/lldb-types.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "lldb/Host/aix/Support.h" + +#include "NativeThreadAIX.h" +#include "lldb/Host/common/NativeProcessProtocol.h" +#include "Plugins/Process/Utility/NativeProcessSoftwareSingleStep.h" + +namespace lldb_private { +class Status; +class Scalar; + +namespace process_aix { +/// \class NativeProcessAIX +/// Manages communication with the inferior (debugee) process. +/// +/// Upon construction, this class prepares and launches an inferior process +/// for debugging. +/// +/// Changes in the inferior process state are broadcasted. +class NativeProcessAIX : public NativeProcessProtocol, + private NativeProcessSoftwareSingleStep { +public: + class Manager : public NativeProcessProtocol::Manager { + public: + Manager(MainLoop &mainloop); + + llvm::Expected> + Launch(ProcessLaunchInfo &launch_info, + NativeDelegate &native_delegate) override; + + llvm::Expected> + Attach(lldb::pid_t pid, NativeDelegate &native_delegate) override; + + Extension GetSupportedExtensions() const override; + + void AddProcess(NativeProcessAIX &process) { + m_processes.insert(&process); + } + + void RemoveProcess(NativeProcessAIX &process) { + m_processes.erase(&process); + } + + // Collect an event for the given tid, waiting for it if necessary. + void CollectThread(::pid_t tid); + + private: + MainLoop::SignalHandleUP m_sigchld_handle; + + llvm::SmallPtrSet m_processes; + + // Threads (events) which haven't been claimed by any process. + llvm::DenseSet<::pid_t> m_unowned_threads; + + void SigchldHandler(); + }; + + // NativeProcessProtocol Interface + + ~NativeProcessAIX() override { m_manager.RemoveProcess(*this); } + + Status Resume(const ResumeActionList &resume_actions) override; + + Status Halt() override; + + Status Detach() override; + + Status Signal(int signo) override; + + Status Interrupt() override; + + Status Kill() override; + + lldb::addr_t GetSharedLibraryInfoAddress() override; + + Status GetMemoryRegionInfo(lldb::addr_t load_addr, + MemoryRegionInfo &range_info) override; + + Status ReadMemory(lldb::addr_t addr, void *buf, size_t size, + size_t &bytes_read) override; + + Status WriteMemory(lldb::addr_t addr, const void *buf, size_t size, + size_t &bytes_written) override; + + llvm::Expected AllocateMemory(size_t size, + uint32_t permissions) override; + + llvm::Error DeallocateMemory(lldb::addr_t addr) override; + + Status ReadMemoryTags(int32_t type, lldb::addr_t addr, size_t len, + std::vector &tags) override; + + Status WriteMemoryTags(int32_t type, lldb::addr_t addr, size_t len, + const std::vector &tags) override; + + size_t UpdateThreads() override; + + const ArchSpec &GetArchitecture() const override { return m_arch; } + + Status SetBreakpoint(lldb::addr_t addr, uint32_t size, + bool hardware) override; + + Status RemoveBreakpoint(lldb::addr_t addr, bool hardware = false) override; + + void DoStopIDBumped(uint32_t newBumpId) override; + + Status GetLoadedModuleFileSpec(const char *module_path, + FileSpec &file_spec) override; + + Status GetFileLoadAddress(const llvm::StringRef &file_name, + lldb::addr_t &load_addr) override; + + NativeThreadAIX *GetThreadByID(lldb::tid_t id); + NativeThreadAIX *GetCurrentThread(); + + llvm::ErrorOr> + GetAuxvData() const override { + // Not available on this target. + return llvm::errc::not_supported; + } + + /// Tracing + /// These methods implement the jLLDBTrace packets + /// \{ + llvm::Error TraceStart(llvm::StringRef json_request, + llvm::StringRef type) override; + + llvm::Error TraceStop(const TraceStopRequest &request) override; + + llvm::Expected + TraceGetState(llvm::StringRef type) override; + + llvm::Expected> + TraceGetBinaryData(const TraceGetBinaryDataRequest &request) override; + + llvm::Expected TraceSupported() override; + /// } + + // Interface used by NativeRegisterContext-derived classes. + static Status PtraceWrapper(int req, lldb::pid_t pid, void *addr = nullptr, + void *data = nullptr, size_t data_size = 0, + long *result = nullptr); + + bool SupportHardwareSingleStepping() const; + + /// Writes a siginfo_t structure corresponding to the given thread ID to the + /// memory region pointed to by \p siginfo. + int8_t GetSignalInfo(WaitStatus wstatus) const; + +protected: + llvm::Expected> + GetSoftwareBreakpointTrapOpcode(size_t size_hint) override; + + llvm::Expected Syscall(llvm::ArrayRef args); + +private: + Manager &m_manager; + /*MainLoop::SignalHandleUP m_sigchld_handle;*/ + ArchSpec m_arch; + /*MainLoop& m_main_loop;*/ + + LazyBool m_supports_mem_region = eLazyBoolCalculate; + std::vector> m_mem_region_cache; + + lldb::tid_t m_pending_notification_tid = LLDB_INVALID_THREAD_ID; + + /// Inferior memory (allocated by us) and its size. + llvm::DenseMap m_allocated_memory; + + // Private Instance Methods + NativeProcessAIX(::pid_t pid, int terminal_fd, NativeDelegate &delegate, + const ArchSpec &arch, Manager &manager, + llvm::ArrayRef<::pid_t> tids); + + // Returns a list of process threads that we have attached to. + static llvm::Expected> Attach(::pid_t pid); + + static Status SetDefaultPtraceOpts(const lldb::pid_t); + + bool TryHandleWaitStatus(lldb::pid_t pid, WaitStatus status); + + void MonitorCallback(NativeThreadAIX &thread, WaitStatus status); + + void MonitorSIGTRAP(const WaitStatus status, NativeThreadAIX &thread); + + void MonitorTrace(NativeThreadAIX &thread); + + void MonitorBreakpoint(NativeThreadAIX &thread); + + void MonitorWatchpoint(NativeThreadAIX &thread, uint32_t wp_index); + + void MonitorSignal(const WaitStatus status, NativeThreadAIX &thread); + + bool HasThreadNoLock(lldb::tid_t thread_id); + + void StopTrackingThread(NativeThreadAIX &thread); + + /// Create a new thread. + /// + /// If process tracing is enabled and the thread can't be traced, then the + /// thread is left stopped with a \a eStopReasonProcessorTrace status, and + /// then the process is stopped. + /// + /// \param[in] resume + /// If a tracing error didn't happen, then resume the thread after + /// creation if \b true, or leave it stopped with SIGSTOP if \b false. + NativeThreadAIX &AddThread(lldb::tid_t thread_id, bool resume); + + /// Start tracing a new thread if process tracing is enabled. + /// + /// Trace mechanisms should modify this method to provide automatic tracing + /// for new threads. + Status NotifyTracersOfNewThread(lldb::tid_t tid); + + /// Stop tracing threads upon a destroy event. + /// + /// Trace mechanisms should modify this method to provide automatic trace + /// stopping for threads being destroyed. + Status NotifyTracersOfThreadDestroyed(lldb::tid_t tid); + + void NotifyTracersProcessWillResume() override; + + void NotifyTracersProcessDidStop() override; + /// Writes the raw event message code (vis-a-vis PTRACE_GETEVENTMSG) + /// corresponding to the given thread ID to the memory pointed to by @p + /// message. + Status GetEventMessage(lldb::tid_t tid, unsigned long *message); + + void NotifyThreadDeath(lldb::tid_t tid); + + Status Detach(lldb::tid_t tid); + + // This method is requests a stop on all threads which are still running. It + // sets up a + // deferred delegate notification, which will fire once threads report as + // stopped. The + // triggerring_tid will be set as the current thread (main stop reason). + void StopRunningThreads(lldb::tid_t triggering_tid); + + // Notify the delegate if all threads have stopped. + void SignalIfAllThreadsStopped(); + + // Resume the given thread, optionally passing it the given signal. The type + // of resume + // operation (continue, single-step) depends on the state parameter. + Status ResumeThread(NativeThreadAIX &thread, lldb::StateType state, + int signo); + + void ThreadWasCreated(NativeThreadAIX &thread); + + void SigchldHandler(); + + Status PopulateMemoryRegionCache(); + + // Handle a clone()-like event. + bool MonitorClone(NativeThreadAIX &parent, lldb::pid_t child_pid, + int event); +}; + +} // namespace process_aix +} // namespace lldb_private + +#endif // #ifndef liblldb_NativeProcessAIX_H_ diff --git a/lldb/source/Plugins/Process/AIX/NativeRegisterContextAIX.cpp b/lldb/source/Plugins/Process/AIX/NativeRegisterContextAIX.cpp new file mode 100644 index 000000000000000..0859f9501c1b6a6 --- /dev/null +++ b/lldb/source/Plugins/Process/AIX/NativeRegisterContextAIX.cpp @@ -0,0 +1,157 @@ +//===-- NativeRegisterContextAIX.cpp ------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "NativeRegisterContextAIX.h" + +#include "lldb/Host/common/NativeProcessProtocol.h" +#include "lldb/Host/common/NativeThreadProtocol.h" +#include "lldb/Utility/RegisterValue.h" + +#include "Plugins/Process/AIX/NativeProcessAIX.h" +#include "Plugins/Process/POSIX/ProcessPOSIXLog.h" +#include "lldb/Host/aix/Ptrace.h" + +using namespace lldb_private; +using namespace lldb_private::process_aix; + +lldb::ByteOrder NativeRegisterContextAIX::GetByteOrder() const { + return m_thread.GetProcess().GetByteOrder(); +} + +Status NativeRegisterContextAIX::ReadRegisterRaw(uint32_t reg_index, + RegisterValue ®_value) { + const RegisterInfo *const reg_info = GetRegisterInfoAtIndex(reg_index); + if (!reg_info) + return Status("register %" PRIu32 " not found", reg_index); + + return DoReadRegisterValue(GetPtraceOffset(reg_index), reg_info->name, + reg_info->byte_size, reg_value); +} + +Status +NativeRegisterContextAIX::WriteRegisterRaw(uint32_t reg_index, + const RegisterValue ®_value) { + uint32_t reg_to_write = reg_index; + RegisterValue value_to_write = reg_value; + + // Check if this is a subregister of a full register. + const RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg_index); + if (reg_info->invalidate_regs && + (reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM)) { + Status error; + + RegisterValue full_value; + uint32_t full_reg = reg_info->invalidate_regs[0]; + const RegisterInfo *full_reg_info = GetRegisterInfoAtIndex(full_reg); + + // Read the full register. + error = ReadRegister(full_reg_info, full_value); + if (error.Fail()) + return error; + + lldb::ByteOrder byte_order = GetByteOrder(); + uint8_t dst[RegisterValue::kMaxRegisterByteSize]; + + // Get the bytes for the full register. + const uint32_t dest_size = full_value.GetAsMemoryData( + *full_reg_info, dst, sizeof(dst), byte_order, error); + if (error.Success() && dest_size) { + uint8_t src[RegisterValue::kMaxRegisterByteSize]; + + // Get the bytes for the source data. + const uint32_t src_size = reg_value.GetAsMemoryData( + *reg_info, src, sizeof(src), byte_order, error); + if (error.Success() && src_size && (src_size < dest_size)) { + // Copy the src bytes to the destination. + memcpy(dst + (reg_info->byte_offset & 0x1), src, src_size); + // Set this full register as the value to write. + value_to_write.SetBytes(dst, full_value.GetByteSize(), byte_order); + value_to_write.SetType(*full_reg_info); + reg_to_write = full_reg; + } + } + } + + const RegisterInfo *const register_to_write_info_p = + GetRegisterInfoAtIndex(reg_to_write); + assert(register_to_write_info_p && + "register to write does not have valid RegisterInfo"); + if (!register_to_write_info_p) + return Status("NativeRegisterContextAIX::%s failed to get RegisterInfo " + "for write register index %" PRIu32, + __FUNCTION__, reg_to_write); + + return DoWriteRegisterValue(GetPtraceOffset(reg_index), reg_info->name, + reg_value); +} + +Status NativeRegisterContextAIX::ReadGPR() { + return NativeProcessAIX::PtraceWrapper( + PTRACE_GETREGS, m_thread.GetID(), nullptr, GetGPRBuffer(), GetGPRSize()); +} + +Status NativeRegisterContextAIX::WriteGPR() { + return NativeProcessAIX::PtraceWrapper( + PTRACE_SETREGS, m_thread.GetID(), nullptr, GetGPRBuffer(), GetGPRSize()); +} + +Status NativeRegisterContextAIX::ReadFPR() { + return NativeProcessAIX::PtraceWrapper(PTRACE_GETFPREGS, m_thread.GetID(), + nullptr, GetFPRBuffer(), + GetFPRSize()); +} + +Status NativeRegisterContextAIX::WriteFPR() { + return NativeProcessAIX::PtraceWrapper(PTRACE_SETFPREGS, m_thread.GetID(), + nullptr, GetFPRBuffer(), + GetFPRSize()); +} + +Status NativeRegisterContextAIX::ReadRegisterSet(void *buf, size_t buf_size, + unsigned int regset) { + return NativeProcessAIX::PtraceWrapper(PTRACE_GETREGSET, m_thread.GetID(), + static_cast(®set), buf, + buf_size); +} + +Status NativeRegisterContextAIX::WriteRegisterSet(void *buf, size_t buf_size, + unsigned int regset) { + return NativeProcessAIX::PtraceWrapper(PTRACE_SETREGSET, m_thread.GetID(), + static_cast(®set), buf, + buf_size); +} + +Status NativeRegisterContextAIX::DoReadRegisterValue(uint32_t offset, + const char *reg_name, + uint32_t size, + RegisterValue &value) { + Log *log = GetLog(POSIXLog::Registers); + + long data; + Status error = NativeProcessAIX::PtraceWrapper( + PTRACE_PEEKUSER, m_thread.GetID(), reinterpret_cast(offset), + nullptr, 0, &data); + + if (error.Success()) + // First cast to an unsigned of the same size to avoid sign extension. + value.SetUInt(static_cast(data), size); + + LLDB_LOG(log, "{0}: {1:x}", reg_name, data); + return error; +} + +Status NativeRegisterContextAIX::DoWriteRegisterValue( + uint32_t offset, const char *reg_name, const RegisterValue &value) { + Log *log = GetLog(POSIXLog::Registers); + + void *buf = reinterpret_cast(value.GetAsUInt64()); + LLDB_LOG(log, "{0}: {1}", reg_name, buf); + + return NativeProcessAIX::PtraceWrapper( + PTRACE_POKEUSER, m_thread.GetID(), reinterpret_cast(offset), buf); +} diff --git a/lldb/source/Plugins/Process/AIX/NativeRegisterContextAIX.h b/lldb/source/Plugins/Process/AIX/NativeRegisterContextAIX.h new file mode 100644 index 000000000000000..9c2a326856c0b7b --- /dev/null +++ b/lldb/source/Plugins/Process/AIX/NativeRegisterContextAIX.h @@ -0,0 +1,133 @@ +//===-- NativeRegisterContextAIX.h ----------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef lldb_NativeRegisterContextAIX_h +#define lldb_NativeRegisterContextAIX_h + +#include "Plugins/Process/Utility/NativeRegisterContextRegisterInfo.h" +#include "lldb/Host/common/NativeThreadProtocol.h" +#include "lldb/Target/MemoryTagManager.h" +#include "llvm/Support/Error.h" + +namespace lldb_private { +namespace process_aix { + +class NativeThreadAIX; + +class NativeRegisterContextAIX + : public virtual NativeRegisterContextRegisterInfo { +public: + // This function is implemented in the NativeRegisterContextAIX_* subclasses + // to create a new instance of the host specific NativeRegisterContextAIX. + // The implementations can't collide as only one NativeRegisterContextAIX_* + // variant should be compiled into the final executable. + static std::unique_ptr + CreateHostNativeRegisterContextAIX(const ArchSpec &target_arch, + NativeThreadAIX &native_thread); + + // Invalidates cached values in register context data structures + virtual void InvalidateAllRegisters(){} + + struct SyscallData { + /// The syscall instruction. If the architecture uses software + /// single-stepping, the instruction should also be followed by a trap to + /// ensure the process is stopped after the syscall. + llvm::ArrayRef Insn; + + /// Registers used for syscall arguments. The first register is used to + /// store the syscall number. + llvm::ArrayRef Args; + + uint32_t Result; ///< Register containing the syscall result. + }; + /// Return architecture-specific data needed to make inferior syscalls, if + /// they are supported. + virtual std::optional GetSyscallData() { return std::nullopt; } + + struct MmapData { + // Syscall numbers can be found (e.g.) in /usr/include/asm/unistd.h for the + // relevant architecture. + unsigned SysMmap; ///< mmap syscall number. + unsigned SysMunmap; ///< munmap syscall number + }; + /// Return the architecture-specific data needed to make mmap syscalls, if + /// they are supported. + virtual std::optional GetMmapData() { return std::nullopt; } + + struct MemoryTaggingDetails { + /// Object with tag handling utilities. If the function below returns + /// a valid structure, you can assume that this pointer is valid. + std::unique_ptr manager; + int ptrace_read_req; /// ptrace operation number for memory tag read + int ptrace_write_req; /// ptrace operation number for memory tag write + }; + /// Return architecture specific data needed to use memory tags, + /// if they are supported. + virtual llvm::Expected + GetMemoryTaggingDetails(int32_t type) { + return llvm::createStringError( + llvm::inconvertibleErrorCode(), + "Architecture does not support memory tagging"); + } + +protected: + // NB: This constructor is here only because gcc<=6.5 requires a virtual base + // class initializer on abstract class (even though it is never used). It can + // be deleted once we move to gcc>=7.0. + NativeRegisterContextAIX(NativeThreadProtocol &thread) + : NativeRegisterContextRegisterInfo(thread, nullptr) {} + + lldb::ByteOrder GetByteOrder() const; + + virtual Status ReadRegisterRaw(uint32_t reg_index, RegisterValue ®_value); + + virtual Status WriteRegisterRaw(uint32_t reg_index, + const RegisterValue ®_value); + + virtual Status ReadRegisterSet(void *buf, size_t buf_size, + unsigned int regset); + + virtual Status WriteRegisterSet(void *buf, size_t buf_size, + unsigned int regset); + + virtual Status ReadGPR(); + + virtual Status WriteGPR(); + + virtual Status ReadFPR(); + + virtual Status WriteFPR(); + + virtual void *GetGPRBuffer() = 0; + + virtual size_t GetGPRSize() const { + return GetRegisterInfoInterface().GetGPRSize(); + } + + virtual void *GetFPRBuffer() = 0; + + virtual size_t GetFPRSize() = 0; + + virtual uint32_t GetPtraceOffset(uint32_t reg_index) { + return GetRegisterInfoAtIndex(reg_index)->byte_offset; + } + + // The Do*** functions are executed on the privileged thread and can perform + // ptrace + // operations directly. + virtual Status DoReadRegisterValue(uint32_t offset, const char *reg_name, + uint32_t size, RegisterValue &value); + + virtual Status DoWriteRegisterValue(uint32_t offset, const char *reg_name, + const RegisterValue &value); +}; + +} // namespace process_aix +} // namespace lldb_private + +#endif // #ifndef lldb_NativeRegisterContextAIX_h diff --git a/lldb/source/Plugins/Process/AIX/NativeRegisterContextAIX_ppc64.cpp b/lldb/source/Plugins/Process/AIX/NativeRegisterContextAIX_ppc64.cpp new file mode 100644 index 000000000000000..199637379174840 --- /dev/null +++ b/lldb/source/Plugins/Process/AIX/NativeRegisterContextAIX_ppc64.cpp @@ -0,0 +1,744 @@ +//===-- NativeRegisterContextAIX_ppc64.cpp ----------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// This implementation is related to the OpenPOWER ABI for Power Architecture +// 64-bit ELF V2 ABI + +#if defined(__powerpc64__) + +#include "NativeRegisterContextAIX_ppc64.h" + +#include "lldb/Host/common/NativeProcessProtocol.h" +#include "lldb/Utility/DataBufferHeap.h" +#include "lldb/Utility/Log.h" +#include "lldb/Utility/RegisterValue.h" +#include "lldb/Utility/Status.h" +#include "lldb/Host/aix/Ptrace.h" + +#include "Plugins/Process/AIX/NativeProcessAIX.h" +#include "Plugins/Process/Linux/Procfs.h" +#include "Plugins/Process/POSIX/ProcessPOSIXLog.h" +#include "Plugins/Process/Utility/RegisterInfoPOSIX_ppc64le.h" + +// System includes - They have to be included after framework includes because +// they define some macros which collide with variable names in other modules +#include +#include +#include +#include + +#define REG_CONTEXT_SIZE \ + (GetGPRSize() + GetFPRSize() + sizeof(m_vmx_ppc64le) + sizeof(m_vsx_ppc64le)) +using namespace lldb; +using namespace lldb_private; +using namespace lldb_private::process_aix; + +static const uint32_t g_gpr_regnums_ppc64le[] = { + gpr_r0_ppc64le, gpr_r1_ppc64le, gpr_r2_ppc64le, gpr_r3_ppc64le, + gpr_r4_ppc64le, gpr_r5_ppc64le, gpr_r6_ppc64le, gpr_r7_ppc64le, + gpr_r8_ppc64le, gpr_r9_ppc64le, gpr_r10_ppc64le, gpr_r11_ppc64le, + gpr_r12_ppc64le, gpr_r13_ppc64le, gpr_r14_ppc64le, gpr_r15_ppc64le, + gpr_r16_ppc64le, gpr_r17_ppc64le, gpr_r18_ppc64le, gpr_r19_ppc64le, + gpr_r20_ppc64le, gpr_r21_ppc64le, gpr_r22_ppc64le, gpr_r23_ppc64le, + gpr_r24_ppc64le, gpr_r25_ppc64le, gpr_r26_ppc64le, gpr_r27_ppc64le, + gpr_r28_ppc64le, gpr_r29_ppc64le, gpr_r30_ppc64le, gpr_r31_ppc64le, + gpr_pc_ppc64le, gpr_msr_ppc64le, gpr_origr3_ppc64le, gpr_ctr_ppc64le, + gpr_lr_ppc64le, gpr_xer_ppc64le, gpr_cr_ppc64le, gpr_softe_ppc64le, + gpr_trap_ppc64le, + LLDB_INVALID_REGNUM // register sets need to end with this flag +}; + +static const uint32_t g_fpr_regnums_ppc64le[] = { + fpr_f0_ppc64le, fpr_f1_ppc64le, fpr_f2_ppc64le, fpr_f3_ppc64le, + fpr_f4_ppc64le, fpr_f5_ppc64le, fpr_f6_ppc64le, fpr_f7_ppc64le, + fpr_f8_ppc64le, fpr_f9_ppc64le, fpr_f10_ppc64le, fpr_f11_ppc64le, + fpr_f12_ppc64le, fpr_f13_ppc64le, fpr_f14_ppc64le, fpr_f15_ppc64le, + fpr_f16_ppc64le, fpr_f17_ppc64le, fpr_f18_ppc64le, fpr_f19_ppc64le, + fpr_f20_ppc64le, fpr_f21_ppc64le, fpr_f22_ppc64le, fpr_f23_ppc64le, + fpr_f24_ppc64le, fpr_f25_ppc64le, fpr_f26_ppc64le, fpr_f27_ppc64le, + fpr_f28_ppc64le, fpr_f29_ppc64le, fpr_f30_ppc64le, fpr_f31_ppc64le, + fpr_fpscr_ppc64le, + LLDB_INVALID_REGNUM // register sets need to end with this flag +}; + +static const uint32_t g_vmx_regnums_ppc64le[] = { + vmx_vr0_ppc64le, vmx_vr1_ppc64le, vmx_vr2_ppc64le, vmx_vr3_ppc64le, + vmx_vr4_ppc64le, vmx_vr5_ppc64le, vmx_vr6_ppc64le, vmx_vr7_ppc64le, + vmx_vr8_ppc64le, vmx_vr9_ppc64le, vmx_vr10_ppc64le, vmx_vr11_ppc64le, + vmx_vr12_ppc64le, vmx_vr13_ppc64le, vmx_vr14_ppc64le, vmx_vr15_ppc64le, + vmx_vr16_ppc64le, vmx_vr17_ppc64le, vmx_vr18_ppc64le, vmx_vr19_ppc64le, + vmx_vr20_ppc64le, vmx_vr21_ppc64le, vmx_vr22_ppc64le, vmx_vr23_ppc64le, + vmx_vr24_ppc64le, vmx_vr25_ppc64le, vmx_vr26_ppc64le, vmx_vr27_ppc64le, + vmx_vr28_ppc64le, vmx_vr29_ppc64le, vmx_vr30_ppc64le, vmx_vr31_ppc64le, + vmx_vscr_ppc64le, vmx_vrsave_ppc64le, + LLDB_INVALID_REGNUM // register sets need to end with this flag +}; + +static const uint32_t g_vsx_regnums_ppc64le[] = { + vsx_vs0_ppc64le, vsx_vs1_ppc64le, vsx_vs2_ppc64le, vsx_vs3_ppc64le, + vsx_vs4_ppc64le, vsx_vs5_ppc64le, vsx_vs6_ppc64le, vsx_vs7_ppc64le, + vsx_vs8_ppc64le, vsx_vs9_ppc64le, vsx_vs10_ppc64le, vsx_vs11_ppc64le, + vsx_vs12_ppc64le, vsx_vs13_ppc64le, vsx_vs14_ppc64le, vsx_vs15_ppc64le, + vsx_vs16_ppc64le, vsx_vs17_ppc64le, vsx_vs18_ppc64le, vsx_vs19_ppc64le, + vsx_vs20_ppc64le, vsx_vs21_ppc64le, vsx_vs22_ppc64le, vsx_vs23_ppc64le, + vsx_vs24_ppc64le, vsx_vs25_ppc64le, vsx_vs26_ppc64le, vsx_vs27_ppc64le, + vsx_vs28_ppc64le, vsx_vs29_ppc64le, vsx_vs30_ppc64le, vsx_vs31_ppc64le, + vsx_vs32_ppc64le, vsx_vs33_ppc64le, vsx_vs34_ppc64le, vsx_vs35_ppc64le, + vsx_vs36_ppc64le, vsx_vs37_ppc64le, vsx_vs38_ppc64le, vsx_vs39_ppc64le, + vsx_vs40_ppc64le, vsx_vs41_ppc64le, vsx_vs42_ppc64le, vsx_vs43_ppc64le, + vsx_vs44_ppc64le, vsx_vs45_ppc64le, vsx_vs46_ppc64le, vsx_vs47_ppc64le, + vsx_vs48_ppc64le, vsx_vs49_ppc64le, vsx_vs50_ppc64le, vsx_vs51_ppc64le, + vsx_vs52_ppc64le, vsx_vs53_ppc64le, vsx_vs54_ppc64le, vsx_vs55_ppc64le, + vsx_vs56_ppc64le, vsx_vs57_ppc64le, vsx_vs58_ppc64le, vsx_vs59_ppc64le, + vsx_vs60_ppc64le, vsx_vs61_ppc64le, vsx_vs62_ppc64le, vsx_vs63_ppc64le, + LLDB_INVALID_REGNUM // register sets need to end with this flag +}; + +// Number of register sets provided by this context. +static constexpr int k_num_register_sets = 4; + +static const RegisterSet g_reg_sets_ppc64le[k_num_register_sets] = { + {"General Purpose Registers", "gpr", k_num_gpr_registers_ppc64le, + g_gpr_regnums_ppc64le}, + {"Floating Point Registers", "fpr", k_num_fpr_registers_ppc64le, + g_fpr_regnums_ppc64le}, + {"AltiVec/VMX Registers", "vmx", k_num_vmx_registers_ppc64le, + g_vmx_regnums_ppc64le}, + {"VSX Registers", "vsx", k_num_vsx_registers_ppc64le, + g_vsx_regnums_ppc64le}, +}; + +std::unique_ptr +NativeRegisterContextAIX::CreateHostNativeRegisterContextAIX( + const ArchSpec &target_arch, NativeThreadAIX &native_thread) { + switch (target_arch.GetMachine()) { + case llvm::Triple::ppc64: + return std::make_unique(target_arch, + native_thread); + default: + llvm_unreachable("have no register context for architecture"); + } +} + +NativeRegisterContextAIX_ppc64::NativeRegisterContextAIX_ppc64( + const ArchSpec &target_arch, NativeThreadProtocol &native_thread) + : NativeRegisterContextRegisterInfo( + native_thread, new RegisterInfoPOSIX_ppc64le(target_arch)), + NativeRegisterContextAIX(native_thread) { + if (target_arch.GetMachine() != llvm::Triple::ppc64) { + llvm_unreachable("Unhandled target architecture."); + } + + ::memset(&m_gpr_ppc64le, 0, sizeof(m_gpr_ppc64le)); + ::memset(&m_fpr_ppc64le, 0, sizeof(m_fpr_ppc64le)); + ::memset(&m_vmx_ppc64le, 0, sizeof(m_vmx_ppc64le)); + ::memset(&m_vsx_ppc64le, 0, sizeof(m_vsx_ppc64le)); + ::memset(&m_hwp_regs, 0, sizeof(m_hwp_regs)); +} + +uint32_t NativeRegisterContextAIX_ppc64::GetRegisterSetCount() const { + return k_num_register_sets; +} + +const RegisterSet * +NativeRegisterContextAIX_ppc64::GetRegisterSet(uint32_t set_index) const { + if (set_index < k_num_register_sets) + return &g_reg_sets_ppc64le[set_index]; + + return nullptr; +} + +uint32_t NativeRegisterContextAIX_ppc64::GetUserRegisterCount() const { + uint32_t count = 0; + for (uint32_t set_index = 0; set_index < k_num_register_sets; ++set_index) + count += g_reg_sets_ppc64le[set_index].num_registers; + return count; +} + +Status NativeRegisterContextAIX_ppc64::ReadRegister( + const RegisterInfo *reg_info, RegisterValue ®_value) { + Status error; + + if (!reg_info) { + error.SetErrorString("reg_info NULL"); + return error; + } + + const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB]; + + if (IsFPR(reg)) { + error = ReadFPR(); + if (error.Fail()) + return error; + + // Get pointer to m_fpr_ppc64le variable and set the data from it. + uint32_t fpr_offset = CalculateFprOffset(reg_info); + assert(fpr_offset < sizeof m_fpr_ppc64le); + uint8_t *src = (uint8_t *)&m_fpr_ppc64le + fpr_offset; + reg_value.SetFromMemoryData(*reg_info, src, reg_info->byte_size, + eByteOrderLittle, error); + } else if (IsVSX(reg)) { + uint32_t vsx_offset = CalculateVsxOffset(reg_info); + assert(vsx_offset < sizeof(m_vsx_ppc64le)); + + if (vsx_offset < sizeof(m_vsx_ppc64le) / 2) { + error = ReadVSX(); + if (error.Fail()) + return error; + + error = ReadFPR(); + if (error.Fail()) + return error; + + uint64_t value[2]; + uint8_t *dst, *src; + dst = (uint8_t *)&value; + src = (uint8_t *)&m_vsx_ppc64le + vsx_offset / 2; + ::memcpy(dst, src, 8); + dst += 8; + src = (uint8_t *)&m_fpr_ppc64le + vsx_offset / 2; + ::memcpy(dst, src, 8); + reg_value.SetFromMemoryData(*reg_info, &value, reg_info->byte_size, + eByteOrderLittle, error); + } else { + error = ReadVMX(); + if (error.Fail()) + return error; + + // Get pointer to m_vmx_ppc64le variable and set the data from it. + uint32_t vmx_offset = vsx_offset - sizeof(m_vsx_ppc64le) / 2; + uint8_t *src = (uint8_t *)&m_vmx_ppc64le + vmx_offset; + reg_value.SetFromMemoryData(*reg_info, src, reg_info->byte_size, + eByteOrderLittle, error); + } + } else if (IsVMX(reg)) { + error = ReadVMX(); + if (error.Fail()) + return error; + + // Get pointer to m_vmx_ppc64le variable and set the data from it. + uint32_t vmx_offset = CalculateVmxOffset(reg_info); + assert(vmx_offset < sizeof m_vmx_ppc64le); + uint8_t *src = (uint8_t *)&m_vmx_ppc64le + vmx_offset; + reg_value.SetFromMemoryData(*reg_info, src, reg_info->byte_size, + eByteOrderLittle, error); + } else if (IsGPR(reg)) { + error = ReadGPR(); + if (error.Fail()) + return error; + + uint8_t *src = (uint8_t *) &m_gpr_ppc64le + reg_info->byte_offset; + reg_value.SetFromMemoryData(*reg_info, src, reg_info->byte_size, + eByteOrderLittle, error); + } else { + return Status("failed - register wasn't recognized to be a GPR, FPR, VSX " + "or VMX, read strategy unknown"); + } + + return error; +} + +Status NativeRegisterContextAIX_ppc64::WriteRegister( + const RegisterInfo *reg_info, const RegisterValue ®_value) { + Status error; + if (!reg_info) + return Status("reg_info NULL"); + + const uint32_t reg_index = reg_info->kinds[lldb::eRegisterKindLLDB]; + if (reg_index == LLDB_INVALID_REGNUM) + return Status("no lldb regnum for %s", reg_info && reg_info->name + ? reg_info->name + : ""); + + if (IsGPR(reg_index)) { + error = ReadGPR(); + if (error.Fail()) + return error; + + uint8_t *dst = (uint8_t *)&m_gpr_ppc64le + reg_info->byte_offset; + ::memcpy(dst, reg_value.GetBytes(), reg_value.GetByteSize()); + *(uint64_t *)dst = llvm::byteswap(*(uint64_t *)dst); + + error = WriteGPR(); + if (error.Fail()) + return error; + + return Status(); + } + + if (IsFPR(reg_index)) { + error = ReadFPR(); + if (error.Fail()) + return error; + + // Get pointer to m_fpr_ppc64le variable and set the data to it. + uint32_t fpr_offset = CalculateFprOffset(reg_info); + assert(fpr_offset < GetFPRSize()); + uint8_t *dst = (uint8_t *)&m_fpr_ppc64le + fpr_offset; + ::memcpy(dst, reg_value.GetBytes(), reg_value.GetByteSize()); + + error = WriteFPR(); + if (error.Fail()) + return error; + + return Status(); + } + + if (IsVMX(reg_index)) { + error = ReadVMX(); + if (error.Fail()) + return error; + + // Get pointer to m_vmx_ppc64le variable and set the data to it. + uint32_t vmx_offset = CalculateVmxOffset(reg_info); + assert(vmx_offset < sizeof(m_vmx_ppc64le)); + uint8_t *dst = (uint8_t *)&m_vmx_ppc64le + vmx_offset; + ::memcpy(dst, reg_value.GetBytes(), reg_value.GetByteSize()); + + error = WriteVMX(); + if (error.Fail()) + return error; + + return Status(); + } + + if (IsVSX(reg_index)) { + uint32_t vsx_offset = CalculateVsxOffset(reg_info); + assert(vsx_offset < sizeof(m_vsx_ppc64le)); + + if (vsx_offset < sizeof(m_vsx_ppc64le) / 2) { + error = ReadVSX(); + if (error.Fail()) + return error; + + error = ReadFPR(); + if (error.Fail()) + return error; + + uint64_t value[2]; + ::memcpy(value, reg_value.GetBytes(), 16); + uint8_t *dst, *src; + src = (uint8_t *)value; + dst = (uint8_t *)&m_vsx_ppc64le + vsx_offset / 2; + ::memcpy(dst, src, 8); + src += 8; + dst = (uint8_t *)&m_fpr_ppc64le + vsx_offset / 2; + ::memcpy(dst, src, 8); + + WriteVSX(); + WriteFPR(); + } else { + error = ReadVMX(); + if (error.Fail()) + return error; + + // Get pointer to m_vmx_ppc64le variable and set the data from it. + uint32_t vmx_offset = vsx_offset - sizeof(m_vsx_ppc64le) / 2; + uint8_t *dst = (uint8_t *)&m_vmx_ppc64le + vmx_offset; + ::memcpy(dst, reg_value.GetBytes(), reg_value.GetByteSize()); + WriteVMX(); + } + + return Status(); + } + + return Status("failed - register wasn't recognized to be a GPR, FPR, VSX " + "or VMX, write strategy unknown"); +} + +Status NativeRegisterContextAIX_ppc64::ReadAllRegisterValues( + lldb::WritableDataBufferSP &data_sp) { + Status error; + + data_sp.reset(new DataBufferHeap(REG_CONTEXT_SIZE, 0)); + error = ReadGPR(); + if (error.Fail()) + return error; + + error = ReadFPR(); + if (error.Fail()) + return error; + + error = ReadVMX(); + if (error.Fail()) + return error; + + error = ReadVSX(); + if (error.Fail()) + return error; + + uint8_t *dst = data_sp->GetBytes(); + ::memcpy(dst, &m_gpr_ppc64le, GetGPRSize()); + dst += GetGPRSize(); + ::memcpy(dst, &m_fpr_ppc64le, GetFPRSize()); + dst += GetFPRSize(); + ::memcpy(dst, &m_vmx_ppc64le, sizeof(m_vmx_ppc64le)); + dst += sizeof(m_vmx_ppc64le); + ::memcpy(dst, &m_vsx_ppc64le, sizeof(m_vsx_ppc64le)); + + return error; +} + +Status NativeRegisterContextAIX_ppc64::WriteAllRegisterValues( + const lldb::DataBufferSP &data_sp) { + Status error; + + if (!data_sp) { + error.SetErrorStringWithFormat( + "NativeRegisterContextAIX_ppc64::%s invalid data_sp provided", + __FUNCTION__); + return error; + } + + if (data_sp->GetByteSize() != REG_CONTEXT_SIZE) { + error.SetErrorStringWithFormat( + "NativeRegisterContextAIX_ppc64::%s data_sp contained mismatched " + "data size, expected %" PRIu64 ", actual %" PRIu64, + __FUNCTION__, REG_CONTEXT_SIZE, data_sp->GetByteSize()); + return error; + } + + const uint8_t *src = data_sp->GetBytes(); + if (src == nullptr) { + error.SetErrorStringWithFormat("NativeRegisterContextAIX_ppc64::%s " + "DataBuffer::GetBytes() returned a null " + "pointer", + __FUNCTION__); + return error; + } + + ::memcpy(&m_gpr_ppc64le, src, GetGPRSize()); + error = WriteGPR(); + + if (error.Fail()) + return error; + + src += GetGPRSize(); + ::memcpy(&m_fpr_ppc64le, src, GetFPRSize()); + + error = WriteFPR(); + if (error.Fail()) + return error; + + src += GetFPRSize(); + ::memcpy(&m_vmx_ppc64le, src, sizeof(m_vmx_ppc64le)); + + error = WriteVMX(); + if (error.Fail()) + return error; + + src += sizeof(m_vmx_ppc64le); + ::memcpy(&m_vsx_ppc64le, src, sizeof(m_vsx_ppc64le)); + error = WriteVSX(); + + return error; +} + +bool NativeRegisterContextAIX_ppc64::IsGPR(unsigned reg) const { + return reg <= k_last_gpr_ppc64le; // GPR's come first. +} + +bool NativeRegisterContextAIX_ppc64::IsFPR(unsigned reg) const { + return (k_first_fpr_ppc64le <= reg && reg <= k_last_fpr_ppc64le); +} + +uint32_t NativeRegisterContextAIX_ppc64::CalculateFprOffset( + const RegisterInfo *reg_info) const { + return reg_info->byte_offset - + GetRegisterInfoAtIndex(k_first_fpr_ppc64le)->byte_offset; +} + +uint32_t NativeRegisterContextAIX_ppc64::CalculateVmxOffset( + const RegisterInfo *reg_info) const { + return reg_info->byte_offset - + GetRegisterInfoAtIndex(k_first_vmx_ppc64le)->byte_offset; +} + +uint32_t NativeRegisterContextAIX_ppc64::CalculateVsxOffset( + const RegisterInfo *reg_info) const { + return reg_info->byte_offset - + GetRegisterInfoAtIndex(k_first_vsx_ppc64le)->byte_offset; +} + +Status NativeRegisterContextAIX_ppc64::ReadVMX() { + return NativeProcessAIX::PtraceWrapper(PTRACE_GETVRREGS, m_thread.GetID(), + nullptr, &m_vmx_ppc64le, + sizeof(m_vmx_ppc64le)); +} + +Status NativeRegisterContextAIX_ppc64::WriteVMX() { + //FIXME + int regset = 0/*NT_PPC_VMX*/; + return NativeProcessAIX::PtraceWrapper(PT_CLEAR/*PTRACE_SETVRREGS*/, m_thread.GetID(), + ®set, &m_vmx_ppc64le, + sizeof(m_vmx_ppc64le)); +} + +Status NativeRegisterContextAIX_ppc64::ReadVSX() { + return NativeProcessAIX::PtraceWrapper(PTRACE_GETVSRREGS, m_thread.GetID(), + nullptr, &m_vsx_ppc64le, + sizeof(m_vsx_ppc64le)); +} + +Status NativeRegisterContextAIX_ppc64::WriteVSX() { + //FIXME + int regset = 0/*NT_PPC_VSX*/; + return NativeProcessAIX::PtraceWrapper(PT_CLEAR/*PTRACE_SETVSRREGS*/, m_thread.GetID(), + ®set, &m_vsx_ppc64le, + sizeof(m_vsx_ppc64le)); +} + +bool NativeRegisterContextAIX_ppc64::IsVMX(unsigned reg) { + return (reg >= k_first_vmx_ppc64le) && (reg <= k_last_vmx_ppc64le); +} + +bool NativeRegisterContextAIX_ppc64::IsVSX(unsigned reg) { + return (reg >= k_first_vsx_ppc64le) && (reg <= k_last_vsx_ppc64le); +} + +uint32_t NativeRegisterContextAIX_ppc64::NumSupportedHardwareWatchpoints() { + Log *log = GetLog(POSIXLog::Watchpoints); + + // Read hardware breakpoint and watchpoint information. + Status error = ReadHardwareDebugInfo(); + + if (error.Fail()) + return 0; + + LLDB_LOG(log, "{0}", m_max_hwp_supported); + return m_max_hwp_supported; +} + +uint32_t NativeRegisterContextAIX_ppc64::SetHardwareWatchpoint( + lldb::addr_t addr, size_t size, uint32_t watch_flags) { + Log *log = GetLog(POSIXLog::Watchpoints); + LLDB_LOG(log, "addr: {0:x}, size: {1:x} watch_flags: {2:x}", addr, size, + watch_flags); + + // Read hardware breakpoint and watchpoint information. + Status error = ReadHardwareDebugInfo(); + + if (error.Fail()) + return LLDB_INVALID_INDEX32; + + uint32_t control_value = 0, wp_index = 0; + lldb::addr_t real_addr = addr; + uint32_t rw_mode = 0; + + // Check if we are setting watchpoint other than read/write/access Update + // watchpoint flag to match ppc64le write-read bit configuration. + switch (watch_flags) { + case eWatchpointKindWrite: + //FIXME + //rw_mode = 0/*PPC_BREAKPOINT_TRIGGER_WRITE*/; + watch_flags = 2; + break; + // Watchpoint read not supported + case eWatchpointKindRead: + case (eWatchpointKindRead | eWatchpointKindWrite): + default: + return LLDB_INVALID_INDEX32; + } + + // Check if size has a valid hardware watchpoint length. + if (size != 8) + return LLDB_INVALID_INDEX32; + + // Check 8-byte alignment for hardware watchpoint target address. Below is a + // hack to recalculate address and size in order to make sure we can watch + // non 8-byte aligned addresses as well. + if (addr & 0x07) { + + addr_t begin = llvm::alignDown(addr, 8); + addr_t end = llvm::alignTo(addr + size, 8); + size = llvm::PowerOf2Ceil(end - begin); + + addr = addr & (~0x07); + } + + // Setup control value + control_value = watch_flags << 3; + control_value |= ((1 << size) - 1) << 5; + control_value |= (2 << 1) | 1; + + // Iterate over stored watchpoints and find a free wp_index + wp_index = LLDB_INVALID_INDEX32; + for (uint32_t i = 0; i < m_max_hwp_supported; i++) { + if ((m_hwp_regs[i].control & 1) == 0) { + wp_index = i; // Mark last free slot + } else if (m_hwp_regs[i].address == addr) { + return LLDB_INVALID_INDEX32; // We do not support duplicate watchpoints. + } + } + + if (wp_index == LLDB_INVALID_INDEX32) + return LLDB_INVALID_INDEX32; + + // Update watchpoint in local cache + m_hwp_regs[wp_index].real_addr = real_addr; + m_hwp_regs[wp_index].address = addr; + m_hwp_regs[wp_index].control = control_value; + //m_hwp_regs[wp_index].mode = rw_mode; + + // PTRACE call to set corresponding watchpoint register. + error = WriteHardwareDebugRegs(); + + if (error.Fail()) { + m_hwp_regs[wp_index].address = 0; + m_hwp_regs[wp_index].control &= llvm::maskTrailingZeros(1); + + return LLDB_INVALID_INDEX32; + } + + return wp_index; +} + +bool NativeRegisterContextAIX_ppc64::ClearHardwareWatchpoint( + uint32_t wp_index) { + Log *log = GetLog(POSIXLog::Watchpoints); + LLDB_LOG(log, "wp_index: {0}", wp_index); + + // Read hardware breakpoint and watchpoint information. + Status error = ReadHardwareDebugInfo(); + + if (error.Fail()) + return false; + + if (wp_index >= m_max_hwp_supported) + return false; + + // Create a backup we can revert to in case of failure. + lldb::addr_t tempAddr = m_hwp_regs[wp_index].address; + uint32_t tempControl = m_hwp_regs[wp_index].control; + long *tempSlot = reinterpret_cast(m_hwp_regs[wp_index].slot); + + // Update watchpoint in local cache + m_hwp_regs[wp_index].control &= llvm::maskTrailingZeros(1); + m_hwp_regs[wp_index].address = 0; + m_hwp_regs[wp_index].slot = 0; + m_hwp_regs[wp_index].mode = 0; + + // Ptrace call to update hardware debug registers + //FIXME + error = NativeProcessAIX::PtraceWrapper(PT_CLEAR/*PPC_PTRACE_DELHWDEBUG*/, + m_thread.GetID(), 0, tempSlot); + + if (error.Fail()) { + m_hwp_regs[wp_index].control = tempControl; + m_hwp_regs[wp_index].address = tempAddr; + m_hwp_regs[wp_index].slot = reinterpret_cast(tempSlot); + + return false; + } + + return true; +} + +uint32_t +NativeRegisterContextAIX_ppc64::GetWatchpointSize(uint32_t wp_index) { + Log *log = GetLog(POSIXLog::Watchpoints); + LLDB_LOG(log, "wp_index: {0}", wp_index); + + unsigned control = (m_hwp_regs[wp_index].control >> 5) & 0xff; + if (llvm::isPowerOf2_32(control + 1)) { + return llvm::popcount(control); + } + + return 0; +} + +bool NativeRegisterContextAIX_ppc64::WatchpointIsEnabled( + uint32_t wp_index) { + Log *log = GetLog(POSIXLog::Watchpoints); + LLDB_LOG(log, "wp_index: {0}", wp_index); + + return !!((m_hwp_regs[wp_index].control & 0x1) == 0x1); +} + +Status NativeRegisterContextAIX_ppc64::GetWatchpointHitIndex( + uint32_t &wp_index, lldb::addr_t trap_addr) { + Log *log = GetLog(POSIXLog::Watchpoints); + LLDB_LOG(log, "wp_index: {0}, trap_addr: {1:x}", wp_index, trap_addr); + + uint32_t watch_size; + lldb::addr_t watch_addr; + + for (wp_index = 0; wp_index < m_max_hwp_supported; ++wp_index) { + watch_size = GetWatchpointSize(wp_index); + watch_addr = m_hwp_regs[wp_index].address; + + if (WatchpointIsEnabled(wp_index) && trap_addr >= watch_addr && + trap_addr <= watch_addr + watch_size) { + m_hwp_regs[wp_index].hit_addr = trap_addr; + return Status(); + } + } + + wp_index = LLDB_INVALID_INDEX32; + return Status(); +} + +lldb::addr_t +NativeRegisterContextAIX_ppc64::GetWatchpointAddress(uint32_t wp_index) { + Log *log = GetLog(POSIXLog::Watchpoints); + LLDB_LOG(log, "wp_index: {0}", wp_index); + + if (wp_index >= m_max_hwp_supported) + return LLDB_INVALID_ADDRESS; + + if (WatchpointIsEnabled(wp_index)) + return m_hwp_regs[wp_index].real_addr; + else + return LLDB_INVALID_ADDRESS; +} + +lldb::addr_t +NativeRegisterContextAIX_ppc64::GetWatchpointHitAddress(uint32_t wp_index) { + Log *log = GetLog(POSIXLog::Watchpoints); + LLDB_LOG(log, "wp_index: {0}", wp_index); + + if (wp_index >= m_max_hwp_supported) + return LLDB_INVALID_ADDRESS; + + if (WatchpointIsEnabled(wp_index)) + return m_hwp_regs[wp_index].hit_addr; + + return LLDB_INVALID_ADDRESS; +} + +Status NativeRegisterContextAIX_ppc64::ReadHardwareDebugInfo() { + if (!m_refresh_hwdebug_info) { + return Status(); + } + + m_max_hwp_supported = 1; + m_max_hbp_supported = 0; + m_refresh_hwdebug_info = false; + + return Status(); +} + +Status NativeRegisterContextAIX_ppc64::WriteHardwareDebugRegs() { + Status error; + long ret; + + for (uint32_t i = 0; i < m_max_hwp_supported; i++) { + if ((m_hwp_regs[i].control & 1) == 0) + continue; + + error = NativeProcessAIX::PtraceWrapper(PT_WATCH, m_thread.GetID(), (void *)m_hwp_regs[i].address, nullptr, 8, &ret); + + if (error.Fail()) + return error; + + m_hwp_regs[i].slot = ret; + } + return error; +} + +#endif // defined(__powerpc64__) diff --git a/lldb/source/Plugins/Process/AIX/NativeRegisterContextAIX_ppc64.h b/lldb/source/Plugins/Process/AIX/NativeRegisterContextAIX_ppc64.h new file mode 100644 index 000000000000000..a29f786f2313a64 --- /dev/null +++ b/lldb/source/Plugins/Process/AIX/NativeRegisterContextAIX_ppc64.h @@ -0,0 +1,138 @@ +//===-- NativeRegisterContextAIX_ppc64.h --------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// This implementation is related to the OpenPOWER ABI for Power Architecture +// 64-bit ELF V2 ABI + +#if defined(__powerpc64__) + +#ifndef lldb_NativeRegisterContextAIX_ppc64_h +#define lldb_NativeRegisterContextAIX_ppc64_h + +#include "Plugins/Process/AIX/NativeRegisterContextAIX.h" +#include "Plugins/Process/Utility/lldb-ppc64le-register-enums.h" + +#define DECLARE_REGISTER_INFOS_PPC64LE_STRUCT +#include "Plugins/Process/Utility/RegisterInfos_ppc64le.h" +#undef DECLARE_REGISTER_INFOS_PPC64LE_STRUCT + +namespace lldb_private { +namespace process_aix { + +class NativeProcessAIX; + +class NativeRegisterContextAIX_ppc64 : public NativeRegisterContextAIX { +public: + NativeRegisterContextAIX_ppc64(const ArchSpec &target_arch, + NativeThreadProtocol &native_thread); + + uint32_t GetRegisterSetCount() const override; + + uint32_t GetUserRegisterCount() const override; + + const RegisterSet *GetRegisterSet(uint32_t set_index) const override; + + Status ReadRegister(const RegisterInfo *reg_info, + RegisterValue ®_value) override; + + Status WriteRegister(const RegisterInfo *reg_info, + const RegisterValue ®_value) override; + + Status ReadAllRegisterValues(lldb::WritableDataBufferSP &data_sp) override; + + Status WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override; + + // Hardware watchpoint management functions + + uint32_t NumSupportedHardwareWatchpoints() override; + + uint32_t SetHardwareWatchpoint(lldb::addr_t addr, size_t size, + uint32_t watch_flags) override; + + bool ClearHardwareWatchpoint(uint32_t hw_index) override; + + Status GetWatchpointHitIndex(uint32_t &wp_index, + lldb::addr_t trap_addr) override; + + lldb::addr_t GetWatchpointHitAddress(uint32_t wp_index) override; + + lldb::addr_t GetWatchpointAddress(uint32_t wp_index) override; + + uint32_t GetWatchpointSize(uint32_t wp_index); + + bool WatchpointIsEnabled(uint32_t wp_index); + +protected: + bool IsVMX(unsigned reg); + + bool IsVSX(unsigned reg); + + Status ReadVMX(); + + Status WriteVMX(); + + Status ReadVSX(); + + Status WriteVSX(); + + void *GetGPRBuffer() override { return &m_gpr_ppc64le; } + + void *GetFPRBuffer() override { return &m_fpr_ppc64le; } + + size_t GetFPRSize() override { return sizeof(m_fpr_ppc64le); } + +private: + GPR m_gpr_ppc64le; // 64-bit general purpose registers. + FPR m_fpr_ppc64le; // floating-point registers including extended register. + VMX m_vmx_ppc64le; // VMX registers. + VSX m_vsx_ppc64le; // Last lower bytes from first VSX registers. + + bool IsGPR(unsigned reg) const; + + bool IsFPR(unsigned reg) const; + + bool IsVMX(unsigned reg) const; + + bool IsVSX(unsigned reg) const; + + uint32_t CalculateFprOffset(const RegisterInfo *reg_info) const; + + uint32_t CalculateVmxOffset(const RegisterInfo *reg_info) const; + + uint32_t CalculateVsxOffset(const RegisterInfo *reg_info) const; + + Status ReadHardwareDebugInfo(); + + Status WriteHardwareDebugRegs(); + + // Debug register info for hardware watchpoints management. + struct DREG { + lldb::addr_t address; // Breakpoint/watchpoint address value. + lldb::addr_t hit_addr; // Address at which last watchpoint trigger + // exception occurred. + lldb::addr_t real_addr; // Address value that should cause target to stop. + uint32_t control; // Breakpoint/watchpoint control value. + uint32_t refcount; // Serves as enable/disable and reference counter. + long slot; // Saves the value returned from PTRACE_SETHWDEBUG. + int mode; // Defines if watchpoint is read/write/access. + }; + + std::array m_hwp_regs; + + // 16 is just a maximum value, query hardware for actual watchpoint count + uint32_t m_max_hwp_supported = 16; + uint32_t m_max_hbp_supported = 16; + bool m_refresh_hwdebug_info = true; +}; + +} // namespace process_aix +} // namespace lldb_private + +#endif // #ifndef lldb_NativeRegisterContextAIX_ppc64_h + +#endif // defined(__powerpc64__) diff --git a/lldb/source/Plugins/Process/AIX/NativeThreadAIX.cpp b/lldb/source/Plugins/Process/AIX/NativeThreadAIX.cpp new file mode 100644 index 000000000000000..e07daccdff550e1 --- /dev/null +++ b/lldb/source/Plugins/Process/AIX/NativeThreadAIX.cpp @@ -0,0 +1,526 @@ +//===-- NativeThreadAIX.cpp ---------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "NativeThreadAIX.h" + +#include +#include + +#include "NativeProcessAIX.h" +#include "NativeRegisterContextAIX.h" + +#include "lldb/Host/HostNativeThread.h" +#include "lldb/Utility/LLDBAssert.h" +#include "lldb/Utility/LLDBLog.h" +#include "lldb/Utility/Log.h" +#include "lldb/Utility/State.h" +#include "lldb/lldb-enumerations.h" + +#include "llvm/ADT/SmallString.h" + +#include "Plugins/Process/POSIX/CrashReason.h" + +#include +#include +#include + +#if 0 +#include +// Try to define a macro to encapsulate the tgkill syscall +#define tgkill(pid, tid, sig) \ + syscall(__NR_tgkill, static_cast<::pid_t>(pid), static_cast<::pid_t>(tid), \ + sig) +#endif + +using namespace lldb; +using namespace lldb_private; +using namespace lldb_private::process_aix; + +namespace { +void LogThreadStopInfo(Log &log, const ThreadStopInfo &stop_info, + const char *const header) { + switch (stop_info.reason) { + case eStopReasonNone: + log.Printf("%s: %s no stop reason", __FUNCTION__, header); + return; + case eStopReasonTrace: + log.Printf("%s: %s trace, stopping signal 0x%" PRIx32, __FUNCTION__, header, + stop_info.signo); + return; + case eStopReasonBreakpoint: + log.Printf("%s: %s breakpoint, stopping signal 0x%" PRIx32, __FUNCTION__, + header, stop_info.signo); + return; + case eStopReasonWatchpoint: + log.Printf("%s: %s watchpoint, stopping signal 0x%" PRIx32, __FUNCTION__, + header, stop_info.signo); + return; + case eStopReasonSignal: + log.Printf("%s: %s signal 0x%02" PRIx32, __FUNCTION__, header, + stop_info.signo); + return; + case eStopReasonException: + log.Printf("%s: %s exception type 0x%02" PRIx64, __FUNCTION__, header, + stop_info.details.exception.type); + return; + case eStopReasonExec: + log.Printf("%s: %s exec, stopping signal 0x%" PRIx32, __FUNCTION__, header, + stop_info.signo); + return; + case eStopReasonPlanComplete: + log.Printf("%s: %s plan complete", __FUNCTION__, header); + return; + case eStopReasonThreadExiting: + log.Printf("%s: %s thread exiting", __FUNCTION__, header); + return; + case eStopReasonInstrumentation: + log.Printf("%s: %s instrumentation", __FUNCTION__, header); + return; + case eStopReasonProcessorTrace: + log.Printf("%s: %s processor trace", __FUNCTION__, header); + return; + default: + log.Printf("%s: %s invalid stop reason %" PRIu32, __FUNCTION__, header, + static_cast(stop_info.reason)); + } +} +} + +NativeThreadAIX::NativeThreadAIX(NativeProcessAIX &process, + lldb::tid_t tid) + : NativeThreadProtocol(process, tid), m_state(StateType::eStateInvalid), + m_stop_info(), + m_reg_context_up( + NativeRegisterContextAIX::CreateHostNativeRegisterContextAIX( + process.GetArchitecture(), *this)), + m_stop_description() {} + +std::string NativeThreadAIX::GetName() { + NativeProcessAIX &process = GetProcess(); + + auto BufferOrError = getProcFile(process.GetID(), GetID(), "comm"); + if (!BufferOrError) + return ""; + return std::string(BufferOrError.get()->getBuffer().rtrim('\n')); +} + +lldb::StateType NativeThreadAIX::GetState() { return m_state; } + +bool NativeThreadAIX::GetStopReason(ThreadStopInfo &stop_info, + std::string &description) { + Log *log = GetLog(LLDBLog::Thread); + + description.clear(); + + switch (m_state) { + case eStateStopped: + case eStateCrashed: + case eStateExited: + case eStateSuspended: + case eStateUnloaded: + if (log) + LogThreadStopInfo(*log, m_stop_info, "m_stop_info in thread:"); + stop_info = m_stop_info; + description = m_stop_description; + if (log) + LogThreadStopInfo(*log, stop_info, "returned stop_info:"); + + return true; + + case eStateInvalid: + case eStateConnected: + case eStateAttaching: + case eStateLaunching: + case eStateRunning: + case eStateStepping: + case eStateDetached: + if (log) { + LLDB_LOGF(log, + "NativeThreadAIX::%s tid %" PRIu64 + " in state %s cannot answer stop reason", + __FUNCTION__, GetID(), StateAsCString(m_state)); + } + return false; + } + llvm_unreachable("unhandled StateType!"); +} + +Status NativeThreadAIX::SetWatchpoint(lldb::addr_t addr, size_t size, + uint32_t watch_flags, bool hardware) { + if (!hardware) + return Status("not implemented"); + if (m_state == eStateLaunching) + return Status(); + Status error = RemoveWatchpoint(addr); + if (error.Fail()) + return error; + uint32_t wp_index = + m_reg_context_up->SetHardwareWatchpoint(addr, size, watch_flags); + if (wp_index == LLDB_INVALID_INDEX32) + return Status("Setting hardware watchpoint failed."); + m_watchpoint_index_map.insert({addr, wp_index}); + return Status(); +} + +Status NativeThreadAIX::RemoveWatchpoint(lldb::addr_t addr) { + auto wp = m_watchpoint_index_map.find(addr); + if (wp == m_watchpoint_index_map.end()) + return Status(); + uint32_t wp_index = wp->second; + m_watchpoint_index_map.erase(wp); + if (m_reg_context_up->ClearHardwareWatchpoint(wp_index)) + return Status(); + return Status("Clearing hardware watchpoint failed."); +} + +Status NativeThreadAIX::SetHardwareBreakpoint(lldb::addr_t addr, + size_t size) { + if (m_state == eStateLaunching) + return Status(); + + Status error = RemoveHardwareBreakpoint(addr); + if (error.Fail()) + return error; + + uint32_t bp_index = m_reg_context_up->SetHardwareBreakpoint(addr, size); + + if (bp_index == LLDB_INVALID_INDEX32) + return Status("Setting hardware breakpoint failed."); + + m_hw_break_index_map.insert({addr, bp_index}); + return Status(); +} + +Status NativeThreadAIX::RemoveHardwareBreakpoint(lldb::addr_t addr) { + auto bp = m_hw_break_index_map.find(addr); + if (bp == m_hw_break_index_map.end()) + return Status(); + + uint32_t bp_index = bp->second; + if (m_reg_context_up->ClearHardwareBreakpoint(bp_index)) { + m_hw_break_index_map.erase(bp); + return Status(); + } + + return Status("Clearing hardware breakpoint failed."); +} + +Status NativeThreadAIX::Resume(uint32_t signo) { + const StateType new_state = StateType::eStateRunning; + MaybeLogStateChange(new_state); + m_state = new_state; + + m_stop_info.reason = StopReason::eStopReasonNone; + m_stop_description.clear(); + + // If watchpoints have been set, but none on this thread, then this is a new + // thread. So set all existing watchpoints. + if (m_watchpoint_index_map.empty()) { + NativeProcessAIX &process = GetProcess(); + + const auto &watchpoint_map = process.GetWatchpointMap(); + m_reg_context_up->ClearAllHardwareWatchpoints(); + for (const auto &pair : watchpoint_map) { + const auto &wp = pair.second; + SetWatchpoint(wp.m_addr, wp.m_size, wp.m_watch_flags, wp.m_hardware); + } + } + + // Set all active hardware breakpoint on all threads. + if (m_hw_break_index_map.empty()) { + NativeProcessAIX &process = GetProcess(); + + const auto &hw_breakpoint_map = process.GetHardwareBreakpointMap(); + m_reg_context_up->ClearAllHardwareBreakpoints(); + for (const auto &pair : hw_breakpoint_map) { + const auto &bp = pair.second; + SetHardwareBreakpoint(bp.m_addr, bp.m_size); + } + } + + intptr_t data = 0; + + if (signo != LLDB_INVALID_SIGNAL_NUMBER) + data = signo; + + return NativeProcessAIX::PtraceWrapper(PT_CONTINUE, GetID(), nullptr, + reinterpret_cast(data)); +} + +Status NativeThreadAIX::SingleStep(uint32_t signo) { + const StateType new_state = StateType::eStateStepping; + MaybeLogStateChange(new_state); + m_state = new_state; + m_stop_info.reason = StopReason::eStopReasonNone; + + intptr_t data = 0; + if (signo != LLDB_INVALID_SIGNAL_NUMBER) + data = signo; + + // If hardware single-stepping is not supported, we just do a continue. The + // breakpoint on the next instruction has been setup in + // NativeProcessAIX::Resume. + return NativeProcessAIX::PtraceWrapper( + GetProcess().SupportHardwareSingleStepping() ? PT_STEP : PT_CONTINUE, + m_tid, nullptr, reinterpret_cast(data)); +} + +void NativeThreadAIX::SetStoppedBySignal(uint32_t signo, + const siginfo_t *info) { + Log *log = GetLog(LLDBLog::Thread); + LLDB_LOGF(log, "NativeThreadAIX::%s called with signal 0x%02" PRIx32, + __FUNCTION__, signo); + + SetStopped(); + + m_stop_info.reason = StopReason::eStopReasonSignal; + m_stop_info.signo = signo; + + m_stop_description.clear(); + switch (signo) { + case SIGSEGV: + case SIGBUS: + case SIGFPE: + case SIGILL: + break; + } +} + +void NativeThreadAIX::AnnotateSyncTagCheckFault(const siginfo_t *info) { + int32_t allocation_tag_type = 0; + switch (GetProcess().GetArchitecture().GetMachine()) { + default: + return; + } + + auto details = + GetRegisterContext().GetMemoryTaggingDetails(allocation_tag_type); + if (!details) { + llvm::consumeError(details.takeError()); + return; + } + + // We assume that the stop description is currently: + // signal SIGSEGV: sync tag check fault (fault address: ) + // Remove the closing ) + m_stop_description.pop_back(); + + std::stringstream ss; + lldb::addr_t fault_addr = reinterpret_cast(info->si_addr); + std::unique_ptr manager(std::move(details->manager)); + + ss << " logical tag: 0x" << std::hex << manager->GetLogicalTag(fault_addr); + + std::vector allocation_tag_data; + // The fault address may not be granule aligned. ReadMemoryTags will granule + // align any range you give it, potentially making it larger. + // To prevent this set len to 1. This always results in a range that is at + // most 1 granule in size and includes fault_addr. + Status status = GetProcess().ReadMemoryTags(allocation_tag_type, fault_addr, + 1, allocation_tag_data); + + if (status.Success()) { + llvm::Expected> allocation_tag = + manager->UnpackTagsData(allocation_tag_data, 1); + if (allocation_tag) { + ss << " allocation tag: 0x" << std::hex << allocation_tag->front() << ")"; + } else { + llvm::consumeError(allocation_tag.takeError()); + ss << ")"; + } + } else + ss << ")"; + + m_stop_description += ss.str(); +} + +bool NativeThreadAIX::IsStopped(int *signo) { + if (!StateIsStoppedState(m_state, false)) + return false; + + // If we are stopped by a signal, return the signo. + if (signo && m_state == StateType::eStateStopped && + m_stop_info.reason == StopReason::eStopReasonSignal) { + *signo = m_stop_info.signo; + } + + // Regardless, we are stopped. + return true; +} + +void NativeThreadAIX::SetStopped() { + // On every stop, clear any cached register data structures + GetRegisterContext().InvalidateAllRegisters(); + + const StateType new_state = StateType::eStateStopped; + MaybeLogStateChange(new_state); + m_state = new_state; + m_stop_description.clear(); +} + +void NativeThreadAIX::SetStoppedByExec() { + Log *log = GetLog(LLDBLog::Thread); + LLDB_LOGF(log, "NativeThreadAIX::%s()", __FUNCTION__); + + SetStopped(); + + m_stop_info.reason = StopReason::eStopReasonExec; + m_stop_info.signo = SIGSTOP; +} + +void NativeThreadAIX::SetStoppedByBreakpoint() { + SetStopped(); + + m_stop_info.reason = StopReason::eStopReasonBreakpoint; + m_stop_info.signo = SIGTRAP; + m_stop_description.clear(); +} + +void NativeThreadAIX::SetStoppedByWatchpoint(uint32_t wp_index) { + SetStopped(); + + lldbassert(wp_index != LLDB_INVALID_INDEX32 && "wp_index cannot be invalid"); + + std::ostringstream ostr; + ostr << m_reg_context_up->GetWatchpointAddress(wp_index) << " "; + ostr << wp_index; + + /* + * MIPS: Last 3bits of the watchpoint address are masked by the kernel. For + * example: + * 'n' is at 0x120010d00 and 'm' is 0x120010d04. When a watchpoint is set at + * 'm', then + * watch exception is generated even when 'n' is read/written. To handle this + * case, + * find the base address of the load/store instruction and append it in the + * stop-info + * packet. + */ + ostr << " " << m_reg_context_up->GetWatchpointHitAddress(wp_index); + + m_stop_description = ostr.str(); + + m_stop_info.reason = StopReason::eStopReasonWatchpoint; + m_stop_info.signo = SIGTRAP; +} + +bool NativeThreadAIX::IsStoppedAtBreakpoint() { + return GetState() == StateType::eStateStopped && + m_stop_info.reason == StopReason::eStopReasonBreakpoint; +} + +bool NativeThreadAIX::IsStoppedAtWatchpoint() { + return GetState() == StateType::eStateStopped && + m_stop_info.reason == StopReason::eStopReasonWatchpoint; +} + +void NativeThreadAIX::SetStoppedByTrace() { + SetStopped(); + + m_stop_info.reason = StopReason::eStopReasonTrace; + m_stop_info.signo = SIGTRAP; +} + +void NativeThreadAIX::SetStoppedByFork(bool is_vfork, lldb::pid_t child_pid) { + SetStopped(); + + m_stop_info.reason = + is_vfork ? StopReason::eStopReasonVFork : StopReason::eStopReasonFork; + m_stop_info.details.fork.child_pid = child_pid; + m_stop_info.details.fork.child_tid = child_pid; +} + +void NativeThreadAIX::SetStoppedByVForkDone() { + SetStopped(); + + m_stop_info.reason = StopReason::eStopReasonVForkDone; +} + +void NativeThreadAIX::SetStoppedWithNoReason() { + SetStopped(); + + m_stop_info.reason = StopReason::eStopReasonNone; + m_stop_info.signo = 0; +} + +void NativeThreadAIX::SetStoppedByProcessorTrace( + llvm::StringRef description) { + SetStopped(); + + m_stop_info.reason = StopReason::eStopReasonProcessorTrace; + m_stop_info.signo = 0; + m_stop_description = description.str(); +} + +void NativeThreadAIX::SetExited() { + const StateType new_state = StateType::eStateExited; + MaybeLogStateChange(new_state); + m_state = new_state; + + m_stop_info.reason = StopReason::eStopReasonThreadExiting; +} + +Status NativeThreadAIX::RequestStop() { + Log *log = GetLog(LLDBLog::Thread); + + NativeProcessAIX &process = GetProcess(); + + lldb::pid_t pid = process.GetID(); + lldb::tid_t tid = GetID(); + + LLDB_LOGF(log, + "NativeThreadAIX::%s requesting thread stop(pid: %" PRIu64 + ", tid: %" PRIu64 ")", + __FUNCTION__, pid, tid); + + Status err; + errno = 0; + if (::kill(pid, SIGSTOP) != 0) { + err.SetErrorToErrno(); + LLDB_LOGF(log, + "NativeThreadAIX::%s kill(%" PRIu64 ", SIGSTOP) failed: %s", + __FUNCTION__, pid, err.AsCString()); + } + return err; +} + +void NativeThreadAIX::MaybeLogStateChange(lldb::StateType new_state) { + Log *log = GetLog(LLDBLog::Thread); + // If we're not logging, we're done. + if (!log) + return; + + // If this is a state change to the same state, we're done. + lldb::StateType old_state = m_state; + if (new_state == old_state) + return; + + LLDB_LOG(log, "pid={0}, tid={1}: changing from state {2} to {3}", + m_process.GetID(), GetID(), old_state, new_state); +} + +NativeProcessAIX &NativeThreadAIX::GetProcess() { + return static_cast(m_process); +} + +const NativeProcessAIX &NativeThreadAIX::GetProcess() const { + return static_cast(m_process); +} + +llvm::Expected> +NativeThreadAIX::GetSiginfo() const { + auto siginfo_buf = + llvm::WritableMemoryBuffer::getNewUninitMemBuffer(sizeof(siginfo_t)); +#if 0 + Status error = + GetProcess().GetSignalInfo(GetID(), siginfo_buf->getBufferStart()); + if (!error.Success()) + return error.ToError(); +#endif + return std::move(siginfo_buf); +} diff --git a/lldb/source/Plugins/Process/AIX/NativeThreadAIX.h b/lldb/source/Plugins/Process/AIX/NativeThreadAIX.h new file mode 100644 index 000000000000000..706a7ce69da8eb6 --- /dev/null +++ b/lldb/source/Plugins/Process/AIX/NativeThreadAIX.h @@ -0,0 +1,126 @@ +//===-- NativeThreadAIX.h ----------------------------------- -*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_NativeThreadAIX_H_ +#define liblldb_NativeThreadAIX_H_ + +#include "Plugins/Process/AIX/NativeRegisterContextAIX.h" +#include "lldb/Host/common/NativeThreadProtocol.h" +#include "lldb/lldb-private-forward.h" + +#include "llvm/ADT/StringRef.h" + +#include +#include +#include +#include + +namespace lldb_private { +namespace process_aix { + +class NativeProcessAIX; + +class NativeThreadAIX : public NativeThreadProtocol { + friend class NativeProcessAIX; + +public: + NativeThreadAIX(NativeProcessAIX &process, lldb::tid_t tid); + + // NativeThreadProtocol Interface + std::string GetName() override; + + lldb::StateType GetState() override; + + bool GetStopReason(ThreadStopInfo &stop_info, + std::string &description) override; + + NativeRegisterContextAIX &GetRegisterContext() override { + return *m_reg_context_up; + } + + Status SetWatchpoint(lldb::addr_t addr, size_t size, uint32_t watch_flags, + bool hardware) override; + + Status RemoveWatchpoint(lldb::addr_t addr) override; + + Status SetHardwareBreakpoint(lldb::addr_t addr, size_t size) override; + + Status RemoveHardwareBreakpoint(lldb::addr_t addr) override; + + NativeProcessAIX &GetProcess(); + + const NativeProcessAIX &GetProcess() const; + + llvm::Expected> + GetSiginfo() const override; + +private: + // Interface for friend classes + + /// Resumes the thread. If \p signo is anything but + /// LLDB_INVALID_SIGNAL_NUMBER, deliver that signal to the thread. + Status Resume(uint32_t signo); + + /// Single steps the thread. If \p signo is anything but + /// LLDB_INVALID_SIGNAL_NUMBER, deliver that signal to the thread. + Status SingleStep(uint32_t signo); + + void SetStoppedBySignal(uint32_t signo, const siginfo_t *info = nullptr); + + /// Return true if the thread is stopped. + /// If stopped by a signal, indicate the signo in the signo argument. + /// Otherwise, return LLDB_INVALID_SIGNAL_NUMBER. + bool IsStopped(int *signo); + + void SetStoppedByExec(); + + void SetStoppedByBreakpoint(); + + void SetStoppedByWatchpoint(uint32_t wp_index); + + bool IsStoppedAtBreakpoint(); + + bool IsStoppedAtWatchpoint(); + + void SetStoppedByTrace(); + + void SetStoppedByFork(bool is_vfork, lldb::pid_t child_pid); + + void SetStoppedByVForkDone(); + + void SetStoppedWithNoReason(); + + void SetStoppedByProcessorTrace(llvm::StringRef description); + + void SetExited(); + + Status RequestStop(); + + // Private interface + void MaybeLogStateChange(lldb::StateType new_state); + + void SetStopped(); + + /// Extend m_stop_description with logical and allocation tag values. + /// If there is an error along the way just add the information we were able + /// to get. + void AnnotateSyncTagCheckFault(const siginfo_t *info); + + // Member Variables + lldb::StateType m_state; + ThreadStopInfo m_stop_info; + std::unique_ptr m_reg_context_up; + std::string m_stop_description; + using WatchpointIndexMap = std::map; + WatchpointIndexMap m_watchpoint_index_map; + WatchpointIndexMap m_hw_break_index_map; +}; +} // namespace process_aix +} // namespace lldb_private + +#endif // #ifndef liblldb_NativeThreadAIX_H_ diff --git a/lldb/source/Plugins/Process/CMakeLists.txt b/lldb/source/Plugins/Process/CMakeLists.txt index a51d0f7afd17591..01bb5f462eba44c 100644 --- a/lldb/source/Plugins/Process/CMakeLists.txt +++ b/lldb/source/Plugins/Process/CMakeLists.txt @@ -7,6 +7,9 @@ elseif (CMAKE_SYSTEM_NAME MATCHES "FreeBSD") elseif (CMAKE_SYSTEM_NAME MATCHES "NetBSD") add_subdirectory(NetBSD) add_subdirectory(POSIX) +elseif (CMAKE_SYSTEM_NAME MATCHES "AIX") + add_subdirectory(AIX) + add_subdirectory(POSIX) elseif (CMAKE_SYSTEM_NAME MATCHES "Windows") add_subdirectory(Windows/Common) elseif (CMAKE_SYSTEM_NAME MATCHES "Darwin") diff --git a/lldb/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp b/lldb/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp index 32c71d87c7f58ca..db271357d792ae7 100644 --- a/lldb/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp +++ b/lldb/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp @@ -46,8 +46,34 @@ bool lldb_private::InferiorCallMmap(Process *process, addr_t &allocated_addr, function_options.include_inlines = false; SymbolContextList sc_list; +#if !defined(__AIX__) process->GetTarget().GetImages().FindFunctions( ConstString("mmap"), eFunctionNameTypeFull, function_options, sc_list); +#else + process->GetTarget().GetImages().FindFunctions( + ConstString("mmap64"), eFunctionNameTypeFull, function_options, sc_list); + SymbolContextList toc_list; + process->GetTarget().GetImages().FindSymbolsWithNameAndType( + ConstString("TOC"), lldb::eSymbolTypeAny, toc_list); + + AddressRange toc_range; + if (sc_list.GetSize() > 0) { + SymbolContext sc; + if (sc_list.GetContextAtIndex(0, sc)) { + for (int i = 0; i < toc_list.GetSize(); ++i) { + SymbolContext tocSC; + if (toc_list.GetContextAtIndex(i, tocSC)) { + if (tocSC.module_sp == sc.module_sp) { + if (tocSC.GetAddressRange(eSymbolContextSymbol, 0, false, + toc_range)) { + break; + } + } + } + } + } + } +#endif const uint32_t count = sc_list.GetSize(); if (count > 0) { SymbolContext sc; @@ -96,9 +122,16 @@ bool lldb_private::InferiorCallMmap(Process *process, addr_t &allocated_addr, MmapArgList args = process->GetTarget().GetPlatform()->GetMmapArgumentList( arch, addr, length, prot_arg, flags, fd, offset); +#if defined(__AIX__) + lldb::ThreadPlanSP call_plan_sp( + new ThreadPlanCallFunction(*thread, mmap_range.GetBaseAddress(), + toc_range.GetBaseAddress(), + void_ptr_type, args, options)); +#else lldb::ThreadPlanSP call_plan_sp( new ThreadPlanCallFunction(*thread, mmap_range.GetBaseAddress(), void_ptr_type, args, options)); +#endif if (call_plan_sp) { DiagnosticManager diagnostics; diff --git a/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_ppc64le.cpp b/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_ppc64le.cpp index 159fd2856443cca..d9b41d595147f39 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_ppc64le.cpp +++ b/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_ppc64le.cpp @@ -23,6 +23,8 @@ static const lldb_private::RegisterInfo * GetRegisterInfoPtr(const lldb_private::ArchSpec &target_arch) { switch (target_arch.GetMachine()) { + //HH + case llvm::Triple::ppc64: case llvm::Triple::ppc64le: return g_register_infos_ppc64le; default: @@ -34,6 +36,8 @@ GetRegisterInfoPtr(const lldb_private::ArchSpec &target_arch) { static uint32_t GetRegisterInfoCount(const lldb_private::ArchSpec &target_arch) { switch (target_arch.GetMachine()) { + //HitchHike + case llvm::Triple::ppc64: case llvm::Triple::ppc64le: return static_cast(sizeof(g_register_infos_ppc64le) / sizeof(g_register_infos_ppc64le[0])); diff --git a/lldb/source/Plugins/Process/Utility/ThreadMemory.cpp b/lldb/source/Plugins/Process/Utility/ThreadMemory.cpp index 89ecc757a68f56f..550b53688fd39e2 100644 --- a/lldb/source/Plugins/Process/Utility/ThreadMemory.cpp +++ b/lldb/source/Plugins/Process/Utility/ThreadMemory.cpp @@ -20,7 +20,7 @@ using namespace lldb; using namespace lldb_private; -ThreadMemory::ThreadMemory(Process &process, tid_t tid, +ThreadMemory::ThreadMemory(Process &process, lldb::tid_t tid, const ValueObjectSP &thread_info_valobj_sp) : Thread(process, tid), m_backing_thread_sp(), m_thread_info_valobj_sp(thread_info_valobj_sp), m_name(), m_queue(), diff --git a/lldb/source/Plugins/Process/gdb-remote/CMakeLists.txt b/lldb/source/Plugins/Process/gdb-remote/CMakeLists.txt index 6755999b18185ec..4eddbb5ec4cfdc6 100644 --- a/lldb/source/Plugins/Process/gdb-remote/CMakeLists.txt +++ b/lldb/source/Plugins/Process/gdb-remote/CMakeLists.txt @@ -6,6 +6,11 @@ lldb_tablegen(ProcessGDBRemotePropertiesEnum.inc -gen-lldb-property-enum-defs SOURCE ProcessGDBRemoteProperties.td TARGET LLDBPluginProcessGDBRemotePropertiesEnumGen) +if (UNIX AND ${CMAKE_SYSTEM_NAME} MATCHES "AIX") + remove_definitions("-D_XOPEN_SOURCE=700") + add_definitions("-D_ALL_SOURCE") +endif() + set(LLDB_PLUGINS lldbPluginProcessUtility ) diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp index 74e392249a94eb8..b7ecf7a5dc32877 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp @@ -40,6 +40,10 @@ #include "llvm/ADT/StringSwitch.h" #include "llvm/Support/JSON.h" +#if defined(__AIX__) +#include +#endif + #if defined(HAVE_LIBCOMPRESSION) #include #endif @@ -1710,6 +1714,32 @@ Status GDBRemoteCommunicationClient::GetMemoryRegionInfo( return error; } +#if defined(__AIX__) +Status GDBRemoteCommunicationClient::GetLDXINFO(struct ld_xinfo *info_ptr) +{ + Status error; + + char packet[64]; + const int packet_len = ::snprintf(packet, sizeof(packet), "qLDXINFO"); + assert(packet_len < (int)sizeof(packet)); + UNUSED_IF_ASSERT_DISABLED(packet_len); + StringExtractorGDBRemote response; + if (SendPacketAndWaitForResponse(packet, response) == + PacketResult::Success && + response.GetResponseType() == StringExtractorGDBRemote::eResponse) { + llvm::MutableArrayRef infoData((uint8_t *)info_ptr, sizeof(struct ld_xinfo)*64); + size_t got_bytes = response.GetHexBytesAvail(infoData); + if (got_bytes != sizeof(struct ld_xinfo)*64) { + error.SetErrorString("qLDXINFO ret bad size"); + return error; + } + } else { + error.SetErrorString("qLDXINFO is not supported"); + } + return error; +} +#endif + Status GDBRemoteCommunicationClient::GetQXferMemoryMapRegionInfo( lldb::addr_t addr, MemoryRegionInfo ®ion) { Status error = LoadQXferMemoryMap(); diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h index 898d176abc3465a..520f37ac5671648 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h @@ -32,6 +32,10 @@ #include "llvm/Support/VersionTuple.h" +#if defined(__AIX__) +struct ld_xinfo; +#endif + namespace lldb_private { namespace process_gdb_remote { @@ -196,6 +200,9 @@ class GDBRemoteCommunicationClient : public GDBRemoteClientBase { Status GetMemoryRegionInfo(lldb::addr_t addr, MemoryRegionInfo &range_info); std::optional GetWatchpointSlotCount(); +#if defined(__AIX__) + Status GetLDXINFO(struct ld_xinfo *info_ptr); +#endif std::optional GetWatchpointReportedAfter(); diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp index a0b08a219ae147e..f019062986925e1 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp @@ -48,6 +48,9 @@ #include "ProcessGDBRemote.h" #include "ProcessGDBRemoteLog.h" #include "lldb/Utility/StringExtractorGDBRemote.h" +#if defined(__AIX__) +#include +#endif using namespace lldb; using namespace lldb_private; @@ -193,6 +196,8 @@ void GDBRemoteCommunicationServerLLGS::RegisterPacketHandlers() { &GDBRemoteCommunicationServerLLGS::Handle_Z); RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_z, &GDBRemoteCommunicationServerLLGS::Handle_z); + RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qLDXINFO, + &GDBRemoteCommunicationServerLLGS::Handle_qLDXINFO); RegisterMemberFunctionHandler( StringExtractorGDBRemote::eServerPacketType_QPassSignals, &GDBRemoteCommunicationServerLLGS::Handle_QPassSignals); @@ -3006,6 +3011,29 @@ GDBRemoteCommunicationServerLLGS::Handle_z(StringExtractorGDBRemote &packet) { } } +GDBRemoteCommunication::PacketResult +GDBRemoteCommunicationServerLLGS::Handle_qLDXINFO(StringExtractorGDBRemote &packet) { + if (!m_current_process || + (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) { + Log *log = GetLog(LLDBLog::Process); + LLDB_LOG(log, "qLDXINFO failed, no process available"); + return SendErrorResponse(0xff); + } + +#if defined(__AIX__) + // FIXME: buffer size + struct ld_xinfo info[64]; + if (ptrace64(PT_LDXINFO, m_current_process->GetID(), (long long)&(info[0]), sizeof(info), nullptr) != 0) { + return SendErrorResponse(0xff); + } + StreamGDBRemote response; + response.PutBytesAsRawHex8(&(info[0]), sizeof(info)); + return SendPacketNoLock(response.GetString()); +#else + return SendErrorResponse(0xff); +#endif +} + GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerLLGS::Handle_s(StringExtractorGDBRemote &packet) { Log *log = GetLog(LLDBLog::Process | LLDBLog::Thread); diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h index 646b6a102abf62a..a464479e178de1d 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h @@ -211,6 +211,8 @@ class GDBRemoteCommunicationServerLLGS PacketResult Handle_z(StringExtractorGDBRemote &packet); + PacketResult Handle_qLDXINFO(StringExtractorGDBRemote &packet); + PacketResult Handle_s(StringExtractorGDBRemote &packet); PacketResult Handle_qXfer(StringExtractorGDBRemote &packet); diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp index 6f9c2cc1e4b4e84..10fbaa2b3c8372a 100644 --- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp @@ -92,6 +92,10 @@ #include "llvm/Support/Threading.h" #include "llvm/Support/raw_ostream.h" +#if defined(__AIX__) +#include +#endif + #define DEBUGSERVER_BASENAME "debugserver" using namespace lldb; using namespace lldb_private; @@ -1513,7 +1517,7 @@ bool ProcessGDBRemote::DoUpdateThreadList(ThreadList &old_thread_list, ThreadList old_thread_list_copy(old_thread_list); if (num_thread_ids > 0) { for (size_t i = 0; i < num_thread_ids; ++i) { - tid_t tid = m_thread_ids[i]; + lldb::tid_t tid = m_thread_ids[i]; ThreadSP thread_sp( old_thread_list_copy.RemoveThreadByProtocolID(tid, false)); if (!thread_sp) { @@ -2945,6 +2949,13 @@ Status ProcessGDBRemote::DoGetMemoryRegionInfo(addr_t load_addr, return error; } +#if defined(__AIX__) +Status ProcessGDBRemote::DoGetLDXINFO(struct ld_xinfo *info_ptr) { + Status error(m_gdb_comm.GetLDXINFO(info_ptr)); + return error; +} +#endif + std::optional ProcessGDBRemote::GetWatchpointSlotCount() { return m_gdb_comm.GetWatchpointSlotCount(); } diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h index 2492795851388a3..82200fbea21cd41 100644 --- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h +++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h @@ -37,6 +37,10 @@ #include "GDBRemoteCommunicationClient.h" #include "GDBRemoteRegisterContext.h" +#if defined(__AIX__) +struct ld_xinfo; +#endif + #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/StringMap.h" @@ -423,6 +427,10 @@ class ProcessGDBRemote : public Process, Status DoGetMemoryRegionInfo(lldb::addr_t load_addr, MemoryRegionInfo ®ion_info) override; +#if defined(__AIX__) + Status DoGetLDXINFO(struct ld_xinfo *info_ptr) override; +#endif + private: // For ProcessGDBRemote only std::string m_partial_profile_data; diff --git a/lldb/source/Plugins/Process/mach-core/ProcessMachCore.cpp b/lldb/source/Plugins/Process/mach-core/ProcessMachCore.cpp index 1da7696c9a352ab..930c707604bb384 100644 --- a/lldb/source/Plugins/Process/mach-core/ProcessMachCore.cpp +++ b/lldb/source/Plugins/Process/mach-core/ProcessMachCore.cpp @@ -593,19 +593,19 @@ bool ProcessMachCore::DoUpdateThreadList(ThreadList &old_thread_list, ObjectFile *core_objfile = m_core_module_sp->GetObjectFile(); if (core_objfile) { - std::set used_tids; + std::set used_tids; const uint32_t num_threads = core_objfile->GetNumThreadContexts(); - std::vector tids; + std::vector tids; if (core_objfile->GetCorefileThreadExtraInfos(tids)) { assert(tids.size() == num_threads); // Find highest tid value. - tid_t highest_tid = 0; + lldb::tid_t highest_tid = 0; for (uint32_t i = 0; i < num_threads; i++) { if (tids[i] != LLDB_INVALID_THREAD_ID && tids[i] > highest_tid) highest_tid = tids[i]; } - tid_t current_unused_tid = highest_tid + 1; + lldb::tid_t current_unused_tid = highest_tid + 1; for (uint32_t i = 0; i < num_threads; i++) { if (tids[i] == LLDB_INVALID_THREAD_ID) { tids[i] = current_unused_tid++; diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/CMakeLists.txt b/lldb/source/Plugins/ScriptInterpreter/Python/CMakeLists.txt index 7523d65abf0f802..1ce60a0b6615462 100644 --- a/lldb/source/Plugins/ScriptInterpreter/Python/CMakeLists.txt +++ b/lldb/source/Plugins/ScriptInterpreter/Python/CMakeLists.txt @@ -20,6 +20,11 @@ if (LLDB_ENABLE_LIBEDIT) endif() add_subdirectory(Interfaces) +if (UNIX AND ${CMAKE_SYSTEM_NAME} MATCHES "AIX") + remove_definitions("-D_XOPEN_SOURCE=700") + add_definitions("-D_ALL_SOURCE") +endif() + add_lldb_library(lldbPluginScriptInterpreterPython PLUGIN PythonDataObjects.cpp diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp index e1f73f1997e3692..92882cfc3da3108 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp @@ -500,6 +500,8 @@ dw_addr_t DWARFFormValue::Address() const { &offset, index_size); } +bool UGLY_FLAG_FOR_AIX __attribute__((weak)) = false; + std::pair DWARFFormValue::ReferencedUnitAndOffset() const { uint64_t value = m_value.value.uval; @@ -512,6 +514,8 @@ DWARFFormValue::ReferencedUnitAndOffset() const { assert(m_unit); // Unit must be valid for DW_FORM_ref forms that are compile // unit relative or we will get this wrong value += m_unit->GetOffset(); + if (UGLY_FLAG_FOR_AIX) + value -= 8; if (!m_unit->ContainsDIEOffset(value)) { m_unit->GetSymbolFileDWARF().GetObjectFile()->GetModule()->ReportError( "DW_FORM_ref* DIE reference {0:x16} is outside of its CU", value); diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp index 66a762bf9b68542..6721c1895a576ec 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp @@ -924,6 +924,12 @@ const DWARFDebugAranges &DWARFUnit::GetFunctionAranges() { return *m_func_aranges_up; } +/* AIX-NOTE - TODO: Removed conflicting code due to merge conflicts + * Refer Patches: 27,28,29,30,35 and 76 + * and modify the code accordingly. */ + +bool UGLY_FLAG_FOR_AIX __attribute__((weak)) = false; + llvm::Expected DWARFUnit::extract(SymbolFileDWARF &dwarf, user_id_t uid, const DWARFDataExtractor &debug_info, @@ -1002,6 +1008,10 @@ const lldb_private::DWARFDataExtractor &DWARFUnit::GetData() const { uint32_t DWARFUnit::GetHeaderByteSize() const { switch (m_header.getUnitType()) { case llvm::dwarf::DW_UT_compile: + if (UGLY_FLAG_FOR_AIX) + return 11 + 4/*GetDWARFSizeOfOffset*/; + else + return GetVersion() < 5 ? 11 : 12; case llvm::dwarf::DW_UT_partial: return GetVersion() < 5 ? 11 : 12; case llvm::dwarf::DW_UT_skeleton: @@ -1016,7 +1026,7 @@ uint32_t DWARFUnit::GetHeaderByteSize() const { std::optional DWARFUnit::GetStringOffsetSectionItem(uint32_t index) const { - offset_t offset = GetStrOffsetsBase() + index * 4; + lldb::offset_t offset = GetStrOffsetsBase() + index * 4; return m_dwarf.GetDWARFContext().getOrLoadStrOffsetsData().GetU32(&offset); } diff --git a/lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetThreadItemInfoHandler.cpp b/lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetThreadItemInfoHandler.cpp index 2064b73dc3ea5be..824528fc3acfa2d 100644 --- a/lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetThreadItemInfoHandler.cpp +++ b/lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetThreadItemInfoHandler.cpp @@ -216,7 +216,7 @@ lldb::addr_t AppleGetThreadItemInfoHandler::SetupGetThreadItemInfoFunction( AppleGetThreadItemInfoHandler::GetThreadItemInfoReturnInfo AppleGetThreadItemInfoHandler::GetThreadItemInfo(Thread &thread, - tid_t thread_id, + lldb::tid_t thread_id, addr_t page_to_free, uint64_t page_to_free_size, Status &error) { diff --git a/lldb/source/Symbol/DWARFCallFrameInfo.cpp b/lldb/source/Symbol/DWARFCallFrameInfo.cpp index f3df8a2c27f5ace..de244e372579db2 100644 --- a/lldb/source/Symbol/DWARFCallFrameInfo.cpp +++ b/lldb/source/Symbol/DWARFCallFrameInfo.cpp @@ -33,7 +33,7 @@ using namespace lldb_private::dwarf; // Used for calls when the value type is specified by a DWARF EH Frame pointer // encoding. static uint64_t -GetGNUEHPointer(const DataExtractor &DE, offset_t *offset_ptr, +GetGNUEHPointer(const DataExtractor &DE, lldb::offset_t *offset_ptr, uint32_t eh_ptr_enc, addr_t pc_rel_addr, addr_t text_addr, addr_t data_addr) //, BSDRelocs *data_relocs) const { @@ -588,7 +588,7 @@ bool DWARFCallFrameInfo::FDEToUnwindPlan(dw_offset_t dwarf_offset, if (cie->augmentation[0] == 'z') { uint32_t aug_data_len = (uint32_t)m_cfi_data.GetULEB128(&offset); if (aug_data_len != 0 && cie->lsda_addr_encoding != DW_EH_PE_omit) { - offset_t saved_offset = offset; + lldb::offset_t saved_offset = offset; lsda_data_file_address = GetGNUEHPointer(m_cfi_data, &offset, cie->lsda_addr_encoding, pc_rel_addr, text_addr, data_addr); diff --git a/lldb/source/Target/ABI.cpp b/lldb/source/Target/ABI.cpp index 110b5c86fc42567..6df03533cda2995 100644 --- a/lldb/source/Target/ABI.cpp +++ b/lldb/source/Target/ABI.cpp @@ -208,6 +208,15 @@ bool ABI::PrepareTrivialCall(Thread &thread, lldb::addr_t sp, llvm_unreachable("Should never get here!"); } +bool ABI::PrepareTrivialCall(Thread &thread, lldb::addr_t sp, + lldb::addr_t functionAddress, + lldb::addr_t tocAddress, + lldb::addr_t returnAddress, + llvm::ArrayRef args) const { + // dummy prepare trivial call + llvm_unreachable("Should never get here!"); +} + bool ABI::GetFallbackRegisterLocation( const RegisterInfo *reg_info, UnwindPlan::Row::RegisterLocation &unwind_regloc) { diff --git a/lldb/source/Target/CMakeLists.txt b/lldb/source/Target/CMakeLists.txt index a42c44b761dc56e..833489b16dfd7ff 100644 --- a/lldb/source/Target/CMakeLists.txt +++ b/lldb/source/Target/CMakeLists.txt @@ -1,3 +1,8 @@ +if (UNIX AND ${CMAKE_SYSTEM_NAME} MATCHES "AIX") + remove_definitions("-D_XOPEN_SOURCE=700") + add_definitions("-D_ALL_SOURCE") +endif() + lldb_tablegen(TargetProperties.inc -gen-lldb-property-defs SOURCE TargetProperties.td TARGET LLDBTargetPropertiesGen) diff --git a/lldb/source/Target/Process.cpp b/lldb/source/Target/Process.cpp index e3c4f2ee398cc46..e31245178b2f21c 100644 --- a/lldb/source/Target/Process.cpp +++ b/lldb/source/Target/Process.cpp @@ -75,6 +75,10 @@ #include "lldb/Utility/State.h" #include "lldb/Utility/Timer.h" +#if defined(__AIX__) +#include +#endif + using namespace lldb; using namespace lldb_private; using namespace std::chrono; @@ -6206,6 +6210,12 @@ Status Process::GetMemoryRegionInfo(lldb::addr_t load_addr, return DoGetMemoryRegionInfo(load_addr, range_info); } +#if defined(__AIX__) +Status Process::GetLDXINFO(struct ld_xinfo *info_ptr) { + return DoGetLDXINFO(info_ptr); +} +#endif + Status Process::GetMemoryRegions(lldb_private::MemoryRegionInfos ®ion_list) { Status error; diff --git a/lldb/source/Target/RegisterContextUnwind.cpp b/lldb/source/Target/RegisterContextUnwind.cpp index a61228d092d8982..57f42ea56cb18f6 100644 --- a/lldb/source/Target/RegisterContextUnwind.cpp +++ b/lldb/source/Target/RegisterContextUnwind.cpp @@ -40,6 +40,9 @@ #include #include +#ifdef __AIX__ +#include "Plugins/Process/Utility/lldb-ppc64le-register-enums.h" +#endif using namespace lldb; using namespace lldb_private; @@ -1257,6 +1260,10 @@ bool RegisterContextUnwind::IsTrapHandlerSymbol( // Answer the question: Where did THIS frame save the CALLER frame ("previous" // frame)'s register value? +#ifdef __AIX__ +extern bool UGLY_HACK_NULL_TOPFRAME; +#endif + enum UnwindLLDB::RegisterSearchResult RegisterContextUnwind::SavedLocationForRegister( uint32_t lldb_regnum, lldb_private::UnwindLLDB::RegisterLocation ®loc) { @@ -1517,6 +1524,11 @@ RegisterContextUnwind::SavedLocationForRegister( new_regloc.type = UnwindLLDB::RegisterLocation::eRegisterInLiveRegisterContext; new_regloc.location.register_number = regnum.GetAsKind(eRegisterKindLLDB); +#ifdef __AIX__ + if (UGLY_HACK_NULL_TOPFRAME && new_regloc.location.register_number == 0x20) { + new_regloc.location.register_number = 0x24; + } +#endif m_registers[regnum.GetAsKind(eRegisterKindLLDB)] = new_regloc; regloc = new_regloc; UnwindLogMsg("supplying caller's register %s (%d) from the live " @@ -2368,6 +2380,40 @@ bool RegisterContextUnwind::ReadPC(addr_t &pc) { } } +#ifdef __AIX__ +bool RegisterContextUnwind::ReadLR(addr_t &lr) { + if (!IsValid()) + return false; + + bool above_trap_handler = false; + if (GetNextFrame().get() && GetNextFrame()->IsValid() && + GetNextFrame()->IsTrapHandlerFrame()) + above_trap_handler = true; + + if (ReadGPRValue(eRegisterKindLLDB, gpr_lr_ppc64le, lr)) { + // A lr value of 0 or 1 is impossible in the middle of the stack -- it + // indicates the end of a stack walk. + // On the currently executing frame (or such a frame interrupted + // asynchronously by sigtramp et al) this may occur if code has jumped + // through a NULL pointer -- we want to be able to unwind past that frame + // to help find the bug. + + ProcessSP process_sp (m_thread.GetProcess()); + if (process_sp) + { + ABI *abi = process_sp->GetABI().get(); + if (abi) + lr = abi->FixCodeAddress(lr); + } + + return !(m_all_registers_available == false && + above_trap_handler == false && (lr == 0 || lr == 1)); + } else { + return false; + } +} +#endif + void RegisterContextUnwind::UnwindLogMsg(const char *fmt, ...) { Log *log = GetLog(LLDBLog::Unwind); if (!log) diff --git a/lldb/source/Target/ThreadPlanCallFunction.cpp b/lldb/source/Target/ThreadPlanCallFunction.cpp index 50dcb66b9719fe8..0926579ea2930b3 100644 --- a/lldb/source/Target/ThreadPlanCallFunction.cpp +++ b/lldb/source/Target/ThreadPlanCallFunction.cpp @@ -127,6 +127,40 @@ ThreadPlanCallFunction::ThreadPlanCallFunction( m_valid = true; } +ThreadPlanCallFunction::ThreadPlanCallFunction( + Thread &thread, const Address &function, const Address &toc, + const CompilerType &return_type, + llvm::ArrayRef args, const EvaluateExpressionOptions &options) + : ThreadPlan(ThreadPlan::eKindCallFunction, "Call function plan", thread, + eVoteNoOpinion, eVoteNoOpinion), + m_valid(false), m_stop_other_threads(options.GetStopOthers()), + m_unwind_on_error(options.DoesUnwindOnError()), + m_ignore_breakpoints(options.DoesIgnoreBreakpoints()), + m_debug_execution(options.GetDebug()), + m_trap_exceptions(options.GetTrapExceptions()), m_function_addr(function), + m_function_sp(0), m_takedown_done(false), + m_should_clear_objc_exception_bp(false), + m_should_clear_cxx_exception_bp(false), + m_stop_address(LLDB_INVALID_ADDRESS), m_return_type(return_type) { + lldb::addr_t start_load_addr = LLDB_INVALID_ADDRESS; + lldb::addr_t function_load_addr = LLDB_INVALID_ADDRESS; + lldb::addr_t toc_addr = LLDB_INVALID_ADDRESS; + ABI *abi = nullptr; + + if (!ConstructorSetup(thread, abi, start_load_addr, function_load_addr)) + return; + + toc_addr = toc.GetLoadAddress(&GetTarget()); + + if (!abi->PrepareTrivialCall(thread, m_function_sp, function_load_addr, + toc_addr, start_load_addr, args)) + return; + + ReportRegisterState("Function call was set up. Register state was:"); + + m_valid = true; +} + ThreadPlanCallFunction::ThreadPlanCallFunction( Thread &thread, const Address &function, const EvaluateExpressionOptions &options) diff --git a/lldb/source/Target/UnwindLLDB.cpp b/lldb/source/Target/UnwindLLDB.cpp index f43e940492b09b5..255b829738ba229 100644 --- a/lldb/source/Target/UnwindLLDB.cpp +++ b/lldb/source/Target/UnwindLLDB.cpp @@ -68,6 +68,10 @@ uint32_t UnwindLLDB::DoGetFrameCount() { return m_frames.size(); } +#ifdef __AIX__ +bool UGLY_HACK_NULL_TOPFRAME = false; +#endif + bool UnwindLLDB::AddFirstFrame() { if (m_frames.size() > 0) return true; @@ -91,6 +95,17 @@ bool UnwindLLDB::AddFirstFrame() { if (!reg_ctx_sp->ReadPC(first_cursor_sp->start_pc)) goto unwind_done; +#ifdef __AIX__ + lldb::addr_t lr; + if (!reg_ctx_sp->ReadLR(lr)) + goto unwind_done; + + if (first_cursor_sp->start_pc == 0) { + first_cursor_sp->start_pc = lr; + UGLY_HACK_NULL_TOPFRAME = true; + } +#endif + // Everything checks out, so release the auto pointer value and let the // cursor own it in its shared pointer first_cursor_sp->reg_ctx_lldb_sp = reg_ctx_sp; diff --git a/lldb/source/Utility/ArchSpec.cpp b/lldb/source/Utility/ArchSpec.cpp index 07ef435ef451d2a..3868f77169cc662 100644 --- a/lldb/source/Utility/ArchSpec.cpp +++ b/lldb/source/Utility/ArchSpec.cpp @@ -14,6 +14,7 @@ #include "lldb/lldb-defines.h" #include "llvm/ADT/STLExtras.h" #include "llvm/BinaryFormat/COFF.h" +#include "llvm/BinaryFormat/XCOFF.h" #include "llvm/BinaryFormat/ELF.h" #include "llvm/BinaryFormat/MachO.h" #include "llvm/Support/Compiler.h" @@ -459,10 +460,22 @@ static const ArchDefinition g_coff_arch_def = { "pe-coff", }; +static const ArchDefinitionEntry g_xcoff_arch_entries[] = { + {ArchSpec::eCore_ppc_generic, llvm::XCOFF::TCPU_COM, LLDB_INVALID_CPUTYPE, 0xFFFFFFFFu, 0xFFFFFFFFu}, + {ArchSpec::eCore_ppc64_generic, llvm::XCOFF::TCPU_PPC64, LLDB_INVALID_CPUTYPE, 0xFFFFFFFFu, 0xFFFFFFFFu} +}; + +static const ArchDefinition g_xcoff_arch_def = { + eArchTypeXCOFF, + std::size(g_xcoff_arch_entries), + g_xcoff_arch_entries, + "xcoff", +}; + //===----------------------------------------------------------------------===// // Table of all ArchDefinitions static const ArchDefinition *g_arch_definitions[] = { - &g_macho_arch_def, &g_elf_arch_def, &g_coff_arch_def}; + &g_macho_arch_def, &g_elf_arch_def, &g_coff_arch_def, &g_xcoff_arch_def}; //===----------------------------------------------------------------------===// // Static helper functions. @@ -903,6 +916,9 @@ bool ArchSpec::SetArchitecture(ArchitectureType arch_type, uint32_t cpu, } else if (arch_type == eArchTypeCOFF && os == llvm::Triple::Win32) { m_triple.setVendor(llvm::Triple::PC); m_triple.setOS(llvm::Triple::Win32); + } else if (arch_type == eArchTypeXCOFF && os == llvm::Triple::AIX) { + m_triple.setVendor(llvm::Triple::IBM); + m_triple.setOS(llvm::Triple::AIX); } else { m_triple.setVendor(llvm::Triple::UnknownVendor); m_triple.setOS(llvm::Triple::UnknownOS); diff --git a/lldb/source/Utility/StringExtractorGDBRemote.cpp b/lldb/source/Utility/StringExtractorGDBRemote.cpp index 9f79d2271b1e69d..dbd3236536f8cd6 100644 --- a/lldb/source/Utility/StringExtractorGDBRemote.cpp +++ b/lldb/source/Utility/StringExtractorGDBRemote.cpp @@ -227,6 +227,8 @@ StringExtractorGDBRemote::GetServerPacketType() const { return eServerPacketType_qLaunchGDBServer; if (PACKET_MATCHES("qLaunchSuccess")) return eServerPacketType_qLaunchSuccess; + if (PACKET_MATCHES("qLDXINFO")) + return eServerPacketType_qLDXINFO; break; case 'M': diff --git a/lldb/test/CMakeLists.txt b/lldb/test/CMakeLists.txt index 5ac474736eb63dd..413a1e51202880b 100644 --- a/lldb/test/CMakeLists.txt +++ b/lldb/test/CMakeLists.txt @@ -155,7 +155,7 @@ if(TARGET clang) add_lldb_test_dependency(clang) # TestFullLtoStepping depends on LTO, and only runs when the compiler is clang. - add_lldb_test_dependency(LTO) + #add_lldb_test_dependency(LTO) if (TARGET libcxx OR ("libcxx" IN_LIST LLVM_ENABLE_RUNTIMES)) set(LLDB_HAS_LIBCXX ON) diff --git a/lldb/test/Shell/Expr/TestIRMemoryMap.test b/lldb/test/Shell/Expr/TestIRMemoryMap.test index 9dd0413be14cf0a..5ed61ad33ffc440 100644 --- a/lldb/test/Shell/Expr/TestIRMemoryMap.test +++ b/lldb/test/Shell/Expr/TestIRMemoryMap.test @@ -1,6 +1,6 @@ # UNSUPPORTED: system-windows -# RUN: %clangxx_host %p/Inputs/call-function.cpp -g -o %t +# RUN: %clangxx_host -std=c++11 %p/Inputs/env.cpp -o %t # RUN: lldb-test ir-memory-map %t %S/Inputs/ir-memory-map-basic # RUN: lldb-test ir-memory-map -host-only %t %S/Inputs/ir-memory-map-basic diff --git a/lldb/test/Shell/Process/TestEnvironment.test b/lldb/test/Shell/Process/TestEnvironment.test index e6d6e56fc92035b..2ead258719f3269 100644 --- a/lldb/test/Shell/Process/TestEnvironment.test +++ b/lldb/test/Shell/Process/TestEnvironment.test @@ -3,7 +3,7 @@ UNSUPPORTED: lldb-repro The double quotes around "BAR" ensure we don't match the command. -RUN: %clangxx_host -std=c++11 %p/Inputs/env.cpp -o %t +RUN: %clangxx_host -std=c++11 -I/compgpfs/build/xlcit/rings/openxlC/aix/wyvern_dev/ring0/latest/opt/IBM/openxlC/17.1.2/include/c++/v1/ %p/Inputs/env.cpp -o %t RUN: %lldb %t -o 'process launch --environment FOO="BAR"' | FileCheck %s RUN: %lldb %t -o 'env FOO="BAR"' -o 'process launch' | FileCheck %s diff --git a/lldb/tools/driver/CMakeLists.txt b/lldb/tools/driver/CMakeLists.txt index cd304a047dea6d2..78617be24f78068 100644 --- a/lldb/tools/driver/CMakeLists.txt +++ b/lldb/tools/driver/CMakeLists.txt @@ -11,6 +11,11 @@ if(APPLE) set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-sectcreate,__TEXT,__info_plist,${CMAKE_CURRENT_BINARY_DIR}/lldb-Info.plist") endif() +if (UNIX AND ${CMAKE_SYSTEM_NAME} MATCHES "AIX") + remove_definitions("-D_XOPEN_SOURCE=700") + add_definitions("-D_ALL_SOURCE") +endif() + add_lldb_tool(lldb Driver.cpp Platform.cpp diff --git a/lldb/tools/driver/Driver.cpp b/lldb/tools/driver/Driver.cpp index 14371da64f2f2f4..f7eaf56738d7d0c 100644 --- a/lldb/tools/driver/Driver.cpp +++ b/lldb/tools/driver/Driver.cpp @@ -639,7 +639,7 @@ void sigwinch_handler(int signo) { } void sigint_handler(int signo) { -#ifdef _WIN32 // Restore handler as it is not persistent on Windows +#if defined(_WIN32) || defined(__AIX__) // Restore handler as it is not persistent on Windows signal(SIGINT, sigint_handler); #endif static std::atomic_flag g_interrupt_sent = ATOMIC_FLAG_INIT; @@ -727,8 +727,11 @@ static void printHelp(LLDBOptTable &table, llvm::StringRef tool_name) { int main(int argc, char const *argv[]) { // Editline uses for example iswprint which is dependent on LC_CTYPE. + // FIXME: this caused unexpected SIGTRAP on AIX +#ifndef __AIX__ std::setlocale(LC_ALL, ""); std::setlocale(LC_CTYPE, ""); +#endif // Setup LLVM signal handlers and make sure we call llvm_shutdown() on // destruction. diff --git a/lldb/tools/lldb-dap/CMakeLists.txt b/lldb/tools/lldb-dap/CMakeLists.txt index f8f0d86453f585b..2fa6f6c9a536904 100644 --- a/lldb/tools/lldb-dap/CMakeLists.txt +++ b/lldb/tools/lldb-dap/CMakeLists.txt @@ -6,6 +6,10 @@ if (HAVE_LIBPTHREAD) list(APPEND extra_libs pthread) endif () +if (UNIX AND ${CMAKE_SYSTEM_NAME} MATCHES "AIX") + add_definitions("-D_AIX") + add_definitions("-D_ALL_SOURCE") +endif() if(APPLE) configure_file( diff --git a/lldb/tools/lldb-server/CMakeLists.txt b/lldb/tools/lldb-server/CMakeLists.txt index 9030ed709a647a4..0d69ae32a008fdc 100644 --- a/lldb/tools/lldb-server/CMakeLists.txt +++ b/lldb/tools/lldb-server/CMakeLists.txt @@ -8,6 +8,10 @@ if(CMAKE_SYSTEM_NAME MATCHES "Linux|Android") list(APPEND LLDB_PLUGINS lldbPluginProcessLinux) endif() +if(CMAKE_SYSTEM_NAME MATCHES "AIX") + list(APPEND LLDB_PLUGINS lldbPluginProcessAIX) +endif() + if(CMAKE_SYSTEM_NAME MATCHES "FreeBSD") list(APPEND LLDB_PLUGINS lldbPluginProcessFreeBSD) endif() @@ -20,6 +24,8 @@ if(CMAKE_SYSTEM_NAME MATCHES "Darwin") list(APPEND LLDB_PLUGINS lldbPluginObjectFileMachO) elseif(CMAKE_SYSTEM_NAME MATCHES "Windows") list(APPEND LLDB_PLUGINS lldbPluginObjectFilePECOFF) +elseif(CMAKE_SYSTEM_NAME MATCHES "AIX") + list(APPEND LLDB_PLUGINS lldbPluginObjectFileXCOFF) else() list(APPEND LLDB_PLUGINS lldbPluginObjectFileELF) endif() @@ -54,6 +60,7 @@ add_lldb_tool(lldb-server lldbPluginInstructionMIPS lldbPluginInstructionMIPS64 lldbPluginInstructionRISCV + lldbPluginInstructionPPC64 ${LLDB_SYSTEM_LIBS} LINK_COMPONENTS diff --git a/lldb/tools/lldb-server/SystemInitializerLLGS.cpp b/lldb/tools/lldb-server/SystemInitializerLLGS.cpp index 4233252a84dfc72..91bb2083a88b594 100644 --- a/lldb/tools/lldb-server/SystemInitializerLLGS.cpp +++ b/lldb/tools/lldb-server/SystemInitializerLLGS.cpp @@ -14,6 +14,9 @@ using HostObjectFile = ObjectFileMachO; #elif defined(_WIN32) #include "Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.h" using HostObjectFile = ObjectFilePECOFF; +#elif defined(__AIX__) +#include "Plugins/ObjectFile/XCOFF/ObjectFileXCOFF.h" +using HostObjectFile = ObjectFileXCOFF; #else #include "Plugins/ObjectFile/ELF/ObjectFileELF.h" using HostObjectFile = ObjectFileELF; @@ -46,6 +49,10 @@ using HostObjectFile = ObjectFileELF; #include "Plugins/Instruction/MIPS/EmulateInstructionMIPS.h" #endif +#if defined(__AIX__) +#include "Plugins/Instruction/PPC64/EmulateInstructionPPC64.h" +#endif + #if defined(__riscv) #define LLDB_TARGET_RISCV #include "Plugins/Instruction/RISCV/EmulateInstructionRISCV.h" @@ -75,6 +82,10 @@ llvm::Error SystemInitializerLLGS::Initialize() { EmulateInstructionRISCV::Initialize(); #endif +#if defined(__AIX__) + EmulateInstructionPPC64::Initialize(); +#endif + return llvm::Error::success(); } @@ -97,5 +108,9 @@ void SystemInitializerLLGS::Terminate() { EmulateInstructionRISCV::Terminate(); #endif +#if defined(__AIX__) + EmulateInstructionPPC64::Terminate(); +#endif + SystemInitializerCommon::Terminate(); } diff --git a/lldb/tools/lldb-server/lldb-gdbserver.cpp b/lldb/tools/lldb-server/lldb-gdbserver.cpp index 563284730bc7052..2a14f4f9c82aa8b 100644 --- a/lldb/tools/lldb-server/lldb-gdbserver.cpp +++ b/lldb/tools/lldb-server/lldb-gdbserver.cpp @@ -45,6 +45,8 @@ #include "Plugins/Process/NetBSD/NativeProcessNetBSD.h" #elif defined(_WIN32) #include "Plugins/Process/Windows/Common/NativeProcessWindows.h" +#elif defined(__AIX__) +#include "Plugins/Process/AIX/NativeProcessAIX.h" #endif #ifndef LLGS_PROGRAM_NAME @@ -70,6 +72,8 @@ typedef process_freebsd::NativeProcessFreeBSD::Manager NativeProcessManager; typedef process_netbsd::NativeProcessNetBSD::Manager NativeProcessManager; #elif defined(_WIN32) typedef NativeProcessWindows::Manager NativeProcessManager; +#elif defined(__AIX__) +typedef process_aix::NativeProcessAIX::Manager NativeProcessManager; #else // Dummy implementation to make sure the code compiles class NativeProcessManager : public NativeProcessProtocol::Manager { diff --git a/lldb/unittests/Host/FileSystemTest.cpp b/lldb/unittests/Host/FileSystemTest.cpp index 58887f6b2467e0e..89d0f5b87171a31 100644 --- a/lldb/unittests/Host/FileSystemTest.cpp +++ b/lldb/unittests/Host/FileSystemTest.cpp @@ -59,7 +59,7 @@ class DummyFileSystem : public vfs::FileSystem { return I->second; } ErrorOr> - openFileForRead(const Twine &Path) override { + openFileForRead(const Twine &Path, bool IsText) override { auto S = status(Path); if (S) return std::unique_ptr(new DummyFile{*S}); diff --git a/lldb/unittests/Host/posix/TerminalTest.cpp b/lldb/unittests/Host/posix/TerminalTest.cpp index 5187a0c20a68b2e..f3de92c0852b1c3 100644 --- a/lldb/unittests/Host/posix/TerminalTest.cpp +++ b/lldb/unittests/Host/posix/TerminalTest.cpp @@ -94,15 +94,19 @@ TEST_F(TerminalTest, SetRaw) { TEST_F(TerminalTest, SetBaudRate) { struct termios terminfo; +#if (defined(__AIX__) && defined(B38400)) || !defined(__AIX__) ASSERT_THAT_ERROR(m_term.SetBaudRate(38400), llvm::Succeeded()); ASSERT_EQ(tcgetattr(m_fd, &terminfo), 0); EXPECT_EQ(cfgetispeed(&terminfo), static_cast(B38400)); EXPECT_EQ(cfgetospeed(&terminfo), static_cast(B38400)); +#endif +#if (defined(__AIX__) && defined(B115200)) || !defined(__AIX__) ASSERT_THAT_ERROR(m_term.SetBaudRate(115200), llvm::Succeeded()); ASSERT_EQ(tcgetattr(m_fd, &terminfo), 0); EXPECT_EQ(cfgetispeed(&terminfo), static_cast(B115200)); EXPECT_EQ(cfgetospeed(&terminfo), static_cast(B115200)); +#endif // uncommon value #if defined(B153600) diff --git a/llvm/include/llvm/Object/XCOFFObjectFile.h b/llvm/include/llvm/Object/XCOFFObjectFile.h index 5a7cd8e38f2b761..fa9c6781e24f532 100644 --- a/llvm/include/llvm/Object/XCOFFObjectFile.h +++ b/llvm/include/llvm/Object/XCOFFObjectFile.h @@ -542,7 +542,6 @@ class XCOFFObjectFile : public ObjectFile { template const T *sectionHeaderTable() const; size_t getFileHeaderSize() const; - size_t getSectionHeaderSize() const; const XCOFFSectionHeader32 *toSection32(DataRefImpl Ref) const; const XCOFFSectionHeader64 *toSection64(DataRefImpl Ref) const; @@ -578,6 +577,9 @@ class XCOFFObjectFile : public ObjectFile { void checkSectionAddress(uintptr_t Addr, uintptr_t TableAddr) const; public: + size_t getSectionHeaderSize() const; + Expected getLoaderSectionAddress() const; + static constexpr uint64_t InvalidRelocOffset = std::numeric_limits::max(); diff --git a/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp b/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp index bdd04b00f557bd5..9c96df1bbdc5413 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp @@ -251,10 +251,16 @@ Expected DWARFUnit::getStringOffsetSectionItem(uint32_t Index) const { return DA.getRelocatedValue(ItemSize, &Offset); } +bool UGLY_FLAG_FOR_AIX __attribute__((weak)) = false; + Error DWARFUnitHeader::extract(DWARFContext &Context, const DWARFDataExtractor &debug_info, uint64_t *offset_ptr, DWARFSectionKind SectionKind) { + if (UGLY_FLAG_FOR_AIX) { + // FIXME: hack to get version + *offset_ptr += 8; + } Offset = *offset_ptr; Error Err = Error::success(); IndexEntry = nullptr; @@ -267,8 +273,13 @@ Error DWARFUnitHeader::extract(DWARFContext &Context, AbbrOffset = debug_info.getRelocatedValue( FormParams.getDwarfOffsetByteSize(), offset_ptr, nullptr, &Err); } else { - AbbrOffset = debug_info.getRelocatedValue( - FormParams.getDwarfOffsetByteSize(), offset_ptr, nullptr, &Err); + if (UGLY_FLAG_FOR_AIX) { + AbbrOffset = debug_info.getRelocatedValue( + 8, offset_ptr, nullptr, &Err); + } else { + AbbrOffset = debug_info.getRelocatedValue( + FormParams.getDwarfOffsetByteSize(), offset_ptr, nullptr, &Err); + } FormParams.AddrSize = debug_info.getU8(offset_ptr, &Err); // Fake a unit type based on the section type. This isn't perfect, // but distinguishing compile and type units is generally enough. From b1da5b1cf35829fcbf4ad6564c6005c755012e47 Mon Sep 17 00:00:00 2001 From: Dhruv-Srivastava Date: Wed, 7 Aug 2024 12:18:45 -0500 Subject: [PATCH 02/31] Code license notice --- lldb/NOTICE.TXT | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 lldb/NOTICE.TXT diff --git a/lldb/NOTICE.TXT b/lldb/NOTICE.TXT new file mode 100644 index 000000000000000..d814272967476ed --- /dev/null +++ b/lldb/NOTICE.TXT @@ -0,0 +1,7 @@ + +This product contains small piece of code to support AIX, taken from netbsd. + + * LICENSE: + * lldb/source/Host/common/LICENSE.aix-netbsd.txt (OpenSSL License) + * HOMEPAGE: + * https://ftp.netbsd.org/pub/NetBSD/NetBSD-current/src/crypto/external/bsd/openssl/dist From 50ad673a78029fd6c47d90317e2c61ca2b59d5c5 Mon Sep 17 00:00:00 2001 From: Dhruv-Srivastava Date: Wed, 7 Aug 2024 13:27:20 -0500 Subject: [PATCH 03/31] Reverting .tests --- lldb/test/Shell/Expr/TestIRMemoryMap.test | 2 +- lldb/test/Shell/Process/TestEnvironment.test | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lldb/test/Shell/Expr/TestIRMemoryMap.test b/lldb/test/Shell/Expr/TestIRMemoryMap.test index 5ed61ad33ffc440..9dd0413be14cf0a 100644 --- a/lldb/test/Shell/Expr/TestIRMemoryMap.test +++ b/lldb/test/Shell/Expr/TestIRMemoryMap.test @@ -1,6 +1,6 @@ # UNSUPPORTED: system-windows -# RUN: %clangxx_host -std=c++11 %p/Inputs/env.cpp -o %t +# RUN: %clangxx_host %p/Inputs/call-function.cpp -g -o %t # RUN: lldb-test ir-memory-map %t %S/Inputs/ir-memory-map-basic # RUN: lldb-test ir-memory-map -host-only %t %S/Inputs/ir-memory-map-basic diff --git a/lldb/test/Shell/Process/TestEnvironment.test b/lldb/test/Shell/Process/TestEnvironment.test index 2ead258719f3269..e6d6e56fc92035b 100644 --- a/lldb/test/Shell/Process/TestEnvironment.test +++ b/lldb/test/Shell/Process/TestEnvironment.test @@ -3,7 +3,7 @@ UNSUPPORTED: lldb-repro The double quotes around "BAR" ensure we don't match the command. -RUN: %clangxx_host -std=c++11 -I/compgpfs/build/xlcit/rings/openxlC/aix/wyvern_dev/ring0/latest/opt/IBM/openxlC/17.1.2/include/c++/v1/ %p/Inputs/env.cpp -o %t +RUN: %clangxx_host -std=c++11 %p/Inputs/env.cpp -o %t RUN: %lldb %t -o 'process launch --environment FOO="BAR"' | FileCheck %s RUN: %lldb %t -o 'env FOO="BAR"' -o 'process launch' | FileCheck %s From c1967be8fe14d469cb5ae9d41d115a7003ff39b6 Mon Sep 17 00:00:00 2001 From: Lakshmi Surekha Kovvuri Date: Thu, 22 Aug 2024 08:49:50 -0500 Subject: [PATCH 04/31] For TestSuite Run --- lldb/unittests/Host/FileSystemTest.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lldb/unittests/Host/FileSystemTest.cpp b/lldb/unittests/Host/FileSystemTest.cpp index 89d0f5b87171a31..58887f6b2467e0e 100644 --- a/lldb/unittests/Host/FileSystemTest.cpp +++ b/lldb/unittests/Host/FileSystemTest.cpp @@ -59,7 +59,7 @@ class DummyFileSystem : public vfs::FileSystem { return I->second; } ErrorOr> - openFileForRead(const Twine &Path, bool IsText) override { + openFileForRead(const Twine &Path) override { auto S = status(Path); if (S) return std::unique_ptr(new DummyFile{*S}); From 758ab642d0974e799ac902d8ad240a3a90aeb24d Mon Sep 17 00:00:00 2001 From: Lakshmi Surekha Kovvuri Date: Fri, 30 Aug 2024 08:33:32 -0500 Subject: [PATCH 05/31] Changes made to AIX-specific files to eliminate errors encountered during CI when updating LLDB. --- .../Plugins/Process/AIX/NativeProcessAIX.cpp | 20 ++++++++++--------- .../Process/AIX/NativeRegisterContextAIX.cpp | 4 ++-- .../AIX/NativeRegisterContextAIX_ppc64.cpp | 10 +++++----- .../Plugins/Process/AIX/NativeThreadAIX.cpp | 2 +- .../GDBRemoteCommunicationClient.cpp | 4 ++-- 5 files changed, 21 insertions(+), 19 deletions(-) diff --git a/lldb/source/Plugins/Process/AIX/NativeProcessAIX.cpp b/lldb/source/Plugins/Process/AIX/NativeProcessAIX.cpp index 882f20d30a3bf7a..5b01a66b0453f5a 100644 --- a/lldb/source/Plugins/Process/AIX/NativeProcessAIX.cpp +++ b/lldb/source/Plugins/Process/AIX/NativeProcessAIX.cpp @@ -211,12 +211,14 @@ static Status EnsureFDFlags(int fd, int flags) { int status = fcntl(fd, F_GETFL); if (status == -1) { - error.SetErrorToErrno(); + error = Status::FromErrno(); + // error.SetErrorToErrno(); return error; } if (fcntl(fd, F_SETFL, status | flags) == -1) { - error.SetErrorToErrno(); + error = Status::FromErrno(); + // error.SetErrorToErrno(); return error; } @@ -813,7 +815,7 @@ Status NativeProcessAIX::Resume(const ResumeActionList &resume_actions) { Status error = ResumeThread(static_cast(*thread), action->state, signo); if (error.Fail()) - return Status("NativeProcessAIX::%s: failed to resume thread " + return Status::FromErrorStringWithFormat("NativeProcessAIX::%s: failed to resume thread " "for pid %" PRIu64 ", tid %" PRIu64 ", error = %s", __FUNCTION__, GetID(), thread->GetID(), error.AsCString()); @@ -826,7 +828,7 @@ Status NativeProcessAIX::Resume(const ResumeActionList &resume_actions) { break; default: - return Status("NativeProcessAIX::%s (): unexpected state %s specified " + return Status::FromErrorStringWithFormat("NativeProcessAIX::%s (): unexpected state %s specified " "for pid %" PRIu64 ", tid %" PRIu64, __FUNCTION__, StateAsCString(action->state), GetID(), thread->GetID()); @@ -840,7 +842,7 @@ Status NativeProcessAIX::Halt() { Status error; if (kill(GetID(), SIGSTOP) != 0) - error.SetErrorToErrno(); + error = Status::FromErrno(); return error; } @@ -874,7 +876,7 @@ Status NativeProcessAIX::Signal(int signo) { Host::GetSignalAsCString(signo), GetID()); if (kill(GetID(), signo)) - error.SetErrorToErrno(); + error = Status::FromErrno(); return error; } @@ -951,7 +953,7 @@ Status NativeProcessAIX::Kill() { } if (kill(GetID(), SIGKILL) != 0) { - error.SetErrorToErrno(); + error = Status::FromErrno(); return error; } @@ -1555,7 +1557,7 @@ Status NativeProcessAIX::GetLoadedModuleFileSpec(const char *module_path, return Status(); } } - return Status("Module file (%s) not found in /proc/%" PRIu64 "/maps file!", + return Status::FromErrorStringWithFormat("Module file (%s) not found in /proc/%" PRIu64 "/maps file!", module_file_spec.GetFilename().AsCString(), GetID()); } @@ -2011,7 +2013,7 @@ Status NativeProcessAIX::PtraceWrapper(int req, lldb::pid_t pid, void *addr, } if (errno) { - error.SetErrorToErrno(); + error = Status::FromErrno(); ret = -1; } diff --git a/lldb/source/Plugins/Process/AIX/NativeRegisterContextAIX.cpp b/lldb/source/Plugins/Process/AIX/NativeRegisterContextAIX.cpp index 0859f9501c1b6a6..071e55543cc3c28 100644 --- a/lldb/source/Plugins/Process/AIX/NativeRegisterContextAIX.cpp +++ b/lldb/source/Plugins/Process/AIX/NativeRegisterContextAIX.cpp @@ -27,7 +27,7 @@ Status NativeRegisterContextAIX::ReadRegisterRaw(uint32_t reg_index, RegisterValue ®_value) { const RegisterInfo *const reg_info = GetRegisterInfoAtIndex(reg_index); if (!reg_info) - return Status("register %" PRIu32 " not found", reg_index); + return Status::FromErrorStringWithFormat("register %" PRIu32 " not found", reg_index); return DoReadRegisterValue(GetPtraceOffset(reg_index), reg_info->name, reg_info->byte_size, reg_value); @@ -82,7 +82,7 @@ NativeRegisterContextAIX::WriteRegisterRaw(uint32_t reg_index, assert(register_to_write_info_p && "register to write does not have valid RegisterInfo"); if (!register_to_write_info_p) - return Status("NativeRegisterContextAIX::%s failed to get RegisterInfo " + return Status::FromErrorStringWithFormat("NativeRegisterContextAIX::%s failed to get RegisterInfo " "for write register index %" PRIu32, __FUNCTION__, reg_to_write); diff --git a/lldb/source/Plugins/Process/AIX/NativeRegisterContextAIX_ppc64.cpp b/lldb/source/Plugins/Process/AIX/NativeRegisterContextAIX_ppc64.cpp index 199637379174840..0132b52dec6f2e0 100644 --- a/lldb/source/Plugins/Process/AIX/NativeRegisterContextAIX_ppc64.cpp +++ b/lldb/source/Plugins/Process/AIX/NativeRegisterContextAIX_ppc64.cpp @@ -165,7 +165,7 @@ Status NativeRegisterContextAIX_ppc64::ReadRegister( Status error; if (!reg_info) { - error.SetErrorString("reg_info NULL"); + error.FromErrorString("reg_info NULL"); return error; } @@ -251,7 +251,7 @@ Status NativeRegisterContextAIX_ppc64::WriteRegister( const uint32_t reg_index = reg_info->kinds[lldb::eRegisterKindLLDB]; if (reg_index == LLDB_INVALID_REGNUM) - return Status("no lldb regnum for %s", reg_info && reg_info->name + return Status::FromErrorStringWithFormat("no lldb regnum for %s", reg_info && reg_info->name ? reg_info->name : ""); @@ -389,14 +389,14 @@ Status NativeRegisterContextAIX_ppc64::WriteAllRegisterValues( Status error; if (!data_sp) { - error.SetErrorStringWithFormat( + error = Status::FromErrorStringWithFormat( "NativeRegisterContextAIX_ppc64::%s invalid data_sp provided", __FUNCTION__); return error; } if (data_sp->GetByteSize() != REG_CONTEXT_SIZE) { - error.SetErrorStringWithFormat( + error = Status::FromErrorStringWithFormat( "NativeRegisterContextAIX_ppc64::%s data_sp contained mismatched " "data size, expected %" PRIu64 ", actual %" PRIu64, __FUNCTION__, REG_CONTEXT_SIZE, data_sp->GetByteSize()); @@ -405,7 +405,7 @@ Status NativeRegisterContextAIX_ppc64::WriteAllRegisterValues( const uint8_t *src = data_sp->GetBytes(); if (src == nullptr) { - error.SetErrorStringWithFormat("NativeRegisterContextAIX_ppc64::%s " + error = Status::FromErrorStringWithFormat("NativeRegisterContextAIX_ppc64::%s " "DataBuffer::GetBytes() returned a null " "pointer", __FUNCTION__); diff --git a/lldb/source/Plugins/Process/AIX/NativeThreadAIX.cpp b/lldb/source/Plugins/Process/AIX/NativeThreadAIX.cpp index e07daccdff550e1..bb14b6ab4a05e86 100644 --- a/lldb/source/Plugins/Process/AIX/NativeThreadAIX.cpp +++ b/lldb/source/Plugins/Process/AIX/NativeThreadAIX.cpp @@ -481,7 +481,7 @@ Status NativeThreadAIX::RequestStop() { Status err; errno = 0; if (::kill(pid, SIGSTOP) != 0) { - err.SetErrorToErrno(); + err = Status::FromErrno(); LLDB_LOGF(log, "NativeThreadAIX::%s kill(%" PRIu64 ", SIGSTOP) failed: %s", __FUNCTION__, pid, err.AsCString()); diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp index 17926f8e4ab5356..0aa68a4a09cbe91 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp @@ -1728,11 +1728,11 @@ Status GDBRemoteCommunicationClient::GetLDXINFO(struct ld_xinfo *info_ptr) llvm::MutableArrayRef infoData((uint8_t *)info_ptr, sizeof(struct ld_xinfo)*64); size_t got_bytes = response.GetHexBytesAvail(infoData); if (got_bytes != sizeof(struct ld_xinfo)*64) { - error.SetErrorString("qLDXINFO ret bad size"); + error.FromErrorString("qLDXINFO ret bad size"); return error; } } else { - error.SetErrorString("qLDXINFO is not supported"); + error.FromErrorString("qLDXINFO is not supported"); } return error; } From 33d561f4bb74a2efd0da163ebde416c9ad1c2925 Mon Sep 17 00:00:00 2001 From: Dhruv-Srivastava Date: Tue, 10 Sep 2024 02:00:09 -0500 Subject: [PATCH 06/31] Removed non-required PTRACE defs --- lldb/include/lldb/Host/aix/Ptrace.h | 22 ++-------------------- 1 file changed, 2 insertions(+), 20 deletions(-) diff --git a/lldb/include/lldb/Host/aix/Ptrace.h b/lldb/include/lldb/Host/aix/Ptrace.h index 88928f18102d7c8..393928a89add3ee 100644 --- a/lldb/include/lldb/Host/aix/Ptrace.h +++ b/lldb/include/lldb/Host/aix/Ptrace.h @@ -34,29 +34,11 @@ #ifndef PTRACE_SETREGSET #define PTRACE_SETREGSET 0x4205 #endif -#ifndef PTRACE_GET_THREAD_AREA -#define PTRACE_GET_THREAD_AREA (PT_COMMAND_MAX+5) -#endif -#ifndef PTRACE_ARCH_PRCTL -#define PTRACE_ARCH_PRCTL (PT_COMMAND_MAX+6) -#endif -#ifndef ARCH_GET_FS -#define ARCH_SET_GS 0x1001 -#define ARCH_SET_FS 0x1002 -#define ARCH_GET_FS 0x1003 -#define ARCH_GET_GS 0x1004 -#endif -#ifndef PTRACE_PEEKMTETAGS -#define PTRACE_PEEKMTETAGS (PT_COMMAND_MAX+7) -#endif -#ifndef PTRACE_POKEMTETAGS -#define PTRACE_POKEMTETAGS (PT_COMMAND_MAX+8) -#endif #ifndef PTRACE_GETVRREGS -#define PTRACE_GETVRREGS (PT_COMMAND_MAX+9) +#define PTRACE_GETVRREGS (PT_COMMAND_MAX+5) #endif #ifndef PTRACE_GETVSRREGS -#define PTRACE_GETVSRREGS (PT_COMMAND_MAX+10) +#define PTRACE_GETVSRREGS (PT_COMMAND_MAX+6) #endif #endif // liblldb_Host_aix_Ptrace_h_ From 450793d7270999ecdd6714c4222663517dab3928 Mon Sep 17 00:00:00 2001 From: Lakshmi Surekha Kovvuri Date: Wed, 11 Sep 2024 02:52:41 -0500 Subject: [PATCH 07/31] Patch for running of unit testcases without hang --- lldb/unittests/Host/MainLoopTest.cpp | 4 +++- lldb/unittests/Host/PipeTest.cpp | 2 ++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/lldb/unittests/Host/MainLoopTest.cpp b/lldb/unittests/Host/MainLoopTest.cpp index 4084e90782fd5d1..9e92ec1470d4d6e 100644 --- a/lldb/unittests/Host/MainLoopTest.cpp +++ b/lldb/unittests/Host/MainLoopTest.cpp @@ -183,7 +183,7 @@ TEST_F(MainLoopTest, PendingCallbackAfterLoopExited) { loop.AddPendingCallback([&](MainLoopBase &loop) {}); } -#ifdef LLVM_ON_UNIX +#if defined(LLVM_ON_UNIX) && !defined(__AIX__) TEST_F(MainLoopTest, DetectsEOF) { PseudoTerminal term; @@ -202,7 +202,9 @@ TEST_F(MainLoopTest, DetectsEOF) { ASSERT_TRUE(loop.Run().Success()); ASSERT_EQ(1u, callback_count); } +// #endif +// #ifdef LLVM_ON_UNIX TEST_F(MainLoopTest, Signal) { MainLoop loop; Status error; diff --git a/lldb/unittests/Host/PipeTest.cpp b/lldb/unittests/Host/PipeTest.cpp index 506f3d225a21ea5..c1013aa7a7e4ea3 100644 --- a/lldb/unittests/Host/PipeTest.cpp +++ b/lldb/unittests/Host/PipeTest.cpp @@ -55,6 +55,7 @@ TEST_F(PipeTest, OpenAsReader) { } #endif +#if !defined(__AIX__) TEST_F(PipeTest, WriteWithTimeout) { Pipe pipe; ASSERT_THAT_ERROR(pipe.CreateNew(false).ToError(), llvm::Succeeded()); @@ -150,3 +151,4 @@ TEST_F(PipeTest, WriteWithTimeout) { .ToError(), llvm::Succeeded()); } +#endif From 61e7843b431ff3657e3c4b39d1559401ff3de891 Mon Sep 17 00:00:00 2001 From: Lakshmi Surekha Kovvuri Date: Thu, 12 Sep 2024 13:22:03 -0500 Subject: [PATCH 08/31] changes applied to NativeProcessAIX.cpp file to solve build errors while making LLDB up to date --- .../Plugins/Process/AIX/NativeProcessAIX.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/lldb/source/Plugins/Process/AIX/NativeProcessAIX.cpp b/lldb/source/Plugins/Process/AIX/NativeProcessAIX.cpp index 5b01a66b0453f5a..fc847638574538e 100644 --- a/lldb/source/Plugins/Process/AIX/NativeProcessAIX.cpp +++ b/lldb/source/Plugins/Process/AIX/NativeProcessAIX.cpp @@ -862,7 +862,7 @@ Status NativeProcessAIX::Detach() { Status e = Detach(thread->GetID()); if (e.Fail()) error = - e; // Save the error, but still attempt to detach from other threads. + e.Clone(); // Save the error, but still attempt to detach from other threads. } return error; @@ -1240,7 +1240,7 @@ Status NativeProcessAIX::ReadMemoryTags(int32_t type, lldb::addr_t addr, llvm::Expected details = GetCurrentThread()->GetRegisterContext().GetMemoryTaggingDetails(type); if (!details) - return Status(details.takeError()); + return Status::FromError(details.takeError()); // Ignore 0 length read if (!len) @@ -1295,7 +1295,7 @@ Status NativeProcessAIX::WriteMemoryTags(int32_t type, lldb::addr_t addr, llvm::Expected details = GetCurrentThread()->GetRegisterContext().GetMemoryTaggingDetails(type); if (!details) - return Status(details.takeError()); + return Status::FromError(details.takeError()); // Ignore 0 length write if (!len) @@ -1312,18 +1312,18 @@ Status NativeProcessAIX::WriteMemoryTags(int32_t type, lldb::addr_t addr, llvm::Expected> unpacked_tags_or_err = details->manager->UnpackTagsData(tags); if (!unpacked_tags_or_err) - return Status(unpacked_tags_or_err.takeError()); + return Status::FromError(unpacked_tags_or_err.takeError()); llvm::Expected> repeated_tags_or_err = details->manager->RepeatTagsForRange(*unpacked_tags_or_err, range); if (!repeated_tags_or_err) - return Status(repeated_tags_or_err.takeError()); + return Status::FromError(repeated_tags_or_err.takeError()); // Repack them for ptrace to use llvm::Expected> final_tag_data = details->manager->PackTags(*repeated_tags_or_err); if (!final_tag_data) - return Status(final_tag_data.takeError()); + return Status::FromError(final_tag_data.takeError()); struct iovec tags_vec; uint8_t *src = final_tag_data->data(); @@ -1609,13 +1609,13 @@ Status NativeProcessAIX::ResumeThread(NativeThreadAIX &thread, // reflect it is running after this completes. switch (state) { case eStateRunning: { - const auto resume_result = thread.Resume(signo); + Status resume_result = thread.Resume(signo); if (resume_result.Success()) SetState(eStateRunning, true); return resume_result; } case eStateStepping: { - const auto step_result = thread.SingleStep(signo); + Status step_result = thread.SingleStep(signo); if (step_result.Success()) SetState(eStateRunning, true); return step_result; From 627a5427daba3fc5ea03ae481874f4aa1b4d2ed0 Mon Sep 17 00:00:00 2001 From: Lakshmi-Surekha Date: Fri, 13 Sep 2024 16:25:47 +0530 Subject: [PATCH 09/31] Revert "Removed non-required PTRACE defs" --- lldb/include/lldb/Host/aix/Ptrace.h | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/lldb/include/lldb/Host/aix/Ptrace.h b/lldb/include/lldb/Host/aix/Ptrace.h index 393928a89add3ee..88928f18102d7c8 100644 --- a/lldb/include/lldb/Host/aix/Ptrace.h +++ b/lldb/include/lldb/Host/aix/Ptrace.h @@ -34,11 +34,29 @@ #ifndef PTRACE_SETREGSET #define PTRACE_SETREGSET 0x4205 #endif +#ifndef PTRACE_GET_THREAD_AREA +#define PTRACE_GET_THREAD_AREA (PT_COMMAND_MAX+5) +#endif +#ifndef PTRACE_ARCH_PRCTL +#define PTRACE_ARCH_PRCTL (PT_COMMAND_MAX+6) +#endif +#ifndef ARCH_GET_FS +#define ARCH_SET_GS 0x1001 +#define ARCH_SET_FS 0x1002 +#define ARCH_GET_FS 0x1003 +#define ARCH_GET_GS 0x1004 +#endif +#ifndef PTRACE_PEEKMTETAGS +#define PTRACE_PEEKMTETAGS (PT_COMMAND_MAX+7) +#endif +#ifndef PTRACE_POKEMTETAGS +#define PTRACE_POKEMTETAGS (PT_COMMAND_MAX+8) +#endif #ifndef PTRACE_GETVRREGS -#define PTRACE_GETVRREGS (PT_COMMAND_MAX+5) +#define PTRACE_GETVRREGS (PT_COMMAND_MAX+9) #endif #ifndef PTRACE_GETVSRREGS -#define PTRACE_GETVSRREGS (PT_COMMAND_MAX+6) +#define PTRACE_GETVSRREGS (PT_COMMAND_MAX+10) #endif #endif // liblldb_Host_aix_Ptrace_h_ From ea34b15d8568b4639b4e850ef032e684d82dd971 Mon Sep 17 00:00:00 2001 From: Dhruv-Srivastava Date: Thu, 10 Oct 2024 00:38:18 -0500 Subject: [PATCH 10/31] Replaced __AIX__ with _AIX --- clang/test/SemaCXX/class-layout.cpp | 2 +- lldb/CMakeLists.txt | 2 +- lldb/include/lldb/Host/HostGetOpt.h | 2 +- lldb/include/lldb/Host/HostInfo.h | 2 +- lldb/include/lldb/Host/XML.h | 2 +- lldb/include/lldb/Host/common/GetOptInc.h | 4 ++-- lldb/include/lldb/Target/Process.h | 6 +++--- lldb/include/lldb/Target/RegisterContextUnwind.h | 2 +- lldb/source/Core/Mangled.cpp | 2 +- lldb/source/Core/Section.cpp | 2 +- lldb/source/Host/common/Host.cpp | 4 ++-- lldb/source/Host/common/XML.cpp | 2 +- lldb/source/Host/posix/ConnectionFileDescriptorPosix.cpp | 2 +- lldb/source/Host/posix/FileSystemPosix.cpp | 2 +- lldb/source/Host/posix/MainLoopPosix.cpp | 4 ++-- lldb/source/Host/posix/ProcessLauncherPosixFork.cpp | 2 +- lldb/source/Initialization/SystemInitializerCommon.cpp | 4 ++-- lldb/source/Plugins/ABI/PowerPC/ABISysV_ppc64.cpp | 4 ++-- .../DynamicLoader/AIX-DYLD/DynamicLoaderAIXDYLD.cpp | 6 +++--- .../Plugins/Instruction/PPC64/EmulateInstructionPPC64.h | 2 +- lldb/source/Plugins/JITLoader/GDB/JITLoaderGDB.cpp | 2 +- lldb/source/Plugins/Language/ObjC/Cocoa.cpp | 2 +- .../BSD-Archive/ObjectContainerBSDArchive.cpp | 2 +- .../Big-Archive/ObjectContainerBigArchive.cpp | 2 +- .../Plugins/ObjectFile/Minidump/ObjectFileMinidump.cpp | 2 +- lldb/source/Plugins/ObjectFile/PDB/ObjectFilePDB.cpp | 6 +++--- .../source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp | 6 +++--- lldb/source/Plugins/Platform/AIX/PlatformAIX.cpp | 6 +++--- lldb/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp | 4 ++-- .../Process/gdb-remote/GDBRemoteCommunicationClient.cpp | 4 ++-- .../Process/gdb-remote/GDBRemoteCommunicationClient.h | 4 ++-- .../gdb-remote/GDBRemoteCommunicationServerLLGS.cpp | 4 ++-- .../Plugins/Process/gdb-remote/ProcessGDBRemote.cpp | 4 ++-- lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h | 4 ++-- lldb/source/Target/Process.cpp | 4 ++-- lldb/source/Target/RegisterContextUnwind.cpp | 8 ++++---- lldb/source/Target/UnwindLLDB.cpp | 4 ++-- lldb/tools/driver/Driver.cpp | 4 ++-- lldb/tools/lldb-server/SystemInitializerLLGS.cpp | 8 ++++---- lldb/tools/lldb-server/lldb-gdbserver.cpp | 4 ++-- lldb/unittests/Host/MainLoopTest.cpp | 2 +- lldb/unittests/Host/PipeTest.cpp | 2 +- lldb/unittests/Host/posix/TerminalTest.cpp | 4 ++-- 43 files changed, 75 insertions(+), 75 deletions(-) diff --git a/clang/test/SemaCXX/class-layout.cpp b/clang/test/SemaCXX/class-layout.cpp index 22fb34b8419c583..0931d905a97495b 100644 --- a/clang/test/SemaCXX/class-layout.cpp +++ b/clang/test/SemaCXX/class-layout.cpp @@ -639,7 +639,7 @@ namespace PR37275 { #pragma pack(pop) } -#endif // !defined(__MVS__) && !defined(__AIX__) +#endif // !defined(__MVS__) && !defined(_AIX) namespace non_pod { struct t1 { diff --git a/lldb/CMakeLists.txt b/lldb/CMakeLists.txt index 2e9ae0d0b3221c4..a4fd8bccf056dc5 100644 --- a/lldb/CMakeLists.txt +++ b/lldb/CMakeLists.txt @@ -39,7 +39,7 @@ include(LLDBConfig) include(AddLLDB) if (UNIX AND ${CMAKE_SYSTEM_NAME} MATCHES "AIX") - add_definitions("-D__AIX__") + add_definitions("-D_AIX") endif() # Define the LLDB_CONFIGURATION_xxx matching the build type. diff --git a/lldb/include/lldb/Host/HostGetOpt.h b/lldb/include/lldb/Host/HostGetOpt.h index f450e561d6afb19..b2b436e64a692f0 100644 --- a/lldb/include/lldb/Host/HostGetOpt.h +++ b/lldb/include/lldb/Host/HostGetOpt.h @@ -9,7 +9,7 @@ #ifndef LLDB_HOST_HOSTGETOPT_H #define LLDB_HOST_HOSTGETOPT_H -#if !defined(_MSC_VER) && !defined(__NetBSD__) && !defined(__AIX__) +#if !defined(_MSC_VER) && !defined(__NetBSD__) && !defined(_AIX) #include #include diff --git a/lldb/include/lldb/Host/HostInfo.h b/lldb/include/lldb/Host/HostInfo.h index 156df8cf6901df7..0f7ec0e0aa0d24d 100644 --- a/lldb/include/lldb/Host/HostInfo.h +++ b/lldb/include/lldb/Host/HostInfo.h @@ -55,7 +55,7 @@ #elif defined(__APPLE__) #include "lldb/Host/macosx/HostInfoMacOSX.h" #define HOST_INFO_TYPE HostInfoMacOSX -#elif defined(__AIX__) +#elif defined(_AIX) #include "lldb/Host/aix/HostInfoAIX.h" #define HOST_INFO_TYPE HostInfoAIX #else diff --git a/lldb/include/lldb/Host/XML.h b/lldb/include/lldb/Host/XML.h index cf359f7726d5d6b..483589f1abc753a 100644 --- a/lldb/include/lldb/Host/XML.h +++ b/lldb/include/lldb/Host/XML.h @@ -11,7 +11,7 @@ #include "lldb/Host/Config.h" -#if defined(__AIX__) +#if defined(_AIX) //FIXME for AIX #undef LLDB_ENABLE_LIBXML2 #endif diff --git a/lldb/include/lldb/Host/common/GetOptInc.h b/lldb/include/lldb/Host/common/GetOptInc.h index ebb475bfaf6b8d2..652e6174ff8b6a0 100644 --- a/lldb/include/lldb/Host/common/GetOptInc.h +++ b/lldb/include/lldb/Host/common/GetOptInc.h @@ -11,11 +11,11 @@ #include "lldb/lldb-defines.h" -#if defined(_MSC_VER) || defined(__AIX__) +#if defined(_MSC_VER) || defined(_AIX) #define REPLACE_GETOPT #define REPLACE_GETOPT_LONG #endif -#if defined(_MSC_VER) || defined(__NetBSD__) || defined(__AIX__) +#if defined(_MSC_VER) || defined(__NetBSD__) || defined(_AIX) #define REPLACE_GETOPT_LONG_ONLY #endif diff --git a/lldb/include/lldb/Target/Process.h b/lldb/include/lldb/Target/Process.h index 4a47ffd8d779d03..d1527d316d6782f 100644 --- a/lldb/include/lldb/Target/Process.h +++ b/lldb/include/lldb/Target/Process.h @@ -65,7 +65,7 @@ #include "llvm/Support/Threading.h" #include "llvm/Support/VersionTuple.h" -#if defined(__AIX__) +#if defined(_AIX) struct ld_xinfo; #endif @@ -1884,7 +1884,7 @@ class Process : public std::enable_shared_from_this, Status GetMemoryRegionInfo(lldb::addr_t load_addr, MemoryRegionInfo &range_info); -#if defined(__AIX__) +#if defined(_AIX) Status GetLDXINFO(struct ld_xinfo *info_ptr); #endif @@ -2823,7 +2823,7 @@ void PruneThreadPlans(); "Process::DoGetMemoryRegionInfo() not supported"); } -#if defined(__AIX__) +#if defined(_AIX) virtual Status DoGetLDXINFO(struct ld_xinfo *info_ptr) { return Status("Process::DoGetLDXINFO() not supported"); } diff --git a/lldb/include/lldb/Target/RegisterContextUnwind.h b/lldb/include/lldb/Target/RegisterContextUnwind.h index 46c06cb422cafb0..b6176f8e5727f95 100644 --- a/lldb/include/lldb/Target/RegisterContextUnwind.h +++ b/lldb/include/lldb/Target/RegisterContextUnwind.h @@ -67,7 +67,7 @@ class RegisterContextUnwind : public lldb_private::RegisterContext { bool ReadPC(lldb::addr_t &start_pc); -#ifdef __AIX__ +#ifdef _AIX bool ReadLR(lldb::addr_t &lr); #endif diff --git a/lldb/source/Core/Mangled.cpp b/lldb/source/Core/Mangled.cpp index 43c5b043ef7a288..8f2e3562f6577eb 100644 --- a/lldb/source/Core/Mangled.cpp +++ b/lldb/source/Core/Mangled.cpp @@ -167,7 +167,7 @@ static char *GetItaniumDemangledStr(const char *M) { "Expected demangled_size to return length including trailing null"); } -#if !defined(__AIX__) +#if !defined(_AIX) if (Log *log = GetLog(LLDBLog::Demangle)) { if (demangled_cstr) LLDB_LOGF(log, "demangled itanium: %s -> \"%s\"", M, demangled_cstr); diff --git a/lldb/source/Core/Section.cpp b/lldb/source/Core/Section.cpp index 9ed55853930a674..e0a9f7fcc713599 100644 --- a/lldb/source/Core/Section.cpp +++ b/lldb/source/Core/Section.cpp @@ -263,7 +263,7 @@ bool Section::ResolveContainedAddress(addr_t offset, Address &so_addr, bool Section::ContainsFileAddress(addr_t vm_addr) const { const addr_t file_addr = GetFileAddress(); -#ifdef __AIX__ +#ifdef _AIX if (file_addr == 0) return false; #endif diff --git a/lldb/source/Host/common/Host.cpp b/lldb/source/Host/common/Host.cpp index 94b1d0fd57d0724..dc48cb87b5ce6e3 100644 --- a/lldb/source/Host/common/Host.cpp +++ b/lldb/source/Host/common/Host.cpp @@ -358,7 +358,7 @@ bool Host::ResolveExecutableInBundle(FileSpec &file) { return false; } #ifndef _WIN32 -#if defined(__AIX__) +#if defined(_AIX) #include extern char **p_xargv; @@ -525,7 +525,7 @@ static int dladdr(const void *ptr, Dl_info *dl) FileSpec Host::GetModuleFileSpecForHostAddress(const void *host_addr) { FileSpec module_filespec; #if !defined(__ANDROID__) -#ifdef __AIX__ +#ifdef _AIX if (host_addr == reinterpret_cast(HostInfoBase::ComputeSharedLibraryDirectory)) { // FIXME: AIX dladdr return "lldb" for this case if (p_xargv[0]) { diff --git a/lldb/source/Host/common/XML.cpp b/lldb/source/Host/common/XML.cpp index 62cac78aaac230f..fbc409105fe607c 100644 --- a/lldb/source/Host/common/XML.cpp +++ b/lldb/source/Host/common/XML.cpp @@ -10,7 +10,7 @@ #include "lldb/Host/XML.h" #include "llvm/ADT/StringExtras.h" -#if defined(__AIX__) +#if defined(_AIX) #undef LLDB_ENABLE_LIBXML2 #endif diff --git a/lldb/source/Host/posix/ConnectionFileDescriptorPosix.cpp b/lldb/source/Host/posix/ConnectionFileDescriptorPosix.cpp index bd204c812b7e3ef..09c3fd2af6d3e1c 100644 --- a/lldb/source/Host/posix/ConnectionFileDescriptorPosix.cpp +++ b/lldb/source/Host/posix/ConnectionFileDescriptorPosix.cpp @@ -722,7 +722,7 @@ ConnectionFileDescriptor::ConnectFD(llvm::StringRef s, ConnectionStatus ConnectionFileDescriptor::ConnectFile( llvm::StringRef s, socket_id_callback_type socket_id_callback, Status *error_ptr) { -#if !defined(__AIX__) +#if !defined(_AIX) #if LLDB_ENABLE_POSIX std::string addr_str = s.str(); // file:///PATH diff --git a/lldb/source/Host/posix/FileSystemPosix.cpp b/lldb/source/Host/posix/FileSystemPosix.cpp index 866fd8ac96c7b7c..21da5612ff6b8d8 100644 --- a/lldb/source/Host/posix/FileSystemPosix.cpp +++ b/lldb/source/Host/posix/FileSystemPosix.cpp @@ -11,7 +11,7 @@ // C includes #include #include -#if !defined(__AIX__) +#if !defined(_AIX) #include #endif #include diff --git a/lldb/source/Host/posix/MainLoopPosix.cpp b/lldb/source/Host/posix/MainLoopPosix.cpp index d1eba52791a7891..015570236b9d3c4 100644 --- a/lldb/source/Host/posix/MainLoopPosix.cpp +++ b/lldb/source/Host/posix/MainLoopPosix.cpp @@ -179,7 +179,7 @@ Status MainLoopPosix::RunImpl::Poll() { read_fds.push_back(pfd); } -#if defined(__AIX__) +#if defined(_AIX) sigset_t origmask; int timeout; @@ -325,7 +325,7 @@ MainLoopPosix::RegisterSignal(int signo, const Callback &callback, // If we're using kqueue, the signal needs to be unblocked in order to // receive it. If using pselect/ppoll, we need to block it, and later unblock // it as a part of the system call. -#if defined(__AIX__) +#if defined(_AIX) //FIXME: where is signal unblocked? ret = pthread_sigmask(SIG_UNBLOCK, &new_action.sa_mask, &old_set); #else diff --git a/lldb/source/Host/posix/ProcessLauncherPosixFork.cpp b/lldb/source/Host/posix/ProcessLauncherPosixFork.cpp index b8a96fbd19f0201..f9f99decd39c297 100644 --- a/lldb/source/Host/posix/ProcessLauncherPosixFork.cpp +++ b/lldb/source/Host/posix/ProcessLauncherPosixFork.cpp @@ -193,7 +193,7 @@ struct ForkLaunchInfo { } // Start tracing this child that is about to exec. -#if !defined(__AIX__) +#if !defined(_AIX) if (ptrace(PT_TRACE_ME, 0, nullptr, 0) == -1) ExitWithError(error_fd, "ptrace"); #else diff --git a/lldb/source/Initialization/SystemInitializerCommon.cpp b/lldb/source/Initialization/SystemInitializerCommon.cpp index 4b01442a94bacfa..2e2d622d9981ce7 100644 --- a/lldb/source/Initialization/SystemInitializerCommon.cpp +++ b/lldb/source/Initialization/SystemInitializerCommon.cpp @@ -19,7 +19,7 @@ #include "lldb/Version/Version.h" #if defined(__linux__) || defined(__FreeBSD__) || defined(__NetBSD__) || \ - defined(__OpenBSD__) || defined(__AIX__) + defined(__OpenBSD__) || defined(_AIX) #include "Plugins/Process/POSIX/ProcessPOSIXLog.h" #endif @@ -79,7 +79,7 @@ llvm::Error SystemInitializerCommon::Initialize() { process_gdb_remote::ProcessGDBRemoteLog::Initialize(); #if defined(__linux__) || defined(__FreeBSD__) || defined(__NetBSD__) || \ - defined(__OpenBSD__) || defined(__AIX__) + defined(__OpenBSD__) || defined(_AIX) ProcessPOSIXLog::Initialize(); #endif #if defined(_WIN32) diff --git a/lldb/source/Plugins/ABI/PowerPC/ABISysV_ppc64.cpp b/lldb/source/Plugins/ABI/PowerPC/ABISysV_ppc64.cpp index 88a82f4a0d20c7f..a3abb15ee625bf2 100644 --- a/lldb/source/Plugins/ABI/PowerPC/ABISysV_ppc64.cpp +++ b/lldb/source/Plugins/ABI/PowerPC/ABISysV_ppc64.cpp @@ -156,7 +156,7 @@ bool ABISysV_ppc64::PrepareTrivialCall(Thread &thread, addr_t sp, if (!reg_ctx->WriteRegisterFromUnsigned(r12_reg_info, func_addr)) return false; -#if defined(__AIX__) +#if defined(_AIX) assert(0); #else // Read TOC pointer value. @@ -279,7 +279,7 @@ bool ABISysV_ppc64::PrepareTrivialCall(Thread &thread, addr_t sp, if (!reg_ctx->WriteRegisterFromUnsigned(r12_reg_info, func_addr)) return false; -#if defined(__AIX__) +#if defined(_AIX) LLDB_LOGF(log, "Writing R2: 0x%" PRIx64, (uint64_t)toc_addr); if (!reg_ctx->WriteRegisterFromUnsigned(r2_reg_info, toc_addr)) return false; diff --git a/lldb/source/Plugins/DynamicLoader/AIX-DYLD/DynamicLoaderAIXDYLD.cpp b/lldb/source/Plugins/DynamicLoader/AIX-DYLD/DynamicLoaderAIXDYLD.cpp index 62663974134b077..7f3a638d5b02847 100644 --- a/lldb/source/Plugins/DynamicLoader/AIX-DYLD/DynamicLoaderAIXDYLD.cpp +++ b/lldb/source/Plugins/DynamicLoader/AIX-DYLD/DynamicLoaderAIXDYLD.cpp @@ -18,7 +18,7 @@ #include "lldb/Target/ThreadPlanStepInstruction.h" #include "lldb/Utility/LLDBLog.h" #include "lldb/Utility/Log.h" -#if defined(__AIX__) +#if defined(_AIX) #include #endif @@ -160,7 +160,7 @@ void DynamicLoaderAIXDYLD::DidAttach() { auto error = m_process->LoadModules(); LLDB_LOG_ERROR(log, std::move(error), "failed to load modules: {0}"); -#if defined(__AIX__) +#if defined(_AIX) // Get struct ld_xinfo (FIXME) struct ld_xinfo ldinfo[64]; Status status = m_process->GetLDXINFO(&(ldinfo[0])); @@ -221,7 +221,7 @@ void DynamicLoaderAIXDYLD::DidLaunch() { LLDB_LOG_ERROR(log, std::move(error), "failed to load modules: {0}"); } -#if defined(__AIX__) +#if defined(_AIX) // Get struct ld_xinfo (FIXME) struct ld_xinfo ldinfo[64]; Status status = m_process->GetLDXINFO(&(ldinfo[0])); diff --git a/lldb/source/Plugins/Instruction/PPC64/EmulateInstructionPPC64.h b/lldb/source/Plugins/Instruction/PPC64/EmulateInstructionPPC64.h index 1576c9700e55724..d98b2880ca3b4d0 100644 --- a/lldb/source/Plugins/Instruction/PPC64/EmulateInstructionPPC64.h +++ b/lldb/source/Plugins/Instruction/PPC64/EmulateInstructionPPC64.h @@ -39,7 +39,7 @@ class EmulateInstructionPPC64 : public EmulateInstruction { return true; case eInstructionTypePCModifying: -#if defined(__AIX__) +#if defined(_AIX) return true; #else return false; diff --git a/lldb/source/Plugins/JITLoader/GDB/JITLoaderGDB.cpp b/lldb/source/Plugins/JITLoader/GDB/JITLoaderGDB.cpp index 690fb0d60a09a9a..9a52fb2f2adc5ac 100644 --- a/lldb/source/Plugins/JITLoader/GDB/JITLoaderGDB.cpp +++ b/lldb/source/Plugins/JITLoader/GDB/JITLoaderGDB.cpp @@ -194,7 +194,7 @@ void JITLoaderGDB::SetJITBreakpoint(lldb_private::ModuleList &module_list) { if (jit_addr == LLDB_INVALID_ADDRESS) return; -#if defined(__AIX__) +#if defined(_AIX) return; #endif diff --git a/lldb/source/Plugins/Language/ObjC/Cocoa.cpp b/lldb/source/Plugins/Language/ObjC/Cocoa.cpp index fb5bc2c58e6fb8b..71f2b127afb128c 100644 --- a/lldb/source/Plugins/Language/ObjC/Cocoa.cpp +++ b/lldb/source/Plugins/Language/ObjC/Cocoa.cpp @@ -1227,7 +1227,7 @@ bool lldb_private::formatters::ObjCSELSummaryProvider( time_t lldb_private::formatters::GetOSXEpoch() { static time_t epoch = 0; if (!epoch) { -#if !defined(__AIX__) +#if !defined(_AIX) #ifndef _WIN32 tzset(); tm tm_epoch; diff --git a/lldb/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp b/lldb/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp index 5ea55772c3aba1b..4f747ab20c9efa8 100644 --- a/lldb/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp +++ b/lldb/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp @@ -8,7 +8,7 @@ #include "ObjectContainerBSDArchive.h" -#if defined(_WIN32) || defined(__ANDROID__) || defined(__AIX__) +#if defined(_WIN32) || defined(__ANDROID__) || defined(_AIX) // Defines from ar, missing on Windows #define SARMAG 8 #define ARFMAG "`\n" diff --git a/lldb/source/Plugins/ObjectContainer/Big-Archive/ObjectContainerBigArchive.cpp b/lldb/source/Plugins/ObjectContainer/Big-Archive/ObjectContainerBigArchive.cpp index 050ad73f1d19af4..38756a0dd29696d 100644 --- a/lldb/source/Plugins/ObjectContainer/Big-Archive/ObjectContainerBigArchive.cpp +++ b/lldb/source/Plugins/ObjectContainer/Big-Archive/ObjectContainerBigArchive.cpp @@ -8,7 +8,7 @@ #include "ObjectContainerBigArchive.h" -#if defined(_WIN32) || defined(__ANDROID__) || defined(__AIX__) +#if defined(_WIN32) || defined(__ANDROID__) || defined(_AIX) // Defines from ar, missing on Windows #define ARMAG "!\n" #define SARMAG 8 diff --git a/lldb/source/Plugins/ObjectFile/Minidump/ObjectFileMinidump.cpp b/lldb/source/Plugins/ObjectFile/Minidump/ObjectFileMinidump.cpp index d8834af2c33ef69..9aab76c6c48baba 100644 --- a/lldb/source/Plugins/ObjectFile/Minidump/ObjectFileMinidump.cpp +++ b/lldb/source/Plugins/ObjectFile/Minidump/ObjectFileMinidump.cpp @@ -51,7 +51,7 @@ size_t ObjectFileMinidump::GetModuleSpecifications( const lldb_private::FileSpec &file, lldb::DataBufferSP &data_sp, lldb::offset_t data_offset, lldb::offset_t file_offset, lldb::offset_t length, lldb_private::ModuleSpecList &specs) { -#if !defined(__AIX__) +#if !defined(_AIX) specs.Clear(); #endif return 0; diff --git a/lldb/source/Plugins/ObjectFile/PDB/ObjectFilePDB.cpp b/lldb/source/Plugins/ObjectFile/PDB/ObjectFilePDB.cpp index 75cc54e4f0d484f..d76d6adb1be2c72 100644 --- a/lldb/source/Plugins/ObjectFile/PDB/ObjectFilePDB.cpp +++ b/lldb/source/Plugins/ObjectFile/PDB/ObjectFilePDB.cpp @@ -117,7 +117,7 @@ size_t ObjectFilePDB::GetModuleSpecifications( llvm::BumpPtrAllocator allocator; std::unique_ptr pdb_file = loadPDBFile(file.GetPath(), allocator); if (!pdb_file){ -#if !defined(__AIX__) +#if !defined(_AIX) return initial_count; #else return specs.GetSize() - initial_count; @@ -127,7 +127,7 @@ size_t ObjectFilePDB::GetModuleSpecifications( auto info_stream = pdb_file->getPDBInfoStream(); if (!info_stream) { llvm::consumeError(info_stream.takeError()); -#if !defined(__AIX__) +#if !defined(_AIX) return initial_count; #else return specs.GetSize() - initial_count; @@ -136,7 +136,7 @@ size_t ObjectFilePDB::GetModuleSpecifications( auto dbi_stream = pdb_file->getPDBDbiStream(); if (!dbi_stream) { llvm::consumeError(dbi_stream.takeError()); -#if !defined(__AIX__) +#if !defined(_AIX) return initial_count; #else return specs.GetSize() - initial_count; diff --git a/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp b/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp index 519ce2ca4a0b24b..02a86234bd3635e 100644 --- a/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp +++ b/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp @@ -254,7 +254,7 @@ size_t ObjectFilePECOFF::GetModuleSpecifications( lldb::offset_t length, lldb_private::ModuleSpecList &specs) { const size_t initial_count = specs.GetSize(); if (!data_sp || !ObjectFilePECOFF::MagicBytesMatch(data_sp)){ -#if !defined(__AIX__) +#if !defined(_AIX) return initial_count; #else return specs.GetSize() - initial_count; @@ -272,7 +272,7 @@ size_t ObjectFilePECOFF::GetModuleSpecifications( if (!binary) { LLDB_LOG_ERROR(log, binary.takeError(), "Failed to create binary for file ({1}): {0}", file); -#if !defined(__AIX__) +#if !defined(_AIX) return initial_count; #else return specs.GetSize() - initial_count; @@ -281,7 +281,7 @@ size_t ObjectFilePECOFF::GetModuleSpecifications( auto *COFFObj = llvm::dyn_cast(binary->get()); if (!COFFObj){ -#if !defined(__AIX__) +#if !defined(_AIX) return initial_count; #else return specs.GetSize() - initial_count; diff --git a/lldb/source/Plugins/Platform/AIX/PlatformAIX.cpp b/lldb/source/Plugins/Platform/AIX/PlatformAIX.cpp index b6b08b73bec4137..5c9447700297891 100644 --- a/lldb/source/Plugins/Platform/AIX/PlatformAIX.cpp +++ b/lldb/source/Plugins/Platform/AIX/PlatformAIX.cpp @@ -31,7 +31,7 @@ // Define these constants from AIX mman.h for use when targeting remote aix // systems even when host has different values. -#if defined(__AIX__) +#if defined(_AIX) #include #endif @@ -80,7 +80,7 @@ void PlatformAIX::Initialize() { PlatformPOSIX::Initialize(); if (g_initialize_count++ == 0) { -#if defined(__AIX__) +#if defined(_AIX) PlatformSP default_platform_sp(new PlatformAIX(true)); default_platform_sp->SetSystemArchitecture(HostInfo::GetArchitecture()); Platform::SetHostPlatform(default_platform_sp); @@ -294,7 +294,7 @@ MmapArgList PlatformAIX::GetMmapArgumentList(const ArchSpec &arch, addr_t addr, addr_t length, unsigned prot, unsigned flags, addr_t fd, addr_t offset) { -#if defined(__AIX__) +#if defined(_AIX) unsigned flags_platform = MAP_VARIABLE | MAP_PRIVATE | MAP_ANONYMOUS; #else unsigned flags_platform = 0; diff --git a/lldb/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp b/lldb/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp index db271357d792ae7..ea758caa653a15a 100644 --- a/lldb/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp +++ b/lldb/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp @@ -46,7 +46,7 @@ bool lldb_private::InferiorCallMmap(Process *process, addr_t &allocated_addr, function_options.include_inlines = false; SymbolContextList sc_list; -#if !defined(__AIX__) +#if !defined(_AIX) process->GetTarget().GetImages().FindFunctions( ConstString("mmap"), eFunctionNameTypeFull, function_options, sc_list); #else @@ -122,7 +122,7 @@ bool lldb_private::InferiorCallMmap(Process *process, addr_t &allocated_addr, MmapArgList args = process->GetTarget().GetPlatform()->GetMmapArgumentList( arch, addr, length, prot_arg, flags, fd, offset); -#if defined(__AIX__) +#if defined(_AIX) lldb::ThreadPlanSP call_plan_sp( new ThreadPlanCallFunction(*thread, mmap_range.GetBaseAddress(), toc_range.GetBaseAddress(), diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp index 443b7c7b2c7fb7f..fa0a3b5d4dc3851 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp @@ -41,7 +41,7 @@ #include "llvm/Config/llvm-config.h" // for LLVM_ENABLE_ZLIB #include "llvm/Support/JSON.h" -#if defined(__AIX__) +#if defined(_AIX) #include #endif @@ -1715,7 +1715,7 @@ Status GDBRemoteCommunicationClient::GetMemoryRegionInfo( return error; } -#if defined(__AIX__) +#if defined(_AIX) Status GDBRemoteCommunicationClient::GetLDXINFO(struct ld_xinfo *info_ptr) { Status error; diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h index 520f37ac5671648..1812fc9b7ca6557 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h @@ -32,7 +32,7 @@ #include "llvm/Support/VersionTuple.h" -#if defined(__AIX__) +#if defined(_AIX) struct ld_xinfo; #endif @@ -200,7 +200,7 @@ class GDBRemoteCommunicationClient : public GDBRemoteClientBase { Status GetMemoryRegionInfo(lldb::addr_t addr, MemoryRegionInfo &range_info); std::optional GetWatchpointSlotCount(); -#if defined(__AIX__) +#if defined(_AIX) Status GetLDXINFO(struct ld_xinfo *info_ptr); #endif diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp index 4f1ef0898ba083c..27be61a47423899 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp @@ -48,7 +48,7 @@ #include "ProcessGDBRemote.h" #include "ProcessGDBRemoteLog.h" #include "lldb/Utility/StringExtractorGDBRemote.h" -#if defined(__AIX__) +#if defined(_AIX) #include #endif @@ -3011,7 +3011,7 @@ GDBRemoteCommunicationServerLLGS::Handle_qLDXINFO(StringExtractorGDBRemote &pack return SendErrorResponse(0xff); } -#if defined(__AIX__) +#if defined(_AIX) // FIXME: buffer size struct ld_xinfo info[64]; if (ptrace64(PT_LDXINFO, m_current_process->GetID(), (long long)&(info[0]), sizeof(info), nullptr) != 0) { diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp index ca381290d0e9f12..5b7ce5f1424d981 100644 --- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp @@ -92,7 +92,7 @@ #include "llvm/Support/Threading.h" #include "llvm/Support/raw_ostream.h" -#if defined(__AIX__) +#if defined(_AIX) #include #endif @@ -2963,7 +2963,7 @@ Status ProcessGDBRemote::DoGetMemoryRegionInfo(addr_t load_addr, return error; } -#if defined(__AIX__) +#if defined(_AIX) Status ProcessGDBRemote::DoGetLDXINFO(struct ld_xinfo *info_ptr) { Status error(m_gdb_comm.GetLDXINFO(info_ptr)); return error; diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h index 82200fbea21cd41..2bf3a04d213d41f 100644 --- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h +++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h @@ -37,7 +37,7 @@ #include "GDBRemoteCommunicationClient.h" #include "GDBRemoteRegisterContext.h" -#if defined(__AIX__) +#if defined(_AIX) struct ld_xinfo; #endif @@ -427,7 +427,7 @@ class ProcessGDBRemote : public Process, Status DoGetMemoryRegionInfo(lldb::addr_t load_addr, MemoryRegionInfo ®ion_info) override; -#if defined(__AIX__) +#if defined(_AIX) Status DoGetLDXINFO(struct ld_xinfo *info_ptr) override; #endif diff --git a/lldb/source/Target/Process.cpp b/lldb/source/Target/Process.cpp index a9aef7ef2185576..e6ae7fc559ef4e0 100644 --- a/lldb/source/Target/Process.cpp +++ b/lldb/source/Target/Process.cpp @@ -75,7 +75,7 @@ #include "lldb/Utility/State.h" #include "lldb/Utility/Timer.h" -#if defined(__AIX__) +#if defined(_AIX) #include #endif @@ -6188,7 +6188,7 @@ Status Process::GetMemoryRegionInfo(lldb::addr_t load_addr, return DoGetMemoryRegionInfo(load_addr, range_info); } -#if defined(__AIX__) +#if defined(_AIX) Status Process::GetLDXINFO(struct ld_xinfo *info_ptr) { return DoGetLDXINFO(info_ptr); } diff --git a/lldb/source/Target/RegisterContextUnwind.cpp b/lldb/source/Target/RegisterContextUnwind.cpp index fbdbc8c63a5d06f..fdf269a3d36531d 100644 --- a/lldb/source/Target/RegisterContextUnwind.cpp +++ b/lldb/source/Target/RegisterContextUnwind.cpp @@ -40,7 +40,7 @@ #include #include -#ifdef __AIX__ +#ifdef _AIX #include "Plugins/Process/Utility/lldb-ppc64le-register-enums.h" #endif @@ -1260,7 +1260,7 @@ bool RegisterContextUnwind::IsTrapHandlerSymbol( // Answer the question: Where did THIS frame save the CALLER frame ("previous" // frame)'s register value? -#ifdef __AIX__ +#ifdef _AIX extern bool UGLY_HACK_NULL_TOPFRAME; #endif @@ -1525,7 +1525,7 @@ RegisterContextUnwind::SavedLocationForRegister( new_regloc.type = UnwindLLDB::ConcreteRegisterLocation::eRegisterInLiveRegisterContext; new_regloc.location.register_number = regnum.GetAsKind(eRegisterKindLLDB); -#ifdef __AIX__ +#ifdef _AIX if (UGLY_HACK_NULL_TOPFRAME && new_regloc.location.register_number == 0x20) { new_regloc.location.register_number = 0x24; } @@ -2390,7 +2390,7 @@ bool RegisterContextUnwind::ReadPC(addr_t &pc) { } } -#ifdef __AIX__ +#ifdef _AIX bool RegisterContextUnwind::ReadLR(addr_t &lr) { if (!IsValid()) return false; diff --git a/lldb/source/Target/UnwindLLDB.cpp b/lldb/source/Target/UnwindLLDB.cpp index 8edf359cac497d6..764bea5bf86c697 100644 --- a/lldb/source/Target/UnwindLLDB.cpp +++ b/lldb/source/Target/UnwindLLDB.cpp @@ -68,7 +68,7 @@ uint32_t UnwindLLDB::DoGetFrameCount() { return m_frames.size(); } -#ifdef __AIX__ +#ifdef _AIX bool UGLY_HACK_NULL_TOPFRAME = false; #endif @@ -95,7 +95,7 @@ bool UnwindLLDB::AddFirstFrame() { if (!reg_ctx_sp->ReadPC(first_cursor_sp->start_pc)) goto unwind_done; -#ifdef __AIX__ +#ifdef _AIX lldb::addr_t lr; if (!reg_ctx_sp->ReadLR(lr)) goto unwind_done; diff --git a/lldb/tools/driver/Driver.cpp b/lldb/tools/driver/Driver.cpp index 45837503e8b73f0..d17ed77485d3104 100644 --- a/lldb/tools/driver/Driver.cpp +++ b/lldb/tools/driver/Driver.cpp @@ -640,7 +640,7 @@ void sigwinch_handler(int signo) { } void sigint_handler(int signo) { -#if defined(_WIN32) || defined(__AIX__) // Restore handler as it is not persistent on Windows +#if defined(_WIN32) || defined(_AIX) // Restore handler as it is not persistent on Windows signal(SIGINT, sigint_handler); #endif static std::atomic_flag g_interrupt_sent = ATOMIC_FLAG_INIT; @@ -729,7 +729,7 @@ static void printHelp(LLDBOptTable &table, llvm::StringRef tool_name) { int main(int argc, char const *argv[]) { // Editline uses for example iswprint which is dependent on LC_CTYPE. // FIXME: this caused unexpected SIGTRAP on AIX -#ifndef __AIX__ +#ifndef _AIX std::setlocale(LC_ALL, ""); std::setlocale(LC_CTYPE, ""); #endif diff --git a/lldb/tools/lldb-server/SystemInitializerLLGS.cpp b/lldb/tools/lldb-server/SystemInitializerLLGS.cpp index 91bb2083a88b594..52c2eae0c90331a 100644 --- a/lldb/tools/lldb-server/SystemInitializerLLGS.cpp +++ b/lldb/tools/lldb-server/SystemInitializerLLGS.cpp @@ -14,7 +14,7 @@ using HostObjectFile = ObjectFileMachO; #elif defined(_WIN32) #include "Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.h" using HostObjectFile = ObjectFilePECOFF; -#elif defined(__AIX__) +#elif defined(_AIX) #include "Plugins/ObjectFile/XCOFF/ObjectFileXCOFF.h" using HostObjectFile = ObjectFileXCOFF; #else @@ -49,7 +49,7 @@ using HostObjectFile = ObjectFileELF; #include "Plugins/Instruction/MIPS/EmulateInstructionMIPS.h" #endif -#if defined(__AIX__) +#if defined(_AIX) #include "Plugins/Instruction/PPC64/EmulateInstructionPPC64.h" #endif @@ -82,7 +82,7 @@ llvm::Error SystemInitializerLLGS::Initialize() { EmulateInstructionRISCV::Initialize(); #endif -#if defined(__AIX__) +#if defined(_AIX) EmulateInstructionPPC64::Initialize(); #endif @@ -108,7 +108,7 @@ void SystemInitializerLLGS::Terminate() { EmulateInstructionRISCV::Terminate(); #endif -#if defined(__AIX__) +#if defined(_AIX) EmulateInstructionPPC64::Terminate(); #endif diff --git a/lldb/tools/lldb-server/lldb-gdbserver.cpp b/lldb/tools/lldb-server/lldb-gdbserver.cpp index 844a6370bdb2e5a..dcbb421a73e25f0 100644 --- a/lldb/tools/lldb-server/lldb-gdbserver.cpp +++ b/lldb/tools/lldb-server/lldb-gdbserver.cpp @@ -45,7 +45,7 @@ #include "Plugins/Process/NetBSD/NativeProcessNetBSD.h" #elif defined(_WIN32) #include "Plugins/Process/Windows/Common/NativeProcessWindows.h" -#elif defined(__AIX__) +#elif defined(_AIX) #include "Plugins/Process/AIX/NativeProcessAIX.h" #endif @@ -72,7 +72,7 @@ typedef process_freebsd::NativeProcessFreeBSD::Manager NativeProcessManager; typedef process_netbsd::NativeProcessNetBSD::Manager NativeProcessManager; #elif defined(_WIN32) typedef NativeProcessWindows::Manager NativeProcessManager; -#elif defined(__AIX__) +#elif defined(_AIX) typedef process_aix::NativeProcessAIX::Manager NativeProcessManager; #else // Dummy implementation to make sure the code compiles diff --git a/lldb/unittests/Host/MainLoopTest.cpp b/lldb/unittests/Host/MainLoopTest.cpp index c76476c94705412..5c042261b9ef219 100644 --- a/lldb/unittests/Host/MainLoopTest.cpp +++ b/lldb/unittests/Host/MainLoopTest.cpp @@ -223,7 +223,7 @@ TEST_F(MainLoopTest, PendingCallbackAfterLoopExited) { loop.AddPendingCallback([&](MainLoopBase &loop) {}); } -#if defined(LLVM_ON_UNIX) && !defined(__AIX__) +#if defined(LLVM_ON_UNIX) && !defined(_AIX) TEST_F(MainLoopTest, DetectsEOF) { PseudoTerminal term; diff --git a/lldb/unittests/Host/PipeTest.cpp b/lldb/unittests/Host/PipeTest.cpp index c1013aa7a7e4ea3..00ffd33d68f7a3f 100644 --- a/lldb/unittests/Host/PipeTest.cpp +++ b/lldb/unittests/Host/PipeTest.cpp @@ -55,7 +55,7 @@ TEST_F(PipeTest, OpenAsReader) { } #endif -#if !defined(__AIX__) +#if !defined(_AIX) TEST_F(PipeTest, WriteWithTimeout) { Pipe pipe; ASSERT_THAT_ERROR(pipe.CreateNew(false).ToError(), llvm::Succeeded()); diff --git a/lldb/unittests/Host/posix/TerminalTest.cpp b/lldb/unittests/Host/posix/TerminalTest.cpp index f3de92c0852b1c3..64e6be64db80c7e 100644 --- a/lldb/unittests/Host/posix/TerminalTest.cpp +++ b/lldb/unittests/Host/posix/TerminalTest.cpp @@ -94,14 +94,14 @@ TEST_F(TerminalTest, SetRaw) { TEST_F(TerminalTest, SetBaudRate) { struct termios terminfo; -#if (defined(__AIX__) && defined(B38400)) || !defined(__AIX__) +#if (defined(_AIX) && defined(B38400)) || !defined(_AIX) ASSERT_THAT_ERROR(m_term.SetBaudRate(38400), llvm::Succeeded()); ASSERT_EQ(tcgetattr(m_fd, &terminfo), 0); EXPECT_EQ(cfgetispeed(&terminfo), static_cast(B38400)); EXPECT_EQ(cfgetospeed(&terminfo), static_cast(B38400)); #endif -#if (defined(__AIX__) && defined(B115200)) || !defined(__AIX__) +#if (defined(_AIX) && defined(B115200)) || !defined(_AIX) ASSERT_THAT_ERROR(m_term.SetBaudRate(115200), llvm::Succeeded()); ASSERT_EQ(tcgetattr(m_fd, &terminfo), 0); EXPECT_EQ(cfgetispeed(&terminfo), static_cast(B115200)); From a8020a6a8692f059679195ae1a0ef5e0eeee94c8 Mon Sep 17 00:00:00 2001 From: Dhruv-Srivastava Date: Thu, 10 Oct 2024 04:52:08 -0500 Subject: [PATCH 11/31] Removed from lldb/CMakeLists --- lldb/CMakeLists.txt | 4 ---- 1 file changed, 4 deletions(-) diff --git a/lldb/CMakeLists.txt b/lldb/CMakeLists.txt index a4fd8bccf056dc5..59cdc4593463c1a 100644 --- a/lldb/CMakeLists.txt +++ b/lldb/CMakeLists.txt @@ -38,10 +38,6 @@ endif() include(LLDBConfig) include(AddLLDB) -if (UNIX AND ${CMAKE_SYSTEM_NAME} MATCHES "AIX") - add_definitions("-D_AIX") -endif() - # Define the LLDB_CONFIGURATION_xxx matching the build type. if(uppercase_CMAKE_BUILD_TYPE STREQUAL "DEBUG" ) add_definitions(-DLLDB_CONFIGURATION_DEBUG) From 7609ad339bfab48412221be54edc2d2d146279c3 Mon Sep 17 00:00:00 2001 From: Lakshmi-Surekha Date: Thu, 14 Nov 2024 13:23:59 -0600 Subject: [PATCH 12/31] Patch for the Merge conflict of xcoff first merge with llvm --- .../ObjectFile/XCOFF/ObjectFileXCOFF.cpp | 253 +++++++++++++++++- 1 file changed, 252 insertions(+), 1 deletion(-) diff --git a/lldb/source/Plugins/ObjectFile/XCOFF/ObjectFileXCOFF.cpp b/lldb/source/Plugins/ObjectFile/XCOFF/ObjectFileXCOFF.cpp index 395a126a01fce0f..a4d9ea295b4c393 100644 --- a/lldb/source/Plugins/ObjectFile/XCOFF/ObjectFileXCOFF.cpp +++ b/lldb/source/Plugins/ObjectFile/XCOFF/ObjectFileXCOFF.cpp @@ -188,7 +188,258 @@ bool ObjectFileXCOFF::ParseHeader() { if (module_sp) { std::lock_guard guard(module_sp->GetMutex()); m_sect_headers.clear(); - lldb::offs + lldb::offset_t offset = 0; + + if (ParseXCOFFHeader(m_data, &offset, m_xcoff_header)) { + m_data.SetAddressByteSize(GetAddressByteSize()); + if (m_xcoff_header.auxhdrsize > 0) + ParseXCOFFOptionalHeader(m_data, &offset); + ParseSectionHeaders(offset); + } + return true; + } + + return false; +} + +bool ObjectFileXCOFF::ParseXCOFFHeader(lldb_private::DataExtractor &data, + lldb::offset_t *offset_ptr, + xcoff_header_t &xcoff_header) { + //FIXME: data.ValidOffsetForDataOfSize + xcoff_header.magic = data.GetU16(offset_ptr); + xcoff_header.nsects = data.GetU16(offset_ptr); + xcoff_header.modtime = data.GetU32(offset_ptr); + xcoff_header.symoff = data.GetU64(offset_ptr); + xcoff_header.auxhdrsize = data.GetU16(offset_ptr); + xcoff_header.flags = data.GetU16(offset_ptr); + xcoff_header.nsyms = data.GetU32(offset_ptr); + return true; +} + +bool ObjectFileXCOFF::ParseXCOFFOptionalHeader(lldb_private::DataExtractor &data, + lldb::offset_t *offset_ptr) { + lldb::offset_t init_offset = *offset_ptr; + //FIXME: data.ValidOffsetForDataOfSize + m_xcoff_aux_header.AuxMagic = data.GetU16(offset_ptr); + m_xcoff_aux_header.Version = data.GetU16(offset_ptr); + m_xcoff_aux_header.ReservedForDebugger = data.GetU32(offset_ptr); + m_xcoff_aux_header.TextStartAddr = data.GetU64(offset_ptr); + m_xcoff_aux_header.DataStartAddr = data.GetU64(offset_ptr); + m_xcoff_aux_header.TOCAnchorAddr = data.GetU64(offset_ptr); + m_xcoff_aux_header.SecNumOfEntryPoint = data.GetU16(offset_ptr); + m_xcoff_aux_header.SecNumOfText = data.GetU16(offset_ptr); + m_xcoff_aux_header.SecNumOfData = data.GetU16(offset_ptr); + m_xcoff_aux_header.SecNumOfTOC = data.GetU16(offset_ptr); + m_xcoff_aux_header.SecNumOfLoader = data.GetU16(offset_ptr); + m_xcoff_aux_header.SecNumOfBSS = data.GetU16(offset_ptr); + m_xcoff_aux_header.MaxAlignOfText = data.GetU16(offset_ptr); + m_xcoff_aux_header.MaxAlignOfData = data.GetU16(offset_ptr); + m_xcoff_aux_header.ModuleType = data.GetU16(offset_ptr); + m_xcoff_aux_header.CpuFlag = data.GetU8(offset_ptr); + m_xcoff_aux_header.CpuType = data.GetU8(offset_ptr); + m_xcoff_aux_header.TextPageSize = data.GetU8(offset_ptr); + m_xcoff_aux_header.DataPageSize = data.GetU8(offset_ptr); + m_xcoff_aux_header.StackPageSize = data.GetU8(offset_ptr); + m_xcoff_aux_header.FlagAndTDataAlignment = data.GetU8(offset_ptr); + m_xcoff_aux_header.TextSize = data.GetU64(offset_ptr); + m_xcoff_aux_header.InitDataSize = data.GetU64(offset_ptr); + m_xcoff_aux_header.BssDataSize = data.GetU64(offset_ptr); + m_xcoff_aux_header.EntryPointAddr = data.GetU64(offset_ptr); + m_xcoff_aux_header.MaxStackSize = data.GetU64(offset_ptr); + m_xcoff_aux_header.MaxDataSize = data.GetU64(offset_ptr); + m_xcoff_aux_header.SecNumOfTData = data.GetU16(offset_ptr); + m_xcoff_aux_header.SecNumOfTBSS = data.GetU16(offset_ptr); + m_xcoff_aux_header.XCOFF64Flag = data.GetU16(offset_ptr); + lldb::offset_t last_offset = *offset_ptr; + if ((last_offset - init_offset) < m_xcoff_header.auxhdrsize) + *offset_ptr += (m_xcoff_header.auxhdrsize - (last_offset - init_offset)); + return true; +} + +bool ObjectFileXCOFF::ParseSectionHeaders( + uint32_t section_header_data_offset) { + const uint32_t nsects = m_xcoff_header.nsects; + m_sect_headers.clear(); + + if (nsects > 0) { + const size_t section_header_byte_size = nsects * m_binary->getSectionHeaderSize(); + lldb_private::DataExtractor section_header_data = + ReadImageData(section_header_data_offset, section_header_byte_size); + + lldb::offset_t offset = 0; + //FIXME: section_header_data.ValidOffsetForDataOfSize + m_sect_headers.resize(nsects); + + for (uint32_t idx = 0; idx < nsects; ++idx) { + const void *name_data = section_header_data.GetData(&offset, 8); + if (name_data) { + memcpy(m_sect_headers[idx].name, name_data, 8); + m_sect_headers[idx].phyaddr = section_header_data.GetU64(&offset); + m_sect_headers[idx].vmaddr = section_header_data.GetU64(&offset); + m_sect_headers[idx].size = section_header_data.GetU64(&offset); + m_sect_headers[idx].offset = section_header_data.GetU64(&offset); + m_sect_headers[idx].reloff = section_header_data.GetU64(&offset); + m_sect_headers[idx].lineoff = section_header_data.GetU64(&offset); + m_sect_headers[idx].nreloc = section_header_data.GetU32(&offset); + m_sect_headers[idx].nline = section_header_data.GetU32(&offset); + m_sect_headers[idx].flags = section_header_data.GetU32(&offset); + offset += 4; + } else { + offset += (m_binary->getSectionHeaderSize() - 8); + } + } + } + + return !m_sect_headers.empty(); +} + +lldb_private::DataExtractor ObjectFileXCOFF::ReadImageData(uint32_t offset, size_t size) { + if (!size) + return {}; + + if (m_data.ValidOffsetForDataOfSize(offset, size)) + return lldb_private::DataExtractor(m_data, offset, size); + + assert(0); + ProcessSP process_sp(m_process_wp.lock()); + lldb_private::DataExtractor data; + if (process_sp) { + auto data_up = std::make_unique(size, 0); + Status readmem_error; + size_t bytes_read = + process_sp->ReadMemory(offset, data_up->GetBytes(), + data_up->GetByteSize(), readmem_error); + if (bytes_read == size) { + DataBufferSP buffer_sp(data_up.release()); + data.SetData(buffer_sp, 0, buffer_sp->GetByteSize()); + } + } + return data; +} + +bool ObjectFileXCOFF::SetLoadAddress(Target &target, lldb::addr_t value, + bool value_is_offset) { + bool changed = false; + ModuleSP module_sp = GetModule(); + if (module_sp) { + size_t num_loaded_sections = 0; + SectionList *section_list = GetSectionList(); + if (section_list) { + const size_t num_sections = section_list->GetSize(); + size_t sect_idx = 0; + + for (sect_idx = 0; sect_idx < num_sections; ++sect_idx) { + // Iterate through the object file sections to find all of the sections + // that have SHF_ALLOC in their flag bits. + SectionSP section_sp(section_list->GetSectionAtIndex(sect_idx)); + if (section_sp && !section_sp->IsThreadSpecific()) { + bool use_offset = false; + if (strcmp(section_sp->GetName().AsCString(), ".text") == 0 || + strcmp(section_sp->GetName().AsCString(), ".data") == 0 || + strcmp(section_sp->GetName().AsCString(), ".bss") == 0) + use_offset = true; + + if (target.GetSectionLoadList().SetSectionLoadAddress( + section_sp, (use_offset ? + (section_sp->GetFileOffset() + value) : (section_sp->GetFileAddress() + value)))) + ++num_loaded_sections; + } + } + changed = num_loaded_sections > 0; + } + } + return changed; +} + +bool ObjectFileXCOFF::SetLoadAddressByType(Target &target, lldb::addr_t value, + bool value_is_offset, int type_id) { + bool changed = false; + ModuleSP module_sp = GetModule(); + if (module_sp) { + size_t num_loaded_sections = 0; + SectionList *section_list = GetSectionList(); + if (section_list) { + const size_t num_sections = section_list->GetSize(); + size_t sect_idx = 0; + + for (sect_idx = 0; sect_idx < num_sections; ++sect_idx) { + // Iterate through the object file sections to find all of the sections + // that have SHF_ALLOC in their flag bits. + SectionSP section_sp(section_list->GetSectionAtIndex(sect_idx)); + if (type_id == 1 && section_sp && strcmp(section_sp->GetName().AsCString(), ".text") == 0) { + if (!section_sp->IsThreadSpecific()) { + if (target.GetSectionLoadList().SetSectionLoadAddress( + section_sp, section_sp->GetFileOffset() + value)) + ++num_loaded_sections; + } + } else if (type_id == 2 && section_sp && strcmp(section_sp->GetName().AsCString(), ".data") == 0) { + if (!section_sp->IsThreadSpecific()) { + if (target.GetSectionLoadList().SetSectionLoadAddress( + section_sp, section_sp->GetFileAddress() + value)) + ++num_loaded_sections; + } + } + } + changed = num_loaded_sections > 0; + } + } + return changed; +} + +ByteOrder ObjectFileXCOFF::GetByteOrder() const { + return eByteOrderBig; +} + +bool ObjectFileXCOFF::IsExecutable() const { + return true; +} + +uint32_t ObjectFileXCOFF::GetAddressByteSize() const { + if (m_xcoff_header.magic == XCOFF::XCOFF64) + return 8; + else if (m_xcoff_header.magic == XCOFF::XCOFF32) + return 4; + return 4; +} + +AddressClass ObjectFileXCOFF::GetAddressClass(addr_t file_addr) { + return AddressClass::eUnknown; +} + +lldb::SymbolType ObjectFileXCOFF::MapSymbolType(llvm::object::SymbolRef::Type sym_type) { + if (sym_type == llvm::object::SymbolRef::ST_Function) + return lldb::eSymbolTypeCode; + else if (sym_type == llvm::object::SymbolRef::ST_Data) + return lldb::eSymbolTypeData; + return lldb::eSymbolTypeInvalid; +} + +void ObjectFileXCOFF::ParseSymtab(Symtab &lldb_symtab) { + SectionList *sect_list = GetSectionList(); + const uint32_t num_syms = m_xcoff_header.nsyms; + uint32_t sidx = 0; + if (num_syms > 0 && m_xcoff_header.symoff > 0) { + const uint32_t symbol_size = XCOFF::SymbolTableEntrySize; + const size_t symbol_data_size = num_syms * symbol_size; + lldb_private::DataExtractor symtab_data = + ReadImageData(m_xcoff_header.symoff, symbol_data_size); + + lldb::offset_t offset = 0; + std::string symbol_name; + Symbol *symbols = lldb_symtab.Resize(num_syms); + llvm::object::symbol_iterator SI = m_binary->symbol_begin(); + for (uint32_t i = 0; i < num_syms; ++i, ++SI) { + xcoff_symbol_t symbol; + const uint32_t symbol_offset = offset; + symbol.value = symtab_data.GetU64(&offset); + symbol.offset = symtab_data.GetU32(&offset); + Expected symbol_name_or_err = m_binary->getStringTableEntry(symbol.offset); + if (!symbol_name_or_err) { + consumeError(symbol_name_or_err.takeError()); + return; + } + StringRef symbol_name_str = symbol_name_or_err.get(); + symbol_name.assign(symbol_name_str.data()); symbol.sect = symtab_data.GetU16(&offset); symbol.type = symtab_data.GetU16(&offset); symbol.storage = symtab_data.GetU8(&offset); From dd56fce276b60b40e1997292b3f554a20157661a Mon Sep 17 00:00:00 2001 From: Dhruv-Srivastava Date: Sun, 17 Nov 2024 00:15:01 -0600 Subject: [PATCH 13/31] Attach fix for AIX --- .../AIX-DYLD/DynamicLoaderAIXDYLD.cpp | 130 ++++++++++++++++++ .../AIX-DYLD/DynamicLoaderAIXDYLD.h | 5 +- 2 files changed, 134 insertions(+), 1 deletion(-) diff --git a/lldb/source/Plugins/DynamicLoader/AIX-DYLD/DynamicLoaderAIXDYLD.cpp b/lldb/source/Plugins/DynamicLoader/AIX-DYLD/DynamicLoaderAIXDYLD.cpp index 7f3a638d5b02847..acaa6a72eddedee 100644 --- a/lldb/source/Plugins/DynamicLoader/AIX-DYLD/DynamicLoaderAIXDYLD.cpp +++ b/lldb/source/Plugins/DynamicLoader/AIX-DYLD/DynamicLoaderAIXDYLD.cpp @@ -18,8 +18,13 @@ #include "lldb/Target/ThreadPlanStepInstruction.h" #include "lldb/Utility/LLDBLog.h" #include "lldb/Utility/Log.h" +#include "llvm/Support/FileSystem.h" #if defined(_AIX) #include +#include +#include +#include +#include #endif /*#include "llvm/ADT/Triple.h" @@ -131,14 +136,139 @@ bool DynamicLoaderAIXDYLD::NotifyBreakpointHit( lldb::user_id_t break_loc_id) { } + +void DynamicLoaderAIXDYLD::ResolveExecutableModule( + lldb::ModuleSP &module_sp) { + Log *log = GetLog(LLDBLog::DynamicLoader); + + if (m_process == nullptr) + return; + + auto &target = m_process->GetTarget(); + const auto platform_sp = target.GetPlatform(); + + ProcessInstanceInfo process_info; + if (!m_process->GetProcessInfo(process_info)) { + LLDB_LOGF(log, + "DynamicLoaderPOSIXDYLD::%s - failed to get process info for " + "pid %" PRIu64, + __FUNCTION__, m_process->GetID()); + return; + } + + char procinfo_path[64], exe_path[PATH_MAX], arg_buffer[8192]; + struct procsinfo64 procs_info; + int32long64_t pid = m_process->GetID(); + std::string proc_file = "/proc/" + std::to_string(pid) + "/psinfo"; + std::string cwd_link = "/proc/" + std::to_string(pid) + "/cwd"; + psinfo_t psinfo; + std::ifstream file(proc_file, std::ios::binary); + if(!file.is_open()) + { + LLDB_LOGF(log, "Error psinfo "); + } + file.read(reinterpret_cast(&psinfo), sizeof(psinfo_t)); + if(!file) + LLDB_LOGF(log, "Error psinfo: Failed to read "); + + std::string relative_path(psinfo.pr_fname); + LLDB_LOGF(log, "relative path %s",relative_path.c_str()); + + char cwd[PATH_MAX]; + char resolved_path[PATH_MAX]; + std::string executable_name; + bool found = 0; + if(readlink(cwd_link.c_str(), cwd, sizeof(cwd)) != -1){ + std::filesystem::path full_path = std::filesystem::path(cwd)/relative_path; + if(realpath(full_path.c_str(), resolved_path)) { + LLDB_LOGF(log, " RESOLVED PATH: %s", resolved_path); + found = 1; + } + else + perror("realpath error");} + + executable_name = resolved_path; + if(found == 0) { + std::string command_line(psinfo.pr_psargs); + LLDB_LOGF(log, "command line %s",command_line.c_str()); + if (!command_line.empty()) { + size_t space1 = command_line.find(' '); + executable_name = command_line.substr(0, space1); + LLDB_LOGF(log, "executable name %s",executable_name.c_str()); + } + } + + LLDB_LOGF(log, "executable name %s",executable_name.c_str()); + /*target.SetExecutableModule(target.GetOrCreateModule(lldb_private::FileSpec(resolved_path), + true),true);*/ + process_info.SetExecutableFile(lldb_private::FileSpec(executable_name), + true); + +/* snprintf(procinfo_path, sizeof(procinfo_path), "/proc/%d/object/a.out", pid); + ssize_t len = readlink(procinfo_path, exe_path, sizeof(exe_path) - 1); + exe_path[len] = '\0'; + int num_procs = getprocs64(&procs_info, sizeof(struct procsinfo64), NULL, 0, + &pid, + 1); + int result = getargs(pid, arg_buffer, sizeof(arg_buffer)); + std::vector args; + char *arg_start = arg_buffer; + while(*arg_start != '\0') { + args.emplace_back(arg_start); + arg_start += strlen(arg_start) + 1; + } + + LLDB_LOGF( + log, "1. DynamicLoaderPOSIXDYLD::%s - got executable by pid %" PRIu64 ": %s" + ", pid: %d, current_path: %s", + __FUNCTION__, m_process->GetID(), + args[0], pid, current_path.c_str()); + LLDB_LOGF( + log, "1. DynamicLoaderPOSIXDYLD::%s - got executable by pid %" PRIu64 ": %s" + "num_procs: %d, pid: %d", + __FUNCTION__, m_process->GetID(), + std::string(procs_info.pi_comm).c_str(), num_procs, pid); + if(num_procs <= 0) + perror("getprocs64 failed"); */ + + LLDB_LOGF( + log, "DynamicLoaderPOSIXDYLD::%s - got executable by pid %" PRIu64 ": %s", + __FUNCTION__, m_process->GetID(), + process_info.GetExecutableFile().GetPath().c_str()); + + ModuleSpec module_spec(process_info.GetExecutableFile(), + process_info.GetArchitecture()); + if (module_sp && module_sp->MatchesModuleSpec(module_spec)) + return; + + const auto executable_search_paths(Target::GetDefaultExecutableSearchPaths()); + auto error = platform_sp->ResolveExecutable( + module_spec, module_sp, + !executable_search_paths.IsEmpty() ? &executable_search_paths : nullptr); + if (error.Fail()) { + StreamString stream; + module_spec.Dump(stream); + + LLDB_LOGF(log, + "DynamicLoaderPOSIXDYLD::%s - failed to resolve executable " + "with module spec \"%s\": %s", + __FUNCTION__, stream.GetData(), error.AsCString()); + return; + } + + target.SetExecutableModule(module_sp, eLoadDependentsNo); +} + void DynamicLoaderAIXDYLD::DidAttach() { Log *log = GetLog(LLDBLog::DynamicLoader); LLDB_LOGF(log, "DynamicLoaderAIXDYLD::%s()", __FUNCTION__); ModuleSP executable = GetTargetExecutable(); + ResolveExecutableModule(executable); if (!executable.get()) return; + LLDB_LOGF(log, "DynamicLoaderAIXDYLD::%s()", __FUNCTION__); // Try to fetch the load address of the file from the process, since there // could be randomization of the load address. diff --git a/lldb/source/Plugins/DynamicLoader/AIX-DYLD/DynamicLoaderAIXDYLD.h b/lldb/source/Plugins/DynamicLoader/AIX-DYLD/DynamicLoaderAIXDYLD.h index ae4b7aca66dcc5f..0ffbe688e0069aa 100644 --- a/lldb/source/Plugins/DynamicLoader/AIX-DYLD/DynamicLoaderAIXDYLD.h +++ b/lldb/source/Plugins/DynamicLoader/AIX-DYLD/DynamicLoaderAIXDYLD.h @@ -24,7 +24,7 @@ class DynamicLoaderAIXDYLD : public DynamicLoader { static void Initialize(); static void Terminate(); - static llvm::StringRef GetPluginNameStatic() { return "windows-dyld"; } + static llvm::StringRef GetPluginNameStatic() { return "aix-dyld"; } static llvm::StringRef GetPluginDescriptionStatic(); static DynamicLoader *CreateInstance(Process *process, bool force); @@ -46,6 +46,9 @@ class DynamicLoaderAIXDYLD : public DynamicLoader { protected: lldb::addr_t GetLoadAddress(lldb::ModuleSP executable); + /// Loads Module from inferior process. + void ResolveExecutableModule(lldb::ModuleSP &module_sp); + private: std::map m_loaded_modules; }; From 48b8b1b6532181acab0ee1710d5f4ab92903ae78 Mon Sep 17 00:00:00 2001 From: Dhruv-Srivastava Date: Mon, 18 Nov 2024 02:56:31 -0600 Subject: [PATCH 14/31] Cleanup --- .../AIX-DYLD/DynamicLoaderAIXDYLD.cpp | 65 +++++-------------- 1 file changed, 17 insertions(+), 48 deletions(-) diff --git a/lldb/source/Plugins/DynamicLoader/AIX-DYLD/DynamicLoaderAIXDYLD.cpp b/lldb/source/Plugins/DynamicLoader/AIX-DYLD/DynamicLoaderAIXDYLD.cpp index acaa6a72eddedee..1a98bb93340437a 100644 --- a/lldb/source/Plugins/DynamicLoader/AIX-DYLD/DynamicLoaderAIXDYLD.cpp +++ b/lldb/source/Plugins/DynamicLoader/AIX-DYLD/DynamicLoaderAIXDYLD.cpp @@ -156,81 +156,50 @@ void DynamicLoaderAIXDYLD::ResolveExecutableModule( return; } - char procinfo_path[64], exe_path[PATH_MAX], arg_buffer[8192]; - struct procsinfo64 procs_info; int32long64_t pid = m_process->GetID(); + char cwd[PATH_MAX], resolved_path[PATH_MAX]; + std::string executable_name; + bool path_resolved = false; + psinfo_t psinfo; + std::string proc_file = "/proc/" + std::to_string(pid) + "/psinfo"; std::string cwd_link = "/proc/" + std::to_string(pid) + "/cwd"; - psinfo_t psinfo; std::ifstream file(proc_file, std::ios::binary); if(!file.is_open()) - { - LLDB_LOGF(log, "Error psinfo "); - } + LLDB_LOGF(log, "Error: Unable to access process info "); + file.read(reinterpret_cast(&psinfo), sizeof(psinfo_t)); if(!file) - LLDB_LOGF(log, "Error psinfo: Failed to read "); + LLDB_LOGF(log, "Process info error: Failed to read "); std::string relative_path(psinfo.pr_fname); - LLDB_LOGF(log, "relative path %s",relative_path.c_str()); + LLDB_LOGF(log, "Relative path %s",relative_path.c_str()); - char cwd[PATH_MAX]; - char resolved_path[PATH_MAX]; - std::string executable_name; - bool found = 0; if(readlink(cwd_link.c_str(), cwd, sizeof(cwd)) != -1){ std::filesystem::path full_path = std::filesystem::path(cwd)/relative_path; if(realpath(full_path.c_str(), resolved_path)) { - LLDB_LOGF(log, " RESOLVED PATH: %s", resolved_path); - found = 1; + LLDB_LOGF(log, "Resolved Path using process info : %s", resolved_path); + path_resolved = true; } else - perror("realpath error");} + LLDB_LOGF(log, "Realpath error: Unable to resolve. "); + } executable_name = resolved_path; - if(found == 0) { + if(path_resolved == false) { std::string command_line(psinfo.pr_psargs); - LLDB_LOGF(log, "command line %s",command_line.c_str()); + LLDB_LOGF(log, "Command line: %s",command_line.c_str()); if (!command_line.empty()) { size_t space1 = command_line.find(' '); executable_name = command_line.substr(0, space1); - LLDB_LOGF(log, "executable name %s",executable_name.c_str()); + LLDB_LOGF(log, "Resolved path using command line arg %s",executable_name.c_str()); } } - LLDB_LOGF(log, "executable name %s",executable_name.c_str()); - /*target.SetExecutableModule(target.GetOrCreateModule(lldb_private::FileSpec(resolved_path), - true),true);*/ + LLDB_LOGF(log, "Executable Name %s",executable_name.c_str()); process_info.SetExecutableFile(lldb_private::FileSpec(executable_name), true); -/* snprintf(procinfo_path, sizeof(procinfo_path), "/proc/%d/object/a.out", pid); - ssize_t len = readlink(procinfo_path, exe_path, sizeof(exe_path) - 1); - exe_path[len] = '\0'; - int num_procs = getprocs64(&procs_info, sizeof(struct procsinfo64), NULL, 0, - &pid, - 1); - int result = getargs(pid, arg_buffer, sizeof(arg_buffer)); - std::vector args; - char *arg_start = arg_buffer; - while(*arg_start != '\0') { - args.emplace_back(arg_start); - arg_start += strlen(arg_start) + 1; - } - - LLDB_LOGF( - log, "1. DynamicLoaderPOSIXDYLD::%s - got executable by pid %" PRIu64 ": %s" - ", pid: %d, current_path: %s", - __FUNCTION__, m_process->GetID(), - args[0], pid, current_path.c_str()); - LLDB_LOGF( - log, "1. DynamicLoaderPOSIXDYLD::%s - got executable by pid %" PRIu64 ": %s" - "num_procs: %d, pid: %d", - __FUNCTION__, m_process->GetID(), - std::string(procs_info.pi_comm).c_str(), num_procs, pid); - if(num_procs <= 0) - perror("getprocs64 failed"); */ - LLDB_LOGF( log, "DynamicLoaderPOSIXDYLD::%s - got executable by pid %" PRIu64 ": %s", __FUNCTION__, m_process->GetID(), From d410734184a681b3e95949d3953142995682d7f6 Mon Sep 17 00:00:00 2001 From: Lakshmi-Surekha Date: Tue, 19 Nov 2024 09:44:42 -0600 Subject: [PATCH 15/31] Patch in MainLoopPosix.cpp for runtime issue --- lldb/source/Host/posix/MainLoopPosix.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lldb/source/Host/posix/MainLoopPosix.cpp b/lldb/source/Host/posix/MainLoopPosix.cpp index f68268f114075df..4c617cdde67ba2d 100644 --- a/lldb/source/Host/posix/MainLoopPosix.cpp +++ b/lldb/source/Host/posix/MainLoopPosix.cpp @@ -149,7 +149,7 @@ Status MainLoopPosix::RunImpl::Poll() { int timeout; timeout = -1; - pthread_sigmask(SIG_SETMASK, &sigmask, &origmask); + pthread_sigmask(SIG_SETMASK, nullptr, &origmask); int ready = poll(read_fds.data(), read_fds.size(), timeout); pthread_sigmask(SIG_SETMASK, &origmask, nullptr); if (ready == -1 && errno != EINTR) From 48f39dadbbdb4874fbd9b6350933dc67e8823339 Mon Sep 17 00:00:00 2001 From: Lakshmi-Surekha Date: Thu, 5 Dec 2024 05:13:14 -0600 Subject: [PATCH 16/31] Patch for compilation failure in DomainSocket.cpp, AbstractSocket.cpp and AbstractSocket.h --- lldb/include/lldb/Host/aix/AbstractSocket.h | 2 +- lldb/source/Host/aix/AbstractSocket.cpp | 3 +-- lldb/source/Host/posix/DomainSocket.cpp | 4 ++++ 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/lldb/include/lldb/Host/aix/AbstractSocket.h b/lldb/include/lldb/Host/aix/AbstractSocket.h index 78a567a6b909532..accfd01457a5e0c 100644 --- a/lldb/include/lldb/Host/aix/AbstractSocket.h +++ b/lldb/include/lldb/Host/aix/AbstractSocket.h @@ -14,7 +14,7 @@ namespace lldb_private { class AbstractSocket : public DomainSocket { public: - AbstractSocket(bool child_processes_inherit); + AbstractSocket(); protected: size_t GetNameOffset() const override; diff --git a/lldb/source/Host/aix/AbstractSocket.cpp b/lldb/source/Host/aix/AbstractSocket.cpp index bfb67d452f7ec07..fddf78f54f46d8a 100644 --- a/lldb/source/Host/aix/AbstractSocket.cpp +++ b/lldb/source/Host/aix/AbstractSocket.cpp @@ -13,8 +13,7 @@ using namespace lldb; using namespace lldb_private; -AbstractSocket::AbstractSocket(bool child_processes_inherit) - : DomainSocket(ProtocolUnixAbstract, child_processes_inherit) {} +AbstractSocket::AbstractSocket() : DomainSocket(ProtocolUnixAbstract) {} size_t AbstractSocket::GetNameOffset() const { return 1; } diff --git a/lldb/source/Host/posix/DomainSocket.cpp b/lldb/source/Host/posix/DomainSocket.cpp index 9a0b385d998bfcc..6cbffb2d9c4bdbd 100644 --- a/lldb/source/Host/posix/DomainSocket.cpp +++ b/lldb/source/Host/posix/DomainSocket.cpp @@ -17,6 +17,10 @@ #include #include +#if defined(_AIX) +#include +#endif + using namespace lldb; using namespace lldb_private; From 97531f7bf6e385f0f51d860c6eea17aeb32f6594 Mon Sep 17 00:00:00 2001 From: Lakshmi-Surekha Date: Thu, 19 Dec 2024 06:38:36 -0600 Subject: [PATCH 17/31] Patch for merge conflict in ObjectFileXCOFF.cpp & ObjectFileXCOFF.h --- .../ObjectFile/XCOFF/ObjectFileXCOFF.cpp | 253 +++++++++++++++++- 1 file changed, 252 insertions(+), 1 deletion(-) diff --git a/lldb/source/Plugins/ObjectFile/XCOFF/ObjectFileXCOFF.cpp b/lldb/source/Plugins/ObjectFile/XCOFF/ObjectFileXCOFF.cpp index 395a126a01fce0f..a4d9ea295b4c393 100644 --- a/lldb/source/Plugins/ObjectFile/XCOFF/ObjectFileXCOFF.cpp +++ b/lldb/source/Plugins/ObjectFile/XCOFF/ObjectFileXCOFF.cpp @@ -188,7 +188,258 @@ bool ObjectFileXCOFF::ParseHeader() { if (module_sp) { std::lock_guard guard(module_sp->GetMutex()); m_sect_headers.clear(); - lldb::offs + lldb::offset_t offset = 0; + + if (ParseXCOFFHeader(m_data, &offset, m_xcoff_header)) { + m_data.SetAddressByteSize(GetAddressByteSize()); + if (m_xcoff_header.auxhdrsize > 0) + ParseXCOFFOptionalHeader(m_data, &offset); + ParseSectionHeaders(offset); + } + return true; + } + + return false; +} + +bool ObjectFileXCOFF::ParseXCOFFHeader(lldb_private::DataExtractor &data, + lldb::offset_t *offset_ptr, + xcoff_header_t &xcoff_header) { + //FIXME: data.ValidOffsetForDataOfSize + xcoff_header.magic = data.GetU16(offset_ptr); + xcoff_header.nsects = data.GetU16(offset_ptr); + xcoff_header.modtime = data.GetU32(offset_ptr); + xcoff_header.symoff = data.GetU64(offset_ptr); + xcoff_header.auxhdrsize = data.GetU16(offset_ptr); + xcoff_header.flags = data.GetU16(offset_ptr); + xcoff_header.nsyms = data.GetU32(offset_ptr); + return true; +} + +bool ObjectFileXCOFF::ParseXCOFFOptionalHeader(lldb_private::DataExtractor &data, + lldb::offset_t *offset_ptr) { + lldb::offset_t init_offset = *offset_ptr; + //FIXME: data.ValidOffsetForDataOfSize + m_xcoff_aux_header.AuxMagic = data.GetU16(offset_ptr); + m_xcoff_aux_header.Version = data.GetU16(offset_ptr); + m_xcoff_aux_header.ReservedForDebugger = data.GetU32(offset_ptr); + m_xcoff_aux_header.TextStartAddr = data.GetU64(offset_ptr); + m_xcoff_aux_header.DataStartAddr = data.GetU64(offset_ptr); + m_xcoff_aux_header.TOCAnchorAddr = data.GetU64(offset_ptr); + m_xcoff_aux_header.SecNumOfEntryPoint = data.GetU16(offset_ptr); + m_xcoff_aux_header.SecNumOfText = data.GetU16(offset_ptr); + m_xcoff_aux_header.SecNumOfData = data.GetU16(offset_ptr); + m_xcoff_aux_header.SecNumOfTOC = data.GetU16(offset_ptr); + m_xcoff_aux_header.SecNumOfLoader = data.GetU16(offset_ptr); + m_xcoff_aux_header.SecNumOfBSS = data.GetU16(offset_ptr); + m_xcoff_aux_header.MaxAlignOfText = data.GetU16(offset_ptr); + m_xcoff_aux_header.MaxAlignOfData = data.GetU16(offset_ptr); + m_xcoff_aux_header.ModuleType = data.GetU16(offset_ptr); + m_xcoff_aux_header.CpuFlag = data.GetU8(offset_ptr); + m_xcoff_aux_header.CpuType = data.GetU8(offset_ptr); + m_xcoff_aux_header.TextPageSize = data.GetU8(offset_ptr); + m_xcoff_aux_header.DataPageSize = data.GetU8(offset_ptr); + m_xcoff_aux_header.StackPageSize = data.GetU8(offset_ptr); + m_xcoff_aux_header.FlagAndTDataAlignment = data.GetU8(offset_ptr); + m_xcoff_aux_header.TextSize = data.GetU64(offset_ptr); + m_xcoff_aux_header.InitDataSize = data.GetU64(offset_ptr); + m_xcoff_aux_header.BssDataSize = data.GetU64(offset_ptr); + m_xcoff_aux_header.EntryPointAddr = data.GetU64(offset_ptr); + m_xcoff_aux_header.MaxStackSize = data.GetU64(offset_ptr); + m_xcoff_aux_header.MaxDataSize = data.GetU64(offset_ptr); + m_xcoff_aux_header.SecNumOfTData = data.GetU16(offset_ptr); + m_xcoff_aux_header.SecNumOfTBSS = data.GetU16(offset_ptr); + m_xcoff_aux_header.XCOFF64Flag = data.GetU16(offset_ptr); + lldb::offset_t last_offset = *offset_ptr; + if ((last_offset - init_offset) < m_xcoff_header.auxhdrsize) + *offset_ptr += (m_xcoff_header.auxhdrsize - (last_offset - init_offset)); + return true; +} + +bool ObjectFileXCOFF::ParseSectionHeaders( + uint32_t section_header_data_offset) { + const uint32_t nsects = m_xcoff_header.nsects; + m_sect_headers.clear(); + + if (nsects > 0) { + const size_t section_header_byte_size = nsects * m_binary->getSectionHeaderSize(); + lldb_private::DataExtractor section_header_data = + ReadImageData(section_header_data_offset, section_header_byte_size); + + lldb::offset_t offset = 0; + //FIXME: section_header_data.ValidOffsetForDataOfSize + m_sect_headers.resize(nsects); + + for (uint32_t idx = 0; idx < nsects; ++idx) { + const void *name_data = section_header_data.GetData(&offset, 8); + if (name_data) { + memcpy(m_sect_headers[idx].name, name_data, 8); + m_sect_headers[idx].phyaddr = section_header_data.GetU64(&offset); + m_sect_headers[idx].vmaddr = section_header_data.GetU64(&offset); + m_sect_headers[idx].size = section_header_data.GetU64(&offset); + m_sect_headers[idx].offset = section_header_data.GetU64(&offset); + m_sect_headers[idx].reloff = section_header_data.GetU64(&offset); + m_sect_headers[idx].lineoff = section_header_data.GetU64(&offset); + m_sect_headers[idx].nreloc = section_header_data.GetU32(&offset); + m_sect_headers[idx].nline = section_header_data.GetU32(&offset); + m_sect_headers[idx].flags = section_header_data.GetU32(&offset); + offset += 4; + } else { + offset += (m_binary->getSectionHeaderSize() - 8); + } + } + } + + return !m_sect_headers.empty(); +} + +lldb_private::DataExtractor ObjectFileXCOFF::ReadImageData(uint32_t offset, size_t size) { + if (!size) + return {}; + + if (m_data.ValidOffsetForDataOfSize(offset, size)) + return lldb_private::DataExtractor(m_data, offset, size); + + assert(0); + ProcessSP process_sp(m_process_wp.lock()); + lldb_private::DataExtractor data; + if (process_sp) { + auto data_up = std::make_unique(size, 0); + Status readmem_error; + size_t bytes_read = + process_sp->ReadMemory(offset, data_up->GetBytes(), + data_up->GetByteSize(), readmem_error); + if (bytes_read == size) { + DataBufferSP buffer_sp(data_up.release()); + data.SetData(buffer_sp, 0, buffer_sp->GetByteSize()); + } + } + return data; +} + +bool ObjectFileXCOFF::SetLoadAddress(Target &target, lldb::addr_t value, + bool value_is_offset) { + bool changed = false; + ModuleSP module_sp = GetModule(); + if (module_sp) { + size_t num_loaded_sections = 0; + SectionList *section_list = GetSectionList(); + if (section_list) { + const size_t num_sections = section_list->GetSize(); + size_t sect_idx = 0; + + for (sect_idx = 0; sect_idx < num_sections; ++sect_idx) { + // Iterate through the object file sections to find all of the sections + // that have SHF_ALLOC in their flag bits. + SectionSP section_sp(section_list->GetSectionAtIndex(sect_idx)); + if (section_sp && !section_sp->IsThreadSpecific()) { + bool use_offset = false; + if (strcmp(section_sp->GetName().AsCString(), ".text") == 0 || + strcmp(section_sp->GetName().AsCString(), ".data") == 0 || + strcmp(section_sp->GetName().AsCString(), ".bss") == 0) + use_offset = true; + + if (target.GetSectionLoadList().SetSectionLoadAddress( + section_sp, (use_offset ? + (section_sp->GetFileOffset() + value) : (section_sp->GetFileAddress() + value)))) + ++num_loaded_sections; + } + } + changed = num_loaded_sections > 0; + } + } + return changed; +} + +bool ObjectFileXCOFF::SetLoadAddressByType(Target &target, lldb::addr_t value, + bool value_is_offset, int type_id) { + bool changed = false; + ModuleSP module_sp = GetModule(); + if (module_sp) { + size_t num_loaded_sections = 0; + SectionList *section_list = GetSectionList(); + if (section_list) { + const size_t num_sections = section_list->GetSize(); + size_t sect_idx = 0; + + for (sect_idx = 0; sect_idx < num_sections; ++sect_idx) { + // Iterate through the object file sections to find all of the sections + // that have SHF_ALLOC in their flag bits. + SectionSP section_sp(section_list->GetSectionAtIndex(sect_idx)); + if (type_id == 1 && section_sp && strcmp(section_sp->GetName().AsCString(), ".text") == 0) { + if (!section_sp->IsThreadSpecific()) { + if (target.GetSectionLoadList().SetSectionLoadAddress( + section_sp, section_sp->GetFileOffset() + value)) + ++num_loaded_sections; + } + } else if (type_id == 2 && section_sp && strcmp(section_sp->GetName().AsCString(), ".data") == 0) { + if (!section_sp->IsThreadSpecific()) { + if (target.GetSectionLoadList().SetSectionLoadAddress( + section_sp, section_sp->GetFileAddress() + value)) + ++num_loaded_sections; + } + } + } + changed = num_loaded_sections > 0; + } + } + return changed; +} + +ByteOrder ObjectFileXCOFF::GetByteOrder() const { + return eByteOrderBig; +} + +bool ObjectFileXCOFF::IsExecutable() const { + return true; +} + +uint32_t ObjectFileXCOFF::GetAddressByteSize() const { + if (m_xcoff_header.magic == XCOFF::XCOFF64) + return 8; + else if (m_xcoff_header.magic == XCOFF::XCOFF32) + return 4; + return 4; +} + +AddressClass ObjectFileXCOFF::GetAddressClass(addr_t file_addr) { + return AddressClass::eUnknown; +} + +lldb::SymbolType ObjectFileXCOFF::MapSymbolType(llvm::object::SymbolRef::Type sym_type) { + if (sym_type == llvm::object::SymbolRef::ST_Function) + return lldb::eSymbolTypeCode; + else if (sym_type == llvm::object::SymbolRef::ST_Data) + return lldb::eSymbolTypeData; + return lldb::eSymbolTypeInvalid; +} + +void ObjectFileXCOFF::ParseSymtab(Symtab &lldb_symtab) { + SectionList *sect_list = GetSectionList(); + const uint32_t num_syms = m_xcoff_header.nsyms; + uint32_t sidx = 0; + if (num_syms > 0 && m_xcoff_header.symoff > 0) { + const uint32_t symbol_size = XCOFF::SymbolTableEntrySize; + const size_t symbol_data_size = num_syms * symbol_size; + lldb_private::DataExtractor symtab_data = + ReadImageData(m_xcoff_header.symoff, symbol_data_size); + + lldb::offset_t offset = 0; + std::string symbol_name; + Symbol *symbols = lldb_symtab.Resize(num_syms); + llvm::object::symbol_iterator SI = m_binary->symbol_begin(); + for (uint32_t i = 0; i < num_syms; ++i, ++SI) { + xcoff_symbol_t symbol; + const uint32_t symbol_offset = offset; + symbol.value = symtab_data.GetU64(&offset); + symbol.offset = symtab_data.GetU32(&offset); + Expected symbol_name_or_err = m_binary->getStringTableEntry(symbol.offset); + if (!symbol_name_or_err) { + consumeError(symbol_name_or_err.takeError()); + return; + } + StringRef symbol_name_str = symbol_name_or_err.get(); + symbol_name.assign(symbol_name_str.data()); symbol.sect = symtab_data.GetU16(&offset); symbol.type = symtab_data.GetU16(&offset); symbol.storage = symtab_data.GetU8(&offset); From 71d2fcff8975831e7f0a657481220749b0a473dc Mon Sep 17 00:00:00 2001 From: Dhruv-Srivastava Date: Tue, 24 Dec 2024 02:05:35 -0600 Subject: [PATCH 18/31] Added upcoming clang-format and other merge changes --- .../posix/ConnectionFileDescriptorPosix.cpp | 9 ++-- lldb/source/Host/posix/DomainSocket.cpp | 5 ++- lldb/source/Host/posix/FileSystemPosix.cpp | 2 +- lldb/source/Host/posix/MainLoopPosix.cpp | 43 ++++++++----------- .../Host/posix/ProcessLauncherPosixFork.cpp | 2 +- lldb/source/Plugins/Language/ObjC/Cocoa.cpp | 17 +++----- .../BSD-Archive/ObjectContainerBSDArchive.cpp | 29 +++++++------ lldb/source/Utility/ArchSpec.cpp | 1 - 8 files changed, 49 insertions(+), 59 deletions(-) diff --git a/lldb/source/Host/posix/ConnectionFileDescriptorPosix.cpp b/lldb/source/Host/posix/ConnectionFileDescriptorPosix.cpp index 32d034e60d26c4c..e3d1300cf76edae 100644 --- a/lldb/source/Host/posix/ConnectionFileDescriptorPosix.cpp +++ b/lldb/source/Host/posix/ConnectionFileDescriptorPosix.cpp @@ -119,8 +119,7 @@ bool ConnectionFileDescriptor::IsConnected() const { ConnectionStatus ConnectionFileDescriptor::Connect(llvm::StringRef path, Status *error_ptr) { - return Connect( - path, [](llvm::StringRef) {}, error_ptr); + return Connect(path, [](llvm::StringRef) {}, error_ptr); } ConnectionStatus @@ -716,8 +715,7 @@ ConnectionFileDescriptor::ConnectFD(llvm::StringRef s, ConnectionStatus ConnectionFileDescriptor::ConnectFile( llvm::StringRef s, socket_id_callback_type socket_id_callback, Status *error_ptr) { -#if !defined(_AIX) -#if LLDB_ENABLE_POSIX +#if LLDB_ENABLE_POSIX && !defined(_AIX) std::string addr_str = s.str(); // file:///PATH int fd = FileSystem::Instance().Open(addr_str.c_str(), O_RDWR); @@ -748,8 +746,7 @@ ConnectionStatus ConnectionFileDescriptor::ConnectFile( m_io_sp = std::make_shared(fd, File::eOpenOptionReadWrite, true); return eConnectionStatusSuccess; -#endif // LLDB_ENABLE_POSIX -#endif +#endif // LLDB_ENABLE_POSIX && !defined(_AIX) llvm_unreachable("this function should be only called w/ LLDB_ENABLE_POSIX"); } diff --git a/lldb/source/Host/posix/DomainSocket.cpp b/lldb/source/Host/posix/DomainSocket.cpp index 6cbffb2d9c4bdbd..28db5964a5a8a66 100644 --- a/lldb/source/Host/posix/DomainSocket.cpp +++ b/lldb/source/Host/posix/DomainSocket.cpp @@ -89,8 +89,9 @@ Status DomainSocket::Connect(llvm::StringRef name) { m_socket = CreateSocket(kDomain, kType, 0, error); if (error.Fail()) return error; - if (llvm::sys::RetryAfterSignal(-1, ::connect, GetNativeSocket(), - (struct sockaddr *)&saddr_un, saddr_un_len) < 0) + if (llvm::sys::RetryAfterSignal(-1, ::connect, GetNativeSocket(), + (struct sockaddr *)&saddr_un, + saddr_un_len) < 0) SetLastError(error); return error; diff --git a/lldb/source/Host/posix/FileSystemPosix.cpp b/lldb/source/Host/posix/FileSystemPosix.cpp index 21da5612ff6b8d8..1a84f550662d753 100644 --- a/lldb/source/Host/posix/FileSystemPosix.cpp +++ b/lldb/source/Host/posix/FileSystemPosix.cpp @@ -11,7 +11,7 @@ // C includes #include #include -#if !defined(_AIX) +#ifndef _AIX #include #endif #include diff --git a/lldb/source/Host/posix/MainLoopPosix.cpp b/lldb/source/Host/posix/MainLoopPosix.cpp index 125b954023dc081..e4ff928a5896247 100644 --- a/lldb/source/Host/posix/MainLoopPosix.cpp +++ b/lldb/source/Host/posix/MainLoopPosix.cpp @@ -99,6 +99,7 @@ class MainLoopPosix::RunImpl { ~RunImpl() = default; Status Poll(); + int StartPoll(std::optional point); void ProcessReadEvents(); private: @@ -159,6 +160,22 @@ MainLoopPosix::RunImpl::RunImpl(MainLoopPosix &loop) : loop(loop) { read_fds.reserve(loop.m_read_fds.size()); } +int MainLoopPosix::RunImpl::StartPoll( + std::optional point) { +#if HAVE_PPOLL + return ppoll(read_fds.data(), read_fds.size(), ToTimeSpec(point), + /*sigmask=*/nullptr); +#else + using namespace std::chrono; + int timeout = -1; + if (point) { + nanoseconds dur = std::max(*point - steady_clock::now(), nanoseconds(0)); + timeout = ceil(dur).count(); + } + return poll(read_fds.data(), read_fds.size(), timeout); +#endif +} + Status MainLoopPosix::RunImpl::Poll() { read_fds.clear(); @@ -169,24 +186,10 @@ Status MainLoopPosix::RunImpl::Poll() { pfd.revents = 0; read_fds.push_back(pfd); } + int ready = StartPoll(loop.GetNextWakeupTime()); -#if defined(_AIX) - sigset_t origmask; - int timeout; - - timeout = -1; - pthread_sigmask(SIG_SETMASK, nullptr, &origmask); - int ready = poll(read_fds.data(), read_fds.size(), timeout); - pthread_sigmask(SIG_SETMASK, &origmask, nullptr); if (ready == -1 && errno != EINTR) return Status(errno, eErrorTypePOSIX); -#else - if (ppoll(read_fds.data(), read_fds.size(), - ToTimeSpec(loop.GetNextWakeupTime()), - /*sigmask=*/nullptr) == -1 && - errno != EINTR) - return Status(errno, eErrorTypePOSIX); -#endif return Status(); } @@ -291,16 +294,6 @@ MainLoopPosix::RegisterSignal(int signo, const Callback &callback, UNUSED_IF_ASSERT_DISABLED(ret); assert(ret == 0 && "sigaction failed"); -#if HAVE_SYS_EVENT_H - struct kevent ev; - EV_SET(&ev, signo, EVFILT_SIGNAL, EV_ADD, 0, 0, 0); - ret = kevent(m_kqueue, &ev, 1, nullptr, 0, nullptr); - assert(ret == 0); -#endif - - // If we're using kqueue, the signal needs to be unblocked in order to - // receive it. If using pselect/ppoll, we need to block it, and later unblock - // it as a part of the system call. ret = pthread_sigmask(SIG_UNBLOCK, &new_action.sa_mask, &old_set); assert(ret == 0 && "pthread_sigmask failed"); info.was_blocked = sigismember(&old_set, signo); diff --git a/lldb/source/Host/posix/ProcessLauncherPosixFork.cpp b/lldb/source/Host/posix/ProcessLauncherPosixFork.cpp index 52fc58aa21bf45c..7b8b42a4b7fe07a 100644 --- a/lldb/source/Host/posix/ProcessLauncherPosixFork.cpp +++ b/lldb/source/Host/posix/ProcessLauncherPosixFork.cpp @@ -197,7 +197,7 @@ struct ForkLaunchInfo { #else if (ptrace(PT_TRACE_ME, 0, nullptr, 0) == -1) #endif - ExitWithError(error_fd, "ptrace"); + ExitWithError(error_fd, "ptrace"); } // Execute. We should never return... diff --git a/lldb/source/Plugins/Language/ObjC/Cocoa.cpp b/lldb/source/Plugins/Language/ObjC/Cocoa.cpp index 1d841a032aa6e32..1d79edbede5d67b 100644 --- a/lldb/source/Plugins/Language/ObjC/Cocoa.cpp +++ b/lldb/source/Plugins/Language/ObjC/Cocoa.cpp @@ -31,7 +31,6 @@ #include "llvm/ADT/APInt.h" #include "llvm/ADT/bit.h" - using namespace lldb; using namespace lldb_private; using namespace lldb_private::formatters; @@ -267,21 +266,21 @@ bool lldb_private::formatters::NSIndexSetSummaryProvider( if (class_name == "NSIndexSet" || class_name == "NSMutableIndexSet") { // Foundation version 2000 added a bitmask if the index set fit in 64 bits // and a Tagged Pointer version if the bitmask is small enough to fit in - // the tagged pointer payload. + // the tagged pointer payload. // It also changed the layout (but not the size) of the set descriptor. // First check whether this is a tagged pointer. The bitmask will be in // the payload of the tagged pointer. uint64_t payload; - if (runtime->GetFoundationVersion() >= 2000 - && descriptor->GetTaggedPointerInfo(nullptr, nullptr, &payload)) { + if (runtime->GetFoundationVersion() >= 2000 && + descriptor->GetTaggedPointerInfo(nullptr, nullptr, &payload)) { count = llvm::popcount(payload); break; } // The first 32 bits describe the index set in all cases: Status error; uint32_t mode = process_sp->ReadUnsignedIntegerFromMemory( - valobj_addr + ptr_size, 4, 0, error); + valobj_addr + ptr_size, 4, 0, error); if (error.Fail()) return false; // Now check if the index is held in a bitmask in the object: @@ -292,7 +291,7 @@ bool lldb_private::formatters::NSIndexSetSummaryProvider( if ((mode & 2) == 2) { // The bitfield is a 64 bit uint at the beginning of the data var. uint64_t bitfield = process_sp->ReadUnsignedIntegerFromMemory( - valobj_addr + 2 * ptr_size, 8, 0, error); + valobj_addr + 2 * ptr_size, 8, 0, error); if (error.Fail()) return false; count = llvm::popcount(bitfield); @@ -309,7 +308,7 @@ bool lldb_private::formatters::NSIndexSetSummaryProvider( count = 0; break; } - + if ((mode & 2) == 2) mode = 1; // this means the set only has one range else @@ -1227,8 +1226,7 @@ bool lldb_private::formatters::ObjCSELSummaryProvider( time_t lldb_private::formatters::GetOSXEpoch() { static time_t epoch = 0; if (!epoch) { -#if !defined(_AIX) -#ifndef _WIN32 +#if !defined(_WIN32) && !defined(_AIX) tzset(); tm tm_epoch; tm_epoch.tm_sec = 0; @@ -1241,7 +1239,6 @@ time_t lldb_private::formatters::GetOSXEpoch() { tm_epoch.tm_gmtoff = 0; tm_epoch.tm_zone = nullptr; epoch = timegm(&tm_epoch); -#endif #endif } return epoch; diff --git a/lldb/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp b/lldb/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp index 4f747ab20c9efa8..b202898ff438a63 100644 --- a/lldb/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp +++ b/lldb/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp @@ -81,10 +81,10 @@ size_t ObjectContainerBSDArchive::Archive::ParseObjects() { std::unique_ptr mem_buffer = llvm::MemoryBuffer::getMemBuffer( - llvm::StringRef((const char *)data.GetDataStart(), - data.GetByteSize()), - llvm::StringRef(), - /*RequiresNullTerminator=*/false); + llvm::StringRef((const char *)data.GetDataStart(), + data.GetByteSize()), + llvm::StringRef(), + /*RequiresNullTerminator=*/false); auto exp_ar = llvm::object::Archive::create(mem_buffer->getMemBufferRef()); if (!exp_ar) { @@ -95,7 +95,7 @@ size_t ObjectContainerBSDArchive::Archive::ParseObjects() { llvm::Error iter_err = llvm::Error::success(); Object obj; - for (const auto &child: llvm_archive->children(iter_err)) { + for (const auto &child : llvm_archive->children(iter_err)) { obj.Clear(); auto exp_name = child.getName(); if (exp_name) { @@ -111,7 +111,9 @@ size_t ObjectContainerBSDArchive::Archive::ParseObjects() { obj.modification_time = std::chrono::duration_cast( std::chrono::time_point_cast( - exp_mtime.get()).time_since_epoch()).count(); + exp_mtime.get()) + .time_since_epoch()) + .count(); } else { LLDB_LOG_ERROR(l, exp_mtime.takeError(), "failed to get archive object time: {0}"); @@ -331,21 +333,21 @@ ObjectContainer *ObjectContainerBSDArchive::CreateInstance( ArchiveType ObjectContainerBSDArchive::MagicBytesMatch(const DataExtractor &data) { uint32_t offset = 0; - const char *armag = (const char *)data.PeekData(offset, - sizeof(ar_hdr) + SARMAG); + const char *armag = + (const char *)data.PeekData(offset, sizeof(ar_hdr) + SARMAG); if (armag == nullptr) return ArchiveType::Invalid; ArchiveType result = ArchiveType::Invalid; if (strncmp(armag, ArchiveMagic, SARMAG) == 0) - result = ArchiveType::Archive; + result = ArchiveType::Archive; else if (strncmp(armag, ThinArchiveMagic, SARMAG) == 0) - result = ArchiveType::ThinArchive; + result = ArchiveType::ThinArchive; else - return ArchiveType::Invalid; + return ArchiveType::Invalid; armag += offsetof(struct ar_hdr, ar_fmag) + SARMAG; if (strncmp(armag, ARFMAG, 2) == 0) - return result; + return result; return ArchiveType::Invalid; } @@ -443,7 +445,8 @@ size_t ObjectContainerBSDArchive::GetModuleSpecifications( return 0; const size_t initial_count = specs.GetSize(); - llvm::sys::TimePoint<> file_mod_time = FileSystem::Instance().GetModificationTime(file); + llvm::sys::TimePoint<> file_mod_time = + FileSystem::Instance().GetModificationTime(file); Archive::shared_ptr archive_sp( Archive::FindCachedArchive(file, ArchSpec(), file_mod_time, file_offset)); bool set_archive_arch = false; diff --git a/lldb/source/Utility/ArchSpec.cpp b/lldb/source/Utility/ArchSpec.cpp index ac91183a271cc65..85bb85044ec156c 100644 --- a/lldb/source/Utility/ArchSpec.cpp +++ b/lldb/source/Utility/ArchSpec.cpp @@ -14,7 +14,6 @@ #include "lldb/lldb-defines.h" #include "llvm/ADT/STLExtras.h" #include "llvm/BinaryFormat/COFF.h" -#include "llvm/BinaryFormat/XCOFF.h" #include "llvm/BinaryFormat/ELF.h" #include "llvm/BinaryFormat/MachO.h" #include "llvm/BinaryFormat/XCOFF.h" From 8fcf69ed77148f8b339b87f75ed97e5ce719b4ba Mon Sep 17 00:00:00 2001 From: Dhruv-Srivastava Date: Fri, 27 Dec 2024 06:50:27 -0600 Subject: [PATCH 19/31] Some Updates --- lldb/include/lldb/Host/aix/HostInfoAIX.h | 11 +-- lldb/source/Host/aix/HostInfoAIX.cpp | 65 +------------- .../ObjectFile/XCOFF/ObjectFileXCOFF.cpp | 87 +++++++++---------- .../ObjectFile/XCOFF/ObjectFileXCOFF.h | 11 ++- 4 files changed, 50 insertions(+), 124 deletions(-) diff --git a/lldb/include/lldb/Host/aix/HostInfoAIX.h b/lldb/include/lldb/Host/aix/HostInfoAIX.h index ced4cf34d38a817..ba727e1d5f17126 100644 --- a/lldb/include/lldb/Host/aix/HostInfoAIX.h +++ b/lldb/include/lldb/Host/aix/HostInfoAIX.h @@ -6,16 +6,14 @@ // //===----------------------------------------------------------------------===// -#ifndef lldb_Host_aix_HostInfoAIX_h_ -#define lldb_Host_aix_HostInfoAIX_h_ +#ifndef LLDB_HOST_AIX_HOSTINFOAIX_H_ +#define LLDB_HOST_AIX_HOSTINFOAIX_H_ #include "lldb/Host/posix/HostInfoPosix.h" #include "lldb/Utility/FileSpec.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/VersionTuple.h" -#include - namespace lldb_private { class HostInfoAIX : public HostInfoPosix { @@ -25,15 +23,10 @@ class HostInfoAIX : public HostInfoPosix { static void Initialize(SharedLibraryDirectoryHelper *helper = nullptr); static void Terminate(); - static llvm::VersionTuple GetOSVersion(); - static std::optional GetOSBuildString(); static llvm::StringRef GetDistributionId(); static FileSpec GetProgramFileSpec(); protected: - static bool ComputeSupportExeDirectory(FileSpec &file_spec); - static bool ComputeSystemPluginsDirectory(FileSpec &file_spec); - static bool ComputeUserPluginsDirectory(FileSpec &file_spec); static void ComputeHostArchitectureSupport(ArchSpec &arch_32, ArchSpec &arch_64); }; diff --git a/lldb/source/Host/aix/HostInfoAIX.cpp b/lldb/source/Host/aix/HostInfoAIX.cpp index 8bda09e01741b6a..ef07b07c8cab21c 100644 --- a/lldb/source/Host/aix/HostInfoAIX.cpp +++ b/lldb/source/Host/aix/HostInfoAIX.cpp @@ -29,8 +29,6 @@ namespace { struct HostInfoAIXFields { llvm::once_flag m_distribution_once_flag; std::string m_distribution_id; - llvm::once_flag m_os_version_once_flag; - llvm::VersionTuple m_os_version; }; } // namespace @@ -49,33 +47,6 @@ void HostInfoAIX::Terminate() { HostInfoBase::Terminate(); } -llvm::VersionTuple HostInfoAIX::GetOSVersion() { - assert(g_fields && "Missing call to Initialize?"); - llvm::call_once(g_fields->m_os_version_once_flag, []() { - struct utsname un; - if (uname(&un) != 0) - return; - - llvm::StringRef release = un.release; - // The kernel release string can include a lot of stuff (e.g. - // 4.9.0-6-amd64). We're only interested in the numbered prefix. - release = release.substr(0, release.find_first_not_of("0123456789.")); - g_fields->m_os_version.tryParse(release); - }); - - return g_fields->m_os_version; -} - -std::optional HostInfoAIX::GetOSBuildString() { - struct utsname un; - ::memset(&un, 0, sizeof(utsname)); - - if (uname(&un) < 0) - return std::nullopt; - - return std::string(un.release); -} - llvm::StringRef HostInfoAIX::GetDistributionId() { assert(g_fields && "Missing call to Initialize?"); // Try to run 'lbs_release -i', and use that response for the distribution @@ -122,8 +93,7 @@ llvm::StringRef HostInfoAIX::GetDistributionId() { if (strstr(distribution_id, distributor_id_key)) { // strip newlines std::string id_string(distribution_id + strlen(distributor_id_key)); - id_string.erase(std::remove(id_string.begin(), id_string.end(), '\n'), - id_string.end()); + llvm::erase(id_string, '\n'); // lower case it and convert whitespace to underscores std::transform( @@ -167,42 +137,11 @@ FileSpec HostInfoAIX::GetProgramFileSpec() { return g_program_filespec; } -bool HostInfoAIX::ComputeSupportExeDirectory(FileSpec &file_spec) { - if (HostInfoPosix::ComputeSupportExeDirectory(file_spec) && - file_spec.IsAbsolute() && FileSystem::Instance().Exists(file_spec)) - return true; - file_spec.SetDirectory(GetProgramFileSpec().GetDirectory()); - return !file_spec.GetDirectory().IsEmpty(); -} - -bool HostInfoAIX::ComputeSystemPluginsDirectory(FileSpec &file_spec) { - FileSpec temp_file("/usr/" LLDB_INSTALL_LIBDIR_BASENAME "/lldb/plugins"); - FileSystem::Instance().Resolve(temp_file); - file_spec.SetDirectory(temp_file.GetPath()); - return true; -} - -bool HostInfoAIX::ComputeUserPluginsDirectory(FileSpec &file_spec) { - // XDG Base Directory Specification - // http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html If - // XDG_DATA_HOME exists, use that, otherwise use ~/.local/share/lldb. - const char *xdg_data_home = getenv("XDG_DATA_HOME"); - if (xdg_data_home && xdg_data_home[0]) { - std::string user_plugin_dir(xdg_data_home); - user_plugin_dir += "/lldb"; - file_spec.SetDirectory(user_plugin_dir.c_str()); - } else - file_spec.SetDirectory("~/.local/share/lldb"); - return true; -} - void HostInfoAIX::ComputeHostArchitectureSupport(ArchSpec &arch_32, ArchSpec &arch_64) { HostInfoPosix::ComputeHostArchitectureSupport(arch_32, arch_64); - const char *distribution_id = GetDistributionId().data(); - - // On Linux, "unknown" in the vendor slot isn't what we want for the default + // "unknown" in the vendor slot isn't what we want for the default // triple. It's probably an artifact of config.guess. if (arch_32.IsValid()) { if (arch_32.GetTriple().getVendor() == llvm::Triple::UnknownVendor) diff --git a/lldb/source/Plugins/ObjectFile/XCOFF/ObjectFileXCOFF.cpp b/lldb/source/Plugins/ObjectFile/XCOFF/ObjectFileXCOFF.cpp index a4d9ea295b4c393..afd8027bab06c3d 100644 --- a/lldb/source/Plugins/ObjectFile/XCOFF/ObjectFileXCOFF.cpp +++ b/lldb/source/Plugins/ObjectFile/XCOFF/ObjectFileXCOFF.cpp @@ -1,4 +1,5 @@ -//===-- ObjectFileXCOFF.cpp -------------------------------------------------===// +//===-- ObjectFileXCOFF.cpp +//-------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -7,13 +8,6 @@ //===----------------------------------------------------------------------===// #include "ObjectFileXCOFF.h" - -#include -#include -#include -#include - -#include "lldb/Utility/FileSpecList.h" #include "lldb/Core/Module.h" #include "lldb/Core/ModuleSpec.h" #include "lldb/Core/PluginManager.h" @@ -28,6 +22,7 @@ #include "lldb/Target/Target.h" #include "lldb/Utility/ArchSpec.h" #include "lldb/Utility/DataBufferHeap.h" +#include "lldb/Utility/FileSpecList.h" #include "lldb/Utility/LLDBLog.h" #include "lldb/Utility/Log.h" #include "lldb/Utility/RangeMap.h" @@ -38,12 +33,16 @@ #include "llvm/ADT/PointerUnion.h" #include "llvm/ADT/StringRef.h" #include "llvm/BinaryFormat/XCOFF.h" +#include "llvm/Object/XCOFFObjectFile.h" #include "llvm/Object/Decompressor.h" #include "llvm/Support/CRC.h" #include "llvm/Support/FormatVariadic.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/MemoryBuffer.h" -#include "llvm/Object/XCOFFObjectFile.h" +#include +#include +#include +#include using namespace llvm; using namespace lldb; @@ -69,21 +68,19 @@ void ObjectFileXCOFF::Terminate() { bool UGLY_FLAG_FOR_AIX __attribute__((weak)) = false; ObjectFile *ObjectFileXCOFF::CreateInstance(const lldb::ModuleSP &module_sp, - DataBufferSP data_sp, - lldb::offset_t data_offset, - const lldb_private::FileSpec *file, - lldb::offset_t file_offset, - lldb::offset_t length) { + DataBufferSP data_sp, + lldb::offset_t data_offset, + const lldb_private::FileSpec *file, + lldb::offset_t file_offset, + lldb::offset_t length) { if (!data_sp) { data_sp = MapFileData(*file, length, file_offset); if (!data_sp) return nullptr; data_offset = 0; } - if (!ObjectFileXCOFF::MagicBytesMatch(data_sp, data_offset, length)) return nullptr; - // Update the data to contain the entire file if it doesn't already if (data_sp->GetByteSize() < length) { data_sp = MapFileData(*file, length, file_offset); @@ -114,15 +111,15 @@ bool ObjectFileXCOFF::CreateBinary() { Log *log = GetLog(LLDBLog::Object); - auto binary = llvm::object::XCOFFObjectFile::createObjectFile(llvm::MemoryBufferRef( - toStringRef(m_data.GetData()), m_file.GetFilename().GetStringRef()), - file_magic::xcoff_object_64); + auto binary = llvm::object::ObjectFile::createObjectFile( + llvm::MemoryBufferRef(toStringRef(m_data.GetData()), + m_file.GetFilename().GetStringRef()), + file_magic::xcoff_object_64); if (!binary) { LLDB_LOG_ERROR(log, binary.takeError(), "Failed to create binary for file ({1}): {0}", m_file); return false; } - // Make sure we only handle COFF format. m_binary = llvm::unique_dyn_cast(std::move(*binary)); @@ -132,6 +129,7 @@ bool ObjectFileXCOFF::CreateBinary() { LLDB_LOG(log, "this = {0}, module = {1} ({2}), file = {3}, binary = {4}", this, GetModule().get(), GetModule()->GetSpecificationDescription(), m_file.GetPath(), m_binary.get()); + return true; } @@ -148,9 +146,12 @@ size_t ObjectFileXCOFF::GetModuleSpecifications( const size_t initial_count = specs.GetSize(); if (ObjectFileXCOFF::MagicBytesMatch(data_sp, 0, data_sp->GetByteSize())) { - ArchSpec arch_spec = ArchSpec(eArchTypeXCOFF, XCOFF::TCPU_PPC64, LLDB_INVALID_CPUTYPE); + ArchSpec arch_spec = + ArchSpec(eArchTypeXCOFF, XCOFF::TCPU_PPC64, LLDB_INVALID_CPUTYPE); ModuleSpec spec(file, arch_spec); - spec.GetArchitecture().SetArchitecture(eArchTypeXCOFF, XCOFF::TCPU_PPC64, LLDB_INVALID_CPUTYPE, llvm::Triple::AIX); + spec.GetArchitecture().SetArchitecture(eArchTypeXCOFF, XCOFF::TCPU_PPC64, + LLDB_INVALID_CPUTYPE, + llvm::Triple::AIX); specs.Append(spec); } return specs.GetSize() - initial_count; @@ -158,11 +159,9 @@ size_t ObjectFileXCOFF::GetModuleSpecifications( static uint32_t XCOFFHeaderSizeFromMagic(uint32_t magic) { switch (magic) { - /* TODO: 32bit not supported yet - case XCOFF::XCOFF32: - return sizeof(struct llvm::object::XCOFFFileHeader32); - */ - + // TODO: 32bit not supported. + // case XCOFF::XCOFF32: + // return sizeof(struct llvm::object::XCOFFFileHeader32); case XCOFF::XCOFF64: return sizeof(struct llvm::object::XCOFFFileHeader64); break; @@ -174,10 +173,12 @@ static uint32_t XCOFFHeaderSizeFromMagic(uint32_t magic) { } bool ObjectFileXCOFF::MagicBytesMatch(DataBufferSP &data_sp, - lldb::addr_t data_offset, - lldb::addr_t data_length) { - lldb_private::DataExtractor data; + lldb::addr_t data_offset, + lldb::addr_t data_length) { + lldb_private::DataExtractor data; data.SetData(data_sp, data_offset, data_length); + // Need to set this as XCOFF is only compatible with Big Endian + data.SetByteOrder(eByteOrderBig); lldb::offset_t offset = 0; uint16_t magic = data.GetU16(&offset); return XCOFFHeaderSizeFromMagic(magic) != 0; @@ -386,13 +387,10 @@ bool ObjectFileXCOFF::SetLoadAddressByType(Target &target, lldb::addr_t value, return changed; } -ByteOrder ObjectFileXCOFF::GetByteOrder() const { - return eByteOrderBig; -} -bool ObjectFileXCOFF::IsExecutable() const { - return true; -} +ByteOrder ObjectFileXCOFF::GetByteOrder() const { return eByteOrderBig; } + +bool ObjectFileXCOFF::IsExecutable() const { return true; } uint32_t ObjectFileXCOFF::GetAddressByteSize() const { if (m_xcoff_header.magic == XCOFF::XCOFF64) @@ -592,13 +590,12 @@ void ObjectFileXCOFF::Dump(Stream *s) { } ArchSpec ObjectFileXCOFF::GetArchitecture() { - ArchSpec arch_spec = ArchSpec(eArchTypeXCOFF, XCOFF::TCPU_PPC64, LLDB_INVALID_CPUTYPE); + ArchSpec arch_spec = + ArchSpec(eArchTypeXCOFF, XCOFF::TCPU_PPC64, LLDB_INVALID_CPUTYPE); return arch_spec; } -UUID ObjectFileXCOFF::GetUUID() { - return UUID(); -} +UUID ObjectFileXCOFF::GetUUID() { return UUID(); } std::optional ObjectFileXCOFF::GetDebugLink() { return std::nullopt; @@ -724,16 +721,14 @@ lldb_private::Address ObjectFileXCOFF::GetBaseAddress() { } ObjectFile::Type ObjectFileXCOFF::CalculateType() { - if (m_xcoff_header.flags & XCOFF::F_EXEC) + if (m_binary->fileHeader64()->Flags & XCOFF::F_EXEC) return eTypeExecutable; - else if (m_xcoff_header.flags & XCOFF::F_SHROBJ) + else if (m_binary->fileHeader64()->Flags & XCOFF::F_SHROBJ) return eTypeSharedLibrary; return eTypeUnknown; } -ObjectFile::Strata ObjectFileXCOFF::CalculateStrata() { - return eStrataUnknown; -} +ObjectFile::Strata ObjectFileXCOFF::CalculateStrata() { return eStrataUnknown; } llvm::StringRef ObjectFileXCOFF::StripLinkerSymbolAnnotations(llvm::StringRef symbol_name) const { @@ -752,7 +747,7 @@ ObjectFileXCOFF::GetLoadableData(Target &target) { lldb::WritableDataBufferSP ObjectFileXCOFF::MapFileDataWritable(const FileSpec &file, uint64_t Size, - uint64_t Offset) { + uint64_t Offset) { return FileSystem::Instance().CreateWritableDataBuffer(file.GetPath(), Size, Offset); } diff --git a/lldb/source/Plugins/ObjectFile/XCOFF/ObjectFileXCOFF.h b/lldb/source/Plugins/ObjectFile/XCOFF/ObjectFileXCOFF.h index 5a12d16886489d5..f827fca3932f476 100644 --- a/lldb/source/Plugins/ObjectFile/XCOFF/ObjectFileXCOFF.h +++ b/lldb/source/Plugins/ObjectFile/XCOFF/ObjectFileXCOFF.h @@ -1,4 +1,5 @@ -//===-- ObjectFileXCOFF.h --------------------------------------- -*- C++ -*-===// +//===-- ObjectFileXCOFF.h --------------------------------------- -*- C++ +//-*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -9,16 +10,14 @@ #ifndef LLDB_SOURCE_PLUGINS_OBJECTFILE_XCOFF_OBJECTFILEXCOFF_H #define LLDB_SOURCE_PLUGINS_OBJECTFILE_XCOFF_OBJECTFILEXCOFF_H -#include - -#include - #include "lldb/Symbol/ObjectFile.h" #include "lldb/Utility/ArchSpec.h" #include "lldb/Utility/FileSpec.h" #include "lldb/Utility/UUID.h" #include "lldb/lldb-private.h" #include "llvm/Object/XCOFFObjectFile.h" +#include +#include /// \class ObjectFileXCOFF /// Generic XCOFF object file reader. @@ -240,4 +239,4 @@ class ObjectFileXCOFF : public lldb_private::ObjectFile { std::map> m_deps_base_members; }; -#endif // LLDB_SOURCE_PLUGINS_OBJECTFILE_ELF_OBJECTFILEELF_H +#endif // LLDB_SOURCE_PLUGINS_OBJECTFILE_XCOFF_OBJECTFILE_H From f8b05dfc9fc75177a63dfa2d6df4a9af143b09b8 Mon Sep 17 00:00:00 2001 From: Dhruv-Srivastava Date: Sun, 5 Jan 2025 05:01:47 -0600 Subject: [PATCH 20/31] HostInfoAIX Cleanup --- lldb/include/lldb/Host/aix/HostInfoAIX.h | 4 - lldb/source/Host/aix/HostInfoAIX.cpp | 108 ----------------------- 2 files changed, 112 deletions(-) diff --git a/lldb/include/lldb/Host/aix/HostInfoAIX.h b/lldb/include/lldb/Host/aix/HostInfoAIX.h index ba727e1d5f17126..5a52c42fa6199b8 100644 --- a/lldb/include/lldb/Host/aix/HostInfoAIX.h +++ b/lldb/include/lldb/Host/aix/HostInfoAIX.h @@ -23,12 +23,8 @@ class HostInfoAIX : public HostInfoPosix { static void Initialize(SharedLibraryDirectoryHelper *helper = nullptr); static void Terminate(); - static llvm::StringRef GetDistributionId(); static FileSpec GetProgramFileSpec(); -protected: - static void ComputeHostArchitectureSupport(ArchSpec &arch_32, - ArchSpec &arch_64); }; } diff --git a/lldb/source/Host/aix/HostInfoAIX.cpp b/lldb/source/Host/aix/HostInfoAIX.cpp index ef07b07c8cab21c..2996fcb55f81163 100644 --- a/lldb/source/Host/aix/HostInfoAIX.cpp +++ b/lldb/source/Host/aix/HostInfoAIX.cpp @@ -11,117 +11,25 @@ #include "lldb/Host/FileSystem.h" #include "lldb/Utility/LLDBLog.h" #include "lldb/Utility/Log.h" - #include "llvm/Support/Threading.h" - #include #include #include #include #include - #include #include using namespace lldb_private; -namespace { -struct HostInfoAIXFields { - llvm::once_flag m_distribution_once_flag; - std::string m_distribution_id; -}; -} // namespace - -static HostInfoAIXFields *g_fields = nullptr; - void HostInfoAIX::Initialize(SharedLibraryDirectoryHelper *helper) { HostInfoPosix::Initialize(helper); - - g_fields = new HostInfoAIXFields(); } void HostInfoAIX::Terminate() { - assert(g_fields && "Missing call to Initialize?"); - delete g_fields; - g_fields = nullptr; HostInfoBase::Terminate(); } -llvm::StringRef HostInfoAIX::GetDistributionId() { - assert(g_fields && "Missing call to Initialize?"); - // Try to run 'lbs_release -i', and use that response for the distribution - // id. - llvm::call_once(g_fields->m_distribution_once_flag, []() { - Log *log = GetLog(LLDBLog::Host); - LLDB_LOGF(log, "attempting to determine AIX distribution..."); - - // check if the lsb_release command exists at one of the following paths - const char *const exe_paths[] = {"/bin/lsb_release", - "/usr/bin/lsb_release"}; - - for (size_t exe_index = 0; - exe_index < sizeof(exe_paths) / sizeof(exe_paths[0]); ++exe_index) { - const char *const get_distribution_info_exe = exe_paths[exe_index]; - if (access(get_distribution_info_exe, F_OK)) { - // this exe doesn't exist, move on to next exe - LLDB_LOGF(log, "executable doesn't exist: %s", - get_distribution_info_exe); - continue; - } - - // execute the distribution-retrieval command, read output - std::string get_distribution_id_command(get_distribution_info_exe); - get_distribution_id_command += " -i"; - - FILE *file = popen(get_distribution_id_command.c_str(), "r"); - if (!file) { - LLDB_LOGF(log, - "failed to run command: \"%s\", cannot retrieve " - "platform information", - get_distribution_id_command.c_str()); - break; - } - - // retrieve the distribution id string. - char distribution_id[256] = {'\0'}; - if (fgets(distribution_id, sizeof(distribution_id) - 1, file) != - nullptr) { - LLDB_LOGF(log, "distribution id command returned \"%s\"", - distribution_id); - - const char *const distributor_id_key = "Distributor ID:\t"; - if (strstr(distribution_id, distributor_id_key)) { - // strip newlines - std::string id_string(distribution_id + strlen(distributor_id_key)); - llvm::erase(id_string, '\n'); - - // lower case it and convert whitespace to underscores - std::transform( - id_string.begin(), id_string.end(), id_string.begin(), - [](char ch) { return tolower(isspace(ch) ? '_' : ch); }); - - g_fields->m_distribution_id = id_string; - LLDB_LOGF(log, "distribution id set to \"%s\"", - g_fields->m_distribution_id.c_str()); - } else { - LLDB_LOGF(log, "failed to find \"%s\" field in \"%s\"", - distributor_id_key, distribution_id); - } - } else { - LLDB_LOGF(log, - "failed to retrieve distribution id, \"%s\" returned no" - " lines", - get_distribution_id_command.c_str()); - } - - // clean up the file - pclose(file); - } - }); - - return g_fields->m_distribution_id; -} - FileSpec HostInfoAIX::GetProgramFileSpec() { static FileSpec g_program_filespec; @@ -136,19 +44,3 @@ FileSpec HostInfoAIX::GetProgramFileSpec() { return g_program_filespec; } - -void HostInfoAIX::ComputeHostArchitectureSupport(ArchSpec &arch_32, - ArchSpec &arch_64) { - HostInfoPosix::ComputeHostArchitectureSupport(arch_32, arch_64); - - // "unknown" in the vendor slot isn't what we want for the default - // triple. It's probably an artifact of config.guess. - if (arch_32.IsValid()) { - if (arch_32.GetTriple().getVendor() == llvm::Triple::UnknownVendor) - arch_32.GetTriple().setVendorName(llvm::StringRef()); - } - if (arch_64.IsValid()) { - if (arch_64.GetTriple().getVendor() == llvm::Triple::UnknownVendor) - arch_64.GetTriple().setVendorName(llvm::StringRef()); - } -} From 57d080e44e80203a6ab848c362469954a7c9f067 Mon Sep 17 00:00:00 2001 From: Dhruv-Srivastava Date: Sun, 5 Jan 2025 05:49:40 -0600 Subject: [PATCH 21/31] Cleanup HostInfoAIX Including the previous commit, Removed: GetDistributionID, ComputeHostArchitectureSupport and Reduced GetProgramFileSpec as it was not needed --- lldb/source/Host/aix/HostInfoAIX.cpp | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/lldb/source/Host/aix/HostInfoAIX.cpp b/lldb/source/Host/aix/HostInfoAIX.cpp index 2996fcb55f81163..d09b9052668af37 100644 --- a/lldb/source/Host/aix/HostInfoAIX.cpp +++ b/lldb/source/Host/aix/HostInfoAIX.cpp @@ -26,21 +26,9 @@ void HostInfoAIX::Initialize(SharedLibraryDirectoryHelper *helper) { HostInfoPosix::Initialize(helper); } -void HostInfoAIX::Terminate() { - HostInfoBase::Terminate(); -} +void HostInfoAIX::Terminate() { HostInfoBase::Terminate(); } FileSpec HostInfoAIX::GetProgramFileSpec() { static FileSpec g_program_filespec; - - if (!g_program_filespec) { - char exe_path[PATH_MAX]; - ssize_t len = readlink("/proc/self/exe", exe_path, sizeof(exe_path) - 1); - if (len > 0) { - exe_path[len] = 0; - g_program_filespec.SetFile(exe_path, FileSpec::Style::native); - } - } - return g_program_filespec; } From 673713a9339de4e4ea395ee2e7f65dc1db43bcf9 Mon Sep 17 00:00:00 2001 From: Dhruv-Srivastava Date: Sun, 5 Jan 2025 15:35:23 -0600 Subject: [PATCH 22/31] Removing headers --- lldb/include/lldb/Host/aix/HostInfoAIX.h | 2 -- lldb/source/Host/aix/HostInfoAIX.cpp | 12 ------------ 2 files changed, 14 deletions(-) diff --git a/lldb/include/lldb/Host/aix/HostInfoAIX.h b/lldb/include/lldb/Host/aix/HostInfoAIX.h index 5a52c42fa6199b8..331a27463085025 100644 --- a/lldb/include/lldb/Host/aix/HostInfoAIX.h +++ b/lldb/include/lldb/Host/aix/HostInfoAIX.h @@ -11,8 +11,6 @@ #include "lldb/Host/posix/HostInfoPosix.h" #include "lldb/Utility/FileSpec.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/Support/VersionTuple.h" namespace lldb_private { diff --git a/lldb/source/Host/aix/HostInfoAIX.cpp b/lldb/source/Host/aix/HostInfoAIX.cpp index d09b9052668af37..61b47462dd64734 100644 --- a/lldb/source/Host/aix/HostInfoAIX.cpp +++ b/lldb/source/Host/aix/HostInfoAIX.cpp @@ -7,18 +7,6 @@ //===----------------------------------------------------------------------===// #include "lldb/Host/aix/HostInfoAIX.h" -#include "lldb/Host/Config.h" -#include "lldb/Host/FileSystem.h" -#include "lldb/Utility/LLDBLog.h" -#include "lldb/Utility/Log.h" -#include "llvm/Support/Threading.h" -#include -#include -#include -#include -#include -#include -#include using namespace lldb_private; From cdc31f3963365e4595247ff5a7155662df1ce1af Mon Sep 17 00:00:00 2001 From: Dhruv-Srivastava Date: Mon, 6 Jan 2025 09:28:56 -0600 Subject: [PATCH 23/31] Reverted merge blunder CMakeLists --- lldb/source/Host/CMakeLists.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lldb/source/Host/CMakeLists.txt b/lldb/source/Host/CMakeLists.txt index f326bc07dc1f613..f4fca8acc4d83e4 100644 --- a/lldb/source/Host/CMakeLists.txt +++ b/lldb/source/Host/CMakeLists.txt @@ -141,7 +141,10 @@ else() elseif (CMAKE_SYSTEM_NAME MATCHES "AIX") add_host_subdirectory(aix + aix/AbstractSocket.cpp + aix/Host.cpp aix/HostInfoAIX.cpp + aix/Support.cpp ) endif() endif() From 713a6cbbb97b9bc56b039ab050a1690eccc017e3 Mon Sep 17 00:00:00 2001 From: Dhruv-Srivastava Date: Mon, 6 Jan 2025 09:39:36 -0600 Subject: [PATCH 24/31] Removed DomainSocket.cpp FileSystemPosix.cpp includes --- lldb/source/Host/posix/DomainSocket.cpp | 4 ---- lldb/source/Host/posix/FileSystemPosix.cpp | 3 --- 2 files changed, 7 deletions(-) diff --git a/lldb/source/Host/posix/DomainSocket.cpp b/lldb/source/Host/posix/DomainSocket.cpp index f30e84d83efcaee..be8fcdf2c8f2c8f 100644 --- a/lldb/source/Host/posix/DomainSocket.cpp +++ b/lldb/source/Host/posix/DomainSocket.cpp @@ -17,10 +17,6 @@ #include #include -#if defined(_AIX) -#include -#endif - using namespace lldb; using namespace lldb_private; diff --git a/lldb/source/Host/posix/FileSystemPosix.cpp b/lldb/source/Host/posix/FileSystemPosix.cpp index 1a84f550662d753..a631bb01209ec13 100644 --- a/lldb/source/Host/posix/FileSystemPosix.cpp +++ b/lldb/source/Host/posix/FileSystemPosix.cpp @@ -11,9 +11,6 @@ // C includes #include #include -#ifndef _AIX -#include -#endif #include #include #include From 0a706d29dabeefa62e354fc9358d650f89032048 Mon Sep 17 00:00:00 2001 From: Dhruv-Srivastava Date: Mon, 6 Jan 2025 09:44:10 -0600 Subject: [PATCH 25/31] sys/mount.h --- lldb/source/Host/posix/FileSystemPosix.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/lldb/source/Host/posix/FileSystemPosix.cpp b/lldb/source/Host/posix/FileSystemPosix.cpp index a631bb01209ec13..945e2affc837150 100644 --- a/lldb/source/Host/posix/FileSystemPosix.cpp +++ b/lldb/source/Host/posix/FileSystemPosix.cpp @@ -11,6 +11,7 @@ // C includes #include #include +#include #include #include #include From 84ebb4ec9b542c38fe1b60261a3253383e9fbf5d Mon Sep 17 00:00:00 2001 From: Dhruv-Srivastava Date: Mon, 6 Jan 2025 09:54:58 -0600 Subject: [PATCH 26/31] sys/mount.h --- lldb/source/Host/posix/FileSystemPosix.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lldb/source/Host/posix/FileSystemPosix.cpp b/lldb/source/Host/posix/FileSystemPosix.cpp index 945e2affc837150..1a84f550662d753 100644 --- a/lldb/source/Host/posix/FileSystemPosix.cpp +++ b/lldb/source/Host/posix/FileSystemPosix.cpp @@ -11,7 +11,9 @@ // C includes #include #include +#ifndef _AIX #include +#endif #include #include #include From 844f7980040de9e13620e9d65a3fcaef56b6c8d6 Mon Sep 17 00:00:00 2001 From: Dhruv Srivastava Date: Thu, 9 Jan 2025 09:47:43 +0530 Subject: [PATCH 27/31] Removed _AIX from ConnectionFileDescriptorPosix.cpp --- lldb/source/Host/posix/ConnectionFileDescriptorPosix.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lldb/source/Host/posix/ConnectionFileDescriptorPosix.cpp b/lldb/source/Host/posix/ConnectionFileDescriptorPosix.cpp index 2530c8fa353ba4f..0ed2016667162a7 100644 --- a/lldb/source/Host/posix/ConnectionFileDescriptorPosix.cpp +++ b/lldb/source/Host/posix/ConnectionFileDescriptorPosix.cpp @@ -715,7 +715,7 @@ ConnectionFileDescriptor::ConnectFD(llvm::StringRef s, ConnectionStatus ConnectionFileDescriptor::ConnectFile( llvm::StringRef s, socket_id_callback_type socket_id_callback, Status *error_ptr) { -#if LLDB_ENABLE_POSIX && !defined(_AIX) +#if LLDB_ENABLE_POSIX std::string addr_str = s.str(); // file:///PATH int fd = FileSystem::Instance().Open(addr_str.c_str(), O_RDWR); @@ -756,7 +756,7 @@ ConnectionStatus ConnectionFileDescriptor::ConnectFile( m_io_sp = std::make_shared(fd, File::eOpenOptionReadWrite, true); return eConnectionStatusSuccess; -#endif // LLDB_ENABLE_POSIX && !defined(_AIX) +#endif // LLDB_ENABLE_POSIX llvm_unreachable("this function should be only called w/ LLDB_ENABLE_POSIX"); } From 4fe42cda7c2f4990b18a39c1d6563094fb88775f Mon Sep 17 00:00:00 2001 From: ravindra shinde Date: Fri, 17 Jan 2025 13:58:13 +0530 Subject: [PATCH 28/31] [ObjectFileXCOFF] Fix access to protected member 'GetSectionLoadList' in Target - Added a public method to Target for accessing 'GetSectionLoadList' safely. - Updated ObjectFileXCOFF to use the new public method, ensuring compliance with encapsulation rules. This resolves the build error caused by direct access to the protected member. Signed-off-by: ravindra shinde --- lldb/include/lldb/Target/Target.h | 5 +++++ lldb/source/Plugins/ObjectFile/XCOFF/ObjectFileXCOFF.cpp | 6 +++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/lldb/include/lldb/Target/Target.h b/lldb/include/lldb/Target/Target.h index f31ac381391b450..75f9c9c2e999cc3 100644 --- a/lldb/include/lldb/Target/Target.h +++ b/lldb/include/lldb/Target/Target.h @@ -522,6 +522,7 @@ class Target : public std::enable_shared_from_this, eBroadcastBitSymbolsChanged = (1 << 5), }; + // These two functions fill out the Broadcaster interface: static llvm::StringRef GetStaticBroadcasterClass(); @@ -1644,6 +1645,10 @@ class Target : public std::enable_shared_from_this, TargetStats &GetStatistics() { return m_stats; } +public: + SectionLoadList &GetSectionLoadListPublic() { + return GetSectionLoadList(); + } protected: /// Construct with optional file and arch. /// diff --git a/lldb/source/Plugins/ObjectFile/XCOFF/ObjectFileXCOFF.cpp b/lldb/source/Plugins/ObjectFile/XCOFF/ObjectFileXCOFF.cpp index afd8027bab06c3d..cf11e5fb8f5a383 100644 --- a/lldb/source/Plugins/ObjectFile/XCOFF/ObjectFileXCOFF.cpp +++ b/lldb/source/Plugins/ObjectFile/XCOFF/ObjectFileXCOFF.cpp @@ -340,7 +340,7 @@ bool ObjectFileXCOFF::SetLoadAddress(Target &target, lldb::addr_t value, strcmp(section_sp->GetName().AsCString(), ".bss") == 0) use_offset = true; - if (target.GetSectionLoadList().SetSectionLoadAddress( + if (target.GetSectionLoadListPublic().SetSectionLoadAddress( section_sp, (use_offset ? (section_sp->GetFileOffset() + value) : (section_sp->GetFileAddress() + value)))) ++num_loaded_sections; @@ -369,13 +369,13 @@ bool ObjectFileXCOFF::SetLoadAddressByType(Target &target, lldb::addr_t value, SectionSP section_sp(section_list->GetSectionAtIndex(sect_idx)); if (type_id == 1 && section_sp && strcmp(section_sp->GetName().AsCString(), ".text") == 0) { if (!section_sp->IsThreadSpecific()) { - if (target.GetSectionLoadList().SetSectionLoadAddress( + if (target.GetSectionLoadListPublic().SetSectionLoadAddress( section_sp, section_sp->GetFileOffset() + value)) ++num_loaded_sections; } } else if (type_id == 2 && section_sp && strcmp(section_sp->GetName().AsCString(), ".data") == 0) { if (!section_sp->IsThreadSpecific()) { - if (target.GetSectionLoadList().SetSectionLoadAddress( + if (target.GetSectionLoadListPublic().SetSectionLoadAddress( section_sp, section_sp->GetFileAddress() + value)) ++num_loaded_sections; } From e5ed4f21c5bbc709e5e2eff0f83995cc6d89de48 Mon Sep 17 00:00:00 2001 From: Dhruv-Srivastava Date: Sun, 19 Jan 2025 03:43:11 -0600 Subject: [PATCH 29/31] Resolved cmake failure for SBProgress.cpp --- lldb/source/API/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/lldb/source/API/CMakeLists.txt b/lldb/source/API/CMakeLists.txt index eb348e2b972320d..0a03e000c0cae2e 100644 --- a/lldb/source/API/CMakeLists.txt +++ b/lldb/source/API/CMakeLists.txt @@ -85,6 +85,7 @@ add_lldb_library(liblldb STATIC ${option_framework} SBModuleSpec.cpp SBPlatform.cpp SBProcess.cpp + SBProgress.cpp SBProcessInfo.cpp SBProcessInfoList.cpp SBQueue.cpp From 82dbcb0e776c438e5f40c9f8d8c8e8eb81b7febd Mon Sep 17 00:00:00 2001 From: Dhruv-Srivastava Date: Mon, 27 Jan 2025 06:35:19 -0600 Subject: [PATCH 30/31] Host.cpp ANDROID --- lldb/source/Host/common/Host.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lldb/source/Host/common/Host.cpp b/lldb/source/Host/common/Host.cpp index 758e9f49ade2c71..adf74df8aa90b79 100644 --- a/lldb/source/Host/common/Host.cpp +++ b/lldb/source/Host/common/Host.cpp @@ -1,4 +1,4 @@ -//===-- Host.cpp ----------------------------------------------------------===// + // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -516,7 +516,6 @@ static int dladdr(const void *ptr, Dl_info *dl) FileSpec Host::GetModuleFileSpecForHostAddress(const void *host_addr) { FileSpec module_filespec; -#if !defined(__ANDROID__) #ifdef _AIX if (host_addr == reinterpret_cast(HostInfoBase::ComputeSharedLibraryDirectory)) { // FIXME: AIX dladdr return "lldb" for this case @@ -527,6 +526,7 @@ FileSpec Host::GetModuleFileSpecForHostAddress(const void *host_addr) { } } #endif +#if !defined(__ANDROID__) Dl_info info; if (::dladdr(host_addr, &info)) { if (info.dli_fname) { @@ -534,6 +534,7 @@ FileSpec Host::GetModuleFileSpecForHostAddress(const void *host_addr) { FileSystem::Instance().Resolve(module_filespec); } } +#endif return module_filespec; } From 60294eaa1611632afc94b9da503752e34ad2703d Mon Sep 17 00:00:00 2001 From: Ravindra Shinde Date: Tue, 4 Feb 2025 03:23:56 -0600 Subject: [PATCH 31/31] Resolving the fatal error while build Build is failing due to the fatal error: 'sys/syscall.h' file not found Signed-off-by: Ravindra Shinde --- lldb/source/Host/common/Host.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lldb/source/Host/common/Host.cpp b/lldb/source/Host/common/Host.cpp index 40ce76d70d6e881..b5bd68b8539bd77 100644 --- a/lldb/source/Host/common/Host.cpp +++ b/lldb/source/Host/common/Host.cpp @@ -18,8 +18,12 @@ #include #include #include + +#ifndef _AIX #include #include +#endif + #include #include #endif